Fix: Prevent wrong values of statistics data because of non-atomic transaction

This commit is contained in:
Thomas Basler 2023-07-31 21:48:26 +02:00
parent 9821c1905b
commit 14305a9f12
3 changed files with 31 additions and 0 deletions

View File

@ -40,11 +40,13 @@ bool RealTimeRunDataCommand::handleResponse(InverterAbstract* inverter, fragment
// Move all fragments into target buffer // Move all fragments into target buffer
uint8_t offs = 0; uint8_t offs = 0;
inverter->Statistics()->beginAppendFragment();
inverter->Statistics()->clearBuffer(); inverter->Statistics()->clearBuffer();
for (uint8_t i = 0; i < max_fragment_id; i++) { for (uint8_t i = 0; i < max_fragment_id; i++) {
inverter->Statistics()->appendFragment(offs, fragment[i].fragment, fragment[i].len); inverter->Statistics()->appendFragment(offs, fragment[i].fragment, fragment[i].len);
offs += (fragment[i].len); offs += (fragment[i].len);
} }
inverter->Statistics()->endAppendFragment();
inverter->Statistics()->resetRxFailureCount(); inverter->Statistics()->resetRxFailureCount();
inverter->Statistics()->setLastUpdate(millis()); inverter->Statistics()->setLastUpdate(millis());
return true; return true;

View File

@ -5,6 +5,11 @@
#include "StatisticsParser.h" #include "StatisticsParser.h"
#include "../Hoymiles.h" #include "../Hoymiles.h"
#define HOY_SEMAPHORE_TAKE() \
do { \
} while (xSemaphoreTake(_xSemaphore, portMAX_DELAY) != pdPASS)
#define HOY_SEMAPHORE_GIVE() xSemaphoreGive(_xSemaphore)
static float calcYieldTotalCh0(StatisticsParser* iv, uint8_t arg0); static float calcYieldTotalCh0(StatisticsParser* iv, uint8_t arg0);
static float calcYieldDayCh0(StatisticsParser* iv, uint8_t arg0); static float calcYieldDayCh0(StatisticsParser* iv, uint8_t arg0);
static float calcUdcCh(StatisticsParser* iv, uint8_t arg0); static float calcUdcCh(StatisticsParser* iv, uint8_t arg0);
@ -28,6 +33,13 @@ const calcFunc_t calcFunctions[] = {
{ CALC_IRR_CH, &calcIrradiation } { CALC_IRR_CH, &calcIrradiation }
}; };
StatisticsParser::StatisticsParser()
: Parser()
{
_xSemaphore = xSemaphoreCreateMutex();
HOY_SEMAPHORE_GIVE(); // release before first use
}
void StatisticsParser::setByteAssignment(const byteAssign_t* byteAssignment, uint8_t size) void StatisticsParser::setByteAssignment(const byteAssign_t* byteAssignment, uint8_t size)
{ {
_byteAssignment = byteAssignment; _byteAssignment = byteAssignment;
@ -62,6 +74,16 @@ void StatisticsParser::appendFragment(uint8_t offset, uint8_t* payload, uint8_t
_statisticLength += len; _statisticLength += len;
} }
void StatisticsParser::beginAppendFragment()
{
HOY_SEMAPHORE_TAKE();
}
void StatisticsParser::endAppendFragment()
{
HOY_SEMAPHORE_GIVE();
}
const byteAssign_t* StatisticsParser::getAssignmentByChannelField(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId) const byteAssign_t* StatisticsParser::getAssignmentByChannelField(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId)
{ {
for (uint8_t i = 0; i < _byteAssignmentSize; i++) { for (uint8_t i = 0; i < _byteAssignmentSize; i++) {
@ -98,10 +120,12 @@ float StatisticsParser::getChannelFieldValue(ChannelType_t type, ChannelNum_t ch
if (CMD_CALC != div) { if (CMD_CALC != div) {
// Value is a static value // Value is a static value
uint32_t val = 0; uint32_t val = 0;
HOY_SEMAPHORE_TAKE();
do { do {
val <<= 8; val <<= 8;
val |= _payloadStatistic[ptr]; val |= _payloadStatistic[ptr];
} while (++ptr != end); } while (++ptr != end);
HOY_SEMAPHORE_GIVE();
float result; float result;
if (pos->isSigned && pos->num == 2) { if (pos->isSigned && pos->num == 2) {

View File

@ -104,8 +104,11 @@ typedef struct {
class StatisticsParser : public Parser { class StatisticsParser : public Parser {
public: public:
StatisticsParser();
void clearBuffer(); void clearBuffer();
void appendFragment(uint8_t offset, uint8_t* payload, uint8_t len); void appendFragment(uint8_t offset, uint8_t* payload, uint8_t len);
void beginAppendFragment();
void endAppendFragment();
void setByteAssignment(const byteAssign_t* byteAssignment, uint8_t size); void setByteAssignment(const byteAssign_t* byteAssignment, uint8_t size);
@ -146,4 +149,6 @@ private:
std::list<fieldSettings_t> _fieldSettings; std::list<fieldSettings_t> _fieldSettings;
uint32_t _rxFailureCount = 0; uint32_t _rxFailureCount = 0;
SemaphoreHandle_t _xSemaphore;
}; };