NEWS
[Problem] Fibaro Roller Shutter mit Alexa nach % steuern
-
Hallo zusammen,
ich bin noch ein absoluter Einsteiger in die Heimautomatisierung und noch ganz am Anfang.
Da ich gerne das ganze mit Alexa steuern möchte, bin ich auf ioBroker gestossen.
Als Hardware habe ich ein Raspberry pi 3 und Fibaro Aktoren.
Bei meinem ersten Testaufbau mit dem Fibaro Roller Shutter FGR-222 bin ich leider schon an meine ersten Grenzen gestoßen….
Mein Problem ist, dass ich die Rolladen über Alexa nicht nach % Werten steuern kann.
Über die Taster und die ioBroker Software funktioniert es.
Deshalb denke ich auch, dass die Kalibrierung i.O. ist.
Sobald ich einen 50% Wert über die Alexa angebe, erscheint "Switch Multilevel --> Level_1" der Wert 127,5.
Damit kann der Aktor nichts anfangen da der Wert von 0 (Rolladen Zu) bis 99 (Rolladen Auf) geht.
Gebe ich hier den Wert 50 ein, fährt der Rolladen zu 50% zu.
Kann mir einer Sagen wo mein Fehler liegt?
Vielen Dank
-
Gebe ich hier den Wert 50 ein, fährt der Rolladen zu 50% zu.
Kann mir einer Sagen wo mein Fehler liegt? `
Du machst nix falsch. Das ist eine Eigenheit von ZWave, die von ioBroker/Alexa ohne weiteres nicht unterstützt wird. Zwave-Dimmer und -Rolladenaktoren akzeptieren zusätzlich zu 0-99 auch noch den Wert 255, der den letzten nicht-0-Zustand ansteuert. Deswegen sieht es für ioBroker aus als wäre der Wertebereich 0-255.Dem kann z.B. per Skript begegnet werden. Dazu benötigst du für jeden dieser States einen weiteren State, der von einem Skript überwacht wird. Dieser sollte den Wertebereich 0-99 haben und anstatt der Aktoren in Alexa eingebunden werden. Jede Änderung an diesem State muss vom Skript auf den ZWave-State übertragen werden.
Ich wollte das schon länger mal angehen, da ich das gleiche Problem habe, aber es gibt soo viele Baustellen. Vielleicht hilft dir dabei auch das "Virtual Devices"-Skript, welches hier im Forum herumgeistert.
-
Vielen Dank für die Antwort und ausführliche Erklärung.
Das ist zwar nicht das was ich hören wollte
Aber dann kann ich wenigstens aufhören irgendwelche Einstellungen zu verändern und mich mit meinen anderen Problemen beschäftigen.
Falls jemand hierfür eine Lösung per Skript erarbeitet hat, würde ich mich über eine Info freuen.
Grüße
Heromic
-
Falls jemand hierfür eine Lösung per Skript erarbeitet hat, würde ich mich über eine Info freuen. `
Wie gesagt, such mal nach dem Virtual Devices-Skript. Eventuell ist es damit möglich, mit einer recht einfachen Definition deine States "umzubiegen". -
Moin. Ich haben den Fibaro Roller Shutter 2 im Einsatz und nutze ihn per Homekit (yahka Adapter) Alexa und manuell über die Tasten.
Das Ganze habe ich mit Hilfe des Virtual Devices-Skript umgesetzt. Bei mir ist 0= Rollladen geschlossen und 100=Rollladen geöffnet.
Das Skript unter common legt 4 Datenpunkte unter javascript.0.virtualDevice.Rolllaeden.EsszimmerOsten (Pfad kann konfiguriert werden) an.
-
AlexaLevel -> Rollladen in cloud Adapter einbinden und mit Alexa steuern. Funktion: hoch, runter und angesagt %-Zahl
-
LevelRollo -> Abbild (binding) mit Level_1 des zwave Aktors
-
PowerRollo -> Abbild (binding) mit Power_1 des zwave Aktors
-
TargetLevel -> Hier wird der Zielwert, auf den der Rollladen fahren soll, reingeschrieben.
Hinweis: Diese Lösung ist recht yahka spezifisch. Sollte yahka nicht genutzt werden muss das Skript unter common sicher angepasst werden. Ggf. kann ich hier unterstützen.
Details zu 2. und 3.:
Zur korrekten Darstellung von öffnen und schließen in yahka ist es wichtig, dass ein Datenpunkt den Zielwert (TargetLevel, z.B. 70%) und ein Datenpunkt den IST-Wert anzeigt (TargetLevel, z.B. 0%).
Daher die beiden Datenpunkte.
Details zu 4.:
Für die korrekte Anzeige des %-Werte in yahka bei manueller Betätigung über den Taster direkt am Fibaro Aktor werte ich PowerRollo aus. Also: Wenn der Rollladen still steht (PowerRollo < 1 für 5000ms) dann setze den Targetwert auf den IST-Wert.
Da ich vielen Funktionen unter global ausgelagert habe, habe ich ich der Einfachheit halber alles in ein Skript zusammen kopiert. Ich hoffe mir ist da kein Fehler unterlaufen.
Eigentlich müssen nur die Variablen LevelDevice und PowerDevice an den eigene Aktor angepasst werden, Skript Starten, erzeugte Datenpunkte in die Adapter einbinden, fertig.
Ich hoffe ich habe nix vergessen. Ich habe das mal schnell auf der Arbeit zusammengeschrieben.
Unter global einfügen und starten:
/*VirtualDevice v0.3 // http://forum.iobroker.net/viewtopic.php?f=21&t=8192&hilit=virtuelle+Geräte var AdapterPfadVirtuelleGeraete = 'javascript.', virtualDevicePfad = 'virtualDevice.'; Structure of config: { name: 'name', //name of device namespace: '', //create device within this namespace (device ID will be namespace.name) common: {}, //(optional) native: {}, //(optional) copy: objectId, //(optional) ID of device or channel to copy common and native from onCreate: function(device, callback) {} //called once on device creation states: { 'stateA': { //State Id will be namespace.name.stateA common: {}, //(optional) native: {}, //(optional) copy: stateId, read: { //(optional) states which should write to "stateA" 'stateId1': { trigger: {ack: true, change: 'any'} //(optional) see https://github.com/ioBroker/ioBroker.javascript#on---subscribe-on-changes-or-updates-of-some-state convert: function(val) {}, //(optional) functions should return converted value before: function(device, value, callback) {}, //(optional) called before writing new state. has to call callback or new value will not be written delay: 0, //(optional) delay in ms before new value gets written after: function(device, value) {}, //(optional) called after new value has been written validFor: //(optional) ms, to ignore old data which did not change for a long time. }, ... }, readLogic: 'last' || 'max' || 'min' || 'average', //(optional) default: last (only last implemented) write: { //(optional) states which "stateA" should write to 'stateId1': { convert: function(val) {}, //(optional) functions should return converted value before: function(device, value, callback) {}, //(optional) called before writing new state. has to call callback or new value will not be written delay: 0, //(optional) delay in ms before new value gets written after: function(device, value) {}, //(optional) called after new value has been written }, 'stateId3': { convert: function(val) {}, //(optional) functions should return converted value before: function(device, value, callback) {}, //(optional) called before writing new state. has to call callback or new value will not be written delay: 0, //(optional) delay in ms before new value gets written after: function(device, value) {}, //(optional) called after new value has been written }, ... }, }, ... } } */ //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 = virtualDevicePfad + 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(AdapterPfadVirtuelleGeraete + instance + '.' + this.namespace, { type: "device", 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) : { 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); } createState(id, obj.common, obj.native, function (err) { if (err) { log('skipping creation of state ' + id, 'debug'); } else { log('created state ' + id, 'debug'); } this.connectState(stateId); countCreated++; if (countCreated >= stateIds.length) { log('created ' + countCreated + ' states for device ' + this.namespace, 'debug'); callback(); } }.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) { 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 (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: AdapterPfadVirtuelleGeraete + instance + '.' + 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'); } VirtualDevice.prototype.subRead = function (trigger, readObj, state) { var func = function (obj) { var val = this.convertValue(obj.state.val, readObj.convert); //@todo aggregations 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); }
Unter commoneinfügen und starten (Es kann ggf. sein, dass das Skript 2x gestartet werden muss, da das Erzeugen der Datenpunkte und das zugehörige binding "sich nicht finden":
// Alle Datenpunkte erzeugen, die dieses Gerät benötigt var LevelDevice = 'zwave.0.NODE10.SWITCH_MULTILEVEL.Level_1', PowerDevice = 'zwave.0.NODE10.SENSOR_MULTILEVEL.Power_1'; var WriteTargetLevelTimeout = 5000, // Timeout für das Schreiben des Levelwerte in den Targetwert bei Fibaro Rollladenaktoren. LevelPowerRolloMeldewert = 1; // Kleiner diesen Wert wird der Rollladen als stillstehend erkannt. // Der Datenpunkt des Cloudadapters zur Alexa Rollladensteuerung hoch/runter var cloudAlexa = 'cloud.0.smart.lastCommand'; var basisPfad = 'javascript.0.virtualDevice.'; var ersteSubEbene = 'Rolllaeden', zweiteSubEbene = 'EsszimmerOsten', kompletterPfad = [basisPfad,ersteSubEbene,'.',zweiteSubEbene,'.'].join(''), Alexa = 'AlexaLevel', LevelRollo = 'LevelRollo', TargetLevel = 'TargetLevel'; var Rollo_Alexa = [kompletterPfad,Alexa].join(''), TargetLevel = [kompletterPfad,TargetLevel].join(''), LevelRollo = [kompletterPfad,LevelRollo].join(''), Schreibverzoegerung; var Name = 'Rollladen WZ Osten ', AlexaTag = Name + 'Alexasteuerung', LevelTag = Name + 'Level Aktor', PowerTag = Name + 'Power Aktor', TargetTag = Name + 'Target-Level für Homekit'; createState(Rollo_Alexa, { type: 'number', name: AlexaTag, min: 0, max: 100, def: 0, read: true, write: true }); createState(TargetLevel, { type: 'number', name: TargetTag, min: 0, max: 100, def: 0, }); // Hilfsfunktionen... // Konvertiert die Fibarowerte (0-99) in ein Wert von 0-100 // Manchmal zeigt Level_1 der Aktoren nach einer manuellen Bedienung nicht 0/99 an, sondern 1 oder 96\. Das wird hier korrigiert function convertFibaroAuf (wertFibaroAuf) { if (wertFibaroAuf >= 95) { return(100); } else if (wertFibaroAuf <= 2) { return(0); } else { return(wertFibaroAuf); } } function convertFibaroZu (wertFibaroZU) { if (wertFibaroZU == 100) { return (99); } else { return(wertFibaroZU); } } // Umsetzung von hoch und runter mit Alexa function steuereRolllaedenAlexa(Rollladen) { letztesAlexaKommando = getState(cloudAlexa).val; // if Abfrage, um hoch und runter von Alexa zu ermöglichen if (letztesAlexaKommando == '--25') { // fahre Rolladen runter return 'runter'; } else if (letztesAlexaKommando == '+25') { // fahre Rolladen hoch return 'hoch'; } else { // Mache das, was Alexa in den Datenpunkt schreibt return 'nativ'; } } // Verarbeitung der virtuellen Geräte für die Fibaro Aktoren. // Level_1 und Power_1 new VirtualDevice({ // z.B. 'Rollaeden' für javascript.0.virtualDevice.Rollaeden... oder 'Rolllaeden.bla' javascript.0.virtualDevice.Rollaeden.bla... namespace: ersteSubEbene, name: zweiteSubEbene, //das Gerät wird unter javascript.0.virtualDevice.namespace.name erstellt states: { //welche States sollen erstellt werden? 'LevelRollo': { //State Konfiguration common: {type: 'number', def: 0, min: 0, max: 100, read: true, write: true, name: LevelTag}, read: { //von welchen States sollen Werte eingelesen werden? [LevelDevice]: { convert: function (val) { //wert soll konvertiert werden // Konvertiere die Fibarowerte zu 0-100 var wert = convertFibaroAuf(val); //console.log('### LevelRollo: ' + wert); return wert; }, }, }, write: { //in welche States sollen Werte geschrieben werden? [LevelDevice]: { convert: function (val) { //wert soll konvertiert werden // Konvertiere die Fibarowerte zu 0-100 var wert = convertFibaroZu(val); return wert; }, }, } }, 'PowerRollo': { //State Konfiguration common: {type: 'number', def: 0, min: 0, max: 300, read: true, write: false, name: PowerTag}, read: { //von welchen States sollen Werte eingelesen werden? [PowerDevice]: { trigger: {ack: true, change: 'ne'}, // Falls der Rolladen manuell bedient wurde, müssen wir nun alles für eine korrekte Anzeige in Homekit bereitstelen after: function(device, value) { // Mache etwas, wenn der Rollladen still steht, also der Verbrauch kleiner LevelPowerRolloMeldewert ist if (value < LevelPowerRolloMeldewert) { var level = getState(LevelRollo).val; var levelAck = getState(LevelRollo).ack; var TargetLevelAktuell = getState(TargetLevel).val; if (!levelAck) { console.log('### Level NICHT ACK: ' + level + ', levelAck: ' + levelAck); } // Alten Timer, falls vorhanden, löschen (function () {if (Schreibverzoegerung) {clearTimeout(Schreibverzoegerung); Schreibverzoegerung = null;}})(); // Verzögerung beim Schreiben, da Level_1 machmal etwas länger zum Aktualisieren des Zielwertes braucht. //console.log('### Level vor TIMEOUT: ' + level + ', levelAck: ' + levelAck); //console.log('### TargetLevelAktuell vor TIMEOUT: ' + TargetLevelAktuell); Schreibverzoegerung = setTimeout(function () { level = getState(LevelRollo).val; levelAck = getState(LevelRollo).ack; TargetLevelAktuell = getState(TargetLevel).val; //console.log('### Level nach TIMEOUT: ' + level + '#, levelAck: ' + levelAck); //console.log('### TargetLevelAktuell nach TIMEOUT: ' + TargetLevelAktuell); // Wenn Level_1 und Target nicht gleich sind, dann müssen wir etwas machen if (level != TargetLevelAktuell) { console.log('Setze Target (aktuell: ' + getState(TargetLevel).val + ') auf: ' + level); setState(TargetLevel,level); } else { console.log('### TargetLevel muss nicht aktualisiert werden (aktuell: ' + getState(TargetLevel).val + ', Zielwert: ' + level + ').'); } }, WriteTargetLevelTimeout); } }, }, }, }, }, }); // Verarbeitung des Tagetwertes zur korrekten Bedienung und Anzeige in Homekit on({id: TargetLevel, change: "ne"}, function (obj) { var value = obj.state.val; var oldValue = obj.oldState.val; if (value != oldValue) { var wert = getState(TargetLevel).val; setState(LevelRollo, wert); } }); // Alexasteuerung on({id: Rollo_Alexa, change: "any"}, function (obj) { var AlexaAktion = steuereRolllaedenAlexa(Rollo_Alexa), wert; //console.log('### Alexa: ' + AlexaAktion); if (AlexaAktion == 'runter') { // fahre Rolladen runter wert = 0; } else if (AlexaAktion == 'hoch') { // fahre Rolladen hoch wert = 100; } else { // fahre Rolladen auf den übergebenen Wert wert = value; } // Über den TargetLevel wird dann auch der Frostschutz gesteuert setState(TargetLevel,wert); });
23.05.2018: Die im Folgenden offenbarten, fehlenden Variablen wurden hinzugefügt.
-
-
Boah
vielen Dank für die gute und ausführliche Beschreibung.
Da ich in Skripten noch sehr jungfräulich bin, muss ich darüber mal eine Nacht schlafen um das ganze zu verstehen und auf meine Bedürfnisse anzupassen.
Zumindestens habe ich jetzt Lösungsansätze auf die ich aufbauen kann.
-
Hier noch mal eine abgespeckte Variante für nicht Apple/homekit Nutzer:
Er gibt 2 Datenpunkte:
1. AlexaLevel -> Rollladen in cloud Adapter einbinden und mit Alexa steuern. Funktion: hoch, runter und angesagt %-Zahl
2. LevelRollo -> Abbild (binding) mit Level_1 des zwave Aktors
// Alle Datenpunkte erzeugen, die dieses Gerät benötigt var LevelDevice = 'zwave.0.NODE10.SWITCH_MULTILEVEL.Level_1', PowerDevice = 'zwave.0.NODE10.SENSOR_MULTILEVEL.Power_1'; // Der Datenpunkt des Cloudadapters zur Alexa Rollladensteuerung hoch/runter var cloudAlexa = 'cloud.0.smart.lastCommand'; var ersteSubEbene = 'Rolllaeden', zweiteSubEbene = 'EsszimmerOsten', kompletterPfad = [basisPfad,ersteSubEbene,'.',zweiteSubEbene,'.'].join(''), Alexa = 'AlexaLevel', LevelRollo = 'LevelRollo'; var Rollo_Alexa = [kompletterPfad,Alexa].join(''), LevelRollo = [kompletterPfad,LevelRollo].join(''); var Name = 'Rollladen WZ Osten ', AlexaTag = Name + 'Alexasteuerung', LevelTag = Name + 'Level Aktor'; createState(Rollo_Alexa, { type: 'number', name: AlexaTag, min: 0, max: 100, def: 0, read: true, write: true }); // Hilfsfunktionen... // Konvertiert die Fibarowerte (0-99) in ein Wert von 0-100 // Manchmal zeigt Level_1 der Aktoren nach einer manuellen Bedienung nicht 0/99 an, sondern 1 oder 96\. Das wird hier korrigiert function convertFibaroAuf (wertFibaroAuf) { if (wertFibaroAuf >= 95) { return(100); } else if (wertFibaroAuf <= 2) { return(0); } else { return(wertFibaroAuf); } } function convertFibaroZu (wertFibaroZU) { if (wertFibaroZU == 100) { return (99); } else { return(wertFibaroZU); } } // Umsetzung von hoch und runter mit Alexa function steuereRolllaedenAlexa(Rollladen) { letztesAlexaKommando = getState(cloudAlexa).val; // if Abfrage, um hoch und runter von Alexa zu ermöglichen if (letztesAlexaKommando == '--25') { // fahre Rolladen runter return 'runter'; } else if (letztesAlexaKommando == '+25') { // fahre Rolladen hoch return 'hoch'; } else { // Mache das, was Alexa in den Datenpunkt schreibt return 'nativ'; } } // Verarbeitung der virtuellen Geräte für die Fibaro Aktoren. // Level_1 und Power_1 new VirtualDevice({ // z.B. 'Rollaeden' für javascript.0.virtualDevice.Rollaeden... oder 'Rolllaeden.bla' javascript.0.virtualDevice.Rollaeden.bla... namespace: ersteSubEbene, name: zweiteSubEbene, //das Gerät wird unter javascript.0.virtualDevice.namespace.name erstellt states: { //welche States sollen erstellt werden? 'LevelRollo': { //State Konfiguration common: {type: 'number', def: 0, min: 0, max: 100, read: true, write: true, name: LevelTag}, read: { //von welchen States sollen Werte eingelesen werden? [LevelDevice]: { convert: function (val) { //wert soll konvertiert werden // Konvertiere die Fibarowerte zu 0-100 var wert = convertFibaroAuf(val); //console.log('### LevelRollo: ' + wert); return wert; }, }, }, write: { //in welche States sollen Werte geschrieben werden? [LevelDevice]: { convert: function (val) { //wert soll konvertiert werden // Konvertiere die Fibarowerte zu 0-100 var wert = convertFibaroZu(val); return wert; }, }, } }, }, }); >! // Alexasteuerung on({id: Rollo_Alexa, change: "any"}, function (obj) { var AlexaAktion = steuereRolllaedenAlexa(Rollo_Alexa), wert; //console.log('### Alexa: ' + AlexaAktion); if (AlexaAktion == 'runter') { // fahre Rolladen runter wert = 0; } else if (AlexaAktion == 'hoch') { // fahre Rolladen hoch wert = 100; } else { // fahre Rolladen auf den übergebenen Wert wert = value; } setState(LevelRollo,wert); });
-
Hallo,
wollte das oben gepostete Skript gerade mal bei mir ausprobieren.
Bekomme folgende Fehlermeldung
[javascript.0 2018-04-01 14:40:16.935 error at ContextifyScript.Script.runInContext (vm.js:35:29) javascript.0 2018-04-01 14:40:16.934 error at script.js.common.Test_01-04-2018:10:23 javascript.0 2018-04-01 14:40:16.934 error ReferenceError: basisPfad is not defined javascript.0 2018-04-01 14:40:16.933 error ^ javascript.0 2018-04-01 14:40:16.933 error kompletterPfad = [basisPfad,ersteSubEbene,'.',zweiteSubEbene,'.'].join(''), javascript.0 2018-04-01 14:40:16.932 error script.js.common.Test_01-04-2018: script.js.common.Test_01-04-2018:10]
Ich vermute mal, du hast noch ein weiteres Global Skript aktiv.
Deshalb kann das Skript nicht den Basis Pfad zuweisen.
Kannst du mir auf die Sprünge helfen, wie ich das Skript bei mir zum laufen bekomme?
Vielend Dank
-
Schreibe mal folgendes in Skript:
var basisPfad = 'javascript.0.virtualDevice.';
-
Vielen Dank
Daumen Hoch !
Diese Fehlermeldung ist nun verschwunden und die nächste folgt zugleich …
Ich versuche mich aber erstmal ein wenig mit java Script auseinanderzusetzen,
damit ich ich das ganze wenigstens ein bisschen nachvollziehen kann
-
Vielen Dank
Daumen Hoch !
Diese Fehlermeldung ist nun verschwunden und die nächste folgt zugleich …
Ich versuche mich aber erstmal ein wenig mit java Script auseinanderzusetzen,
damit ich ich das ganze wenigstens ein bisschen nachvollziehen kann `
Poste mal der Fehlermeldung. Hast Du das Virtual Device Skript wie oben beschrieben in global eingefügt und gestartet?
Wie oben geschrieben habe ich das nur mal nebenbei zusammen kopiert. Denn bei mir ist viel in globalen Variablen und zentralen Funktionen ausgelagert. Daher können da sicher Bugs drin sein…
-
> Hast Du das Virtual Device Skript wie oben beschrieben in global eingefügt und gestartet?
Jep, ich denke das war es.
Die Fehlermeldung war
javascript.0 2018-04-02 17:40:59.526 error ReferenceError: VirtualDevice is not defined javascript.0 2018-04-02 17:40:59.526 error ^ javascript.0 2018-04-02 17:40:59.525 error new VirtualDevice({
Ich habe das Script nochmal gestartet und die Fehlermeldung war verschwunden.
Jetzt sehe ich es auch als virtl. device
Supi
Klasse support
Vielen Dank
-
Hi zusammen
Ich lese seit längerem in diesem Forum mit.
Ich habe ebenfalls das problem, dass in meinem Fall Homekit (yahka) "öffnen" einen Wert von 100 übermittelt.
Ich habe die beiden Skripts mal importiert und erhalte folgenden Fehler:
javascript.0 2018-05-21 00:14:54.669 error at ContextifyScript.Script.runInContext (vm.js:59:29) javascript.0 2018-05-21 00:14:54.669 error at script.js.common.v-common:87:1 javascript.0 2018-05-21 00:14:54.668 error at new VirtualDevice (script.js.common.v-common:63:22) javascript.0 2018-05-21 00:14:54.667 error ReferenceError: virtualDevicePfad is not defined javascript.0 2018-05-21 00:14:54.667 error ^ javascript.0 2018-05-21 00:14:54.666 error this.namespace = virtualDevicePfad + config.namespace + '.' + config.name; javascript.0 2018-05-21 00:14:54.665 error script.js.common.v-common: script.js.common.v-common:63
Kamm mir jemand helfen das Skript für HomeKit anzupassen?
Danke und Grüsse
Sven
-
Schreib mal folgendes in das Skript in global:
var virtualDevicePfad = 'virtualDevice.';
-
OK
hab das in Zeile 61 im global script eingefügt:
`/*VirtualDevice v0.3 // http://forum.iobroker.net/viewtopic.php?f=21&t=8192&hilit=virtuelle+Geräte Structure of config: { name: 'name', //name of device namespace: '', //create device within this namespace (device ID will be namespace.name) common: {}, //(optional) native: {}, //(optional) copy: objectId, //(optional) ID of device or channel to copy common and native from onCreate: function(device, callback) {} //called once on device creation states: { 'stateA': { //State Id will be namespace.name.stateA common: {}, //(optional) native: {}, //(optional) copy: stateId, read: { //(optional) states which should write to "stateA" 'stateId1': { trigger: {ack: true, change: 'any'} //(optional) see https://github.com/ioBroker/ioBroker.javascript#on---subscribe-on-changes-or-updates-of-some-state convert: function(val) {}, //(optional) functions should return converted value before: function(device, value, callback) {}, //(optional) called before writing new state. has to call callback or new value will not be written delay: 0, //(optional) delay in ms before new value gets written after: function(device, value) {}, //(optional) called after new value has been written validFor: //(optional) ms, to ignore old data which did not change for a long time. }, ... }, readLogic: 'last' || 'max' || 'min' || 'average', //(optional) default: last (only last implemented) write: { //(optional) states which "stateA" should write to 'stateId1': { convert: function(val) {}, //(optional) functions should return converted value before: function(device, value, callback) {}, //(optional) called before writing new state. has to call callback or new value will not be written delay: 0, //(optional) delay in ms before new value gets written after: function(device, value) {}, //(optional) called after new value has been written }, 'stateId3': { convert: function(val) {}, //(optional) functions should return converted value before: function(device, value, callback) {}, //(optional) called before writing new state. has to call callback or new value will not be written delay: 0, //(optional) delay in ms before new value gets written after: function(device, value) {}, //(optional) called after new value has been written }, ... }, }, ... } } */ //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; } virtualDevicePfad = 'VirtualDevice.', this.config = config; this.namespace = virtualDevicePfad + 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(AdapterPfadVirtuelleGeraete + instance + '.' + this.namespace, { type: "device", 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) : { 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); } createState(id, obj.common, obj.native, function (err) { if (err) { log('skipping creation of state ' + id, 'debug'); } else { log('created state ' + id, 'debug'); } this.connectState(stateId); countCreated++; if (countCreated >= stateIds.length) { log('created ' + countCreated + ' states for device ' + this.namespace, 'debug'); callback(); } }.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) { 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 (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: AdapterPfadVirtuelleGeraete + instance + '.' + 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'); } VirtualDevice.prototype.subRead = function (trigger, readObj, state) { var func = function (obj) { var val = this.convertValue(obj.state.val, readObj.convert); //@todo aggregations 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); }
Beim nächsten Fehler findet er keine Zuweisung für AdapterPfadVirtuelleGeraete:
~~javascript.0 2018-05-22 15:00:29.038 error at ContextifyScript.Script.runInContext (vm.js:59:29) javascript.0 2018-05-22 15:00:29.038 error at script.js.common.v-common:87:1 javascript.0 2018-05-22 15:00:29.038 error at new VirtualDevice (script.js.common.v-common:69:10) javascript.0 2018-05-22 15:00:29.037 error at VirtualDevice.createDevice (script.js.common.v-common:87:18) javascript.0 2018-05-22 15:00:29.037 error ReferenceError: AdapterPfadVirtuelleGeraete is not defined javascript.0 2018-05-22 15:00:29.036 error ^ javascript.0 2018-05-22 15:00:29.036 error extendObject(AdapterPfadVirtuelleGeraete + instance + '.' + this.namespace, { javascript.0 2018-05-22 15:00:29.035 error script.js.common.v-common: script.js.common.v-common:87
Wohin sollte der zeigen?[/i][/i][/i][/i][/i][/i]
-
In global noch mal folgendes hinzufügen oder das global Skript von oben neu kopieren und einfügen. Da habe ich es korrigiert.
var AdapterPfadVirtuelleGeraete = 'javascript.';
-
In global noch mal folgendes hinzufügen oder das global Skript von oben neu kopieren und einfügen. Da habe ich es korrigiert.
var AdapterPfadVirtuelleGeraete = 'javascript.'; ```` ` Kurze Frage… kann ich den so mit iobroker verbinden oder brauche ich dazu noch extra Hardware... Gruss
Gesendet von meinem SM-G928F mit Tapatalk
-
Kurze Frage… kann ich den so mit iobroker verbinden oder brauche ich dazu noch extra Hardware... Gruss
Gesendet von meinem SM-G928F mit Tapatalk `
Ich verstehe die Frage nicht…
-
Kurze Frage… kann ich den so mit iobroker verbinden oder brauche ich dazu noch extra Hardware... Gruss
Gesendet von meinem SM-G928F mit Tapatalk `
Ich verstehe die Frage nicht… ` Also ich meine wenn ich mir den Fibaro Schalter kaufe ob ich ihn so mit dem iobroker System verbinden kann.. oder braucht Mann dazu noch etwas..
Gesendet von meinem SM-G928F mit Tapatalk
-
Man brauch nach einen Sender/Empfänger der das ZWAVE Protokoll spricht.
Siehe https://github.com/ioBroker/ioBroker.zwave/ -> Tested Hardware