NEWS
In einer Funktion auf Änderung eines Datenpunkts warten
-
Hallo zusammen,
ich stehe gerade auf dem Schlauch: Innerhalb einer Funktion, die über on() getriggert wird, nutze ich ein setState(), um einen Aktor zu starten. Als nächstes soll ein Datenpunkt überwacht werden und erst, wenn dieser auf einen bestimmten Wert geht, soll die Funktion weiter abgearbeitet werden. Ist sowas überhaupt möglich?
Das mit dem while() im folgenden Code ist Quatsch, aber vielleicht ist das verständlicher :
function garageDoorOpen() { if(getState(dpGarageDoorState).val == 0 || getState(dpGarageDoorState).val == 2) { setState(dpGarageDoorCommand, 1); setState(dpInstanz + dpGarageDoorStatus, txtGarageDoorOpen); while(getState(dpGarageDoorProcess).val === 1) { // An dieser Stelle soll die Funktion solange warten, // bis "getState(dpGarageDoorProcess).val === 1" ist } setState(dpInstanz + dpGarageDoorStatus, txtGarageDoorIsOpened); setState(dpInstanz + dpGarageDoorOpen, false); } } on ({ id: dpInstanz + dpGarageDoorOpen, change: 'any', val: true }, function () { garageDoorOpen(); });
Viele Grüße
Levy -
@levyko sagte in In einer Funktion auf Änderung eines Datenpunkts warten:
dpGarageDoorProcess
Warum in die Funktion garageDoorOpen?
Pack doch den DP als on()-Trigger und frage den entsprechenden Wert ab und setz dann die anderen Werte. -
warten in einer schleife ist nie gut
aber du hast hier dann 2 trigger- den du schon umgesetzt hast und den
- wenn sich dpGarageDoorProcess (wieder) ändert
da wäre dann der weitere teil deiner Verarbeitung
Darüber hinaus kannst du deinen code optimieren.
wenn der trigger aufgerufen wird, wird der wert ja bereits mitgeliefert, dann musst du den nicht nochmal per getstate abfragen
https://github.com/ioBroker/ioBroker.javascript/blob/master/docs/en/javascript.md#on---subscribe-on-changes-or-updates-of-some-stateich gehe mal davon aus, das du die garage öffnen willst und dann wenn sich das tor zu ende bewegt hat, dann nochmal den richtigen status setzen
dann wären die statusübergänge wie folgt
Closed->Opening->Opened->Closing->Closed -
@levyko
Welche Werte (mit welcher Bedeutung) kann der DPdpGarageDoorState
annehmen? Wahrscheinlich genügt es, diesen DP als weiteren Trigger zu verwenden, etwa so:var doorState = getState(dpGarageDoorState).val; on ({id: dpInstanz + dpGarageDoorOpen, val: true}, function () { if(doorState == 0 || doorState == 2) { setState(dpGarageDoorCommand, 1); setState(dpGarageDoorStatus, txtGarageDoorOpen, true); } }); on(dpGarageDoorState, function(dp) { doorState = dp.state.val; if(doorState == 1) { // is Opened? setState(dpGarageDoorStatus, txtGarageDoorIsOpened, true); setState(dpGarageDoorOpen, false, true); } });
Anmerkung: Wenn
dpInstanz
= 'javascript.N.' ist, kann bei setState(id, val, true) die verkürzte ID verwendet werden. Nur on(pattern, cb) benötigt die vollständige ID. Das Rücksetzen des Taster-DP (Zeile 14) ist normalerweise nicht nötig. -
async function garageDoorOpen() { if(getState(dpGarageDoorState).val == 0 || getState(dpGarageDoorState).val == 2) { setState(dpGarageDoorCommand, 1); setState(dpInstanz + dpGarageDoorStatus, txtGarageDoorOpen); while(getState(dpGarageDoorProcess).val === 1) { await sleep(500) } setState(dpInstanz + dpGarageDoorStatus, txtGarageDoorIsOpened); setState(dpInstanz + dpGarageDoorOpen, false); } }
Ich stimme dem Rest zu, nur weils geht ist es keine gute Idee Was passiert eigentlich wenn du dich umentscheidest?
-
Erst einmal vielen Dank für die Antworten und Denkanstöße. Ich habe es jetzt, wie von Euch vorgeschlagen, mit vier on()'s realisiert. Hier mal das komplette Script:
var dpGarageDoorOpen = '0_userdata.0.Trigger.TriggerGarageDoorOpen'; var dpGarageDoorClose = '0_userdata.0.Trigger.TriggerGarageDoorClose'; var dpGarageDoorStatus = '0_userdata.0.Trigger.TriggerGarageDoorStatus'; var dpGarageDoorState = 'hm-rpc.0.00XXXXXXXXXXF7.1.DOOR_STATE'; var dpGarageDoorCommand = 'hm-rpc.0.00XXXXXXXXXXF7.1.DOOR_COMMAND'; var dpGarageDoorProcess = 'hm-rpc.0.00XXXXXXXXXXF7.1.PROCESS'; on ({ id: dpGarageDoorOpen, change: 'ne', val: true }, function () { if(getState(dpGarageDoorState).val === 0 || getState(dpGarageDoorState).val === 2 || getState(dpGarageDoorState).val === 3) { setState(dpGarageDoorCommand, 1); } else { setState(dpGarageDoorOpen, false); setState(dpGarageDoorClose, false); } }); on ({ id: dpGarageDoorClose, change: 'ne', val: true }, function () { if(getState(dpGarageDoorState).val === 1 || getState(dpGarageDoorState).val === 2 || getState(dpGarageDoorState).val === 3) { setState(dpGarageDoorCommand, 3); } else { setState(dpGarageDoorOpen, false); setState(dpGarageDoorClose, false); } }); on ({ id: dpGarageDoorProcess, change: 'ne' }, function () { if(getState(dpGarageDoorOpen).val == true) { if(getState(dpGarageDoorProcess).val === 1) setState(dpGarageDoorStatus, 'wird geöffnet'); } if(getState(dpGarageDoorClose).val == true) { if(getState(dpGarageDoorProcess).val === 1) setState(dpGarageDoorStatus, 'wird geschlossen'); } }); on ({ id: dpGarageDoorState, change: 'ne' }, function () { if(getState(dpGarageDoorState).val === 0) { setState(dpGarageDoorStatus, 'geschlossen'); setState(dpGarageDoorOpen, false); setState(dpGarageDoorClose, false); toLog('Das Garagentor wurde geschlossen'); } if(getState(dpGarageDoorState).val === 1) { setState(dpGarageDoorStatus, 'offen'); setState(dpGarageDoorOpen, false); setState(dpGarageDoorClose, false); toLog('Das Garagentor wurde geöffnet'); } });
Da kann ich sicherlich noch einiges optimieren, aber so läuft es jetzt ersteinmal. Rein muss für den normalen Betrieb noch die Abfrage nach Blockade und Drücken von Stop.
Hintergrund ist, dass bisher für VIS einfach direkt auf die Datenpunkte des HmIP-MOD-HO gegangen bin. Das funktionierte soweit auch. Nun wird die Garage aber als separate Zone in unsere Alarmanlage integriert und ich muss ein "versehentliches" Öffnen durch VIS bei Scharfschaltung verhindern. Das kann ich über das Script alles abfangen. Zusätzlich kann ich nun über Alexa vom Auto aus (nennt sich bei Audi "integrated Alexa" oder so) das Tor auf- und zufahren. Daher die beiden Trigger-Datenpunkte.
Viele Grüße
Levy -
@levyko sagte: Da kann ich sicherlich noch einiges optimieren
Allerdings.
const dpGarageDoorOpen = '0_userdata.0.Trigger.TriggerGarageDoorOpen'; const dpGarageDoorClose = '0_userdata.0.Trigger.TriggerGarageDoorClose'; const dpGarageDoorStatus = '0_userdata.0.Trigger.TriggerGarageDoorStatus'; const dpGarageDoorState = 'hm-rpc.0.00XXXXXXXXXXF7.1.DOOR_STATE'; const dpGarageDoorCommand = 'hm-rpc.0.00XXXXXXXXXXF7.1.DOOR_COMMAND'; // var dpGarageDoorProcess = 'hm-rpc.0.00XXXXXXXXXXF7.1.PROCESS'; var doorState = getState(dpGarageDoorState).val; on ({id: dpGarageDoorOpen, change: 'ne', val: true}, function () { if(doorState != 1) { setState(dpGarageDoorCommand, 1); setState(dpGarageDoorStatus, 'wird geöffnet', true); } setState(dpGarageDoorOpen, false, true); }); on ({id: dpGarageDoorClose, change: 'ne', val: true }, function () { if(doorState > 0) { setState(dpGarageDoorCommand, 3); setState(dpGarageDoorStatus, 'wird geschlossen', true); } setState(dpGarageDoorClose, false, true); }); on (dpGarageDoorState, function (dp) { // triggert bei Wertänderung doorState = dp.state.val; let msg = ''; if(doorState === 0) { msg = 'geschlossen'; } else if(doorState === 1) { msg = 'offen'; } if(msg) { setState(dpGarageDoorStatus, msg, true); log('Das Garagentor ist ' + msg); } });
Ist toLog() eine globale Funktion?
-
@paul53
Danke für die Überarbeitung. Das sieht doch wesentlich kompakter ausJa, toLog() ist eine globale Funktion, die mir eine Aktivitätsliste füllt und gleichzeitig einen Log-Eintrag erstellt.
Da neben der Steuerung des Tors in dem eigentlichen Script noch die Regelung eines Lüfters drin ist, hier mal der aktuelle Stand des gesamten Scripts:
/* ** ** Steuerung Garage ** */ var cronVal = '*/15 * * * *'; var numMinDuration = 30; var dpAussenTemperatur = 'hm-rpc.0.00XXXXXXXXXXEF.1.ACTUAL_TEMPERATURE'; var dpAussenFeuchtigkeit = 'hm-rpc.0.00XXXXXXXXXXEF.1.HUMIDITY'; var dpGarageFeuchtigkeit = 'hm-rpc.0.00XXXXXXXXXX5F.1.HUMIDITY'; var dpGarageLuefter = 'hm-rpc.0.00XXXXXXXXXX9D.3.STATE'; const dpGarageDoorOpen = '0_userdata.0.Trigger.TriggerGarageDoorOpen'; const dpGarageDoorClose = '0_userdata.0.Trigger.TriggerGarageDoorClose'; const dpGarageDoorStatus = '0_userdata.0.Trigger.TriggerGarageDoorStatus'; const dpGarageDoorState = 'hm-rpc.0.00XXXXXXXXXXF7.1.DOOR_STATE'; const dpGarageDoorCommand = 'hm-rpc.0.00XXXXXXXXXXF7.1.DOOR_COMMAND'; var doorState = getState(dpGarageDoorState).val; /* ** Create Datapoints */ createState(dpGarageDoorOpen, false, { name: 'TriggerGarageDoorOpen', desc: 'TriggerGarageDoorOpen', type: 'boolean', role: 'state' }); createState(dpGarageDoorClose, false, { name: 'TriggerGarageDoorClose', desc: 'TriggerGarageDoorClose', type: 'boolean', role: 'state' }); createState(dpGarageDoorStatus, '-', { name: 'TriggerGarageDoorStatus', desc: 'TriggerGarageDoorStatus', type: 'string', role: 'value' }); /* ** Subscriptions */ schedule(cronVal, function() { if(getState(dpGarageLuefter).val === false) { if(getState(dpGarageFeuchtigkeit).val > getState(dpAussenFeuchtigkeit).val) { if(getState(dpAussenTemperatur).val > 5) { if(getState(dpAussenTemperatur).val < 20) { var numMilSecsDur = numMinDuration * 60000; var endTime = Date.now() + numMilSecsDur; setState(dpGarageLuefter, true); toLog('Garagenbelüftung eingeschaltet (Dauer: ' + numMinDuration + ' - Lf: ' + getState(dpGarageFeuchtigkeit).val + '%)'); var sHandler = schedule(endTime, function () { setState(dpGarageLuefter, false); toLog('Garagenbelüftung ausgeschaltet (Lf: ' + getState(dpGarageFeuchtigkeit).val + '%)'); clearSchedule(sHandler); }); } } } } }); on ({id: dpGarageDoorOpen, change: 'ne', val: true}, function () { if(doorState != 1) { setState(dpGarageDoorCommand, 1); setState(dpGarageDoorStatus, 'wird geöffnet', true); } setState(dpGarageDoorOpen, false, true); }); on ({id: dpGarageDoorClose, change: 'ne', val: true }, function () { if(doorState > 0) { setState(dpGarageDoorCommand, 3); setState(dpGarageDoorStatus, 'wird geschlossen', true); } setState(dpGarageDoorClose, false, true); }); on (dpGarageDoorState, function (dp) { doorState = dp.state.val; let msg = ''; if(doorState === 0) { msg = 'geschlossen'; } else if(doorState === 1) { msg = 'offen'; } if(msg) { setState(dpGarageDoorStatus, msg, true); toLog('Das Garagentor ist ' + msg); } });
Vielleicht kann der eine oder andere davon etwas gebrauchen.
Viele Grüße
Levy