From f566a8c52235a122e279a562fd079b1a3550599c Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Tue, 9 Aug 2022 20:04:06 +0200 Subject: [PATCH] Implemented parser methods and publish to mqtt --- lib/Hoymiles/src/parser/DevInfoParser.cpp | 55 ++++++++++++++++++++++- lib/Hoymiles/src/parser/DevInfoParser.h | 8 +++- src/MqttPublishing.cpp | 16 +++++++ 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/lib/Hoymiles/src/parser/DevInfoParser.cpp b/lib/Hoymiles/src/parser/DevInfoParser.cpp index 9249748..69a233c 100644 --- a/lib/Hoymiles/src/parser/DevInfoParser.cpp +++ b/lib/Hoymiles/src/parser/DevInfoParser.cpp @@ -10,9 +10,62 @@ void DevInfoParser::clearBuffer() void DevInfoParser::appendFragment(uint8_t offset, uint8_t* payload, uint8_t len) { if (offset + len > DEV_INFO_SIZE) { - Serial.printf("FATAL: (%s, %d) stats packet too large for buffer\n", __FILE__, __LINE__); + Serial.printf("FATAL: (%s, %d) dev info packet too large for buffer\n", __FILE__, __LINE__); return; } memcpy(&_payloadDevInfo[offset], payload, len); _devInfoLength += len; +} + +uint16_t DevInfoParser::getFwBuildVersion() +{ + return (((uint16_t)_payloadDevInfo[0]) << 8) | _payloadDevInfo[1]; +} + +time_t DevInfoParser::getFwBuildDateTime() +{ + struct tm timeinfo = { 0 }; + timeinfo.tm_year = ((((uint16_t)_payloadDevInfo[2]) << 8) | _payloadDevInfo[3]) - 1900; + + timeinfo.tm_mon = ((((uint16_t)_payloadDevInfo[4]) << 8) | _payloadDevInfo[5]) / 100 - 1; + timeinfo.tm_mday = ((((uint16_t)_payloadDevInfo[4]) << 8) | _payloadDevInfo[5]) % 100; + + timeinfo.tm_hour = ((((uint16_t)_payloadDevInfo[6]) << 8) | _payloadDevInfo[7]) / 100; + timeinfo.tm_min = ((((uint16_t)_payloadDevInfo[6]) << 8) | _payloadDevInfo[7]) % 100; + + return timegm(&timeinfo); +} + +uint16_t DevInfoParser::getFwBootloaderVersion() +{ + return (((uint16_t)_payloadDevInfo[8]) << 8) | _payloadDevInfo[9]; +} + +/* struct tm to seconds since Unix epoch */ +time_t DevInfoParser::timegm(struct tm* t) +{ + register long year; + register time_t result; +#define MONTHSPERYEAR 12 /* months per calendar year */ + static const int cumdays[MONTHSPERYEAR] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + + /*@ +matchanyintegral @*/ + year = 1900 + t->tm_year + t->tm_mon / MONTHSPERYEAR; + result = (year - 1970) * 365 + cumdays[t->tm_mon % MONTHSPERYEAR]; + result += (year - 1968) / 4; + result -= (year - 1900) / 100; + result += (year - 1600) / 400; + if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) && (t->tm_mon % MONTHSPERYEAR) < 2) + result--; + result += t->tm_mday - 1; + result *= 24; + result += t->tm_hour; + result *= 60; + result += t->tm_min; + result *= 60; + result += t->tm_sec; + if (t->tm_isdst == 1) + result -= 3600; + /*@ -matchanyintegral @*/ + return (result); } \ No newline at end of file diff --git a/lib/Hoymiles/src/parser/DevInfoParser.h b/lib/Hoymiles/src/parser/DevInfoParser.h index 4cedfdf..115fd53 100644 --- a/lib/Hoymiles/src/parser/DevInfoParser.h +++ b/lib/Hoymiles/src/parser/DevInfoParser.h @@ -1,14 +1,20 @@ #include "Parser.h" #include -#define DEV_INFO_SIZE 30 +#define DEV_INFO_SIZE 20 class DevInfoParser : public Parser { public: void clearBuffer(); void appendFragment(uint8_t offset, uint8_t* payload, uint8_t len); + uint16_t getFwBuildVersion(); + time_t getFwBuildDateTime(); + uint16_t getFwBootloaderVersion(); + private: + time_t timegm(struct tm *tm); + uint8_t _payloadDevInfo[DEV_INFO_SIZE]; uint8_t _devInfoLength; }; \ No newline at end of file diff --git a/src/MqttPublishing.cpp b/src/MqttPublishing.cpp index 090177f..1e066af 100644 --- a/src/MqttPublishing.cpp +++ b/src/MqttPublishing.cpp @@ -5,6 +5,7 @@ #include "MqttPublishing.h" #include "MqttSettings.h" #include "NetworkSettings.h" +#include MqttPublishingClass MqttPublishing; @@ -34,8 +35,23 @@ void MqttPublishingClass::loop() ((uint32_t)(inv->serial() & 0xFFFFFFFF))); String subtopic = String(buffer); + // Name MqttSettings.publish(subtopic + "/name", inv->name()); + if (inv->DevInfo()->getLastUpdate() > 0) { + // Bootloader Version + MqttSettings.publish(subtopic + "/firmware/bootloaderversion", String(inv->DevInfo()->getFwBootloaderVersion())); + + // Firmware Version + MqttSettings.publish(subtopic + "/firmware/buildversion", String(inv->DevInfo()->getFwBuildVersion())); + + // Firmware Build DateTime + char timebuffer[32]; + const time_t t = inv->DevInfo()->getFwBuildDateTime(); + std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", gmtime(&t)); + MqttSettings.publish(subtopic + "/firmware/builddatetime", String(buffer)); + } + uint32_t lastUpdate = inv->Statistics()->getLastUpdate(); if (lastUpdate > 0 && lastUpdate != _lastPublishStats[i]) { _lastPublishStats[i] = lastUpdate;