Added parser and commands for hardware version and part nr
This commit is contained in:
parent
c3a043b1ce
commit
528c56eaa6
@ -32,7 +32,7 @@ void HoymilesClass::loop()
|
|||||||
iv->sendAlarmLogRequest(_radio.get());
|
iv->sendAlarmLogRequest(_radio.get());
|
||||||
|
|
||||||
// Fetch dev info (but first fetch stats)
|
// Fetch dev info (but first fetch stats)
|
||||||
if (iv->Statistics()->getLastUpdate() > 0 && iv->DevInfo()->getLastUpdate() == 0) {
|
if (iv->Statistics()->getLastUpdate() > 0 && (iv->DevInfo()->getLastUpdateAll() == 0 || iv->DevInfo()->getLastUpdateSample() == 0)) {
|
||||||
Serial.println(F("Request device info"));
|
Serial.println(F("Request device info"));
|
||||||
iv->sendDevInfoRequest(_radio.get());
|
iv->sendDevInfoRequest(_radio.get());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,11 +18,11 @@ bool DevInfoAllCommand::handleResponse(InverterAbstract* inverter, fragment_t fr
|
|||||||
|
|
||||||
// Move all fragments into target buffer
|
// Move all fragments into target buffer
|
||||||
uint8_t offs = 0;
|
uint8_t offs = 0;
|
||||||
inverter->DevInfo()->clearBuffer();
|
inverter->DevInfo()->clearBufferAll();
|
||||||
for (uint8_t i = 0; i < max_fragment_id; i++) {
|
for (uint8_t i = 0; i < max_fragment_id; i++) {
|
||||||
inverter->DevInfo()->appendFragment(offs, fragment[i].fragment, fragment[i].len);
|
inverter->DevInfo()->appendFragmentAll(offs, fragment[i].fragment, fragment[i].len);
|
||||||
offs += (fragment[i].len);
|
offs += (fragment[i].len);
|
||||||
}
|
}
|
||||||
inverter->DevInfo()->setLastUpdate(millis());
|
inverter->DevInfo()->setLastUpdateAll(millis());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
28
lib/Hoymiles/src/commands/DevInfoSampleCommand.cpp
Normal file
28
lib/Hoymiles/src/commands/DevInfoSampleCommand.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "DevInfoSampleCommand.h"
|
||||||
|
#include "inverters/InverterAbstract.h"
|
||||||
|
|
||||||
|
DevInfoSampleCommand::DevInfoSampleCommand(uint64_t target_address, uint64_t router_address, time_t time)
|
||||||
|
: MultiDataCommand(target_address, router_address)
|
||||||
|
{
|
||||||
|
setTime(time);
|
||||||
|
setDataType(0x00);
|
||||||
|
setTimeout(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DevInfoSampleCommand::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()->clearBufferSample();
|
||||||
|
for (uint8_t i = 0; i < max_fragment_id; i++) {
|
||||||
|
inverter->DevInfo()->appendFragmentSample(offs, fragment[i].fragment, fragment[i].len);
|
||||||
|
offs += (fragment[i].len);
|
||||||
|
}
|
||||||
|
inverter->DevInfo()->setLastUpdateSample(millis());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
10
lib/Hoymiles/src/commands/DevInfoSampleCommand.h
Normal file
10
lib/Hoymiles/src/commands/DevInfoSampleCommand.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MultiDataCommand.h"
|
||||||
|
|
||||||
|
class DevInfoSampleCommand : public MultiDataCommand {
|
||||||
|
public:
|
||||||
|
DevInfoSampleCommand(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);
|
||||||
|
};
|
||||||
@ -2,6 +2,7 @@
|
|||||||
#include "HoymilesRadio.h"
|
#include "HoymilesRadio.h"
|
||||||
#include "commands/AlarmDataCommand.h"
|
#include "commands/AlarmDataCommand.h"
|
||||||
#include "commands/DevInfoAllCommand.h"
|
#include "commands/DevInfoAllCommand.h"
|
||||||
|
#include "commands/DevInfoSampleCommand.h"
|
||||||
#include "commands/RealTimeRunDataCommand.h"
|
#include "commands/RealTimeRunDataCommand.h"
|
||||||
|
|
||||||
HM_Abstract::HM_Abstract(uint64_t serial)
|
HM_Abstract::HM_Abstract(uint64_t serial)
|
||||||
@ -59,9 +60,13 @@ bool HM_Abstract::sendDevInfoRequest(HoymilesRadio* radio)
|
|||||||
time_t now;
|
time_t now;
|
||||||
time(&now);
|
time(&now);
|
||||||
|
|
||||||
DevInfoAllCommand* cmd = radio->enqueCommand<DevInfoAllCommand>();
|
DevInfoAllCommand* cmdAll = radio->enqueCommand<DevInfoAllCommand>();
|
||||||
cmd->setTime(now);
|
cmdAll->setTime(now);
|
||||||
cmd->setTargetAddress(serial());
|
cmdAll->setTargetAddress(serial());
|
||||||
|
|
||||||
|
DevInfoSampleCommand* cmdSample = radio->enqueCommand<DevInfoSampleCommand>();
|
||||||
|
cmdSample->setTime(now);
|
||||||
|
cmdSample->setTargetAddress(serial());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1,44 +1,98 @@
|
|||||||
#include "DevInfoParser.h"
|
#include "DevInfoParser.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
void DevInfoParser::clearBuffer()
|
void DevInfoParser::clearBufferAll()
|
||||||
{
|
{
|
||||||
memset(_payloadDevInfo, 0, DEV_INFO_SIZE);
|
memset(_payloadDevInfoAll, 0, DEV_INFO_SIZE);
|
||||||
_devInfoLength = 0;
|
_devInfoAllLength = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevInfoParser::appendFragment(uint8_t offset, uint8_t* payload, uint8_t len)
|
void DevInfoParser::appendFragmentAll(uint8_t offset, uint8_t* payload, uint8_t len)
|
||||||
{
|
{
|
||||||
if (offset + len > DEV_INFO_SIZE) {
|
if (offset + len > DEV_INFO_SIZE) {
|
||||||
Serial.printf("FATAL: (%s, %d) dev info packet too large for buffer\n", __FILE__, __LINE__);
|
Serial.printf("FATAL: (%s, %d) dev info all packet too large for buffer\n", __FILE__, __LINE__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memcpy(&_payloadDevInfo[offset], payload, len);
|
memcpy(&_payloadDevInfoAll[offset], payload, len);
|
||||||
_devInfoLength += len;
|
_devInfoAllLength += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevInfoParser::clearBufferSample()
|
||||||
|
{
|
||||||
|
memset(_payloadDevInfoSample, 0, DEV_INFO_SIZE);
|
||||||
|
_devInfoSampleLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevInfoParser::appendFragmentSample(uint8_t offset, uint8_t* payload, uint8_t len)
|
||||||
|
{
|
||||||
|
if (offset + len > DEV_INFO_SIZE) {
|
||||||
|
Serial.printf("FATAL: (%s, %d) dev info Sample packet too large for buffer\n", __FILE__, __LINE__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(&_payloadDevInfoSample[offset], payload, len);
|
||||||
|
_devInfoSampleLength += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DevInfoParser::getLastUpdateAll()
|
||||||
|
{
|
||||||
|
return _lastUpdateAll;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevInfoParser::setLastUpdateAll(uint32_t lastUpdate)
|
||||||
|
{
|
||||||
|
_lastUpdateAll = lastUpdate;
|
||||||
|
setLastUpdate(lastUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DevInfoParser::getLastUpdateSample()
|
||||||
|
{
|
||||||
|
return _lastUpdateSample;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevInfoParser::setLastUpdateSample(uint32_t lastUpdate)
|
||||||
|
{
|
||||||
|
_lastUpdateSample = lastUpdate;
|
||||||
|
setLastUpdate(lastUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t DevInfoParser::getFwBuildVersion()
|
uint16_t DevInfoParser::getFwBuildVersion()
|
||||||
{
|
{
|
||||||
return (((uint16_t)_payloadDevInfo[0]) << 8) | _payloadDevInfo[1];
|
return (((uint16_t)_payloadDevInfoAll[0]) << 8) | _payloadDevInfoAll[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t DevInfoParser::getFwBuildDateTime()
|
time_t DevInfoParser::getFwBuildDateTime()
|
||||||
{
|
{
|
||||||
struct tm timeinfo = { 0 };
|
struct tm timeinfo = { 0 };
|
||||||
timeinfo.tm_year = ((((uint16_t)_payloadDevInfo[2]) << 8) | _payloadDevInfo[3]) - 1900;
|
timeinfo.tm_year = ((((uint16_t)_payloadDevInfoAll[2]) << 8) | _payloadDevInfoAll[3]) - 1900;
|
||||||
|
|
||||||
timeinfo.tm_mon = ((((uint16_t)_payloadDevInfo[4]) << 8) | _payloadDevInfo[5]) / 100 - 1;
|
timeinfo.tm_mon = ((((uint16_t)_payloadDevInfoAll[4]) << 8) | _payloadDevInfoAll[5]) / 100 - 1;
|
||||||
timeinfo.tm_mday = ((((uint16_t)_payloadDevInfo[4]) << 8) | _payloadDevInfo[5]) % 100;
|
timeinfo.tm_mday = ((((uint16_t)_payloadDevInfoAll[4]) << 8) | _payloadDevInfoAll[5]) % 100;
|
||||||
|
|
||||||
timeinfo.tm_hour = ((((uint16_t)_payloadDevInfo[6]) << 8) | _payloadDevInfo[7]) / 100;
|
timeinfo.tm_hour = ((((uint16_t)_payloadDevInfoAll[6]) << 8) | _payloadDevInfoAll[7]) / 100;
|
||||||
timeinfo.tm_min = ((((uint16_t)_payloadDevInfo[6]) << 8) | _payloadDevInfo[7]) % 100;
|
timeinfo.tm_min = ((((uint16_t)_payloadDevInfoAll[6]) << 8) | _payloadDevInfoAll[7]) % 100;
|
||||||
|
|
||||||
return timegm(&timeinfo);
|
return timegm(&timeinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t DevInfoParser::getFwBootloaderVersion()
|
uint16_t DevInfoParser::getFwBootloaderVersion()
|
||||||
{
|
{
|
||||||
return (((uint16_t)_payloadDevInfo[8]) << 8) | _payloadDevInfo[9];
|
return (((uint16_t)_payloadDevInfoAll[8]) << 8) | _payloadDevInfoAll[9];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DevInfoParser::getHwPartNumber()
|
||||||
|
{
|
||||||
|
uint16_t hwpn_h;
|
||||||
|
uint16_t hwpn_l;
|
||||||
|
|
||||||
|
hwpn_h = (((uint16_t)_payloadDevInfoSample[2]) << 8) | _payloadDevInfoSample[3];
|
||||||
|
hwpn_l = (((uint16_t)_payloadDevInfoSample[4]) << 8) | _payloadDevInfoSample[5];
|
||||||
|
|
||||||
|
return ((uint32_t)hwpn_h << 16) | ((uint32_t)hwpn_l);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t DevInfoParser::getHwVersion()
|
||||||
|
{
|
||||||
|
return (((uint16_t)_payloadDevInfoSample[6]) << 8) | _payloadDevInfoSample[7];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* struct tm to seconds since Unix epoch */
|
/* struct tm to seconds since Unix epoch */
|
||||||
|
|||||||
@ -5,16 +5,34 @@
|
|||||||
|
|
||||||
class DevInfoParser : public Parser {
|
class DevInfoParser : public Parser {
|
||||||
public:
|
public:
|
||||||
void clearBuffer();
|
void clearBufferAll();
|
||||||
void appendFragment(uint8_t offset, uint8_t* payload, uint8_t len);
|
void appendFragmentAll(uint8_t offset, uint8_t* payload, uint8_t len);
|
||||||
|
|
||||||
|
void clearBufferSample();
|
||||||
|
void appendFragmentSample(uint8_t offset, uint8_t* payload, uint8_t len);
|
||||||
|
|
||||||
|
uint32_t getLastUpdateAll();
|
||||||
|
void setLastUpdateAll(uint32_t lastUpdate);
|
||||||
|
|
||||||
|
uint32_t getLastUpdateSample();
|
||||||
|
void setLastUpdateSample(uint32_t lastUpdate);
|
||||||
|
|
||||||
uint16_t getFwBuildVersion();
|
uint16_t getFwBuildVersion();
|
||||||
time_t getFwBuildDateTime();
|
time_t getFwBuildDateTime();
|
||||||
uint16_t getFwBootloaderVersion();
|
uint16_t getFwBootloaderVersion();
|
||||||
|
|
||||||
private:
|
uint32_t getHwPartNumber();
|
||||||
time_t timegm(struct tm *tm);
|
uint16_t getHwVersion();
|
||||||
|
|
||||||
uint8_t _payloadDevInfo[DEV_INFO_SIZE];
|
private:
|
||||||
uint8_t _devInfoLength;
|
time_t timegm(struct tm* tm);
|
||||||
|
|
||||||
|
uint32_t _lastUpdateAll = 0;
|
||||||
|
uint32_t _lastUpdateSample = 0;
|
||||||
|
|
||||||
|
uint8_t _payloadDevInfoAll[DEV_INFO_SIZE];
|
||||||
|
uint8_t _devInfoAllLength;
|
||||||
|
|
||||||
|
uint8_t _payloadDevInfoSample[DEV_INFO_SIZE];
|
||||||
|
uint8_t _devInfoSampleLength;
|
||||||
};
|
};
|
||||||
Loading…
Reference in New Issue
Block a user