diff --git a/lib/Hoymiles/src/Hoymiles.cpp b/lib/Hoymiles/src/Hoymiles.cpp index 46c5a284..6f039751 100644 --- a/lib/Hoymiles/src/Hoymiles.cpp +++ b/lib/Hoymiles/src/Hoymiles.cpp @@ -32,11 +32,17 @@ void HoymilesClass::loop() iv->sendAlarmLogRequest(_radio.get()); // Fetch limit - if ((iv->SystemConfigPara()->getLastUpdate() == 0) || (millis() - iv->SystemConfigPara()->getLastUpdate() > HOY_SYSTEM_CONFIG_PARA_POLL_INTERVAL)) { + if ((iv->SystemConfigPara()->getLastLimitRequestSuccess() == CMD_NOK) || (millis() - iv->SystemConfigPara()->getLastUpdate() > HOY_SYSTEM_CONFIG_PARA_POLL_INTERVAL)) { Serial.println("Request SystemConfigPara"); iv->sendSystemConfigParaRequest(_radio.get()); } + // Set limit if required + if (iv->SystemConfigPara()->getLastLimitCommandSuccess() == CMD_NOK) { + Serial.println(F("Resend ActivePowerControl")); + iv->resendActivePowerControlRequest(_radio.get()); + } + // Fetch dev info (but first fetch stats) if (iv->Statistics()->getLastUpdate() > 0 && (iv->DevInfo()->getLastUpdateAll() == 0 || iv->DevInfo()->getLastUpdateSample() == 0)) { Serial.println(F("Request device info")); diff --git a/lib/Hoymiles/src/HoymilesRadio.cpp b/lib/Hoymiles/src/HoymilesRadio.cpp index f9c34105..99abe117 100644 --- a/lib/Hoymiles/src/HoymilesRadio.cpp +++ b/lib/Hoymiles/src/HoymilesRadio.cpp @@ -91,15 +91,14 @@ void HoymilesRadio::loop() if (nullptr != inv) { CommandAbstract* cmd = _commandQueue.front().get(); uint8_t verifyResult = inv->verifyAllFragments(cmd); - if (verifyResult == FRAGMENT_ALL_MISSING) { - 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; - } + if (verifyResult == FRAGMENT_ALL_MISSING_RESEND) { + Serial.println(F("Nothing received, resend whole request")); + sendLastPacketAgain(); + + } else if (verifyResult == FRAGMENT_ALL_MISSING_TIMEOUT) { + Serial.println(F("Nothing received, resend count exeeded")); + _commandQueue.pop(); + _busyFlag = false; } else if (verifyResult == FRAGMENT_RETRANSMIT_TIMEOUT) { Serial.println(F("Retransmit timeout")); diff --git a/lib/Hoymiles/src/HoymilesRadio.h b/lib/Hoymiles/src/HoymilesRadio.h index acbf4fb1..9d6062cc 100644 --- a/lib/Hoymiles/src/HoymilesRadio.h +++ b/lib/Hoymiles/src/HoymilesRadio.h @@ -12,8 +12,6 @@ // number of fragments hold in buffer #define FRAGMENT_BUFFER_SIZE 30 -#define MAX_RESEND_COUNT 4 - #ifndef HOYMILES_PIN_MISO #define HOYMILES_PIN_MISO 19 #endif diff --git a/lib/Hoymiles/src/commands/ActivePowerControlCommand.cpp b/lib/Hoymiles/src/commands/ActivePowerControlCommand.cpp index cafc6089..83ddc82e 100644 --- a/lib/Hoymiles/src/commands/ActivePowerControlCommand.cpp +++ b/lib/Hoymiles/src/commands/ActivePowerControlCommand.cpp @@ -1,4 +1,5 @@ #include "ActivePowerControlCommand.h" +#include "inverters/InverterAbstract.h" #define CRC_SIZE 6 @@ -34,6 +35,16 @@ void ActivePowerControlCommand::setActivePowerLimit(float limit, PowerLimitContr udpateCRC(CRC_SIZE); } +bool ActivePowerControlCommand::handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id) +{ + if (!DevControlCommand::handleResponse(inverter, fragment, max_fragment_id)) { + return false; + } + + inverter->SystemConfigPara()->setLastLimitCommandSuccess(CMD_OK); + return true; +} + float ActivePowerControlCommand::getLimit() { uint16_t l = (((uint16_t)_payload[12] << 8) | _payload[13]); @@ -44,3 +55,8 @@ PowerLimitControlType ActivePowerControlCommand::getType() { return (PowerLimitControlType)(((uint16_t)_payload[14] << 8) | _payload[15]); } + +void ActivePowerControlCommand::gotTimeout(InverterAbstract* inverter) +{ + inverter->SystemConfigPara()->setLastLimitCommandSuccess(CMD_NOK); +} \ No newline at end of file diff --git a/lib/Hoymiles/src/commands/ActivePowerControlCommand.h b/lib/Hoymiles/src/commands/ActivePowerControlCommand.h index 47089baf..35398816 100644 --- a/lib/Hoymiles/src/commands/ActivePowerControlCommand.h +++ b/lib/Hoymiles/src/commands/ActivePowerControlCommand.h @@ -12,6 +12,8 @@ typedef enum { // ToDo: to be verified by field tests class ActivePowerControlCommand : public DevControlCommand { public: ActivePowerControlCommand(uint64_t target_address = 0, uint64_t router_address = 0); + virtual bool handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id); + virtual void gotTimeout(InverterAbstract* inverter); void setActivePowerLimit(float limit, PowerLimitControlType type = RelativNonPersistent); float getLimit(); diff --git a/lib/Hoymiles/src/commands/CommandAbstract.cpp b/lib/Hoymiles/src/commands/CommandAbstract.cpp index db7c6d31..f5bf8e5c 100644 --- a/lib/Hoymiles/src/commands/CommandAbstract.cpp +++ b/lib/Hoymiles/src/commands/CommandAbstract.cpp @@ -99,4 +99,8 @@ void CommandAbstract::convertSerialToPacketId(uint8_t buffer[], uint64_t serial) buffer[2] = s.b[1]; buffer[1] = s.b[2]; buffer[0] = s.b[3]; +} + +void CommandAbstract::gotTimeout(InverterAbstract* inverter) +{ } \ No newline at end of file diff --git a/lib/Hoymiles/src/commands/CommandAbstract.h b/lib/Hoymiles/src/commands/CommandAbstract.h index dfcd5224..2358ddf1 100644 --- a/lib/Hoymiles/src/commands/CommandAbstract.h +++ b/lib/Hoymiles/src/commands/CommandAbstract.h @@ -37,6 +37,7 @@ public: virtual CommandAbstract* getRequestFrameCommand(uint8_t frame_no); virtual bool handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id) = 0; + virtual void gotTimeout(InverterAbstract* inverter); protected: uint8_t _payload[RF_LEN]; diff --git a/lib/Hoymiles/src/commands/SystemConfigParaCommand.cpp b/lib/Hoymiles/src/commands/SystemConfigParaCommand.cpp index 664442bb..65267f49 100644 --- a/lib/Hoymiles/src/commands/SystemConfigParaCommand.cpp +++ b/lib/Hoymiles/src/commands/SystemConfigParaCommand.cpp @@ -24,5 +24,11 @@ bool SystemConfigParaCommand::handleResponse(InverterAbstract* inverter, fragmen offs += (fragment[i].len); } inverter->SystemConfigPara()->setLastUpdate(millis()); + inverter->SystemConfigPara()->setLastLimitRequestSuccess(CMD_OK); return true; +} + +void SystemConfigParaCommand::gotTimeout(InverterAbstract* inverter) +{ + inverter->SystemConfigPara()->setLastLimitRequestSuccess(CMD_NOK); } \ No newline at end of file diff --git a/lib/Hoymiles/src/commands/SystemConfigParaCommand.h b/lib/Hoymiles/src/commands/SystemConfigParaCommand.h index 805f665e..1ff43a0e 100644 --- a/lib/Hoymiles/src/commands/SystemConfigParaCommand.h +++ b/lib/Hoymiles/src/commands/SystemConfigParaCommand.h @@ -7,4 +7,5 @@ public: explicit SystemConfigParaCommand(uint64_t target_address = 0, uint64_t router_address = 0, time_t time = 0); virtual bool handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id); + virtual void gotTimeout(InverterAbstract* inverter); }; \ No newline at end of file diff --git a/lib/Hoymiles/src/inverters/HM_Abstract.cpp b/lib/Hoymiles/src/inverters/HM_Abstract.cpp index ac1191ea..f02744ac 100644 --- a/lib/Hoymiles/src/inverters/HM_Abstract.cpp +++ b/lib/Hoymiles/src/inverters/HM_Abstract.cpp @@ -86,18 +86,28 @@ bool HM_Abstract::sendSystemConfigParaRequest(HoymilesRadio* radio) SystemConfigParaCommand* cmd = radio->enqueCommand(); cmd->setTime(now); cmd->setTargetAddress(serial()); + SystemConfigPara()->setLastLimitRequestSuccess(CMD_PENDING); return true; } bool HM_Abstract::sendActivePowerControlRequest(HoymilesRadio* radio, float limit, PowerLimitControlType type) { + _activePowerControlLimit = limit; + _activePowerControlType = type; + ActivePowerControlCommand* cmd = radio->enqueCommand(); cmd->setActivePowerLimit(limit, type); cmd->setTargetAddress(serial()); + SystemConfigPara()->setLastLimitCommandSuccess(CMD_PENDING); // request updated limits sendSystemConfigParaRequest(radio); return true; +} + +bool HM_Abstract::resendActivePowerControlRequest(HoymilesRadio* radio) +{ + return sendActivePowerControlRequest(radio, _activePowerControlLimit, _activePowerControlType); } \ No newline at end of file diff --git a/lib/Hoymiles/src/inverters/HM_Abstract.h b/lib/Hoymiles/src/inverters/HM_Abstract.h index a42691f5..efbe50b2 100644 --- a/lib/Hoymiles/src/inverters/HM_Abstract.h +++ b/lib/Hoymiles/src/inverters/HM_Abstract.h @@ -10,7 +10,10 @@ public: bool sendDevInfoRequest(HoymilesRadio* radio); bool sendSystemConfigParaRequest(HoymilesRadio* radio); bool sendActivePowerControlRequest(HoymilesRadio* radio, float limit, PowerLimitControlType type); + bool resendActivePowerControlRequest(HoymilesRadio* radio); private: uint8_t _lastAlarmLogCnt = 0; + float _activePowerControlLimit = 0; + PowerLimitControlType _activePowerControlType = PowerLimitControlType::AbsolutNonPersistent; }; \ No newline at end of file diff --git a/lib/Hoymiles/src/inverters/InverterAbstract.cpp b/lib/Hoymiles/src/inverters/InverterAbstract.cpp index 6fa04253..77250bfe 100644 --- a/lib/Hoymiles/src/inverters/InverterAbstract.cpp +++ b/lib/Hoymiles/src/inverters/InverterAbstract.cpp @@ -110,7 +110,13 @@ uint8_t InverterAbstract::verifyAllFragments(CommandAbstract* cmd) // All missing if (_rxFragmentLastPacketId == 0) { Serial.println(F("All missing")); - return FRAGMENT_ALL_MISSING; + if (cmd->getSendCount() <= MAX_RESEND_COUNT) { + return FRAGMENT_ALL_MISSING_RESEND; + } + else { + cmd->gotTimeout(this); + return FRAGMENT_ALL_MISSING_TIMEOUT; + } } // Last fragment is missing (thte one with 0x80) @@ -119,6 +125,7 @@ uint8_t InverterAbstract::verifyAllFragments(CommandAbstract* cmd) if (_rxFragmentRetransmitCnt++ < MAX_RETRANSMIT_COUNT) { return _rxFragmentLastPacketId + 1; } else { + cmd->gotTimeout(this); return FRAGMENT_RETRANSMIT_TIMEOUT; } } @@ -130,12 +137,14 @@ uint8_t InverterAbstract::verifyAllFragments(CommandAbstract* cmd) if (_rxFragmentRetransmitCnt++ < MAX_RETRANSMIT_COUNT) { return i + 1; } else { + cmd->gotTimeout(this); return FRAGMENT_RETRANSMIT_TIMEOUT; } } } if (!cmd->handleResponse(this, _rxFragmentBuffer, _rxFragmentMaxPacketId)) { + cmd->gotTimeout(this); return FRAGMENT_HANDLE_ERROR; } diff --git a/lib/Hoymiles/src/inverters/InverterAbstract.h b/lib/Hoymiles/src/inverters/InverterAbstract.h index bd2d0b85..5f145e8f 100644 --- a/lib/Hoymiles/src/inverters/InverterAbstract.h +++ b/lib/Hoymiles/src/inverters/InverterAbstract.h @@ -13,14 +13,16 @@ #define MAX_NAME_LENGTH 32 enum { - FRAGMENT_ALL_MISSING = 255, - FRAGMENT_RETRANSMIT_TIMEOUT = 254, - FRAGMENT_HANDLE_ERROR = 253, + FRAGMENT_ALL_MISSING_RESEND = 255, + FRAGMENT_ALL_MISSING_TIMEOUT = 254, + FRAGMENT_RETRANSMIT_TIMEOUT = 253, + FRAGMENT_HANDLE_ERROR = 252, FRAGMENT_OK = 0 }; #define MAX_RF_FRAGMENT_COUNT 13 -#define MAX_RETRANSMIT_COUNT 5 +#define MAX_RETRANSMIT_COUNT 5 // Used to send the retransmit package +#define MAX_RESEND_COUNT 4 // Used if all packages are missing class CommandAbstract; @@ -44,6 +46,7 @@ public: virtual bool sendDevInfoRequest(HoymilesRadio* radio) = 0; virtual bool sendSystemConfigParaRequest(HoymilesRadio* radio) = 0; virtual bool sendActivePowerControlRequest(HoymilesRadio* radio, float limit, PowerLimitControlType type) = 0; + virtual bool resendActivePowerControlRequest(HoymilesRadio* radio) = 0; AlarmLogParser* EventLog(); DevInfoParser* DevInfo(); diff --git a/lib/Hoymiles/src/parser/Parser.h b/lib/Hoymiles/src/parser/Parser.h index 8188a3bc..3d29d300 100644 --- a/lib/Hoymiles/src/parser/Parser.h +++ b/lib/Hoymiles/src/parser/Parser.h @@ -1,6 +1,12 @@ #pragma once #include +typedef enum { + CMD_OK, + CMD_NOK, + CMD_PENDING +} LastCommandSuccess; + class Parser { public: uint32_t getLastUpdate(); diff --git a/lib/Hoymiles/src/parser/SystemConfigParaParser.cpp b/lib/Hoymiles/src/parser/SystemConfigParaParser.cpp index 364fefff..e989a013 100644 --- a/lib/Hoymiles/src/parser/SystemConfigParaParser.cpp +++ b/lib/Hoymiles/src/parser/SystemConfigParaParser.cpp @@ -20,4 +20,24 @@ void SystemConfigParaParser::appendFragment(uint8_t offset, uint8_t* payload, ui float SystemConfigParaParser::getLimitPercent() { return ((((uint16_t)_payload[2]) << 8) | _payload[3]) / 10; +} + +void SystemConfigParaParser::setLastLimitCommandSuccess(LastCommandSuccess status) +{ + _lastLimitCommandSuccess = status; +} + +LastCommandSuccess SystemConfigParaParser::getLastLimitCommandSuccess() +{ + return _lastLimitCommandSuccess; +} + +void SystemConfigParaParser::setLastLimitRequestSuccess(LastCommandSuccess status) +{ + _lastLimitRequestSuccess = status; +} + +LastCommandSuccess SystemConfigParaParser::getLastLimitRequestSuccess() +{ + return _lastLimitRequestSuccess; } \ No newline at end of file diff --git a/lib/Hoymiles/src/parser/SystemConfigParaParser.h b/lib/Hoymiles/src/parser/SystemConfigParaParser.h index 2def6c8d..992bb15d 100644 --- a/lib/Hoymiles/src/parser/SystemConfigParaParser.h +++ b/lib/Hoymiles/src/parser/SystemConfigParaParser.h @@ -11,7 +11,16 @@ public: float getLimitPercent(); + void setLastLimitCommandSuccess(LastCommandSuccess status); + LastCommandSuccess getLastLimitCommandSuccess(); + + void setLastLimitRequestSuccess(LastCommandSuccess status); + LastCommandSuccess getLastLimitRequestSuccess(); + private: uint8_t _payload[SYSTEM_CONFIG_PARA_SIZE]; uint8_t _payloadLength; + + LastCommandSuccess _lastLimitCommandSuccess = CMD_OK; // Set to OK because we have to assume nothing is done at startup + LastCommandSuccess _lastLimitRequestSuccess = CMD_NOK; // Set to NOK to fetch at startup }; \ No newline at end of file