diff --git a/lib/packet_builder/PacketBuilder.cpp b/lib/packet_builder/PacketBuilder.cpp new file mode 100644 index 0000000..6ead493 --- /dev/null +++ b/lib/packet_builder/PacketBuilder.cpp @@ -0,0 +1,84 @@ +#include "PacketBuilder.h" + +PacketBuilder::PacketBuilder() +{ +} + +Packet PacketBuilder::buildOpenPacket(uint16_t destination) +{ + Packet packet; + auto header = UnicastHeader{}; + header.destination = destination; + header.source = 0x0000; + packet.header = header; + packet.type = PacketType::OPEN; + + return packet; +} + +Packet PacketBuilder::buildClosePacket(uint16_t destination) +{ + Packet packet; + auto header = UnicastHeader{}; + header.destination = destination; + header.source = 0x0000; + packet.header = header; + packet.type = PacketType::CLOSE; + + return packet; +} + +Packet PacketBuilder::buildStopPacket(uint16_t destination) +{ + Packet packet; + auto header = UnicastHeader{}; + header.destination = destination; + header.source = 0x0000; + packet.header = header; + packet.type = PacketType::STOP; + + return packet; +} + +Packet PacketBuilder::buildSetPositionPacket(uint16_t destination, float percentage) +{ + Packet packet; + auto header = UnicastHeader{}; + header.destination = destination; + header.source = 0x0000; + packet.header = header; + packet.type = PacketType::FIELD_COMMAND; + + std::vector fields; + + uint8_t identifier = 0x50; // position + FieldType type = FieldType::SET; + uint16_t position = (uint16_t)(0xFFFF * percentage); + fields.push_back(Field{identifier, type, true, position}); + + packet.parameters = FieldsParameters{fields}; + + return packet; +} + +Packet PacketBuilder::buildFetchPositionPacket(uint16_t destination) +{ + Packet packet; + auto header = UnicastHeader{}; + header.destination = destination; + header.source = 0x0000; + packet.header = header; + packet.type = PacketType::FIELD_COMMAND; + + std::vector fields; + + // position + fields.push_back(Field{0x50, FieldType::FETCH, false, std::monostate{}}); + + // battery + fields.push_back(Field{0x42, FieldType::FETCH, false, std::monostate{}}); + + packet.parameters = FieldsParameters{fields}; + + return packet; +} \ No newline at end of file diff --git a/lib/packet_builder/PacketBuilder.h b/lib/packet_builder/PacketBuilder.h new file mode 100644 index 0000000..78e76e7 --- /dev/null +++ b/lib/packet_builder/PacketBuilder.h @@ -0,0 +1,17 @@ +#ifndef PACKET_BUILDER_H +#define PACKET_BUILDER_H + +#include + +class PacketBuilder { +public: + PacketBuilder(); + + Packet buildOpenPacket(uint16_t destination); + Packet buildClosePacket(uint16_t destination); + Packet buildStopPacket(uint16_t destination); + Packet buildSetPositionPacket(uint16_t destination, float percentage); + Packet buildFetchPositionPacket(uint16_t destination); +}; + +#endif // PACKET_BUILDER_H diff --git a/lib/packet_sender/PacketSender.cpp b/lib/packet_sender/PacketSender.cpp new file mode 100644 index 0000000..3d7daf7 --- /dev/null +++ b/lib/packet_sender/PacketSender.cpp @@ -0,0 +1,27 @@ +#include "PacketSender.h" + +PacketSender::PacketSender(RFPowerView& powerView) : powerView(powerView) +{ +} + +bool PacketSender::send(Packet packet) +{ + Serial.println("Attempting to send a packet"); + packet.rollingCode1 = lastRollingCode1 + 1; + packet.rollingCode2 = lastRollingCode2 + 1; + + bool didSend = powerView.sendPacket(&packet); + if (!didSend) { + Serial.println("Failed to send"); + return false; + } else { + lastRollingCode1++; + lastRollingCode2++; + return true; + } +} + +void PacketSender::setLastRollingCodes(uint8_t code1, uint8_t code2) { + lastRollingCode1 = code1; + lastRollingCode2 = code2; +} diff --git a/lib/packet_sender/PacketSender.h b/lib/packet_sender/PacketSender.h new file mode 100644 index 0000000..d6fbebf --- /dev/null +++ b/lib/packet_sender/PacketSender.h @@ -0,0 +1,20 @@ +#ifndef PACKET_SENDER_H +#define PACKET_SENDER_H + +#include +#include + +class PacketSender { +public: + PacketSender(RFPowerView& powerView); + + bool send(Packet packet); + void setLastRollingCodes(uint8_t code1, uint8_t code2); +private: + RFPowerView& powerView; + + uint8_t lastRollingCode1 = 0x3D; + uint8_t lastRollingCode2 = 0x96; +}; + +#endif // PACKET_SENDER_H diff --git a/src/main.cpp b/src/main.cpp index 45f4dc4..cfd3c0e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,15 +12,14 @@ #include "secrets.h" #include "ShadeCommand.h" #include "PositionWatcher.h" +#include "PacketBuilder.h" +#include "PacketSender.h" #include #define SER_BAUDRATE (115200) RFPowerView powerView(RF_CE_PIN, RF_CS_PIN, RF_IRQ_PIN, RF_ID); -uint8_t lastRollingCode1 = 0x3D; -uint8_t lastRollingCode2 = 0x96; - static std::mt19937 generator(std::chrono::system_clock::now().time_since_epoch().count()); std::string generate_client_id_suffix(int length) { @@ -61,17 +60,14 @@ HADiscovery haDiscovery(topic_prefix.c_str(), [] (const char* topic, const char* client.publish(topic, message); }); +PacketBuilder packetBuilder; + +PacketSender packetSender(powerView); + void processPacket(const Packet*); void processCommandMessage(const String& topic, const String &payload); void processSetPositionMessage(const String& topic, const String &payload); -bool sendOpenPacket(uint16_t destination); -bool sendClosePacket(uint16_t destination); -bool sendStopPacket(uint16_t destination); -bool sendSetPosition(uint16_t destination, float percentage); -bool sendFetchPosition(uint16_t destination); -bool sendPacket(Packet *packet); - void publishPosition(const std::string& shadeKey, const uint8_t position); void publishState(const std::string& shadeKey, const String& state); void publishBattery(const std::string& shadeKey, const uint8_t battery); @@ -133,7 +129,7 @@ void loop() { if (std::holds_alternative(command)) { auto openCommand = std::get(command); Serial.printf("Open command received for shade 0x%04x\n", openCommand.shadeID); - if (sendOpenPacket(openCommand.shadeID)) { + if (packetSender.send(packetBuilder.buildOpenPacket(openCommand.shadeID))) { auto shade = shadeRepository.findById(openCommand.shadeID); if (shade != nullptr) { shade->state = "opening"; @@ -145,7 +141,7 @@ void loop() { } else if (std::holds_alternative(command)) { auto closeCommand = std::get(command); Serial.printf("Close command received for shade 0x%04x\n", closeCommand.shadeID); - if (sendClosePacket(closeCommand.shadeID)) { + if (packetSender.send(packetBuilder.buildClosePacket(closeCommand.shadeID))) { auto shade = shadeRepository.findById(closeCommand.shadeID); if (shade != nullptr) { shade->state = "closing"; @@ -156,13 +152,13 @@ void loop() { } else if (std::holds_alternative(command)) { auto stopCommand = std::get(command); Serial.printf("Stop command received for shade 0x%04x\n", stopCommand.shadeID); - sendStopPacket(stopCommand.shadeID); + packetSender.send(packetBuilder.buildStopPacket(stopCommand.shadeID)); startPositionWatcher(stopCommand.shadeID, -1); } else if (std::holds_alternative(command)) { auto setPositionCommand = std::get(command); Serial.printf("Set Position command received for shade 0x%04x (%.2f)\n", setPositionCommand.shadeID, setPositionCommand.percentage); - if (sendSetPosition(setPositionCommand.shadeID, setPositionCommand.percentage)) { + if (packetSender.send(packetBuilder.buildSetPositionPacket(setPositionCommand.shadeID, setPositionCommand.percentage))) { auto shade = shadeRepository.findById(setPositionCommand.shadeID); if (shade != nullptr) { if (setPositionCommand.percentage > shade->lastPosition / 100.0f) { @@ -184,7 +180,7 @@ void loop() { for (auto& [shadeID, watcher] : positionWatchers) { if (watcher.shouldFetch()) { - if (sendFetchPosition(shadeID)) { + if (packetSender.send(packetBuilder.buildFetchPositionPacket(shadeID))) { watcher.fetchQueued(); } } else if (!watcher.isWatching()) { @@ -239,8 +235,7 @@ void processPacket(const Packet *packet) { // Update last rolling codes each time a packet from a real hub is detected if (source == 0x0000) { Serial.println("Updating rolling codes"); - lastRollingCode1 = packet->rollingCode1; - lastRollingCode2 = packet->rollingCode2; + packetSender.setLastRollingCodes(packet->rollingCode1, packet->rollingCode2); } if (packet->type == PacketType::FIELDS) { @@ -296,96 +291,6 @@ void onConnectionEstablished() { }); } -bool sendOpenPacket(uint16_t destination) { - Packet packet; - auto header = UnicastHeader {}; - header.destination = destination; - header.source = 0x0000; - packet.header = header; - packet.type = PacketType::OPEN; - - return sendPacket(&packet); -} - -bool sendClosePacket(uint16_t destination) { - Packet packet; - auto header = UnicastHeader {}; - header.destination = destination; - header.source = 0x0000; - packet.header = header; - packet.type = PacketType::CLOSE; - - return sendPacket(&packet); -} - -bool sendStopPacket(uint16_t destination) { - Packet packet; - auto header = UnicastHeader {}; - header.destination = destination; - header.source = 0x0000; - packet.header = header; - packet.type = PacketType::STOP; - - return sendPacket(&packet); -} - -bool sendSetPosition(uint16_t destination, float percentage) { - Packet packet; - auto header = UnicastHeader {}; - header.destination = destination; - header.source = 0x0000; - packet.header = header; - packet.type = PacketType::FIELD_COMMAND; - - std::vector fields; - - uint8_t identifier = 0x50; // position - FieldType type = FieldType::SET; - uint16_t position = (uint16_t)(0xFFFF * percentage); - fields.push_back(Field{identifier, type, true, position}); - - packet.parameters = FieldsParameters {fields}; - - return sendPacket(&packet); -} - -bool sendFetchPosition(uint16_t destination) { - Packet packet; - auto header = UnicastHeader {}; - header.destination = destination; - header.source = 0x0000; - packet.header = header; - packet.type = PacketType::FIELD_COMMAND; - - std::vector fields; - - // position - fields.push_back(Field{0x50, FieldType::FETCH, false, std::monostate{}}); - - // battery - fields.push_back(Field{0x42, FieldType::FETCH, false, std::monostate{}}); - - packet.parameters = FieldsParameters {fields}; - - return sendPacket(&packet); -} - -bool sendPacket(Packet *packet) { - Serial.println("Attempting to send a packet"); - packet->rollingCode1 = lastRollingCode1 + 1; - packet->rollingCode2 = lastRollingCode2 + 1; - - bool didSend = powerView.sendPacket(packet); - if (!didSend) { - Serial.println("Failed to send"); - return false; - } else { - lastRollingCode1++; - lastRollingCode2++; - return true; - } -} - void startPositionWatcher(uint16_t shadeID, uint8_t targetValue) { auto& watcher = positionWatchers.try_emplace(shadeID).first->second; watcher.start(targetValue);