Replace inverter_transaction with new command classes
This commit is contained in:
parent
4daa121663
commit
4413b603e3
@ -1,5 +1,6 @@
|
||||
#include "HoymilesRadio.h"
|
||||
#include "Hoymiles.h"
|
||||
#include "commands/RequestFrameCommand.h"
|
||||
#include "crc.h"
|
||||
#include <Every.h>
|
||||
#include <FunctionalInterrupt.h>
|
||||
@ -85,16 +86,17 @@ void HoymilesRadio::loop()
|
||||
|
||||
if (_busyFlag && _rxTimeout.occured()) {
|
||||
Serial.println(F("RX Period End"));
|
||||
std::shared_ptr<InverterAbstract> inv = Hoymiles.getInverterBySerial(currentTransaction.target.u64);
|
||||
std::shared_ptr<InverterAbstract> inv = Hoymiles.getInverterBySerial(_commandQueue.front().get()->getTargetAddress());
|
||||
|
||||
if (nullptr != inv) {
|
||||
uint8_t verifyResult = inv->verifyAllFragments();
|
||||
if (verifyResult == FRAGMENT_ALL_MISSING) {
|
||||
if (currentTransaction.sendCount < MAX_RESEND_COUNT) {
|
||||
if (_commandQueue.front().get()->getSendCount() < MAX_RESEND_COUNT) {
|
||||
Serial.println(F("Nothing received, resend whole request"));
|
||||
sendLastPacketAgain();
|
||||
} else {
|
||||
Serial.println(F("Nothing received, resend count exeeded"));
|
||||
_commandQueue.pop();
|
||||
_busyFlag = false;
|
||||
}
|
||||
|
||||
@ -115,18 +117,19 @@ void HoymilesRadio::loop()
|
||||
} else {
|
||||
// Successfull received all packages
|
||||
Serial.println(F("Success"));
|
||||
_commandQueue.pop();
|
||||
_busyFlag = false;
|
||||
}
|
||||
}
|
||||
} else if (!_busyFlag) {
|
||||
// Currently in idle mode --> send packet if one is in the queue
|
||||
if (!_txBuffer.empty()) {
|
||||
inverter_transaction_t* t = _txBuffer.getBack();
|
||||
auto inv = Hoymiles.getInverterBySerial(t->target.u64);
|
||||
inv->setLastRequest(t->requestType);
|
||||
if (!_commandQueue.empty()) {
|
||||
CommandAbstract* cmd = _commandQueue.front().get();
|
||||
|
||||
auto inv = Hoymiles.getInverterBySerial(cmd->getTargetAddress());
|
||||
inv->setLastRequest(cmd->getRequestType());
|
||||
inv->clearRxFragmentBuffer();
|
||||
sendEsbPacket(t->target, t->mainCmd, t->subCmd, t->payload, t->len, t->timeout);
|
||||
_txBuffer.popBack();
|
||||
sendEsbPacket(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -207,102 +210,51 @@ serial_u HoymilesRadio::convertSerialToRadioId(serial_u serial)
|
||||
return radioId;
|
||||
}
|
||||
|
||||
void HoymilesRadio::convertSerialToPacketId(uint8_t buffer[], serial_u serial)
|
||||
{
|
||||
buffer[3] = serial.b[0];
|
||||
buffer[2] = serial.b[1];
|
||||
buffer[1] = serial.b[2];
|
||||
buffer[0] = serial.b[3];
|
||||
}
|
||||
|
||||
bool HoymilesRadio::checkFragmentCrc(fragment_t* fragment)
|
||||
{
|
||||
uint8_t crc = crc8(fragment->fragment, fragment->len - 1);
|
||||
return (crc == fragment->fragment[fragment->len - 1]);
|
||||
}
|
||||
|
||||
void HoymilesRadio::sendEsbPacket(serial_u target, uint8_t mainCmd, uint8_t subCmd, uint8_t payload[], uint8_t len, uint32_t timeout, bool resend)
|
||||
void HoymilesRadio::sendEsbPacket(CommandAbstract* cmd)
|
||||
{
|
||||
static uint8_t txBuffer[MAX_RF_PAYLOAD_SIZE];
|
||||
cmd->incrementSendCount();
|
||||
|
||||
if (10 + currentTransaction.len + 1 > MAX_RF_PAYLOAD_SIZE) {
|
||||
Serial.printf("FATAL: (%s, %d) payload too large\n", __FILE__, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!resend) {
|
||||
currentTransaction.sendCount = 0;
|
||||
currentTransaction.target = target;
|
||||
currentTransaction.mainCmd = mainCmd;
|
||||
currentTransaction.target = target;
|
||||
currentTransaction.subCmd = subCmd;
|
||||
memcpy(currentTransaction.payload, payload, len);
|
||||
currentTransaction.len = len;
|
||||
currentTransaction.timeout = timeout;
|
||||
} else {
|
||||
currentTransaction.sendCount++;
|
||||
}
|
||||
|
||||
memset(txBuffer, 0, MAX_RF_PAYLOAD_SIZE);
|
||||
|
||||
txBuffer[0] = currentTransaction.mainCmd;
|
||||
convertSerialToPacketId(&txBuffer[1], currentTransaction.target); // 4 byte long
|
||||
convertSerialToPacketId(&txBuffer[5], DtuSerial()); // 4 byte long
|
||||
txBuffer[9] = currentTransaction.subCmd;
|
||||
|
||||
memcpy(&txBuffer[10], currentTransaction.payload, currentTransaction.len);
|
||||
txBuffer[10 + currentTransaction.len] = crc8(txBuffer, 10 + currentTransaction.len);
|
||||
cmd->setRouterAddress(DtuSerial().u64);
|
||||
|
||||
_radio->stopListening();
|
||||
_radio->setChannel(getTxNxtChannel());
|
||||
openWritingPipe(currentTransaction.target);
|
||||
|
||||
serial_u s;
|
||||
s.u64 = cmd->getTargetAddress();
|
||||
openWritingPipe(s);
|
||||
_radio->setRetries(3, 15);
|
||||
|
||||
dumpBuf("TX ", txBuffer, 10 + currentTransaction.len + 1);
|
||||
_radio->write(txBuffer, 10 + currentTransaction.len + 1);
|
||||
cmd->dumpDataPayload(Serial);
|
||||
_radio->write(cmd->getDataPayload(), cmd->getDataSize());
|
||||
|
||||
_radio->setRetries(0, 0);
|
||||
openReadingPipe();
|
||||
_radio->setChannel(getRxNxtChannel());
|
||||
_radio->startListening();
|
||||
_busyFlag = true;
|
||||
_rxTimeout.set(currentTransaction.timeout);
|
||||
}
|
||||
|
||||
bool HoymilesRadio::enqueTransaction(inverter_transaction_t* transaction)
|
||||
{
|
||||
if (!_txBuffer.full()) {
|
||||
inverter_transaction_t* t;
|
||||
t = _txBuffer.getFront();
|
||||
memcpy(t, transaction, sizeof(inverter_transaction_t));
|
||||
_txBuffer.pushFront(t);
|
||||
return true;
|
||||
} else {
|
||||
Serial.println(F("TX Buffer full"));
|
||||
}
|
||||
|
||||
return false;
|
||||
_rxTimeout.set(cmd->getTimeout());
|
||||
}
|
||||
|
||||
void HoymilesRadio::sendRetransmitPacket(uint8_t fragment_id)
|
||||
{
|
||||
sendEsbPacket(
|
||||
currentTransaction.target,
|
||||
currentTransaction.mainCmd,
|
||||
(uint8_t)(0x80 + fragment_id), 0, 0, 60);
|
||||
RequestFrameCommand cmd(
|
||||
_commandQueue.front().get()->getTargetAddress(),
|
||||
DtuSerial().u64,
|
||||
fragment_id);
|
||||
|
||||
sendEsbPacket(&cmd);
|
||||
}
|
||||
|
||||
void HoymilesRadio::sendLastPacketAgain()
|
||||
{
|
||||
sendEsbPacket(currentTransaction.target, 0, 0, 0, 0, 60, true);
|
||||
}
|
||||
|
||||
void HoymilesRadio::u32CpyLittleEndian(uint8_t dest[], uint32_t src)
|
||||
{
|
||||
dest[0] = ((src >> 24) & 0xff);
|
||||
dest[1] = ((src >> 16) & 0xff);
|
||||
dest[2] = ((src >> 8) & 0xff);
|
||||
dest[3] = ((src)&0xff);
|
||||
CommandAbstract* cmd = _commandQueue.front().get();
|
||||
sendEsbPacket(cmd);
|
||||
}
|
||||
|
||||
void HoymilesRadio::dumpBuf(const char* info, uint8_t buf[], uint8_t len)
|
||||
|
||||
@ -2,16 +2,18 @@
|
||||
|
||||
#include "CircularBuffer.h"
|
||||
#include "TimeoutHelper.h"
|
||||
#include "commands/CommandAbstract.h"
|
||||
#include "types.h"
|
||||
#include <RF24.h>
|
||||
#include <memory>
|
||||
#include <nRF24L01.h>
|
||||
#include <queue>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// number of fragments hold in buffer
|
||||
#define FRAGMENT_BUFFER_SIZE 30
|
||||
|
||||
#define TX_BUFFER_SIZE 5
|
||||
|
||||
#define MAX_RESEND_COUNT 3
|
||||
|
||||
#ifndef HOYMILES_PIN_MISO
|
||||
@ -48,17 +50,20 @@ public:
|
||||
void setDtuSerial(uint64_t serial);
|
||||
|
||||
bool isIdle();
|
||||
void sendEsbPacket(serial_u target, uint8_t mainCmd, uint8_t subCmd, uint8_t payload[], uint8_t len, uint32_t timeout, bool resend = false);
|
||||
void sendEsbPacket(CommandAbstract* cmd);
|
||||
void sendRetransmitPacket(uint8_t fragment_id);
|
||||
void sendLastPacketAgain();
|
||||
bool enqueTransaction(inverter_transaction_t* transaction);
|
||||
|
||||
static void u32CpyLittleEndian(uint8_t dest[], uint32_t src);
|
||||
template <typename T>
|
||||
T* enqueCommand()
|
||||
{
|
||||
_commandQueue.push(make_shared<T>());
|
||||
return static_cast<T*>(_commandQueue.back().get());
|
||||
}
|
||||
|
||||
private:
|
||||
void ARDUINO_ISR_ATTR handleIntr();
|
||||
static serial_u convertSerialToRadioId(serial_u serial);
|
||||
static void convertSerialToPacketId(uint8_t buffer[], serial_u serial);
|
||||
uint8_t getRxNxtChannel();
|
||||
uint8_t getTxNxtChannel();
|
||||
void switchRxCh();
|
||||
@ -84,6 +89,5 @@ private:
|
||||
|
||||
bool _busyFlag = false;
|
||||
|
||||
inverter_transaction_t currentTransaction;
|
||||
CircularBuffer<inverter_transaction_t, TX_BUFFER_SIZE> _txBuffer;
|
||||
queue<shared_ptr<CommandAbstract>> _commandQueue;
|
||||
};
|
||||
@ -1,6 +1,7 @@
|
||||
#include "HM_Abstract.h"
|
||||
#include "HoymilesRadio.h"
|
||||
#include "crc.h"
|
||||
#include "commands/AlarmDataCommand.h"
|
||||
#include "commands/RealTimeRunDataCommand.h"
|
||||
|
||||
HM_Abstract::HM_Abstract(uint64_t serial)
|
||||
: InverterAbstract(serial) {};
|
||||
@ -15,29 +16,10 @@ bool HM_Abstract::sendStatsRequest(HoymilesRadio* radio)
|
||||
time_t now;
|
||||
time(&now);
|
||||
|
||||
inverter_transaction_t payload;
|
||||
RealTimeRunDataCommand* cmd = radio->enqueCommand<RealTimeRunDataCommand>();
|
||||
cmd->setTime(now);
|
||||
cmd->setTargetAddress(serial());
|
||||
|
||||
memset(payload.payload, 0, MAX_RF_PAYLOAD_SIZE);
|
||||
|
||||
payload.target.u64 = serial();
|
||||
payload.mainCmd = 0x15;
|
||||
payload.subCmd = 0x80;
|
||||
payload.timeout = 200;
|
||||
payload.len = 16;
|
||||
|
||||
payload.payload[0] = 0x0b;
|
||||
payload.payload[1] = 0x00;
|
||||
|
||||
HoymilesRadio::u32CpyLittleEndian(&payload.payload[2], now); // sets the 4 following elements {2, 3, 4, 5}
|
||||
payload.payload[9] = 0x05;
|
||||
|
||||
uint16_t crc = crc16(&payload.payload[0], 14);
|
||||
payload.payload[14] = (crc >> 8) & 0xff;
|
||||
payload.payload[15] = (crc)&0xff;
|
||||
|
||||
payload.requestType = RequestType::Stats;
|
||||
|
||||
radio->enqueTransaction(&payload);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -59,27 +41,9 @@ bool HM_Abstract::sendAlarmLogRequest(HoymilesRadio* radio)
|
||||
time_t now;
|
||||
time(&now);
|
||||
|
||||
inverter_transaction_t payload;
|
||||
AlarmDataCommand* cmd = radio->enqueCommand<AlarmDataCommand>();
|
||||
cmd->setTime(now);
|
||||
cmd->setTargetAddress(serial());
|
||||
|
||||
memset(payload.payload, 0, MAX_RF_PAYLOAD_SIZE);
|
||||
|
||||
payload.target.u64 = serial();
|
||||
payload.mainCmd = 0x15;
|
||||
payload.subCmd = 0x80;
|
||||
payload.timeout = 200;
|
||||
payload.len = 16;
|
||||
|
||||
payload.payload[0] = 0x11;
|
||||
payload.payload[1] = 0x00;
|
||||
|
||||
HoymilesRadio::u32CpyLittleEndian(&payload.payload[2], now); // sets the 4 following elements {2, 3, 4, 5}
|
||||
|
||||
uint16_t crc = crc16(&payload.payload[0], 14);
|
||||
payload.payload[14] = (crc >> 8) & 0xff;
|
||||
payload.payload[15] = (crc)&0xff;
|
||||
|
||||
payload.requestType = RequestType::AlarmLog;
|
||||
|
||||
radio->enqueTransaction(&payload);
|
||||
return true;
|
||||
}
|
||||
@ -20,14 +20,3 @@ enum class RequestType {
|
||||
Stats,
|
||||
AlarmLog
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
serial_u target;
|
||||
RequestType requestType = RequestType::None;
|
||||
uint8_t mainCmd;
|
||||
uint8_t subCmd;
|
||||
uint8_t payload[MAX_RF_PAYLOAD_SIZE];
|
||||
uint8_t len;
|
||||
uint32_t timeout;
|
||||
uint8_t sendCount;
|
||||
} inverter_transaction_t;
|
||||
Loading…
Reference in New Issue
Block a user