NEWS
Wert in Datenpunkt schreiben
-
Hallo Leute, ich komme hier nicht weiter.
Ich habe hier einen Datenpunkt:homeconnect.0.xxxxxxxxxxxxxxxxxx.programs.active.options.LaundryCare_WasherDryer_Option_ProgramMode
Wenn ich im Objektbaum mit der der Maus über diesen Datenpunkt streiche dann
sehe ich den Wert `Washing´Kann mir jemand sagen wie ich diesen Wert auslesen kann und in einen neuen
bestehenden Datenpunkt schreiben kann?
Ich hoffe ich habe mich richtig ausgedrückt. -
@malleralle bitte die Objektdaten des Datenpunkts im Expertenmodus zeigen.
Das JSON hier in code-tags posten -
@malleralle sagte: sehe ich den Wert `Washing´
Das ist nicht der Wert, sondern der zum Wert gehörige Zustandstext. In "OBJEKTDATEN" (Expertenmodus) sieht man unter common.states die zu den Werten (links) zugehörigen Zustandstexte (rechts).
Bitte keine Fotos, sondern Screenshots posten! -
@malleralle sagte: diesen Wert auslesen kann und in einen neuen bestehenden Datenpunkt schreiben kann?
Inhalt der Funktion stateText(id, val):
return getObject(id).common.states[val];
-
{ "type": "state", "common": { "name": "Programmtyp", "type": "mixed", "role": "indicator", "write": true, "read": true, "unit": "", "states": { "LaundryCare.WasherDryer.EnumType.ProgramMode.Washing": "Washing" } }, "native": {}, "from": "system.adapter.homeconnect.0", "user": "system.user.admin", "ts": 1739299667852, "_id": "homeconnect.0.xxxxxxxxxxxxxxxxxx.programs.active.options.LaundryCare_WasherDryer_Option_ProgramMode", "acl": { "object": 1636, "state": 1636, "owner": "system.user.admin", "ownerGroup": "system.group.administrator" } }
-
@malleralle
Der "ProgramMode" hat nur einen Wert, lässt sich also nicht ändern? -
@malleralle gibt es dann etwa für jeden Modus einen eigenen Datenpunkt?
-
Der Datenpunkt kann auch andere Werte anzeigen: Drying, Schleudern, usw
Nein, gibt nur einen Datenpunkt. Zumindest für Programmmode -
@malleralle sagte in Wert in Datenpunkt schreiben:
Der Datenpunkt kann auch andere Werte anzeigen: Drying, Schleudern, usw
Das hatten wir erwartet, ist aber in den Objektdaten nicht verankert
-
@malleralle sagte in Wert in Datenpunkt schreiben:
_id": "homeconnect.0.874110537388003932.programs.active.options.LaundryCare_WasherDryer_Option_ProgramMode",
@malleralle sagte in Wert in Datenpunkt schreiben:
LaundryCare.WasherDryer.EnumType.ProgramMode.Washing": "Washing"
Vielleicht steckt in der Extension die Lösung
-
Also der Ansatz von @paul53 hier ist schon mal gut.
Aber der Datenpunkt wird von HomeConnect bei fertigen Programmende des Waschtrockners wohl gelöscht. Er ist jedenfalls dann nicht mehr vorhanden...
Wenn Maschine an und Programm in der Maschine ausgewählt und gestartet ist, dann ist der Datenpunkt wieder da und gefüllt.
Das bringt mir beim start des Programms und Befüllung des Datenpunktes eine Fehlermeldung.
Gefüllt wird vom homeconnect Adapter in zwei unterschiedliche Datenpunkte:LaundryCare.WasherDryer.EnumType.ProgramMode.Washing
LaundryCare.Common.EnumType.ProcessPhase.DetectingLoad
Muss doch irgenwie möglich sein den Wert hinter:
LaundryCare.Common.EnumType.ProcessPhase.
oder:
LaundryCare.WasherDryer.EnumType.ProgramMode.
auszulesen. Vieleicht mit regex?
Hier die Fehlermeldung:
javascript.0 2025-02-12 08:47:02.525 error at processImmediate (node:internal/timers:491:21) javascript.0 2025-02-12 08:47:02.525 error at Immediate.<anonymous> (/opt/iobroker/node_modules/@iobroker/js-controller-adapter/src/lib/adapter/adapter.ts:11048:62) javascript.0 2025-02-12 08:47:02.524 error at Object.stateChange (/opt/iobroker/node_modules/iobroker.javascript/main.js:645:29) javascript.0 2025-02-12 08:47:02.524 error at Object.callback (/opt/iobroker/node_modules/iobroker.javascript/lib/sandbox.js:1452:38) javascript.0 2025-02-12 08:47:02.524 error at Object.<anonymous> (script.js.Datenpunkte.Waschtrockner2:13:75) javascript.0 2025-02-12 08:47:02.524 error at programmtyp (script.js.Datenpunkte.Waschtrockner2:6:39) javascript.0 2025-02-12 08:47:02.523 error script.js.Datenpunkte.Waschtrockner2: TypeError: Cannot read properties of undefined (reading 'LaundryCare.WasherDryer.EnumType.ProgramMode.Washing') javascript.0 2025-02-12 08:47:02.477 error at processImmediate (node:internal/timers:491:21) javascript.0 2025-02-12 08:47:02.477 error at Immediate.<anonymous> (/opt/iobroker/node_modules/@iobroker/js-controller-adapter/src/lib/adapter/adapter.ts:11048:62) javascript.0 2025-02-12 08:47:02.476 error at Object.stateChange (/opt/iobroker/node_modules/iobroker.javascript/main.js:645:29) javascript.0 2025-02-12 08:47:02.476 error at Object.callback (/opt/iobroker/node_modules/iobroker.javascript/lib/sandbox.js:1452:38) javascript.0 2025-02-12 08:47:02.476 error at Object.<anonymous> (script.js.Datenpunkte.Waschtrockner1:42:85) javascript.0 2025-02-12 08:47:02.476 error at prozessphase (script.js.Datenpunkte.Waschtrockner1:6:39) javascript.0 2025-02-12 08:47:02.475 error script.js.Datenpunkte.Waschtrockner1: TypeError: Cannot read properties of undefined (reading 'LaundryCare.Common.EnumType.ProcessPhase.DetectingLoad')
-
Vielen Dank Euch beiden.
Ich habe das Script nun fertig und läuft.
DeepSeek hat mir dabei geholfen...// Konfiguration const SOURCE_DATAPOINT_PROGRAM_MODE = 'homeconnect.0.xxxxxxxxxxxxxxxxxx.programs.active.options.LaundryCare_WasherDryer_Option_ProgramMode'; const SOURCE_DATAPOINT_PROCESS_PHASE = 'homeconnect.0.xxxxxxxxxxxxxxxxxx.programs.active.options.LaundryCare_Common_Option_ProcessPhase'; const SOURCE_DATAPOINT_STATUS = 'homeconnect.0.xxxxxxxxxxxxxxxxxx.status.BSH_Common_Status_OperationState'; const SOURCE_DATAPOINT_DOOR_STATE = 'homeconnect.0.xxxxxxxxxxxxxxxxxx.status.BSH_Common_Status_DoorState'; // Datenpunkt für Türstatus const SOURCE_DATAPOINT_ACTIVE_PROGRAM = 'homeconnect.0.xxxxxxxxxxxxxxxxxx.programs.active.BSH_Common_Root_ActiveProgram'; // Neuer Datenpunkt const TARGET_DATAPOINT_PROGRAM_MODE = 'Geräte.0.Waschtrockner-Bosch.Programm'; const TARGET_DATAPOINT_PROCESS_PHASE = 'Geräte.0.Waschtrockner-Bosch.ProgrammPhase'; const TARGET_DATAPOINT_STATUS = 'Geräte.0.Waschtrockner-Bosch.Status'; const TARGET_DATAPOINT_DOOR_STATE = 'Geräte.0.Waschtrockner-Bosch.Türstatus'; // Ziel-Datenpunkt für Türstatus const TARGET_DATAPOINT_ACTIVE_PROGRAM = 'Geräte.0.Waschtrockner-Bosch.Programm-Läuft'; // Neuer Ziel-Datenpunkt const RETRY_DELAY_1 = 7000; // Verzögerung für den 1. Versuch const RETRY_DELAY_2 = 5000; // Verzögerung für den 2. Versuch const STATUS_CHECK_DELAY = 2000; // Verzögerung für die Statusüberprüfung // Globale Variablen let programModeListenerId; let processPhaseListenerId; let statusListenerId; let doorStateListenerId; let activeProgramListenerId; let triggerActive = false; let programModeDatapointExists = false; let processPhaseDatapointExists = false; let washingMachineRunning = false; let retryTimeoutId; // Timeout-ID für den 2. Versuch // Funktion zum Extrahieren des Werts und Schreiben in den Ziel-Datenpunkt function updateValue(state, targetDatapoint) { if (state && state.val !== undefined && state.val !== null && state.val !== '') { let value = state.val; if (typeof value === 'string') { // Extrahiere den letzten Teil des Strings (z. B. "Open" aus "BSH.Common.EnumType.DoorState.Open") value = value.substring(value.lastIndexOf('.') + 1); } console.log(`Schreibe Wert in ${targetDatapoint}: ${value}`); // Wert wird hier protokolliert setState(targetDatapoint, value, true); } else { console.log(`Fehler: state oder state.val ist undefined, null oder leer für ${targetDatapoint}. Setze Standardwert.`); setState(targetDatapoint, 'Unbekannt', true); // Setze einen Standardwert } } // Funktion zum Extrahieren des aktiven Programms function updateActiveProgram(state, targetDatapoint) { if (state && state.val !== undefined && state.val !== null && state.val !== '') { let value = state.val; if (typeof value === 'string') { // Entferne die Punkte am Ende des Strings value = value.replace(/\.+$/, ''); // Extrahiere den letzten Teil des Strings (z. B. "EasyCare" aus "LaundryCare.WasherDryer.Program.EasyCare") value = value.substring(value.lastIndexOf('.') + 1); } console.log(`Schreibe Wert in ${targetDatapoint}: ${value}`); // Wert wird hier protokolliert setState(targetDatapoint, value, true); } else { console.log(`Fehler: state oder state.val ist undefined, null oder leer für ${targetDatapoint}. Setze Standardwert.`); setState(targetDatapoint, 'Unbekannt', true); // Setze einen Standardwert } } // Funktion zum Einrichten eines Listeners für einen Datenpunkt function setupListener(sourceDatapoint, targetDatapoint, updateFunction = updateValue) { getObject(sourceDatapoint, (err, obj) => { if (!err && obj) { console.log(`Datenpunkt ${sourceDatapoint} existiert. Listener wird eingerichtet.`); // Initialen Wert abrufen und schreiben getState(sourceDatapoint, (err, state) => { if (!err && state && state.val !== undefined && state.val !== null && state.val !== '') { updateFunction(state, targetDatapoint); } else { console.log(`Fehler beim Lesen des initialen Zustands für ${sourceDatapoint}. Setze Standardwert.`); setState(targetDatapoint, 'Unbekannt', true); // Setze einen Standardwert } }); // Listener für Änderungen am Datenpunkt const listenerId = on({ id: sourceDatapoint, change: 'any' }, (state) => { console.log(`Änderung erkannt für ${sourceDatapoint}:`, state); if (state.val === undefined || state.val === null || state.val === '') { console.log(`Warnung: Der Wert für ${sourceDatapoint} ist undefined, null oder leer.`); // Versuche, den Wert erneut abzurufen getState(sourceDatapoint, (err, state) => { if (!err && state && state.val !== undefined && state.val !== null && state.val !== '') { updateFunction(state, targetDatapoint); } else { console.log(`Fehler beim erneuten Abruf des Zustands für ${sourceDatapoint}.`); } }); } else { updateFunction(state, targetDatapoint); } }); if (sourceDatapoint === SOURCE_DATAPOINT_PROGRAM_MODE) { programModeListenerId = listenerId; programModeDatapointExists = true; } else if (sourceDatapoint === SOURCE_DATAPOINT_PROCESS_PHASE) { processPhaseListenerId = listenerId; processPhaseDatapointExists = true; } else if (sourceDatapoint === SOURCE_DATAPOINT_STATUS) { statusListenerId = listenerId; } else if (sourceDatapoint === SOURCE_DATAPOINT_DOOR_STATE) { doorStateListenerId = listenerId; console.log(`Listener für Türstatus (${sourceDatapoint}) erfolgreich eingerichtet.`); } else if (sourceDatapoint === SOURCE_DATAPOINT_ACTIVE_PROGRAM) { activeProgramListenerId = listenerId; console.log(`Listener für aktives Programm (${sourceDatapoint}) erfolgreich eingerichtet.`); } } else { console.log(`Datenpunkt ${sourceDatapoint} existiert nicht oder Fehler:`, err); } }); } // Funktion zum Stoppen des Skripts und Aufräumen function stopScript() { console.log("Skript wird gestoppt und aufgeräumt."); washingMachineRunning = false; triggerActive = false; programModeDatapointExists = false; processPhaseDatapointExists = false; if (programModeListenerId) { clearTimeout(programModeListenerId); programModeListenerId = null; } if (processPhaseListenerId) { clearTimeout(processPhaseListenerId); processPhaseListenerId = null; } if (statusListenerId) { clearTimeout(statusListenerId); statusListenerId = null; } if (doorStateListenerId) { clearTimeout(doorStateListenerId); doorStateListenerId = null; } if (activeProgramListenerId) { clearTimeout(activeProgramListenerId); activeProgramListenerId = null; } if (retryTimeoutId) { clearTimeout(retryTimeoutId); // Stoppe den 2. Versuch, falls er aktiv ist retryTimeoutId = null; } } // Funktion zum Überprüfen des Trigger-Zustands function checkTrigger(state) { // Überprüfen, ob state oder state.val undefined oder null ist if (!state || state.val === undefined || state.val === null || state.val === '') { console.log("Status ist leer, undefined oder null. Warte..."); setTimeout(() => { getState(SOURCE_DATAPOINT_STATUS, (err, state) => { if (!err && state && state.val !== undefined && state.val !== null && state.val !== '') { checkTrigger(state); // Erneut versuchen, wenn ein gültiger Status verfügbar ist } else { console.log("Status immer noch nicht verfügbar. Warte weiter..."); } }); }, STATUS_CHECK_DELAY); // Verzögerung vor dem erneuten Versuch return; } const status = state.val; // Überprüfen, ob der Status ein gültiger String ist if (typeof status !== 'string') { console.log("Status ist kein gültiger String. Warte..."); return; } // Schreibe jeden Statuswert in den Ziel-Datenpunkt updateValue(state, TARGET_DATAPOINT_STATUS); // Starte oder stoppe das Skript basierend auf dem Status if (status === 'BSH.Common.EnumType.OperationState.Inactive') { console.log("Waschmaschine inaktiv. Skript wird gestoppt."); stopScript(); } else if (status === 'BSH.Common.EnumType.OperationState.Ready') { console.log(`Waschmaschine bereit (Status: ${status}). Listener für OperationState und DoorState werden gestartet.`); if (!statusListenerId) { setupListener(SOURCE_DATAPOINT_STATUS, TARGET_DATAPOINT_STATUS); } if (!doorStateListenerId) { setupListener(SOURCE_DATAPOINT_DOOR_STATE, TARGET_DATAPOINT_DOOR_STATE); } } else if (status === 'BSH.Common.EnumType.OperationState.Run') { console.log(`Waschmaschine läuft (Status: ${status}). Listener für ProgramMode, ProcessPhase und ActiveProgram werden gestartet.`); if (!programModeDatapointExists || !processPhaseDatapointExists) { setTimeout(() => { console.log('Überprüfe und starte Listener für Datenpunkte (1. Versuch)...'); if (!programModeDatapointExists) { setupListener(SOURCE_DATAPOINT_PROGRAM_MODE, TARGET_DATAPOINT_PROGRAM_MODE); programModeDatapointExists = true; // Flag direkt setzen } if (!processPhaseDatapointExists) { setupListener(SOURCE_DATAPOINT_PROCESS_PHASE, TARGET_DATAPOINT_PROCESS_PHASE); processPhaseDatapointExists = true; // Flag direkt setzen } if (!activeProgramListenerId) { setupListener(SOURCE_DATAPOINT_ACTIVE_PROGRAM, TARGET_DATAPOINT_ACTIVE_PROGRAM, updateActiveProgram); } // Überprüfen, ob der zweite Versuch notwendig ist if (!programModeDatapointExists || !processPhaseDatapointExists) { retryTimeoutId = setTimeout(() => { console.log('Überprüfe und starte Listener für Datenpunkte (2. Versuch)...'); if (!programModeDatapointExists) { setupListener(SOURCE_DATAPOINT_PROGRAM_MODE, TARGET_DATAPOINT_PROGRAM_MODE); } if (!processPhaseDatapointExists) { setupListener(SOURCE_DATAPOINT_PROCESS_PHASE, TARGET_DATAPOINT_PROCESS_PHASE); } if (!activeProgramListenerId) { setupListener(SOURCE_DATAPOINT_ACTIVE_PROGRAM, TARGET_DATAPOINT_ACTIVE_PROGRAM, updateActiveProgram); } }, RETRY_DELAY_2); } }, RETRY_DELAY_1); } } } // Überwache den Status-Datenpunkt on({ id: SOURCE_DATAPOINT_STATUS, change: 'any' }, (state) => { checkTrigger(state); }); // Initiale Überprüfung des Status setTimeout(() => { getState(SOURCE_DATAPOINT_STATUS, (err, state) => { if (!err && state && state.val !== undefined && state.val !== null && state.val !== '') { checkTrigger(state); } else { console.log("Initialer Status ist leer, undefined oder null. Überprüfe später erneut."); setTimeout(() => { getState(SOURCE_DATAPOINT_STATUS, (err, state) => { if (!err && state && state.val !== undefined && state.val !== null && state.val !== '') { checkTrigger(state); } else { console.log("Immer noch kein initialer Status. Skript wird beendet."); } }); }, STATUS_CHECK_DELAY); // Verzögerung vor dem erneuten Versuch } }); }, STATUS_CHECK_DELAY); // Verzögerung vor der initialen Überprüfung // Listener für den Status-Datenpunkt direkt starten setupListener(SOURCE_DATAPOINT_STATUS, TARGET_DATAPOINT_STATUS); // Listener für den Türstatus-Datenpunkt starten setupListener(SOURCE_DATAPOINT_DOOR_STATE, TARGET_DATAPOINT_DOOR_STATE); // Listener für den aktiven Programm-Datenpunkt starten setupListener(SOURCE_DATAPOINT_ACTIVE_PROGRAM, TARGET_DATAPOINT_ACTIVE_PROGRAM, updateActiveProgram);
-
@malleralle sagte in Wert in Datenpunkt schreiben:
Vielen Dank Euch beiden.
Ich hatte das selbe Problem und dank eurer Lösung konnte ich mir einen Codeschnipsel raus kopieren . Da ich nur drei Funktionen abfrage, langt mir eine einfache Lösung. Hier ein Beispiel wie ich einen DP abfrage.
// Status const dp1='homeconnect.0.BOSCH-WDU28513-68A40E987899.status.BSH_Common_Status_OperationState'; getState(dp1, (err, state) => { if (!err && state && state.val !== undefined && state.val !== null && state.val !== '') { let id=getState(dp1).val; let tx=getObject(dp1).common.states[id]; setState('0_userdata.0.Waschmaschine.Status',tx); } else { setState('0_userdata.0.Waschmaschine.Status','Aus'); } });
Das kann man jetzt beliebig erweitern, einfach kopieren und z.B. neuen DP in eine const dp2 eintragen, also danke an alle.