Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Soulforged

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    S
    • Profile
    • Following 0
    • Followers 0
    • Topics 4
    • Posts 12
    • Best 1
    • Groups 1

    Soulforged

    @Soulforged

    1
    Reputation
    127
    Profile views
    12
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    Soulforged Follow
    Starter

    Best posts made by Soulforged

    • [Tutorial] Node Red Sub-Flow: Yeelights steuern mit Alexa

      Hallo Community,

      Ich melde mich nach langer Zeit mal wieder zurück und möchte einen kleinen Sub-Flow mit euch teilen um Yeelights über Alexa und Node-Red mit node-red-contrib-amazon-echo ansteuern zu können. Entstanden ist dieser Flow aus mehreren Gründen. Zum einen wurden es im laufen der Zeit extrem viele Datenpunkte die im Hauptflow eingefügt werden mussten und ich hatte das Problem, dass teilweise Farben die in VIS gesetzt wurden später durch Alexa beim Ausschalten überschrieben wurden.

      Hoffentlich ist das ganze nicht doppelt. Als voraussetzung muss noch das node-red-contrib-color-convert Paket installiert werden.

      Nach dem Einfügen vom Flow gebt ihr diesem noch die IDs der Datenpunkte für power, rgb, active_bright und ct mit

      Anmerkung 2020-03-01 163347.png

      [{"id":"2d0f0584.d8aa7a","type":"subflow","name":"Yeelight","info":"","category":"","in":[{"x":60,"y":60,"wires":[{"id":"b3475bcf.d6b288"}]}],"out":[],"env":[{"name":"id_on_off","type":"str","value":""},{"name":"id_rgb","type":"str","value":""},{"name":"id_bright","type":"str","value":""},{"name":"id_ct","type":"str","value":""}],"color":"#DDAA99"},{"id":"b3475bcf.d6b288","type":"switch","z":"2d0f0584.d8aa7a","name":"was?","property":"meta.input","propertyType":"msg","rules":[{"t":"hask","v":"on","vt":"str"},{"t":"hask","v":"bri","vt":"str"},{"t":"hask","v":"ct","vt":"str"},{"t":"hask","v":"hue","vt":"str"}],"checkall":"true","repair":false,"outputs":4,"x":190,"y":60,"wires":[["5f0ae8c3.9baae8"],["27bdd852.7755d8"],["625c6fb5.e27f3"],["5f20cadd.4fbe04"]]},{"id":"5f0ae8c3.9baae8","type":"change","z":"2d0f0584.d8aa7a","name":"on","rules":[{"t":"move","p":"meta.input.on","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":40,"wires":[["8903d883.8da6e8"]]},{"id":"8903d883.8da6e8","type":"ioBroker out","z":"2d0f0584.d8aa7a","name":"AN/AUS","topic":"${id_on_off}","ack":"false","autoCreate":"false","x":760,"y":40,"wires":[]},{"id":"625c6fb5.e27f3","type":"change","z":"2d0f0584.d8aa7a","name":"ct","rules":[{"t":"move","p":"meta.input.ct","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":120,"wires":[["16ef54f7.7aca0b"]]},{"id":"27bdd852.7755d8","type":"change","z":"2d0f0584.d8aa7a","name":"%","rules":[{"t":"move","p":"meta.input.bri","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":80,"wires":[["2798e9f6.606c66"]]},{"id":"16ef54f7.7aca0b","type":"range","z":"2d0f0584.d8aa7a","minin":"153","maxin":"500","minout":"6500","maxout":"2600","action":"clamp","round":true,"property":"payload","name":"","x":570,"y":120,"wires":[["4d7a88c5.b679a8"]]},{"id":"2798e9f6.606c66","type":"range","z":"2d0f0584.d8aa7a","minin":"4","maxin":"254","minout":"1","maxout":"100","action":"scale","round":true,"property":"payload","name":"","x":550,"y":80,"wires":[["fe3442c.2a198c"]]},{"id":"5f20cadd.4fbe04","type":"change","z":"2d0f0584.d8aa7a","name":"rgb","rules":[{"t":"move","p":"rgb","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":160,"wires":[["3a67967f.0f7b6a"]]},{"id":"3a67967f.0f7b6a","type":"color-convert","z":"2d0f0584.d8aa7a","input":"rgb","output":"hex","outputType":"string","scaleInput":false,"x":570,"y":160,"wires":[["2018210e.d81d7e"]]},{"id":"2018210e.d81d7e","type":"ioBroker out","z":"2d0f0584.d8aa7a","name":"Farbe","topic":"${id_rgb}","ack":"false","autoCreate":"false","x":750,"y":160,"wires":[]},{"id":"fe3442c.2a198c","type":"ioBroker out","z":"2d0f0584.d8aa7a","name":"Helligkeit","topic":"${id_bright}","ack":"false","autoCreate":"false","x":760,"y":80,"wires":[]},{"id":"4d7a88c5.b679a8","type":"ioBroker out","z":"2d0f0584.d8aa7a","name":"ct","topic":"${id_ct}","ack":"false","autoCreate":"false","x":750,"y":120,"wires":[]}]
      

      Vielleicht hilft es ja dem einen oder anderem ebenfalls weiter das WIrrwar in Node Red etwas aufzuräumen.
      Als nächstes baue ich mir dann noch Flows für die Zigbee Geräte die über deconz eingebunden sind.

      posted in Praktische Anwendungen (Showcase)
      S
      Soulforged

    Latest posts made by Soulforged

    • [Tutorial] Node Red Sub-Flow: Yeelights steuern mit Alexa

      Hallo Community,

      Ich melde mich nach langer Zeit mal wieder zurück und möchte einen kleinen Sub-Flow mit euch teilen um Yeelights über Alexa und Node-Red mit node-red-contrib-amazon-echo ansteuern zu können. Entstanden ist dieser Flow aus mehreren Gründen. Zum einen wurden es im laufen der Zeit extrem viele Datenpunkte die im Hauptflow eingefügt werden mussten und ich hatte das Problem, dass teilweise Farben die in VIS gesetzt wurden später durch Alexa beim Ausschalten überschrieben wurden.

      Hoffentlich ist das ganze nicht doppelt. Als voraussetzung muss noch das node-red-contrib-color-convert Paket installiert werden.

      Nach dem Einfügen vom Flow gebt ihr diesem noch die IDs der Datenpunkte für power, rgb, active_bright und ct mit

      Anmerkung 2020-03-01 163347.png

      [{"id":"2d0f0584.d8aa7a","type":"subflow","name":"Yeelight","info":"","category":"","in":[{"x":60,"y":60,"wires":[{"id":"b3475bcf.d6b288"}]}],"out":[],"env":[{"name":"id_on_off","type":"str","value":""},{"name":"id_rgb","type":"str","value":""},{"name":"id_bright","type":"str","value":""},{"name":"id_ct","type":"str","value":""}],"color":"#DDAA99"},{"id":"b3475bcf.d6b288","type":"switch","z":"2d0f0584.d8aa7a","name":"was?","property":"meta.input","propertyType":"msg","rules":[{"t":"hask","v":"on","vt":"str"},{"t":"hask","v":"bri","vt":"str"},{"t":"hask","v":"ct","vt":"str"},{"t":"hask","v":"hue","vt":"str"}],"checkall":"true","repair":false,"outputs":4,"x":190,"y":60,"wires":[["5f0ae8c3.9baae8"],["27bdd852.7755d8"],["625c6fb5.e27f3"],["5f20cadd.4fbe04"]]},{"id":"5f0ae8c3.9baae8","type":"change","z":"2d0f0584.d8aa7a","name":"on","rules":[{"t":"move","p":"meta.input.on","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":40,"wires":[["8903d883.8da6e8"]]},{"id":"8903d883.8da6e8","type":"ioBroker out","z":"2d0f0584.d8aa7a","name":"AN/AUS","topic":"${id_on_off}","ack":"false","autoCreate":"false","x":760,"y":40,"wires":[]},{"id":"625c6fb5.e27f3","type":"change","z":"2d0f0584.d8aa7a","name":"ct","rules":[{"t":"move","p":"meta.input.ct","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":120,"wires":[["16ef54f7.7aca0b"]]},{"id":"27bdd852.7755d8","type":"change","z":"2d0f0584.d8aa7a","name":"%","rules":[{"t":"move","p":"meta.input.bri","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":80,"wires":[["2798e9f6.606c66"]]},{"id":"16ef54f7.7aca0b","type":"range","z":"2d0f0584.d8aa7a","minin":"153","maxin":"500","minout":"6500","maxout":"2600","action":"clamp","round":true,"property":"payload","name":"","x":570,"y":120,"wires":[["4d7a88c5.b679a8"]]},{"id":"2798e9f6.606c66","type":"range","z":"2d0f0584.d8aa7a","minin":"4","maxin":"254","minout":"1","maxout":"100","action":"scale","round":true,"property":"payload","name":"","x":550,"y":80,"wires":[["fe3442c.2a198c"]]},{"id":"5f20cadd.4fbe04","type":"change","z":"2d0f0584.d8aa7a","name":"rgb","rules":[{"t":"move","p":"rgb","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":160,"wires":[["3a67967f.0f7b6a"]]},{"id":"3a67967f.0f7b6a","type":"color-convert","z":"2d0f0584.d8aa7a","input":"rgb","output":"hex","outputType":"string","scaleInput":false,"x":570,"y":160,"wires":[["2018210e.d81d7e"]]},{"id":"2018210e.d81d7e","type":"ioBroker out","z":"2d0f0584.d8aa7a","name":"Farbe","topic":"${id_rgb}","ack":"false","autoCreate":"false","x":750,"y":160,"wires":[]},{"id":"fe3442c.2a198c","type":"ioBroker out","z":"2d0f0584.d8aa7a","name":"Helligkeit","topic":"${id_bright}","ack":"false","autoCreate":"false","x":760,"y":80,"wires":[]},{"id":"4d7a88c5.b679a8","type":"ioBroker out","z":"2d0f0584.d8aa7a","name":"ct","topic":"${id_ct}","ack":"false","autoCreate":"false","x":750,"y":120,"wires":[]}]
      

      Vielleicht hilft es ja dem einen oder anderem ebenfalls weiter das WIrrwar in Node Red etwas aufzuräumen.
      Als nächstes baue ich mir dann noch Flows für die Zigbee Geräte die über deconz eingebunden sind.

      posted in Praktische Anwendungen (Showcase)
      S
      Soulforged
    • RE: Xiaomi Yeelight Smart LED (DE)

      @reini:

      Blöde Frage, wie importiere ich diese Widgets?

      thx `

      Im Vis einfach oben auf Widget importieren und dann den Code (Text) reinkopieren.

      posted in Praktische Anwendungen (Showcase)
      S
      Soulforged
    • [Vorlage] Einbinden des Xiaomi Mijia Bluetooth Thermo- und Hygrometer

      Mir ist es endlich gelungen mein Bluetooth Thermo- und Hygrometer in ioBroker einzubinden. Nun möchte ich meine Lösung allen anderen natürlich auch zur Verfügung stellen. Ich Kürze das Gerät im folgenden mit TH ab.

      Fangen wir mit den Vorraussetzungen an: Wir benötigen auf unserem Host-System (in meinem Fall ein Raspi3) das Programm gatttool um auf die Bluetooth LE Schnittstelle zugreifen zu können. Wer den Bluetooth Adapter installier hat, wird diesen Schritt schon durchlaufen haben. Für alle anderen heißt es zunächt die Consolte zu öffnen

      sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev
      

      Als nächstes müsst ihr die MAC-Adresse eures TH herausbekommen. Ich habe hierzu eine Android-App namens nRF Connect benutzt. Diese wurde beim Bluetooth Adapter empfohlen und hat sehr gut funktoiniert https://play.google.com/store/apps/deta … ndroid.mcp

      Nun werden wir in einem kleinen JavaScript in ioBroker mit Hilfe des gatttools in regelmäßigen Abständen Messwerte vom TH anfordern. In den ersten 3 Zeilen des Scripts trag ihr bitte die MAC Adresse eures TH ein und wählt ein Abfrageintervall aus. Ich habe meines auf 5 Minuten gestellt, da Temperatur und Luftfeuchte in aller Regel sich sehr langsam verändernde größen sind. Je seltener man es durchführt umso schonender ist es für die Batterie in dem kleinen Gerät. die Sekunden bitte auf 0 stehen lassen sofern euer Intervall auch in Minuten angegeben wird.

      ! ````
      const pollrate_s = 0; //Abfrageintervall in Sekunden (bei nutzung der Minuten auf 0 Stellen)
      const pollrate_m = 5; //Abfrageintervall in Minuten (Empfehlung alle 5 Minuten / Temperaturänderung ist langsam / Schont die Batterie)
      const bluetooth_mac = '4C:65:A8:D0:13:83';
      ! const s_temp = "javascript.0.Bluetooth.XiaomiHygroTemp.Temperatur";
      const s_hygro = "javascript.0.Bluetooth.XiaomiHygroTemp.Luftfeuchte";
      ! createState(s_temp, 0,{unit: "°C", name: "Temperatur"});
      createState(s_hygro, 0,{unit: "%", name: "Luftfeuchte"});
      ! var cronstring;
      if (pollrate_s > 0) {
      cronstring = "*/" + pollrate_s + " * * * * ";
      }
      else {
      cronstring = "
      /" + pollrate_m + " * * * *";
      }
      ! schedule(cronstring, function () {
      poll_XiaomiHygroTemp(bluetooth_mac);
      });
      ! function poll_XiaomiHygroTemp(mac){
      var i = 1;
      var bluetooth_message = '';
      var messwerte;
      var temperatur;
      var feuchte;

      var spawn = require('child_process').spawn,
      gattool    = spawn('gatttool',['-b', mac , '--char-write-req', '-a', '0x10', '-n', '0100' ,'--listen']);
      
      gattool.stdout.on('data', function (data) {
        //console.log('stdout: ' + data.toString());
        bluetooth_message += data.toString();
        if(i==5) { //5 stdout nachrichten abfangen. Ergibt overhead + ca 1,5-2 mal einen Messwert.
            gattool.kill('SIGQUIT'); //gatttool in kommandozeile unsanft beenden
            //console.log('message:' + bluetooth_message);
            messwerte = bluetooth_message.substr(82,38); 
            stellen = bluetooth_message.substr(82,38).split(" "); //Messwerte extrahieren (stehen immer an der gleichen stelle der Ausgabe) und an leerzeichen auftrennen. 
            //Temperatur ist dann im Array an 2 (Zehner) 3 (Einer) 4 (Komma) und 5(Nachkommestelle) Stelle
            //Feuchte an Stelle 9 (Zehner) 10 (Einer) 11 (Komma) und 12 (Nachkommestelle) 
            //Ziffern ins ASCII sind 30+Ziffer. Also je 30 abziehen und mit der Zehnerpotenz multiplizieren
            temperatur = (stellen[2]-30)*10+(stellen[3]-30)+(stellen[5]-30)/10;
            feuchte = (stellen[9]-30)*10+(stellen[10]-30)+(stellen[12]-30)/10;
            //console.log('Temp:' + temperatur);
            //console.log('Feuchte:' + feuchte);
            setState(s_temp, temperatur, true);
            setState(s_hygro, feuchte, true);
        }
        i++;
      });
      
      gattool.stderr.on('data', function (data) {
        //console.log('stderr: ' + data.toString());
        log("Xiaomi hat nicht geantwortet. Warte auf nächsten Poll")
      });
      

      }

      
      Das Script erzeugt nach dem ersten Durchlauf zwei States in javascript.0.Bluetooth.XiaomiHygroTemp für Temperatur und Luftfeuchte.
      
      Diese kann man im vis z.B. in eine HTML-Tabelle packen:
      
      >! ````
      [{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":true,"g_css_border":true,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"Klima\n\n    \n        \n        \n    \n    \n        \n        \n    \n
      >! | Temperatur: | {javascript.0.Bluetooth.XiaomiHygroTemp.Temperatur} °C |
      | Luftfeuchte: | {javascript.0.Bluetooth.XiaomiHygroTemp.Luftfeuchte}% |
      >! "},"style":{"left":"860px","top":"180px","color":"#EEEEEE","border-width":"2px","border-style":"solid","width":"227px","height":"85px","font-size":"larger","z-index":"0","line-height":"25px","border-radius":"10px","border-color":"#EEEEEE","padding-left":"6px","padding-top":"3px"},"widgetSet":"basic"}]
      
      posted in ioBroker Allgemein
      S
      Soulforged
    • Zwei Objekte in vis Binding vergleichen

      Guten Abend zusammen,

      ich verzweifle gerade etwas an den Skripten in vis.

      Ich habe mir eine nette Ansicht mit den aktuellen Spritpreisen aus dem Tankerkönig-Adapter zusammengebaut. Das funktioniert soweit super.

      Nun wollte ich noch einbauen, dass je Kraftstoffart noch der jeweils beste Preis in grüner Schrift angezeigt wird.

      Mein Lösungsansatz war ins Font & Text –> color ein Binding einzubauen

      {wert1:tankerkoenig.0.stations.1.e5.combined;wert2:tankerkoenig.0.stations.cheapest.e5.combined; (wert1==wert2) ? "green" : "#EEEEEE"}

      Leider funktioniert das nicht. Die Schrift bleibt schwarz, was genau genommen keine der beiden Möglichkeiten entsprich die vorgegeben habe.

      Ich habe das Binding auch Testweise an anderen Stellen (z.B. HTML Widget) als Text probiert und bekomme dabei einfach eine 0.

      Kann mir jemand einen Tipp geben wo mein Denkfehler liegt?

      EDIT: Habe es herausgefunden! Über Child_Process.spawn ging was. Fertiges Script zur Einbindung poste ich gleich in den Funktionsansagen.

      posted in Visualisierung
      S
      Soulforged
    • Problem beim Einbinden des Xiaomi Bluetooth Thermo- und Hygrometer

      Hallo Community,

      ich habe seit einiger Zeit von Xiaomi ein kleines rundes Thermometer/Hygrometer mit Display und Bluetooth LE Schnittstelle.

      Nun wollte ich natürlich die Werte von dem Teil auch an ioBroker. Mit dem BLE Adapter funktioniert es leider nicht, weil das Gerät die Mwsswerte nicht in seinen "advertised" services hat, sondern nur als notification die angefragt (request) werden muss. Durch einen Hinweis beim FHEM Forum bin ich dann auf das Kommandozeilentool GATTTOOL gestoßen mit dem Genau das möglich ist. Über die Kommandozeile konnte ich so die Werte entsprechend auslesen. Die Hex werte können direkt in ASCII gewandelt werden. Im folgenden Bespielt heißt das Ergebnis umgewandelt also "T=22.7 H=33.7"

      Auf einen Request folgen 10(!) Notifications des Sensors und anschließend ist ruhe.

      pi@ioBroker-Pi:~ $ gatttool -b 4C:65:A8:D0:13:83 --char-write-req -a 0x10 -n 0100 --listen
      Characteristic value was written successfully
      Notification handle = 0x000e value: 54 3d 32 32 2e 37 20 48 3d 33 33 2e 37 00
      Notification handle = 0x000e value: 54 3d 32 32 2e 35 20 48 3d 33 33 2e 39 00
      Notification handle = 0x000e value: 54 3d 32 32 2e 36 20 48 3d 33 33 2e 37 00
      Notification handle = 0x000e value: 54 3d 32 32 2e 35 20 48 3d 33 34 2e 30 00
      Notification handle = 0x000e value: 54 3d 32 32 2e 36 20 48 3d 33 33 2e 37 00
      Notification handle = 0x000e value: 54 3d 32 32 2e 34 20 48 3d 33 34 2e 30 00
      Notification handle = 0x000e value: 54 3d 32 32 2e 36 20 48 3d 33 33 2e 39 00
      Notification handle = 0x000e value: 54 3d 32 32 2e 36 20 48 3d 33 34 2e 30 00
      Notification handle = 0x000e value: 54 3d 32 32 2e 36 20 48 3d 33 33 2e 38 00
      Notification handle = 0x000e value: 54 3d 32 32 2e 35 20 48 3d 33 34 2e 30 00
      

      Nun kommt mein Problem, von dem ich hoffe, dass einer von euch bei dessen Lösung behilflich sein kann:

      Führt man das gatttool wie oben beschrieben aus wird es so lange ausgeführt bis man mit Strg+C abbricht. D.h. die 10 Werte kommen rein und anschließend passiert einfach nichts mehr.

      Wenn ich also in Java Script per "exec()" gatttool aufrufe bekomme ich leider nie ein gültige antwort. Hat von euch jemand eine Idee wie ich die Werte aus der Kommandozeile nach ioBroker bekomme? Das Ziel ist in greifbarer Nähe, aber doch so fern…

      posted in Skripten / Logik
      S
      Soulforged
    • RE: Xiaomi Yeelight Smart LED (DE)

      @e-p-s:

      Vielleicht Erbamt sich mal jemand und macht einen Nativ Adapter. `
      Das dachte ich anfangs auch, bin mir aber aktuell gar nicht mehr so sicher wie sinnvoll das ist. Ein Adapter braucht fast immer an die 30MB Ram und der ist leider, zumindest auf meinem Raspi 3, relativ knapp. Wenn ich überlege, dass ich teilweise für nur 1 Gerät und davon 2 Kommandos einen ganzen Adapter installieren muss.

      Da die Yeelights bei mir die Hälfte aller Geräte ausmachen muss ich dir aber schon recht geben. Ein Adapter wäre schön. Ich wollte mich ohnehin mal mit der Adapterentwicklung beschäftigen, wenn der Rest von meinem System komplett läuft. Vielleicht mache ich das mal auf Basis von Magdas Scripten (+meine eigenen Erweiterungen)

      posted in Praktische Anwendungen (Showcase)
      S
      Soulforged
    • RE: Adapter-Anfrage Sony Bravia TV

      @Schuko80:

      Ich sage schon mal danke, werde es mir am Wochenende mal ansehen, aktuell bin ich leider etwas angeschlagen `
      Gib mir bitte mal kurz Bescheid ob es bei dir auch funktioniert. Wenn ich irgendwann etwas Zeit finde werde ich versuchen mein Skript direkt in den Adapter mit aufzunehmen, dann muss der TV nicht mehr an zwei stellen integriert werden.

      Aktuell sehe ich aber, dass der Adapter häufig auf "gelb" springt, weil der TV nicht erreichbar wäre. Ich habe die "einfache IP Steuerung" (= Low Level Protokoll) bei meinem deaktiviert, weil er dann keinen TCP Dienst aufrecht erhält, der scheinbar viel Strom benötigt aber für unser vorhaben nicht notwendig ist, weil mein Script und auch der Adapter auf HTTP Requests und das damit verbundene "High Level" Protokoll aufbauen.

      posted in ioBroker Allgemein
      S
      Soulforged
    • RE: Adapter-Anfrage Sony Bravia TV

      Sooo alle zusammen. Ich habe ein Skript gebastelt, dass von unseren Bravia TVs den aktuellen Status, die aktuelle Laustärke und den aktuellen Titel auslesen kann.

      Ich musste mich erstmal in die Erstellung von HTTP-Requests einlesen, daher hat es etwas gedauert.

      Da mir das Stufenweise hoch und runterschalten der Lautstärke nicht gefallen hat, habe ich den Lautstärke Stat schreibbar gemacht. –> Einfach einen Schieberegler mit step=1 drauf und es sollte gehen.

      Im Skript-Kopf müsst ihr noch die IP des Gerätes, den PSK (also euren vergebenen PIN) und das gewünschte Abfrage-Intervall eingeben. Zusätzlich zur Abfrage alle x sekunden habe ich noch eine Abfrage jeweils 1 Sekunde nach dem Tastendruck aus den Tasten aus dem Adapter eingebaut. Somit bekommt man relativ schnell eine Antwort, wenn man ausschaltet.

      Code hier im "Spoiler" damit der Thread lesbar bleibt.

      ! ```
      `//################### Script Configuration ####################################################
      const bravia_ip = "192.168.1.65"; //Hier die IP des TV einsetzen.
      const psk = "geheim"; //Hier PSK einetzen (PIN der in TV Konfiguration gewählt wurde)
      const poll_intervall = 30; //Abfrageintervall für den Status in Sekunden
      //#############################################################################################
      ! const request = require('request');
      //const util = require('util');
      var message_id = 0;
      ! //Alle Konstanten und States erstellen, die abgefragt werden sollen
      const s_powerstate = 'javascript.0.Bravia.powerstate'; //An/Aus Status
      const s_nowplaying = 'javascript.0.Bravia.nowPlaying'; //aktueller Titel
      const s_volume = 'javascript.0.Bravia.actVolume'; //aktuelle Lautstärke
      ! createState(s_powerstate, "unknown", {type: "string", role: "State"});
      createState(s_nowplaying, "unknown", {type: "string", role: "State"});
      createState(s_volume, "unknown", {type: "string", role: "State"});
      ! function getTVStatus(){ //Funktion führt nacheinander alle ABfragen durch. Wirde als schedule alle x Sekunden ausgeführt.
      bravia('/sony/system','getPowerStatus', [], s_powerstate);
      bravia('/sony/audio', 'getVolumeInformation', [], s_volume);
      bravia('/sony/avContent', 'getPlayingContentInfo', [], s_nowplaying);
      }
      schedule("*/"+poll_intervall+" * * * *", getTVStatus);
      ! function bravia(tv_urlextension, tv_method, tv_params, tv_stateID){ //Funktion fragt einzelnen Stat ab
      //tv_urlextension = in welchem "ordner" liegt die Methode
      //tv_method = wie heißt die Methode (zB. getPowerStatus)
      //tv_params = welche Parameter müssen an die Methode übergeben werden (bei PowerStatus leer []
      //tv_stateID = wo soll das Ergebnis gespeichert werden

      if (message_id > 5000){ //fortlaufende id um Nachrichten identifizieren zu können. Läuft zwischen 5000 und 1.
          message_id=1;
      }else{
          message_id +=1;
      }
      
      request({ //TV Anfragen
          url: 'http://' + bravia_ip + tv_urlextension,
          method: "POST",
          json: true,
          headers: {
             'X-Auth-PSK': psk,
             'connection' : 'close'
          },
          body: { 
                  'method': tv_method,
                  'params': tv_params,
                  'id' : message_id,
                  'version' : '1.0'
              } 
      }, function (error, response, body) {
              //log(response.statusCode);
              //log(util.inspect(body, false, null)); //Komplette ANtwort im Log wegen Debugging
              if (!error && response.statusCode == 200) {
                  if (tv_stateID !== undefined) { //nur wenn State für Update angegeben, sonst handelt es sich um einen BEfehl und keine Statusabfrage
                      //Je nach abgefragtem Status sieht die Antwort anders aus --> Switch unterscheidet
                      var wert = ''; //wenn nichts gefunden wird, nehmen wir an, der TV wäre aus.
                      if(!body.hasOwnProperty('error')) { //Wenn ein Fehler zurück kommt, (zB TV ist aus und Lautstärke wird abgefragt) --> tue nichts
      
                          switch(tv_method){ //je nach ABfrage versteckt sich der wert an einer anderen stelle im result
                              case 'getPowerStatus':
                                  wert = body.result[0].status;
                                  break;
                              case 'getVolumeInformation': //Bei Volume muss nach dem key volume gesucht werden bei dem target : speaker 
                                  for (var i =0; i<=body.result[0].length; i++)
                                  {
                                       if (body.result[0][i].target =="speaker") {wert=body.result[0][i].volume.toString(); break;}
                                  }
                                  break;
                               case 'getPlayingContentInfo': //Bei bei playing content ziehen wir uns den wert "title"
                                  wert = body.result[0].title;
                                  break;    
                              default: 
                                  return false;
                          }
                      }
                      //log(tv_method+": "+wert);
                      setState(tv_stateID, wert, true); //State schreiben mit Ack flag --> wert aktualisiert
                  }
              }
          }
      );
      

      }

      ! //Subscription auf alle Funktionen aus Adapter (=Befehle an TV). ~1 Sekunden nach Befehl an TV Status abfragen
      subscribe({id: /^sony-bravia.0.*/}, function (obj) {
      setTimeout(getTVStatus, 1000);
      }
      );
      ! //Lautstärke-Änderung über Schieberegler --> subscribe auf Läutstäre State. Bei Änderung Nachricht an TV mit neuer Lautstärke
      subscribe({id: s_volume, change: "ne"}, function (obj) {
      bravia('/sony/audio', 'setAudioVolume', [{"target": "speaker", "volume": obj.state.val.toString()}]);
      setTimeout(getTVStatus, 1000); //Sekunde später Werte lesen
      }
      );` [/i][/i]

      posted in ioBroker Allgemein
      S
      Soulforged
    • RE: Xiaomi Yeelight Smart LED (DE)

      @wecker6789:

      Guten Tag,

      Meinen vollsten Respekt an euch alle.

      Bei mir hört es leider schon auf wie ich den Bash.script auf dem IOBroker installiere?

      Ich fühle mich da wirklich doof…..

      Hoffe es kann mir dort jemand helfen.

      Danke an euch. `

      Hallo Wecker6789,

      ein Script muss nicht installiert werden 😉 Es genügt völlig, wenn du es an der entsprechenden Ordner auf dem Raspberry (/opt/iobroker) legst. Dazu kannst du bspw. die ftp Verbindung nutzen.

      Wenn du Magdas Script verwendest, benötigst du aber das Bash-Script nicht, da die JavaScripts die komplette Steuerung übernehmen.

      –---------------------------------------------------------------------------------------------

      Ich habe bis eben mit meinen Yeelight Ceiling Lights gekämpft. Diese haben einen sogenannten "Moon-Mode" bzw. Nightmode, der bislang nicht ansteuerbar war. Nun habe ich herausgefunden, dass diese durch ein weiteres argument namens "mode" beim "set_power" gesetzt werden können, wenn mode auf 5 steht (0=default, 1-3 sind RGB, HUE+Sat und weiß).

      Nun habe ich die Scripts von Magda nach meinen Bedürfnissen etwas erweitert.

      Find:

      Es wird grundsätzlich ein stat "model" mit angelegt, welche die Art der Lampe enthält (zb. "color", "strip" und eben auch "ceiling" bzw "ceiling1" (letzte erst mit der neuesten Firmware). Wenn Model nun "Ceiling" oder "Ceiling1" ist wird ein weiterer stat namens "nightmode" angelet.

      Add:

      Ich fange die Änderungen von Nightmode mit ab und führe bei true den Befehl set_power mit dem modus 5 aus. Zurücksetzen geht indem man die colortemperature ändert --> die eingestellte wird nochmals geschickt.

      Hier die beiden angepassten Scripte, falls sie jemand bei sich auch ausporbieren möchte:

      yeelight add:

      ! var net = require('net');
      ! var clients = [];
      ! var debug = true;
      ! const switchEffect = 'smooth'; //smooth or sudden
      ! const switchEffectTime = 1000; // min value 30
      ! const s_dataset = 'javascript.0.Yeelight.Bulb';
      ! const s_bright = '.bright';
      ! const s_hue = '.hue';
      ! const s_colorMode = '.color_mode';
      ! const s_rgb = '.rgb';
      ! const s_sat = '.sat';
      ! const s_power = '.power';
      ! const s_ct = '.ct';
      ! const s_name = '.name';
      ! const s_nightmode = '.nightmode';
      ! const s_model = '.model';
      ! function createClient(bulbID, location) {
      ! var port = (new RegExp(':([0-9]{1,5})')).exec(location)[1];
      ! var ipAddress = (new RegExp('(?:[0-9]{1,3}.){3}[0-9]{1,3}')).exec(location)[0];
      ! clients[bulbID - 1] = net.createConnection(port, ipAddress);
      ! if (debug) console.log('Client erstellt für Lampe ' + bulbID);
      ! clients[bulbID - 1].on('data', function(data) {
      ! if (debug) console.log('Empfangen: ' + data);
      ! notificationReceived(bulbID, data)
      ! });
      ! clients[bulbID - 1].on('close', function() {
      ! if (debug) console.log('Verbindung geschlossen');
      ! });
      ! clients[bulbID - 1].on('error', function() {
      ! if (debug) console.log('Verbindung fehlerhaft');
      ! });
      ! }
      ! function killClient(bulbID) {
      ! if (clients[bulbID - 1]) {
      ! clients[bulbID - 1].destroy();
      ! if (debug) console.log('Client beendet für Lampe ' + bulbID);
      ! }
      ! }
      ! function sendBulbCommand(bulbID, changedValue, param1, effect, effectTime) {
      ! var command;
      ! var p_mode=0;
      ! switch (changedValue) {
      ! case 'ct':
      ! //wenn die Lampe eine Ceiling ist, geht der Nightmode mit aus. Da kein Status zurück kommt, muss er hier gesetzt werden. Wenn Nightmode aus gesetzt wird, wird ohnehin ct gesetzt, also nur nightmode ausschalten
      ! var bulbmodel = getState(s_dataset + bulbID + s_model).val;
      ! if( bulbmodel =="ceiling" || bulbmodel == "ceiling1") {
      ! setState(s_dataset + bulbID + s_nightmode, false, false);
      ! return;
      ! }else{
      ! command = '{"id":' + bulbID + ',"method":"set_ct_abx","params":[' + param1 + ', "' + effect + '", ' + effectTime + ']}\r\n';
      ! }
      ! break;
      ! case 'rgb':
      ! command = '{"id":' + bulbID + ',"method":"set_rgb","params":[' + parseInt(param1.substring(1), 16) + ', "' + effect + '", ' + effectTime + ']}\r\n';
      ! break;
      ! case 'hue':
      ! var sat = getState(s_dataset+ bulbID + '.sat').val;
      ! command = '{"id":' + bulbID + ',"method":"set_hsv","params":[' + param1 + ', ' + sat + ', "' + effect + '", ' + effectTime + ']}\r\n';
      ! break;
      ! case 'sat':
      ! var hue = getState(s_dataset + bulbID + '.hue').val;
      ! command = '{"id":' + bulbID + ',"method":"set_hsv","params":[' + hue + ', ' + param1 + ', "' + effect + '", ' + effectTime + ']}\r\n';
      ! break;
      ! case 'bright':
      ! command = '{"id":' + bulbID + ',"method":"set_bright","params":[' + param1 + ', "' + effect + '", ' + effectTime + ']}\r\n';
      ! break;
      ! case 'power':
      ! command = '{"id":' + bulbID + ',"method":"set_power","params":["' + param1 + '", "' + effect + '", ' + effectTime + ']}\r\n';
      ! break;
      ! case 'nightmode':
      ! if(param1===true) { //night mode can only be set through power command with mode = 5
      ! p_mode = 5;
      ! command = '{"id":' + bulbID + ',"method":"set_power","params":["on", "' + effect + '", ' + effectTime + ', ' + p_mode + ']}\r\n';
      ! }else{ //night mode is unset through change of color temp –> set color temperature to last known value
      ! var last_known_ct = getState(s_dataset + bulbID + s_ct).val;
      ! command = '{"id":' + bulbID + ',"method":"set_ct_abx","params":[' + last_known_ct + ', "' + effect + '", ' + effectTime + ']}\r\n';
      ! }
      ! break;
      ! case 'toggle':
      ! command = '{"id":' + bulbID + ',"method":"toggle","params":[]}\r\n';
      ! break;
      ! default:
      ! if (debug) console.log('Unbekanntes Kommando');
      ! return;
      ! }
      ! if (debug) console.log(command);
      ! var commandClient = new net.Socket();
      ! //if (debug) console.log(clients[bulbID - 1].remoteAddress);
      ! //if (debug) console.log(clients[bulbID - 1].remotePort);
      ! var location = getState('javascript.0.Yeelight.Bulb' + bulbID + '.Location').val;
      ! var port = (new RegExp(':([0-9]{1,5})')).exec(location)[1];
      ! var ipAddress = (new RegExp('(?:[0-9]{1,3}.){3}[0-9]{1,3}')).exec(location)[0];
      ! commandClient.connect(port, ipAddress, function() {
      ! commandClient.write(command);
      ! if (debug) console.log("CommandClient Command gesendet");
      ! });
      ! commandClient.on('data', function(data) {
      ! if (debug) console.log('CommandClient empfangen: ' + data);
      ! commandClient.destroy(); // kill client after server's response
      ! if (debug) console.log('CommandClient beendet');
      ! });
      ! }
      ! function notificationReceived(bulbID, data) {
      ! var notification = JSON.parse(data);
      ! if (notification.params.power) {
      ! setState(s_dataset + bulbID + s_power, notification.params.power, true);
      ! }
      ! if (notification.params.bright) {
      ! setState(s_dataset + bulbID + s_bright, parseInt(notification.params.bright), true);
      ! }
      ! if (notification.params.ct) {
      ! setState(s_dataset + bulbID + s_ct, parseInt(notification.params.ct), true);
      ! }
      ! if (notification.params.rgb) {
      ! setState(s_dataset + bulbID + s_rgb, '#' + parseInt(notification.params.rgb).toString(16), true);
      ! }
      ! if (notification.params.hue) {
      ! setState(s_dataset + bulbID + s_hue, parseInt(notification.params.hue), true);
      ! }
      ! if (notification.params.sat) {
      ! setState(s_dataset + bulbID + s_sat, parseInt(notification.params.sat), true);
      ! }
      ! if (notification.params.color_mode) {
      ! setState(s_dataset + bulbID + s_colorMode, parseInt(notification.params.color_mode), true);
      ! }
      ! }
      ! //Subscribe für Änderung der Datenpunkte
      ! subscribe({id: /^javascript.0.Yeelight.Bulb./, change: 'any', ack: false}, function (obj) {
      ! var bulbID = (new RegExp('^javascript.0.Yeelight.Bulb([0-9]?[0-9]).')).exec(obj.id)[1];
      ! var changedValue = (new RegExp('^javascript.0.Yeelight.Bulb[0-9]?[0-9].(.
      )')).exec(obj.id)[1];
      ! if (debug) console.log('Kommando für Lampe ' + bulbID + ' mit ' + changedValue);
      ! if (changedValue == 'Location') {
      ! killClient(bulbID);
      ! createClient(bulbID, obj.state.val);
      ! } else {
      ! sendBulbCommand(bulbID, changedValue, obj.state.val, switchEffect, switchEffectTime);
      ! }
      ! });

      yeelight_find

      ! var dgram = require('dgram');
      ! var s = dgram.createSocket('udp4');
      ! var debug = true;
      ! const MULTICAST_IP = '239.255.255.250';
      ! const s_dataset = 'javascript.0.Yeelight.Bulb';
      ! const s_id = '.id';
      ! const s_address = '.Location';
      ! const s_bright = '.bright';
      ! const s_hue = '.hue';
      ! const s_colorMode = '.color_mode';
      ! const s_rgb = '.rgb';
      ! const s_sat = '.sat';
      ! const s_power = '.power';
      ! const s_ct = '.ct';
      ! const s_name = '.name';
      ! const s_group = '.group';
      ! const s_model = '.model';
      ! const s_nightmode = '.nightmode';
      ! s.bind(1982, function() {
      ! s.addMembership(MULTICAST_IP);
      ! if (debug) console.log("listening on all addresses");
      ! });
      ! s.on("message", function (msg, rinfo) {
      ! if (debug) console.log('Broadcast empfangen: ' + msg);
      ! if (msg.indexOf('yeelight') < 0) {
      ! if (debug) console.log("Kein Yeelight Broadcast");
      ! return;
      ! }
      ! var bulbID = extractValue('id: ', msg);
      ! var i = 1;
      ! var unknownBulb = true;
      ! //wenn Lampe vorhanden, dann Werte aktualisieren
      ! while (getObject(s_dataset + i + s_id)) {
      ! if (getState(s_dataset + i + s_id).val == bulbID) {
      ! setState(s_dataset + i + s_address, extractValue('Location: ', msg), false);
      ! setState(s_dataset + i + s_bright, parseInt(extractValue('bright: ', msg)), true);
      ! setState(s_dataset + i + s_hue, parseInt(extractValue('hue: ', msg)), true);
      ! setState(s_dataset + i + s_colorMode, parseInt(extractValue('color_mode: ', msg)), true);
      ! setState(s_dataset + i + s_rgb, '#' + parseInt(extractValue('rgb: ', msg)).toString(16), true); //Wert umgewandelt von Dec zu Hex damit Colorpicker Widget einfacher zu nutzen ist
      ! setState(s_dataset + i + s_sat, parseInt(extractValue('sat: ', msg)), true);
      ! setState(s_dataset + i + s_ct, parseInt(extractValue('ct: ', msg)), true);
      ! setState(s_dataset + i + s_power, extractValue('power: ', msg), true);
      ! setState(s_dataset + i + s_model, extractValue('model: ', msg), true);
      ! unknownBulb = false;
      ! if (debug) console.log('Werte für Lampe ' + i + ' aktualisiert');
      ! break;
      ! }
      ! i++;
      ! //Notaus
      ! if (i >= 100) {
      ! if (debug) console.log('zu viele Schleifendurchläufe');
      ! break;
      ! }
      ! }
      ! //wenn Lampe nicht gefunden, dann neue Lampe erstellen
      ! if (unknownBulb) {
      ! if (debug) console.log('neue Lampe wird erstellt');
      ! createNewBulb(i, msg);
      ! }
      ! });
      ! function createNewBulb(i, msg) {
      ! createState(s_dataset + i + s_id, extractValue('id: ', msg), {read: true, write: true, desc: "unique ID der Yeelight Lampe", type: "string", def: ""});
      ! createState(s_dataset + i + s_address, extractValue('Location: ', msg), {read: true, write: true, desc: "URL der Yeelight Lampe", type: "string", def: ""});
      ! createState(s_dataset + i + s_bright, parseInt(extractValue('bright: ', msg)), {read: true, write: true, desc: "Helligkeit", type: "number", min: 1, max: 100, def: 1, unit: "%"});
      ! createState(s_dataset + i + s_hue, parseInt(extractValue('hue: ', msg)), {read: true, write: true, desc: "HSV Farbwert", type: "number", min: 0, max: 359, def: 1, unit: ""});
      ! createState(s_dataset + i + s_colorMode, parseInt(extractValue('color_mode: ', msg)), {read: true, write: true, desc: "Farbwert", type: "number", min: 1, max: 3, def: 1, unit: ""});
      ! createState(s_dataset + i + s_rgb, '#' + parseInt(extractValue('rgb: ', msg)).toString(16), {read: true, write: true, desc: "RGB Farbwert in HEX", type: "string", def: ""});
      ! createState(s_dataset + i + s_sat, parseInt(extractValue('sat: ', msg)), {read: true, write: true, desc: "HSV Sättigung", type: "number", min: 1, max: 100, def: 1, unit: ""});
      ! createState(s_dataset + i + s_ct, parseInt(extractValue('ct: ', msg)), {read: true, write: true, desc: "Farbtemperatur weiß", type: "number", min: 1700, max: 6500, def: 5000, unit: ""});
      ! createState(s_dataset + i + s_power, extractValue('power: ', msg), {read: true, write: true, desc: "Zustand on/off", type: "string", def: ""});
      ! createState(s_dataset + i + s_name, '', {read: true, write: true, desc: "selbst vergebener Name", type: "string", def: "Yeelight"});
      ! createState(s_dataset + i + s_model, extractValue('model: ', msg), {read: true, write: false, desc: "Lampenmodel", type: "string", def: "Yeelight"});
      ! if((extractValue('model: ', msg)=="ceiling")||(extractValue('model: ', msg)=="ceiling1")) { //if it is a ceiling light, create state to activate nightligth mode
      ! createState(s_dataset + i + s_nightmode, 0, {read: false, write: true, desc: "Powermode nightlight", type: "boolean", def: true});
      ! }
      ! createState(s_dataset + i + s_group, i, {read: true, write: true, desc: "Gruppe", type: "number", min: 1, max: 100, def: 1, unit: ""});
      ! if (debug) console.log('neue Lampe erstellt mit ID: ' + i);
      ! }
      ! function extractValue(key, message) {
      ! var text = message.toString('utf-8');
      ! var startPos = (text.indexOf(key) + key.length);
      ! var endPos = text.substring(startPos).indexOf('\r\n');
      ! return text.substr(startPos, endPos);
      ! }
      ! // close connection if script stopped
      ! onStop(function (callback) {
      ! if (s) {
      ! // close connection
      ! s.close();
      ! if (debug) console.log('UDP Client gestoppt');
      ! }
      ! callback();
      ! }, 2000 /ms/);

      posted in Praktische Anwendungen (Showcase)
      S
      Soulforged
    • RE: Adapter-Anfrage Sony Bravia TV

      Den Python Adapter von Domoticz habe ich mir ja angeschaut. Der fragt mittels HTTP Requests quasi bei jedem Knopfdruck einmal das ganze Gerät ab + bei jedem "Heartbeat" des Systems. Funktionieren wird es sicherlich, aber erzeugt auch eine Menge Traffic/Requests die eigentlich unnötig sind.

      Wenn ich Zeit finde (frühestens nächstes Wochenende) schaue ich mal, ob ich die Requests mit JavaScript nachbilden kann. Eigentlich kein Hexenwerk, da meine Yeelights ja auch über HTTP gesteuert werden. Und ich werde mal schauen, ob der TV am Nicht sowieso einen Broadcast mit seinem Status schickt. Dann bräuchte man sich nur auf den registrieren. (Soweit mein Verständnis)

      posted in ioBroker Allgemein
      S
      Soulforged
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo