NEWS
js-controller 4.0 jetzt im BETA/LATEST!
-
Ok, mit letzten kleineren Optimierungen rollte die 4.0.12 an (Stable RC3):
4.0.12 (2022-02-17)
- (Apollon77) make sure to really end CLI process when they should end in error cases
- (Apollon77) catch error when streaming data to stdout and this is closed already
Also alle "stoppedList"-Fehler bei CLI Kommandos sollten jetzt weg sein, bitte generell gern nochmal CLI Kommandos testen
-
@dolomiti Das hat nichts mit dem Controller zu tun. Das liegt an Nodejs 14 und scheinbar einer "alten" version von node-red der eine buggy mongodb version enthalten hat und diese verursacht diese Fejhler. ALso bitte node-red aktualisieren
@apollon77 sagte in js-controller 4.0 jetzt im BETA/LATEST!:
@dolomiti Das hat nichts mit dem Controller zu tun. Das liegt an Nodejs 14 und scheinbar einer "alten" version von node-red der eine buggy mongodb version enthalten hat und diese verursacht diese Fejhler. ALso bitte node-red aktualisieren
Node-Red war aktuell bei 2.4.2. Habe es jetzt mal deinstalliert, dann war der Fehler weg. Nach Neuinstallation von 2.4.2 aus dem latest-Zweig, als auch 2.4.1 aus dem stable-Zweig ist die Meldung wieder da.
Soll ich ein Issue bei Node-Red-Adapter machen?Gruß
Dolomiti
-
@apollon77 Update lief ohne OOM oder ähnliches durch. Danach noch backitup Adapter in der GUI aktualisiert, aber auch das ohne Auffälligkeiten.
-
@apollon77 sagte in js-controller 4.0 jetzt im BETA/LATEST!:
@dolomiti Das hat nichts mit dem Controller zu tun. Das liegt an Nodejs 14 und scheinbar einer "alten" version von node-red der eine buggy mongodb version enthalten hat und diese verursacht diese Fejhler. ALso bitte node-red aktualisieren
Node-Red war aktuell bei 2.4.2. Habe es jetzt mal deinstalliert, dann war der Fehler weg. Nach Neuinstallation von 2.4.2 aus dem latest-Zweig, als auch 2.4.1 aus dem stable-Zweig ist die Meldung wieder da.
Soll ich ein Issue bei Node-Red-Adapter machen?Gruß
Dolomiti
-
Ok, mit letzten kleineren Optimierungen rollte die 4.0.12 an (Stable RC3):
4.0.12 (2022-02-17)
- (Apollon77) make sure to really end CLI process when they should end in error cases
- (Apollon77) catch error when streaming data to stdout and this is closed already
Also alle "stoppedList"-Fehler bei CLI Kommandos sollten jetzt weg sein, bitte generell gern nochmal CLI Kommandos testen
@apollon77 sagte in js-controller 4.0 jetzt im BETA/LATEST!:
Ok, mit letzten kleineren Optimierungen rollte die 4.0.12 an (Stable RC3):
4.0.12 auf Master und Slave erfolgreich aktualisiert und keine Probleme beim starten.
-
Ok, mit letzten kleineren Optimierungen rollte die 4.0.12 an (Stable RC3):
4.0.12 (2022-02-17)
- (Apollon77) make sure to really end CLI process when they should end in error cases
- (Apollon77) catch error when streaming data to stdout and this is closed already
Also alle "stoppedList"-Fehler bei CLI Kommandos sollten jetzt weg sein, bitte generell gern nochmal CLI Kommandos testen
@apollon77 verlief fehlerfrei incl. backitup update:wink:
nur das ich jetzt wieder die doppelt CPU Auslastung habe -
@apollon77 verlief fehlerfrei incl. backitup update:wink:
nur das ich jetzt wieder die doppelt CPU Auslastung habe -
@crunchip und welcher Prozess ist es? Vllt solltest du dich mal einige Host und Adapter States mit History mitloggen das du genauer sagen kannst was sich wann wie anders verhält.
@apollon77 glaub ich hab das Problem schon gefunden, scheint an javascript zu liegen, bzw eher ein Script, das Wetterwarn Script https://forum.iobroker.net/topic/30616/script-dwd-uwz-nina-warnungen-als-push-sprachnachrichten/
das war das einzige was ich die Tage aktualisiert hatte. Wenn ich das deaktiviere, geht die CPU runter
Edit
Bei der Javascript Instanz lagen die Ein/Ausgänge bei ~3500/~1000 nach dem iobroker gestartet wurde -
@apollon77 glaub ich hab das Problem schon gefunden, scheint an javascript zu liegen, bzw eher ein Script, das Wetterwarn Script https://forum.iobroker.net/topic/30616/script-dwd-uwz-nina-warnungen-als-push-sprachnachrichten/
das war das einzige was ich die Tage aktualisiert hatte. Wenn ich das deaktiviere, geht die CPU runter
Edit
Bei der Javascript Instanz lagen die Ein/Ausgänge bei ~3500/~1000 nach dem iobroker gestartet wurde -
@crunchip ok. Na dann viel Spaß beim weiter forschen ;-)
Eingehend JavaScript ist immer seh hoch weil ja alles rein geht bei Standard Konfiguration. Aber 1000 ausgehende ist ne Menge ;-) (ist eine 15s Messung) ;-)
@apollon77 script ist in arbeit,
wenns normal läuft liegt die Instanz im Schnitt bei 1000/14 -
@apollon77 script ist in arbeit,
wenns normal läuft liegt die Instanz im Schnitt bei 1000/14@crunchip said in js-controller 4.0 jetzt im BETA/LATEST!:
@apollon77 script ist in arbeit,
wenns normal läuft liegt die Instanz im Schnitt bei 1000/14ich hab 3 JavaScript Instanzen. bei 2 davon geb ich dir recht mit
-) 5680/11
-) 5702/11
aber bei der dritten
-) 5386/2642 -
@diginix sagte in js-controller 4.0 jetzt im BETA/LATEST!:
Alle in/out aller 47 Instanzen ging als Screenshot am einfachsten:
https://www.dropbox.com/s/ceafuk51rhv0om2/2022-02-17_in_out_adapter.png?dl=0Auf der Instanzübersicht wärs etwas kompakter gewesen :)

Naja gut, sieht jetzt aber nicht überlastet aus... Bin mal auf den RAM gespannt.
@alcalzone sagte in js-controller 4.0 jetzt im BETA/LATEST!:
Naja gut, sieht jetzt aber nicht überlastet aus... Bin mal auf den RAM gespannt.
iobroker start nach js-controller Update auf 4.0.12. Wobei die Ver. wahrs. egal ist. Aber der js-controller nimmt sich da fast 3min 2 GB RAM. Da ist klar warum der bei sonst <1GB freien RAM der VM vom OOM abgeschossen wurde.

States in/out ist dabei unspektakulär.
-
@crunchip said in js-controller 4.0 jetzt im BETA/LATEST!:
@apollon77 script ist in arbeit,
wenns normal läuft liegt die Instanz im Schnitt bei 1000/14ich hab 3 JavaScript Instanzen. bei 2 davon geb ich dir recht mit
-) 5680/11
-) 5702/11
aber bei der dritten
-) 5386/2642@homecineplexx sagte in js-controller 4.0 jetzt im BETA/LATEST!:
-) 5386/2642
Naja dann hast Du in der dritten ein Skript laufen was sehr viele "setState" oder andere Aktionen macht ... Wenn das so soll ist ja alles in Ordnung :-)
-
@alcalzone sagte in js-controller 4.0 jetzt im BETA/LATEST!:
Naja gut, sieht jetzt aber nicht überlastet aus... Bin mal auf den RAM gespannt.
iobroker start nach js-controller Update auf 4.0.12. Wobei die Ver. wahrs. egal ist. Aber der js-controller nimmt sich da fast 3min 2 GB RAM. Da ist klar warum der bei sonst <1GB freien RAM der VM vom OOM abgeschossen wurde.

States in/out ist dabei unspektakulär.
@diginix sagte in js-controller 4.0 jetzt im BETA/LATEST!:
iobroker start nach js-controller Update auf 4.0.12. Wobei die Ver. wahrs. egal ist. Aber der js-controller nimmt sich da fast 3min 2 GB RAM. Da ist klar warum der bei sonst <1GB freien RAM der VM vom OOM abgeschossen wurde.
D.h. der Peak ist der Controller-Start? Wenn ja, magst du mir mal deine objects.jsonl, states.jsonl und iobroker.json schicken, dass ich das nachstellen kann? Schick dir nen Upload-Link per PN.
-
@alcalzone sagte in js-controller 4.0 jetzt im BETA/LATEST!:
Naja gut, sieht jetzt aber nicht überlastet aus... Bin mal auf den RAM gespannt.
iobroker start nach js-controller Update auf 4.0.12. Wobei die Ver. wahrs. egal ist. Aber der js-controller nimmt sich da fast 3min 2 GB RAM. Da ist klar warum der bei sonst <1GB freien RAM der VM vom OOM abgeschossen wurde.

States in/out ist dabei unspektakulär.
-
@diginix sagte in js-controller 4.0 jetzt im BETA/LATEST!:
iobroker start nach js-controller Update auf 4.0.12. Wobei die Ver. wahrs. egal ist. Aber der js-controller nimmt sich da fast 3min 2 GB RAM. Da ist klar warum der bei sonst <1GB freien RAM der VM vom OOM abgeschossen wurde.
D.h. der Peak ist der Controller-Start? Wenn ja, magst du mir mal deine objects.jsonl, states.jsonl und iobroker.json schicken, dass ich das nachstellen kann? Schick dir nen Upload-Link per PN.
@alcalzone sagte in js-controller 4.0 jetzt im BETA/LATEST!:
@diginix sagte in js-controller 4.0 jetzt im BETA/LATEST!:
iobroker start nach js-controller Update auf 4.0.12. Wobei die Ver. wahrs. egal ist. Aber der js-controller nimmt sich da fast 3min 2 GB RAM. Da ist klar warum der bei sonst <1GB freien RAM der VM vom OOM abgeschossen wurde.
D.h. der Peak ist der Controller-Start? Wenn ja, magst du mir mal deine objects.jsonl, states.jsonl und iobroker.json schicken, dass ich das nachstellen kann? Schick dir nen Upload-Link per PN.
Ja der peak war bei/ab "iobroker start" nach dem js-controller Update auf 4.0.12.
Dateien sende ich dir.
-
@alcalzone sagte in js-controller 4.0 jetzt im BETA/LATEST!:
@diginix sagte in js-controller 4.0 jetzt im BETA/LATEST!:
iobroker start nach js-controller Update auf 4.0.12. Wobei die Ver. wahrs. egal ist. Aber der js-controller nimmt sich da fast 3min 2 GB RAM. Da ist klar warum der bei sonst <1GB freien RAM der VM vom OOM abgeschossen wurde.
D.h. der Peak ist der Controller-Start? Wenn ja, magst du mir mal deine objects.jsonl, states.jsonl und iobroker.json schicken, dass ich das nachstellen kann? Schick dir nen Upload-Link per PN.
Ja der peak war bei/ab "iobroker start" nach dem js-controller Update auf 4.0.12.
Dateien sende ich dir.
-
@homecineplexx sagte in js-controller 4.0 jetzt im BETA/LATEST!:
-) 5386/2642
Naja dann hast Du in der dritten ein Skript laufen was sehr viele "setState" oder andere Aktionen macht ... Wenn das so soll ist ja alles in Ordnung :-)
@apollon77 said in js-controller 4.0 jetzt im BETA/LATEST!:
@homecineplexx sagte in js-controller 4.0 jetzt im BETA/LATEST!:
-) 5386/2642
Naja dann hast Du in der dritten ein Skript laufen was sehr viele "setState" oder andere Aktionen macht ... Wenn das so soll ist ja alles in Ordnung :-)
ich hab hier einfach viele solcher Skripte am laufen, die mir quasi einen Alias machen und bissl mehr noch.
Vielleicht könnte man diese ja auch vereinfachen...?var preNameSpace = 'VirtualDevice.0.'; //generic virtual device function VirtualDevice(config) { //sanity check if (typeof config !== 'object' || typeof config.namespace !== 'string' || typeof config.name !== 'string' || typeof config.states !== 'object') { log('sanity check failed, no device created', 'warn'); return; } this.config = config; this.namespace = preNameSpace + config.namespace + '.' + config.name; this.name = config.name; //create virtual device log('creating virtual device ' + this.namespace); this.createDevice(function () { this.createStates(function () { log('created virtual device ' + this.namespace); }.bind(this)); }.bind(this)); } VirtualDevice.prototype.createDevice = function (callback) { log('creating object for device ' + this.namespace, 'debug'); //create device object var obj = this.config.copy ? getObject(this.config.copy) : {common: {}, native: {}}; delete obj.common.custom; if (typeof this.config.common === 'object') { obj.common = Object.assign(obj.common, this.config.common); } if (typeof this.config.native === 'object') { obj.native = Object.assign(obj.native, this.config.native); } extendObject(this.namespace, { //type: "device", type: "channel", common: obj.common, native: obj.native }, function (err) { if (err) { log('could not create virtual device: ' + this.namespace, 'warn'); return; } log('created object for device ' + this.namespace, 'debug'); if (typeof this.config.onCreate === 'function') { this.config.onCreate(this, callback); } else { callback(); } }.bind(this)); }; VirtualDevice.prototype.createStates = function (callback) { "use strict"; log('creating states for device ' + this.namespace, 'debug'); var stateIds = Object.keys(this.config.states); log('creating states ' + JSON.stringify(stateIds), 'debug'); var countCreated = 0; for (var i = 0; i < stateIds.length; i++) { let stateId = stateIds[i]; this.normalizeState(stateId); var id = this.namespace + '.' + stateId; log('creating state ' + id, 'debug'); var obj = this.config.states[stateId].copy ? getObject(this.config.states[stateId].copy) : { type: "state", common: {}, native: {} }; delete obj.common.custom; if (typeof this.config.states[stateId].common === 'object') { obj.common = Object.assign(obj.common, this.config.states[stateId].common); } if (typeof this.config.states[stateId].native === 'object') { obj.native = Object.assign(obj.native, this.config.states[stateId].native); } setObject(id, obj, function(err, checkObj) { if (err) { log('skipping creation of state ' + id, 'debug'); } else { log('created state ' + id, 'debug'); } if (!err && checkObj) { //setTimeout(function(){ this.connectState(stateId); countCreated++; if (countCreated >= stateIds.length) { log('created ' + countCreated + ' states for device ' + this.namespace, 'debug'); callback(); } var newId = checkObj.id; var helper = newId.substr(newId.lastIndexOf('.') + 1, newId.length); var stateValueNew = this.config.states[helper].stateValue; if (stateValueNew !== undefined) { setStateDelayed(newId, stateValueNew, true, 1000); log('set default: ' + stateValueNew + ' for ' + newId); } //}.bind(this), 500); } }.bind(this)); } }; VirtualDevice.prototype.normalizeState = function (state) { log('normalizing state ' + state, 'debug'); if (typeof this.config.states[state].read !== 'object') { this.config.states[state].read = {}; } if (typeof this.config.states[state].write !== 'object') { this.config.states[state].write = {}; } var readIds = Object.keys(this.config.states[state].read); for (var i = 0; i < readIds.length; i++) { var readId = this.config.states[state].read[readIds[i]]; if (typeof readId.before !== 'function') { this.config.states[state].read[readIds[i]].before = function (device, value, callback) { callback(); }; } if (typeof readId.after !== 'function') { this.config.states[state].read[readIds[i]].after = function (device, value) { }; } } var writeIds = Object.keys(this.config.states[state].write); for (i = 0; i < writeIds.length; i++) { var writeId = this.config.states[state].write[writeIds[i]]; if (typeof writeId.before !== 'function') { this.config.states[state].write[writeIds[i]].before = function (device, value, callback) { callback() }; } if (typeof writeId.after !== 'function') { this.config.states[state].write[writeIds[i]].after = function (device, value) { }; } } log('normalized state ' + state, 'debug'); }; VirtualDevice.prototype.connectState = function (state) { setTimeout(function(){ log('connecting state ' + state, 'debug'); var id = this.namespace + '.' + state; //subscribe to read ids var readIds = Object.keys(this.config.states[state].read); for (var i = 0; i < readIds.length; i++) { if (readIds[i] === null || readIds[i] === undefined || readIds[i] === '') { continue; } if (getState(readIds[i]).notExist === true) { //check if state exists log('cannot connect to not existing state: ' + readIds[i], 'warn'); continue; } var readObj = this.config.states[state].read[readIds[i]]; var trigger = readObj.trigger || {change: 'any'}; trigger.ack = true; trigger.id = readIds[i]; this.subRead(trigger, readObj, state); log('connected ' + readIds[i] + ' to ' + id, 'debug'); } //subscribe to this state and write to write ids var writeIds = Object.keys(this.config.states[state].write); var trigger = {id: this.namespace + '.' + state, change: 'any', ack: false}; on(trigger, function (obj) { "use strict"; log('detected change of ' + state, 'debug'); for (var i = 0; i < writeIds.length; i++) { let writeObj = this.config.states[state].write[writeIds[i]]; let val = this.convertValue(obj.state.val, writeObj.convert); let writeId = writeIds[i]; log('executing function before for ' + writeId, 'debug'); writeObj.before(this, val, function (newVal, newDelay) { if (newVal !== undefined && newVal !== null) val = newVal; var delay = writeObj.delay; if (newDelay !== undefined && newDelay !== null) delay = newDelay; log(newVal + 'writing value ' + val + ' to ' + writeId + ' with delay ' + delay, 'debug'); setStateDelayed(writeId, val, false, delay || 0, true, function () { log('executing function after for ' + writeId, 'debug'); writeObj.after(this, val); }.bind(this)); }.bind(this)); } }.bind(this)); log('connected ' + state + ' to ' + JSON.stringify(writeIds), 'debug'); }.bind(this), 500); }; VirtualDevice.prototype.subRead = function (trigger, readObj, state) { var func = function (obj) { var val = this.convertValue(obj.state.val, readObj.convert); log('executing function before for ' + trigger.id, 'debug'); readObj.before(this, val, function (newVal, newDelay) { if (newVal !== undefined && newVal !== null) val = newVal; if (newDelay !== undefined && newDelay !== null) writeObj.delay = newDelay; log('reading value ' + val + ' to ' + this.namespace + '.' + state, 'debug'); setStateDelayed(this.namespace + '.' + state, val, true, readObj.delay || 0, true, function () { log('executing function after for ' + trigger.id, 'debug'); readObj.after(this, val); }.bind(this)); }.bind(this)); }.bind(this); func({state: getState(trigger.id)}); on(trigger, func); }; VirtualDevice.prototype.convertValue = function (val, func) { if (typeof func !== 'function') { return val; } return func(val); }; var deviceId = 'Deckenlicht'; var namespace = 'Ankleide'; var path = preNameSpace + namespace + '.' + deviceId; new VirtualDevice({ namespace: namespace, name: deviceId, states: { 'name': { common: {name: 'name', role: 'text', type: 'string', desc: 'name', read: true, write: false, def: namespace + ' - ' + deviceId}, stateValue: namespace + ' - ' + deviceId }, 'isTelegramInfo': { common: {name: 'TelegramInfo wird durch JavaScript gesetzt', role: 'state', type: 'boolean', desc: 'TelegramInfo', read: true, write: true, def: true}, stateValue: true }, 'isTelegramInfoSwitch': { common: {name: 'TelegramInfo wird durch JavaScript gesetzt', role: 'state', type: 'boolean', desc: 'TelegramInfo', read: true, write: true, def: true}, stateValue: true }, 'switch': { common: {name: 'switch', role: 'switch', type: 'boolean', desc: 'switch', def: false, read: true, write: true, custom: { 'influxdb.0': { 'enabled': true, 'changesOnly': true, 'debounce': 0, 'maxLength': 10, 'retention': 0, 'changesRelogInterval': 30, 'changesMinDelta': 0, 'storageType': '', 'aliasId': '' } } }, read: { 'mqtt.0.shellies.shelly1-555EDB.relay.0': { convert: function (val) { if (val == 'on') { val = true; } else { val = false; } return val; }, trigger: setTimeout(function(){ on({id:path + '.switch', change: 'ne'}, function (obj) { if (getState(path + '.isTelegramInfoSwitch').val === true) { var value = obj.state.val; var name = getState(path + '.name').val; _sendLogToTelegram(_findCorrectEmoji(name + ' wurde ' + (value === true ? 'eingeschaltet.' : 'ausgeschaltet.'))); } }) }, 500) }, }, write: { 'mqtt.0.shellies.shelly1-555EDB.relay.0.command': { convert: function (val) { if (val === true) { val ='on'; } else { val = 'off'; } return val; }, }, } }, 'online': { common: {name: 'online', role: 'variable', type: 'boolean', desc: 'online', read: true, write: false, def: false, custom: { 'influxdb.0': { 'enabled': true, 'changesOnly': true, 'debounce': 0, 'maxLength': 10, 'retention': 0, 'changesRelogInterval': 30, 'changesMinDelta': 0, 'storageType': '', 'aliasId': '' } } }, read: { 'mqtt.0.shellies.shelly1-555EDB.online': { trigger: setTimeout(function(){ on({id:path + '.online', change: 'ne'}, function (obj) { var value = obj.state.val; if (value === false) { setState('AllOwnCreated.0.shelly.isWrongState', true); } if (getState(path + '.isTelegramInfo').val === true) { var name = getState(path + '.name').val; _sendLogToTelegram(_findCorrectEmoji('OnlineStatus: ' + name + ' ist ' + (value === true ? 'wieder' : 'nicht') + ' erreichbar.')); } }) }, 500) }, }, write: {} }, 'command': { common: {name: 'command', role: 'variable', type: 'string', desc: 'command', read: true, write: true, def: ''}, read: { 'mqtt.0.shellies.shelly1-555EDB.command': {}, }, write: { 'mqtt.0.shellies.shelly1-555EDB.command': { }, } }, 'announce': { common: {name: 'announce', role: 'variable', type: 'string', desc: 'announce', read: true, write: false, def: ''}, read: { 'mqtt.0.shellies.shelly1-555EDB.announce': { convert: function (val) { var jsonValue = JSON.parse(val); calculateJson(jsonValue, 'Info'); return val; }, }, }, }, 'info': { common: {name: 'info', role: 'variable', type: 'string', desc: 'info', read: true, write: false, def: ''}, read: { 'mqtt.0.shellies.shelly1-555EDB.info': {}, }, }, } }); function calculateJson(jsonValue, subFolder) { for (var key in jsonValue) { if (jsonValue.hasOwnProperty(key)) { try { var jsonNewValue = JSON.parse(jsonValue[key]); calculateJson(jsonNewValue) } catch (e) { if (typeof jsonValue[key] == 'object') { for (var item in jsonValue[key]) { //var commonType = getCommonType(item); var commonType = null; doCreateStates(path + '.' + subFolder +'.' + item, item, jsonValue[key][item], commonType) } } else { doCreateStates(path + '.' + subFolder + '.' + key, key, jsonValue[key]) } } } } } function doCreateStates(newObject, name, value, commonType) { var obj = getObject(newObject); if (commonType == undefined) { commonType = {'name': name, 'role': 'state', 'type': 'string', desc: name, read: true, write: false, def: ''}; } if (commonType['type'] == 'number') { } else { value = '' + value; } if (!obj) { setObject(newObject, { type: 'state', common: commonType, native: {} }, function(err, obj) { if (!err && obj) { console.log('Object for ' + obj.id + ' created'); setState(newObject, value, true); } }); } else { setState(newObject, value, true); } if (name == 'LWT') { setTimeout(function() { on({id:newObject, change: 'ne'}, function (obj) { if (getState(path + '.isTelegramInfo').val === true) { var value = obj.state.val; var name = getState(path + '.name').val; _sendLogToTelegram(_findCorrectEmoji(name + ' wurde neu gestartet. Grund: ' + value)); } }) }, 500) } } -
@apollon77 said in js-controller 4.0 jetzt im BETA/LATEST!:
@homecineplexx sagte in js-controller 4.0 jetzt im BETA/LATEST!:
-) 5386/2642
Naja dann hast Du in der dritten ein Skript laufen was sehr viele "setState" oder andere Aktionen macht ... Wenn das so soll ist ja alles in Ordnung :-)
ich hab hier einfach viele solcher Skripte am laufen, die mir quasi einen Alias machen und bissl mehr noch.
Vielleicht könnte man diese ja auch vereinfachen...?var preNameSpace = 'VirtualDevice.0.'; //generic virtual device function VirtualDevice(config) { //sanity check if (typeof config !== 'object' || typeof config.namespace !== 'string' || typeof config.name !== 'string' || typeof config.states !== 'object') { log('sanity check failed, no device created', 'warn'); return; } this.config = config; this.namespace = preNameSpace + config.namespace + '.' + config.name; this.name = config.name; //create virtual device log('creating virtual device ' + this.namespace); this.createDevice(function () { this.createStates(function () { log('created virtual device ' + this.namespace); }.bind(this)); }.bind(this)); } VirtualDevice.prototype.createDevice = function (callback) { log('creating object for device ' + this.namespace, 'debug'); //create device object var obj = this.config.copy ? getObject(this.config.copy) : {common: {}, native: {}}; delete obj.common.custom; if (typeof this.config.common === 'object') { obj.common = Object.assign(obj.common, this.config.common); } if (typeof this.config.native === 'object') { obj.native = Object.assign(obj.native, this.config.native); } extendObject(this.namespace, { //type: "device", type: "channel", common: obj.common, native: obj.native }, function (err) { if (err) { log('could not create virtual device: ' + this.namespace, 'warn'); return; } log('created object for device ' + this.namespace, 'debug'); if (typeof this.config.onCreate === 'function') { this.config.onCreate(this, callback); } else { callback(); } }.bind(this)); }; VirtualDevice.prototype.createStates = function (callback) { "use strict"; log('creating states for device ' + this.namespace, 'debug'); var stateIds = Object.keys(this.config.states); log('creating states ' + JSON.stringify(stateIds), 'debug'); var countCreated = 0; for (var i = 0; i < stateIds.length; i++) { let stateId = stateIds[i]; this.normalizeState(stateId); var id = this.namespace + '.' + stateId; log('creating state ' + id, 'debug'); var obj = this.config.states[stateId].copy ? getObject(this.config.states[stateId].copy) : { type: "state", common: {}, native: {} }; delete obj.common.custom; if (typeof this.config.states[stateId].common === 'object') { obj.common = Object.assign(obj.common, this.config.states[stateId].common); } if (typeof this.config.states[stateId].native === 'object') { obj.native = Object.assign(obj.native, this.config.states[stateId].native); } setObject(id, obj, function(err, checkObj) { if (err) { log('skipping creation of state ' + id, 'debug'); } else { log('created state ' + id, 'debug'); } if (!err && checkObj) { //setTimeout(function(){ this.connectState(stateId); countCreated++; if (countCreated >= stateIds.length) { log('created ' + countCreated + ' states for device ' + this.namespace, 'debug'); callback(); } var newId = checkObj.id; var helper = newId.substr(newId.lastIndexOf('.') + 1, newId.length); var stateValueNew = this.config.states[helper].stateValue; if (stateValueNew !== undefined) { setStateDelayed(newId, stateValueNew, true, 1000); log('set default: ' + stateValueNew + ' for ' + newId); } //}.bind(this), 500); } }.bind(this)); } }; VirtualDevice.prototype.normalizeState = function (state) { log('normalizing state ' + state, 'debug'); if (typeof this.config.states[state].read !== 'object') { this.config.states[state].read = {}; } if (typeof this.config.states[state].write !== 'object') { this.config.states[state].write = {}; } var readIds = Object.keys(this.config.states[state].read); for (var i = 0; i < readIds.length; i++) { var readId = this.config.states[state].read[readIds[i]]; if (typeof readId.before !== 'function') { this.config.states[state].read[readIds[i]].before = function (device, value, callback) { callback(); }; } if (typeof readId.after !== 'function') { this.config.states[state].read[readIds[i]].after = function (device, value) { }; } } var writeIds = Object.keys(this.config.states[state].write); for (i = 0; i < writeIds.length; i++) { var writeId = this.config.states[state].write[writeIds[i]]; if (typeof writeId.before !== 'function') { this.config.states[state].write[writeIds[i]].before = function (device, value, callback) { callback() }; } if (typeof writeId.after !== 'function') { this.config.states[state].write[writeIds[i]].after = function (device, value) { }; } } log('normalized state ' + state, 'debug'); }; VirtualDevice.prototype.connectState = function (state) { setTimeout(function(){ log('connecting state ' + state, 'debug'); var id = this.namespace + '.' + state; //subscribe to read ids var readIds = Object.keys(this.config.states[state].read); for (var i = 0; i < readIds.length; i++) { if (readIds[i] === null || readIds[i] === undefined || readIds[i] === '') { continue; } if (getState(readIds[i]).notExist === true) { //check if state exists log('cannot connect to not existing state: ' + readIds[i], 'warn'); continue; } var readObj = this.config.states[state].read[readIds[i]]; var trigger = readObj.trigger || {change: 'any'}; trigger.ack = true; trigger.id = readIds[i]; this.subRead(trigger, readObj, state); log('connected ' + readIds[i] + ' to ' + id, 'debug'); } //subscribe to this state and write to write ids var writeIds = Object.keys(this.config.states[state].write); var trigger = {id: this.namespace + '.' + state, change: 'any', ack: false}; on(trigger, function (obj) { "use strict"; log('detected change of ' + state, 'debug'); for (var i = 0; i < writeIds.length; i++) { let writeObj = this.config.states[state].write[writeIds[i]]; let val = this.convertValue(obj.state.val, writeObj.convert); let writeId = writeIds[i]; log('executing function before for ' + writeId, 'debug'); writeObj.before(this, val, function (newVal, newDelay) { if (newVal !== undefined && newVal !== null) val = newVal; var delay = writeObj.delay; if (newDelay !== undefined && newDelay !== null) delay = newDelay; log(newVal + 'writing value ' + val + ' to ' + writeId + ' with delay ' + delay, 'debug'); setStateDelayed(writeId, val, false, delay || 0, true, function () { log('executing function after for ' + writeId, 'debug'); writeObj.after(this, val); }.bind(this)); }.bind(this)); } }.bind(this)); log('connected ' + state + ' to ' + JSON.stringify(writeIds), 'debug'); }.bind(this), 500); }; VirtualDevice.prototype.subRead = function (trigger, readObj, state) { var func = function (obj) { var val = this.convertValue(obj.state.val, readObj.convert); log('executing function before for ' + trigger.id, 'debug'); readObj.before(this, val, function (newVal, newDelay) { if (newVal !== undefined && newVal !== null) val = newVal; if (newDelay !== undefined && newDelay !== null) writeObj.delay = newDelay; log('reading value ' + val + ' to ' + this.namespace + '.' + state, 'debug'); setStateDelayed(this.namespace + '.' + state, val, true, readObj.delay || 0, true, function () { log('executing function after for ' + trigger.id, 'debug'); readObj.after(this, val); }.bind(this)); }.bind(this)); }.bind(this); func({state: getState(trigger.id)}); on(trigger, func); }; VirtualDevice.prototype.convertValue = function (val, func) { if (typeof func !== 'function') { return val; } return func(val); }; var deviceId = 'Deckenlicht'; var namespace = 'Ankleide'; var path = preNameSpace + namespace + '.' + deviceId; new VirtualDevice({ namespace: namespace, name: deviceId, states: { 'name': { common: {name: 'name', role: 'text', type: 'string', desc: 'name', read: true, write: false, def: namespace + ' - ' + deviceId}, stateValue: namespace + ' - ' + deviceId }, 'isTelegramInfo': { common: {name: 'TelegramInfo wird durch JavaScript gesetzt', role: 'state', type: 'boolean', desc: 'TelegramInfo', read: true, write: true, def: true}, stateValue: true }, 'isTelegramInfoSwitch': { common: {name: 'TelegramInfo wird durch JavaScript gesetzt', role: 'state', type: 'boolean', desc: 'TelegramInfo', read: true, write: true, def: true}, stateValue: true }, 'switch': { common: {name: 'switch', role: 'switch', type: 'boolean', desc: 'switch', def: false, read: true, write: true, custom: { 'influxdb.0': { 'enabled': true, 'changesOnly': true, 'debounce': 0, 'maxLength': 10, 'retention': 0, 'changesRelogInterval': 30, 'changesMinDelta': 0, 'storageType': '', 'aliasId': '' } } }, read: { 'mqtt.0.shellies.shelly1-555EDB.relay.0': { convert: function (val) { if (val == 'on') { val = true; } else { val = false; } return val; }, trigger: setTimeout(function(){ on({id:path + '.switch', change: 'ne'}, function (obj) { if (getState(path + '.isTelegramInfoSwitch').val === true) { var value = obj.state.val; var name = getState(path + '.name').val; _sendLogToTelegram(_findCorrectEmoji(name + ' wurde ' + (value === true ? 'eingeschaltet.' : 'ausgeschaltet.'))); } }) }, 500) }, }, write: { 'mqtt.0.shellies.shelly1-555EDB.relay.0.command': { convert: function (val) { if (val === true) { val ='on'; } else { val = 'off'; } return val; }, }, } }, 'online': { common: {name: 'online', role: 'variable', type: 'boolean', desc: 'online', read: true, write: false, def: false, custom: { 'influxdb.0': { 'enabled': true, 'changesOnly': true, 'debounce': 0, 'maxLength': 10, 'retention': 0, 'changesRelogInterval': 30, 'changesMinDelta': 0, 'storageType': '', 'aliasId': '' } } }, read: { 'mqtt.0.shellies.shelly1-555EDB.online': { trigger: setTimeout(function(){ on({id:path + '.online', change: 'ne'}, function (obj) { var value = obj.state.val; if (value === false) { setState('AllOwnCreated.0.shelly.isWrongState', true); } if (getState(path + '.isTelegramInfo').val === true) { var name = getState(path + '.name').val; _sendLogToTelegram(_findCorrectEmoji('OnlineStatus: ' + name + ' ist ' + (value === true ? 'wieder' : 'nicht') + ' erreichbar.')); } }) }, 500) }, }, write: {} }, 'command': { common: {name: 'command', role: 'variable', type: 'string', desc: 'command', read: true, write: true, def: ''}, read: { 'mqtt.0.shellies.shelly1-555EDB.command': {}, }, write: { 'mqtt.0.shellies.shelly1-555EDB.command': { }, } }, 'announce': { common: {name: 'announce', role: 'variable', type: 'string', desc: 'announce', read: true, write: false, def: ''}, read: { 'mqtt.0.shellies.shelly1-555EDB.announce': { convert: function (val) { var jsonValue = JSON.parse(val); calculateJson(jsonValue, 'Info'); return val; }, }, }, }, 'info': { common: {name: 'info', role: 'variable', type: 'string', desc: 'info', read: true, write: false, def: ''}, read: { 'mqtt.0.shellies.shelly1-555EDB.info': {}, }, }, } }); function calculateJson(jsonValue, subFolder) { for (var key in jsonValue) { if (jsonValue.hasOwnProperty(key)) { try { var jsonNewValue = JSON.parse(jsonValue[key]); calculateJson(jsonNewValue) } catch (e) { if (typeof jsonValue[key] == 'object') { for (var item in jsonValue[key]) { //var commonType = getCommonType(item); var commonType = null; doCreateStates(path + '.' + subFolder +'.' + item, item, jsonValue[key][item], commonType) } } else { doCreateStates(path + '.' + subFolder + '.' + key, key, jsonValue[key]) } } } } } function doCreateStates(newObject, name, value, commonType) { var obj = getObject(newObject); if (commonType == undefined) { commonType = {'name': name, 'role': 'state', 'type': 'string', desc: name, read: true, write: false, def: ''}; } if (commonType['type'] == 'number') { } else { value = '' + value; } if (!obj) { setObject(newObject, { type: 'state', common: commonType, native: {} }, function(err, obj) { if (!err && obj) { console.log('Object for ' + obj.id + ' created'); setState(newObject, value, true); } }); } else { setState(newObject, value, true); } if (name == 'LWT') { setTimeout(function() { on({id:newObject, change: 'ne'}, function (obj) { if (getState(path + '.isTelegramInfo').val === true) { var value = obj.state.val; var name = getState(path + '.name').val; _sendLogToTelegram(_findCorrectEmoji(name + ' wurde neu gestartet. Grund: ' + value)); } }) }, 500) } }@homecineplexx naja wenn duhier mit einem JavaScript sehr viele "States mirrorst" dann ist das ja alles "Ok" dasdie Zahl so hoch ist - was willst Du da noch optimieren :-) (Ausser es auf echte Aliases umzubauen, dann brauchst Du solche Skripte nicht) ...
-
@apollon77 Vermute mal ja. Das Update war ja nur der Auslöser für den Neustart. Ich warte mal was @AlCalzone zu meinen Dateien sagt und dann kann ich das auch noch mal testen ohne Updates oder sonstige Änderungen.