Nun noch die hoffentlich
letzte Version des Skripts.
Vorweg die Anleitung
Action URLs auf dem Motion: Keine anderen als die aufgelisteten!
- http://<IP Zieladresse>/script/<Skript Id>/on?<Dauer in Sekunden>
Schaltet für die Dauer ein, wenn ausgeschaltet ist - für "Motion detected" geeignet. - http://<IP Zieladresse>/script/<Skript Id>/on
Schaltet dauerhaft ein, wenn ausgeschaltet ist - für "Motion detected" geeignet. - http://<IP Zieladresse>/script/<Skript Id>/off
Schaltet aus, wenn per Motion, d.h. per "on" (s.o.), eingeschaltet wurde - für "End of motion detected" geeignet.
Action URL auf einem remote Button, bspw. Shelly i4 oder Shelly Button 1: Kein anderer URL!
http://<IP Zieladresse>/script/<Skript Id>/toggle
Verhalten des Skripts, wenn obige Anleitung befolgt wird
Das automatische Ausschalten per Timer oder per "off" erfolgt ausschließlich, wenn per "on" (Motion-Anwendung) eingeschaltet wurde.
Schaltet man per "toggle" (Button) ein, während bereits per "on" (Motion) eingeschaltet war, bleibt die Lampe an, auch wenn der Motion ein "off" sendet.
Letzteres gilt bei jeder Quelle, die nicht per "on" einschaltet - also auch per angeschlossenem Schalter, wenn der Eingang als Schalter konfiguriert ist.
Ein angeschlossener Button kann entweder nur umschalten (ein->aus, aus->ein) oder er muss als detached eingestellt werden und per Action obigen URL mit "toggle" nutzen.
Die Bezeichnungen "on", "off" und "toggle" sind historisch aus der Weiterentwicklung entstanden. Insbesondere "toggle" ist hier nicht in jedem Fall wörtlich zu nehmen.
Ich bin zuversichtlich, dass ich damit alle möglichen Kombinationen berücksichtigt habe.
Das Skript
// Created by Gerhard Eichelsdörfer alias eiche - 2024-03-14
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 an optional duration value
HTTPServer.registerEndpoint('on',
function (request, response) {
send_response(response, "OK");
let para = 0;
if(request.query.length > 0) para = JSON.parse(request.query);
if(!isNaN(para) && para>0 && (!on || (Retrigger && src===MotionName))) startTimer(para);
if(!on) {
src = MotionName;
switchSet(out, true);
}
}
);
// from a remote motion sensor - e.g. at the end of motion detected
HTTPServer.registerEndpoint('off',
function (request, response) {
send_response(response, "OK");
if(on && src===MotionName) switchSet(out, false);
}
);
// 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 with an optional duration is:');
print('http://' + ipAddress + '/script/' + myId + '/on?<duration in seconds>');
print('For switching off via motion the action URL is:');
print('http://' + ipAddress + '/script/' + myId + '/off');
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