NEWS
XML-RPC fault - Fehler abfangen?
-
Ich erhalte - unregelmäßig - folgende Fehlermeldung im log:
hm-rpc.1 2024-07-30 07:30:00.764 error Cannot call setValue: XML-RPC fault: Generic error (TIMEOUT) hm-rpc.1 2024-07-30 07:30:00.756 error xmlrpc -> setValue ["00021D89A1B3E0:3","STATE",true] BOOL
wobei es sich bei hm-rpc.1 um meine homematic ip Geräte handelt.
Daran schließen sich zwei Fragen ab:
- was könnte die Ursache für den Fehler sein?
- kann ich den Fehler gegebenenfalls mit einem Skript abfangen? (Es sieht so aus, als würde der entsprechende Schaltaktor, ein einfacher Zwischenstecker, den Schaltbefehl aus einem Skript nicht durchführen. Das perfide ist, dass es manchmal funktioniert, manchmal nicht. Andererseits kann ich über die WebUI den Schalter ein- und ausschalten. Heute Morgen zum Beispiel trat der Fehler um 7:30 Uhr auf. Um 8:30 Uhr habe ich es bemerkt und konnte dann den Schalter unproblematisch schalten.)
-
@skorpil sagte in XML-RPC fault - Fehler abfangen?:
was könnte die Ursache für den Fehler sein?
eine Kommunikationsstörung
-
@homoran und wie könnte ich gegebenenfalls diese Kommunikationsstörung, die offensichtlich nur kurz auftritt, gegebenenfalls mit einem Skript abfangen beziehungsweise darauf reagieren?
-
@skorpil sagte in XML-RPC fault - Fehler abfangen?:
die offensichtlich nur kurz auftritt,
ist meistens nur kurz, wenn da z.B. zeitgleich Funkpakete unterwegs sind, warum auch immer.
@skorpil sagte in XML-RPC fault - Fehler abfangen?:
gegebenenfalls mit einem Skript abfangen beziehungsweise darauf reagieren?
keine Ahnung.
Ich würde erstmal prüfen ob die Kollisionen absehbar wären. -
Diese Art von Kommunikationsfehlern bei Homematic IP treten immer wieder in unregelmäßigen Abständen auf. Eine Systematik dahinter konnte ich nicht entdecken. Ich würde gerne die Schalt Befehle immer dann noch einmal senden, wenn ein solcher Kommunikationsfehler auftritt. Wie kann ich ein Skript erstellen, dass auf den Kommunikationsfehler reagiert?
-
@skorpil keine Ahnung!
wird der Schaltbefehl denn nie ausgeführt wenn diese Meldung kommt? -
@homoran nein, der Schalt Befehl wird nie ausgeführt. Daher würde ich ja gerne auf den Fehler reagieren und den Befehl nochmals senden.
Was hältst du davon, wenn ich die Frage nochmals im unter Forum Javascript stelle?
-
@skorpil sagte in XML-RPC fault - Fehler abfangen?:
der Schalt Befehl wird nie ausgeführt.
also müsstest du "nur" prüfen ob nach 1 sec der Wert ist wie er sein soll.?!
-
@skorpil sagte in XML-RPC fault - Fehler abfangen?:
kann ich den Fehler gegebenenfalls mit einem Skript abfangen?
Klar, mit dem onLog-Baustein in Blockly. Dann schauen, ob der gesuchte Text darin vorkommt. Habe ich mit einem ähnlichen Beispiel im Kurs erklärt
-
z.B.
-
@haus-automatisierung dann muss ich noch mal in den Kurs hinein schauen, den habe ich ja gebucht. Trotzdem noch eine Frage, geht das auch außerhalb von blockly mit einem normalen Java Skript? Denn ich arbeite mit blockly nicht.
-
@skorpil sagte in XML-RPC fault - Fehler abfangen?:
geht das auch außerhalb von blocky mit einem normalen Java Skript?
Klar, da Blockly einfach nur JavaScript generiert
https://github.com/ioBroker/ioBroker.javascript/blob/master/docs/en/javascript.md#onlog
-
@haus-automatisierung ich werde mich daran mal versuchen und meine Lösung hier zeigen
-
mit Hilfe von KI habe ich folgendes Script zum erneuten Senden des Schaltbefehls (max. 3 mal, jeweils nach 5 sec) erstellt, wenn ein Kommunikationsfehler auftritt. Jetzt muß ich abwarten und sehen, wie es reagiert
// Warteschlange zur Speicherung der Schaltbefehl-Meldungen let setValueQueue = []; // Verwenden der onLog-Anweisung, um Logmeldungen zu überwachen onLog('error', function (obj) { const logMessage = obj.message; const source = obj.from; // Überprüfen, ob die Quelle 'hm-rpc.1' ist if (source === 'hm-rpc.1') { // Prüfen, ob die Logmeldung ein Schaltbefehl ist if (logMessage.includes('xmlrpc -> setValue')) { // Schaltbefehl in die Warteschlange speichern setValueQueue.push({ message: logMessage }); } // Prüfen, ob die Logmeldung ein Kommunikationsfehler ist if (logMessage.includes('Cannot call setValue: XML-RPC fault: Generic error (TIMEOUT)')) { // Prüfen, ob es einen gespeicherten Schaltbefehl gibt, der zu diesem Fehler passt if (setValueQueue.length > 0) { // Die älteste Schaltbefehl-Meldung aus der Warteschlange holen const lastSetValueLogEntry = setValueQueue.shift(); // Extrahiere die Gerätedaten aus dem Schaltbefehl const match = lastSetValueLogEntry.message.match(/xmlrpc -> setValue ["(.+?):(\d+)","(.+?)",(true|false)] BOOL/); if (match) { const deviceAddress = match[1]; // Adresse des Geräts const channel = match[2]; // Kanal des Geräts const stateName = match[3]; // Zustandsname (z.B. "STATE") const value = match[4] === 'true'; // Wert, den der Zustand annehmen soll // Befehl mit Verzögerung und Wiederholungslogik senden sendCommandWithRetry(deviceAddress, channel, stateName, value, 3); } } else { log('Kein zugehöriger Schaltbefehl für den Kommunikationsfehler gefunden.', 'warn'); } } } }); // Funktion, um den Schaltbefehl mit Wiederholungslogik zu senden function sendCommandWithRetry(deviceAddress, channel, stateName, value, retries) { const stateId = `hm-rpc.1.${deviceAddress}:${channel}.${stateName}`; const attemptToSendCommand = (remainingRetries) => { // Befehl senden setState(stateId, value, false, (err) => { if (err) { log(`Fehler beim Senden des Befehls für ${stateId}: ${err}`, 'error'); if (remainingRetries > 0) { log(`Wiederhole den Befehl in 5 Sekunden (${remainingRetries} Versuche verbleibend).`); // Erneut versuchen, nachdem eine Verzögerung von 5 Sekunden abgewartet wurde setTimeout(() => attemptToSendCommand(remainingRetries - 1), 5000); // 5000 ms = 5 Sekunden } else { log(`Maximale Anzahl an Wiederholungen erreicht für ${stateId}. Befehl wird nicht erneut gesendet.`, 'error'); } } else { log(`Befehl erfolgreich gesendet für ${stateId}`); } }); }; // Erste Ausführung des Befehls attemptToSendCommand(retries); }
-
@skorpil sagte: kann ich den Fehler gegebenenfalls mit einem Skript abfangen?
Ich gehe mal davon aus, dass es immer wieder die gleichen Aktoren betrifft und der Adapter bei Kommunikationsstörung den betreffenden Wert nicht bestätigt (ack = false). Dann kann man bei nicht bestätigter Änderung eine Wiederholung anstoßen, die bei Bestätigung des Wertes abgebrochen wird.
Skript für einen Aktor mit Wiederholung nach 1 s und 5 s:const idAktor = 'hm-rpc.1.00021D89A1B3E0.3.STATE'; var soll = getState(idAktor).val; var timer1 = null; var timer5 = null; on({id: idAktor}, function(dp) { if(dp.state.ack) { if(dp.state.val == soll) { clearTimeout(timer1); clearTimeout(timer5); } } else if(dp.state.val != soll) { soll = dp.state.val; timer1 = setTimeout(function() {setState(idAktor, soll);}, 1000); timer5 = setTimeout(function() {setState(idAktor, soll);}, 5000); } });
-
@paul53 ja, es sind immer wieder meine homematic IP Geräte. Keine Ahnung, warum! Das ist ein guter Vorschlag, ich werde auch diese Variante prüfen. Dankeschön.
-
@paul53 ich würde Dein Script gerne "generalisieren". Hier mal mein Versuch:
// Funktion, um relevante STATE-IDs im hm-rpc.1-Adapter zu ermitteln function getRelevantDeviceIds() { const ids = []; const states = $('state[id=hm-rpc.1.*.STATE]'); // Verwenden von Selektoren, um alle STATE-IDs zu finden states.each(function (id, i) { // Prüfen, ob die STATE-ID den Kanal 3 oder 4 betrifft const parts = id.split('.'); const channel = parts[parts.length - 2]; // Extrahiere die Kanalnummer if (channel === '3' || channel === '4') { ids.push(id); } }); return ids; } // Hauptfunktion, um für alle relevanten Geräte-IDs das Skript zu implementieren function setupListeners() { const deviceIds = getRelevantDeviceIds(); // Einmalige Auflistung der relevanten STATE-IDs beim Start des Skripts log('Relevante STATE-IDs im Adapter hm-rpc.1:', 'info'); deviceIds.forEach(id => log(id, 'info')); log('Anzahl der überwachten Geräte: ' + deviceIds.length, 'info'); // Log für die Anzahl der Geräte deviceIds.forEach(idAktor => { var soll = getState(idAktor).val; log('Initialer Soll-Wert für ' + idAktor + ': ' + soll, 'debug'); // Debug-Log für den initialen Soll-Wert var timer1 = null; var timer5 = null; // Ereignislistener für Zustandsänderungen des Gerätes on({id: idAktor}, function(dp) { log('Zustandsänderung bei ' + idAktor + ': ' + dp.state.val, 'debug'); // Debug-Log für Zustandsänderungen if (dp.state.ack) { if (dp.state.val == soll) { log('Zustand bestätigt und entspricht dem Soll-Wert bei ' + idAktor, 'debug'); // Debug-Log bei bestätigtem Zustand clearTimeout(timer1); clearTimeout(timer5); } } else if (dp.state.val != soll) { log('Neuer Soll-Wert für ' + idAktor + ': ' + dp.state.val, 'debug'); // Debug-Log für neuen Soll-Wert soll = dp.state.val; timer1 = setTimeout(function() { setState(idAktor, soll); log('Soll-Wert nach 1 Sekunde gesetzt bei ' + idAktor + ': ' + soll, 'debug'); // Debug-Log nach 1 Sekunde }, 1000); timer5 = setTimeout(function() { setState(idAktor, soll); log('Soll-Wert nach 5 Sekunden gesetzt bei ' + idAktor + ': ' + soll, 'debug'); // Debug-Log nach 5 Sekunden }, 5000); } }); }); } // Skriptausführung starten setupListeners();
Ich habe allerdings festgestellt, daß sich bei HMIP Zwischensteckern der relevante State im Kanal 3 findet, bei den HMIP Lichtschaltern im Kanal 4. Fällt Dir irgendeine Möglichkeit ein, im IObroker die für die Schaltung relevanten Kanäle zu ermitteln? Dummerweise gibt es auch in anderen Kanälen "States".Z.B. beim Zwischenstecker in Kanal 4. So dass "States" nicht trennscharf sind.
Der Einfachheit halber kann man natürlich alle States in Kanal 3 und 4 überwachen. Aber bei HMIP Lichtschaltern ist das ja nicht relevant, obwohl es eben da einen state gibt.
Ideal wäre es, nur die States zu überwachen, die wirklich relevant sind.
-
@skorpil HmIP arbeitet mit virtuellen Kanälen!
der jeweils erste in dem der State vorkommt dient nur der Anzeige des Gesamtergebnisses der Verknüpfungen der anderen virtuellen Kanäle.
nur diese lassen sich auch steuern -
@homoran Dankeschön. Und welchen muss ich dann steuern? (denn ich vermute, dass mein Problem mit den Fehlermeldungen vielleicht damit zusammen hängt, dass ich den falschen Kanal steuere?)
-
@skorpil sagte in XML-RPC fault - Fehler abfangen?:
Und welchen muss ich dann steuern?
kommt auf deine Konfiguration an.
so kannst du beim Dimmer z.b. an einem Kanal normal dimmen, am anderen Kanal einen "Faktor" einstellen, so dass es nachts nicht gar so hell wird.