Heute habe ich versucht,
eine schnelle Warteschlange für den Shelly.call() zu erstellen. Dabei bin ich zufällig auf den MQTT Overflow-Bug gestoßen.
Mein Skript hat sich auch als Shelly-Benchmark erwiesen, abhängig von den Einstellungen können Out-of-Memory-Fehler, MQTT0 Queue-Overflow-Fehler oder sogar ein Shelly-Absturz verursacht werden.
In der Konfiguration 20,4,50 treten viele MQTT0 Queue-Overflow-Fehlermeldungen auf, obwohl ich im Skript keine einzige MQTT-Funktion verwende. Wahrscheinlich überlastet diese Konfiguration den Prozessor und beeinträchtigt so die interne MQTT-Warteschlange, was zu den MQTT0 Queue-Overflow-Fehlermeldungen sowie zu einigen interne verlorene Shelly Status MQTT-Nachrichten führt.
- In der Konfiguration 1000,4,50 crashed das Skript den Shelly, vermutlich aufgrund einer gleichzeitigen Überlastung von Memory und CPU.
- In der Konfiguration 20,5,100 stoppt das Skript gelegentlich, ohne eine Fehlermeldung zu generieren, wahrscheinlich sind 5 aktive Calls einfach zu viel.
- In der Konfiguration 1000,4,1000 wird das Skript gestoppt und es wird ne versteckte Out-of-Memory-Fehlermeldung ausgelöst.
- In der Konfiguration 20,4,500 läuft das Skript problemlos durch.
Das Script:
/* ============================= Config CHANGE HERE =============================== */
let call_cacheLimit = 20;
let call_activeLimit = 4;
let call_delayLimit = 50;
/* ============================== STOP CHANGING HERE =============================== */
/* +++++++++++++++++++++++++++++ Dekats Toolbox +++++++++++++++++++++++++++++*/
function Str(d){ //Upgrade for JSON.stringify()
if(d === null || d === undefined)return null;
if(typeof d === 'string')return d;
return JSON.stringify(d);}
function EventFilter(d,p) { //Filter for Events, Parameters = filter as Array, callback, userdata, debug
if(!d || !d.info || !p) return;
if(p.filter)for(f of p.filter)for(k of Object.keys(d.info))if(f===k) filterResult[k] = d.info[k];
if(p.debug) print('\nDebug: EventData-> ',d,'\n\nDebug: Result-> ',filterResult,'\n');
if(Object.keys(filterResult).length === 0) return null;
if(p.userdata) filterResult.userdata = p.userdata;
if(p.callback) p.callback(filterResult);
return filterResult;}
function InCall(r,e,m,d){ //Call() Error Check ,data as object or function, you can put data.userData or/and data.CallBack insiede data.
zz--;
if(zd) {print('Error: Call(), to many activ Calls, out of Memory, dropped ',zd,' Calls!'); zd = 0;}
if(e) {print('Error: ',e,' Call(), ',m); return;}
if(typeof d === 'function') d(r);
if(typeof d === 'object' && d.CallBack) {d.userData ? d.CallBack(r,d.userData): d.CallBack(r);} else {if(Str(d)) print(d);}}
function Call(m,p,d){ //Upgrade for Shelly.call()
if(!Str(m) && p !== 'object'){print('Error: Call(), wrong Arguments'); return;}
let szy = Str(zy), cacheLimit = call_cacheLimit, activeLimit = call_activeLimit, delayLimit = call_delayLimit;
function DelC(){delete cCache['sM'+szy]; delete cCache['sP'+szy]; zy--; if(Str(cCache['sD'+szy])) delete cCache['sD'+szy];}
if(zy > cacheLimit){DelC(); zd++}
if(zz >= activeLimit && m !== 'loop') {zy++; szy = Str(zy); cCache['sM'+szy] = m; cCache['sP'+szy] = p; if(Str(d)) cCache['sD'+szy] = d;}
if(m === 'loop') {m = cCache['sM'+szy]; p = cCache['sP'+szy]; if(Str(cCache['sD'+szy])) d = cCache['sD'+szy];}
if(zz < activeLimit) try{zz++; Shelly.call(m, p, InCall, d); if(zy)DelC();} catch(e){print(e); zz--; if(zy)DelC();}
if(Object.keys(cCache).length > 0){if(!tH9) tH9 = Timer.set(delayLimit,false, function() {tH9 = null; Call('loop',{});});}}
function Setup(){ //Wating 5sek befor running Main(), to avoid a Shelly FW Bug
if(tH9) {tH9 = null; print('Debug: Setup finished, Script starting'); return;}
if(Main !== undefined) {tH9 = Timer.set(5000,false,Main); return;}
print('Error: Setup(), Main() undefined');}
var GetStatus = Shelly.getComponentStatus, GetInfo = Shelly.getDeviceInfo(), filterResult = {}, zz = zy = zd = 0; tH9 = null, cCache = {};
/* ++++++++++++++++++++++++ !!! Shelly FW >1.0.0 !!! ++++++++++++++++++++++++++*/
function Main(){
Setup();
Call('Switch.set', {on: true, id:0}, 1);
Call('Switch.set', {on: false, id:0}, 2);
Call('Switch.set', {on: true, id:0}, 3);
Call('Switch.set', {on: false, id:0}, 4);
Call('Switch.set', {on: true, id:0}, 5);
Call('Switch.set', {on: false, id:0}, 6);
Call('Switch.set', {on: true, id:0}, 7);
Call('Switch.set', {on: false, id:0}, 8);
Call('Switch.set', {on: true, id:0}, 9);
Call('Switch.set', {on: false, id:0}, 10);
Call('Switch.set', {on: true, id:0}, 1);
Call('Switch.set', {on: false, id:0}, 2);
Call('Switch.set', {on: true, id:0}, 3);
Call('Switch.set', {on: false, id:0}, 4);
Call('Switch.set', {on: true, id:0}, 5);
Call('Switch.set', {on: false, id:0}, 6);
Call('Switch.set', {on: true, id:0}, 7);
Call('Switch.set', {on: false, id:0}, 8);
Call('Switch.set', {on: true, id:0}, 9);
Call('Switch.set', {on: false, id:0}, 10);
Call('Switch.set', {on: true, id:0}, 1);
Call('Switch.set', {on: false, id:0}, 2);
Call('Switch.set', {on: true, id:0}, 3);
Call('Switch.set', {on: false, id:0}, 4);
Call('Switch.set', {on: true, id:0}, 5);
Call('Switch.set', {on: false, id:0}, 6);
Call('Switch.set', {on: true, id:0}, 7);
Call('Switch.set', {on: false, id:0}, 8);
Call('Switch.set', {on: true, id:0}, 9);
Call('Switch.set', {on: false, id:0}, 10);
Call('Switch.set', {on: true, id:0}, 1);
Call('Switch.set', {on: false, id:0}, 2);
Call('Switch.set', {on: true, id:0}, 3);
Call('Switch.set', {on: false, id:0}, 4);
Call('Switch.set', {on: true, id:0}, 5);
Call('Switch.set', {on: false, id:0}, 6);
Call('Switch.set', {on: true, id:0}, 7);
Call('Switch.set', {on: false, id:0}, 8);
Call('Switch.set', {on: true, id:0}, 9);
Call('Switch.set', {on: false, id:0}, 10);
Call('Switch.set', {on: true, id:0}, 1);
Call('Switch.set', {on: false, id:0}, 2);
Call('Switch.set', {on: true, id:0}, 3);
Call('Switch.set', {on: false, id:0}, 4);
Call('Switch.set', {on: true, id:0}, 5);
Call('Switch.set', {on: false, id:0}, 6);
Call('Switch.set', {on: true, id:0}, 7);
Call('Switch.set', {on: false, id:0}, 8);
Call('Switch.set', {on: true, id:0}, 9);
Call('Switch.set', {on: false, id:0}, 10);
Call('Switch.set', {on: true, id:0}, 1);
Call('Switch.set', {on: false, id:0}, 2);
Call('Switch.set', {on: true, id:0}, 3);
Call('Switch.set', {on: false, id:0}, 4);
Call('Switch.set', {on: true, id:0}, 5);
Call('Switch.set', {on: false, id:0}, 6);
Call('Switch.set', {on: true, id:0}, 7);
Call('Switch.set', {on: false, id:0}, 8);
Call('Switch.set', {on: true, id:0}, 9);
Call('Switch.set', {on: false, id:0}, 10);
Call('Switch.set', {on: true, id:0}, 1);
Call('Switch.set', {on: false, id:0}, 2);
Call('Switch.set', {on: true, id:0}, 3);
Call('Switch.set', {on: false, id:0}, 4);
Call('Switch.set', {on: true, id:0}, 5);
Call('Switch.set', {on: false, id:0}, 6);
Call('Switch.set', {on: true, id:0}, 7);
Call('Switch.set', {on: false, id:0}, 8);
Call('Switch.set', {on: true, id:0}, 9);
Call('Switch.set', {on: false, id:0}, 10);
Call('Switch.set', {on: true, id:0}, 1);
Call('Switch.set', {on: false, id:0}, 2);
Call('Switch.set', {on: true, id:0}, 3);
Call('Switch.set', {on: false, id:0}, 4);
Call('Switch.set', {on: true, id:0}, 5);
Call('Switch.set', {on: false, id:0}, 6);
Call('Switch.set', {on: true, id:0}, 7);
Call('Switch.set', {on: false, id:0}, 8);
Call('Switch.set', {on: true, id:0}, 9);
Call('Switch.set', {on: false, id:0}, 10);
Call('Switch.set', {on: true, id:0}, 1);
Call('Switch.set', {on: false, id:0}, 2);
Call('Switch.set', {on: true, id:0}, 3);
Call('Switch.set', {on: false, id:0}, 4);
Call('Switch.set', {on: true, id:0}, 5);
Call('Switch.set', {on: false, id:0}, 6);
Call('Switch.set', {on: true, id:0}, 7);
Call('Switch.set', {on: false, id:0}, 8);
Call('Switch.set', {on: true, id:0}, 9);
Call('Switch.set', {on: false, id:0}, 10);
Call('Switch.set', {on: true, id:0}, 1);
Call('Switch.set', {on: false, id:0}, 2);
Call('Switch.set', {on: true, id:0}, 3);
Call('Switch.set', {on: false, id:0}, 4);
Call('Switch.set', {on: true, id:0}, 5);
Call('Switch.set', {on: false, id:0}, 6);
Call('Switch.set', {on: true, id:0}, 7);
Call('Switch.set', {on: false, id:0}, 8);
Call('Switch.set', {on: true, id:0}, 9);
Call('Switch.set', {on: false, id:0}, 10);
Call('Switch.set', {on: true, id:0}, 1);
Call('Switch.set', {on: false, id:0}, 2);
Call('Switch.set', {on: true, id:0}, 3);
Call('Switch.set', {on: false, id:0}, 4);
Call('Switch.set', {on: true, id:0}, 5);
Call('Switch.set', {on: false, id:0}, 6);
Call('Switch.set', {on: true, id:0}, 7);
Call('Switch.set', {on: false, id:0}, 8);
Call('Switch.set', {on: true, id:0}, 9);
Call('Switch.set', {on: false, id:0}, 10);
Call('Switch.set', {on: true, id:0}, 1);
Call('Switch.set', {on: false, id:0}, 2);
Call('Switch.set', {on: true, id:0}, 3);
Call('Switch.set', {on: false, id:0}, 4);
Call('Switch.set', {on: true, id:0}, 5);
Call('Switch.set', {on: false, id:0}, 6);
Call('Switch.set', {on: true, id:0}, 7);
Call('Switch.set', {on: false, id:0}, 8);
Call('Switch.set', {on: true, id:0}, 9);
Call('Switch.set', {on: false, id:0}, 10);
Call('Switch.set', {on: true, id:0}, 1);
Call('Switch.set', {on: false, id:0}, 2);
Call('Switch.set', {on: true, id:0}, 3);
Call('Switch.set', {on: false, id:0}, 4);
Call('Switch.set', {on: true, id:0}, 5);
Call('Switch.set', {on: false, id:0}, 6);
Call('Switch.set', {on: true, id:0}, 7);
Call('Switch.set', {on: false, id:0}, 8);
Call('Switch.set', {on: true, id:0}, 9);
Call('Switch.set', {on: false, id:0}, 10);
Call('Switch.set', {on: true, id:0}, 1);
Call('Switch.set', {on: false, id:0}, 2);
Call('Switch.set', {on: true, id:0}, 3);
Call('Switch.set', {on: false, id:0}, 4);
Call('Switch.set', {on: true, id:0}, 5);
Call('Switch.set', {on: false, id:0}, 6);
Call('Switch.set', {on: true, id:0}, 7);
Call('Switch.set', {on: false, id:0}, 8);
Call('Switch.set', {on: true, id:0}, 9);
Call('Switch.set', {on: false, id:0}, 10);
}
Setup();
Alles anzeigen