Move packet building and sending logic out of main.cpp
This commit is contained in:
84
lib/packet_builder/PacketBuilder.cpp
Normal file
84
lib/packet_builder/PacketBuilder.cpp
Normal file
@@ -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<Field> 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<Field> 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;
|
||||||
|
}
|
||||||
17
lib/packet_builder/PacketBuilder.h
Normal file
17
lib/packet_builder/PacketBuilder.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef PACKET_BUILDER_H
|
||||||
|
#define PACKET_BUILDER_H
|
||||||
|
|
||||||
|
#include <PacketTypes.h>
|
||||||
|
|
||||||
|
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
|
||||||
27
lib/packet_sender/PacketSender.cpp
Normal file
27
lib/packet_sender/PacketSender.cpp
Normal file
@@ -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;
|
||||||
|
}
|
||||||
20
lib/packet_sender/PacketSender.h
Normal file
20
lib/packet_sender/PacketSender.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef PACKET_SENDER_H
|
||||||
|
#define PACKET_SENDER_H
|
||||||
|
|
||||||
|
#include <RFPowerView.h>
|
||||||
|
#include <PacketTypes.h>
|
||||||
|
|
||||||
|
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
|
||||||
119
src/main.cpp
119
src/main.cpp
@@ -12,15 +12,14 @@
|
|||||||
#include "secrets.h"
|
#include "secrets.h"
|
||||||
#include "ShadeCommand.h"
|
#include "ShadeCommand.h"
|
||||||
#include "PositionWatcher.h"
|
#include "PositionWatcher.h"
|
||||||
|
#include "PacketBuilder.h"
|
||||||
|
#include "PacketSender.h"
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#define SER_BAUDRATE (115200)
|
#define SER_BAUDRATE (115200)
|
||||||
|
|
||||||
RFPowerView powerView(RF_CE_PIN, RF_CS_PIN, RF_IRQ_PIN, RF_ID);
|
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());
|
static std::mt19937 generator(std::chrono::system_clock::now().time_since_epoch().count());
|
||||||
|
|
||||||
std::string generate_client_id_suffix(int length) {
|
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);
|
client.publish(topic, message);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
PacketBuilder packetBuilder;
|
||||||
|
|
||||||
|
PacketSender packetSender(powerView);
|
||||||
|
|
||||||
void processPacket(const Packet*);
|
void processPacket(const Packet*);
|
||||||
void processCommandMessage(const String& topic, const String &payload);
|
void processCommandMessage(const String& topic, const String &payload);
|
||||||
void processSetPositionMessage(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 publishPosition(const std::string& shadeKey, const uint8_t position);
|
||||||
void publishState(const std::string& shadeKey, const String& state);
|
void publishState(const std::string& shadeKey, const String& state);
|
||||||
void publishBattery(const std::string& shadeKey, const uint8_t battery);
|
void publishBattery(const std::string& shadeKey, const uint8_t battery);
|
||||||
@@ -133,7 +129,7 @@ void loop() {
|
|||||||
if (std::holds_alternative<OpenCommand>(command)) {
|
if (std::holds_alternative<OpenCommand>(command)) {
|
||||||
auto openCommand = std::get<OpenCommand>(command);
|
auto openCommand = std::get<OpenCommand>(command);
|
||||||
Serial.printf("Open command received for shade 0x%04x\n", openCommand.shadeID);
|
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);
|
auto shade = shadeRepository.findById(openCommand.shadeID);
|
||||||
if (shade != nullptr) {
|
if (shade != nullptr) {
|
||||||
shade->state = "opening";
|
shade->state = "opening";
|
||||||
@@ -145,7 +141,7 @@ void loop() {
|
|||||||
} else if (std::holds_alternative<CloseCommand>(command)) {
|
} else if (std::holds_alternative<CloseCommand>(command)) {
|
||||||
auto closeCommand = std::get<CloseCommand>(command);
|
auto closeCommand = std::get<CloseCommand>(command);
|
||||||
Serial.printf("Close command received for shade 0x%04x\n", closeCommand.shadeID);
|
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);
|
auto shade = shadeRepository.findById(closeCommand.shadeID);
|
||||||
if (shade != nullptr) {
|
if (shade != nullptr) {
|
||||||
shade->state = "closing";
|
shade->state = "closing";
|
||||||
@@ -156,13 +152,13 @@ void loop() {
|
|||||||
} else if (std::holds_alternative<StopCommand>(command)) {
|
} else if (std::holds_alternative<StopCommand>(command)) {
|
||||||
auto stopCommand = std::get<StopCommand>(command);
|
auto stopCommand = std::get<StopCommand>(command);
|
||||||
Serial.printf("Stop command received for shade 0x%04x\n", stopCommand.shadeID);
|
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);
|
startPositionWatcher(stopCommand.shadeID, -1);
|
||||||
|
|
||||||
} else if (std::holds_alternative<SetPositionCommand>(command)) {
|
} else if (std::holds_alternative<SetPositionCommand>(command)) {
|
||||||
auto setPositionCommand = std::get<SetPositionCommand>(command);
|
auto setPositionCommand = std::get<SetPositionCommand>(command);
|
||||||
Serial.printf("Set Position command received for shade 0x%04x (%.2f)\n", setPositionCommand.shadeID, setPositionCommand.percentage);
|
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);
|
auto shade = shadeRepository.findById(setPositionCommand.shadeID);
|
||||||
if (shade != nullptr) {
|
if (shade != nullptr) {
|
||||||
if (setPositionCommand.percentage > shade->lastPosition / 100.0f) {
|
if (setPositionCommand.percentage > shade->lastPosition / 100.0f) {
|
||||||
@@ -184,7 +180,7 @@ void loop() {
|
|||||||
|
|
||||||
for (auto& [shadeID, watcher] : positionWatchers) {
|
for (auto& [shadeID, watcher] : positionWatchers) {
|
||||||
if (watcher.shouldFetch()) {
|
if (watcher.shouldFetch()) {
|
||||||
if (sendFetchPosition(shadeID)) {
|
if (packetSender.send(packetBuilder.buildFetchPositionPacket(shadeID))) {
|
||||||
watcher.fetchQueued();
|
watcher.fetchQueued();
|
||||||
}
|
}
|
||||||
} else if (!watcher.isWatching()) {
|
} 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
|
// Update last rolling codes each time a packet from a real hub is detected
|
||||||
if (source == 0x0000) {
|
if (source == 0x0000) {
|
||||||
Serial.println("Updating rolling codes");
|
Serial.println("Updating rolling codes");
|
||||||
lastRollingCode1 = packet->rollingCode1;
|
packetSender.setLastRollingCodes(packet->rollingCode1, packet->rollingCode2);
|
||||||
lastRollingCode2 = packet->rollingCode2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet->type == PacketType::FIELDS) {
|
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<Field> 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<Field> 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) {
|
void startPositionWatcher(uint16_t shadeID, uint8_t targetValue) {
|
||||||
auto& watcher = positionWatchers.try_emplace(shadeID).first->second;
|
auto& watcher = positionWatchers.try_emplace(shadeID).first->second;
|
||||||
watcher.start(targetValue);
|
watcher.start(targetValue);
|
||||||
|
|||||||
Reference in New Issue
Block a user