Implemented method to check whether the last command was successfull

This also allows to retransmit the command after specific time if not successfull
This commit is contained in:
Thomas Basler 2022-09-23 19:09:22 +02:00
parent a8ee8afb17
commit a707ab501d
16 changed files with 110 additions and 17 deletions

View File

@ -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"));

View File

@ -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"));

View File

@ -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

View File

@ -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);
}

View File

@ -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();

View File

@ -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)
{
}

View File

@ -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];

View File

@ -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);
}

View File

@ -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);
};

View File

@ -86,18 +86,28 @@ bool HM_Abstract::sendSystemConfigParaRequest(HoymilesRadio* radio)
SystemConfigParaCommand* cmd = radio->enqueCommand<SystemConfigParaCommand>();
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<ActivePowerControlCommand>();
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);
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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();

View File

@ -1,6 +1,12 @@
#pragma once
#include <cstdint>
typedef enum {
CMD_OK,
CMD_NOK,
CMD_PENDING
} LastCommandSuccess;
class Parser {
public:
uint32_t getLastUpdate();

View File

@ -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;
}

View File

@ -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
};