Remove RequestType and place handling of response in the command class

This commit is contained in:
Thomas Basler 2022-08-03 18:50:34 +02:00
parent a73707380f
commit 857e4a3671
18 changed files with 81 additions and 72 deletions

View File

@ -89,7 +89,8 @@ void HoymilesRadio::loop()
std::shared_ptr<InverterAbstract> inv = Hoymiles.getInverterBySerial(_commandQueue.front().get()->getTargetAddress()); std::shared_ptr<InverterAbstract> inv = Hoymiles.getInverterBySerial(_commandQueue.front().get()->getTargetAddress());
if (nullptr != inv) { if (nullptr != inv) {
uint8_t verifyResult = inv->verifyAllFragments(); CommandAbstract* cmd = _commandQueue.front().get();
uint8_t verifyResult = inv->verifyAllFragments(cmd);
if (verifyResult == FRAGMENT_ALL_MISSING) { if (verifyResult == FRAGMENT_ALL_MISSING) {
if (_commandQueue.front().get()->getSendCount() <= MAX_RESEND_COUNT) { if (_commandQueue.front().get()->getSendCount() <= MAX_RESEND_COUNT) {
Serial.println(F("Nothing received, resend whole request")); Serial.println(F("Nothing received, resend whole request"));
@ -127,7 +128,6 @@ void HoymilesRadio::loop()
CommandAbstract* cmd = _commandQueue.front().get(); CommandAbstract* cmd = _commandQueue.front().get();
auto inv = Hoymiles.getInverterBySerial(cmd->getTargetAddress()); auto inv = Hoymiles.getInverterBySerial(cmd->getTargetAddress());
inv->setLastRequest(cmd->getRequestType());
inv->clearRxFragmentBuffer(); inv->clearRxFragmentBuffer();
sendEsbPacket(cmd); sendEsbPacket(cmd);
} }

View File

@ -1,4 +1,5 @@
#include "AlarmDataCommand.h" #include "AlarmDataCommand.h"
#include "inverters/InverterAbstract.h"
AlarmDataCommand::AlarmDataCommand(uint64_t target_address, uint64_t router_address, time_t time) AlarmDataCommand::AlarmDataCommand(uint64_t target_address, uint64_t router_address, time_t time)
: MultiDataCommand(target_address, router_address) : MultiDataCommand(target_address, router_address)
@ -6,4 +7,16 @@ AlarmDataCommand::AlarmDataCommand(uint64_t target_address, uint64_t router_addr
setTime(time); setTime(time);
setDataType(0x11); setDataType(0x11);
setTimeout(200); setTimeout(200);
}
void AlarmDataCommand::handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id)
{
// Move all fragments into target buffer
uint8_t offs = 0;
inverter->EventLog()->clearBuffer();
for (uint8_t i = 0; i < max_fragment_id; i++) {
inverter->EventLog()->appendFragment(offs, fragment[i].fragment, fragment[i].len);
offs += (fragment[i].len);
}
inverter->EventLog()->setLastUpdate(millis());
} }

View File

@ -6,5 +6,5 @@ class AlarmDataCommand : public MultiDataCommand {
public: public:
AlarmDataCommand(uint64_t target_address = 0, uint64_t router_address = 0, time_t time = 0); AlarmDataCommand(uint64_t target_address = 0, uint64_t router_address = 0, time_t time = 0);
RequestType getRequestType() { return RequestType::AlarmLog; }; virtual void handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id);
}; };

View File

@ -6,6 +6,8 @@
#define RF_LEN 32 #define RF_LEN 32
class InverterAbstract;
class CommandAbstract { class CommandAbstract {
public: public:
CommandAbstract(uint64_t target_address = 0, uint64_t router_address = 0); CommandAbstract(uint64_t target_address = 0, uint64_t router_address = 0);
@ -34,7 +36,7 @@ public:
virtual CommandAbstract* getRequestFrameCommand(uint8_t frame_no); virtual CommandAbstract* getRequestFrameCommand(uint8_t frame_no);
virtual RequestType getRequestType() = 0; virtual void handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id) = 0;
protected: protected:
uint8_t _payload[RF_LEN]; uint8_t _payload[RF_LEN];

View File

@ -1,4 +1,5 @@
#include "RealTimeRunDataCommand.h" #include "RealTimeRunDataCommand.h"
#include "inverters/InverterAbstract.h"
RealTimeRunDataCommand::RealTimeRunDataCommand(uint64_t target_address, uint64_t router_address, time_t time) RealTimeRunDataCommand::RealTimeRunDataCommand(uint64_t target_address, uint64_t router_address, time_t time)
: MultiDataCommand(target_address, router_address) : MultiDataCommand(target_address, router_address)
@ -6,4 +7,16 @@ RealTimeRunDataCommand::RealTimeRunDataCommand(uint64_t target_address, uint64_t
setTime(time); setTime(time);
setDataType(0x0b); setDataType(0x0b);
setTimeout(200); setTimeout(200);
}
void RealTimeRunDataCommand::handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id)
{
// Move all fragments into target buffer
uint8_t offs = 0;
inverter->Statistics()->clearBuffer();
for (uint8_t i = 0; i < max_fragment_id; i++) {
inverter->Statistics()->appendFragment(offs, fragment[i].fragment, fragment[i].len);
offs += (fragment[i].len);
}
inverter->Statistics()->setLastUpdate(millis());
} }

View File

@ -6,5 +6,5 @@ class RealTimeRunDataCommand : public MultiDataCommand {
public: public:
RealTimeRunDataCommand(uint64_t target_address = 0, uint64_t router_address = 0, time_t time = 0); RealTimeRunDataCommand(uint64_t target_address = 0, uint64_t router_address = 0, time_t time = 0);
RequestType getRequestType() { return RequestType::Stats; }; virtual void handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id);
}; };

View File

@ -18,4 +18,8 @@ void RequestFrameCommand::setFrameNo(uint8_t frame_no)
uint8_t RequestFrameCommand::getFrameNo() uint8_t RequestFrameCommand::getFrameNo()
{ {
return _payload[9] & (~0x80); return _payload[9] & (~0x80);
}
void RequestFrameCommand::handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id)
{
} }

View File

@ -8,4 +8,6 @@ public:
void setFrameNo(uint8_t frame_no); void setFrameNo(uint8_t frame_no);
uint8_t getFrameNo(); uint8_t getFrameNo();
virtual void handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id);
}; };

View File

@ -5,6 +5,4 @@
class SingleDataCommand : public CommandAbstract { class SingleDataCommand : public CommandAbstract {
public: public:
SingleDataCommand(uint64_t target_address = 0, uint64_t router_address = 0); SingleDataCommand(uint64_t target_address = 0, uint64_t router_address = 0);
RequestType getRequestType() { return RequestType::None; };
}; };

View File

@ -91,7 +91,7 @@ void InverterAbstract::addRxFragment(uint8_t fragment[], uint8_t len)
} }
// Returns Zero on Success or the Fragment ID for retransmit or error code // Returns Zero on Success or the Fragment ID for retransmit or error code
uint8_t InverterAbstract::verifyAllFragments() uint8_t InverterAbstract::verifyAllFragments(CommandAbstract* cmd)
{ {
// All missing // All missing
if (_rxFragmentLastPacketId == 0) { if (_rxFragmentLastPacketId == 0) {
@ -139,45 +139,7 @@ uint8_t InverterAbstract::verifyAllFragments()
return FRAGMENT_CRC_ERROR; return FRAGMENT_CRC_ERROR;
} }
if (getLastRequest() == RequestType::Stats) { cmd->handleResponse(this, _rxFragmentBuffer, _rxFragmentMaxPacketId);
// Move all fragments into target buffer
uint8_t offs = 0;
_statisticsParser.get()->clearBuffer();
for (uint8_t i = 0; i < _rxFragmentMaxPacketId; i++) {
_statisticsParser.get()->appendFragment(offs, _rxFragmentBuffer[i].fragment, _rxFragmentBuffer[i].len);
offs += (_rxFragmentBuffer[i].len);
}
_lastStatsUpdate = millis();
} else if (getLastRequest() == RequestType::AlarmLog) {
// Move all fragments into target buffer
uint8_t offs = 0;
_alarmLogParser.get()->clearBuffer();
for (uint8_t i = 0; i < _rxFragmentMaxPacketId; i++) {
_alarmLogParser.get()->appendFragment(offs, _rxFragmentBuffer[i].fragment, _rxFragmentBuffer[i].len);
offs += (_rxFragmentBuffer[i].len);
}
_lastAlarmLogUpdate = millis();
} else {
Serial.println("Unkown response received");
}
setLastRequest(RequestType::None);
return FRAGMENT_OK; return FRAGMENT_OK;
}
uint32_t InverterAbstract::getLastStatsUpdate()
{
return _lastStatsUpdate;
}
void InverterAbstract::setLastRequest(RequestType request)
{
_lastRequest = request;
}
RequestType InverterAbstract::getLastRequest()
{
return _lastRequest;
} }

View File

@ -19,6 +19,8 @@ enum {
#define MAX_RF_FRAGMENT_COUNT 5 #define MAX_RF_FRAGMENT_COUNT 5
#define MAX_RETRANSMIT_COUNT 5 #define MAX_RETRANSMIT_COUNT 5
class CommandAbstract;
class InverterAbstract { class InverterAbstract {
public: public:
InverterAbstract(uint64_t serial); InverterAbstract(uint64_t serial);
@ -32,20 +34,14 @@ public:
void clearRxFragmentBuffer(); void clearRxFragmentBuffer();
void addRxFragment(uint8_t fragment[], uint8_t len); void addRxFragment(uint8_t fragment[], uint8_t len);
uint8_t verifyAllFragments(); uint8_t verifyAllFragments(CommandAbstract* cmd);
virtual bool sendStatsRequest(HoymilesRadio* radio) = 0; virtual bool sendStatsRequest(HoymilesRadio* radio) = 0;
virtual bool sendAlarmLogRequest(HoymilesRadio* radio) = 0; virtual bool sendAlarmLogRequest(HoymilesRadio* radio) = 0;
uint32_t getLastStatsUpdate();
void setLastRequest(RequestType request);
AlarmLogParser* EventLog(); AlarmLogParser* EventLog();
StatisticsParser* Statistics(); StatisticsParser* Statistics();
protected:
RequestType getLastRequest();
private: private:
serial_u _serial; serial_u _serial;
char _name[MAX_NAME_LENGTH]; char _name[MAX_NAME_LENGTH];
@ -54,11 +50,6 @@ private:
uint8_t _rxFragmentLastPacketId = 0; uint8_t _rxFragmentLastPacketId = 0;
uint8_t _rxFragmentRetransmitCnt = 0; uint8_t _rxFragmentRetransmitCnt = 0;
uint32_t _lastStatsUpdate = 0;
uint32_t _lastAlarmLogUpdate = 0;
RequestType _lastRequest = RequestType::None;
std::unique_ptr<AlarmLogParser> _alarmLogParser; std::unique_ptr<AlarmLogParser> _alarmLogParser;
std::unique_ptr<StatisticsParser> _statisticsParser; std::unique_ptr<StatisticsParser> _statisticsParser;
}; };

View File

@ -258,6 +258,16 @@ void AlarmLogParser::getLogEntry(uint8_t entryId, AlarmLogEntry_t* entry)
} }
} }
uint32_t AlarmLogParser::getLastUpdate()
{
return _lastUpdate;
}
void AlarmLogParser::setLastUpdate(uint32_t lastUpdate)
{
_lastUpdate = lastUpdate;
}
int AlarmLogParser::getTimezoneOffset() int AlarmLogParser::getTimezoneOffset()
{ {
// see: https://stackoverflow.com/questions/13804095/get-the-time-zone-gmt-offset-in-c/44063597#44063597 // see: https://stackoverflow.com/questions/13804095/get-the-time-zone-gmt-offset-in-c/44063597#44063597

View File

@ -20,9 +20,14 @@ public:
uint8_t getEntryCount(); uint8_t getEntryCount();
void getLogEntry(uint8_t entryId, AlarmLogEntry_t* entry); void getLogEntry(uint8_t entryId, AlarmLogEntry_t* entry);
uint32_t getLastUpdate();
void setLastUpdate(uint32_t lastUpdate);
private: private:
static int getTimezoneOffset(); static int getTimezoneOffset();
uint8_t _payloadAlarmLog[ALARM_LOG_ENTRY_SIZE * ALARM_LOG_ENTRY_COUNT]; uint8_t _payloadAlarmLog[ALARM_LOG_ENTRY_SIZE * ALARM_LOG_ENTRY_COUNT];
uint8_t _alarmLogLength; uint8_t _alarmLogLength;
uint32_t _lastUpdate = 0;
}; };

View File

@ -112,6 +112,16 @@ void StatisticsParser::setChannelMaxPower(uint8_t channel, uint16_t power)
} }
} }
uint32_t StatisticsParser::getLastUpdate()
{
return _lastUpdate;
}
void StatisticsParser::setLastUpdate(uint32_t lastUpdate)
{
_lastUpdate = lastUpdate;
}
static float calcYieldTotalCh0(StatisticsParser* iv, uint8_t arg0) static float calcYieldTotalCh0(StatisticsParser* iv, uint8_t arg0)
{ {
float yield = 0; float yield = 0;

View File

@ -110,6 +110,9 @@ public:
uint16_t getChannelMaxPower(uint8_t channel); uint16_t getChannelMaxPower(uint8_t channel);
void setChannelMaxPower(uint8_t channel, uint16_t power); void setChannelMaxPower(uint8_t channel, uint16_t power);
uint32_t getLastUpdate();
void setLastUpdate(uint32_t lastUpdate);
private: private:
uint8_t _payloadStatistic[STATISTIC_PACKET_SIZE]; uint8_t _payloadStatistic[STATISTIC_PACKET_SIZE];
uint8_t _statisticLength; uint8_t _statisticLength;
@ -117,4 +120,6 @@ private:
const byteAssign_t* _byteAssignment; const byteAssign_t* _byteAssignment;
uint8_t _byteAssignmentCount; uint8_t _byteAssignmentCount;
uint32_t _lastUpdate = 0;
}; };

View File

@ -14,9 +14,3 @@ typedef struct {
uint8_t fragment[MAX_RF_PAYLOAD_SIZE]; uint8_t fragment[MAX_RF_PAYLOAD_SIZE];
uint8_t len; uint8_t len;
} fragment_t; } fragment_t;
enum class RequestType {
None,
Stats,
AlarmLog
};

View File

@ -36,7 +36,7 @@ void MqttPublishingClass::loop()
MqttSettings.publish(subtopic + "/name", inv->name()); MqttSettings.publish(subtopic + "/name", inv->name());
uint32_t lastUpdate = inv->getLastStatsUpdate(); uint32_t lastUpdate = inv->Statistics()->getLastUpdate();
if (lastUpdate > 0 && lastUpdate != _lastPublishStats[i]) { if (lastUpdate > 0 && lastUpdate != _lastPublishStats[i]) {
_lastPublishStats[i] = lastUpdate; _lastPublishStats[i] = lastUpdate;

View File

@ -44,8 +44,8 @@ void WebApiWsLiveClass::loop()
for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) {
auto inv = Hoymiles.getInverterByPos(i); auto inv = Hoymiles.getInverterByPos(i);
if (inv->getLastStatsUpdate() > maxTimeStamp) { if (inv->Statistics()->getLastUpdate() > maxTimeStamp) {
maxTimeStamp = inv->getLastStatsUpdate(); maxTimeStamp = inv->Statistics()->getLastUpdate();
} }
} }
@ -80,8 +80,8 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
root[i][F("serial")] = String(buffer); root[i][F("serial")] = String(buffer);
root[i][F("name")] = inv->name(); root[i][F("name")] = inv->name();
root[i][F("data_age")] = (millis() - inv->getLastStatsUpdate()) / 1000; root[i][F("data_age")] = (millis() - inv->Statistics()->getLastUpdate()) / 1000;
root[i][F("age_critical")] = ((millis() - inv->getLastStatsUpdate()) / 1000) > Configuration.get().Dtu_PollInterval * 5; root[i][F("age_critical")] = ((millis() - inv->Statistics()->getLastUpdate()) / 1000) > Configuration.get().Dtu_PollInterval * 5;
// Loop all channels // Loop all channels
for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) { for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) {
@ -110,8 +110,8 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
root[i][F("events")] = -1; root[i][F("events")] = -1;
} }
if (inv->getLastStatsUpdate() > _newestInverterTimestamp) { if (inv->Statistics()->getLastUpdate() > _newestInverterTimestamp) {
_newestInverterTimestamp = inv->getLastStatsUpdate(); _newestInverterTimestamp = inv->Statistics()->getLastUpdate();
} }
} }
} }