Skip to content

Commit

Permalink
Fix: Prevent wrong values of alarm data because of non-atomic transac…
Browse files Browse the repository at this point in the history
…tion and fix calculation of getEntryCount()
  • Loading branch information
tbnobody committed Jul 31, 2023
1 parent 14305a9 commit 698ecbc
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 1 deletion.
2 changes: 2 additions & 0 deletions lib/Hoymiles/src/commands/AlarmDataCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ bool AlarmDataCommand::handleResponse(InverterAbstract* inverter, fragment_t fra

// Move all fragments into target buffer
uint8_t offs = 0;
inverter->EventLog()->beginAppendFragment();
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()->endAppendFragment();
inverter->EventLog()->setLastAlarmRequestSuccess(CMD_OK);
inverter->EventLog()->setLastUpdate(millis());
return true;
Expand Down
29 changes: 29 additions & 0 deletions lib/Hoymiles/src/parser/AlarmLogParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,18 @@ const std::array<const AlarmMessage_t, ALARM_MSG_COUNT> AlarmLogParser::_alarmMe
{ AlarmMessageType_t::ALL, 9000, "Microinverter is suspected of being stolen" },
} };

#define HOY_SEMAPHORE_TAKE() \
do { \
} while (xSemaphoreTake(_xSemaphore, portMAX_DELAY) != pdPASS)
#define HOY_SEMAPHORE_GIVE() xSemaphoreGive(_xSemaphore)

AlarmLogParser::AlarmLogParser()
: Parser()
{
_xSemaphore = xSemaphoreCreateMutex();
HOY_SEMAPHORE_GIVE(); // release before first use
}

void AlarmLogParser::clearBuffer()
{
memset(_payloadAlarmLog, 0, ALARM_LOG_PAYLOAD_SIZE);
Expand All @@ -102,8 +114,21 @@ void AlarmLogParser::appendFragment(uint8_t offset, uint8_t* payload, uint8_t le
_alarmLogLength += len;
}

void AlarmLogParser::beginAppendFragment()
{
HOY_SEMAPHORE_TAKE();
}

void AlarmLogParser::endAppendFragment()
{
HOY_SEMAPHORE_GIVE();
}

uint8_t AlarmLogParser::getEntryCount()
{
if (_alarmLogLength < 2) {
return 0;
}
return (_alarmLogLength - 2) / ALARM_LOG_ENTRY_SIZE;
}

Expand All @@ -128,6 +153,8 @@ void AlarmLogParser::getLogEntry(uint8_t entryId, AlarmLogEntry_t* entry)

int timezoneOffset = getTimezoneOffset();

HOY_SEMAPHORE_TAKE();

uint32_t wcode = (uint16_t)_payloadAlarmLog[entryStartOffset] << 8 | _payloadAlarmLog[entryStartOffset + 1];
uint32_t startTimeOffset = 0;
if (((wcode >> 13) & 0x01) == 1) {
Expand All @@ -143,6 +170,8 @@ void AlarmLogParser::getLogEntry(uint8_t entryId, AlarmLogEntry_t* entry)
entry->StartTime = (((uint16_t)_payloadAlarmLog[entryStartOffset + 4] << 8) | ((uint16_t)_payloadAlarmLog[entryStartOffset + 5])) + startTimeOffset + timezoneOffset;
entry->EndTime = ((uint16_t)_payloadAlarmLog[entryStartOffset + 6] << 8) | ((uint16_t)_payloadAlarmLog[entryStartOffset + 7]);

HOY_SEMAPHORE_GIVE();

if (entry->EndTime > 0) {
entry->EndTime += (endTimeOffset + timezoneOffset);
}
Expand Down
7 changes: 6 additions & 1 deletion lib/Hoymiles/src/parser/AlarmLogParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ typedef struct {

class AlarmLogParser : public Parser {
public:
AlarmLogParser();
void clearBuffer();
void appendFragment(uint8_t offset, uint8_t* payload, uint8_t len);
void beginAppendFragment();
void endAppendFragment();

uint8_t getEntryCount();
void getLogEntry(uint8_t entryId, AlarmLogEntry_t* entry);
Expand All @@ -46,11 +49,13 @@ class AlarmLogParser : public Parser {
static int getTimezoneOffset();

uint8_t _payloadAlarmLog[ALARM_LOG_PAYLOAD_SIZE];
uint8_t _alarmLogLength;
uint8_t _alarmLogLength = 0;

LastCommandSuccess _lastAlarmRequestSuccess = CMD_NOK; // Set to NOK to fetch at startup

AlarmMessageType_t _messageType = AlarmMessageType_t::ALL;

static const std::array<const AlarmMessage_t, ALARM_MSG_COUNT> _alarmMessages;

SemaphoreHandle_t _xSemaphore;
};

0 comments on commit 698ecbc

Please sign in to comment.