Skip to content

Add new Command topics #447

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions extras/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ set(TEST_SRCS
src/test_CloudSchedule.cpp
src/test_decode.cpp
src/test_encode.cpp
src/test_command_decode.cpp
src/test_command_encode.cpp
src/test_publishEvery.cpp
src/test_publishOnChange.cpp
src/test_publishOnChangeRateLimit.cpp
Expand All @@ -55,6 +57,9 @@ set(TEST_DUT_SRCS
../../src/property/PropertyContainer.cpp
../../src/cbor/CBORDecoder.cpp
../../src/cbor/CBOREncoder.cpp
../../src/cbor/MessageDecoder.cpp
../../src/cbor/MessageEncoder.cpp
../../src/cbor/CBOR.cpp
../../src/cbor/lib/tinycbor/src/cborencoder.c
../../src/cbor/lib/tinycbor/src/cborencoder_close_container_checked.c
../../src/cbor/lib/tinycbor/src/cborerrorstrings.c
Expand Down
736 changes: 736 additions & 0 deletions extras/test/src/test_command_decode.cpp

Large diffs are not rendered by default.

322 changes: 322 additions & 0 deletions extras/test/src/test_command_encode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,322 @@
/*
Copyright (c) 2024 Arduino. All rights reserved.
*/

/******************************************************************************
INCLUDE
******************************************************************************/

#include <catch.hpp>

#include <memory>

#include <util/CBORTestUtil.h>
#include <MessageEncoder.h>

/******************************************************************************
TEST CODE
******************************************************************************/

SCENARIO("Test the encoding of command messages") {
/****************************************************************************/

WHEN("Encode the OtaBeginUp message")
{
OtaBeginUp command;
uint8_t sha[SHA256_SIZE] = {0x01, 0x02, 0x03, 0x04};
memcpy(command.params.sha, sha, SHA256_SIZE);

command.c.id = CommandId::OtaBeginUpId;

uint8_t buffer[512];
size_t bytes_encoded = sizeof(buffer);

CBORMessageEncoder encoder;
Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded);

uint8_t expected_result[] = {
0xda, 0x00, 0x01, 0x00, 0x00, 0x81, 0x58, 0x20,
0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

// Test the encoding is
// DA 00010000 # tag(65536)
// 81 # array(1)
// 58 20 # bytes(32)
// 01020304
THEN("The encoding is successful") {
REQUIRE(err == Encoder::Status::Complete);
REQUIRE(bytes_encoded == sizeof(expected_result));
REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0);
}
}


/****************************************************************************/

WHEN("Encode the ThingBeginCmd message")
{
ThingBeginCmd command;
String thing_id = "thing_id";
strcpy(command.params.thing_id, thing_id.c_str());

command.c.id = CommandId::ThingBeginCmdId;

uint8_t buffer[512];
size_t bytes_encoded = sizeof(buffer);

CBORMessageEncoder encoder;
Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded);

uint8_t expected_result[] = {
0xda, 0x00, 0x01, 0x03, 0x00, 0x81, 0x68, 0x74,
0x68, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64
};

// Test the encoding is
// DA 00010300 # tag(66304)
// 81 # array(1)
// 68 # text(8)
// 7468696E675F6964 # "thing_id"

THEN("The encoding is successful") {
REQUIRE(err == Encoder::Status::Complete);
REQUIRE(bytes_encoded == sizeof(expected_result));
REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0);
}
}

/****************************************************************************/

WHEN("Encode the LastValuesBeginCmd message")
{
LastValuesBeginCmd command;
command.c.id = CommandId::LastValuesBeginCmdId;

uint8_t buffer[512];
size_t bytes_encoded = sizeof(buffer);

CBORMessageEncoder encoder;
Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded);

uint8_t expected_result[] = {
0xda, 0x00, 0x01, 0x05, 0x00, 0x80
};

// Test the encoding is
// DA 00010500 # tag(66816)
// 80 # array(0)
THEN("The encoding is successful") {
REQUIRE(err == Encoder::Status::Complete);
REQUIRE(bytes_encoded == sizeof(expected_result));
REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0);
}
}

/**************************************************************************/

WHEN("Encode the DeviceBeginCmd message")
{
DeviceBeginCmd command;
String lib_version = "2.0.0";
strcpy(command.params.lib_version, lib_version.c_str());

command.c.id = CommandId::DeviceBeginCmdId;

uint8_t buffer[512];
size_t bytes_encoded = sizeof(buffer);

CBORMessageEncoder encoder;
Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded);

uint8_t expected_result[] = {
0xda, 0x00, 0x01, 0x07, 0x00, 0x81, 0x65, 0x32,
0x2e, 0x30, 0x2e, 0x30
};

// Test the encoding is
// DA 00010700 # tag(67328)
// 81 # array(1)
// 65 # text(5)
// 322E302E30 # "2.0.0"
THEN("The encoding is successful") {
REQUIRE(err == Encoder::Status::Complete);
REQUIRE(bytes_encoded == sizeof(expected_result));
REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0);
}
}

/****************************************************************************/

WHEN("Encode the OtaProgressCmdUp message")
{
OtaProgressCmdUp command;
command.params.time = 2;

uint8_t id[ID_SIZE] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
memcpy(command.params.id, id, ID_SIZE);
command.params.state = 1;
command.params.state_data = -1;
command.params.time = 100;

command.c.id = CommandId::OtaProgressCmdUpId;

uint8_t buffer[512];
size_t bytes_encoded = sizeof(buffer);

CBORMessageEncoder encoder;
Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded);

uint8_t expected_result[] = {
0xda, 0x00, 0x01, 0x02, 0x00, 0x84, 0x50, 0x00,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xe1,
0x20, 0x18, 0x64
};

// Test the encoding is
// DA 00010200 # tag(66048)
// 84 # array(4)
// 50 # bytes(16)
// 000102030405060708090A0B0C0D0E0F # "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f"
// E1 # primitive(1)
// 20 # negative(0)
// 18 64 # unsigned(100)
THEN("The encoding is successful") {
REQUIRE(err == Encoder::Status::Complete);
REQUIRE(bytes_encoded == sizeof(expected_result));
REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0);
}
}

/****************************************************************************/

WHEN("Encode the TimezoneCommandUp message")
{
TimezoneCommandUp command;
command.c.id = CommandId::TimezoneCommandUpId;

uint8_t buffer[512];
size_t bytes_encoded = sizeof(buffer);

CBORMessageEncoder encoder;
Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded);

uint8_t expected_result[] = {
0xda, 0x00, 0x01, 0x08, 0x00, 0x80
};

// Test the encoding is
// DA 00010800 # tag(67584)
// 80 # array(0)
THEN("The encoding is successful") {
REQUIRE(err == Encoder::Status::Complete);
REQUIRE(bytes_encoded == sizeof(expected_result));
REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0);
}
}

/****************************************************************************/

WHEN("Encode the ThingUpdateCmdId message")
{
ThingUpdateCmd command;
command.c.id = CommandId::ThingUpdateCmdId;

String thing_id = "e4494d55-872a-4fd2-9646-92f87949394c";
strcpy(command.params.thing_id, thing_id.c_str());

uint8_t buffer[512];
size_t bytes_encoded = sizeof(buffer);

CBORMessageEncoder encoder;
Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded);

THEN("The encoding is unsuccessful - ThingUpdateCmdId is not supported") {
REQUIRE(err == Encoder::Status::Error);
}
}

/****************************************************************************/

WHEN("Encode the SetTimezoneCommand message")
{
TimezoneCommandDown command;
command.c.id = CommandId::TimezoneCommandDownId;

command.params.offset = 1708963873;
command.params.until = 2024579473;

uint8_t buffer[512];
size_t bytes_encoded = sizeof(buffer);

CBORMessageEncoder encoder;
Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded);

THEN("The encoding is unsuccessful - SetTimezoneCommand is not supported") {
REQUIRE(err == Encoder::Status::Error);
}
}

/****************************************************************************/

WHEN("Encode the LastValuesUpdateCmd message")
{
LastValuesUpdateCmd command;
command.c.id = CommandId::LastValuesUpdateCmdId;

command.params.length = 13;
uint8_t last_values[13] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x10, 0x11, 0x12};
command.params.last_values = last_values;

uint8_t buffer[512];
size_t bytes_encoded = sizeof(buffer);

CBORMessageEncoder encoder;
Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded);

THEN("The encoding is unsuccessful - LastValuesUpdateCmd is not supported") {
REQUIRE(err == Encoder::Status::Error);
}
}

/****************************************************************************/

WHEN("Encode the OtaUpdateCmdDown message")
{
OtaUpdateCmdDown command;
command.c.id = CommandId::OtaUpdateCmdDownId;

uint8_t buffer[512];
size_t bytes_encoded = sizeof(buffer);

CBORMessageEncoder encoder;
Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded);

THEN("The encoding is unsuccessful - OtaUpdateCmdDown is not supported") {
REQUIRE(err == Encoder::Status::Error);
}
}

/****************************************************************************/

WHEN("Encode a message with unknown command Id")
{
OtaUpdateCmdDown command;
command.c.id = CommandId::UnknownCmdId;

uint8_t buffer[512];
size_t bytes_encoded = sizeof(buffer);

CBORMessageEncoder encoder;
Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded);

THEN("The encoding is unsuccessful - UnknownCmdId is not supported") {
REQUIRE(err == Encoder::Status::Error);
}
}
}
8 changes: 4 additions & 4 deletions src/ArduinoIoTCloudDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,12 @@ ArduinoCloudDevice::State ArduinoCloudDevice::handleInit() {

ArduinoCloudDevice::State ArduinoCloudDevice::handleSendCapabilities() {
/* Sends device capabilities message */
Message message = { DeviceBeginCmdId };
deliver(&message);
DeviceBeginCmd deviceBegin = { DeviceBeginCmdId, AIOT_CONFIG_LIB_VERSION };
deliver(reinterpret_cast<Message*>(&deviceBegin));

/* Subscribe to device topic to request */
message = { ThingBeginCmdId };
deliver(&message);
ThingBeginCmd thingBegin = { ThingBeginCmdId };
deliver(reinterpret_cast<Message*>(&thingBegin));

/* No device configuration received. Wait: 4s -> 8s -> 16s -> 32s -> 32s ...*/
_attachAttempt.retry();
Expand Down
Loading
Loading