|  |  | @ -144,10 +144,13 @@ class PubMqtt { | 
			
		
	
		
			
				
					|  |  |  |                 iv->setValue(pos, rec, 0.0f); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch0/%s", iv->config->name, fields[FLD_YD]); | 
			
		
	
		
			
				
					|  |  |  |                 snprintf(val, 4, "0.0"); | 
			
		
	
		
			
				
					|  |  |  |                 snprintf(val, 2, "0"); | 
			
		
	
		
			
				
					|  |  |  |                 publish(topic, val, true); | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |             // set Total YieldDay to zero
 | 
			
		
	
		
			
				
					|  |  |  |             snprintf(topic, 32 + MAX_NAME_LENGTH, "total/%s", fields[FLD_YD]); | 
			
		
	
		
			
				
					|  |  |  |             snprintf(val, 2, "0"); | 
			
		
	
		
			
				
					|  |  |  |             publish(topic, val, true);        } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         void payloadEventListener(uint8_t cmd) { | 
			
		
	
		
			
				
					|  |  |  |             if(mClient.connected()) { // prevent overflow if MQTT broker is not reachable but set
 | 
			
		
	
	
		
			
				
					|  |  | @ -211,28 +214,44 @@ class PubMqtt { | 
			
		
	
		
			
				
					|  |  |  |             DPRINTLN(DBG_VERBOSE, F("sendMqttDiscoveryConfig")); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             char topic[64], name[32], uniq_id[32]; | 
			
		
	
		
			
				
					|  |  |  |             DynamicJsonDocument doc(128); | 
			
		
	
		
			
				
					|  |  |  |             DynamicJsonDocument doc(256); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             uint8_t fldTotal[4] = {FLD_PAC, FLD_YT, FLD_YD, FLD_PDC}; | 
			
		
	
		
			
				
					|  |  |  |             const char* unitTotal[4] = {"W", "kWh", "Wh", "W"}; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { | 
			
		
	
		
			
				
					|  |  |  |                 Inverter<> *iv = mSys->getInverterByPos(id); | 
			
		
	
		
			
				
					|  |  |  |                 if (NULL == iv) | 
			
		
	
		
			
				
					|  |  |  |             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); | 
			
		
	
		
			
				
					|  |  |  |                 doc.clear(); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 doc[F("name")] = iv->config->name; | 
			
		
	
		
			
				
					|  |  |  |                 doc[F("ids")] = String(iv->config->serial.u64, HEX); | 
			
		
	
		
			
				
					|  |  |  |                 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"); | 
			
		
	
		
			
				
					|  |  |  |                 doc[F("mdl")] = iv->config->name; | 
			
		
	
		
			
				
					|  |  |  |                 JsonObject deviceObj = doc.as<JsonObject>(); // deviceObj is only pointer!?
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 for (uint8_t i = 0; i < (rec->length + 4); i++) { | 
			
		
	
		
			
				
					|  |  |  |                 for (uint8_t i = 0; i < ((!total) ? (rec->length) : (4) ) ; i++) { | 
			
		
	
		
			
				
					|  |  |  |                     const char *devCls, *stateCls; | 
			
		
	
		
			
				
					|  |  |  |                     if(i < rec->length) { | 
			
		
	
		
			
				
					|  |  |  |                     if (!total) { | 
			
		
	
		
			
				
					|  |  |  |                         if (rec->assign[i].ch == CH0) | 
			
		
	
		
			
				
					|  |  |  |                             snprintf(name, 32, "%s %s", iv->config->name, iv->getFieldName(i, rec)); | 
			
		
	
		
			
				
					|  |  |  |                         else | 
			
		
	
	
		
			
				
					|  |  | @ -243,30 +262,32 @@ class PubMqtt { | 
			
		
	
		
			
				
					|  |  |  |                         devCls = getFieldDeviceClass(rec->assign[i].fieldId); | 
			
		
	
		
			
				
					|  |  |  |                         stateCls = getFieldStateClass(rec->assign[i].fieldId); | 
			
		
	
		
			
				
					|  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                     else { // total values
 | 
			
		
	
		
			
				
					|  |  |  |                         snprintf(name, 32, "Total %s", fields[fldTotal[i-rec->length]]); | 
			
		
	
		
			
				
					|  |  |  |                         snprintf(topic, 64, "/%s", fields[fldTotal[i-rec->length]]); | 
			
		
	
		
			
				
					|  |  |  |                         snprintf(uniq_id, 32, "total_%s", fields[fldTotal[i-rec->length]]); | 
			
		
	
		
			
				
					|  |  |  |                         devCls = getFieldDeviceClass(fldTotal[i-rec->length]); | 
			
		
	
		
			
				
					|  |  |  |                         stateCls = getFieldStateClass(fldTotal[i-rec->length]); | 
			
		
	
		
			
				
					|  |  |  |                         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) + "/" + String(iv->config->name) + String(topic); | 
			
		
	
		
			
				
					|  |  |  |                     doc2[F("unit_of_meas")] = iv->getUnit(((i < rec->length) ? i : (i - rec->length)), rec); | 
			
		
	
		
			
				
					|  |  |  |                     doc2[F("uniq_id")] = String(iv->config->serial.u64, HEX) + "_" + uniq_id; | 
			
		
	
		
			
				
					|  |  |  |                     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; | 
			
		
	
		
			
				
					|  |  |  |                     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 (!(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(i < rec->length) | 
			
		
	
		
			
				
					|  |  |  |                     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, iv->config->name, fields[fldTotal[i-rec->length]]); | 
			
		
	
		
			
				
					|  |  |  |                         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); | 
			
		
	
	
		
			
				
					|  |  | @ -450,7 +471,7 @@ class PubMqtt { | 
			
		
	
		
			
				
					|  |  |  |             if(changed) { | 
			
		
	
		
			
				
					|  |  |  |                 snprintf(val, 32, "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((anyAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE))); | 
			
		
	
		
			
				
					|  |  |  |                 publish("status", val, true); | 
			
		
	
		
			
				
					|  |  |  |                 sendIvData(false); // false prevents loop of same function
 | 
			
		
	
		
			
				
					|  |  |  |                 //sendIvData(false); // false prevents loop of same function
 | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             return allAvail; | 
			
		
	
	
		
			
				
					|  |  | @ -494,6 +515,8 @@ class PubMqtt { | 
			
		
	
		
			
				
					|  |  |  |                             switch (rec->assign[i].fieldId) { | 
			
		
	
		
			
				
					|  |  |  |                                 case FLD_YT: | 
			
		
	
		
			
				
					|  |  |  |                                 case FLD_YD: | 
			
		
	
		
			
				
					|  |  |  |                                     if ((rec->assign[i].ch == CH0) && (!iv->isProducing(*mUtcTimestamp))) // avoids returns to 0 on restart
 | 
			
		
	
		
			
				
					|  |  |  |                                         continue; | 
			
		
	
		
			
				
					|  |  |  |                                     retained = true; | 
			
		
	
		
			
				
					|  |  |  |                                     break; | 
			
		
	
		
			
				
					|  |  |  |                             } | 
			
		
	
	
		
			
				
					|  |  | 
 |