WIP: Making RFPowerView class
This commit is contained in:
@@ -2,53 +2,14 @@
|
|||||||
#define PACKET_PARSER_H
|
#define PACKET_PARSER_H
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <variant>
|
#include "PacketTypes.h"
|
||||||
|
|
||||||
// Define packet types
|
|
||||||
enum class PacketType {
|
|
||||||
OPEN,
|
|
||||||
CLOSE,
|
|
||||||
STOP,
|
|
||||||
FIELDS,
|
|
||||||
FIELD_COMMAND,
|
|
||||||
UNKNOWN
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class FieldType {
|
|
||||||
VALUE,
|
|
||||||
SET,
|
|
||||||
FETCH,
|
|
||||||
UNKNOWN
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Field {
|
|
||||||
uint8_t identifier;
|
|
||||||
FieldType type;
|
|
||||||
bool hasValue;
|
|
||||||
std::variant<std::monostate, uint8_t, uint16_t> value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FieldsParameters {
|
|
||||||
std::vector<Field> fields;
|
|
||||||
};
|
|
||||||
|
|
||||||
using PacketParameters = std::variant<std::monostate, FieldsParameters>;
|
|
||||||
|
|
||||||
|
|
||||||
// Define Message structure
|
|
||||||
struct Packet {
|
|
||||||
uint16_t source;
|
|
||||||
uint16_t destination;
|
|
||||||
PacketType type;
|
|
||||||
PacketParameters parameters;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PacketParser {
|
class PacketParser {
|
||||||
public:
|
public:
|
||||||
PacketParser();
|
PacketParser();
|
||||||
~PacketParser();
|
~PacketParser();
|
||||||
|
|
||||||
bool parsePacket(const uint8_t *buffer, Packet& message);
|
bool parsePacket(const uint8_t *buffer, Packet& packet);
|
||||||
private:
|
private:
|
||||||
bool parseFields(const uint8_t *buffer, std::vector<Field>& fields);
|
bool parseFields(const uint8_t *buffer, std::vector<Field>& fields);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#define CIRCULAR_BUFFER_INT_SAFE
|
#define CIRCULAR_BUFFER_INT_SAFE
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <RF24.h>
|
#include <RF24.h>
|
||||||
#include <CircularBuffer.h>
|
#include <CircularBuffer.h>
|
||||||
#include "PacketCRC.h"
|
#include "PacketCRC.h"
|
||||||
@@ -22,8 +23,8 @@ public:
|
|||||||
void loop();
|
void loop();
|
||||||
void read();
|
void read();
|
||||||
|
|
||||||
void setPacketCallback(void (*callback)(const uint8_t *buffer));
|
void setPacketCallback(std::function<void(const uint8_t*)> callback);
|
||||||
void setInvalidPacketCallback(void (*callback)(const uint8_t *buffer));
|
void setInvalidPacketCallback(std::function<void(const uint8_t*)> callback);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RF24 *radio;
|
RF24 *radio;
|
||||||
@@ -34,8 +35,8 @@ private:
|
|||||||
CircularBuffer<uint8_t*, EMPTY_BUFFER_COUNT> freeBuffers;
|
CircularBuffer<uint8_t*, EMPTY_BUFFER_COUNT> freeBuffers;
|
||||||
CircularBuffer<uint8_t*, VALID_BUFFER_COUNT> receivedBuffers;
|
CircularBuffer<uint8_t*, VALID_BUFFER_COUNT> receivedBuffers;
|
||||||
|
|
||||||
void (*packetCallback)(const uint8_t *buffer);
|
std::function<void(const uint8_t*)> packetCallback;
|
||||||
void (*invalidPacketCallback)(const uint8_t *buffer);
|
std::function<void(const uint8_t*)> invalidPacketCallback;
|
||||||
|
|
||||||
bool isSanePacket(uint8_t *buffer);
|
bool isSanePacket(uint8_t *buffer);
|
||||||
bool isValidPacket(uint8_t *buffer);
|
bool isValidPacket(uint8_t *buffer);
|
||||||
|
|||||||
47
include/PacketTypes.h
Normal file
47
include/PacketTypes.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#ifndef PACKET_TYPES_H
|
||||||
|
#define PACKET_TYPES_H
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
// Define packet types
|
||||||
|
enum class PacketType {
|
||||||
|
OPEN,
|
||||||
|
CLOSE,
|
||||||
|
STOP,
|
||||||
|
FIELDS,
|
||||||
|
FIELD_COMMAND,
|
||||||
|
UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class FieldType {
|
||||||
|
VALUE,
|
||||||
|
SET,
|
||||||
|
FETCH,
|
||||||
|
UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Field {
|
||||||
|
uint8_t identifier;
|
||||||
|
FieldType type;
|
||||||
|
bool hasValue;
|
||||||
|
std::variant<std::monostate, uint8_t, uint16_t> value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FieldsParameters {
|
||||||
|
std::vector<Field> fields;
|
||||||
|
};
|
||||||
|
|
||||||
|
using PacketParameters = std::variant<std::monostate, FieldsParameters>;
|
||||||
|
|
||||||
|
|
||||||
|
// Define Message structure
|
||||||
|
struct Packet {
|
||||||
|
uint16_t source;
|
||||||
|
uint16_t destination;
|
||||||
|
PacketType type;
|
||||||
|
PacketParameters parameters;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // PACKET_TYPES_H
|
||||||
38
include/RFPowerView.h
Normal file
38
include/RFPowerView.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef RFPOWERVIEW_H
|
||||||
|
#define RFPOWERVIEW_H
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <RF24.h>
|
||||||
|
#include "PacketReceiver.h"
|
||||||
|
#include "PacketParser.h"
|
||||||
|
#include "PacketTypes.h"
|
||||||
|
|
||||||
|
#define DEFAULT_RF_CHANNEL (7) //this is the channel HD shades use
|
||||||
|
#define DEFAULT_RF_DATARATE (RF24_1MBPS) //this is the speed HD shades use
|
||||||
|
|
||||||
|
class RFPowerView {
|
||||||
|
public:
|
||||||
|
RFPowerView(
|
||||||
|
uint8_t cePin,
|
||||||
|
uint8_t csPin,
|
||||||
|
uint8_t irqPin,
|
||||||
|
uint16_t rfID
|
||||||
|
);
|
||||||
|
|
||||||
|
bool begin();
|
||||||
|
void loop();
|
||||||
|
void startListening();
|
||||||
|
private:
|
||||||
|
RF24 radio;
|
||||||
|
PacketReceiver packetReceiver;
|
||||||
|
PacketParser packetParser;
|
||||||
|
uint8_t irqPin;
|
||||||
|
uint8_t rfID[2];
|
||||||
|
|
||||||
|
void interruptHandler();
|
||||||
|
|
||||||
|
void processPacketBuffer(const uint8_t *buffer);
|
||||||
|
void processInvalidPacketBuffer(const uint8_t *buffer);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RFPOWERVIEW_H
|
||||||
@@ -8,33 +8,33 @@ PacketParser::~PacketParser()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PacketParser::parsePacket(const uint8_t *buffer, Packet& message)
|
bool PacketParser::parsePacket(const uint8_t *buffer, Packet& packet)
|
||||||
{
|
{
|
||||||
message.source = (uint16_t)(buffer[14] << 8 | buffer[15]);
|
packet.source = (uint16_t)(buffer[14] << 8 | buffer[15]);
|
||||||
message.destination = (uint16_t)(buffer[12] << 8 | buffer[13]);
|
packet.destination = (uint16_t)(buffer[12] << 8 | buffer[13]);
|
||||||
|
|
||||||
if (buffer[16] == 0x52 && buffer[17] == 0x53) {
|
if (buffer[16] == 0x52 && buffer[17] == 0x53) {
|
||||||
message.type = PacketType::STOP;
|
packet.type = PacketType::STOP;
|
||||||
message.parameters = std::monostate{};
|
packet.parameters = std::monostate{};
|
||||||
} else if (buffer[16] == 0x52 && buffer[17] == 0x44) {
|
} else if (buffer[16] == 0x52 && buffer[17] == 0x44) {
|
||||||
message.type = PacketType::CLOSE;
|
packet.type = PacketType::CLOSE;
|
||||||
message.parameters = std::monostate{};
|
packet.parameters = std::monostate{};
|
||||||
} else if (buffer[16] == 0x52 && buffer[17] == 0x55) {
|
} else if (buffer[16] == 0x52 && buffer[17] == 0x55) {
|
||||||
message.type = PacketType::OPEN;
|
packet.type = PacketType::OPEN;
|
||||||
message.parameters = std::monostate{};
|
packet.parameters = std::monostate{};
|
||||||
} else if (buffer[16] == 0x21 && buffer[17] == 0x5A) {
|
} else if (buffer[16] == 0x21 && buffer[17] == 0x5A) {
|
||||||
message.type = PacketType::FIELDS;
|
packet.type = PacketType::FIELDS;
|
||||||
std::vector<Field> fields;
|
std::vector<Field> fields;
|
||||||
parseFields(buffer, fields);
|
parseFields(buffer, fields);
|
||||||
message.parameters = FieldsParameters{fields};
|
packet.parameters = FieldsParameters{fields};
|
||||||
} else if (buffer[16] == 0x3F && buffer[17] == 0x5A) {
|
} else if (buffer[16] == 0x3F && buffer[17] == 0x5A) {
|
||||||
message.type = PacketType::FIELD_COMMAND;
|
packet.type = PacketType::FIELD_COMMAND;
|
||||||
std::vector<Field> fields;
|
std::vector<Field> fields;
|
||||||
parseFields(buffer, fields);
|
parseFields(buffer, fields);
|
||||||
message.parameters = FieldsParameters{fields};
|
packet.parameters = FieldsParameters{fields};
|
||||||
} else {
|
} else {
|
||||||
message.type = PacketType::UNKNOWN;
|
packet.type = PacketType::UNKNOWN;
|
||||||
message.parameters = std::monostate{};
|
packet.parameters = std::monostate{};
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "PacketReceiver.h"
|
#include "PacketReceiver.h"
|
||||||
|
|
||||||
PacketReceiver::PacketReceiver(RF24 *radio) : radio(radio), packetCallback(nullptr), invalidPacketCallback(nullptr) {
|
PacketReceiver::PacketReceiver(RF24 *radio) : radio(radio) {
|
||||||
for (int i = 0; i < TOTAL_BUFFER_COUNT; i++) {
|
for (int i = 0; i < TOTAL_BUFFER_COUNT; i++) {
|
||||||
if (!freeBuffers.isFull()) {
|
if (!freeBuffers.isFull()) {
|
||||||
freeBuffers.push(buffers[i]);
|
freeBuffers.push(buffers[i]);
|
||||||
@@ -69,11 +69,11 @@ void PacketReceiver::read() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketReceiver::setPacketCallback(void (*callback)(const uint8_t *buffer)) {
|
void PacketReceiver::setPacketCallback(std::function<void(const uint8_t*)> callback) {
|
||||||
this->packetCallback = callback;
|
this->packetCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketReceiver::setInvalidPacketCallback(void (*callback)(const uint8_t *buffer))
|
void PacketReceiver::setInvalidPacketCallback(std::function<void(const uint8_t*)> callback)
|
||||||
{
|
{
|
||||||
this->invalidPacketCallback = callback;
|
this->invalidPacketCallback = callback;
|
||||||
}
|
}
|
||||||
|
|||||||
63
src/RFPowerView.cpp
Normal file
63
src/RFPowerView.cpp
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#include "RFPowerView.h"
|
||||||
|
#include <FunctionalInterrupt.h>
|
||||||
|
|
||||||
|
RFPowerView::RFPowerView(uint8_t cePin, uint8_t csPin, uint8_t irqPin, uint16_t rfID) :
|
||||||
|
radio(cePin, csPin),
|
||||||
|
packetReceiver(&radio),
|
||||||
|
irqPin(irqPin),
|
||||||
|
rfID{static_cast<uint8_t>(rfID & 0xFF), static_cast<uint8_t>(rfID >> 8)} {}
|
||||||
|
|
||||||
|
bool RFPowerView::begin() {
|
||||||
|
if (!radio.begin()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
packetReceiver.setPacketCallback([this](const uint8_t* buffer) { this->processPacketBuffer(buffer); });
|
||||||
|
packetReceiver.setInvalidPacketCallback([this](const uint8_t* buffer) { this->processInvalidPacketBuffer(buffer); });
|
||||||
|
|
||||||
|
startListening();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RFPowerView::loop() {
|
||||||
|
packetReceiver.loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RFPowerView::startListening() {
|
||||||
|
radio.setChannel(DEFAULT_RF_CHANNEL);
|
||||||
|
radio.setDataRate(DEFAULT_RF_DATARATE);
|
||||||
|
radio.setAutoAck(false);
|
||||||
|
radio.disableCRC();
|
||||||
|
radio.setPayloadSize(32);
|
||||||
|
|
||||||
|
// TODO: Verify that putting this in begin() instead of startListening() works
|
||||||
|
pinMode(irqPin, INPUT);
|
||||||
|
|
||||||
|
radio.setAddressWidth(2);
|
||||||
|
radio.openReadingPipe(0, rfID);
|
||||||
|
|
||||||
|
radio.startListening();
|
||||||
|
Serial.println("Listening");
|
||||||
|
// TODO: Verify that putting this in being() instead of startListening() works
|
||||||
|
attachInterrupt(digitalPinToInterrupt(irqPin), std::bind(&RFPowerView::interruptHandler, this), FALLING);
|
||||||
|
interrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RFPowerView::interruptHandler() {
|
||||||
|
packetReceiver.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RFPowerView::processPacketBuffer(const uint8_t *buffer) {
|
||||||
|
Packet packet;
|
||||||
|
bool result = packetParser.parsePacket(buffer, packet);
|
||||||
|
if (result) {
|
||||||
|
Serial.print("Parsed packet! ");
|
||||||
|
Serial.print((int)packet.type);
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RFPowerView::processInvalidPacketBuffer(const uint8_t *buffer) {
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user