mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-22 21:36:11 +02:00
Merge branch 'development03' into hms
This commit is contained in:
commit
8ad9a919f4
9 changed files with 200 additions and 195 deletions
|
@ -2,6 +2,10 @@
|
|||
|
||||
(starting from release version `0.5.66`)
|
||||
|
||||
## 0.5.106
|
||||
* merged MI and debug message changes #804
|
||||
* fixed MQTT autodiscover #794, #632
|
||||
|
||||
## 0.5.105
|
||||
* merged MI, thx @rejoe2 #788
|
||||
* fixed reboot message #793
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
//-------------------------------------
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 5
|
||||
#define VERSION_PATCH 105
|
||||
#define VERSION_PATCH 106
|
||||
|
||||
//-------------------------------------
|
||||
typedef struct {
|
||||
|
|
|
@ -144,10 +144,9 @@ class Inverter {
|
|||
template <typename T>
|
||||
void enqueCommand(uint8_t cmd) {
|
||||
_commandQueue.push(std::make_shared<T>(cmd));
|
||||
DPRINT(DBG_INFO, F("(#"));
|
||||
DBGPRINT(String(id));
|
||||
DBGPRINT(F(") enqueCommand: 0x"));
|
||||
DHEX(cmd);
|
||||
DPRINT_IVID(DBG_INFO, id);
|
||||
DBGPRINTLN(F("enqueCommand: 0x"));
|
||||
DBGHEXLN(cmd);
|
||||
}
|
||||
|
||||
void setQueuedCmdFinished() {
|
||||
|
@ -290,7 +289,8 @@ class Inverter {
|
|||
alarmMesIndex = rec->record[pos];
|
||||
//enqueCommand<InfoCommand>(AlarmUpdate); // What is the function of AlarmUpdate?
|
||||
|
||||
DPRINTLN(DBG_INFO, "alarm ID incremented to " + String(alarmMesIndex));
|
||||
DPRINT(DBG_INFO, "alarm ID incremented to ");
|
||||
DBGPRINTLN(String(alarmMesIndex));
|
||||
enqueCommand<InfoCommand>(AlarmData);
|
||||
}
|
||||
}
|
||||
|
@ -304,7 +304,8 @@ class Inverter {
|
|||
DPRINTLN(DBG_DEBUG, "add config");
|
||||
if (getPosByChFld(0, FLD_ACT_ACTIVE_PWR_LIMIT, rec) == pos){
|
||||
actPowerLimit = rec->record[pos];
|
||||
DPRINT(DBG_DEBUG, F("Inverter actual power limit: ") + String(actPowerLimit, 1));
|
||||
DPRINT(DBG_DEBUG, F("Inverter actual power limit: "));
|
||||
DBGPRINTLN(String(actPowerLimit, 1));
|
||||
}
|
||||
}
|
||||
else if (rec->assign == AlarmDataAssignment) {
|
||||
|
|
|
@ -118,12 +118,10 @@ class HmPayload {
|
|||
mStat->rxFail++; // got fragments but not complete response
|
||||
|
||||
iv->setQueuedCmdFinished(); // command failed
|
||||
if (mSerialDebug)
|
||||
DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout"));
|
||||
if (mSerialDebug) {
|
||||
DPRINT(DBG_INFO, F("(#"));
|
||||
DBGPRINT(String(iv->id));
|
||||
DBGPRINT(F(") no Payload received! (retransmits: "));
|
||||
DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout"));
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINT(F("no Payload received! (retransmits: "));
|
||||
DBGPRINT(String(mPayload[iv->id].retransmits));
|
||||
DBGPRINTLN(F(")"));
|
||||
}
|
||||
|
@ -136,17 +134,15 @@ class HmPayload {
|
|||
|
||||
yield();
|
||||
if (mSerialDebug) {
|
||||
DPRINT(DBG_INFO, F("(#"));
|
||||
DBGPRINT(String(iv->id));
|
||||
DBGPRINT(F(") Requesting Inv SN "));
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINT(F("Requesting Inv SN "));
|
||||
DBGPRINTLN(String(iv->config->serial.u64, HEX));
|
||||
}
|
||||
|
||||
if (iv->getDevControlRequest()) {
|
||||
if (mSerialDebug) {
|
||||
DPRINT(DBG_INFO, F("(#"));
|
||||
DBGPRINT(String(iv->id));
|
||||
DBGPRINT(F(") Devcontrol request 0x"));
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINT(F("Devcontrol request 0x"));
|
||||
DBGPRINT(String(iv->devControlCmd, HEX));
|
||||
DBGPRINT(F(" power limit "));
|
||||
DBGPRINTLN(String(iv->powerLimit[0]));
|
||||
|
@ -157,10 +153,9 @@ class HmPayload {
|
|||
//iv->enqueCommand<InfoCommand>(SystemConfigPara); // read back power limit
|
||||
} else {
|
||||
uint8_t cmd = iv->getQueuedCmd();
|
||||
DPRINT(DBG_INFO, F("(#"));
|
||||
DBGPRINT(String(iv->id));
|
||||
DBGPRINT(F(") prepareDevInformCmd 0x"));
|
||||
DBGPRINTLN(String(cmd, HEX));
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINT(F("prepareDevInformCmd 0x"));
|
||||
DBGHEXLN(cmd);
|
||||
mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false);
|
||||
mPayload[iv->id].txCmd = cmd;
|
||||
}
|
||||
|
@ -172,9 +167,10 @@ class HmPayload {
|
|||
DPRINTLN(DBG_DEBUG, F("Response from info request received"));
|
||||
uint8_t *pid = &p->packet[9];
|
||||
if (*pid == 0x00) {
|
||||
DPRINT(DBG_DEBUG, F("fragment number zero received and ignored"));
|
||||
DPRINTLN(DBG_DEBUG, F("fragment number zero received and ignored"));
|
||||
} else {
|
||||
DPRINTLN(DBG_DEBUG, "PID: 0x" + String(*pid, HEX));
|
||||
DPRINT(DBG_DEBUG, F("PID: 0x"));
|
||||
DBGHEXLN(*pid);
|
||||
if ((*pid & 0x7F) < MAX_PAYLOAD_ENTRIES) {
|
||||
memcpy(mPayload[iv->id].data[(*pid & 0x7F) - 1], &p->packet[10], p->len - 11);
|
||||
mPayload[iv->id].len[(*pid & 0x7F) - 1] = p->len - 11;
|
||||
|
@ -202,8 +198,8 @@ class HmPayload {
|
|||
mApp->setMqttPowerLimitAck(iv);
|
||||
else
|
||||
ok = false;
|
||||
DPRINT(DBG_INFO, F("(#"));
|
||||
DBGPRINT(String(iv->id));
|
||||
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINT(F(" has "));
|
||||
if(!ok) DBGPRINT(F("not "));
|
||||
DBGPRINT(F("accepted power limit set point "));
|
||||
|
@ -245,9 +241,8 @@ class HmPayload {
|
|||
DPRINTLN(DBG_INFO, F("Prevent retransmit on Restart / CleanState_LockAndAlarm..."));
|
||||
mPayload[iv->id].retransmits = mMaxRetrans;
|
||||
} else if(iv->devControlCmd == ActivePowerContr) {
|
||||
DPRINT(DBG_INFO, F("(#"));
|
||||
DBGPRINT(String(iv->id));
|
||||
DPRINTLN(DBG_INFO, F(") retransmit power limit"));
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DPRINTLN(DBG_INFO, F("retransmit power limit"));
|
||||
mRadio->sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true);
|
||||
} else {
|
||||
if(false == mPayload[iv->id].gotFragment) {
|
||||
|
@ -257,16 +252,14 @@ class HmPayload {
|
|||
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") prepareDevInformCmd 0x") + String(mPayload[iv->id].txCmd, HEX));
|
||||
mRadio->prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true);
|
||||
*/
|
||||
DPRINT(DBG_INFO, F("(#"));
|
||||
DBGPRINT(String(iv->id));
|
||||
DBGPRINTLN(F(") nothing received"));
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINTLN(F("nothing received"));
|
||||
mPayload[iv->id].retransmits = mMaxRetrans;
|
||||
} else {
|
||||
for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) {
|
||||
if (mPayload[iv->id].len[i] == 0) {
|
||||
DPRINT(DBG_WARN, F("(#"));
|
||||
DBGPRINT(String(iv->id));
|
||||
DBGPRINT(F(") Frame "));
|
||||
DPRINT_IVID(DBG_WARN, iv->id);
|
||||
DBGPRINT(F("Frame "));
|
||||
DBGPRINT(String(i + 1));
|
||||
DBGPRINTLN(F(" missing: Request Retransmit"));
|
||||
mRadio->sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true);
|
||||
|
@ -283,19 +276,18 @@ class HmPayload {
|
|||
mPayload[iv->id].retransmits++;
|
||||
DPRINTLN(DBG_WARN, F("CRC Error: Request Complete Retransmit"));
|
||||
mPayload[iv->id].txCmd = iv->getQueuedCmd();
|
||||
DPRINT(DBG_INFO, F("(#"));
|
||||
DBGPRINT(String(iv->id));
|
||||
DBGPRINT(F(") prepareDevInformCmd 0x"));
|
||||
DHEXLN(mPayload[iv->id].txCmd);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINT(F("prepareDevInformCmd 0x"));
|
||||
DBGHEXLN(mPayload[iv->id].txCmd);
|
||||
mRadio->prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true);
|
||||
}
|
||||
} else { // payload complete
|
||||
DPRINT(DBG_INFO, F("procPyld: cmd: 0x"));
|
||||
DHEXLN(mPayload[iv->id].txCmd);
|
||||
DBGHEXLN(mPayload[iv->id].txCmd);
|
||||
DPRINT(DBG_INFO, F("procPyld: txid: 0x"));
|
||||
DHEXLN(mPayload[iv->id].txId);
|
||||
DPRINTLN(DBG_DEBUG, F("procPyld: max: "));
|
||||
DBGPRINT(String(mPayload[iv->id].maxPackId));
|
||||
DBGHEXLN(mPayload[iv->id].txId);
|
||||
DPRINT(DBG_DEBUG, F("procPyld: max: "));
|
||||
DBGPRINTLN(String(mPayload[iv->id].maxPackId));
|
||||
record_t<> *rec = iv->getRecordStruct(mPayload[iv->id].txCmd); // choose the parser
|
||||
mPayload[iv->id].complete = true;
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ class HmRadio {
|
|||
|
||||
void sendControlPacket(uint64_t invId, uint8_t cmd, uint16_t *data, bool isRetransmit, bool isNoMI = true) {
|
||||
DPRINT(DBG_INFO, F("sendControlPacket cmd: 0x"));
|
||||
DBGPRINTLN(String(cmd, HEX));
|
||||
DBGHEXLN(cmd);
|
||||
initPacket(invId, TX_REQ_DEVCONTROL, SINGLE_FRAME);
|
||||
uint8_t cnt = 10;
|
||||
if (isNoMI) {
|
||||
|
@ -187,6 +187,7 @@ class HmRadio {
|
|||
default:
|
||||
return;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
sendPacket(invId, cnt, isRetransmit);
|
||||
}
|
||||
|
|
|
@ -94,10 +94,10 @@ class MiPayload {
|
|||
|
||||
iv->setQueuedCmdFinished(); // command failed
|
||||
if (mSerialDebug)
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINTLN(F("enqueued cmd failed/timeout"));
|
||||
if (mSerialDebug) {
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINT(F("no Payload received! (retransmits: "));
|
||||
DBGPRINT(String(mPayload[iv->id].retransmits));
|
||||
DBGPRINTLN(F(")"));
|
||||
|
@ -111,14 +111,14 @@ class MiPayload {
|
|||
|
||||
yield();
|
||||
if (mSerialDebug){
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINT(F("Requesting Inv SN "));
|
||||
DBGPRINTLN(String(iv->config->serial.u64, HEX));
|
||||
}
|
||||
|
||||
if (iv->getDevControlRequest()) {
|
||||
if (mSerialDebug) {
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINT(F("Devcontrol request 0x"));
|
||||
DHEX(iv->devControlCmd);
|
||||
DBGPRINT(F(" power limit "));
|
||||
|
@ -132,9 +132,9 @@ class MiPayload {
|
|||
iv->enqueCommand<InfoCommand>(SystemConfigPara); // try to read back power limit
|
||||
} else {
|
||||
uint8_t cmd = iv->getQueuedCmd();
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINT(F("prepareDevInformCmd 0x"));
|
||||
DHEXLN(cmd);
|
||||
DBGHEXLN(cmd);
|
||||
uint8_t cmd2 = cmd;
|
||||
if ( cmd == SystemConfigPara ) { //0x05 for HM-types
|
||||
if (!mPayload[iv->id].limitrequested) { // only do once at startup
|
||||
|
@ -180,7 +180,8 @@ class MiPayload {
|
|||
|
||||
else if ( p->packet[0] == 0x09 + ALL_FRAMES ||
|
||||
p->packet[0] == 0x11 + ALL_FRAMES ||
|
||||
( p->packet[0] >= (0x36 + ALL_FRAMES) && p->packet[0] < (0x39 + SINGLE_FRAME) ) ) { // small MI or MI 1500 data responses to 0x09, 0x11, 0x36, 0x37, 0x38 and 0x39
|
||||
( p->packet[0] >= (0x36 + ALL_FRAMES) && p->packet[0] < (0x39 + SINGLE_FRAME)
|
||||
&& mPayload[iv->id].txCmd != 0x0f) ) { // small MI or MI 1500 data responses to 0x09, 0x11, 0x36, 0x37, 0x38 and 0x39
|
||||
mPayload[iv->id].txId = p->packet[0];
|
||||
miDataDecode(iv,p);
|
||||
}
|
||||
|
@ -231,13 +232,15 @@ const byteAssign_t InfoAssignment[] = {
|
|||
iv->setValue(i, rec, (float) ((p->packet[(12+2*i)] << 8) + p->packet[(13+2*i)])/1);
|
||||
}
|
||||
iv->isConnected = true;
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
if(mSerialDebug) {
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DPRINT(DBG_INFO,F("HW_VER is "));
|
||||
DBGPRINTLN(String((p->packet[24] << 8) + p->packet[25]));
|
||||
}
|
||||
/*iv->setQueuedCmdFinished();
|
||||
mSys->Radio.sendCmdPacket(iv->radioId.u64, 0x0f, 0x01, false);*/
|
||||
} else if ( p->packet[9] == 0x01 || p->packet[9] == 0x10 ) {//second frame for MI, 3rd gen. answers in 0x10
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
if ( p->packet[9] == 0x01 ) {
|
||||
DBGPRINTLN(F("got 2nd frame (hw info)"));
|
||||
} else {
|
||||
|
@ -248,9 +251,11 @@ const byteAssign_t InfoAssignment[] = {
|
|||
DBGPRINTLN(String((uint32_t) (((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13]));
|
||||
//DBGPRINTLN(String((p->packet[12] << 8) + p->packet[13]));
|
||||
if ( p->packet[9] == 0x01 ) {
|
||||
iv->setValue(iv->getPosByChFld(0, FLD_YT, rec), rec, (float) ((p->packet[20] << 8) + p->packet[21])/1);
|
||||
if(mSerialDebug) {
|
||||
DPRINT(DBG_INFO,F("HW_ECapValue "));
|
||||
DBGPRINTLN(String((p->packet[20] << 8) + p->packet[21]));
|
||||
iv->setValue(iv->getPosByChFld(0, FLD_YT, rec), rec, (float) ((p->packet[20] << 8) + p->packet[21])/1);
|
||||
|
||||
DPRINT(DBG_INFO,F("HW_FB_TLmValue "));
|
||||
DBGPRINTLN(String((p->packet[14] << 8) + p->packet[15]));
|
||||
DPRINT(DBG_INFO,F("HW_FB_ReSPRT "));
|
||||
|
@ -258,8 +263,9 @@ const byteAssign_t InfoAssignment[] = {
|
|||
DPRINT(DBG_INFO,F("HW_GridSamp_ResValule "));
|
||||
DBGPRINTLN(String((p->packet[18] << 8) + p->packet[19]));
|
||||
}
|
||||
}
|
||||
} else if ( p->packet[9] == 0x12 ) {//3rd frame
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINTLN(F("got 3rd frame (hw info)"));
|
||||
iv->setQueuedCmdFinished();
|
||||
mStat->rxSuccess++;
|
||||
|
@ -276,9 +282,8 @@ const byteAssign_t InfoAssignment[] = {
|
|||
DPRINT(DBG_DEBUG, F("fragment number zero received"));
|
||||
iv->setQueuedCmdFinished();
|
||||
} else if (p->packet[9] == 0x81) { // might need some additional check, as this is only ment for short answers!
|
||||
DPRINT(DBG_WARN, F("(#"));
|
||||
DBGPRINT(String(iv->id));
|
||||
DBGPRINTLN(F(") seems to use 3rd gen. protocol - switching ivGen!"));
|
||||
DPRINT_IVID(DBG_WARN, iv->id);
|
||||
DBGPRINTLN(F("seems to use 3rd gen. protocol - switching ivGen!"));
|
||||
iv->ivGen = IV_HM;
|
||||
iv->setQueuedCmdFinished();
|
||||
iv->clearCmdQueue();
|
||||
|
@ -301,7 +306,7 @@ const byteAssign_t InfoAssignment[] = {
|
|||
//}
|
||||
} else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES ) // response from dev control command
|
||||
|| p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES -1)) { // response from DRED instruction
|
||||
DPRINTHEAD(DBG_DEBUG, iv->id);
|
||||
DPRINT_IVID(DBG_DEBUG, iv->id);
|
||||
DBGPRINTLN(F("Response from devcontrol request received"));
|
||||
|
||||
mPayload[iv->id].txId = p->packet[0];
|
||||
|
@ -309,7 +314,7 @@ const byteAssign_t InfoAssignment[] = {
|
|||
|
||||
if ((p->packet[9] == 0x5a) && (p->packet[10] == 0x5a)) {
|
||||
mApp->setMqttPowerLimitAck(iv);
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINT(F("has accepted power limit set point "));
|
||||
DBGPRINT(String(iv->powerLimit[0]));
|
||||
DBGPRINT(F(" with PowerLimitControl "));
|
||||
|
@ -321,9 +326,9 @@ const byteAssign_t InfoAssignment[] = {
|
|||
iv->devControlCmd = Init;
|
||||
} else { // some other response; copied from hmPayload:process; might not be correct to do that here!!!
|
||||
DPRINT(DBG_INFO, F("procPyld: cmd: 0x"));
|
||||
DHEXLN(mPayload[iv->id].txCmd);
|
||||
DBGHEXLN(mPayload[iv->id].txCmd);
|
||||
DPRINT(DBG_INFO, F("procPyld: txid: 0x"));
|
||||
DHEXLN(mPayload[iv->id].txId);
|
||||
DBGHEXLN(mPayload[iv->id].txId);
|
||||
//DPRINT(DBG_DEBUG, F("procPyld: max: "));
|
||||
//DBGPRINTLN(String(mPayload[iv->id].maxPackId));
|
||||
record_t<> *rec = iv->getRecordStruct(mPayload[iv->id].txCmd); // choose the parser
|
||||
|
@ -420,11 +425,11 @@ const byteAssign_t InfoAssignment[] = {
|
|||
if ((mPayload[iv->id].requested) && (retransmit)) {
|
||||
if (iv->devControlCmd == Restart || iv->devControlCmd == CleanState_LockAndAlarm) {
|
||||
// This is required to prevent retransmissions without answer.
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINTLN(F("Prevent retransmit on Restart / CleanState_LockAndAlarm..."));
|
||||
mPayload[iv->id].retransmits = mMaxRetrans;
|
||||
} else if(iv->devControlCmd == ActivePowerContr) {
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINTLN(F("retransmit power limit"));
|
||||
mRadio->sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true, false);
|
||||
} else {
|
||||
|
@ -432,7 +437,7 @@ const byteAssign_t InfoAssignment[] = {
|
|||
if (mPayload[iv->id].retransmits < mMaxRetrans) {
|
||||
mPayload[iv->id].retransmits++;
|
||||
if( !mPayload[iv->id].gotFragment ) {
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINTLN(F("nothing received"));
|
||||
mPayload[iv->id].retransmits = mMaxRetrans;
|
||||
} else if ( cmd == 0x0f ) {
|
||||
|
@ -463,7 +468,7 @@ const byteAssign_t InfoAssignment[] = {
|
|||
}
|
||||
}
|
||||
}
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
if (change) {
|
||||
DBGPRINT(F("next request is"));
|
||||
//mPayload[iv->id].skipfirstrepeat = 0;
|
||||
|
@ -472,7 +477,7 @@ const byteAssign_t InfoAssignment[] = {
|
|||
DBGPRINT(F(" missing: Request Retransmit"));
|
||||
}
|
||||
DBGPRINT(F(" 0x"));
|
||||
DHEXLN(cmd);
|
||||
DBGHEXLN(cmd);
|
||||
//mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd, true);
|
||||
mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, true, cmd);
|
||||
mPayload[iv->id].txCmd = cmd;
|
||||
|
@ -484,13 +489,13 @@ const byteAssign_t InfoAssignment[] = {
|
|||
} else if(!crcPass && pyldComplete) { // crc error on complete Payload
|
||||
if (mPayload[iv->id].retransmits < mMaxRetrans) {
|
||||
mPayload[iv->id].retransmits++;
|
||||
DPRINTHEAD(DBG_WARN, iv->id);
|
||||
DPRINT_IVID(DBG_WARN, iv->id);
|
||||
DBGPRINTLN(F("CRC Error: Request Complete Retransmit"));
|
||||
mPayload[iv->id].txCmd = iv->getQueuedCmd();
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
|
||||
DBGPRINT(F("prepareDevInformCmd 0x"));
|
||||
DHEXLN(mPayload[iv->id].txCmd);
|
||||
DBGHEXLN(mPayload[iv->id].txCmd);
|
||||
mRadio->prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true);
|
||||
}
|
||||
}
|
||||
|
@ -574,8 +579,8 @@ const byteAssign_t InfoAssignment[] = {
|
|||
void miStsConsolidate(Inverter<> *iv, uint8_t stschan, record_t<> *rec, uint8_t uState, uint8_t uEnum, uint8_t lState = 0, uint8_t lEnum = 0) {
|
||||
//uint8_t status = (p->packet[11] << 8) + p->packet[12];
|
||||
uint16_t status = 3; // regular status for MI, change to 1 later?
|
||||
if ( uState < 3 ) {
|
||||
status = uState*100 + stschan; //first approach, needs review!
|
||||
if ( uState == 2 ) {
|
||||
status = 5050 + stschan; //first approach, needs review!
|
||||
if (lState)
|
||||
status += lState*10;
|
||||
} else if ( uState > 3 ) {
|
||||
|
@ -587,13 +592,16 @@ const byteAssign_t InfoAssignment[] = {
|
|||
if (uEnum < 6) {
|
||||
status += stschan;
|
||||
}
|
||||
if (status == 8000)
|
||||
status = 8310; //trick?
|
||||
}
|
||||
|
||||
uint16_t prntsts = status == 3 ? 1 : status;
|
||||
if ( status != mPayload[iv->id].sts[stschan] ) { //sth.'s changed?
|
||||
mPayload[iv->id].sts[stschan] = status;
|
||||
DPRINT(DBG_WARN, F("Status change for CH"));
|
||||
DBGPRINT(String(stschan)); DBGPRINT(F(": "));
|
||||
DBGPRINT(String(stschan)); DBGPRINT(F(" ("));
|
||||
DBGPRINT(String(prntsts)); DBGPRINT(F("): "));
|
||||
DBGPRINTLN(iv->getAlarmStr(prntsts));
|
||||
}
|
||||
|
||||
|
@ -605,7 +613,7 @@ const byteAssign_t InfoAssignment[] = {
|
|||
if (iv->alarmMesIndex < rec->record[iv->getPosByChFld(0, FLD_EVT, rec)]){
|
||||
iv->alarmMesIndex = rec->record[iv->getPosByChFld(0, FLD_EVT, rec)]; // seems there's no status per channel in 3rd gen. models?!?
|
||||
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINT(F("alarm ID incremented to "));
|
||||
DBGPRINTLN(String(iv->alarmMesIndex));
|
||||
}
|
||||
|
@ -692,7 +700,7 @@ const byteAssign_t InfoAssignment[] = {
|
|||
/*if (iv->alarmMesIndex < rec->record[iv->getPosByChFld(0, FLD_EVT, rec)]){
|
||||
iv->alarmMesIndex = rec->record[iv->getPosByChFld(0, FLD_EVT, rec)];
|
||||
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINT_TXT(TXT_INCRALM);
|
||||
DBGPRINTLN(String(iv->alarmMesIndex));
|
||||
}*/
|
||||
|
@ -728,7 +736,7 @@ const byteAssign_t InfoAssignment[] = {
|
|||
if (mPayload[iv->id].complete)
|
||||
return; //if we got second message as well in repreated attempt
|
||||
mPayload[iv->id].complete = true; // For 2 CH devices, this might be too short...
|
||||
DPRINTHEAD(DBG_INFO, iv->id);
|
||||
DPRINT_IVID(DBG_INFO, iv->id);
|
||||
DBGPRINTLN(F("got all msgs"));
|
||||
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||
iv->setValue(iv->getPosByChFld(0, FLD_YD, rec), rec, calcYieldDayCh0(iv,0));
|
||||
|
@ -753,38 +761,23 @@ const byteAssign_t InfoAssignment[] = {
|
|||
|
||||
bool build(uint8_t id, bool *complete) {
|
||||
DPRINTLN(DBG_VERBOSE, F("build"));
|
||||
//DPRINTLN_TXT(DBG_VERBOSE, TXT_BUILD);
|
||||
/*uint16_t crc = 0xffff, crcRcv = 0x0000;
|
||||
if (mPayload[id].maxPackId > MAX_PAYLOAD_ENTRIES)
|
||||
mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES;
|
||||
*/
|
||||
// check if all messages are there
|
||||
|
||||
*complete = mPayload[id].complete;
|
||||
uint8_t txCmd = mPayload[id].txCmd;
|
||||
//uint8_t cmd = getQueuedCmd();
|
||||
|
||||
if(!*complete) {
|
||||
DPRINTLN(DBG_VERBOSE, F("incomlete, txCmd is 0x") + String(txCmd, HEX)); // + F("cmd is 0x") + String(cmd, HEX));
|
||||
DPRINTLN(DBG_VERBOSE, F("incomlete, txCmd is 0x") + String(txCmd, HEX));
|
||||
//DBGHEXLN(txCmd);
|
||||
if (txCmd == 0x09 || txCmd == 0x11 || (txCmd >= 0x36 && txCmd <= 0x39))
|
||||
return false;
|
||||
}
|
||||
|
||||
/*for (uint8_t i = 0; i < mPayload[id].maxPackId; i++) {
|
||||
if (mPayload[id].len[i] > 0) {
|
||||
if (i == (mPayload[id].maxPackId - 1)) {
|
||||
crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i] - 2, crc);
|
||||
crcRcv = (mPayload[id].data[i][mPayload[id].len[i] - 2] << 8) | (mPayload[id].data[i][mPayload[id].len[i] - 1]);
|
||||
} else
|
||||
crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i], crc);
|
||||
}
|
||||
yield();
|
||||
}
|
||||
return (crc == crcRcv) ? true : false;*/
|
||||
return true;
|
||||
}
|
||||
|
||||
void reset(uint8_t id, bool clrSts = false) {
|
||||
DPRINTHEAD(DBG_INFO, id);
|
||||
DPRINT_IVID(DBG_INFO, id);
|
||||
DBGPRINTLN(F("resetPayload"));
|
||||
memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES);
|
||||
mPayload[id].gotFragment = false;
|
||||
|
|
|
@ -35,25 +35,20 @@ extra_scripts =
|
|||
|
||||
lib_deps =
|
||||
https://github.com/yubox-node-org/ESPAsyncWebServer
|
||||
nrf24/RF24
|
||||
paulstoffregen/Time
|
||||
nrf24/RF24 @ ^1.4.5
|
||||
paulstoffregen/Time @ ^1.6.1
|
||||
https://github.com/bertmelis/espMqttClient#v1.4.1
|
||||
bblanchon/ArduinoJson
|
||||
https://github.com/JChristensen/Timezone
|
||||
olikraus/U8g2
|
||||
zinggjm/GxEPD2@^1.5.0
|
||||
;esp8266/DNSServer
|
||||
;esp8266/EEPROM
|
||||
;esp8266/ESP8266WiFi
|
||||
;esp8266/SPI
|
||||
;esp8266/Ticker
|
||||
bblanchon/ArduinoJson @ ^6.21.0
|
||||
https://github.com/JChristensen/Timezone @ ^1.2.4
|
||||
olikraus/U8g2 @ ^2.34.16
|
||||
zinggjm/GxEPD2 @ ^1.5.0
|
||||
|
||||
|
||||
[env:esp8266-release]
|
||||
platform = espressif8266
|
||||
board = esp12e
|
||||
board_build.f_cpu = 80000000L
|
||||
build_flags = -D RELEASE
|
||||
build_flags = -D RELEASE -Wl,-Map,output.map
|
||||
monitor_filters =
|
||||
;default ; Remove typical terminal control codes from input
|
||||
;time ; Add timestamp with milliseconds for each new line
|
||||
|
|
|
@ -34,6 +34,12 @@ struct alarm_t {
|
|||
alarm_t(uint16_t c, uint32_t s, uint32_t e) : code(c), start(s), end(e) {}
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
bool running;
|
||||
uint8_t lastIvId;
|
||||
uint8_t sub;
|
||||
} discovery_t;
|
||||
|
||||
template<class HMSYSTEM>
|
||||
class PubMqtt {
|
||||
public:
|
||||
|
@ -55,6 +61,8 @@ class PubMqtt {
|
|||
mUtcTimestamp = utcTs;
|
||||
mIntervalTimeout = 1;
|
||||
|
||||
mDiscovery.running = false;
|
||||
|
||||
snprintf(mLwtTopic, MQTT_TOPIC_LEN + 5, "%s/mqtt", mCfgMqtt->topic);
|
||||
|
||||
if((strlen(mCfgMqtt->user) > 0) && (strlen(mCfgMqtt->pwd) > 0))
|
||||
|
@ -82,6 +90,9 @@ class PubMqtt {
|
|||
mClient.loop();
|
||||
yield();
|
||||
#endif
|
||||
|
||||
if(mDiscovery.running)
|
||||
discoveryConfigLoop();
|
||||
}
|
||||
|
||||
|
||||
|
@ -210,92 +221,9 @@ class PubMqtt {
|
|||
|
||||
void sendDiscoveryConfig(void) {
|
||||
DPRINTLN(DBG_VERBOSE, F("sendMqttDiscoveryConfig"));
|
||||
|
||||
char topic[64], name[32], uniq_id[32];
|
||||
DynamicJsonDocument doc(256);
|
||||
|
||||
uint8_t fldTotal[4] = {FLD_PAC, FLD_YT, FLD_YD, FLD_PDC};
|
||||
const char* unitTotal[4] = {"W", "kWh", "Wh", "W"};
|
||||
|
||||
String node_mac = WiFi.macAddress().substring(12,14)+ WiFi.macAddress().substring(15,17);
|
||||
String node_id = "AHOY_DTU_" + node_mac;
|
||||
bool total = false;
|
||||
|
||||
for (uint8_t id = 0; id < mSys->getNumInverters() ; id++) {
|
||||
doc.clear();
|
||||
|
||||
if (total) // total become true at iv = NULL next cycle
|
||||
continue;
|
||||
|
||||
Inverter<> *iv = mSys->getInverterByPos(id);
|
||||
if (NULL == iv)
|
||||
total = true;
|
||||
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||
|
||||
if (!total) {
|
||||
doc[F("name")] = iv->config->name;
|
||||
doc[F("ids")] = String(iv->config->serial.u64, HEX);
|
||||
doc[F("mdl")] = iv->config->name;
|
||||
}
|
||||
else {
|
||||
doc[F("name")] = node_id;
|
||||
doc[F("ids")] = node_id;
|
||||
doc[F("mdl")] = node_id;
|
||||
}
|
||||
|
||||
doc[F("cu")] = F("http://") + String(WiFi.localIP().toString());
|
||||
doc[F("mf")] = F("Hoymiles");
|
||||
JsonObject deviceObj = doc.as<JsonObject>(); // deviceObj is only pointer!?
|
||||
|
||||
for (uint8_t i = 0; i < ((!total) ? (rec->length) : (4) ) ; i++) {
|
||||
const char *devCls, *stateCls;
|
||||
if (!total) {
|
||||
if (rec->assign[i].ch == CH0)
|
||||
snprintf(name, 32, "%s %s", iv->config->name, iv->getFieldName(i, rec));
|
||||
else
|
||||
snprintf(name, 32, "%s CH%d %s", iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec));
|
||||
snprintf(topic, 64, "/ch%d/%s", rec->assign[i].ch, iv->getFieldName(i, rec));
|
||||
snprintf(uniq_id, 32, "ch%d_%s", rec->assign[i].ch, iv->getFieldName(i, rec));
|
||||
|
||||
devCls = getFieldDeviceClass(rec->assign[i].fieldId);
|
||||
stateCls = getFieldStateClass(rec->assign[i].fieldId);
|
||||
}
|
||||
|
||||
else { // total values
|
||||
snprintf(name, 32, "Total %s", fields[fldTotal[i]]);
|
||||
snprintf(topic, 64, "/%s", fields[fldTotal[i]]);
|
||||
snprintf(uniq_id, 32, "total_%s", fields[fldTotal[i]]);
|
||||
devCls = getFieldDeviceClass(fldTotal[i]);
|
||||
stateCls = getFieldStateClass(fldTotal[i]);
|
||||
}
|
||||
|
||||
DynamicJsonDocument doc2(512);
|
||||
doc2[F("name")] = name;
|
||||
doc2[F("stat_t")] = String(mCfgMqtt->topic) + "/" + ((!total) ? String(iv->config->name) : "total" ) + String(topic);
|
||||
doc2[F("unit_of_meas")] = ((!total) ? (iv->getUnit(i,rec)) : (unitTotal[i]));
|
||||
doc2[F("uniq_id")] = ((!total) ? (String(iv->config->serial.u64, HEX)) : (node_id)) + "_" + uniq_id;
|
||||
doc2[F("dev")] = deviceObj;
|
||||
if (!(String(stateCls) == String("total_increasing")))
|
||||
doc2[F("exp_aft")] = MQTT_INTERVAL + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!?
|
||||
if (devCls != NULL)
|
||||
doc2[F("dev_cla")] = String(devCls);
|
||||
if (stateCls != NULL)
|
||||
doc2[F("stat_cla")] = String(stateCls);
|
||||
|
||||
if (!total)
|
||||
snprintf(topic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec));
|
||||
else // total values
|
||||
snprintf(topic, 64, "%s/sensor/%s/total_%s/config", MQTT_DISCOVERY_PREFIX, node_id.c_str(),fields[fldTotal[i]]);
|
||||
size_t size = measureJson(doc2) + 1;
|
||||
char *buf = new char[size];
|
||||
memset(buf, 0, size);
|
||||
serializeJson(doc2, buf, size);
|
||||
publish(topic, buf, true, false);
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
yield();
|
||||
}
|
||||
mDiscovery.running = true;
|
||||
mDiscovery.lastIvId = 0;
|
||||
mDiscovery.sub = 0;
|
||||
}
|
||||
|
||||
void setPowerLimitAck(Inverter<> *iv) {
|
||||
|
@ -415,6 +343,95 @@ class PubMqtt {
|
|||
mRxCnt++;
|
||||
}
|
||||
|
||||
void discoveryConfigLoop(void) {
|
||||
char topic[64], name[32], uniq_id[32], buf[350];
|
||||
DynamicJsonDocument doc(256);
|
||||
|
||||
uint8_t fldTotal[4] = {FLD_PAC, FLD_YT, FLD_YD, FLD_PDC};
|
||||
const char* unitTotal[4] = {"W", "kWh", "Wh", "W"};
|
||||
|
||||
String node_mac = WiFi.macAddress().substring(12,14)+ WiFi.macAddress().substring(15,17);
|
||||
String node_id = "AHOY_DTU_" + node_mac;
|
||||
bool total = (mDiscovery.lastIvId == MAX_NUM_INVERTERS);
|
||||
|
||||
Inverter<> *iv = mSys->getInverterByPos(mDiscovery.lastIvId);
|
||||
record_t<> *rec;
|
||||
if (NULL != iv)
|
||||
rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||
|
||||
if ((NULL != iv) || total) {
|
||||
if (!total) {
|
||||
doc[F("name")] = iv->config->name;
|
||||
doc[F("ids")] = String(iv->config->serial.u64, HEX);
|
||||
doc[F("mdl")] = iv->config->name;
|
||||
}
|
||||
else {
|
||||
doc[F("name")] = node_id;
|
||||
doc[F("ids")] = node_id;
|
||||
doc[F("mdl")] = node_id;
|
||||
}
|
||||
|
||||
doc[F("cu")] = F("http://") + String(WiFi.localIP().toString());
|
||||
doc[F("mf")] = F("Hoymiles");
|
||||
JsonObject deviceObj = doc.as<JsonObject>(); // deviceObj is only pointer!?
|
||||
|
||||
const char *devCls, *stateCls;
|
||||
if (!total) {
|
||||
if (rec->assign[mDiscovery.sub].ch == CH0)
|
||||
snprintf(name, 32, "%s %s", iv->config->name, iv->getFieldName(mDiscovery.sub, rec));
|
||||
else
|
||||
snprintf(name, 32, "%s CH%d %s", iv->config->name, rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
|
||||
snprintf(topic, 64, "/ch%d/%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
|
||||
snprintf(uniq_id, 32, "ch%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
|
||||
|
||||
devCls = getFieldDeviceClass(rec->assign[mDiscovery.sub].fieldId);
|
||||
stateCls = getFieldStateClass(rec->assign[mDiscovery.sub].fieldId);
|
||||
}
|
||||
|
||||
else { // total values
|
||||
snprintf(name, 32, "Total %s", fields[fldTotal[mDiscovery.sub]]);
|
||||
snprintf(topic, 64, "/%s", fields[fldTotal[mDiscovery.sub]]);
|
||||
snprintf(uniq_id, 32, "total_%s", fields[fldTotal[mDiscovery.sub]]);
|
||||
devCls = getFieldDeviceClass(fldTotal[mDiscovery.sub]);
|
||||
stateCls = getFieldStateClass(fldTotal[mDiscovery.sub]);
|
||||
}
|
||||
|
||||
DynamicJsonDocument doc2(512);
|
||||
doc2[F("name")] = name;
|
||||
doc2[F("stat_t")] = String(mCfgMqtt->topic) + "/" + ((!total) ? String(iv->config->name) : "total" ) + String(topic);
|
||||
doc2[F("unit_of_meas")] = ((!total) ? (iv->getUnit(mDiscovery.sub, rec)) : (unitTotal[mDiscovery.sub]));
|
||||
doc2[F("uniq_id")] = ((!total) ? (String(iv->config->serial.u64, HEX)) : (node_id)) + "_" + uniq_id;
|
||||
doc2[F("dev")] = deviceObj;
|
||||
if (!(String(stateCls) == String("total_increasing")))
|
||||
doc2[F("exp_aft")] = MQTT_INTERVAL + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!?
|
||||
if (devCls != NULL)
|
||||
doc2[F("dev_cla")] = String(devCls);
|
||||
if (stateCls != NULL)
|
||||
doc2[F("stat_cla")] = String(stateCls);
|
||||
|
||||
if (!total)
|
||||
snprintf(topic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
|
||||
else // total values
|
||||
snprintf(topic, 64, "%s/sensor/%s/total_%s/config", MQTT_DISCOVERY_PREFIX, node_id.c_str(),fields[fldTotal[mDiscovery.sub]]);
|
||||
size_t size = measureJson(doc2) + 1;
|
||||
memset(buf, 0, size);
|
||||
serializeJson(doc2, buf, size);
|
||||
publish(topic, buf, true, false);
|
||||
|
||||
if(++mDiscovery.sub == ((!total) ? (rec->length) : 4)) {
|
||||
mDiscovery.sub = 0;
|
||||
if(++mDiscovery.lastIvId == (MAX_NUM_INVERTERS + 1))
|
||||
mDiscovery.running = false;
|
||||
}
|
||||
} else {
|
||||
mDiscovery.sub = 0;
|
||||
if(++mDiscovery.lastIvId == (MAX_NUM_INVERTERS + 1))
|
||||
mDiscovery.running = false;
|
||||
}
|
||||
|
||||
yield();
|
||||
}
|
||||
|
||||
const char *getFieldDeviceClass(uint8_t fieldId) {
|
||||
uint8_t pos = 0;
|
||||
for (; pos < DEVICE_CLS_ASSIGN_LIST_LEN; pos++) {
|
||||
|
@ -643,6 +660,8 @@ class PubMqtt {
|
|||
char mClientId[24]; // number of chars is limited to 23 up to v3.1 of MQTT
|
||||
// global buffer for mqtt topic. Used when publishing mqtt messages.
|
||||
char mTopic[MQTT_TOPIC_LEN + 32 + MAX_NAME_LENGTH + 1];
|
||||
|
||||
discovery_t mDiscovery;
|
||||
};
|
||||
|
||||
#endif /*__PUB_MQTT_H__*/
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
inline void DHEXLN(uint8_t b) {
|
||||
inline void DBGHEXLN(uint8_t b) {
|
||||
DHEX(b);
|
||||
DBGPRINT(F("\r\n"));
|
||||
}
|
||||
|
@ -151,7 +151,7 @@
|
|||
}\
|
||||
})
|
||||
|
||||
#define DPRINTHEAD(level, id) ({\
|
||||
#define DPRINT_IVID(level, id) ({\
|
||||
DPRINT(level, F("(#")); DBGPRINT(String(id)); DBGPRINT(F(") "));\
|
||||
})
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue