Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Cloud Dienste
  4. [Problem] Fibaro Roller Shutter mit Alexa nach % steuern

NEWS

  • Neuer Blogbeitrag: Monatsrückblick - Dezember 2025 🎄
    BluefoxB
    Bluefox
    7
    1
    65

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    24
    1
    1.4k

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    9.3k

[Problem] Fibaro Roller Shutter mit Alexa nach % steuern

Geplant Angeheftet Gesperrt Verschoben Cloud Dienste
34 Beiträge 11 Kommentatoren 4.5k Aufrufe 1 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • T Offline
    T Offline
    threedee
    schrieb am zuletzt editiert von
    #25

    Hallo zusammen,

    ich habe das Script für die virtuellen Devices so angepasst das man nur noch ein Script für alle seine Rollos braucht. Vielleicht kann es ja jemand gebrauchen.

    ! ````
    // Alle Datenpunkte erzeugen, die dieses Gerät benötigt
    const devices = [
    {subEbene: "Gästebad", levelDevice: 'zwave.0.NODE13.SWITCH_MULTILEVEL.Level_1', powerDevice: "zwave.0.NODE13.METER.Power_1"/Power/},
    {subEbene: "Arbeitszimmer", levelDevice: 'zwave.0.NODE2.SWITCH_MULTILEVEL.Level_1', powerDevice: 'zwave.0.NODE2.SENSOR_MULTILEVEL.Power_1'},
    {subEbene: "Ankleide", levelDevice: "zwave.0.NODE25.SWITCH_MULTILEVEL.Level_1", powerDevice: "zwave.0.NODE25.SENSOR_MULTILEVEL.Power_1"/Power/},
    {subEbene: "Esszimmer", levelDevice: "zwave.0.NODE6.SWITCH_MULTILEVEL.Level_1"/Level/, powerDevice: "zwave.0.NODE6.SENSOR_MULTILEVEL.Power_1"/Power/},
    {subEbene: "Garderobe", levelDevice: "zwave.0.NODE12.SWITCH_MULTILEVEL.Level_1"/Level/, powerDevice: "zwave.0.NODE12.SENSOR_MULTILEVEL.Power_1"/Power/},
    {subEbene: "Küche Garten", levelDevice: "zwave.0.NODE7.SWITCH_MULTILEVEL.Level_1"/Level/, powerDevice: "zwave.0.NODE7.SENSOR_MULTILEVEL.Power_1"/Power/},
    {subEbene: "Küche Strasse", levelDevice: "zwave.0.NODE8.SWITCH_MULTILEVEL.Level_1"/Level/, powerDevice: "zwave.0.NODE8.SENSOR_MULTILEVEL.Power_1"/Power/},
    {subEbene: "Ole Schlafzimmer", levelDevice: "zwave.0.NODE22.SWITCH_MULTILEVEL.Level_1"/Level/, powerDevice: "zwave.0.NODE22.SENSOR_MULTILEVEL.Power_1"/Power/},
    {subEbene: "Ole Spielzimmer", levelDevice: "zwave.0.NODE23.SWITCH_MULTILEVEL.Level_1"/Level/, powerDevice: "zwave.0.NODE23.SENSOR_MULTILEVEL.Power_1"/Power/},
    {subEbene: "Schlafzimmer", levelDevice: "zwave.0.NODE24.SWITCH_MULTILEVEL.Level_1"/Level/, powerDevice: "zwave.0.NODE24.SENSOR_MULTILEVEL.Power_1"/Power/},
    {subEbene: "Terasse", levelDevice: "zwave.0.NODE10.SWITCH_MULTILEVEL.Level_1"/Level/, powerDevice: "zwave.0.NODE10.SENSOR_MULTILEVEL.Power_1"/Power/},
    {subEbene: "Wohnzimmer hinten", levelDevice: "zwave.0.NODE10.SWITCH_MULTILEVEL.Level_1"/Level/, powerDevice: "zwave.0.NODE10.SENSOR_MULTILEVEL.Power_1"/Power/},
    {subEbene: "Wohnzimmer Strasse", levelDevice: "zwave.0.NODE9.SWITCH_MULTILEVEL.Level_1"/Level/, powerDevice: "zwave.0.NODE9.SENSOR_MULTILEVEL.Power_1"/Power/}

                ];
    

    var targetLevelList = [];
    var alexaRolloList = [];
    const virtualDevicesRollo = function(deviceList) {
    deviceList.forEach(function(entry) {

        var LevelDevice = entry.levelDevice;
        var PowerDevice = entry.powerDevice;
    
        var WriteTargetLevelTimeout = 5000;
        var LevelPowerRolloMeldewert = 1;
        // Der Datenpunkt des Cloudadapters zur Alexa Rollladensteuerung hoch/runter
        var cloudAlexa = "cloud.0.smart.lastCommand";
        var basisPfad = 'javascript.' + instance + '.virtualDevice.';
    
        var ersteSubEbene = 'Rollaeden';
    
        var kompletterPfad = [basisPfad,ersteSubEbene,'.',entry.subEbene,'.'].join('');
    
        var Rollo_Alexa = [kompletterPfad,'AlexaLevel'].join('');
        var TargetLevel = [kompletterPfad,'TargetLevel'].join('');
        var LevelRollo = [kompletterPfad,'LevelRollo'].join('');
        var timerSchreibverzoegerung;
    
        var Name = 'Rollo ' + entry.subEbene;
    
        targetLevelList.push(TargetLevel);
        alexaRolloList.push(Rollo_Alexa);
        createState(Rollo_Alexa, {
            type: 'number',
            name: Name + 'Alexasteuerung',
            min: 0,
            max: 100,
            def: 0,
            read: true,
            write: true
        });
    
        createState(TargetLevel, {
            type: 'number',
            name: Name + 'Target-Level für Homekit',
            min: 0,
            max: 100,
            def: 0,
        });
    
        new VirtualDevice({
            namespace: ersteSubEbene,
            name: entry.subEbene, 
            states: {
                'LevelRollo': {
                    common: {type: 'number', def: 0, min: 0, max: 100, read: true, write: true, name: Name + 'Level Aktor'},
                    read: {
                        [LevelDevice]: {
                            convert: function (val) { 
                                return convertFibaroAuf(val);
                            },
                        },
                    },
                    write: {
                        [LevelDevice]: {
                            convert: function (val) {
                                return convertFibaroZu(val);
                            },
                        },
                    }
                },
                'PowerRollo': {
                        common: {type: 'number', def: 0, min: 0, max: 300, read: true, write: false, name: Name + 'Power Aktor'},
                        read: {
                            [PowerDevice]: {
                                trigger: {ack: true, change: 'ne'},
                                after: function(device, value) {
                                    if (value < LevelPowerRolloMeldewert) {
                                        var level = getState(LevelRollo).val;
                                        var levelAck = getState(LevelRollo).ack;
    
                                        if (!levelAck) {
                                            console.log('### Level NICHT ACK: ' + level + ', levelAck: ' + levelAck);
                                        }
    
                                        if (timerSchreibverzoegerung) {
                                            clearTimeout(timerSchreibverzoegerung); 
                                            timerSchreibverzoegerung = null;
                                        }
    
                                        timerSchreibverzoegerung = setTimeout(function () {
                                            level = getState(LevelRollo).val;
                                            TargetLevelAktuell =  getState(TargetLevel).val;
                                            if (level != TargetLevelAktuell) {
                                                console.log('Setze Target (aktuell: ' + TargetLevelAktuell + ') auf: ' + level);   
                                                setState(TargetLevel,level);
                                            } else {
                                                console.log('### TargetLevel muss nicht aktualisiert werden (aktuell: ' + TargetLevelAktuell + ', Zielwert: ' + level + ').');
                                            }
                                        }, WriteTargetLevelTimeout);
                                    }
                                },
                            },
                        },
                },
            },
        });
    
    });
    

    };

    ! virtualDevicesRollo(devices);
    ! // 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) {
    var retValue = wertFibaroAuf;
    if (wertFibaroAuf >= 95) {
    retValue = 100;
    } else if (wertFibaroAuf <= 2) {
    retValue = 0;
    }
    return retValue;
    }
    ! function convertFibaroZu (wertFibaroZu) {
    var retValue = wertFibaroZu;
    if (wertFibaroZu == 100) {
    retValue = 99;
    }
    return retValue;
    }
    ! // Umsetzung von hoch und runter mit Alexa
    function steuereRollaedenAlexa(Rolladen) {
    letztesAlexaKommando = getState("cloud.0.smart.lastCommand").val;
    var retValue = getState(Rolladen).val;
    // if Abfrage, um hoch und runter von Alexa zu ermöglichen
    if (letztesAlexaKommando == '--25') {
    // fahre Rolladen runter
    retValue = 0;
    } else if (letztesAlexaKommando == '+25') {
    // fahre Rolladen hoch
    retValue = 100;
    } else {
    // Mache das, was Alexa in den Datenpunkt schreibt
    retValue = getState(Rolladen).val;
    }
    return retValue;
    }
    ! // Verarbeitung des Targetwertes zur korrekten Bedienung und Anzeige in Homekit
    on({id: targetLevelList, change: "ne"}, function (obj) {
    var value = obj.state.val;
    var oldValue = obj.oldState.val;
    if (value != oldValue) {
    var wert = getState(obj.id).val;
    var rollo = obj.id.replace('TargetLevel', 'LevelRollo')

        setState(rollo, wert);
    }
    

    });
    // Alexasteuerung
    on({id: alexaRolloList, change: "any"}, function (obj) {
    var value = obj.newState.val;
    var wert = steuereRollaedenAlexa(obj.id);

    ! var rollo = obj.id.replace('AlexaLevel', 'TargetLevel');
    setState(rollo,wert);
    });
    ! ````

    1 Antwort Letzte Antwort
    0
    • S Offline
      S Offline
      sebastian.eberle
      schrieb am zuletzt editiert von
      #26

      @eumats:

      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.

      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

      3. PowerRollo -> Abbild (binding) mit Power_1 des zwave Aktors

      4. 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.

      <u>Details zu 2. und 3.:</u>

      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.

      <u>Details zu 4.:</u>

      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 <u>global</u> 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 **[b]<u>[u]common [/u]</u>[/b]**einfü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":
      ! >! [spoiler]`
      [code]
      // 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);
      

      });[/code]`[/spoiler]

      ! ~~[b]~~23.05.2018: Die im Folgenden offenbarten, fehlenden Variablen wurden hinzugefügt.[/b]
      ! Kannst du mal nen Screenshot von deiner Yahka cofig eines rollos machen? wäre super :)[/i][/i][/i][/i][/i][/i]
      ``` `

      1 Antwort Letzte Antwort
      0
      • eumatsE Offline
        eumatsE Offline
        eumats
        schrieb am zuletzt editiert von
        #27

        Hier ein Beispiel-Screen Shot…
        3610_6b745157-04ed-45ab-b0ac-be183d067806.jpeg

        1 Antwort Letzte Antwort
        0
        • O Offline
          O Offline
          Oelman
          schrieb am zuletzt editiert von
          #28

          Hallo, kann mir vielleicht jemand mit einem Skript helfen, bei dem nur die Werte von HomeKit in die Werte für den Fibaro Roller Shutter (0) (99) umgerechnet werden. Den Rest des hier angegebenen Skripts benötige ich nicht. Leider bin ich, was das erstellen von Skripten angeht, nicht erfahren.

          Schon mal vielen Dank!

          eumatsE 1 Antwort Letzte Antwort
          0
          • O Oelman

            Hallo, kann mir vielleicht jemand mit einem Skript helfen, bei dem nur die Werte von HomeKit in die Werte für den Fibaro Roller Shutter (0) (99) umgerechnet werden. Den Rest des hier angegebenen Skripts benötige ich nicht. Leider bin ich, was das erstellen von Skripten angeht, nicht erfahren.

            Schon mal vielen Dank!

            eumatsE Offline
            eumatsE Offline
            eumats
            schrieb am zuletzt editiert von eumats
            #29

            @Oelman So genau weis ich nicht was du brauchst und wie du es einbinden willst.
            Das Skript aus diesem Post macht das alles was du brauchst...

            1 Antwort Letzte Antwort
            0
            • eumatsE eumats

              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.

              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

              3. PowerRollo -> Abbild (binding) mit Power_1 des zwave Aktors

              4. 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.

              O Offline
              O Offline
              oliver1000
              schrieb am zuletzt editiert von
              #30

              @eumats Thank you for the script. Within the new forum it is a bit destroyed by the layout. could you please post it again? Than you!

              1 Antwort Letzte Antwort
              0
              • eumatsE eumats

                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.

                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

                3. PowerRollo -> Abbild (binding) mit Power_1 des zwave Aktors

                4. 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.

                D Offline
                D Offline
                Denis1988
                schrieb am zuletzt editiert von
                #31

                @eumats ich habe auch dieses Problem mit meinen Fibaro Rollershutter. Bei mir ist es jedoch so dass bei geschlossen der Wert 99 ist und bei geöffnet der Wert 0. Wollte meine Rollershutter in den shutte control adapter einpflegen. der adapter ist jedoch so konzipiert, dass er nur mit 0 für geschlossen und 100 für geöffnet arbeitet. auf der Suche nach einer Lösung bin ich dann hier auf dein skript gestoßen.
                hört sich schonmal sehr vielversprechend für mein vorhaben an. kann es sein dass das skript hier nicht mehr richtig dargestellt wird. sehe hier immer nur so kleine schnippsel und weiss nicht was ich gedau zusammenstellen muss. Könntest du eventuell das skript hier nochmal komplett reinstellen? das wäre sehr nett.

                VG denis

                FredFF eumatsE 2 Antworten Letzte Antwort
                0
                • D Denis1988

                  @eumats ich habe auch dieses Problem mit meinen Fibaro Rollershutter. Bei mir ist es jedoch so dass bei geschlossen der Wert 99 ist und bei geöffnet der Wert 0. Wollte meine Rollershutter in den shutte control adapter einpflegen. der adapter ist jedoch so konzipiert, dass er nur mit 0 für geschlossen und 100 für geöffnet arbeitet. auf der Suche nach einer Lösung bin ich dann hier auf dein skript gestoßen.
                  hört sich schonmal sehr vielversprechend für mein vorhaben an. kann es sein dass das skript hier nicht mehr richtig dargestellt wird. sehe hier immer nur so kleine schnippsel und weiss nicht was ich gedau zusammenstellen muss. Könntest du eventuell das skript hier nochmal komplett reinstellen? das wäre sehr nett.

                  VG denis

                  FredFF Offline
                  FredFF Offline
                  FredF
                  Most Active Forum Testing
                  schrieb am zuletzt editiert von
                  #32

                  @Denis1988
                  Ich habe den von dir genannten Beitrag mal gemeldet, um das Skript leserlich darstellen zu können. (Es gab eine Froumumstellung und einige alte Beiträge sind danach nicht mehr leserlich)
                  Wenn du sowas wieder findest kannst du das auch einfach selbermachen:
                  Beitrag die drei Punkte rechts:

                  2019-12-16-12-17-57.png

                  1 Antwort Letzte Antwort
                  0
                  • D Denis1988

                    @eumats ich habe auch dieses Problem mit meinen Fibaro Rollershutter. Bei mir ist es jedoch so dass bei geschlossen der Wert 99 ist und bei geöffnet der Wert 0. Wollte meine Rollershutter in den shutte control adapter einpflegen. der adapter ist jedoch so konzipiert, dass er nur mit 0 für geschlossen und 100 für geöffnet arbeitet. auf der Suche nach einer Lösung bin ich dann hier auf dein skript gestoßen.
                    hört sich schonmal sehr vielversprechend für mein vorhaben an. kann es sein dass das skript hier nicht mehr richtig dargestellt wird. sehe hier immer nur so kleine schnippsel und weiss nicht was ich gedau zusammenstellen muss. Könntest du eventuell das skript hier nochmal komplett reinstellen? das wäre sehr nett.

                    VG denis

                    eumatsE Offline
                    eumatsE Offline
                    eumats
                    schrieb am zuletzt editiert von eumats
                    #33

                    @Denis1988
                    Das alles leserlich unter https://forum.iobroker.net/topic/11743/problem-fibaro-roller-shutter-mit-alexa-nach-steuern/5

                    Oder was genau fehlt Dir?

                    D 1 Antwort Letzte Antwort
                    0
                    • eumatsE eumats

                      @Denis1988
                      Das alles leserlich unter https://forum.iobroker.net/topic/11743/problem-fibaro-roller-shutter-mit-alexa-nach-steuern/5

                      Oder was genau fehlt Dir?

                      D Offline
                      D Offline
                      Denis1988
                      schrieb am zuletzt editiert von
                      #34

                      @eumats jetzt sieht es gut aus. Zuvor wurden die skripts bei mir nicht richtig dargestellt. Vielen lieben Dank!

                      1 Antwort Letzte Antwort
                      0
                      Antworten
                      • In einem neuen Thema antworten
                      Anmelden zum Antworten
                      • Älteste zuerst
                      • Neuste zuerst
                      • Meiste Stimmen


                      Support us

                      ioBroker
                      Community Adapters
                      Donate
                      FAQ Cloud / IOT
                      HowTo: Node.js-Update
                      HowTo: Backup/Restore
                      Downloads
                      BLOG

                      446

                      Online

                      32.5k

                      Benutzer

                      81.7k

                      Themen

                      1.3m

                      Beiträge
                      Community
                      Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                      ioBroker Community 2014-2025
                      logo
                      • Anmelden

                      • Du hast noch kein Konto? Registrieren

                      • Anmelden oder registrieren, um zu suchen
                      • Erster Beitrag
                        Letzter Beitrag
                      0
                      • Home
                      • Aktuell
                      • Tags
                      • Ungelesen 0
                      • Kategorien
                      • Unreplied
                      • Beliebt
                      • GitHub
                      • Docu
                      • Hilfe