shelly-EM / openDTU power smoocher: act_power+epex -> js script -> websocket

Version 0.51 seit 1 Tag aktiv.

//                           shelly meter script power smooch for openDTU oB.
//  smoothes power signal, modifies via signals from epex script, line status
//     openDTU oB setup: http+json, interval 1s, http://< addr >/script/2/dtu
var a=0,b=0;                                                      // pointers
var sp=28.0;                                // send power. preset for startup
const pl=500.0                                        // inverter power limit
var s0=Shelly.getComponentStatus("switch",0);//array for switch 0 = min price
//var s1=Shelly.getComponentStatus("switch",1);//array for switch 1 = max pri
var s1=Shelly.getComponentStatus("switch",100);//array for switch 100 = max p
//var s1=Shelly.getComponentStatus("boolean",200);//array for switch 200 = ma
var ev=Shelly.getComponentStatus("EM1",0);              // array for response
var ip=[];                                             // array for act_power
var up=160.0;                           // max. act_power increase into array
var dp=-80.0;                           // max. act_power decrease into array
const ip_sz=5;                                               // size of array
const tick_sz=495;                                         // timer tick (ms)
var TickHandle;
var tock=false;
for (b=0;b<ip_sz;b++){ip.push(sp)};             // preset array of size ip_sz
function Tick(){
 ev=Shelly.getComponentStatus("EM1",0);              // get shelly power ch 0
 b++;                                    // b is pointer into smoothing array
 if(b>=ip_sz||b<0){b=0};                                // ip_sz ticks passed
 ip[b]=((0.98*ev.act_power)-(0.11*ev.aprt_power));//store real power in array
// s1=Shelly.getComponentStatus("switch",1);              // max price switch
 s1=Shelly.getComponentStatus("switch",100);              // max price switch
// s1=Shelly.getComponentStatus("boolean",200);           // max price switch
 if(s1){if (s1.output===true){ip[b]=up}};  // if max price true: inverter max
// if(s1){if (s1.value===true){ip[b]=100}};// if max price true: inverter max
 s0=Shelly.getComponentStatus("switch",0);  // get min price switch(spotelly)
 if(s0){if (s0.output===true){ip[b]=dp}};  // if min price true: inverter off
 if(ev.freq<49.9){ip[b]=up};   // freq < min: inverter max to smoothing array
 if(ev.freq>50.1){ip[b]=dp};   // freq > max: inverter off to smoothing array
 if(ev.voltage<212){ip[b]+=50};        // local voltage low: inverter ramp up
 if(ev.voltage>248){ip[b]-=50};     // local voltage high: inverter ramp down
 if(ip[b]>pl){ip[b]=pl}else if(ip[b]>up){ip[b]=up};       // rise/fall limits
 if(ip[b]<(-pl/2)){ip[b]=(-pl/2)}else if(ip[b]<dp){ip[b]=dp};// rise/fall limits
 sp=0;                                                    // clear send power
 for (a=0;a<(ip_sz);a++){sp+=ip[a]};          // add all power array elements
 sp=((sp/(ip_sz)));                                      // resize send power
 if(ev.freq<49.9){sp=2000};           // freq < min: inverter max immediately
 if(ev.freq>50.1){sp=-2000}};         // freq > max: inverter off immediately
function startTimer(){TickHandle=Timer.set(tick_sz,true,Tick)};
startTimer();
function ps(req,res){                           // THIS IS WEBSOCKET ENDPOINT
 sp=(Math.round(sp*10)/10);                          // prepare outgoing data
 tock=!tock;
 if(tock){Shelly.call("Number.Set",{"id":200,"value":sp})};
 ev.act_power=sp;                                    // prepare outgoing data
 ev.id=2;
 res.code=200;
 res.body=JSON.stringify(ev);
 res.headers=[["Content-Type","application/json"],["X-Device-Id",Shelly.getDeviceInfo().id]];
 res.send()};
HTTPServer.registerEndpoint("dtu",ps);

Wesentliche Änderung ist Sprungantwort: Taktende Verbraucher wie Kochplatte werden jetzt schneller nachgeregelt. Das findet sich in diesen Zeilen, in pl wird die Leistung des Inverters eingetragen

const pl=500.0                                        // inverter power limit
(...)
if(ip[b]>pl){ip[b]=pl}else if(ip[b]>up){ip[b]=up};       // rise/fall limits
if(ip[b]<(-pl/2)){ip[b]=(-pl/2)}else if(ip[b]<dp){ip[b]=dp};// rise/fall limits

Die gestern von mir aufgespielte aktuelle Version der openDTU oB hat bei mir ein etwas anderes Regelverhalten. Leichte Oszillation der Leistung, daher smoothing array auf 5 Elemente geändert und timer tick auf 495ms.