Compare commits

9 Commits

Author SHA1 Message Date
746d0fad6f Create initial tests
Tests are run via a PlatformIO project
2024-04-09 00:31:46 +10:00
4460224202 Reformat library.json 2024-04-04 21:50:14 +11:00
a7db18d8ac Bump version to 0.0.3 2024-04-04 18:00:46 +11:00
52d03a1ac9 Add support for more packet types 2024-04-04 17:58:18 +11:00
07f46ecfe7 Add support for various header values 2024-04-04 17:58:18 +11:00
90e101c47e Add callbacks for getting raw buffer 2024-04-04 17:58:18 +11:00
e488cf86d4 Add a tiny bit more context to the README 2024-04-04 17:55:36 +11:00
9f9dfbfff2 Update library.json to point to Github mirror 2024-04-04 17:55:20 +11:00
89dd174543 Set specific version numbers for dependencies 2024-02-18 23:35:44 +11:00
11 changed files with 363 additions and 73 deletions

View File

@@ -1,2 +1,4 @@
# RFPowerView # RFPowerView
A library for receiving and sending PowerView packets via an nRF24L01 module

View File

@@ -19,11 +19,11 @@ private:
void setPacketSize(uint8_t *buffer, uint8_t); void setPacketSize(uint8_t *buffer, uint8_t);
void setConstants(uint8_t *buffer); void setConstants(uint8_t *buffer);
void setSourceAddress(uint8_t *buffer, uint16_t); void setSourceAddress(uint8_t *buffer, uint8_t offset, uint16_t source);
void setDestinationAddress(uint8_t *buffer, uint16_t); void setDestinationAddress(uint8_t *buffer, uint8_t offset, uint16_t destination);
void setRollingCodes(uint8_t *buffer, uint8_t rollingCode1, uint8_t rollingCode2); void setRollingCodes(uint8_t *buffer, uint8_t rollingCode1, uint8_t rollingCode2);
void setProtocolVersion(uint8_t *buffer, uint8_t); void setProtocolVersion(uint8_t *buffer, uint8_t);
void setFieldsData(uint8_t *buffer, const FieldsParameters& parameters); void setFieldsData(uint8_t *buffer, uint8_t offset, const FieldsParameters& parameters);
void calculateCRC(uint8_t *buffer); void calculateCRC(uint8_t *buffer);
void incrementRollingCodes(); void incrementRollingCodes();
uint8_t calculateTotalFieldSize(const FieldsParameters& parameters); uint8_t calculateTotalFieldSize(const FieldsParameters& parameters);

View File

@@ -9,6 +9,9 @@ enum class PacketType {
OPEN, OPEN,
CLOSE, CLOSE,
STOP, STOP,
OPEN_SLOW,
CLOSE_SLOW,
MOVE_TO_SAVED_POSITION,
FIELDS, FIELDS,
FIELD_COMMAND, FIELD_COMMAND,
UNKNOWN UNKNOWN
@@ -34,11 +37,25 @@ struct FieldsParameters {
using PacketParameters = std::variant<std::monostate, FieldsParameters>; using PacketParameters = std::variant<std::monostate, FieldsParameters>;
struct BroadcastHeader {
uint16_t source;
};
// Define Message structure struct UnicastHeader {
struct Packet {
uint16_t source; uint16_t source;
uint16_t destination; uint16_t destination;
};
struct GroupsHeader {
uint16_t source;
std::vector<uint8_t> groups;
};
using PacketHeader = std::variant<BroadcastHeader, UnicastHeader, GroupsHeader>;
// Define Packet structure
struct Packet {
PacketHeader header;
PacketType type; PacketType type;
PacketParameters parameters; PacketParameters parameters;
uint8_t rollingCode1; uint8_t rollingCode1;

View File

@@ -23,7 +23,10 @@ public:
bool begin(); bool begin();
void loop(); void loop();
void setPacketCallback(std::function<void(const Packet*)> callback); void setPacketReceivedCallback(std::function<void(const Packet*)> callback);
void setValidBufferReceivedCallback(std::function<void(const uint8_t*)> callback);
void setInvalidBufferReceivedCallback(std::function<void(const uint8_t*)> callback);
bool sendPacket(const Packet* packet); bool sendPacket(const Packet* packet);
private: private:
@@ -34,7 +37,9 @@ private:
uint8_t irqPin; uint8_t irqPin;
uint8_t rfID[2]; uint8_t rfID[2];
std::function<void(const Packet*)> packetCallback; std::function<void(const Packet*)> packetReceivedCallback;
std::function<void(const uint8_t*)> validBufferReceivedCallback;
std::function<void(const uint8_t*)> invalidBufferReceivedCallback;
uint8_t sendBuffer[32]; uint8_t sendBuffer[32];

View File

@@ -1,14 +1,13 @@
{ {
"name": "RFPowerView", "name": "RFPowerView",
"version": "0.0.1", "version": "0.0.3",
"description": "A library for receiving and sending PowerView packets via an nRF24L01 module", "description": "A library for receiving and sending PowerView packets via an nRF24L01 module",
"keywords": "powerview, hunterdouglas, luxaflex, rf, radio", "keywords": "powerview, hunterdouglas, luxaflex, rf, radio",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://git.mattway.com.au/matt/RFPowerView.git" "url": "https://github.com/mattyway/RFPowerView.git"
}, },
"authors": "authors": [
[
{ {
"name": "Matt Way", "name": "Matt Way",
"email": "mattyway@gmail.com" "email": "mattyway@gmail.com"
@@ -16,12 +15,10 @@
], ],
"license": "GPL-2.0-only", "license": "GPL-2.0-only",
"dependencies": { "dependencies": {
"robtillaart/CRC": "^1.0.2", "robtillaart/CRC": "1.0.2",
"nrf24/RF24": "^1.4.8", "nrf24/RF24": "1.4.8",
"rlogiacco/CircularBuffer": "^1.3.3" "rlogiacco/CircularBuffer": "1.3.3"
}, },
"frameworks": "arduino", "frameworks": "arduino",
"platforms": [ "platforms": ["espressif8266"]
"espressif8266"
]
} }

23
platformio.ini Normal file
View File

@@ -0,0 +1,23 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:nodemcuv2]
platform = espressif8266
board = nodemcuv2
framework = arduino
[env]
monitor_speed = 115200
test_build_src = true
test_framework = unity
lib_deps =
robtillaart/CRC @ 1.0.2
nrf24/RF24 @ 1.4.8
rlogiacco/CircularBuffer @ 1.3.3

View File

@@ -11,45 +11,86 @@ BufferFiller::~BufferFiller()
bool BufferFiller::fill(uint8_t *buffer, const Packet* packet) { bool BufferFiller::fill(uint8_t *buffer, const Packet* packet) {
setConstants(buffer); setConstants(buffer);
setProtocolVersion(buffer, protocolVersion);
setSourceAddress(buffer, packet->source); int dataOffset = -1;
setDestinationAddress(buffer, packet->destination);
if (std::holds_alternative<BroadcastHeader>(packet->header)) {
setProtocolVersion(buffer, 0x04);
auto header = std::get<BroadcastHeader>(packet->header);
setSourceAddress(buffer, 12, header.source);
dataOffset = 14;
} else if (std::holds_alternative<UnicastHeader>(packet->header)) {
setProtocolVersion(buffer, 0x05);
auto header = std::get<UnicastHeader>(packet->header);
setDestinationAddress(buffer, 12, header.destination);
setSourceAddress(buffer, 14, header.source);
dataOffset = 16;
} else if (std::holds_alternative<GroupsHeader>(packet->header)) {
setProtocolVersion(buffer, 0x06);
auto header = std::get<GroupsHeader>(packet->header);
int groupsOffset = 12;
for (size_t i = 0; i < header.groups.size(); i++) {
buffer[groupsOffset] = header.groups[i];
groupsOffset++;
}
buffer[groupsOffset] = 0x00;
setSourceAddress(buffer, groupsOffset + 1, header.source);
dataOffset = groupsOffset + 3;
}
switch(packet->type) { switch(packet->type) {
case PacketType::STOP: case PacketType::STOP:
setPacketSize(buffer, 0x11); setPacketSize(buffer, 0x11);
buffer[16] = 0x52; buffer[dataOffset + 0] = 0x52;
buffer[17] = 0x53; buffer[dataOffset + 1] = 0x53;
buffer[18] = 0x00; buffer[dataOffset + 2] = 0x00;
break; break;
case PacketType::CLOSE: case PacketType::CLOSE:
setPacketSize(buffer, 0x11); setPacketSize(buffer, 0x11);
buffer[16] = 0x52; buffer[dataOffset + 0] = 0x52;
buffer[17] = 0x44; buffer[dataOffset + 1] = 0x44;
buffer[18] = 0x00; buffer[dataOffset + 2] = 0x00;
break; break;
case PacketType::OPEN: case PacketType::OPEN:
setPacketSize(buffer, 0x11); setPacketSize(buffer, 0x11);
buffer[16] = 0x52; buffer[dataOffset + 0] = 0x52;
buffer[17] = 0x55; buffer[dataOffset + 1] = 0x55;
buffer[18] = 0x00; buffer[dataOffset + 2] = 0x00;
break;
case PacketType::CLOSE_SLOW:
setPacketSize(buffer, 0x11);
buffer[dataOffset + 0] = 0x52;
buffer[dataOffset + 1] = 0x4C;
buffer[dataOffset + 2] = 0x00;
break;
case PacketType::OPEN_SLOW:
setPacketSize(buffer, 0x11);
buffer[dataOffset + 0] = 0x52;
buffer[dataOffset + 1] = 0x52;
buffer[dataOffset + 2] = 0x00;
break;
case PacketType::MOVE_TO_SAVED_POSITION:
setPacketSize(buffer, 0x11);
buffer[dataOffset + 0] = 0x52;
buffer[dataOffset + 1] = 0x48;
buffer[dataOffset + 2] = 0x00;
break; break;
case PacketType::FIELDS: { case PacketType::FIELDS: {
FieldsParameters parameters = std::get<FieldsParameters>(packet->parameters); FieldsParameters parameters = std::get<FieldsParameters>(packet->parameters);
// 0x10 is the number of bytes without any fields // 0x10 is the number of bytes without any fields
setPacketSize(buffer, 0x10 + calculateTotalFieldSize(parameters)); setPacketSize(buffer, 0x10 + calculateTotalFieldSize(parameters));
buffer[16] = 0x21; buffer[dataOffset + 0] = 0x21;
buffer[17] = 0x5A; buffer[dataOffset + 1] = 0x5A;
setFieldsData(buffer, parameters); setFieldsData(buffer, dataOffset + 2, parameters);
break; break;
} }
case PacketType::FIELD_COMMAND: { case PacketType::FIELD_COMMAND: {
FieldsParameters parameters = std::get<FieldsParameters>(packet->parameters); FieldsParameters parameters = std::get<FieldsParameters>(packet->parameters);
// 0x10 is the number of bytes without any fields // 0x10 is the number of bytes without any fields
setPacketSize(buffer, 0x10 + calculateTotalFieldSize(parameters)); setPacketSize(buffer, 0x10 + calculateTotalFieldSize(parameters));
buffer[16] = 0x3F; buffer[dataOffset + 0] = 0x3F;
buffer[17] = 0x5A; buffer[dataOffset + 1] = 0x5A;
setFieldsData(buffer, std::get<FieldsParameters>(packet->parameters)); setFieldsData(buffer, dataOffset + 2, parameters);
break; break;
} }
default: default:
@@ -62,9 +103,7 @@ bool BufferFiller::fill(uint8_t *buffer, const Packet* packet) {
return true; return true;
} }
void BufferFiller::setFieldsData(uint8_t *buffer, const FieldsParameters& parameters) { void BufferFiller::setFieldsData(uint8_t *buffer, uint8_t offset, const FieldsParameters& parameters) {
uint8_t offset = 18;
for (size_t i = 0; i < parameters.fields.size(); i++) { for (size_t i = 0; i < parameters.fields.size(); i++) {
Field field = parameters.fields[i]; Field field = parameters.fields[i];
uint8_t fieldSize = calculateFieldSize(field); uint8_t fieldSize = calculateFieldSize(field);
@@ -113,20 +152,20 @@ void BufferFiller::setConstants(uint8_t *buffer) {
buffer[9] = 0x86; // Constant? buffer[9] = 0x86; // Constant?
} }
void BufferFiller::setSourceAddress(uint8_t *buffer, uint16_t sourceID) { void BufferFiller::setSourceAddress(uint8_t *buffer, uint8_t offset, uint16_t sourceID) {
// Physical source address (could be the address of a repeater when receiving a packet) // Physical source address (could be the address of a repeater when receiving a packet)
buffer[7] = (uint8_t)((sourceID & 0xFF00) >> 8); buffer[7] = (uint8_t)((sourceID & 0xFF00) >> 8);
buffer[8] = (uint8_t)(sourceID & 0x00FF); buffer[8] = (uint8_t)(sourceID & 0x00FF);
// Logical source address (usually the same as the physical source address) // Logical source address (usually the same as the physical source address)
buffer[14] = (uint8_t)((sourceID & 0xFF00) >> 8); buffer[offset + 0] = (uint8_t)((sourceID & 0xFF00) >> 8);
buffer[15] = (uint8_t)(sourceID & 0x00FF); buffer[offset + 1] = (uint8_t)(sourceID & 0x00FF);
} }
void BufferFiller::setDestinationAddress(uint8_t *buffer, uint16_t targetID) { void BufferFiller::setDestinationAddress(uint8_t *buffer, uint8_t offset, uint16_t targetID) {
// Logical target address // Logical target address
buffer[12] = (uint8_t)((targetID & 0xFF00) >> 8); buffer[offset + 0] = (uint8_t)((targetID & 0xFF00) >> 8);
buffer[13] = (uint8_t)(targetID & 0x00FF); buffer[offset + 1] = (uint8_t)(targetID & 0x00FF);
} }
void BufferFiller::setRollingCodes(uint8_t *buffer, uint8_t rollingCode1, uint8_t rollingCode2) { void BufferFiller::setRollingCodes(uint8_t *buffer, uint8_t rollingCode1, uint8_t rollingCode2) {

View File

@@ -10,27 +10,65 @@ PacketParser::~PacketParser()
bool PacketParser::parsePacket(const uint8_t *buffer, Packet& packet) bool PacketParser::parsePacket(const uint8_t *buffer, Packet& packet)
{ {
packet.source = (uint16_t)(buffer[14] << 8 | buffer[15]); int dataOffset = -1;
packet.destination = (uint16_t)(buffer[12] << 8 | buffer[13]); if (buffer[10] == 0x04) {
BroadcastHeader header{};
header.source = (uint16_t)(buffer[12] << 8 | buffer[13]);
packet.header = header;
dataOffset = 14;
} else if(buffer[10] == 0x05) {
UnicastHeader header{};
header.destination = (uint16_t)(buffer[12] << 8 | buffer[13]);
header.source = (uint16_t)(buffer[14] << 8 | buffer[15]);
packet.header = header;
dataOffset = 16;
} else if (buffer[10] == 0x06) {
GroupsHeader header{};
size_t i = 12;
uint8_t length = buffer[1] + 2;
while (i < length) {
if (buffer[i] == 0x00) {
dataOffset = i + 3;
break;
} else {
header.groups.push_back(buffer[i]);
}
i++;
}
if (i == length) {
return false;
}
header.source = (uint16_t)(buffer[i + 1] << 8 | buffer[i + 2]);
packet.header = header;
}
packet.rollingCode1 = buffer[4]; packet.rollingCode1 = buffer[4];
packet.rollingCode2 = buffer[11]; packet.rollingCode2 = buffer[11];
if (buffer[16] == 0x52 && buffer[17] == 0x53) { if (buffer[dataOffset + 0] == 0x52 && buffer[dataOffset + 1] == 0x53) {
packet.type = PacketType::STOP; packet.type = PacketType::STOP;
packet.parameters = std::monostate{}; packet.parameters = std::monostate{};
} else if (buffer[16] == 0x52 && buffer[17] == 0x44) { } else if (buffer[dataOffset + 0] == 0x52 && buffer[dataOffset + 1] == 0x44) {
packet.type = PacketType::CLOSE; packet.type = PacketType::CLOSE;
packet.parameters = std::monostate{}; packet.parameters = std::monostate{};
} else if (buffer[16] == 0x52 && buffer[17] == 0x55) { } else if (buffer[dataOffset + 0] == 0x52 && buffer[dataOffset + 1] == 0x55) {
packet.type = PacketType::OPEN; packet.type = PacketType::OPEN;
packet.parameters = std::monostate{}; packet.parameters = std::monostate{};
} else if (buffer[16] == 0x21 && buffer[17] == 0x5A) { } else if (buffer[dataOffset + 0] == 0x52 && buffer[dataOffset + 1] == 0x4C) {
packet.type = PacketType::CLOSE_SLOW;
packet.parameters = std::monostate{};
} else if (buffer[dataOffset + 0] == 0x52 && buffer[dataOffset + 1] == 0x52) {
packet.type = PacketType::OPEN_SLOW;
packet.parameters = std::monostate{};
} else if (buffer[dataOffset + 0] == 0x52 && buffer[dataOffset + 1] == 0x48) {
packet.type = PacketType::MOVE_TO_SAVED_POSITION;
packet.parameters = std::monostate{};
} else if (buffer[dataOffset + 0] == 0x21 && buffer[dataOffset + 1] == 0x5A) {
packet.type = PacketType::FIELDS; packet.type = PacketType::FIELDS;
std::vector<Field> fields; std::vector<Field> fields;
parseFields(buffer, fields); parseFields(buffer, fields);
packet.parameters = FieldsParameters{fields}; packet.parameters = FieldsParameters{fields};
} else if (buffer[16] == 0x3F && buffer[17] == 0x5A) { } else if (buffer[dataOffset + 0] == 0x3F && buffer[dataOffset + 1] == 0x5A) {
packet.type = PacketType::FIELD_COMMAND; packet.type = PacketType::FIELD_COMMAND;
std::vector<Field> fields; std::vector<Field> fields;
parseFields(buffer, fields); parseFields(buffer, fields);

View File

@@ -7,7 +7,9 @@ RFPowerView::RFPowerView(uint8_t cePin, uint8_t csPin, uint8_t irqPin, uint16_t
bufferFiller(0x05), bufferFiller(0x05),
irqPin(irqPin), irqPin(irqPin),
rfID{static_cast<uint8_t>(rfID & 0xFF), static_cast<uint8_t>(rfID >> 8)}, rfID{static_cast<uint8_t>(rfID & 0xFF), static_cast<uint8_t>(rfID >> 8)},
packetCallback(nullptr) {} packetReceivedCallback(nullptr),
validBufferReceivedCallback(nullptr),
invalidBufferReceivedCallback(nullptr) {}
bool RFPowerView::begin() { bool RFPowerView::begin() {
if (!radio.begin()) { if (!radio.begin()) {
@@ -60,21 +62,35 @@ void RFPowerView::interruptHandler() {
} }
void RFPowerView::processBuffer(const uint8_t *buffer) { void RFPowerView::processBuffer(const uint8_t *buffer) {
if (validBufferReceivedCallback != nullptr) {
validBufferReceivedCallback(buffer);
}
Packet packet; Packet packet;
bool result = packetParser.parsePacket(buffer, packet); bool result = packetParser.parsePacket(buffer, packet);
if (result) { if (result) {
if (packetCallback != nullptr) { if (packetReceivedCallback != nullptr) {
packetCallback(&packet); packetReceivedCallback(&packet);
} }
} }
} }
void RFPowerView::processInvalidBuffer(const uint8_t *buffer) { void RFPowerView::processInvalidBuffer(const uint8_t *buffer) {
if (invalidBufferReceivedCallback != nullptr) {
invalidBufferReceivedCallback(buffer);
}
} }
void RFPowerView::setPacketCallback(std::function<void(const Packet*)> callback) { void RFPowerView::setPacketReceivedCallback(std::function<void(const Packet*)> callback) {
packetCallback = callback; packetReceivedCallback = callback;
}
void RFPowerView::setValidBufferReceivedCallback(std::function<void(const uint8_t*)> callback) {
validBufferReceivedCallback = callback;
}
void RFPowerView::setInvalidBufferReceivedCallback(std::function<void(const uint8_t*)> callback) {
invalidBufferReceivedCallback = callback;
} }
bool RFPowerView::sendPacket(const Packet* packet) { bool RFPowerView::sendPacket(const Packet* packet) {

View File

@@ -0,0 +1,85 @@
#include <unity.h>
#include <Arduino.h>
#include "PacketCRC.h"
void run_calculate_test(const uint8_t *packet_data, const uint16_t expected_checksum)
{
PacketCRC packetCRC;
uint16_t actual_checksum = packetCRC.calculate(packet_data);
TEST_ASSERT_EQUAL_UINT16(expected_checksum, actual_checksum);
}
void test_calculate_withDataLengthOf15()
{
const uint8_t packet_data[] = {0xC0, 0x0F, 0x00, 0x05, 0xA1, 0xFF, 0xFF, 0x00, 0x00, 0x86, 0x04, 0xFF, 0x00, 0x00, 0x53, 0x47, 0x1B};
const uint16_t expected_checksum = 0x446B;
run_calculate_test(packet_data, expected_checksum);
}
void test_calculate_withDataLengthOf17()
{
const uint8_t packet_data[] = {0xC0, 0x11, 0x00, 0x05, 0xD7, 0xFF, 0xFF, 0x36, 0x9E, 0x86, 0x06, 0xB3, 0x04, 0x00, 0x36, 0x9E, 0x52, 0x53, 0x00};
const uint16_t expected_checksum = 0xE04C;
run_calculate_test(packet_data, expected_checksum);
}
void test_calculate_withDataLengthOf19()
{
const uint8_t packet_data[] = {0xC0, 0x13, 0x00, 0x05, 0xDD, 0xFF, 0xFF, 0x00, 0x00, 0x86, 0x05, 0x36, 0x4E, 0xF1, 0x00, 0x00, 0x3F, 0x5A, 0x02, 0x3F, 0x42};
const uint16_t expected_checksum = 0x9BD3;
run_calculate_test(packet_data, expected_checksum);
}
void test_calculate_withDataLengthOf20()
{
const uint8_t packet_data[] = {0xC0, 0x14, 0x10, 0x05, 0x59, 0xFF, 0xFF, 0x4E, 0xF1, 0x86, 0x05, 0xC2, 0x00, 0x00, 0x4E, 0xF1, 0x21, 0x5A, 0x03, 0x21, 0x42, 0x9C};
const uint16_t expected_checksum = 0x4A8B;
run_calculate_test(packet_data, expected_checksum);
}
void test_calculate_withDataLengthOf21()
{
const uint8_t packet_data[] = {0xC0, 0x15, 0x10, 0x05, 0xEA, 0xFF, 0xFF, 0x4E, 0xF1, 0x86, 0x05, 0x24, 0x00, 0x00, 0x4E, 0xF1, 0x21, 0x46, 0x4E, 0x98, 0x07, 0x08, 0x01};
const uint16_t expected_checksum = 0x9887;
run_calculate_test(packet_data, expected_checksum);
}
void test_calculate_withDataLengthOf25()
{
const uint8_t packet_data[] = {0xC0, 0x19, 0x00, 0x05, 0x47, 0xFF, 0xFF, 0x00, 0x00, 0x86, 0x05, 0x3D, 0x4E, 0xF1, 0x00, 0x00, 0x3F, 0x5A, 0x02, 0x3F, 0x50, 0x02, 0x3F, 0x4D, 0x02, 0x3F, 0x54};
const uint16_t expected_checksum = 0x8318;
run_calculate_test(packet_data, expected_checksum);
}
int runUnityTests(void)
{
UNITY_BEGIN();
RUN_TEST(test_calculate_withDataLengthOf15);
RUN_TEST(test_calculate_withDataLengthOf17);
RUN_TEST(test_calculate_withDataLengthOf19);
RUN_TEST(test_calculate_withDataLengthOf20);
RUN_TEST(test_calculate_withDataLengthOf21);
RUN_TEST(test_calculate_withDataLengthOf25);
return UNITY_END();
}
/**
* For Arduino framework
*/
void setup()
{
// Wait ~2 seconds before the Unity test runner
// establishes connection with a board Serial interface
delay(2000);
runUnityTests();
}
void loop() {}

View File

@@ -0,0 +1,68 @@
#include <unity.h>
#include <Arduino.h>
#include "PacketParser.h"
void run_parse_test(const uint8_t *packet_data, Packet& packet)
{
PacketParser packetParser;
bool result = packetParser.parsePacket(packet_data, packet);
TEST_ASSERT_TRUE(result);
}
void test_parse_stop()
{
const uint8_t packet_data[] = {0xC0, 0x11, 0x00, 0x05, 0x6C, 0xFF, 0xFF, 0x36, 0x9E, 0x86, 0x06, 0x3C, 0x04, 0x00, 0x36, 0x9E, 0x52, 0x53, 0x00};
Packet packet;
run_parse_test(packet_data, packet);
TEST_ASSERT_TRUE(packet.type == PacketType::STOP);
}
void test_parse_close()
{
const uint8_t packet_data[] = {0xC0, 0x11, 0x00, 0x05, 0x6C, 0xFF, 0xFF, 0x36, 0x9E, 0x86, 0x06, 0x3C, 0x04, 0x00, 0x36, 0x9E, 0x52, 0x44, 0x00};
Packet packet;
run_parse_test(packet_data, packet);
TEST_ASSERT_TRUE(packet.type == PacketType::CLOSE);
}
void test_parse_open()
{
const uint8_t packet_data[] = {0xC0, 0x11, 0x00, 0x05, 0x6C, 0xFF, 0xFF, 0x36, 0x9E, 0x86, 0x06, 0x3C, 0x04, 0x00, 0x36, 0x9E, 0x52, 0x55, 0x00};
Packet packet;
run_parse_test(packet_data, packet);
TEST_ASSERT_TRUE(packet.type == PacketType::OPEN);
}
int runParseUnityTests(void)
{
UNITY_BEGIN();
RUN_TEST(test_parse_stop);
RUN_TEST(test_parse_close);
RUN_TEST(test_parse_open);
return UNITY_END();
}
/**
* For Arduino framework
*/
void setup()
{
// Wait ~2 seconds before the Unity test runner
// establishes connection with a board Serial interface
delay(2000);
runParseUnityTests();
}
void loop() {}