Und, wo wir gerade dabei sind. Der vertikale Balken, links vor dem Avatar ist etwas unschön.
Beiträge von ostfriese
-
-
Ahh, so geht's. Danke dir.
-
-
Kann man keine named Links mehr setzen? Nur noch Link als URL?
-
abschaltbare / minimierbare forum.eu grafik im seitenkopf
-
@Tech-Nick Danke für die abgesetzte Signatur. Sieht schick aus.
-
Nur eine Kleinigkeit und nicht entscheidend. Der Signaturbereich ist nicht abgesetzt. Das irritiert ein wenig.
-
Also, ich bin begeistert. Die Geschwindigkeit ist super, das Design gefällt mir. Es dauert sicher noch ein bisschen, bis man alle Feinheiten herausgefunden hat, aber das kommt schon.
Super finde ich die neue Ausrichtung, auch hin zu anderen Smart-Home Produkten. Shelly ist schon ein Produkt, dass seine Daseinsberechtigung auf dem Smart-Home Markt hat, ist aber auch ein Nischenprodukt.
Die Öffnung für andere Anbieter wird das Forum bereichern, da bin ich mir ganz sicher.
Ich danke dem Admin/Moderatoren-Team für seinen Einsatz. Es ist vorstellbar, wie viel Arbeit und, nicht zuletzt auch monetäre Ressourcen
ihr hier 'reinsteckt. Danke dafür!
-
Nur, um keine Missverständnisse aufkommen zu lassen. Ich möchte Thomas gar nichts zumuten. Der Shelly ist mir egal. Läuft alles unter Forschung.
-
Ich war sogar so optimistisch das Rückporto mitgeschickt zu haben
-
Die Entwickler waren der Meinung, sie würden das im Labor hinbekommen, wollen aber den Aufwand nicht betreiben, da es sowieso einen Fix in einem der nächsten Updates geben wird. Deswegen sehe ich da Chancen. Was die Entwickler können, kannst du schon lange, Thomas thgoebel
-
-
By the way, der Patient ist auf dem Weg zu Thomas thgoebel . Bin gespannt, ob eine Reanimation gelingt.
-
Ich hatte gar keine Einwände, Gerhard. Nur Erklärungen, warum ich Sachen so mache. Natürlich kann man viele Sachen auch anders machen.
Aber, es funktioniert ja alles prima, es sei denn, man macht dämliche Tippfehler
Das mit dem while brauche ich auch gar nicht mehr. War nur, wie es beim Snooker genannt wird, ein Shot to Nothing.
Deine vorgeschlagene Timer Funktion bildet ja im Prinzip eine While-Schleife mit einem sleep ab. Ist somit die bessere Konstruktion, da sie zu keiner Zeit zu einem Block
der CPU durch Auslastung führt. Ein Zerstören des Shelly ist somit ausgeschlossen.
Gut ist aber, dass Alterco, durch meinen dämlichen Fehler, erkannt hat, dass das nicht nur zu einem Ärgernis durch die quasi Zerstörung EINES Shelly führt, sondern auch ein potenzielles Sicherheitsrisiko für ALLE (Gen 2/3) Shelly birgt. Besser ist also, solche Fehler by design auszuschließen.
Hierzu haben besonders Devil und 66er im Hintergrund beigetragen. Danke dafür!
-
Ach ja, das wird auch noch gebraucht:
Code
Alles anzeigenlet CONFIG = { scan_duration: BLE.Scanner.INFINITE_SCAN, temperature_thr: 18, switch_id: 0, mqtt_topic: "ruuvi", event_name: "ruuvi.measurement", }; let RUUVI_MFD_ID = 0x0499; let RUUVI_DATA_FMT = 5; //format is subset of https://docs.python.org/3/library/struct.html let packedStruct = { buffer: '', setBuffer: function(buffer) { this.buffer = buffer; }, utoi: function(u16) { return (u16 & 0x8000) ? u16 - 0x10000 : u16; }, getUInt8: function() { return this.buffer.at(0) }, getInt8: function() { let int = this.getUInt8(); if(int & 0x80) int = int - 0x100; return int; }, getUInt16LE: function() { return 0xffff & (this.buffer.at(1) << 8 | this.buffer.at(0)); }, getInt16LE: function() { return this.utoi(this.getUInt16LE()); }, getUInt16BE: function() { return 0xffff & (this.buffer.at(0) << 8 | this.buffer.at(1)); }, getInt16BE: function() { return this.utoi(this.getUInt16BE(this.buffer)); }, unpack: function(fmt, keyArr) { let b = '<>!'; let le = fmt[0] === '<'; if(b.indexOf(fmt[0]) >= 0) { fmt = fmt.slice(1); } let pos = 0; let jmp; let bufFn; let res = {}; while(pos<fmt.length && pos<keyArr.length && this.buffer.length > 0) { jmp = 0; bufFn = null; if(fmt[pos] === 'b' || fmt[pos] === 'B') jmp = 1; if(fmt[pos] === 'h' || fmt[pos] === 'H') jmp = 2; if(fmt[pos] === 'b') { res[keyArr[pos]] = this.getInt8(); } else if(fmt[pos] === 'B') { res[keyArr[pos]] = this.getUInt8(); } else if(fmt[pos] === 'h') { res[keyArr[pos]] = le ? this.getInt16LE() : this.getInt16BE(); } else if(fmt[pos] === 'H') { res[keyArr[pos]] = le ? this.getUInt16LE() : this.getUInt16BE(); } this.buffer = this.buffer.slice(jmp); pos++; } return res; } }; let RuuviParser = { getData: function (res) { let data = BLE.GAP.ParseManufacturerData(res.advData); if (typeof data !== "string" || data.length < 26) return null; packedStruct.setBuffer(data); let hdr = packedStruct.unpack('<HB', ['mfd_id', 'data_fmt']); if(hdr.mfd_id !== RUUVI_MFD_ID) return null; if(hdr.data_fmt !== RUUVI_DATA_FMT) { print("unsupported data format from", res.addr); print("expected format", RUUVI_DATA_FMT); return null; }; let rm = packedStruct.unpack('>hHHhhhHBHBBBBBB', [ 'temp', 'humidity', 'pressure', 'acc_x', 'acc_y', 'acc_z', 'pwr', 'cnt', 'sequence', 'mac_0','mac_1','mac_2','mac_3','mac_4','mac_5' ]); rm.temp = rm.temp * 0.005; rm.humidity = rm.humidity * 0.0025; rm.pressure = rm.pressure + 50000; rm.batt = (rm.pwr >> 5) + 1600; rm.tx = (rm.pwr & 0x001f * 2) - 40; rm.addr = res.addr.slice(0, -2); rm.rssi = res.rssi; return rm; }, }; function publishToMqtt(measurement) { MQTT.publish( CONFIG.mqtt_topic + "/" + measurement.addr, JSON.stringify(measurement) ); } function emitOverWs(measurement) { Shelly.emitEvent(CONFIG.event_name, measurement); } function triggerAutomation(measurement) { if (measurement.temp < CONFIG.temperature_thr) { // turn the heater on Shelly.call("Switch.Set", { id: CONFIG.switch_id, on: true }); } } function scanCB(ev, res) { if (ev !== BLE.Scanner.SCAN_RESULT) return; let measurement = RuuviParser.getData(res); if (measurement === null) return; print("ruuvi measurement:", JSON.stringify(measurement)); publishToMqtt(measurement); emitOverWs(measurement); triggerAutomation(measurement); } BLE.Scanner.Start({ duration_ms: CONFIG.scan_duration }, scanCB);
-
1.) ja, in einer Datei, nicht im KVS
2.) Bin mit dem while einem intuitiven, von Python Erfahrungen getriggertem Impuls gefolgt. Da würde man noch ein sleep(1000) einbauen,
gibt es aber bei Shelly nicht.
3.) Ich brauche zum jetzigen Zeitpunkt schon 2 laufende Skripte, das 3. noch zugelassene ist für etwas anderes vorgesehen.
4.) -
5.) -
Ich bin mit dem Skript jetzt schon am Limit, was die Code-Länge, (deshalb das Auslagern von Skriptteilen in non-excecutable), Aufruf von Calls (hier habe ich schon alles Mögliche in stacks verpackt), und die Nutzung des zugelassenen Ram-Speichers ist auch am Limit.
Aber, macht euch selbst ein Bild:
Skript:
Code
Alles anzeigen//Cut value to digits function cut(val, digit) { val = val.toFixed(digit); st = String(val); st = st.slice(0, st.indexOf('.') + digit) return parseFloat(st); } //Look for value in list function includes(list, value) { for (let i = 0; i < list.length; i++) { if(value === list[i]) return true; } return false; } //Do some conversions on raw data function treat_data(data, proto, host) { try { alarm_state = false; raw = data; let ruuvi = {}; ruuvi['Mac'] = raw.addr; if(ruuvi.Mac.length < 18) { last_oct = data.mac_5.toString(16); if(last_oct.length < 2) last_oct = 0 + last_oct; ruuvi.Mac += last_oct; } if(components[ruuvi.Mac] === undefined) return; ruuvi['Temperatur'] = cut(raw.temp,3); ruuvi['Luftfeuchtigkeit'] = cut(raw.humidity,3); ruuvi['Luftdruck'] = cut(raw.pressure/100,3); ruuvi['RSSI'] = raw.rssi; ruuvi['Batterie'] = cut(raw.batt/1000,3); ruuvi['Counter'] = raw.cnt; ruuvi['Update'] = full_time(); ruuvi['Ts'] = Shelly.getComponentStatus('sys').unixtime; for (var key in ruuvi) { if(key != 'Mac') { components[ruuvi.Mac][key] = ruuvi[key]; } } if (components[ruuvi.Mac]['Alarm_cnt'] === undefined) { components[ruuvi.Mac]['Alarm_cnt'] = ruuvi['Counter']; components[ruuvi.Mac]['Alarm_ts'] = 0; } if (ruuvi['Counter'] > components[ruuvi.Mac]['Alarm_cnt']) { components[ruuvi.Mac]['Alarm_cnt'] = ruuvi['Counter']; components[ruuvi.Mac]['Alarm_ts'] = Shelly.getComponentStatus('sys').unixtime; if(v.alarm_onoff) { if(v.debug) print(components[ruuvi.Mac]['Name'] + ' !!! Alarm !!!'); alarm_ts = components[ruuvi.Mac]['Alarm_ts']; alarm_name = components[ruuvi.Mac]['Name']; alarm_time = full_time(components[ruuvi.Mac]['Alarm_ts']); treat_http(); } ruuvi = {}; } } catch(e){print('ERROR in treat_data:', e.message)}; } //Get time in hh:mm:ss function full_time() { date_now = Date(Shelly.getComponentStatus('sys').unixtime * 1000); return time = ('0' + date_now.getHours()).substr(-2) + ':' + ('0' + date_now.getMinutes()).substr(-2) + ':' + ('0' + date_now.getSeconds()).substr(-2); } //Manipulate dynamic data function treat_http() { try { html_data = ''; for(var each in components) { let cl = ''; let since = ''; if(components[each].Ts != null) { if(Shelly.getComponentStatus('sys').unixtime - components[each].Ts > v.not_seen) { cl = 'blink'; since = 'seit '; if (v.language === 'EN') since = 'since '; } } else cl = 'blink'; html_data += '<table>\n'; for(var key in components[each]) { if(key != 'show' && includes(components[each]['show'], key)) { if(key === 'Name') { html_data += '\t<tr class="' + cl + '">\n\t\t<td colspan="3" style="text-align:center;">' + components[each][key] + ' ' + since + components[each]['Update'] + '</td>\n\t</tr>\n'; } else { dat = String(components[each][key]); if (typeof(components[each][key]) === 'number') { if(dat.indexOf('.') === - 1) dat += '.00'; while(dat.length - dat.indexOf('.') < 3) {dat += '0'}; } let unit = units[key]; html_data += '\t<tr>\n\t\t<td style="text-align:left;">' + key + '</td>\n\t\t<td style="text-align:right;">' + dat + '</td>\n\t\t<td style="text-align:right;">' + unit + '</td>\n\t</tr>\n'; } } } let to_rep = '</br>wartet auf Daten'; if (v.language === 'EN') to_rep = '</br>waiting for data'; html_data = html_data.replace('undefined',to_rep) + '</table>\n'; if(v.language === 'EN') { i=0; for(var each in units) { html_data = html_data.replace(each,translate[i]); i++; } html_data = html_data.replace('<tr><td style="text-align:left;">Temp', '<tr><td style="text-align:left;">Temperature'); } } cl = ''; let bg = v.al_off_color; txt = 'Alarm ist ausgeschaltet'; if (v.alarm_onoff) {bg = v.al_on_color; txt = 'Alarm ist eingeschaltet';}; if (v.alarm_onoff && Shelly.getComponentStatus('sys').unixtime - alarm_ts < v.alarm_duration) { bg = v.al_ongoing_color; txt = '!!! Alarm ist aktiv !!!'; cl = 'blink'; } if(v.language === 'EN') { txt=txt.replace('ist ausgeschaltet','is switched off'); txt=txt.replace('ist eingeschaltet','is switched on'); txt=txt.replace('ist aktiv','is active'); } if (bg === v.al_off_color) {alarm_name = ''; alarm_time = '';}; let a_name = alarm_name; if(alarm_name) {a_name = '</br>' + a_name; bg = v.al_ongoing_color;}; let alarm_link = '<table style="height:' + String(3 * v.font_size) + 'px;">\n' + '\t<tr>\n\t\t<td style="text-align:center;background-color:' + bg + ';"">' + '\n\t\t\t<a class="' + cl + '" id="alarm_link" style="text-decoration:none;display:block;color:' + v.font_color + ';"' + 'href="javascript:com(\'' + v.endpoint + '?switch_alarm\')">' + txt + ' ' + a_name + ' ' + alarm_time + '</a>\n\t\t</td>\n\t</tr>\n</table>'; html_data += alarm_link; }catch(e){print('ERROR in treat_http:', e.message)}; } //Responde to http_requets function send_response(response, body) { try { response.code = 200; response.body = body; response.send(); }catch(e){print('ERROR in send_response:', e.message)}; } //Get input from ws function get_ws(ev) { try { //if(check_for_shelly(ev.info.data,'ws ','ws')) return; if (ev.info.event === 'ruuvi.measurement') { let device = ev.info.data.addr + ev.info.data.mac_5.toString(16); if(device != undefined) { if(components[device] === undefined) { components[device] = {'Name':'XXX','show':['Temperatur','Luftfeuchtigkeit','Luftdruck','Batterie','Name','RSSI']}; get_file('config', null, 'components_write'); } print('Device : ' + components[device]['Name']); treat_data(ev.info.data, 'ws '); } } }catch(e){print('ERROR in get_ws:', e.message)} } function get_file() { //print(JSON.stringify(file_stack)); //print(file_stack.length); if(file_stack.length === 0 || file_stack_busy) return; file_stack_busy = true; filename=file_stack[0][0];extra=file_stack[0][1];what=file_stack[0][2]; print(filename); Shelly.call('Script.List','', function(result, error_code, error_message){ let a = result['scripts']; for (let i=0; i<a.length; i++) { if(a[i]['name'] === filename) { let para = {id:a[i]['id']}; Shelly.call('Script.GetCode', para, function(result, error_code, error_message){ let sep = '//+++++++++++++++++++++++++++++++++++ '; if(what === 'script') { let aw=result.data.slice(result.data.indexOf(sep + 'script'), result.data.indexOf(sep + 'script end')); aw = aw.replace('*first','"' + first + '"').replace('*first','"' + first + '"'); send_response(extra, aw.replace('XXXXXX',v.endpoint) .replace('YYYYYY',meld).replace(sep + 'script\n','')); aw = ''; file_stack.splice(0,1);file_stack_busy = false; return; } if(what === '') { print(JSON.stringify(v)); let aw=result.data.slice(result.data.indexOf(sep + 'html'), result.data.indexOf(sep + 'html end')); aw = aw.replace('<title>*endpoint','<title>' + v.endpoint.toUpperCase()); aw = aw.replace('*endpoint',v.endpoint).replace('*font_family',v.font_family).replace('*endpoint',v.endpoint); aw = aw.replace('*font_size',v.font_size).replace('*font_family',v.font_family); aw = aw.replace('*font_color',v.font_color).replace('*bg_color',v.bg_color).replace('*first',first); aw = aw.replace('*font_weight',v.font_weight); send_response(extra, aw.replace(sep + 'html\n','')); aw = ''; file_stack.splice(0,1);file_stack_busy = false; return; } if(what.indexOf('components') > -1) { let aw=result.data.slice(result.data.indexOf(sep + 'components'), result.data.indexOf(sep + 'components end')); aw = aw.replace(sep + 'components\n',''); if(what.indexOf('components_write') > -1) { let c = '{\n'; for (var each in components) { let n = each; if(components[each]['Name']!='XXX') { n=components[each]['Name']; }else { components[each]['Name']=String(each); } c = c + JSON.stringify(each) + ':{"Name":"' + n + '","show":["Temperatur","Luftfeuchtigkeit","Luftdruck","Batterie","Name","RSSI"]},\n'; } c = c.slice(0,c.length - 2) + '\n}\n'; Shelly.call('Script.PutCode', {id:i,code:result.data.replace(aw,c)}); aw = ''; file_stack.splice(0,1);file_stack_busy = false; return; } aw = JSON.parse(aw); components = aw; aw = ''; file_stack.splice(0,1);file_stack_busy = false; return; } if(what === 'v') { let aw=result.data.slice(result.data.indexOf(sep + 'vars'), result.data.indexOf(sep + 'vars end')); aw = aw.replace(sep + 'vars\n',''); aw = JSON.parse(aw); v = aw; aw = ''; file_stack.splice(0,1);file_stack_busy = false; return; } }); ; } } } ); } //React on http function get_http(request,response) { try { let query = String(request.query); if(request.query === 'script') { if(v.debug) print('Browser : ' + query); file_stack.push(['config',response,query]); //get_file('config', response, query); } if(request.query === 'switch_alarm') { Timer.clear(t1); if(v.debug) print('Browser : ' + query); if(v.alarm_onoff===true) { v.alarm_onoff = false; } else { v.alarm_onoff = true; } treat_http(); send_response(response, ''); t1= Timer.set(20000,true,treat_http); } if(request.query === '') { if(v.debug) print('Browser : ' + 'html'); treat_http(); file_stack.push(['config',response,query]); //get_file('config', response, query); } if(request.query === 'data') { if(v.debug) print('Browser : ' + query); send_response(response, html_data); } }catch(e){print('ERROR in get_http:', e.message)}; } function main() { //Do some user friendly printout print('Your url is:'); print('http://' + Shelly.getComponentStatus("wifi").sta_ip + '/script/' + Shelly.getCurrentScriptId() + '/' + v.endpoint); t1= Timer.set(20000,true,treat_http); meld = '<div class=\\"blink\\">Alarm wird umgeschaltet</div>'; first = 'Warte auf Daten...'; if(v.language==='EN') { meld = '<div class=\\"blink\\">Alarm will be toggled</div>'; first = 'Waiting for data...'; } HTTPServer.registerEndpoint(v.endpoint,get_http); Shelly.addEventHandler(get_ws); } //Some pre config let units = {'Temperatur':'°C', 'Luftfeuchtigkeit':'%', 'Luftdruck':'hPa', 'Batterie':'V','RSSI':'dBm', 'Update':'', 'Name':'','Mac':''}; let translate = ['Temp','Humidity','Pressure','Battery','RSSI','Name','Mac']; let html_data = ''; let alarm_ts = 0; let alarm_name = ''; let alarm_time = ''; let components = {}; let v = {}; file_stack = []; file_stack_busy = false; let meld; let first; let t1; let t2=Timer.set(500,true,get_file); try { file_stack.push(['config',null,'components']); //get_file('config', null, 'components'); } catch(e){print('ERROR in config:', e.message)}; file_stack.push(['config', null, 'v']); //while(v.endpoint === undefined){}; //get_file('config', null, 'v'); let delay = 2; //print(Shelly.getComponentStatus('voltmeter:100').voltage); if (Shelly.getComponentStatus('sys').uptime<10) delay=5; Timer.set(delay * 1000,false,main);
Non excutable config:
HTML
Alles anzeigen//+++++++++++++++++++++++++++++++++++ components { "f2:9f:86:22:d5:46":{"Name":"Bunker","show":["Temperatur","Luftfeuchtigkeit","Luftdruck","Batterie","Name","RSSI"]}, "c1:e3:4c:7a:27:b5":{"Name":"Briefkasten","show":["Temperatur","Luftfeuchtigkeit","Luftdruck","Batterie","Name","RSSI"]}, "c6:c5:22:e7:ab:7a":{"Name":"Reserve","show":["Temperatur","Luftfeuchtigkeit","Luftdruck","Batterie","Name","RSSI"]} } //+++++++++++++++++++++++++++++++++++ components end //+++++++++++++++++++++++++++++++++++ vars { 'endpoint' : 'ruuvi', 'alarm_onoff' : true, 'alarm_duration' : 30, 'language' : 'DE', 'not_seen' : 60, 'font_family' : 'monospace', 'font_size' : 40, 'font_weight' : 10, 'font_color' : '#FCFCFC', 'bg_color' : '#000000', 'al_ongoing_color' : '#9C071A', 'al_on_color' : '#228B22', 'al_off_color' : '#000000', 'debug' : true } //+++++++++++++++++++++++++++++++++++ vars end //+++++++++++++++++++++++++++++++++++ script function updateDiv() { try{ if(index===true) return; fetch("XXXXXX?data") .then ( function(response) { return response.text(); } ) .then ( function(data) { console.log(data); if(data.indexOf("Not Found") > -1) data = old.replace("<table>","<table class = \"blink\">"); if(index===true) return; if(data === '') data ="<div class=\"blink\">" + *first + "<div>"; document.getElementById("dataDiv").innerHTML=data; old=data; } ); }catch(e){return;}; } function com(command){ index = true; console.log(command.split("?")[1]); if(command.split("?")[1] === "switch_alarm") { document.getElementById("alarm_link").innerHTML = "<div class=\"blink\">YYYYYY</div>"; } fetch(command).then(function() {index = false;updateDiv();}); } let index = false; let old = ""; updateDiv(); setInterval(updateDiv, 10000); //+++++++++++++++++++++++++++++++++++ script end //+++++++++++++++++++++++++++++++++++ html <!doctype html> <html> <head> <title>*endpoint</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <style> body {font-size:*font_sizepx;background-color:*bg_color;color:*font_color;font-weight:*font_weight;px;font-family:*font_family;} tr {border:px;} td {padding-right:10px;padding-left:10px;} table {width:100%;border-radius:20px;border:5px solid #899499} .blink {animation-name:animation_blink;animation-timing-function:ease-in;animation-duration:3s;animation-iteration-count:infinite;} @keyframes animation_blink {0% { opacity: 1; }50% { opacity: 0.1; }100% { opacity: 1; }} </style> </head> <body> <div id="dataDiv"><div class="blink">*first</div></div> <script type="application/javascript" src="*endpoint?script"></script> </body> </html> //+++++++++++++++++++++++++++++++++++ html end
Ihr seht, dass ist schon aufwändig
-
Ich schreibe mal, wie das passiert ist.
Nach dem Start habe ich einen Timer gesetzt.
In der Function wird ein Objekt v befüllt. Es werden Werte aus einer Datei ausgelesen und in das Objekt geschrieben,
Wenn das geschehen ist, sieht v dann so aus:
Code
Alles anzeigen//+++++++++++++++++++++++++++++++++++ vars { 'endpoint' : 'ruuvi', 'alarm_onoff' : true, 'alarm_duration' : 30, 'language' : 'DE', 'not_seen' : 60, 'font_family' : 'monospace', 'font_size' : 40, 'font_weight' : 10, 'font_color' : '#FCFCFC', 'bg_color' : '#000000', 'al_ongoing_color' : '#9C071A', 'al_on_color' : '#228B22', 'al_off_color' : '#000000', 'debug' : true }
Hier sind alle wichtigen Variablen für den korrekten Lauf des Skriptes untergebracht.
Da das Skript ohne diese Variablen nicht lauffähig ist, diese aber erst nach 500 ms im Timer beschrieben werden, dachte ich, es wäre eine gute Idee folgendes zu machen:
Normal kein Problem, es sei denn, man macht einen einen kleinen, aber fatalen Fehler und schreibt:
Der kleine Unterschied ist das "t" am Ende. v.endpoin wird nie beschrieben, bleibt also undefined.
Da ich diese Routine eingeführt habe, um das Startverhalten des Skriptes zu optimieren, --> Reboot --> tot.
Eigentlich ist in der API beschrieben, dass der Shelly by design das erkennt, und den Autostart des Skriptes deaktiviert.
ZitatKnown Issues
Non-blocking execution
Shelly scripts are executed in an environment which shares CPU time with the rest of the firmware. Code in the scripts runs on the main system task and is not allowed to block for long. This is why any APIs which can potentially take a long while are callback-based. Still, it is possible to write code which will hoard the CPU for longer then acceptable. Such code may cause issues with other firmware features, communication or even cause the device to crash. One obvious example is an infinite (or near infinite) loop:
Loop for too long
let n = 0;while (n < 500000) {
n = n + 1;
}
If a script manages to crash the device the system will detect this and disable the script at the next boot.
Leider hat dieses Feature nicht funktioniert.
Das ist der gesamte Hintergrund.
Das hat das zur Folge, dass man keinem Skript mehr vertrauen kann, sofern man nicht in der Lage ist, das Skript selber zu lesen und zu interpretieren.
(Eigentlich sowieso eine Selbstverständlichkeit, aber seid mal ehrlich )
So, jetzt kennt ihr den Hintergrund.
-
66er Danke für die Rückmeldung. Schön, dass das gefixt wird. Ist zwar ein seltener Fall, aber auch eine Sicherheitslücke, die jetzt geschlossen wird.
-
Hääh
Na klar, habe ICH es ganz alleine geschafft, da eine Endlosschleife einzubauen. Und na klar, war das dämlich, sogar DAU-mäßig.
Beschwert habe ich mich zu keinem Zeitpunkt. Der Shelly, als rein monetärer Verlust, ist mir auch egal.
Mein Anliegen ist durch reine Neugierde, ob man dieses Problem gelöst bekommt, getriggert.
Per Software nicht lösbar, Flaschen ohne Löten geht nicht, Alterco hat nichts gesagt (müssen die ja auch nicht, war ja eigene Blödheit),
also, ein nettes Problem für die kollektive Intelligenz hier.
Nicht mehr und nicht weniger.
-
OT: Would be nice, but I've got other informations.