diff --git a/lib/Hoymiles/src/Hoymiles.cpp b/lib/Hoymiles/src/Hoymiles.cpp index 7717c46b..adabed51 100644 --- a/lib/Hoymiles/src/Hoymiles.cpp +++ b/lib/Hoymiles/src/Hoymiles.cpp @@ -3,6 +3,7 @@ #include "inverters/HM_2CH.h" #include "inverters/HM_4CH.h" #include +#include HoymilesClass Hoymiles; @@ -30,6 +31,15 @@ void HoymilesClass::loop() // Fetch event log iv->sendAlarmLogRequest(_radio.get()); + + // Fetch dev info + if (iv->DevInfo()->getLastUpdate() == 0) { + EVERY_N_MINUTES(10) + { + Serial.println(F("Request device info")); + iv->sendDevInfoRequest(_radio.get()); + } + } } if (++inverterPos >= getNumInverters()) { @@ -46,11 +56,9 @@ std::shared_ptr HoymilesClass::addInverter(const char* name, u std::shared_ptr i; if (HM_4CH::isValidSerial(serial)) { i = std::make_shared(serial); - } - else if (HM_2CH::isValidSerial(serial)) { + } else if (HM_2CH::isValidSerial(serial)) { i = std::make_shared(serial); - } - else if (HM_1CH::isValidSerial(serial)) { + } else if (HM_1CH::isValidSerial(serial)) { i = std::make_shared(serial); } diff --git a/lib/Hoymiles/src/commands/DevInfoAllCommand.cpp b/lib/Hoymiles/src/commands/DevInfoAllCommand.cpp new file mode 100644 index 00000000..0ac65d0b --- /dev/null +++ b/lib/Hoymiles/src/commands/DevInfoAllCommand.cpp @@ -0,0 +1,28 @@ +#include "DevInfoAllCommand.h" +#include "inverters/InverterAbstract.h" + +DevInfoAllCommand::DevInfoAllCommand(uint64_t target_address, uint64_t router_address, time_t time) + : MultiDataCommand(target_address, router_address) +{ + setTime(time); + setDataType(0x01); + setTimeout(200); +} + +bool DevInfoAllCommand::handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id) +{ + // Check CRC of whole payload + if (!MultiDataCommand::handleResponse(inverter, fragment, max_fragment_id)) { + return false; + } + + // Move all fragments into target buffer + uint8_t offs = 0; + inverter->DevInfo()->clearBuffer(); + for (uint8_t i = 0; i < max_fragment_id; i++) { + inverter->DevInfo()->appendFragment(offs, fragment[i].fragment, fragment[i].len); + offs += (fragment[i].len); + } + inverter->DevInfo()->setLastUpdate(millis()); + return true; +} \ No newline at end of file diff --git a/lib/Hoymiles/src/commands/DevInfoAllCommand.h b/lib/Hoymiles/src/commands/DevInfoAllCommand.h new file mode 100644 index 00000000..16a0bd9b --- /dev/null +++ b/lib/Hoymiles/src/commands/DevInfoAllCommand.h @@ -0,0 +1,10 @@ +#pragma once + +#include "MultiDataCommand.h" + +class DevInfoAllCommand : public MultiDataCommand { +public: + DevInfoAllCommand(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); +}; \ 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 e11c52b2..52c47ccb 100644 --- a/lib/Hoymiles/src/inverters/HM_Abstract.cpp +++ b/lib/Hoymiles/src/inverters/HM_Abstract.cpp @@ -1,6 +1,7 @@ #include "HM_Abstract.h" #include "HoymilesRadio.h" #include "commands/AlarmDataCommand.h" +#include "commands/DevInfoAllCommand.h" #include "commands/RealTimeRunDataCommand.h" HM_Abstract::HM_Abstract(uint64_t serial) @@ -45,5 +46,22 @@ bool HM_Abstract::sendAlarmLogRequest(HoymilesRadio* radio) cmd->setTime(now); cmd->setTargetAddress(serial()); + return true; +} + +bool HM_Abstract::sendDevInfoRequest(HoymilesRadio* radio) +{ + struct tm timeinfo; + if (!getLocalTime(&timeinfo)) { + return false; + } + + time_t now; + time(&now); + + DevInfoAllCommand* cmd = radio->enqueCommand(); + cmd->setTime(now); + cmd->setTargetAddress(serial()); + return true; } \ 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 8c79653a..bd10be9e 100644 --- a/lib/Hoymiles/src/inverters/HM_Abstract.h +++ b/lib/Hoymiles/src/inverters/HM_Abstract.h @@ -7,6 +7,7 @@ public: HM_Abstract(uint64_t serial); bool sendStatsRequest(HoymilesRadio* radio); bool sendAlarmLogRequest(HoymilesRadio* radio); + bool sendDevInfoRequest(HoymilesRadio* radio); private: uint8_t _lastAlarmLogCnt = 0; diff --git a/lib/Hoymiles/src/inverters/InverterAbstract.cpp b/lib/Hoymiles/src/inverters/InverterAbstract.cpp index 8cbbb058..4005479a 100644 --- a/lib/Hoymiles/src/inverters/InverterAbstract.cpp +++ b/lib/Hoymiles/src/inverters/InverterAbstract.cpp @@ -6,6 +6,7 @@ InverterAbstract::InverterAbstract(uint64_t serial) { _serial.u64 = serial; _alarmLogParser.reset(new AlarmLogParser()); + _devInfoParser.reset(new DevInfoParser()); _statisticsParser.reset(new StatisticsParser()); } @@ -43,6 +44,11 @@ AlarmLogParser* InverterAbstract::EventLog() return _alarmLogParser.get(); } +DevInfoParser* InverterAbstract::DevInfo() +{ + return _devInfoParser.get(); +} + StatisticsParser* InverterAbstract::Statistics() { return _statisticsParser.get(); diff --git a/lib/Hoymiles/src/inverters/InverterAbstract.h b/lib/Hoymiles/src/inverters/InverterAbstract.h index 74e68c3b..e863cf0c 100644 --- a/lib/Hoymiles/src/inverters/InverterAbstract.h +++ b/lib/Hoymiles/src/inverters/InverterAbstract.h @@ -2,6 +2,7 @@ #include "../parser/AlarmLogParser.h" #include "../parser/StatisticsParser.h" +#include "../parser/DevInfoParser.h" #include "HoymilesRadio.h" #include "types.h" #include @@ -38,8 +39,10 @@ public: virtual bool sendStatsRequest(HoymilesRadio* radio) = 0; virtual bool sendAlarmLogRequest(HoymilesRadio* radio) = 0; + virtual bool sendDevInfoRequest(HoymilesRadio* radio) = 0; AlarmLogParser* EventLog(); + DevInfoParser* DevInfo(); StatisticsParser* Statistics(); private: @@ -51,5 +54,6 @@ private: uint8_t _rxFragmentRetransmitCnt = 0; std::unique_ptr _alarmLogParser; + std::unique_ptr _devInfoParser; std::unique_ptr _statisticsParser; }; \ No newline at end of file diff --git a/lib/Hoymiles/src/parser/DevInfoParser.cpp b/lib/Hoymiles/src/parser/DevInfoParser.cpp new file mode 100644 index 00000000..9249748f --- /dev/null +++ b/lib/Hoymiles/src/parser/DevInfoParser.cpp @@ -0,0 +1,18 @@ +#include "DevInfoParser.h" +#include + +void DevInfoParser::clearBuffer() +{ + memset(_payloadDevInfo, 0, DEV_INFO_SIZE); + _devInfoLength = 0; +} + +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__); + return; + } + memcpy(&_payloadDevInfo[offset], payload, len); + _devInfoLength += len; +} \ No newline at end of file diff --git a/lib/Hoymiles/src/parser/DevInfoParser.h b/lib/Hoymiles/src/parser/DevInfoParser.h new file mode 100644 index 00000000..4cedfdf9 --- /dev/null +++ b/lib/Hoymiles/src/parser/DevInfoParser.h @@ -0,0 +1,14 @@ +#include "Parser.h" +#include + +#define DEV_INFO_SIZE 30 + +class DevInfoParser : public Parser { +public: + void clearBuffer(); + void appendFragment(uint8_t offset, uint8_t* payload, uint8_t len); + +private: + uint8_t _payloadDevInfo[DEV_INFO_SIZE]; + uint8_t _devInfoLength; +}; \ No newline at end of file diff --git a/lib/Hoymiles/src/parser/Parser.cpp b/lib/Hoymiles/src/parser/Parser.cpp new file mode 100644 index 00000000..57db09c0 --- /dev/null +++ b/lib/Hoymiles/src/parser/Parser.cpp @@ -0,0 +1,11 @@ +#include "Parser.h" + +uint32_t Parser::getLastUpdate() +{ + return _lastUpdate; +} + +void Parser::setLastUpdate(uint32_t lastUpdate) +{ + _lastUpdate = lastUpdate; +} \ No newline at end of file diff --git a/lib/Hoymiles/src/parser/Parser.h b/lib/Hoymiles/src/parser/Parser.h new file mode 100644 index 00000000..8188a3bc --- /dev/null +++ b/lib/Hoymiles/src/parser/Parser.h @@ -0,0 +1,11 @@ +#pragma once +#include + +class Parser { +public: + uint32_t getLastUpdate(); + void setLastUpdate(uint32_t lastUpdate); + +private: + uint32_t _lastUpdate = 0; +}; \ No newline at end of file