Hello Flytrapp,
yah thats possible, here is a Script for this:
Code
//Config __There is a Maximum of 5 Channels/Devices__
var debug= false; //Create Debug output
var configON= { //Device Name and Channel als Key --> 'switch:0', Value als Shelly.Call Array.
called: [], //Called Variabel to reduce useless Calls
powerLimit: 2, //Limit in Watt, power needs to be > Limit for sending a Call
powerTime: 1, //Time in seconds, how long the power needs to be over the powerLimit, before sending a call
'switch:0': ['HTTP.GET',{url:'http://192.168.178.100/relay/0/?turn=on'},null,null,debug],
}
var configOFF= { //Device Name and Channel als Key --> 'switch:0', Value als Shelly.Call Array.
called: [], //Called Variabel to reduce useless Calls
powerLimit: 2, //Limit in Watt, power needs to be <= Limit for sending a Call
powerTime: 1, //Time in seconds, how long the power needs to be over the powerLimit, before sending a call
'switch:0': ['HTTP.GET',{url:'http://192.168.178.100/relay/0/?turn=off'},null,null,debug],
}
var tHandel= []; //global Variabl
function Clear_Timer(id){
Timer.clear(tHandel[id]); //Reset Timer
tHandel[id]= 0;
return id;
}
function DoCall(device,id,map){ //Do call
try{
map.called[id]= true;
tHandel[id]= 0; //Reset Timer Handel
Call(map[device][0],map[device][1],map[device][2],map[device][3],map[device][4]);
}catch(e){ErrorMsg(e,'DoCall()');}
}
function CheckPower(d){
try{
let r= Efilter(d,{device:Object.keys(configON), filterKey:['apower','id','component','state']},0); //Filter event data
if(r && r.state === false){ //Switch off if switch is off
configON.called[r.id]= false;
r.id= Clear_Timer(r.id);
tHandel[r.id]= Timer.set(1000*configOFF.powerTime,false,function(){DoCall(r.component, r.id, configOFF)}); //Delayed Call
}
if(!r || !Str(r.apower)) return; //Exit if usless data
if(r.apower > configON.powerLimit && !configON.called[r.id]){ //Check if over Powerlimit
configOFF.called[r.id]= false;
r.id= Clear_Timer(r.id);
tHandel[r.id]= Timer.set(1000*configON.powerTime,false,function(){DoCall(r.component, r.id, configON)}); //Delayed Call
}
if(r.apower <= configOFF.powerLimit && !configOFF.called[r.id]){ //Check if under Powerlimit
configON.called[r.id]= false;
r.id= Clear_Timer(r.id);
tHandel[r.id]= Timer.set(1000*configOFF.powerTime,false,function(){DoCall(r.component, r.id, configOFF)}); //Delayed Call
}
if(debug) print('Debug: found Event\n',r,'\nDebug:',r.component,'Timer activ:',tHandel[r.id]>0,'\nDebug: called ON:',configON.called[r.id],', OFF:',configOFF.called[r.id]); //Debug output
}catch(e){ErrorMsg(e,'CheckPower()');}
}
function Main(){ //Main Code
try{
let fakeEvents= {};
for(e in configON){ //Create Fake Power Event for Restart
if(Cut(e,':')){
let deviceType= Cut(e,':',0,true); //Getting Device Type
let channelID= Number(Cut(e,':',':')) //Getting Channel ID
fakeEvents[e]= {info: {}}; //Create fake power Event
fakeEvents[e].info.component= e;
fakeEvents[e].info.id= channelID;
fakeEvents[e].info.apower= Status(deviceType,channelID).apower;
}
}
for(e of fakeEvents){
CheckPower(e); //Send fake Power Event
}
}catch(e){ErrorMsg(e,'Creating Fake Power Event');}
fakeEvents= 0; //Delete useless Data
Shelly.addEventHandler(CheckPower); //Add EventHandler with Asyn CallBack
}
// Dekats Toolbox, a universal Toolbox for Shelly scripts
function Efilter(d,p,deBug) { //Event Filter, d=eventdata, p={device:[], filterKey:[], filterValue:[], noInfo:true, inData:true}->optional_parameter
try{
let fR= {};
if(p.noInfo){fR= d; d= {}; d.info= fR; fR= {};} if(p.inData && d.info.data){d.info= d.info.data; delete d.info.data;}
if(!d.info) fR.useless= true; if(p.device && p.device.length > 0 && p.device.indexOf(d.info.component) === -1) fR.useless= true;
if(p.device && p.device.length > 0 && !fR.useless && !p.filterKey && !p.filterValue) fR= d.info;
if(p.filterKey && !fR.useless) for(f of p.filterKey) for(k in d.info) if(f === k) fR[k]= d.info[k];
if(p.filterValue && !fR.useless) for(f of p.filterValue) for(v of d.info) if(Str(v) && f === v) fR[Str(v)]= v;
if(deBug) print('\nDebug: EventData-> ', d, '\n\nDebug: Result-> ', fR, '\n');
if(Str(fR) === '{}' || fR.useless){return;} return fR;}catch(e){ErrorMsg(e,'Efilter()');}}
function ErrorChk(r,e,m,d){ //Shelly.call error check
try{
aC--; if(aC<0) aC= 0;
if(d.CB && d.uD) d.CB(r,d.uD); if(d.CB && !d.uD) d.CB(r);
if(!d.CB && d.uD) print('Debug: ',d.uD); if(e) throw new Error(Str(m));
if(Str(r) && Str(r.code) && r.code !== 200) throw new Error(Str(r));
}catch(e){ErrorMsg(e,'ErrorChk(), call Answer');}}
function Cqueue(){ //Shelly.call queue
try{
if(!cCache[0] && !nCall[0]) return; if(!nCall[0]){nCall= cCache[0]; cCache.splice(0,1);}
if(nCall[0] && aC < callLimit){Call(nCall[0],nCall[1],nCall[2],nCall[3],nCall[4]); nCall= [];}
if((nCall[0] || cCache[0]) && !tH7) tH7= Timer.set(1000*cSp,0,function(){tH7= 0; Cqueue();});}catch(e){ErrorMsg(e,'Cqueue()');}}
function Call(m,p,CB,uD,deBug){ //Upgrade Shelly.call
try{
let d= {};
if(deBug) print('Debug: calling:',m,p); if(CB) d.CB= CB; if(Str(uD)) d.uD= uD; if(!m && CB){CB(uD); return;}
if(aC < callLimit){aC++; Shelly.call(m,p,ErrorChk,d);}else if(cCache.length < cacheLimit){
cCache.push([m,p,CB,uD,deBug]); if(deBug) print('Debug: save call:',m,p,', call queue now:',cCache.length); Cqueue();
}else{throw new Error('to many Calls in use, droping call: '+Str(m)+', '+Str(p));}}catch(e){ErrorMsg(e,'Call()');}}
function Str(d){ //Upgrade JSON.stringify
try{
if(d === null || d === undefined) return null; if(typeof d === 'string')return d;
return JSON.stringify(d);}catch(e){ErrorMsg(e,'Str()');}}
function Cut(f,k,o,i){ //Upgrade slice f=fullData, k=key-> where to cut, o=offset->offset behind key, i=invertCut
try{
let s= f.indexOf(k); if(s === -1) return; if(o) s= s+o.length || s+o; if(i) return f.slice(0,s);
return f.slice(s);}catch(e){ErrorMsg(e,'Cut()');}}
function Setup(l){ //Wating 2sek, to avoid a Shelly FW Bug
try{
if(Main && !tH9){tH9= Timer.set(2000,l,function(){print('\nStatus: started Script _[', scriptN,']_');
if(callLimit > 5){callLimit= 5;} try{Main();}catch(e){ErrorMsg(e,'Main()'); Setup();}});}}catch(e){ErrorMsg(e,'Setup()');}}
function ErrorMsg(e,s){ //Toolbox formatted Error Msg
try{
let i= 0; if(Cut(e.message, '-104: Timed out')) i= 'wrong URL or device may be offline';
if(s === 'Main()') i= e.stack; if(Cut(e.message, '"Main" is not')) i= 'define a Main() function before using Setup()';
print('Error:',s || "",'---> ',e.type,e.message); if(i) print('Info: maybe -->',i);}catch(e){print('Error: ErrorMsg() --->',e);}}
var tH7= 0, tH8= 0, tH9= 0, aC= 0, cCache= [], nCall= [], callLimit= 4, cacheLimit= 40, cSp= 0.2; //Toolbox global variable
var Status= Shelly.getComponentStatus, Config= Shelly.getComponentConfig; //Renamed native function
var info= Shelly.getDeviceInfo(), scriptID= Shelly.getCurrentScriptId(), scriptN= Config('script',scriptID).name; //Pseudo const, variabel
//Toolbox v2.5-Alpha(cut), Shelly FW >1.0.8
Setup();
Alles anzeigen
Preview:
shelly-support.eu/attachment/48692/
Instructions (only in German sry)
shelly-support.eu/forum/thread/23654/More Infos about Shelly.Call():