@66er
Auto Off gelingt afaik nur per Sekunden-Auflösung und nicht per Millisekunden.
Ich nehme gerne wieder mal etwas ...
VPN/Proxy erkannt
Es scheint, dass Sie einen VPN- oder Proxy-Dienst verwenden. Bitte beachten Sie, dass die Nutzung eines solchen Dienstes die Funktionalität dieser Webseite einschränken kann.
@66er
Auto Off gelingt afaik nur per Sekunden-Auflösung und nicht per Millisekunden.
Ich nehme gerne wieder mal etwas ...
Szenen sind mir nur per Cloud bekannt.
Mit einem Shelly der zweiten Generation und Skriptfähigkeit gelingt so etwas locker.
Über Messwerte kann ich mangels solchem Gerätes leider nichts sagen.
Dann beschreibe bitte mal möglichst genau, was du damit tun willst!
Soll die Einschaltdauer parametrierbar sein?
...
Ich kenne insbesondere die Zeitpläne (= Schedule Jobs) von Shelly der zweiten Generation - mit dem Plus im Namen.
Diese Schedule Jobs arbeiten nach meinen Erfahrungen sehr verlässlich und sie sind sehr flexibel nutzbar.
Zu Zeitplänen der ersten Generation kann ich derzeit leider wenig mitteilen.
Wenn dir diese Funktionalität wichtig ist, könntest du über einen Wechsel zu einem Plus 1 PM nachdenken.
Ich besitze keinen solchen Shelly.
Die Fehlermeldung ist sehr allgemein formuliert.
Hast du mal versucht, das Protokoll zu löschen?
Eine andere Ursache könnten (theoretisch) zu dicht aufeinanderfolgende Ereignisse sein.
Was muss oder kann ich ändern?
Auf bessere Firmware warten
Vielleicht sind die Schwankungen in erster Linie auf das Relais zurückzuführen.
Hast du das Gleiche mal mit einem SSR geprüft?
Damit sollte auch das Prellen entfallen.
Das sind 500ms bis 2000ms und gelingt per Timer in einem Skript. Somit gelingt dies mit skriptfähigen Shelly.
Ein sog. HTTP Endpoint ist ein Name, welcher einer Funktion zugeordnet ist.
Aufruf: http://<IP Adresse des Schalt-Shelly>/script/<Skript Id>/<selbst gewählter Name>?<optionale Parameterliste>
Bsp: http://<IP Adresse des Schalt-Shelly>/script/1/ein?700
Der Skriptcode:
function send_response(response, body) {
response.code = 200;
response.body = body;
response.send();
}
HTTPServer.registerEndpoint('ein',
function (request, response) {
send_response(response, "OK");
let dur = 0;
if(request.query.length > 0) dur = JSON.parse(request.query);
if(!isNaN(dur) && dur>=500) {
if(dur>2000) dur = 2000;
Shelly.call("Switch.Set", {id:0, on:true});
Timer.set(Math.floor(dur), false, function() {Shelly.call("Switch.Set", {id:0, on:false});}
}
}
);
Alles anzeigen
Du kannst vermutlich erkennen, dass die Dauer parametrierbar ist und evtl. dass die Dauer auf 2s begrenzt ist.
Nachgereicht:
Ich habe die Dauer auch nach unten, zu kleineren Werten, begrenzt.
Ich habe das über Action gelöst.
Was hast du über solche Actions gelöst?
Hast du den Thread gelesen?
Hier ist erheblich mehr gewünscht als das, was du per Actions lösen könntest.
Mit diesen URL wird das Gewünschte jedenfalls (noch) nicht gelingen.
Wenn solches gelesen und nicht geprüft wird, stellen sich völlig falsche Vorstellungen ein.
Ich lasse mich gerne überraschen.
Das Skript sollte so arbeiten und tut dies bei mir auch.
Wenn der Motion das Licht einschalten lässt und während der Einschaltdauer die zugeordnete Taste am i4 gedrückt wird, wird der Timer zum ausschalten gelöscht.
Damit bleibt das Licht solange an, bis es von einem nicht Motion Gerät, also bspw. dem i4 per Taste, ausgeschaltet wird.
Überprüfe das Bitte!
Das gelingt selbstverständlich nur dann, wenn der URL stimmt und die Taste gedrückt wird, die diesem URL zugeordnet ist (Action ...).
Falls dies nicht gelingen sollte, experimentiere bitte mit den Einstellung am Eingang des i4 zu dieser Taste!
egal ob Bewegung erkannt wird
Das könnte an den Einstellungen am Motion liegen. Wenn im Skript Retrigger auf true steht, dann muss mit jeder Nachricht vom Motion die Einschaltdauer von vorne beginnen, weil dann der Timer neu gestartet wird.
ich habe eure Geduld genug strapaziert
Nein! Ich bin davon überzeugt, dass alles genau so funktioniert, wie ich es beschrieb und dies afaik von dir gewünscht ist.
Ich gebe nicht eher Ruhe, bis es gelingt.
... ähm ... oder es dich zu sehr nervt.
Es ließ mir keine Ruhe. Hier die verbesserte Version des Skripts.
Was habe ich verbessert?
Was bleibt wie es war?
Der Action URL in den Bewegungsmeldern, also nicht ändern! Endpoint Name lautet "on".
http://<IP Adresse des Schalt-Shelly>/script/<Skript Id>/on?<Dauer in Sekunden>
Was muss geändert werden?
Der Action URL in den Geräten, die remote umschalten, also ändern! Endpoint Name lautet "toggle".
http://<IP Adresse des Schalt-Shelly>/script/<Skript Id>/toggle
Beide Informationen werden bei Skriptstart im Protokollfenster mit aktuellen Werten ausgegeben.
// Created by Gerhard Eichelsdörfer alias eiche - 2024-03-13
let Retrigger = true, // Set to false if you don't want the motion to retrigger!
MotionName = "motion",
RemoteName = "remote",
out = 0, // output id
on = null, // output status
th = null, // timer handle
src = null; // source of switching
function send_response(response, body) {
response.code = 200;
response.body = body;
response.send();
}
function switchSet(id, state) {
Shelly.call("Switch.set", {id:id, on:state},
function(result, errcode, errmsg, ud) {
if(errcode!==0) print("error in switchSet(" + ud.id + ", " + ud.state + "): ", errcode, ", ", errmsg);
}, {id:id, state:state}
);
}
function startTimer(dur) {
Timer.clear(th);
if(dur>0) {
dur = Math.floor(1000*dur);
th = Timer.set(dur, false, function () {switchSet(out, false);});
print("Timer started for " + (dur/1000) +" seconds");
}
}
// from a remote motion sensor - with a duration value
HTTPServer.registerEndpoint('on',
function (request, response) {
send_response(response, "OK");
let dur = 0;
if(request.query.length > 0) dur = JSON.parse(request.query);
if(!isNaN(dur) && dur>0 && (!on || (Retrigger && src===MotionName))) startTimer(dur);
if(!on) {
src = MotionName;
switchSet(out, true);
}
}
);
// from a remote toggle call, e.g. from an i4.
HTTPServer.registerEndpoint('toggle',
function (request, response) {
send_response(response, "OK");
let tmp = src;
src = RemoteName;
let st = Shelly.getComponentStatus("switch:" + out);
if(st.output && tmp===MotionName) {
Timer.clear(th);
print("source: ", src, ", Timer cleared")
return;
}
Shelly.call("Switch.Toggle", {id:out},
function (result, errcode, errmsg, ud) {
if(errcode!==0) {
src = ud.src;
print(ud.msg, errcode, ", ", errmsg);
}
}, {src:tmp, msg:"error in remote toggle: "}
);
}
);
Shelly.addEventHandler(function(e) {
//print(JSON.stringify(e));
if(e.info.event==="toggle") {
on = e.info.state;
let st = Shelly.getComponentStatus("switch:" + out);
if(st.source!==undefined && st.source!=="loopback") src = st.source;
print("source: ", src, ", status: ", on ? "on" : "off");
}
});
//Do some user friendly printout
function messages() {
let ipAddress = Shelly.getComponentStatus("wifi").sta_ip;
if(ipAddress===null) ipAddress = '<IP address of your switching Shelly>';
let myId = Shelly.getCurrentScriptId();
print('The action URL of your motion is: http://' + ipAddress + '/script/' + myId + '/on?<duration in seconds>');
print('When switching via remote command, e.g. Shelly i4, the URL for the remote action is:');
print('http://' + ipAddress + '/script/' + myId + '/toggle');
}
messages();
let info = Shelly.getComponentStatus("switch:" + out);
//print(JSON.stringify(info));
src = info.source;
on = info.output;
Alles anzeigen
Das gleiche Skript mit der nach ostfriese kleiner Änderung für die anwenderfreundliche Ausgabe nach Skriptstart.
Dafür ist nichts an den anderen Geräten zu ändern.
// Created by Gerhard Eichelsdörfer alias eiche - 2024-03-13
let Retrigger = true, // Set to false if you don't want the motion to retrigger!
MotionName = "motion",
RemoteName = "remote",
on = null, // output status
th = null, // timer handle
src = null; // source of switching
function send_response(response, body) {
response.code = 200;
response.body = body;
response.send();
}
function switchSet(state) {
Shelly.call("Switch.set", {id:0, on:state},
function(result, errcode, errmsg) {
let msg = "switchSet(" + state + "): ";
if(errcode!==0) msg += "error " + errcode + ", " + errmsg;
else msg += state ? "is on" : "is off";
print(msg);
}
);
}
function startTimer(dur) {
Timer.clear(th);
if(dur>0) th = Timer.set(Math.floor(1000*dur), false, function () {switchSet(false);});
}
HTTPServer.registerEndpoint('on',
function (request, response) {
send_response(response, "OK");
let dur = 0;
if(request.query.length > 0) dur = JSON.parse(request.query);
if(!on) src = MotionName;
if(!isNaN(dur) && dur>0 && (!on || (Retrigger && src===MotionName))) startTimer(dur);
if(!on) {
src = MotionName;
switchSet(true);
}
}
);
Shelly.addEventHandler(function(e) {
//print(JSON.stringify(e));
if(e.info.event==="toggle") {
on = e.info.state;
let st = Shelly.getComponentStatus("switch:0");
//print(JSON.stringify(st));
if(st.source!=="loopback") src = st.source;
if (e.component==="input:0" || st.source==="button" || st.source==="WS_in" || st.source==="SHC" || src===RemoteName) {
print("source: ", src);
Timer.clear(th);
}
}
});
// from a remote toggle call, e.g. from an i4.
function remoteButton() {
let err = "error in remoteButton:";
let st = Shelly.getComponentStatus("switch:0");
if(!st.output || src===MotionName) Shelly.call("Switch.Set", {id:0, on:true},
function (result, errcode, errmsg, err) {
if(errcode!==0) print(err, errcode, ", ", errmsg);
else src = RemoteName;
}, err
);
else Shelly.call("Switch.Toggle", {id:0},
function (result, errcode, errmsg, err) {
if(errcode!==0) print(err, errcode, ", ", errmsg);
else src = RemoteName;
}, err
);
}
//Do some user friendly printout
function messages() {
let ipAddress = Shelly.getComponentStatus("wifi").sta_ip;
if(ipAddress===null) ipAddress = '<IP address of your switching Shelly>';
let myId = Shelly.getCurrentScriptId();
print('The action URL of your motion is: http://' + ipAddress + '/script/' + myId + '/on?<duration in seconds>');
print('When switching via remote command, e.g. Shelly i4, the URL for the remote action is:');
print('http://' + ipAddress + '/rpc/script.eval?id=' + myId + '&code="remoteButton()"');
}
messages();
let info = Shelly.getComponentStatus("switch:0");
//print(JSON.stringify(info));
src = info.source;
on = info.output;
Alles anzeigen
Neue Erkenntnis meinerseits.
Nach Tests mit der Firmware 1.2.3 stellte ich fest, dass diese offensichtlich nach Erhalt der IP Adresse per DHCP diese Adresse nicht im nichtflüchtigen Konfigurationsspeicher ablegt.
Somit findet man bei DHCP in der Antwort auf Methode Shelly.GetConfig keine IP Adresse, d.h. dass dort null steht.
Ob dies auch in älteren Firmwareversionen so ist, kann ich derzeit nicht prüfen.
Vielleicht werde ich gelegentlich das Skript so ändern, dass ein fehlerhafter URL das Skript nicht abbricht.
Dazu muss ich statt der RPC Methode Script.Eval einen HTTP Endpoint verwenden, wie ich seit gerade eben feststellen konnte.
Für die Motions habe ich im Skript einen solchen Endpoint verwendet.
Der Unterschied:
Methode Script.Eval: http://<IP Zieladresse>/rpc/script.eval?id=<script id>&code="<Funktionsaufruf>"
HTTP Endpoint: http://<IP Zieladresse>/script/<script id>/<Endpointname> ...
Wenn es mich packt, könnte ich das Skript entsprechend anpassen. Dann würde das Skript bei nicht existentem Endpointnamen selbstverständlich nicht reagieren aber auch nicht abgebrochen werden.
Vielleicht wird ein Skript bei falschem Script.Eval Funktionsaufruf in einer späteren Firmware-Version nicht mehr abgebrochen - in Version 5.9.x vielleicht.
Es liegt nicht am WLAN sondern an der Firmware 1.2.3 oder (einschließend) am DHCP.
Sorry, ich vergaß mitzuteilen, dass die alten URL nicht mehr passen. Du musst somit in allen hier beteiligten Geräten, bis auf Motions, den URL ändern.
Er lautet jetzt am Ende ...&code="remoteButton()".
Ich weiß derzeit nicht, wie ich einen solchen von extern verursachten Fehler (falscher URL) per Ausnahmebehandlung auffangen könnte. Vielleicht wäre dies mit dem Framework von @De kat möglich. Damit beschäftige ich mich aber jetzt nicht auch noch.
Um die Wirkung eines solchen Fehlers deutlich zu verringern, kann man einen Schedule Job (Zeitplan) anlegen, der das Skript alle 5 Minuten (oder so) startet. Das gelingt aber nur per URL und nicht per Web UI, App oder Cloud.
Zu deiner off topic Frage:
würde mich interessieren wofür du sie überall einsetzt beim WoMo
Ich setze bisher im WoMo keinen einzigen Shelly ein. Den zusätzlichen Verbrauch scheue ich.
Meine 12V Versorgung inkl. Gleichspannungswandler für
können wir per "Cockpit" Schalterchen inkl. Dioden-Logik und starken Solid State Relais ein- und ausschalten. Somit wird fast kein Strömchen für diese Geräte im ausgeschalteten Zustand verbraucht.
Nur eine Stelle kann mich für den Einsatz eines Shelly + 12V Magnetventil NC reizen: Öffnen und Schließen des Grauwasserabflusses.
Vermutlich lasse ich aber auch das sein.
Aber einen kleinen Ama... Echo Input mit kleinem externen Bluetooth fähigen Lautsprecher führe ich mit und setze diesen gelegentlich zum hören von interessanten Radio-Programmen ein (fast ausschließlich WDR 5, die meisten anderen Programme sind imho großer Mist). Manchmal lasse ich darüber remote auch eine Lampe zu Hause schalten.