Skip to content

JavaScript

Hilfe für Skripterstellung mit JavaScript

2.5k Topics 48.5k Posts

NEWS

  • HowTo: Zusatz-Programme fuer jarvis v3

    javascript
    889
    4 Votes
    889 Posts
    217k Views
    M
    Vorsicht kein Nodejs Update auf 22.21.0 siehe https://forum.iobroker.net/topic/82601/vorsicht-jarvis-user-kein-nodejs-update-auf-22-21-0 Hat sich mit Update auf Nodejs 22.21.1 erledigt.
  • Gibt es schon was mit Energiemanager?

    2
    0 Votes
    2 Posts
    137 Views
    H
    @martin-5 Sowas: https://forum.iobroker.net/topic/81755/test-adapter-smartloadmanager-v0-0-x-latest-repo
  • Performance Profile für Javascript in iobroker

    2
    0 Votes
    2 Posts
    167 Views
    arteckA
    @homeuser nö.. gibbet nicht..
  • [erl.]wie speichert man Array von Arrays

    3
    0 Votes
    3 Posts
    272 Views
    paul53P
    @asgothian sagte: der einfachste weg: Nicht mit @liv-in-sky sagte in wie speichert man Array von Arrays: datenpunkt vom type "array" , denn dann nimmt der Javascript-Adapter die Wandlung nach/von JSON vor.
  • JSON Tabelle FuelPriceMonitor [Austria]

    77
    4
    3 Votes
    77 Posts
    7k Views
    liv-in-skyL
    @australien im ersten post dieses threads ist mein script - was du gepostet hast, kenn ich nicht - evtl hat es jmd weiterntwickelt ? wie erwähnt - ich nutze das ja nicht und bin somit nicht auf dem laufenden :-(
  • Info: Auslagerung von Global-Scripten ins Filesystem

    12
    1
    5 Votes
    12 Posts
    1k Views
    I
    @uwe72 Hab mir ein bisschen die Zähne ausgebissen, bis es bei mir lief. Das Problem war, dass ich mit Windows arbeite und ich nicht sicher war, ob es an den Pfadangaben gelegen hat. Das Problem war, dass Dein Beispiel für Javascript eben Typescript enthält ( : number ) und das funktioniert halt in einem .js script nicht und muss transpiliert werden. Der Transpiler hat das dann rausgenommen. Vielleicht kannst du das für andere ja kurz anpassen. Trotzdem finde ich die Variante gut!
  • Von Javascript adapter auf das DOM in der vis zugreifen

    16
    0 Votes
    16 Posts
    484 Views
    I
    @codierknecht @OliverIO Danke erst mal. Ich muss das erst mal durchdenken und ausprobieren. Melde mich ev. später wieder ... ;-)
  • 2 Votes
    145 Posts
    26k Views
    U
    Hallo Leute, Das Thema ist zwar sehr alt, aber ich habe es heute wieder einmal heraus gekramt, weil ich genau das brauchte. Vielen Dank für alles. Es hat zuerst ganz gut Funktioniert. Das einzige, was doof war, war das der JavaScript Editor die match Variable nicht erkannt hat und diese als Fehler im Skript dargestellt wurden. Das konnte man recht einfach mit mit "var match;" vor jeder Verwendungsstelle, die Variable erst einmal definiert. Also zweites hatte ich dann bei bestimmten Geräten auch das Problem, dass mir die Sperren an den falschen Geräten eingestellt wurden. Hier ist das Problem das Folgende. Die Filter müssen auf Basis der Geräte ID gesetzt werden. Für die Einfachere Handhabbarkeit wird im Skript aber der Gerätename angegeben. Das Skript fragt daher vorher zu dem Gerätenamen die ID ab. Dabei wird einer Liste aller Gerätenamen mit zugehöriger ID angelegt. Wenn man auf fBListOnly = true setzt, dann sieht man diese Liste auch. Leider kann man aber hier schlecht nachvollziehen, ob diese Liste stimmt. Jedenfalls stimmte diese Liste bei mir nicht. Es gab einen Versatz. Bei mir wurde dieser ausgelöst durch eine "()" im Namen. Fehlerbehebung: Zeile 210: var rx = new RegExp( /class=\"name\"\stitle=\"([a-zA-Z0-9 äöüÄÖÜ\-\_\.]*)\"\sdatalabel/g ); druch var rx = new RegExp( /class=\"name\"\stitle=\"([a-zA-Z0-9 äöüÄÖÜ\-\_\.]*)\"\sdatalabel/g ) ; ersetzen! Desweiteren ist die request Funktion veraltet. Das wirft jedes Mal eine Warnung, wenn man das Skript startet. Da fingen die Probleme dann richtig an. Ich kann zwar grundsätzlich Programmieren, aber diese tiefen vom Java Script und den Webapplikationen gehen dann doch weit über mein Wissen hinaus. Ich beschreibe das mal so, wie ich es mir zusammengereimt habe. anstatt request.get soll man httpGet() oder anstatt request.post http.Post() verwenden. Eins zu eins tauschen ist nicht. Also habe ich etwas gegoogelt und ChatGpt befragt, aber irgendwie war die Funktion nicht so, wie sie zu erwarten war. Das Problem hier war, dass das so genannte axios irgendwo im Iobroker installiert ist und die standard httpGet und httpPost Funktionen überschreibt. Die neuen Funktionen funktionieren dann anders, weil es axios ist. Als ich dann soweit erstmal war, hat ChatGpt mir ganz gut geholfen, alle requst zu ersetzen. Wichtig ist, dann man oben dieses request = require("request") dann auch noch entfernt, weil sonst die Warnung weiterhin auftaucht. Die neuen httpGet() Funktionen bekommen die Werte nicht mehr alle in einer Struct sondern als einzelne Parameter. Auch die Rückgabewerte vom Body sind etwas woanders. Es gibt keine drei Rückgabewerte mehr im Callback, sondern nur noch zwei und der response (zweiter Wert) hat den alten "body" dann unter response.data. Da ich sehr viele Geräte in meiner Fritzbox habe, musste ich zudem bei einem httpPost() von getfBDevices das Timeout noch erhöhen. Das war ein hartes Stück Arbeit, dass alles heraus zu bekommen, aber ChatGPT ist echt erstaunlich und hat viel geholfen. Ich füge mein neues Skipt jetzt hier ein. Es ist leider komplett Umgebaut, weil ich es als Klasse haben wollte. Ich arbeitet generell in meinen Skripten viel mit Klassen. So habe ich eine Klasse "VirtuellesGerät". Wenn ich davon eine Instanz erzeuge, kann ich einen Namen übergeben. Unter diesem Namen wird dann ein Datenpunkt angelegt. Mit einer Methode setCallback(function()) kann ich dem Objekt dann direkt ein Callback geben, welches aufgerufen wird, wenn sich der Datenpunkt ändert. Ich kann so auch sehr einfach ein und Ausschaltzeiten für das Gerät definieren, weil meine Klasse das alles kann. Diese Zeiten schalten auch den Datenpunkt, wodurch dann der Callback ebenfalls ausgelöst wird. Daher wollte ich für meine ganzen Fritzbox Geräte, die ich Sperren möchte, eines meiner Virtuellen Geräte angelegen und im Callback dann die Methode meiner neuen Fritzbox Klasse aufrufen, um die Internetsperre ein oder auszuschalten. Hier daher mein Funktionierenden Fritzbox Klassen Skript als Unterstützung zum Nachbauen der von mir oben beschriebenen Änderungen. class FritzBox { Ip; User; Password; Debug; Liste; Active; headers; secChallenge; secMd5; secLogin; secSid; secProfileNames = []; secProfileIds = []; secDeviceNames = []; secDeviceIds = []; JsonList = ""; hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ InternetAn = "filtprof3"; InternetAus = "filtprof1371"; Debugging = false; ListOnly = false; CreateList = false; constructor (IP,User,Password,Debug = false) { this.Ip = IP; this.User = User; this.Password = Password; this.log("Fritzbox für IP: " + this.Ip + " erstellt"); this.Debug = Debug; this.Liste = new Map(); this.Active = false; this.headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'curl/7.64.0', 'Accept': '*/*' }; if (this.ListOnly) { this.getFbChallenge(); } } log(Message) { if (this.Debug) { console.log("FritzBox: " + Message); } } EintagHinzufuegen(name, state) { this.Liste.set(name, state); if (!this.Active) { this.Active = true; this.CheckListe(); } } CheckListe() { if (this.Liste.size != 0) { const [name, state] = this.Liste.entries().next().value; this.SetDevice(name, state); this.log("Set Device: " + name); } else { this.Active = false; } } SetDevice(Device,Internet) { this.Device = Device; if (Internet) { this.Profile = this.InternetAn; } else { this.Profile = this.InternetAus; } this.getFbChallenge(); } hex_md5(s) { return this.rstr2hex(this.rstr_md5(this.str2rstr_utf8(s))); } b64_md5(s) { return this.rstr2b64(this.rstr_md5(this.str2rstr_utf8(s))); } any_md5(s, e) { return this.rstr2any(this.rstr_md5(this.str2rstr_utf8(s)), e); } hex_hmac_md5(k, d) { return this.rstr2hex(this.rstr_hmac_md5(this.str2rstr_utf8(k), this.str2rstr_utf8(d))); } b64_hmac_md5(k, d) { return this.rstr2b64(this.rstr_hmac_md5(this.str2rstr_utf8(k), this.str2rstr_utf8(d))); } any_hmac_md5(k, d, e) { return this.rstr2any(this.rstr_hmac_md5(this.str2rstr_utf8(k), this.str2rstr_utf8(d)), e); } /* * Perform a simple self-test to see if the VM is working */ md5_vm_test() { return this.hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72"; } /* * Calculate the MD5 of a raw string */ rstr_md5(s) { return this.binl2rstr(this.binl_md5(this.rstr2binl(s), s.length * 8)); } /* * Calculate the HMAC-MD5, of a key and some data (raw strings) */ rstr_hmac_md5(key, data) { var bkey = this.rstr2binl(key); if(bkey.length > 16) bkey = this.binl_md5(bkey, key.length * 8); var ipad = Array(16), opad = Array(16); for(var i = 0; i < 16; i++) { ipad[i] = bkey[i] ^ 0x36363636; opad[i] = bkey[i] ^ 0x5C5C5C5C; } var hash = this.binl_md5(ipad.concat(this.rstr2binl(data)), 512 + data.length * 8); return this.binl2rstr(this.binl_md5(opad.concat(hash), 512 + 128)); } /* * Convert a raw string to a hex string */ rstr2hex(input) { try { this.hexcase } catch(e) { this.hexcase=0; } var hex_tab = this.hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var output = ""; var x; for(var i = 0; i < input.length; i++) { x = input.charCodeAt(i); output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt( x & 0x0F); } return output; } /* * Convert a raw string to a base-64 string */ rstr2b64(input) { try { this.b64pad } catch(e) { this.b64pad=''; } var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var output = ""; var len = input.length; for(var i = 0; i < len; i += 3) { var triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i+2) : 0); for(var j = 0; j < 4; j++) { if(i * 8 + j * 6 > input.length * 8) output += this.b64pad; else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); } } return output; } /* * Convert a raw string to an arbitrary string encoding */ rstr2any(input, encoding) { var divisor = encoding.length; var i, j, q, x, quotient; /* Convert to an array of 16-bit big-endian values, forming the dividend */ var dividend = Array(Math.ceil(input.length / 2)); for(i = 0; i < dividend.length; i++) { dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); } /* * Repeatedly perform a long division. The binary array forms the dividend, * the length of the encoding is the divisor. Once computed, the quotient * forms the dividend for the next step. All remainders are stored for later * use. */ var full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2))); var remainders = Array(full_length); for(j = 0; j < full_length; j++) { quotient = Array(); x = 0; for(i = 0; i < dividend.length; i++) { x = (x << 16) + dividend[i]; q = Math.floor(x / divisor); x -= q * divisor; if(quotient.length > 0 || q > 0) quotient[quotient.length] = q; } remainders[j] = x; dividend = quotient; } /* Convert the remainders to the output string */ var output = ""; for(i = remainders.length - 1; i >= 0; i--) output += encoding.charAt(remainders[i]); return output; } /* * Encode a string as utf-8. * For efficiency, this assumes the input is valid utf-16. */ str2rstr_utf8(input) { var output = ""; var i = -1; var x, y; while(++i < input.length) { /* Decode utf-16 surrogate pairs */ x = input.charCodeAt(i); y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) { x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); i++; } /* Encode output as utf-8 */ if(x <= 0x7F) output += String.fromCharCode(x); else if(x <= 0x7FF) output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F), 0x80 | ( x & 0x3F)); else if(x <= 0xFFFF) output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), 0x80 | ((x >>> 6 ) & 0x3F), 0x80 | ( x & 0x3F)); else if(x <= 0x1FFFFF) output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), 0x80 | ((x >>> 12) & 0x3F), 0x80 | ((x >>> 6 ) & 0x3F), 0x80 | ( x & 0x3F)); } return output; } str2rstr_utf16le(input) { var output = ""; for(var i = 0; i < input.length; i++) output += String.fromCharCode( input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF); return output; } str2rstr_utf16be(input) { var output = ""; for(var i = 0; i < input.length; i++) output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF); return output; } rstr2binl(input) { var output = Array(input.length >> 2); for(var i = 0; i < output.length; i++) output[i] = 0; for(var i = 0; i < input.length * 8; i += 8) output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32); return output; } /* * Convert an array of little-endian words to a string */ binl2rstr(input) { var output = ""; for(var i = 0; i < input.length * 32; i += 8) output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF); return output; } /* * Calculate the MD5 of an array of little-endian words, and a bit length. */ binl_md5(x, len) { /* append padding */ x[len >> 5] |= 0x80 << ((len) % 32); x[(((len + 64) >>> 9) << 4) + 14] = len; var a = 1732584193; var b = -271733879; var c = -1732584194; var d = 271733878; for(var i = 0; i < x.length; i += 16) { var olda = a; var oldb = b; var oldc = c; var oldd = d; a = this.md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); d = this.md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); c = this.md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); b = this.md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); a = this.md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); d = this.md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); c = this.md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); b = this.md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); a = this.md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); d = this.md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); c = this.md5_ff(c, d, a, b, x[i+10], 17, -42063); b = this.md5_ff(b, c, d, a, x[i+11], 22, -1990404162); a = this.md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); d = this.md5_ff(d, a, b, c, x[i+13], 12, -40341101); c = this.md5_ff(c, d, a, b, x[i+14], 17, -1502002290); b = this.md5_ff(b, c, d, a, x[i+15], 22, 1236535329); a = this.md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); d = this.md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); c = this.md5_gg(c, d, a, b, x[i+11], 14, 643717713); b = this.md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); a = this.md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); d = this.md5_gg(d, a, b, c, x[i+10], 9 , 38016083); c = this.md5_gg(c, d, a, b, x[i+15], 14, -660478335); b = this.md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); a = this.md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); d = this.md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); c = this.md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); b = this.md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); a = this.md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); d = this.md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); c = this.md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); b = this.md5_gg(b, c, d, a, x[i+12], 20, -1926607734); a = this.md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); d = this.md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); c = this.md5_hh(c, d, a, b, x[i+11], 16, 1839030562); b = this.md5_hh(b, c, d, a, x[i+14], 23, -35309556); a = this.md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); d = this.md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); c = this.md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); b = this.md5_hh(b, c, d, a, x[i+10], 23, -1094730640); a = this.md5_hh(a, b, c, d, x[i+13], 4 , 681279174); d = this.md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); c = this.md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); b = this.md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); a = this.md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); d = this.md5_hh(d, a, b, c, x[i+12], 11, -421815835); c = this.md5_hh(c, d, a, b, x[i+15], 16, 530742520); b = this.md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); a = this.md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); d = this.md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); c = this.md5_ii(c, d, a, b, x[i+14], 15, -1416354905); b = this.md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); a = this.md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); d = this.md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); c = this.md5_ii(c, d, a, b, x[i+10], 15, -1051523); b = this.md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); a = this.md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); d = this.md5_ii(d, a, b, c, x[i+15], 10, -30611744); c = this.md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); b = this.md5_ii(b, c, d, a, x[i+13], 21, 1309151649); a = this.md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); d = this.md5_ii(d, a, b, c, x[i+11], 10, -1120210379); c = this.md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); b = this.md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); a = this.safe_add(a, olda); b = this.safe_add(b, oldb); c = this.safe_add(c, oldc); d = this.safe_add(d, oldd); } return Array(a, b, c, d); } /* * These functions implement the four basic operations the algorithm uses. */ md5_cmn(q, a, b, x, s, t) { return this.safe_add(this.bit_rol(this.safe_add(this.safe_add(a, q), this.safe_add(x, t)), s),b); } md5_ff(a, b, c, d, x, s, t) { return this.md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); } md5_gg(a, b, c, d, x, s, t) { return this.md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); } md5_hh(a, b, c, d, x, s, t) { return this.md5_cmn(b ^ c ^ d, a, b, x, s, t); } md5_ii(a, b, c, d, x, s, t) { return this.md5_cmn(c ^ (b | (~d)), a, b, x, s, t); } /* * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters. */ safe_add(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } /* * Bitwise rotate a 32-bit number to the left. */ bit_rol(num, cnt) { return (num << cnt) | (num >>> (32 - cnt)); } getFbChallenge() { this.log("function getFbChallenge"); httpGet ('http://' + this.Ip + '/login_sid.lua?username=' + this.User,{ headers: this.headers }, (error, body) => { if (error) log(error, 'error'); this.log(body.data); // https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/RegExp // <?xml version="1.0" encoding="utf-8"?><SessionInfo><SID>0000000000000000</SID><Challenge>d36de231</Challenge><BlockTime>0</BlockTime><Rights></Rights></SessionI this.secChallenge = body.data.match(/Challenge>(.*)<\/Challenge/)[1]; this.log(" > Challenge : " + this.secChallenge); var uft16le = this.str2rstr_utf16le(this.secChallenge + "-" + this.Password ); var md5 = this.rstr_md5(uft16le); this.secMd5 = this.rstr2hex(md5); this.log(" > MD5 : " + this.secMd5); // response="${challenge}-${md5}" // sid=$(curl -i -s -k -d "response=${response}&username=" "http://$1" | grep -Po -m 1 '(?<=sid=)[a-f\d]+' | tail -1) this.secLogin = "response=" + this.secChallenge + "-" + this.secMd5 + "&username=" + this.User; this.log(" > Login : " + this.secLogin); this.getFbSid(); }); } // Get the SID from the Fritzbox getFbSid() { this.log("function getFbSid"); //this.log('httpPost typeof: ' + typeof httpPost); //this.log('httpPost function content:\n' + httpPost.toString()); httpPost('http://' + this.Ip + '/login_sid.lua', this.secLogin, { headers: this.headers }, (error, response ) => { this.log(response.data); if (error) log(error, 'error'); // SID filtern // "sid":"c503b24dae458086" try { //this.secSid = response.data.match(/\"sid\":\"(.*)\"/)[1]; this.secSid = response.data.match(/<SID>(.*?)<\/SID>/)[1]; } catch (e) { if (this.secSid == undefined) { this.log("Your login was not successful. End Script " + Error) return; } } this.log(" > SID : " + this.secSid); //getFbDeviceInfos(); this.getFbProfiles(); }); } // TBD: // Netzwerkinfos mit allen Devices lesen: // var req = "xhr=1&sid=" + secSid + "&lang=de&page=netDev&xhrId=cleanup&useajax=1&no_sidrenew=" getFbDeviceInfos(){ this.log("function getFbDeviceInfos"); var req = "xhr=1&sid=" + this.secSid + "&lang=de&page=netDev&xhrId=cleanup&useajax=1&no_sidrenew=" httpPost('http://' +this.Ip + '/data.lua',req, { headers: this.headers }, (error, response) => { if (error) log(error, 'error'); this.log(response.data); }); } // Get all Profiles from the Fritzbox getFbProfiles() { this.log("function getFbProfiles"); // #curl -d "xhr=1&sid=${sid}&lang=de&no_sidrenew=&page=kidPro" "http://$1/data.lua" var req = "xhr=1&sid=" + this.secSid + "&lang=de&no_sidrenew=&page=kidPro"; var match; httpPost('http://' + this.Ip + '/data.lua',req, { headers: this.headers, }, (error, response) => { if (error) log(error, 'error'); if (this.Debugging){ this.log(" > response.body : \n" + response.data); } this.secProfileIds = []; this.secProfileNames = []; this.log(" > Decode Names") var rx = new RegExp( /class=\"name\"\stitle=\"([a-zA-Z0-9 äöüÄÖÜ\-\_\.]*)\"\sdatalabel/g ); while( (match = rx.exec( response.data )) != null ) { this.secProfileNames.push(match[1]); } if (this.Debugging){ this.log(" > secProfileNames : \n" + this.secProfileNames); } this.log(" > Decode Filters") // submit" name="edit" value=" rx = new RegExp( /submit\"\sname=\"edit\"\svalue=\"([a-zA-Z0-9 äöüÄÖÜ\-\_\.]*)\"\sclass=\"icon/g ); while( (match = rx.exec( response.data )) != null ) { this.secProfileIds.push(match[1]); } if (this.Debugging){ this.log(" > secProfileIds : \n" + this.secProfileIds); } if (this.ListOnly) { this.log("Filter Count : " + this.secProfileIds.length); for (var i = 0; i < this.secProfileIds.length; i++) { this.log("Filter named '"+ this.secProfileNames[i] + "' has ID : " + this.secProfileIds[i]); } } this.getFbDevices(); }); } // IMPORTANT: // The DeviceId changes when you switch the profile. // If you use default profiles it is something like "landevice308962" // If you use your own profiles it is something like "user7749" getFbDevices() { this.log("function getFbDevices"); var match; // xhr=1&sid=5f5ba302815594d8&lang=de&no_sidrenew=&page=kidLis var req = "xhr=1&sid=" + this.secSid + "&lang=de&no_sidrenew=&page=kidLis"; httpPost('http://' + this.Ip + '/data.lua',req, { headers: this.headers, timeout: 10000 }, (error, response) => { if (error) this.log("HTTP Fehler: " + error); if (this.Debugging){ this.log(" > response.data : \n" + response.data); } // TESTING //body = getState("Global.0.Testing.StringValue").val; this.secDeviceNames = []; this.secDeviceIds = []; this.log(" > Decode Device Names") var rx = /class=\"name"\stitle=\"([^"]*)\"\sdatalabel/g; //var rx = new RegExp( /class=\"name"\stitle=\"([a-zA-Z0-9 äöüÄÖÜ\-\_\.]*)\"\sdatalabel/g ); while( (match = rx.exec( response.data )) != null ) { this.secDeviceNames.push(match[1]); } if (this){ this.log(" > secDeviceNames : \n" + this.secDeviceNames); } this.log(" > Decode Device Ids") rx = new RegExp( /name=\"profile:([a-zA-Z0-9 äöüÄÖÜ\-\_\.]*)\"><option/g ); while( (match = rx.exec( response.data )) != null ) { this.secDeviceIds.push(match[1]); } if (this.Debugging){ this.log(" > secDeviceIds : \n" + this.secDeviceIds); } if (this.ListOnly) { this.log("Device Count : " + this.secDeviceIds.length); for (var i = 0; i < this.secDeviceNames.length; i++) { this.log(i + " - Device named '"+ this.secDeviceNames[i] + "' has ID : " + this.secDeviceIds[i]); } } if (!this.ListOnly) { this.setFbSperre(); } else { this.log("DONE : Listmode - No Device blocking ..."); } }); } //curl -d "sid=${sid}&edit=$3&time=$4&budget=unlimited&apply=&page=kids_profileedit" "http://$1/data.lua" >/dev/null 2>&1 setFbSperre() { this.log("function setFbSperre"); // Device suchen ... var devId = -1; for (var i = 0; i < this.secDeviceNames.length; i++) { if (this.secDeviceNames[i] == this.Device) { devId = i; } } this.log(" > Device Nr : " + devId); this.log(" > Device ID : " + this.secDeviceIds[devId]); this.log(" > Device Name : " + this.secDeviceNames[devId]); //var profile = "filtprof4"; //var profile = "filtprof3079"; // xhr=1&sid=b46f3d48b3b0fcc2&lang=de&no_sidrenew=&profile%3Alandevice308962=filtprof4&apply=&oldpage=%2Finternet%2Fkids_userlist.lua var req2 = "xhr=1&sid=" + this.secSid + "&lang=de&no_sidrenew=&profile%3A" + this.secDeviceIds[devId] + "=" + this.Profile + "&apply=&oldpage=%2Finternet%2Fkids_userlist.lua"; this.log(" > req : " + req2); httpPost('http://' + this.Ip + '/data.lua',req2, { headers: this.headers, }, (error, response) => { if (error) log(error, 'error'); if (this.Debugging){ this.log(" > response : \n" + response.data); } this.log("Change done. Check your FB / Device if it worked :-)"); this.Liste.delete(this.Device); this.CheckListe(); if (this.CreateList) { this.getFbDeviceFilterList(); } }); } getFbDeviceFilterList() { this.log("function getFbDeviceFilterList"); // xhr=1&sid=e2d99419592fb780&lang=de&no_sidrenew=&page=kidLis var req = "xhr=1&sid=" + this.secSid + "&lang=de&no_sidrenew=&page=kidLis"; var match; httpPost('http://' + this.Ip + '/data.lua',req, { headers: this.headers, }, (error, response) => { //if (error) log(error, 'error'); //this.log(response.body); this.JsonList = ""; var tmpDevices = []; var tmpUsage = []; var tmpProfilesId = []; var tmpProfilesName = []; var tmpTimes = []; // TESTING //body = getState("Global.0.Testing.StringValue").val; this.log(" > Decode Device Names") var rx = new RegExp(/class=\"name"\stitle=\"([a-zA-Z0-9 äöüÄÖÜ\-\_\.]*)\"\sdatalabel/g); while ((match = rx.exec(response.data)) != null) { tmpDevices.push(match[1]); } //this.log(" > " + tmpDevices); this.log(" > Decode Device Profile ID"); //rx = new RegExp(/button\s.*?value=\"([a-zA-Z0-9 äöüÄÖÜ]*?)\"/g); rx = new RegExp(/option\svalue=\"([a-zA-Z0-9 äöüÄÖÜ\-]*?)\"\sselected/g); while ((match = rx.exec(response.data)) != null) { tmpProfilesId.push(match[1]); } //this.log(" > " + tmpProfilesId); this.log(" > Decode Device Profile Names"); for (var i = 0; i < tmpProfilesId.length; i++) { for (var j = 0; j < this.secProfileIds.length; j++) { //this.log(tmpProfilesId[i] + " > " + secProfileIds[j]); if (tmpProfilesId[i] == this.secProfileIds[j]){ tmpProfilesName.push(this.secProfileNames[j]); } } } //this.log(" > " + tmpProfilesName); this.log(" > Decode Internetnutzung") rx = new RegExp(/td\sdatalabel=\"[a-zA-Z0-9 äöüÄÖÜ\-]+\"\sclass=\"usage\">(.*?)<\/td>/g); while ((match = rx.exec(response.data)) != null) { var tmp = match[1]; tmp = tmp.replace("<span>", "").replace("<\/span>", ""); tmpUsage.push(tmp); } //this.log(" > " + tmpUsage); this.log(" > Decode Times") rx = new RegExp(/td\sdatalabel=\"[a-zA-Z0-9 äöüÄÖÜ\-]+\"\sclass=\"bar\stime\">(.*?)<\/td>/g); while ((match = rx.exec(response.data)) != null) { var tmp = match[1]; if (tmp.includes("\"")) { tmp = tmp.replace("<span title=\"", ""); tmp = tmp.slice(0, tmp.indexOf("\"")); tmpTimes.push(tmp); } else { tmpTimes.push(tmp); } } //this.log(" > " + tmpTimes); // this.log("Device Count : " + secDeviceIds.length); this.JsonList = "["; for (var i = 0; i < tmpDevices.length; i++) { this.JsonList += "{"; this.JsonList += "\"Device\": \"" + tmpDevices[i] + "\"," this.JsonList += "\"Profile ID\": \"" + tmpProfilesId[i] + "\"," this.JsonList += "\"Profile Name\": \"" + tmpProfilesName[i] + "\"," this.JsonList += "\"Usage\": \"" + tmpUsage[i] + "\"," this.JsonList += "\"Time\": \"" + tmpTimes[i] + "\"" if (i != tmpDevices.length - 1) { this.JsonList += "},"; } else { this.JsonList += "}"; } } this.JsonList += "]"; this.log("DONE : List generated ..."); }); } }; let _FritzBox = new FritzBox("192.168.2.254","user","passwort",true); //_FritzBox.EintagHinzufuegen("TV Schlafzimmer",true); Ich habe oben im Skript die zwei Profile für InternetAn und InternetAus definiert. Daher kann ich mit "TV Schlafzimmer",true das Internet für den FireTV Stick im Schlafzimmer auf einschalten und mit false ausschalten. Ebenfalls sollte berücksichtigt sein, dass Anfragen, die Gleichzeitig kommen, nacheinander abgearbeitet werden. So mal eben 4 Stunden Kopfzerbrechen, nur damit die Kinder nicht Heimlich an Fernsehen und Tablet gucken können. (9 und 12 Jahre). Ich denke, jetzt habe ich wieder die Nase vorn aber es wird nicht lange dauern, dann werden die Kinder diese Sperren auch umgehen können, da bin ich mir sicher. Ein ständiger Wettkampf.
  • Skript läuft plötzlich nicht mehr

    28
    0 Votes
    28 Posts
    1k Views
    OliverIOO
    @hotspot_2 sagte in Skript läuft plötzlich nicht mehr: Auch wann es sinnvoll ist Helper (functions) anzulegen und wann nicht. Das geht in die richtige Richtung und ich lerne auch was dabei. hardcore sprach-stilisten wollen eine funktion nicht mehr wie 10-20 Zeilen lang + Dokumentation. Nur dann bleibt der code für jemanden 3.wartbar oder auch für dich wenn du nach einem Jahr wieder drauf schauen musst. d.h. Funktionen entsprechend unterteilen. Dann gäbe es noch die Steuerungsschicht (wo nur die Logik hinterlegt ist) und dann die eigentliche Funktionsebene, anhand der die Steuerungsschicht entscheidet wohin es hingeht und welche Ergebnisse wie verarbeitet werden. Aber das ist dann schon sehr Theorie
  • [erledigt]Skript zum Einsammeln von Batteriestatus von ...

    17
    1
    0 Votes
    17 Posts
    692 Views
    M
    hier mein Skript - chatgpt hat mit draufgeschaut - ich schließe hier. // ===== Einstellungen ===== const OUT = "0_userdata.0.vis.BatterieListeDebug"; // Datenpunkt für VIS const THRESH_LOW = 30; const THRESH_MED = 60; const MAX_HEIGHT = 660; const WIDTH = 405; // Gesamtbreite const STALE_HOURS = 168; // >7 Tage ohne Meldung = "nicht aktiv" // === Helfer === function colorByVal(v) { if (!isFinite(v)) return "#9e9e9e"; if (v < THRESH_LOW) return "#e53935"; // rot if (v < THRESH_MED) return "#fdd835"; // gelb return "#43a047"; // grün } function devRoot(id) { const p = id.split("."); return [p[0], p[1], p[2]].join("."); } function niceNameFromRoot(rootId) { const obj = getObject(rootId); return obj?.common?.name || rootId; } function voltageToPercent(v) { if (!isFinite(v)) return null; const min = 2.0, max = 3.0; let pct = ((v - min) / (max - min)) * 100; return Math.max(0, Math.min(100, Math.round(pct))); } // Liefert den letzten Änderungszeitpunkt aller States eines Geräts function lastSeenDevice(root) { let last = 0; $('' + root + '.*').each(id => { const st = getState(id); if (st && st.lc && st.lc > last) last = st.lc; }); return last; } // === Rendering === function render() { const map = {}; // Zigbee: echte % $('zigbee.0.*.battery').each(id => { const root = devRoot(id); const name = niceNameFromRoot(root); const raw = getState(id)?.val; const val = isFinite(raw) ? Math.max(0, Math.min(100, Math.round(Number(raw)))) : null; if (val !== null) map[root] = { type: "percent", name, val, sys: "Zigbee" }; }); // HmIP: Operating Voltage -> % $('hm-rpc.0.*.OPERATING_VOLTAGE').each(id => { const root = devRoot(id); const name = niceNameFromRoot(root); const val = voltageToPercent(getState(id)?.val); if (val !== null) map[root] = { type: "percent", name, val, sys: "HmIP" }; }); // Homematic: LOWBAT $('hm-rpc.0.*.LOWBAT').each(id => { const root = devRoot(id); const name = niceNameFromRoot(root); const lowbat = !!(getState(id)?.val); const unreach = !!(getState(root + ".0.UNREACH")?.val); const last = lastSeenDevice(root); const ageH = (Date.now() - last) / (1000 * 60 * 60); if (unreach) { map[root] = { type: "unreach", name, sys: "HM" }; } else if (ageH > STALE_HOURS) { map[root] = { type: "stale", name, sys: "HM" }; } else { map[root] = { type: "lowbat", name, lowbat, sys: "HM" }; } }); // Homematic: LOW_BAT $('hm-rpc.0.*.LOW_BAT').each(id => { const root = devRoot(id); const name = niceNameFromRoot(root); const lowbat = !!(getState(id)?.val); const unreach = !!(getState(root + ".0.UNREACH")?.val); const last = lastSeenDevice(root); const ageH = (Date.now() - last) / (1000 * 60 * 60); if (unreach) { map[root] = { type: "unreach", name, sys: "HmIP" }; } else if (ageH > STALE_HOURS) { map[root] = { type: "stale", name, sys: "HmIP" }; } else { map[root] = { type: "lowbat", name, lowbat, sys: "HmIP" }; } }); // Liste bauen let list = Object.values(map); // Sortierung (angepasst) list.sort((a, b) => { function weight(it) { if (it.type === "unreach") return 0; // HM keine Meldung if (it.type === "percent" && it.sys === "Zigbee" && it.val === 0) return 1; // Zigbee 0% if (it.type === "stale") return 2; // HM nicht aktiv if (it.type === "percent" && it.sys === "Zigbee" && it.val < THRESH_LOW) return 3; // Zigbee rot if (it.type === "lowbat" && it.lowbat === true) return 4; // HM low if (it.type === "percent" && it.sys === "Zigbee" && it.val < THRESH_MED) return 5; // Zigbee gelb if (it.type === "percent" && it.sys === "Zigbee" && it.val >= THRESH_MED) return 6; // Zigbee grün if (it.type === "lowbat" && it.lowbat === false) return 7; // HM grün return 99; } const wa = weight(a), wb = weight(b); if (wa !== wb) return wa - wb; // Falls gleiche Kategorie: nach Wert sortieren if (a.type === "percent" && b.type === "percent") { if (a.val == null) return 1; if (b.val == null) return -1; return a.val - b.val; } return 0; }); // Zeilen bauen const rows = list.map(it => { if (it.type === "percent") { return ` <tr style="border-bottom:1px solid #444;"> <td style="width:55px; color:#f5f5f5;">${it.sys}</td> <td style="width:120px; color:#f5f5f5; font-size:12px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" title="${it.name}">${it.name}</td> <td style="width:55px; text-align:right; color:#f5f5f5;">${it.val == null ? "-" : it.val + " %"}</td> <td style="width:175px;"> <div style="width:100%; height:10px; border-radius:5px; background:#333; overflow:hidden;"> <div style="height:100%; width:${it.val ?? 0}%; background:${colorByVal(it.val)};"></div> </div> </td> </tr>`; } if (it.type === "lowbat") { const ok = it.lowbat === false; const color = ok ? "#43a047" : "#e53935"; const text = ok ? "OK" : "LOW"; return ` <tr style="border-bottom:1px solid #444;"> <td style="width:55px; color:#f5f5f5;">${it.sys}</td> <td style="width:120px; color:#f5f5f5; font-size:12px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" title="${it.name}">${it.name}</td> <td style="width:55px; text-align:right; color:#f5f5f5;">–</td> <td style="width:175px; color:${color}; font-weight:bold;">${text}</td> </tr>`; } if (it.type === "unreach") { return ` <tr style="border-bottom:1px solid #444;"> <td style="width:55px; color:#f5f5f5;">${it.sys}</td> <td style="width:120px; color:#f5f5f5; font-size:12px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" title="${it.name}">${it.name}</td> <td style="width:55px; text-align:right; color:#f5f5f5;">–</td> <td style="width:175px; color:#ff9800; font-weight:bold;">KEINE MELDUNG</td> </tr>`; } if (it.type === "stale") { return ` <tr style="border-bottom:1px solid #444;"> <td style="width:55px; color:#f5f5f5;">${it.sys}</td> <td style="width:120px; color:#f5f5f5; font-size:12px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" title="${it.name}">${it.name}</td> <td style="width:55px; text-align:right; color:#f5f5f5;">–</td> <td style="width:175px; color:#ff5722; font-weight:bold;">NICHT AKTIV</td> </tr>`; } }).join(""); // HTML mit sticky Header const html = ` <div style="font-family: system-ui, Segoe UI, Roboto, Arial; font-size:13px; width:${WIDTH}px; max-height:${MAX_HEIGHT}px; overflow-y:auto; padding:0; background:transparent;"> <table style="width:${WIDTH}px; border-collapse:collapse; background:transparent;"> <thead style="background:#212121;"> <tr style="border-bottom:1px solid #666;"> <th style="width:55px; text-align:left; color:#f5f5f5; position:sticky; top:0; background:#212121;">Typ</th> <th style="width:120px; text-align:left; color:#f5f5f5; position:sticky; top:0; background:#212121;">Gerät</th> <th style="width:55px; text-align:right; color:#f5f5f5; position:sticky; top:0; background:#212121;">Batterie</th> <th style="width:175px; text-align:left; color:#f5f5f5; position:sticky; top:0; background:#212121;">Status</th> </tr> </thead> <tbody>${rows}</tbody> </table> </div>`; setState(OUT, html, true); } // === Setup === createState(OUT, "", { type: "string", role: "html", read: true, write: false }, () => { render(); $('zigbee.0.*.battery').each(id => on({ id, change: "ne" }, render)); $('hm-rpc.0.*.OPERATING_VOLTAGE').each(id => on({ id, change: "ne" }, render)); $('hm-rpc.0.*.LOWBAT').each(id => on({ id, change: "ne" }, render)); $('hm-rpc.0.*.LOW_BAT').each(id => on({ id, change: "ne" }, render)); $('hm-rpc.0.*.UNREACH').each(id => on({ id, change: "ne" }, render)); // Refresh alle 12 Stunden schedule("0 */12 * * *", render); }); [image: 1759269909407-6b5592ae-b6ff-4685-8d3d-b1c59447e64e-grafik.png] Tabelle ist html und lässt sich scrollen in meiner VIS
  • Cronjob läuft nicht

    5
    0 Votes
    5 Posts
    244 Views
    CodierknechtC
    @pseudoreal sagte in Cronjob läuft nicht: Ich habe einfach den Wizard genutzt... Der generiert Dir lediglich die korrekte Syntax den CRON ... mehr nicht. Das muss natürlich dann noch in ein passendes Schedule eingebaut werden, wie es @paul53 gezeigt hat.
  • Frage zum Log

    4
    1
    0 Votes
    4 Posts
    200 Views
    M-A HuebM
    @homoran danke genau das hab ich gemeint
  • ecoflow-connector-Script zur dynamischen Leistungsanpassung

    Moved
    2k
    3
    7 Votes
    2k Posts
    752k Views
    eric ch.E
    Guten Tag, Glückwunsch zu all der geleisteten Arbeit. Ich habe einen STREAM von Ecoflow. Glauben Sie, dass es möglich ist, die Solarproduktion zu regulieren? Das Gerät ist neuer, und ich habe den Eindruck, dass es weniger zugänglich ist als der POWERSTREAM.
  • Unterscheiden Manuelle Bedienung von automatischer

    4
    0 Votes
    4 Posts
    289 Views
    D
    @paul53 Danke alle Sorry dass ich erst jetzt antworte, aber ich habe keine Mail bekommen dass jemand geantwortet hat. Ich versuch mich mal dran Gruss Ralf
  • Servicemeldungen - All inclusive für Homematic -

    Moved javascript
    1k
    2
    12 Votes
    1k Posts
    326k Views
    hg6806H
    Moin zusammen, ich nutze das Script auch seit einigen Jahren und lief immer problemlos. Doch neuerdings häufen sich Meldungen wegen gestörter Kommunikation, die dann aber auch gleich wieder gelöscht werden. Da ich so gar kein Programmierer bin, tue ich mich immer schwer sich wieder damit zu befassen. Wo kann ich diese Meldungen löschen, damit sie nicht aufpoppen? Auf Github ist V1.59, ich habe 1.86. Woher bekomm ich also das neuste wenn es was neueres gibt? Auf "Volume2" wollte ich aus Zeitgründen nicht gehen.
  • Integration einer Ambientika-Lüftungsanlage

    5
    0 Votes
    5 Posts
    339 Views
    J
    @djlex Hallo, ich habe deine Anpassung von Home Assistant an den iobroker hier gefunden. Kannst du auch die Datenpunkte über die API schreiben? Was bietet die API noch für Datenpunkte? Gibt es dazu eine Übersicht? Grüße
  • Alexa Quittierungston (Ping bzw. "Okay") killen

    5
    0 Votes
    5 Posts
    239 Views
    N
    @negalein oha das ist mal fies haha - ich versuche jetzt gerade nur noch das ducking zu deaktivieren - alexa reduziert leider 15 Sekunden lang die Lautstärke des Sonos Gerätes - nicht so schön
  • Sonoff Geräte als HTML Tabelle - Vis

    javascript monitoring template
    632
    4
    8 Votes
    632 Posts
    137k Views
    blue231181B
    @liv-in-sky Hat funktioniert, vielen Dank
  • Javascript für Textoverlay Hikvision Kamera

    1
    1
    0 Votes
    1 Posts
    170 Views
    No one has replied
  • Kamera Statusauswertung und Meldung an Homematic

    16
    0 Votes
    16 Posts
    392 Views
    M
    @homoran ja das passt, danke ab dem 2. Element gibt es immer 3 führende Leerzeichen

602

Online

32.5k

Users

81.6k

Topics

1.3m

Posts