Closed MiniOh closed 1 year ago
ja richtig beobachtet. Ich denke ich weiß wo der Fehler sitzt und werde ihn in den nächsten Tagen beseitigen
Super. Vielen Dank.
bitte mit 0.5.85
nochmal testen
OK, werde ich machen, berichte später.
@lumapu Negativ Euer Ehren 😪 85 macht es auch noch. Spannend finde ich aber, bin noch schnell zurück auf die 78, und da hat er die Werte noch bekommen, obwohl er schon nicht mehr produktiv war. Das Nullen muß also bereits beim nicht mehr einspeisen passieren, nicht erst bei „not available“. Vielleicht hilft das bei der Problemsuche ?
Ja, bei mir ebenso. In dem Moment wo die Inverter offline gehen, zeigt die Webseite unter "live" weiterhin den richtigen inverter/total/YieldTotal Wert an. Per MQTT werden aber offenbar nur die Werte übertragen von den noch onlinen oder produzierenden Wechselrichtern.
wir hatten erst kürzlich einen pull request für MqTT. Der sollte verhindern, dass unvollständige Totalwerte übertragen werden. Ich bin mir jetzt fast sicher: Der Fehler liegt in pubMqtt.h
Auch @beegee3 hatte hier Änderungen beigetragen.
Die 0.5.78 darf ich als letzte funktionierende werten?
ja die 5.78 funktioniert in jedem Fall, bei der 5.83 und 5.85 hab ich den fehler bemerkt bei der 5.80 bin ich selbst nicht sicher
wir hatten erst kürzlich einen pull request für MqTT. Der sollte verhindern, dass unvollständige Totalwerte übertragen werden. Ich bin mir jetzt fast sicher: Der Fehler liegt in
pubMqtt.h
Auch @beegee3 hatte hier Änderungen beigetragen. Die 0.5.78 darf ich als letzte funktionierende werten?
Ob die 0.5.78 die letzte funktionierende ist, kann ich auch nicht sicher sagen. Aber in der Version ist das übermitteln der Total Werte auf jeden Fall Ok.
das Problem ist, dass bei der Ermittlung der Totalwerte die mit Status MQTT_STATUS_NOT_AVAIL_NOT_PROD nicht berücksichtigt werden. Ich arbeite an einer Korrektur, kommt heute noch.
@beegee3 Ist das die 87 ?
nein, das kommt erst hier:
@lumapu habe die Ausgabe der Daten eines einzelnen Inverters in eine eigene Funktion
sendData(Inverter<> *iv, InfoCmdType curInfoCmd)
verlegt. Dadurch kann processIvStatus
die letzten Daten senden, wenn der Inverter in den Nicht-Produzier Status fällt. processIvStatus
wird nicht mehr in tickerMinute
aufgerufen (wäre jetzt schädlich!) dafür als erstes in sendIvData
, was ja aus tickerSecond
aufgerufen wird. Alles weitere habe ich in sendIvData
kommentiert.
Hier die Änderungen (auch wenn das onMessage
Problem #650 noch nicht gelöst ist, da bist du gefragt 😄)
...
PubMqtt() {
mRxCnt = 0;
mTxCnt = 0;
mSubscriptionCb = NULL;
memset(mLastIvState, MQTT_STATUS_NOT_AVAIL_NOT_PROD, MAX_NUM_INVERTERS);
mLastAnyAvail = false;
}
...
void tickerMinute() {
char val[12];
snprintf(val, 12, "%ld", millis() / 1000);
publish("uptime", val);
publish("wifi_rssi", String(WiFi.RSSI()).c_str());
publish("free_heap", String(ESP.getFreeHeap()).c_str());
}
...
bool processIvStatus() {
// returns true if any inverter is available
bool allAvail = true; // shows if all enabled inverters are available
bool anyAvail = false; // shows if at least one enabled inverter is available
bool changed = false;
char topic[7 + MQTT_TOPIC_LEN], val[40];
Inverter<> *iv;
record_t<> *rec;
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
iv = mSys->getInverterByPos(id);
if (NULL == iv)
continue; // skip to next inverter
if (!iv->config->enabled)
continue; // skip to next inverter
rec = iv->getRecordStruct(RealTimeRunData_Debug);
// inverter status
uint8_t status = MQTT_STATUS_NOT_AVAIL_NOT_PROD;
if (iv->isAvailable(*mUtcTimestamp)) {
anyAvail = true;
status = (iv->isProducing(*mUtcTimestamp)) ? MQTT_STATUS_AVAIL_PROD : MQTT_STATUS_AVAIL_NOT_PROD;
}
else // inverter is enabled but not available
allAvail = false;
if(mLastIvState[id] != status) {
// if status changed from producing to not producing send last data immediately
if (MQTT_STATUS_AVAIL_PROD == mLastIvState[id])
sendData(iv, RealTimeRunData_Debug);
mLastIvState[id] = status;
changed = true;
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name);
snprintf(val, 40, "%d", status);
publish(topic, val, true);
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->config->name);
snprintf(val, 40, "%d", iv->getLastTs(rec));
publish(topic, val, true);
}
}
if(changed) {
snprintf(val, 32, "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((anyAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE)));
publish("status", val, true);
}
return anyAvail;
}
...
void sendData(Inverter<> *iv, uint8_t curInfoCmd) {
char topic[7 + MQTT_TOPIC_LEN], val[40];
record_t<> *rec = iv->getRecordStruct(curInfoCmd);
if (iv->getLastTs(rec) > 0) {
for (uint8_t i = 0; i < rec->length; i++) {
bool retained = false;
if (curInfoCmd == RealTimeRunData_Debug) {
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;
}
}
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]);
snprintf(val, 40, "%g", ah::round3(iv->getValue(i, rec)));
publish(topic, val, retained);
yield();
}
}
}
void sendIvData() {
bool anyAvail = processIvStatus();
if (mLastAnyAvail != anyAvail)
mSendList.push(RealTimeRunData_Debug); // makes shure that total values are calculated
if(mSendList.empty())
return;
char topic[7 + MQTT_TOPIC_LEN], val[40];
float total[4];
bool RTRDataHasBeenSent = false;
while(!mSendList.empty()) {
memset(total, 0, sizeof(float) * 4);
uint8_t curInfoCmd = mSendList.front();
if ((curInfoCmd != RealTimeRunData_Debug) || !RTRDataHasBeenSent) { // send RTR Data only once
bool sendTotals = (curInfoCmd == RealTimeRunData_Debug);
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
Inverter<> *iv = mSys->getInverterByPos(id);
if (NULL == iv)
continue; // skip to next inverter
if (!iv->config->enabled)
continue; // skip to next inverter
// send RTR Data only if status is available
if ((curInfoCmd != RealTimeRunData_Debug) || (MQTT_STATUS_NOT_AVAIL_NOT_PROD != mLastIvState[id]))
sendData(iv, curInfoCmd);
// calculate total values for RealTimeRunData_Debug
if (sendTotals) {
record_t<> *rec = iv->getRecordStruct(curInfoCmd);
sendTotals &= (iv->getLastTs(rec) > 0);
if (sendTotals) {
for (uint8_t i = 0; i < rec->length; i++) {
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();
}
if (sendTotals) {
uint8_t fieldId;
for (uint8_t i = 0; i < 4; i++) {
switch (i) {
default:
case 0:
fieldId = FLD_PAC;
break;
case 1:
fieldId = FLD_YT;
break;
case 2:
fieldId = FLD_YD;
break;
case 3:
fieldId = FLD_PDC;
break;
}
snprintf(topic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]);
snprintf(val, 40, "%g", ah::round3(total[i]));
publish(topic, val, true);
}
RTRDataHasBeenSent = true;
yield();
}
}
mSendList.pop(); // remove from list once all inverters were processed
}
mLastAnyAvail = anyAvail;
}
...
bool mLastAnyAvail;
...
};
Schade, die 87 macht es auch noch. Also hoffen das @beegee3 das gefixed hat und @lumapu das in die 88 rein baut 😅 Ansonsten muß ich mir überlegen ob ich die total/Yield-Werte in Zukunft über Node-Red selbst zusammenrechnen muß 😇
Ja, bei mir hat die 87 auch noch den "Fehler", dass beim Offline gehen der Inverter Zero Werte übermittelt werden. Die Anzeige unter "Live" stimmt aber nach wie vor, nur die Werte per MQTT nicht.
die 87er Version hat nur die "händische" Yield Total Correction je Solarmodul in den Inverter Settings und noch keinen Fix für das hier aufgeführte Issue. Mein Vorschlag kam erst nachdem 87 raus war.
... beim Offline gehen der Inverter Zero Werte übermittelt werden
Nein, auch in der 87 werden keine Zero Werte übermittelt. Die Total Berechnung ist schlichtweg falsch weil nur die Inverter berücksichtigt sind, die noch Online sind. Aber das hat sich ja hoffentlich mit der nächsten Version erledigt🤞
@lumapu noch ein Nachtrag (reine Pedanterie, hat eigentlich keine Auswirkungen und wenig mit dem Issue zu tun)
in app.h
im payloadEventListener
noch if (mMqttEnabled)
einbauen, d.h.
void payloadEventListener(uint8_t cmd) {
#if !defined(AP_ONLY)
if (mMqttEnabled)
mMqtt.payloadEventListener(cmd);
#endif
if(mConfig->plugin.display.type != 0)
mMonoDisplay.payloadEventListener(cmd);
}
hab' die Korrektur oben an 3 Stellen verändert:
in sendData
und sendIvData
ist curInfoCmd ist vom Type uint8_t (nicht InfoCmdType, das ging nur mit angepasster mSendList
)
und in sendData
war die topic
Definition abhanden gekommen.
Wann gibts die .88 ;-)
@MiniOh 13.02.2023 23:00 😅
na, super den schwarzen Peter auf mich schieben, wenn's morgen nicht klappt 😦😨 Wollte es heute checken, aber erst, als es zu spät war, hab' ich gemerkt, dass MQTT für andere Tests abgeklemmt war 😒 Aber noch vor @knickohr 's Zeitvorgabe! 🙇
Einer muss ja Schuld sein 🙂
Es hat sich definitiv was geändert 😲
Es werden jetzt keine Werte von den einzelnen Strängen der WRs mehr ausgegeben, obwohl schon eingespeist wird. Die Inverter sind aber noch im Status 1. erst wenn die Inverter im Status 2 sind werden auch Werte zu den Strängen per MQTT geliefert. Das war vorher nicht so. Ist das gewünscht ?
(Im Bild fehlen die Daten der einzelnen Inverter, obwohl schon eingespeist wird)
ich fand es vorher „ehrlicher“, ist aber kein Beinbruch wenn man es weiß. Bin gespannt auf heute Abend 😉
na, super den schwarzen Peter auf mich schieben, wenn's morgen nicht klappt 😦😨 Wollte es heute checken, aber erst, als es zu spät war, hab' ich gemerkt, dass MQTT für andere Tests abgeklemmt war 😒 Aber noch vor @knickohr 's Zeitvorgabe! 🙇
nein, wir sind eher dankbar, dass du dich dem Thema auch angenommen hast 😃
@knickohr stimmt, ist ein Inverter im Status 1 (MQTT_STATUS_AVAIL_NOT_PROD) werden seine Daten nicht ausgegeben. Ich wollte vermeiden, dass permanent Ausgaben erfolgen, solange der IV in diesem Status ist also online ist, aber nichts produziert. Aber, hast ja Recht, wenn man nicht nur an den Yield Werten interessiert ist, macht eine Ausgabe im Status 1 auch Sinn.
@lumapu also in sendIvData
die Zeile
if ((curInfoCmd != RealTimeRunData_Debug) || (MQTT_STATUS_AVAIL_PROD == mLastIvState[id]))
ändern zu
if ((curInfoCmd != RealTimeRunData_Debug) || (MQTT_STATUS_NOT_AVAIL_NOT_PROD != mLastIvState[id]))
und eine Korrektur in processIvStatus
(peinlicherweise wurde anyAvail
gar nicht angepasst 😲):
// inverter status
uint8_t status = MQTT_STATUS_NOT_AVAIL_NOT_PROD;
if (iv->config->enabled) {
if (iv->isAvailable(*mUtcTimestamp)) {
anyAvail = true;
status = (iv->isProducing(*mUtcTimestamp)) ? MQTT_STATUS_AVAIL_PROD : MQTT_STATUS_AVAIL_NOT_PROD;
}
else // inverter is enabled but not available
allAvail = false;
}
habe den Code oben entsprechend korrigiert.
Geschafft ! Es funktioniert wieder 😎 Jetzt nur noch der kleine Schönheitsfehler mit dem Status, dann haben wir wieder den Stand zuvor 👍
Ja, sieht gut aus. Auch hier keine Zero Werte mehr. Die .88 sieht nach der .78 wieder gut aus ... jetzt muss nur noch etwas mehr Stabilität hier, dann ist erst mal alles klasse. Aber das ist ja ein anderes Thema, aber auch das ist u.U. mit der .88 auch schon besser?
Freut mich zu hören, @beegee3 das sind deine Lorbeeren.
Stabilität ist für die 90ger Versionen vorgesehen 🙈 und bei 100 machen wir ein Release 😂
sind deine Lorbeeren
steck ich gerne ein 🪴. Vor dem Release hätte ich vielleicht noch etwas zur Verbesserung des Radio (auch wenn das schon gut läuft).
Versuche gerade, diese Info zu nutzen um die 'missing Frame' Rate zu senken. Eine Anpassung macht aber nur Sinn, wenn dass allgemein so ist. Die FX und RX Channel kann man im serial log sehen, für die Wartezeit muss man einen zusätzlichen Debug in die Radio loop einbauen, da die RX Channel Ausgabe erst nach der loop gemacht wird. Frage in die Runde: könnt ihr das (zumindest die Punkte 1 und 2) bestätigen? Dann votet bitte mit 👍, sieht's bei euch anders aus, dann bitte 👎 (und ggfs. Beschreibung). Sehe ich nur Daumen hoch, mach' ich ein neues Issue dafür auf.
Muß ich Morgen mal genauer drauf schauen.
sind deine Lorbeeren
steck ich gerne ein 🪴. Vor dem Release hätte ich vielleicht noch etwas zur Verbesserung des Radio (auch wenn das schon gut läuft).
1. mir ist aufgefallen, dass bei vollständigem Empfang (keine 'missing Frames') fast immer ein 3 Channel Versatz zwischen TX und RX Channel (1.Frame) ist (TX=03 -> RX=61, TX=23 -> RX=75, TX=40 -> RX=03, usw.). Ist Channel 75 beteiligt, ist der Unterschied manchmal anders. 2. oft kommt der nächste Frame auf demselben RX Channel und wenn es ein anderer ist, dann immer der in der Liste (03, 23, 40, 61, 75) vorherige. Ist Channel 75 beteiligt, ist der Unterschied manchmal 2 statt 1 Channel. 3. die Wartezeit zwischen 2 Frames liegt bei 30-50 ms.
Versuche gerade, diese Info zu nutzen um die 'missing Frame' Rate zu senken. Eine Anpassung macht aber nur Sinn, wenn dass allgemein so ist. Die FX und RX Channel kann man im serial log sehen, für die Wartezeit muss man einen zusätzlichen Debug in die Radio loop einbauen, da die RX Channel Ausgabe erst nach der loop gemacht wird. Frage in die Runde: könnt ihr das (zumindest die Punkte 1 und 2) bestätigen? Dann votet bitte mit 👍, sieht's bei euch anders aus, dann bitte 👎 (und ggfs. Beschreibung). Sehe ich nur Daumen hoch, mach' ich ein neues Issue dafür auf.
Ich habe relativ viele "Missing Frames". Konnte ich bisher auch durch ändern des Empfangs am NRF nicht beseitigen, Hat mich aber bisher auch nicht weiter gestört TX und RX fails hab ich sogut wie keine. Und nochmal danke für das wiederherstellen der "Total Werte"
Hey,
ich vermute es passt noch nicht ganz mit den Zero Werten bei der 0.5.88. Beim offline gehen der Inverter sieht alles richtig aus. Beim Booten der DTU, wenn gerade die Kommunikation mit den Invertern aufgebaut wird, werden erst Zeros übermittelt, dann die Werte des ersten Inverters, bis die Werte dann wieder stimmen, wenn alle Inverter einmal online waren. Könnt Ihr das bestätigen?
ja, hab' ich auch heute morgen festgestellt. Die Zeros kommen wohl, wenn der Inverter als produktiv festgestellt wurde, aber noch keine Werte ermittelt wurden. Beim Booten sind natürlich erst alle Werte aller Inverter auf 0. Da die Total Angaben gemacht werden, sobald ein Inverter produktiv ist, werden die Summen solange falsch berechnet, bis alle online sind (wie du's beschrieben hast). @lumapu da muss ich wohl nochmal ran: meine Idee ist, für jeden Inverter einen Status zu hinterlegen, der zeigt, ob sein YieldTotal > 0 ist. Erst dann werden seine Werte veröffentlicht. Totals werden erst rausgegeben, wenn YieldTotal aller Inverter positiv sind. Das sollte die hier beschriebenen Probleme beseitigen. Das von @knickohr oben beschriebene (Status 1 bzw. 2) wird nach einem Reboot dann wiederkommen, aber damit muss man leben, wenn die Total Werte stimmen sollen. Und so oft sollten mit den 90er Versionen Reboots ja nicht mehr notwendig sein 🤞
@beegee3 Wenn das nach einem Reboot oder Crash vorkommt ist es Schnuppe. Es sollte halt nicht vorkommen wenn die Inverter morgens aufwachen oder sich abends schlafen legen.
@beegee3 So, ich habe jetzt eine halbe Stunde das Serial Log angeglotzt. Hier ist die Antwort 👍
@beegee3 Ich habe mal nach deinen Anweisungen mitgeloggt. Grob überflogen habe ich es auch, was ich oft gesehen habe ist TX 40 -> RX 3
. Leider habe ich sehr viele Retransmits heute - scheinbar viel Funkverkehr bei mir 🤨
230215_0.5.89_timing.log
Code oben editiert (sendData
und sendIvData
). Werte eines einzelnen Inverters werden nur ausgegeben, wenn auch welche vorhanden sind. Totals werden nur ausgegeben, wenn bei allen Invertern Werte vorhanden sind.
Wollte es ja über YieldTotal > 0 machen, geht aber nicht wegen 'Yield Total Correction'. Und YieldDay kann auch noch 0 sein. Wäre da noch U_AC. Schien mir auch unsicher (Batterie, u.a.).
Jetzt wird auf Timestamp (iv->getLastTs(rec) > 0
) geprüft. Das sollte nur = 0 sein, wenn noch keine Werte ermittelt wurden (d.h. nach Reboot). Allerdings könnte es nun passieren, dass morgens, wenn der Inverter online geht, noch die Werte vom Abend vorher übermittelt werden, wenn die aktuellen noch nicht vorliegen.
@lumapu
Ich habe mal nach deinen Anweisungen mitgeloggt
ja, der log ist schwierig, sind ja fast nur Retransmits 😞 Aber auch hier scheinen sich die Vermutungen 1 und 2 zu bestätigen. Ich versuche mal mit RX Channel = 3 Channel Versatz zu TX zu starten und RX dann rückwärts laufen zu lassen. Dazu noch eine Warteschleife nach einem RX Treffer, bei der auf demselben Channel gehorcht wird. Probiere dafür mal 35, 40, 45 bzw. 50 ms aus. Mal sehen, ob das die 'missing Frame' Rate senkt (davon hatte ich heute auch mehr als sonst).
Code oben editiert (
sendData
undsendIvData
). Werte eines einzelnen Inverters werden nur ausgegeben, wenn auch welche vorhanden sind. Totals werden nur ausgegeben, wenn bei allen Invertern Werte vorhanden sind. Wollte es ja über YieldTotal > 0 machen, geht aber nicht wegen 'Yield Total Correction'. Und YieldDay kann auch noch 0 sein. Wäre da noch U_AC. Schien mir auch unsicher (Batterie, u.a.). Jetzt wird auf Timestamp (iv->getLastTs(rec) > 0
) geprüft. Das sollte nur = 0 sein, wenn noch keine Werte ermittelt wurden (d.h. nach Reboot). Allerdings könnte es nun passieren, dass morgens, wenn der Inverter online geht, noch die Werte vom Abend vorher übermittelt werden, wenn die aktuellen noch nicht vorliegen.
Guten Morgen,
diese Anpassungen sind noch nicht in der .89 drin, oder?
sind noch nicht drin, alle Änderungen betreffen Stabilitätsprobleme
@lumapu an vielen Stellen werden Inverter mit Inverter<> *iv = mSys->getInverterByPos(id);
ermittelt und bei NULL == iv
ignoriert. Allerdings wird nur in wenigen Fällen iv->config->enabled
geprüft, obwohl diese häufig auch ignoriert werden könnten (bei app, xxPayload, pubMqtt, pubSerial, MonochromeDisplay; bei RestApi getLive, getRecord wohl auch?)
du könntest das in getInverterByPos
mit einem weiteren bool Parameter abfangen (hast ja schon einen drin).
Habe vorsichtshalber processIvStatus
und sendIvData
im Code oben angepasst, da zumindest die Total Berechnung nach meiner letzten Anpassung sonst nicht funktioniert.
@lumapu 👍zur neuen Version 0.5.90. Leider haben es die letzten Änderungen an processIvStatus
, sendData
und sendIvData
nicht mehr in die Version geschafft.
Wären aber wichtig:
iv->config->enabled
berücksichtigen (processIvStatus
und sendIvData
)anyAvail
richtig ermitteln und somit 'status' topic richtig setzen (processIvStatus
)iv->getLastTs(rec) > 0
Werte publishen (sendData
für den einzelnen Inverter und sendIvData
für die Totals)processIvStatus
)Auch das dürfte gefixed sein. eben hat es bei mir wieder funktioniert 👍
Hallo
kann es sein, dass mit der 0.5.83 nun auch Zero Werte bei inverter/total/YieldDay, inverter/total/YieldTotal und inverter/total/P_AC per MQTT übertragen werden, wenn die WR Abends offline gehn. Mit der 0.5.78 war das nicht der Fall.
Mit der 0.5.78 war es doch so, dass z.B. YieldDay mit dem Offline schalten der Wechselrichter nicht mehr "kleiner" wurde. Wenn z.B. bis Abends 6.5kWh Erzeugt wurden, wurden 6500Wh per MQTT übertragen, auch wenn bereits einer der Wechselrichter offline war.
Bei der 0.5.83 scheint es so zu sein, dass dann noch die YieldDay von 2 von 3, und später von 1 von 3 WR übertragen werden und am Ende noch ein paar Zero Werte bevor die MQTT Übertragung endet.
Jeweils keine Settings aktiv bei:
Reset YieldDay at Midnight Reset Values at Communication stop Reset Values on 'not available'
Ebenfalls nichts gesetzt bei: disable night communication
Hardware