diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index bff4c8e8..bb431a50 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -192,12 +192,13 @@ void app::loop(void) { for(uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); if(NULL != iv) { - if(iv->isAvailable(mTimestamp)) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + if(iv->isAvailable(mTimestamp, rec)) { DPRINTLN(DBG_INFO, "Inverter: " + String(id)); - for(uint8_t i = 0; i < iv->listLen; i++) { - if(0.0f != iv->getValue(i)) { - snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, iv->getFieldName(i)); - snprintf(val, 10, "%.3f %s", iv->getValue(i), iv->getUnit(i)); + for(uint8_t i = 0; i < rec->length; i++) { + if(0.0f != iv->getValue(i, rec)) { + snprintf(topic, 30, "%s/ch%d/%s", iv->name, rec->assign[i].ch, iv->getFieldName(i, rec)); + snprintf(val, 10, "%.3f %s", iv->getValue(i, rec), iv->getUnit(i, rec)); DPRINTLN(DBG_INFO, String(topic) + ": " + String(val)); } yield(); @@ -249,17 +250,21 @@ void app::loop(void) { resetPayload(iv); yield(); - if(mConfig.serialDebug) + if(mConfig.serialDebug) { DPRINTLN(DBG_DEBUG, F("app:loop WiFi WiFi.status ") + String(WiFi.status())); DPRINTLN(DBG_INFO, F("Requesting Inverter SN ") + String(iv->serial.u64, HEX)); + } if(iv->devControlRequest && (iv->powerLimit[0] > 0) && (NoPowerLimit != iv->powerLimit[1])) { // prevent to "switch off" if(mConfig.serialDebug) DPRINTLN(DBG_INFO, F("Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0])); - mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd ,iv->powerLimit); + mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit); + mPayload[iv->id].txCmd = iv->devControlCmd; iv->clearCmdQueue(); iv->enqueCommand(SystemConfigPara); } else { - mSys->Radio.sendTimePacket(iv->radioId.u64,iv->getQueuedCmd(), mPayload[iv->id].ts,iv->alarmMesIndex); + uint8_t cmd = iv->getQueuedCmd(); + mSys->Radio.sendTimePacket(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex); + mPayload[iv->id].txCmd = cmd; mRxTicker = 0; } } @@ -320,7 +325,7 @@ void app::processPayload(bool retransmit) { mPayload[iv->id].complete = true; } if(!mPayload[iv->id].complete ) { - if(!buildPayload(iv->id)) { + if(!buildPayload(iv->id)) { // payload not complete if(mPayload[iv->id].requested) { if(retransmit) { if(mPayload[iv->id].retransmits < mConfig.maxRetransPerPyld) { @@ -339,19 +344,26 @@ void app::processPayload(bool retransmit) { else { if(mConfig.serialDebug) DPRINTLN(DBG_ERROR, F("while retrieving data: last frame missing: Request Retransmit")); - if(0x00 != mLastPacketId) - mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, mLastPacketId, true); - else - mSys->Radio.sendTimePacket(iv->radioId.u64, iv->getQueuedCmd(), mPayload[iv->id].ts,iv->alarmMesIndex); + //if(0x00 != mLastPacketId) + // mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, mLastPacketId, true); + //else + mSys->Radio.sendTimePacket(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex); } mSys->Radio.switchRxCh(100); } } } } - else { + else { // payload complete + DPRINTLN(DBG_INFO, F("procPyld: cmd: ") + String(mPayload[iv->id].txCmd)); + DPRINTLN(DBG_INFO, F("procPyld: txid: ") + String(mPayload[iv->id].txId)); + DPRINTLN(DBG_INFO, F("procPyld: max: ") + String(mPayload[iv->id].maxPackId)); + record_t<> *rec = iv->getRecordStruct(mPayload[iv->id].txCmd); // choose the parser + if(NULL == rec) + DPRINTLN(DBG_ERROR, F("record is NULL!")); mPayload[iv->id].complete = true; - iv->ts = mPayload[iv->id].ts; + rec->ts = mPayload[iv->id].ts; + mStat.rxSuccess++; uint8_t payload[128]; uint8_t offs = 0; @@ -367,14 +379,12 @@ void app::processPayload(bool retransmit) { DPRINT(DBG_INFO, F("Payload (") + String(offs) + "): "); mSys->Radio.dumpBuf(NULL, payload, offs); } - mStat.rxSuccess++; - - iv->getAssignment(); // choose the parser - for(uint8_t i = 0; i < iv->listLen; i++) { - iv->addValue(i, payload); // cmd value decides which parser is used to decode payload + + for(uint8_t i = 0; i < rec->length; i++) { + iv->addValue(i, payload, rec); yield(); } - iv->doCalculations(); // cmd value decides which parser is used to decode payload + iv->doCalculations(); iv->setQueuedCmdFinished(); @@ -386,22 +396,22 @@ void app::processPayload(bool retransmit) { for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); if (NULL != iv) { - if (iv->isAvailable(mTimestamp)) { - for (uint8_t i = 0; i < iv->listLen; i++) { - snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, fields[iv->assign[i].fieldId]); - snprintf(val, 10, "%.3f", iv->getValue(i)); - mMqtt.sendMsg(topic, val); - if(iv->isLiveDataAssignment()) { - if(CH0 == iv->assign[i].ch) { - switch(iv->assign[i].fieldId) { - case FLD_PAC: total[0] += iv->getValue(i); break; - case FLD_YT: total[1] += iv->getValue(i); break; - case FLD_YD: total[2] += iv->getValue(i); break; - case FLD_PDC: total[3] += iv->getValue(i); break; + if(iv->getRecordStruct(RealTimeRunData_Debug) == rec) { + if (iv->isAvailable(mTimestamp, rec)) { + for (uint8_t i = 0; i < rec->length; i++) { + snprintf(topic, 30, "%s/ch%d/%s", iv->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]); + snprintf(val, 10, "%.3f", iv->getValue(i, rec)); + mMqtt.sendMsg(topic, val); + if(CH0 == rec->assign[i].ch) { + switch(rec->assign[i].fieldId) { + case FLD_PAC: total[0] += iv->getValue(i, rec); break; + case FLD_YT: total[1] += iv->getValue(i, rec); break; + case FLD_YD: total[2] += iv->getValue(i, rec); break; + case FLD_PDC: total[3] += iv->getValue(i, rec); break; } } + yield(); } - yield(); } } } @@ -424,6 +434,8 @@ void app::processPayload(bool retransmit) { } } + resetPayload(iv); + #ifdef __MQTT_AFTER_RX__ doMQTT = true; #endif @@ -543,7 +555,8 @@ void app::sendMqttDiscoveryConfig(void) { for(uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); if(NULL != iv) { - if(iv->isAvailable(mTimestamp) && mMqttConfigSendState[id] != true) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + if(iv->isAvailable(mTimestamp, rec) && mMqttConfigSendState[id] != true) { DynamicJsonDocument deviceDoc(128); deviceDoc["name"] = iv->name; deviceDoc["ids"] = String(iv->serial.u64, HEX); @@ -553,21 +566,21 @@ void app::sendMqttDiscoveryConfig(void) { JsonObject deviceObj = deviceDoc.as(); DynamicJsonDocument doc(384); - for(uint8_t i = 0; i < iv->listLen; i++) { - if (iv->assign[i].ch == CH0) { - snprintf(name, 32, "%s %s", iv->name, iv->getFieldName(i)); + for(uint8_t i = 0; i < rec->length; i++) { + if (rec->assign[i].ch == CH0) { + snprintf(name, 32, "%s %s", iv->name, iv->getFieldName(i, rec)); } else { - snprintf(name, 32, "%s CH%d %s", iv->name, iv->assign[i].ch, iv->getFieldName(i)); + snprintf(name, 32, "%s CH%d %s", iv->name, rec->assign[i].ch, iv->getFieldName(i, rec)); } - snprintf(stateTopic, 64, "%s/%s/ch%d/%s", mConfig.mqtt.topic, iv->name, iv->assign[i].ch, iv->getFieldName(i)); - snprintf(discoveryTopic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->name, iv->assign[i].ch, iv->getFieldName(i)); - snprintf(uniq_id, 32, "ch%d_%s", iv->assign[i].ch, iv->getFieldName(i)); - const char* devCls = getFieldDeviceClass(iv->assign[i].fieldId); - const char* stateCls = getFieldStateClass(iv->assign[i].fieldId); + snprintf(stateTopic, 64, "%s/%s/ch%d/%s", mConfig.mqtt.topic, iv->name, rec->assign[i].ch, iv->getFieldName(i, rec)); + snprintf(discoveryTopic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->name, rec->assign[i].ch, iv->getFieldName(i, rec)); + snprintf(uniq_id, 32, "ch%d_%s", rec->assign[i].ch, iv->getFieldName(i, rec)); + const char* devCls = getFieldDeviceClass(rec->assign[i].fieldId); + const char* stateCls = getFieldStateClass(rec->assign[i].fieldId); doc["name"] = name; doc["stat_t"] = stateTopic; - doc["unit_of_meas"] = iv->getUnit(i); + doc["unit_of_meas"] = iv->getUnit(i, rec); doc["uniq_id"] = String(iv->serial.u64, HEX) + "_" + uniq_id; doc["dev"] = deviceObj; doc["exp_aft"] = mMqttInterval + 5; // add 5 sec if connection is bad or ESP too slow @@ -644,7 +657,12 @@ void app::resetSystem(void) { mShowRebootRequest = false; - memset(mPayload, 0, (MAX_NUM_INVERTERS * sizeof(invPayload_t))); + Inverter<> *iv; + for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { + iv = mSys->getInverterByPos(i, false); + if(NULL != iv) + resetPayload(iv); + } memset(&mStat, 0, sizeof(statistics_t)); mLastPacketId = 0x00; } @@ -806,13 +824,12 @@ void app::setupMqtt(void) { } //----------------------------------------------------------------------------- -void app::resetPayload(Inverter<>* iv) -{ - // reset payload data +void app::resetPayload(Inverter<>* iv) { memset(mPayload[iv->id].len, 0, MAX_PAYLOAD_ENTRIES); + mPayload[iv->id].txCmd = 0; mPayload[iv->id].retransmits = 0; - mPayload[iv->id].maxPackId = 0; - mPayload[iv->id].complete = false; - mPayload[iv->id].requested = true; - mPayload[iv->id].ts = mTimestamp; + mPayload[iv->id].maxPackId = 0; + mPayload[iv->id].complete = false; + mPayload[iv->id].requested = true; + mPayload[iv->id].ts = mTimestamp; } diff --git a/tools/esp8266/app.h b/tools/esp8266/app.h index 0f42cb2b..012c710b 100644 --- a/tools/esp8266/app.h +++ b/tools/esp8266/app.h @@ -38,6 +38,7 @@ typedef HmSystem HmSyste typedef struct { + uint8_t txCmd; uint8_t txId; uint8_t invId; uint32_t ts; diff --git a/tools/esp8266/hmDefines.h b/tools/esp8266/hmDefines.h index baec0f75..18498fd6 100644 --- a/tools/esp8266/hmDefines.h +++ b/tools/esp8266/hmDefines.h @@ -30,6 +30,7 @@ enum {FLD_UDC = 0, FLD_IDC, FLD_PDC, FLD_YD, FLD_YW, FLD_YT, const char* const fields[] = {"U_DC", "I_DC", "P_DC", "YieldDay", "YieldWeek", "YieldTotal", "U_AC", "I_AC", "P_AC", "Freq", "Temp", "Pct", "Efficiency", "Irradiation","P_ACr", "ALARM_MES_ID","FWVersion","FWBuildYear","FWBuildMonthDay","HWPartId","PowerLimit","LastAlarmCode"}; +const char* const notAvail = "n/a"; // mqtt discovery device classes enum {DEVICE_CLS_NONE = 0, DEVICE_CLS_CURRENT, DEVICE_CLS_ENERGY, DEVICE_CLS_PWR, DEVICE_CLS_VOLTAGE, DEVICE_CLS_FREQ, DEVICE_CLS_TEMP}; @@ -207,7 +208,7 @@ const byteAssign_t hm4chAssignment[] = { { FLD_F, UNIT_HZ, CH0, 48, 2, 100 }, { FLD_PCT, UNIT_PCT, CH0, 56, 2, 10 }, { FLD_T, UNIT_C, CH0, 58, 2, 10 }, - { FLD_ALARM_MES_ID, UNIT_NONE, CH0, 60, 2, 1 }, + { FLD_ALARM_MES_ID, UNIT_NONE, CH0, 60, 2, 1 }, { FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC }, { FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC }, { FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC }, diff --git a/tools/esp8266/hmInverter.h b/tools/esp8266/hmInverter.h index 6a309590..ea83587d 100644 --- a/tools/esp8266/hmInverter.h +++ b/tools/esp8266/hmInverter.h @@ -23,7 +23,7 @@ */ // forward declaration of class -template +template class Inverter; @@ -55,17 +55,23 @@ struct calcFunc_t { func_t* func; // function pointer }; +template +struct record_t { + byteAssign_t* assign; // assigment of bytes in payload + uint8_t length; // length of the assignment list + T *record; // data pointer + uint32_t ts; // timestamp of last received payload +}; class CommandAbstract { public: - CommandAbstract(uint8_t txType = 0, uint8_t cmd = 0){ + CommandAbstract(uint8_t txType = 0, uint8_t cmd = 0) { _TxType = txType; _Cmd = cmd; }; virtual ~CommandAbstract() {}; - const uint8_t getCmd() - { + const uint8_t getCmd() { return _Cmd; } @@ -75,11 +81,11 @@ class CommandAbstract { }; class InfoCommand : public CommandAbstract { -public: - InfoCommand(uint8_t cmd){ - _TxType = 0x15; - _Cmd = cmd; - } + public: + InfoCommand(uint8_t cmd){ + _TxType = 0x15; + _Cmd = cmd; + } }; // list of all available functions, mapped in hmDefines.h @@ -94,35 +100,34 @@ const calcFunc_t calcFunctions[] = { }; -template +template class Inverter { public: - uint8_t id; // unique id + uint8_t id; // unique id char name[MAX_NAME_LENGTH]; // human readable name, eg. "HM-600.1" - uint8_t type; // integer which refers to inverter type - byteAssign_t* assign; // type of inverter - uint8_t listLen; // length of assignments - uint16_t alarmMesIndex; // Last recorded Alarm Message Index - uint16_t fwVersion; // Firmware Version from Info Command Request - uint16_t powerLimit[2]; // limit power output - uint16_t actPowerLimit; // - uint8_t devControlCmd; // carries the requested cmd - bool devControlRequest; // true if change needed - serial_u serial; // serial number as on barcode - serial_u radioId; // id converted to modbus - uint8_t channels; // number of PV channels (1-4) - uint32_t ts; // timestamp of last received payload - RECORDTYPE *record; // pointer for values - uint16_t chMaxPwr[4]; // maximum power of the modules (Wp) - char chName[4][MAX_NAME_LENGTH]; // human readable name for channel + uint8_t type; // integer which refers to inverter type + uint16_t alarmMesIndex; // Last recorded Alarm Message Index + uint16_t fwVersion; // Firmware Version from Info Command Request + uint16_t powerLimit[2]; // limit power output + uint16_t actPowerLimit; // + uint8_t devControlCmd; // carries the requested cmd + bool devControlRequest; // true if change needed + serial_u serial; // serial number as on barcode + serial_u radioId; // id converted to modbus + uint8_t channels; // number of PV channels (1-4) + record_t recordMeas; // structure for measured values + record_t recordInfo; // structure for info values + record_t recordConfig; // structure for system config values + record_t recordAlarm; // structure for alarm values + uint16_t chMaxPwr[4]; // maximum power of the modules (Wp) + char chName[4][MAX_NAME_LENGTH]; // human readable name for channels String lastAlarmMsg; - bool initialized; // needed to check if the inverter was correctly added (ESP32 specific - union types are never null) + bool initialized; // needed to check if the inverter was correctly added (ESP32 specific - union types are never null) Inverter() { - ts = 0; - powerLimit[0] = 0xffff; // 65535 W Limit -> unlimited - powerLimit[1] = NoPowerLimit; // - actPowerLimit = 0xffff; // init feedback from inverter to -1 + powerLimit[0] = 0xffff; // 65535 W Limit -> unlimited + powerLimit[1] = NoPowerLimit; // default power limit setting + actPowerLimit = 0xffff; // init feedback from inverter to -1 devControlRequest = false; devControlCmd = InitDataState; initialized = false; @@ -174,187 +179,201 @@ class Inverter { void init(void) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:init")); - getAssignment(); + initAssignment(&recordMeas, RealTimeRunData_Debug); + initAssignment(&recordInfo, InverterDevInform_All); + initAssignment(&recordConfig, SystemConfigPara); + initAssignment(&recordAlarm, AlarmData); toRadioId(); - record = new RECORDTYPE[listLen]; memset(name, 0, MAX_NAME_LENGTH); memset(chName, 0, MAX_NAME_LENGTH * 4); - memset(record, 0, sizeof(RECORDTYPE) * listLen); initialized = true; } - uint8_t getPosByChFld(uint8_t channel, uint8_t fieldId) { + uint8_t getPosByChFld(uint8_t channel, uint8_t fieldId, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getPosByChFld")); uint8_t pos = 0; - for(; pos < listLen; pos++) { - if((assign[pos].ch == channel) && (assign[pos].fieldId == fieldId)) - break; + if(NULL != rec) { + for(; pos < rec->length; pos++) { + if((rec->assign[pos].ch == channel) && (rec->assign[pos].fieldId == fieldId)) + break; + } + return (pos >= rec->length) ? 0xff : pos; } - return (pos >= listLen) ? 0xff : pos; + else + return 0xff; } - const char *getFieldName(uint8_t pos) { + const char *getFieldName(uint8_t pos, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getFieldName")); - return fields[assign[pos].fieldId]; + if(NULL != rec) + return fields[rec->assign[pos].fieldId]; + return notAvail; } - const char *getUnit(uint8_t pos) { + const char *getUnit(uint8_t pos, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getUnit")); - return units[assign[pos].unitId]; + if(NULL != rec) + return units[rec->assign[pos].unitId]; + return notAvail; } - uint8_t getChannel(uint8_t pos) { + uint8_t getChannel(uint8_t pos, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getChannel")); - return assign[pos].ch; + if(NULL != rec) + return rec->assign[pos].ch; + return 0; } - void addValue(uint8_t pos, uint8_t buf[]) { + void addValue(uint8_t pos, uint8_t buf[], record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:addValue")); - uint8_t cmd = getQueuedCmd(); - uint8_t ptr = assign[pos].start; - uint8_t end = ptr + assign[pos].num; - uint16_t div = assign[pos].div; - if(CMD_CALC != div) { - uint32_t val = 0; - do { - val <<= 8; - val |= buf[ptr]; - } while(++ptr != end); - if ((RECORDTYPE)(div) > 1){ - record[pos] = (RECORDTYPE)(val) / (RECORDTYPE)(div); - } - else { - record[pos] = (RECORDTYPE)(val); - } - - } - if (cmd == RealTimeRunData_Debug) { - // get last alarm message index and save it in the inverter object - if (getPosByChFld(0, FLD_ALARM_MES_ID) == pos){ - if (alarmMesIndex < record[pos]){ - alarmMesIndex = record[pos]; - //enqueCommand(AlarmUpdate); // What is the function of AlarmUpdate? - enqueCommand(AlarmData); + if(NULL != rec) { + uint8_t ptr = rec->assign[pos].start; + uint8_t end = ptr + rec->assign[pos].num; + uint16_t div = rec->assign[pos].div; + if(rec == &recordMeas) { + if(CMD_CALC != div) { + uint32_t val = 0; + do { + val <<= 8; + val |= buf[ptr]; + } while(++ptr != end); + if ((REC_TYP)(div) > 1) + rec->record[pos] = (REC_TYP)(val) / (REC_TYP)(div); + else + rec->record[pos] = (REC_TYP)(val); } - else { - alarmMesIndex = record[pos]; // no change + // get last alarm message index and save it in the inverter object + if (getPosByChFld(0, FLD_ALARM_MES_ID, rec) == pos){ + if (alarmMesIndex < rec->record[pos]){ + alarmMesIndex = rec->record[pos]; + //enqueCommand(AlarmUpdate); // What is the function of AlarmUpdate? + enqueCommand(AlarmData); + } + else { + alarmMesIndex = rec->record[pos]; // no change + } } } - } - if (cmd == InverterDevInform_All) { - // get at least the firmware version and save it to the inverter object - if (getPosByChFld(0, FLD_FW_VERSION) == pos){ - fwVersion = record[pos]; - DPRINT(DBG_DEBUG, F("Inverter FW-Version: ") + String(fwVersion)); + if (rec == &recordInfo) { + // get at least the firmware version and save it to the inverter object + if (getPosByChFld(0, FLD_FW_VERSION, rec) == pos){ + fwVersion = rec->record[pos]; + DPRINT(DBG_DEBUG, F("Inverter FW-Version: ") + String(fwVersion)); + } } - } - if (cmd == SystemConfigPara) { - // get at least the firmware version and save it to the inverter object - if (getPosByChFld(0, FLD_ACT_PWR_LIMIT) == pos){ - actPowerLimit = record[pos]; - DPRINT(DBG_DEBUG, F("Inverter actual power limit: ") + String(actPowerLimit)); + if (rec == &recordConfig) { + // get at least the firmware version and save it to the inverter object + if (getPosByChFld(0, FLD_ACT_PWR_LIMIT, rec) == pos){ + actPowerLimit = rec->record[pos]; + DPRINT(DBG_DEBUG, F("Inverter actual power limit: ") + String(actPowerLimit)); + } } - } - if (cmd == AlarmData){ - if (getPosByChFld(0, FLD_LAST_ALARM_CODE) == pos){ - lastAlarmMsg = getAlarmStr(record[pos]); + if (rec == &recordAlarm){ + if (getPosByChFld(0, FLD_LAST_ALARM_CODE, rec) == pos){ + lastAlarmMsg = getAlarmStr(rec->record[pos]); + } } } + else + DPRINTLN(DBG_ERROR, F("addValue: assignment not found with cmd 0x")); } - RECORDTYPE getValue(uint8_t pos) { + REC_TYP getValue(uint8_t pos, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getValue")); - return record[pos]; + if(NULL == rec) + return 0; + return rec->record[pos]; } void doCalculations() { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:doCalculations")); - uint8_t cmd = getQueuedCmd(); - getAssignment(); - if (cmd == RealTimeRunData_Debug){ - for(uint8_t i = 0; i < listLen; i++) { - if(CMD_CALC == assign[i].div) { - record[i] = calcFunctions[assign[i].start].func(this, assign[i].num); - } - yield(); + record_t<> *rec = getRecordStruct(RealTimeRunData_Debug); + for(uint8_t i = 0; i < rec->length; i++) { + if(CMD_CALC == rec->assign[i].div) { + rec->record[i] = calcFunctions[rec->assign[i].start].func(this, rec->assign[i].num); } + yield(); } } - bool isAvailable(uint32_t timestamp) { + bool isAvailable(uint32_t timestamp, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:isAvailable")); - return ((timestamp - ts) < INACT_THRES_SEC); + return ((timestamp - rec->ts) < INACT_THRES_SEC); } - bool isProducing(uint32_t timestamp) { + bool isProducing(uint32_t timestamp, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:isProducing")); - if(isAvailable(timestamp)) { - uint8_t pos = getPosByChFld(CH0, FLD_PAC); - return (getValue(pos) > INACT_PWR_THRESH); + if(isAvailable(timestamp, rec)) { + uint8_t pos = getPosByChFld(CH0, FLD_PAC, rec); + return (getValue(pos, rec) > INACT_PWR_THRESH); } return false; } - uint32_t getLastTs(void) { + uint32_t getLastTs(record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getLastTs")); - return ts; + return rec->ts; } - void getAssignment() { - DPRINTLN(DBG_DEBUG, F("hmInverter.h:getAssignment")); - // Default assignment; - if (INV_TYPE_1CH == type) { - listLen = (uint8_t)(HM1CH_LIST_LEN); - assign = (byteAssign_t *)hm1chAssignment; - channels = 1; - } - else if (INV_TYPE_2CH == type) { - listLen = (uint8_t)(HM2CH_LIST_LEN); - assign = (byteAssign_t *)hm2chAssignment; - channels = 2; - } - else if (INV_TYPE_4CH == type) { - listLen = (uint8_t)(HM4CH_LIST_LEN); - assign = (byteAssign_t *)hm4chAssignment; - channels = 4; - } - else { - listLen = 0; - channels = 0; - assign = NULL; + record_t<> *getRecordStruct(uint8_t cmd) { + switch (cmd) { + case RealTimeRunData_Debug: return &recordMeas; + case InverterDevInform_All: return &recordInfo; + case SystemConfigPara: return &recordConfig; + case AlarmData: return &recordAlarm; + default: break; } + return NULL; + } - switch (getQueuedCmd()) { + void initAssignment(record_t<> *rec, uint8_t cmd) { + DPRINTLN(DBG_VERBOSE, F("hmInverter.h:initAssignment")); + rec->ts = 0; + rec->length = 0; + switch (cmd) { case RealTimeRunData_Debug: - // Do nothing will use default + if (INV_TYPE_1CH == type) { + rec->length = (uint8_t)(HM1CH_LIST_LEN); + rec->assign = (byteAssign_t *)hm1chAssignment; + channels = 1; + } + else if (INV_TYPE_2CH == type) { + rec->length = (uint8_t)(HM2CH_LIST_LEN); + rec->assign = (byteAssign_t *)hm2chAssignment; + channels = 2; + } + else if (INV_TYPE_4CH == type) { + rec->length = (uint8_t)(HM4CH_LIST_LEN); + rec->assign = (byteAssign_t *)hm4chAssignment; + channels = 4; + } + else { + rec->length = 0; + rec->assign = NULL; + channels = 0; + } break; case InverterDevInform_All: - listLen = (uint8_t)(HMINFO_LIST_LEN); - assign = (byteAssign_t *)InfoAssignment; + rec->length = (uint8_t)(HMINFO_LIST_LEN); + rec->assign = (byteAssign_t *)InfoAssignment; break; case SystemConfigPara: - listLen = (uint8_t)(HMSYSTEM_LIST_LEN); - assign = (byteAssign_t *)SystemConfigParaAssignment; + rec->length = (uint8_t)(HMSYSTEM_LIST_LEN); + rec->assign = (byteAssign_t *)SystemConfigParaAssignment; break; case AlarmData: - listLen = (uint8_t)(HMALARMDATA_LIST_LEN); - assign = (byteAssign_t *)AlarmDataAssignment; + rec->length = (uint8_t)(HMALARMDATA_LIST_LEN); + rec->assign = (byteAssign_t *)AlarmDataAssignment; break; default: - DPRINTLN(DBG_INFO, "Parser not implemented"); + DPRINTLN(DBG_INFO, F("initAssignment: Parser not implemented")); break; } - } - bool isLiveDataAssignment(void) { - if(assign == (byteAssign_t *)hm1chAssignment) - return true; - else if(assign == (byteAssign_t *)hm2chAssignment) - return true; - else if(assign == (byteAssign_t *)hm4chAssignment) - return true; - else - return false; + if(0 != rec->length) { + rec->record = new REC_TYP[rec->length]; + memset(rec->record, 0, sizeof(REC_TYP) * rec->length); + } } String getAlarmStr(u_int16_t alarmCode) { @@ -455,10 +474,11 @@ template static T calcYieldTotalCh0(Inverter<> *iv, uint8_t arg0) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcYieldTotalCh0")); if(NULL != iv) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); T yield = 0; for(uint8_t i = 1; i <= iv->channels; i++) { - uint8_t pos = iv->getPosByChFld(i, FLD_YT); - yield += iv->getValue(pos); + uint8_t pos = iv->getPosByChFld(i, FLD_YT, rec); + yield += iv->getValue(pos, rec); } return yield; } @@ -469,10 +489,11 @@ template static T calcYieldDayCh0(Inverter<> *iv, uint8_t arg0) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcYieldDayCh0")); if(NULL != iv) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); T yield = 0; for(uint8_t i = 1; i <= iv->channels; i++) { - uint8_t pos = iv->getPosByChFld(i, FLD_YD); - yield += iv->getValue(pos); + uint8_t pos = iv->getPosByChFld(i, FLD_YD, rec); + yield += iv->getValue(pos, rec); } return yield; } @@ -483,9 +504,10 @@ template static T calcUdcCh(Inverter<> *iv, uint8_t arg0) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcUdcCh")); // arg0 = channel of source - for(uint8_t i = 0; i < iv->listLen; i++) { - if((FLD_UDC == iv->assign[i].fieldId) && (arg0 == iv->assign[i].ch)) { - return iv->getValue(i); + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + for(uint8_t i = 0; i < rec->length; i++) { + if((FLD_UDC == rec->assign[i].fieldId) && (arg0 == rec->assign[i].ch)) { + return iv->getValue(i, rec); } } @@ -496,10 +518,11 @@ template static T calcPowerDcCh0(Inverter<> *iv, uint8_t arg0) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcPowerDcCh0")); if(NULL != iv) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); T dcPower = 0; for(uint8_t i = 1; i <= iv->channels; i++) { - uint8_t pos = iv->getPosByChFld(i, FLD_PDC); - dcPower += iv->getValue(pos); + uint8_t pos = iv->getPosByChFld(i, FLD_PDC, rec); + dcPower += iv->getValue(pos, rec); } return dcPower; } @@ -510,12 +533,13 @@ template static T calcEffiencyCh0(Inverter<> *iv, uint8_t arg0) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcEfficiencyCh0")); if(NULL != iv) { - uint8_t pos = iv->getPosByChFld(CH0, FLD_PAC); - T acPower = iv->getValue(pos); + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + uint8_t pos = iv->getPosByChFld(CH0, FLD_PAC, rec); + T acPower = iv->getValue(pos, rec); T dcPower = 0; for(uint8_t i = 1; i <= iv->channels; i++) { - pos = iv->getPosByChFld(i, FLD_PDC); - dcPower += iv->getValue(pos); + pos = iv->getPosByChFld(i, FLD_PDC, rec); + dcPower += iv->getValue(pos, rec); } if(dcPower > 0) return acPower / dcPower * 100.0f; @@ -528,9 +552,10 @@ static T calcIrradiation(Inverter<> *iv, uint8_t arg0) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcIrradiation")); // arg0 = channel if(NULL != iv) { - uint8_t pos = iv->getPosByChFld(arg0, FLD_PDC); + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + uint8_t pos = iv->getPosByChFld(arg0, FLD_PDC, rec); if(iv->chMaxPwr[arg0-1] > 0) - return iv->getValue(pos) / iv->chMaxPwr[arg0-1] * 100.0f; + return iv->getValue(pos, rec) / iv->chMaxPwr[arg0-1] * 100.0f; } return 0.0; } diff --git a/tools/esp8266/hmRadio.h b/tools/esp8266/hmRadio.h index 35b1d08c..8c04ffef 100644 --- a/tools/esp8266/hmRadio.h +++ b/tools/esp8266/hmRadio.h @@ -164,7 +164,7 @@ class HmRadio { } void sendControlPacket(uint64_t invId, uint8_t cmd, uint16_t *data) { - DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendControlPacket")); + DPRINTLN(DBG_INFO, F("sendControlPacket")); sendCmdPacket(invId, TX_REQ_DEVCONTROL, ALL_FRAMES, false); // 0x80 implementation as original DTU code int cnt = 0; mTxBuf[10] = cmd; // cmd --> 0x0b => Type_ActivePowerContr, 0 on, 1 off, 2 restart, 12 reactive power, 13 power factor @@ -187,17 +187,14 @@ class HmRadio { } void sendTimePacket(uint64_t invId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId) { - //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendTimePacket")); + DPRINTLN(DBG_INFO, F("sendTimePacket")); sendCmdPacket(invId, TX_REQ_INFO, ALL_FRAMES, false); mTxBuf[10] = cmd; // cid mTxBuf[11] = 0x00; CP_U32_LittleEndian(&mTxBuf[12], ts); - if (cmd == RealTimeRunData_Debug || cmd == AlarmData ){ + if (cmd == RealTimeRunData_Debug || cmd == AlarmData ) { mTxBuf[18] = (alarmMesId >> 8) & 0xff; mTxBuf[19] = (alarmMesId ) & 0xff; - } else { - mTxBuf[18] = 0x00; - mTxBuf[19] = 0x00; } uint16_t crc = Ahoy::crc16(&mTxBuf[10], 14); mTxBuf[24] = (crc >> 8) & 0xff; @@ -208,7 +205,7 @@ class HmRadio { } void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool calcCrc = true) { - //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendCmdPacket")); + DPRINTLN(DBG_INFO, F("sendCmdPacket, mid: ") + String(mid, HEX) + F(" pid: ") + String(pid, HEX)); memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE); mTxBuf[0] = mid; // message id CP_U32_BigEndian(&mTxBuf[1], (invId >> 8)); @@ -221,7 +218,7 @@ class HmRadio { } bool checkPaketCrc(uint8_t buf[], uint8_t *len, uint8_t rxCh) { - //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:checkPaketCrc")); + //DPRINTLN(DBG_INFO, F("hmRadio.h:checkPaketCrc")); *len = (buf[0] >> 2); if(*len > (MAX_RF_PAYLOAD_SIZE - 2)) *len = MAX_RF_PAYLOAD_SIZE - 2; @@ -237,8 +234,6 @@ class HmRadio { bool switchRxCh(uint16_t addLoop = 0) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:switchRxCh")); - //DPRINTLN(DBG_VERBOSE, F("R")); - mRxLoopCnt += addLoop; if(mRxLoopCnt != 0) { mRxLoopCnt--; diff --git a/tools/esp8266/hmSystem.h b/tools/esp8266/hmSystem.h index 150853ad..eb246ccb 100644 --- a/tools/esp8266/hmSystem.h +++ b/tools/esp8266/hmSystem.h @@ -63,14 +63,8 @@ class HmSystem { uint8_t len = (uint8_t)strlen(name); strncpy(p->name, name, (len > MAX_NAME_LENGTH) ? MAX_NAME_LENGTH : len); - if(NULL == p->assign) { - DPRINT(DBG_ERROR, F("no assignment for type found!")); - return NULL; - } - else { - mNumInv ++; - return p; - } + mNumInv ++; + return p; } INVERTERTYPE *findInverter(uint8_t buf[]) { diff --git a/tools/esp8266/html/index.html b/tools/esp8266/html/index.html index 26a9728d..201f13d7 100644 --- a/tools/esp8266/html/index.html +++ b/tools/esp8266/html/index.html @@ -27,14 +27,14 @@
This project was started from this discussion. (Mikrocontroller.net)
- New updates can be found on Github: https://github.com/grindylow/ahoy
+ New updates can be found on Github: https://github.com/lumapu/ahoy

- Please report issues using the feature provided by Github
+ Please report issues using the feature provided by Github

Discuss with us on Discord

Creative Commons - https://creativecommons.org/licenses/by-nc-sa/3.0/de/
- Check the licenses which are published on https://github.com/grindylow/ahoy as well

+ Check the licenses which are published on https://github.com/lumapu/ahoy as well