Autor Thema: Node-Red als Frontend  (Gelesen 14126 mal)

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Node-Red als Frontend
« am: 26 Oktober 2017, 13:07:28 »
Moin  ;)

Es gibt hier noch gar keinen Bereich für Node-Red als Frontend - ja Node-Red ist natürlich auch mehr als das... aber ja durchaus auch ein Frontend.
Gibt es da gar keine Nachfrage nach oder keine Nutzer hier? :-)
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline rudolfkoenig

  • Administrator
  • Hero Member
  • *****
  • Beiträge: 19335
Antw:Node-Red als Frontend
« Antwort #1 am: 26 Oktober 2017, 13:22:13 »
Vermutlich braucht man erst einen Entwickler, die Nutzer kommen dann schon freiwillig :)
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #2 am: 26 Oktober 2017, 13:27:08 »
Ich schau mir das mal an - es agiert ja als MQTT Client. Somit sollte das relativ wenig Aufwand sein, da ja FHEM als Client schon vorhanden ist.

Oder ich werde mein blaues Wunder erleben :-)
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
Antw:Node-Red als Frontend
« Antwort #3 am: 26 Oktober 2017, 14:42:56 »
Da bin ich ja mal gespannt.  :)

Viellicht finde ich ja so doch den Weg zu MQTT.  ;D
FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix

Offline hexenmeister

  • Developer
  • Hero Member
  • ****
  • Beiträge: 4221
    • tech_LogBuch
Antw:Node-Red als Frontend
« Antwort #4 am: 26 Oktober 2017, 14:47:42 »
Durch eine Entkopplung über MQTT ist das noch überhaupt ein FHEM-Thema? Anders gefragt, was muss man denn in FHEM denn noch tun außer generischen MQTT-Bridges?
In Verwendung: HM, EnOcean, 1wire, Firmata, MySensors, ESPEasy, MQTT*, NodeRED, Alexa, Telegram,..
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy
Kaffeekasse: https://www.paypal.me/s6z

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #5 am: 26 Oktober 2017, 14:50:14 »
Berechtigter Einwand... es hat wahrscheinlich weniger mit FHEM zu tun - aber ich habe halt FHEM und werde es versuchen in Node-Red als Oberfläche abzubilden für Handy und Tablet. Daher hat es dann halt wieder was mit FHEM zu tun... :-D

Aber wer weiß schon was da für Probleme aufkommen... :-D Scheint es ja noch gar nicht zu geben.
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline hexenmeister

  • Developer
  • Hero Member
  • ****
  • Beiträge: 4221
    • tech_LogBuch
Antw:Node-Red als Frontend
« Antwort #6 am: 26 Oktober 2017, 15:00:11 »
Nicht falsch zu verstehen... Ich mag MQTT und auch NodeRed.
Mit MQTT verbinde ich mehrere FHEM-Instances miteinander (dafür habe ich sogar paar Erweiterungen zu dem MQTT-Modul beigesteuert) => funktioniert prima (nach mir besser und einfacher als FHEM2FHEM). :)
NodeRed nutze ich für Definitionen einiger Scenarien und für Alexa-Anbindung.
Habe auch schon versucht, IOBrocker als Oberfläche so anzubinden, bin aber mit dem IOBrocker (trotz einiger tollen Features) nicht so richtig warm geworden.
Daher werde ich Dein Vorhaben mit Interesse weiter verfolgen 8)
In Verwendung: HM, EnOcean, 1wire, Firmata, MySensors, ESPEasy, MQTT*, NodeRED, Alexa, Telegram,..
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy
Kaffeekasse: https://www.paypal.me/s6z
Gefällt mir Gefällt mir x 2 Liste anzeigen

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
Antw:Node-Red als Frontend
« Antwort #7 am: 26 Oktober 2017, 15:02:29 »
Habe auch schon versucht, IOBrocker als Oberfläche so anzubinden, bin aber mit dem IOBrocker (trotz einiger tollen Features) nicht so richtig warm geworden.
Daher werde ich Dein Vorhaben mit Interesse weiter verfolgen 8)

Genau so sieht es auch bei mir aus ;)
FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #8 am: 26 Oktober 2017, 15:02:59 »
Hehe alles gut :-)

Hatte ich nicht negativ aufgefasst.
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline ak323

  • Full Member
  • ***
  • Beiträge: 194
Antw:Node-Red als Frontend
« Antwort #9 am: 26 Oktober 2017, 16:57:47 »
... klingt auf jeden Fall nach einem interessanten Ansatz ...
(wenn Du im FHEM Forum suchst, findest Du einige "Schnipsel" an Infos ...)

VG ak323
RaspberryPi 2 im 19" Rack mit 16x2 i2c LCD, FHEM, diverse HomeMatic, 1-Wire (8x DS18B20, 3x DS2408, 2x DS2413, 5x DS2401, DS2423 ATTiny) über DS9490R#, Waterkotte Ai1QE (WWPR) Wärmepumpe über Modbus, WH1080 über Signalduino, 433MHz Funksteckdosen, WiFi Light, WiFi RGB, WiFi RGBWW ...
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
Antw:Node-Red als Frontend
« Antwort #10 am: 29 Oktober 2017, 16:34:02 »
Habe mir nun auch mal Node-RED angesehen, mir ist aber nicht klar wie man damit ein Frontend umsetzten soll. :-[
FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #11 am: 29 Oktober 2017, 18:54:23 »
Node Red + Node-Red-Dashboard (UI)

https://flows.nodered.org/node/node-red-dashboard
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)
Informativ Informativ x 1 Liste anzeigen

Offline Bapt. Reverend Magersuppe

  • Full Member
  • ***
  • Beiträge: 400
  • Flipperball geschluckt!
    • Kotolette!
Antw:Node-Red als Frontend
« Antwort #12 am: 29 Oktober 2017, 20:53:50 »
Wieso nur als Frontend? Das kann man doch dank der Oberfläche schon zur Gestaltung der Automatisierung einsetzen. Nicht nur als Frontend. Lieber anderster herum gedreht den Fall: fhem als Deckel für nodered.
--
If I was born in 1453, Leonardo da Vinci would be jealous of me.
Reverend Paul Egon Magersuppe
https://www.kopp.eu/de/produkt/4008224141147
Manch einer hat die Weisheit mit Löffeln gefressen. Ich Vla.

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #13 am: 29 Oktober 2017, 20:56:43 »
Nun - es kann durchaus sein, dass sich das noch dreht und wendet wenn ich erst mal angefangen habe.

Aber aktuell denke ich erst mal als Frontend.

Effektiv gesehen kannst du FHEM auch weg lassen sofern Node Red vieles anbietet und du den Rest implementieren kannst.
Will ich aber gar nicht - ich mag FHEM und ich mag die mir hier bekannt gewordene Community und die Kraft mit der viele hier was umsetzen.
« Letzte Änderung: 29 Oktober 2017, 21:25:40 von Master_Nick »
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)
Gefällt mir Gefällt mir x 2 Liste anzeigen

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
Antw:Node-Red als Frontend
« Antwort #14 am: 14 Dezember 2017, 14:42:25 »
Und gibt es hier schon was neues ?  :)

Gruß
FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix
Zustimmung Zustimmung x 1 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #15 am: 14 Dezember 2017, 14:52:08 »
 ;) Ich bin aktiv dabei mir den besten Ansatz zu suchen.
Ich überlege aktuell FHEM alles was an Aktionen (Schaltaktionen, Temperaturen, etc) rein kommt über MQTT an Node-Red weiter zu geben und dann dort zu anzuzeigen.
Eine direkte Schnittstelle scheint es nicht zu geben, von daher ist das bisher der einzige Weg der mir offen erscheint.

Ansonsten leider noch nicht viel - generell habe ich mein 10" Touchpanel schon fertig gestellt und kämpfe aktuell noch stark mit anderen Problemen die mich ablenken da sie in die aktuelle Nutzung einstreuen. (FHEM -> FCM -> andFHEM -> Widgets bleiben einfach wie sie sind statt Schaltzustände korrekt wiederzugeben - Da bin ich in regem Kontakt mit dem Entwickler)

Aber der Urlaub kommt. Und wenn ich die ersten Punkte gekaut und geschluckt habe wird es denke ich auch nicht mehr wie ein Berg aussehen.

Kurz um verzögert aber nicht begraben ;-)
« Letzte Änderung: 14 Dezember 2017, 14:53:40 von Master_Nick »
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline TWART016

  • Sr. Member
  • ****
  • Beiträge: 779
Antw:Node-Red als Frontend
« Antwort #16 am: 14 Dezember 2017, 15:18:33 »
Intel NUC, Raspberry Pi,CUL 433+868, JeeLink, Uniroll, LD382/LD686 + WifiLight, Eventghost, Tablet UI, Homekit/Homebridge/Siri, Alexa, Squeezebox, Onkyo, MAX, Harmony, KODI, Winconnect, Geofancy, Nmap, Sysmon, Telegram
Gefällt mir Gefällt mir x 2 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #17 am: 14 Dezember 2017, 15:22:20 »
Definitiv nicht falsch denke ich.
Man muss das Rad ja nicht immer neu erfinden.

Danke dir!
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline hexenmeister

  • Developer
  • Hero Member
  • ****
  • Beiträge: 4221
    • tech_LogBuch
Antw:Node-Red als Frontend
« Antwort #18 am: 15 Dezember 2017, 10:31:01 »
Eventuell hilft das
https://www.youtube.com/watch?v=AGn_QfPmk-g
Interessanter Ansatz. Bring mich auf eine Idee :) Warum nicht gleich ein Device entwickeln, das diese ganze Scripterei in sich vereint und mqtt-Pub/Sub-Funktionalität für alle Geräte zur Verfügung stellt
Die Definitionen könnte in etwa so aussehen:

defmod mqttBridge MQTT_GENERIC_BRIDGE
attr mqttBridge mqttTopicPrefix /haus/

defmod sensorXYZ bla
...
attr sensorXYZ mqttTopic sensorXYZ
attr sensorXYZ mqttPubNames temperature humidity
...

defmod rolloX blup
...
attr rolloX mqttTopic rolloX
attr rolloX mqttPubNames pct:position state
attr rolloX mqttSubNames set:pct
...

wobei mqttBridge das Gerät wäre, das alles andere intern verwaltet.
Für sensorXYZ würden dann Readings temperature und humidity als /haus/sensorXYZ/temperature bzw. /haus/sensorXYZ/humidity gepublished.
Für rolloX würde die Position und State gepublished (Reading pct als /haus/rolloX/position und state als /haus/rolloX/state) und zusätzlich würde Topic /haus/rolloX/set aboniert und dessen Inhalte per "set rolloX pct VALUE" gesetzt.

Das würde mir meine Konfiguration an vielen Stellen vereinfachen. Vlt. realisiere ich das mal :)
Wie findet ihr die Idee?
In Verwendung: HM, EnOcean, 1wire, Firmata, MySensors, ESPEasy, MQTT*, NodeRED, Alexa, Telegram,..
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy
Kaffeekasse: https://www.paypal.me/s6z
Gefällt mir Gefällt mir x 7 Zustimmung Zustimmung x 1 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #19 am: 15 Dezember 2017, 12:56:32 »
Ich denke das wäre ein Träumchen! Super Idee! Man könnte es fast als Schnittstelle verstehen. :-)

Interessanter Ansatz. Bring mich auf eine Idee :) Warum nicht gleich ein Device entwickeln, das diese ganze Scripterei in sich vereint und mqtt-Pub/Sub-Funktionalität für alle Geräte zur Verfügung stellt
Die Definitionen könnte in etwa so aussehen:

defmod mqttBridge MQTT_GENERIC_BRIDGE
attr mqttBridge mqttTopicPrefix /haus/

defmod sensorXYZ bla
...
attr sensorXYZ mqttTopic sensorXYZ
attr sensorXYZ mqttPubNames temperature humidity
...

defmod rolloX blup
...
attr rolloX mqttTopic rolloX
attr rolloX mqttPubNames pct:position state
attr rolloX mqttSubNames set:pct
...

wobei mqttBridge das Gerät wäre, das alles andere intern verwaltet.
Für sensorXYZ würden dann Readings temperature und humidity als /haus/sensorXYZ/temperature bzw. /haus/sensorXYZ/humidity gepublished.
Für rolloX würde die Position und State gepublished (Reading pct als /haus/rolloX/position und state als /haus/rolloX/state) und zusätzlich würde Topic /haus/rolloX/set aboniert und dessen Inhalte per "set rolloX pct VALUE" gesetzt.

Das würde mir meine Konfiguration an vielen Stellen vereinfachen. Vlt. realisiere ich das mal :)
Wie findet ihr die Idee?
« Letzte Änderung: 15 Dezember 2017, 13:04:09 von Master_Nick »
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline hexenmeister

  • Developer
  • Hero Member
  • ****
  • Beiträge: 4221
    • tech_LogBuch
Antw:Node-Red als Frontend
« Antwort #20 am: 17 Dezember 2017, 23:17:25 »
Habe eine erste teil-funktioniernde Version (nur publish, keine subscribe). Bin mir aber noch nicht sicher, wie (Format) ich die KonfigurationsAttribute haben will. Ich werde die Tage ein neuen Thread dafür eröffnen, hier sind wir schon sehr OT.
In Verwendung: HM, EnOcean, 1wire, Firmata, MySensors, ESPEasy, MQTT*, NodeRED, Alexa, Telegram,..
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy
Kaffeekasse: https://www.paypal.me/s6z
Gefällt mir Gefällt mir x 2 Zustimmung Zustimmung x 1 Liste anzeigen

Offline Absolute Beginner

  • Full Member
  • ***
  • Beiträge: 121
  • was man anfängt soll man auch
Antw:Node-Red als Frontend
« Antwort #21 am: 20 Dezember 2017, 17:18:49 »
Hochinteressantes Thema! Habe Node-RED als Frontend zu FHEM im Test, nutze ausschließlich MQTT als Interface. Läuft prima und ich wundere mich, warum hier im Forum so wenig über Node-RED steht. Nur leider ist die Einrichtung aller Instanzen über die MQTT-Bridge ziemlich aufwändig. Am ioBroker habe ich mich auch schon versucht - der hat sehr wohl einige Vorteile, mir ist er aber zu 'unhandlich' (dito für Openhab2). Deshalb würde ich mich sehr über eine generische Bridge freuen. Devices mit FHEM einrichten ist einfach und gut! Bei dieser Gelegenheit gefragt: FHEM und Node-RED auf einem Rpi3 - läuft das gut zusammen? Gibt es etwas zu beachten?
Raspberry Pi 3 - CUL868 - Jessie - FHEM5.8 - MQTT - Node-RED
HM-TC-IT-WM-W-EU, HM-LC-BI1PBU-FM, HM-Sec-SCo, HM-WDS30-0T2-SM, SOMFY, Echo, ESP, SonOff

Offline hexenmeister

  • Developer
  • Hero Member
  • ****
  • Beiträge: 4221
    • tech_LogBuch
Antw:Node-Red als Frontend
« Antwort #22 am: 20 Dezember 2017, 17:24:21 »
Bei mir laufen 3 FHEM Instanzen plus Node-Red auf einem Rpi3 zusammen. Sprechen munter miteinander über mosquitto, das wiederum auf einem Cubietruck (zusammen mit einer weiteren FHEM Instanz) installiert ist.
Keine Probleme.
In Verwendung: HM, EnOcean, 1wire, Firmata, MySensors, ESPEasy, MQTT*, NodeRED, Alexa, Telegram,..
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy
Kaffeekasse: https://www.paypal.me/s6z

Offline Absolute Beginner

  • Full Member
  • ***
  • Beiträge: 121
  • was man anfängt soll man auch
Antw:Node-Red als Frontend
« Antwort #23 am: 20 Dezember 2017, 17:55:40 »
Und wenn der Broker (Mosquitto) auch auf dem einen RPi läuft? Bisher habe ich Node-RED auf einem PC zum Testen laufen.
Raspberry Pi 3 - CUL868 - Jessie - FHEM5.8 - MQTT - Node-RED
HM-TC-IT-WM-W-EU, HM-LC-BI1PBU-FM, HM-Sec-SCo, HM-WDS30-0T2-SM, SOMFY, Echo, ESP, SonOff

Offline hexenmeister

  • Developer
  • Hero Member
  • ****
  • Beiträge: 4221
    • tech_LogBuch
Antw:Node-Red als Frontend
« Antwort #24 am: 20 Dezember 2017, 18:29:32 »
Wird auch kein Problem sein. Mosquitto braucht nicht viel.
In Verwendung: HM, EnOcean, 1wire, Firmata, MySensors, ESPEasy, MQTT*, NodeRED, Alexa, Telegram,..
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy
Kaffeekasse: https://www.paypal.me/s6z

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
Antw:Node-Red als Frontend
« Antwort #25 am: 20 Dezember 2017, 18:35:25 »
Habe eine erste teil-funktioniernde Version (nur publish, keine subscribe). Bin mir aber noch nicht sicher, wie (Format) ich die KonfigurationsAttribute haben will. Ich werde die Tage ein neuen Thread dafür eröffnen, hier sind wir schon sehr OT.

Hast Du da schon was zu testen   ::) ;D
FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix

Offline hexenmeister

  • Developer
  • Hero Member
  • ****
  • Beiträge: 4221
    • tech_LogBuch
Antw:Node-Red als Frontend
« Antwort #26 am: 20 Dezember 2017, 23:43:53 »
Habe ich. Versuche morgen bereit zu stellen. Sorry, gerade zeitlich sehr knapp.
In Verwendung: HM, EnOcean, 1wire, Firmata, MySensors, ESPEasy, MQTT*, NodeRED, Alexa, Telegram,..
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy
Kaffeekasse: https://www.paypal.me/s6z
Gefällt mir Gefällt mir x 3 Liste anzeigen

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
Antw:Node-Red als Frontend
« Antwort #27 am: 21 Dezember 2017, 00:29:26 »
Habe ich. Versuche morgen bereit zu stellen. Sorry, gerade zeitlich sehr knapp.

Bloß kein Stress ;)
Bin aber gespannt! 
FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline hexenmeister

  • Developer
  • Hero Member
  • ****
  • Beiträge: 4221
    • tech_LogBuch
Antw:Node-Red als Frontend
« Antwort #28 am: 21 Dezember 2017, 22:36:27 »
Bin aber gespannt!

Wie angedroht ;D hier ist das in einem neuen Thread: https://forum.fhem.de/index.php?topic=81418.new#new
In Verwendung: HM, EnOcean, 1wire, Firmata, MySensors, ESPEasy, MQTT*, NodeRED, Alexa, Telegram,..
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy
Kaffeekasse: https://www.paypal.me/s6z
Gefällt mir Gefällt mir x 3 Liste anzeigen

Offline Darrol

  • New Member
  • *
  • Beiträge: 20
Antw:Node-Red als Frontend
« Antwort #29 am: 08 Januar 2018, 22:23:58 »
Habe heute mein TabletUI durch die MQTT/NodeRed-Dashboardlösung ersetzt und bin begeistert.
Die größte Herausforderung war lediglich den Output von der Log-Datenbank für die Charts aufzubereiten.
Der Rest ging quasi im Handumdrehen.
Das Dashboard lädt schnell und reagiert praktisch ohne erkennbare Verzögerung.
Bei mir laufen Fhem, postgres, Mosquitto und Node-RED auf einer Intel-NUC in Containern.

Allerdings muss ich sagen, dass die TabletUI von Fhem sehr viel umfangreicher und teilweise auch hübscher ist als das Node-Red-Dashboard. Leider ist mir da aber die Einrichtung zu frickelig und die Performance auch nur so lala.
Für mich ist damit der größte Knackpunkt von Fhem, nämlich das fehlende, saubere und flotte  Anwender-Frontend, behoben bzw. umschifft.
IntelNUC
-Fhem 5.8 in Ubuntu 16.04-Container
-dbLog & configDB auf Postgres-DB
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #30 am: 13 Januar 2018, 19:51:45 »
Hehe,
schön zu hören - leider bin ich immer noch arg zurück geworfen aktuell.
Viel um die Ohren und dann Bau ich gerade eine komplette Steuerung neu weil sie unzuverlässig war.

Aber mein  10" Touchdisplay mit ZeroW hat immerhin schon eine Rahmung und ist Montagebereit.
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #31 am: 05 Februar 2018, 14:31:53 »
Habe heute mein TabletUI durch die MQTT/NodeRed-Dashboardlösung ersetzt und bin begeistert.
Die größte Herausforderung war lediglich den Output von der Log-Datenbank für die Charts aufzubereiten.
Der Rest ging quasi im Handumdrehen.
Das Dashboard lädt schnell und reagiert praktisch ohne erkennbare Verzögerung.
Bei mir laufen Fhem, postgres, Mosquitto und Node-RED auf einer Intel-NUC in Containern.

Allerdings muss ich sagen, dass die TabletUI von Fhem sehr viel umfangreicher und teilweise auch hübscher ist als das Node-Red-Dashboard. Leider ist mir da aber die Einrichtung zu frickelig und die Performance auch nur so lala.
Für mich ist damit der größte Knackpunkt von Fhem, nämlich das fehlende, saubere und flotte  Anwender-Frontend, behoben bzw. umschifft.

Kannst du mir deine Lösung etwas offenlegen ;-)

Wie schaltest du deine nicht MQTT Geräte in FHEM mit Node-RED? Das Tool von hexenmeister kann ja bisher nur publishen nicht aber auslesen, soweit ich gelesen habe.

Ich plane aktuell Node-RED wirklich nur als Interface zu nutzen ohne Logik.
Also soll es INFOS von FHEM über alle Devices bekommen (hexenmeisters Modul würde das bringen).
Es soll aber ebenso alle Geräte schalten können (da fehlt mir aktuell die Möglichkeit NICHT MQTT Geräte zu schalten in FHEM (klar könnte man per CURL machen erst mal...)
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Darrol

  • New Member
  • *
  • Beiträge: 20
Antw:Node-Red als Frontend
« Antwort #32 am: 05 Februar 2018, 19:19:14 »
Kannst du mir deine Lösung etwas offenlegen ;-)


Na klar doch.

Im Grunde ist es bloß eine Umsetzung von dem dieses Tutorials hier:
https://haus-automatisierung.com/nodered/2017/12/13/node-red-tutorial-reihe-part-4-verbindung-fhem.html
Ich glaube hexenmeister hat das entsprechende YT-Video dazu ja auch schon hier gepostet.

Das man einen laufenden MQTT-Server und eine dazu passende Broker-Verbindung zu FHEM hat sehe ich mal als gegeben

Zunächst benötigt man dazu zwei zusätzliche Userattribute auf dem Global-Device:
attr global userattr mqttName mqttRoom <und das was hier vorher schon stand>
Als nächstes richtet man ein Notify ein, das alle Events von Geräten published, die diese beiden Attribute gesetzt haben:
defmod ntfy_publish_mqtt notify .*:.* {\
my $mqttRoom = AttrVal($NAME, 'mqttRoom', '');;\
my $mqttName = AttrVal($NAME, 'mqttName', '');;\
\
    if ($mqttRoom ne '' && $mqttName ne '') {\
        my $reading = "";;\
        my $message = "";;\
\
        if ($EVENT =~ qr/(.*?): (.*)/p) {\
            $reading = $1;;\
            $message = $2;;\
        } else {\
            $reading = "state";;\
            $message = $EVENT;;\
        }\
\
        my $topic = "/$mqttRoom/$mqttName/$reading";;\
\
        fhem("set Mosquitto publish $topic $message");;\
    }\
}

Damit wäre die Kommunikation von FHEM in Richtung Node-REd schonmal startklar.

Für die andere Richtung benötigt man ein zusätzliches MQTT_DEVICE welches die Kommandos von NR empfängt
und ein weiters Notify welches diese ausführt:

defmod SYS_MQTT MQTT_DEVICE
attr SYS_MQTT userattr subscribeReading_cmnd
attr SYS_MQTT DbLogExclude .*
attr SYS_MQTT IODev Mosquitto
attr SYS_MQTT alias MQTT-Command
attr SYS_MQTT group Dienste
attr SYS_MQTT icon mqtt_device
attr SYS_MQTT room System
attr SYS_MQTT stateFormat Letztes Kommando: cmnd
attr SYS_MQTT subscribeReading_cmnd /Service/fhem/cmnd

defmod n_SYS_MQTT_cmnd notify SYS_MQTT:cmnd:.* {\
if ($EVENT =~ qr/.*?: (.*)/p) {\
        my $cmnd = $1;;\
        fhem($cmnd);;\
    }\
}

Und nun ein paar dazu passende Nodes:
Hier ein Schieberegler, der ein Homematic-Thermostat regelt
[[{"id":"49c5d0bf.e83b4","type":"mqtt in","z":"4908d1e9.14cae","name":"Zieltemperatur, Wohnzimmer","topic":"/OG/Wohnzimmer/Heizung/desired-temp","qos":"2","broker":"b0a683bf.368fb","x":140,"y":120,"wires":[["8342fd3f.af6d7","113b53a8.f839fc"]]},{"id":"8342fd3f.af6d7","type":"ui_slider","z":"4908d1e9.14cae","name":"Zieltemperatur, Slider","label":"","group":"12eafd47.715883","order":3,"width":"6","height":"1","passthru":false,"topic":"set HM_5AD3D3_Clima desired-temp ","min":"12","max":"30","step":"0.5","x":400,"y":120,"wires":[["2f199b9a.6e7e54","113b53a8.f839fc"]]},{"id":"113b53a8.f839fc","type":"ui_text","z":"4908d1e9.14cae","group":"12eafd47.715883","order":2,"width":"6","height":"1","name":"Zieltemperatur","label":"Zieltemperatur","format":"{{msg.payload}}","layout":"col-center","x":600,"y":160,"wires":[],"inputLabels":["Zieltemperatur"]},{"id":"161c33aa.36577c","type":"mqtt out","z":"4908d1e9.14cae","name":"Heizung stellen","topic":"/Service/fhem/cmnd","qos":"2","retain":"false","broker":"b0a683bf.368fb","x":1020,"y":120,"wires":[]},{"id":"5f2cf46f.806f8c","type":"function","z":"4908d1e9.14cae","name":"Aufbau Fhem-CMD","func":"return { payload: msg.topic + msg.payload };","outputs":1,"noerr":0,"x":810,"y":120,"wires":[["161c33aa.36577c"]]},{"id":"2b9861fa.96dc3e","type":"ui_toast","z":"4908d1e9.14cae","position":"top right","displayTime":"3","highlight":"","outputs":0,"ok":"OK","cancel":"","topic":"neue Zieltemperatur","name":"Zieltemperatur","x":1020,"y":80,"wires":[]},{"id":"10763929.3c1587","type":"function","z":"4908d1e9.14cae","name":"Zieltemp. toString","func":"var pl = msg.payload.toString();\nmsg.payload = pl + \"°C\";\nreturn msg;","outputs":1,"noerr":0,"x":810,"y":80,"wires":[["2b9861fa.96dc3e"]]},{"id":"2f199b9a.6e7e54","type":"trigger","z":"4908d1e9.14cae","op1":"","op2":"","op1type":"nul","op2type":"payl","duration":"1500","extend":true,"units":"ms","reset":"","name":"","x":600,"y":120,"wires":[["5f2cf46f.806f8c","10763929.3c1587"]]},{"id":"b0a683bf.368fb","type":"mqtt-broker","z":"","broker":"100.10.1.6","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willPayload":"","birthTopic":"","birthQos":"0","birthPayload":""},{"id":"12eafd47.715883","type":"ui_group","z":"","name":"Raumklima","tab":"3a31dbc6.b1d4e4","order":1,"disp":true,"width":"6"},{"id":"3a31dbc6.b1d4e4","type":"ui_tab","z":"","name":"Wohnzimmer","icon":"dashboard","order":2}]]
Und ein einfacher Schalter, der ein Fibaro-Wandschalter umschaltet:
[{"id":"49c5d0bf.e83b4","type":"mqtt in","z":"4908d1e9.14cae","name":"Zieltemperatur, Wohnzimmer","topic":"/OG/Wohnzimmer/Heizung/desired-temp","qos":"2","broker":"b0a683bf.368fb","x":140,"y":120,"wires":[["8342fd3f.af6d7","113b53a8.f839fc"]]},{"id":"8342fd3f.af6d7","type":"ui_slider","z":"4908d1e9.14cae","name":"Zieltemperatur, Slider","label":"","group":"12eafd47.715883","order":3,"width":"6","height":"1","passthru":false,"topic":"","min":"12","max":"30","step":"0.5","x":400,"y":120,"wires":[["2f199b9a.6e7e54","113b53a8.f839fc"]]},{"id":"113b53a8.f839fc","type":"ui_text","z":"4908d1e9.14cae","group":"12eafd47.715883","order":2,"width":"6","height":"1","name":"Zieltemperatur","label":"Zieltemperatur","format":"{{msg.payload}}","layout":"col-center","x":600,"y":160,"wires":[],"inputLabels":["Zieltemperatur"]},{"id":"161c33aa.36577c","type":"mqtt out","z":"4908d1e9.14cae","name":"Heizung stellen","topic":"/Service/fhem/cmnd","qos":"2","retain":"false","broker":"b0a683bf.368fb","x":1020,"y":120,"wires":[]},{"id":"5f2cf46f.806f8c","type":"function","z":"4908d1e9.14cae","name":"Aufbau Fhem-CMD","func":"return { payload: \"set HM_5AD3D3_Clima desired-temp \" + msg.payload };","outputs":1,"noerr":0,"x":810,"y":120,"wires":[["161c33aa.36577c"]]},{"id":"2b9861fa.96dc3e","type":"ui_toast","z":"4908d1e9.14cae","position":"top right","displayTime":"3","highlight":"","outputs":0,"ok":"OK","cancel":"","topic":"neue Zieltemperatur","name":"Zieltemperatur","x":1020,"y":80,"wires":[]},{"id":"10763929.3c1587","type":"function","z":"4908d1e9.14cae","name":"Zieltemp. toString","func":"var pl = msg.payload.toString();\nmsg.payload = pl + \"°C\";\nreturn msg;","outputs":1,"noerr":0,"x":810,"y":80,"wires":[["2b9861fa.96dc3e"]]},{"id":"2f199b9a.6e7e54","type":"trigger","z":"4908d1e9.14cae","op1":"","op2":"","op1type":"nul","op2type":"payl","duration":"1500","extend":true,"units":"ms","reset":"","name":"","x":600,"y":120,"wires":[["5f2cf46f.806f8c","10763929.3c1587"]]},{"id":"b0a683bf.368fb","type":"mqtt-broker","z":"","broker":"100.10.1.6","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willPayload":"","birthTopic":"","birthQos":"0","birthPayload":""},{"id":"12eafd47.715883","type":"ui_group","z":"","name":"Raumklima","tab":"3a31dbc6.b1d4e4","order":1,"disp":true,"width":"6"},{"id":"3a31dbc6.b1d4e4","type":"ui_tab","z":"","name":"Wohnzimmer","icon":"dashboard","order":2}]
« Letzte Änderung: 05 Februar 2018, 19:30:06 von d.mrugalla »
IntelNUC
-Fhem 5.8 in Ubuntu 16.04-Container
-dbLog & configDB auf Postgres-DB
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #33 am: 07 Februar 2018, 15:19:31 »
 ;D ;D Ich gebe zu ich hatte mich versucht mit einigen Tutorials an Node-RED zu bringen - hatte da aber völlig falsche Verwendungszwecke innerhalb der Tutorials, so das es sich nicht adaptieren ließ (Websocket - http und wer weiß was.. völlig verrant).

Habe jetzt meine ersten Dinge fertig und es ist ja unglaublich flach und einfach gehalten (man kann es natürlich auch voll pumpen mit Kram). Aber im eigentlich reichen 4 Nodes (MQTT Input -> JSON -> switch -> MQTT Output) für einen simplen Schalter mit MQTT.

Bin sehr zufrieden und werde nun nach und nach alle devices mittels der hier im Forum oder schon in FHEM angebotenen Wege an den MQTT Broker bringen und dann ist die Visualisierung in Node-Red ein Klacks.

Hier mal ein super minimalistisches Beispiel (der erste in Betrieb genommene SonOff S20) der UI die Node-RED am Handy oder aber auch am Touchscreen bereitstellt :D.
Und die Config die dafür in Node-RED gemacht werden muss (gut der Broker muss auch einmal angelegt werden und der Raum braucht einen Namen und die Gruppe)

« Letzte Änderung: 07 Februar 2018, 15:23:55 von Master_Nick »
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline Darrol

  • New Member
  • *
  • Beiträge: 20
Antw:Node-Red als Frontend
« Antwort #34 am: 08 Februar 2018, 21:27:16 »
Habe jetzt meine ersten Dinge fertig und es ist ja unglaublich flach und einfach gehalten (man kann es natürlich auch voll pumpen mit Kram). Aber im eigentlich reichen 4 Nodes (MQTT Input -> JSON -> switch -> MQTT Output) für einen simplen Schalter mit MQTT.

Yup und v.a. kann man superschnell per copy/paste ganze Node-Gruppen duplizieren und muss, wenn man richtig voregeabreitet hat, nur noch den Raum- und Gerätenamen anpassen damit die laufen.
So hat man im Handumdrehen für alle Räume eine Dashboard-Seite eingerichtet.

Knifflig wird es allerdings wenn man xy-chart aus dem fhem-db-log füttern möchte. Die sind nämlich darauf ausgerichtet erstmal selbst Daten zu sammeln anstatt einfach einen vollständigen Datensatz darzustellen.

Hier eine Node-Kette zum darstellen eines Temperaturplots über die Vergangenen 24h:
[{"id":"134e6bc.9411a94","type":"postgres","z":"4908d1e9.14cae","postgresdb":"","name":"Fhem-Datenbank","output":true,"outputs":1,"x":370,"y":720,"wires":[["fb2198d8.03ff28","7c6a0d59.71e564"]]},{"id":"89378517.545228","type":"inject","z":"4908d1e9.14cae","name":"Datenselektion","topic":"Query Luftfeuchtigkeit","payload":"select timestamp as x, value::float as y1 from public.history  where device='ESP_Wohnzimmer' and reading='Temperatur'  order by timestamp desc limit 576","payloadType":"str","repeat":"150","crontab":"","once":true,"x":120,"y":720,"wires":[["134e6bc.9411a94"]]},{"id":"e9adfacc.187088","type":"ui_chart","z":"4908d1e9.14cae","name":"Verlauf Temperatur","group":"3dfb78a5.81ceb8","order":0,"width":"0","height":"0","label":"Verlauf Temperatur","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"bezier","nodata":"Lade Daten","dot":false,"ymin":"10","ymax":"30","removeOlder":"24","removeOlderPoints":"576","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#ff0000","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":930,"y":720,"wires":[[],[]],"outputLabels":["O",""]},{"id":"fb2198d8.03ff28","type":"function","z":"4908d1e9.14cae","name":"SQL-Output zu Chart-Array","func":"// name of the time column values:\nvar tcol = \"x\";\n// list of columns to be charted:\nvar cols = [\"y1\"];\n\n// iterate over each column of the query results\nvar data = cols.map(function(col) {\n    // iterate over each row of the query results\n    var vals = msg.payload.map(function(row) {\n        // return a data point for each col\n        return [ +row[tcol], +row[col] ];\n    });\n\n    // return data object for each line on the chart\n    return { key: \"Temperatur\", values: vals };\n});\n\n// now put the new chart data in the payload\nmsg.payload = data;\nreturn msg;","outputs":1,"noerr":0,"x":660,"y":720,"wires":[["e9adfacc.187088","d65dc628.33a998"]]},{"id":"d65dc628.33a998","type":"debug","z":"4908d1e9.14cae","name":"plotdata","active":true,"console":"false","complete":"payload","x":900,"y":760,"wires":[]},{"id":"7c6a0d59.71e564","type":"debug","z":"4908d1e9.14cae","name":"db-Output","active":true,"console":"false","complete":"payload","x":600,"y":760,"wires":[]},{"id":"3dfb78a5.81ceb8","type":"ui_group","z":"","name":"Zeitlinie","tab":"3a31dbc6.b1d4e4","order":4,"disp":true,"width":"6"},{"id":"3a31dbc6.b1d4e4","type":"ui_tab","z":"","name":"Wohnzimmer","icon":"dashboard","order":2}]
Man muss dazu das Array aus der Datenbank in einen Haufen einzelner Datenpunkte(Arrays) zerlegen.
Dafür hab ich diesen Codeschnipsel hier gefunden:
// name of the time column values:
var tcol = "x";
// list of columns to be charted:
var cols = ["y1"];

// iterate over each column of the query results
var data = cols.map(function(col) {
    // iterate over each row of the query results
    var vals = msg.payload.map(function(row) {
        // return a data point for each col
        return [ +row[tcol], +row[col] ];
    });

    // return data object for each line on the chart
    return { key: "Temperatur", values: vals };
});

// now put the new chart data in the payload
msg.payload = data;
return msg;
Der ist glaube ich auch nicht postgres-spezifisch.


« Letzte Änderung: 08 Februar 2018, 21:31:24 von d.mrugalla »
IntelNUC
-Fhem 5.8 in Ubuntu 16.04-Container
-dbLog & configDB auf Postgres-DB
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #35 am: 08 Februar 2018, 21:57:22 »
Sehr sexy!  ;)

Das kann ich direkt mal schauen wie ich das umsetze.

Temp und Hygro hab ich in jedem Raum.

Du sprichst von Datenbank? Du machst also kein FileLog? :-D Oder welche Datenbank meinst du?
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Darrol

  • New Member
  • *
  • Beiträge: 20
Antw:Node-Red als Frontend
« Antwort #36 am: 09 Februar 2018, 19:04:51 »

Du sprichst von Datenbank? Du machst also kein FileLog? :-D Oder welche Datenbank meinst du?

Genau das.
Ich nutze sowohl configDB als auch DbLog in einer Postgres-Datenbank.

Gesendet von meinem YD201 mit Tapatalk
IntelNUC
-Fhem 5.8 in Ubuntu 16.04-Container
-dbLog & configDB auf Postgres-DB

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #37 am: 09 Februar 2018, 19:09:53 »
Ich gestehe ich bin bei beidem noch oldschool.  :-\
Aber muss jetzt eh einmal alles umziehen da neue Hardware.
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #38 am: 27 Februar 2018, 02:12:14 »
Auf das DbLog bin ich noch immer nich geswitched aber ich habe mittels der MQTT Generic Bridge nun meiner Thermostate schon mal (lesend) drin.

Unfassbar einfach ist das mit Node-Red.


Ich denke, wenn ich einen guten Stand habe, kann ich mal eine Doku schreiben von der Installation von Node-Red über die Nutzung mit der MQTT Generic Bridge (https://forum.fhem.de/index.php/topic,81418.0.html) und normalen MQTT Devices. :-)

*Edit* Man kann die Finger nicht von lassen ;-) Hab es erweitert.
« Letzte Änderung: 27 Februar 2018, 11:45:13 von Master_Nick »
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)
Gefällt mir Gefällt mir x 1 Informativ Informativ x 1 Liste anzeigen

Offline hexenmeister

  • Developer
  • Hero Member
  • ****
  • Beiträge: 4221
    • tech_LogBuch
Antw:Node-Red als Frontend
« Antwort #39 am: 28 Februar 2018, 00:42:31 »
Sieht gut aus! Postest Du für Nachahmer Nodes-Export?
In Verwendung: HM, EnOcean, 1wire, Firmata, MySensors, ESPEasy, MQTT*, NodeRED, Alexa, Telegram,..
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy
Kaffeekasse: https://www.paypal.me/s6z
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #40 am: 28 Februar 2018, 00:51:16 »
Klar kein Thema hier dann also die fertig gestellte "Klima" Seite

Siehe Anhang - es war einfach zu viel für in den Post  8)
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
Antw:Node-Red als Frontend
« Antwort #41 am: 28 Februar 2018, 15:10:58 »
Habe mal eben was für mein Handy fertig gemacht....
FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #42 am: 28 Februar 2018, 15:17:12 »
Auch eine gute Idee spart man 2 Elemente indem man den einen Kringel da nimmt - welcher ist das? ;-) Donut?
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #44 am: 28 Februar 2018, 15:23:30 »
Ah da war ich vor kurzem auch mal drüber gehuscht :-D

Jo sieht gut aus - mal sehen ;-D
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
Antw:Node-Red als Frontend
« Antwort #45 am: 01 März 2018, 15:13:24 »
Das ist HTML (http://www.ajso.lt/node-red/nest-thermostat-dashboard-html5-widget-node-red/)

Hmm....
Aber so richtig Funktioniert das mit den Steuerelement nicht.
Bei einen Page reload fehlen ab und dann die Werte :(

FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #46 am: 01 März 2018, 17:23:57 »
Das kann durchaus mal am Browser liegen - ich hatte sowas mal bei Firefox und FHEM.... da blieb dann ne ganze Ecke einfach hängen und fehlte und alles war unnutzbar bis man oben in die Adresszeile klickte und Enter drückte. (STRG+SHIFT+R brachte nicht das gleiche Ergebnis)
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
Antw:Node-Red als Frontend
« Antwort #47 am: 01 März 2018, 20:46:36 »
Habe schon mehre Browser und Devices durch kommt auf allen leider vor :(
FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #48 am: 01 März 2018, 21:04:17 »
Dann ist das eher raus... :-/ Schade
Oder mal Bescheid sagen bei dem Typen :-D Bug öffnen.
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline SpeedyRS2

  • New Member
  • *
  • Beiträge: 18
Antw:Node-Red als Frontend
« Antwort #49 am: 06 März 2018, 10:45:49 »
Ich bin mittlerweile auch bei NodeRed als Frontend für FHEM angekommen.
Ich habe vorher unheimlich viel mit dem TabletUI rumprobiert und es immer wieder umgestellt. Optisch hat es mir nachher sogar sehr gut gefallen. Allerdings fand ich die Bedienung über das TabletUI irgendwie doch sehr träge und hakelig. Das hat mich echt gestört. Da bringt das schickste UI nichts.

Daraufhin habe ich mich mal an NodeRed gesetzt.
Ich war von der ersten Sekunde an total begeistert.
Kommunikation zwischen FHEM und NodeRed läuft über MQTT und das ohne Zeitverlust. Ich hatte schon die Befürchtung, dass man die zusätzliche Schicht merkt. Ist aber gar nicht so. Änderungen in FHEM werden direkt in NodeRed dargestellt.
Das Dashboard ist super simpel zu erstellen und wirklich flott in der Bedienung. Gerade die Slider haben mich beim TabletUI in den Wahnsinn getrieben. Im NodeRed Dashboard flutscht es einfach nur perfekt.

Hier mal ein paar Screens, wie Teile meines Dashboards jetzt aussehen:
Gefällt mir Gefällt mir x 4 Zustimmung Zustimmung x 1 Liste anzeigen

Offline SpeedyRS2

  • New Member
  • *
  • Beiträge: 18
Antw:Node-Red als Frontend
« Antwort #50 am: 06 März 2018, 11:51:03 »
Für das NEST Widget hab ich, glaube ich  ;) , auch eine Lösung gefunden.

Änderungen habe ich an den im Screenshot markierten Elementen vorgenommen.

Hier mal der exportierte Flow:
[{"id":"2c174318.8fafec","type":"tab","label":"Flow 2","disabled":false,"info":""},{"id":"85e9547.e3387a8","type":"ui_template","z":"2c174318.8fafec","group":"8db78a1d.f45e08","name":"Nest","order":1,"width":"6","height":"6","format":"<div id=\"thermostat\"></div>\n\n<style>\n@import url(http://fonts.googleapis.com/css?family=Open+Sans:300);\n#thermostat {\n  margin: 0 auto;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n.dial {\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n}\n.dial.away .dial__ico__leaf {\n  visibility: hidden;\n}\n.dial.away .dial__lbl--target {\n  visibility: hidden;\n}\n.dial.away .dial__lbl--target--half {\n  visibility: hidden;\n}\n.dial.away .dial__lbl--away {\n  opacity: 1;\n}\n.dial .dial__shape {\n  -webkit-transition: fill 0.5s;\n  transition: fill 0.5s;\n}\n.dial__ico__leaf {\n  fill: #13EB13;\n  opacity: 0;\n  -webkit-transition: opacity 0.5s;\n  transition: opacity 0.5s;\n  pointer-events: none;\n}\n.dial.has-leaf .dial__ico__leaf {\n  display: block;\n  opacity: 1;\n  pointer-events: initial;\n}\n.dial__editableIndicator {\n  fill: white;\n  fill-rule: evenodd;\n  opacity: 0;\n  -webkit-transition: opacity 0.5s;\n  transition: opacity 0.5s;\n}\n.dial--edit .dial__editableIndicator {\n  opacity: 1;\n}\n.dial--state--off .dial__shape {\n  fill: #3d3c3c;\n}\n.dial--state--heating .dial__shape {\n  fill: #E36304;\n}\n.dial--state--cooling .dial__shape {\n  fill: #007AF1;\n}\n.dial__ticks path {\n  fill: rgba(255, 255, 255, 0.3);\n}\n.dial__ticks path.active {\n  fill: rgba(255, 255, 255, 0.8);\n}\n.dial text {\n  fill: white;\n  text-anchor: middle;\n  font-family: Helvetica, sans-serif;\n  alignment-baseline: central;\n}\n.dial__lbl--target {\n  font-size: 120px;\n  font-weight: bold;\n}\n.dial__lbl--target--half {\n  font-size: 40px;\n  font-weight: bold;\n  opacity: 0;\n  -webkit-transition: opacity 0.1s;\n  transition: opacity 0.1s;\n}\n.dial__lbl--target--half.shown {\n  opacity: 1;\n  -webkit-transition: opacity 0s;\n  transition: opacity 0s;\n}\n.dial__lbl--ambient {\n  font-size: 22px;\n  font-weight: bold;\n}\n.dial__lbl--away {\n  font-size: 72px;\n  font-weight: bold;\n  opacity: 0;\n  pointer-events: none;\n}\n#controls {\n  font-family: Open Sans;\n  background-color: rgba(255, 255, 255, 0.25);\n  padding: 20px;\n  border-radius: 5px;\n  position: absolute;\n  left: 50%;\n  -webkit-transform: translatex(-50%);\n          transform: translatex(-50%);\n  margin-top: 20px;\n}\n#controls label {\n  text-align: left;\n  display: block;\n}\n#controls label span {\n  display: inline-block;\n  width: 200px;\n  text-align: right;\n  font-size: 0.8em;\n  text-transform: uppercase;\n}\n#controls p {\n  margin: 0;\n  margin-bottom: 1em;\n  padding-bottom: 1em;\n  border-bottom: 2px solid #ccc;\n}\n</style>\n<script>\n    var thermostatDial = (function() {\n\t\n\t/*\n\t * Utility functions\n\t */\n\t\n\t// Create an element with proper SVG namespace, optionally setting its attributes and appending it to another element\n\tfunction createSVGElement(tag,attributes,appendTo) {\n\t\tvar element = document.createElementNS('http://www.w3.org/2000/svg',tag);\n\t\tattr(element,attributes);\n\t\tif (appendTo) {\n\t\t\tappendTo.appendChild(element);\n\t\t}\n\t\treturn element;\n\t}\n\t\n\t// Set attributes for an element\n\tfunction attr(element,attrs) {\n\t\tfor (var i in attrs) {\n\t\t\telement.setAttribute(i,attrs[i]);\n\t\t}\n\t}\n\t\n\t// Rotate a cartesian point about given origin by X degrees\n\tfunction rotatePoint(point, angle, origin) {\n\t\tvar radians = angle * Math.PI/180;\n\t\tvar x = point[0]-origin[0];\n\t\tvar y = point[1]-origin[1];\n\t\tvar x1 = x*Math.cos(radians) - y*Math.sin(radians) + origin[0];\n\t\tvar y1 = x*Math.sin(radians) + y*Math.cos(radians) + origin[1];\n\t\treturn [x1,y1];\n\t}\n\t\n\t// Rotate an array of cartesian points about a given origin by X degrees\n\tfunction rotatePoints(points, angle, origin) {\n\t\treturn points.map(function(point) {\n\t\t\treturn rotatePoint(point, angle, origin);\n\t\t});\n\t}\n\t\n\t// Given an array of points, return an SVG path string representing the shape they define\n\tfunction pointsToPath(points) {\n\t\treturn points.map(function(point, iPoint) {\n\t\t\treturn (iPoint>0?'L':'M') + point[0] + ' ' + point[1];\n\t\t}).join(' ')+'Z';\n\t}\n\t\n\tfunction circleToPath(cx, cy, r) {\n\t\treturn [\n\t\t\t\"M\",cx,\",\",cy,\n\t\t\t\"m\",0-r,\",\",0,\n\t\t\t\"a\",r,\",\",r,0,1,\",\",0,r*2,\",\",0,\n\t\t\t\"a\",r,\",\",r,0,1,\",\",0,0-r*2,\",\",0,\n\t\t\t\"z\"\n\t\t].join(' ').replace(/\\s,\\s/g,\",\");\n\t}\n\t\n\tfunction donutPath(cx,cy,rOuter,rInner) {\n\t\treturn circleToPath(cx,cy,rOuter) + \" \" + circleToPath(cx,cy,rInner);\n\t}\n\t\n\t// Restrict a number to a min + max range\n\tfunction restrictToRange(val,min,max) {\n\t\tif (val < min) return min;\n\t\tif (val > max) return max;\n\t\treturn val;\n\t}\n\t\n\t// Round a number to the nearest 0.5\n\tfunction roundHalf(num) {\n\t\treturn Math.round(num*2)/2;\n\t}\n\t\n\tfunction setClass(el, className, state) {\n\t\tel.classList[state ? 'add' : 'remove'](className);\n\t}\n\t\n\t/*\n\t * The \"MEAT\"\n\t */\n\n\treturn function(targetElement, options) {\n\t\tvar self = this;\n\t\t\n\t\t/*\n\t\t * Options\n\t\t */\n\t\toptions = options || {};\n\t\toptions = {\n\t\t\tdiameter: options.diameter || 400,\n\t\t\tminValue: options.minValue || 10, // Minimum value for target temperature\n\t\t\tmaxValue: options.maxValue || 30, // Maximum value for target temperature\n\t\t\tnumTicks: options.numTicks || 200, // Number of tick lines to display around the dial\n\t\t\tonSetTargetTemperature: options.onSetTargetTemperature || function() {}, // Function called when new target temperature set by the dial\n\t\t};\n\t\t\n\t\t/*\n\t\t * Properties - calculated from options in many cases\n\t\t */\n\t\tvar properties = {\n\t\t\ttickDegrees: 300, //  Degrees of the dial that should be covered in tick lines\n\t\t\trangeValue: options.maxValue - options.minValue,\n\t\t\tradius: options.diameter/2,\n\t\t\tticksOuterRadius: options.diameter / 30,\n\t\t\tticksInnerRadius: options.diameter / 8,\n\t\t\thvac_states: ['off', 'heating', 'cooling'],\n\t\t\tdragLockAxisDistance: 15,\n\t\t}\n\t\tproperties.lblAmbientPosition = [properties.radius, properties.ticksOuterRadius-(properties.ticksOuterRadius-properties.ticksInnerRadius)/2]\n\t\tproperties.offsetDegrees = 180-(360-properties.tickDegrees)/2;\n\t\t\n\t\t/*\n\t\t * Object state\n\t\t */\n\t\tvar state = {\n\t\t\ttarget_temperature: options.minValue,\n\t\t\tambient_temperature: options.minValue,\n\t\t\thvac_state: properties.hvac_states[0],\n\t\t\thas_leaf: false,\n\t\t\taway: false\n\t\t};\n\t\t\n\t\t/*\n\t\t * Property getter / setters\n\t\t */\n\t\tObject.defineProperty(this,'target_temperature',{\n\t\t\tget: function() {\n\t\t\t\treturn state.target_temperature;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tstate.target_temperature = restrictTargetTemperature(+val);\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(this,'ambient_temperature',{\n\t\t\tget: function() {\n\t\t\t\treturn state.ambient_temperature;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tstate.ambient_temperature = roundHalf(+val);\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(this,'hvac_state',{\n\t\t\tget: function() {\n\t\t\t\treturn state.hvac_state;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tif (properties.hvac_states.indexOf(val)>=0) {\n\t\t\t\t\tstate.hvac_state = val;\n\t\t\t\t\trender();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(this,'has_leaf',{\n\t\t\tget: function() {\n\t\t\t\treturn state.has_leaf;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tstate.has_leaf = !!val;\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(this,'away',{\n\t\t\tget: function() {\n\t\t\t\treturn state.away;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tstate.away = !!val;\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t\t\n\t\t/*\n\t\t * SVG\n\t\t */\n\t\tvar svg = createSVGElement('svg',{\n\t\t\twidth: '100%', //options.diameter+'px',\n\t\t\theight: '100%', //options.diameter+'px',\n\t\t\tviewBox: '0 0 '+options.diameter+' '+options.diameter,\n\t\t\tclass: 'dial'\n\t\t},targetElement);\n\t\t// CIRCULAR DIAL\n\t\tvar circle = createSVGElement('circle',{\n\t\t\tcx: properties.radius,\n\t\t\tcy: properties.radius,\n\t\t\tr: properties.radius,\n\t\t\tclass: 'dial__shape'\n\t\t},svg);\n\t\t// EDITABLE INDICATOR\n\t\tvar editCircle = createSVGElement('path',{\n\t\t\td: donutPath(properties.radius,properties.radius,properties.radius-4,properties.radius-8),\n\t\t\tclass: 'dial__editableIndicator',\n\t\t},svg);\n\t\t\n\t\t/*\n\t\t * Ticks\n\t\t */\n\t\tvar ticks = createSVGElement('g',{\n\t\t\tclass: 'dial__ticks'\t\n\t\t},svg);\n\t\tvar tickPoints = [\n\t\t\t[properties.radius-1, properties.ticksOuterRadius],\n\t\t\t[properties.radius+1, properties.ticksOuterRadius],\n\t\t\t[properties.radius+1, properties.ticksInnerRadius],\n\t\t\t[properties.radius-1, properties.ticksInnerRadius]\n\t\t];\n\t\tvar tickPointsLarge = [\n\t\t\t[properties.radius-1.5, properties.ticksOuterRadius],\n\t\t\t[properties.radius+1.5, properties.ticksOuterRadius],\n\t\t\t[properties.radius+1.5, properties.ticksInnerRadius+20],\n\t\t\t[properties.radius-1.5, properties.ticksInnerRadius+20]\n\t\t];\n\t\tvar theta = properties.tickDegrees/options.numTicks;\n\t\tvar tickArray = [];\n\t\tfor (var iTick=0; iTick<options.numTicks; iTick++) {\n\t\t\ttickArray.push(createSVGElement('path',{d:pointsToPath(tickPoints)},ticks));\n\t\t};\n\t\t\n\t\t/*\n\t\t * Labels\n\t\t */\n\t\tvar lblTarget = createSVGElement('text',{\n\t\t\tx: properties.radius,\n\t\t\ty: properties.radius,\n\t\t\tclass: 'dial__lbl dial__lbl--target'\n\t\t},svg);\n\t\tvar lblTarget_text = document.createTextNode('');\n\t\tlblTarget.appendChild(lblTarget_text);\n\t\t//\n\t\tvar lblTargetHalf = createSVGElement('text',{\n\t\t\tx: properties.radius + properties.radius/2.5,\n\t\t\ty: properties.radius - properties.radius/8,\n\t\t\tclass: 'dial__lbl dial__lbl--target--half'\n\t\t},svg);\n\t\tvar lblTargetHalf_text = document.createTextNode('5');\n\t\tlblTargetHalf.appendChild(lblTargetHalf_text);\n\t\t//\n\t\tvar lblAmbient = createSVGElement('text',{\n\t\t\tclass: 'dial__lbl dial__lbl--ambient'\n\t\t},svg);\n\t\tvar lblAmbient_text = document.createTextNode('');\n\t\tlblAmbient.appendChild(lblAmbient_text);\n\t\t//\n\t\tvar lblAway = createSVGElement('text',{\n\t\t\tx: properties.radius,\n\t\t\ty: properties.radius,\n\t\t\tclass: 'dial__lbl dial__lbl--away'\n\t\t},svg);\n\t\tvar lblAway_text = document.createTextNode('AWAY');\n\t\tlblAway.appendChild(lblAway_text);\n\t\t//\n\t\tvar icoLeaf = createSVGElement('path',{\n\t\t\tclass: 'dial__ico__leaf'\n\t\t},svg);\n\t\t\n\t\t/*\n\t\t * LEAF\n\t\t */\n\t\tvar leafScale = properties.radius/5/100;\n\t\tvar leafDef = [\"M\", 3, 84, \"c\", 24, 17, 51, 18, 73, -6, \"C\", 100, 52, 100, 22, 100, 4, \"c\", -13, 15, -37, 9, -70, 19, \"C\", 4, 32, 0, 63, 0, 76, \"c\", 6, -7, 18, -17, 33, -23, 24, -9, 34, -9, 48, -20, -9, 10, -20, 16, -43, 24, \"C\", 22, 63, 8, 78, 3, 84, \"z\"].map(function(x) {\n\t\t\treturn isNaN(x) ? x : x*leafScale;\n\t\t}).join(' ');\n\t\tvar translate = [properties.radius-(leafScale*100*0.5),properties.radius*1.5]\n\t\tvar icoLeaf = createSVGElement('path',{\n\t\t\tclass: 'dial__ico__leaf',\n\t\t\td: leafDef,\n\t\t\ttransform: 'translate('+translate[0]+','+translate[1]+')'\n\t\t},svg);\n\t\t\t\n\t\t/*\n\t\t * RENDER\n\t\t */\n\t\tfunction render() {\n\t\t\trenderAway();\n\t\t\trenderHvacState();\n\t\t\trenderTicks();\n\t\t\trenderTargetTemperature();\n\t\t\trenderAmbientTemperature();\n\t\t\trenderLeaf();\n\t\t}\n\t\trender();\n\n\t\t/*\n\t\t * RENDER - ticks\n\t\t */\n\t\tfunction renderTicks() {\n\t\t\tvar vMin, vMax;\n\t\t\tif (self.away) {\n\t\t\t\tvMin = self.ambient_temperature;\n\t\t\t\tvMax = vMin;\n\t\t\t} else {\n\t\t\t\tvMin = Math.min(self.ambient_temperature, self.target_temperature);\n\t\t\t\tvMax = Math.max(self.ambient_temperature, self.target_temperature);\n\t\t\t}\n\t\t\tvar min = restrictToRange(Math.round((vMin-options.minValue)/properties.rangeValue * options.numTicks),0,options.numTicks-1);\n\t\t\tvar max = restrictToRange(Math.round((vMax-options.minValue)/properties.rangeValue * options.numTicks),0,options.numTicks-1);\n\t\t\t//\n\t\t\ttickArray.forEach(function(tick,iTick) {\n\t\t\t\tvar isLarge = iTick==min || iTick==max;\n\t\t\t\tvar isActive = iTick >= min && iTick <= max;\n\t\t\t\tattr(tick,{\n\t\t\t\t\td: pointsToPath(rotatePoints(isLarge ? tickPointsLarge: tickPoints,iTick*theta-properties.offsetDegrees,[properties.radius, properties.radius])),\n\t\t\t\t\tclass: isActive ? 'active' : ''\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t\n\t\t/*\n\t\t * RENDER - ambient temperature\n\t\t */\n\t\tfunction renderAmbientTemperature() {\n\t\t\tlblAmbient_text.nodeValue = Math.floor(self.ambient_temperature);\n\t\t\tif (self.ambient_temperature%1!=0) {\n\t\t\t\tlblAmbient_text.nodeValue += '⁵';\n\t\t\t}\n\t\t\tvar peggedValue = restrictToRange(self.ambient_temperature, options.minValue, options.maxValue);\n\t\t\tdegs = properties.tickDegrees * (peggedValue-options.minValue)/properties.rangeValue - properties.offsetDegrees;\n\t\t\tif (peggedValue > self.target_temperature) {\n\t\t\t\tdegs += 8;\n\t\t\t} else {\n\t\t\t\tdegs -= 8;\n\t\t\t}\n\t\t\tvar pos = rotatePoint(properties.lblAmbientPosition,degs,[properties.radius, properties.radius]);\n\t\t\tattr(lblAmbient,{\n\t\t\t\tx: pos[0],\n\t\t\t\ty: pos[1]\n\t\t\t});\n\t\t}\n\n\t\t/*\n\t\t * RENDER - target temperature\n\t\t */\n\t\tfunction renderTargetTemperature() {\n\t\t\tlblTarget_text.nodeValue = Math.floor(self.target_temperature);\n\t\t\tsetClass(lblTargetHalf,'shown',self.target_temperature%1!=0);\n\t\t}\n\t\t\n\t\t/*\n\t\t * RENDER - leaf\n\t\t */\n\t\tfunction renderLeaf() {\n\t\t\tsetClass(svg,'has-leaf',self.has_leaf);\n\t\t}\n\t\t\n\t\t/*\n\t\t * RENDER - HVAC state\n\t\t */\n\t\tfunction renderHvacState() {\n\t\t\tArray.prototype.slice.call(svg.classList).forEach(function(c) {\n\t\t\t\tif (c.match(/^dial--state--/)) {\n\t\t\t\t\tsvg.classList.remove(c);\n\t\t\t\t};\n\t\t\t});\n\t\t\tsvg.classList.add('dial--state--'+self.hvac_state);\n\t\t}\n\t\t\n\t\t/*\n\t\t * RENDER - away\n\t\t */\n\t\tfunction renderAway() {\n\t\t\tsvg.classList[self.away ? 'add' : 'remove']('away');\n\t\t}\n\t\t\n\t\t/*\n\t\t * Drag to control\n\t\t */\n\t\tvar _drag = {\n\t\t\tinProgress: false,\n\t\t\tstartPoint: null,\n\t\t\tstartTemperature: 0,\n\t\t\tlockAxis: undefined\n\t\t};\n\t\t\n\t\tfunction eventPosition(ev) {\n\t\t\tif (ev.targetTouches && ev.targetTouches.length) {\n\t\t\t\treturn  [ev.targetTouches[0].clientX, ev.targetTouches[0].clientY];\n\t\t\t} else {\n\t\t\t\treturn [ev.x, ev.y];\n\t\t\t};\n\t\t}\n\t\t\n\t\tvar startDelay;\n\t\tfunction dragStart(ev) {\n\t\t\tstartDelay = setTimeout(function() {\n\t\t\t\tsetClass(svg, 'dial--edit', true);\n\t\t\t\t_drag.inProgress = true;\n\t\t\t\t_drag.startPoint = eventPosition(ev);\n\t\t\t\t_drag.startTemperature = self.target_temperature || options.minValue;\n\t\t\t\t_drag.lockAxis = undefined;\n\t\t\t},1000);\n\t\t};\n\t\t\n\t\tfunction dragEnd (ev) {\n\t\t\tclearTimeout(startDelay);\n\t\t\tsetClass(svg, 'dial--edit', false);\n\t\t\tif (!_drag.inProgress) return;\n\t\t\t_drag.inProgress = false;\n\t\t\tif (self.target_temperature != _drag.startTemperature) {\n\t\t\t\tif (typeof options.onSetTargetTemperature == 'function') {\n\t\t\t\t\toptions.onSetTargetTemperature(self.target_temperature);\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t\t\n\t\tfunction dragMove(ev) {\n\t\t\tev.preventDefault();\n\t\t\tif (!_drag.inProgress) return;\n\t\t\tvar evPos =  eventPosition(ev);\n\t\t\tvar dy = _drag.startPoint[1]-evPos[1];\n\t\t\tvar dx = evPos[0] - _drag.startPoint[0];\n\t\t\tvar dxy;\n\t\t\tif (_drag.lockAxis == 'x') {\n\t\t\t\tdxy  = dx;\n\t\t\t} else if (_drag.lockAxis == 'y') {\n\t\t\t\tdxy = dy;\n\t\t\t} else if (Math.abs(dy) > properties.dragLockAxisDistance) {\n\t\t\t\t_drag.lockAxis = 'y';\n\t\t\t\tdxy = dy;\n\t\t\t} else if (Math.abs(dx) > properties.dragLockAxisDistance) {\n\t\t\t\t_drag.lockAxis = 'x';\n\t\t\t\tdxy = dx;\n\t\t\t} else {\n\t\t\t\tdxy = (Math.abs(dy) > Math.abs(dx)) ? dy : dx;\n\t\t\t};\n\t\t\tvar dValue = (dxy*getSizeRatio())/(options.diameter)*properties.rangeValue;\n\t\t\tself.target_temperature = roundHalf(_drag.startTemperature+dValue);\n\t\t}\n\t\t\n\t\tsvg.addEventListener('mousedown',dragStart);\n\t\tsvg.addEventListener('touchstart',dragStart);\n\t\t\n\t\tsvg.addEventListener('mouseup',dragEnd);\n\t\tsvg.addEventListener('mouseleave',dragEnd);\n\t\tsvg.addEventListener('touchend',dragEnd);\n\t\t\n\t\tsvg.addEventListener('mousemove',dragMove);\n\t\tsvg.addEventListener('touchmove',dragMove);\n\t\t//\n\t\t\n\t\t/*\n\t\t * Helper functions\n\t\t */\n\t\tfunction restrictTargetTemperature(t) {\n\t\t\treturn restrictToRange(roundHalf(t),options.minValue,options.maxValue);\n\t\t}\n\t\t\n\t\tfunction angle(point) {\n\t\t\tvar dx = point[0] - properties.radius;\n\t\t\tvar dy = point[1] - properties.radius;\n\t\t\tvar theta = Math.atan(dx/dy) / (Math.PI/180);\n\t\t\tif (point[0]>=properties.radius && point[1] < properties.radius) {\n\t\t\t\ttheta = 90-theta - 90;\n\t\t\t} else if (point[0]>=properties.radius && point[1] >= properties.radius) {\n\t\t\t\ttheta = 90-theta + 90;\n\t\t\t} else if (point[0]<properties.radius && point[1] >= properties.radius) {\n\t\t\t\ttheta = 90-theta + 90;\n\t\t\t} else if (point[0]<properties.radius && point[1] < properties.radius) {\n\t\t\t\ttheta = 90-theta+270;\n\t\t\t}\n\t\t\treturn theta;\n\t\t};\n\t\t\n\t\tfunction getSizeRatio() {\n\t\t\treturn options.diameter / targetElement.clientWidth;\n\t\t}\n\t\t\n\t};\n})();\n\n/* ==== */\n(function(scope) {\n    \n    var nest = new thermostatDial(document.getElementById('thermostat'),{\n    \tonSetTargetTemperature: function(v) {\n    \t\tscope.send({topic: \"target_temperature\", payload: v});\n    \t}\n    });\n\n\n    scope.$watch('msg', function(data) {\n        //console.log(data.topic+\"  \"+data.payload);\n        if (data.topic == \"ambient_temperature\") {\n            nest.ambient_temperature = data.payload;\n        } if (data.topic == \"target_temperature\") {\n            nest.target_temperature = data.payload;\n        } if (data.topic == \"hvac_state\") {\n            nest.hvac_state = data.payload;\n        } if (data.topic == \"has_leaf\") {\n            nest.has_leaf = data.payload;\n        } if (data.topic == \"away\") {\n            nest.away = data.payload;\n        }\n    });\n})(scope);\n\n</script>","storeOutMessages":true,"fwdInMessages":false,"templateScope":"local","x":710,"y":300,"wires":[["602fed2a.3f1da4"]]},{"id":"121fdb16.06c045","type":"function","z":"2c174318.8fafec","name":"ambient_temperature","func":"flow.set(\"ambient_temp_topic\", msg.topic); \nflow.set(\"ambient_temp_payload\", msg.payload); \nmsg.topic = \"ambient_temperature\";\n\nreturn msg;","outputs":1,"noerr":0,"x":500,"y":300,"wires":[["85e9547.e3387a8"]]},{"id":"cde4777b.ed2518","type":"function","z":"2c174318.8fafec","name":"target_temperature","func":"flow.set(\"target_temp_topic\", msg.topic); \nflow.set(\"target_temp_payload\", msg.payload); \nmsg.topic = \"target_temperature\";\nreturn msg;","outputs":1,"noerr":0,"x":490,"y":340,"wires":[["85e9547.e3387a8"]]},{"id":"919595ac.732ca8","type":"function","z":"2c174318.8fafec","name":"hvac_state","func":"msg.topic = \"hvac_state\";\nreturn msg;","outputs":1,"noerr":0,"x":450,"y":400,"wires":[["85e9547.e3387a8"]]},{"id":"2fb888e5.40db78","type":"function","z":"2c174318.8fafec","name":"has_leaf","func":"msg.topic = \"has_leaf\";\nreturn msg;","outputs":1,"noerr":0,"x":440,"y":440,"wires":[["85e9547.e3387a8"]]},{"id":"d5e8585d.3e0038","type":"function","z":"2c174318.8fafec","name":"away","func":"msg.topic = \"away\";\nreturn msg;","outputs":1,"noerr":0,"x":430,"y":480,"wires":[["85e9547.e3387a8"]]},{"id":"595d8c0.c132074","type":"inject","z":"2c174318.8fafec","name":"","topic":"has_leaf","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":true,"x":170,"y":520,"wires":[["2fb888e5.40db78"]]},{"id":"b99a72e7.57614","type":"inject","z":"2c174318.8fafec","name":"","topic":"has_leaf","payload":"false","payloadType":"bool","repeat":"","crontab":"","once":false,"x":170,"y":560,"wires":[["2fb888e5.40db78"]]},{"id":"62f528cc.4f7cd8","type":"inject","z":"2c174318.8fafec","name":"","topic":"away","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"x":160,"y":600,"wires":[["d5e8585d.3e0038"]]},{"id":"4105734f.e0fb3c","type":"inject","z":"2c174318.8fafec","name":"","topic":"away","payload":"false","payloadType":"bool","repeat":"","crontab":"","once":false,"x":160,"y":640,"wires":[["d5e8585d.3e0038"]]},{"id":"52530d07.ac8b64","type":"inject","z":"2c174318.8fafec","name":"","topic":"hvac_state","payload":"off","payloadType":"str","repeat":"","crontab":"","once":false,"x":170,"y":400,"wires":[["919595ac.732ca8"]]},{"id":"1fa4d3.85fffb2d","type":"inject","z":"2c174318.8fafec","name":"","topic":"hvac_state","payload":"heating","payloadType":"str","repeat":"","crontab":"","once":false,"x":190,"y":440,"wires":[["919595ac.732ca8"]]},{"id":"9cd66a26.829668","type":"inject","z":"2c174318.8fafec","name":"","topic":"hvac_state","payload":"cooling","payloadType":"str","repeat":"","crontab":"","once":false,"x":190,"y":480,"wires":[["919595ac.732ca8"]]},{"id":"fc61a2c4.d585d","type":"inject","z":"2c174318.8fafec","name":"","topic":"ambient_temperature","payload":"21.5","payloadType":"num","repeat":"","crontab":"","once":true,"x":230,"y":300,"wires":[["121fdb16.06c045"]]},{"id":"f38cf4a3.ae78a8","type":"inject","z":"2c174318.8fafec","name":"","topic":"target_temperature","payload":"20","payloadType":"num","repeat":"","crontab":"","once":true,"x":220,"y":340,"wires":[["cde4777b.ed2518"]]},{"id":"602fed2a.3f1da4","type":"function","z":"2c174318.8fafec","name":"target_temperature","func":"if (msg.topic == \"target_temperature\") {\n    flow.set(\"target_temp_topic\", msg.topic); \n    flow.set(\"target_temp_payload\", msg.payload); \n    return msg;\n}","outputs":1,"noerr":0,"x":890,"y":300,"wires":[["89041053.48c4f"]]},{"id":"89041053.48c4f","type":"debug","z":"2c174318.8fafec","name":"","active":true,"console":"false","complete":"false","x":1090,"y":300,"wires":[]},{"id":"e9312d8.4023cd","type":"ui_text","z":"2c174318.8fafec","group":"8db78a1d.f45e08","order":0,"width":0,"height":0,"name":"","label":"AmbientTemp","format":"{{msg.payload}}","layout":"row-spread","x":780,"y":60,"wires":[]},{"id":"18a62e57.881fe2","type":"function","z":"2c174318.8fafec","name":"Ambient_Temp im Flow Speichern","func":"var t_topic = flow.get(\"ambient_temp_topic\");\nvar t_payload = flow.get(\"ambient_temp_payload\");\nmsg.payload = t_payload;\nmsg.topic = t_topic;\n\nreturn msg;\n\n\n","outputs":1,"noerr":0,"x":480,"y":100,"wires":[["e9312d8.4023cd","dd132023.ada06","85e9547.e3387a8"]]},{"id":"dd132023.ada06","type":"debug","z":"2c174318.8fafec","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":770,"y":120,"wires":[]},{"id":"88ebaa81.cc5e78","type":"ui_ui_control","z":"2c174318.8fafec","name":"","x":210,"y":100,"wires":[["18a62e57.881fe2"]]},{"id":"6328dc39.79dae4","type":"ui_text","z":"2c174318.8fafec","group":"8db78a1d.f45e08","order":0,"width":0,"height":0,"name":"","label":"TargetTemp","format":"{{msg.payload}}","layout":"row-spread","x":790,"y":680,"wires":[]},{"id":"7dd3f4ef.cfe85c","type":"function","z":"2c174318.8fafec","name":"Target_Temp im Flow speichern","func":"var t_topic = flow.get(\"target_temp_topic\");\nvar t_payload = flow.get(\"target_temp_payload\");\nmsg.payload = t_payload;\nmsg.topic = t_topic;\n\nreturn msg;\n\n\n","outputs":1,"noerr":0,"x":510,"y":720,"wires":[["6328dc39.79dae4","ab8ff2e2.a6156","85e9547.e3387a8"]]},{"id":"ab8ff2e2.a6156","type":"debug","z":"2c174318.8fafec","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":790,"y":740,"wires":[]},{"id":"712ded86.c2fbe4","type":"ui_ui_control","z":"2c174318.8fafec","name":"","x":230,"y":720,"wires":[["7dd3f4ef.cfe85c"]]},{"id":"8db78a1d.f45e08","type":"ui_group","z":"","name":"Default","tab":"135cb0cd.dc652f","disp":true,"width":"6","collapse":false},{"id":"135cb0cd.dc652f","type":"ui_tab","z":"","name":"Test","icon":"build"}]
Gefällt mir Gefällt mir x 1 Informativ Informativ x 1 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #51 am: 06 März 2018, 12:03:17 »
Na, ob wir bei 4613 Aufrufe und 50 Antworten bald eine eigene Node-RED Sektion bekommen ;-D ?
Wobei es einfach zu wenig - und das ist ja sehr schön - Probleme gibt mit Node-RED *hehe*

Ich bin auch super zufrieden eben genau die Punkte Geschwindigkeit und Träge Reaktion haben mich von den anderen weg zu Node-RED geführt.
Auch das effektiv soviele Instanzen wie man will mithören könnten ohne eine Trägheit hinein zu bringen ist was feines.
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)
Gefällt mir Gefällt mir x 1 Liste anzeigen

Online Ranseyer

  • Hero Member
  • *****
  • Beiträge: 1176
    • Homepage
Antw:Node-Red als Frontend
« Antwort #52 am: 08 März 2018, 17:00:40 »
Das Thema finde ich super spannend. Aus Zeitgründungen werde ich mich vermutlich erst im Winter dranhängen. Aber ich lese mal mit.

PS: Ich habe außer NodeRed eigentlich schon alles angetestet. Im Moment nutze ich FTUI. Daran stört mich der für mich sehr hohe Pflegeaufwand und die extreme Trägheit auf alten Tablets. Allerdingt gibt es halt schon sehr viele fertige Zutaten.

IOBroker wäre für mich von der Idee genau richtig, ist mir aber zu unzuverlässig beim Konfigurieren und ich vertraue dem nicht genügend. Außerdem frisst es auch mehr Zeit als man annehmen könnte.
FHEM mit FTUI. Homematic-Funk für Thermostate und Licht. MySensors als Basis für eigene HW.
Zentrale ist der MAPLE-CUL mit RFM69+HModUART-AddOn.
Doku zu meinen Projekten: Github/Ranseyer. Platinen falls verfügbar gerne auf Anfrage.
Zustimmung Zustimmung x 2 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #53 am: 08 März 2018, 17:30:22 »
Du wirst dich wundern wie schnell du in Node-RED auf brauchbare Ergebnisse kommst.  :D ;D
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
Antw:Node-Red als Frontend
« Antwort #54 am: 09 März 2018, 11:16:42 »
Im Moment nutze ich FTUI. Daran stört mich der für mich sehr hohe Pflegeaufwand und die extreme Trägheit auf alten Tablets. Allerdingt gibt es halt schon sehr viele fertige Zutaten.

IOBroker wäre für mich von der Idee genau richtig, ist mir aber zu unzuverlässig beim Konfigurieren und ich vertraue dem nicht genügend


Das unterschreibe ich so, das sind auch genau meine Erfahrungen.
FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix

Offline hermann1514

  • Full Member
  • ***
  • Beiträge: 194
Antw:Node-Red als Frontend
« Antwort #55 am: 12 März 2018, 10:06:58 »
Hallo zusammen,

ich habe nun auch mein TabletUI zur Seite gelegt und bin mit NodeRed angefangen. Wenn man sich mal ein wenig eingearbeitet hat ist das aus Supi und läuft wie S.. :-)

Nun, ich habe meine historischen Daten wie Temperatur, ValvePostion usw. in eine INFLUXDB liegen und habe die Graphen mit Grafana erstellt. Ich möchte nun aber mit den INFLUXDB Plugin für NodeRed die Grapgen direkt in NODERED erstellen.
Habe schon einiges probiert - aber dammit bin ich noch nicht weitergekommen.

Kann mir jemand helfen?

Danke.
Gruß
Hermann

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #56 am: 12 März 2018, 11:28:46 »
Moin  ;)

Schön wie das Thema immer mehr Zuwachs erfährt!  8)

Ich persönlich habe noch keine Graphen in Node-RED realisiert, auch der geplante Umstieg auf eine Log-DB steht noch weiter aus  ::). Ich habe aber wohl eine Seite mit 5 Thermostaten und 6 Hygrometern/Thermometern. Diese Seite hat beim initialen Laden schon eine gewisse Ladezeit (auf S7 edge, Raspi 3 und Windows PC) durch das Abfragen/Verarbeiten der verschiedenen Werte und Anzeigen, die anschließende dauerhafte Live-Anzeige ist verlustfrei.

Daher habe ich für mich entschieden nur aktuelle Werte auf Node-ERED anzeigen zu lassen, da es mir hauptsächlich um eine komfortable übersichtliche Steuerung des Systems geht. Graphen kann ich in der FHEM Web-Instanz einsehen oder wie ich finde noch komfortabler über andFHEM am Handy.
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
Antw:Node-Red als Frontend
« Antwort #57 am: 12 März 2018, 11:35:34 »
Diese Seite hat beim initialen Laden schon eine gewisse Ladezeit (auf S7 edge, Raspi 3 und Windows PC) durch das Abfragen/Verarbeiten der verschiedenen Werte und Anzeigen, die anschließende dauerhafte Live-Anzeige ist verlustfrei.

Das hat damit zu tun das Node-Red diese Daten als Json ab Webbrowser gibt und der dann lange rechnet. (da es zum teil doch schon sehr viele Messungen sind die da zusammen kommen)
Wenn man allerdings z.B. vorberechnete 15min, 30min oder Stunden Durchschnittswerte übergibt bleibt es schnell ;)

FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #58 am: 12 März 2018, 12:38:55 »
Mhh - ich glaube das hilft dann nur bei Graphen.

Bei Raumtemperatursteuerung und aktueller Temperatur helfen Durchschnittswerte aus meiner Sicht weniger.  ;D
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
Antw:Node-Red als Frontend
« Antwort #59 am: 12 März 2018, 13:04:48 »
Achsooo, bei dir ist das auch langsam ohne Graphen?

Das kann ich dann aber so nicht bestätigen, ich habe 14 auf einer Seite und die kommt so  schnell wie die anderen.
FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #60 am: 12 März 2018, 13:13:22 »
Langsam will ich nicht sagen, es hat 2 Sekunden Ladezeit, bis die Anzeige der Seite steht. Die Seiten die nur Switches haben gehen deutlich fixer. Es ist jammern auf hohem Niveau :-D und geht echt nur um die Ladezeit.

Gehostet habe ich Node-RED auf einem Pi3 und die Anzeige erfolgt auf einem anderen Pi3, PC oder Handy.
« Letzte Änderung: 12 März 2018, 13:16:29 von Master_Nick »
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
Antw:Node-Red als Frontend
« Antwort #61 am: 12 März 2018, 13:18:08 »
Ok, ich habe da einen Odroid C2 mit NandFlash hinter der ist da einiges Performanter.
FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #62 am: 12 März 2018, 13:22:01 »
 ;D Dann liegt es evtl daran.  8)
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Shojo

  • Full Member
  • ***
  • Beiträge: 325
  • Wie, Was, Wo?
    • DER BASTELBUNKER / Meine kleinen Projekte…
Antw:Node-Red als Frontend
« Antwort #63 am: 07 April 2018, 13:05:33 »
Hier noch mal ein Ansatz von mir.

Jeder Schalter oder Regler bekommt von mir als Topic das Fhem Device mitgegeben.
Wenn ich aber was anderes wie den State schalten möchte z.B. den HSV Wert sieht das so aus WZ.Licht.RGB.Fensterfront hvs
Hier noch die kleine Logik des Fhem Messages bauen:
var temp = msg.payload;
if (typeof temp == "string" && temp.startsWith("hsv"))
{
    temp = temp.replace(/ /g,"");
    temp = temp.replace(/%/g,"");
    temp = temp.replace(/hsv\(/g,"");
    temp = temp.replace(/\)/g,"");
    var x = temp.split(",");
    temp =  x[0] + "," + x[1] + "," + x[2];
}

msg.payload = "set " +  msg.topic + " " + temp;
return msg;

Und das Fhem Device:
defmod MQTT.NodeRed.Input MQTT_DEVICE
attr MQTT.NodeRed.Input IODev MQTTBroker
attr MQTT.NodeRed.Input stateFormat transmission-state
attr MQTT.NodeRed.Input subscribeReading_cmd {fhem("$message")} NodeRed/ToFHEM/cmd qos:1
« Letzte Änderung: 07 April 2018, 13:09:20 von Shojo »
FHEM auf: Odroid-C2 (Docker)
Bridge: Signalduino 433mHz, SignalESP 433mHz, nanoCUL 868mHz, HM-MOD-RPI-PCB, JeeLink, zigbee2mqtt (CC2531 USB sniffer) ,hue
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum, ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #64 am: 12 April 2018, 23:12:42 »
Ich habe meine gesamte Thermostatgeschichte nun auf Nest Optik gezogen die Benutzbarkeit ist hier viel besser als bei einem Schieberegler.  8) ;D

Finde es richtig geil!
Habe allerdings mit den hier gelieferten Dingen nur teils was arbeiten können - die hatten beim Reload immer noch Probleme bei mir :-)
Habe das Ganze beim Ursprung des Nest Thermostats für NodeRed dann gefunden und mit Ideen von dort gelöst... krieg es schon kaum noch auf die Kette was wie wo... viel Arbeit/Lesen gewesen.
Habe dann noch einige Icons eingebunden und bin sehr zufrieden.

Auch wird hier die Temperatur verglichen und entschieden ob geheizt wird (rotes Nest Thermostat). Und das Blatt kommt bei gewissen Zieltemperaturen die man als "sparend" betrachten könnte (kann man alles selber anpassen). Ansonsten habe ich meinen VOC Sensor im Wohnzimmer noch mit eingebunden ohne Werte sondern mittels 3er Symbole: Daumen hoch grün, Daumen hoch gelb und Daumen runter rot. Auch Window Open wird angezeigt wenn der Wert auf 1 steht - gelber Text "Window" erscheint dann.

Bei mehr als einem Thermostat ist es wichtig das DIV umzubenennen und Im weiteren Code den Namen der vorher ganz oben im DIV Stand erneut zu ändern.
Ich erweitere noch um ein eingeblendetes Fenstersymbol.

Code für NodeRed für das Wohnzimmer Thermostat:
[{"id":"53e6b42a.aabbe4","type":"function","z":"15bc8d4b.90af3b","name":"Konvertieren der Temperatur","func":"msg.payload = parseFloat(msg.payload);\nmsg.topic = 'sensor_temperature';\nnode.status({text:msg.payload + \"°C\"});\nreturn msg;","outputs":1,"noerr":0,"x":810,"y":300,"wires":[["730bb5a.9f6bfcc","c0dc329a.4f59b"]]},{"id":"730bb5a.9f6bfcc","type":"debug","z":"15bc8d4b.90af3b","name":"Temp Sensor","active":false,"console":"false","complete":"payload","x":1130,"y":300,"wires":[]},{"id":"63e04c4d.bb5f6c","type":"ui_template","z":"15bc8d4b.90af3b","group":"d2bea201.d68888","name":"Nest","order":5,"width":"6","height":"6","format":"<div id=\"thermostat-WZ\"></div>\n\n<style>\n@import url(http://fonts.googleapis.com/css?family=Open+Sans:300);\n#thermostat {\n  margin: 0 auto;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n.dial {\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n}\n.dial.away .dial__ico__leaf {\n  visibility: hidden;\n}\n.dial.away .dial__lbl--target {\n  visibility: hidden;\n}\n.dial.away .dial__lbl--target--half {\n  visibility: hidden;\n}\n.dial.away .dial__lbl--away {\n  opacity: 1;\n}\n.dial .dial__shape {\n  -webkit-transition: fill 0.5s;\n  transition: fill 0.5s;\n}\n.dial__ico__leaf {\n  fill: #13EB13;\n  opacity: 0;\n  -webkit-transition: opacity 0.5s;\n  transition: opacity 0.5s;\n  pointer-events: none;\n}\n.dial.has-leaf .dial__ico__leaf {\n  display: block;\n  opacity: 1;\n  pointer-events: initial;\n}\n.dial__editableIndicator {\n  fill: white;\n  fill-rule: evenodd;\n  opacity: 0;\n  -webkit-transition: opacity 0.5s;\n  transition: opacity 0.5s;\n}\n.dial--edit .dial__editableIndicator {\n  opacity: 1;\n}\n.dial--state--off .dial__shape {\n  fill: #3d3c3c;\n}\n.dial--state--heating .dial__shape {\n  fill: #E36304;\n}\n.dial--state--cooling .dial__shape {\n  fill: #007AF1;\n}\n.dial__ticks path {\n  fill: rgba(255, 255, 255, 0.3);\n}\n.dial__ticks path.active {\n  fill: rgba(255, 255, 255, 0.8);\n}\n.dial text {\n  fill: white;\n  text-anchor: middle;\n  font-family: Helvetica, sans-serif;\n  alignment-baseline: central;\n}\n.dial__lbl--target {\n  font-size: 120px;\n  font-weight: bold;\n}\n.dial__lbl--target--half {\n  font-size: 40px;\n  font-weight: bold;\n  opacity: 0;\n  -webkit-transition: opacity 0.1s;\n  transition: opacity 0.1s;\n}\n.dial__lbl--target--half.shown {\n  opacity: 1;\n  -webkit-transition: opacity 0s;\n  transition: opacity 0s;\n}\n.dial__lbl--ambient {\n  font-size: 22px;\n  font-weight: bold;\n}\n.dial__lbl--away {\n  font-size: 72px;\n  font-weight: bold;\n  opacity: 0;\n  pointer-events: none;\n}\n#controls {\n  font-family: Open Sans;\n  background-color: rgba(255, 255, 255, 0.25);\n  padding: 20px;\n  border-radius: 5px;\n  position: absolute;\n  left: 50%;\n  -webkit-transform: translatex(-50%);\n          transform: translatex(-50%);\n  margin-top: 20px;\n}\n#controls label {\n  text-align: left;\n  display: block;\n}\n#controls label span {\n  display: inline-block;\n  width: 200px;\n  text-align: right;\n  font-size: 0.8em;\n  text-transform: uppercase;\n}\n#controls p {\n  margin: 0;\n  margin-bottom: 1em;\n  padding-bottom: 1em;\n  border-bottom: 2px solid #ccc;\n}\n</style>\n<script>\n    var thermostatDial = (function() {\n\t\n\t/*\n\t * Utility functions\n\t */\n\t\n\t// Create an element with proper SVG namespace, optionally setting its attributes and appending it to another element\n\tfunction createSVGElement(tag,attributes,appendTo) {\n\t\tvar element = document.createElementNS('http://www.w3.org/2000/svg',tag);\n\t\tattr(element,attributes);\n\t\tif (appendTo) {\n\t\t\tappendTo.appendChild(element);\n\t\t}\n\t\treturn element;\n\t}\n\t\n\t// Set attributes for an element\n\tfunction attr(element,attrs) {\n\t\tfor (var i in attrs) {\n\t\t\telement.setAttribute(i,attrs[i]);\n\t\t}\n\t}\n\t\n\t// Rotate a cartesian point about given origin by X degrees\n\tfunction rotatePoint(point, angle, origin) {\n\t\tvar radians = angle * Math.PI/180;\n\t\tvar x = point[0]-origin[0];\n\t\tvar y = point[1]-origin[1];\n\t\tvar x1 = x*Math.cos(radians) - y*Math.sin(radians) + origin[0];\n\t\tvar y1 = x*Math.sin(radians) + y*Math.cos(radians) + origin[1];\n\t\treturn [x1,y1];\n\t}\n\t\n\t// Rotate an array of cartesian points about a given origin by X degrees\n\tfunction rotatePoints(points, angle, origin) {\n\t\treturn points.map(function(point) {\n\t\t\treturn rotatePoint(point, angle, origin);\n\t\t});\n\t}\n\t\n\t// Given an array of points, return an SVG path string representing the shape they define\n\tfunction pointsToPath(points) {\n\t\treturn points.map(function(point, iPoint) {\n\t\t\treturn (iPoint>0?'L':'M') + point[0] + ' ' + point[1];\n\t\t}).join(' ')+'Z';\n\t}\n\t\n\tfunction circleToPath(cx, cy, r) {\n\t\treturn [\n\t\t\t\"M\",cx,\",\",cy,\n\t\t\t\"m\",0-r,\",\",0,\n\t\t\t\"a\",r,\",\",r,0,1,\",\",0,r*2,\",\",0,\n\t\t\t\"a\",r,\",\",r,0,1,\",\",0,0-r*2,\",\",0,\n\t\t\t\"z\"\n\t\t].join(' ').replace(/\\s,\\s/g,\",\");\n\t}\n\t\n\tfunction donutPath(cx,cy,rOuter,rInner) {\n\t\treturn circleToPath(cx,cy,rOuter) + \" \" + circleToPath(cx,cy,rInner);\n\t}\n\t\n\t// Restrict a number to a min + max range\n\tfunction restrictToRange(val,min,max) {\n\t\tif (val < min) return min;\n\t\tif (val > max) return max;\n\t\treturn val;\n\t}\n\t\n\t// Round a number to the nearest 0.5\n\tfunction roundHalf(num) {\n\t\treturn Math.round(num*2)/2;\n\t}\n\t\n\tfunction setClass(el, className, state) {\n\t\tel.classList[state ? 'add' : 'remove'](className);\n\t}\n\t\n\t/*\n\t * The \"MEAT\"\n\t */\n\n\treturn function(targetElement, options) {\n\t\tvar self = this;\n\t\t\n\t\t/*\n\t\t * Options\n\t\t */\n\t\toptions = options || {};\n\t\toptions = {\n\t\t\tdiameter: options.diameter || 400,\n\t\t\tminValue: options.minValue || 10, // Minimum value for target temperature\n\t\t\tmaxValue: options.maxValue || 30, // Maximum value for target temperature\n\t\t\tnumTicks: options.numTicks || 200, // Number of tick lines to display around the dial\n\t\t\tonSetTargetTemperature: options.onSetTargetTemperature || function() {}, // Function called when new target temperature set by the dial\n\t\t};\n\t\t\n\t\t/*\n\t\t * Properties - calculated from options in many cases\n\t\t */\n\t\tvar properties = {\n\t\t\ttickDegrees: 300, //  Degrees of the dial that should be covered in tick lines\n\t\t\trangeValue: options.maxValue - options.minValue,\n\t\t\tradius: options.diameter/2,\n\t\t\tticksOuterRadius: options.diameter / 30,\n\t\t\tticksInnerRadius: options.diameter / 8,\n\t\t\thvac_states: ['off', 'heating', 'cooling'],\n\t\t\tdragLockAxisDistance: 15,\n\t\t}\n\t\tproperties.lblAmbientPosition = [properties.radius, properties.ticksOuterRadius-(properties.ticksOuterRadius-properties.ticksInnerRadius)/2]\n\t\tproperties.offsetDegrees = 180-(360-properties.tickDegrees)/2;\n\t\t\n\t\t/*\n\t\t * Object state\n\t\t */\n\t\tvar state = {\n\t\t\ttarget_temperature: options.minValue,\n\t\t\tambient_temperature: options.minValue,\n\t\t\thvac_state: properties.hvac_states[0],\n\t\t\thas_leaf: false,\n\t\t\taway: false\n\t\t};\n\t\t\n\t\t/*\n\t\t * Property getter / setters\n\t\t */\n\t\tObject.defineProperty(this,'target_temperature',{\n\t\t\tget: function() {\n\t\t\t\treturn state.target_temperature;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tstate.target_temperature = restrictTargetTemperature(+val);\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(this,'ambient_temperature',{\n\t\t\tget: function() {\n\t\t\t\treturn state.ambient_temperature;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tstate.ambient_temperature = roundHalf(+val);\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(this,'hvac_state',{\n\t\t\tget: function() {\n\t\t\t\treturn state.hvac_state;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tif (properties.hvac_states.indexOf(val)>=0) {\n\t\t\t\t\tstate.hvac_state = val;\n\t\t\t\t\trender();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(this,'has_leaf',{\n\t\t\tget: function() {\n\t\t\t\treturn state.has_leaf;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tstate.has_leaf = !!val;\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(this,'away',{\n\t\t\tget: function() {\n\t\t\t\treturn state.away;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tstate.away = !!val;\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t\t\n\t\t/*\n\t\t * SVG\n\t\t */\n\t\tvar svg = createSVGElement('svg',{\n\t\t\twidth: '100%', //options.diameter+'px',\n\t\t\theight: '100%', //options.diameter+'px',\n\t\t\tviewBox: '0 0 '+options.diameter+' '+options.diameter,\n\t\t\tclass: 'dial'\n\t\t},targetElement);\n\t\t// CIRCULAR DIAL\n\t\tvar circle = createSVGElement('circle',{\n\t\t\tcx: properties.radius,\n\t\t\tcy: properties.radius,\n\t\t\tr: properties.radius,\n\t\t\tclass: 'dial__shape'\n\t\t},svg);\n\t\t// EDITABLE INDICATOR\n\t\tvar editCircle = createSVGElement('path',{\n\t\t\td: donutPath(properties.radius,properties.radius,properties.radius-4,properties.radius-8),\n\t\t\tclass: 'dial__editableIndicator',\n\t\t},svg);\n\t\t\n\t\t/*\n\t\t * Ticks\n\t\t */\n\t\tvar ticks = createSVGElement('g',{\n\t\t\tclass: 'dial__ticks'\t\n\t\t},svg);\n\t\tvar tickPoints = [\n\t\t\t[properties.radius-1, properties.ticksOuterRadius],\n\t\t\t[properties.radius+1, properties.ticksOuterRadius],\n\t\t\t[properties.radius+1, properties.ticksInnerRadius],\n\t\t\t[properties.radius-1, properties.ticksInnerRadius]\n\t\t];\n\t\tvar tickPointsLarge = [\n\t\t\t[properties.radius-1.5, properties.ticksOuterRadius],\n\t\t\t[properties.radius+1.5, properties.ticksOuterRadius],\n\t\t\t[properties.radius+1.5, properties.ticksInnerRadius+20],\n\t\t\t[properties.radius-1.5, properties.ticksInnerRadius+20]\n\t\t];\n\t\tvar theta = properties.tickDegrees/options.numTicks;\n\t\tvar tickArray = [];\n\t\tfor (var iTick=0; iTick<options.numTicks; iTick++) {\n\t\t\ttickArray.push(createSVGElement('path',{d:pointsToPath(tickPoints)},ticks));\n\t\t};\n\t\t\n\t\t/*\n\t\t * Labels\n\t\t */\n\t\tvar lblTarget = createSVGElement('text',{\n\t\t\tx: properties.radius,\n\t\t\ty: properties.radius,\n\t\t\tclass: 'dial__lbl dial__lbl--target'\n\t\t},svg);\n\t\tvar lblTarget_text = document.createTextNode('');\n\t\tlblTarget.appendChild(lblTarget_text);\n\t\t//\n\t\tvar lblTargetHalf = createSVGElement('text',{\n\t\t\tx: properties.radius + properties.radius/2.5,\n\t\t\ty: properties.radius - properties.radius/8,\n\t\t\tclass: 'dial__lbl dial__lbl--target--half'\n\t\t},svg);\n\t\tvar lblTargetHalf_text = document.createTextNode('5');\n\t\tlblTargetHalf.appendChild(lblTargetHalf_text);\n\t\t//\n\t\tvar lblAmbient = createSVGElement('text',{\n\t\t\tclass: 'dial__lbl dial__lbl--ambient'\n\t\t},svg);\n\t\tvar lblAmbient_text = document.createTextNode('');\n\t\tlblAmbient.appendChild(lblAmbient_text);\n\t\t//\n\t\tvar lblAway = createSVGElement('text',{\n\t\t\tx: properties.radius,\n\t\t\ty: properties.radius,\n\t\t\tclass: 'dial__lbl dial__lbl--away'\n\t\t},svg);\n\t\tvar lblAway_text = document.createTextNode('AWAY');\n\t\tlblAway.appendChild(lblAway_text);\n\t\t//\n\t\tvar icoLeaf = createSVGElement('path',{\n\t\t\tclass: 'dial__ico__leaf'\n\t\t},svg);\n\t\t\n\t\t/*\n\t\t * LEAF\n\t\t */\n\t\tvar leafScale = properties.radius/5/100;\n\t\tvar leafDef = [\"M\", 3, 84, \"c\", 24, 17, 51, 18, 73, -6, \"C\", 100, 52, 100, 22, 100, 4, \"c\", -13, 15, -37, 9, -70, 19, \"C\", 4, 32, 0, 63, 0, 76, \"c\", 6, -7, 18, -17, 33, -23, 24, -9, 34, -9, 48, -20, -9, 10, -20, 16, -43, 24, \"C\", 22, 63, 8, 78, 3, 84, \"z\"].map(function(x) {\n\t\t\treturn isNaN(x) ? x : x*leafScale;\n\t\t}).join(' ');\n\t\tvar translate = [properties.radius-(leafScale*100*0.5),properties.radius*1.5]\n\t\tvar icoLeaf = createSVGElement('path',{\n\t\t\tclass: 'dial__ico__leaf',\n\t\t\td: leafDef,\n\t\t\ttransform: 'translate('+translate[0]+','+translate[1]+')'\n\t\t},svg);\n\t\t\t\n\t\t/*\n\t\t * RENDER\n\t\t */\n\t\tfunction render() {\n\t\t\trenderAway();\n\t\t\trenderHvacState();\n\t\t\trenderTicks();\n\t\t\trenderTargetTemperature();\n\t\t\trenderAmbientTemperature();\n\t\t\trenderLeaf();\n\t\t}\n\t\trender();\n\n\t\t/*\n\t\t * RENDER - ticks\n\t\t */\n\t\tfunction renderTicks() {\n\t\t\tvar vMin, vMax;\n\t\t\tif (self.away) {\n\t\t\t\tvMin = self.ambient_temperature;\n\t\t\t\tvMax = vMin;\n\t\t\t} else {\n\t\t\t\tvMin = Math.min(self.ambient_temperature, self.target_temperature);\n\t\t\t\tvMax = Math.max(self.ambient_temperature, self.target_temperature);\n\t\t\t}\n\t\t\tvar min = restrictToRange(Math.round((vMin-options.minValue)/properties.rangeValue * options.numTicks),0,options.numTicks-1);\n\t\t\tvar max = restrictToRange(Math.round((vMax-options.minValue)/properties.rangeValue * options.numTicks),0,options.numTicks-1);\n\t\t\t//\n\t\t\ttickArray.forEach(function(tick,iTick) {\n\t\t\t\tvar isLarge = iTick==min || iTick==max;\n\t\t\t\tvar isActive = iTick >= min && iTick <= max;\n\t\t\t\tattr(tick,{\n\t\t\t\t\td: pointsToPath(rotatePoints(isLarge ? tickPointsLarge: tickPoints,iTick*theta-properties.offsetDegrees,[properties.radius, properties.radius])),\n\t\t\t\t\tclass: isActive ? 'active' : ''\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t\n\t\t/*\n\t\t * RENDER - ambient temperature\n\t\t */\n\t\tfunction renderAmbientTemperature() {\n\t\t\tlblAmbient_text.nodeValue = Math.floor(self.ambient_temperature);\n\t\t\tif (self.ambient_temperature%1!=0) {\n\t\t\t\tlblAmbient_text.nodeValue += '⁵';\n\t\t\t}\n\t\t\tvar peggedValue = restrictToRange(self.ambient_temperature, options.minValue, options.maxValue);\n\t\t\tdegs = properties.tickDegrees * (peggedValue-options.minValue)/properties.rangeValue - properties.offsetDegrees;\n\t\t\tif (peggedValue > self.target_temperature) {\n\t\t\t\tdegs += 8;\n\t\t\t} else {\n\t\t\t\tdegs -= 8;\n\t\t\t}\n\t\t\tvar pos = rotatePoint(properties.lblAmbientPosition,degs,[properties.radius, properties.radius]);\n\t\t\tattr(lblAmbient,{\n\t\t\t\tx: pos[0],\n\t\t\t\ty: pos[1]\n\t\t\t});\n\t\t}\n\n\t\t/*\n\t\t * RENDER - target temperature\n\t\t */\n\t\tfunction renderTargetTemperature() {\n\t\t\tlblTarget_text.nodeValue = Math.floor(self.target_temperature);\n\t\t\tsetClass(lblTargetHalf,'shown',self.target_temperature%1!=0);\n\t\t}\n\t\t\n\t\t/*\n\t\t * RENDER - leaf\n\t\t */\n\t\tfunction renderLeaf() {\n\t\t\tsetClass(svg,'has-leaf',self.has_leaf);\n\t\t}\n\t\t\n\t\t/*\n\t\t * RENDER - HVAC state\n\t\t */\n\t\tfunction renderHvacState() {\n\t\t\tArray.prototype.slice.call(svg.classList).forEach(function(c) {\n\t\t\t\tif (c.match(/^dial--state--/)) {\n\t\t\t\t\tsvg.classList.remove(c);\n\t\t\t\t};\n\t\t\t});\n\t\t\tsvg.classList.add('dial--state--'+self.hvac_state);\n\t\t}\n\t\t\n\t\t/*\n\t\t * RENDER - away\n\t\t */\n\t\tfunction renderAway() {\n\t\t\tsvg.classList[self.away ? 'add' : 'remove']('away');\n\t\t}\n\t\t\n\t\t/*\n\t\t * Drag to control\n\t\t */\n\t\tvar _drag = {\n\t\t\tinProgress: false,\n\t\t\tstartPoint: null,\n\t\t\tstartTemperature: 0,\n\t\t\tlockAxis: undefined\n\t\t};\n\t\t\n\t\tfunction eventPosition(ev) {\n\t\t\tif (ev.targetTouches && ev.targetTouches.length) {\n\t\t\t\treturn  [ev.targetTouches[0].clientX, ev.targetTouches[0].clientY];\n\t\t\t} else {\n\t\t\t\treturn [ev.x, ev.y];\n\t\t\t};\n\t\t}\n\t\t\n\t\tvar startDelay;\n\t\tfunction dragStart(ev) {\n\t\t\tstartDelay = setTimeout(function() {\n\t\t\t\tsetClass(svg, 'dial--edit', true);\n\t\t\t\t_drag.inProgress = true;\n\t\t\t\t_drag.startPoint = eventPosition(ev);\n\t\t\t\t_drag.startTemperature = self.target_temperature || options.minValue;\n\t\t\t\t_drag.lockAxis = undefined;\n\t\t\t},1000);\n\t\t};\n\t\t\n\t\tfunction dragEnd (ev) {\n\t\t\tclearTimeout(startDelay);\n\t\t\tsetClass(svg, 'dial--edit', false);\n\t\t\tif (!_drag.inProgress) return;\n\t\t\t_drag.inProgress = false;\n\t\t\tif (self.target_temperature != _drag.startTemperature) {\n\t\t\t\tif (typeof options.onSetTargetTemperature == 'function') {\n\t\t\t\t\toptions.onSetTargetTemperature(self.target_temperature);\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t\t\n\t\tfunction dragMove(ev) {\n\t\t\tev.preventDefault();\n\t\t\tif (!_drag.inProgress) return;\n\t\t\tvar evPos =  eventPosition(ev);\n\t\t\tvar dy = _drag.startPoint[1]-evPos[1];\n\t\t\tvar dx = evPos[0] - _drag.startPoint[0];\n\t\t\tvar dxy;\n\t\t\tif (_drag.lockAxis == 'x') {\n\t\t\t\tdxy  = dx;\n\t\t\t} else if (_drag.lockAxis == 'y') {\n\t\t\t\tdxy = dy;\n\t\t\t} else if (Math.abs(dy) > properties.dragLockAxisDistance) {\n\t\t\t\t_drag.lockAxis = 'y';\n\t\t\t\tdxy = dy;\n\t\t\t} else if (Math.abs(dx) > properties.dragLockAxisDistance) {\n\t\t\t\t_drag.lockAxis = 'x';\n\t\t\t\tdxy = dx;\n\t\t\t} else {\n\t\t\t\tdxy = (Math.abs(dy) > Math.abs(dx)) ? dy : dx;\n\t\t\t};\n\t\t\tvar dValue = (dxy*getSizeRatio())/(options.diameter)*properties.rangeValue;\n\t\t\tself.target_temperature = roundHalf(_drag.startTemperature+dValue);\n\t\t}\n\t\t\n\t\tsvg.addEventListener('mousedown',dragStart);\n\t\tsvg.addEventListener('touchstart',dragStart);\n\t\t\n\t\tsvg.addEventListener('mouseup',dragEnd);\n\t\tsvg.addEventListener('mouseleave',dragEnd);\n\t\tsvg.addEventListener('touchend',dragEnd);\n\t\t\n\t\tsvg.addEventListener('mousemove',dragMove);\n\t\tsvg.addEventListener('touchmove',dragMove);\n\t\t//\n\t\t\n\t\t/*\n\t\t * Helper functions\n\t\t */\n\t\tfunction restrictTargetTemperature(t) {\n\t\t\treturn restrictToRange(roundHalf(t),options.minValue,options.maxValue);\n\t\t}\n\t\t\n\t\tfunction angle(point) {\n\t\t\tvar dx = point[0] - properties.radius;\n\t\t\tvar dy = point[1] - properties.radius;\n\t\t\tvar theta = Math.atan(dx/dy) / (Math.PI/180);\n\t\t\tif (point[0]>=properties.radius && point[1] < properties.radius) {\n\t\t\t\ttheta = 90-theta - 90;\n\t\t\t} else if (point[0]>=properties.radius && point[1] >= properties.radius) {\n\t\t\t\ttheta = 90-theta + 90;\n\t\t\t} else if (point[0]<properties.radius && point[1] >= properties.radius) {\n\t\t\t\ttheta = 90-theta + 90;\n\t\t\t} else if (point[0]<properties.radius && point[1] < properties.radius) {\n\t\t\t\ttheta = 90-theta+270;\n\t\t\t}\n\t\t\treturn theta;\n\t\t};\n\t\t\n\t\tfunction getSizeRatio() {\n\t\t\treturn options.diameter / targetElement.clientWidth;\n\t\t}\n\t\t\n\t};\n})();\n\n/* ==== */\n(function(scope) {\n    \n    var nest = new thermostatDial(document.getElementById('thermostat-WZ'),{\n    \tonSetTargetTemperature: function(v) {\n    \t\tscope.send({topic: \"target_temperature\", payload: v});\n    \t}\n    });\n\n\n    scope.$watch('msg', function(data) {\n        //console.log(data.topic+\"  \"+data.payload);\n        if (data.topic == \"ambient_temperature\") {\n            nest.ambient_temperature = data.payload;\n        } if (data.topic == \"target_temperature\") {\n            nest.target_temperature = data.payload;\n        } if (data.topic == \"hvac_state\") {\n            nest.hvac_state = data.payload;\n        } if (data.topic == \"has_leaf\") {\n            nest.has_leaf = data.payload;\n        } if (data.topic == \"away\") {\n            nest.away = data.payload;\n        }\n    });\n})(scope);\n\n</script>","storeOutMessages":true,"fwdInMessages":false,"templateScope":"local","x":1030,"y":540,"wires":[["228ed0cb.d3b908"]]},{"id":"773154d5.ab0824","type":"function","z":"15bc8d4b.90af3b","name":"ambient_temperature","func":"msg.topic = \"ambient_temperature\";\nglobal.set(\"wz-ambient\",msg.payload);\nnode.status({text:msg.payload + \"°C\"});\nreturn msg;","outputs":1,"noerr":0,"x":777.6190490722656,"y":388.33333587646484,"wires":[["63e04c4d.bb5f6c"]]},{"id":"1ae634e.7e416cb","type":"function","z":"15bc8d4b.90af3b","name":"hvac_state","func":"global.set(\"wz-state\",msg.payload);\n\nmsg.topic = \"hvac_state\";\nnode.status({text:msg.payload});\nreturn msg;","outputs":1,"noerr":0,"x":1670,"y":340,"wires":[["63e04c4d.bb5f6c"]]},{"id":"228ed0cb.d3b908","type":"function","z":"15bc8d4b.90af3b","name":"target_temperature","func":"if (msg.topic == \"target_temperature\") {\nglobal.set(\"wz-target\",msg.payload);\nreturn msg;\n}","outputs":1,"noerr":0,"x":1210,"y":540,"wires":[["c0dc329a.4f59b","2ab0e1e3.ac211e"]]},{"id":"c0dc329a.4f59b","type":"function","z":"15bc8d4b.90af3b","name":"Temperaturen Vergleichen","func":"context.target = context.target || 0.0;\ncontext.sensor = context.sensor || 0.0;\n\nif (msg.topic === 'sensor_temperature') {\n  context.sensor = msg.payload;\n} else if (msg.topic === 'target_temperature') {\n  context.target = msg.payload;\n} \n\nif (context.target >= context.sensor) {\n  return {payload: 1};\n} else {\n  return {payload: 0};\n}\nnode.status({text:msg.payload});","outputs":1,"noerr":0,"x":1460,"y":500,"wires":[["7dc8f30f.3d7064"]]},{"id":"7dc8f30f.3d7064","type":"function","z":"15bc8d4b.90af3b","name":"Farbstatus Nest","func":"msg.topic = \"hvac_state\";\nnode.status({text:msg.payload});\nreturn msg;","outputs":1,"noerr":0,"x":1700,"y":500,"wires":[["74d1ff15.059858"]]},{"id":"74d1ff15.059858","type":"switch","z":"15bc8d4b.90af3b","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"eq","v":"1","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":1310,"y":360,"wires":[["3d83fd16.3def3a"],["42df8b17.773ac4"]]},{"id":"3d83fd16.3def3a","type":"template","z":"15bc8d4b.90af3b","name":"Heizen OFF","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"off","output":"str","x":1490,"y":300,"wires":[["1ae634e.7e416cb"]]},{"id":"42df8b17.773ac4","type":"template","z":"15bc8d4b.90af3b","name":"Heizen ON","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"heating","output":"str","x":1490,"y":380,"wires":[["1ae634e.7e416cb"]]},{"id":"bcc9c2f.902a54","type":"delay","z":"15bc8d4b.90af3b","name":"","pauseType":"delay","timeout":"50","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":540,"y":540,"wires":[["c6c28969.9dbff8","bf2d08a0.229458","c02295c7.804d98","dc76cf88.de8868"]]},{"id":"c6c28969.9dbff8","type":"function","z":"15bc8d4b.90af3b","name":"global target-temp","func":"msg.payload = global.get(\"wz-target\");\nmsg.topic = 'target_temperature';\nnode.status({text:msg.payload + \"°C\"});\nreturn msg;","outputs":1,"noerr":0,"x":770,"y":440,"wires":[["63e04c4d.bb5f6c"]]},{"id":"ae55f012.dbc9e","type":"ui_ui_control","z":"15bc8d4b.90af3b","name":"ui change","x":360,"y":540,"wires":[["bcc9c2f.902a54"]]},{"id":"c02295c7.804d98","type":"function","z":"15bc8d4b.90af3b","name":"global color-state","func":"msg.payload = global.get(\"wz-state\");\nmsg.topic = \"hvac_state\";\nnode.status({text:msg.payload});\nreturn msg;","outputs":1,"noerr":0,"x":770,"y":560,"wires":[["63e04c4d.bb5f6c"]]},{"id":"8872a148.d992","type":"function","z":"15bc8d4b.90af3b","name":"Leaf","func":"minleaf = 15;\nmaxleaf = 22;\ntemperature = msg.payload;\nmsg.payload=false;\nif (temperature >= minleaf){\n    if (temperature <= maxleaf){\n        msg.payload = true;\n    }\n}\nmsg.topic = \"has_leaf\";\nglobal.set(\"wz-leaf\",msg.payload);\nnode.status({text:msg.payload});\nreturn msg;","outputs":1,"noerr":0,"x":810,"y":720,"wires":[["63e04c4d.bb5f6c"]]},{"id":"4737da1d.f282fc","type":"mqtt in","z":"15bc8d4b.90af3b","name":"","topic":"homeland/haushalt/heizung/Wohnzimmer_Thermostat/desiredTemperature","qos":"2","broker":"34eb4531.5459e2","x":350,"y":720,"wires":[["137bccd8.b66d93","8872a148.d992","19428fcb.0c576"]],"outputLabels":["target_temperature"]},{"id":"b09e0a1f.5122c8","type":"mqtt in","z":"15bc8d4b.90af3b","name":"","topic":"homeland/haushalt/heizung/Wohnzimmer_Thermostat/temperature","qos":"2","broker":"34eb4531.5459e2","x":360,"y":300,"wires":[["773154d5.ab0824","53e6b42a.aabbe4"]],"outputLabels":["ambient_temperature"]},{"id":"137bccd8.b66d93","type":"function","z":"15bc8d4b.90af3b","name":"target_temperature","func":"msg.topic = 'target_temperature';\nglobal.set(\"wz-target\",msg.payload);\nnode.status({text:msg.payload + \"°C\"});\nreturn msg;","outputs":1,"noerr":0,"x":770,"y":680,"wires":[["63e04c4d.bb5f6c","c0dc329a.4f59b"]]},{"id":"7f9ed5e0.953424","type":"mqtt out","z":"15bc8d4b.90af3b","name":"","topic":"homeland/haushalt/heizung/Wohnzimmer_Thermostat/desiredTemperature/set","qos":"2","retain":"false","broker":"34eb4531.5459e2","x":2040,"y":620,"wires":[]},{"id":"bf2d08a0.229458","type":"function","z":"15bc8d4b.90af3b","name":"global target-temp","func":"msg.payload = global.get(\"wz-ambient\");\nmsg.topic = 'ambient_temperature';\nnode.status({text:msg.payload + \"°C\"});\nreturn msg;","outputs":1,"noerr":0,"x":770,"y":500,"wires":[["63e04c4d.bb5f6c"]]},{"id":"dc76cf88.de8868","type":"function","z":"15bc8d4b.90af3b","name":"global target-temp","func":"msg.payload = global.get(\"wz-leaf\");\nmsg.topic = 'has_leaf';\nnode.status({text:msg.payload});\nreturn msg;","outputs":1,"noerr":0,"x":770,"y":620,"wires":[["63e04c4d.bb5f6c"]]},{"id":"a84aee83.b857b","type":"mqtt in","z":"15bc8d4b.90af3b","name":"","topic":"homeland/haushalt/heizung/Wohnzimmer_Thermostat/humidity","qos":"2","broker":"34eb4531.5459e2","x":350,"y":120,"wires":[["6ea3b9b3.85c2e"]],"outputLabels":["humidity"]},{"id":"b04d3a0d.8c6ba8","type":"trigger","z":"15bc8d4b.90af3b","op1":"","op2":"","op1type":"nul","op2type":"payl","duration":"4","extend":true,"units":"s","reset":"","bytopic":"all","name":"","x":1680,"y":620,"wires":[["7f9ed5e0.953424"]]},{"id":"8b86a571.ef3fb","type":"mqtt in","z":"15bc8d4b.90af3b","name":"","topic":"homeland/haushalt/heizung/Wohnzimmer_Thermostat/voc","qos":"2","broker":"34eb4531.5459e2","x":330,"y":180,"wires":[["4b4c2777.fcd59"]]},{"id":"4b4c2777.fcd59","type":"function","z":"15bc8d4b.90af3b","name":"","func":"node.status({text:msg.payload});\nbad = 'Air: <div class=\"fa fa-thumbs-down fa-2x nr-dashboard-error\"></div>';\nok = 'Air: <div class=\"fa fa-thumbs-up fa-2x nr-dashboard-warning\"></div>';\ngood = 'Air: <div class=\"fa fa-thumbs-up fa-2x nr-dashboard-ok\"></div>';\nif (msg.payload > 1750) { \n    msg.payload = (bad);\n    msg.topic = 'air';\n}\nif (msg.payload <= 1750 && msg.payload > 750) {\n    msg.payload = (ok);\n    msg.topic = 'air';\n}\nif (msg.payload <= 750) {\n    msg.payload = (good);\n    msg.topic = 'air';\n}\nreturn msg;","outputs":1,"noerr":0,"x":670,"y":180,"wires":[["44ad4257.3b5dec"]]},{"id":"45291976.3021f","type":"mqtt in","z":"15bc8d4b.90af3b","name":"","topic":"homeland/haushalt/heizung/Wohnzimmer_Thermostat/windowOpen","qos":"2","broker":"34eb4531.5459e2","x":360,"y":240,"wires":[["3708d80.98e8aa8"]]},{"id":"3708d80.98e8aa8","type":"function","z":"15bc8d4b.90af3b","name":"","func":"node.status({text:msg.payload});\ntext = '<div class=\"nr-dashboard-warning\">Window</div>';\nif (msg.payload == \"1\") {\n    msg.payload = (text);\n    msg.topic = 'window';\n}\nreturn msg;","outputs":1,"noerr":0,"x":670,"y":240,"wires":[["44ad4257.3b5dec"]]},{"id":"f6640250.4d957","type":"ui_text","z":"15bc8d4b.90af3b","group":"d2bea201.d68888","order":1,"width":"0","height":"0","name":"Temperatur/Luftfeuchtigkeit","label":"{{msg.payload.humidity.payload}}","format":"{{msg.payload.air.payload}} {{msg.payload.window.payload}}","layout":"row-spread","x":1040,"y":180,"wires":[]},{"id":"6ea3b9b3.85c2e","type":"function","z":"15bc8d4b.90af3b","name":"","func":"node.status({text:msg.payload});\ntext1 = '<div class=\"fa fa-tint fa-2x nr-dashboard-dim\"></div> ';\ntext2 = ' %';\nmsg.payload = (text1 + msg.payload + text2);\nmsg.topic = 'humidity';\nreturn msg;","outputs":1,"noerr":0,"x":670,"y":120,"wires":[["44ad4257.3b5dec"]]},{"id":"44ad4257.3b5dec","type":"join","z":"15bc8d4b.90af3b","name":"","mode":"custom","build":"object","property":"","propertyType":"full","key":"topic","joiner":"\\n","joinerType":"str","accumulate":true,"timeout":"","count":"1","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":830,"y":180,"wires":[["f6640250.4d957"]]},{"id":"2ab0e1e3.ac211e","type":"function","z":"15bc8d4b.90af3b","name":"Nur bei Abweichung senden","func":"if (msg.topic === 'target_temperature_old')\n{\n  oldvalue = msg.payload;\n} \nelse if (msg.topic === 'target_temperature')\n{\n  newvalue = msg.payload;\n} \n\nif (oldvalue != newvalue) {\n  oldvalue = newvalue;\n  return {payload: newvalue};\n}","outputs":1,"noerr":0,"x":1460,"y":620,"wires":[["b04d3a0d.8c6ba8"]]},{"id":"19428fcb.0c576","type":"function","z":"15bc8d4b.90af3b","name":"target_temperature_old","func":"msg.topic = 'target_temperature_old';\nnode.status({text:msg.payload + \"°C\"});\nreturn msg;","outputs":1,"noerr":0,"x":790,"y":760,"wires":[["2ab0e1e3.ac211e"]]},{"id":"d2bea201.d68888","type":"ui_group","z":"","name":"Wohnzimmer","tab":"7a08a4e0.9f9cf4","disp":true,"width":"6","collapse":false},{"id":"34eb4531.5459e2","type":"mqtt-broker","z":"","name":"","broker":"192.168.0.8","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"willTopic":"homeland/haushalt/steuerung/nodered/$online","willQos":"0","willPayload":"false","birthTopic":"","birthQos":"0","birthPayload":""},{"id":"7a08a4e0.9f9cf4","type":"ui_tab","z":"","name":"Klima","icon":"dashboard"}]
« Letzte Änderung: 13 April 2018, 11:30:09 von Master_Nick »
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)
Gefällt mir Gefällt mir x 3 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #65 am: 16 April 2018, 19:34:34 »
So ich habe noch weiter getweakt.

Wenn ihr Fragen oder Code braucht einfach Bescheid geben :-)
Sonst belasse ich es erst mal beim komplexesten dem Wohnzimmerthermostat.
Generell habe ich alle angepasst um den Minimal Wert und den Maximalwert zu ändern (statt 10° 4° beim Balkon -20° bis 50°).
Und Missbrauche die nun der Optik wegen auch für normales Thermo/Hygrometer. Auch habe ich das symbolisieren von Heizen von Zieltemp >= Sensortemp auf nur > geändert.

Ansonsten mal ein Bild von meinem Touch Display - befeuert von einem Raspi3.

[{"id":"53e6b42a.aabbe4","type":"function","z":"15bc8d4b.90af3b","name":"Konvertieren der Temperatur","func":"msg.payload = parseFloat(msg.payload);\nmsg.topic = 'sensor_temperature';\nnode.status({text:msg.payload + \"°C\"});\nreturn msg;","outputs":1,"noerr":0,"x":810,"y":300,"wires":[["730bb5a.9f6bfcc","c0dc329a.4f59b"]]},{"id":"730bb5a.9f6bfcc","type":"debug","z":"15bc8d4b.90af3b","name":"Temp Sensor","active":false,"console":"false","complete":"payload","x":1130,"y":300,"wires":[]},{"id":"63e04c4d.bb5f6c","type":"ui_template","z":"15bc8d4b.90af3b","group":"d2bea201.d68888","name":"Nest","order":5,"width":"6","height":"6","format":"<div id=\"thermostat-WZ\"></div>\n\n<style>\n@import url(http://fonts.googleapis.com/css?family=Open+Sans:300);\n#thermostat {\n  margin: 0 auto;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n.dial {\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n}\n.dial.away .dial__ico__leaf {\n  visibility: hidden;\n}\n.dial.away .dial__lbl--target {\n  visibility: hidden;\n}\n.dial.away .dial__lbl--target--half {\n  visibility: hidden;\n}\n.dial.away .dial__lbl--away {\n  opacity: 1;\n}\n.dial .dial__shape {\n  -webkit-transition: fill 0.5s;\n  transition: fill 0.5s;\n}\n.dial__ico__leaf {\n  fill: #13EB13;\n  opacity: 0;\n  -webkit-transition: opacity 0.5s;\n  transition: opacity 0.5s;\n  pointer-events: none;\n}\n.dial.has-leaf .dial__ico__leaf {\n  display: block;\n  opacity: 1;\n  pointer-events: initial;\n}\n.dial__editableIndicator {\n  fill: white;\n  fill-rule: evenodd;\n  opacity: 0;\n  -webkit-transition: opacity 0.5s;\n  transition: opacity 0.5s;\n}\n.dial--edit .dial__editableIndicator {\n  opacity: 1;\n}\n.dial--state--off .dial__shape {\n  fill: #3d3c3c;\n}\n.dial--state--heating .dial__shape {\n  fill: #E36304;\n}\n.dial--state--cooling .dial__shape {\n  fill: #007AF1;\n}\n.dial__ticks path {\n  fill: rgba(255, 255, 255, 0.3);\n}\n.dial__ticks path.active {\n  fill: rgba(255, 255, 255, 0.8);\n}\n.dial text {\n  fill: white;\n  text-anchor: middle;\n  font-family: Helvetica, sans-serif;\n  alignment-baseline: central;\n}\n.dial__lbl--target {\n  font-size: 120px;\n  font-weight: bold;\n}\n.dial__lbl--target--half {\n  font-size: 40px;\n  font-weight: bold;\n  opacity: 0;\n  -webkit-transition: opacity 0.1s;\n  transition: opacity 0.1s;\n}\n.dial__lbl--target--half.shown {\n  opacity: 1;\n  -webkit-transition: opacity 0s;\n  transition: opacity 0s;\n}\n.dial__lbl--ambient {\n  font-size: 22px;\n  font-weight: bold;\n}\n.dial__lbl--away {\n  font-size: 72px;\n  font-weight: bold;\n  opacity: 0;\n  pointer-events: none;\n}\n#controls {\n  font-family: Open Sans;\n  background-color: rgba(255, 255, 255, 0.25);\n  padding: 20px;\n  border-radius: 5px;\n  position: absolute;\n  left: 50%;\n  -webkit-transform: translatex(-50%);\n          transform: translatex(-50%);\n  margin-top: 20px;\n}\n#controls label {\n  text-align: left;\n  display: block;\n}\n#controls label span {\n  display: inline-block;\n  width: 200px;\n  text-align: right;\n  font-size: 0.8em;\n  text-transform: uppercase;\n}\n#controls p {\n  margin: 0;\n  margin-bottom: 1em;\n  padding-bottom: 1em;\n  border-bottom: 2px solid #ccc;\n}\n</style>\n<script>\n    var thermostatDial = (function() {\n\t\n\t/*\n\t * Utility functions\n\t */\n\t\n\t// Create an element with proper SVG namespace, optionally setting its attributes and appending it to another element\n\tfunction createSVGElement(tag,attributes,appendTo) {\n\t\tvar element = document.createElementNS('http://www.w3.org/2000/svg',tag);\n\t\tattr(element,attributes);\n\t\tif (appendTo) {\n\t\t\tappendTo.appendChild(element);\n\t\t}\n\t\treturn element;\n\t}\n\t\n\t// Set attributes for an element\n\tfunction attr(element,attrs) {\n\t\tfor (var i in attrs) {\n\t\t\telement.setAttribute(i,attrs[i]);\n\t\t}\n\t}\n\t\n\t// Rotate a cartesian point about given origin by X degrees\n\tfunction rotatePoint(point, angle, origin) {\n\t\tvar radians = angle * Math.PI/180;\n\t\tvar x = point[0]-origin[0];\n\t\tvar y = point[1]-origin[1];\n\t\tvar x1 = x*Math.cos(radians) - y*Math.sin(radians) + origin[0];\n\t\tvar y1 = x*Math.sin(radians) + y*Math.cos(radians) + origin[1];\n\t\treturn [x1,y1];\n\t}\n\t\n\t// Rotate an array of cartesian points about a given origin by X degrees\n\tfunction rotatePoints(points, angle, origin) {\n\t\treturn points.map(function(point) {\n\t\t\treturn rotatePoint(point, angle, origin);\n\t\t});\n\t}\n\t\n\t// Given an array of points, return an SVG path string representing the shape they define\n\tfunction pointsToPath(points) {\n\t\treturn points.map(function(point, iPoint) {\n\t\t\treturn (iPoint>0?'L':'M') + point[0] + ' ' + point[1];\n\t\t}).join(' ')+'Z';\n\t}\n\t\n\tfunction circleToPath(cx, cy, r) {\n\t\treturn [\n\t\t\t\"M\",cx,\",\",cy,\n\t\t\t\"m\",0-r,\",\",0,\n\t\t\t\"a\",r,\",\",r,0,1,\",\",0,r*2,\",\",0,\n\t\t\t\"a\",r,\",\",r,0,1,\",\",0,0-r*2,\",\",0,\n\t\t\t\"z\"\n\t\t].join(' ').replace(/\\s,\\s/g,\",\");\n\t}\n\t\n\tfunction donutPath(cx,cy,rOuter,rInner) {\n\t\treturn circleToPath(cx,cy,rOuter) + \" \" + circleToPath(cx,cy,rInner);\n\t}\n\t\n\t// Restrict a number to a min + max range\n\tfunction restrictToRange(val,min,max) {\n\t\tif (val < min) return min;\n\t\tif (val > max) return max;\n\t\treturn val;\n\t}\n\t\n\t// Round a number to the nearest 0.5\n\tfunction roundHalf(num) {\n\t\treturn Math.round(num*2)/2;\n\t}\n\t\n\tfunction setClass(el, className, state) {\n\t\tel.classList[state ? 'add' : 'remove'](className);\n\t}\n\t\n\t/*\n\t * The \"MEAT\"\n\t */\n\n\treturn function(targetElement, options) {\n\t\tvar self = this;\n\t\t\n\t\t/*\n\t\t * Options\n\t\t */\n\t\toptions = options || {};\n\t\toptions = {\n\t\t\tdiameter: options.diameter || 400,\n\t\t\tminValue: options.minValue || 4, // Minimum value for target temperature\n\t\t\tmaxValue: options.maxValue || 30, // Maximum value for target temperature\n\t\t\tnumTicks: options.numTicks || 200, // Number of tick lines to display around the dial\n\t\t\tonSetTargetTemperature: options.onSetTargetTemperature || function() {}, // Function called when new target temperature set by the dial\n\t\t};\n\t\t\n\t\t/*\n\t\t * Properties - calculated from options in many cases\n\t\t */\n\t\tvar properties = {\n\t\t\ttickDegrees: 300, //  Degrees of the dial that should be covered in tick lines\n\t\t\trangeValue: options.maxValue - options.minValue,\n\t\t\tradius: options.diameter/2,\n\t\t\tticksOuterRadius: options.diameter / 30,\n\t\t\tticksInnerRadius: options.diameter / 8,\n\t\t\thvac_states: ['off', 'heating', 'cooling'],\n\t\t\tdragLockAxisDistance: 15,\n\t\t}\n\t\tproperties.lblAmbientPosition = [properties.radius, properties.ticksOuterRadius-(properties.ticksOuterRadius-properties.ticksInnerRadius)/2]\n\t\tproperties.offsetDegrees = 180-(360-properties.tickDegrees)/2;\n\t\t\n\t\t/*\n\t\t * Object state\n\t\t */\n\t\tvar state = {\n\t\t\ttarget_temperature: options.minValue,\n\t\t\tambient_temperature: options.minValue,\n\t\t\thvac_state: properties.hvac_states[0],\n\t\t\thas_leaf: false,\n\t\t\taway: false\n\t\t};\n\t\t\n\t\t/*\n\t\t * Property getter / setters\n\t\t */\n\t\tObject.defineProperty(this,'target_temperature',{\n\t\t\tget: function() {\n\t\t\t\treturn state.target_temperature;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tstate.target_temperature = restrictTargetTemperature(+val);\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(this,'ambient_temperature',{\n\t\t\tget: function() {\n\t\t\t\treturn state.ambient_temperature;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tstate.ambient_temperature = roundHalf(+val);\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(this,'hvac_state',{\n\t\t\tget: function() {\n\t\t\t\treturn state.hvac_state;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tif (properties.hvac_states.indexOf(val)>=0) {\n\t\t\t\t\tstate.hvac_state = val;\n\t\t\t\t\trender();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(this,'has_leaf',{\n\t\t\tget: function() {\n\t\t\t\treturn state.has_leaf;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tstate.has_leaf = !!val;\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(this,'away',{\n\t\t\tget: function() {\n\t\t\t\treturn state.away;\n\t\t\t},\n\t\t\tset: function(val) {\n\t\t\t\tstate.away = !!val;\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t\t\n\t\t/*\n\t\t * SVG\n\t\t */\n\t\tvar svg = createSVGElement('svg',{\n\t\t\twidth: '100%', //options.diameter+'px',\n\t\t\theight: '100%', //options.diameter+'px',\n\t\t\tviewBox: '0 0 '+options.diameter+' '+options.diameter,\n\t\t\tclass: 'dial'\n\t\t},targetElement);\n\t\t// CIRCULAR DIAL\n\t\tvar circle = createSVGElement('circle',{\n\t\t\tcx: properties.radius,\n\t\t\tcy: properties.radius,\n\t\t\tr: properties.radius,\n\t\t\tclass: 'dial__shape'\n\t\t},svg);\n\t\t// EDITABLE INDICATOR\n\t\tvar editCircle = createSVGElement('path',{\n\t\t\td: donutPath(properties.radius,properties.radius,properties.radius-4,properties.radius-8),\n\t\t\tclass: 'dial__editableIndicator',\n\t\t},svg);\n\t\t\n\t\t/*\n\t\t * Ticks\n\t\t */\n\t\tvar ticks = createSVGElement('g',{\n\t\t\tclass: 'dial__ticks'\t\n\t\t},svg);\n\t\tvar tickPoints = [\n\t\t\t[properties.radius-1, properties.ticksOuterRadius],\n\t\t\t[properties.radius+1, properties.ticksOuterRadius],\n\t\t\t[properties.radius+1, properties.ticksInnerRadius],\n\t\t\t[properties.radius-1, properties.ticksInnerRadius]\n\t\t];\n\t\tvar tickPointsLarge = [\n\t\t\t[properties.radius-1.5, properties.ticksOuterRadius],\n\t\t\t[properties.radius+1.5, properties.ticksOuterRadius],\n\t\t\t[properties.radius+1.5, properties.ticksInnerRadius+20],\n\t\t\t[properties.radius-1.5, properties.ticksInnerRadius+20]\n\t\t];\n\t\tvar theta = properties.tickDegrees/options.numTicks;\n\t\tvar tickArray = [];\n\t\tfor (var iTick=0; iTick<options.numTicks; iTick++) {\n\t\t\ttickArray.push(createSVGElement('path',{d:pointsToPath(tickPoints)},ticks));\n\t\t};\n\t\t\n\t\t/*\n\t\t * Labels\n\t\t */\n\t\tvar lblTarget = createSVGElement('text',{\n\t\t\tx: properties.radius,\n\t\t\ty: properties.radius,\n\t\t\tclass: 'dial__lbl dial__lbl--target'\n\t\t},svg);\n\t\tvar lblTarget_text = document.createTextNode('');\n\t\tlblTarget.appendChild(lblTarget_text);\n\t\t//\n\t\tvar lblTargetHalf = createSVGElement('text',{\n\t\t\tx: properties.radius + properties.radius/2.5,\n\t\t\ty: properties.radius - properties.radius/8,\n\t\t\tclass: 'dial__lbl dial__lbl--target--half'\n\t\t},svg);\n\t\tvar lblTargetHalf_text = document.createTextNode('5');\n\t\tlblTargetHalf.appendChild(lblTargetHalf_text);\n\t\t//\n\t\tvar lblAmbient = createSVGElement('text',{\n\t\t\tclass: 'dial__lbl dial__lbl--ambient'\n\t\t},svg);\n\t\tvar lblAmbient_text = document.createTextNode('');\n\t\tlblAmbient.appendChild(lblAmbient_text);\n\t\t//\n\t\tvar lblAway = createSVGElement('text',{\n\t\t\tx: properties.radius,\n\t\t\ty: properties.radius,\n\t\t\tclass: 'dial__lbl dial__lbl--away'\n\t\t},svg);\n\t\tvar lblAway_text = document.createTextNode('AWAY');\n\t\tlblAway.appendChild(lblAway_text);\n\t\t//\n\t\tvar icoLeaf = createSVGElement('path',{\n\t\t\tclass: 'dial__ico__leaf'\n\t\t},svg);\n\t\t\n\t\t/*\n\t\t * LEAF\n\t\t */\n\t\tvar leafScale = properties.radius/5/100;\n\t\tvar leafDef = [\"M\", 3, 84, \"c\", 24, 17, 51, 18, 73, -6, \"C\", 100, 52, 100, 22, 100, 4, \"c\", -13, 15, -37, 9, -70, 19, \"C\", 4, 32, 0, 63, 0, 76, \"c\", 6, -7, 18, -17, 33, -23, 24, -9, 34, -9, 48, -20, -9, 10, -20, 16, -43, 24, \"C\", 22, 63, 8, 78, 3, 84, \"z\"].map(function(x) {\n\t\t\treturn isNaN(x) ? x : x*leafScale;\n\t\t}).join(' ');\n\t\tvar translate = [properties.radius-(leafScale*100*0.5),properties.radius*1.5]\n\t\tvar icoLeaf = createSVGElement('path',{\n\t\t\tclass: 'dial__ico__leaf',\n\t\t\td: leafDef,\n\t\t\ttransform: 'translate('+translate[0]+','+translate[1]+')'\n\t\t},svg);\n\t\t\t\n\t\t/*\n\t\t * RENDER\n\t\t */\n\t\tfunction render() {\n\t\t\trenderAway();\n\t\t\trenderHvacState();\n\t\t\trenderTicks();\n\t\t\trenderTargetTemperature();\n\t\t\trenderAmbientTemperature();\n\t\t\trenderLeaf();\n\t\t}\n\t\trender();\n\n\t\t/*\n\t\t * RENDER - ticks\n\t\t */\n\t\tfunction renderTicks() {\n\t\t\tvar vMin, vMax;\n\t\t\tif (self.away) {\n\t\t\t\tvMin = self.ambient_temperature;\n\t\t\t\tvMax = vMin;\n\t\t\t} else {\n\t\t\t\tvMin = Math.min(self.ambient_temperature, self.target_temperature);\n\t\t\t\tvMax = Math.max(self.ambient_temperature, self.target_temperature);\n\t\t\t}\n\t\t\tvar min = restrictToRange(Math.round((vMin-options.minValue)/properties.rangeValue * options.numTicks),0,options.numTicks-1);\n\t\t\tvar max = restrictToRange(Math.round((vMax-options.minValue)/properties.rangeValue * options.numTicks),0,options.numTicks-1);\n\t\t\t//\n\t\t\ttickArray.forEach(function(tick,iTick) {\n\t\t\t\tvar isLarge = iTick==min || iTick==max;\n\t\t\t\tvar isActive = iTick >= min && iTick <= max;\n\t\t\t\tattr(tick,{\n\t\t\t\t\td: pointsToPath(rotatePoints(isLarge ? tickPointsLarge: tickPoints,iTick*theta-properties.offsetDegrees,[properties.radius, properties.radius])),\n\t\t\t\t\tclass: isActive ? 'active' : ''\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t\n\t\t/*\n\t\t * RENDER - ambient temperature\n\t\t */\n\t\tfunction renderAmbientTemperature() {\n\t\t\tlblAmbient_text.nodeValue = Math.floor(self.ambient_temperature);\n\t\t\tif (self.ambient_temperature%1!=0) {\n\t\t\t\tlblAmbient_text.nodeValue += '⁵';\n\t\t\t}\n\t\t\tvar peggedValue = restrictToRange(self.ambient_temperature, options.minValue, options.maxValue);\n\t\t\tdegs = properties.tickDegrees * (peggedValue-options.minValue)/properties.rangeValue - properties.offsetDegrees;\n\t\t\tif (peggedValue > self.target_temperature) {\n\t\t\t\tdegs += 8;\n\t\t\t} else {\n\t\t\t\tdegs -= 8;\n\t\t\t}\n\t\t\tvar pos = rotatePoint(properties.lblAmbientPosition,degs,[properties.radius, properties.radius]);\n\t\t\tattr(lblAmbient,{\n\t\t\t\tx: pos[0],\n\t\t\t\ty: pos[1]\n\t\t\t});\n\t\t}\n\n\t\t/*\n\t\t * RENDER - target temperature\n\t\t */\n\t\tfunction renderTargetTemperature() {\n\t\t\tlblTarget_text.nodeValue = Math.floor(self.target_temperature);\n\t\t\tsetClass(lblTargetHalf,'shown',self.target_temperature%1!=0);\n\t\t}\n\t\t\n\t\t/*\n\t\t * RENDER - leaf\n\t\t */\n\t\tfunction renderLeaf() {\n\t\t\tsetClass(svg,'has-leaf',self.has_leaf);\n\t\t}\n\t\t\n\t\t/*\n\t\t * RENDER - HVAC state\n\t\t */\n\t\tfunction renderHvacState() {\n\t\t\tArray.prototype.slice.call(svg.classList).forEach(function(c) {\n\t\t\t\tif (c.match(/^dial--state--/)) {\n\t\t\t\t\tsvg.classList.remove(c);\n\t\t\t\t};\n\t\t\t});\n\t\t\tsvg.classList.add('dial--state--'+self.hvac_state);\n\t\t}\n\t\t\n\t\t/*\n\t\t * RENDER - away\n\t\t */\n\t\tfunction renderAway() {\n\t\t\tsvg.classList[self.away ? 'add' : 'remove']('away');\n\t\t}\n\t\t\n\t\t/*\n\t\t * Drag to control\n\t\t */\n\t\tvar _drag = {\n\t\t\tinProgress: false,\n\t\t\tstartPoint: null,\n\t\t\tstartTemperature: 0,\n\t\t\tlockAxis: undefined\n\t\t};\n\t\t\n\t\tfunction eventPosition(ev) {\n\t\t\tif (ev.targetTouches && ev.targetTouches.length) {\n\t\t\t\treturn  [ev.targetTouches[0].clientX, ev.targetTouches[0].clientY];\n\t\t\t} else {\n\t\t\t\treturn [ev.x, ev.y];\n\t\t\t};\n\t\t}\n\t\t\n\t\tvar startDelay;\n\t\tfunction dragStart(ev) {\n\t\t\tstartDelay = setTimeout(function() {\n\t\t\t\tsetClass(svg, 'dial--edit', true);\n\t\t\t\t_drag.inProgress = true;\n\t\t\t\t_drag.startPoint = eventPosition(ev);\n\t\t\t\t_drag.startTemperature = self.target_temperature || options.minValue;\n\t\t\t\t_drag.lockAxis = undefined;\n\t\t\t},1000);\n\t\t};\n\t\t\n\t\tfunction dragEnd (ev) {\n\t\t\tclearTimeout(startDelay);\n\t\t\tsetClass(svg, 'dial--edit', false);\n\t\t\tif (!_drag.inProgress) return;\n\t\t\t_drag.inProgress = false;\n\t\t\tif (self.target_temperature != _drag.startTemperature) {\n\t\t\t\tif (typeof options.onSetTargetTemperature == 'function') {\n\t\t\t\t\toptions.onSetTargetTemperature(self.target_temperature);\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t\t\n\t\tfunction dragMove(ev) {\n\t\t\tev.preventDefault();\n\t\t\tif (!_drag.inProgress) return;\n\t\t\tvar evPos =  eventPosition(ev);\n\t\t\tvar dy = _drag.startPoint[1]-evPos[1];\n\t\t\tvar dx = evPos[0] - _drag.startPoint[0];\n\t\t\tvar dxy;\n\t\t\tif (_drag.lockAxis == 'x') {\n\t\t\t\tdxy  = dx;\n\t\t\t} else if (_drag.lockAxis == 'y') {\n\t\t\t\tdxy = dy;\n\t\t\t} else if (Math.abs(dy) > properties.dragLockAxisDistance) {\n\t\t\t\t_drag.lockAxis = 'y';\n\t\t\t\tdxy = dy;\n\t\t\t} else if (Math.abs(dx) > properties.dragLockAxisDistance) {\n\t\t\t\t_drag.lockAxis = 'x';\n\t\t\t\tdxy = dx;\n\t\t\t} else {\n\t\t\t\tdxy = (Math.abs(dy) > Math.abs(dx)) ? dy : dx;\n\t\t\t};\n\t\t\tvar dValue = (dxy*getSizeRatio())/(options.diameter)*properties.rangeValue;\n\t\t\tself.target_temperature = roundHalf(_drag.startTemperature+dValue);\n\t\t}\n\t\t\n\t\tsvg.addEventListener('mousedown',dragStart);\n\t\tsvg.addEventListener('touchstart',dragStart);\n\t\t\n\t\tsvg.addEventListener('mouseup',dragEnd);\n\t\tsvg.addEventListener('mouseleave',dragEnd);\n\t\tsvg.addEventListener('touchend',dragEnd);\n\t\t\n\t\tsvg.addEventListener('mousemove',dragMove);\n\t\tsvg.addEventListener('touchmove',dragMove);\n\t\t//\n\t\t\n\t\t/*\n\t\t * Helper functions\n\t\t */\n\t\tfunction restrictTargetTemperature(t) {\n\t\t\treturn restrictToRange(roundHalf(t),options.minValue,options.maxValue);\n\t\t}\n\t\t\n\t\tfunction angle(point) {\n\t\t\tvar dx = point[0] - properties.radius;\n\t\t\tvar dy = point[1] - properties.radius;\n\t\t\tvar theta = Math.atan(dx/dy) / (Math.PI/180);\n\t\t\tif (point[0]>=properties.radius && point[1] < properties.radius) {\n\t\t\t\ttheta = 90-theta - 90;\n\t\t\t} else if (point[0]>=properties.radius && point[1] >= properties.radius) {\n\t\t\t\ttheta = 90-theta + 90;\n\t\t\t} else if (point[0]<properties.radius && point[1] >= properties.radius) {\n\t\t\t\ttheta = 90-theta + 90;\n\t\t\t} else if (point[0]<properties.radius && point[1] < properties.radius) {\n\t\t\t\ttheta = 90-theta+270;\n\t\t\t}\n\t\t\treturn theta;\n\t\t};\n\t\t\n\t\tfunction getSizeRatio() {\n\t\t\treturn options.diameter / targetElement.clientWidth;\n\t\t}\n\t\t\n\t};\n})();\n\n/* ==== */\n(function(scope) {\n    \n    var nest = new thermostatDial(document.getElementById('thermostat-WZ'),{\n    \tonSetTargetTemperature: function(v) {\n    \t\tscope.send({topic: \"target_temperature\", payload: v});\n    \t}\n    });\n\n\n    scope.$watch('msg', function(data) {\n        //console.log(data.topic+\"  \"+data.payload);\n        if (data.topic == \"ambient_temperature\") {\n            nest.ambient_temperature = data.payload;\n        } if (data.topic == \"target_temperature\") {\n            nest.target_temperature = data.payload;\n        } if (data.topic == \"hvac_state\") {\n            nest.hvac_state = data.payload;\n        } if (data.topic == \"has_leaf\") {\n            nest.has_leaf = data.payload;\n        } if (data.topic == \"away\") {\n            nest.away = data.payload;\n        }\n    });\n})(scope);\n\n</script>","storeOutMessages":true,"fwdInMessages":false,"templateScope":"local","x":1030,"y":540,"wires":[["228ed0cb.d3b908"]]},{"id":"773154d5.ab0824","type":"function","z":"15bc8d4b.90af3b","name":"ambient_temperature","func":"msg.topic = \"ambient_temperature\";\nglobal.set(\"wz-ambient\",msg.payload);\nnode.status({text:msg.payload + \"°C\"});\nreturn msg;","outputs":1,"noerr":0,"x":777.6190490722656,"y":388.33333587646484,"wires":[["63e04c4d.bb5f6c"]]},{"id":"1ae634e.7e416cb","type":"function","z":"15bc8d4b.90af3b","name":"hvac_state","func":"global.set(\"wz-state\",msg.payload);\n\nmsg.topic = \"hvac_state\";\nnode.status({text:msg.payload});\nreturn msg;","outputs":1,"noerr":0,"x":1670,"y":340,"wires":[["63e04c4d.bb5f6c"]]},{"id":"228ed0cb.d3b908","type":"function","z":"15bc8d4b.90af3b","name":"target_temperature","func":"if (msg.topic == \"target_temperature\") {\nglobal.set(\"wz-target\",msg.payload);\nreturn msg;\n}","outputs":1,"noerr":0,"x":1210,"y":540,"wires":[["c0dc329a.4f59b","2ab0e1e3.ac211e"]]},{"id":"c0dc329a.4f59b","type":"function","z":"15bc8d4b.90af3b","name":"Temperaturen Vergleichen","func":"context.target = context.target || 0.0;\ncontext.sensor = context.sensor || 0.0;\n\nif (msg.topic === 'sensor_temperature') {\n  context.sensor = msg.payload;\n} else if (msg.topic === 'target_temperature') {\n  context.target = msg.payload;\n} \n\nif (context.target > context.sensor) {\n  return {payload: 1};\n} else {\n  return {payload: 0};\n}\nnode.status({text:msg.payload});","outputs":1,"noerr":0,"x":1460,"y":500,"wires":[["7dc8f30f.3d7064"]]},{"id":"7dc8f30f.3d7064","type":"function","z":"15bc8d4b.90af3b","name":"Farbstatus Nest","func":"msg.topic = \"hvac_state\";\nnode.status({text:msg.payload});\nreturn msg;","outputs":1,"noerr":0,"x":1700,"y":500,"wires":[["74d1ff15.059858"]]},{"id":"74d1ff15.059858","type":"switch","z":"15bc8d4b.90af3b","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"eq","v":"1","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":1310,"y":360,"wires":[["3d83fd16.3def3a"],["42df8b17.773ac4"]]},{"id":"3d83fd16.3def3a","type":"template","z":"15bc8d4b.90af3b","name":"Heizen OFF","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"off","output":"str","x":1490,"y":300,"wires":[["1ae634e.7e416cb"]]},{"id":"42df8b17.773ac4","type":"template","z":"15bc8d4b.90af3b","name":"Heizen ON","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"heating","output":"str","x":1490,"y":380,"wires":[["1ae634e.7e416cb"]]},{"id":"bcc9c2f.902a54","type":"delay","z":"15bc8d4b.90af3b","name":"","pauseType":"delay","timeout":"50","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":540,"y":540,"wires":[["c6c28969.9dbff8","bf2d08a0.229458","c02295c7.804d98","dc76cf88.de8868"]]},{"id":"c6c28969.9dbff8","type":"function","z":"15bc8d4b.90af3b","name":"global target-temp","func":"msg.payload = global.get(\"wz-target\");\nmsg.topic = 'target_temperature';\nnode.status({text:msg.payload + \"°C\"});\nreturn msg;","outputs":1,"noerr":0,"x":770,"y":440,"wires":[["63e04c4d.bb5f6c"]]},{"id":"ae55f012.dbc9e","type":"ui_ui_control","z":"15bc8d4b.90af3b","name":"ui change","x":360,"y":540,"wires":[["bcc9c2f.902a54"]]},{"id":"c02295c7.804d98","type":"function","z":"15bc8d4b.90af3b","name":"global color-state","func":"msg.payload = global.get(\"wz-state\");\nmsg.topic = \"hvac_state\";\nnode.status({text:msg.payload});\nreturn msg;","outputs":1,"noerr":0,"x":770,"y":560,"wires":[["63e04c4d.bb5f6c"]]},{"id":"8872a148.d992","type":"function","z":"15bc8d4b.90af3b","name":"Leaf","func":"minleaf = 15;\nmaxleaf = 22;\ntemperature = msg.payload;\nmsg.payload=false;\nif (temperature >= minleaf){\n    if (temperature <= maxleaf){\n        msg.payload = true;\n    }\n}\nmsg.topic = \"has_leaf\";\nglobal.set(\"wz-leaf\",msg.payload);\nnode.status({text:msg.payload});\nreturn msg;","outputs":1,"noerr":0,"x":810,"y":720,"wires":[["63e04c4d.bb5f6c"]]},{"id":"4737da1d.f282fc","type":"mqtt in","z":"15bc8d4b.90af3b","name":"","topic":"homeland/haushalt/heizung/Wohnzimmer_Thermostat/desiredTemperature","qos":"2","broker":"34eb4531.5459e2","x":350,"y":720,"wires":[["137bccd8.b66d93","8872a148.d992","19428fcb.0c576"]],"outputLabels":["target_temperature"]},{"id":"b09e0a1f.5122c8","type":"mqtt in","z":"15bc8d4b.90af3b","name":"","topic":"homeland/haushalt/heizung/Wohnzimmer_Thermostat/temperature","qos":"2","broker":"34eb4531.5459e2","x":360,"y":300,"wires":[["773154d5.ab0824","53e6b42a.aabbe4"]],"outputLabels":["ambient_temperature"]},{"id":"137bccd8.b66d93","type":"function","z":"15bc8d4b.90af3b","name":"target_temperature","func":"msg.topic = 'target_temperature';\nglobal.set(\"wz-target\",msg.payload);\nnode.status({text:msg.payload + \"°C\"});\nreturn msg;","outputs":1,"noerr":0,"x":770,"y":680,"wires":[["63e04c4d.bb5f6c","c0dc329a.4f59b"]]},{"id":"7f9ed5e0.953424","type":"mqtt out","z":"15bc8d4b.90af3b","name":"","topic":"homeland/haushalt/heizung/Wohnzimmer_Thermostat/desiredTemperature/set","qos":"2","retain":"false","broker":"34eb4531.5459e2","x":2040,"y":620,"wires":[]},{"id":"bf2d08a0.229458","type":"function","z":"15bc8d4b.90af3b","name":"global target-temp","func":"msg.payload = global.get(\"wz-ambient\");\nmsg.topic = 'ambient_temperature';\nnode.status({text:msg.payload + \"°C\"});\nreturn msg;","outputs":1,"noerr":0,"x":770,"y":500,"wires":[["63e04c4d.bb5f6c"]]},{"id":"dc76cf88.de8868","type":"function","z":"15bc8d4b.90af3b","name":"global target-temp","func":"msg.payload = global.get(\"wz-leaf\");\nmsg.topic = 'has_leaf';\nnode.status({text:msg.payload});\nreturn msg;","outputs":1,"noerr":0,"x":770,"y":620,"wires":[["63e04c4d.bb5f6c"]]},{"id":"a84aee83.b857b","type":"mqtt in","z":"15bc8d4b.90af3b","name":"","topic":"homeland/haushalt/heizung/Wohnzimmer_Thermostat/humidity","qos":"2","broker":"34eb4531.5459e2","x":350,"y":120,"wires":[["6ea3b9b3.85c2e"]],"outputLabels":["humidity"]},{"id":"b04d3a0d.8c6ba8","type":"trigger","z":"15bc8d4b.90af3b","op1":"","op2":"","op1type":"nul","op2type":"payl","duration":"4","extend":true,"units":"s","reset":"","bytopic":"all","name":"","x":1680,"y":620,"wires":[["7f9ed5e0.953424"]]},{"id":"8b86a571.ef3fb","type":"mqtt in","z":"15bc8d4b.90af3b","name":"","topic":"homeland/haushalt/heizung/Wohnzimmer_Thermostat/voc","qos":"2","broker":"34eb4531.5459e2","x":330,"y":180,"wires":[["4b4c2777.fcd59"]]},{"id":"4b4c2777.fcd59","type":"function","z":"15bc8d4b.90af3b","name":"","func":"node.status({text:msg.payload});\nbad = 'Air: <div class=\"fa fa-thumbs-down fa-2x nr-dashboard-error\"></div>';\nok = 'Air: <div class=\"fa fa-thumbs-up fa-2x nr-dashboard-warning\"></div>';\ngood = 'Air: <div class=\"fa fa-thumbs-up fa-2x nr-dashboard-ok\"></div>';\nif (msg.payload > 1750) { \n    msg.payload = (bad);\n    msg.topic = 'air';\n}\nif (msg.payload <= 1750 && msg.payload > 750) {\n    msg.payload = (ok);\n    msg.topic = 'air';\n}\nif (msg.payload <= 750) {\n    msg.payload = (good);\n    msg.topic = 'air';\n}\nreturn msg;","outputs":1,"noerr":0,"x":670,"y":180,"wires":[["44ad4257.3b5dec"]]},{"id":"45291976.3021f","type":"mqtt in","z":"15bc8d4b.90af3b","name":"","topic":"homeland/haushalt/heizung/Wohnzimmer_Thermostat/windowOpen","qos":"2","broker":"34eb4531.5459e2","x":360,"y":240,"wires":[["3708d80.98e8aa8"]]},{"id":"3708d80.98e8aa8","type":"function","z":"15bc8d4b.90af3b","name":"","func":"node.status({text:msg.payload});\ntext = '<div class=\"nr-dashboard-warning\">Window</div>';\nif (msg.payload == \"1\") {\n    msg.payload = (text);\n    msg.topic = 'window';\n}\nreturn msg;","outputs":1,"noerr":0,"x":670,"y":240,"wires":[["44ad4257.3b5dec"]]},{"id":"f6640250.4d957","type":"ui_text","z":"15bc8d4b.90af3b","group":"d2bea201.d68888","order":1,"width":"0","height":"0","name":"Temperatur/Luftfeuchtigkeit","label":"{{msg.payload.humidity.payload}}","format":"{{msg.payload.air.payload}} {{msg.payload.window.payload}}","layout":"row-spread","x":1040,"y":180,"wires":[]},{"id":"6ea3b9b3.85c2e","type":"function","z":"15bc8d4b.90af3b","name":"","func":"node.status({text:msg.payload});\ntext1 = '<div class=\"fa fa-tint fa-2x nr-dashboard-dim\"></div> ';\ntext2 = ' %';\nmsg.payload = (text1 + msg.payload + text2);\nmsg.topic = 'humidity';\nreturn msg;","outputs":1,"noerr":0,"x":670,"y":120,"wires":[["44ad4257.3b5dec"]]},{"id":"44ad4257.3b5dec","type":"join","z":"15bc8d4b.90af3b","name":"","mode":"custom","build":"object","property":"","propertyType":"full","key":"topic","joiner":"\\n","joinerType":"str","accumulate":true,"timeout":"","count":"1","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":830,"y":180,"wires":[["f6640250.4d957"]]},{"id":"2ab0e1e3.ac211e","type":"function","z":"15bc8d4b.90af3b","name":"Nur bei Abweichung senden","func":"if (msg.topic === 'target_temperature_old')\n{\n  oldvalue = msg.payload;\n} \nelse if (msg.topic === 'target_temperature')\n{\n  newvalue = msg.payload;\n} \n\nif (oldvalue != newvalue) {\n  oldvalue = newvalue;\n  return {payload: newvalue};\n}","outputs":1,"noerr":0,"x":1460,"y":620,"wires":[["b04d3a0d.8c6ba8"]]},{"id":"19428fcb.0c576","type":"function","z":"15bc8d4b.90af3b","name":"target_temperature_old","func":"msg.topic = 'target_temperature_old';\nnode.status({text:msg.payload + \"°C\"});\nreturn msg;","outputs":1,"noerr":0,"x":790,"y":760,"wires":[["2ab0e1e3.ac211e"]]},{"id":"d2bea201.d68888","type":"ui_group","z":"","name":"Wohnzimmer","tab":"7a08a4e0.9f9cf4","order":1,"disp":true,"width":"7","collapse":false},{"id":"34eb4531.5459e2","type":"mqtt-broker","z":"","name":"","broker":"192.168.0.8","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"willTopic":"homeland/haushalt/steuerung/nodered/$online","willQos":"0","willPayload":"false","birthTopic":"","birthQos":"0","birthPayload":""},{"id":"7a08a4e0.9f9cf4","type":"ui_tab","z":"","name":"Klima","icon":"dashboard","order":1}]
« Letzte Änderung: 16 April 2018, 19:40:10 von Master_Nick »
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)
Gefällt mir Gefällt mir x 2 Liste anzeigen

Offline SamNitro

  • Sr. Member
  • ****
  • Beiträge: 547
  • Kölner Wimpelbeauftragter
Antw:Node-Red als Frontend
« Antwort #66 am: 16 Mai 2018, 19:34:20 »
Hat jemand eine schöne Lösung einen WeekdayTimer zu realisieren, wie beim TabletUI?
https://forum.fhem.de/index.php/topic,48106.msg397622.html#msg397622
Gruß Patrick
------------------------
(Rpi 3, Stretch) (HM-LGW) (CUL868) (CUL433) (Homematic Komponenten) (FS20) (SONOFF) (ESP8266) (EchoDot)

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #67 am: 16 Mai 2018, 20:05:48 »
 ;) Alos ich nicht, da ich dafür aber auch irgendwie keinerlei Verwendung habe.
Jede tiefere Schaltung die nicht an aus ist frühstücke ich in FHEM ab.
Machbar sind diverse Logiken aber generell auch in Node-Red.
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline SamNitro

  • Sr. Member
  • ****
  • Beiträge: 547
  • Kölner Wimpelbeauftragter
Antw:Node-Red als Frontend
« Antwort #68 am: 16 Mai 2018, 20:25:44 »
Ja ein paar Lösungen habe ich auch schon aber leider nicht so komfortabel wie der WeekdayTimer.

node-red-contrib-schedex:
Schöne Funktion mit sunrise sunset.

node-red-contrib-simple-weekly-scheduler:
Einfache Schaltungen.

Aber beide haben eine kleines Problem die wollen immer einen aus und an Befehl haben. Wenn man nur eins haben will muss man filtern.
Gruß Patrick
------------------------
(Rpi 3, Stretch) (HM-LGW) (CUL868) (CUL433) (Homematic Komponenten) (FS20) (SONOFF) (ESP8266) (EchoDot)

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #69 am: 23 Mai 2018, 12:17:10 »
Das kannste dir doch bestimmt mit einem Switch auf JS Basis umbauen.
Oder was meinst du mit AN/AUS Befehl?
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline SamNitro

  • Sr. Member
  • ****
  • Beiträge: 547
  • Kölner Wimpelbeauftragter
Antw:Node-Red als Frontend
« Antwort #70 am: 23 Mai 2018, 12:25:13 »
Die fertigen Nodes sind so ausgelegt das man eine einschaltzeit und eine ausschaltzeit programmieren muss.

Wenn ich jetzt aber z.B. einen Rollladen nur um 09:00 Uhr hochfahren möchte muss ich die andere Zeit filtern.

Schön wäre hier ein Node wo man pro Position die man hinzufügt nur eine schalt Befehl hat.

Als Eingabe dann
-Zeit
-On/Off oder Position
-ggf. noch der Wochentag


Mobil unterwegs!
« Letzte Änderung: 23 Mai 2018, 12:29:23 von SamNitro »
Gruß Patrick
------------------------
(Rpi 3, Stretch) (HM-LGW) (CUL868) (CUL433) (Homematic Komponenten) (FS20) (SONOFF) (ESP8266) (EchoDot)

Offline Absolute Beginner

  • Full Member
  • ***
  • Beiträge: 121
  • was man anfängt soll man auch
Antw:Node-Red als Frontend
« Antwort #71 am: 25 Mai 2018, 15:27:51 »
Lange nicht mehr hier gewesen. Ich möchte kurz über meine Erfahrungen berichten. Mit Node-RED bin ich nach wie vor begeistert unterwegs. Die Möglichkeiten der Bedienoberfläche sind gut, und ich habe diese auf meine Bedürfnisse für ein Smartphone optimiert (siehe Screenshot). Dabei geht es mir um eine Ein-Seiten-Darstellung aller relevanten Informationen (Licht, Rollos, Heizung, Anwesenheit, Temperaturen und Wetter. Solange alles 'im grünen Bereich' ist, sehe ich dies auf einem Blick - sonst tauchen andere Farben auf. So schön und praktisch Slider auch sind - ich habe sie gegen Pull-down-Menüs ausgetauscht, weil sie beim Wischen ständig ungewollt Aktionen ausführten. Auf weiteren Seiten sind Anrufliste, Systemkontrollen und Ansichten von Videokameras.

Angefangen habe ich mit der Brückenfunktion FHEM-MQTT-NodeRED. Inzwischen habe ich mehr und mehr direkt in NodeRED umgesetzt (8266-basierte WLAN-Produkte, Intertechno, Anrufliste, Wettervorhersage, IKEA Tradfri und Alexa-Sprachbedienung), sodass heute nur noch HomeMatic und SOMFY (über CUL) und Viessmann-Heizung (über USB) mittels FHEM/MQTT laufen.

Ich würde mich natürlich freuen, wenn hier mehr Aktivität zum Thema zu finden ist. Gerne beantworte ich Fragen zu meiner Umsetzung.
Raspberry Pi 3 - CUL868 - Jessie - FHEM5.8 - MQTT - Node-RED
HM-TC-IT-WM-W-EU, HM-LC-BI1PBU-FM, HM-Sec-SCo, HM-WDS30-0T2-SM, SOMFY, Echo, ESP, SonOff
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline SamNitro

  • Sr. Member
  • ****
  • Beiträge: 547
  • Kölner Wimpelbeauftragter
Antw:Node-Red als Frontend
« Antwort #72 am: 25 Mai 2018, 21:48:51 »
Hier mal eine kleine Übersicht von mir. Alles noch ziemlich am Anfang.
Gruß Patrick
------------------------
(Rpi 3, Stretch) (HM-LGW) (CUL868) (CUL433) (Homematic Komponenten) (FS20) (SONOFF) (ESP8266) (EchoDot)

Offline oetti77

  • Jr. Member
  • **
  • Beiträge: 90
Antw:Node-Red als Frontend
« Antwort #73 am: 23 Juni 2018, 12:24:35 »
Hallo zusammen,

ich habe mich mal an euren Beispielen orientiert, und habe aktuell eine HUE als Switch im Dashboard zum Testen.
Den State der HUE habe ich per Funktion auseinander genommen, da dieser nicht nur "on","off", sondern auch "dimXX%" sein kann, und dann per String an den Switch übergeben - funktioniert soweit.

Was mir nicht ganz klar ist, wie die Änderung im Dashboard wieder zurück zum FHEM kommt. Nehmt ihr das gleiche Topic, wie für den Input? Was muss im FHEM noch gemacht werden? Reicht da ein Subscribe auf das Topic?

Fragen über Fragen - ich hoffe ihr könnt mir helfen :-)

Danke
Chris

Erledigt! Habe mir nochmal genau Shojo's Flow angeschaut, da ist mir das Prinzipp bewusst geworden  ;D
« Letzte Änderung: 23 Juni 2018, 14:56:26 von oetti77 »
FHEM 5.8 (CentOS 7 auf ESXi 6.5), HM-CC-RT-DN, HM-Sec-Sc, HM-WDS40-TO, HM-LC-SW1-FM, HM-LC-Bl1PBU-FM, Sonos, Alexa, Nest Protect 2, Tradfri

Module: HUE, Lightify, ECOTOUCH, TelegramBot, Sonos, Alexa, Pushover, Enigma2

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #74 am: 25 Juni 2018, 11:39:23 »
Jeder Device hat ein Topic auf dem er lauscht und danach schaltet und ein Topic auf dem er Rückmeldung gibt.

Beispiel fürs schalten:  wohnung/elektrik/sonoff/sonoff-s20-3/relay/set

Beispiel fürs Rückmelden:  wohnung/elektrik/sonoff/sonoff-s20-3/relay/

Beim ersten würde FHEM ein "set true" auf das topic "wohnung/elektrik/sonoff/sonoff-s20-3/relay/set"  abliefern (publish) beim 2. bekommt FHEM die Rückmeldung über den tatsächlichen Zustand (subscribe auf wohnung/elektrik/sonoff/sonoff-s20-3/relay/).
Konvertierungen von Strings und Co. sind mit NodeRed kein problem. Zur not einfach mal Google anhauen oder deinen Flow mal hier posten.
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #75 am: 09 August 2018, 20:49:25 »
 ;D Mahlzeit, ich wollte mal wieder meine aktuellen Stand zeigen.

Ich habe mir auf jedem Tab einen globalen Bereich eingerichtet um wichtige Aktoren oder Status immer zu sehen.

Das Ganze hängt weiter im Flur mittels Touchscreen und Bewegungsmelder der im Rahmen des Screens eingelassen ist (Bilderrahmen).
Ansonsten per Handy/Tablet/PC natürlich auch erreichbar solange man im WLAN ist. Als neustes habe ich nun Waschmaschine und Trockner mit eingebunden über jeweils eine TP Link HS110 (Modul für FHEM gab es schon - merkte ich als ich fast schon am bauen war mit einem python Client  ;D ).
Die Waschmaschine und der Trockner haben im abgeschalteten Modus lediglich ein normales Bild - werden sie aktiv so zeigt Node-Red jeweils ein Gif an. Das war einfacher als das ganze selber zu animieren mittes Javascript oder ähnlichem.

Das Gif der Waschmaschine ist mal eben 10 MB :-D das wollte nicht hier im Forum laden ;-)
Das hier ist das Orignal:  https://cdn.dribbble.com/users/893939/screenshots/2223098/washing_machine2.gif (meines ist geschnitten, dass es keinen Rand hat)

Hier kann man es abgefilmt von meinem Touchpanel sehen: https://youtu.be/BkjPVJx2zeQ
« Letzte Änderung: 09 August 2018, 21:05:02 von Master_Nick »
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)
Gefällt mir Gefällt mir x 2 Liste anzeigen

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #76 am: 29 Oktober 2018, 19:27:39 »
Wer sich nach einem Update von NodeRed oder NodeJS ärgert über die hässliche Ansicht seiner Sachen sollte folgende Option prüfen:,

https://forum.fhem.de/index.php?action=dlattach;topic=78512.0;attach=107876;image

Bei mir sahen die Nest Thermometer auf einmal grausig aus....

RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Online Biervögelhasso

  • New Member
  • *
  • Beiträge: 10
Antw:Node-Red als Frontend
« Antwort #77 am: 05 November 2018, 15:50:33 »
Hallo,

ich habe ein kleines Problem mit Node-RED und komme an dieser Stelle nicht weiter. Ich habe mir ein kleines Dashboard gebaut und kann vom Handy darauf zugreifen. ( Node-Red läuft auf einen PI, Handy ist im WLAN verbunden) Das Problem ist nun leider das ich bei jeden neuem Aufruf meinen Login für Node-Red eingeben muß.  Ist dies bei Euch auch so? Wie habt ihr das gelöst?

Und noch eine zweite Frage. Wie habt ihr das Dashboard aufgebaut. Hab ihr zwei verschiedene eins fürs Handy und eins fürs Tablet?


Vielen Dank für Eure Hilfe.

FHEM auf Raspy3 mit Stretch, CUL, SDuino, JeeLink, SomfyHomematic, MQTT, Grafana, Node-RED

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #78 am: 05 November 2018, 15:54:52 »
NodeRed ist bei richtiger Nutzung 100% responsive - soll heißen es passt sich an die Geräte auf denen es aufgerufen wird anhand der erkannten nutzbaren Bildschirmgröße an und sortiert die verschiedenen Elemente so, dass es gut passt.

Ich habe somit genau eine Instanz NodeRed zuhause laufen.

Warum genau nutzt du Zugangsdaten? Bei mir ist das WLAN über Zugangsdaten gesichert, das NodeRed selber kann man sobald man in diesem WLAN ist einfach aufrufen ohne jede Authentifizierung.
« Letzte Änderung: 05 November 2018, 16:30:48 von Master_Nick »
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Online Biervögelhasso

  • New Member
  • *
  • Beiträge: 10
Antw:Node-Red als Frontend
« Antwort #79 am: 06 November 2018, 13:23:35 »
NodeRed ist bei richtiger Nutzung 100% responsive - soll heißen es passt sich an die Geräte auf denen es aufgerufen wird anhand der erkannten nutzbaren Bildschirmgröße an und sortiert die verschiedenen Elemente so, dass es gut passt.

Ich habe somit genau eine Instanz NodeRed zuhause laufen.

Warum genau nutzt du Zugangsdaten? Bei mir ist das WLAN über Zugangsdaten gesichert, das NodeRed selber kann man sobald man in diesem WLAN ist einfach aufrufen ohne jede Authentifizierung.

Hallo Master_Nick,

vielen Dank für die Information. Ich habe das Passwort deaktiviert. Nun kann man sehr schnell auf das Dashboard zugreifen.
Ich hätte gern zwei Dashboards da ich auf dem Handy andere Informationen sehen möchte wie auf dem Tablet.  Ich werde nun aber mit dem Dashboard für das Tablet beginnen und dann weiter schauen.

Viele Grüße.
FHEM auf Raspy3 mit Stretch, CUL, SDuino, JeeLink, SomfyHomematic, MQTT, Grafana, Node-RED

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #80 am: 06 November 2018, 14:36:00 »
Dann mach dir doch mehrere Tabs?

Und rufe diesen dann jeweils mit seiner festen Adresse auf:

http://IP:1880/ui/#/0 <- wäre der erste Tab z.B für dein Handy
http://IP:1880/ui/#/1 <- wäre der zweite

Und dann kann man dennoch zwischen beiden Wechseln, also sie sind nicht voreinander versteckt - wobei man das Top Menü abschalten kann glaub ich und auch den Swipe zwischen den Tabs kann man deaktivieren.
Dann hättest du deine 2 Uis
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Online Biervögelhasso

  • New Member
  • *
  • Beiträge: 10
Antw:Node-Red als Frontend
« Antwort #81 am: 09 November 2018, 09:26:20 »
Dann mach dir doch mehrere Tabs?

Und rufe diesen dann jeweils mit seiner festen Adresse auf:

http://IP:1880/ui/#/0 <- wäre der erste Tab z.B für dein Handy
http://IP:1880/ui/#/1 <- wäre der zweite

Und dann kann man dennoch zwischen beiden Wechseln, also sie sind nicht voreinander versteckt - wobei man das Top Menü abschalten kann glaub ich und auch den Swipe zwischen den Tabs kann man deaktivieren.
Dann hättest du deine 2 Uis

Hi,
genaus so werde ich es machen. Ich kann nur sagen NODE-RED ist genau das was mir noch gefehlt hat. Ich fand es immer sehr aufwändig mit dem FHEM Tablet UI.
Ich besitze leider keine Programmierkenntnisse aber in nur 3 Tage habe ich mir meine Tablet Seite zusammengebaut. Das Dashboard läuft viel flüssiger auf meinem Samsung TAB3.
Ein paar kleine Nachteile gibt es leider auch. NODE-RED besitzt nicht so schöne Icons. Ein Icon für die Jalousie die langsam runter fährt habe ich leider noch nicht gefunden.
Auch Icons für die Garage oder offene Fenster konnte ich nicht finden.

FHEM auf Raspy3 mit Stretch, CUL, SDuino, JeeLink, SomfyHomematic, MQTT, Grafana, Node-RED

Offline Master_Nick

  • Sr. Member
  • ****
  • Beiträge: 625
Antw:Node-Red als Frontend
« Antwort #82 am: 09 November 2018, 13:09:27 »
Du kannst dir eigene Gifs bauen und einbinde, so wie ich es bei meinem Trockner und der Waschmaschine gemacht habe.
RasPi 3 mit nanoCUL (a-culfw) | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem 0.3.0 | WOL | NFC | Harmony UltimateHub | Homestate | Roomba | 10" Touch mit Node-Red | SonOff S20 | Und ganz viel anderes tolles Gerödel.... ;-)

Offline SamNitro

  • Sr. Member
  • ****
  • Beiträge: 547
  • Kölner Wimpelbeauftragter
Antw:Node-Red als Frontend
« Antwort #83 am: 09 November 2018, 16:30:54 »
Garage und Fenster kann ich dir heute Abend rein stellen.



Edit:


[
    {
        "id": "d46c7631.59f9a",
        "type": "function",
        "z": "9d8c568.24a8628",
        "name": "check",
        "func": "if (msg.payload === \"ON\"){\n    msg.payload = \"#FF0000\";\n    return msg;\n}else if (msg.payload === \"OFF\"){\n    msg.payload = \"#00FF00\";\n    return msg;\n}\n",
        "outputs": 1,
        "noerr": 0,
        "x": 410,
        "y": 1320,
        "wires": [
            [
                "1673ba21.82cede"
            ]
        ]
    },
    {
        "id": "1673ba21.82cede",
        "type": "ui_template",
        "z": "9d8c568.24a8628",
        "group": "bf451414.e71f48",
        "name": "Status Garage LED",
        "order": 15,
        "width": "0",
        "height": "0",
        "format": "<style>\n.led {\n    float: right;\n    padding: 3px;\n    width: 10px;\n    height: 10px;\n    margin: 5px 5px 5px 5px;\n    border-radius: 50%;\n    \n}\n</style>\n\n<div>Status Garage<span class=\"led\" style=\"background-color: {{msg.payload}}; box-shadow: black 0 -1px 1px 0px, inset black  0 -1px 4px, {{msg.payload}} 0 3px 15px;\"></span></div>\n",
        "storeOutMessages": true,
        "fwdInMessages": true,
        "templateScope": "local",
        "x": 690,
        "y": 1320,
        "wires": [
            []
        ]
    },
    {
        "id": "bf451414.e71f48",
        "type": "ui_group",
        "z": "",
        "name": "FHEM",
        "tab": "dbb46b72.63ce3",
        "order": 1,
        "disp": true,
        "width": "6",
        "collapse": false
    },
    {
        "id": "dbb46b72.63ce3",
        "type": "ui_tab",
        "z": "",
        "name": "Home",
        "icon": "dashboard",
        "order": 1
    }
]
« Letzte Änderung: 09 November 2018, 20:19:44 von SamNitro »
Gruß Patrick
------------------------
(Rpi 3, Stretch) (HM-LGW) (CUL868) (CUL433) (Homematic Komponenten) (FS20) (SONOFF) (ESP8266) (EchoDot)

Online Biervögelhasso

  • New Member
  • *
  • Beiträge: 10
Antw:Node-Red als Frontend
« Antwort #84 am: 10 November 2018, 14:32:00 »
Hallo SamNitro,

ich habe mich vielleicht falsch ausgedrückt. Ich suche direkt ein Icon Garage oder offenes Fenster wie ich es im FHEM Tablet UI hatte.
Wenn ich Zeit habe schau ich mir den Vorschlag von Master_Nick an. Er hat eigene GIFs erstellt und eingebaut.

Viele Grüße
FHEM auf Raspy3 mit Stretch, CUL, SDuino, JeeLink, SomfyHomematic, MQTT, Grafana, Node-RED

 

decade-submarginal