<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>http://wiki.fhem.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=F+Klee</id>
	<title>FHEMWiki - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.fhem.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=F+Klee"/>
	<link rel="alternate" type="text/html" href="http://wiki.fhem.de/wiki/Spezial:Beitr%C3%A4ge/F_Klee"/>
	<updated>2026-04-30T15:34:05Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=LightScene&amp;diff=39914</id>
		<title>LightScene</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=LightScene&amp;diff=39914"/>
		<updated>2025-02-07T19:05:13Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Define aus commandref eingefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Speicherung und Wiederherstellung des Zustands von einer Gruppe von Geräten.&lt;br /&gt;
|ModType=h&lt;br /&gt;
&amp;lt;!-- |ModCategory=?? --&amp;gt;&lt;br /&gt;
&amp;lt;!-- |ModCmdRef=http://fhem.de/commandref.html#LightScene --&amp;gt;&lt;br /&gt;
|ModTechName=31_LightScene.pm&lt;br /&gt;
|ModOwner=justme1968&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightScene&#039;&#039;&#039; ist ein Hilfsmodul, das es erlaubt, Zustände einer Gruppe von Geräten abzuspeichern und wiederherzustellen.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
=== Define ===&lt;br /&gt;
:&amp;lt;code&amp;gt;define &amp;lt;name&amp;gt; LightScene [&amp;lt;dev1&amp;gt;] [&amp;lt;dev2&amp;gt;] [&amp;lt;dev3&amp;gt;] ... &amp;lt;/code&amp;gt;&lt;br /&gt;
:Beispiele:&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
define light_group LightScene Lampe1 Lampe2 Dimmer1&lt;br /&gt;
define kino_group LightScene LampeDecke LampeFernseher Fernseher Verstaerker&lt;br /&gt;
define Wohnzimmer LightScene Leinwand Beamer TV Leselampe Deckenlampe&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Gerätedetailansicht zeigt eine HTML-Übersicht über den aktuellen Zustand aller eingebundenen Geräte und aller konfigurierten Szenen mit den jeweiligen Gerätezuständen. Die Spaltenüberschrift mit den Gerätenamen ist anklickbar, um zur Detailansicht dieses Geräts zu gelangen. Die erste Zeile, die den aktuellen Gerätezustand anzeigt, ist anklickbar und sollte wie ein Klick auf das Gerätesymbol in einer Raumübersicht reagieren. Damit kann interaktiv eine neue Szene konfiguriert und mit dem Befehlsmenü der Detailansicht gespeichert werden. Die erste Spalte der Tabelle mit den Szenennamen ist anklickbar, um die Szene zu aktivieren.&lt;br /&gt;
:Ein Weblink mit einer Szenenübersicht, der in jeden Raum oder Grundriss eingebunden werden kann, lässt sich erstellen mit:&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
define wlScene weblink htmlCode {LightScene_2html(&amp;quot;LightSceneName&amp;quot;)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Set ===&lt;br /&gt;
&lt;br /&gt;
=== Get ===&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
== Funktionen ==&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
* [[XBMC#Lichtsteuerung_durch_KODI_oder_PLEX|Lichtsteuerung durch KODI oder PLEX]]&lt;br /&gt;
* [[Zuhause-Status|Umsetzung Zuhause-Status mit LightScene]]&lt;br /&gt;
* [[ReadingsGroup#LightScene_DropDown-Men.C3.BC_f.C3.BCr_smallscreen_Styles_oder_Floorplan|LightScene-DropDown-Menü für Smallscreen-Styles oder Floorplan]]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* weitere Dokumentation&lt;br /&gt;
* ...&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Stromz%C3%A4hler_auslesen&amp;diff=39799</id>
		<title>Stromzähler auslesen</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Stromz%C3%A4hler_auslesen&amp;diff=39799"/>
		<updated>2025-01-12T12:27:07Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Hichi zu den Kombigeräten hinzu gefügt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;quot;EM&amp;quot; in FHEM steht für &amp;quot;EnergieMessung&amp;quot;, der Stromzähler im Haushalt ist also ein naheliegendes Objekt der Erfassung durch FHEM.&lt;br /&gt;
In Deutschland waren 2018 noch 78% der Stromzähler klassische elektromechanische Zähler &amp;lt;ref&amp;gt;https://de.statista.com/statistik/daten/studie/298727/umfrage/verteilung-der-zaehlertechnik-in-deutschen-haushalten/&amp;lt;/ref&amp;gt;, auch [https://de.wikipedia.org/wiki/Ferraris-Z%C3%A4hler Ferraris-Zähler] genannt. Neben dem Zwischenschritt, der elektronischen Messeinrichtung, dürfen heute aber nur noch [https://www.bundesnetzagentur.de/SharedDocs/A_Z/M/ModerneMesseinrichtung.html moderne Messeinrichtungen] (&amp;quot;mMe&amp;quot;) verbaut werden, und sollen bis 2032 komplett ersetzt werden. &amp;lt;ref&amp;gt;https://www.bundesnetzagentur.de/DE/Sachgebiete/ElektrizitaetundGas/Verbraucher/Metering/SmartMeter_node.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
Die dritte Gruppe sind die [https://www.bundesnetzagentur.de/SharedDocs/Mediathek/Verbraucherhefte/Energie/IntelligentesMessystem_SmartMeter.pdf Intelligenten Messsysteme]. Bei diesen überträgt zusätzlich zu den modernen Messeinrichtungen ein SmartMeterGateway viertelstündlich die Zählerstände zum Messstellenbetreiber. Eine Ablesung durch den Nutzer selber oder den Betreiber entfällt damit. Das SmartMeterGateway soll zusätzlich auch einen Steuerungsrückkanal z.B. für Ladesäulen im Haushalt zur Verfügung stellen - diese Spezifikationen sind allerdings noch teilweise (Stand 2020) in der Entwicklung.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsfälle der Verbrauchserfassung ==&lt;br /&gt;
[[Datei:Verbrauchssteuerung mit FHEM.jpeg|mini|Steuerung zweier Hausverbraucher (Heizkreispumpe, Tiefkühltruhe) über FHEM. Nach Abschluss der Heizphase der Waschmaschine wird die Heizkreispumpe eingeschaltet, was wiederum kurz danach einen Start des Brenners auslöst. Mit kurzer Verzögerung wird nach dem Abschalten des Brenners der Tiefkühlschrank eingeschaltet.]]&lt;br /&gt;
&lt;br /&gt;
=== Ohne eigene Stromerzeugung: ===&lt;br /&gt;
* Abrechnung von Nutzungszeiträumen, z.B. bei einer überlassenen Ferienwohnung&lt;br /&gt;
* Selbstanreiz zum Stromsparen durch zeitnahes Feedback (z.B.: Tagesvergleich, Wochenvergleich)&lt;br /&gt;
* Ermitteln der eigenen Tageslastkurve (Stromverbrauch nach Uhrzeit), um qualifiziert das Eigenverbrauchspotential bei einer Solaranlage vorab abschätzen zu können&lt;br /&gt;
* Überwachung des 24-h-Mindestverbrauchs: Ist der Mindestwert des Stromverbrauch auf Minutenbasis im Vergleich zum Vortag angestiegen, liegt der Verdacht nahe, dass entweder ein signifikanter Standby-Verbraucher hinzugekommen ist, oder z.B. ein Kellerlicht vergessen wurde.&lt;br /&gt;
&lt;br /&gt;
=== Mit eigener Stromerzeugung (Solar etc.): ===&lt;br /&gt;
* Bestimmung des Eigenverbrauchs / der Autarkie-Quote&lt;br /&gt;
* Signalisierung der Überschuss-Situation, z.B. durch eine farbige Lampe in der Wohnung (&amp;quot;Licht aus = kein Überschuss, dunkelrot = bis 500 Watt Überschuss, grün = 500-2000 Watt Überschuss, hellblau = &amp;gt; 2000 Watt Überschuss), um Großverbraucher bewusst einzuschalten. &lt;br /&gt;
* Automatische Steuerung von Stromverbrauchern je nach Überschuss:  Wärmepumpe, Wallbox, Waschmaschine / Trockner / Geschirrspüler, Tiefkühltruhe&lt;br /&gt;
&lt;br /&gt;
== Schnittstellen ==&lt;br /&gt;
[[Datei:Stromzaehler ohne.jpeg|mini|D0-Schnittstelle an einer modernen Messeinrichtung oben rechts]]&lt;br /&gt;
&lt;br /&gt;
=== D0-Schnittstelle ===&lt;br /&gt;
[[Datei:Stromzaehler mit.jpeg|mini|... und mit angebrachtem IR-Schreib/Lese-Kopf]]&lt;br /&gt;
Für den Nutzer spielt der Unterschied zwischen moderner Messeinrichtung und intelligentem Messsystem vor allem preislich eine Rolle: Die Grundgebühr für den Messstellenbetrieb, die bei der modernen Messeinrichtung z.Zt. auf 20€ im Jahr begrenzt ist, ist beim intelligenten Messsystem gestaffelt höher. An der Schnittstelle zum Nutzer ändert sich nichts: In der Regel verfügen moderne Messeinrichtung wie auch intelligentes Messsystem über eine digitale optische Schnittstelle für den Kunden: Die D0-Schnittstelle nach DIN EN 62056-21. Diese Schnittstelle findet sich in der Regel in Form eines durch eine Erhebung auf der Frontseite des Zählers gebildeten Kreises mit je einer IR-Leucht- und einer Foto-Diode am Zähler. Auf der Rückwand ist i.d.R. eine Eisenplatte angebracht, die es erlaubt, einen optischen Lesekopf mit Magneten stabil auf dem Zähler zu platzieren. Auf der D0-Schnittstelle werden - ggf. nach einmaliger oder regelmässiger Aktivierung durch eine PIN - regelmäßig (ggf. sekündlich) sowohl momentane Lastwerte (Watt) als auch Zählerstände ausgegeben.&lt;br /&gt;
&lt;br /&gt;
=== S0-Schnittstelle ===&lt;br /&gt;
Ältere Zähler oder frei am Markt verfügbare Zwischenzähler bieten hingegen oft lediglich eine [https://de.wikipedia.org/wiki/S0-Schnittstelle S0-Schnittstelle]. Die S0-Schnittstelle entspricht der alten roten Markierung auf der Drehscheibe des Ferrariszählers: Sie liefert Impulse, deren Auftreten den Verbrauch von z.B. einer Wattstunde (Wh) signalisiert. Damit kann durch ununterbrochenes Mitzählen der Impulse der Verbrauch in relativ grober zeitlicher Auflösung erfasst werden. Neben der gröberen zeitlichen Auflösung lassen sich aber absolute Zählerstände nicht einlesen, und eine Unterbrechung der Erfassung kann nicht automatisch korrigiert werden. Eine Beschreibung, eine S0-Schnittstelle in FHEM verfügbar zu machen und mit dem Modul ElectricityCalculator auszuwerten, befindet sich z.B. [https://haus-automatisierung.com/projekt/2019/04/21/projekt-s0-zaehler-loxone-fhem.html hier].&lt;br /&gt;
&lt;br /&gt;
=== Vorläufer-Lösungen ===&lt;br /&gt;
Auch für Ferraris-Zähler wurden optische Auslese-Lösungen entwickelt. Diese werden hier aber nicht beschrieben, weil der Hardware-Aufwand für eine Lösung, die ohnehin absehbar abgeschaltet wird, nicht lohnenswert ist.&lt;br /&gt;
&lt;br /&gt;
=== RS485 Schnittstelle ===&lt;br /&gt;
Einige Zähler und Netzbetreiber erlauben das Auslesen über eine serielle RS485 Schnittstelle, welche ansonsten von einem Smartmeter-gateway genutzt werden würde. Ist die Schnittstelle nicht belegt durch eine Einrichtung des Netzbetreibers, dann ist es hiermit ebenfalls möglich, die Daten des Stromzählers analog zur D0 Schnittstelle auszulesen.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen für die Erfassung ==&lt;br /&gt;
=== Eine Moderne Messeinrichtung erhalten ===&lt;br /&gt;
Grundsätzlich obliegt es dem Messstellenbetreiber, über den Zeitpunkt des Einbaus einer modernen Messeinrichtung bis spätestens 2032 zu entscheiden. Die Entscheidung kann durch folgende Schritte des Benutzers forciert werden:&lt;br /&gt;
* Gespräch mit dem Messstellenbetreiber&lt;br /&gt;
* Verbrauch von mehr als 6000 kWh im Jahr&lt;br /&gt;
* Betrieb einer steckerfertigen Solaranlage: Denn die Mehrzahl der Ferrariszähler würden sich beim Betrieb einer steckerfertigen Solaranlage (&amp;quot;Balkon-Kraftwerk&amp;quot;, &amp;quot;Guerilla-PV&amp;quot;) rückwärts drehen, da sie nicht über eine Rücklaufsperre verfügen. Dieses Rückwärtsdrehen des Zähler entspräche einem Verstoß gegen verschiedene Vorschriften, insbesondere auch ein Steuervergehen im Sinne der Stromsteuer.&lt;br /&gt;
* Inbetriebnahme einer &amp;quot;großen&amp;quot; Solar-Dachanlage&lt;br /&gt;
&lt;br /&gt;
=== D0-Schnittstelle aktivieren ===&lt;br /&gt;
In Deutschland zeigt eine moderne Messeinrichtung i.d.R. nach dem Einbau lediglich den Zählerstand in kWh ohne Nachkommastelle an. Auch die optische D0-Schnittstelle ist entweder überhaupt nicht aktiviert, oder sendet lediglich diesen ungenauen Zählerstand. In Österreich ist die D0-Schnittstelle hingegen i.d.R. aktiviert, sendet aber verschlüsselt Daten aus. In Deutschland muss der Kunde die genaue Auflösung des Zählers erst per PIN aktivieren. Diese kann vom Messstellenbetreiber i.d.R. problemlos angefordert werden, und muss dann an der D0-Schnittstelle z.B. mit einer Taschenlampe &amp;quot;hineingemorsed&amp;quot; werden. Die Netzbetreiber stellen i.d.R. in Zusammenarbeit mit den Herstellern der Zähler hierfür Anleitungen bereit. Beispielhaft ein Video zur [https://www.youtube.com/watch?v=TonPnmOtBM0 ISKRA-Zählerfreischaltung].&lt;br /&gt;
&lt;br /&gt;
Ist &amp;quot;der Datenschutz&amp;quot; erst einmal &amp;quot;weggemorsed&amp;quot;, ergeben sich durch die direkte Anzeige des Live-Verbrauchs in Watt bereits Vorteile: Die Suche nach Standby-Verbrauchern kann unmittelbar am Stromzählerschrank über das Abschalten von Sicherungskreisen eingegrenzt werden.&lt;br /&gt;
&lt;br /&gt;
== Anbindungsoptionen an FHEM ==&lt;br /&gt;
Die Lösungen zum Auslesen beginnen bei der Befestigung einer Fotodiode mit Knetmasse oder Klebeband, einem Pullup-Widerstand und der direkten Verknüpfung mit GPIO-Ports eines Raspberry. &lt;br /&gt;
&amp;lt;ref&amp;gt;[https://wiki.volkszaehler.org/hardware/controllers/ir-schreib-lesekopf-pi-ausgang Einfachlösung von Volkszaehler.org]&amp;lt;/ref&amp;gt;&lt;br /&gt;
Da manche Zähler allerdings erst nach Senden einer Anforderung ihrerseits Daten versenden, ist für diese Zähler auch eine sendende IR-LED notwendig. Das erste Unterscheidungsmerkmal ist also &amp;quot;Nur Lesen&amp;quot; versus &amp;quot;Lesen / Schreiben&amp;quot;. Die weitere Unterscheidung ist insbesondere die computerseitige Schnittstelle:&lt;br /&gt;
* TTL-Ausgang zur Verbindung mit einem GPIO-Port z.B. eines ESP8266 (z.B. Wemos D1) oder einem Raspberry&lt;br /&gt;
* USB-Ausgang zur Verbindung mit einem USB-Port (z.B. am Raspberry)&lt;br /&gt;
* Kombigeräte mit direkt verbundenem ESP8266&lt;br /&gt;
* &amp;quot;poweropti&amp;quot; von Power 42 GmH (&amp;quot;powerfox&amp;quot;)&lt;br /&gt;
=== USB-IR-Köpfe ===&lt;br /&gt;
Generell ist für Nutzer ohne Lötkolbenerfahrung, die ihre FHEM-Hardware in USB-Entfernung zum Schaltschrank betreiben, der USB-Anschluss sicherlich die einfachste Möglichkeit. Neben Selbstbauanleitungen und 3D-Drucker-Files wie sie insbesondere vom Projekt [https://volkszaehler.org Volkszaehler.org] veröffentlicht wurden, gibt es hier auch zahlreiche Anbieter. Das reicht von Bastlern, die eine Überschussproduktion an Platinen fertig aufgebaut für unter 20 Euro anbieten &amp;lt;ref&amp;gt;https://wiki.volkszaehler.org/hardware/controllers/ir-schreib-lesekopf-usb-ausgang&amp;lt;/ref&amp;gt;, geht über professionelle ebay-Angebote z.B. der Verkäufer o_electronics_o und anderer Anbieter zwischen 20-25 Euro bis zum oft eingesetzten &amp;quot;Weidmann-Schreib/Lesekopf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Sofern am FHEM-Computer noch ein USB-Port frei ist und die Stromversorgung ausreicht, genügt hier hardwareseitig das Andocken des Lesekopfes mit dem Kabel nach unten zeigend und das Einstecken in einen freien USB-Port. Unter FHEM wird das Modul 47_OBIS.pm eingebunden.&lt;br /&gt;
&lt;br /&gt;
=== TTL-IR-Köpfe ===&lt;br /&gt;
Ist der &amp;quot;FHEM-Hauptcomputer&amp;quot; weiter vom Stromzähler entfernt (z.B. wegen eines angeschlossenen Displays oder mangelnder Reichweite angeschlossener Funklösungen in Zählerschranknähe), sind aber beim Stromzähler eine Steckdose und ausreichende WLAN-Abdeckung gegeben, so bietet sich ein TTL-Lesekopf in Verbindung mit einem ESP8266 als nicht ganz lötfreie, aber sparsame Lösung an. Hierbei kann zwischen folgenden Lösungen unterschieden werden:&lt;br /&gt;
* Der ESP8266 überträgt lediglich die Rohdaten der seriellen Schnittstelle per TCP zu FHEM. Eine vollständige Lösung (inkl. 3D-Drucker-Dateien) mit ESPEasy ist [https://mwinkler.jimdo.com/smarthome/aktoren-sensoren/stromz%C3%A4hler-digital/ hier] von Michael Winkler beschrieben. Auf FHEM-Seite dekodiert ebenfalls 47_OBIS.pm den Datenstrom&lt;br /&gt;
* Die SML-Dekodierung erfolgt auf dem ESP8266, und dieser liefert per MQTT die Daten an FHEM. Eine Lösung ist die Software [https://github.com/mruettgers/SMLReader SMLReader] von Michael Rüttgers, eine andere das [https://tasmota.github.io/docs/Smart-Meter-Interface/ SmartMeter-Interface von Tasmota]. &lt;br /&gt;
&lt;br /&gt;
=== Kombigeräte mit direkt verbundenem ESP8266 oder ESP32 ===&lt;br /&gt;
Eine fertige Lösung (IR-Lesekopf mit ESP8266 und Gehäuse) wird z.B. vom ebay-Verkäufer peterling11 vertrieben. Das Gerät kann nach Wunsch entweder direkt MQTT senden, oder es arbeitet über ser2net mit dem FHEM 47_OBIS-Modul zusammen. Der Vorteil in beiden Fällen: Der Stromzähler muss lediglich WLAN-Versorgung haben.&lt;br /&gt;
&lt;br /&gt;
Wer bei eBay oder Amazon nach Hichi sucht, findet weitere (fast) fertige Lösungen auf Tasmota-Basis (nicht nur Hichi). Benötigt wird nur noch ein USB-Netzteil. Je nach Stromzähler-Typ muss noch das passende Script von der [https://tasmota.github.io/docs/Smart-Meter-Interface/ Tasmota-Seite] eingespielt werden. Die Daten werden dann per MQTT an FHEM gesendet. An die V2 mit ESP32 können zusätzlich noch TTL-IR-Köpfe für weitere Zähler angeschlossen werden.&lt;br /&gt;
&lt;br /&gt;
=== poweropti ===&lt;br /&gt;
Der &amp;quot;poweropti&amp;quot; der power 42 GmbH ist eine Cloud-Lösung, die diverse Funktionen für den Endanwender in der Cloud bereitstellt. Das Gerät kommt Adaptern, Support und App und ist durchgängig auf Otto-Normal-Anwender ausgerichtet (Erklärvideos, QR-Codes scannen, App, u.s.w.). Der Hersteller stellt eine API bereit, die es u.a. erlaubt, die Parameter &amp;quot;aktuelle Watt-Zahl&amp;quot;, bezogene und gelieferte kWh mit einer Auflösung von 10 Sekunden auszulesen. Eine interne Schnittstelle im heimischen LAN ist wohl vorhanden, allerdings nicht dokumentiert. Daher müssen diese Werte per HTTPMOD aus der Cloud nach FHEM zurückgelesen werden. Die Einbindung in FHEM ist hier beschrieben: [[poweropti]].&lt;br /&gt;
&lt;br /&gt;
== Referenzen ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Z-Wave-Eurotronic_Spirit_Thermostat&amp;diff=39600</id>
		<title>Z-Wave-Eurotronic Spirit Thermostat</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Z-Wave-Eurotronic_Spirit_Thermostat&amp;diff=39600"/>
		<updated>2024-10-05T18:05:03Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* Features */  Link zum Handbuch eingefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Hardware&lt;br /&gt;
|Bild=platzHalter.png&lt;br /&gt;
|Bildbeschreibung=todo&lt;br /&gt;
|HWProtocol=Z-Wave Plus &lt;br /&gt;
|HWType=Aktor, Empfänger und Sender, Sensor&lt;br /&gt;
|HWCategory=Z-Wave&lt;br /&gt;
|HWComm=Funk 868MHz&lt;br /&gt;
|HWChannels=&lt;br /&gt;
|HWVoltage=3V&lt;br /&gt;
|HWPowerConsumption=&lt;br /&gt;
|HWPoweredBy=2xBatterie AA Mignon&lt;br /&gt;
|HWSize=&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#ZWave Z-Wave]&lt;br /&gt;
|HWManufacturer=[https://eurotronic.org/ EUROTRONIC Technology GmbH]&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Z-Wave-Eurotronic Spirit Thermostat]] ist ein Heizungsthermostat mit Z-Wave 500er-Serie-Chip und Z-Wave Plus-Zertifizierung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* [[Z-Wave#FLIRS-Ger.C3.A4te|FLiRS-Gerät]]&lt;br /&gt;
* siehe [https://eurotronic.org/wp-content/uploads/2024/06/bedienungsanleitung-spirit-z-wave-plus-de.pdf Handbuch]&lt;br /&gt;
&lt;br /&gt;
== Hinweise zum Betrieb mit FHEM ==&lt;br /&gt;
=== Inklusion === &lt;br /&gt;
Der Aktor wird bei der Inklusion und aktiviertem [[Autocreate|autocreate]] vollautomatisch erkannt und definiert.&lt;br /&gt;
&lt;br /&gt;
Eine beispielhafte durch autocreate erzeugte Definition mit Hinweisen zu manuellen Ergänzungen findet sich unter [[#Definition|Definition]].&lt;br /&gt;
&lt;br /&gt;
=== Assoziation ===&lt;br /&gt;
Der Controller muss zur korrekten Funktion in die Assoziationsgruppe 1 des Thermostats aufgenommen werden. Dies geschieht während der Inklusion durch FHEM automatisch durch Absetzen des folgenden Befehls:&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; associationAdd 1 &amp;lt;Controller-NodeID&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die erfolgreiche Ausführung des Befehls während der Inklusion durch Abfrage überprüfen:&lt;br /&gt;
:&amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; associationAll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
Konfigurationsanpassungen des Thermostates an eigene Wunschvorstellungen können anschließend vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
Abschließend ist es sinnvoll die Konfiguration zu Sicherungs- und Kontrollzwecken komplett abzurufen:&lt;br /&gt;
:&amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; configAll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Befehle zur Steuerung ===&lt;br /&gt;
{{Hinweis|Das Thermostat antwortet bei Einstellungen per Funk mit einem set-Befehl mit einem Ack-Telegramm über die vorgenommene Änderung, sendet aber keine explizite Änderung des Werts. Um die entsprechenden Readings aktuell zu halten und die erfolgreiche Übermittlung des set-Befehls zu kontrollieren kann bei ZWDongle als Interface das Attribut &#039;&#039;setReadingOnAck&#039;&#039; gesetzt werden. Dies hat allerdings den Nachteil, dass auch ungültige Befehle als ausgeführt angezeigt werden. Alternativ kann der zugehörige get-Befehl, der im Folgenden jeweils aufgeführt wird, verwendet werden, was aber zusätzlichen Funkverkehr erzeugt. Bei Änderungen über die Bedienung am Gerät wird FHEM hingegen per Telegramm über die vorgenommene Änderung informiert.}}&lt;br /&gt;
&lt;br /&gt;
==== Betriebsmodi ====&lt;br /&gt;
Die nachfolgende Tabelle enthält die Aktivierungsbefehle für alle Betriebsmodi des Thermostats. Weitere Modi (tmCooling, tmAuto, tmFan) werden vom Gerät -obwohl von FHEM angeboten- nicht unterstützt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Befehl!!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; tmOff&amp;lt;/code&amp;gt;||Aus-Modus: Aus mit Regelung auf 6°C als Frostschutz&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; tmHeating&amp;lt;/code&amp;gt;||Komfortmodus: Regelung entsprechend [[#Komfortmodus|Solltemperatur Komfortmodus]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; tmEnergySaveHeating&amp;lt;/code&amp;gt;||Absenkmodus: Regelung entsprechend [[#Absenkmodus|Solltemperatur Absenkmodus]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; tmFullPower&amp;lt;/code&amp;gt;||Boostmodus: schnellstmögliche Raumaufheizung für maximal 5 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; tmManual&amp;lt;/code&amp;gt;||Stellwertmodus (Manufacturer Specific): Ventilöffnung über Command Class SWITCH_MUTILEVEL einstellen&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Abfrage des eingestellten Betriebsmodus mit: &amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; thermostatMode&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Steuerungsbefehle der Command Class SWITCH_MUTILEVEL ausschließlich für den Stellwertmodus (tmManual):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Befehl im Stellwertmodus!!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; dim %&amp;lt;/code&amp;gt;|| Ventilöffnung von 0% bis 100%, wobei 99 = 100%&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on&amp;lt;/code&amp;gt;||letzten Ventilöffnungsgrad einstellen; sinnvoll beispielsweise nach Aus-Modus (tmOff)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; off&amp;lt;/code&amp;gt;||kleinstmögliche Ventilöffnung; entspricht 0%&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Im Stellwertmodus erfolgt keine automatische Temperaturregelung durch das Spirit, sondern diese muss durch separate Logik (beispielsweise mit Hilfe von [[PID20 - Der PID-Regler|PID20]]) überwacht und geregelt werden. &lt;br /&gt;
&lt;br /&gt;
Der Öffnungsstand wird mit &amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; swmStatus&amp;lt;/code&amp;gt; abgefragt. Zudem kann mit der Parameternummer 6 der Command Class CONFIGURATION der automatische Versand des Ventilöffnungsgrades bei bestimmten Veränderungen eingeschaltet werden (configValveOpeningPercentageReport).&lt;br /&gt;
&lt;br /&gt;
==== Solltemperaturen ====&lt;br /&gt;
Die Solltemperaturen in den Modi Komfortmodus (tmHeating) und Absenkmodus (tmEnergySaveHeating) lassen sich im Temperaturbereich 8°C bis 28 °C anpassen. Die Solltemperatur für den Absenkmodus lässt sich ausschließlich per Funk anpassen. Im Aus-Modus (tmOff) und Boostmodus (tmFullPower) ist keine Anpassung möglich.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung der Solltemperaturen erfolgt mit dem set-Befehl &amp;lt;code&amp;gt;thermostatSetpointSet&amp;lt;/code&amp;gt; oder dem funktionsgleichen set-Befehl &amp;lt;code&amp;gt;desired-temp&amp;lt;/code&amp;gt;. Der letzte Befehl wurde zur Angleichung an andere Module eingeführt und im folgenden genutzt.&lt;br /&gt;
&lt;br /&gt;
===== Komfortmodus =====&lt;br /&gt;
Die Solltemperatur auf NN.N °C wird mit folgendem Kurzbefehl eingestellt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; desired-temp NN.N&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies entspricht dem ausführlichen Befehl:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; desired-temp NN.N C 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die eingestellte Solltemperatur abrufen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; setpoint 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder mit dem Kurzbefehl&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; setpoint&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Absenkmodus =====&lt;br /&gt;
Die Solltemperatur auf NN.N °C wird mit folgendem Befehl eingestellt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; desired-temp NN.N C 11&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die eingestellte Solltemperatur abrufen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; setpoint 11&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Kindersicherung ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Befehl!!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; protectionOff&amp;lt;/code&amp;gt;||Ungeschützt - Bedienung am Gerät uneingeschränkt möglich&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; protectionSeq&amp;lt;/code&amp;gt;||Eingeschränkt - Bedienung am Gerät erst nach Entsperrung am Gerät (gleichzeitiges Drücken von {{Taste|+}} und {{Taste|-}} für 3 Sekunden)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; protectionOn&amp;lt;/code&amp;gt;||Deaktiviert - Bedienung am Gerät deaktiviert und Steuerung ausschließlich per Funk&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Abfrage der eingestellten Kindersicherung mit: &amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; protection&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Definition ===&lt;br /&gt;
Ein Beispiel für ein Spirit FHEM-Device enthält der nachfolgende exemplarische Auszug aus der [[Konfiguration]]:&lt;br /&gt;
 define ZWave_THERMOSTAT_53 ZWave e345c452 53&lt;br /&gt;
 attr ZWave_THERMOSTAT_53 IODev ZWDongle&lt;br /&gt;
 attr ZWave_THERMOSTAT_53 classes ZWAVEPLUS_INFO ASSOCIATION ASSOCIATION_GRP_INFO VERSION MANUFACTURER_SPECIFIC DEVICE_RESET_LOCALLY PROTECTION SENSOR_MULTILEVEL SWITCH_MULTILEVEL THERMOSTAT_MODE THERMOSTAT_SETPOINT BATTERY &lt;br /&gt;
 CONFIGURATION ALARM POWERLEVEL SECURITY SECURITY_S2 TRANSPORT_SERVICE SUPERVISION FIRMWARE_UPDATE_MD&lt;br /&gt;
 attr ZWave_THERMOSTAT_53 extendedAlarmReadings 1&lt;br /&gt;
 attr ZWave_THERMOSTAT_53 room ZWave&lt;br /&gt;
 attr ZWave_THERMOSTAT_53 stateFormat temperature&lt;br /&gt;
 attr ZWave_THERMOSTAT_53 vclasses ALARM:8 ASSOCIATION:2 ASSOCIATION_GRP_INFO:1 BATTERY:1 CONFIGURATION:1 DEVICE_RESET_LOCALLY:1 FIRMWARE_UPDATE_MD:3 MANUFACTURER_SPECIFIC:1 POWERLEVEL:1 PROTECTION:1 SECURITY:1 SECURITY_S2:1 &lt;br /&gt;
 SENSOR_MULTILEVEL:5 SUPERVISION:1 SWITCH_MULTILEVEL:1 THERMOSTAT_MODE:3 THERMOSTAT_SETPOINT:3 TRANSPORT_SERVICE:2 VERSION:2 ZWAVEPLUS_INFO:2&lt;br /&gt;
Im vorstehenden Beispiel wurde manuell das Attribut &amp;lt;code&amp;gt;extendedAlarmReadings&amp;lt;/code&amp;gt; auf &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; gesetzt, damit für die diversen Alarmarten einfacher unterscheidbare Events erzeugt und separate Readings angelegt werden. Zudem wurde manuell das Attribut &amp;lt;code&amp;gt;stateFormat&amp;lt;/code&amp;gt; angelegt. Sämliche anderen Angaben der Defintion nebst Attributen wurden von FHEM bei der Inklusion automatisch durch autocreate angelegt.&lt;br /&gt;
&lt;br /&gt;
=== Logbeispiel ===&lt;br /&gt;
 2018-10-19_18:04:14 ZWave_THERMOSTAT_53 setpointTemp: 18.0 C energySaveHeating&lt;br /&gt;
 2018-10-19_18:04:34 ZWave_THERMOSTAT_53 setpointTemp: 22.0 C heating&lt;br /&gt;
 2018-10-19_18:04:54 ZWave_THERMOSTAT_53 thermostatMode: heating&lt;br /&gt;
 2018-10-19_18:05:03 ZWave_THERMOSTAT_53 thermostatSetpointSupported: heating energySaveHeating&lt;br /&gt;
 2018-10-19_18:05:13 ZWave_THERMOSTAT_53 version: Lib 3 Prot 4.61 App 0.16 HW 49 FWCounter 1 FW 0.10&lt;br /&gt;
 2018-10-19_18:05:24 ZWave_THERMOSTAT_53 zwavePlusInfo:  version:01 role:SleepingListeningSlave node:Z-Wave+Node installerIcon:1200 userIcon:1200&lt;br /&gt;
 2018-10-19_18:06:32 ZWave_THERMOSTAT_53 alarm_System: Event cleared: unknown event 0, notificationIsOn&lt;br /&gt;
 2018-10-19_18:08:02 ZWave_THERMOSTAT_53 battery: 100 %&lt;br /&gt;
 2018-10-19_18:08:02 ZWave_THERMOSTAT_53 batteryState: ok&lt;br /&gt;
 2018-10-19_18:08:02 ZWave_THERMOSTAT_53 batteryPercent: 100&lt;br /&gt;
 2018-10-19_18:10:10 ZWave_THERMOSTAT_53 temperature: 23.27 C&lt;br /&gt;
 2018-10-19_18:18:10 ZWave_THERMOSTAT_53 temperature: 22.73 C&lt;br /&gt;
 2018-10-19_18:30:10 ZWave_THERMOSTAT_53 temperature: 22.29 C&lt;br /&gt;
 2018-10-19_19:00:17 ZWave_THERMOSTAT_53 thermostatMode: energySaveHeating&lt;br /&gt;
 2018-10-19_19:00:55 ZWave_THERMOSTAT_53 thermostatMode: off&lt;br /&gt;
 2018-10-19_19:06:10 ZWave_THERMOSTAT_53 temperature: 21.75 C&lt;br /&gt;
 2018-10-19_23:22:18 ZWave_THERMOSTAT_53 thermostatMode: energySaveHeating&lt;br /&gt;
 2018-10-19_23:27:31 ZWave_THERMOSTAT_53 set_tmHeating&lt;br /&gt;
 2018-10-19_23:27:32 ZWave_THERMOSTAT_53 tmHeating&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://products.z-wavealliance.org/products/2543 Eintrag in http://products.z-wavealliance.org mit Handbuch und mehr]&lt;br /&gt;
* [https://eurotronic.org/wp-content/uploads/2024/06/bedienungsanleitung-spirit-z-wave-plus-de.pdf deutsches Handbuch auf Hersteller-Webseite]&lt;br /&gt;
* Nutzung eines direkt assozierten Fenstersensors zur Fenster-Offen-Erkennung: {{Link2Forum|Topic=92206}}&lt;br /&gt;
* setList-Attribut: {{Link2Forum|Topic=112955|Message=1092262|LinkText=Temperaturwerte eines Nicht-ZWave-Gerätes an das Spirit zur Regelung übermitteln}} ({{Link2Forum|Topic=77598|Message=701397|LinkText=bisheriger Hack}})&lt;br /&gt;
* {{Link2Forum|Topic=77598|Message=854445|LinkText=Nutzung des Modul PID20 zur Temperaturregelung im Stellwertmodus (tmManual)}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Z-Wave Components|Sensor]]&lt;br /&gt;
[[Kategorie:Heizungsventile]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Z-Wave-Eurotronic_Spirit_Thermostat&amp;diff=39599</id>
		<title>Z-Wave-Eurotronic Spirit Thermostat</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Z-Wave-Eurotronic_Spirit_Thermostat&amp;diff=39599"/>
		<updated>2024-10-05T18:02:48Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Link zur Bedienungsanleitung aktualisiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Hardware&lt;br /&gt;
|Bild=platzHalter.png&lt;br /&gt;
|Bildbeschreibung=todo&lt;br /&gt;
|HWProtocol=Z-Wave Plus &lt;br /&gt;
|HWType=Aktor, Empfänger und Sender, Sensor&lt;br /&gt;
|HWCategory=Z-Wave&lt;br /&gt;
|HWComm=Funk 868MHz&lt;br /&gt;
|HWChannels=&lt;br /&gt;
|HWVoltage=3V&lt;br /&gt;
|HWPowerConsumption=&lt;br /&gt;
|HWPoweredBy=2xBatterie AA Mignon&lt;br /&gt;
|HWSize=&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#ZWave Z-Wave]&lt;br /&gt;
|HWManufacturer=[https://eurotronic.org/ EUROTRONIC Technology GmbH]&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Z-Wave-Eurotronic Spirit Thermostat]] ist ein Heizungsthermostat mit Z-Wave 500er-Serie-Chip und Z-Wave Plus-Zertifizierung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* [[Z-Wave#FLIRS-Ger.C3.A4te|FLiRS-Gerät]]&lt;br /&gt;
* siehe Handbuch&lt;br /&gt;
&lt;br /&gt;
== Hinweise zum Betrieb mit FHEM ==&lt;br /&gt;
=== Inklusion === &lt;br /&gt;
Der Aktor wird bei der Inklusion und aktiviertem [[Autocreate|autocreate]] vollautomatisch erkannt und definiert.&lt;br /&gt;
&lt;br /&gt;
Eine beispielhafte durch autocreate erzeugte Definition mit Hinweisen zu manuellen Ergänzungen findet sich unter [[#Definition|Definition]].&lt;br /&gt;
&lt;br /&gt;
=== Assoziation ===&lt;br /&gt;
Der Controller muss zur korrekten Funktion in die Assoziationsgruppe 1 des Thermostats aufgenommen werden. Dies geschieht während der Inklusion durch FHEM automatisch durch Absetzen des folgenden Befehls:&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; associationAdd 1 &amp;lt;Controller-NodeID&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die erfolgreiche Ausführung des Befehls während der Inklusion durch Abfrage überprüfen:&lt;br /&gt;
:&amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; associationAll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
Konfigurationsanpassungen des Thermostates an eigene Wunschvorstellungen können anschließend vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
Abschließend ist es sinnvoll die Konfiguration zu Sicherungs- und Kontrollzwecken komplett abzurufen:&lt;br /&gt;
:&amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; configAll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Befehle zur Steuerung ===&lt;br /&gt;
{{Hinweis|Das Thermostat antwortet bei Einstellungen per Funk mit einem set-Befehl mit einem Ack-Telegramm über die vorgenommene Änderung, sendet aber keine explizite Änderung des Werts. Um die entsprechenden Readings aktuell zu halten und die erfolgreiche Übermittlung des set-Befehls zu kontrollieren kann bei ZWDongle als Interface das Attribut &#039;&#039;setReadingOnAck&#039;&#039; gesetzt werden. Dies hat allerdings den Nachteil, dass auch ungültige Befehle als ausgeführt angezeigt werden. Alternativ kann der zugehörige get-Befehl, der im Folgenden jeweils aufgeführt wird, verwendet werden, was aber zusätzlichen Funkverkehr erzeugt. Bei Änderungen über die Bedienung am Gerät wird FHEM hingegen per Telegramm über die vorgenommene Änderung informiert.}}&lt;br /&gt;
&lt;br /&gt;
==== Betriebsmodi ====&lt;br /&gt;
Die nachfolgende Tabelle enthält die Aktivierungsbefehle für alle Betriebsmodi des Thermostats. Weitere Modi (tmCooling, tmAuto, tmFan) werden vom Gerät -obwohl von FHEM angeboten- nicht unterstützt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Befehl!!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; tmOff&amp;lt;/code&amp;gt;||Aus-Modus: Aus mit Regelung auf 6°C als Frostschutz&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; tmHeating&amp;lt;/code&amp;gt;||Komfortmodus: Regelung entsprechend [[#Komfortmodus|Solltemperatur Komfortmodus]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; tmEnergySaveHeating&amp;lt;/code&amp;gt;||Absenkmodus: Regelung entsprechend [[#Absenkmodus|Solltemperatur Absenkmodus]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; tmFullPower&amp;lt;/code&amp;gt;||Boostmodus: schnellstmögliche Raumaufheizung für maximal 5 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; tmManual&amp;lt;/code&amp;gt;||Stellwertmodus (Manufacturer Specific): Ventilöffnung über Command Class SWITCH_MUTILEVEL einstellen&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Abfrage des eingestellten Betriebsmodus mit: &amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; thermostatMode&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Steuerungsbefehle der Command Class SWITCH_MUTILEVEL ausschließlich für den Stellwertmodus (tmManual):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Befehl im Stellwertmodus!!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; dim %&amp;lt;/code&amp;gt;|| Ventilöffnung von 0% bis 100%, wobei 99 = 100%&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on&amp;lt;/code&amp;gt;||letzten Ventilöffnungsgrad einstellen; sinnvoll beispielsweise nach Aus-Modus (tmOff)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; off&amp;lt;/code&amp;gt;||kleinstmögliche Ventilöffnung; entspricht 0%&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Im Stellwertmodus erfolgt keine automatische Temperaturregelung durch das Spirit, sondern diese muss durch separate Logik (beispielsweise mit Hilfe von [[PID20 - Der PID-Regler|PID20]]) überwacht und geregelt werden. &lt;br /&gt;
&lt;br /&gt;
Der Öffnungsstand wird mit &amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; swmStatus&amp;lt;/code&amp;gt; abgefragt. Zudem kann mit der Parameternummer 6 der Command Class CONFIGURATION der automatische Versand des Ventilöffnungsgrades bei bestimmten Veränderungen eingeschaltet werden (configValveOpeningPercentageReport).&lt;br /&gt;
&lt;br /&gt;
==== Solltemperaturen ====&lt;br /&gt;
Die Solltemperaturen in den Modi Komfortmodus (tmHeating) und Absenkmodus (tmEnergySaveHeating) lassen sich im Temperaturbereich 8°C bis 28 °C anpassen. Die Solltemperatur für den Absenkmodus lässt sich ausschließlich per Funk anpassen. Im Aus-Modus (tmOff) und Boostmodus (tmFullPower) ist keine Anpassung möglich.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung der Solltemperaturen erfolgt mit dem set-Befehl &amp;lt;code&amp;gt;thermostatSetpointSet&amp;lt;/code&amp;gt; oder dem funktionsgleichen set-Befehl &amp;lt;code&amp;gt;desired-temp&amp;lt;/code&amp;gt;. Der letzte Befehl wurde zur Angleichung an andere Module eingeführt und im folgenden genutzt.&lt;br /&gt;
&lt;br /&gt;
===== Komfortmodus =====&lt;br /&gt;
Die Solltemperatur auf NN.N °C wird mit folgendem Kurzbefehl eingestellt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; desired-temp NN.N&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies entspricht dem ausführlichen Befehl:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; desired-temp NN.N C 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die eingestellte Solltemperatur abrufen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; setpoint 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder mit dem Kurzbefehl&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; setpoint&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Absenkmodus =====&lt;br /&gt;
Die Solltemperatur auf NN.N °C wird mit folgendem Befehl eingestellt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; desired-temp NN.N C 11&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die eingestellte Solltemperatur abrufen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; setpoint 11&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Kindersicherung ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Befehl!!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; protectionOff&amp;lt;/code&amp;gt;||Ungeschützt - Bedienung am Gerät uneingeschränkt möglich&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; protectionSeq&amp;lt;/code&amp;gt;||Eingeschränkt - Bedienung am Gerät erst nach Entsperrung am Gerät (gleichzeitiges Drücken von {{Taste|+}} und {{Taste|-}} für 3 Sekunden)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; protectionOn&amp;lt;/code&amp;gt;||Deaktiviert - Bedienung am Gerät deaktiviert und Steuerung ausschließlich per Funk&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Abfrage der eingestellten Kindersicherung mit: &amp;lt;code&amp;gt;get &amp;lt;device&amp;gt; protection&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Definition ===&lt;br /&gt;
Ein Beispiel für ein Spirit FHEM-Device enthält der nachfolgende exemplarische Auszug aus der [[Konfiguration]]:&lt;br /&gt;
 define ZWave_THERMOSTAT_53 ZWave e345c452 53&lt;br /&gt;
 attr ZWave_THERMOSTAT_53 IODev ZWDongle&lt;br /&gt;
 attr ZWave_THERMOSTAT_53 classes ZWAVEPLUS_INFO ASSOCIATION ASSOCIATION_GRP_INFO VERSION MANUFACTURER_SPECIFIC DEVICE_RESET_LOCALLY PROTECTION SENSOR_MULTILEVEL SWITCH_MULTILEVEL THERMOSTAT_MODE THERMOSTAT_SETPOINT BATTERY &lt;br /&gt;
 CONFIGURATION ALARM POWERLEVEL SECURITY SECURITY_S2 TRANSPORT_SERVICE SUPERVISION FIRMWARE_UPDATE_MD&lt;br /&gt;
 attr ZWave_THERMOSTAT_53 extendedAlarmReadings 1&lt;br /&gt;
 attr ZWave_THERMOSTAT_53 room ZWave&lt;br /&gt;
 attr ZWave_THERMOSTAT_53 stateFormat temperature&lt;br /&gt;
 attr ZWave_THERMOSTAT_53 vclasses ALARM:8 ASSOCIATION:2 ASSOCIATION_GRP_INFO:1 BATTERY:1 CONFIGURATION:1 DEVICE_RESET_LOCALLY:1 FIRMWARE_UPDATE_MD:3 MANUFACTURER_SPECIFIC:1 POWERLEVEL:1 PROTECTION:1 SECURITY:1 SECURITY_S2:1 &lt;br /&gt;
 SENSOR_MULTILEVEL:5 SUPERVISION:1 SWITCH_MULTILEVEL:1 THERMOSTAT_MODE:3 THERMOSTAT_SETPOINT:3 TRANSPORT_SERVICE:2 VERSION:2 ZWAVEPLUS_INFO:2&lt;br /&gt;
Im vorstehenden Beispiel wurde manuell das Attribut &amp;lt;code&amp;gt;extendedAlarmReadings&amp;lt;/code&amp;gt; auf &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; gesetzt, damit für die diversen Alarmarten einfacher unterscheidbare Events erzeugt und separate Readings angelegt werden. Zudem wurde manuell das Attribut &amp;lt;code&amp;gt;stateFormat&amp;lt;/code&amp;gt; angelegt. Sämliche anderen Angaben der Defintion nebst Attributen wurden von FHEM bei der Inklusion automatisch durch autocreate angelegt.&lt;br /&gt;
&lt;br /&gt;
=== Logbeispiel ===&lt;br /&gt;
 2018-10-19_18:04:14 ZWave_THERMOSTAT_53 setpointTemp: 18.0 C energySaveHeating&lt;br /&gt;
 2018-10-19_18:04:34 ZWave_THERMOSTAT_53 setpointTemp: 22.0 C heating&lt;br /&gt;
 2018-10-19_18:04:54 ZWave_THERMOSTAT_53 thermostatMode: heating&lt;br /&gt;
 2018-10-19_18:05:03 ZWave_THERMOSTAT_53 thermostatSetpointSupported: heating energySaveHeating&lt;br /&gt;
 2018-10-19_18:05:13 ZWave_THERMOSTAT_53 version: Lib 3 Prot 4.61 App 0.16 HW 49 FWCounter 1 FW 0.10&lt;br /&gt;
 2018-10-19_18:05:24 ZWave_THERMOSTAT_53 zwavePlusInfo:  version:01 role:SleepingListeningSlave node:Z-Wave+Node installerIcon:1200 userIcon:1200&lt;br /&gt;
 2018-10-19_18:06:32 ZWave_THERMOSTAT_53 alarm_System: Event cleared: unknown event 0, notificationIsOn&lt;br /&gt;
 2018-10-19_18:08:02 ZWave_THERMOSTAT_53 battery: 100 %&lt;br /&gt;
 2018-10-19_18:08:02 ZWave_THERMOSTAT_53 batteryState: ok&lt;br /&gt;
 2018-10-19_18:08:02 ZWave_THERMOSTAT_53 batteryPercent: 100&lt;br /&gt;
 2018-10-19_18:10:10 ZWave_THERMOSTAT_53 temperature: 23.27 C&lt;br /&gt;
 2018-10-19_18:18:10 ZWave_THERMOSTAT_53 temperature: 22.73 C&lt;br /&gt;
 2018-10-19_18:30:10 ZWave_THERMOSTAT_53 temperature: 22.29 C&lt;br /&gt;
 2018-10-19_19:00:17 ZWave_THERMOSTAT_53 thermostatMode: energySaveHeating&lt;br /&gt;
 2018-10-19_19:00:55 ZWave_THERMOSTAT_53 thermostatMode: off&lt;br /&gt;
 2018-10-19_19:06:10 ZWave_THERMOSTAT_53 temperature: 21.75 C&lt;br /&gt;
 2018-10-19_23:22:18 ZWave_THERMOSTAT_53 thermostatMode: energySaveHeating&lt;br /&gt;
 2018-10-19_23:27:31 ZWave_THERMOSTAT_53 set_tmHeating&lt;br /&gt;
 2018-10-19_23:27:32 ZWave_THERMOSTAT_53 tmHeating&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://products.z-wavealliance.org/products/2543 Eintrag in http://products.z-wavealliance.org mit Handbuch und mehr]&lt;br /&gt;
* [https://eurotronic.org/wp-content/uploads/2024/06/bedienungsanleitung-spirit-z-wave-plus-de.pdf deutsches Handbuch auf Hersteller-Webseite]&lt;br /&gt;
* Nutzung eines direkt assozierten Fenstersensors zur Fenster-Offen-Erkennung: {{Link2Forum|Topic=92206}}&lt;br /&gt;
* setList-Attribut: {{Link2Forum|Topic=112955|Message=1092262|LinkText=Temperaturwerte eines Nicht-ZWave-Gerätes an das Spirit zur Regelung übermitteln}} ({{Link2Forum|Topic=77598|Message=701397|LinkText=bisheriger Hack}})&lt;br /&gt;
* {{Link2Forum|Topic=77598|Message=854445|LinkText=Nutzung des Modul PID20 zur Temperaturregelung im Stellwertmodus (tmManual)}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Z-Wave Components|Sensor]]&lt;br /&gt;
[[Kategorie:Heizungsventile]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Gleitende_Mittelwerte_berechnen_und_loggen&amp;diff=39544</id>
		<title>Gleitende Mittelwerte berechnen und loggen</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Gleitende_Mittelwerte_berechnen_und_loggen&amp;diff=39544"/>
		<updated>2024-08-09T17:03:01Z</updated>

		<summary type="html">&lt;p&gt;F Klee: HTML-Sonderzeichen ersetzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Für verschiedene Wettersensoren ist es oftmals wünschenswert, gleitende Mittelwerte (fälschlich auch als &amp;quot;relative&amp;quot; Mittelwerte bezeichnet) über ein bestimmtes Zeitfenster auszugeben oder in den Logs zu speichern und zu plotten. Beispiele:&lt;br /&gt;
* Die momentanen Winddaten eines KS300 sind oft stark schwankend. Hier wäre ein Mittelwert z.B. der letzten 2-3 Stunden interessant. &lt;br /&gt;
* Für die Außentemperatur ist anhand eines Mittelwertes der letzten 24 Stunden evtl. ein gewisser Trend der generellen Entwicklung der Temperatur ableitbar.&lt;br /&gt;
&lt;br /&gt;
Mit Modulen wie &#039;&#039;rain&#039;&#039; oder &#039;&#039;average&#039;&#039; ist konzeptbedingt nur ein Mittelwert von fixen Zeiträumen (aktueller Tag, Monat, etc.) möglich. &lt;br /&gt;
&lt;br /&gt;
Im Nachfolgenden werden deshalb zwei Programme vorgestellt, die solche gleitenden Mittelwerte bereitstellen. Beide Programme werden in die Datei [[99 myUtils anlegen|99_MyUtils.pm]] eingetragen und dann von FHEM aufgerufen. Das erste Programm macht dies für beliebige Readings beliebiger Devices, das zweite Programm greift auf beliebige [[FileLog|File-]] oder [[DbLog|DbLogs]] zurück.&lt;br /&gt;
&lt;br /&gt;
== Gleitender Mittelwert für beliebige Readings ==&lt;br /&gt;
=== Subroutine movingAverage in 99_MyUtils anlegen ===&lt;br /&gt;
Es werden die Funktionen &#039;&#039;movingAverage&#039;&#039; und &#039;&#039;movingAverageT&#039;&#039; in die 99_MyUtils Datei übernommen werden. Wenn noch nicht vorhanden, sollte die Datei dann so aussehen, der übliche Speicherort ist &#039;&#039;/opt/fhem/FHEM/99_MyUtils.pm&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;package main;&lt;br /&gt;
  use strict;&lt;br /&gt;
  use warnings;&lt;br /&gt;
  sub&lt;br /&gt;
  MyUtils_Initialize($$)&lt;br /&gt;
  {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
  }&lt;br /&gt;
  ###############################################################################&lt;br /&gt;
  #&lt;br /&gt;
  #  Moving average &lt;br /&gt;
  #&lt;br /&gt;
  #  Aufruf: movingAverage(devicename,readingname,zeitspanne in s)&lt;br /&gt;
  #&lt;br /&gt;
  ###############################################################################&lt;br /&gt;
  &lt;br /&gt;
  sub movingAverage($$$){&lt;br /&gt;
     my ($name,$reading,$avtime) = @_;&lt;br /&gt;
     my $hash = $defs{$name};&lt;br /&gt;
     my @new = my ($val,$time) = ($hash-&amp;gt;{READINGS}{$reading}{VAL},$hash-&amp;gt;{READINGS}{$reading}{TIME});&lt;br /&gt;
     my ($cyear, $cmonth, $cday, $chour, $cmin, $csec) = $time =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/;&lt;br /&gt;
     my $ctime = $csec+60*$cmin+3600*$chour;&lt;br /&gt;
     my $num;&lt;br /&gt;
     my $arr;&lt;br /&gt;
     #-- initialize if requested&lt;br /&gt;
     if( ($avtime eq &amp;quot;-1&amp;quot;) ){&lt;br /&gt;
       $hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}=undef;&lt;br /&gt;
     }&lt;br /&gt;
     #-- test for existence&lt;br /&gt;
     if( !$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}){&lt;br /&gt;
        #Log 1,&amp;quot;ARRAY CREATED&amp;quot;;&lt;br /&gt;
        push(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}},\@new);&lt;br /&gt;
        $num = 1;&lt;br /&gt;
        $arr=\@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}};&lt;br /&gt;
     } else {&lt;br /&gt;
        $num = int(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}});&lt;br /&gt;
        $arr=\@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}};&lt;br /&gt;
        my $starttime = $arr-&amp;gt;[0][1];&lt;br /&gt;
        my ($syear, $smonth, $sday, $shour, $smin, $ssec) = $starttime =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/;&lt;br /&gt;
        my $stime = $ssec+60*$smin+3600*$shour;&lt;br /&gt;
        #-- correct for daybreak&lt;br /&gt;
        $stime-=86400 &lt;br /&gt;
          if( $stime &amp;gt; $ctime);&lt;br /&gt;
        if( ($num &amp;lt; 25)&amp;amp;&amp;amp;( ($ctime-$stime)&amp;lt;$avtime) ){&lt;br /&gt;
          #Log 1,&amp;quot;ARRAY has $num elements, adding another one&amp;quot;;&lt;br /&gt;
          push(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}},\@new);&lt;br /&gt;
        }else{&lt;br /&gt;
          shift(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}});&lt;br /&gt;
          push(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}},\@new);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      #-- output and average&lt;br /&gt;
      my $average = 0;&lt;br /&gt;
      for(my $i=0;$i&amp;lt;$num;$i++){&lt;br /&gt;
        $average+=$arr-&amp;gt;[$i][0];&lt;br /&gt;
        Log 4,&amp;quot;[$name moving average] Value = &amp;quot;.$arr-&amp;gt;[$i][0].&amp;quot; Time = &amp;quot;.$arr-&amp;gt;[$i][1]; &lt;br /&gt;
      }&lt;br /&gt;
      $average=sprintf( &amp;quot;%5.3f&amp;quot;, $average/$num);&lt;br /&gt;
      #--average&lt;br /&gt;
      Log 4,&amp;quot;[$name moving average] calculated over $num values is $average&amp;quot;;  &lt;br /&gt;
      return $average;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  ###############################################################################&lt;br /&gt;
  #&lt;br /&gt;
  #  Moving average of last X seconds, weigh values by time&lt;br /&gt;
  #&lt;br /&gt;
  #  movingAverageT(Devicename, Readingname, HistoryLength)&lt;br /&gt;
  #&lt;br /&gt;
  ###############################################################################&lt;br /&gt;
  sub movingAverageT($$$){&lt;br /&gt;
    my ($name, $reading, $hSeconds) = @_;&lt;br /&gt;
    my $hash = $defs{$name};&lt;br /&gt;
    my @new = my ($val, $time) = ($hash-&amp;gt;{READINGS}{$reading}{VAL}, $hash-&amp;gt;{READINGS}{$reading}{TIME});&lt;br /&gt;
    &lt;br /&gt;
    #create new hash &amp;quot;history&amp;quot; if not already existing&lt;br /&gt;
    if ( !$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}) {&lt;br /&gt;
      @{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}} = \@new;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    #get reference to hash &amp;quot;history&amp;quot;&lt;br /&gt;
    my $arr = \@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}};&lt;br /&gt;
&lt;br /&gt;
    #just add values if timestamp differs to last item in history&lt;br /&gt;
    if( &amp;quot;$time&amp;quot; ne &amp;quot;$arr-&amp;gt;[-1][1]&amp;quot; ) {&lt;br /&gt;
      #append the new entry&lt;br /&gt;
      push(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}}, \@new);&lt;br /&gt;
      &lt;br /&gt;
      #remove entries that are too old&lt;br /&gt;
      while( time() - time_str2num((\@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}})-&amp;gt;[0][1]) &amp;gt; $hSeconds ) {&lt;br /&gt;
        #Log 1,&amp;quot;[$name:$reading] removing reading, it is too old&amp;quot;;&lt;br /&gt;
        shift(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}});&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    #length of current history&lt;br /&gt;
    my $aLength = int(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}});&lt;br /&gt;
    &lt;br /&gt;
    #if history currently consists of a single value, just return it&lt;br /&gt;
    if ($aLength &amp;lt;= 1) {&lt;br /&gt;
      #Log 1,&amp;quot;[$name:$reading] Average of a single value is the single value: $val&amp;quot;;&lt;br /&gt;
      return sprintf(&amp;quot;%5.3f&amp;quot;, $val);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    #sum up all values multiplied with fraction of duration, a value that was valid longer weighs more&lt;br /&gt;
    my $average = 0;&lt;br /&gt;
    my $oldest = $arr-&amp;gt;[0][1];&lt;br /&gt;
    my $newest = $arr-&amp;gt;[-1][1];&lt;br /&gt;
    #Log 1,&amp;quot;[$name:$reading] Oldest Timestamp = &amp;quot;.$oldest.&amp;quot;, Newest Timestamp: &amp;quot;.$newest;&lt;br /&gt;
&lt;br /&gt;
    $oldest = time_str2num($oldest);&lt;br /&gt;
    $newest = time_str2num($newest);&lt;br /&gt;
    my $timespan = $newest - $oldest;&lt;br /&gt;
    #Log 1,&amp;quot;[$name:$reading] Total Timespan: &amp;quot;.$timespan;&lt;br /&gt;
    &lt;br /&gt;
    #iterate of the array from index 0 to N-1&lt;br /&gt;
    for(my $i=0; $i&amp;lt;$aLength-1; $i++){&lt;br /&gt;
      #Log 1,&amp;quot;[$name:$reading] Index: $i, Value = &amp;quot;.$arr-&amp;gt;[$i][0].&amp;quot; Time = &amp;quot;.$arr-&amp;gt;[$i][1];&lt;br /&gt;
     &lt;br /&gt;
      my $thisTime = time_str2num($arr-&amp;gt;[$i][1]);&lt;br /&gt;
      my $nextTime = time_str2num($arr-&amp;gt;[$i+1][1]);&lt;br /&gt;
      my $diffTime = $nextTime - $thisTime;&lt;br /&gt;
      my $fraction = $diffTime / $timespan;&lt;br /&gt;
      &lt;br /&gt;
      #Log 1,&amp;quot;[$name:$reading] diffTime = $diffTime, Fraction: $fraction&amp;quot;;&lt;br /&gt;
      &lt;br /&gt;
      $average += $arr-&amp;gt;[$i][0] * $fraction;&lt;br /&gt;
    }&lt;br /&gt;
    #Log 1,&amp;quot;[$name:$reading] Average: $average&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    return sprintf(&amp;quot;%5.3f&amp;quot;, $average);;&lt;br /&gt;
  }&lt;br /&gt;
    &lt;br /&gt;
  1;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Funktion movingAverage() aufrufen und nutzen ===&lt;br /&gt;
Bei jedem Aufruf schiebt die obige Funktion den gegenwärtigen Wert sowie den Zeitpunkt eines Readings (zweiter Parameter) ans Ende eines Arrays (maximal 25 Einträge) und wirft dafür den ersten Eintrag heraus. Die Anzahl der Einträge im Array wird so gewählt, dass die Zeitpunkte der Readings größer oder gleich der gewünschten Zeitspanne für die Mittelung sind. Über diese Werte wird dann gemittelt und der Wert zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
Zur Anwendung empfiehlt sich, dem gewünschten Device ein userReading zu geben:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr devicename userReadings readingname.av {movingAverage(&amp;quot;devicename&amp;quot;,&amp;quot;readingname&amp;quot;,zeitspanne)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieses wird dann automatisch bei jedem neuen Wert des Readings mit dem neuen gleitenden Mittelwert über die vergangene Zeitspanne gefüllt.&lt;br /&gt;
&lt;br /&gt;
Beispiel: Das Reading &amp;quot;pressure&amp;quot; des Devices &amp;quot;A.OWB&amp;quot; wird alle 5 Minuten aktualisiert. Das Device bekommt nun ein userReading:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr A.OWB userReadings pressure.av {movingAverage(&amp;quot;A.OWB&amp;quot;,&amp;quot;pressure&amp;quot;,1800)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieses schreibt bei jeder Aktualisierung von &amp;quot;pressure&amp;quot; einen neuen Eintrag in sein Array - allerdings maximal sechs Werte, dann wird immer der älteste Eintrag gelöscht. Damit ist sichergestellt, dass diese mindestens 1800 Sekunden abdecken - also sechs Einträge.&lt;br /&gt;
&lt;br /&gt;
=== Funktion movingAverageT() aufrufen und nutzen ===&lt;br /&gt;
Bei jedem Aufruf schiebt die Funktion &#039;&#039;movingAverageT&#039;&#039; den gegenwärtigen Wert sowie den Zeitpunkt eines Readings (zweiter Parameter) ans Ende eines Arrays und verwirft Einträge die älter als das Zeitlimit aus dem dritten Parameter sind. Die Anzahl der Einträge im Array ist nicht limitiert und es wird nur anhand des Zeitstempels entschieden, ob ein Wert im Array verbleibt. Über die Werte im Array wird dann gemittelt und der Wert zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
Zur Anwendung empfiehlt sich, dem gewünschten Device ein userReading zu geben:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr devicename userReadings readingname.av {movingAverageT(&amp;quot;devicename&amp;quot;, &amp;quot;readingname&amp;quot;, Zeitspanne_in_Sekunden)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieses wird dann automatisch bei jedem neuen Wert des Readings mit dem neuen gleitenden Mittelwert über die vergangene Zeitspanne gefüllt.&lt;br /&gt;
&lt;br /&gt;
Beispiel: Das Reading &amp;quot;pressure&amp;quot; des Devices &amp;quot;A.OWB&amp;quot; wird alle 5 Minuten aktualisiert. Das Device bekommt nun ein userReading:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr A.OWB userReadings pressure.av {movingAverageT(&amp;quot;A.OWB&amp;quot;, &amp;quot;pressure&amp;quot;, 1800)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieses schreibt bei jeder Aktualisierung von &amp;quot;pressure&amp;quot; einen neuen Eintrag an das ende seines Array und löscht zu alte Werte am Anfang des Array wieder heraus.&lt;br /&gt;
&lt;br /&gt;
== Gleitender Mittelwert aus Log-Dateien ==&lt;br /&gt;
=== Subroutine myAverage() in 99_MyUtils anlegen ===&lt;br /&gt;
Zuerst muss die Subroutine myAverage in die 99_MyUtils übernommen werden. Wenn noch nicht vorhanden, sollte die Datei dann so aussehen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
 package main;&lt;br /&gt;
  use strict;&lt;br /&gt;
  use warnings;&lt;br /&gt;
  sub&lt;br /&gt;
  MyUtils_Initialize($$)&lt;br /&gt;
  {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
  }&lt;br /&gt;
  ##########################################################&lt;br /&gt;
  # myAverage&lt;br /&gt;
  # berechnet den Mittelwert aus LogFiles über einen beliebigen Zeitraum&lt;br /&gt;
  # Args: $offset = Offset in Sekunden&lt;br /&gt;
  #		$logfile = LogFile, z.B. DbLog Device&lt;br /&gt;
  #     $cspec = column-spec, z.B. 4:temp:: (4.Spalte, Zeile enthält temp)&lt;br /&gt;
sub myAverage($$$) {&lt;br /&gt;
   my ($offset,$logfile,$cspec) = @_;&lt;br /&gt;
   my $period_s = strftime &amp;quot;%Y-%m-%d\x5f%H:%M:%S&amp;quot;, localtime(time-$offset);&lt;br /&gt;
   my $period_e = strftime &amp;quot;%Y-%m-%d\x5f%H:%M:%S&amp;quot;, localtime;&lt;br /&gt;
   my $oll = $attr{global}{verbose};&lt;br /&gt;
   $attr{global}{verbose} = 0; &lt;br /&gt;
   my @logdata = split(&amp;quot;\n&amp;quot;, fhem(&amp;quot;get $logfile - - $period_s $period_e $cspec&amp;quot;));&lt;br /&gt;
   $attr{global}{verbose} = $oll; &lt;br /&gt;
   my ($cnt, $cum, $avg) = (0)x3;&lt;br /&gt;
   foreach (@logdata){&lt;br /&gt;
    my @line = split(&amp;quot; &amp;quot;, $_);&lt;br /&gt;
    if(defined $line[1] &amp;amp;&amp;amp; $line[1] ne &amp;quot;&amp;quot;){&lt;br /&gt;
     $cnt += 1;&lt;br /&gt;
     $cum += $line[1];&lt;br /&gt;
    }&lt;br /&gt;
   }&lt;br /&gt;
   if(&amp;quot;$cnt&amp;quot; &amp;gt; 0){$avg = sprintf(&amp;quot;%0.1f&amp;quot;, $cum/$cnt)};&lt;br /&gt;
   Log 4, (&amp;quot;myAverage: File: $logfile, Field: $cspec, Period: $period_s bis $period_e, Count: $cnt, Cum: $cum, Average: $avg&amp;quot;);&lt;br /&gt;
   return $avg;&lt;br /&gt;
  }&lt;br /&gt;
  ##########################################################&lt;br /&gt;
  1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Funktion myAverage() aufrufen und nutzen ===&lt;br /&gt;
Jetzt kann die Funktion &amp;lt;code&amp;gt;myAverage(&amp;amp;lt;offset&amp;amp;gt;, &amp;amp;lt;logfile&amp;amp;gt;, &amp;amp;lt;column-spec&amp;amp;gt;)&amp;lt;/code&amp;gt; ganz normal auf der FHEM-Konsole (telnet localhost 7072) genutzt werden. Hier z.B. die Ausgabe des Mittelwertes des Windsensors, eines KS300, über die letzten drei Stunden (Angabe in 3*3600s) oder der Temperaturmittelwert der letzten 24 Stunden.&lt;br /&gt;
&lt;br /&gt;
Mit FileLog:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;fhem&amp;amp;gt; {myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;)}&lt;br /&gt;
  6.3&lt;br /&gt;
  fhem&amp;amp;gt; {myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;4:::&amp;amp;quot;)}&lt;br /&gt;
  -2.7&lt;br /&gt;
  fhem&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit DbLog:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;fhem&amp;amp;gt; {myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;myDbLog&amp;amp;quot;, &amp;amp;quot;KS300:wind::&amp;amp;quot;)}&lt;br /&gt;
  5.9&lt;br /&gt;
  fhem&amp;amp;gt; {myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;myDbLog&amp;amp;quot;, &amp;amp;quot;KS300:temperature::&amp;amp;quot;)}&lt;br /&gt;
  -2.7&lt;br /&gt;
  fhem&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ähnlich ist die Verwendung in perl-Code in der [[Konfiguration|fhem.cfg]]:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;my $avg = myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;);;\&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Ein [[notify]], welches bei jedem neuen Sensorwert die Mitteltemperatur der letzten 24 Stunden als Event &amp;quot;average-temp xy&amp;quot; ins Logfile schreibt, sieht dann wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define KS300_T_notify notify KS300:temperature.* {\&lt;br /&gt;
   fhem(&#039;trigger KS300 average-temp: &#039;.myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;4:::&amp;amp;quot;));;\&lt;br /&gt;
  }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;!-- korrigiert lt. http://forum.fhem.de/index.php/topic,11622.msg170331.html#msg170331 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analog dazu wäre mit den Winddaten zu verfahren.&lt;br /&gt;
&lt;br /&gt;
== Gleitender Mittelwert und Minimum und Maximum aus Log-Dateien ==&lt;br /&gt;
&lt;br /&gt;
Manchmal interessieren einem auch Minimum und Maximum Werte über einen bestimmten Zeitraum, die Funktion &#039;&#039;myAverage&#039;&#039; kann einfach entsprechend abgeändert werden:&lt;br /&gt;
&lt;br /&gt;
=== Subroutine avgMinMaxAusLog() in 99_MyUtils anlegen ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
  # Berechnet den Mittelwert, Minimum und Maximum aus LogFiles über einen beliebigen Zeitraum&lt;br /&gt;
  # Args: $offset = Offset in Sekunden&lt;br /&gt;
  #		$logfile = LogFile, z.B. DbLog Device&lt;br /&gt;
  #		$cspec = column-spec, siehe https://fhem.de/commandref_DE.html#DbLog -&amp;gt; get&lt;br /&gt;
  sub avgMinMaxAusLog($$$) {&lt;br /&gt;
  	my($offset, $logfile, $cspec) = @_;&lt;br /&gt;
  	my $period_s = strftime &amp;quot;%Y-%m-%d\x5f%H:%M:%S&amp;quot;, localtime(time - $offset);&lt;br /&gt;
  	my $period_e = strftime &amp;quot;%Y-%m-%d\x5f%H:%M:%S&amp;quot;, localtime;&lt;br /&gt;
  	my $oll = $attr { global } { verbose };&lt;br /&gt;
  	$attr { global } { verbose } = 0;&lt;br /&gt;
  	my @logdata = split(&amp;quot;\n&amp;quot;, fhem(&amp;quot;get $logfile - - $period_s $period_e $cspec&amp;quot;));&lt;br /&gt;
  	$attr { global } { verbose } = $oll;&lt;br /&gt;
  	my ($cnt, $cum, $avg, $min, $max) = (0)x5;&lt;br /&gt;
  	foreach(@logdata) {&lt;br /&gt;
  		my @line = split(&amp;quot; &amp;quot;, $_);&lt;br /&gt;
  		if (defined $line[1] &amp;amp;&amp;amp; $line[1] ne &amp;quot;&amp;quot;) {&lt;br /&gt;
  			$cnt += 1;&lt;br /&gt;
  			$cum += $line[1];&lt;br /&gt;
  			# Beim ersten Eintrag min/max setzen&lt;br /&gt;
  			if ($cnt == 1) {&lt;br /&gt;
  				$min = $line[1];&lt;br /&gt;
  				$max = $line[1];&lt;br /&gt;
  			# Bei den darauffolgenden Einträgen $min/max ermitteln&lt;br /&gt;
  			} else {&lt;br /&gt;
  				if ($line[1] &amp;lt; $min) { $min = $line[1]; }&lt;br /&gt;
  				if ($line[1] &amp;gt; $max) { $max = $line[1]; }&lt;br /&gt;
  			}&lt;br /&gt;
  		}&lt;br /&gt;
  	}&lt;br /&gt;
  	if (&amp;quot;$cnt&amp;quot; &amp;gt; 0) {&lt;br /&gt;
  		$avg = sprintf(&amp;quot;%0.1f&amp;quot;, $cum / $cnt)&lt;br /&gt;
  	};&lt;br /&gt;
  	Log 4, (&amp;quot;avgMinMaxAusLog: File: $logfile, Field: $cspec, Period: $period_s bis $period_e, Count: $cnt, Cum: $cum, Average: $avg, Minimum: $min, Maximum: $max&amp;quot;);&lt;br /&gt;
  	return ($avg, $min, $max);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Anwendung wie oben. Statt nur dem Mittelwert wird eine Liste zurückgeliefert mit Mittelwert, Minimum und Maximum. Verwendung z.B. wie folgt:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;my ($avg, $min, $max) = myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;);;\&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Eigenes Filelog und Plot ==&lt;br /&gt;
==== Definitionen ====&lt;br /&gt;
Ich schreibe ein komplett eigenes Logfile und lasse über eine spezielle gplot-Definition die Temperatur- und Winddaten loggen und plotten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
define KS300_W dummy&lt;br /&gt;
  define KS300_W_notify notify KS300:wind.* {\&lt;br /&gt;
   my $avg = myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;);;\&lt;br /&gt;
   my $event = sprintf(&amp;amp;quot;Wc:&amp;amp;#160;%0.1f Wd:&amp;amp;#160;%0.1f Wm:&amp;amp;#160;%0.1f Wlh:&amp;amp;#160;%0.1f&amp;amp;quot;, ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;wind&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;W_avg_day&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;W_avg_month&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), $avg);;\&lt;br /&gt;
   Log 2, (&amp;amp;quot;K300_W: Event: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&amp;amp;quot;trigger KS300_W data: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&amp;amp;quot;trigger KS300 average-wind: $avg&amp;amp;quot;);;\&lt;br /&gt;
  }&lt;br /&gt;
  define FileLog_KS300_W FileLog ./log/KS300_W-%Y.log KS300_W.*&lt;br /&gt;
  attr FileLog_KS300_W logtype text&lt;br /&gt;
  attr FileLog_KS300_W room Logs&lt;br /&gt;
  define KS300_TH dummy&lt;br /&gt;
  define KS300_TH_notify notify KS300:temperature.* {\&lt;br /&gt;
   my $avg = myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;4:::&amp;amp;quot;);;\&lt;br /&gt;
   my $event = sprintf(&amp;amp;quot;Tc:&amp;amp;#160;%0.1f Hc:&amp;amp;#160;%0.1f Tavg:&amp;amp;#160;%0.1f&amp;amp;quot;, ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;temperature&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;humidity&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), $avg);;\&lt;br /&gt;
   Log 2, (&amp;amp;quot;K300_TH: Event: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&amp;amp;quot;trigger KS300_TH data: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&#039;trigger KS300 average-temp: &#039;.$avg);;\&lt;br /&gt;
  }&lt;br /&gt;
  define FileLog_KS300_TH FileLog ./log/KS300_TH-%Y.log KS300_TH.*&lt;br /&gt;
  attr FileLog_KS300_TH logtype text&lt;br /&gt;
  attr FileLog_KS300_TH room Logs&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Die Definitionen für die Plots schauen so aus:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define weblink_KS300_W weblink fileplot FileLog_KS300_W:ks300_wind:CURRENT&lt;br /&gt;
  attr weblink_KS300_W label &amp;amp;quot;Wind - Min: $data{min1}, Max: $data{max1}, Last: $data{currval1}&amp;amp;quot;&lt;br /&gt;
  attr weblink_KS300_W room Dachterasse&lt;br /&gt;
  define weblink_KS300_TH weblink fileplot FileLog_KS300_TH:ks300_temphum:CURRENT&lt;br /&gt;
  attr weblink_KS300_TH label &amp;amp;quot;Temperatur/Feuchte - Min: $data{min1}, Max: $data{max1}, Last: $data{currval1}&amp;amp;quot;&lt;br /&gt;
  attr weblink_KS300_TH room Dachterasse&lt;br /&gt;
  define weblink_KS300_R weblink fileplot FileLog_KS300:ks300_rain10:CURRENT&lt;br /&gt;
  attr weblink_KS300_R label &amp;amp;quot;Regen - Min: $data{min1}, Max: $data{max1}, Last: $data{currval1}&amp;amp;quot;&lt;br /&gt;
  attr weblink_KS300_R room Dachterasse&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Angepasste gplot-Dateien ====&lt;br /&gt;
Nun noch die speziellen gplot-Dateien.&lt;br /&gt;
ks300_wind.gplot&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
  ############################&lt;br /&gt;
  # Display the wind values of a KS300.&lt;br /&gt;
  # Corresponding FileLog definition:&lt;br /&gt;
  # define &amp;amp;lt;filelogname&amp;amp;gt; FileLog ./log/KS300_W-%Y.log KS300_W.*&lt;br /&gt;
  set terminal png transparent size &amp;amp;lt;SIZE&amp;amp;gt; crop&lt;br /&gt;
  set output &#039;&amp;amp;lt;OUT&amp;amp;gt;.png&#039;&lt;br /&gt;
  set xdata time&lt;br /&gt;
  set timefmt &amp;amp;quot;%Y-%m-%d_%H:%M:%S&amp;amp;quot;&lt;br /&gt;
  set xlabel &amp;amp;quot; &amp;amp;quot;&lt;br /&gt;
  set ytics nomirror&lt;br /&gt;
  #set y2tics&lt;br /&gt;
  set ytics&lt;br /&gt;
  set title &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
  set grid xtics ytics&lt;br /&gt;
  set yrange [0:]&lt;br /&gt;
  set y2range [0:]&lt;br /&gt;
  set ylabel &amp;amp;quot;Wind (aktuell) [km/h]&amp;amp;quot;&lt;br /&gt;
  set y2label &amp;amp;quot;Wind (gemittelt) [km/h]&amp;amp;quot;&lt;br /&gt;
  set format y2 &amp;amp;quot;%0.1f&amp;amp;quot;&lt;br /&gt;
  #FileLog 5:Wc\x3a:0:&lt;br /&gt;
  #FileLog 11:Wlh\x3a:0:&lt;br /&gt;
  plot &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:5 ls l7fill axes x1y1 title &#039;Wind (aktuell)&#039; with lines,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:11 ls l5 axes x1y2 title &#039;Wind (3h-Mittel)&#039; with steps,\&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ks300_temphum.gplot&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
  ############################&lt;br /&gt;
  # Display the Temperature und Humidity values of a KS300.&lt;br /&gt;
  # Corresponding FileLog definition:&lt;br /&gt;
  # define &amp;amp;lt;filelogname&amp;amp;gt; FileLog ./log/KS300_TH-%Y.log KS300_TH.*&lt;br /&gt;
  set terminal png transparent size &amp;amp;lt;SIZE&amp;amp;gt; crop&lt;br /&gt;
  set output &#039;&amp;amp;lt;OUT&amp;amp;gt;.png&#039;&lt;br /&gt;
  set xdata time&lt;br /&gt;
  set timefmt &amp;amp;quot;%Y-%m-%d_%H:%M:%S&amp;amp;quot;&lt;br /&gt;
  set xlabel &amp;amp;quot; &amp;amp;quot;&lt;br /&gt;
  set ytics nomirror&lt;br /&gt;
  set y2tics&lt;br /&gt;
  #set ytics&lt;br /&gt;
  set title &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
  set grid xtics y2tics&lt;br /&gt;
  set y2label &amp;amp;quot;Temperatur [°C]&amp;amp;quot;&lt;br /&gt;
  set ylabel &amp;amp;quot;Luftfeuchte [%]&amp;amp;quot;&lt;br /&gt;
  #FileLog 5:Tc\x3a:0:&lt;br /&gt;
  #FileLog 9:Tavg\x3a:0:&lt;br /&gt;
  #FileLog 7:Hc\x3a:0:&lt;br /&gt;
  plot &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:5 axes x1y2 ls l0 title &#039;Temperatur&#039; with lines,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:9 axes x1y2 ls l10 title &#039;Temperatur (24h-Mittel)&#039; with lines,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:7 axes x1y1 ls l2fill title &#039;Luftfeuchte&#039; with lines&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Den Plot für den Regen habe ich noch um Punkt-Plots für den israining-Status erweitert, so dass Punkte bei &amp;quot;yes&amp;quot; geplottet werden.&lt;br /&gt;
&lt;br /&gt;
ks300_rain10.gplot&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
  ############################&lt;br /&gt;
  # Display the Rain values of a KS300.&lt;br /&gt;
  # Corresponding FileLog definition:&lt;br /&gt;
  # define &amp;amp;lt;filelogname&amp;amp;gt; FileLog ./log/KS300-%Y.log KS300:T:.*&lt;br /&gt;
  set terminal png transparent size &amp;amp;lt;SIZE&amp;amp;gt; crop&lt;br /&gt;
  set output &#039;&amp;amp;lt;OUT&amp;amp;gt;.png&#039;&lt;br /&gt;
  set xdata time&lt;br /&gt;
  set timefmt &amp;amp;quot;%Y-%m-%d_%H:%M:%S&amp;amp;quot;&lt;br /&gt;
  set xlabel &amp;amp;quot; &amp;amp;quot;&lt;br /&gt;
  set ytics nomirror&lt;br /&gt;
  #set y2tics&lt;br /&gt;
  set ytics&lt;br /&gt;
  set title &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
  set grid xtics ytics&lt;br /&gt;
  set y2range [0.5:1.5]&lt;br /&gt;
  set y2tics (&amp;amp;quot;&amp;amp;quot; 0, &amp;amp;quot;Regen&amp;amp;quot; 1)&lt;br /&gt;
  set pointsize 7&lt;br /&gt;
  set ylabel &amp;amp;quot;Regen (l/m²)&amp;amp;quot;&lt;br /&gt;
  set yrange [0:]&lt;br /&gt;
  # Computing Rain/h and Rain/d values by accumulating the changes.&lt;br /&gt;
  #FileLog 10:IR\x3a:0:delta-h&lt;br /&gt;
  #FileLog 10:IR\x3a:0:delta-d&lt;br /&gt;
  #FileLog 12:IR:0:$fld[11]=~&amp;amp;quot;yes&amp;amp;quot;?1:0&lt;br /&gt;
  plot &amp;amp;quot;&amp;amp;lt;grep -v avg_ &amp;amp;lt;IN&amp;amp;gt; | perl -ane &#039;\&lt;br /&gt;
      @a = split(\&amp;amp;quot;[_:]\&amp;amp;quot;, $F[0]);\&lt;br /&gt;
      if(defined($lh) &amp;amp;amp;&amp;amp;amp; $lh ne $a[1])\&lt;br /&gt;
       { printf(\&amp;amp;quot;${ld}_$lh:30:00&amp;amp;#160;%f\n\&amp;amp;quot;, $hv); $hv = 0; }\&lt;br /&gt;
      if($lv) { $hv += ($F[9]-$lv); }\&lt;br /&gt;
      $lh = $a[1]; $ld = $a[0]; $lv = $F[9];\&lt;br /&gt;
      END { printf(\&amp;amp;quot;${ld}_$lh:30:00&amp;amp;#160;%f\n\&amp;amp;quot;, $hv) }&#039;&amp;amp;quot;\&lt;br /&gt;
     using 1:2 axes x1y1 ls l1fill title &#039;Regen pro Stunde&#039; with histeps,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;grep -v avg_ &amp;amp;lt;IN&amp;amp;gt; | perl -ane &#039;\&lt;br /&gt;
      @a = split(\&amp;amp;quot;[_]\&amp;amp;quot;, $F[0]);\&lt;br /&gt;
      if(defined($ld) &amp;amp;amp;&amp;amp;amp; $ld ne $a[0]) {\&lt;br /&gt;
       printf(\&amp;amp;quot;${ld}_12:00:00&amp;amp;#160;%f\n\&amp;amp;quot;, $dv); $dv = 0; }\&lt;br /&gt;
       if($lv) { $dv += ($F[9]-$lv); }\&lt;br /&gt;
       $ld = $a[0]; $lv = $F[9];\&lt;br /&gt;
       END {printf(\&amp;amp;quot;${ld}_12:00:00&amp;amp;#160;%f\n\&amp;amp;quot;, $dv)}&#039;&amp;amp;quot;\&lt;br /&gt;
     using 1:2 axes x1y1 ls l7 title &#039;Regen pro Tag&#039; with histeps&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;grep -v avg_ &amp;amp;lt;IN&amp;amp;gt; | awk &#039;{print $1, $12==\&amp;amp;quot;yes\&amp;amp;quot;? 1&amp;amp;#160;: 0; }&#039;&amp;amp;quot;\&lt;br /&gt;
     using 1:2 axes x1y2 ls l11fill title &#039;Regen aktuell&#039; with points&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Eventuell müssen in den gplots noch die Linienstile/Farben den eigenen Bedürfnissen angepasst werden. Ich verwende hier eigene Farben und Füllungen.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;br /&gt;
[[Kategorie:Logging]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Diskussion:FHEM_Tablet_UI&amp;diff=39512</id>
		<title>Diskussion:FHEM Tablet UI</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Diskussion:FHEM_Tablet_UI&amp;diff=39512"/>
		<updated>2024-08-05T09:27:08Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Abschnitt gelöscht. Wiki-Seite wurde verschoben. Es fehlt aber der Hinweis für alle, die über die alte Seite einsteigen.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Sollte man nicht die Widgets alphabetisch sortieren ? &lt;br /&gt;
&lt;br /&gt;
Ich kann das gerne machen... bzw. mache das, wenn ich keinen Widerspruch höre  --[[Benutzer:Nobby1805|Nobby1805]] ([[Benutzer Diskussion:Nobby1805|Diskussion]]) 13:05, 6. Mai 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
Ich habe die Reihenfolge von github übernommen. Aber klar, eine alphabetische Sortierung ist durchaus sinnvoll. Dann aber auch die Beispiele entsprechend sortieren.&lt;br /&gt;
&lt;br /&gt;
:Ich setz mich mal dran .. oder willst du noch aktuell noch etwas ändern ?--[[Benutzer:Nobby1805|Nobby1805]] ([[Benutzer Diskussion:Nobby1805|Diskussion]]) 16:48, 7. Mai 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Sprung von der Widget-Auflistung zu den Beschreibungen ==&lt;br /&gt;
&lt;br /&gt;
... habe ich testweise mal für CIRCLEMENU gemacht ... werde ich in den nächsten Tagen für alle nachzioehgen ... und von dort dann sinnvollerweise auch zu den Beispielen ?! --[[Benutzer:Nobby1805|Nobby1805]] ([[Benutzer Diskussion:Nobby1805|Diskussion]]) 11:54, 14. Mai 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Update Link falsch? ==&lt;br /&gt;
&lt;br /&gt;
Müsste der Update Link zum hinzfügen nicht wie folgt heißen: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;update add https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ich bekomme mit dem aktuell hinterlegten Link nämlich einen Fehler&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:Amenophis86|Amenophis86]] ([[Benutzer Diskussion:Amenophis86|Diskussion]]) 14:35, 16. Feb. 2016 (CET)&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
: Hallo!&lt;br /&gt;
: Ja, Link auf Wiki-Seite war falsch; controlfile-Angabe fehlt dort.&lt;br /&gt;
: Ist korrigiert.&lt;br /&gt;
: Danke, --[[Benutzer:Krikan|Christian]] ([[Benutzer Diskussion:Krikan|Diskussion]]) 14:52, 16. Feb. 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Deutsch / Englisch ==&lt;br /&gt;
Sollten die Texte nicht eingedeutscht werden? Inhalt ist mal deutsch mal englisch --[[Benutzer:Svenson08|Svenson08]] ([[Benutzer Diskussion:Svenson08|Diskussion]]) 06:37, 2. Mär. 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Ist richtig, hat nur noch keiner gemacht. Kommt daher, dass setstate es auf seiner github Seite in Englisch hat und von dort das Meiste kopiert wurde. --[[Benutzer:Amenophis86|Amenophis86]] ([[Benutzer Diskussion:Amenophis86|Diskussion]]) 00:57, 5. Mär. 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Widgets ==&lt;br /&gt;
zur besseren Lesbarkeit wäre es besser je Widget ein eigenen &amp;quot;Kapitel&amp;quot;/Überschrift in der Seite anzulegen. Es macht auch wenig Sinn die Beispiele eines Widgets am Ende der Seite einzuhängen. Verständlicher ist es Wenn die Beispiele bei dessen Erläuterung aufgeführt sind. Beispiele ohne Bilder machen wenig Sinn wenn ich ein UI erklären will. --[[Benutzer:Svenson08|Svenson08]] ([[Benutzer Diskussion:Svenson08|Diskussion]]) 19:39, 7. Mär. 2016 (CET)&lt;br /&gt;
:Da stimme ich nicht zu ... die jetzige Version mit den zusätzliche &amp;quot;Überschriften&#039; bei Label und Level ist m.E. unübersichtlicher ... aus der alphabetischen Übersicht kommt ja immer durch die Links schnell zu den Beschreibungen  und ebenfalls durch die Links zu den Beispielen ... wenn ich zu einem Widget die Argumente nachschlagen will würden m.E. die immer wieder dazwischen liegenden Beispiele eher stören --[[Benutzer:Nobby1805|Nobby1805]] ([[Benutzer Diskussion:Nobby1805|Diskussion]]) 23:33, 7. Mär. 2016 (CET)&lt;br /&gt;
Da diese Überschriften keine Kapitel sind ist diese Bearbeitung, Ergänzung mühselig. Das sollten zumindest Kapitel sein um das besser zu bearbeiten und in der Seiten Übersicht sind diese dann ebenfalls mit einem Blick zu sehen und man direkt von dort zum Beispiel springen. Ist eine kleinere Änderung. --[[Benutzer:Svenson08|Svenson08]] ([[Benutzer Diskussion:Svenson08|Diskussion]]) 04:54, 8. Mär. 2016 (CET)&lt;br /&gt;
Längere Artikel ohne Kapitel sind nur schwer zu Pflege, das dadurch ein index gebildet wird, besser ein Inhaltsverzeichnis halte ich sehr wohl als übersichtlicher, aber das sieht jeder anders. Aber bearbeite mal eine bestimmte stelle wenn du mehrere tausend Zeilen bis zur gesuchten Zeile scrollen musst. Diese Übersichtlichkeit ist ein Grund warum es die Funktion in jeder wiki Engine gibt.--[[Benutzer:Svenson08|Svenson08]] ([[Benutzer Diskussion:Svenson08|Diskussion]]) 04:58, 8. Mär. 2016 (CET)&lt;br /&gt;
:Ein seitlanges Inhaltsverzeichnis finde ich allerdings nicht so prickelnd ;) Ansonsten hast du ja nicht unrecht, ich habe schon mehrfach kleinere Änderungen an den Widgetbeschreibungen durchgeführt, das wäre einfacher wenn die Abschnitte kleiner wären. --[[Benutzer:Nobby1805|Nobby1805]] ([[Benutzer Diskussion:Nobby1805|Diskussion]]) 09:42, 8. Mär. 2016 (CET)&lt;br /&gt;
: :-) Toll, ich hab mal recht .... Spaß bei seite. Ich hab auch schon überlegt ob man den einzelnen Widgets nicht einzelne Artikel spendiert. Gibts hier im Wiki auch schon bei ähnlich ausführlicheren Dokus. Auch wenn mal (viel) mehr Beispiele zu einem Widget erfasst werden wäre das vielleicht nicht verkehrt. Hab aber keine Endgültige Meinung dazu.--[[Benutzer:Svenson08|Svenson08]] ([[Benutzer Diskussion:Svenson08|Diskussion]]) 12:25, 8. Mär. 2016 (CET) &lt;br /&gt;
:Ich finde die Idee der einzelnen Unterabschnitte, wie sie aktuell zB bei Label gemacht wurde nicht schlecht. Allerdings sollte weiterhin eine Übersichtsliste bleiben, wie sie aktuell unter &amp;quot;Widgets -- Konfiguration&amp;quot; ist. Wenn alle Widgets ein eigener Unterabschnitt ist, dann kann man auch die Beispiele direkt dort einfügen und zB Bilder hinzufügen. Allerdings sollte es dann auch nicht &amp;quot;Widgets LABEL&amp;quot; heißen, sondern &amp;quot;Widget LABEL&amp;quot;. Ist ja dann nur noch ein Widget, welches angezeigt wird ;) --[[Benutzer:Amenophis86|Amenophis86]] ([[Benutzer Diskussion:Amenophis86|Diskussion]]) 15:22, 9. Mär. 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Betriff Abschnitt Vorraussetungen ==&lt;br /&gt;
Vorausgesetzt ist noch ein definierte FHEMWEB Instance, ohne das würden die Fhem Befehle nicht gesendet werden, longpoll, etc. Zwar ist das Default jeder installation, aber man sollte darauf Hinweisen. --[[Benutzer:Svenson08|Svenson08]] ([[Benutzer Diskussion:Svenson08|Diskussion]]) 05:54, 8. Mär. 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Anmerkung Link ==&lt;br /&gt;
&lt;br /&gt;
Hallo,&lt;br /&gt;
&lt;br /&gt;
ich hatte Darstellungsprobleme, wenn ich den im Beitrag genannten Link verwendet habe. (Sowohl Chrome als auch Firefox)&lt;br /&gt;
Mit diesem Link ging es dann ohne Probleme: http://&amp;lt;fhem-server&amp;gt;:8083/fhem/ftui&#039;&#039;&#039;/&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gruß&lt;br /&gt;
Andy&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Diskussion:FHEM_Tablet_UI&amp;diff=39511</id>
		<title>Diskussion:FHEM Tablet UI</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Diskussion:FHEM_Tablet_UI&amp;diff=39511"/>
		<updated>2024-08-05T09:14:00Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Neuer Abschnitt /* Wiki-Seite geleert??? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Sollte man nicht die Widgets alphabetisch sortieren ? &lt;br /&gt;
&lt;br /&gt;
Ich kann das gerne machen... bzw. mache das, wenn ich keinen Widerspruch höre  --[[Benutzer:Nobby1805|Nobby1805]] ([[Benutzer Diskussion:Nobby1805|Diskussion]]) 13:05, 6. Mai 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
Ich habe die Reihenfolge von github übernommen. Aber klar, eine alphabetische Sortierung ist durchaus sinnvoll. Dann aber auch die Beispiele entsprechend sortieren.&lt;br /&gt;
&lt;br /&gt;
:Ich setz mich mal dran .. oder willst du noch aktuell noch etwas ändern ?--[[Benutzer:Nobby1805|Nobby1805]] ([[Benutzer Diskussion:Nobby1805|Diskussion]]) 16:48, 7. Mai 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Sprung von der Widget-Auflistung zu den Beschreibungen ==&lt;br /&gt;
&lt;br /&gt;
... habe ich testweise mal für CIRCLEMENU gemacht ... werde ich in den nächsten Tagen für alle nachzioehgen ... und von dort dann sinnvollerweise auch zu den Beispielen ?! --[[Benutzer:Nobby1805|Nobby1805]] ([[Benutzer Diskussion:Nobby1805|Diskussion]]) 11:54, 14. Mai 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Update Link falsch? ==&lt;br /&gt;
&lt;br /&gt;
Müsste der Update Link zum hinzfügen nicht wie folgt heißen: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;update add https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ich bekomme mit dem aktuell hinterlegten Link nämlich einen Fehler&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:Amenophis86|Amenophis86]] ([[Benutzer Diskussion:Amenophis86|Diskussion]]) 14:35, 16. Feb. 2016 (CET)&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
: Hallo!&lt;br /&gt;
: Ja, Link auf Wiki-Seite war falsch; controlfile-Angabe fehlt dort.&lt;br /&gt;
: Ist korrigiert.&lt;br /&gt;
: Danke, --[[Benutzer:Krikan|Christian]] ([[Benutzer Diskussion:Krikan|Diskussion]]) 14:52, 16. Feb. 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Deutsch / Englisch ==&lt;br /&gt;
Sollten die Texte nicht eingedeutscht werden? Inhalt ist mal deutsch mal englisch --[[Benutzer:Svenson08|Svenson08]] ([[Benutzer Diskussion:Svenson08|Diskussion]]) 06:37, 2. Mär. 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Ist richtig, hat nur noch keiner gemacht. Kommt daher, dass setstate es auf seiner github Seite in Englisch hat und von dort das Meiste kopiert wurde. --[[Benutzer:Amenophis86|Amenophis86]] ([[Benutzer Diskussion:Amenophis86|Diskussion]]) 00:57, 5. Mär. 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Widgets ==&lt;br /&gt;
zur besseren Lesbarkeit wäre es besser je Widget ein eigenen &amp;quot;Kapitel&amp;quot;/Überschrift in der Seite anzulegen. Es macht auch wenig Sinn die Beispiele eines Widgets am Ende der Seite einzuhängen. Verständlicher ist es Wenn die Beispiele bei dessen Erläuterung aufgeführt sind. Beispiele ohne Bilder machen wenig Sinn wenn ich ein UI erklären will. --[[Benutzer:Svenson08|Svenson08]] ([[Benutzer Diskussion:Svenson08|Diskussion]]) 19:39, 7. Mär. 2016 (CET)&lt;br /&gt;
:Da stimme ich nicht zu ... die jetzige Version mit den zusätzliche &amp;quot;Überschriften&#039; bei Label und Level ist m.E. unübersichtlicher ... aus der alphabetischen Übersicht kommt ja immer durch die Links schnell zu den Beschreibungen  und ebenfalls durch die Links zu den Beispielen ... wenn ich zu einem Widget die Argumente nachschlagen will würden m.E. die immer wieder dazwischen liegenden Beispiele eher stören --[[Benutzer:Nobby1805|Nobby1805]] ([[Benutzer Diskussion:Nobby1805|Diskussion]]) 23:33, 7. Mär. 2016 (CET)&lt;br /&gt;
Da diese Überschriften keine Kapitel sind ist diese Bearbeitung, Ergänzung mühselig. Das sollten zumindest Kapitel sein um das besser zu bearbeiten und in der Seiten Übersicht sind diese dann ebenfalls mit einem Blick zu sehen und man direkt von dort zum Beispiel springen. Ist eine kleinere Änderung. --[[Benutzer:Svenson08|Svenson08]] ([[Benutzer Diskussion:Svenson08|Diskussion]]) 04:54, 8. Mär. 2016 (CET)&lt;br /&gt;
Längere Artikel ohne Kapitel sind nur schwer zu Pflege, das dadurch ein index gebildet wird, besser ein Inhaltsverzeichnis halte ich sehr wohl als übersichtlicher, aber das sieht jeder anders. Aber bearbeite mal eine bestimmte stelle wenn du mehrere tausend Zeilen bis zur gesuchten Zeile scrollen musst. Diese Übersichtlichkeit ist ein Grund warum es die Funktion in jeder wiki Engine gibt.--[[Benutzer:Svenson08|Svenson08]] ([[Benutzer Diskussion:Svenson08|Diskussion]]) 04:58, 8. Mär. 2016 (CET)&lt;br /&gt;
:Ein seitlanges Inhaltsverzeichnis finde ich allerdings nicht so prickelnd ;) Ansonsten hast du ja nicht unrecht, ich habe schon mehrfach kleinere Änderungen an den Widgetbeschreibungen durchgeführt, das wäre einfacher wenn die Abschnitte kleiner wären. --[[Benutzer:Nobby1805|Nobby1805]] ([[Benutzer Diskussion:Nobby1805|Diskussion]]) 09:42, 8. Mär. 2016 (CET)&lt;br /&gt;
: :-) Toll, ich hab mal recht .... Spaß bei seite. Ich hab auch schon überlegt ob man den einzelnen Widgets nicht einzelne Artikel spendiert. Gibts hier im Wiki auch schon bei ähnlich ausführlicheren Dokus. Auch wenn mal (viel) mehr Beispiele zu einem Widget erfasst werden wäre das vielleicht nicht verkehrt. Hab aber keine Endgültige Meinung dazu.--[[Benutzer:Svenson08|Svenson08]] ([[Benutzer Diskussion:Svenson08|Diskussion]]) 12:25, 8. Mär. 2016 (CET) &lt;br /&gt;
:Ich finde die Idee der einzelnen Unterabschnitte, wie sie aktuell zB bei Label gemacht wurde nicht schlecht. Allerdings sollte weiterhin eine Übersichtsliste bleiben, wie sie aktuell unter &amp;quot;Widgets -- Konfiguration&amp;quot; ist. Wenn alle Widgets ein eigener Unterabschnitt ist, dann kann man auch die Beispiele direkt dort einfügen und zB Bilder hinzufügen. Allerdings sollte es dann auch nicht &amp;quot;Widgets LABEL&amp;quot; heißen, sondern &amp;quot;Widget LABEL&amp;quot;. Ist ja dann nur noch ein Widget, welches angezeigt wird ;) --[[Benutzer:Amenophis86|Amenophis86]] ([[Benutzer Diskussion:Amenophis86|Diskussion]]) 15:22, 9. Mär. 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Betriff Abschnitt Vorraussetungen ==&lt;br /&gt;
Vorausgesetzt ist noch ein definierte FHEMWEB Instance, ohne das würden die Fhem Befehle nicht gesendet werden, longpoll, etc. Zwar ist das Default jeder installation, aber man sollte darauf Hinweisen. --[[Benutzer:Svenson08|Svenson08]] ([[Benutzer Diskussion:Svenson08|Diskussion]]) 05:54, 8. Mär. 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Anmerkung Link ==&lt;br /&gt;
&lt;br /&gt;
Hallo,&lt;br /&gt;
&lt;br /&gt;
ich hatte Darstellungsprobleme, wenn ich den im Beitrag genannten Link verwendet habe. (Sowohl Chrome als auch Firefox)&lt;br /&gt;
Mit diesem Link ging es dann ohne Probleme: http://&amp;lt;fhem-server&amp;gt;:8083/fhem/ftui&#039;&#039;&#039;/&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gruß&lt;br /&gt;
Andy&lt;br /&gt;
&lt;br /&gt;
== Wiki-Seite geleert??? ==&lt;br /&gt;
&lt;br /&gt;
Warum wurde die Wiki-Seite geleert? Natürlich gibt es eine neue Version, die auch weiter entwickelt wird. Und vielleicht gibt es inzwischen dafür sogar ein (brauchbares) Wiki. Allerdings gibt es auch mit Sicherheit genügend User, die das alte FTUI als völlig ausreichend betrachten und überhaupt nicht die Notwendigkeit sehen, auf V3 umzusteigen. Und diesen hast du nun das Nachschlagewerk weg genommen. V2 ist nicht unbrauchbar, weil es nicht weiter entwickelt wird. Es läuft ja. Es wird unbrauchbar, wenn man seine Oberfläche nicht mehr bearbeiten kann, weil die Bedienungsanleitung fehlt.&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39384</id>
		<title>AT kleine Helferlein</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39384"/>
		<updated>2024-07-25T18:05:16Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Anker hinzu gefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein AT kann statt einer Uhrzeit bzw. eines Datums mit einer Uhrzeit auch eine Perl-Funktion nutzen. Beispiel solcher Funktionen sind [[At#at ultimo|at_ultimo]] oder das Modul [[SUNRISE_EL]]. Hier sollen weitere Funktionen vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Der Code kann in der [[99 myUtils anlegen|99 myUtils]] untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
== {{Anker|AT am x-ten Wochentag im Monat ausführen}}AT am x-ten Wochentag im Monat ausführen ==&lt;br /&gt;
&lt;br /&gt;
Aufgabe ist es, das at z.B. an jedem 2. Montag im Monat auszuführen. Zusätzlich gibt es auch die Möglichkeit, das at immer am z.B. letzten Montag im Monat auszuführen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# x.ten Wochentags im Monat&lt;br /&gt;
#&lt;br /&gt;
# x=1-4 x.ter Wochentag im Monat&lt;br /&gt;
# x=9   letzter Wochentag im Monat&lt;br /&gt;
# w=1-7 Wochentag, 1=Montag&lt;br /&gt;
# h,m,s Uhrzeit Stunde, Minute, Sekunde&lt;br /&gt;
#&lt;br /&gt;
sub at_xwday($$$$$) {&lt;br /&gt;
    my ($x,$w,$h,$m,$s) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $ziel_tag = 0;&lt;br /&gt;
&lt;br /&gt;
    # akt. Datum und Uhrzeit in Variablen aufteilen&lt;br /&gt;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = &lt;br /&gt;
        localtime(time);&lt;br /&gt;
&lt;br /&gt;
    # bei Neuberechnung einen Monat addieren&lt;br /&gt;
    my $add = $data{AT_RECOMPUTE} ? 1 : 0;&lt;br /&gt;
    $mon = $mon + $add;&lt;br /&gt;
&lt;br /&gt;
    my ($nm, $ny) = ($mon == 12) ? (0,$year+1) : ($mon,$year);&lt;br /&gt;
&lt;br /&gt;
    # Letztes Vorkommen des Wochentags berechnen?&lt;br /&gt;
    if ($x == 9) {&lt;br /&gt;
        # Berechnen des letzten Tags des Monats&lt;br /&gt;
        # ersten Tag des Folgemonats als timestamp&lt;br /&gt;
        my ($xm, $xy) = ($mon == 11) ? (0,$year+1) : ($mon+1,$year);&lt;br /&gt;
        my $nt = mktime(0, 0, 0, 1, $xm, $xy);&lt;br /&gt;
&lt;br /&gt;
        # letzter Tag des aktuellen Monats = erster Tag des Folgemonats minus ein Tag&lt;br /&gt;
        my ($letzter_tag_des_monats, $letzter_wochentag) = (localtime($nt - DAYSECONDS))[3,6];&lt;br /&gt;
&lt;br /&gt;
        # Prüfen, ob der letzte Wochentag im Monat mit dem gewünschten Wochentag übereinstimmt&lt;br /&gt;
        $ziel_tag = $letzter_tag_des_monats;&lt;br /&gt;
        if ($letzter_wochentag &amp;gt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag später im Monat ist, subtrahiere die Differenz&lt;br /&gt;
           my $differenz = $letzter_wochentag - $w;&lt;br /&gt;
           $ziel_tag -= $differenz;&lt;br /&gt;
        } elsif ($letzter_wochentag &amp;lt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag früher im Monat ist, subtrahiere 7 plus die Differenz&lt;br /&gt;
           my $differenz = $w - $letzter_wochentag;&lt;br /&gt;
           $ziel_tag -= (7 - $differenz);&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        # Berechne den Tag des ersten Vorkommens des Wochentags im Monat&lt;br /&gt;
        my $erster_tag = 1;&lt;br /&gt;
        my $erster_tag_des_monats = (localtime(mktime(0,0,0,$erster_tag,$nm,$ny)))[6];&lt;br /&gt;
        my $erstes_vorkommen = ($w - $erster_tag_des_monats + 7) % 7 + 1;&lt;br /&gt;
&lt;br /&gt;
        # Berechne den Tag des x.ten Vorkommens des Wochentags im Monat&lt;br /&gt;
        $ziel_tag = $erstes_vorkommen + 7 * ($x - 1);&lt;br /&gt;
&lt;br /&gt;
        # Überprüfe, ob das Datum im gültigen Bereich liegt&lt;br /&gt;
        if ($ziel_tag &amp;gt; 31 || $ziel_tag &amp;lt; 1) {&lt;br /&gt;
          return &amp;quot;Ungültiges Datum&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return mktime($s,$m,$h,$ziel_tag,$nm,$ny);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Als Parameter benötigt die Funktion, welches Vorkommen des Wochentags berechnet werden soll (1-4). Soll das letzte Vorkommen berechnet werden, übergibt man 9. Als Wochentag wird 1-7 angegeben, wobei Montag der Wochentag 1 ist. Danach kommen als getrennte Parameter Stunde, Minute und Sekunde. Die Definition sieht dann so aus&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod at_heat1_Treffen_FG_Radverkehr at *{at_xwday(1,2,17,45,0)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_FG_Radverkehr at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Heizung wird für das Treffen der Fachgruppe Radverkehr am ersten Dienstag im Monat auf 21 Grad gestellt. Gleichzeitig wird ein AT gestartet, das die Heizung zwei Stunden später wieder auf 15 Grad reduziert. Kleiner Tipp: Man kann im AT auch zwei FHEM-Befehle hintereinander senden. Klappte in diesem Fall aber nur über den kleinen Umweg über Perl.&lt;br /&gt;
&lt;br /&gt;
== {{Anker|AT alle x Tage ausführen}}AT alle x Tage ausführen ==&lt;br /&gt;
&lt;br /&gt;
Soll ein Termin z.B. alle sechs Wochen stattfinden, so kann folgende Funktion genutzt werden.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# nächsten Treffens in x Tagen&lt;br /&gt;
&lt;br /&gt;
sub at_xdays($$) {&lt;br /&gt;
	my ($tm,$days) = @_;&lt;br /&gt;
	my $delta = $days * DAYSECONDS;		# Nächster Termin in sec&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;Wrong timespec, use \&amp;quot;yyyy-mm-ddThh:mm:ss\&amp;quot;&amp;quot; if($tm !~ m/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)$/);&lt;br /&gt;
	my ($y,$m,$d,$h,$m2,$s) = ($1,$2,$3,$4,$5,$6);&lt;br /&gt;
	my $abstime = mktime($s,$m2,$h,$d,$m-1,$y-1900, 0,0,-1);&lt;br /&gt;
	my $now = int(time);&lt;br /&gt;
&lt;br /&gt;
	my $diff = $now-$abstime;&lt;br /&gt;
	if ($diff&amp;gt;0){&lt;br /&gt;
    	# bei Neuberechnung sechs Wochen zur aktuellen Zeit addieren&lt;br /&gt;
		# wird auch bei Erstberechnung aufgerufen, wenn Timestamp in der Vergangenheit&lt;br /&gt;
		my $temp = ((int($diff/$delta)+1)*$delta)+$abstime;&lt;br /&gt;
		my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($temp);&lt;br /&gt;
		return mktime($s,$m2,$h,$mday,$mon,$year);&lt;br /&gt;
	} else {return $abstime;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dabei wird der erste Ausführungstermin im FHEM-üblichen Format (&amp;quot;yyyy-mm-ddThh:mm:ss&amp;quot;) und das Intervall in Tagen übergeben. Die Variable $delta enthält dann das Intervall in Sekunden. Es wird zwar mit dem Timestamp gerechnet. Zurückgegeben wird aber das berechnete Datum und die der Funktion übergebene Uhrzeit. Das verhindert Probleme mit der Zeitumstellung. Hier die Definition für einen Termin alle sechs Wochen, beginnend am 29.05.2024 um 18:45 Uhr. Auch hier wird die Heizung zwei Stunden später wieder herunter gestellt.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod at_heat2_Lasse at *{at_xdays(&amp;quot;2024-05-29T18:45:00&amp;quot;,42)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_Lasse at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=At&amp;diff=39383</id>
		<title>At</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=At&amp;diff=39383"/>
		<updated>2024-07-25T18:03:39Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Links hinzu gefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{SEITENTITEL:at}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Setzt einen Fhem-Befehl zu einem späteren Zeitpunkt ab.&lt;br /&gt;
|ModType=h&lt;br /&gt;
&amp;lt;!-- |ModCategory= (noch?) nicht verwendet --&amp;gt;&lt;br /&gt;
|ModCmdRef=at&lt;br /&gt;
|ModTechName=90_at.pm&lt;br /&gt;
|ModOwner={{Link2FU|8|rudolfkoenig}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[at]] ist ein Erweiterungsmodul, mit dessen Hilfe FHEM-Befehle/-Aktionen zu einem späteren Zeitpunkt ausgeführt werden können. Es läßt sich sowohl einmalige Ausführung, als auch regelmäßige Wiederholung erzielen, Zeitangaben können relativ oder absolut erfolgen.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
&amp;lt;!-- AUSKOMMENTIERT wegen derzeitiger Funktionsproblemen iZm codemirror {{Randnotiz|RNTyp=[g|Info|RNText=FHEM enthält für at eine eingebaute Perl-Syntax-Prüfung. Diese ist nach [http://fhem.de/commandref.html#perlSyntaxCheck Aktivierung] aber nur aktiv, wenn die [[Konfiguration]] -wie empfohlen- nicht direkt bearbeitet wird. ({{Link2Forum|Topic=51744}}) }} --&amp;gt;&lt;br /&gt;
Keine.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
=== Define ===&lt;br /&gt;
&amp;lt;code&amp;gt;define &amp;lt;name&amp;gt; at &amp;lt;timespec|datespec&amp;gt; &amp;lt;command&amp;gt;&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Besonderheit ===&lt;br /&gt;
*timespec - &#039;&#039;&#039;nur Zeit&#039;&#039;&#039; im Format HH:MM:SS &#039;&#039;&#039;kann eine&#039;&#039;&#039; Perlfunktion sein. &lt;br /&gt;
*datespec - &#039;&#039;&#039;Datum und Zeit&#039;&#039;&#039; ISO 8601 oder &amp;quot;number of sec since 1970&amp;quot; &#039;&#039;&#039;darf keine&#039;&#039;&#039; Perlfunktion sein.&lt;br /&gt;
Siehe {{Link2Forum|Topic=91625|Message=168475}} &lt;br /&gt;
&lt;br /&gt;
=== Beispiele ===&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at 02:02:00 set lamp on&amp;lt;/code&amp;gt; →              das nächste Mal um zwei Minuten nach 2 Uhr &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at *02:02:00 set lamp on&amp;lt;/code&amp;gt; →             jeden Tag um zwei Minuten nach 2 Uhr &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at {ReadingsVal(&amp;quot;Dummy&amp;quot;,&amp;quot;Zeit&amp;quot;,&amp;quot;&amp;quot;)} set lamp on&amp;lt;/code&amp;gt; →              das nächste Mal um (Perlfunktion liest Zeit aus dem Dummy) &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at 2016-01-25T02:02:00 set lamp on&amp;lt;/code&amp;gt; →              das nächste Mal am 25.01.2016 um zwei Minuten nach 2 Uhr &amp;quot;lamp&amp;quot; einschalten (ISO 8601)&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at 1453683720 set lamp on&amp;lt;/code&amp;gt; →              das nächste Mal am 25.01.2016 um zwei Minuten nach 2 Uhr &amp;quot;lamp&amp;quot; einschalten (number of sec since 1970)&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at +02:02:00 set lamp on&amp;lt;/code&amp;gt;    →         in zwei Stunden und 2 Minuten &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at +*02:02:00 set lamp on&amp;lt;/code&amp;gt;   →        alle zwei Stunden und 2 Minuten &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
Um datespec auch variabel mit setzen zu können gibt es einen Workaround: Perlebene, Perlfunktion und Übergabe in Variable. &lt;br /&gt;
&lt;br /&gt;
Beispiele für &amp;quot;number of seconds since 1970&amp;quot;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
{my $time=time_str2num(&amp;quot;2019-09-14 23:00:00&amp;quot;);;fhem(&amp;quot;define MeineAktion at $time set lamp on&amp;quot;)}&lt;br /&gt;
{my $time=1568494800;;fhem(&amp;quot;define MeineAktion at $time set lamp on&amp;quot;)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Beispiel im ISO 8601 Format&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{my $time=&amp;quot;2019-09-14T23:00:00&amp;quot;;;fhem(&amp;quot;define MeineAktion at $time set lamp on&amp;quot;)}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mehrere Aktionen ausführen ===&lt;br /&gt;
Die Verwendung der Semikolon erfordert immer besondere Aufmerksamkeit!&lt;br /&gt;
*&amp;lt;code&amp;gt;set lampe1 on ; set lampe2 on &amp;lt;/code&amp;gt;   →        Schaltet sofort beide Lampen ein ( ein bisschen OT, weil kein at)&lt;br /&gt;
*&amp;lt;code&amp;gt;define morgens at *7:00:00 set lampe1 on ; set lampe2 on&amp;lt;/code&amp;gt;   →     schaltet lampe 1 immer um 7 an, aber lampe2 sofort. Der erste Befehl landet in der config (im at) der zweite Befehl wird genau wie der define Befehl einfach sofort ausgeführt.  &lt;br /&gt;
*&amp;lt;code&amp;gt;define morgens at *7:00:00 set lampe1 on ;; set lampe2 on&amp;lt;/code&amp;gt;   →     schaltet BEIDE Lampen immer um 7 an. Beide Befehle landen in der config (im at), nur der define Befehl wird ausgeführt&lt;br /&gt;
*&amp;lt;code&amp;gt;define morgens at *7:00:00 set lampe1,lampe2 on&amp;lt;/code&amp;gt;   →     schaltet BEIDE Lampen immer um 7 an. Geht nur wenn der gleiche Befehl an 2 oder mehr Geräte gesendet werden soll&lt;br /&gt;
&lt;br /&gt;
=== at_ultimo ===&lt;br /&gt;
Die integrierte Funktion at_ultimo() dient dazu, an jedem letzten Tag des Monats einen FHEM-Befehl auszuführen. Sie kann als Perlfunc für timespec verwendet werden:&lt;br /&gt;
:&amp;lt;code&amp;gt;define at_ultimo at *{at_ultimo()} set Lampe1 off&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dadurch wird ein at-device erstellt, das am letzten Tag des Monats um 23:59:00 Uhr ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
at_ultimo() kann zusätzliche Parameter annehmen, um eine andere Zeit an diesem Tag anzugeben:&lt;br /&gt;
:&amp;lt;code&amp;gt;define at_ultimo at *{at_ultimo(12,23,45)} set Lampe1 off&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dadurch wird ein at-device erstellt, das am letzten Tag des Monats um 12:23:45 Uhr ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
=== Attribute ===&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
=== Testen ===&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;Versionsspezifisch:&#039;&#039;&#039; Der Befehl &#039;&#039;execNow&#039;&#039; ist in FHEM 5.7/90_at.pm ab 30.4.2016 verfügbar.}}&lt;br /&gt;
Mit dem Befehl &lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;devspec&amp;gt; execNow&amp;lt;/code&amp;gt;&lt;br /&gt;
lässt sich eine &#039;&#039;at&#039;&#039;-Definition (einmalig, beispielsweise zu Testzwecken) unabhängig vom Erreichen der angegebenen Zeitspezifikation ausführen.&lt;br /&gt;
&lt;br /&gt;
=== Ändern / Modifizieren ===&lt;br /&gt;
Das Zeit-Attribut eines existierenden Timers sollte via &amp;lt;code&amp;gt;modifyTimeSpec&amp;lt;/code&amp;gt; (Befehls-Syntax via Web-Interface ermitteln) geändert werden können.&lt;br /&gt;
Details dazu in den Forenbeiträgen&lt;br /&gt;
* {{Link2Forum|Topic=76227|LinkText=modifyTimeSpec fehlerhaft!?}}&lt;br /&gt;
* {{Link2Forum|Topic=36326|LinkText=defmod}} &lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
* [[AT an einem bestimmten Wochentag ausführen|at an einem bestimmten Wochentag ausführen]]&lt;br /&gt;
* [[AT kleine Helferlein#AT am x-ten Wochentag im Monat ausführen|at am x-ten Wochentag im Monat ausführen]]&lt;br /&gt;
* [[AT kleine Helferlein#AT alle x Tage ausführen|at alle x Tage ausführen]]&lt;br /&gt;
* [[AT um eine Temperaturabhängige Nachtabsenkung zu realisieren|at um eine Temperaturabhängige Nachtabsenkung zu realisieren]]&lt;br /&gt;
* [[AT zu einem absoluten Datum ausführen|at zu einem absoluten Datum ausführen]]&lt;br /&gt;
* [[SUNRISE_EL|at in Verbindung mit SUNRISE_EL]]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Abfrage, ob at definiert ist: {{Link2Forum|Topic=23584|Message=841269}}&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39382</id>
		<title>AT kleine Helferlein</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39382"/>
		<updated>2024-07-25T18:00:58Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Anker hinzu gefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein AT kann statt einer Uhrzeit bzw. eines Datums mit einer Uhrzeit auch eine Perl-Funktion nutzen. Beispiel solcher Funktionen sind [[At#at ultimo|at_ultimo]] oder das Modul [[SUNRISE_EL]]. Hier sollen weitere Funktionen vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Der Code kann in der [[99 myUtils anlegen|99 myUtils]] untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
== {{Anker|AT am x-ten Wochentag im Monat ausführen}}AT am x-ten Wochentag im Monat ausführen ==&lt;br /&gt;
&lt;br /&gt;
Aufgabe ist es, das at z.B. an jedem 2. Montag im Monat auszuführen. Zusätzlich gibt es auch die Möglichkeit, das at immer am z.B. letzten Montag im Monat auszuführen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# x.ten Wochentags im Monat&lt;br /&gt;
#&lt;br /&gt;
# x=1-4 x.ter Wochentag im Monat&lt;br /&gt;
# x=9   letzter Wochentag im Monat&lt;br /&gt;
# w=1-7 Wochentag, 1=Montag&lt;br /&gt;
# h,m,s Uhrzeit Stunde, Minute, Sekunde&lt;br /&gt;
#&lt;br /&gt;
sub at_xwday($$$$$) {&lt;br /&gt;
    my ($x,$w,$h,$m,$s) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $ziel_tag = 0;&lt;br /&gt;
&lt;br /&gt;
    # akt. Datum und Uhrzeit in Variablen aufteilen&lt;br /&gt;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = &lt;br /&gt;
        localtime(time);&lt;br /&gt;
&lt;br /&gt;
    # bei Neuberechnung einen Monat addieren&lt;br /&gt;
    my $add = $data{AT_RECOMPUTE} ? 1 : 0;&lt;br /&gt;
    $mon = $mon + $add;&lt;br /&gt;
&lt;br /&gt;
    my ($nm, $ny) = ($mon == 12) ? (0,$year+1) : ($mon,$year);&lt;br /&gt;
&lt;br /&gt;
    # Letztes Vorkommen des Wochentags berechnen?&lt;br /&gt;
    if ($x == 9) {&lt;br /&gt;
        # Berechnen des letzten Tags des Monats&lt;br /&gt;
        # ersten Tag des Folgemonats als timestamp&lt;br /&gt;
        my ($xm, $xy) = ($mon == 11) ? (0,$year+1) : ($mon+1,$year);&lt;br /&gt;
        my $nt = mktime(0, 0, 0, 1, $xm, $xy);&lt;br /&gt;
&lt;br /&gt;
        # letzter Tag des aktuellen Monats = erster Tag des Folgemonats minus ein Tag&lt;br /&gt;
        my ($letzter_tag_des_monats, $letzter_wochentag) = (localtime($nt - DAYSECONDS))[3,6];&lt;br /&gt;
&lt;br /&gt;
        # Prüfen, ob der letzte Wochentag im Monat mit dem gewünschten Wochentag übereinstimmt&lt;br /&gt;
        $ziel_tag = $letzter_tag_des_monats;&lt;br /&gt;
        if ($letzter_wochentag &amp;gt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag später im Monat ist, subtrahiere die Differenz&lt;br /&gt;
           my $differenz = $letzter_wochentag - $w;&lt;br /&gt;
           $ziel_tag -= $differenz;&lt;br /&gt;
        } elsif ($letzter_wochentag &amp;lt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag früher im Monat ist, subtrahiere 7 plus die Differenz&lt;br /&gt;
           my $differenz = $w - $letzter_wochentag;&lt;br /&gt;
           $ziel_tag -= (7 - $differenz);&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        # Berechne den Tag des ersten Vorkommens des Wochentags im Monat&lt;br /&gt;
        my $erster_tag = 1;&lt;br /&gt;
        my $erster_tag_des_monats = (localtime(mktime(0,0,0,$erster_tag,$nm,$ny)))[6];&lt;br /&gt;
        my $erstes_vorkommen = ($w - $erster_tag_des_monats + 7) % 7 + 1;&lt;br /&gt;
&lt;br /&gt;
        # Berechne den Tag des x.ten Vorkommens des Wochentags im Monat&lt;br /&gt;
        $ziel_tag = $erstes_vorkommen + 7 * ($x - 1);&lt;br /&gt;
&lt;br /&gt;
        # Überprüfe, ob das Datum im gültigen Bereich liegt&lt;br /&gt;
        if ($ziel_tag &amp;gt; 31 || $ziel_tag &amp;lt; 1) {&lt;br /&gt;
          return &amp;quot;Ungültiges Datum&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return mktime($s,$m,$h,$ziel_tag,$nm,$ny);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Als Parameter benötigt die Funktion, welches Vorkommen des Wochentags berechnet werden soll (1-4). Soll das letzte Vorkommen berechnet werden, übergibt man 9. Als Wochentag wird 1-7 angegeben, wobei Montag der Wochentag 1 ist. Danach kommen als getrennte Parameter Stunde, Minute und Sekunde. Die Definition sieht dann so aus&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod at_heat1_Treffen_FG_Radverkehr at *{at_xwday(1,2,17,45,0)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_FG_Radverkehr at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Heizung wird für das Treffen der Fachgruppe Radverkehr am ersten Dienstag im Monat auf 21 Grad gestellt. Gleichzeitig wird ein AT gestartet, das die Heizung zwei Stunden später wieder auf 15 Grad reduziert. Kleiner Tipp: Man kann im AT auch zwei FHEM-Befehle hintereinander senden. Klappte in diesem Fall aber nur über den kleinen Umweg über Perl.&lt;br /&gt;
&lt;br /&gt;
== AT alle x Tage ausführen ==&lt;br /&gt;
&lt;br /&gt;
Soll ein Termin z.B. alle sechs Wochen stattfinden, so kann folgende Funktion genutzt werden.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# nächsten Treffens in x Tagen&lt;br /&gt;
&lt;br /&gt;
sub at_xdays($$) {&lt;br /&gt;
	my ($tm,$days) = @_;&lt;br /&gt;
	my $delta = $days * DAYSECONDS;		# Nächster Termin in sec&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;Wrong timespec, use \&amp;quot;yyyy-mm-ddThh:mm:ss\&amp;quot;&amp;quot; if($tm !~ m/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)$/);&lt;br /&gt;
	my ($y,$m,$d,$h,$m2,$s) = ($1,$2,$3,$4,$5,$6);&lt;br /&gt;
	my $abstime = mktime($s,$m2,$h,$d,$m-1,$y-1900, 0,0,-1);&lt;br /&gt;
	my $now = int(time);&lt;br /&gt;
&lt;br /&gt;
	my $diff = $now-$abstime;&lt;br /&gt;
	if ($diff&amp;gt;0){&lt;br /&gt;
    	# bei Neuberechnung sechs Wochen zur aktuellen Zeit addieren&lt;br /&gt;
		# wird auch bei Erstberechnung aufgerufen, wenn Timestamp in der Vergangenheit&lt;br /&gt;
		my $temp = ((int($diff/$delta)+1)*$delta)+$abstime;&lt;br /&gt;
		my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($temp);&lt;br /&gt;
		return mktime($s,$m2,$h,$mday,$mon,$year);&lt;br /&gt;
	} else {return $abstime;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dabei wird der erste Ausführungstermin im FHEM-üblichen Format (&amp;quot;yyyy-mm-ddThh:mm:ss&amp;quot;) und das Intervall in Tagen übergeben. Die Variable $delta enthält dann das Intervall in Sekunden. Es wird zwar mit dem Timestamp gerechnet. Zurückgegeben wird aber das berechnete Datum und die der Funktion übergebene Uhrzeit. Das verhindert Probleme mit der Zeitumstellung. Hier die Definition für einen Termin alle sechs Wochen, beginnend am 29.05.2024 um 18:45 Uhr. Auch hier wird die Heizung zwei Stunden später wieder herunter gestellt.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod at_heat2_Lasse at *{at_xdays(&amp;quot;2024-05-29T18:45:00&amp;quot;,42)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_Lasse at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Dummy&amp;diff=39381</id>
		<title>Dummy</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Dummy&amp;diff=39381"/>
		<updated>2024-07-22T10:22:46Z</updated>

		<summary type="html">&lt;p&gt;F Klee: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{SEITENTITEL:dummy}}  &amp;lt;!-- da richtige Schreibweise kleinen Anfangsbuchstaben hat --&amp;gt;&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Definition von Hilfsobjekten&lt;br /&gt;
|ModType=h&lt;br /&gt;
|ModCmdRef=dummy&lt;br /&gt;
|ModForumArea=Automatisierung&lt;br /&gt;
|ModTechName=98_dummy.pm&lt;br /&gt;
|ModOwner=Rudolf König/rudolfkoenig ({{Link2FU|8|Forum}}/[[Benutzer Diskussion:Rudolfkoenig|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Geräte vom Typ [[dummy]] können für verschiedene Zwecke genutzt werden, die im folgenden anhand von Beispielen aufgeführt werden. Wenn geplant ist, mit einem dummy Schalter zu definieren (Ein-/Ausschaltung), ist wahrscheinlich ein [[readingsProxy]] besser geeignet.  &lt;br /&gt;
&lt;br /&gt;
Zusatzlich zum Device &#039;&#039;dummy&#039;&#039; gibt es auch ein gleichnamiges [[dummy (Attribut)|allgemeingültiges Attribut]].&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Siehe {{Link2CmdRef|Anker=dummydefine}}.&lt;br /&gt;
&lt;br /&gt;
== Attribute ==&lt;br /&gt;
Siehe {{Link2CmdRef|Anker=dummyattr}}.&lt;br /&gt;
&lt;br /&gt;
== Beispiele ==&lt;br /&gt;
=== Jahreszeiten ===&lt;br /&gt;
[[Datei:dummySeasons.png|mini|right|Darstellung mit allen vorgesehenen Icons]]&lt;br /&gt;
Eine typische Anwendung eines &#039;&#039;dummy&#039;&#039; besteht in der Platzierung eines Buttons (Icon, Schaltfläche) auf der Benutzeroberfläche, wobei diesem &amp;quot;Device&amp;quot; unterschiedliche Werte zugeordnet werden können. Im Detail soll das verdeutlicht werden am Dummy &lt;br /&gt;
[[Datei:dummySeasonsInternals.png|mini|right|Auswahlliste in der &#039;&#039;Details&#039;&#039;-Ansicht des &#039;&#039;dummy&#039;&#039; Objekts aufgrund des Attributs &#039;&#039;setState&#039;&#039;]]&lt;br /&gt;
* &#039;&#039;&#039;dy_Season&#039;&#039;&#039;&lt;br /&gt;
* mit dem &#039;&#039;alias&#039;&#039; &#039;&#039;&#039;Jahreszeit&#039;&#039;&#039; und&lt;br /&gt;
* vier vorgesehenen Werten, &lt;br /&gt;
* die jeweils durch ein spezifisches Icon dargestellt und &lt;br /&gt;
* durch Klick auf das Icon gewechselt werden können.&lt;br /&gt;
Hierbei werden die &amp;quot;erlaubten&amp;quot; Werte für den &#039;&#039;state&#039;&#039; durch das Attribut &#039;&#039;[[setList]]&#039;&#039; festgelegt:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr dy_Season setList state:Winter,Frühling,Sommer,Herbst&amp;lt;/code&amp;gt;&lt;br /&gt;
Damit werden &amp;quot;Winter&amp;quot;, &amp;quot;Frühling&amp;quot;, &amp;quot;Sommer&amp;quot;, &amp;quot;Herbst&amp;quot; in der Auswahlliste angeboten.&lt;br /&gt;
&lt;br /&gt;
Die Zuordnung von Icons zu den Werten sowie die Festlegung des Folgezustands nach anklicken des Icons werden mit dem Attribut &#039;&#039;[[devStateIcon]]&#039;&#039; bestimmt:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr dy_Season devStateIcon Sommer:weather_summer:Herbst Frühling:weather_pollen:Sommer Herbst:weather_wind:Winter Winter:weather_winter:Frühling&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der bei diesem &#039;&#039;dummy&#039;&#039; gesetzte Wert (state) kann in Folge z.B. in Bedingungen verwendet werden; hier ein Auszug aus einem [[DOIF]]&lt;br /&gt;
:&amp;lt;code&amp;gt;([12:45] and [dy_Season:state] eq &amp;quot;Sommer&amp;quot;) (...)&amp;lt;/code&amp;gt;&lt;br /&gt;
bei dem die definierte Aktion (...) um 12:45 Uhr nur dann durchgeführt würde, wenn das beschriebene &#039;&#039;dummy&#039;&#039; Objekt auf &amp;quot;Sommer&amp;quot; steht. Generell gesagt lassen sich also mit Hilfe dieses Mechanismus Aktionen in Abhängigkeit einer (benutzerdefinierten!) Jahreszeit bedingt ausführen. &lt;br /&gt;
&lt;br /&gt;
=== ntfy_setreading ===&lt;br /&gt;
{{Randnotiz|RNTyp=[g|Info]|RNText=Es wird nur auf Devices getriggert, die mit &amp;quot;d_&amp;quot; anfangen. Sollten die dummy Devices anders heißen, muss das entsprechend in der DEF angepasst werden.}}&lt;br /&gt;
Wird bei einem Dummy mit [[setList]] gearbeitet, um mehrere Readings in einem Dummy zu haben, erfolgt bei einer Änderung nur das Setzen des Status nach &amp;lt;reading&amp;gt; &amp;lt;value&amp;gt;. Ein Reading wird dabei nicht angelegt oder aktualisiert. Damit dies doch geschieht, muss ein notify nach folgendem Muster angelegt werden:&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{{Randnotiz|RNTyp=y|RNText=Das Konstrukt mit ~~ verursacht massive Warnungen im Log wegen (der Perl Funktion) Smartmatch und ist aus diesem Grund nicht zu empfehlen!}}&lt;br /&gt;
:&amp;lt;code&amp;gt;define ntfy_setreading notify d_.* { if( ($EVENT ~~ / /) and ($EVENT !~ /: /) ) {fhem(&amp;quot;setreading $NAME $EVENT&amp;quot;)} }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== d_label ===&lt;br /&gt;
Für [[readingsGroup]]s kann es hilfreich sein, Überschriften aus einem Reading zu bekommen. So können sie beispielsweise mit valueColumns bearbeitet werden und Sonderzeichen wie {{Taste|:}} oder Leerzeichen ({{Taste| }}) müssen nicht umständlich eingefügt werden.&lt;br /&gt;
:&amp;lt;code&amp;gt;define d_label dummy&amp;lt;/code&amp;gt;&lt;br /&gt;
Durch das [[#ntfy_setreading|ntfy_setreading]] können Labels nun einfach über einen set Befehl erstellt werden:&lt;br /&gt;
:&amp;lt;code&amp;gt;set d_label HHMM (HH:MM)&amp;lt;/code&amp;gt;&lt;br /&gt;
Damit wird ein Reading &#039;&#039;HHMM&#039;&#039; erzeugt mit dem Wert &#039;&#039;(HH:MM)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Statt in einem dummy können diese Hilfs-Readings auch direkt in der readingsGroup untergebracht werden. Auch die Verwendung mit dem !-Flag in der readingsGroup bietet sich an.&lt;br /&gt;
=== set ===&lt;br /&gt;
Mit der Anweisung &lt;br /&gt;
:&amp;lt;code&amp;gt;set &#039;&#039;dummyName&#039;&#039; dummyWert&amp;lt;/code&amp;gt;&lt;br /&gt;
wird dem Dummy &#039;&#039;dummyName&#039;&#039; der  Wert &#039;&#039;dummyWert&#039;&#039; zugewiesen. In der Detail-Ansicht (oder dem &#039;&#039;list&#039;&#039;) von &#039;&#039;dummyName&#039;&#039; erscheint der zugewiesene Wert im &#039;&#039;&#039;Internal&#039;&#039;&#039; &#039;&#039;STATE&#039;&#039; sowie im &#039;&#039;&#039;Reading&#039;&#039;&#039; &#039;&#039;state&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Der folgende Text stammt aus Forentopic #13498 und hat keinen speziellen Bezug zu &#039;dummy&#039; --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Auskommentiert, da in diesem Kontext weder auffindbar noch speziell relevant.&lt;br /&gt;
Man kann fhem Kommandos nicht mit Perl vermischen, wenn der Autor des Moduls, in diesem Fall set es nicht vorgesehen hat.&lt;br /&gt;
Das Kommando &amp;quot;set &amp;lt;dummy&amp;gt; &amp;lt;value&amp;gt;&amp;quot; verändert den Inhalt von &amp;lt;dummy&amp;gt; auf den Text &amp;lt;value&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Achtung, falsch!!:&lt;br /&gt;
&lt;br /&gt;
 set twilight_condition {ReadingsVal(myTwilight, condition, &amp;quot;99&amp;quot;)} &lt;br /&gt;
&lt;br /&gt;
Das dummy twilight_condition wird durch deine Zuweisung vermutlich den Inhalt &amp;quot;{ReadingsVal(myTwilight, condition, &amp;quot;99&amp;quot;)}&amp;quot; bekommen. Der PerlCode wird &#039;&#039;&#039;nicht&#039;&#039;&#039; ausgeführt.&lt;br /&gt;
&lt;br /&gt;
Richtig: &lt;br /&gt;
 fhem (&amp;quot;set twilight_condition &amp;quot; . ReadingsVal(&amp;quot;myTwilight&amp;quot;,&amp;quot;condition&amp;quot;,99)) &lt;br /&gt;
Als ganzes notify, bei jedem Temperaturupdate (Aussen) die Vorlauftemperatur neu berechnen und in Heizung_VL_Soll zur Verfügung stellen: &lt;br /&gt;
 define setVL notify S300TH:temperature.* { fhem(&amp;quot;set Heizung_VL_Soll &amp;quot;. calcVL(ReadingsVal(&amp;quot;Heizung_Slider&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;0&amp;quot;),&amp;quot;0&amp;quot;,&amp;quot;0.5&amp;quot;,&amp;quot;0.7&amp;quot;))}&lt;br /&gt;
-- Ende der auskommentierten, nicht wirklich sachdienlichen Passage --&amp;gt;&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DWD_OpenData&amp;diff=39376</id>
		<title>DWD OpenData</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DWD_OpenData&amp;diff=39376"/>
		<updated>2024-06-28T18:45:59Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* Readings */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Versionsänderung: Die Vorhersagedaten wurden Mitte September 2018 von CSV auf KML umgestellt. Diese Umstellung ist inkompatibel: das DWD_OpenData-Modul muss aktualisiert werden, einige Reading-Namen haben sich geändert und der Weblink muss deinstalliert und neu installiert werden (siehe diesen {{Link2Forum|Topic=83097|Message=840270|Linktext=Beitrag im Forum}}).}} &lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Daten vom DWD OpenData Server abrufen&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModCmdRef=DWD_OpenData&lt;br /&gt;
|ModForumArea=Unterstützende Dienste/Wettermodule&lt;br /&gt;
|ModTechName=55_DWD_OpenData.pm&lt;br /&gt;
|ModOwner=JensB ({{Link2FU|14024|Forum}}/[[Benutzer Diskussion:JensB|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
Der Deutsche Wetterdienst (DWD) stellt Wetterdaten über den [https://www.dwd.de/DE/leistungen/opendata/opendata.html Open Data Server] zur Verfügung. Die Verwendung dieses Dienstes und der vom DWD zur Verfügung gestellten Daten unterliegt den auf der OpenData Webseite beschriebenen Bedingungen. Einen Überblick über die verfügbaren Daten findet man in der Tabelle [https://www.dwd.de/DE/leistungen/opendata/help/inhalt_allgemein/opendata_content_de_en_xls.xls OpenData_weather_content.xls] oder hier: https://opendata.dwd.de/weather/lib/MetElementDefinition.xml.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Aufgrund der unterschiedlichen vom DWD bereitgestellten Datenformate benötigt das Modul zur Dekodierung je nach gewünschtem Funktionsumfang zusätzliche Perl-Module, die nicht standardmäßig vorinstalliert sind und je nach Systemkonfiguration nachinstalliert werden müssen. Außerdem unterstützt das Modul Zeitzonen, um z.B. die Wettervorhersage internationaler Stationen in Ortszeit darstellen zu können. Hierfür sind je nach Systemkonfiguration weitere Einstellungen erforderlich. Auch die Sprache der Wochentage für die Wettervorhersage ist frei wählbar. Je nach Systemkonfiguration ist aber die Standardsprache u.U. auf Englisch eingestellt, was weitere Anpassungen der Systemkonfiguration erforderlich macht.&lt;br /&gt;
&lt;br /&gt;
=== Vorbereitung ===&lt;br /&gt;
Im folgenden wird z.T. von einem System mit Rasbian oder Debian mit System-V Startsystem ausgegangen. Auf anderen Betriebssystemen und auf Systemen mit System-D müssen die Installationsschritte ggf. angepasst werden.&lt;br /&gt;
&lt;br /&gt;
1. Für die Wettervorhersage und die Wetterwarnungen:&lt;br /&gt;
Installation des Perl-Moduls &#039;&#039;XML::LibXML&#039;&#039; über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install libxml-libxml-perl&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
oder mit CPAN.&lt;br /&gt;
&lt;br /&gt;
2. Weiterhin ist das Perl-Modul &#039;&#039; DateTime&#039;&#039; erforderlich. Dieses lässt sich mit &amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;sudo apt-get install libdatetime-perl&amp;lt;/syntaxhighlight&amp;gt; installieren.&lt;br /&gt;
&lt;br /&gt;
3. Falls man einen eigenen Internet-Proxy nutzt:&lt;br /&gt;
Die Konfiguration des Proxies für FHEM erfolgt z.B. durch Eintrag von&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr global proxy &amp;lt;myProxyHost&amp;gt;:&amp;lt;myProxyPort&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
in die [[Konfiguration]], wobei &#039;&#039;myProxyHost&#039;&#039; durch den Namen oder die IP-Adresse des Proxy-Servers ersetzt werden muss und für &#039;&#039;myProxyPort&#039;&#039; der Port des Proxy-Servers eingetragen werden muss (oft 3128).&lt;br /&gt;
&lt;br /&gt;
3. FHEM Uhrzeit und Zeitzone:&lt;br /&gt;
Durch Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 {localtime()}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
in die FHEM-Kommandozeile überprüfen, ob die FHEM-Uhrzeit plausibel ist. Ist dies nicht der Fall sollten die Uhrzeit auf Systemebene überprüft werden und ggf. die Systemeinstellungen angepasst werden.&lt;br /&gt;
Ermitteln der Bezeichnung der eigenen Zeitzone über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  tzselect&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und diese Bezeichnung in die Datei &#039;&#039;/etc/timezone&#039;&#039; eintragen und &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 export TZ=`cat /etc/timezone`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
der Datei &#039;&#039;/etc/profile&#039;&#039; hinzufügen und dann das System neu starten. Nun muss die Zeitanzeige in FHEM korrekt sein.&lt;br /&gt;
&lt;br /&gt;
4. FHEM Sprache:&lt;br /&gt;
Durch Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 {$ENV{LANG}}&lt;br /&gt;
&amp;lt;/pre&amp;gt; in die FHEM-Kommandozeile überprüfen, in welcher Sprache der Wochentag angezeigt wird. Stimmt die Sprache nicht, dann auf der System-Kommandozeile&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dpkg-reconfigure locales&lt;br /&gt;
&amp;lt;/pre&amp;gt; eingeben und aus der Liste z.B. &#039;&#039;de_DE.UTF-8&#039;&#039; zusätzlich auswählen. Dieser Befehl gilt für Debian-basierte Betriebssysteme - für andere Betriebssysteme ist eine analoge Funktion zu verwenden. Mit Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 locale -a&lt;br /&gt;
&amp;lt;/pre&amp;gt; auf der System-Kommandozeile überprüfen, ob die ausgewählte Sprache nun zur Verfügung steht. Sollte FHEM nach einem Neustart noch immer nicht die gewünschte Sprache verwenden, kann man auf einem System V Linux durch Hinzufügen von z.B.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 export LANG=de_DE.UTF-8&lt;br /&gt;
&amp;lt;/pre&amp;gt; in die Datei &#039;&#039;/etc/init.d/fhem&#039;&#039; (irgendwo zwischen &#039;&#039;start&#039;&#039; und &#039;&#039;perl&#039;&#039;) und erneutem Neustart von FHEM die Sprache für FHEM erzwingen. Bei einem Systemd Linux kann man die Einstellungen mit &#039;&#039;systemctl edit --full fhem.service&#039;&#039; bearbeiten. Spätestes jetzt muss die Wochentagsanzeige in FHEM korrekt sein.&lt;br /&gt;
&lt;br /&gt;
5. Nur für den Weblink erforderlich:&lt;br /&gt;
Installation des Perl-Moduls &#039;&#039;DateTime&#039;&#039; über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sudo apt-get install libdatetime-perl&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
oder mit CPAN.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
Siehe {{Link2CmdRef|Anker=DWD_OpenDatadefine|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
Siehe {{Link2CmdRef|Anker=DWD_OpenDataattr|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
=== Readings ===&lt;br /&gt;
Die Prognosewerte sind wie folgt aufgebaut:&lt;br /&gt;
 fc&amp;lt;day&amp;gt;_[&amp;lt;sample&amp;gt;_]&amp;lt;property&amp;gt;&lt;br /&gt;
Eine Beschreibung der über 70 verfügbaren Eigenschaften und ihrer Maßeinheiten finden Sie hier. Die Maßeinheiten für Temperaturen und Windgeschwindigkeiten werden jeweils in °C und km/h umgerechnet. In den folgenden Abschnitten sind nur einige ausgewählte Eigenschaften aufgeführt:&lt;br /&gt;
&lt;br /&gt;
* day – relativer Tag (0 .. 9) basierend auf dem Zeitzonenattribut, wobei 0 für heute steht&lt;br /&gt;
&lt;br /&gt;
* sample – relative Zeit (0 .. 3, 7 oder 23), die einem Vielfachen von 6, 3 oder 1 Stunde UTC entspricht, abhängig vom Attribut forecastResolution&lt;br /&gt;
&lt;br /&gt;
* day properties (normalerweise für 06:00 Uhr Stationszeit, siehe Rohdaten der Station für tatsächliche Zeitbeziehung)&lt;br /&gt;
    date – Datum basierend auf dem Zeitzonenattribut&lt;br /&gt;
    weekday – abgekürzter Wochentag basierend auf dem Zeitzonenattribut in der Sprache Ihres FHEM-Systems&lt;br /&gt;
    Tn [°C] – Mindesttemperatur der letzten 12 Stunden&lt;br /&gt;
    Tx [°C] – Höchsttemperatur der letzten 12 Stunden (normalerweise um 18:00 Stationszeit)&lt;br /&gt;
    Tm [°C] – Durchschnittstemperatur der letzten 24 Stunden&lt;br /&gt;
    Tg [°C] – Mindesttemperatur 5 cm über dem Boden der letzten 12 Stunden&lt;br /&gt;
    PEvap [kg/m2] – Evapotranspiration der letzten 24 Stunden&lt;br /&gt;
    SunD [s] - Gesamtsonnenscheindauer des vorherigen Tages&lt;br /&gt;
&lt;br /&gt;
* hour properties&lt;br /&gt;
    time - Zeit basierend auf dem Zeitzonenattribut&lt;br /&gt;
    TTT [°C] - Trockentemperatur in 2 Metern Höhe über dem Boden&lt;br /&gt;
    Td [°C] - Taupunkttemperatur in 2 Metern Höhe über dem Boden&lt;br /&gt;
    DD [°] - durchschnittliche Windrichtung in 10 m Höhe über dem Boden&lt;br /&gt;
    FF [km/h] - durchschnittliche Windgeschwindigkeit in 10 m Höhe über dem Boden&lt;br /&gt;
    FX1 [km/h] - maximale Windgeschwindigkeit in der letzten Stunde&lt;br /&gt;
    SunD1 [s] - Sonnenscheindauer in der letzten Stunde&lt;br /&gt;
    SunD3 [s] - Sonnenscheindauer in den letzten 3 Stunden&lt;br /&gt;
    RR1c [kg/m2] - Niederschlagsmenge in der letzten Stunde&lt;br /&gt;
    RR3c [kg/m2] - Niederschlagsmenge in den letzten 3 Stunden&lt;br /&gt;
    RR6c [kg/m2] - Niederschlagsmenge in den letzten 6 Stunden&lt;br /&gt;
    R600 [%] - Regenwahrscheinlichkeit in den letzten 6 Stunden&lt;br /&gt;
    RRhc [kg/m2] - Niederschlagsmenge in den letzten 12 Stunden&lt;br /&gt;
    Rh00 [%] - Regenwahrscheinlichkeit in den letzten 12 Stunden&lt;br /&gt;
    RRdc [kg/m2] - Niederschlagsmenge in den letzten 24 Stunden&lt;br /&gt;
    Rd00 [%] - Regenwahrscheinlichkeit in den letzten 24 Stunden&lt;br /&gt;
    ww - Wettercode (siehe WMO 4680/4677, SYNOP)&lt;br /&gt;
    wwd - deutsche Wettercodebeschreibung&lt;br /&gt;
    VV [m] - horizontale Sichtweite&lt;br /&gt;
    Neff [%] - effektive Wolkenbedeckung&lt;br /&gt;
    Nl [%] - untere Wolkenbedeckung unter 2000 m&lt;br /&gt;
    Nm [%] - mittlere Wolkenbedeckung unter 7000 m&lt;br /&gt;
    Nh [%] - hohe Wolkenbedeckung über 7000 m&lt;br /&gt;
    PPPP [hPa] - Druckäquivalent auf Meereshöhe&lt;br /&gt;
&lt;br /&gt;
* Zusätzliche Tageseigenschaften, nicht vom DWD bereitgestellt&lt;br /&gt;
    SunRise - Sonnenaufgangszeit basierend auf dem Zeitzonenattribut&lt;br /&gt;
    SunSet - Sonnenuntergangszeit basierend auf dem Zeitzonenattribut&lt;br /&gt;
&lt;br /&gt;
* Zusätzliche Stundeneigenschaften, nicht vom DWD bereitgestellt&lt;br /&gt;
    SunAz [°] - Sonnenazimut&lt;br /&gt;
    SunEl [°] - Sonnenhöhe&lt;br /&gt;
    SunUp - Sonnenaufgang (0: Nacht, 1: Tag)&lt;br /&gt;
&lt;br /&gt;
Zusätzlich gibt es globale Prognosewerte:&lt;br /&gt;
&lt;br /&gt;
* fc_state - Status der letzten Prognoseaktualisierung, mögliche Werte sind „updated“ und „error: ...“&lt;br /&gt;
* fc_station - Prognosestationscode (WMO oder DWD)&lt;br /&gt;
* fc_description - Stationsbeschreibung&lt;br /&gt;
* fc_coordinates - Weltkoordinate und Höhe der Station&lt;br /&gt;
* fc_time - Zeitpunkt der Veröffentlichung der Prognose basierend auf dem Zeitzonenattribut&lt;br /&gt;
* fc_copyright - rechtliche Informationen, müssen mit Prognosedaten angezeigt werden, siehe DWD-Nutzungsbedingungen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Alarmwerte sind nach Beginn sortiert und folgendermaßen aufgebaut:&lt;br /&gt;
 a_&amp;lt;index&amp;gt;_&amp;lt;property&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* index - Alarmindex, beginnend mit 0, Gesamtanzahl a_count, sortiert nach Beginn&lt;br /&gt;
&lt;br /&gt;
* alert properties&lt;br /&gt;
    category - „Met“ oder „Health“&lt;br /&gt;
    event - numerischer Ereigniscode, siehe DWD-Dokumentation für Details&lt;br /&gt;
    eventDesc - kurze Ereignisbeschreibung in ausgewählter Sprache&lt;br /&gt;
    eventGroup - Ereignisgruppe, siehe DWD-Dokumentation für Details&lt;br /&gt;
    responseType - „None“ = nein Anweisungen, „Vorbereiten“ = Anweisungen, „AllClear“ = Alarm gelöscht&lt;br /&gt;
    urgency – „Immediate“ = Warnung oder „Zukünftig“ = Information&lt;br /&gt;
    severity – „Minor, „Moderate“, „Severe“ or „Extreme“&lt;br /&gt;
    areaColor – RGB-Farbe je nach Dringlichkeit und Schweregrad, durch Komma getrennte Dezimalzahlen&lt;br /&gt;
    onset – Startzeit des Alarms basierend auf dem Zeitzonenattribut&lt;br /&gt;
    expires – Endzeit des Alarms basierend auf dem Zeitzonenattribut&lt;br /&gt;
    headline – Überschrift in ausgewählter Sprache, normalerweise eine Kombination der Eigenschaften Dringlichkeit und Ereignis&lt;br /&gt;
    description – Beschreibung des Alarms in ausgewählter Sprache&lt;br /&gt;
    instruction – Sicherheitsanweisungen in ausgewählter Sprache&lt;br /&gt;
    area – numerische Warnzellen-ID&lt;br /&gt;
    areaDesc – Beschreibung des Bereichs, z. B. „Stadt Berlin“&lt;br /&gt;
    altitude – min. Höhe [m]&lt;br /&gt;
    ceiling – max. Höhe [m]&lt;br /&gt;
&lt;br /&gt;
Zusätzlich gibt es einige globale Alarmwerte:&lt;br /&gt;
&lt;br /&gt;
* a_state – Status der letzten Alarmaktualisierung, mögliche Werte sind „aktualisiert“ und „Fehler: ...“&lt;br /&gt;
&lt;br /&gt;
* a_time – Zeitpunkt des Downloads der letzten Alarmaktualisierung, basierend auf der Zeitzone attribut&lt;br /&gt;
&lt;br /&gt;
* a_count – Anzahl der für die ausgewählte Warnzellen-ID verfügbaren Alarme&lt;br /&gt;
&lt;br /&gt;
* a_copyright – rechtliche Informationen, müssen mit Prognosedaten angezeigt werden, siehe DWD-Nutzungsbedingungen, nicht verfügbar, wenn count null ist&lt;br /&gt;
&lt;br /&gt;
Alarme sollten unabhängig von der Dringlichkeit für onset &amp;lt;= now &amp;lt; expires und responseType != „AllClear“ als aktiv betrachtet werden. Inaktive Alarme mit responseType = „AllClear“ können relevante Anweisungen enthalten.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass alle Alarmwerte bei jeder Aktualisierung vollständig ersetzt und neu indexiert werden!&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zu den Alarmeigenschaften finden Sie in der Dokumentation des CAP DWS-Profils.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
=== Beispiel zur Modul-Einrichtung ===&lt;br /&gt;
&lt;br /&gt;
* Wettervorhersage&lt;br /&gt;
Für die Wettervorhersage muss der Stationscode ermittelt werden. Dazu den [https://www.dwd.de/DE/leistungen/met_verfahren_mosmix/mosmix_stationskatalog.pdf MOSMIX Stationskatalog] herunterladen, öffnen und die gewünschte Station heraussuchen (Spalte &#039;&#039;id&#039;&#039;). Einen Teil der deutschen Stationen kann man auch der [https://www.dwd.de/DE/derdwd/messnetz/bodenbeobachtung/messnetzkarte_boden.pdf Bodenmessnetzkarte] entnehmen. Den ermittelten Stationscode kann man dann entweder für eine Einzelabfrage als Parameter für das Kommando &#039;&#039;get forecast&#039;&#039; verwenden oder für die automatische Aktualisierung als Attribut &#039;&#039;forecastStation&#039;&#039; hinterlegen. Insgesamt werden vom DWD mehr als 70 Merkmale zur Verfügung gestellt. Eine Auflistung findet sich im Dokument [https://opendata.dwd.de/weather/lib/MetElementDefinition.xml MetElementDefinition]. Nur ein kleiner Teil der Merkmale wird in der Standardeinstellung des Moduls als Reading zur Verfügung gestellt. Wer andere Merkmale benötigt muss sie mit Komma getrennt dem Attribut &#039;&#039;forecastProperties&#039;&#039; zuweisen. Es empfiehlt sich zur Performance-Optimierung sowohl das Attribut &#039;&#039;forecastDays&#039;&#039; als auch das Attribut &#039;&#039;forecastProperties&#039;&#039; auf den tatsächlichen Bedarf einzustellen.&lt;br /&gt;
&lt;br /&gt;
* Wetterwarnungen&lt;br /&gt;
Für die Wetterwarnungen muss die Warnzelle ermittelt werden. Dazu [https://www.dwd.de/DE/leistungen/opendata/help/warnungen/cap_warncellids_csv.csv Warnzellen-ID Katalog] herunterladen, öffnen und die gewünschte Warnzelle heraussuchen. Unterstützt werden Gemeinden (beginnen mit 8), Landkreise (beginnen mit 1 oder 9) oder Küste (beginnen mit 5). Die Warnzellen-ID kann man dann entweder für eine Einzelabfrage als Parameter für das Kommando &#039;&#039;get alerts&#039;&#039; verwenden oder für die automatische Aktualisierung als Attribut &#039;&#039;alertArea&#039;&#039; hinterlegen. Die Warnzellen-ID ist ab der 2. Stelle identisch mit den ersten Ziffern des amtlichen Gemeindeschlüssels. Man kann z.B. den Namen von Gemeinde oder Landkreis bei den [https://www.statistik-bw.de/Statistik-Portal/gemeindeverz.asp Statistischen Ämtern des Bundes und der Länder] eingeben, den amtlichen Gemeindeschlüssel ermitteln und dann mit vorangestellter 1, 8 oder 9 im Warnzellen-ID Katalog des DWD nach einem Eintrag mit exakter oder weitgehender Übereinstimmung suchen. Wem das zu kompliziert vorkommt, der kann bei mehrdeutigen Gemeinde- bzw. Landkreisbezeichnungen auch versuchen auszuprobieren, welche die richtige Warnzellen-ID ist.&lt;br /&gt;
&lt;br /&gt;
Um das Modul mit automatisch Aktualisierung von Vorhersage und Wetterwarnungen zu nutzen, kann z.B. folgendes in die [[Konfiguration]] eingetragen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 define DWD DWD_OpenData&lt;br /&gt;
 attr DWD alertArea 111000000&lt;br /&gt;
 attr DWD forecastStation 99810&lt;br /&gt;
 attr DWD forecastDays 3&lt;br /&gt;
 attr DWD forecastWW2Text 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Performance&lt;br /&gt;
Das DWD_OpenData-Modul ist ein Datenmodul mit relativ vielen Readings. In der Standardkonfiguration wird, wie bei jedem anderen FHEM Modul, bei jeder Änderung jedes Readings ein FHEM internes Ereignis erzeugt, damit andere FHEM Devices auf diese Änderungen reagieren können. Diese Ereignisse sorgen auch dafür, dass man Änderungen in der Weboberfläche sofort angezeigt bekommt, ohne die Webseite neu aufzurufen. Interessiert sich aber kein FHEM Device für die Änderungsbenachrichtigung bestimmter Readings, entsteht unnötiger Verarbeitungs-Overhead, der je nach FHEM Konfiguration und verfügbarer CPU-Leistung auch mehrere Sekunden benötigen kann und in dieser Zeit andere Abläufe blockiert. Um die Performance zu optimieren, empfiehlt es sich,  mit [[event-on-update-reading]] für eine angepasste und dadurch effizientere Verarbeitung zu sorgen, indem man nur für jene Readings Ereignisse zulässt, welche man für die Weiterverarbeitung braucht. Der DWD_OpenData_Weblink braucht z.B. gar keine Ereignisse, um zu funktionieren. Hier eine minimalistische Beispielkonfiguration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr DWD event-on-update-reading state,fc_state,a_state&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Details zur Installation und Konfiguration des Moduls finden sich in der&lt;br /&gt;
{{Link2CmdRef|Anker=DWD_OpenData|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für die Einrichtung eines Meteogramms ===&lt;br /&gt;
Um den vorhergesagten Wetterverlauf als Meteogramm in Kurvenform mit [[SVG]] darzustellen, kann man wie folgt vorgehen:&lt;br /&gt;
&lt;br /&gt;
1. 99_myUtils.pm&lt;br /&gt;
&lt;br /&gt;
Für die Bestimmung der Werte für den SVG-Plot wird eine Perl-Funktion benötigt, die in die Datei 99_myUtils.pm vor dem Ende eingefügt wird. Wer diese FHEM-Datei noch nicht nutzt, legt sie einfach an (siehe [[99_myUtils_anlegen]]).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
package main;&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
 &lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# (c) mumpitzstuff 19.12.2018&lt;br /&gt;
#&lt;br /&gt;
# see https://forum.fhem.de/index.php/topic,83097.msg874150.html#msg874150&lt;br /&gt;
#&lt;br /&gt;
sub logProxy_dwd2Plot($$$$;$$$)&lt;br /&gt;
{&lt;br /&gt;
  my ($device, $fcValue, $from, $to, $fcHour, $expMode, $shiftTime) = @_;&lt;br /&gt;
  my $regex;&lt;br /&gt;
  my @rl;&lt;br /&gt;
&lt;br /&gt;
  return undef if(!$device);&lt;br /&gt;
&lt;br /&gt;
  if ($fcValue =~ s/_$//)&lt;br /&gt;
  {&lt;br /&gt;
    $regex = &amp;quot;^fc[\\d]+_[\\d]+_&amp;quot;.$fcValue.&amp;quot;\$&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    $regex = &amp;quot;^fc[\\d]+_&amp;quot;.$fcValue.&amp;quot;\$&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $fcHour = 12 if(!defined($fcHour));&lt;br /&gt;
  $expMode = &amp;quot;point&amp;quot; if(!defined($expMode));&lt;br /&gt;
  #Log3 undef,2, &amp;quot;Regex: &amp;quot;.$regex;&lt;br /&gt;
&lt;br /&gt;
  # ermitteln aller relevanten Readings&lt;br /&gt;
  if ( defined($defs{$device}) )&lt;br /&gt;
  {&lt;br /&gt;
    if ( $defs{$device}{TYPE} eq &amp;quot;DWD_OpenData&amp;quot; )&lt;br /&gt;
    {&lt;br /&gt;
      @rl = sort&lt;br /&gt;
      {&lt;br /&gt;
        my ($an) = ($a =~ m/fc(\d+)_.*/);&lt;br /&gt;
        my ($bn) = ($b =~ m/fc(\d+)_.*/);&lt;br /&gt;
        my ($ao) = ($a =~ m/fc\d+_(\d+).*/);&lt;br /&gt;
        my ($bo) = ($b =~ m/fc\d+_(\d+).*/);&lt;br /&gt;
        $an &amp;lt;=&amp;gt; $bn or $ao &amp;lt;=&amp;gt; $bo or $a cmp $b;&lt;br /&gt;
      } ( grep /${regex}/,keys %{$defs{$device}{READINGS}} );&lt;br /&gt;
      return undef if ( !@rl );&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      Log3 undef, 2, &amp;quot;logProxy_dwd2Plot: $device is not a DWD_OpenData device&amp;quot;;&lt;br /&gt;
      return undef;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my $fromsec = SVG_time_to_sec($from);&lt;br /&gt;
  my $tosec   = SVG_time_to_sec($to);&lt;br /&gt;
  my $sec = $fromsec;&lt;br /&gt;
  my ($h, $hp, $fcDay, $mday, $mon, $year);&lt;br /&gt;
  my $timestamp;&lt;br /&gt;
&lt;br /&gt;
  my $reading;&lt;br /&gt;
  my $value;&lt;br /&gt;
  my $prev_value;&lt;br /&gt;
  my $min = 999999;&lt;br /&gt;
  my $max = -999999;&lt;br /&gt;
  my $ret = &amp;quot;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  # while not end of plot range reached&lt;br /&gt;
  while (($sec &amp;lt; $tosec) &amp;amp;&amp;amp; @rl)&lt;br /&gt;
  {&lt;br /&gt;
    #remember previous value for start of plot range&lt;br /&gt;
    $prev_value = $value;&lt;br /&gt;
&lt;br /&gt;
    $reading = shift @rl;&lt;br /&gt;
    ($fcDay) = $reading =~ m/^fc(\d+).*/;&lt;br /&gt;
    ($hp) = $reading =~ m/^fc\d+_(\d+).*/;&lt;br /&gt;
    #Log 1, &amp;quot;hp: &amp;quot;.$hp;&lt;br /&gt;
&lt;br /&gt;
    if ($hp)&lt;br /&gt;
    {&lt;br /&gt;
      $h = ReadingsVal($device, &amp;quot;fc&amp;quot;.$fcDay.&amp;quot;_&amp;quot;.$hp.&amp;quot;_time&amp;quot;, $fcHour);&lt;br /&gt;
      if ($h =~ m/^(\d+):\d+/)&lt;br /&gt;
      {&lt;br /&gt;
        $h = $1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      $h = $fcHour;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $value = ReadingsVal($device, $reading, undef);&lt;br /&gt;
&lt;br /&gt;
    # calculate minutes of sunshine per hour&lt;br /&gt;
    if ($fcValue =~ /^SunD(\d+)/)&lt;br /&gt;
    {&lt;br /&gt;
      if (defined($1))&lt;br /&gt;
      {&lt;br /&gt;
        $value = $value / ($1 * 36);&lt;br /&gt;
      }&lt;br /&gt;
      else&lt;br /&gt;
      {&lt;br /&gt;
        $value = $value / (12 * 36);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # calculate amount of rain per hour&lt;br /&gt;
    if ($fcValue =~ /^RR(\d+)c$/)&lt;br /&gt;
    {&lt;br /&gt;
      if (defined($1))&lt;br /&gt;
      {&lt;br /&gt;
        $value /= $1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    ($year, $mon, $mday) = split(&#039;\-&#039;,ReadingsVal($device, &amp;quot;fc&amp;quot;.$fcDay.&amp;quot;_date&amp;quot;,undef));&lt;br /&gt;
    $timestamp = sprintf(&amp;quot;%04d-%02d-%02d_%02d:%02d:%02d&amp;quot;, $year, $mon, $mday, $h, 0, 0);&lt;br /&gt;
    $sec = SVG_time_to_sec($timestamp);&lt;br /&gt;
    if (defined($shiftTime))&lt;br /&gt;
    {&lt;br /&gt;
      $sec += $shiftTime;&lt;br /&gt;
      $timestamp = logProxy_shiftTime($timestamp, $shiftTime);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # skip all values before start of plot range&lt;br /&gt;
    next if ( $sec &amp;lt; $fromsec );&lt;br /&gt;
&lt;br /&gt;
    # add first value at start of plot range&lt;br /&gt;
    if ( !$ret &amp;amp;&amp;amp; $prev_value )&lt;br /&gt;
    {&lt;br /&gt;
      $min = $prev_value if ( $prev_value &amp;lt; $min );&lt;br /&gt;
      $max = $prev_value if ( $prev_value &amp;gt; $max );&lt;br /&gt;
      $ret .= &amp;quot;$from $prev_value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # done if after end of plot range&lt;br /&gt;
    last if ($sec &amp;gt; $tosec);&lt;br /&gt;
&lt;br /&gt;
    $min = $value if ( $value &amp;lt; $min );&lt;br /&gt;
    $max = $value if ( $value &amp;gt; $max );&lt;br /&gt;
&lt;br /&gt;
    # add actual control point&lt;br /&gt;
    $ret .= &amp;quot;$timestamp $value\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (($sec &amp;lt; $tosec) &amp;amp;&amp;amp; !@rl &amp;amp;&amp;amp; ($expMode eq &amp;quot;day&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
    $timestamp = sprintf(&amp;quot;%04d-%02d-%02d_%02d:%02d:%02d&amp;quot;, $year, $mon, $mday, 23, 59, 59);&lt;br /&gt;
    $_ = SVG_time_to_sec($timestamp);&lt;br /&gt;
    if (defined($shiftTime))&lt;br /&gt;
    {&lt;br /&gt;
      $_ += $shiftTime;&lt;br /&gt;
      $timestamp = logProxy_shiftTime($timestamp, $shiftTime);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($_ &amp;lt; $tosec)&lt;br /&gt;
    {&lt;br /&gt;
      $ret .= &amp;quot;$timestamp $value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      $ret .= &amp;quot;$to $value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  elsif (($sec &amp;gt; $tosec) &amp;amp;&amp;amp; ($expMode eq &amp;quot;day&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
    $value = $prev_value + ($value - $prev_value) * (86400 + ($tosec - $sec)) / 86400;&lt;br /&gt;
    $ret .= &amp;quot;$to $value\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ($ret, $min, $max, $prev_value);&lt;br /&gt;
} &lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. LogProxy&lt;br /&gt;
&lt;br /&gt;
Wer bereits ein [[logProxy]]-Device hat, muss den Namen seines logProxy-Devices in die weiter unter aufgeführte GPlot-Konfiguration eintragen. Ansonsten wird es wie folgt neu erstellt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define LogProxy logProxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. FileLog&lt;br /&gt;
&lt;br /&gt;
Das Meteogramm kennt anders als andere FHEM-Plots keine Vergangenheit außer heute. Trotzdem wird aus formalen Gründen ein [[FileLog]]-Device benötigt. Dazu kann ein beliebiges vorhandenes FileLog-Device verwendet werden. Wer will, kann hierfür aber auch ein neues FileLog Device für das DWD_OpenData-Device anlegen (Achtung: wird schnell umfangreich):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define FileLog_DWD FileLog ./log/DWD-%Y-%m.log DWD&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im folgenden wird für das FileLog-Device der Platzhalter &#039;&#039;FileLog_Dummy&#039;&#039; verwendet, der mit dem Namen des gewählten FileLog-Devices zu ersetzen ist.&lt;br /&gt;
&lt;br /&gt;
4. SVG Plot&lt;br /&gt;
&lt;br /&gt;
Das eigentliche Meteogramm ist ein SVG-Device. Will man mehrere Tage darstellen bietet sich die folgende Definition an:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_DWD SVG FileLog_Dummy:SVG_DWD:CURRENT&lt;br /&gt;
attr SVG_DWD fixedoffset 6&lt;br /&gt;
attr SVG_DWD fixedrange 7days&lt;br /&gt;
attr SVG_DWD nrAxis 1,2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei muss das SVG-Attribut &#039;&#039;fixedoffset&#039;&#039; entweder gleich oder kleiner als die Einstellung des DWD_OpenData-Attributs &#039;&#039;forecastDays&#039;&#039; (Standardwert: 6 Tage) gewählt werden und das SVG-Attribut &#039;&#039;fixedrange&#039;&#039; um eins größer als &#039;&#039;fixedoffset&#039;&#039; eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Will man stattdessen nur die nächsten 24 Stunden anzeigen, nimmt man folgende Einstellungen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_DWD SVG FileLog_Dummy:SVG_DWD:CURRENT&lt;br /&gt;
attr SVG_DWD endPlotNow 1&lt;br /&gt;
attr SVG_DWD fixedoffset 1&lt;br /&gt;
attr SVG_FileLog_WETTER_DWD_3 label &amp;quot;Tmin: $data{max1} °C, Tmax: $data{min1} °C&amp;quot;&lt;br /&gt;
attr SVG_DWD nrAxis 1,2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um die DWD_OpenData-Readings mit dem Plot zu verknüpfen, muss man nun die GPlot-Konfigurationsdatei des SVG-Plots manuell bearbeiten. Dazu auf den Link klicken, der im SVG_DWD-Device am Internal &#039;&#039;GPLOTFILE&#039;&#039; steht. Die y-Wertebereiche für die Regenmenge und die Temperaturen sind im Beispiel auskommentiert (Autorange). Das kann man so lassen oder man stellt sie nach den eigenen Wetter-Gegebenheiten ein. Je nach Konfiguration des DWD_OpenData-Attributs &#039;&#039;forecastResolution&#039;&#039; sind aber noch einige weitere Einstellungen anzupassen. Das folgende Beispiel ist für die 3h-Auflösung:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;Wettervorhersage&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid ytics&lt;br /&gt;
set ylabel &amp;quot;Regen [mm]&amp;quot;&lt;br /&gt;
#set yrange [0:4]&lt;br /&gt;
set y2label &amp;quot;Temperatur [°C]&amp;quot;&lt;br /&gt;
#set y2range [-5:35]&lt;br /&gt;
set y3label &amp;quot;Wolken/Regen/Sonne [%]&amp;quot;&lt;br /&gt;
set y3range [0:100]&lt;br /&gt;
&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tx&amp;quot;,$from,$to,18,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tn&amp;quot;,$from,$to,6,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD3_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR3c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R600_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstX:TimeNow(),0,100&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;T&#039; ls l0 lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Tmax&#039; ls l0dot lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Tmin&#039; ls l0dot lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Sonne&#039; ls l4fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Regenmenge&#039; ls l2fill lw 1 with steps,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wind&#039; ls l1 lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Regen&#039; ls l5fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wolken&#039; ls l6fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 notitle ls l5 lw 4 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 notitle ls l5 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verwendet man dagegen eine Auflösung von 1 Stunde, sind folgende LogProxy-Einträge erforderlich:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tx&amp;quot;,$from,$to,18,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tn&amp;quot;,$from,$to,6,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR1c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R101_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-0.5*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstX:TimeNow(),0,100&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für die Darstellung der nächsten 24 Stunden mit einer Auflösung von 1 Stunde nimmt man folgende GPlot-Konfiguration:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;L1&amp;gt;&#039;&lt;br /&gt;
set ytics&lt;br /&gt;
set y2tics&lt;br /&gt;
set y3tics&lt;br /&gt;
set grid xtics y2tics&lt;br /&gt;
set ylabel &amp;quot;Regen [mm]&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Temperatur [°C]&amp;quot;&lt;br /&gt;
set y3label &amp;quot;Wolken/Regen/Sonne [%]&amp;quot;&lt;br /&gt;
set y3range [0:100]&lt;br /&gt;
&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR1c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R101_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-0.5*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;T&#039; ls l0 lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Sonne&#039; ls l4fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Regenmenge&#039; ls l2fill lw 1 with steps,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wind&#039; ls l1 lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Regen&#039; ls l5fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wolken&#039; ls l6fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 notitle ls l2 lw 2 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nachdem, welche Auflösung man verwendet, werden unterschiedliche Readings des DWD_OpenData-Devices benötigt. Diese sind in den LogProxy-Zeilen in der GPlot-Konfigurationsdatei zu finden und müssen auf jeden Fall dem Attribut &#039;&#039;forecastProperties&#039;&#039; des DWD_OpenData-Device hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
Viele Detaileinstellungen des Meteogramms lassen sich individualisieren. Man kann z.B. mehr oder weniger Daten anzeigen und zumindest für &#039;&#039;heute&#039;&#039; auch aktuelle Messwerte hinzufügen.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel für ein Meteogramm über 4 Tage mit 3 Stunden Auflösung:&lt;br /&gt;
&lt;br /&gt;
[[File:DWDODmeteogram4d3h.png|500px]]&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für die Einrichtung eines Weblinks ===&lt;br /&gt;
Zur graphischen Darstellung der Vorhersage und der Wetterwarnungen mit [[FHEMWEB]] steht das Modul [https://raw.githubusercontent.com/jnsbyr/fhem/master/FHEM/98_DWD_OpenData_Weblink.pm 98_DWD_OpenData_Weblink.pm] zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Zunächst die Moduldatei herunterladen und in das Modulverzeichnis &#039;&#039;fhem/FHEM&#039;&#039; kopieren. Entweder die Datei direkt auf den FHEM-Server herunterladen (z.B. mit &#039;&#039;wget&#039;&#039;) oder beim indirekten Herunterladen darauf achten, dass dabei das Encoding nicht verändert wird (also z.B. bei WinSCP den Binär-Modus und nicht den Text-Modus verwenden). Ansonsten werden später z.B. Sonderzeichen wie &#039;&#039;°C&#039;&#039; falsch angezeigt. &lt;br /&gt;
&lt;br /&gt;
Anschließend kann in die [[Konfiguration]] z.B. folgendes eingetragen werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
 define DWD_Weblink_Generator DWD_OpenData_Weblink&lt;br /&gt;
 attr DWD_Weblink_Generator IODev DWD&lt;br /&gt;
 attr DWD_Weblink_Generator forecastDays 4&lt;br /&gt;
 # refreshRate nur dann setzten, wenn der Browser Java-Script beherrscht:&lt;br /&gt;
 attr DWD_Weblink_Generator refreshRate 900&lt;br /&gt;
 &lt;br /&gt;
 define DWD_Weblink weblink htmlCode { DWD_OpenData_Weblink::AsHtmlH(&amp;quot;DWD_Weblink_Generator&amp;quot;) } &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit legt man das Weblink-Generator-Device an und verknüpft es mit dem DWD_OpenData-Device. Außerdem wird der [[weblink ]] selbst angelegt, der seinerseits mit dem Weblink-Generator-Device verknüpft wird. Der Weblink benötigt für seine Funktion eine bestimmte Auswahl der Vorhersage-Merkmale. Wer das Attribut &#039;&#039;forecastProperties&#039;&#039; des DWD_OpenData-Moduls anpassen will, muss diese Merkmale auf jeden Fall mit berücksichtigen. &lt;br /&gt;
&lt;br /&gt;
Wenn vom Weblink nichts im Browser zu sehen ist, kann das daran liegen, dass der Browser kein aktuelles JavaScript verwendet oder JavaScript deaktiviert ist. Dann sollte das Attribut &#039;&#039;refreshRate&#039;&#039; auf 0 Sekunden eingestellt oder gelöscht werden. Mit aktiviertem Refresh werden die Daten auch ohne Seitenneuaufbau regelmäßig und bei Tab-Wechsel aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Die Liste der erforderlichen Vorhersage-Merkmale finden sich zusammen mit allen weiteren Details zur Installation und Konfiguration in der Modulhilfe von &#039;&#039;98_DWD_OpenData_Weblink.pm&#039;&#039;, die man z.B. nach dem Anlegen des Weblink-Generator-Devices über die Weboberfläche abrufen kann.&lt;br /&gt;
&lt;br /&gt;
Hier ein Ausschnitt aus der Darstellung des Weblinks mit [[FHEMWEB]]:&lt;br /&gt;
[[File:DWDODweblink.png|500px]]&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für die Einbindung auf einer Webseite außerhalb von FHEM ===&lt;br /&gt;
Für manche Anwendungsfälle, etwa die Ansicht in FTUI, ist es erforderlich, das mit dem &#039;&#039;&#039;DWD_Weblink_Generator&#039;&#039;&#039; erzeugte Bild an anderer Stelle in eine Webseite einzubinden. Dazu kann man folgende Schritte verwenden. &lt;br /&gt;
&lt;br /&gt;
Zunächst wird ein statisches CSS-Stylesheet erzeugt, etwa in der Datei &#039;&#039;ftui_weather.css&#039;&#039; im Unterverzeichnis &#039;&#039;css&#039;&#039;. Dorthin werden die ganzen CSS-Klassen geschrieben, die der Webbrowser benötigt, um aus den Daten des DWD_Weblink_Generator eine Tabelle zu machen (siehe den etwas länglichen Code am Ende dieses Abschnitts).&lt;br /&gt;
&lt;br /&gt;
Dann ist zunächst dafür zu sorgen, dass im Header der Webseite, die später die Wettervorhersage anzeigen soll, dieses Stylesheet eingebunden wird. Dazu muss in den Header die Zeile&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;css/ftui_weather.css&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
eingetragen werden.&lt;br /&gt;
&lt;br /&gt;
Der zweite Schritt besteht darin, ebenfalls in den Header der betreffenden Webseite ein paar Zeilen JavaScript einzubinden, die dem Holen der Daten dienen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
    function getDWDOpenDataWeblink() {&lt;br /&gt;
        var fwcsrf = &amp;quot;&amp;lt;HIER DER csrf-Token DES ENTFERNTEN FHEM-SERVERS&amp;gt;&amp;quot;;&lt;br /&gt;
        $. get (&amp;quot;http://&amp;lt;HIER DIE ADRESSE DES ENTFERNTEN FHEM-SERVERS&amp;gt;:8083/fhem?cmd=get%20DWD_Weblink_Generator%20horizontalForecast&amp;amp;XHR=1&amp;amp;fwcsrf=&amp;quot; + fwcsrf,&lt;br /&gt;
        function (forecastElements) {&lt;br /&gt;
            $(&amp;quot;#DWD_OpenData_Weblink&amp;quot;).html(forecastElements);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    function getdata() {&lt;br /&gt;
        getDWDOpenDataWeblink();&lt;br /&gt;
        setInterval(getDWDOpenDataWeblink, 900000);&lt;br /&gt;
        $(window).on(&amp;quot;focus&amp;quot;, getDWDOpenDataWeblink);&lt;br /&gt;
    };&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der dritte Schritt besteht darin, auf der betreffenden Webseite einen Ort zu definieren, an welchen das Wettervorhersagebild geschoben wird, z.B.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;DWD_OpenData_Weblink&amp;quot; style=&amp;quot;position:absolute; left:10px;top:500px; width:600px; height:200px; float:left; overflow-y:hidden;overflow-x:auto;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der letzte Schritt sorgt dafür, dass die oben definierte JavaScript-Funktion beim Laden der Webseite auch aufgerufen wird. Dazu muss ein entsprechendes Attribut im body-Tag der Seite eingebaut werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;body onload=&amp;quot;getdata()&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nachstehend nun der etwas längliche CSS-Code für das statische Stylesheet:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
/* weather table with fixed column width */&lt;br /&gt;
.weatherForecast {&lt;br /&gt;
    display: table;&lt;br /&gt;
    table-layout: fixed;&lt;br /&gt;
    column-gap: 40px;&lt;br /&gt;
}&lt;br /&gt;
/* weather table header row */&lt;br /&gt;
.weatherHeaderRow {&lt;br /&gt;
    display: table-header-group;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
/* weather table data row */&lt;br /&gt;
.weatherDataRow {&lt;br /&gt;
    display: table-row-group;&lt;br /&gt;
}&lt;br /&gt;
/* weather table data cells */&lt;br /&gt;
#weatherFontBold {&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
.weatherWeekday {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    min-width: 80px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.weatherCondition {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    position: relative;&lt;br /&gt;
    top: -4px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    font-size: 80%;&lt;br /&gt;
    word-wrap: break-word;&lt;br /&gt;
}&lt;br /&gt;
.weatherTemperature {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    font-size: 100%;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
.weatherWind {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    font-size: 80%;&lt;br /&gt;
    padding-top: 3px;&lt;br /&gt;
}&lt;br /&gt;
/* weather table condition icon cell */&lt;br /&gt;
.weatherIcon {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    position: relative;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
/* weather icon */&lt;br /&gt;
.weatherIcon img {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
/* embedded alert icon with pointer support */&lt;br /&gt;
.weatherAlertIcon {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    top: 5px;&lt;br /&gt;
    right: 5px;&lt;br /&gt;
    width: 25px;&lt;br /&gt;
    height: 22px;&lt;br /&gt;
    background-size: 25px 22px;&lt;br /&gt;
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAkCAMAAADM4ogkAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NjcyOSwgMjAxMi8wNS8wMy0xMzo0MDowMyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDEyLjAgV2luZG93cyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1RjU1NzJBRDMyRTcxMUU1QTk4MkI0RTkwODEwODQ1QSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1RjU1NzJBRTMyRTcxMUU1QTk4MkI0RTkwODEwODQ1QSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjVGNTU3MkFCMzJFNzExRTVBOTgyQjRFOTA4MTA4NDVBIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjVGNTU3MkFDMzJFNzExRTVBOTgyQjRFOTA4MTA4NDVBIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+oFydjAAAAwBQTFRF9fX267W51Csy9d7c1VBV9uPc/vz89+nl5YB/2Flk2mZp1Cgv0Csw5pWR7K2t1Soy1Cow7b6y0iUr+/r61jI54X+A+uvq21xV44qO/fj400tU1kxG3nNx2mJp34Bz/Pj2a2tr4Ht91S43fn5+1jA31S0y0iYu1TA1/ff3+/TxEhIS3W1u1jA010Q++efj1kVH1Tk+gYGB6qWh4oWEtra21TI48sjH1VVc1tbW1jY22ltd4YF/1kFHl5eX/vz7/Pz84nZt+evt9+Tm2mNu1Sw14YSD1Ss04YKC0isv4X5/0zc21CUu8cnL0jA20jAz22xy1jE422Zv1i800isw1Cgx11xjKysr1FFZ4X190iQsGRkZ0jY+1TE41Cww0y0y0ykt1i431i4z0y800ikvPz4/AAAA////DQwM1TI30yYs1TE31TA21TE21S401S801S810ycs//7+1TA3///+/v791TI2/v//0Sov0iYt0yYt6urqkZGR1TM40ycu1S414ODg4YB3+/Hw7bK0/vv78fHxh4eH+OPf0i8w1DI30icu1y843Zia/PX13Nvb6aWZ4YKE+fDv21RT00E83G5y3m9x7tDF3Gdu99fW1EJK1ktK3t7e5I+R4oeH3WNp3oCF+vH16ZOJ1Sw27cG31i018dDL4qOf3Wde7Kqe+O7m2ERH+e3o+u/t4YuY/Pb15IqG5p2R4np52TA82mhx2V1p3mpx5oWL66uiRkZG4YOR/v7+1ygz1TxC8dDV9dHS2VJL1CUw8by79+Hg7bq3vr6+9dnR1Tc49d/X11le77yv22hl2lVY+Ofo33540icspqan+/f49N/h5J6m2HB7zczN3nZ88c3FsrKz3HZ74ICC4YGA1oJy10JD+Onj8c3J1Dk71T494oaE4HpxNTU14XRz7Ozs7+/vcG9v+/bz/Pj1/fr3IiIi676/5IJx4Hpr6amn56On6aGd2mlu4X2A22Vm2WFk1jI33GNk+/Ds2VJU2FZW8/Pz78jD3V1v55iY3W1x////C1yJRAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAMKSURBVHjajNEFWBNxGAbwOXEoUzYnqCgGuPMUUFE8sRuwgDlUEJmK8z6/XWyEEjrswu7u7u7u7u4u7G7FWxoj/J6L9/7v77nnQpTpMM7XFkocV0UOK2VKbkt3/R+4KY0Zlnw8d7ikBeu9VroRcoXPg5F1Y5Mn5wYPaRnGqOxMfPbIGXZfFMxxJGtg0lxzhoWlKpYfSrCd9f4rc4JPKs1l9B1aeabGoLRQTnBxG8T2K2DwLV7FRVTOHi47yKKmxGyAagoGxb7x2cLSMuS0eZIAMopJUaWtkR3M1yUBpe8lkuoj4WYYm8Bf98gaxjdsSik7toKydPQ0OKEzUnGuWcOLWgZPXoCe3Wi6HlS+zVMG/35Zwfq7eqO+wxk4T9N0OYDXKQylnZ4VnKdxM5bfAtDTh6arAlT4IldxXYo6woyS3hwxpRHA12ia7gUA3yKUKL8f7wCPiClMOSsA0VPTMwIkeeoQm+39F1asZECZ02kBFGlH06eEM+Rt0RvFHyX/wNUy7JGex9Q3EGB1U4BCLVXK9D1/wxu1lJS8lMTc36Pp/eZQcaoM9Us9/oSJL8QUGbrDXMNmOvqBJe3TxqC22p/wgIbBlrMsLZSju1pT93dSZDsW/Q3rF/NG3r+xte4zqKY1QY0IBuVvwQ4LazFGUTzRVhexJziahkzyTht8PM6AwXUbWbutj3za2W+5IIxEovYAKxwlww+KV7buYTfzL7TODOGry/tb4KdaCSg/VsFWDfSx/ELLLK9CILl9hBnOEaOq4DN7BZe6lv36++plJ3ST/zDBfEOEN6udBNnNWDHFhTpnihIbNkXKUNfLyyuqeciVOwFvr7oHrApqHhTiPjog6EqdNVFVDIji/JmiiYQbopFM3R0XF6fT6VJ15jFFnUJhSqQRETV5RXfnGykhMea9B2M624ezBaOmuKiv1GDg9TxJ8sIxltB7E0QsT/BqpdrPT9g4P7VaTcZKL4vGDP/psq71BpdSLj9nTmod3mTC+HDfN+FN2jodjlwfGRnoFNg2cH2B7+ca/xJgAFL1l3PxpIx4AAAAAElFTkSuQmCC);&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:hover {&lt;br /&gt;
    opacity: 0.7;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus {&lt;br /&gt;
    opacity: 1.0;&lt;br /&gt;
}&lt;br /&gt;
/* opaque white background for alerts dialog */&lt;br /&gt;
.weatherOverlay {&lt;br /&gt;
    display: none;&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    z-index: 1;&lt;br /&gt;
    opacity: 0.2;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    background: white;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus .weatherOverlay {&lt;br /&gt;
    display: block;&lt;br /&gt;
}&lt;br /&gt;
/* alerts dialog box */&lt;br /&gt;
[class ^= weatherAlertBox] {&lt;br /&gt;
    display: none;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    z-index: 2;&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    border: 3px solid white;&lt;br /&gt;
    border-radius: 3px;&lt;br /&gt;
    box-shadow: 0px 0px 6px 4px #666;&lt;br /&gt;
    background: #EEE;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus .weatherAlertBoxLeft {&lt;br /&gt;
    display: block;&lt;br /&gt;
    right: -268px;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus .weatherAlertBoxCenter {&lt;br /&gt;
    display: block;&lt;br /&gt;
    left: -178px;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus .weatherAlertBoxRight {&lt;br /&gt;
    display: block;&lt;br /&gt;
    left: -312px;&lt;br /&gt;
}&lt;br /&gt;
/* alerts dialog close button */&lt;br /&gt;
.weatherAlertsClose {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    top: -12px;&lt;br /&gt;
    right: -13px;&lt;br /&gt;
&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    box-shadow: 1px 1px 3px #666;&lt;br /&gt;
&lt;br /&gt;
    line-height: 21px;&lt;br /&gt;
    width: 21px;&lt;br /&gt;
    background: #606061;&lt;br /&gt;
&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    text-decoration: none;&lt;br /&gt;
    font-family: Sans-serif;&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: white;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertsClose:hover {&lt;br /&gt;
    opacity: 0.8;&lt;br /&gt;
}&lt;br /&gt;
/* alerts dialog title */&lt;br /&gt;
.weaterAlertsTitle {&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: black;&lt;br /&gt;
}&lt;br /&gt;
/* alert messages */&lt;br /&gt;
[class ^= weaterAlertMessage] {&lt;br /&gt;
    float: left;&lt;br /&gt;
    text-align: left;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
.weaterAlertMessage p {&lt;br /&gt;
    white-space: normal;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DWD_OpenData&amp;diff=39375</id>
		<title>DWD OpenData</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DWD_OpenData&amp;diff=39375"/>
		<updated>2024-06-28T18:45:05Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Formattierung optimiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Versionsänderung: Die Vorhersagedaten wurden Mitte September 2018 von CSV auf KML umgestellt. Diese Umstellung ist inkompatibel: das DWD_OpenData-Modul muss aktualisiert werden, einige Reading-Namen haben sich geändert und der Weblink muss deinstalliert und neu installiert werden (siehe diesen {{Link2Forum|Topic=83097|Message=840270|Linktext=Beitrag im Forum}}).}} &lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Daten vom DWD OpenData Server abrufen&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModCmdRef=DWD_OpenData&lt;br /&gt;
|ModForumArea=Unterstützende Dienste/Wettermodule&lt;br /&gt;
|ModTechName=55_DWD_OpenData.pm&lt;br /&gt;
|ModOwner=JensB ({{Link2FU|14024|Forum}}/[[Benutzer Diskussion:JensB|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
Der Deutsche Wetterdienst (DWD) stellt Wetterdaten über den [https://www.dwd.de/DE/leistungen/opendata/opendata.html Open Data Server] zur Verfügung. Die Verwendung dieses Dienstes und der vom DWD zur Verfügung gestellten Daten unterliegt den auf der OpenData Webseite beschriebenen Bedingungen. Einen Überblick über die verfügbaren Daten findet man in der Tabelle [https://www.dwd.de/DE/leistungen/opendata/help/inhalt_allgemein/opendata_content_de_en_xls.xls OpenData_weather_content.xls] oder hier: https://opendata.dwd.de/weather/lib/MetElementDefinition.xml.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Aufgrund der unterschiedlichen vom DWD bereitgestellten Datenformate benötigt das Modul zur Dekodierung je nach gewünschtem Funktionsumfang zusätzliche Perl-Module, die nicht standardmäßig vorinstalliert sind und je nach Systemkonfiguration nachinstalliert werden müssen. Außerdem unterstützt das Modul Zeitzonen, um z.B. die Wettervorhersage internationaler Stationen in Ortszeit darstellen zu können. Hierfür sind je nach Systemkonfiguration weitere Einstellungen erforderlich. Auch die Sprache der Wochentage für die Wettervorhersage ist frei wählbar. Je nach Systemkonfiguration ist aber die Standardsprache u.U. auf Englisch eingestellt, was weitere Anpassungen der Systemkonfiguration erforderlich macht.&lt;br /&gt;
&lt;br /&gt;
=== Vorbereitung ===&lt;br /&gt;
Im folgenden wird z.T. von einem System mit Rasbian oder Debian mit System-V Startsystem ausgegangen. Auf anderen Betriebssystemen und auf Systemen mit System-D müssen die Installationsschritte ggf. angepasst werden.&lt;br /&gt;
&lt;br /&gt;
1. Für die Wettervorhersage und die Wetterwarnungen:&lt;br /&gt;
Installation des Perl-Moduls &#039;&#039;XML::LibXML&#039;&#039; über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install libxml-libxml-perl&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
oder mit CPAN.&lt;br /&gt;
&lt;br /&gt;
2. Weiterhin ist das Perl-Modul &#039;&#039; DateTime&#039;&#039; erforderlich. Dieses lässt sich mit &amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;sudo apt-get install libdatetime-perl&amp;lt;/syntaxhighlight&amp;gt; installieren.&lt;br /&gt;
&lt;br /&gt;
3. Falls man einen eigenen Internet-Proxy nutzt:&lt;br /&gt;
Die Konfiguration des Proxies für FHEM erfolgt z.B. durch Eintrag von&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr global proxy &amp;lt;myProxyHost&amp;gt;:&amp;lt;myProxyPort&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
in die [[Konfiguration]], wobei &#039;&#039;myProxyHost&#039;&#039; durch den Namen oder die IP-Adresse des Proxy-Servers ersetzt werden muss und für &#039;&#039;myProxyPort&#039;&#039; der Port des Proxy-Servers eingetragen werden muss (oft 3128).&lt;br /&gt;
&lt;br /&gt;
3. FHEM Uhrzeit und Zeitzone:&lt;br /&gt;
Durch Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 {localtime()}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
in die FHEM-Kommandozeile überprüfen, ob die FHEM-Uhrzeit plausibel ist. Ist dies nicht der Fall sollten die Uhrzeit auf Systemebene überprüft werden und ggf. die Systemeinstellungen angepasst werden.&lt;br /&gt;
Ermitteln der Bezeichnung der eigenen Zeitzone über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  tzselect&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und diese Bezeichnung in die Datei &#039;&#039;/etc/timezone&#039;&#039; eintragen und &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 export TZ=`cat /etc/timezone`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
der Datei &#039;&#039;/etc/profile&#039;&#039; hinzufügen und dann das System neu starten. Nun muss die Zeitanzeige in FHEM korrekt sein.&lt;br /&gt;
&lt;br /&gt;
4. FHEM Sprache:&lt;br /&gt;
Durch Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 {$ENV{LANG}}&lt;br /&gt;
&amp;lt;/pre&amp;gt; in die FHEM-Kommandozeile überprüfen, in welcher Sprache der Wochentag angezeigt wird. Stimmt die Sprache nicht, dann auf der System-Kommandozeile&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dpkg-reconfigure locales&lt;br /&gt;
&amp;lt;/pre&amp;gt; eingeben und aus der Liste z.B. &#039;&#039;de_DE.UTF-8&#039;&#039; zusätzlich auswählen. Dieser Befehl gilt für Debian-basierte Betriebssysteme - für andere Betriebssysteme ist eine analoge Funktion zu verwenden. Mit Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 locale -a&lt;br /&gt;
&amp;lt;/pre&amp;gt; auf der System-Kommandozeile überprüfen, ob die ausgewählte Sprache nun zur Verfügung steht. Sollte FHEM nach einem Neustart noch immer nicht die gewünschte Sprache verwenden, kann man auf einem System V Linux durch Hinzufügen von z.B.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 export LANG=de_DE.UTF-8&lt;br /&gt;
&amp;lt;/pre&amp;gt; in die Datei &#039;&#039;/etc/init.d/fhem&#039;&#039; (irgendwo zwischen &#039;&#039;start&#039;&#039; und &#039;&#039;perl&#039;&#039;) und erneutem Neustart von FHEM die Sprache für FHEM erzwingen. Bei einem Systemd Linux kann man die Einstellungen mit &#039;&#039;systemctl edit --full fhem.service&#039;&#039; bearbeiten. Spätestes jetzt muss die Wochentagsanzeige in FHEM korrekt sein.&lt;br /&gt;
&lt;br /&gt;
5. Nur für den Weblink erforderlich:&lt;br /&gt;
Installation des Perl-Moduls &#039;&#039;DateTime&#039;&#039; über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sudo apt-get install libdatetime-perl&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
oder mit CPAN.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
Siehe {{Link2CmdRef|Anker=DWD_OpenDatadefine|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
Siehe {{Link2CmdRef|Anker=DWD_OpenDataattr|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
=== Readings ===&lt;br /&gt;
Die Prognosewerte sind wie folgt aufgebaut:&lt;br /&gt;
 fc&amp;lt;day&amp;gt;_[&amp;lt;sample&amp;gt;_]&amp;lt;property&amp;gt;&lt;br /&gt;
Eine Beschreibung der über 70 verfügbaren Eigenschaften und ihrer Maßeinheiten finden Sie hier. Die Maßeinheiten für Temperaturen und Windgeschwindigkeiten werden jeweils in °C und km/h umgerechnet. In den folgenden Abschnitten sind nur einige ausgewählte Eigenschaften aufgeführt:&lt;br /&gt;
&lt;br /&gt;
* day – relativer Tag (0 .. 9) basierend auf dem Zeitzonenattribut, wobei 0 für heute steht&lt;br /&gt;
&lt;br /&gt;
* sample – relative Zeit (0 .. 3, 7 oder 23), die einem Vielfachen von 6, 3 oder 1 Stunde UTC entspricht, abhängig vom Attribut forecastResolution&lt;br /&gt;
&lt;br /&gt;
* day properties (normalerweise für 06:00 Uhr Stationszeit, siehe Rohdaten der Station für tatsächliche Zeitbeziehung)&lt;br /&gt;
    date – Datum basierend auf dem Zeitzonenattribut&lt;br /&gt;
    weekday – abgekürzter Wochentag basierend auf dem Zeitzonenattribut in der Sprache Ihres FHEM-Systems&lt;br /&gt;
    Tn [°C] – Mindesttemperatur der letzten 12 Stunden&lt;br /&gt;
    Tx [°C] – Höchsttemperatur der letzten 12 Stunden (normalerweise um 18:00 Stationszeit)&lt;br /&gt;
    Tm [°C] – Durchschnittstemperatur der letzten 24 Stunden&lt;br /&gt;
    Tg [°C] – Mindesttemperatur 5 cm über dem Boden der letzten 12 Stunden&lt;br /&gt;
    PEvap [kg/m2] – Evapotranspiration der letzten 24 Stunden&lt;br /&gt;
    SunD [s] - Gesamtsonnenscheindauer des vorherigen Tages&lt;br /&gt;
&lt;br /&gt;
* hour properties time - Zeit basierend auf dem Zeitzonenattribut&lt;br /&gt;
    TTT [°C] - Trockentemperatur in 2 Metern Höhe über dem Boden&lt;br /&gt;
    Td [°C] - Taupunkttemperatur in 2 Metern Höhe über dem Boden&lt;br /&gt;
    DD [°] - durchschnittliche Windrichtung in 10 m Höhe über dem Boden&lt;br /&gt;
    FF [km/h] - durchschnittliche Windgeschwindigkeit in 10 m Höhe über dem Boden&lt;br /&gt;
    FX1 [km/h] - maximale Windgeschwindigkeit in der letzten Stunde&lt;br /&gt;
    SunD1 [s] - Sonnenscheindauer in der letzten Stunde&lt;br /&gt;
    SunD3 [s] - Sonnenscheindauer in den letzten 3 Stunden&lt;br /&gt;
    RR1c [kg/m2] - Niederschlagsmenge in der letzten Stunde&lt;br /&gt;
    RR3c [kg/m2] - Niederschlagsmenge in den letzten 3 Stunden&lt;br /&gt;
    RR6c [kg/m2] - Niederschlagsmenge in den letzten 6 Stunden&lt;br /&gt;
    R600 [%] - Regenwahrscheinlichkeit in den letzten 6 Stunden&lt;br /&gt;
    RRhc [kg/m2] - Niederschlagsmenge in den letzten 12 Stunden&lt;br /&gt;
    Rh00 [%] - Regenwahrscheinlichkeit in den letzten 12 Stunden&lt;br /&gt;
    RRdc [kg/m2] - Niederschlagsmenge in den letzten 24 Stunden&lt;br /&gt;
    Rd00 [%] - Regenwahrscheinlichkeit in den letzten 24 Stunden&lt;br /&gt;
    ww - Wettercode (siehe WMO 4680/4677, SYNOP)&lt;br /&gt;
    wwd - deutsche Wettercodebeschreibung&lt;br /&gt;
    VV [m] - horizontale Sichtweite&lt;br /&gt;
    Neff [%] - effektive Wolkenbedeckung&lt;br /&gt;
    Nl [%] - untere Wolkenbedeckung unter 2000 m&lt;br /&gt;
    Nm [%] - mittlere Wolkenbedeckung unter 7000 m&lt;br /&gt;
    Nh [%] - hohe Wolkenbedeckung über 7000 m&lt;br /&gt;
    PPPP [hPa] - Druckäquivalent auf Meereshöhe&lt;br /&gt;
&lt;br /&gt;
* Zusätzliche Tageseigenschaften, nicht vom DWD bereitgestellt&lt;br /&gt;
    SunRise - Sonnenaufgangszeit basierend auf dem Zeitzonenattribut&lt;br /&gt;
    SunSet - Sonnenuntergangszeit basierend auf dem Zeitzonenattribut&lt;br /&gt;
&lt;br /&gt;
* Zusätzliche Stundeneigenschaften, nicht vom DWD bereitgestellt&lt;br /&gt;
    SunAz [°] - Sonnenazimut&lt;br /&gt;
    SunEl [°] - Sonnenhöhe&lt;br /&gt;
    SunUp - Sonnenaufgang (0: Nacht, 1: Tag)&lt;br /&gt;
&lt;br /&gt;
Zusätzlich gibt es globale Prognosewerte:&lt;br /&gt;
&lt;br /&gt;
* fc_state - Status der letzten Prognoseaktualisierung, mögliche Werte sind „updated“ und „error: ...“&lt;br /&gt;
* fc_station - Prognosestationscode (WMO oder DWD)&lt;br /&gt;
* fc_description - Stationsbeschreibung&lt;br /&gt;
* fc_coordinates - Weltkoordinate und Höhe der Station&lt;br /&gt;
* fc_time - Zeitpunkt der Veröffentlichung der Prognose basierend auf dem Zeitzonenattribut&lt;br /&gt;
* fc_copyright - rechtliche Informationen, müssen mit Prognosedaten angezeigt werden, siehe DWD-Nutzungsbedingungen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Alarmwerte sind nach Beginn sortiert und folgendermaßen aufgebaut:&lt;br /&gt;
 a_&amp;lt;index&amp;gt;_&amp;lt;property&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* index - Alarmindex, beginnend mit 0, Gesamtanzahl a_count, sortiert nach Beginn&lt;br /&gt;
&lt;br /&gt;
* alert properties&lt;br /&gt;
    category - „Met“ oder „Health“&lt;br /&gt;
    event - numerischer Ereigniscode, siehe DWD-Dokumentation für Details&lt;br /&gt;
    eventDesc - kurze Ereignisbeschreibung in ausgewählter Sprache&lt;br /&gt;
    eventGroup - Ereignisgruppe, siehe DWD-Dokumentation für Details&lt;br /&gt;
    responseType - „None“ = nein Anweisungen, „Vorbereiten“ = Anweisungen, „AllClear“ = Alarm gelöscht&lt;br /&gt;
    urgency – „Immediate“ = Warnung oder „Zukünftig“ = Information&lt;br /&gt;
    severity – „Minor, „Moderate“, „Severe“ or „Extreme“&lt;br /&gt;
    areaColor – RGB-Farbe je nach Dringlichkeit und Schweregrad, durch Komma getrennte Dezimalzahlen&lt;br /&gt;
    onset – Startzeit des Alarms basierend auf dem Zeitzonenattribut&lt;br /&gt;
    expires – Endzeit des Alarms basierend auf dem Zeitzonenattribut&lt;br /&gt;
    headline – Überschrift in ausgewählter Sprache, normalerweise eine Kombination der Eigenschaften Dringlichkeit und Ereignis&lt;br /&gt;
    description – Beschreibung des Alarms in ausgewählter Sprache&lt;br /&gt;
    instruction – Sicherheitsanweisungen in ausgewählter Sprache&lt;br /&gt;
    area – numerische Warnzellen-ID&lt;br /&gt;
    areaDesc – Beschreibung des Bereichs, z. B. „Stadt Berlin“&lt;br /&gt;
    altitude – min. Höhe [m]&lt;br /&gt;
    ceiling – max. Höhe [m]&lt;br /&gt;
&lt;br /&gt;
Zusätzlich gibt es einige globale Alarmwerte:&lt;br /&gt;
&lt;br /&gt;
* a_state – Status der letzten Alarmaktualisierung, mögliche Werte sind „aktualisiert“ und „Fehler: ...“&lt;br /&gt;
&lt;br /&gt;
* a_time – Zeitpunkt des Downloads der letzten Alarmaktualisierung, basierend auf der Zeitzone attribut&lt;br /&gt;
&lt;br /&gt;
* a_count – Anzahl der für die ausgewählte Warnzellen-ID verfügbaren Alarme&lt;br /&gt;
&lt;br /&gt;
* a_copyright – rechtliche Informationen, müssen mit Prognosedaten angezeigt werden, siehe DWD-Nutzungsbedingungen, nicht verfügbar, wenn count null ist&lt;br /&gt;
&lt;br /&gt;
Alarme sollten unabhängig von der Dringlichkeit für onset &amp;lt;= now &amp;lt; expires und responseType != „AllClear“ als aktiv betrachtet werden. Inaktive Alarme mit responseType = „AllClear“ können relevante Anweisungen enthalten.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass alle Alarmwerte bei jeder Aktualisierung vollständig ersetzt und neu indexiert werden!&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zu den Alarmeigenschaften finden Sie in der Dokumentation des CAP DWS-Profils.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
=== Beispiel zur Modul-Einrichtung ===&lt;br /&gt;
&lt;br /&gt;
* Wettervorhersage&lt;br /&gt;
Für die Wettervorhersage muss der Stationscode ermittelt werden. Dazu den [https://www.dwd.de/DE/leistungen/met_verfahren_mosmix/mosmix_stationskatalog.pdf MOSMIX Stationskatalog] herunterladen, öffnen und die gewünschte Station heraussuchen (Spalte &#039;&#039;id&#039;&#039;). Einen Teil der deutschen Stationen kann man auch der [https://www.dwd.de/DE/derdwd/messnetz/bodenbeobachtung/messnetzkarte_boden.pdf Bodenmessnetzkarte] entnehmen. Den ermittelten Stationscode kann man dann entweder für eine Einzelabfrage als Parameter für das Kommando &#039;&#039;get forecast&#039;&#039; verwenden oder für die automatische Aktualisierung als Attribut &#039;&#039;forecastStation&#039;&#039; hinterlegen. Insgesamt werden vom DWD mehr als 70 Merkmale zur Verfügung gestellt. Eine Auflistung findet sich im Dokument [https://opendata.dwd.de/weather/lib/MetElementDefinition.xml MetElementDefinition]. Nur ein kleiner Teil der Merkmale wird in der Standardeinstellung des Moduls als Reading zur Verfügung gestellt. Wer andere Merkmale benötigt muss sie mit Komma getrennt dem Attribut &#039;&#039;forecastProperties&#039;&#039; zuweisen. Es empfiehlt sich zur Performance-Optimierung sowohl das Attribut &#039;&#039;forecastDays&#039;&#039; als auch das Attribut &#039;&#039;forecastProperties&#039;&#039; auf den tatsächlichen Bedarf einzustellen.&lt;br /&gt;
&lt;br /&gt;
* Wetterwarnungen&lt;br /&gt;
Für die Wetterwarnungen muss die Warnzelle ermittelt werden. Dazu [https://www.dwd.de/DE/leistungen/opendata/help/warnungen/cap_warncellids_csv.csv Warnzellen-ID Katalog] herunterladen, öffnen und die gewünschte Warnzelle heraussuchen. Unterstützt werden Gemeinden (beginnen mit 8), Landkreise (beginnen mit 1 oder 9) oder Küste (beginnen mit 5). Die Warnzellen-ID kann man dann entweder für eine Einzelabfrage als Parameter für das Kommando &#039;&#039;get alerts&#039;&#039; verwenden oder für die automatische Aktualisierung als Attribut &#039;&#039;alertArea&#039;&#039; hinterlegen. Die Warnzellen-ID ist ab der 2. Stelle identisch mit den ersten Ziffern des amtlichen Gemeindeschlüssels. Man kann z.B. den Namen von Gemeinde oder Landkreis bei den [https://www.statistik-bw.de/Statistik-Portal/gemeindeverz.asp Statistischen Ämtern des Bundes und der Länder] eingeben, den amtlichen Gemeindeschlüssel ermitteln und dann mit vorangestellter 1, 8 oder 9 im Warnzellen-ID Katalog des DWD nach einem Eintrag mit exakter oder weitgehender Übereinstimmung suchen. Wem das zu kompliziert vorkommt, der kann bei mehrdeutigen Gemeinde- bzw. Landkreisbezeichnungen auch versuchen auszuprobieren, welche die richtige Warnzellen-ID ist.&lt;br /&gt;
&lt;br /&gt;
Um das Modul mit automatisch Aktualisierung von Vorhersage und Wetterwarnungen zu nutzen, kann z.B. folgendes in die [[Konfiguration]] eingetragen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 define DWD DWD_OpenData&lt;br /&gt;
 attr DWD alertArea 111000000&lt;br /&gt;
 attr DWD forecastStation 99810&lt;br /&gt;
 attr DWD forecastDays 3&lt;br /&gt;
 attr DWD forecastWW2Text 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Performance&lt;br /&gt;
Das DWD_OpenData-Modul ist ein Datenmodul mit relativ vielen Readings. In der Standardkonfiguration wird, wie bei jedem anderen FHEM Modul, bei jeder Änderung jedes Readings ein FHEM internes Ereignis erzeugt, damit andere FHEM Devices auf diese Änderungen reagieren können. Diese Ereignisse sorgen auch dafür, dass man Änderungen in der Weboberfläche sofort angezeigt bekommt, ohne die Webseite neu aufzurufen. Interessiert sich aber kein FHEM Device für die Änderungsbenachrichtigung bestimmter Readings, entsteht unnötiger Verarbeitungs-Overhead, der je nach FHEM Konfiguration und verfügbarer CPU-Leistung auch mehrere Sekunden benötigen kann und in dieser Zeit andere Abläufe blockiert. Um die Performance zu optimieren, empfiehlt es sich,  mit [[event-on-update-reading]] für eine angepasste und dadurch effizientere Verarbeitung zu sorgen, indem man nur für jene Readings Ereignisse zulässt, welche man für die Weiterverarbeitung braucht. Der DWD_OpenData_Weblink braucht z.B. gar keine Ereignisse, um zu funktionieren. Hier eine minimalistische Beispielkonfiguration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr DWD event-on-update-reading state,fc_state,a_state&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Details zur Installation und Konfiguration des Moduls finden sich in der&lt;br /&gt;
{{Link2CmdRef|Anker=DWD_OpenData|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für die Einrichtung eines Meteogramms ===&lt;br /&gt;
Um den vorhergesagten Wetterverlauf als Meteogramm in Kurvenform mit [[SVG]] darzustellen, kann man wie folgt vorgehen:&lt;br /&gt;
&lt;br /&gt;
1. 99_myUtils.pm&lt;br /&gt;
&lt;br /&gt;
Für die Bestimmung der Werte für den SVG-Plot wird eine Perl-Funktion benötigt, die in die Datei 99_myUtils.pm vor dem Ende eingefügt wird. Wer diese FHEM-Datei noch nicht nutzt, legt sie einfach an (siehe [[99_myUtils_anlegen]]).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
package main;&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
 &lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# (c) mumpitzstuff 19.12.2018&lt;br /&gt;
#&lt;br /&gt;
# see https://forum.fhem.de/index.php/topic,83097.msg874150.html#msg874150&lt;br /&gt;
#&lt;br /&gt;
sub logProxy_dwd2Plot($$$$;$$$)&lt;br /&gt;
{&lt;br /&gt;
  my ($device, $fcValue, $from, $to, $fcHour, $expMode, $shiftTime) = @_;&lt;br /&gt;
  my $regex;&lt;br /&gt;
  my @rl;&lt;br /&gt;
&lt;br /&gt;
  return undef if(!$device);&lt;br /&gt;
&lt;br /&gt;
  if ($fcValue =~ s/_$//)&lt;br /&gt;
  {&lt;br /&gt;
    $regex = &amp;quot;^fc[\\d]+_[\\d]+_&amp;quot;.$fcValue.&amp;quot;\$&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    $regex = &amp;quot;^fc[\\d]+_&amp;quot;.$fcValue.&amp;quot;\$&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $fcHour = 12 if(!defined($fcHour));&lt;br /&gt;
  $expMode = &amp;quot;point&amp;quot; if(!defined($expMode));&lt;br /&gt;
  #Log3 undef,2, &amp;quot;Regex: &amp;quot;.$regex;&lt;br /&gt;
&lt;br /&gt;
  # ermitteln aller relevanten Readings&lt;br /&gt;
  if ( defined($defs{$device}) )&lt;br /&gt;
  {&lt;br /&gt;
    if ( $defs{$device}{TYPE} eq &amp;quot;DWD_OpenData&amp;quot; )&lt;br /&gt;
    {&lt;br /&gt;
      @rl = sort&lt;br /&gt;
      {&lt;br /&gt;
        my ($an) = ($a =~ m/fc(\d+)_.*/);&lt;br /&gt;
        my ($bn) = ($b =~ m/fc(\d+)_.*/);&lt;br /&gt;
        my ($ao) = ($a =~ m/fc\d+_(\d+).*/);&lt;br /&gt;
        my ($bo) = ($b =~ m/fc\d+_(\d+).*/);&lt;br /&gt;
        $an &amp;lt;=&amp;gt; $bn or $ao &amp;lt;=&amp;gt; $bo or $a cmp $b;&lt;br /&gt;
      } ( grep /${regex}/,keys %{$defs{$device}{READINGS}} );&lt;br /&gt;
      return undef if ( !@rl );&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      Log3 undef, 2, &amp;quot;logProxy_dwd2Plot: $device is not a DWD_OpenData device&amp;quot;;&lt;br /&gt;
      return undef;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my $fromsec = SVG_time_to_sec($from);&lt;br /&gt;
  my $tosec   = SVG_time_to_sec($to);&lt;br /&gt;
  my $sec = $fromsec;&lt;br /&gt;
  my ($h, $hp, $fcDay, $mday, $mon, $year);&lt;br /&gt;
  my $timestamp;&lt;br /&gt;
&lt;br /&gt;
  my $reading;&lt;br /&gt;
  my $value;&lt;br /&gt;
  my $prev_value;&lt;br /&gt;
  my $min = 999999;&lt;br /&gt;
  my $max = -999999;&lt;br /&gt;
  my $ret = &amp;quot;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  # while not end of plot range reached&lt;br /&gt;
  while (($sec &amp;lt; $tosec) &amp;amp;&amp;amp; @rl)&lt;br /&gt;
  {&lt;br /&gt;
    #remember previous value for start of plot range&lt;br /&gt;
    $prev_value = $value;&lt;br /&gt;
&lt;br /&gt;
    $reading = shift @rl;&lt;br /&gt;
    ($fcDay) = $reading =~ m/^fc(\d+).*/;&lt;br /&gt;
    ($hp) = $reading =~ m/^fc\d+_(\d+).*/;&lt;br /&gt;
    #Log 1, &amp;quot;hp: &amp;quot;.$hp;&lt;br /&gt;
&lt;br /&gt;
    if ($hp)&lt;br /&gt;
    {&lt;br /&gt;
      $h = ReadingsVal($device, &amp;quot;fc&amp;quot;.$fcDay.&amp;quot;_&amp;quot;.$hp.&amp;quot;_time&amp;quot;, $fcHour);&lt;br /&gt;
      if ($h =~ m/^(\d+):\d+/)&lt;br /&gt;
      {&lt;br /&gt;
        $h = $1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      $h = $fcHour;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $value = ReadingsVal($device, $reading, undef);&lt;br /&gt;
&lt;br /&gt;
    # calculate minutes of sunshine per hour&lt;br /&gt;
    if ($fcValue =~ /^SunD(\d+)/)&lt;br /&gt;
    {&lt;br /&gt;
      if (defined($1))&lt;br /&gt;
      {&lt;br /&gt;
        $value = $value / ($1 * 36);&lt;br /&gt;
      }&lt;br /&gt;
      else&lt;br /&gt;
      {&lt;br /&gt;
        $value = $value / (12 * 36);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # calculate amount of rain per hour&lt;br /&gt;
    if ($fcValue =~ /^RR(\d+)c$/)&lt;br /&gt;
    {&lt;br /&gt;
      if (defined($1))&lt;br /&gt;
      {&lt;br /&gt;
        $value /= $1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    ($year, $mon, $mday) = split(&#039;\-&#039;,ReadingsVal($device, &amp;quot;fc&amp;quot;.$fcDay.&amp;quot;_date&amp;quot;,undef));&lt;br /&gt;
    $timestamp = sprintf(&amp;quot;%04d-%02d-%02d_%02d:%02d:%02d&amp;quot;, $year, $mon, $mday, $h, 0, 0);&lt;br /&gt;
    $sec = SVG_time_to_sec($timestamp);&lt;br /&gt;
    if (defined($shiftTime))&lt;br /&gt;
    {&lt;br /&gt;
      $sec += $shiftTime;&lt;br /&gt;
      $timestamp = logProxy_shiftTime($timestamp, $shiftTime);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # skip all values before start of plot range&lt;br /&gt;
    next if ( $sec &amp;lt; $fromsec );&lt;br /&gt;
&lt;br /&gt;
    # add first value at start of plot range&lt;br /&gt;
    if ( !$ret &amp;amp;&amp;amp; $prev_value )&lt;br /&gt;
    {&lt;br /&gt;
      $min = $prev_value if ( $prev_value &amp;lt; $min );&lt;br /&gt;
      $max = $prev_value if ( $prev_value &amp;gt; $max );&lt;br /&gt;
      $ret .= &amp;quot;$from $prev_value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # done if after end of plot range&lt;br /&gt;
    last if ($sec &amp;gt; $tosec);&lt;br /&gt;
&lt;br /&gt;
    $min = $value if ( $value &amp;lt; $min );&lt;br /&gt;
    $max = $value if ( $value &amp;gt; $max );&lt;br /&gt;
&lt;br /&gt;
    # add actual control point&lt;br /&gt;
    $ret .= &amp;quot;$timestamp $value\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (($sec &amp;lt; $tosec) &amp;amp;&amp;amp; !@rl &amp;amp;&amp;amp; ($expMode eq &amp;quot;day&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
    $timestamp = sprintf(&amp;quot;%04d-%02d-%02d_%02d:%02d:%02d&amp;quot;, $year, $mon, $mday, 23, 59, 59);&lt;br /&gt;
    $_ = SVG_time_to_sec($timestamp);&lt;br /&gt;
    if (defined($shiftTime))&lt;br /&gt;
    {&lt;br /&gt;
      $_ += $shiftTime;&lt;br /&gt;
      $timestamp = logProxy_shiftTime($timestamp, $shiftTime);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($_ &amp;lt; $tosec)&lt;br /&gt;
    {&lt;br /&gt;
      $ret .= &amp;quot;$timestamp $value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      $ret .= &amp;quot;$to $value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  elsif (($sec &amp;gt; $tosec) &amp;amp;&amp;amp; ($expMode eq &amp;quot;day&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
    $value = $prev_value + ($value - $prev_value) * (86400 + ($tosec - $sec)) / 86400;&lt;br /&gt;
    $ret .= &amp;quot;$to $value\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ($ret, $min, $max, $prev_value);&lt;br /&gt;
} &lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. LogProxy&lt;br /&gt;
&lt;br /&gt;
Wer bereits ein [[logProxy]]-Device hat, muss den Namen seines logProxy-Devices in die weiter unter aufgeführte GPlot-Konfiguration eintragen. Ansonsten wird es wie folgt neu erstellt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define LogProxy logProxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. FileLog&lt;br /&gt;
&lt;br /&gt;
Das Meteogramm kennt anders als andere FHEM-Plots keine Vergangenheit außer heute. Trotzdem wird aus formalen Gründen ein [[FileLog]]-Device benötigt. Dazu kann ein beliebiges vorhandenes FileLog-Device verwendet werden. Wer will, kann hierfür aber auch ein neues FileLog Device für das DWD_OpenData-Device anlegen (Achtung: wird schnell umfangreich):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define FileLog_DWD FileLog ./log/DWD-%Y-%m.log DWD&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im folgenden wird für das FileLog-Device der Platzhalter &#039;&#039;FileLog_Dummy&#039;&#039; verwendet, der mit dem Namen des gewählten FileLog-Devices zu ersetzen ist.&lt;br /&gt;
&lt;br /&gt;
4. SVG Plot&lt;br /&gt;
&lt;br /&gt;
Das eigentliche Meteogramm ist ein SVG-Device. Will man mehrere Tage darstellen bietet sich die folgende Definition an:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_DWD SVG FileLog_Dummy:SVG_DWD:CURRENT&lt;br /&gt;
attr SVG_DWD fixedoffset 6&lt;br /&gt;
attr SVG_DWD fixedrange 7days&lt;br /&gt;
attr SVG_DWD nrAxis 1,2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei muss das SVG-Attribut &#039;&#039;fixedoffset&#039;&#039; entweder gleich oder kleiner als die Einstellung des DWD_OpenData-Attributs &#039;&#039;forecastDays&#039;&#039; (Standardwert: 6 Tage) gewählt werden und das SVG-Attribut &#039;&#039;fixedrange&#039;&#039; um eins größer als &#039;&#039;fixedoffset&#039;&#039; eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Will man stattdessen nur die nächsten 24 Stunden anzeigen, nimmt man folgende Einstellungen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_DWD SVG FileLog_Dummy:SVG_DWD:CURRENT&lt;br /&gt;
attr SVG_DWD endPlotNow 1&lt;br /&gt;
attr SVG_DWD fixedoffset 1&lt;br /&gt;
attr SVG_FileLog_WETTER_DWD_3 label &amp;quot;Tmin: $data{max1} °C, Tmax: $data{min1} °C&amp;quot;&lt;br /&gt;
attr SVG_DWD nrAxis 1,2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um die DWD_OpenData-Readings mit dem Plot zu verknüpfen, muss man nun die GPlot-Konfigurationsdatei des SVG-Plots manuell bearbeiten. Dazu auf den Link klicken, der im SVG_DWD-Device am Internal &#039;&#039;GPLOTFILE&#039;&#039; steht. Die y-Wertebereiche für die Regenmenge und die Temperaturen sind im Beispiel auskommentiert (Autorange). Das kann man so lassen oder man stellt sie nach den eigenen Wetter-Gegebenheiten ein. Je nach Konfiguration des DWD_OpenData-Attributs &#039;&#039;forecastResolution&#039;&#039; sind aber noch einige weitere Einstellungen anzupassen. Das folgende Beispiel ist für die 3h-Auflösung:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;Wettervorhersage&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid ytics&lt;br /&gt;
set ylabel &amp;quot;Regen [mm]&amp;quot;&lt;br /&gt;
#set yrange [0:4]&lt;br /&gt;
set y2label &amp;quot;Temperatur [°C]&amp;quot;&lt;br /&gt;
#set y2range [-5:35]&lt;br /&gt;
set y3label &amp;quot;Wolken/Regen/Sonne [%]&amp;quot;&lt;br /&gt;
set y3range [0:100]&lt;br /&gt;
&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tx&amp;quot;,$from,$to,18,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tn&amp;quot;,$from,$to,6,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD3_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR3c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R600_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstX:TimeNow(),0,100&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;T&#039; ls l0 lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Tmax&#039; ls l0dot lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Tmin&#039; ls l0dot lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Sonne&#039; ls l4fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Regenmenge&#039; ls l2fill lw 1 with steps,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wind&#039; ls l1 lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Regen&#039; ls l5fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wolken&#039; ls l6fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 notitle ls l5 lw 4 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 notitle ls l5 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verwendet man dagegen eine Auflösung von 1 Stunde, sind folgende LogProxy-Einträge erforderlich:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tx&amp;quot;,$from,$to,18,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tn&amp;quot;,$from,$to,6,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR1c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R101_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-0.5*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstX:TimeNow(),0,100&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für die Darstellung der nächsten 24 Stunden mit einer Auflösung von 1 Stunde nimmt man folgende GPlot-Konfiguration:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;L1&amp;gt;&#039;&lt;br /&gt;
set ytics&lt;br /&gt;
set y2tics&lt;br /&gt;
set y3tics&lt;br /&gt;
set grid xtics y2tics&lt;br /&gt;
set ylabel &amp;quot;Regen [mm]&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Temperatur [°C]&amp;quot;&lt;br /&gt;
set y3label &amp;quot;Wolken/Regen/Sonne [%]&amp;quot;&lt;br /&gt;
set y3range [0:100]&lt;br /&gt;
&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR1c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R101_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-0.5*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;T&#039; ls l0 lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Sonne&#039; ls l4fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Regenmenge&#039; ls l2fill lw 1 with steps,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wind&#039; ls l1 lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Regen&#039; ls l5fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wolken&#039; ls l6fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 notitle ls l2 lw 2 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nachdem, welche Auflösung man verwendet, werden unterschiedliche Readings des DWD_OpenData-Devices benötigt. Diese sind in den LogProxy-Zeilen in der GPlot-Konfigurationsdatei zu finden und müssen auf jeden Fall dem Attribut &#039;&#039;forecastProperties&#039;&#039; des DWD_OpenData-Device hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
Viele Detaileinstellungen des Meteogramms lassen sich individualisieren. Man kann z.B. mehr oder weniger Daten anzeigen und zumindest für &#039;&#039;heute&#039;&#039; auch aktuelle Messwerte hinzufügen.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel für ein Meteogramm über 4 Tage mit 3 Stunden Auflösung:&lt;br /&gt;
&lt;br /&gt;
[[File:DWDODmeteogram4d3h.png|500px]]&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für die Einrichtung eines Weblinks ===&lt;br /&gt;
Zur graphischen Darstellung der Vorhersage und der Wetterwarnungen mit [[FHEMWEB]] steht das Modul [https://raw.githubusercontent.com/jnsbyr/fhem/master/FHEM/98_DWD_OpenData_Weblink.pm 98_DWD_OpenData_Weblink.pm] zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Zunächst die Moduldatei herunterladen und in das Modulverzeichnis &#039;&#039;fhem/FHEM&#039;&#039; kopieren. Entweder die Datei direkt auf den FHEM-Server herunterladen (z.B. mit &#039;&#039;wget&#039;&#039;) oder beim indirekten Herunterladen darauf achten, dass dabei das Encoding nicht verändert wird (also z.B. bei WinSCP den Binär-Modus und nicht den Text-Modus verwenden). Ansonsten werden später z.B. Sonderzeichen wie &#039;&#039;°C&#039;&#039; falsch angezeigt. &lt;br /&gt;
&lt;br /&gt;
Anschließend kann in die [[Konfiguration]] z.B. folgendes eingetragen werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
 define DWD_Weblink_Generator DWD_OpenData_Weblink&lt;br /&gt;
 attr DWD_Weblink_Generator IODev DWD&lt;br /&gt;
 attr DWD_Weblink_Generator forecastDays 4&lt;br /&gt;
 # refreshRate nur dann setzten, wenn der Browser Java-Script beherrscht:&lt;br /&gt;
 attr DWD_Weblink_Generator refreshRate 900&lt;br /&gt;
 &lt;br /&gt;
 define DWD_Weblink weblink htmlCode { DWD_OpenData_Weblink::AsHtmlH(&amp;quot;DWD_Weblink_Generator&amp;quot;) } &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit legt man das Weblink-Generator-Device an und verknüpft es mit dem DWD_OpenData-Device. Außerdem wird der [[weblink ]] selbst angelegt, der seinerseits mit dem Weblink-Generator-Device verknüpft wird. Der Weblink benötigt für seine Funktion eine bestimmte Auswahl der Vorhersage-Merkmale. Wer das Attribut &#039;&#039;forecastProperties&#039;&#039; des DWD_OpenData-Moduls anpassen will, muss diese Merkmale auf jeden Fall mit berücksichtigen. &lt;br /&gt;
&lt;br /&gt;
Wenn vom Weblink nichts im Browser zu sehen ist, kann das daran liegen, dass der Browser kein aktuelles JavaScript verwendet oder JavaScript deaktiviert ist. Dann sollte das Attribut &#039;&#039;refreshRate&#039;&#039; auf 0 Sekunden eingestellt oder gelöscht werden. Mit aktiviertem Refresh werden die Daten auch ohne Seitenneuaufbau regelmäßig und bei Tab-Wechsel aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Die Liste der erforderlichen Vorhersage-Merkmale finden sich zusammen mit allen weiteren Details zur Installation und Konfiguration in der Modulhilfe von &#039;&#039;98_DWD_OpenData_Weblink.pm&#039;&#039;, die man z.B. nach dem Anlegen des Weblink-Generator-Devices über die Weboberfläche abrufen kann.&lt;br /&gt;
&lt;br /&gt;
Hier ein Ausschnitt aus der Darstellung des Weblinks mit [[FHEMWEB]]:&lt;br /&gt;
[[File:DWDODweblink.png|500px]]&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für die Einbindung auf einer Webseite außerhalb von FHEM ===&lt;br /&gt;
Für manche Anwendungsfälle, etwa die Ansicht in FTUI, ist es erforderlich, das mit dem &#039;&#039;&#039;DWD_Weblink_Generator&#039;&#039;&#039; erzeugte Bild an anderer Stelle in eine Webseite einzubinden. Dazu kann man folgende Schritte verwenden. &lt;br /&gt;
&lt;br /&gt;
Zunächst wird ein statisches CSS-Stylesheet erzeugt, etwa in der Datei &#039;&#039;ftui_weather.css&#039;&#039; im Unterverzeichnis &#039;&#039;css&#039;&#039;. Dorthin werden die ganzen CSS-Klassen geschrieben, die der Webbrowser benötigt, um aus den Daten des DWD_Weblink_Generator eine Tabelle zu machen (siehe den etwas länglichen Code am Ende dieses Abschnitts).&lt;br /&gt;
&lt;br /&gt;
Dann ist zunächst dafür zu sorgen, dass im Header der Webseite, die später die Wettervorhersage anzeigen soll, dieses Stylesheet eingebunden wird. Dazu muss in den Header die Zeile&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;css/ftui_weather.css&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
eingetragen werden.&lt;br /&gt;
&lt;br /&gt;
Der zweite Schritt besteht darin, ebenfalls in den Header der betreffenden Webseite ein paar Zeilen JavaScript einzubinden, die dem Holen der Daten dienen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
    function getDWDOpenDataWeblink() {&lt;br /&gt;
        var fwcsrf = &amp;quot;&amp;lt;HIER DER csrf-Token DES ENTFERNTEN FHEM-SERVERS&amp;gt;&amp;quot;;&lt;br /&gt;
        $. get (&amp;quot;http://&amp;lt;HIER DIE ADRESSE DES ENTFERNTEN FHEM-SERVERS&amp;gt;:8083/fhem?cmd=get%20DWD_Weblink_Generator%20horizontalForecast&amp;amp;XHR=1&amp;amp;fwcsrf=&amp;quot; + fwcsrf,&lt;br /&gt;
        function (forecastElements) {&lt;br /&gt;
            $(&amp;quot;#DWD_OpenData_Weblink&amp;quot;).html(forecastElements);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    function getdata() {&lt;br /&gt;
        getDWDOpenDataWeblink();&lt;br /&gt;
        setInterval(getDWDOpenDataWeblink, 900000);&lt;br /&gt;
        $(window).on(&amp;quot;focus&amp;quot;, getDWDOpenDataWeblink);&lt;br /&gt;
    };&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der dritte Schritt besteht darin, auf der betreffenden Webseite einen Ort zu definieren, an welchen das Wettervorhersagebild geschoben wird, z.B.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;DWD_OpenData_Weblink&amp;quot; style=&amp;quot;position:absolute; left:10px;top:500px; width:600px; height:200px; float:left; overflow-y:hidden;overflow-x:auto;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der letzte Schritt sorgt dafür, dass die oben definierte JavaScript-Funktion beim Laden der Webseite auch aufgerufen wird. Dazu muss ein entsprechendes Attribut im body-Tag der Seite eingebaut werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;body onload=&amp;quot;getdata()&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nachstehend nun der etwas längliche CSS-Code für das statische Stylesheet:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
/* weather table with fixed column width */&lt;br /&gt;
.weatherForecast {&lt;br /&gt;
    display: table;&lt;br /&gt;
    table-layout: fixed;&lt;br /&gt;
    column-gap: 40px;&lt;br /&gt;
}&lt;br /&gt;
/* weather table header row */&lt;br /&gt;
.weatherHeaderRow {&lt;br /&gt;
    display: table-header-group;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
/* weather table data row */&lt;br /&gt;
.weatherDataRow {&lt;br /&gt;
    display: table-row-group;&lt;br /&gt;
}&lt;br /&gt;
/* weather table data cells */&lt;br /&gt;
#weatherFontBold {&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
.weatherWeekday {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    min-width: 80px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.weatherCondition {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    position: relative;&lt;br /&gt;
    top: -4px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    font-size: 80%;&lt;br /&gt;
    word-wrap: break-word;&lt;br /&gt;
}&lt;br /&gt;
.weatherTemperature {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    font-size: 100%;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
.weatherWind {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    font-size: 80%;&lt;br /&gt;
    padding-top: 3px;&lt;br /&gt;
}&lt;br /&gt;
/* weather table condition icon cell */&lt;br /&gt;
.weatherIcon {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    position: relative;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
/* weather icon */&lt;br /&gt;
.weatherIcon img {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
/* embedded alert icon with pointer support */&lt;br /&gt;
.weatherAlertIcon {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    top: 5px;&lt;br /&gt;
    right: 5px;&lt;br /&gt;
    width: 25px;&lt;br /&gt;
    height: 22px;&lt;br /&gt;
    background-size: 25px 22px;&lt;br /&gt;
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAkCAMAAADM4ogkAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NjcyOSwgMjAxMi8wNS8wMy0xMzo0MDowMyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDEyLjAgV2luZG93cyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1RjU1NzJBRDMyRTcxMUU1QTk4MkI0RTkwODEwODQ1QSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1RjU1NzJBRTMyRTcxMUU1QTk4MkI0RTkwODEwODQ1QSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjVGNTU3MkFCMzJFNzExRTVBOTgyQjRFOTA4MTA4NDVBIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjVGNTU3MkFDMzJFNzExRTVBOTgyQjRFOTA4MTA4NDVBIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+oFydjAAAAwBQTFRF9fX267W51Csy9d7c1VBV9uPc/vz89+nl5YB/2Flk2mZp1Cgv0Csw5pWR7K2t1Soy1Cow7b6y0iUr+/r61jI54X+A+uvq21xV44qO/fj400tU1kxG3nNx2mJp34Bz/Pj2a2tr4Ht91S43fn5+1jA31S0y0iYu1TA1/ff3+/TxEhIS3W1u1jA010Q++efj1kVH1Tk+gYGB6qWh4oWEtra21TI48sjH1VVc1tbW1jY22ltd4YF/1kFHl5eX/vz7/Pz84nZt+evt9+Tm2mNu1Sw14YSD1Ss04YKC0isv4X5/0zc21CUu8cnL0jA20jAz22xy1jE422Zv1i800isw1Cgx11xjKysr1FFZ4X190iQsGRkZ0jY+1TE41Cww0y0y0ykt1i431i4z0y800ikvPz4/AAAA////DQwM1TI30yYs1TE31TA21TE21S401S801S810ycs//7+1TA3///+/v791TI2/v//0Sov0iYt0yYt6urqkZGR1TM40ycu1S414ODg4YB3+/Hw7bK0/vv78fHxh4eH+OPf0i8w1DI30icu1y843Zia/PX13Nvb6aWZ4YKE+fDv21RT00E83G5y3m9x7tDF3Gdu99fW1EJK1ktK3t7e5I+R4oeH3WNp3oCF+vH16ZOJ1Sw27cG31i018dDL4qOf3Wde7Kqe+O7m2ERH+e3o+u/t4YuY/Pb15IqG5p2R4np52TA82mhx2V1p3mpx5oWL66uiRkZG4YOR/v7+1ygz1TxC8dDV9dHS2VJL1CUw8by79+Hg7bq3vr6+9dnR1Tc49d/X11le77yv22hl2lVY+Ofo33540icspqan+/f49N/h5J6m2HB7zczN3nZ88c3FsrKz3HZ74ICC4YGA1oJy10JD+Onj8c3J1Dk71T494oaE4HpxNTU14XRz7Ozs7+/vcG9v+/bz/Pj1/fr3IiIi676/5IJx4Hpr6amn56On6aGd2mlu4X2A22Vm2WFk1jI33GNk+/Ds2VJU2FZW8/Pz78jD3V1v55iY3W1x////C1yJRAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAMKSURBVHjajNEFWBNxGAbwOXEoUzYnqCgGuPMUUFE8sRuwgDlUEJmK8z6/XWyEEjrswu7u7u7u7u4u7G7FWxoj/J6L9/7v77nnQpTpMM7XFkocV0UOK2VKbkt3/R+4KY0Zlnw8d7ikBeu9VroRcoXPg5F1Y5Mn5wYPaRnGqOxMfPbIGXZfFMxxJGtg0lxzhoWlKpYfSrCd9f4rc4JPKs1l9B1aeabGoLRQTnBxG8T2K2DwLV7FRVTOHi47yKKmxGyAagoGxb7x2cLSMuS0eZIAMopJUaWtkR3M1yUBpe8lkuoj4WYYm8Bf98gaxjdsSik7toKydPQ0OKEzUnGuWcOLWgZPXoCe3Wi6HlS+zVMG/35Zwfq7eqO+wxk4T9N0OYDXKQylnZ4VnKdxM5bfAtDTh6arAlT4IldxXYo6woyS3hwxpRHA12ia7gUA3yKUKL8f7wCPiClMOSsA0VPTMwIkeeoQm+39F1asZECZ02kBFGlH06eEM+Rt0RvFHyX/wNUy7JGex9Q3EGB1U4BCLVXK9D1/wxu1lJS8lMTc36Pp/eZQcaoM9Us9/oSJL8QUGbrDXMNmOvqBJe3TxqC22p/wgIbBlrMsLZSju1pT93dSZDsW/Q3rF/NG3r+xte4zqKY1QY0IBuVvwQ4LazFGUTzRVhexJziahkzyTht8PM6AwXUbWbutj3za2W+5IIxEovYAKxwlww+KV7buYTfzL7TODOGry/tb4KdaCSg/VsFWDfSx/ELLLK9CILl9hBnOEaOq4DN7BZe6lv36++plJ3ST/zDBfEOEN6udBNnNWDHFhTpnihIbNkXKUNfLyyuqeciVOwFvr7oHrApqHhTiPjog6EqdNVFVDIji/JmiiYQbopFM3R0XF6fT6VJ15jFFnUJhSqQRETV5RXfnGykhMea9B2M624ezBaOmuKiv1GDg9TxJ8sIxltB7E0QsT/BqpdrPT9g4P7VaTcZKL4vGDP/psq71BpdSLj9nTmod3mTC+HDfN+FN2jodjlwfGRnoFNg2cH2B7+ca/xJgAFL1l3PxpIx4AAAAAElFTkSuQmCC);&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:hover {&lt;br /&gt;
    opacity: 0.7;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus {&lt;br /&gt;
    opacity: 1.0;&lt;br /&gt;
}&lt;br /&gt;
/* opaque white background for alerts dialog */&lt;br /&gt;
.weatherOverlay {&lt;br /&gt;
    display: none;&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    z-index: 1;&lt;br /&gt;
    opacity: 0.2;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    background: white;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus .weatherOverlay {&lt;br /&gt;
    display: block;&lt;br /&gt;
}&lt;br /&gt;
/* alerts dialog box */&lt;br /&gt;
[class ^= weatherAlertBox] {&lt;br /&gt;
    display: none;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    z-index: 2;&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    border: 3px solid white;&lt;br /&gt;
    border-radius: 3px;&lt;br /&gt;
    box-shadow: 0px 0px 6px 4px #666;&lt;br /&gt;
    background: #EEE;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus .weatherAlertBoxLeft {&lt;br /&gt;
    display: block;&lt;br /&gt;
    right: -268px;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus .weatherAlertBoxCenter {&lt;br /&gt;
    display: block;&lt;br /&gt;
    left: -178px;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus .weatherAlertBoxRight {&lt;br /&gt;
    display: block;&lt;br /&gt;
    left: -312px;&lt;br /&gt;
}&lt;br /&gt;
/* alerts dialog close button */&lt;br /&gt;
.weatherAlertsClose {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    top: -12px;&lt;br /&gt;
    right: -13px;&lt;br /&gt;
&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    box-shadow: 1px 1px 3px #666;&lt;br /&gt;
&lt;br /&gt;
    line-height: 21px;&lt;br /&gt;
    width: 21px;&lt;br /&gt;
    background: #606061;&lt;br /&gt;
&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    text-decoration: none;&lt;br /&gt;
    font-family: Sans-serif;&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: white;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertsClose:hover {&lt;br /&gt;
    opacity: 0.8;&lt;br /&gt;
}&lt;br /&gt;
/* alerts dialog title */&lt;br /&gt;
.weaterAlertsTitle {&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: black;&lt;br /&gt;
}&lt;br /&gt;
/* alert messages */&lt;br /&gt;
[class ^= weaterAlertMessage] {&lt;br /&gt;
    float: left;&lt;br /&gt;
    text-align: left;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
.weaterAlertMessage p {&lt;br /&gt;
    white-space: normal;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DWD_OpenData&amp;diff=39374</id>
		<title>DWD OpenData</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DWD_OpenData&amp;diff=39374"/>
		<updated>2024-06-28T18:25:45Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Readings hinzu gefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Versionsänderung: Die Vorhersagedaten wurden Mitte September 2018 von CSV auf KML umgestellt. Diese Umstellung ist inkompatibel: das DWD_OpenData-Modul muss aktualisiert werden, einige Reading-Namen haben sich geändert und der Weblink muss deinstalliert und neu installiert werden (siehe diesen {{Link2Forum|Topic=83097|Message=840270|Linktext=Beitrag im Forum}}).}} &lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Daten vom DWD OpenData Server abrufen&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModCmdRef=DWD_OpenData&lt;br /&gt;
|ModForumArea=Unterstützende Dienste/Wettermodule&lt;br /&gt;
|ModTechName=55_DWD_OpenData.pm&lt;br /&gt;
|ModOwner=JensB ({{Link2FU|14024|Forum}}/[[Benutzer Diskussion:JensB|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
Der Deutsche Wetterdienst (DWD) stellt Wetterdaten über den [https://www.dwd.de/DE/leistungen/opendata/opendata.html Open Data Server] zur Verfügung. Die Verwendung dieses Dienstes und der vom DWD zur Verfügung gestellten Daten unterliegt den auf der OpenData Webseite beschriebenen Bedingungen. Einen Überblick über die verfügbaren Daten findet man in der Tabelle [https://www.dwd.de/DE/leistungen/opendata/help/inhalt_allgemein/opendata_content_de_en_xls.xls OpenData_weather_content.xls] oder hier: https://opendata.dwd.de/weather/lib/MetElementDefinition.xml.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Aufgrund der unterschiedlichen vom DWD bereitgestellten Datenformate benötigt das Modul zur Dekodierung je nach gewünschtem Funktionsumfang zusätzliche Perl-Module, die nicht standardmäßig vorinstalliert sind und je nach Systemkonfiguration nachinstalliert werden müssen. Außerdem unterstützt das Modul Zeitzonen, um z.B. die Wettervorhersage internationaler Stationen in Ortszeit darstellen zu können. Hierfür sind je nach Systemkonfiguration weitere Einstellungen erforderlich. Auch die Sprache der Wochentage für die Wettervorhersage ist frei wählbar. Je nach Systemkonfiguration ist aber die Standardsprache u.U. auf Englisch eingestellt, was weitere Anpassungen der Systemkonfiguration erforderlich macht.&lt;br /&gt;
&lt;br /&gt;
=== Vorbereitung ===&lt;br /&gt;
Im folgenden wird z.T. von einem System mit Rasbian oder Debian mit System-V Startsystem ausgegangen. Auf anderen Betriebssystemen und auf Systemen mit System-D müssen die Installationsschritte ggf. angepasst werden.&lt;br /&gt;
&lt;br /&gt;
1. Für die Wettervorhersage und die Wetterwarnungen:&lt;br /&gt;
Installation des Perl-Moduls &#039;&#039;XML::LibXML&#039;&#039; über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install libxml-libxml-perl&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
oder mit CPAN.&lt;br /&gt;
&lt;br /&gt;
2. Weiterhin ist das Perl-Modul &#039;&#039; DateTime&#039;&#039; erforderlich. Dieses lässt sich mit &amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;sudo apt-get install libdatetime-perl&amp;lt;/syntaxhighlight&amp;gt; installieren.&lt;br /&gt;
&lt;br /&gt;
3. Falls man einen eigenen Internet-Proxy nutzt:&lt;br /&gt;
Die Konfiguration des Proxies für FHEM erfolgt z.B. durch Eintrag von&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr global proxy &amp;lt;myProxyHost&amp;gt;:&amp;lt;myProxyPort&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
in die [[Konfiguration]], wobei &#039;&#039;myProxyHost&#039;&#039; durch den Namen oder die IP-Adresse des Proxy-Servers ersetzt werden muss und für &#039;&#039;myProxyPort&#039;&#039; der Port des Proxy-Servers eingetragen werden muss (oft 3128).&lt;br /&gt;
&lt;br /&gt;
3. FHEM Uhrzeit und Zeitzone:&lt;br /&gt;
Durch Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 {localtime()}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
in die FHEM-Kommandozeile überprüfen, ob die FHEM-Uhrzeit plausibel ist. Ist dies nicht der Fall sollten die Uhrzeit auf Systemebene überprüft werden und ggf. die Systemeinstellungen angepasst werden.&lt;br /&gt;
Ermitteln der Bezeichnung der eigenen Zeitzone über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  tzselect&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und diese Bezeichnung in die Datei &#039;&#039;/etc/timezone&#039;&#039; eintragen und &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 export TZ=`cat /etc/timezone`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
der Datei &#039;&#039;/etc/profile&#039;&#039; hinzufügen und dann das System neu starten. Nun muss die Zeitanzeige in FHEM korrekt sein.&lt;br /&gt;
&lt;br /&gt;
4. FHEM Sprache:&lt;br /&gt;
Durch Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 {$ENV{LANG}}&lt;br /&gt;
&amp;lt;/pre&amp;gt; in die FHEM-Kommandozeile überprüfen, in welcher Sprache der Wochentag angezeigt wird. Stimmt die Sprache nicht, dann auf der System-Kommandozeile&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dpkg-reconfigure locales&lt;br /&gt;
&amp;lt;/pre&amp;gt; eingeben und aus der Liste z.B. &#039;&#039;de_DE.UTF-8&#039;&#039; zusätzlich auswählen. Dieser Befehl gilt für Debian-basierte Betriebssysteme - für andere Betriebssysteme ist eine analoge Funktion zu verwenden. Mit Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 locale -a&lt;br /&gt;
&amp;lt;/pre&amp;gt; auf der System-Kommandozeile überprüfen, ob die ausgewählte Sprache nun zur Verfügung steht. Sollte FHEM nach einem Neustart noch immer nicht die gewünschte Sprache verwenden, kann man auf einem System V Linux durch Hinzufügen von z.B.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 export LANG=de_DE.UTF-8&lt;br /&gt;
&amp;lt;/pre&amp;gt; in die Datei &#039;&#039;/etc/init.d/fhem&#039;&#039; (irgendwo zwischen &#039;&#039;start&#039;&#039; und &#039;&#039;perl&#039;&#039;) und erneutem Neustart von FHEM die Sprache für FHEM erzwingen. Bei einem Systemd Linux kann man die Einstellungen mit &#039;&#039;systemctl edit --full fhem.service&#039;&#039; bearbeiten. Spätestes jetzt muss die Wochentagsanzeige in FHEM korrekt sein.&lt;br /&gt;
&lt;br /&gt;
5. Nur für den Weblink erforderlich:&lt;br /&gt;
Installation des Perl-Moduls &#039;&#039;DateTime&#039;&#039; über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sudo apt-get install libdatetime-perl&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
oder mit CPAN.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
Siehe {{Link2CmdRef|Anker=DWD_OpenDatadefine|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
Siehe {{Link2CmdRef|Anker=DWD_OpenDataattr|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
=== Readings ===&lt;br /&gt;
Die Prognosewerte sind wie folgt aufgebaut:&lt;br /&gt;
 fc&amp;lt;day&amp;gt;_[&amp;lt;sample&amp;gt;_]&amp;lt;property&amp;gt;&lt;br /&gt;
Eine Beschreibung der über 70 verfügbaren Eigenschaften und ihrer Maßeinheiten finden Sie hier. Die Maßeinheiten für Temperaturen und Windgeschwindigkeiten werden jeweils in °C und km/h umgerechnet. In den folgenden Abschnitten sind nur einige ausgewählte Eigenschaften aufgeführt:&lt;br /&gt;
&lt;br /&gt;
* day – relativer Tag (0 .. 9) basierend auf dem Zeitzonenattribut, wobei 0 für heute steht&lt;br /&gt;
&lt;br /&gt;
* sample – relative Zeit (0 .. 3, 7 oder 23), die einem Vielfachen von 6, 3 oder 1 Stunde UTC entspricht, abhängig vom Attribut forecastResolution&lt;br /&gt;
&lt;br /&gt;
* day properties (normalerweise für 06:00 Uhr Stationszeit, siehe Rohdaten der Station für tatsächliche Zeitbeziehung) date – Datum basierend auf dem Zeitzonenattribut weekday – abgekürzter Wochentag basierend auf dem Zeitzonenattribut in der Sprache Ihres FHEM-Systems Tn [°C] – Mindesttemperatur der letzten 12 Stunden Tx [°C] – Höchsttemperatur der letzten 12 Stunden (normalerweise um 18:00 Stationszeit) Tm [°C] – Durchschnittstemperatur der letzten 24 Stunden Tg [°C] – Mindesttemperatur 5 cm über dem Boden der letzten 12 Stunden PEvap [kg/m2] – Evapotranspiration der letzten 24 Stunden SunD [s] - Gesamtsonnenscheindauer des vorherigen Tages&lt;br /&gt;
&lt;br /&gt;
* hour properties time - Zeit basierend auf dem Zeitzonenattribut TTT [°C] - Trockentemperatur in 2 Metern Höhe über dem Boden Td [°C] - Taupunkttemperatur in 2 Metern Höhe über dem Boden DD [°] - durchschnittliche Windrichtung in 10 m Höhe über dem Boden FF [km/h] - durchschnittliche Windgeschwindigkeit in 10 m Höhe über dem Boden FX1 [km/h] - maximale Windgeschwindigkeit in der letzten Stunde SunD1 [s] - Sonnenscheindauer in der letzten Stunde SunD3 [s] - Sonnenscheindauer in den letzten 3 Stunden RR1c [kg/m2] - Niederschlagsmenge in der letzten Stunde RR3c [kg/m2] - Niederschlagsmenge in den letzten 3 Stunden RR6c [kg/m2] - Niederschlagsmenge in den letzten 6 Stunden R600 [%] - Regenwahrscheinlichkeit in den letzten 6 Stunden RRhc [kg/m2] - Niederschlagsmenge in den letzten 12 Stunden Rh00 [%] - Regenwahrscheinlichkeit in den letzten 12 Stunden RRdc [kg/m2] - Niederschlagsmenge in den letzten 24 Stunden Rd00 [%] - Regenwahrscheinlichkeit in den letzten 24 Stunden ww - Wettercode (siehe WMO 4680/4677, SYNOP) wwd - deutsche Wettercodebeschreibung VV [m] - horizontale Sichtweite Neff [%] - effektive Wolkenbedeckung Nl [%] - untere Wolkenbedeckung unter 2000 m Nm [%] - mittlere Wolkenbedeckung unter 7000 m Nh [%] - hohe Wolkenbedeckung über 7000 m PPPP [hPa] - Druckäquivalent auf Meereshöhe&lt;br /&gt;
&lt;br /&gt;
* Zusätzliche Tageseigenschaften, nicht vom DWD bereitgestellt SunRise - Sonnenaufgangszeit basierend auf dem Zeitzonenattribut SunSet - Sonnenuntergangszeit basierend auf dem Zeitzonenattribut&lt;br /&gt;
&lt;br /&gt;
* Zusätzliche Stundeneigenschaften, nicht vom DWD bereitgestellt SunAz [°] - Sonnenazimut SunEl [°] - Sonnenhöhe SunUp - Sonnenaufgang (0: Nacht, 1: Tag)&lt;br /&gt;
&lt;br /&gt;
Zusätzlich gibt es globale Prognosewerte:&lt;br /&gt;
&lt;br /&gt;
* fc_state - Status der letzten Prognoseaktualisierung, mögliche Werte sind „updated“ und „error: ...“&lt;br /&gt;
* fc_station - Prognosestationscode (WMO oder DWD)&lt;br /&gt;
* fc_description - Stationsbeschreibung&lt;br /&gt;
* fc_coordinates - Weltkoordinate und Höhe der Station&lt;br /&gt;
* fc_time - Zeitpunkt der Veröffentlichung der Prognose basierend auf dem Zeitzonenattribut&lt;br /&gt;
* fc_copyright - rechtliche Informationen, müssen mit Prognosedaten angezeigt werden, siehe DWD-Nutzungsbedingungen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Alarmwerte sind nach Beginn sortiert und folgendermaßen aufgebaut:&lt;br /&gt;
 a_&amp;lt;index&amp;gt;_&amp;lt;property&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* index - Alarmindex, beginnend mit 0, Gesamtanzahl a_count, sortiert nach Beginn&lt;br /&gt;
&lt;br /&gt;
* alert properties category - „Met“ oder „Health“ event - numerischer Ereigniscode, siehe DWD-Dokumentation für Details eventDesc - kurze Ereignisbeschreibung in ausgewählter Sprache eventGroup - Ereignisgruppe, siehe DWD-Dokumentation für Details responseType - „None“ = nein Anweisungen, „Vorbereiten“ = Anweisungen, „AllClear“ = Alarm gelöscht urgency – „Immediate“ = Warnung oder „Zukünftig“ = Information severity – „Minor, „Moderate“, „Severe“ or „Extreme“ areaColor – RGB-Farbe je nach Dringlichkeit und Schweregrad, durch Komma getrennte Dezimalzahlen onset – Startzeit des Alarms basierend auf dem Zeitzonenattribut expires – Endzeit des Alarms basierend auf dem Zeitzonenattribut headline – Überschrift in ausgewählter Sprache, normalerweise eine Kombination der Eigenschaften Dringlichkeit und Ereignis description – Beschreibung des Alarms in ausgewählter Sprache instruction – Sicherheitsanweisungen in ausgewählter Sprache area – numerische Warnzellen-ID areaDesc – Beschreibung des Bereichs, z. B. „Stadt Berlin“ altitude – min. Höhe [m] ceiling – max. Höhe [m]&lt;br /&gt;
&lt;br /&gt;
Zusätzlich gibt es einige globale Alarmwerte:&lt;br /&gt;
&lt;br /&gt;
* a_state – Status der letzten Alarmaktualisierung, mögliche Werte sind „aktualisiert“ und „Fehler: ...“&lt;br /&gt;
&lt;br /&gt;
* a_time – Zeitpunkt des Downloads der letzten Alarmaktualisierung, basierend auf der Zeitzone attribut&lt;br /&gt;
&lt;br /&gt;
* a_count – Anzahl der für die ausgewählte Warnzellen-ID verfügbaren Alarme&lt;br /&gt;
&lt;br /&gt;
* a_copyright – rechtliche Informationen, müssen mit Prognosedaten angezeigt werden, siehe DWD-Nutzungsbedingungen, nicht verfügbar, wenn count null ist&lt;br /&gt;
&lt;br /&gt;
Alarme sollten unabhängig von der Dringlichkeit für onset &amp;lt;= now &amp;lt; expires und responseType != „AllClear“ als aktiv betrachtet werden. Inaktive Alarme mit responseType = „AllClear“ können relevante Anweisungen enthalten.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass alle Alarmwerte bei jeder Aktualisierung vollständig ersetzt und neu indexiert werden!&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zu den Alarmeigenschaften finden Sie in der Dokumentation des CAP DWS-Profils.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
=== Beispiel zur Modul-Einrichtung ===&lt;br /&gt;
&lt;br /&gt;
* Wettervorhersage&lt;br /&gt;
Für die Wettervorhersage muss der Stationscode ermittelt werden. Dazu den [https://www.dwd.de/DE/leistungen/met_verfahren_mosmix/mosmix_stationskatalog.pdf MOSMIX Stationskatalog] herunterladen, öffnen und die gewünschte Station heraussuchen (Spalte &#039;&#039;id&#039;&#039;). Einen Teil der deutschen Stationen kann man auch der [https://www.dwd.de/DE/derdwd/messnetz/bodenbeobachtung/messnetzkarte_boden.pdf Bodenmessnetzkarte] entnehmen. Den ermittelten Stationscode kann man dann entweder für eine Einzelabfrage als Parameter für das Kommando &#039;&#039;get forecast&#039;&#039; verwenden oder für die automatische Aktualisierung als Attribut &#039;&#039;forecastStation&#039;&#039; hinterlegen. Insgesamt werden vom DWD mehr als 70 Merkmale zur Verfügung gestellt. Eine Auflistung findet sich im Dokument [https://opendata.dwd.de/weather/lib/MetElementDefinition.xml MetElementDefinition]. Nur ein kleiner Teil der Merkmale wird in der Standardeinstellung des Moduls als Reading zur Verfügung gestellt. Wer andere Merkmale benötigt muss sie mit Komma getrennt dem Attribut &#039;&#039;forecastProperties&#039;&#039; zuweisen. Es empfiehlt sich zur Performance-Optimierung sowohl das Attribut &#039;&#039;forecastDays&#039;&#039; als auch das Attribut &#039;&#039;forecastProperties&#039;&#039; auf den tatsächlichen Bedarf einzustellen.&lt;br /&gt;
&lt;br /&gt;
* Wetterwarnungen&lt;br /&gt;
Für die Wetterwarnungen muss die Warnzelle ermittelt werden. Dazu [https://www.dwd.de/DE/leistungen/opendata/help/warnungen/cap_warncellids_csv.csv Warnzellen-ID Katalog] herunterladen, öffnen und die gewünschte Warnzelle heraussuchen. Unterstützt werden Gemeinden (beginnen mit 8), Landkreise (beginnen mit 1 oder 9) oder Küste (beginnen mit 5). Die Warnzellen-ID kann man dann entweder für eine Einzelabfrage als Parameter für das Kommando &#039;&#039;get alerts&#039;&#039; verwenden oder für die automatische Aktualisierung als Attribut &#039;&#039;alertArea&#039;&#039; hinterlegen. Die Warnzellen-ID ist ab der 2. Stelle identisch mit den ersten Ziffern des amtlichen Gemeindeschlüssels. Man kann z.B. den Namen von Gemeinde oder Landkreis bei den [https://www.statistik-bw.de/Statistik-Portal/gemeindeverz.asp Statistischen Ämtern des Bundes und der Länder] eingeben, den amtlichen Gemeindeschlüssel ermitteln und dann mit vorangestellter 1, 8 oder 9 im Warnzellen-ID Katalog des DWD nach einem Eintrag mit exakter oder weitgehender Übereinstimmung suchen. Wem das zu kompliziert vorkommt, der kann bei mehrdeutigen Gemeinde- bzw. Landkreisbezeichnungen auch versuchen auszuprobieren, welche die richtige Warnzellen-ID ist.&lt;br /&gt;
&lt;br /&gt;
Um das Modul mit automatisch Aktualisierung von Vorhersage und Wetterwarnungen zu nutzen, kann z.B. folgendes in die [[Konfiguration]] eingetragen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 define DWD DWD_OpenData&lt;br /&gt;
 attr DWD alertArea 111000000&lt;br /&gt;
 attr DWD forecastStation 99810&lt;br /&gt;
 attr DWD forecastDays 3&lt;br /&gt;
 attr DWD forecastWW2Text 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Performance&lt;br /&gt;
Das DWD_OpenData-Modul ist ein Datenmodul mit relativ vielen Readings. In der Standardkonfiguration wird, wie bei jedem anderen FHEM Modul, bei jeder Änderung jedes Readings ein FHEM internes Ereignis erzeugt, damit andere FHEM Devices auf diese Änderungen reagieren können. Diese Ereignisse sorgen auch dafür, dass man Änderungen in der Weboberfläche sofort angezeigt bekommt, ohne die Webseite neu aufzurufen. Interessiert sich aber kein FHEM Device für die Änderungsbenachrichtigung bestimmter Readings, entsteht unnötiger Verarbeitungs-Overhead, der je nach FHEM Konfiguration und verfügbarer CPU-Leistung auch mehrere Sekunden benötigen kann und in dieser Zeit andere Abläufe blockiert. Um die Performance zu optimieren, empfiehlt es sich,  mit [[event-on-update-reading]] für eine angepasste und dadurch effizientere Verarbeitung zu sorgen, indem man nur für jene Readings Ereignisse zulässt, welche man für die Weiterverarbeitung braucht. Der DWD_OpenData_Weblink braucht z.B. gar keine Ereignisse, um zu funktionieren. Hier eine minimalistische Beispielkonfiguration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr DWD event-on-update-reading state,fc_state,a_state&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Details zur Installation und Konfiguration des Moduls finden sich in der&lt;br /&gt;
{{Link2CmdRef|Anker=DWD_OpenData|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für die Einrichtung eines Meteogramms ===&lt;br /&gt;
Um den vorhergesagten Wetterverlauf als Meteogramm in Kurvenform mit [[SVG]] darzustellen, kann man wie folgt vorgehen:&lt;br /&gt;
&lt;br /&gt;
1. 99_myUtils.pm&lt;br /&gt;
&lt;br /&gt;
Für die Bestimmung der Werte für den SVG-Plot wird eine Perl-Funktion benötigt, die in die Datei 99_myUtils.pm vor dem Ende eingefügt wird. Wer diese FHEM-Datei noch nicht nutzt, legt sie einfach an (siehe [[99_myUtils_anlegen]]).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
package main;&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
 &lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# (c) mumpitzstuff 19.12.2018&lt;br /&gt;
#&lt;br /&gt;
# see https://forum.fhem.de/index.php/topic,83097.msg874150.html#msg874150&lt;br /&gt;
#&lt;br /&gt;
sub logProxy_dwd2Plot($$$$;$$$)&lt;br /&gt;
{&lt;br /&gt;
  my ($device, $fcValue, $from, $to, $fcHour, $expMode, $shiftTime) = @_;&lt;br /&gt;
  my $regex;&lt;br /&gt;
  my @rl;&lt;br /&gt;
&lt;br /&gt;
  return undef if(!$device);&lt;br /&gt;
&lt;br /&gt;
  if ($fcValue =~ s/_$//)&lt;br /&gt;
  {&lt;br /&gt;
    $regex = &amp;quot;^fc[\\d]+_[\\d]+_&amp;quot;.$fcValue.&amp;quot;\$&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    $regex = &amp;quot;^fc[\\d]+_&amp;quot;.$fcValue.&amp;quot;\$&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $fcHour = 12 if(!defined($fcHour));&lt;br /&gt;
  $expMode = &amp;quot;point&amp;quot; if(!defined($expMode));&lt;br /&gt;
  #Log3 undef,2, &amp;quot;Regex: &amp;quot;.$regex;&lt;br /&gt;
&lt;br /&gt;
  # ermitteln aller relevanten Readings&lt;br /&gt;
  if ( defined($defs{$device}) )&lt;br /&gt;
  {&lt;br /&gt;
    if ( $defs{$device}{TYPE} eq &amp;quot;DWD_OpenData&amp;quot; )&lt;br /&gt;
    {&lt;br /&gt;
      @rl = sort&lt;br /&gt;
      {&lt;br /&gt;
        my ($an) = ($a =~ m/fc(\d+)_.*/);&lt;br /&gt;
        my ($bn) = ($b =~ m/fc(\d+)_.*/);&lt;br /&gt;
        my ($ao) = ($a =~ m/fc\d+_(\d+).*/);&lt;br /&gt;
        my ($bo) = ($b =~ m/fc\d+_(\d+).*/);&lt;br /&gt;
        $an &amp;lt;=&amp;gt; $bn or $ao &amp;lt;=&amp;gt; $bo or $a cmp $b;&lt;br /&gt;
      } ( grep /${regex}/,keys %{$defs{$device}{READINGS}} );&lt;br /&gt;
      return undef if ( !@rl );&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      Log3 undef, 2, &amp;quot;logProxy_dwd2Plot: $device is not a DWD_OpenData device&amp;quot;;&lt;br /&gt;
      return undef;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my $fromsec = SVG_time_to_sec($from);&lt;br /&gt;
  my $tosec   = SVG_time_to_sec($to);&lt;br /&gt;
  my $sec = $fromsec;&lt;br /&gt;
  my ($h, $hp, $fcDay, $mday, $mon, $year);&lt;br /&gt;
  my $timestamp;&lt;br /&gt;
&lt;br /&gt;
  my $reading;&lt;br /&gt;
  my $value;&lt;br /&gt;
  my $prev_value;&lt;br /&gt;
  my $min = 999999;&lt;br /&gt;
  my $max = -999999;&lt;br /&gt;
  my $ret = &amp;quot;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  # while not end of plot range reached&lt;br /&gt;
  while (($sec &amp;lt; $tosec) &amp;amp;&amp;amp; @rl)&lt;br /&gt;
  {&lt;br /&gt;
    #remember previous value for start of plot range&lt;br /&gt;
    $prev_value = $value;&lt;br /&gt;
&lt;br /&gt;
    $reading = shift @rl;&lt;br /&gt;
    ($fcDay) = $reading =~ m/^fc(\d+).*/;&lt;br /&gt;
    ($hp) = $reading =~ m/^fc\d+_(\d+).*/;&lt;br /&gt;
    #Log 1, &amp;quot;hp: &amp;quot;.$hp;&lt;br /&gt;
&lt;br /&gt;
    if ($hp)&lt;br /&gt;
    {&lt;br /&gt;
      $h = ReadingsVal($device, &amp;quot;fc&amp;quot;.$fcDay.&amp;quot;_&amp;quot;.$hp.&amp;quot;_time&amp;quot;, $fcHour);&lt;br /&gt;
      if ($h =~ m/^(\d+):\d+/)&lt;br /&gt;
      {&lt;br /&gt;
        $h = $1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      $h = $fcHour;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $value = ReadingsVal($device, $reading, undef);&lt;br /&gt;
&lt;br /&gt;
    # calculate minutes of sunshine per hour&lt;br /&gt;
    if ($fcValue =~ /^SunD(\d+)/)&lt;br /&gt;
    {&lt;br /&gt;
      if (defined($1))&lt;br /&gt;
      {&lt;br /&gt;
        $value = $value / ($1 * 36);&lt;br /&gt;
      }&lt;br /&gt;
      else&lt;br /&gt;
      {&lt;br /&gt;
        $value = $value / (12 * 36);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # calculate amount of rain per hour&lt;br /&gt;
    if ($fcValue =~ /^RR(\d+)c$/)&lt;br /&gt;
    {&lt;br /&gt;
      if (defined($1))&lt;br /&gt;
      {&lt;br /&gt;
        $value /= $1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    ($year, $mon, $mday) = split(&#039;\-&#039;,ReadingsVal($device, &amp;quot;fc&amp;quot;.$fcDay.&amp;quot;_date&amp;quot;,undef));&lt;br /&gt;
    $timestamp = sprintf(&amp;quot;%04d-%02d-%02d_%02d:%02d:%02d&amp;quot;, $year, $mon, $mday, $h, 0, 0);&lt;br /&gt;
    $sec = SVG_time_to_sec($timestamp);&lt;br /&gt;
    if (defined($shiftTime))&lt;br /&gt;
    {&lt;br /&gt;
      $sec += $shiftTime;&lt;br /&gt;
      $timestamp = logProxy_shiftTime($timestamp, $shiftTime);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # skip all values before start of plot range&lt;br /&gt;
    next if ( $sec &amp;lt; $fromsec );&lt;br /&gt;
&lt;br /&gt;
    # add first value at start of plot range&lt;br /&gt;
    if ( !$ret &amp;amp;&amp;amp; $prev_value )&lt;br /&gt;
    {&lt;br /&gt;
      $min = $prev_value if ( $prev_value &amp;lt; $min );&lt;br /&gt;
      $max = $prev_value if ( $prev_value &amp;gt; $max );&lt;br /&gt;
      $ret .= &amp;quot;$from $prev_value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # done if after end of plot range&lt;br /&gt;
    last if ($sec &amp;gt; $tosec);&lt;br /&gt;
&lt;br /&gt;
    $min = $value if ( $value &amp;lt; $min );&lt;br /&gt;
    $max = $value if ( $value &amp;gt; $max );&lt;br /&gt;
&lt;br /&gt;
    # add actual control point&lt;br /&gt;
    $ret .= &amp;quot;$timestamp $value\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (($sec &amp;lt; $tosec) &amp;amp;&amp;amp; !@rl &amp;amp;&amp;amp; ($expMode eq &amp;quot;day&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
    $timestamp = sprintf(&amp;quot;%04d-%02d-%02d_%02d:%02d:%02d&amp;quot;, $year, $mon, $mday, 23, 59, 59);&lt;br /&gt;
    $_ = SVG_time_to_sec($timestamp);&lt;br /&gt;
    if (defined($shiftTime))&lt;br /&gt;
    {&lt;br /&gt;
      $_ += $shiftTime;&lt;br /&gt;
      $timestamp = logProxy_shiftTime($timestamp, $shiftTime);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($_ &amp;lt; $tosec)&lt;br /&gt;
    {&lt;br /&gt;
      $ret .= &amp;quot;$timestamp $value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      $ret .= &amp;quot;$to $value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  elsif (($sec &amp;gt; $tosec) &amp;amp;&amp;amp; ($expMode eq &amp;quot;day&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
    $value = $prev_value + ($value - $prev_value) * (86400 + ($tosec - $sec)) / 86400;&lt;br /&gt;
    $ret .= &amp;quot;$to $value\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ($ret, $min, $max, $prev_value);&lt;br /&gt;
} &lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. LogProxy&lt;br /&gt;
&lt;br /&gt;
Wer bereits ein [[logProxy]]-Device hat, muss den Namen seines logProxy-Devices in die weiter unter aufgeführte GPlot-Konfiguration eintragen. Ansonsten wird es wie folgt neu erstellt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define LogProxy logProxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. FileLog&lt;br /&gt;
&lt;br /&gt;
Das Meteogramm kennt anders als andere FHEM-Plots keine Vergangenheit außer heute. Trotzdem wird aus formalen Gründen ein [[FileLog]]-Device benötigt. Dazu kann ein beliebiges vorhandenes FileLog-Device verwendet werden. Wer will, kann hierfür aber auch ein neues FileLog Device für das DWD_OpenData-Device anlegen (Achtung: wird schnell umfangreich):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define FileLog_DWD FileLog ./log/DWD-%Y-%m.log DWD&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im folgenden wird für das FileLog-Device der Platzhalter &#039;&#039;FileLog_Dummy&#039;&#039; verwendet, der mit dem Namen des gewählten FileLog-Devices zu ersetzen ist.&lt;br /&gt;
&lt;br /&gt;
4. SVG Plot&lt;br /&gt;
&lt;br /&gt;
Das eigentliche Meteogramm ist ein SVG-Device. Will man mehrere Tage darstellen bietet sich die folgende Definition an:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_DWD SVG FileLog_Dummy:SVG_DWD:CURRENT&lt;br /&gt;
attr SVG_DWD fixedoffset 6&lt;br /&gt;
attr SVG_DWD fixedrange 7days&lt;br /&gt;
attr SVG_DWD nrAxis 1,2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei muss das SVG-Attribut &#039;&#039;fixedoffset&#039;&#039; entweder gleich oder kleiner als die Einstellung des DWD_OpenData-Attributs &#039;&#039;forecastDays&#039;&#039; (Standardwert: 6 Tage) gewählt werden und das SVG-Attribut &#039;&#039;fixedrange&#039;&#039; um eins größer als &#039;&#039;fixedoffset&#039;&#039; eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Will man stattdessen nur die nächsten 24 Stunden anzeigen, nimmt man folgende Einstellungen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_DWD SVG FileLog_Dummy:SVG_DWD:CURRENT&lt;br /&gt;
attr SVG_DWD endPlotNow 1&lt;br /&gt;
attr SVG_DWD fixedoffset 1&lt;br /&gt;
attr SVG_FileLog_WETTER_DWD_3 label &amp;quot;Tmin: $data{max1} °C, Tmax: $data{min1} °C&amp;quot;&lt;br /&gt;
attr SVG_DWD nrAxis 1,2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um die DWD_OpenData-Readings mit dem Plot zu verknüpfen, muss man nun die GPlot-Konfigurationsdatei des SVG-Plots manuell bearbeiten. Dazu auf den Link klicken, der im SVG_DWD-Device am Internal &#039;&#039;GPLOTFILE&#039;&#039; steht. Die y-Wertebereiche für die Regenmenge und die Temperaturen sind im Beispiel auskommentiert (Autorange). Das kann man so lassen oder man stellt sie nach den eigenen Wetter-Gegebenheiten ein. Je nach Konfiguration des DWD_OpenData-Attributs &#039;&#039;forecastResolution&#039;&#039; sind aber noch einige weitere Einstellungen anzupassen. Das folgende Beispiel ist für die 3h-Auflösung:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;Wettervorhersage&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid ytics&lt;br /&gt;
set ylabel &amp;quot;Regen [mm]&amp;quot;&lt;br /&gt;
#set yrange [0:4]&lt;br /&gt;
set y2label &amp;quot;Temperatur [°C]&amp;quot;&lt;br /&gt;
#set y2range [-5:35]&lt;br /&gt;
set y3label &amp;quot;Wolken/Regen/Sonne [%]&amp;quot;&lt;br /&gt;
set y3range [0:100]&lt;br /&gt;
&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tx&amp;quot;,$from,$to,18,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tn&amp;quot;,$from,$to,6,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD3_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR3c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R600_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstX:TimeNow(),0,100&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;T&#039; ls l0 lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Tmax&#039; ls l0dot lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Tmin&#039; ls l0dot lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Sonne&#039; ls l4fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Regenmenge&#039; ls l2fill lw 1 with steps,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wind&#039; ls l1 lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Regen&#039; ls l5fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wolken&#039; ls l6fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 notitle ls l5 lw 4 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 notitle ls l5 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verwendet man dagegen eine Auflösung von 1 Stunde, sind folgende LogProxy-Einträge erforderlich:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tx&amp;quot;,$from,$to,18,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tn&amp;quot;,$from,$to,6,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR1c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R101_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-0.5*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstX:TimeNow(),0,100&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für die Darstellung der nächsten 24 Stunden mit einer Auflösung von 1 Stunde nimmt man folgende GPlot-Konfiguration:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;L1&amp;gt;&#039;&lt;br /&gt;
set ytics&lt;br /&gt;
set y2tics&lt;br /&gt;
set y3tics&lt;br /&gt;
set grid xtics y2tics&lt;br /&gt;
set ylabel &amp;quot;Regen [mm]&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Temperatur [°C]&amp;quot;&lt;br /&gt;
set y3label &amp;quot;Wolken/Regen/Sonne [%]&amp;quot;&lt;br /&gt;
set y3range [0:100]&lt;br /&gt;
&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR1c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R101_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-0.5*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;T&#039; ls l0 lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Sonne&#039; ls l4fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Regenmenge&#039; ls l2fill lw 1 with steps,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wind&#039; ls l1 lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Regen&#039; ls l5fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wolken&#039; ls l6fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 notitle ls l2 lw 2 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nachdem, welche Auflösung man verwendet, werden unterschiedliche Readings des DWD_OpenData-Devices benötigt. Diese sind in den LogProxy-Zeilen in der GPlot-Konfigurationsdatei zu finden und müssen auf jeden Fall dem Attribut &#039;&#039;forecastProperties&#039;&#039; des DWD_OpenData-Device hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
Viele Detaileinstellungen des Meteogramms lassen sich individualisieren. Man kann z.B. mehr oder weniger Daten anzeigen und zumindest für &#039;&#039;heute&#039;&#039; auch aktuelle Messwerte hinzufügen.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel für ein Meteogramm über 4 Tage mit 3 Stunden Auflösung:&lt;br /&gt;
&lt;br /&gt;
[[File:DWDODmeteogram4d3h.png|500px]]&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für die Einrichtung eines Weblinks ===&lt;br /&gt;
Zur graphischen Darstellung der Vorhersage und der Wetterwarnungen mit [[FHEMWEB]] steht das Modul [https://raw.githubusercontent.com/jnsbyr/fhem/master/FHEM/98_DWD_OpenData_Weblink.pm 98_DWD_OpenData_Weblink.pm] zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Zunächst die Moduldatei herunterladen und in das Modulverzeichnis &#039;&#039;fhem/FHEM&#039;&#039; kopieren. Entweder die Datei direkt auf den FHEM-Server herunterladen (z.B. mit &#039;&#039;wget&#039;&#039;) oder beim indirekten Herunterladen darauf achten, dass dabei das Encoding nicht verändert wird (also z.B. bei WinSCP den Binär-Modus und nicht den Text-Modus verwenden). Ansonsten werden später z.B. Sonderzeichen wie &#039;&#039;°C&#039;&#039; falsch angezeigt. &lt;br /&gt;
&lt;br /&gt;
Anschließend kann in die [[Konfiguration]] z.B. folgendes eingetragen werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
 define DWD_Weblink_Generator DWD_OpenData_Weblink&lt;br /&gt;
 attr DWD_Weblink_Generator IODev DWD&lt;br /&gt;
 attr DWD_Weblink_Generator forecastDays 4&lt;br /&gt;
 # refreshRate nur dann setzten, wenn der Browser Java-Script beherrscht:&lt;br /&gt;
 attr DWD_Weblink_Generator refreshRate 900&lt;br /&gt;
 &lt;br /&gt;
 define DWD_Weblink weblink htmlCode { DWD_OpenData_Weblink::AsHtmlH(&amp;quot;DWD_Weblink_Generator&amp;quot;) } &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit legt man das Weblink-Generator-Device an und verknüpft es mit dem DWD_OpenData-Device. Außerdem wird der [[weblink ]] selbst angelegt, der seinerseits mit dem Weblink-Generator-Device verknüpft wird. Der Weblink benötigt für seine Funktion eine bestimmte Auswahl der Vorhersage-Merkmale. Wer das Attribut &#039;&#039;forecastProperties&#039;&#039; des DWD_OpenData-Moduls anpassen will, muss diese Merkmale auf jeden Fall mit berücksichtigen. &lt;br /&gt;
&lt;br /&gt;
Wenn vom Weblink nichts im Browser zu sehen ist, kann das daran liegen, dass der Browser kein aktuelles JavaScript verwendet oder JavaScript deaktiviert ist. Dann sollte das Attribut &#039;&#039;refreshRate&#039;&#039; auf 0 Sekunden eingestellt oder gelöscht werden. Mit aktiviertem Refresh werden die Daten auch ohne Seitenneuaufbau regelmäßig und bei Tab-Wechsel aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Die Liste der erforderlichen Vorhersage-Merkmale finden sich zusammen mit allen weiteren Details zur Installation und Konfiguration in der Modulhilfe von &#039;&#039;98_DWD_OpenData_Weblink.pm&#039;&#039;, die man z.B. nach dem Anlegen des Weblink-Generator-Devices über die Weboberfläche abrufen kann.&lt;br /&gt;
&lt;br /&gt;
Hier ein Ausschnitt aus der Darstellung des Weblinks mit [[FHEMWEB]]:&lt;br /&gt;
[[File:DWDODweblink.png|500px]]&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für die Einbindung auf einer Webseite außerhalb von FHEM ===&lt;br /&gt;
Für manche Anwendungsfälle, etwa die Ansicht in FTUI, ist es erforderlich, das mit dem &#039;&#039;&#039;DWD_Weblink_Generator&#039;&#039;&#039; erzeugte Bild an anderer Stelle in eine Webseite einzubinden. Dazu kann man folgende Schritte verwenden. &lt;br /&gt;
&lt;br /&gt;
Zunächst wird ein statisches CSS-Stylesheet erzeugt, etwa in der Datei &#039;&#039;ftui_weather.css&#039;&#039; im Unterverzeichnis &#039;&#039;css&#039;&#039;. Dorthin werden die ganzen CSS-Klassen geschrieben, die der Webbrowser benötigt, um aus den Daten des DWD_Weblink_Generator eine Tabelle zu machen (siehe den etwas länglichen Code am Ende dieses Abschnitts).&lt;br /&gt;
&lt;br /&gt;
Dann ist zunächst dafür zu sorgen, dass im Header der Webseite, die später die Wettervorhersage anzeigen soll, dieses Stylesheet eingebunden wird. Dazu muss in den Header die Zeile&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;css/ftui_weather.css&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
eingetragen werden.&lt;br /&gt;
&lt;br /&gt;
Der zweite Schritt besteht darin, ebenfalls in den Header der betreffenden Webseite ein paar Zeilen JavaScript einzubinden, die dem Holen der Daten dienen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
    function getDWDOpenDataWeblink() {&lt;br /&gt;
        var fwcsrf = &amp;quot;&amp;lt;HIER DER csrf-Token DES ENTFERNTEN FHEM-SERVERS&amp;gt;&amp;quot;;&lt;br /&gt;
        $. get (&amp;quot;http://&amp;lt;HIER DIE ADRESSE DES ENTFERNTEN FHEM-SERVERS&amp;gt;:8083/fhem?cmd=get%20DWD_Weblink_Generator%20horizontalForecast&amp;amp;XHR=1&amp;amp;fwcsrf=&amp;quot; + fwcsrf,&lt;br /&gt;
        function (forecastElements) {&lt;br /&gt;
            $(&amp;quot;#DWD_OpenData_Weblink&amp;quot;).html(forecastElements);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    function getdata() {&lt;br /&gt;
        getDWDOpenDataWeblink();&lt;br /&gt;
        setInterval(getDWDOpenDataWeblink, 900000);&lt;br /&gt;
        $(window).on(&amp;quot;focus&amp;quot;, getDWDOpenDataWeblink);&lt;br /&gt;
    };&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der dritte Schritt besteht darin, auf der betreffenden Webseite einen Ort zu definieren, an welchen das Wettervorhersagebild geschoben wird, z.B.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;DWD_OpenData_Weblink&amp;quot; style=&amp;quot;position:absolute; left:10px;top:500px; width:600px; height:200px; float:left; overflow-y:hidden;overflow-x:auto;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der letzte Schritt sorgt dafür, dass die oben definierte JavaScript-Funktion beim Laden der Webseite auch aufgerufen wird. Dazu muss ein entsprechendes Attribut im body-Tag der Seite eingebaut werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;body onload=&amp;quot;getdata()&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nachstehend nun der etwas längliche CSS-Code für das statische Stylesheet:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
/* weather table with fixed column width */&lt;br /&gt;
.weatherForecast {&lt;br /&gt;
    display: table;&lt;br /&gt;
    table-layout: fixed;&lt;br /&gt;
    column-gap: 40px;&lt;br /&gt;
}&lt;br /&gt;
/* weather table header row */&lt;br /&gt;
.weatherHeaderRow {&lt;br /&gt;
    display: table-header-group;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
/* weather table data row */&lt;br /&gt;
.weatherDataRow {&lt;br /&gt;
    display: table-row-group;&lt;br /&gt;
}&lt;br /&gt;
/* weather table data cells */&lt;br /&gt;
#weatherFontBold {&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
.weatherWeekday {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    min-width: 80px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.weatherCondition {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    position: relative;&lt;br /&gt;
    top: -4px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    font-size: 80%;&lt;br /&gt;
    word-wrap: break-word;&lt;br /&gt;
}&lt;br /&gt;
.weatherTemperature {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    font-size: 100%;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
.weatherWind {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    font-size: 80%;&lt;br /&gt;
    padding-top: 3px;&lt;br /&gt;
}&lt;br /&gt;
/* weather table condition icon cell */&lt;br /&gt;
.weatherIcon {&lt;br /&gt;
    display: table-cell;&lt;br /&gt;
    position: relative;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
/* weather icon */&lt;br /&gt;
.weatherIcon img {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
/* embedded alert icon with pointer support */&lt;br /&gt;
.weatherAlertIcon {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    top: 5px;&lt;br /&gt;
    right: 5px;&lt;br /&gt;
    width: 25px;&lt;br /&gt;
    height: 22px;&lt;br /&gt;
    background-size: 25px 22px;&lt;br /&gt;
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAkCAMAAADM4ogkAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NjcyOSwgMjAxMi8wNS8wMy0xMzo0MDowMyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDEyLjAgV2luZG93cyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1RjU1NzJBRDMyRTcxMUU1QTk4MkI0RTkwODEwODQ1QSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1RjU1NzJBRTMyRTcxMUU1QTk4MkI0RTkwODEwODQ1QSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjVGNTU3MkFCMzJFNzExRTVBOTgyQjRFOTA4MTA4NDVBIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjVGNTU3MkFDMzJFNzExRTVBOTgyQjRFOTA4MTA4NDVBIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+oFydjAAAAwBQTFRF9fX267W51Csy9d7c1VBV9uPc/vz89+nl5YB/2Flk2mZp1Cgv0Csw5pWR7K2t1Soy1Cow7b6y0iUr+/r61jI54X+A+uvq21xV44qO/fj400tU1kxG3nNx2mJp34Bz/Pj2a2tr4Ht91S43fn5+1jA31S0y0iYu1TA1/ff3+/TxEhIS3W1u1jA010Q++efj1kVH1Tk+gYGB6qWh4oWEtra21TI48sjH1VVc1tbW1jY22ltd4YF/1kFHl5eX/vz7/Pz84nZt+evt9+Tm2mNu1Sw14YSD1Ss04YKC0isv4X5/0zc21CUu8cnL0jA20jAz22xy1jE422Zv1i800isw1Cgx11xjKysr1FFZ4X190iQsGRkZ0jY+1TE41Cww0y0y0ykt1i431i4z0y800ikvPz4/AAAA////DQwM1TI30yYs1TE31TA21TE21S401S801S810ycs//7+1TA3///+/v791TI2/v//0Sov0iYt0yYt6urqkZGR1TM40ycu1S414ODg4YB3+/Hw7bK0/vv78fHxh4eH+OPf0i8w1DI30icu1y843Zia/PX13Nvb6aWZ4YKE+fDv21RT00E83G5y3m9x7tDF3Gdu99fW1EJK1ktK3t7e5I+R4oeH3WNp3oCF+vH16ZOJ1Sw27cG31i018dDL4qOf3Wde7Kqe+O7m2ERH+e3o+u/t4YuY/Pb15IqG5p2R4np52TA82mhx2V1p3mpx5oWL66uiRkZG4YOR/v7+1ygz1TxC8dDV9dHS2VJL1CUw8by79+Hg7bq3vr6+9dnR1Tc49d/X11le77yv22hl2lVY+Ofo33540icspqan+/f49N/h5J6m2HB7zczN3nZ88c3FsrKz3HZ74ICC4YGA1oJy10JD+Onj8c3J1Dk71T494oaE4HpxNTU14XRz7Ozs7+/vcG9v+/bz/Pj1/fr3IiIi676/5IJx4Hpr6amn56On6aGd2mlu4X2A22Vm2WFk1jI33GNk+/Ds2VJU2FZW8/Pz78jD3V1v55iY3W1x////C1yJRAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAMKSURBVHjajNEFWBNxGAbwOXEoUzYnqCgGuPMUUFE8sRuwgDlUEJmK8z6/XWyEEjrswu7u7u7u7u4u7G7FWxoj/J6L9/7v77nnQpTpMM7XFkocV0UOK2VKbkt3/R+4KY0Zlnw8d7ikBeu9VroRcoXPg5F1Y5Mn5wYPaRnGqOxMfPbIGXZfFMxxJGtg0lxzhoWlKpYfSrCd9f4rc4JPKs1l9B1aeabGoLRQTnBxG8T2K2DwLV7FRVTOHi47yKKmxGyAagoGxb7x2cLSMuS0eZIAMopJUaWtkR3M1yUBpe8lkuoj4WYYm8Bf98gaxjdsSik7toKydPQ0OKEzUnGuWcOLWgZPXoCe3Wi6HlS+zVMG/35Zwfq7eqO+wxk4T9N0OYDXKQylnZ4VnKdxM5bfAtDTh6arAlT4IldxXYo6woyS3hwxpRHA12ia7gUA3yKUKL8f7wCPiClMOSsA0VPTMwIkeeoQm+39F1asZECZ02kBFGlH06eEM+Rt0RvFHyX/wNUy7JGex9Q3EGB1U4BCLVXK9D1/wxu1lJS8lMTc36Pp/eZQcaoM9Us9/oSJL8QUGbrDXMNmOvqBJe3TxqC22p/wgIbBlrMsLZSju1pT93dSZDsW/Q3rF/NG3r+xte4zqKY1QY0IBuVvwQ4LazFGUTzRVhexJziahkzyTht8PM6AwXUbWbutj3za2W+5IIxEovYAKxwlww+KV7buYTfzL7TODOGry/tb4KdaCSg/VsFWDfSx/ELLLK9CILl9hBnOEaOq4DN7BZe6lv36++plJ3ST/zDBfEOEN6udBNnNWDHFhTpnihIbNkXKUNfLyyuqeciVOwFvr7oHrApqHhTiPjog6EqdNVFVDIji/JmiiYQbopFM3R0XF6fT6VJ15jFFnUJhSqQRETV5RXfnGykhMea9B2M624ezBaOmuKiv1GDg9TxJ8sIxltB7E0QsT/BqpdrPT9g4P7VaTcZKL4vGDP/psq71BpdSLj9nTmod3mTC+HDfN+FN2jodjlwfGRnoFNg2cH2B7+ca/xJgAFL1l3PxpIx4AAAAAElFTkSuQmCC);&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:hover {&lt;br /&gt;
    opacity: 0.7;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus {&lt;br /&gt;
    opacity: 1.0;&lt;br /&gt;
}&lt;br /&gt;
/* opaque white background for alerts dialog */&lt;br /&gt;
.weatherOverlay {&lt;br /&gt;
    display: none;&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    z-index: 1;&lt;br /&gt;
    opacity: 0.2;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    background: white;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus .weatherOverlay {&lt;br /&gt;
    display: block;&lt;br /&gt;
}&lt;br /&gt;
/* alerts dialog box */&lt;br /&gt;
[class ^= weatherAlertBox] {&lt;br /&gt;
    display: none;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    z-index: 2;&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    border: 3px solid white;&lt;br /&gt;
    border-radius: 3px;&lt;br /&gt;
    box-shadow: 0px 0px 6px 4px #666;&lt;br /&gt;
    background: #EEE;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus .weatherAlertBoxLeft {&lt;br /&gt;
    display: block;&lt;br /&gt;
    right: -268px;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus .weatherAlertBoxCenter {&lt;br /&gt;
    display: block;&lt;br /&gt;
    left: -178px;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertIcon:focus .weatherAlertBoxRight {&lt;br /&gt;
    display: block;&lt;br /&gt;
    left: -312px;&lt;br /&gt;
}&lt;br /&gt;
/* alerts dialog close button */&lt;br /&gt;
.weatherAlertsClose {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    top: -12px;&lt;br /&gt;
    right: -13px;&lt;br /&gt;
&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    box-shadow: 1px 1px 3px #666;&lt;br /&gt;
&lt;br /&gt;
    line-height: 21px;&lt;br /&gt;
    width: 21px;&lt;br /&gt;
    background: #606061;&lt;br /&gt;
&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    text-decoration: none;&lt;br /&gt;
    font-family: Sans-serif;&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: white;&lt;br /&gt;
}&lt;br /&gt;
.weatherAlertsClose:hover {&lt;br /&gt;
    opacity: 0.8;&lt;br /&gt;
}&lt;br /&gt;
/* alerts dialog title */&lt;br /&gt;
.weaterAlertsTitle {&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: black;&lt;br /&gt;
}&lt;br /&gt;
/* alert messages */&lt;br /&gt;
[class ^= weaterAlertMessage] {&lt;br /&gt;
    float: left;&lt;br /&gt;
    text-align: left;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
.weaterAlertMessage p {&lt;br /&gt;
    white-space: normal;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Calendar&amp;diff=39372</id>
		<title>Calendar</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Calendar&amp;diff=39372"/>
		<updated>2024-06-23T06:26:42Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Kapitel &amp;quot;Events&amp;quot; aus commandref in Wiki übernommen.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anlegen eines Kalenderobjekts&lt;br /&gt;
|ModType=h&lt;br /&gt;
|ModForumArea=Unterstützende Dienste/Kalendermodule&lt;br /&gt;
|ModTechName=57_Calendar.pm&lt;br /&gt;
|ModOwner=borisneubert ({{Link2FU|10|Dr. Boris Neubert}})&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Calendar]] ist ein Hilfsmodul, das Kalenderereignisse aus einer Datei oder einem über die URL angegeben Kalender holt. Der Kalender muss im iCal-Format vorliegen.&lt;br /&gt;
&lt;br /&gt;
Zur Anzeige der Kalenderereignisse kann das Modul [[CALVIEW]] verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Wenn die Kalender-URL mit &#039;&#039;https://&#039;&#039; beginnt, muss das Perl Modul IO::Socket::SSL installiert sein (z.B. mit &amp;lt;code&amp;gt;cpan -i IO::Socket::SSL&amp;lt;/code&amp;gt; oder mit &amp;lt;code&amp;gt;apt-get install libio-socket-ssl-perl&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
=== Define ===&lt;br /&gt;
Siehe {{Link2CmdRef|Anker=Calendardefine}};&lt;br /&gt;
:&amp;lt;code&amp;gt;define &amp;lt;name&amp;gt; Calendar ical url &amp;lt;URL&amp;gt; [&amp;lt;interval&amp;gt;]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;define &amp;lt;name&amp;gt; Calendar ical file &amp;lt;FILENAME&amp;gt; [&amp;lt;interval&amp;gt;]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sofern für den Zugriff auf den Kalender Benutzername und Passwort erforderlich sind, können diese in der URL beispielsweise so mit angegeben werden:&lt;br /&gt;
:&amp;lt;code&amp;gt;define myCalendar Calendar ical url &amp;lt;nowiki&amp;gt;https://user:password@my.domain.com/.../yourcalendar.ics&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Attribute ===&lt;br /&gt;
Siehe {{Link2CmdRef|Anker=Calendarattr}};&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
Wenn der Kalendar neu geladen oder aktualisiert oder eine Alarm-, Start- oder Endzeit  erreicht wurde, wird ein FHEM-Event erzeugt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;triggered&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann sich darauf verlassen, dass alle Readings des Kalenders in einem konsistenten und aktuellen  Zustand befinden, wenn dieses Event empfangen wird.&lt;br /&gt;
&lt;br /&gt;
Wenn ein Termin geändert wurde, werden zwei FHEM-Events erzeugt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;changed: UID &amp;lt;mode&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;mode&amp;gt;: UID&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;mode&amp;gt; ist der aktuelle Modus des Termins nach der Änderung. Bitte beachten: Im FHEM-Event befindet sich ein Doppelpunkt gefolgt von einem Leerzeichen.&lt;br /&gt;
&lt;br /&gt;
FHEM-Events sollten nur auf den vorgenannten Events basieren und nicht auf FHEM-Events, die durch ändern eines mode... Readings ausgelöst werden.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiel(e) ==&lt;br /&gt;
* Einbindung von owncloud-Kalendern&lt;br /&gt;
Für ownCloud-Kalender muss bei der Definition als &amp;lt;URL&amp;gt; der Link zum Export des jeweiligen Kalenders angegeben werden. Der Link kann in der Weboberfläche von ownCloud gefunden werden. Für ownCloud 9.0 folgt dieser URL z.B. dem folgenden Muster:&lt;br /&gt;
:&amp;lt;code&amp;gt;http://&amp;lt;ownCloud-Benutzer&amp;gt;:&amp;lt;ownCloud-Passwort&amp;gt;@example.com/owncloud/remote.php/dav/calendars/&amp;lt;ownCloud-Benutzer&amp;gt;/&amp;lt;Kalendername&amp;gt;?export&amp;lt;/code&amp;gt;&lt;br /&gt;
Der Standard für &amp;lt;Kalendername&amp;gt; ist &amp;lt;code&amp;gt;defaultcalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
* [[Google-Kalender zur Steuerung von Dummies]]&lt;br /&gt;
* [[Wochenende, Feiertage und Schulferien]]&lt;br /&gt;
* Limitierungen im Sinne der Datenarmut nutzen&lt;br /&gt;
Die Attribute &amp;lt;code&amp;gt;hideOlderThan &amp;lt;timespec&amp;gt;&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;hideLaterThan &amp;lt;timespec&amp;gt;&amp;lt;/code&amp;gt; bewirken, dass nur Kalendereinträge des definierten Zeitraums angezeigt werden. Gerade bei langjährig genutzen Kalendern kann die Datenmenge ansonsten extrem groß werden und schlägt sich in entsprechend langen Update-Runs nieder.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Modul, das alle Termine aus einer bestehenden Instanz von [[Calendar]] in Readings übernimmt: [[CALVIEW]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39316</id>
		<title>AT kleine Helferlein</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39316"/>
		<updated>2024-04-26T16:33:52Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* AT alle x Wochen ausführen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein AT kann statt einer Uhrzeit bzw. eines Datums mit einer Uhrzeit auch eine Perl-Funktion nutzen. Beispiel solcher Funktionen sind [[At#at ultimo|at_ultimo]] oder das Modul [[SUNRISE_EL]]. Hier sollen weitere Funktionen vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Der Code kann in der [[99 myUtils anlegen|99 myUtils]] untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
== AT am x-ten Wochentag im Monat ausführen ==&lt;br /&gt;
&lt;br /&gt;
Aufgabe ist es, das at z.B. an jedem 2. Montag im Monat auszuführen. Zusätzlich gibt es auch die Möglichkeit, das at immer am z.B. letzten Montag im Monat auszuführen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# x.ten Wochentags im Monat&lt;br /&gt;
#&lt;br /&gt;
# x=1-4 x.ter Wochentag im Monat&lt;br /&gt;
# x=9   letzter Wochentag im Monat&lt;br /&gt;
# w=1-7 Wochentag, 1=Montag&lt;br /&gt;
# h,m,s Uhrzeit Stunde, Minute, Sekunde&lt;br /&gt;
#&lt;br /&gt;
sub at_xwday($$$$$) {&lt;br /&gt;
    my ($x,$w,$h,$m,$s) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $ziel_tag = 0;&lt;br /&gt;
&lt;br /&gt;
    # akt. Datum und Uhrzeit in Variablen aufteilen&lt;br /&gt;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = &lt;br /&gt;
        localtime(time);&lt;br /&gt;
&lt;br /&gt;
    # bei Neuberechnung einen Monat addieren&lt;br /&gt;
    my $add = $data{AT_RECOMPUTE} ? 1 : 0;&lt;br /&gt;
    $mon = $mon + $add;&lt;br /&gt;
&lt;br /&gt;
    my ($nm, $ny) = ($mon == 12) ? (0,$year+1) : ($mon,$year);&lt;br /&gt;
&lt;br /&gt;
    # Letztes Vorkommen des Wochentags berechnen?&lt;br /&gt;
    if ($x == 9) {&lt;br /&gt;
        # Berechnen des letzten Tags des Monats&lt;br /&gt;
        # ersten Tag des Folgemonats als timestamp&lt;br /&gt;
        my ($xm, $xy) = ($mon == 11) ? (0,$year+1) : ($mon+1,$year);&lt;br /&gt;
        my $nt = mktime(0, 0, 0, 1, $xm, $xy);&lt;br /&gt;
&lt;br /&gt;
        # letzter Tag des aktuellen Monats = erster Tag des Folgemonats minus ein Tag&lt;br /&gt;
        my ($letzter_tag_des_monats, $letzter_wochentag) = (localtime($nt - DAYSECONDS))[3,6];&lt;br /&gt;
&lt;br /&gt;
        # Prüfen, ob der letzte Wochentag im Monat mit dem gewünschten Wochentag übereinstimmt&lt;br /&gt;
        $ziel_tag = $letzter_tag_des_monats;&lt;br /&gt;
        if ($letzter_wochentag &amp;gt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag später im Monat ist, subtrahiere die Differenz&lt;br /&gt;
           my $differenz = $letzter_wochentag - $w;&lt;br /&gt;
           $ziel_tag -= $differenz;&lt;br /&gt;
        } elsif ($letzter_wochentag &amp;lt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag früher im Monat ist, subtrahiere 7 plus die Differenz&lt;br /&gt;
           my $differenz = $w - $letzter_wochentag;&lt;br /&gt;
           $ziel_tag -= (7 - $differenz);&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        # Berechne den Tag des ersten Vorkommens des Wochentags im Monat&lt;br /&gt;
        my $erster_tag = 1;&lt;br /&gt;
        my $erster_tag_des_monats = (localtime(mktime(0,0,0,$erster_tag,$nm,$ny)))[6];&lt;br /&gt;
        my $erstes_vorkommen = ($w - $erster_tag_des_monats + 7) % 7 + 1;&lt;br /&gt;
&lt;br /&gt;
        # Berechne den Tag des x.ten Vorkommens des Wochentags im Monat&lt;br /&gt;
        $ziel_tag = $erstes_vorkommen + 7 * ($x - 1);&lt;br /&gt;
&lt;br /&gt;
        # Überprüfe, ob das Datum im gültigen Bereich liegt&lt;br /&gt;
        if ($ziel_tag &amp;gt; 31 || $ziel_tag &amp;lt; 1) {&lt;br /&gt;
          return &amp;quot;Ungültiges Datum&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return mktime($s,$m,$h,$ziel_tag,$nm,$ny);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Als Parameter benötigt die Funktion, welches Vorkommen des Wochentags berechnet werden soll (1-4). Soll das letzte Vorkommen berechnet werden, übergibt man 9. Als Wochentag wird 1-7 angegeben, wobei Montag der Wochentag 1 ist. Danach kommen als getrennte Parameter Stunde, Minute und Sekunde. Die Definition sieht dann so aus&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod at_heat1_Treffen_FG_Radverkehr at *{at_xwday(1,2,17,45,0)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_FG_Radverkehr at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Heizung wird für das Treffen der Fachgruppe Radverkehr am ersten Dienstag im Monat auf 21 Grad gestellt. Gleichzeitig wird ein AT gestartet, das die Heizung zwei Stunden später wieder auf 15 Grad reduziert. Kleiner Tipp: Man kann im AT auch zwei FHEM-Befehle hintereinander senden. Klappte in diesem Fall aber nur über den kleinen Umweg über Perl.&lt;br /&gt;
&lt;br /&gt;
== AT alle x Tage ausführen ==&lt;br /&gt;
&lt;br /&gt;
Soll ein Termin z.B. alle sechs Wochen stattfinden, so kann folgende Funktion genutzt werden.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# nächsten Treffens in x Tagen&lt;br /&gt;
&lt;br /&gt;
sub at_xdays($$) {&lt;br /&gt;
	my ($tm,$days) = @_;&lt;br /&gt;
	my $delta = $days * DAYSECONDS;		# Nächster Termin in sec&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;Wrong timespec, use \&amp;quot;yyyy-mm-ddThh:mm:ss\&amp;quot;&amp;quot; if($tm !~ m/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)$/);&lt;br /&gt;
	my ($y,$m,$d,$h,$m2,$s) = ($1,$2,$3,$4,$5,$6);&lt;br /&gt;
	my $abstime = mktime($s,$m2,$h,$d,$m-1,$y-1900, 0,0,-1);&lt;br /&gt;
	my $now = int(time);&lt;br /&gt;
&lt;br /&gt;
	my $diff = $now-$abstime;&lt;br /&gt;
	if ($diff&amp;gt;0){&lt;br /&gt;
    	# bei Neuberechnung sechs Wochen zur aktuellen Zeit addieren&lt;br /&gt;
		# wird auch bei Erstberechnung aufgerufen, wenn Timestamp in der Vergangenheit&lt;br /&gt;
		my $temp = ((int($diff/$delta)+1)*$delta)+$abstime;&lt;br /&gt;
		my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($temp);&lt;br /&gt;
		return mktime($s,$m2,$h,$mday,$mon,$year);&lt;br /&gt;
	} else {return $abstime;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dabei wird der erste Ausführungstermin im FHEM-üblichen Format (&amp;quot;yyyy-mm-ddThh:mm:ss&amp;quot;) und das Intervall in Tagen übergeben. Die Variable $delta enthält dann das Intervall in Sekunden. Es wird zwar mit dem Timestamp gerechnet. Zurückgegeben wird aber das berechnete Datum und die der Funktion übergebene Uhrzeit. Das verhindert Probleme mit der Zeitumstellung. Hier die Definition für einen Termin alle sechs Wochen, beginnend am 29.05.2024 um 18:45 Uhr. Auch hier wird die Heizung zwei Stunden später wieder herunter gestellt.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod at_heat2_Lasse at *{at_xdays(&amp;quot;2024-05-29T18:45:00&amp;quot;,42)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_Lasse at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39309</id>
		<title>AT kleine Helferlein</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39309"/>
		<updated>2024-04-26T15:31:57Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* AT alle x Wochen ausführen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein AT kann statt einer Uhrzeit bzw. eines Datums mit einer Uhrzeit auch eine Perl-Funktion nutzen. Beispiel solcher Funktionen sind [[At#at ultimo|at_ultimo]] oder das Modul [[SUNRISE_EL]]. Hier sollen weitere Funktionen vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Der Code kann in der [[99 myUtils anlegen|99 myUtils]] untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
== AT am x-ten Wochentag im Monat ausführen ==&lt;br /&gt;
&lt;br /&gt;
Aufgabe ist es, das at z.B. an jedem 2. Montag im Monat auszuführen. Zusätzlich gibt es auch die Möglichkeit, das at immer am z.B. letzten Montag im Monat auszuführen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# x.ten Wochentags im Monat&lt;br /&gt;
#&lt;br /&gt;
# x=1-4 x.ter Wochentag im Monat&lt;br /&gt;
# x=9   letzter Wochentag im Monat&lt;br /&gt;
# w=1-7 Wochentag, 1=Montag&lt;br /&gt;
# h,m,s Uhrzeit Stunde, Minute, Sekunde&lt;br /&gt;
#&lt;br /&gt;
sub at_xwday($$$$$) {&lt;br /&gt;
    my ($x,$w,$h,$m,$s) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $ziel_tag = 0;&lt;br /&gt;
&lt;br /&gt;
    # akt. Datum und Uhrzeit in Variablen aufteilen&lt;br /&gt;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = &lt;br /&gt;
        localtime(time);&lt;br /&gt;
&lt;br /&gt;
    # bei Neuberechnung einen Monat addieren&lt;br /&gt;
    my $add = $data{AT_RECOMPUTE} ? 1 : 0;&lt;br /&gt;
    $mon = $mon + $add;&lt;br /&gt;
&lt;br /&gt;
    my ($nm, $ny) = ($mon == 12) ? (0,$year+1) : ($mon,$year);&lt;br /&gt;
&lt;br /&gt;
    # Letztes Vorkommen des Wochentags berechnen?&lt;br /&gt;
    if ($x == 9) {&lt;br /&gt;
        # Berechnen des letzten Tags des Monats&lt;br /&gt;
        # ersten Tag des Folgemonats als timestamp&lt;br /&gt;
        my ($xm, $xy) = ($mon == 11) ? (0,$year+1) : ($mon+1,$year);&lt;br /&gt;
        my $nt = mktime(0, 0, 0, 1, $xm, $xy);&lt;br /&gt;
&lt;br /&gt;
        # letzter Tag des aktuellen Monats = erster Tag des Folgemonats minus ein Tag&lt;br /&gt;
        my ($letzter_tag_des_monats, $letzter_wochentag) = (localtime($nt - DAYSECONDS))[3,6];&lt;br /&gt;
&lt;br /&gt;
        # Prüfen, ob der letzte Wochentag im Monat mit dem gewünschten Wochentag übereinstimmt&lt;br /&gt;
        $ziel_tag = $letzter_tag_des_monats;&lt;br /&gt;
        if ($letzter_wochentag &amp;gt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag später im Monat ist, subtrahiere die Differenz&lt;br /&gt;
           my $differenz = $letzter_wochentag - $w;&lt;br /&gt;
           $ziel_tag -= $differenz;&lt;br /&gt;
        } elsif ($letzter_wochentag &amp;lt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag früher im Monat ist, subtrahiere 7 plus die Differenz&lt;br /&gt;
           my $differenz = $w - $letzter_wochentag;&lt;br /&gt;
           $ziel_tag -= (7 - $differenz);&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        # Berechne den Tag des ersten Vorkommens des Wochentags im Monat&lt;br /&gt;
        my $erster_tag = 1;&lt;br /&gt;
        my $erster_tag_des_monats = (localtime(mktime(0,0,0,$erster_tag,$nm,$ny)))[6];&lt;br /&gt;
        my $erstes_vorkommen = ($w - $erster_tag_des_monats + 7) % 7 + 1;&lt;br /&gt;
&lt;br /&gt;
        # Berechne den Tag des x.ten Vorkommens des Wochentags im Monat&lt;br /&gt;
        $ziel_tag = $erstes_vorkommen + 7 * ($x - 1);&lt;br /&gt;
&lt;br /&gt;
        # Überprüfe, ob das Datum im gültigen Bereich liegt&lt;br /&gt;
        if ($ziel_tag &amp;gt; 31 || $ziel_tag &amp;lt; 1) {&lt;br /&gt;
          return &amp;quot;Ungültiges Datum&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return mktime($s,$m,$h,$ziel_tag,$nm,$ny);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Als Parameter benötigt die Funktion, welches Vorkommen des Wochentags berechnet werden soll (1-4). Soll das letzte Vorkommen berechnet werden, übergibt man 9. Als Wochentag wird 1-7 angegeben, wobei Montag der Wochentag 1 ist. Danach kommen als getrennte Parameter Stunde, Minute und Sekunde. Die Definition sieht dann so aus&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod at_heat1_Treffen_FG_Radverkehr at *{at_xwday(1,2,17,45,0)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_FG_Radverkehr at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Heizung wird für das Treffen der Fachgruppe Radverkehr am ersten Dienstag im Monat auf 21 Grad gestellt. Gleichzeitig wird ein AT gestartet, das die Heizung zwei Stunden später wieder auf 15 Grad reduziert. Kleiner Tipp: Man kann im AT auch zwei FHEM-Befehle hintereinander senden. Klappte in diesem Fall aber nur über den kleinen Umweg über Perl.&lt;br /&gt;
&lt;br /&gt;
== AT alle x Wochen ausführen ==&lt;br /&gt;
&lt;br /&gt;
Soll ein Termin z.B. alle sechs Wochen stattfinden, so kann folgende Funktion genutzt werden.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# nächsten Treffens in sechs Wochen&lt;br /&gt;
&lt;br /&gt;
sub at_sixweek($) {&lt;br /&gt;
	my ($tm) = @_;&lt;br /&gt;
	my $delta = 42 * DAYSECONDS;		# Nächster Termin in sec, hier sechs Wochen&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;Wrong timespec, use \&amp;quot;yyyy-mm-ddThh:mm:ss\&amp;quot;&amp;quot; if($tm !~ m/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)$/);&lt;br /&gt;
	my ($y,$m,$d,$h,$m2,$s) = ($1,$2,$3,$4,$5,$6);&lt;br /&gt;
	my $abstime = mktime($s,$m2,$h,$d,$m-1,$y-1900, 0,0,-1);&lt;br /&gt;
	my $now = int(time);&lt;br /&gt;
&lt;br /&gt;
	my $diff = $now-$abstime;&lt;br /&gt;
	if ($diff&amp;gt;0){&lt;br /&gt;
    	# bei Neuberechnung sechs Wochen zur aktuellen Zeit addieren&lt;br /&gt;
		# wird auch bei Erstberechnung aufgerufen, wenn Timestamp in der Vergangenheit&lt;br /&gt;
		my $temp = ((int($diff/$delta)+1)*$delta)+$abstime;&lt;br /&gt;
		my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($temp);&lt;br /&gt;
		return mktime($s,$m2,$h,$mday,$mon,$year);&lt;br /&gt;
	} else {return $abstime;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dabei wird der erste Ausführungstermin im FHEM-üblichen Format (&amp;quot;yyyy-mm-ddThh:mm:ss&amp;quot;) übergeben. Die Variable $delta enthält das Intervall in Sekunden. Es kann entsprechend angepasst werden. Es wird zwar mit dem Timestamp gerechnet. Zurückgegeben wird aber das berechnete Datum und die der Funktion übergebene Uhrzeit. Das verhindert Probleme mit der Zeitumstellung. Hier die Definition für einen Termin alle sechs Wochen, beginnend am 29.05.2024 um 18:45 Uhr. Auch hier wird die Heizung zwei Stunden später wieder herunter gestellt.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod at_heat2_Lasse at *{at_sixweek(&amp;quot;2024-05-29T18:45:00&amp;quot;)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_Lasse at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39307</id>
		<title>AT kleine Helferlein</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39307"/>
		<updated>2024-04-26T15:23:15Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Fehler in Funktion at_sixweek() behoben&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein AT kann statt einer Uhrzeit bzw. eines Datums mit einer Uhrzeit auch eine Perl-Funktion nutzen. Beispiel solcher Funktionen sind [[At#at ultimo|at_ultimo]] oder das Modul [[SUNRISE_EL]]. Hier sollen weitere Funktionen vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Der Code kann in der [[99 myUtils anlegen|99 myUtils]] untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
== AT am x-ten Wochentag im Monat ausführen ==&lt;br /&gt;
&lt;br /&gt;
Aufgabe ist es, das at z.B. an jedem 2. Montag im Monat auszuführen. Zusätzlich gibt es auch die Möglichkeit, das at immer am z.B. letzten Montag im Monat auszuführen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# x.ten Wochentags im Monat&lt;br /&gt;
#&lt;br /&gt;
# x=1-4 x.ter Wochentag im Monat&lt;br /&gt;
# x=9   letzter Wochentag im Monat&lt;br /&gt;
# w=1-7 Wochentag, 1=Montag&lt;br /&gt;
# h,m,s Uhrzeit Stunde, Minute, Sekunde&lt;br /&gt;
#&lt;br /&gt;
sub at_xwday($$$$$) {&lt;br /&gt;
    my ($x,$w,$h,$m,$s) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $ziel_tag = 0;&lt;br /&gt;
&lt;br /&gt;
    # akt. Datum und Uhrzeit in Variablen aufteilen&lt;br /&gt;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = &lt;br /&gt;
        localtime(time);&lt;br /&gt;
&lt;br /&gt;
    # bei Neuberechnung einen Monat addieren&lt;br /&gt;
    my $add = $data{AT_RECOMPUTE} ? 1 : 0;&lt;br /&gt;
    $mon = $mon + $add;&lt;br /&gt;
&lt;br /&gt;
    my ($nm, $ny) = ($mon == 12) ? (0,$year+1) : ($mon,$year);&lt;br /&gt;
&lt;br /&gt;
    # Letztes Vorkommen des Wochentags berechnen?&lt;br /&gt;
    if ($x == 9) {&lt;br /&gt;
        # Berechnen des letzten Tags des Monats&lt;br /&gt;
        # ersten Tag des Folgemonats als timestamp&lt;br /&gt;
        my ($xm, $xy) = ($mon == 11) ? (0,$year+1) : ($mon+1,$year);&lt;br /&gt;
        my $nt = mktime(0, 0, 0, 1, $xm, $xy);&lt;br /&gt;
&lt;br /&gt;
        # letzter Tag des aktuellen Monats = erster Tag des Folgemonats minus ein Tag&lt;br /&gt;
        my ($letzter_tag_des_monats, $letzter_wochentag) = (localtime($nt - DAYSECONDS))[3,6];&lt;br /&gt;
&lt;br /&gt;
        # Prüfen, ob der letzte Wochentag im Monat mit dem gewünschten Wochentag übereinstimmt&lt;br /&gt;
        $ziel_tag = $letzter_tag_des_monats;&lt;br /&gt;
        if ($letzter_wochentag &amp;gt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag später im Monat ist, subtrahiere die Differenz&lt;br /&gt;
           my $differenz = $letzter_wochentag - $w;&lt;br /&gt;
           $ziel_tag -= $differenz;&lt;br /&gt;
        } elsif ($letzter_wochentag &amp;lt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag früher im Monat ist, subtrahiere 7 plus die Differenz&lt;br /&gt;
           my $differenz = $w - $letzter_wochentag;&lt;br /&gt;
           $ziel_tag -= (7 - $differenz);&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        # Berechne den Tag des ersten Vorkommens des Wochentags im Monat&lt;br /&gt;
        my $erster_tag = 1;&lt;br /&gt;
        my $erster_tag_des_monats = (localtime(mktime(0,0,0,$erster_tag,$nm,$ny)))[6];&lt;br /&gt;
        my $erstes_vorkommen = ($w - $erster_tag_des_monats + 7) % 7 + 1;&lt;br /&gt;
&lt;br /&gt;
        # Berechne den Tag des x.ten Vorkommens des Wochentags im Monat&lt;br /&gt;
        $ziel_tag = $erstes_vorkommen + 7 * ($x - 1);&lt;br /&gt;
&lt;br /&gt;
        # Überprüfe, ob das Datum im gültigen Bereich liegt&lt;br /&gt;
        if ($ziel_tag &amp;gt; 31 || $ziel_tag &amp;lt; 1) {&lt;br /&gt;
          return &amp;quot;Ungültiges Datum&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return mktime($s,$m,$h,$ziel_tag,$nm,$ny);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Als Parameter benötigt die Funktion, welches Vorkommen des Wochentags berechnet werden soll (1-4). Soll das letzte Vorkommen berechnet werden, übergibt man 9. Als Wochentag wird 1-7 angegeben, wobei Montag der Wochentag 1 ist. Danach kommen als getrennte Parameter Stunde, Minute und Sekunde. Die Definition sieht dann so aus&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod at_heat1_Treffen_FG_Radverkehr at *{at_xwday(1,2,17,45,0)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_FG_Radverkehr at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Heizung wird für das Treffen der Fachgruppe Radverkehr am ersten Dienstag im Monat auf 21 Grad gestellt. Gleichzeitig wird ein AT gestartet, das die Heizung zwei Stunden später wieder auf 15 Grad reduziert. Kleiner Tipp: Man kann im AT auch zwei FHEM-Befehle hintereinander senden. Klappte in diesem Fall aber nur über den kleinen Umweg über Perl.&lt;br /&gt;
&lt;br /&gt;
== AT alle x Wochen ausführen ==&lt;br /&gt;
&lt;br /&gt;
Soll ein Termin z.B. alle sechs Wochen stattfinden, so kann folgende Funktion genutzt werden.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# nächsten Treffens in sechs Wochen&lt;br /&gt;
&lt;br /&gt;
sub at_sixweek($) {&lt;br /&gt;
	my ($tm) = @_;&lt;br /&gt;
	my $delta = 3628800;		# Nächster Termin in sec, hier sechs Wochen&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;Wrong timespec, use \&amp;quot;yyyy-mm-ddThh:mm:ss\&amp;quot;&amp;quot; if($tm !~ m/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)$/);&lt;br /&gt;
	my ($y,$m,$d,$h,$m2,$s) = ($1,$2,$3,$4,$5,$6);&lt;br /&gt;
	my $abstime = mktime($s,$m2,$h,$d,$m-1,$y-1900, 0,0,-1);&lt;br /&gt;
	my $now = int(time);&lt;br /&gt;
&lt;br /&gt;
	my $diff = $now-$abstime;&lt;br /&gt;
	if ($diff&amp;gt;0){&lt;br /&gt;
    	# bei Neuberechnung sechs Wochen zur aktuellen Zeit addieren&lt;br /&gt;
		# wird auch bei Erstberechnung aufgerufen, wenn Timestamp in der Vergangenheit&lt;br /&gt;
		my $temp = ((int($diff/$delta)+1)*$delta)+$abstime;&lt;br /&gt;
		my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($temp);&lt;br /&gt;
		return mktime($s,$m2,$h,$mday,$mon,$year);&lt;br /&gt;
	} else {return $abstime;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dabei wird der erste Ausführungstermin im FHEM-üblichen Format (&amp;quot;yyyy-mm-ddThh:mm:ss&amp;quot;) übergeben. Die Variable $delta enthält das Intervall in Sekunden. Es kann entsprechend angepasst werden. Es wird zwar mit dem Timestamp gerechnet. Zurückgegeben wird aber das berechnete Datum und die der Funktion übergebene Uhrzeit. Das verhindert Probleme mit der Zeitumstellung. Hier die Definition für einen Termin alle sechs Wochen, beginnend am 29.05.2024 um 18:45 Uhr. Auch hier wird die Heizung zwei Stunden später wieder herunter gestellt.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod at_heat2_Lasse at *{at_sixweek(&amp;quot;2024-05-29T18:45:00&amp;quot;)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_Lasse at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39274</id>
		<title>AT kleine Helferlein</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39274"/>
		<updated>2024-04-22T17:14:52Z</updated>

		<summary type="html">&lt;p&gt;F Klee: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein AT kann statt einer Uhrzeit bzw. eines Datums mit einer Uhrzeit auch eine Perl-Funktion nutzen. Beispiel solcher Funktionen sind [[At#at ultimo|at_ultimo]] oder das Modul [[SUNRISE_EL]]. Hier sollen weitere Funktionen vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Der Code kann in der [[99 myUtils anlegen|99 myUtils]] untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
== AT am x-ten Wochentag im Monat ausführen ==&lt;br /&gt;
&lt;br /&gt;
Aufgabe ist es, das at z.B. an jedem 2. Montag im Monat auszuführen. Zusätzlich gibt es auch die Möglichkeit, das at immer am z.B. letzten Montag im Monat auszuführen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# x.ten Wochentags im Monat&lt;br /&gt;
#&lt;br /&gt;
# x=1-4 x.ter Wochentag im Monat&lt;br /&gt;
# x=9   letzter Wochentag im Monat&lt;br /&gt;
# w=1-7 Wochentag, 1=Montag&lt;br /&gt;
# h,m,s Uhrzeit Stunde, Minute, Sekunde&lt;br /&gt;
#&lt;br /&gt;
sub at_xwday($$$$$) {&lt;br /&gt;
    my ($x,$w,$h,$m,$s) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $ziel_tag = 0;&lt;br /&gt;
&lt;br /&gt;
    # akt. Datum und Uhrzeit in Variablen aufteilen&lt;br /&gt;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = &lt;br /&gt;
        localtime(time);&lt;br /&gt;
&lt;br /&gt;
    # bei Neuberechnung einen Monat addieren&lt;br /&gt;
    my $add = $data{AT_RECOMPUTE} ? 1 : 0;&lt;br /&gt;
    $mon = $mon + $add;&lt;br /&gt;
&lt;br /&gt;
    my ($nm, $ny) = ($mon == 12) ? (0,$year+1) : ($mon,$year);&lt;br /&gt;
&lt;br /&gt;
    # Letztes Vorkommen des Wochentags berechnen?&lt;br /&gt;
    if ($x == 9) {&lt;br /&gt;
        # Berechnen des letzten Tags des Monats&lt;br /&gt;
        # ersten Tag des Folgemonats als timestamp&lt;br /&gt;
        my ($xm, $xy) = ($mon == 11) ? (0,$year+1) : ($mon+1,$year);&lt;br /&gt;
        my $nt = mktime(0, 0, 0, 1, $xm, $xy);&lt;br /&gt;
&lt;br /&gt;
        # letzter Tag des aktuellen Monats = erster Tag des Folgemonats minus ein Tag&lt;br /&gt;
        my ($letzter_tag_des_monats, $letzter_wochentag) = (localtime($nt - DAYSECONDS))[3,6];&lt;br /&gt;
&lt;br /&gt;
        # Prüfen, ob der letzte Wochentag im Monat mit dem gewünschten Wochentag übereinstimmt&lt;br /&gt;
        $ziel_tag = $letzter_tag_des_monats;&lt;br /&gt;
        if ($letzter_wochentag &amp;gt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag später im Monat ist, subtrahiere die Differenz&lt;br /&gt;
           my $differenz = $letzter_wochentag - $w;&lt;br /&gt;
           $ziel_tag -= $differenz;&lt;br /&gt;
        } elsif ($letzter_wochentag &amp;lt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag früher im Monat ist, subtrahiere 7 plus die Differenz&lt;br /&gt;
           my $differenz = $w - $letzter_wochentag;&lt;br /&gt;
           $ziel_tag -= (7 - $differenz);&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        # Berechne den Tag des ersten Vorkommens des Wochentags im Monat&lt;br /&gt;
        my $erster_tag = 1;&lt;br /&gt;
        my $erster_tag_des_monats = (localtime(mktime(0,0,0,$erster_tag,$nm,$ny)))[6];&lt;br /&gt;
        my $erstes_vorkommen = ($w - $erster_tag_des_monats + 7) % 7 + 1;&lt;br /&gt;
&lt;br /&gt;
        # Berechne den Tag des x.ten Vorkommens des Wochentags im Monat&lt;br /&gt;
        $ziel_tag = $erstes_vorkommen + 7 * ($x - 1);&lt;br /&gt;
&lt;br /&gt;
        # Überprüfe, ob das Datum im gültigen Bereich liegt&lt;br /&gt;
        if ($ziel_tag &amp;gt; 31 || $ziel_tag &amp;lt; 1) {&lt;br /&gt;
          return &amp;quot;Ungültiges Datum&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return mktime($s,$m,$h,$ziel_tag,$nm,$ny);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Als Parameter benötigt die Funktion, welches Vorkommen des Wochentags berechnet werden soll (1-4). Soll das letzte Vorkommen berechnet werden, übergibt man 9. Als Wochentag wird 1-7 angegeben, wobei Montag der Wochentag 1 ist. Danach kommen als getrennte Parameter Stunde, Minute und Sekunde. Die Definition sieht dann so aus&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod at_heat1_Treffen_FG_Radverkehr at *{at_xwday(1,2,17,45,0)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_FG_Radverkehr at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Heizung wird für das Treffen der Fachgruppe Radverkehr am ersten Dienstag im Monat auf 21 Grad gestellt. Gleichzeitig wird ein AT gestartet, das die Heizung zwei Stunden später wieder auf 15 Grad reduziert. Kleiner Tipp: Man kann im AT auch zwei FHEM-Befehle hintereinander senden. Klappte in diesem Fall aber nur über den kleinen Umweg über Perl.&lt;br /&gt;
&lt;br /&gt;
== AT alle x Wochen ausführen ==&lt;br /&gt;
&lt;br /&gt;
Soll ein Termin z.B. alle sechs Wochen stattfinden, so kann folgende Funktion genutzt werden.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# nächsten Treffens in sechs Wochen&lt;br /&gt;
&lt;br /&gt;
sub at_sixweek($) {&lt;br /&gt;
my ($tm) = @_;&lt;br /&gt;
my $delta = 3628800;   # Zeit zwischen den Terminen in Sekunden, hier 6 Wochen&lt;br /&gt;
&lt;br /&gt;
  return &amp;quot;Wrong timespec, use \&amp;quot;yyyy-mm-ddThh:mm:ss\&amp;quot;&amp;quot; if($tm !~ m/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)$/);&lt;br /&gt;
  my ($y,$m,$d,$h,$m2,$s) = ($1,$2,$3,$4,$5,$6);&lt;br /&gt;
  my $abstime = mktime($s,$m2,$h,$d,$m-1,$y-1900, 0,0,-1);&lt;br /&gt;
&lt;br /&gt;
  if ($data{AT_RECOMPUTE}){&lt;br /&gt;
    # bei Neuberechnung sechs Wochen zur aktuellen Zeit addieren&lt;br /&gt;
    my $now = int(time);&lt;br /&gt;
    $abstime = $now+$delta;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return $abstime;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dabei wird der erste Ausführungstermin im FHEM-üblichen Format (&amp;quot;yyyy-mm-ddThh:mm:ss&amp;quot;) übergeben. Die Variable $delta enthält das Intervall in Sekunden. Es kann entsprechend angepasst werden. Die Neuberechnung erfolgt ausgehend vom aktuellen Datum/Uhrzeit. Es kann also als erster Termin nur ein Termin in der Zukunft angegeben werden. Hier die Definition für einen Termin alle sechs Wochen, beginnend am 29.05.2024 um 18:45 Uhr. Auch hier wird die Heizung zwei Stunden später wieder herunter gestellt.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod at_heat2_Lasse at *{at_sixweek(&amp;quot;2024-05-29T18:45:00&amp;quot;)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_Lasse at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39273</id>
		<title>AT kleine Helferlein</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39273"/>
		<updated>2024-04-22T17:00:53Z</updated>

		<summary type="html">&lt;p&gt;F Klee: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein AT kann statt einer Uhrzeit bzw. eines Datums mit einer Uhrzeit auch eine Perl-Funktion nutzen. Beispiel solcher Funktionen sind [[At#at ultimo|at_ultimo]] oder das Modul [[SUNRISE_EL]]. Hier sollen weitere Funktionen vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Der Code kann in der [[99 myUtils anlegen|99 myUtils]] untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
== AT am x-ten Wochentag im Monat ausführen ==&lt;br /&gt;
&lt;br /&gt;
Aufgabe ist es, das at z.B. an jedem 2. Montag im Monat auszuführen. Zusätzlich gibt es auch die Möglichkeit, das at immer am z.B. letzten Montag im Monat auszuführen.&amp;lt;syntaxhighlight lang=&amp;quot;perl6&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# x.ten Wochentags im Monat&lt;br /&gt;
#&lt;br /&gt;
# x=1-4 x.ter Wochentag im Monat&lt;br /&gt;
# x=9   letzter Wochentag im Monat&lt;br /&gt;
# w=1-7 Wochentag, 1=Montag&lt;br /&gt;
# h,m,s Uhrzeit Stunde, Minute, Sekunde&lt;br /&gt;
#&lt;br /&gt;
sub at_xwday($$$$$) {&lt;br /&gt;
    my ($x,$w,$h,$m,$s) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $ziel_tag = 0;&lt;br /&gt;
&lt;br /&gt;
    # akt. Datum und Uhrzeit in Variablen aufteilen&lt;br /&gt;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = &lt;br /&gt;
        localtime(time);&lt;br /&gt;
&lt;br /&gt;
    # bei Neuberechnung einen Monat addieren&lt;br /&gt;
    my $add = $data{AT_RECOMPUTE} ? 1 : 0;&lt;br /&gt;
    $mon = $mon + $add;&lt;br /&gt;
&lt;br /&gt;
    my ($nm, $ny) = ($mon == 12) ? (0,$year+1) : ($mon,$year);&lt;br /&gt;
&lt;br /&gt;
    # Letztes Vorkommen des Wochentags berechnen?&lt;br /&gt;
    if ($x == 9) {&lt;br /&gt;
        # Berechnen des letzten Tags des Monats&lt;br /&gt;
        # ersten Tag des Folgemonats als timestamp&lt;br /&gt;
        my ($xm, $xy) = ($mon == 11) ? (0,$year+1) : ($mon+1,$year);&lt;br /&gt;
        my $nt = mktime(0, 0, 0, 1, $xm, $xy);&lt;br /&gt;
&lt;br /&gt;
        # letzter Tag des aktuellen Monats = erster Tag des Folgemonats minus ein Tag&lt;br /&gt;
        my ($letzter_tag_des_monats, $letzter_wochentag) = (localtime($nt - DAYSECONDS))[3,6];&lt;br /&gt;
&lt;br /&gt;
        # Prüfen, ob der letzte Wochentag im Monat mit dem gewünschten Wochentag übereinstimmt&lt;br /&gt;
        $ziel_tag = $letzter_tag_des_monats;&lt;br /&gt;
        if ($letzter_wochentag &amp;gt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag später im Monat ist, subtrahiere die Differenz&lt;br /&gt;
           my $differenz = $letzter_wochentag - $w;&lt;br /&gt;
           $ziel_tag -= $differenz;&lt;br /&gt;
        } elsif ($letzter_wochentag &amp;lt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag früher im Monat ist, subtrahiere 7 plus die Differenz&lt;br /&gt;
           my $differenz = $w - $letzter_wochentag;&lt;br /&gt;
           $ziel_tag -= (7 - $differenz);&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        # Berechne den Tag des ersten Vorkommens des Wochentags im Monat&lt;br /&gt;
        my $erster_tag = 1;&lt;br /&gt;
        my $erster_tag_des_monats = (localtime(mktime(0,0,0,$erster_tag,$nm,$ny)))[6];&lt;br /&gt;
        my $erstes_vorkommen = ($w - $erster_tag_des_monats + 7) % 7 + 1;&lt;br /&gt;
&lt;br /&gt;
        # Berechne den Tag des x.ten Vorkommens des Wochentags im Monat&lt;br /&gt;
        $ziel_tag = $erstes_vorkommen + 7 * ($x - 1);&lt;br /&gt;
&lt;br /&gt;
        # Überprüfe, ob das Datum im gültigen Bereich liegt&lt;br /&gt;
        if ($ziel_tag &amp;gt; 31 || $ziel_tag &amp;lt; 1) {&lt;br /&gt;
          return &amp;quot;Ungültiges Datum&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return mktime($s,$m,$h,$ziel_tag,$nm,$ny);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Als Parameter benötigt die Funktion, welches Vorkommen des Wochentags berechnet werden soll (1-4). Soll das letzte Vorkommen berechnet werden, übergibt man 9. Als Wochentag wird 1-7 angegeben, wobei Montag der Wochentag 1 ist. Danach kommen als getrennte Parameter Stunde, Minute und Sekunde. Die Definition sieht dann so aus&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
defmod at_heat1_Treffen_FG_Radverkehr at *{at_xwday(1,2,17,45,0)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_FG_Radverkehr at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Heizung wird für das Treffen der Fachgruppe Radverkehr am ersten Dienstag im Monat auf 21 Grad gestellt. Gleichzeitig wird ein AT gestartet, das die Heizung zwei Stunden später wieder auf 15 Grad reduziert. Kleiner Tipp: Man kann im AT auch zwei FHEM-Befehle hintereinander senden. Klappte in diesem Fall aber nur über den kleinen Umweg über Perl.&lt;br /&gt;
&lt;br /&gt;
== AT alle x Wochen ausführen ==&lt;br /&gt;
&lt;br /&gt;
Soll ein Termin z.B. alle sechs Wochen stattfinden, so kann folgende Funktion genutzt werden.&amp;lt;syntaxhighlight lang=&amp;quot;perl6&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# nächsten Treffens in sechs Wochen&lt;br /&gt;
&lt;br /&gt;
sub at_sixweek($) {&lt;br /&gt;
my ($tm) = @_;&lt;br /&gt;
my $delta = 3628800;   # Zeit zwischen den Terminen in Sekunden, hier 6 Wochen&lt;br /&gt;
&lt;br /&gt;
  return &amp;quot;Wrong timespec, use \&amp;quot;yyyy-mm-ddThh:mm:ss\&amp;quot;&amp;quot; if($tm !~ m/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)$/);&lt;br /&gt;
  my ($y,$m,$d,$h,$m2,$s) = ($1,$2,$3,$4,$5,$6);&lt;br /&gt;
  my $abstime = mktime($s,$m2,$h,$d,$m-1,$y-1900, 0,0,-1);&lt;br /&gt;
&lt;br /&gt;
  if ($data{AT_RECOMPUTE}){&lt;br /&gt;
    # bei Neuberechnung sechs Wochen zur aktuellen Zeit addieren&lt;br /&gt;
    my $now = int(time);&lt;br /&gt;
    $abstime = $now+$delta;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return $abstime;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dabei wird der erste Ausführungstermin im FHEM-üblichen Format (&amp;quot;yyyy-mm-ddThh:mm:ss&amp;quot;) übergeben. Die Variable $delta enthält das Intervall in Sekunden. Es kann entsprechend angepasst werden. Die Neuberechnung erfolgt ausgehend vom aktuellen Datum/Uhrzeit. Es kann also als erster Termin nur ein Termin in der Zukunft angegeben werden. Hier die Definition für einen Termin alle sechs Wochen, beginnend am 29.05.2024 um 18:45 Uhr. Auch hier wird die Heizung zwei Stunden später wieder herunter gestellt.&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
defmod at_heat2_Lasse at *{at_sixweek(&amp;quot;2024-05-29T18:45:00&amp;quot;)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_Lasse at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39272</id>
		<title>AT kleine Helferlein</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39272"/>
		<updated>2024-04-22T16:31:13Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Beispieldefinitionen hinzugefügt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein AT kann statt einer Uhrzeit bzw. eines Datums mit einer Uhrzeit auch eine Perl-Funktion nutzen. Beispiel solcher Funktionen sind [[At#at ultimo|at_ultimo]] oder das Modul [[SUNRISE_EL]]. Hier sollen weitere Funktionen vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Der Code kann in der [[99 myUtils anlegen|99 myUtils]] untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
== AT am x-ten Wochentag im Monat ausführen ==&lt;br /&gt;
&lt;br /&gt;
Aufgabe ist es, das at z.B. an jedem 2. Montag im Monat auszuführen. Zusätzlich gibt es auch die Möglichkeit, das at immer am z.B. letzten Montag im Monat auszuführen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# x.ten Wochentags im Monat&lt;br /&gt;
#&lt;br /&gt;
# x=1-4 x.ter Wochentag im Monat&lt;br /&gt;
# x=9   letzter Wochentag im Monat&lt;br /&gt;
# w=1-7 Wochentag, 1=Montag&lt;br /&gt;
# h,m,s Uhrzeit Stunde, Minute, Sekunde&lt;br /&gt;
#&lt;br /&gt;
sub at_xwday($$$$$) {&lt;br /&gt;
    my ($x,$w,$h,$m,$s) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $ziel_tag = 0;&lt;br /&gt;
&lt;br /&gt;
    # akt. Datum und Uhrzeit in Variablen aufteilen&lt;br /&gt;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = &lt;br /&gt;
        localtime(time);&lt;br /&gt;
&lt;br /&gt;
    # bei Neuberechnung einen Monat addieren&lt;br /&gt;
    my $add = $data{AT_RECOMPUTE} ? 1 : 0;&lt;br /&gt;
    $mon = $mon + $add;&lt;br /&gt;
&lt;br /&gt;
    my ($nm, $ny) = ($mon == 12) ? (0,$year+1) : ($mon,$year);&lt;br /&gt;
&lt;br /&gt;
    # Letztes Vorkommen des Wochentags berechnen?&lt;br /&gt;
    if ($x == 9) {&lt;br /&gt;
        # Berechnen des letzten Tags des Monats&lt;br /&gt;
        # ersten Tag des Folgemonats als timestamp&lt;br /&gt;
        my ($xm, $xy) = ($mon == 11) ? (0,$year+1) : ($mon+1,$year);&lt;br /&gt;
        my $nt = mktime(0, 0, 0, 1, $xm, $xy);&lt;br /&gt;
&lt;br /&gt;
        # letzter Tag des aktuellen Monats = erster Tag des Folgemonats minus ein Tag&lt;br /&gt;
        my ($letzter_tag_des_monats, $letzter_wochentag) = (localtime($nt - DAYSECONDS))[3,6];&lt;br /&gt;
&lt;br /&gt;
        # Prüfen, ob der letzte Wochentag im Monat mit dem gewünschten Wochentag übereinstimmt&lt;br /&gt;
        $ziel_tag = $letzter_tag_des_monats;&lt;br /&gt;
        if ($letzter_wochentag &amp;gt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag später im Monat ist, subtrahiere die Differenz&lt;br /&gt;
           my $differenz = $letzter_wochentag - $w;&lt;br /&gt;
           $ziel_tag -= $differenz;&lt;br /&gt;
        } elsif ($letzter_wochentag &amp;lt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag früher im Monat ist, subtrahiere 7 plus die Differenz&lt;br /&gt;
           my $differenz = $w - $letzter_wochentag;&lt;br /&gt;
           $ziel_tag -= (7 - $differenz);&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        # Berechne den Tag des ersten Vorkommens des Wochentags im Monat&lt;br /&gt;
        my $erster_tag = 1;&lt;br /&gt;
        my $erster_tag_des_monats = (localtime(mktime(0,0,0,$erster_tag,$nm,$ny)))[6];&lt;br /&gt;
        my $erstes_vorkommen = ($w - $erster_tag_des_monats + 7) % 7 + 1;&lt;br /&gt;
&lt;br /&gt;
        # Berechne den Tag des x.ten Vorkommens des Wochentags im Monat&lt;br /&gt;
        $ziel_tag = $erstes_vorkommen + 7 * ($x - 1);&lt;br /&gt;
&lt;br /&gt;
        # Überprüfe, ob das Datum im gültigen Bereich liegt&lt;br /&gt;
        if ($ziel_tag &amp;gt; 31 || $ziel_tag &amp;lt; 1) {&lt;br /&gt;
          return &amp;quot;Ungültiges Datum&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return mktime($s,$m,$h,$ziel_tag,$nm,$ny);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Als Parameter benötigt die Funktion, welches Vorkommen des Wochentags berechnet werden soll (1-4). Soll das letzte Vorkommen berechnet werden, übergibt man 9. Als Wochentag wird 1-7 angegeben, wobei Montag der Wochentag 1 ist. Danach kommen als getrennte Parameter Stunde, Minute und Sekunde. Die Definition sieht dann so aus&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
defmod at_heat1_Treffen_FG_Radverkehr at *{at_xwday(1,2,17,45,0)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_FG_Radverkehr at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Heizung wird für das Treffen der Fachgruppe Radverkehr am ersten Dienstag im Monat auf 21 Grad gestellt. Gleichzeitig wird ein AT gestartet, das die Heizung zwei Stunden später wieder auf 15 Grad reduziert. Kleiner Tipp: Man kann im AT auch zwei FHEM-Befehle hintereinander senden. Klappte in diesem Fall aber nur über den kleinen Umweg über Perl.&lt;br /&gt;
&lt;br /&gt;
== AT alle x Wochen ausführen ==&lt;br /&gt;
&lt;br /&gt;
Soll ein Termin z.B. alle sechs Wochen stattfinden, so kann folgende Funktion genutzt werden.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# nächsten Treffens in sechs Wochen&lt;br /&gt;
&lt;br /&gt;
sub at_sixweek($) {&lt;br /&gt;
my ($tm) = @_;&lt;br /&gt;
my $delta = 3628800;   # Zeit zwischen den Terminen in Sekunden, hier 6 Wochen&lt;br /&gt;
&lt;br /&gt;
  return &amp;quot;Wrong timespec, use \&amp;quot;yyyy-mm-ddThh:mm:ss\&amp;quot;&amp;quot; if($tm !~ m/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)$/);&lt;br /&gt;
  my ($y,$m,$d,$h,$m2,$s) = ($1,$2,$3,$4,$5,$6);&lt;br /&gt;
  my $abstime = mktime($s,$m2,$h,$d,$m-1,$y-1900, 0,0,-1);&lt;br /&gt;
&lt;br /&gt;
  if ($data{AT_RECOMPUTE}){&lt;br /&gt;
    # bei Neuberechnung sechs Wochen zur aktuellen Zeit addieren&lt;br /&gt;
    my $now = int(time);&lt;br /&gt;
    $abstime = $now+$delta;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return $abstime;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dabei wird der erste Ausführungstermin im FHEM-üblichen Format (&amp;quot;yyyy-mm-ddThh:mm:ss&amp;quot;) übergeben. Die Variable $delta enthält das Intervall in Sekunden. Es kann entsprechend angepasst werden. Die Neuberechnung erfolgt ausgehend vom aktuellen Datum/Uhrzeit. Es kann also als erster Termin nur ein Termin in der Zukunft angegeben werden. Hier die Definition für einen Termin alle sechs Wochen, beginnend am 29.05.2024 um 18:45 Uhr. Auch hier wird die Heizung zwei Stunden später wieder herunter gestellt.&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
defmod at_heat2_Lasse at *{at_sixweek(&amp;quot;2024-05-29T18:45:00&amp;quot;)} {\&lt;br /&gt;
fhem(&amp;quot;set TRV_Laden temp 21.0&amp;quot;);;\&lt;br /&gt;
fhem(&amp;quot;defmod at_heat_off_Lasse at +02:00:00 set TRV_Laden temp 15.0&amp;quot;);;\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39249</id>
		<title>AT kleine Helferlein</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39249"/>
		<updated>2024-04-20T16:24:26Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* AT am x-ten Wochentag im Monat ausführen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein AT kann statt einer Uhrzeit bzw. eines Datums mit einer Uhrzeit auch eine Perl-Funktion nutzen. Beispiel solcher Funktionen sind [[At#at ultimo|at_ultimo]] oder das Modul [[SUNRISE_EL]]. Hier sollen weitere Funktionen vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Der Code kann in der [[99 myUtils anlegen|99 myUtils]] untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
== AT am x-ten Wochentag im Monat ausführen ==&lt;br /&gt;
&lt;br /&gt;
Aufgabe ist es, das at z.B. an jedem 2. Montag im Monat auszuführen. Zusätzlich gibt es auch die Möglichkeit, das at immer am z.B. letzten Montag im Monat auszuführen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# x.ten Wochentags im Monat&lt;br /&gt;
#&lt;br /&gt;
# x=1-4 x.ter Wochentag im Monat&lt;br /&gt;
# x=9   letzter Wochentag im Monat&lt;br /&gt;
# w=1-7 Wochentag, 1=Montag&lt;br /&gt;
# h,m,s Uhrzeit Stunde, Minute, Sekunde&lt;br /&gt;
#&lt;br /&gt;
sub at_xwday($$$$$) {&lt;br /&gt;
    my ($x,$w,$h,$m,$s) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $ziel_tag = 0;&lt;br /&gt;
&lt;br /&gt;
    # akt. Datum und Uhrzeit in Variablen aufteilen&lt;br /&gt;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = &lt;br /&gt;
        localtime(time);&lt;br /&gt;
&lt;br /&gt;
    # bei Neuberechnung einen Monat addieren&lt;br /&gt;
    my $add = $data{AT_RECOMPUTE} ? 1 : 0;&lt;br /&gt;
    $mon = $mon + $add;&lt;br /&gt;
&lt;br /&gt;
    my ($nm, $ny) = ($mon == 12) ? (0,$year+1) : ($mon,$year);&lt;br /&gt;
&lt;br /&gt;
    # Letztes Vorkommen des Wochentags berechnen?&lt;br /&gt;
    if ($x == 9) {&lt;br /&gt;
        # Berechnen des letzten Tags des Monats&lt;br /&gt;
        # ersten Tag des Folgemonats als timestamp&lt;br /&gt;
        my ($xm, $xy) = ($mon == 11) ? (0,$year+1) : ($mon+1,$year);&lt;br /&gt;
        my $nt = mktime(0, 0, 0, 1, $xm, $xy);&lt;br /&gt;
&lt;br /&gt;
        # letzter Tag des aktuellen Monats = erster Tag des Folgemonats minus ein Tag&lt;br /&gt;
        my ($letzter_tag_des_monats, $letzter_wochentag) = (localtime($nt - DAYSECONDS))[3,6];&lt;br /&gt;
&lt;br /&gt;
        # Prüfen, ob der letzte Wochentag im Monat mit dem gewünschten Wochentag übereinstimmt&lt;br /&gt;
        $ziel_tag = $letzter_tag_des_monats;&lt;br /&gt;
        if ($letzter_wochentag &amp;gt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag später im Monat ist, subtrahiere die Differenz&lt;br /&gt;
           my $differenz = $letzter_wochentag - $w;&lt;br /&gt;
           $ziel_tag -= $differenz;&lt;br /&gt;
        } elsif ($letzter_wochentag &amp;lt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag früher im Monat ist, subtrahiere 7 plus die Differenz&lt;br /&gt;
           my $differenz = $w - $letzter_wochentag;&lt;br /&gt;
           $ziel_tag -= (7 - $differenz);&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        # Berechne den Tag des ersten Vorkommens des Wochentags im Monat&lt;br /&gt;
        my $erster_tag = 1;&lt;br /&gt;
        my $erster_tag_des_monats = (localtime(mktime(0,0,0,$erster_tag,$nm,$ny)))[6];&lt;br /&gt;
        my $erstes_vorkommen = ($w - $erster_tag_des_monats + 7) % 7 + 1;&lt;br /&gt;
&lt;br /&gt;
        # Berechne den Tag des x.ten Vorkommens des Wochentags im Monat&lt;br /&gt;
        $ziel_tag = $erstes_vorkommen + 7 * ($x - 1);&lt;br /&gt;
&lt;br /&gt;
        # Überprüfe, ob das Datum im gültigen Bereich liegt&lt;br /&gt;
        if ($ziel_tag &amp;gt; 31 || $ziel_tag &amp;lt; 1) {&lt;br /&gt;
          return &amp;quot;Ungültiges Datum&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return mktime($s,$m,$h,$ziel_tag,$nm,$ny);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Als Parameter benötigt die Funktion, welches Vorkommen des Wochentags berechnet werden soll (1-4). Soll das letzte Vorkommen berechnet werden, übergibt man 9. Als Wochentag wird 1-7 angegeben, wobei Montag der Wochentag 1 ist. Danach kommen als getrennte Parameter Stunde, Minute und Sekunde.&lt;br /&gt;
&lt;br /&gt;
== AT alle x Wochen ausführen ==&lt;br /&gt;
&lt;br /&gt;
Soll ein Termin z.B. alle sechs Wochen stattfinden, so kann folgende Funktion genutzt werden.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# nächsten Treffens in sechs Wochen&lt;br /&gt;
&lt;br /&gt;
sub at_sixweek($) {&lt;br /&gt;
my ($tm) = @_;&lt;br /&gt;
my $delta = 3628800;   # Zeit zwischen den Terminen in Sekunden, hier 6 Wochen&lt;br /&gt;
&lt;br /&gt;
  return &amp;quot;Wrong timespec, use \&amp;quot;yyyy-mm-ddThh:mm:ss\&amp;quot;&amp;quot; if($tm !~ m/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)$/);&lt;br /&gt;
  my ($y,$m,$d,$h,$m2,$s) = ($1,$2,$3,$4,$5,$6);&lt;br /&gt;
  my $abstime = mktime($s,$m2,$h,$d,$m-1,$y-1900, 0,0,-1);&lt;br /&gt;
&lt;br /&gt;
  if ($data{AT_RECOMPUTE}){&lt;br /&gt;
    # bei Neuberechnung sechs Wochen zur aktuellen Zeit addieren&lt;br /&gt;
    my $now = int(time);&lt;br /&gt;
    $abstime = $now+$delta;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return $abstime;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dabei wird der erste Ausführungstermin im FHEM-üblichen Format (&amp;quot;yyyy-mm-ddThh:mm:ss&amp;quot;) übergeben. Die Variable $delta enthält das Intervall in Sekunden. Es kann entsprechend angepasst werden. Die Neuberechnung erfolgt ausgehend vom aktuellen Datum/Uhrzeit. Es kann also als erster Termin nur ein Termin in der Zukunft angegeben werden. &lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39248</id>
		<title>AT kleine Helferlein</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39248"/>
		<updated>2024-04-20T16:20:29Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* AT am x-ten Wochentag im Monat ausführen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein AT kann statt einer Uhrzeit bzw. eines Datums mit einer Uhrzeit auch eine Perl-Funktion nutzen. Beispiel solcher Funktionen sind [[At#at ultimo|at_ultimo]] oder das Modul [[SUNRISE_EL]]. Hier sollen weitere Funktionen vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Der Code kann in der [[99 myUtils anlegen|99 myUtils]] untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
=== AT am x-ten Wochentag im Monat ausführen ===&lt;br /&gt;
Aufgabe ist es, das at z.B. an jedem 2. Montag im Monat auszuführen. Zusätzlich gibt es auch die Möglichkeit, das at immer am z.B. letzten Montag im Monat auszuführen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# x.ten Wochentags im Monat&lt;br /&gt;
#&lt;br /&gt;
# x=1-4 x.ter Wochentag im Monat&lt;br /&gt;
# x=9   letzter Wochentag im Monat&lt;br /&gt;
# w=1-7 Wochentag, 1=Montag&lt;br /&gt;
# h,m,s Uhrzeit Stunde, Minute, Sekunde&lt;br /&gt;
#&lt;br /&gt;
sub at_xwday($$$$$) {&lt;br /&gt;
    my ($x,$w,$h,$m,$s) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $ziel_tag = 0;&lt;br /&gt;
&lt;br /&gt;
    # akt. Datum und Uhrzeit in Variablen aufteilen&lt;br /&gt;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = &lt;br /&gt;
        localtime(time);&lt;br /&gt;
&lt;br /&gt;
    # bei Neuberechnung einen Monat addieren&lt;br /&gt;
    my $add = $data{AT_RECOMPUTE} ? 1 : 0;&lt;br /&gt;
    $mon = $mon + $add;&lt;br /&gt;
&lt;br /&gt;
    my ($nm, $ny) = ($mon == 12) ? (0,$year+1) : ($mon,$year);&lt;br /&gt;
&lt;br /&gt;
    # Letztes Vorkommen des Wochentags berechnen?&lt;br /&gt;
    if ($x == 9) {&lt;br /&gt;
        # Berechnen des letzten Tags des Monats&lt;br /&gt;
        # ersten Tag des Folgemonats als timestamp&lt;br /&gt;
        my ($xm, $xy) = ($mon == 11) ? (0,$year+1) : ($mon+1,$year);&lt;br /&gt;
        my $nt = mktime(0, 0, 0, 1, $xm, $xy);&lt;br /&gt;
&lt;br /&gt;
        # letzter Tag des aktuellen Monats = erster Tag des Folgemonats minus ein Tag&lt;br /&gt;
        my ($letzter_tag_des_monats, $letzter_wochentag) = (localtime($nt - DAYSECONDS))[3,6];&lt;br /&gt;
&lt;br /&gt;
        # Prüfen, ob der letzte Wochentag im Monat mit dem gewünschten Wochentag übereinstimmt&lt;br /&gt;
        $ziel_tag = $letzter_tag_des_monats;&lt;br /&gt;
        if ($letzter_wochentag &amp;gt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag später im Monat ist, subtrahiere die Differenz&lt;br /&gt;
           my $differenz = $letzter_wochentag - $w;&lt;br /&gt;
           $ziel_tag -= $differenz;&lt;br /&gt;
        } elsif ($letzter_wochentag &amp;lt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag früher im Monat ist, subtrahiere 7 plus die Differenz&lt;br /&gt;
           my $differenz = $w - $letzter_wochentag;&lt;br /&gt;
           $ziel_tag -= (7 - $differenz);&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        # Berechne den Tag des ersten Vorkommens des Wochentags im Monat&lt;br /&gt;
        my $erster_tag = 1;&lt;br /&gt;
        my $erster_tag_des_monats = (localtime(mktime(0,0,0,$erster_tag,$nm,$ny)))[6];&lt;br /&gt;
        my $erstes_vorkommen = ($w - $erster_tag_des_monats + 7) % 7 + 1;&lt;br /&gt;
&lt;br /&gt;
        # Berechne den Tag des x.ten Vorkommens des Wochentags im Monat&lt;br /&gt;
        $ziel_tag = $erstes_vorkommen + 7 * ($x - 1);&lt;br /&gt;
&lt;br /&gt;
        # Überprüfe, ob das Datum im gültigen Bereich liegt&lt;br /&gt;
        if ($ziel_tag &amp;gt; 31 || $ziel_tag &amp;lt; 1) {&lt;br /&gt;
          return &amp;quot;Ungültiges Datum&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return mktime($s,$m,$h,$ziel_tag,$nm,$ny);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Als Parameter benötigt die Funktion, welches Vorkommen des Wochentags berechnet werden soll (1-4). Soll das letzte Vorkommen berechnet werden, übergibt man 9. Als Wochentag wird 1-7 angegeben, wobei Montag der Wochentag 1 ist. Danach kommen als getrennte Parameter Stunde, Minute und Sekunde.&lt;br /&gt;
&lt;br /&gt;
=== AT alle x Wochen ausführen ===&lt;br /&gt;
Soll ein Termin z.B. alle sechs Wochen stattfinden, so kann folgende Funktion genutzt werden.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# nächsten Treffens in sechs Wochen&lt;br /&gt;
&lt;br /&gt;
sub at_sixweek($) {&lt;br /&gt;
my ($tm) = @_;&lt;br /&gt;
my $delta = 3628800;   # Zeit zwischen den Terminen in Sekunden, hier 6 Wochen&lt;br /&gt;
&lt;br /&gt;
  return &amp;quot;Wrong timespec, use \&amp;quot;yyyy-mm-ddThh:mm:ss\&amp;quot;&amp;quot; if($tm !~ m/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)$/);&lt;br /&gt;
  my ($y,$m,$d,$h,$m2,$s) = ($1,$2,$3,$4,$5,$6);&lt;br /&gt;
  my $abstime = mktime($s,$m2,$h,$d,$m-1,$y-1900, 0,0,-1);&lt;br /&gt;
&lt;br /&gt;
  if ($data{AT_RECOMPUTE}){&lt;br /&gt;
    # bei Neuberechnung sechs Wochen zur aktuellen Zeit addieren&lt;br /&gt;
    my $now = int(time);&lt;br /&gt;
    $abstime = $now+$delta;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return $abstime;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dabei wird der erste Ausführungstermin im FHEM-üblichen Format (&amp;quot;yyyy-mm-ddThh:mm:ss&amp;quot;) übergeben. Die Variable $delta enthält das Intervall in Sekunden. Es kann entsprechend angepasst werden. Die Neuberechnung erfolgt ausgehend vom aktuellen Datum/Uhrzeit. Es kann also als erster Termin nur ein Termin in der Zukunft angegeben werden. &lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39247</id>
		<title>AT kleine Helferlein</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39247"/>
		<updated>2024-04-20T16:08:22Z</updated>

		<summary type="html">&lt;p&gt;F Klee: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein AT kann statt einer Uhrzeit bzw. eines Datums mit einer Uhrzeit auch eine Perl-Funktion nutzen. Beispiel solcher Funktionen sind [[At#at ultimo|at_ultimo]] oder das Modul [[SUNRISE_EL]]. Hier sollen weitere Funktionen vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Der Code kann in der [[99 myUtils anlegen|99 myUtils]] untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
=== AT am x-ten Wochentag im Monat ausführen ===&lt;br /&gt;
Aufgabe ist es, das at z.B. an jedem 2. Montag im Monat auszuführen. Zusätzlich gibt es auch die Möglichkeit, das at immer am z.B. letzten Montag im Monat auszuführen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# x.ten Wochentags im Monat&lt;br /&gt;
#&lt;br /&gt;
# x=1-4 x.ter Wochentag im Monat&lt;br /&gt;
# x=9   letzter Wochentag im Monat&lt;br /&gt;
# w=1-7 Wochentag, 1=Montag&lt;br /&gt;
# h,m,s Uhrzeit Stunde, Minute, Sekunde&lt;br /&gt;
#&lt;br /&gt;
sub at_xwday($$$$$) {&lt;br /&gt;
    my ($x,$w,$h,$m,$s) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $ziel_tag = 0;&lt;br /&gt;
&lt;br /&gt;
    # akt. Datum und Uhrzeit in Variablen aufteilen&lt;br /&gt;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = &lt;br /&gt;
        localtime(time);&lt;br /&gt;
&lt;br /&gt;
    # bei Neuberechnung einen Monat addieren&lt;br /&gt;
    my $add = $data{AT_RECOMPUTE} ? 1 : 0;&lt;br /&gt;
    $mon = $mon + $add;&lt;br /&gt;
&lt;br /&gt;
    my ($nm, $ny) = ($mon == 12) ? (0,$year+1) : ($mon,$year);&lt;br /&gt;
&lt;br /&gt;
    # Letztes Vorkommen des Wochentags berechnen?&lt;br /&gt;
    if ($x == 9) {&lt;br /&gt;
        # Berechnen des letzten Tags des Monats&lt;br /&gt;
        # ersten Tag des Folgemonats als timestamp&lt;br /&gt;
        my ($xm, $xy) = ($mon == 11) ? (0,$year+1) : ($mon+1,$year);&lt;br /&gt;
        my $nt = mktime(0, 0, 0, 1, $xm, $xy);&lt;br /&gt;
&lt;br /&gt;
        # letzter Tag des aktuellen Monats = erster Tag des Folgemonats minus ein Tag&lt;br /&gt;
        my ($letzter_tag_des_monats, $letzter_wochentag) = (localtime($nt - DAYSECONDS))[3,6];&lt;br /&gt;
&lt;br /&gt;
        # Prüfen, ob der letzte Wochentag im Monat mit dem gewünschten Wochentag übereinstimmt&lt;br /&gt;
        $ziel_tag = $letzter_tag_des_monats;&lt;br /&gt;
        if ($letzter_wochentag &amp;gt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag später im Monat ist, subtrahiere die Differenz&lt;br /&gt;
           my $differenz = $letzter_wochentag - $w;&lt;br /&gt;
           $ziel_tag -= $differenz;&lt;br /&gt;
        } elsif ($letzter_wochentag &amp;lt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag früher im Monat ist, subtrahiere 7 plus die Differenz&lt;br /&gt;
           my $differenz = $w - $letzter_wochentag;&lt;br /&gt;
           $ziel_tag -= (7 - $differenz);&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        # Berechne den Tag des ersten Vorkommens des Wochentags im Monat&lt;br /&gt;
        my $erster_tag = 1;&lt;br /&gt;
        my $erster_tag_des_monats = (localtime(mktime(0,0,0,$erster_tag,$nm,$ny)))[6];&lt;br /&gt;
        my $erstes_vorkommen = ($w - $erster_tag_des_monats + 7) % 7 + 1;&lt;br /&gt;
&lt;br /&gt;
        # Berechne den Tag des x.ten Vorkommens des Wochentags im Monat&lt;br /&gt;
        $ziel_tag = $erstes_vorkommen + 7 * ($x - 1);&lt;br /&gt;
&lt;br /&gt;
        # Überprüfe, ob das Datum im gültigen Bereich liegt&lt;br /&gt;
        if ($ziel_tag &amp;gt; 31 || $ziel_tag &amp;lt; 1) {&lt;br /&gt;
          return &amp;quot;Ungültiges Datum&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return mktime($s,$m,$h,$ziel_tag,$nm,$ny);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Als Parameter benötigt die Funktion, welches Vorkommen des Wochentags berechnet werden soll (1-4). Soll das letzte Vorkommen berechnet werden, übergibt man 9. Der Montag ist der Wochentag 1. Danach kommen als getrennte Parameter Stunde, Minute und Sekunde.&lt;br /&gt;
&lt;br /&gt;
=== AT alle x Wochen ausführen ===&lt;br /&gt;
Soll ein Termin z.B. alle sechs Wochen stattfinden, so kann folgende Funktion genutzt werden.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# nächsten Treffens in sechs Wochen&lt;br /&gt;
&lt;br /&gt;
sub at_sixweek($) {&lt;br /&gt;
my ($tm) = @_;&lt;br /&gt;
my $delta = 3628800;   # Zeit zwischen den Terminen in Sekunden, hier 6 Wochen&lt;br /&gt;
&lt;br /&gt;
  return &amp;quot;Wrong timespec, use \&amp;quot;yyyy-mm-ddThh:mm:ss\&amp;quot;&amp;quot; if($tm !~ m/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)$/);&lt;br /&gt;
  my ($y,$m,$d,$h,$m2,$s) = ($1,$2,$3,$4,$5,$6);&lt;br /&gt;
  my $abstime = mktime($s,$m2,$h,$d,$m-1,$y-1900, 0,0,-1);&lt;br /&gt;
&lt;br /&gt;
  if ($data{AT_RECOMPUTE}){&lt;br /&gt;
    # bei Neuberechnung sechs Wochen zur aktuellen Zeit addieren&lt;br /&gt;
    my $now = int(time);&lt;br /&gt;
    $abstime = $now+$delta;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return $abstime;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dabei wird der erste Ausführungstermin im FHEM-üblichen Format (&amp;quot;yyyy-mm-ddThh:mm:ss&amp;quot;) übergeben. Die Variable $delta enthält das Intervall in Sekunden. Es kann entsprechend angepasst werden. Die Neuberechnung erfolgt ausgehend vom aktuellen Datum/Uhrzeit. Es kann also als erster Termin nur ein Termin in der Zukunft angegeben werden. &lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39246</id>
		<title>AT kleine Helferlein</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39246"/>
		<updated>2024-04-20T16:07:13Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Inhalt eingefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein AT kann statt einer Uhrzeit bzw. eines Datums mit einer Uhrzeit auch eine Perl-Funktion nutzen. Beispiel solcher Funktionen sind [[At#at ultimo|at_ultimo]] oder das Modul [[SUNRISE_EL]]. Hier sollen weitere Funktionen gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Der Code kann in der [[99 myUtils anlegen|99 myUtils]] untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
=== AT am x-ten Wochentag im Monat ausführen ===&lt;br /&gt;
Aufgabe ist es, das at z.B. an jedem 2. Montag im Monat auszuführen. Zusätzlich gibt es auch die Möglichkeit, das at immer am z.B. letzten Montag im Monat auszuführen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# x.ten Wochentags im Monat&lt;br /&gt;
#&lt;br /&gt;
# x=1-4 x.ter Wochentag im Monat&lt;br /&gt;
# x=9   letzter Wochentag im Monat&lt;br /&gt;
# w=1-7 Wochentag, 1=Montag&lt;br /&gt;
# h,m,s Uhrzeit Stunde, Minute, Sekunde&lt;br /&gt;
#&lt;br /&gt;
sub at_xwday($$$$$) {&lt;br /&gt;
    my ($x,$w,$h,$m,$s) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $ziel_tag = 0;&lt;br /&gt;
&lt;br /&gt;
    # akt. Datum und Uhrzeit in Variablen aufteilen&lt;br /&gt;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = &lt;br /&gt;
        localtime(time);&lt;br /&gt;
&lt;br /&gt;
    # bei Neuberechnung einen Monat addieren&lt;br /&gt;
    my $add = $data{AT_RECOMPUTE} ? 1 : 0;&lt;br /&gt;
    $mon = $mon + $add;&lt;br /&gt;
&lt;br /&gt;
    my ($nm, $ny) = ($mon == 12) ? (0,$year+1) : ($mon,$year);&lt;br /&gt;
&lt;br /&gt;
    # Letztes Vorkommen des Wochentags berechnen?&lt;br /&gt;
    if ($x == 9) {&lt;br /&gt;
        # Berechnen des letzten Tags des Monats&lt;br /&gt;
        # ersten Tag des Folgemonats als timestamp&lt;br /&gt;
        my ($xm, $xy) = ($mon == 11) ? (0,$year+1) : ($mon+1,$year);&lt;br /&gt;
        my $nt = mktime(0, 0, 0, 1, $xm, $xy);&lt;br /&gt;
&lt;br /&gt;
        # letzter Tag des aktuellen Monats = erster Tag des Folgemonats minus ein Tag&lt;br /&gt;
        my ($letzter_tag_des_monats, $letzter_wochentag) = (localtime($nt - DAYSECONDS))[3,6];&lt;br /&gt;
&lt;br /&gt;
        # Prüfen, ob der letzte Wochentag im Monat mit dem gewünschten Wochentag übereinstimmt&lt;br /&gt;
        $ziel_tag = $letzter_tag_des_monats;&lt;br /&gt;
        if ($letzter_wochentag &amp;gt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag später im Monat ist, subtrahiere die Differenz&lt;br /&gt;
           my $differenz = $letzter_wochentag - $w;&lt;br /&gt;
           $ziel_tag -= $differenz;&lt;br /&gt;
        } elsif ($letzter_wochentag &amp;lt; $w) {&lt;br /&gt;
           # Falls der letzte Wochentag früher im Monat ist, subtrahiere 7 plus die Differenz&lt;br /&gt;
           my $differenz = $w - $letzter_wochentag;&lt;br /&gt;
           $ziel_tag -= (7 - $differenz);&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        # Berechne den Tag des ersten Vorkommens des Wochentags im Monat&lt;br /&gt;
        my $erster_tag = 1;&lt;br /&gt;
        my $erster_tag_des_monats = (localtime(mktime(0,0,0,$erster_tag,$nm,$ny)))[6];&lt;br /&gt;
        my $erstes_vorkommen = ($w - $erster_tag_des_monats + 7) % 7 + 1;&lt;br /&gt;
&lt;br /&gt;
        # Berechne den Tag des x.ten Vorkommens des Wochentags im Monat&lt;br /&gt;
        $ziel_tag = $erstes_vorkommen + 7 * ($x - 1);&lt;br /&gt;
&lt;br /&gt;
        # Überprüfe, ob das Datum im gültigen Bereich liegt&lt;br /&gt;
        if ($ziel_tag &amp;gt; 31 || $ziel_tag &amp;lt; 1) {&lt;br /&gt;
          return &amp;quot;Ungültiges Datum&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return mktime($s,$m,$h,$ziel_tag,$nm,$ny);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Als Parameter benötigt die Funktion, welches Vorkommen des Wochentags berechnet werden soll (1-4). Soll das letzte Vorkommen berechnet werden, übergibt man 9. Der Montag ist der Wochentag 1. Danach kommen als getrennte Parameter Stunde, Minute und Sekunde.&lt;br /&gt;
&lt;br /&gt;
=== AT alle x Wochen ausführen ===&lt;br /&gt;
Soll ein Termin z.B. alle sechs Wochen stattfinden, so kann folgende Funktion genutzt werden.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
########################################&lt;br /&gt;
#&lt;br /&gt;
# Berechnung des Datums des &lt;br /&gt;
# nächsten Treffens in sechs Wochen&lt;br /&gt;
&lt;br /&gt;
sub at_sixweek($) {&lt;br /&gt;
my ($tm) = @_;&lt;br /&gt;
my $delta = 3628800;   # Zeit zwischen den Terminen in Sekunden, hier 6 Wochen&lt;br /&gt;
&lt;br /&gt;
  return &amp;quot;Wrong timespec, use \&amp;quot;yyyy-mm-ddThh:mm:ss\&amp;quot;&amp;quot; if($tm !~ m/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)$/);&lt;br /&gt;
  my ($y,$m,$d,$h,$m2,$s) = ($1,$2,$3,$4,$5,$6);&lt;br /&gt;
  my $abstime = mktime($s,$m2,$h,$d,$m-1,$y-1900, 0,0,-1);&lt;br /&gt;
&lt;br /&gt;
  if ($data{AT_RECOMPUTE}){&lt;br /&gt;
    # bei Neuberechnung sechs Wochen zur aktuellen Zeit addieren&lt;br /&gt;
    my $now = int(time);&lt;br /&gt;
    $abstime = $now+$delta;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return $abstime;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dabei wird der erste Ausführungstermin im FHEM-üblichen Format (&amp;quot;yyyy-mm-ddThh:mm:ss&amp;quot;) übergeben. Die Variable $delta enthält das Intervall in Sekunden. Es kann entsprechend angepasst werden. Die Neuberechnung erfolgt ausgehend vom aktuellen Datum/Uhrzeit. Es kann also als erster Termin nur ein Termin in der Zukunft angegeben werden. &lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39245</id>
		<title>AT kleine Helferlein</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39245"/>
		<updated>2024-04-20T15:14:49Z</updated>

		<summary type="html">&lt;p&gt;F Klee: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein AT kann statt einer Uhrzeit bzw. eines Datums mit einer Uhrzeit auch eine Perl-Funktion nutzen. Beispiel solcher Funktionen sind [[At#at ultimo|at_ultimo]] oder das Modul [[SUNRISE_EL]]. Hier sollen weitere Funktionen gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Der Code kann in der [[99 myUtils anlegen|99 myUtils]] untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
=== AT am x-ten Wochentag im Monat ausführen ===&lt;br /&gt;
&lt;br /&gt;
=== AT alle x Wochen ausführen ===&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39244</id>
		<title>AT kleine Helferlein</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_kleine_Helferlein&amp;diff=39244"/>
		<updated>2024-04-20T14:36:19Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Seite erstellt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein AT kann statt einer Uhrzeit bzw. eines Datums mit einer Uhrzeit auch eine Perl-Funktion nutzen. Beispiel solcher Funktionen sind [[At#at ultimo|at_ultimo]] oder das Modul [[SUNRISE_EL]]. Hier sollen weitere Funktionen gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== AT am x-ten Wochentag im Monat ausführen ===&lt;br /&gt;
&lt;br /&gt;
=== AT alle x Wochen ausführen ===&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=ABFALL&amp;diff=39198</id>
		<title>ABFALL</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=ABFALL&amp;diff=39198"/>
		<updated>2024-03-23T15:35:03Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* Voraussetzungen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Filtern von (Abfall-)Terminen aus einem Calendar.&lt;br /&gt;
|ModType=x&lt;br /&gt;
|ModFTopic=48237&lt;br /&gt;
|ModForumArea=Codeschnipsel&lt;br /&gt;
|ModTechName=57_ABFALL.pm&lt;br /&gt;
|ModOwner=Constantin / {{Link2FU|14026|uniqueck}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[ABFALL]] ist ein (inoffizielles, nicht Bestandteil der Distribution) Hilfsmodul, das bestimmte Termine aus einem bestehenden Kalender des Moduls [[Calendar]] in Readings übernimmt. &lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Es muss ein [[Calendar]]-Objekt definiert sein. Der dabei benutzte Name muss in der Definition des ABFALL-Objekts spezifiziert werden.&lt;br /&gt;
Es können auch mehrere Calendar Objekte übergeben werden.&lt;br /&gt;
&lt;br /&gt;
Sonderzeichen aus dem Namen der Termine werden entfernt, um die Namen der generierten Readings FHEM-tauglich zu machen, für die Werte der Readings bleiben diese allerdings erhalten.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
=== Installation ===&lt;br /&gt;
Mit folgendem Befehl kann das Modul direkt in den Standard FHEM Update Prozess eingeklinkt werden.&lt;br /&gt;
:&amp;lt;code&amp;gt;update add https://raw.githubusercontent.com/uniqueck/fhem-abfall/master/controls_fhemabfall.txt&amp;lt;/code&amp;gt;&lt;br /&gt;
Um es nur zu installieren, kann auch einfach nur das Command&lt;br /&gt;
:&amp;lt;code&amp;gt;update all https://raw.githubusercontent.com/uniqueck/fhem-abfall/master/controls_fhemabfall.txt&amp;lt;/code&amp;gt;&lt;br /&gt;
eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
=== Entwicklungsstrang ===&lt;br /&gt;
:&amp;lt;code&amp;gt;update add https://raw.githubusercontent.com/uniqueck/fhem-abfall/develop/controls_fhemabfall.txt&amp;lt;/code&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
:&amp;lt;code&amp;gt;update all https://raw.githubusercontent.com/uniqueck/fhem-abfall/develop/controls_fhemabfall.txt&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
:&amp;lt;code&amp;gt;define &amp;lt;Name&amp;gt; ABFALL &amp;lt;calendarname&amp;gt;,&amp;lt;calendarname2&amp;gt;,...&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Erläuterung der Parameter im &#039;&#039;&#039;define&#039;&#039;&#039;:&lt;br /&gt;
;&amp;lt;calendarname&amp;gt;&lt;br /&gt;
:Name des &#039;&#039;&#039;Calendar&#039;&#039;&#039; Kalenders &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
:&amp;lt;code&amp;gt;define AbfallGoogleCalender Calendar ical url https://......&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;define myABFALL ABFALL AbfallGoogleCalender&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Werte aktualisieren ===&lt;br /&gt;
Die Werte aktualisieren sich abhängig vom [[notify]] der entsprechenden Calendar Instanz, welche im define angegeben wurde(n).&lt;br /&gt;
&lt;br /&gt;
=== Weitere Attribute ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Werteliste&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |calendarname_praefix&lt;br /&gt;
|0 und 1&lt;br /&gt;
|soll der Kalendername als praefix dem Reading vorangestellt werden, sollte bei nur einem Kalender auf 0 gesetzt werden&lt;br /&gt;
|1 - praefix wird vorangestellt, sofern mehrere Kalender angegeben wurden, ansonsten 0 - praefix wird nicht vorangestellt&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |abfall_clear_reading_regex&lt;br /&gt;
|&lt;br /&gt;
|regex zum Entfernen von Anteilen aus dem Termin, dieser wird vor dem Entfernen von Sonderzeichen aus den Namen der Termine angewandt.&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |disable&lt;br /&gt;
|0 und 1&lt;br /&gt;
|deaktiviert das Modul&lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |weekday_mapping&lt;br /&gt;
|&lt;br /&gt;
|Mapping, wie die Readings der Tage angezeigt werden sollen, zum Beispiel So Mo Di Mi Do Fr Sa&lt;br /&gt;
|Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |delimiter_text_reading&lt;br /&gt;
|&lt;br /&gt;
|Wenn zwei Abholungen an ein und demselben Tag existieren, wird dieses Trennzeichen genutzt, um die beiden (oder mehrere) Werte zu einem Text zu verbinden. Nur relevant für die Readings next_text und now_text&lt;br /&gt;
|und&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |delimiter_reading&lt;br /&gt;
|&lt;br /&gt;
|wie attribute delimiter_text_reading, allerdings nur für die readings next und now&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |filter&lt;br /&gt;
|&lt;br /&gt;
|regex zum Filtern der Namen der Termine aus den Kalendern, so dass nur solche genutzt werden, welche diesem Filter entsprechen&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiel(e) ==&lt;br /&gt;
=== Einbindung ins Tablet UI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;div data-device=&amp;quot;myABFALL&amp;quot; data-type=&amp;quot;symbol&amp;quot; class=&amp;quot;bigger warn wider&amp;quot; &lt;br /&gt;
          data-get=&amp;quot;next&amp;quot; data-get-warn=&amp;quot;.*(\d+).*&amp;quot; &lt;br /&gt;
          data-get-on=&#039;[&amp;quot;Restmuell_.*&amp;quot;,&amp;quot;Wertstoff_.*&amp;quot;]&#039;&lt;br /&gt;
          data-colors=&#039;[&amp;quot;#000&amp;quot;,&amp;quot;#6EB54C&amp;quot;]&#039; &lt;br /&gt;
          data-icons=&#039;[&amp;quot;fa-trash-o&amp;quot;,&amp;quot;fa-trash-o&amp;quot;]&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einbindung ins Tablet UI, erweitert ===&lt;br /&gt;
Fallen die Leerungen zweier verschiedener Tonnen nicht auf den selben Tag, reicht es normalerweise, nur ein Symbol auf der Oberfläche zu platzieren und dieses dann dynamisch zu befüllen. In folgendem Beispiel werden folgende Anforderungen umgesetzt:&lt;br /&gt;
* Anzeige unterschiedlicher Symbole bzw. Farben für Papiertonne, Restmülltonne, Biotonne und gelbe Säcke&lt;br /&gt;
* Anzeige der verbleibenden Tage bis zur Leerung als &amp;quot;Warn&amp;quot;-Marker in Rot, aber nur, wenn die Leerung innerhalb der nächsten 2 Tage ist&lt;br /&gt;
* Blinken des Symbols, wenn die nächste Leerung morgen ansteht&lt;br /&gt;
* Rotation des Symbols, wenn die nächste Leerung noch am selben Tag ansteht. Nach einer bestimmten Uhrzeit (z.B. 9 Uhr morgens) soll dann auf die nächste Tonne geschaltet werden&lt;br /&gt;
* Anzeige des Datums bzw. von &amp;quot;heute&amp;quot; oder &amp;quot;morgen&amp;quot; unter dem Symbol als Label&lt;br /&gt;
&lt;br /&gt;
Zur Datumsanzeige wird eine kleine Hilfsfunktion in die 99_myUtils eingebaut. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub datumHeuteMorgen($){&lt;br /&gt;
		my $compareDate = shift;&lt;br /&gt;
		my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);&lt;br /&gt;
		$year += 1900; $mon += 1; &lt;br /&gt;
		my $heute = sprintf(&#039;%02d.%02d.%04d&#039;, $mday, $mon, $year);&lt;br /&gt;
		($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time+86400);&lt;br /&gt;
		$year += 1900; $mon += 1;&lt;br /&gt;
		my $morgen = sprintf(&#039;%02d.%02d.%04d&#039;, $mday, $mon, $year);&lt;br /&gt;
		return &amp;quot;heute&amp;quot; if $compareDate eq $heute;&lt;br /&gt;
		return &amp;quot;morgen&amp;quot; if $compareDate eq $morgen;&lt;br /&gt;
		return $compareDate;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Diese Funktion wird in den userReadings des Abfall-Moduls verwendet. Das Abfallmodul erzeugt eine Gruppe von Readings mit dem Namen now_*, wenn die Leerung am selben Tag ansteht, bzw. genau dann, wenn der Termin im zu Grunde liegenden Kalender gerade aktiv ist. In diesem Beispiel liegt dem Kalender-Modul ein Google-Kalender zu Grunde, bei dem die Termine immer von 0 Uhr bis 9 Uhr morgens eingetragen sind. Dadurch wird erreicht, dass die Anzeige nach 9 Uhr weiterspringt, weil dann die now-Readings verschwinden.&lt;br /&gt;
&lt;br /&gt;
Folgende userReadings werden zum Abfallmodul hinzugefügt, welches in diesem Beispiel &amp;quot;myABFALL&amp;quot; genannt ist:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr myABFALL userReadings ftui_datum {ReadingsVal(&amp;quot;myABFALL&amp;quot;,&amp;quot;now_text&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;&amp;quot; ? datumHeuteMorgen(ReadingsVal(&amp;quot;myABFALL&amp;quot;,&amp;quot;next_date&amp;quot;,&amp;quot;&amp;quot;)) : &amp;quot;heute&amp;quot;;},ftui_next {ReadingsVal(&amp;quot;myABFALL&amp;quot;,&amp;quot;now_text&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;&amp;quot; ? ReadingsVal(&amp;quot;myABFALL&amp;quot;,&amp;quot;next&amp;quot;,&amp;quot;&amp;quot;) : ReadingsVal(&amp;quot;myABFALL&amp;quot;,&amp;quot;now&amp;quot;,&amp;quot;&amp;quot;).&amp;quot;_0&amp;quot;;;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Das Reading &amp;quot;ftui_next&amp;quot; bildet die Grundlage für das Symbol in TabletUI, das Reading &amp;quot;ftui_datum&amp;quot; wird für das Label genutzt. &lt;br /&gt;
&lt;br /&gt;
Somit lässt sich ganze in FTUI wie folgt darstellen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div data-device=&amp;quot;myABFALL&amp;quot; &lt;br /&gt;
                     data-type=&amp;quot;symbol&amp;quot;&lt;br /&gt;
                     data-get=&amp;quot;ftui_next&amp;quot;&lt;br /&gt;
                     data-get-on=&#039;[&amp;quot;Biotonne_0$&amp;quot;,&amp;quot;Biotonne_1$&amp;quot;,&amp;quot;Biotonne_.*&amp;quot;,&amp;quot;GelberSack_0$&amp;quot;,&amp;quot;GelberSack_1$&amp;quot;,&amp;quot;GelberSack_.*&amp;quot;,&amp;quot;Papiertonne_0$&amp;quot;,&amp;quot;Papiertonne_1$&amp;quot;,&amp;quot;Papiertonne_.*&amp;quot;,&amp;quot;Restmuelltonne_0$&amp;quot;,&amp;quot;Restmuelltonne_1$&amp;quot;,&amp;quot;Restmuelltonne_.*&amp;quot;]&#039;&lt;br /&gt;
                     data-get-warn=&amp;quot;.*([0|1|2]).*&amp;quot;&lt;br /&gt;
                     data-colors=&#039;[&amp;quot;#8B4513&amp;quot;,&amp;quot;#8B4513&amp;quot;,&amp;quot;#8B4513&amp;quot;,&amp;quot;#f4e946&amp;quot;,&amp;quot;#f4e946&amp;quot;,&amp;quot;#f4e946&amp;quot;,&amp;quot;#2d9e1c&amp;quot;,&amp;quot;#2d9e1c&amp;quot;,&amp;quot;#2d9e1c&amp;quot;,&amp;quot;#696969&amp;quot;,&amp;quot;#696969&amp;quot;,&amp;quot;#696969&amp;quot;]&#039;&lt;br /&gt;
                     class=&amp;quot;large warn&amp;quot;&lt;br /&gt;
                     data-icons=&#039;[&amp;quot;fa-trash-o fa-spin&amp;quot;,&amp;quot;fa-trash-o blink&amp;quot;,&amp;quot;fa-trash-o&amp;quot;,&amp;quot;fs-bag fa-spin&amp;quot;,&amp;quot;fs-bag blink&amp;quot;,&amp;quot;fs-bag&amp;quot;,&amp;quot;fs-dustbin fa-spin&amp;quot;,&amp;quot;fs-dustbin blink&amp;quot;,&amp;quot;fs-dustbin&amp;quot;,&amp;quot;fa-trash fa-spin&amp;quot;,&amp;quot;fa-trash blink&amp;quot;,&amp;quot;fa-trash&amp;quot;]&#039;&lt;br /&gt;
                     /&amp;gt;&lt;br /&gt;
                &amp;lt;div data-device=&amp;quot;myABFALL&amp;quot; data-get=&amp;quot;ftui_datum&amp;quot; data-type=&amp;quot;label&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Für Jede Tonne werden hier drei Zustände unterschieden und einzeln in &amp;quot;data-get-on&amp;quot;, &amp;quot;data-on-colors&amp;quot; und &amp;quot;data-icons&amp;quot; zugeordnet. Daher haben diese Listen jeweils 12 Einträge.&lt;br /&gt;
&lt;br /&gt;
=== Benachrichtigung ===&lt;br /&gt;
==== DOIF ====&lt;br /&gt;
====== TelegramBot Beispiel ======&lt;br /&gt;
&amp;lt;pre&amp;gt;[myABFALL:next_days] == 1) ( set fhemBot message &#039;Morgen wird [myABFALL:next_text] abgeholt&#039;)&lt;br /&gt;
[myABFALL:now_text] ne &amp;quot;&amp;quot;) ( set fhemBot message &#039;Heute wird [myABFALL:now_text] abgeholt&#039;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====== Pushbullet Beispiel ======&lt;br /&gt;
&lt;br /&gt;
Die morgigen Leerungen per Push um 19:30 mittels [[Pushbullet]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define dAbfallmorgen doif ([19:30] and [myABFALL:next_days] == 1) ( msg |Morgen wird [myABFALL:next_text] abgeholt)&lt;br /&gt;
&lt;br /&gt;
attr dAbfallmorgen do always&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die heutigen Leerungen per Push um 07:00 mittels Pushbullet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define dAbfallheute doif ([07:00] and [myABFALL:now_text] ne &amp;quot;&amp;quot;) ( msg |Heute wird [myABFALL:now_text] abgeholt)&lt;br /&gt;
&lt;br /&gt;
attr dAbfallheute do always&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
* Forenthema {{Link2Forum|Topic=50177|LinkText=Abfall Visualisierung mit Bilderrahmen}}&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=At&amp;diff=39179</id>
		<title>At</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=At&amp;diff=39179"/>
		<updated>2024-03-16T15:46:59Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* at_ultimo */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{SEITENTITEL:at}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Setzt einen Fhem-Befehl zu einem späteren Zeitpunkt ab.&lt;br /&gt;
|ModType=h&lt;br /&gt;
&amp;lt;!-- |ModCategory= (noch?) nicht verwendet --&amp;gt;&lt;br /&gt;
|ModCmdRef=at&lt;br /&gt;
|ModTechName=90_at.pm&lt;br /&gt;
|ModOwner={{Link2FU|8|rudolfkoenig}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[at]] ist ein Erweiterungsmodul, mit dessen Hilfe FHEM-Befehle/-Aktionen zu einem späteren Zeitpunkt ausgeführt werden können. Es läßt sich sowohl einmalige Ausführung, als auch regelmäßige Wiederholung erzielen, Zeitangaben können relativ oder absolut erfolgen.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
&amp;lt;!-- AUSKOMMENTIERT wegen derzeitiger Funktionsproblemen iZm codemirror {{Randnotiz|RNTyp=[g|Info|RNText=FHEM enthält für at eine eingebaute Perl-Syntax-Prüfung. Diese ist nach [http://fhem.de/commandref.html#perlSyntaxCheck Aktivierung] aber nur aktiv, wenn die [[Konfiguration]] -wie empfohlen- nicht direkt bearbeitet wird. ({{Link2Forum|Topic=51744}}) }} --&amp;gt;&lt;br /&gt;
Keine.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
=== Define ===&lt;br /&gt;
&amp;lt;code&amp;gt;define &amp;lt;name&amp;gt; at &amp;lt;timespec|datespec&amp;gt; &amp;lt;command&amp;gt;&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Besonderheit ===&lt;br /&gt;
*timespec - &#039;&#039;&#039;nur Zeit&#039;&#039;&#039; im Format HH:MM:SS &#039;&#039;&#039;kann eine&#039;&#039;&#039; Perlfunktion sein. &lt;br /&gt;
*datespec - &#039;&#039;&#039;Datum und Zeit&#039;&#039;&#039; ISO 8601 oder &amp;quot;number of sec since 1970&amp;quot; &#039;&#039;&#039;darf keine&#039;&#039;&#039; Perlfunktion sein.&lt;br /&gt;
Siehe {{Link2Forum|Topic=91625|Message=168475}} &lt;br /&gt;
&lt;br /&gt;
=== Beispiele ===&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at 02:02:00 set lamp on&amp;lt;/code&amp;gt; →              das nächste Mal um zwei Minuten nach 2 Uhr &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at *02:02:00 set lamp on&amp;lt;/code&amp;gt; →             jeden Tag um zwei Minuten nach 2 Uhr &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at {ReadingsVal(&amp;quot;Dummy&amp;quot;,&amp;quot;Zeit&amp;quot;,&amp;quot;&amp;quot;)} set lamp on&amp;lt;/code&amp;gt; →              das nächste Mal um (Perlfunktion liest Zeit aus dem Dummy) &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at 2016-01-25T02:02:00 set lamp on&amp;lt;/code&amp;gt; →              das nächste Mal am 25.01.2016 um zwei Minuten nach 2 Uhr &amp;quot;lamp&amp;quot; einschalten (ISO 8601)&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at 1453683720 set lamp on&amp;lt;/code&amp;gt; →              das nächste Mal am 25.01.2016 um zwei Minuten nach 2 Uhr &amp;quot;lamp&amp;quot; einschalten (number of sec since 1970)&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at +02:02:00 set lamp on&amp;lt;/code&amp;gt;    →         in zwei Stunden und 2 Minuten &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at +*02:02:00 set lamp on&amp;lt;/code&amp;gt;   →        alle zwei Stunden und 2 Minuten &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
Um datespec auch variabel mit setzen zu können gibt es einen Workaround: Perlebene, Perlfunktion und Übergabe in Variable. &lt;br /&gt;
&lt;br /&gt;
Beispiele für &amp;quot;number of seconds since 1970&amp;quot;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
{my $time=time_str2num(&amp;quot;2019-09-14 23:00:00&amp;quot;);;fhem(&amp;quot;define MeineAktion at $time set lamp on&amp;quot;)}&lt;br /&gt;
{my $time=1568494800;;fhem(&amp;quot;define MeineAktion at $time set lamp on&amp;quot;)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Beispiel im ISO 8601 Format&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{my $time=&amp;quot;2019-09-14T23:00:00&amp;quot;;;fhem(&amp;quot;define MeineAktion at $time set lamp on&amp;quot;)}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mehrere Aktionen ausführen ===&lt;br /&gt;
Die Verwendung der Semikolon erfordert immer besondere Aufmerksamkeit!&lt;br /&gt;
*&amp;lt;code&amp;gt;set lampe1 on ; set lampe2 on &amp;lt;/code&amp;gt;   →        Schaltet sofort beide Lampen ein ( ein bisschen OT, weil kein at)&lt;br /&gt;
*&amp;lt;code&amp;gt;define morgens at *7:00:00 set lampe1 on ; set lampe2 on&amp;lt;/code&amp;gt;   →     schaltet lampe 1 immer um 7 an, aber lampe2 sofort. Der erste Befehl landet in der config (im at) der zweite Befehl wird genau wie der define Befehl einfach sofort ausgeführt.  &lt;br /&gt;
*&amp;lt;code&amp;gt;define morgens at *7:00:00 set lampe1 on ;; set lampe2 on&amp;lt;/code&amp;gt;   →     schaltet BEIDE Lampen immer um 7 an. Beide Befehle landen in der config (im at), nur der define Befehl wird ausgeführt&lt;br /&gt;
*&amp;lt;code&amp;gt;define morgens at *7:00:00 set lampe1,lampe2 on&amp;lt;/code&amp;gt;   →     schaltet BEIDE Lampen immer um 7 an. Geht nur wenn der gleiche Befehl an 2 oder mehr Geräte gesendet werden soll&lt;br /&gt;
&lt;br /&gt;
=== at_ultimo ===&lt;br /&gt;
Die integrierte Funktion at_ultimo() dient dazu, an jedem letzten Tag des Monats einen FHEM-Befehl auszuführen. Sie kann als Perlfunc für timespec verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define at_ultimo at *{at_ultimo()} set Lampe1 off&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dadurch wird ein at-device erstellt, das am letzten Tag des Monats um 23:59:00 Uhr ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
at_ultimo() kann zusätzliche Parameter annehmen, um eine andere Zeit an diesem Tag anzugeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define at_ultimo at *{at_ultimo(12,23,45)} set Lampe1 off&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dadurch wird ein at-device erstellt, das am letzten Tag des Monats um 12:23:45 Uhr ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
=== Attribute ===&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
=== Testen ===&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;Versionsspezifisch:&#039;&#039;&#039; Der Befehl &#039;&#039;execNow&#039;&#039; ist in FHEM 5.7/90_at.pm ab 30.4.2016 verfügbar.}}&lt;br /&gt;
Mit dem Befehl &lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;devspec&amp;gt; execNow&amp;lt;/code&amp;gt;&lt;br /&gt;
lässt sich eine &#039;&#039;at&#039;&#039;-Definition (einmalig, beispielsweise zu Testzwecken) unabhängig vom Erreichen der angegebenen Zeitspezifikation ausführen.&lt;br /&gt;
&lt;br /&gt;
=== Ändern / Modifizieren ===&lt;br /&gt;
Das Zeit-Attribut eines existierenden Timers sollte via &amp;lt;code&amp;gt;modifyTimeSpec&amp;lt;/code&amp;gt; (Befehls-Syntax via Web-Interface ermitteln) geändert werden können.&lt;br /&gt;
Details dazu in den Forenbeiträgen&lt;br /&gt;
* {{Link2Forum|Topic=76227|LinkText=modifyTimeSpec fehlerhaft!?}}&lt;br /&gt;
* {{Link2Forum|Topic=36326|LinkText=defmod}} &lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
* [[AT an einem bestimmten Wochentag ausführen|at an einem bestimmten Wochentag ausführen]]&lt;br /&gt;
* [[AT um eine Temperaturabhängige Nachtabsenkung zu realisieren|at um eine Temperaturabhängige Nachtabsenkung zu realisieren]]&lt;br /&gt;
* [[AT zu einem absoluten Datum ausführen|at zu einem absoluten Datum ausführen]]&lt;br /&gt;
* [[SUNRISE_EL|at in Verbindung mit SUNRISE_EL]] &lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Abfrage, ob at definiert ist: {{Link2Forum|Topic=23584|Message=841269}}&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=At&amp;diff=39178</id>
		<title>At</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=At&amp;diff=39178"/>
		<updated>2024-03-16T15:42:15Z</updated>

		<summary type="html">&lt;p&gt;F Klee: at_ultimo hinzu gefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{SEITENTITEL:at}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Setzt einen Fhem-Befehl zu einem späteren Zeitpunkt ab.&lt;br /&gt;
|ModType=h&lt;br /&gt;
&amp;lt;!-- |ModCategory= (noch?) nicht verwendet --&amp;gt;&lt;br /&gt;
|ModCmdRef=at&lt;br /&gt;
|ModTechName=90_at.pm&lt;br /&gt;
|ModOwner={{Link2FU|8|rudolfkoenig}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[at]] ist ein Erweiterungsmodul, mit dessen Hilfe FHEM-Befehle/-Aktionen zu einem späteren Zeitpunkt ausgeführt werden können. Es läßt sich sowohl einmalige Ausführung, als auch regelmäßige Wiederholung erzielen, Zeitangaben können relativ oder absolut erfolgen.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
&amp;lt;!-- AUSKOMMENTIERT wegen derzeitiger Funktionsproblemen iZm codemirror {{Randnotiz|RNTyp=[g|Info|RNText=FHEM enthält für at eine eingebaute Perl-Syntax-Prüfung. Diese ist nach [http://fhem.de/commandref.html#perlSyntaxCheck Aktivierung] aber nur aktiv, wenn die [[Konfiguration]] -wie empfohlen- nicht direkt bearbeitet wird. ({{Link2Forum|Topic=51744}}) }} --&amp;gt;&lt;br /&gt;
Keine.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
=== Define ===&lt;br /&gt;
&amp;lt;code&amp;gt;define &amp;lt;name&amp;gt; at &amp;lt;timespec|datespec&amp;gt; &amp;lt;command&amp;gt;&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Besonderheit ===&lt;br /&gt;
*timespec - &#039;&#039;&#039;nur Zeit&#039;&#039;&#039; im Format HH:MM:SS &#039;&#039;&#039;kann eine&#039;&#039;&#039; Perlfunktion sein. &lt;br /&gt;
*datespec - &#039;&#039;&#039;Datum und Zeit&#039;&#039;&#039; ISO 8601 oder &amp;quot;number of sec since 1970&amp;quot; &#039;&#039;&#039;darf keine&#039;&#039;&#039; Perlfunktion sein.&lt;br /&gt;
Siehe {{Link2Forum|Topic=91625|Message=168475}} &lt;br /&gt;
&lt;br /&gt;
=== Beispiele ===&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at 02:02:00 set lamp on&amp;lt;/code&amp;gt; →              das nächste Mal um zwei Minuten nach 2 Uhr &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at *02:02:00 set lamp on&amp;lt;/code&amp;gt; →             jeden Tag um zwei Minuten nach 2 Uhr &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at {ReadingsVal(&amp;quot;Dummy&amp;quot;,&amp;quot;Zeit&amp;quot;,&amp;quot;&amp;quot;)} set lamp on&amp;lt;/code&amp;gt; →              das nächste Mal um (Perlfunktion liest Zeit aus dem Dummy) &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at 2016-01-25T02:02:00 set lamp on&amp;lt;/code&amp;gt; →              das nächste Mal am 25.01.2016 um zwei Minuten nach 2 Uhr &amp;quot;lamp&amp;quot; einschalten (ISO 8601)&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at 1453683720 set lamp on&amp;lt;/code&amp;gt; →              das nächste Mal am 25.01.2016 um zwei Minuten nach 2 Uhr &amp;quot;lamp&amp;quot; einschalten (number of sec since 1970)&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at +02:02:00 set lamp on&amp;lt;/code&amp;gt;    →         in zwei Stunden und 2 Minuten &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
*&amp;lt;code&amp;gt;define MeineAktion at +*02:02:00 set lamp on&amp;lt;/code&amp;gt;   →        alle zwei Stunden und 2 Minuten &amp;quot;lamp&amp;quot; einschalten&lt;br /&gt;
Um datespec auch variabel mit setzen zu können gibt es einen Workaround: Perlebene, Perlfunktion und Übergabe in Variable. &lt;br /&gt;
&lt;br /&gt;
Beispiele für &amp;quot;number of seconds since 1970&amp;quot;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
{my $time=time_str2num(&amp;quot;2019-09-14 23:00:00&amp;quot;);;fhem(&amp;quot;define MeineAktion at $time set lamp on&amp;quot;)}&lt;br /&gt;
{my $time=1568494800;;fhem(&amp;quot;define MeineAktion at $time set lamp on&amp;quot;)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Beispiel im ISO 8601 Format&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{my $time=&amp;quot;2019-09-14T23:00:00&amp;quot;;;fhem(&amp;quot;define MeineAktion at $time set lamp on&amp;quot;)}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mehrere Aktionen ausführen ===&lt;br /&gt;
Die Verwendung der Semikolon erfordert immer besondere Aufmerksamkeit!&lt;br /&gt;
*&amp;lt;code&amp;gt;set lampe1 on ; set lampe2 on &amp;lt;/code&amp;gt;   →        Schaltet sofort beide Lampen ein ( ein bisschen OT, weil kein at)&lt;br /&gt;
*&amp;lt;code&amp;gt;define morgens at *7:00:00 set lampe1 on ; set lampe2 on&amp;lt;/code&amp;gt;   →     schaltet lampe 1 immer um 7 an, aber lampe2 sofort. Der erste Befehl landet in der config (im at) der zweite Befehl wird genau wie der define Befehl einfach sofort ausgeführt.  &lt;br /&gt;
*&amp;lt;code&amp;gt;define morgens at *7:00:00 set lampe1 on ;; set lampe2 on&amp;lt;/code&amp;gt;   →     schaltet BEIDE Lampen immer um 7 an. Beide Befehle landen in der config (im at), nur der define Befehl wird ausgeführt&lt;br /&gt;
*&amp;lt;code&amp;gt;define morgens at *7:00:00 set lampe1,lampe2 on&amp;lt;/code&amp;gt;   →     schaltet BEIDE Lampen immer um 7 an. Geht nur wenn der gleiche Befehl an 2 oder mehr Geräte gesendet werden soll&lt;br /&gt;
&lt;br /&gt;
=== at_ultimo ===&lt;br /&gt;
Die integrierte Funktion at_ultimo() dient dazu, an jedem letzten Tag des Monats einen FHEM-Befehl auszuführen. Sie kann als Perlfunc für timespec verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define at_ultimo at *{at_ultimo()} set Lampe1 off&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dadurch wird ein At-Gerät erstellt, das am letzten Tag des Monats um 23:59:00 Uhr ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
at_ultimo() kann zusätzliche Parameter annehmen, um eine andere Zeit an diesem Tag anzugeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define at_ultimo at *{at_ultimo(12,23,45)} set Lampe1 off&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dadurch wird ein AT-Gerät erstellt, das am letzten Tag des Monats um 12:23:45 Uhr ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Attribute ===&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
=== Testen ===&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;Versionsspezifisch:&#039;&#039;&#039; Der Befehl &#039;&#039;execNow&#039;&#039; ist in FHEM 5.7/90_at.pm ab 30.4.2016 verfügbar.}}&lt;br /&gt;
Mit dem Befehl &lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;devspec&amp;gt; execNow&amp;lt;/code&amp;gt;&lt;br /&gt;
lässt sich eine &#039;&#039;at&#039;&#039;-Definition (einmalig, beispielsweise zu Testzwecken) unabhängig vom Erreichen der angegebenen Zeitspezifikation ausführen.&lt;br /&gt;
&lt;br /&gt;
=== Ändern / Modifizieren ===&lt;br /&gt;
Das Zeit-Attribut eines existierenden Timers sollte via &amp;lt;code&amp;gt;modifyTimeSpec&amp;lt;/code&amp;gt; (Befehls-Syntax via Web-Interface ermitteln) geändert werden können.&lt;br /&gt;
Details dazu in den Forenbeiträgen&lt;br /&gt;
* {{Link2Forum|Topic=76227|LinkText=modifyTimeSpec fehlerhaft!?}}&lt;br /&gt;
* {{Link2Forum|Topic=36326|LinkText=defmod}} &lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
* [[AT an einem bestimmten Wochentag ausführen|at an einem bestimmten Wochentag ausführen]]&lt;br /&gt;
* [[AT um eine Temperaturabhängige Nachtabsenkung zu realisieren|at um eine Temperaturabhängige Nachtabsenkung zu realisieren]]&lt;br /&gt;
* [[AT zu einem absoluten Datum ausführen|at zu einem absoluten Datum ausführen]]&lt;br /&gt;
* [[SUNRISE_EL|at in Verbindung mit SUNRISE_EL]] &lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Abfrage, ob at definiert ist: {{Link2Forum|Topic=23584|Message=841269}}&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AT_zu_einem_absoluten_Datum_ausf%C3%BChren&amp;diff=38664</id>
		<title>AT zu einem absoluten Datum ausführen</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AT_zu_einem_absoluten_Datum_ausf%C3%BChren&amp;diff=38664"/>
		<updated>2023-11-03T15:30:59Z</updated>

		<summary type="html">&lt;p&gt;F Klee: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Achtung:&#039;&#039;&#039; der Befehl [[at]] kennt im Gegensatz zur Behauptung im Artikel unten durchaus Ausführungen zu einem bestimmten Datum.&lt;br /&gt;
&lt;br /&gt;
Das letztgenannte Beispiel kann z.b. mit&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define Licht_25_Januar_an at 2011-01-25T07:15:00 set Licht1 on&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Realisiert werden, siehe auch Commandrefeintrag.&lt;br /&gt;
&lt;br /&gt;
Die unten dargestellt Lösung, täglich bei Erreichen der gewünschten Uhrzeit zu prüfen ob der richtige Tag erreicht wurde, erfordert mehr Code und ist auch Perfomanceseitig ungünstiger.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
________________________________________________________________________________________________&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dem Befehl [[at]] können in FHEM Aktionen zu einem definierten Zeitpunkt ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define morgens_Licht_an at *07:15:00 set Licht1 on&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Es können nur relative und absolute Uhrzeiten, jedoch nicht ein bestimmtes Datum definiert werden.&lt;br /&gt;
&lt;br /&gt;
Allerdings kann die Ausführung an Bedingungen geknüpft sein, wie z.b. bestimmte Wochentage oder nur am Wochenende:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define morgens_Licht_Wochenende at *07:15:00 {if (!($we)) {fhem(&amp;quot;set Licht1 on&amp;quot;)} }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Auf die selbe Art kann auch auf ein Ausführungsdatum geprüft werden.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define Licht_25_Januar_an at *07:15:00 {if($year==2011 &amp;amp;amp;&amp;amp;amp; $month==1 &amp;amp;amp;&amp;amp;amp; $mday==25) {fhem(&amp;quot;set Licht1 on&amp;quot;)} }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In diesem Fall wird täglich um 7:15 Uhr geprüft, ob der 25. Januar 2011 ist und falls ja, wird die Aktion ausgeführt.&lt;br /&gt;
&lt;br /&gt;
Da dieser Fall nur einmal zutrifft, ist es sinnvoll, die Aktion nach Auslösung zu löschen, damit nicht nach dem 25. Januar 2011 weiter täglich geprüft wird, ob das Datum nochmal auftritt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;define Licht_25_Januar_an at *07:15:00 {if($year==2011 &amp;amp;amp;&amp;amp;amp; $month==1 &amp;amp;amp;&amp;amp;amp; $mday==25) \&lt;br /&gt;
{fhem (&amp;quot;set Licht1 on; delete Licht_25_Januar_an&amp;quot;} }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT2_DEVICE_-_Schritt_f%C3%BCr_Schritt&amp;diff=38661</id>
		<title>MQTT2 DEVICE - Schritt für Schritt</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT2_DEVICE_-_Schritt_f%C3%BCr_Schritt&amp;diff=38661"/>
		<updated>2023-10-28T16:20:31Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* periodicCmd */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Das Protokoll [[MQTT]] ermöglicht einen flexiblen Datenaustausch zwischen unterschiedlichsten Geräten und FHEM und insbesondere auch bidirektionale Kommunikation von und zu FHEM. Es gibt dabei jedoch nur einen geringen Grad der Standardisierung des Datenaustauschs. In der Praxis sind daher relative viele unterschiedliche Wege aufzufinden, wie die Kommunikation via MQTT in den externen Geräten und Diensten konkret umgesetzt wurde - jeder Autor einer firmware oder Software kann dies so lösen, wie es ihm beliebt, und nicht jeder beherzigt dabei den Grundsatz, dass die Kommunikation via MQTT &amp;quot;leichtgewichtig&amp;quot; sein sollte.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=Grundsätzlich stehen für viele Geräte-Typen bereits Vorlagen zur Verfügung, siehe [[AttrTemplate|attrTemplate]], die einem die wesentliche Konfigurationsarbeit abnehmen können, wie sie hier beschrieben ist. Die damit jeweils erzeugten Konfigurationen sind Einrichtungsbeispiele, die v.a. eine in sich konsistenze Zusammenstellung der verschiedenen Attribute enthalten. Es steht jedem User frei, diese Ausgangsbasis dann nach seinem Belieben zu ändern. Spätere Änderungen des verwendeten attrTemplate wirken sich nicht automatisch auf die durch frühere Versionen oder den User nachkonfigurierte Geräte aus! Da es vorkommen kann, dass sich die per MQTT übermittelten Daten und Topics ändern, wenn z.B. eine firmware aktualisiert wurden, kann dies Anpassungen am jeweiligen Template erforderlich machen. Grundsätzlich sollen die per attrTemplate für MQTT2_DEVICE verfügbaren attrTemplate jeweils für die aktuellste verfügbare stabile firmware-Version passen.}}&lt;br /&gt;
&lt;br /&gt;
Das Modul [[MQTT2_DEVICE]] bietet eine Vielzahl von Möglichkeiten, auf die verschiedensten Anforderungen einzugehen, und die ein- und ausgehenden Daten zu einem oder mehreren FHEM-[[Gerät|Gerät/en]] zusammenzufassen. Eine Übersicht häufig vorkommender MQTT-Geräte ist in [[MQTT2-Module - Praxisbeispiele]] zu finden.&lt;br /&gt;
 &lt;br /&gt;
Ziel dieses Artikels ist die Darstellung der Schritte, die sich als zweckmäßig erwiesen haben zur Einrichtung von &amp;quot;guten&amp;quot; FHEM-Geräten.&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=Viele - teils komplexe Beispiele und weitere Verweise sind im {{Link2Forum|Topic=116162|LinkText=MQTT-Workshop für MQTT2-Module}} zu finden.}}Dabei soll am Ende erreicht werden:&lt;br /&gt;
* standardisierte set- (und ggf. get-)-Kommandos, insbesondere unter Beachtung der [[DevelopmentGuidelinesReadings| Developer Guidelines für Readings]]&lt;br /&gt;
* Schließen des Informationskreises von eventuellen Kommandos bis zur Rückmeldung des (externen) Gerätes oder Dienstes (im Folgenden: &amp;quot;Gegenstelle&amp;quot;)&lt;br /&gt;
* standardisierte Reading-Namen, damit möglichst Auswertungen nicht speziell an das jeweilige Gerät angepasst werden müssen&lt;br /&gt;
* Reduzierung und Vermeidung von unnötigen Datenpunkten und Events&lt;br /&gt;
* Einrichten von regelmäßigen Abfrage-Timern (falls erforderlich!).&lt;br /&gt;
&lt;br /&gt;
== Vorbereitung ==&lt;br /&gt;
=== MQTT2_SERVER ===&lt;br /&gt;
Selbst, wenn grundsätzlich ein externer MQTT-Server IO-Device zum Einsatz kommt, ist sehr zu empfehlen, für die Beschäftigung mit einem neuen, unbekannten Device zunächst einen {{Link2CmdRef|Anker=MQTT2_SERVER|Lang=en|Label=MQTT2_SERVER}} einzurichten. Ist der Port 1883 bereits belegt, nimmt man einfach einen anderen Port, z.B. 1884: &amp;lt;code&amp;gt;define m2server MQTT2_SERVER 1884 global&amp;lt;/code&amp;gt;. Sollte die Gegenstelle tiefer strukturierte Daten im JSON-Format über verschiedene Topics als Payload übermittelt, kann es ausnahmsweise hilfreich sein, &#039;&#039;&#039;in der Einrichtungsphase&#039;&#039;&#039; auch das Attribut &amp;quot;autocreate&amp;quot; am MQTT2_SERVER auf &amp;quot;complex&amp;quot; zu stellen: &amp;lt;code&amp;gt;attr m2server autocreate complex&amp;lt;/code&amp;gt;. Weiter muss die allgemeine [[Autocreate|autocreate-Instanz]] aktiv sein. Für den Regelbetrieb und für einfache, bekannte Devices (sowie für solche, für die bereits attrTemplate vorhanden sind), wird ausdrücklich empfohlen, das &#039;&#039;autocreate&#039;&#039;-Atribut am m2server gar nicht erst zu setzten, dann wird &#039;&#039;autocreate&#039;&#039; mit der (default) Einstellung &#039;&#039;simple&#039;&#039; verwendet. Die Hintergründe sind nachfolgend im Abschnitt zu &#039;&#039;json2nameValue()&#039;&#039; zu finden.&lt;br /&gt;
&lt;br /&gt;
=== Begrifflichkeiten ===&lt;br /&gt;
Ein typisches, von &amp;quot;autocreate&amp;quot; erstelltes Gerät sieht dann z.b. (mit autocreate = simple am MQTT2_SERVER) so aus:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
 defmod MQTT2_DVES_9B01BD MQTT2_DEVICE DVES_9B01BD&lt;br /&gt;
 attr MQTT2_DVES_9B01BD readingList DVES_9B01BD:tele/DVES_9B01BD/STATE:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    DVES_9B01BD:tele/DVES_9B01BD/LWT:.* LWT\&lt;br /&gt;
    DVES_9B01BD:tele/DVES_9B01BD/UPTIME:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    DVES_9B01BD:tele/DVES_9B01BD/SENSOR:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    DVES_9B01BD:tele/DVES_9B01BD/INFO1:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    DVES_9B01BD:tele/DVES_9B01BD/INFO2:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    DVES_9B01BD:tele/DVES_9B01BD/INFO3:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    DVES_9B01BD:stat/DVES_9B01BD/RESULT:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    DVES_9B01BD:stat/DVES_9B01BD/STATE:.* { json2nameValue($EVENT) }&lt;br /&gt;
 attr MQTT2_DVES_9B01BD room MQTT2_DEVICE&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Wir unterscheiden bei jeder Zeile des readingList-Attributs vier Elemente, die ersten drei werden jeweils durch einen Doppelpunkt voneinander getrennt:&lt;br /&gt;
==== CID ====&lt;br /&gt;
Dies ist die Gerätekennung (hier: DVES_9B01BD). Diese ist auch Bestandteil des &#039;&#039;define&#039;&#039;, über diese wird ermittelt, zu welchem FHEM-Gerät via MQTT eingehende Informationen zugeordnet werden sollen. Diese Angabe ist weder im define noch in der readingList zwingend, aber in der Definition für den Hauptkanal eines Gerätes empfohlen. Es empfiehlt sich, die CID-Angaben bei eigenen readingList-Einträgen wegzulassen bzw. diese zu löschen. So kann einfacher zwischen automatisch generierten und eigenen Angaben unterschieden werden und die Geräte sind leichter zwischen verschiedenen IO-Modulen zu verschieben.&lt;br /&gt;
==== Topic ====&lt;br /&gt;
Datenpunkt, an den eine Information gesendet wird. Empfangsseitig sind dies hier z.B. &#039;&#039;tele/DVES_9B01BD/STATE&#039;&#039; oder &#039;&#039;tele/DVES_9B01BD/LWT&#039;&#039;.&lt;br /&gt;
Enthält der Topic Doppelpunkte oder Sonderzeichen, kann dies zu Problemen führen. Da der Topic intern als &#039;&#039;regex&#039;&#039; behandelt wird, kann man sich das in solchen Sonderfälle dadurch zu nutze machen, dass man z.B problematische Zeichen durch Punkte oder &amp;quot;beliebige Zeichenfolgen&amp;quot; ersetzt. So kann z.B. aus dem per autocreate erstellten &amp;lt;code&amp;gt;attr reader readingList SMLReader/Strom/sensor/1/obis/1-0:1.8.0/255/value:.* Strombezug_tariflos&amp;lt;/code&amp;gt; folgendes abgeleitet werden: &amp;lt;code&amp;gt;attr reader readingList SMLReader/Strom/sensor/1/obis/1-0.1.8.0/255/value:.* Strombezug_tariflos&amp;lt;/code&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
==== Payload ====&lt;br /&gt;
Der jeweilige Nachrichteninhalt. Da dieser nicht im vorhinein bekannt ist, wird er in der readingList typischerweise als &amp;quot;beliebige Zeichenfolge&amp;quot; (&amp;quot;.*&amp;quot;) notiert.&lt;br /&gt;
&lt;br /&gt;
==== Auswertung ====&lt;br /&gt;
Dies kann entweder direkt der Reading-Name sein, dem die Payload zugeordnet werden soll, oder ein Perl-Ausdruck. Hier wird z.B. die eingehende Information für &#039;&#039;tele/DVES_9B01BD/LWT&#039;&#039; dem Reading &#039;&#039;LWT&#039;&#039; zugeordnet, während die Informationen aus &#039;&#039;tele/DVES_9B01BD/STATE&#039;&#039; an die Funktion &#039;&#039;json2nameValue()&#039;&#039; übergeben werden. &#039;&#039;$EVENT&#039;&#039; entspricht dabei der &#039;&#039;Payload&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== defaults ===&lt;br /&gt;
Für unbekannte Gegenstellen ist zunächst immer zu empfehlen, deren &amp;quot;Grundeinstellungen&amp;quot; zu verwenden, und Anpassungen erst und nur insoweit vorzunehmen, als es für ein besseres Zusammenspiel mit FHEM sinnvoll ist. Abzuraten ist insbesondere von:&lt;br /&gt;
* Änderungen der Topics und Topic-Sturkturen (ausgenommen den Fall, dass schon andere Gegenstellen im Einsatz sind, die identische Topics verwenden)&lt;br /&gt;
* Vergabe von &#039;&#039;friendly names&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Bestandsaufnahme ==&lt;br /&gt;
=== Projektseiten finden ===&lt;br /&gt;
Viele Geräte, die das MQTT-Protokoll verwenden, haben eigene Projektseiten oder API-Beschreibungen, denen man entnehmen kann, wie mit dieser Gegenstelle Daten ausgetauscht werden können. Diese sollte man bei allen weiteren Schritten stets zur Hand haben. Dabei kann es neben der allgemeinen Beschreibung auch ein oder mehrere Detail-Seiten geben, auf denen nähere Informationen zu den spezifischen Geräte zu finden sein können.&lt;br /&gt;
&lt;br /&gt;
=== MQTT - Datenverkehr mitlesen ===&lt;br /&gt;
Sowohl MQTT2_SERVER wie MQTT2_CLIENT bieten in der Detailansicht die Option &#039;&#039;Show MQTT traffic&#039;&#039;. Darüber läßt sich der ein- und ausgehende Datenverkehr bequem mitlesen. Bei MQTT2_CLIENT wird dabei allerdings vorausgesetzt, dass er überhaupt Daten vom MQTT-Server erhält, also insbesondere die &#039;&#039;subscriptions&#039;&#039; korrekt gesetzt sind (falls per Attribut eingeschränkt).&lt;br /&gt;
 &lt;br /&gt;
=== readingList ===&lt;br /&gt;
Zunächst empfiehlt es sich, einfach die Gegenstelle neu zu starten und (ggf. über ein FileLog) aufzuzuzeichnen, was über welchen Topic wie oft an Informationen gesendet wird. Dabei kann und sollte durchaus - sofern dies möglich ist - der eine oder andere Schaltvorgang (z.B. über das Web-Interface der Gegenstelle) durchgeführt werden, sofern dies möglich ist (oder allgemeiner: möglichst viele bekannte Anweisungen   ausführen lassen). Am Ende sollte man eine möglichst vollständige Auflistung in der readingList erhalten haben.&lt;br /&gt;
Falls strukturierte Daten im JSON-Format als Payload verwendet werden, kann man diese auch zusätzlich ohne die Verarbeitung durch &#039;&#039;json2nameValue()&#039;&#039; aufzeichnen, z.B. indem man die betreffende Zeile in der readingList doppelt:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
 defmod MQTT2_DVES_9B01BD MQTT2_DEVICE DVES_9B01BD&lt;br /&gt;
 attr MQTT2_DVES_9B01BD readingList tele/DVES_9B01BD/STATE:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    tele/DVES_9B01BD/STATE:.* json_STATE\&lt;br /&gt;
    tele/DVES_9B01BD/LWT:.* LWT\&lt;br /&gt;
    [...]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So kann man mit Hilfe des betreffenden Logs ggf. auch über ein externes Tool wie mosquitto_pub MQTT-Nachrichten an FHEM generieren, ohne darauf warten zu müssen, dass diese von der Gegenstelle selbst erzeugt werden.&lt;br /&gt;
&lt;br /&gt;
=== ignoreRegexp ===&lt;br /&gt;
Manche Gegenstellen senden beim Start Konfigurationsinformationen, die allerdings nicht durch FHEM ausgewertet werden können. Die betreffenden Topics sollte man (allgemein) so in die ignoreRegexp beim MQTT2_SERVER bzw. [[MQTT2_CLIENT]] aufnehmen, dass derartige Informationen künftig gar nicht mehr an MQTT2_DEVICE weitergereicht werden. Danach kann man die betreffenden Zeilen aus der readingList löschen! Entsprechendes gilt für die hierüber generierten Readings.&lt;br /&gt;
&lt;br /&gt;
Weiter ist zu empfehlen, in diese ignoreRegexp auch die Topics aufzunehmen, über die Gegenstellen typischerweise Kommandos entgegennehmen. Dies könnte z.B. so aussehen:&lt;br /&gt;
&amp;lt;code&amp;gt;attr m2server ignoreRegexp shellies/[^/]+/command|cmnd/[^/]+/|homeassistant/.*/config|tasmota/discovery&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Viele Geräte? ===&lt;br /&gt;
==== &amp;quot;split&amp;quot; ====&lt;br /&gt;
Sind auf einer Hardware mehrere &amp;quot;Hauptschalter&amp;quot; vorhanden (z.B. ein Relay-Board), ist sehr zu empfehlen, für jeden dieser &amp;quot;Hauptschalter&amp;quot; ein eigenes FHEM-Gerät anzulegen (für logische Einheiten wie Rollladenaktoren ggf. paarweise). MQTT2_DEVICE unterstützt [[DevelopmentModuleAPI#SetExtensions|SetExtensions]] und kann daher Kommandos wie &amp;quot;on-for-timer&amp;quot; über FHEM-interne Mechanismen gut umsetzen. Dies erfordert allerdings, dass die Kommandos &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; verfügbar sein müssen.&lt;br /&gt;
Wird ein Gerät gesplittet, sollten im Gerät, das den ersten (Haupt-) Kanal repräsentiert dann alle Kommunikationsdaten gebündelt werden, Querverweise zu den weiteren Kanälen kann man über das spezielle Readings &amp;quot;associatedWith&amp;quot; herstellen.&lt;br /&gt;
&lt;br /&gt;
==== bridgeRegexp ====&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=Manche derartige Interfaces müssen zunächst entsprechend konfiguriert werden, dass die zu einem Sensor oder Aktor gehörenden Daten jeweils auf einem eigenen Topic ausgegeben werden. Insbesondere ist dies bei Tasmota (ZigBee oder Bluetooth) der Fall!}}&lt;br /&gt;
In eher seltenen Fällen kommt es vor, dass eine Gegenstelle eine Art &amp;quot;Brücke&amp;quot; zu einer Mehrzahl über diese Brücke anzusteuernder (oder zu empfangender) Aktoren oder Sensoren darstellt. In diesen Fällen kann es geboten sein, die eigentliche Gegenstelle als Hauptdevice darzustellen und für jede weitere Hardware (Sensor oder Aktor) dann ein oder mehrere Einzeldevices anzulegen. Dies kann mit Hilfe des Attributs bridgeRegexp automatisiert erfolgen, wenn sich der Sensor/Aktor aus der Topic-Struktur ablesen läßt. &lt;br /&gt;
&lt;br /&gt;
== readingList optimieren==&lt;br /&gt;
=== gute Reading-Namen - Klartext ===&lt;br /&gt;
Viele Gegenstellen senden z.B. einen online/offline-Status als &amp;quot;last will and testament&amp;quot; unter einem Topic, der mit &amp;quot;LWT&amp;quot; endet. Dieses hier sendet zwar passende Daten, aber an einen anderen Topic. In solchen Fällen man kann den von autocreate erzeugten Eintrag einfach anpassen:&lt;br /&gt;
 attr DEVICE readingList /dingtian/DEVNAME/out/lwt_availability:.* LWT&lt;br /&gt;
&lt;br /&gt;
=== Bedingte Hash-Rückgaben ===&lt;br /&gt;
Manchmal erfolgt zwar die Übergabe eines Klartextes als $EVENT - allerdings nicht in der Form, wie man das in FHEM gerne hätte. Hier als &amp;quot;0&amp;quot; oder &amp;quot;1&amp;quot;. Mit etwas Perl und der Rückgabe eines Hashes kann man so etwas beliebig umformen:&lt;br /&gt;
 attr DEVICE readingList DEVNAME/relay/0:.* { $EVENT ? {state=&amp;gt;&#039;on&#039;} : {state=&amp;gt;&#039;off&#039;} }\&lt;br /&gt;
  DEVNAME/status:.* { $EVENT ? {LWT=&amp;gt;&#039;Online&#039;} : {LWT=&amp;gt;&#039;Offline&#039;} }&lt;br /&gt;
Weiteres Beispiel: Der &amp;quot;state&amp;quot; kommt in Großschreibung und soll in Kleinschreibung geändert werden:&lt;br /&gt;
 attr DEVICE readingList switchbot/esp32_2/bot/switchbottwo/state:.* { { state =&amp;gt; lc $EVENT } }&lt;br /&gt;
&lt;br /&gt;
=== json2nameValue() ===&lt;br /&gt;
Mit Hilfe der Funktion json2nameValue() (in Verbindung mit dem attribut &#039;&#039;jsonMap&#039;&#039;) lassen sich &lt;br /&gt;
* &amp;quot;gute Reading-Namen&amp;quot; auch aus JSON-Payloads erzeugen (2. und 3. Argument)&lt;br /&gt;
* unnötige Readings vorab ausfiltern (3., 4. und 5. Argument)&lt;br /&gt;
Beispiele für die Verwendung der Argumente 1 bis 3 sind der commandref in der Erläuterung des Attributs &#039;&#039;jsonMap&#039;&#039; bei MQTT2_DEVICE zu entnehmen, die (wie die Argumente 2 und 3 optionalen) Argumente 4 und 5 entsprechen einem Positiv- bzw.- Negativ-Filter, gefiltert wird, wenn die jeweils übergebene regexp matcht (5. Argument) bzw. nicht matcht (4. Argument).&lt;br /&gt;
Wird (übergangsweise!) &#039;&#039;autocreate&#039;&#039; in der &#039;&#039;complex&#039;&#039;-Variante eingestellt, werden für alle (bisher nicht bekannten) Topics Einträge wie dieser erzeugt:&lt;br /&gt;
 attr MQTT2_DVES_9B01BD readingList tele/DVES_9B01BD/STATE:.* { json2nameValue($EVENT,&#039;STATE_&#039;,$JSONMAP) }&lt;br /&gt;
* Das zweite Argument (&#039;&#039;STATE_&#039;&#039;) ist ein &amp;quot;Präfix&amp;quot;, der allen aus dem JSON erzeugten Readings aus diesem Topic (zunächst) vorangestellt wird. Mit dessen Hilfe läßt sich rekonsturieren, aus welchem Topic die betreffende Information ursprünglich kam. In der Regel ist dies nach der Einrichtung nicht mehr wichtig, und dieses Argument kann auf &amp;quot;nichts&amp;quot; (zwei einfache Quotes) gestellt werden. Allerdings kann es in Einzelfällen sinnvoll sein, Präfixe zu verwenden, um zwischen scheinbar gleichen Werte aus unterschiedlichen Quellen zu unterscheiden. Dies kann man erst abschließend entscheiden, wenn alle von der Gegenstelle gelieferten Daten bekannt sind.&lt;br /&gt;
* Das dritte Argument &#039;&#039;$JSONMAP&#039;&#039; kann in der Regel so belassen werden. Dann kann mit Hilfe des Attributs &#039;&#039;jsonMap&#039;&#039; eine Zuordnungstabelle für Namensänderungen für die zu generierenden Readingnamen erzeugt und/oder Werte schlicht gelöscht werden. &lt;br /&gt;
&lt;br /&gt;
=== Auswertung unterbinden ===&lt;br /&gt;
Indem man einen Perl-Aufruf festlegt (geschweifte Klammern), dieser aber nichts zurückgibt, kann man bestimmte unerwünschte Readings ausfiltern. Im einfachsten Fall wäre dies:&lt;br /&gt;
  shellies/DEVNAME/temperature_f:.* {}&lt;br /&gt;
&lt;br /&gt;
Komplexer mit Auswertung der Payload:&lt;br /&gt;
  STATTOPIC/RESULT:.* { $EVENT =~ m{HSBColor...(\d+),(\d+),(\d+)} ? $2 eq ReadingsVal($NAME,&#039;saturation&#039;,&#039;unknown&#039;) ? return : { saturation=&amp;gt;$2 } : return }&lt;br /&gt;
&lt;br /&gt;
=== Perl ===&lt;br /&gt;
Wie am Beispiel der speziellen Funktion &amp;lt;code&amp;gt;json2nameValue()&amp;lt;/code&amp;gt; sowie der Hash-Rückgabe bereits dargestellt, ist es möglich, bei der Auswertung auch Perl-Funktionen einzusetzen, und diverse Variablen an diese zu übergeben. Ebenso ist es möglich, eigenen Perl-Code zu verwenden, der z.B. dann längere Zuordnungstabellen, Event-Reduzierungsmechanismen, ... enthalten kann.&lt;br /&gt;
&lt;br /&gt;
== Events optimieren==&lt;br /&gt;
Leider senden relativ viele Gegenstellen in ihren Standardeinstellungen sehr viele Daten, auch ohne dass sich etwas geändert hätte. Dies erzeugt uU. in FHEM eine erhebliche Last, so dass es dringend zu empfehlen ist, alle Maßnahmen zu prüfen, durch die dieses Verhalten unterbunden oder vermindert werden kann. Dabei sollte möglichst frühzeitig eingegriffen werden, entsprechend den folgenden Handlungsoptionen: Daten, die die firmware gar nicht erst sendet, muss FHEM nicht am Interface-Modul entgegennehmen. Daten, die direkt am Interface-Modul verworfen werden (ignoreRegexp), muss das Client-Modul nicht auswerten. Readings, die man (an einem bestimmten Device) nicht benötigt, sollte man nicht erzeugen, damit keine [[Eventhandler]] aktiv werden müssen, unveränderte, aber gewünschte Daten müssen nicht unbedingt (immer) Events erzeugen.&lt;br /&gt;
&lt;br /&gt;
=== firmware-Einstellungen ===&lt;br /&gt;
Bei manchen firmwares kann man einstellen, ob bzw. wie oft oder aus welchem Anlass Daten gesendet werden sollen. Es wird dringlich empfohlen, bei &amp;quot;gesprächigen&amp;quot; Gegenstellen zu recherchieren, ob und in welcher Weise diese derartige Möglichkeiten bietet. Falls solche nicht vorhanden sind, lohnt es sich, auf den betreffenden Projektseiten nachzufragen, ob es diese Optionen gibt - nicht selten hat sich ein firmware-Autor darüber schlicht noch keine Gedanken gemacht und baut in der nächsten Version ggf. entsprechende Optionen ein?&lt;br /&gt;
&lt;br /&gt;
=== Auswertung unterbinden ===&lt;br /&gt;
(s.o. für Topics/Readings, die gar nicht benötigt werden). Dies ist insbesondere auch zu empfehlen, wenn identische Daten zum gleichen Zeitpunkt sowohl als Klartext wie auch in einem JSON-Format übermittelt werden. In solchen Fällen ist es eher zu empfehlen, die JSON-Zweige zu abonnieren und den Rest (ggf. über einen ignoreRegexp-Eintrag) gar nicht auszuwerten.&lt;br /&gt;
Doppelungen sollten in jedem Fall vermieden werden!&lt;br /&gt;
Grundsätzlich erzeugt jeder Topic eine eigene Event-Loop, mehrere Readings-updates, die aus einer einzigen JSON-Payload abgeleitet werden, erzeugen dagegen eine gemeinsame Event-Loop. Durch solche Maßnahmen läßt sich die Systembelastung deutlich reduzieren.&lt;br /&gt;
Für Daten aus JSON-Payloads besteht darüber hinaus die Möglichkeit, diese komplett auszufiltern (siehe jsonMap weiter oben)&lt;br /&gt;
&lt;br /&gt;
=== event-on-change-reading und Co. ===&lt;br /&gt;
Da die firmwares häufig recht gesprächig programmiert sind, sollte man auf eine sinnvolle Begrenzung der durch Aktualisierungen verursachten Events besonderen Wert legen. Dazu ist in erster Linie das Attribut [[Event-on-change-reading|event-on-change-reading]] zu bearbeiten und ggf. passende threshold-Werte zu setzen, es empfiehlt sich allerdings, dabei auch zu untersuchen, inwieweit die weiteren, funktional ergänzenden Attribute zu setzen sind:&lt;br /&gt;
* [[Event-min-interval|event-min-interval]]&lt;br /&gt;
* [[Event-on-update-reading|event-on-update-reading]]&lt;br /&gt;
* timestamp-on-change-reading und&lt;br /&gt;
* [[Event-aggregator|event-aggregator]]&lt;br /&gt;
&lt;br /&gt;
=== gute Reading-Namen - userReadings ===&lt;br /&gt;
Manchmal werden per MQTT Werte übersendet, die so nicht direkt verwendbar sind. Beispiele hierfür wären:&lt;br /&gt;
* Batteriespannungen in mV (z.B. bei zigbee2mqtt)&lt;br /&gt;
* Farbwerte als Einzelreading (für die Anzeige in FHEM wird aber ein RGB-Wert benötigt)&lt;br /&gt;
In diesen Fällen kann man zwar nicht ohne weiteres den Ausgangswert umrechnen lassen, (über externe Module wie readingsChange sehr wohl), aber es ist über den Weg &amp;quot;userReadings&amp;quot; ohne weiteres möglich, passende Readings zu generieren. Dabei sollte aber zur Verringerung der Systembelastung allgemein sowie ggf. falscher Ergebnisse unbedingt darauf geachtet werden, dass diese auch mit einer &#039;&#039;trigger&#039;&#039;-Angabe versehen sind!&lt;br /&gt;
&lt;br /&gt;
== setList ==&lt;br /&gt;
&lt;br /&gt;
=== Allgemeines ===&lt;br /&gt;
Die setList ist dazu gedacht, Kommandos zu definieren, welche an die Gegenstelle gesendet werden können. &lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
In der Regel besteht jede Zeile aus folgenden, per Leerzeichen getrennten Argumenten: &lt;br /&gt;
* einem setter-Namen, ggf. ergänzt durch ein widget (s.u.)&lt;br /&gt;
* einem Topic, unter dem die Payload gesendet werden soll und&lt;br /&gt;
* der Payload.&lt;br /&gt;
Es können diverse Variablen genutzt werden, u.A. auch $EVENT und $EVTPARTx-Elemente, die der Rückgabe (setter-Name und ggf. gesetzter Wert) aus dem jeweiligen &amp;quot;widget&amp;quot; entsprechen.&lt;br /&gt;
&lt;br /&gt;
=== on und off ===&lt;br /&gt;
Damit die weitergehenden Befehle wie &#039;&#039;on-for-timer&#039;&#039; aus den [[DevelopmentModuleIntro#X_Set|SetExtensions]] funktionieren, muss ein MQTT2_DEVICE die Befehle &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; kennen. Diese sollten also - wenn es eine Art &amp;quot;Hauptschalter&amp;quot; gibt - gesondert für diesen Hauptschalter angegeben werden.&lt;br /&gt;
Hat ein Gerät mehrerer solcher &amp;quot;Hauptschalter&amp;quot;, empfiehlt es sich, für jeden dieser Schalter eine eigene MQTT2_DEVICE-Instanz anzulegen.&lt;br /&gt;
&lt;br /&gt;
==== setStateList ====&lt;br /&gt;
Gibt es in einem Device neben dem &amp;quot;Hauptschalter&amp;quot; weitere setzbare Readings (z.B. für Helligkeit und Farbe oder eine Temperatur), empfiehlt es sich v.a. dann, wenn das Gerät den Empfang (bzw. die Ausführung) von Befehlen bestätigt, nur die auf den jeweiligen Hauptschalter bezogenen &#039;&#039;set&#039;&#039;-Anweisungen in &#039;&#039;state&#039;&#039; zu schreiben. Diese (z.B. on, off und toggle) wären dann in das &#039;&#039;setStateList&#039;&#039;-Attribut aufzunehmen.&lt;br /&gt;
&lt;br /&gt;
==== setExtensionsEvent ====&lt;br /&gt;
Will man per SetExtensions realisierte laufende Timer visualisieren, empfiehlt es sich, dieses Attribut zu setzen. &lt;br /&gt;
&lt;br /&gt;
=== widgets ===&lt;br /&gt;
In der setList können prinzipiell alle in [[FHEMWEB/Widgets|Widgets]] dargestellten Eingabemöglichkeiten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
=== Perl-Kommandos ===&lt;br /&gt;
Eigentlich ist die setList dazu gedacht, eine publish-Anweisungen über das IODev abzusetzen. Da aber generisch auch Perl-Code aufgerufen werden kann, ist dies nicht zwingend, so dass zum einen aus Perl heraus auch mehrfach-Publishes ebenso möglich sind wie beliebige &amp;quot;fhem&amp;quot;-Kommandos, die gar nichts mit MQTT zu tun haben müssen (z.B. das regelmäßige Löschen von evtl. veralteten Readings am betreffenden Gerät). Wird Text zurückgegeben, wird dies als &amp;quot;&amp;lt;topic&amp;gt; &amp;lt;payload&amp;gt;&amp;quot; interpretiert und dies gepublisht, erfolgt gar keine Rückgabe, unterbleibt dies.&lt;br /&gt;
&lt;br /&gt;
== getList ==&lt;br /&gt;
Die getList ist dazu gedacht, asynchrone Abfragen an die Gegenstelle zu ermöglichen. &lt;br /&gt;
Die Syntax dabei ist&lt;br /&gt;
* einem getter-Namen, ggf. ergänzt durch ein widget (s.u.)&lt;br /&gt;
* Reading-Name, unter dem die Antwort erwartet wird&lt;br /&gt;
* einem Topic, unter dem die Payload gesendet werden soll und&lt;br /&gt;
* (optional) der Payload.&lt;br /&gt;
Auch hier können diverse Variablen genutzt werden, und/oder das ganze für die Ausführung von Perl-Code genutzt werden.&lt;br /&gt;
&lt;br /&gt;
== periodicCmd ==&lt;br /&gt;
Für regelmäßige Aufgaben (mit mind. minütlicher Frequenz) kann eine Liste von get- oder set-Kommandos angegeben werden. Dies kann für regelmäßige Abfragen ebenso genutzt werden wie z.B. zum Löschen veralteter Informationen/Readings.&lt;br /&gt;
&lt;br /&gt;
== Abschließende Aufgaben ==&lt;br /&gt;
Um das finale Aussehen des Gerätes zu beeinflussen, stehen dann noch die weiteren allgemeinen Attribute zur Verfügung, die in [[DeviceOverview anpassen]] beschrieben sind.&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:MQTT]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT2_DEVICE_-_Schritt_f%C3%BCr_Schritt&amp;diff=38660</id>
		<title>MQTT2 DEVICE - Schritt für Schritt</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT2_DEVICE_-_Schritt_f%C3%BCr_Schritt&amp;diff=38660"/>
		<updated>2023-10-28T16:03:05Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* readingList */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Das Protokoll [[MQTT]] ermöglicht einen flexiblen Datenaustausch zwischen unterschiedlichsten Geräten und FHEM und insbesondere auch bidirektionale Kommunikation von und zu FHEM. Es gibt dabei jedoch nur einen geringen Grad der Standardisierung des Datenaustauschs. In der Praxis sind daher relative viele unterschiedliche Wege aufzufinden, wie die Kommunikation via MQTT in den externen Geräten und Diensten konkret umgesetzt wurde - jeder Autor einer firmware oder Software kann dies so lösen, wie es ihm beliebt, und nicht jeder beherzigt dabei den Grundsatz, dass die Kommunikation via MQTT &amp;quot;leichtgewichtig&amp;quot; sein sollte.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=Grundsätzlich stehen für viele Geräte-Typen bereits Vorlagen zur Verfügung, siehe [[AttrTemplate|attrTemplate]], die einem die wesentliche Konfigurationsarbeit abnehmen können, wie sie hier beschrieben ist. Die damit jeweils erzeugten Konfigurationen sind Einrichtungsbeispiele, die v.a. eine in sich konsistenze Zusammenstellung der verschiedenen Attribute enthalten. Es steht jedem User frei, diese Ausgangsbasis dann nach seinem Belieben zu ändern. Spätere Änderungen des verwendeten attrTemplate wirken sich nicht automatisch auf die durch frühere Versionen oder den User nachkonfigurierte Geräte aus! Da es vorkommen kann, dass sich die per MQTT übermittelten Daten und Topics ändern, wenn z.B. eine firmware aktualisiert wurden, kann dies Anpassungen am jeweiligen Template erforderlich machen. Grundsätzlich sollen die per attrTemplate für MQTT2_DEVICE verfügbaren attrTemplate jeweils für die aktuellste verfügbare stabile firmware-Version passen.}}&lt;br /&gt;
&lt;br /&gt;
Das Modul [[MQTT2_DEVICE]] bietet eine Vielzahl von Möglichkeiten, auf die verschiedensten Anforderungen einzugehen, und die ein- und ausgehenden Daten zu einem oder mehreren FHEM-[[Gerät|Gerät/en]] zusammenzufassen. Eine Übersicht häufig vorkommender MQTT-Geräte ist in [[MQTT2-Module - Praxisbeispiele]] zu finden.&lt;br /&gt;
 &lt;br /&gt;
Ziel dieses Artikels ist die Darstellung der Schritte, die sich als zweckmäßig erwiesen haben zur Einrichtung von &amp;quot;guten&amp;quot; FHEM-Geräten.&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=Viele - teils komplexe Beispiele und weitere Verweise sind im {{Link2Forum|Topic=116162|LinkText=MQTT-Workshop für MQTT2-Module}} zu finden.}}Dabei soll am Ende erreicht werden:&lt;br /&gt;
* standardisierte set- (und ggf. get-)-Kommandos, insbesondere unter Beachtung der [[DevelopmentGuidelinesReadings| Developer Guidelines für Readings]]&lt;br /&gt;
* Schließen des Informationskreises von eventuellen Kommandos bis zur Rückmeldung des (externen) Gerätes oder Dienstes (im Folgenden: &amp;quot;Gegenstelle&amp;quot;)&lt;br /&gt;
* standardisierte Reading-Namen, damit möglichst Auswertungen nicht speziell an das jeweilige Gerät angepasst werden müssen&lt;br /&gt;
* Reduzierung und Vermeidung von unnötigen Datenpunkten und Events&lt;br /&gt;
* Einrichten von regelmäßigen Abfrage-Timern (falls erforderlich!).&lt;br /&gt;
&lt;br /&gt;
== Vorbereitung ==&lt;br /&gt;
=== MQTT2_SERVER ===&lt;br /&gt;
Selbst, wenn grundsätzlich ein externer MQTT-Server IO-Device zum Einsatz kommt, ist sehr zu empfehlen, für die Beschäftigung mit einem neuen, unbekannten Device zunächst einen {{Link2CmdRef|Anker=MQTT2_SERVER|Lang=en|Label=MQTT2_SERVER}} einzurichten. Ist der Port 1883 bereits belegt, nimmt man einfach einen anderen Port, z.B. 1884: &amp;lt;code&amp;gt;define m2server MQTT2_SERVER 1884 global&amp;lt;/code&amp;gt;. Sollte die Gegenstelle tiefer strukturierte Daten im JSON-Format über verschiedene Topics als Payload übermittelt, kann es ausnahmsweise hilfreich sein, &#039;&#039;&#039;in der Einrichtungsphase&#039;&#039;&#039; auch das Attribut &amp;quot;autocreate&amp;quot; am MQTT2_SERVER auf &amp;quot;complex&amp;quot; zu stellen: &amp;lt;code&amp;gt;attr m2server autocreate complex&amp;lt;/code&amp;gt;. Weiter muss die allgemeine [[Autocreate|autocreate-Instanz]] aktiv sein. Für den Regelbetrieb und für einfache, bekannte Devices (sowie für solche, für die bereits attrTemplate vorhanden sind), wird ausdrücklich empfohlen, das &#039;&#039;autocreate&#039;&#039;-Atribut am m2server gar nicht erst zu setzten, dann wird &#039;&#039;autocreate&#039;&#039; mit der (default) Einstellung &#039;&#039;simple&#039;&#039; verwendet. Die Hintergründe sind nachfolgend im Abschnitt zu &#039;&#039;json2nameValue()&#039;&#039; zu finden.&lt;br /&gt;
&lt;br /&gt;
=== Begrifflichkeiten ===&lt;br /&gt;
Ein typisches, von &amp;quot;autocreate&amp;quot; erstelltes Gerät sieht dann z.b. (mit autocreate = simple am MQTT2_SERVER) so aus:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
 defmod MQTT2_DVES_9B01BD MQTT2_DEVICE DVES_9B01BD&lt;br /&gt;
 attr MQTT2_DVES_9B01BD readingList DVES_9B01BD:tele/DVES_9B01BD/STATE:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    DVES_9B01BD:tele/DVES_9B01BD/LWT:.* LWT\&lt;br /&gt;
    DVES_9B01BD:tele/DVES_9B01BD/UPTIME:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    DVES_9B01BD:tele/DVES_9B01BD/SENSOR:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    DVES_9B01BD:tele/DVES_9B01BD/INFO1:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    DVES_9B01BD:tele/DVES_9B01BD/INFO2:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    DVES_9B01BD:tele/DVES_9B01BD/INFO3:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    DVES_9B01BD:stat/DVES_9B01BD/RESULT:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    DVES_9B01BD:stat/DVES_9B01BD/STATE:.* { json2nameValue($EVENT) }&lt;br /&gt;
 attr MQTT2_DVES_9B01BD room MQTT2_DEVICE&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Wir unterscheiden bei jeder Zeile des readingList-Attributs vier Elemente, die ersten drei werden jeweils durch einen Doppelpunkt voneinander getrennt:&lt;br /&gt;
==== CID ====&lt;br /&gt;
Dies ist die Gerätekennung (hier: DVES_9B01BD). Diese ist auch Bestandteil des &#039;&#039;define&#039;&#039;, über diese wird ermittelt, zu welchem FHEM-Gerät via MQTT eingehende Informationen zugeordnet werden sollen. Diese Angabe ist weder im define noch in der readingList zwingend, aber in der Definition für den Hauptkanal eines Gerätes empfohlen. Es empfiehlt sich, die CID-Angaben bei eigenen readingList-Einträgen wegzulassen bzw. diese zu löschen. So kann einfacher zwischen automatisch generierten und eigenen Angaben unterschieden werden und die Geräte sind leichter zwischen verschiedenen IO-Modulen zu verschieben.&lt;br /&gt;
==== Topic ====&lt;br /&gt;
Datenpunkt, an den eine Information gesendet wird. Empfangsseitig sind dies hier z.B. &#039;&#039;tele/DVES_9B01BD/STATE&#039;&#039; oder &#039;&#039;tele/DVES_9B01BD/LWT&#039;&#039;.&lt;br /&gt;
Enthält der Topic Doppelpunkte oder Sonderzeichen, kann dies zu Problemen führen. Da der Topic intern als &#039;&#039;regex&#039;&#039; behandelt wird, kann man sich das in solchen Sonderfälle dadurch zu nutze machen, dass man z.B problematische Zeichen durch Punkte oder &amp;quot;beliebige Zeichenfolgen&amp;quot; ersetzt. So kann z.B. aus dem per autocreate erstellten &amp;lt;code&amp;gt;attr reader readingList SMLReader/Strom/sensor/1/obis/1-0:1.8.0/255/value:.* Strombezug_tariflos&amp;lt;/code&amp;gt; folgendes abgeleitet werden: &amp;lt;code&amp;gt;attr reader readingList SMLReader/Strom/sensor/1/obis/1-0.1.8.0/255/value:.* Strombezug_tariflos&amp;lt;/code&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
==== Payload ====&lt;br /&gt;
Der jeweilige Nachrichteninhalt. Da dieser nicht im vorhinein bekannt ist, wird er in der readingList typischerweise als &amp;quot;beliebige Zeichenfolge&amp;quot; (&amp;quot;.*&amp;quot;) notiert.&lt;br /&gt;
&lt;br /&gt;
==== Auswertung ====&lt;br /&gt;
Dies kann entweder direkt der Reading-Name sein, dem die Payload zugeordnet werden soll, oder ein Perl-Ausdruck. Hier wird z.B. die eingehende Information für &#039;&#039;tele/DVES_9B01BD/LWT&#039;&#039; dem Reading &#039;&#039;LWT&#039;&#039; zugeordnet, während die Informationen aus &#039;&#039;tele/DVES_9B01BD/STATE&#039;&#039; an die Funktion &#039;&#039;json2nameValue()&#039;&#039; übergeben werden. &#039;&#039;$EVENT&#039;&#039; entspricht dabei der &#039;&#039;Payload&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== defaults ===&lt;br /&gt;
Für unbekannte Gegenstellen ist zunächst immer zu empfehlen, deren &amp;quot;Grundeinstellungen&amp;quot; zu verwenden, und Anpassungen erst und nur insoweit vorzunehmen, als es für ein besseres Zusammenspiel mit FHEM sinnvoll ist. Abzuraten ist insbesondere von:&lt;br /&gt;
* Änderungen der Topics und Topic-Sturkturen (ausgenommen den Fall, dass schon andere Gegenstellen im Einsatz sind, die identische Topics verwenden)&lt;br /&gt;
* Vergabe von &#039;&#039;friendly names&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Bestandsaufnahme ==&lt;br /&gt;
=== Projektseiten finden ===&lt;br /&gt;
Viele Geräte, die das MQTT-Protokoll verwenden, haben eigene Projektseiten oder API-Beschreibungen, denen man entnehmen kann, wie mit dieser Gegenstelle Daten ausgetauscht werden können. Diese sollte man bei allen weiteren Schritten stets zur Hand haben. Dabei kann es neben der allgemeinen Beschreibung auch ein oder mehrere Detail-Seiten geben, auf denen nähere Informationen zu den spezifischen Geräte zu finden sein können.&lt;br /&gt;
&lt;br /&gt;
=== MQTT - Datenverkehr mitlesen ===&lt;br /&gt;
Sowohl MQTT2_SERVER wie MQTT2_CLIENT bieten in der Detailansicht die Option &#039;&#039;Show MQTT traffic&#039;&#039;. Darüber läßt sich der ein- und ausgehende Datenverkehr bequem mitlesen. Bei MQTT2_CLIENT wird dabei allerdings vorausgesetzt, dass er überhaupt Daten vom MQTT-Server erhält, also insbesondere die &#039;&#039;subscriptions&#039;&#039; korrekt gesetzt sind (falls per Attribut eingeschränkt).&lt;br /&gt;
 &lt;br /&gt;
=== readingList ===&lt;br /&gt;
Zunächst empfiehlt es sich, einfach die Gegenstelle neu zu starten und (ggf. über ein FileLog) aufzuzuzeichnen, was über welchen Topic wie oft an Informationen gesendet wird. Dabei kann und sollte durchaus - sofern dies möglich ist - der eine oder andere Schaltvorgang (z.B. über das Web-Interface der Gegenstelle) durchgeführt werden, sofern dies möglich ist (oder allgemeiner: möglichst viele bekannte Anweisungen   ausführen lassen). Am Ende sollte man eine möglichst vollständige Auflistung in der readingList erhalten haben.&lt;br /&gt;
Falls strukturierte Daten im JSON-Format als Payload verwendet werden, kann man diese auch zusätzlich ohne die Verarbeitung durch &#039;&#039;json2nameValue()&#039;&#039; aufzeichnen, z.B. indem man die betreffende Zeile in der readingList doppelt:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
 defmod MQTT2_DVES_9B01BD MQTT2_DEVICE DVES_9B01BD&lt;br /&gt;
 attr MQTT2_DVES_9B01BD readingList tele/DVES_9B01BD/STATE:.* { json2nameValue($EVENT) }\&lt;br /&gt;
    tele/DVES_9B01BD/STATE:.* json_STATE\&lt;br /&gt;
    tele/DVES_9B01BD/LWT:.* LWT\&lt;br /&gt;
    [...]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So kann man mit Hilfe des betreffenden Logs ggf. auch über ein externes Tool wie mosquitto_pub MQTT-Nachrichten an FHEM generieren, ohne darauf warten zu müssen, dass diese von der Gegenstelle selbst erzeugt werden.&lt;br /&gt;
&lt;br /&gt;
=== ignoreRegexp ===&lt;br /&gt;
Manche Gegenstellen senden beim Start Konfigurationsinformationen, die allerdings nicht durch FHEM ausgewertet werden können. Die betreffenden Topics sollte man (allgemein) so in die ignoreRegexp beim MQTT2_SERVER bzw. [[MQTT2_CLIENT]] aufnehmen, dass derartige Informationen künftig gar nicht mehr an MQTT2_DEVICE weitergereicht werden. Danach kann man die betreffenden Zeilen aus der readingList löschen! Entsprechendes gilt für die hierüber generierten Readings.&lt;br /&gt;
&lt;br /&gt;
Weiter ist zu empfehlen, in diese ignoreRegexp auch die Topics aufzunehmen, über die Gegenstellen typischerweise Kommandos entgegennehmen. Dies könnte z.B. so aussehen:&lt;br /&gt;
&amp;lt;code&amp;gt;attr m2server ignoreRegexp shellies/[^/]+/command|cmnd/[^/]+/|homeassistant/.*/config|tasmota/discovery&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Viele Geräte? ===&lt;br /&gt;
==== &amp;quot;split&amp;quot; ====&lt;br /&gt;
Sind auf einer Hardware mehrere &amp;quot;Hauptschalter&amp;quot; vorhanden (z.B. ein Relay-Board), ist sehr zu empfehlen, für jeden dieser &amp;quot;Hauptschalter&amp;quot; ein eigenes FHEM-Gerät anzulegen (für logische Einheiten wie Rollladenaktoren ggf. paarweise). MQTT2_DEVICE unterstützt [[DevelopmentModuleAPI#SetExtensions|SetExtensions]] und kann daher Kommandos wie &amp;quot;on-for-timer&amp;quot; über FHEM-interne Mechanismen gut umsetzen. Dies erfordert allerdings, dass die Kommandos &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; verfügbar sein müssen.&lt;br /&gt;
Wird ein Gerät gesplittet, sollten im Gerät, das den ersten (Haupt-) Kanal repräsentiert dann alle Kommunikationsdaten gebündelt werden, Querverweise zu den weiteren Kanälen kann man über das spezielle Readings &amp;quot;associatedWith&amp;quot; herstellen.&lt;br /&gt;
&lt;br /&gt;
==== bridgeRegexp ====&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=Manche derartige Interfaces müssen zunächst entsprechend konfiguriert werden, dass die zu einem Sensor oder Aktor gehörenden Daten jeweils auf einem eigenen Topic ausgegeben werden. Insbesondere ist dies bei Tasmota (ZigBee oder Bluetooth) der Fall!}}&lt;br /&gt;
In eher seltenen Fällen kommt es vor, dass eine Gegenstelle eine Art &amp;quot;Brücke&amp;quot; zu einer Mehrzahl über diese Brücke anzusteuernder (oder zu empfangender) Aktoren oder Sensoren darstellt. In diesen Fällen kann es geboten sein, die eigentliche Gegenstelle als Hauptdevice darzustellen und für jede weitere Hardware (Sensor oder Aktor) dann ein oder mehrere Einzeldevices anzulegen. Dies kann mit Hilfe des Attributs bridgeRegexp automatisiert erfolgen, wenn sich der Sensor/Aktor aus der Topic-Struktur ablesen läßt. &lt;br /&gt;
&lt;br /&gt;
== readingList optimieren==&lt;br /&gt;
=== gute Reading-Namen - Klartext ===&lt;br /&gt;
Viele Gegenstellen senden z.B. einen online/offline-Status als &amp;quot;last will and testament&amp;quot; unter einem Topic, der mit &amp;quot;LWT&amp;quot; endet. Dieses hier sendet zwar passende Daten, aber an einen anderen Topic. In solchen Fällen man kann den von autocreate erzeugten Eintrag einfach anpassen:&lt;br /&gt;
 attr DEVICE readingList /dingtian/DEVNAME/out/lwt_availability:.* LWT&lt;br /&gt;
&lt;br /&gt;
=== Bedingte Hash-Rückgaben ===&lt;br /&gt;
Manchmal erfolgt zwar die Übergabe eines Klartextes als $EVENT - allerdings nicht in der Form, wie man das in FHEM gerne hätte. Hier als &amp;quot;0&amp;quot; oder &amp;quot;1&amp;quot;. Mit etwas Perl und der Rückgabe eines Hashes kann man so etwas beliebig umformen:&lt;br /&gt;
 attr DEVICE readingList DEVNAME/relay/0:.* { $EVENT ? {state=&amp;gt;&#039;on&#039;} : {state=&amp;gt;&#039;off&#039;} }\&lt;br /&gt;
  DEVNAME/status:.* { $EVENT ? {LWT=&amp;gt;&#039;Online&#039;} : {LWT=&amp;gt;&#039;Offline&#039;} }&lt;br /&gt;
Weiteres Beispiel: Der &amp;quot;state&amp;quot; kommt in Großschreibung und soll in Kleinschreibung geändert werden:&lt;br /&gt;
 attr DEVICE readingList switchbot/esp32_2/bot/switchbottwo/state:.* { { state =&amp;gt; lc $EVENT } }&lt;br /&gt;
&lt;br /&gt;
=== json2nameValue() ===&lt;br /&gt;
Mit Hilfe der Funktion json2nameValue() (in Verbindung mit dem attribut &#039;&#039;jsonMap&#039;&#039;) lassen sich &lt;br /&gt;
* &amp;quot;gute Reading-Namen&amp;quot; auch aus JSON-Payloads erzeugen (2. und 3. Argument)&lt;br /&gt;
* unnötige Readings vorab ausfiltern (3., 4. und 5. Argument)&lt;br /&gt;
Beispiele für die Verwendung der Argumente 1 bis 3 sind der commandref in der Erläuterung des Attributs &#039;&#039;jsonMap&#039;&#039; bei MQTT2_DEVICE zu entnehmen, die (wie die Argumente 2 und 3 optionalen) Argumente 4 und 5 entsprechen einem Positiv- bzw.- Negativ-Filter, gefiltert wird, wenn die jeweils übergebene regexp matcht (5. Argument) bzw. nicht matcht (4. Argument).&lt;br /&gt;
Wird (übergangsweise!) &#039;&#039;autocreate&#039;&#039; in der &#039;&#039;complex&#039;&#039;-Variante eingestellt, werden für alle (bisher nicht bekannten) Topics Einträge wie dieser erzeugt:&lt;br /&gt;
 attr MQTT2_DVES_9B01BD readingList tele/DVES_9B01BD/STATE:.* { json2nameValue($EVENT,&#039;STATE_&#039;,$JSONMAP) }&lt;br /&gt;
* Das zweite Argument (&#039;&#039;STATE_&#039;&#039;) ist ein &amp;quot;Präfix&amp;quot;, der allen aus dem JSON erzeugten Readings aus diesem Topic (zunächst) vorangestellt wird. Mit dessen Hilfe läßt sich rekonsturieren, aus welchem Topic die betreffende Information ursprünglich kam. In der Regel ist dies nach der Einrichtung nicht mehr wichtig, und dieses Argument kann auf &amp;quot;nichts&amp;quot; (zwei einfache Quotes) gestellt werden. Allerdings kann es in Einzelfällen sinnvoll sein, Präfixe zu verwenden, um zwischen scheinbar gleichen Werte aus unterschiedlichen Quellen zu unterscheiden. Dies kann man erst abschließend entscheiden, wenn alle von der Gegenstelle gelieferten Daten bekannt sind.&lt;br /&gt;
* Das dritte Argument &#039;&#039;$JSONMAP&#039;&#039; kann in der Regel so belassen werden. Dann kann mit Hilfe des Attributs &#039;&#039;jsonMap&#039;&#039; eine Zuordnungstabelle für Namensänderungen für die zu generierenden Readingnamen erzeugt und/oder Werte schlicht gelöscht werden. &lt;br /&gt;
&lt;br /&gt;
=== Auswertung unterbinden ===&lt;br /&gt;
Indem man einen Perl-Aufruf festlegt (geschweifte Klammern), dieser aber nichts zurückgibt, kann man bestimmte unerwünschte Readings ausfiltern. Im einfachsten Fall wäre dies:&lt;br /&gt;
  shellies/DEVNAME/temperature_f:.* {}&lt;br /&gt;
&lt;br /&gt;
Komplexer mit Auswertung der Payload:&lt;br /&gt;
  STATTOPIC/RESULT:.* { $EVENT =~ m{HSBColor...(\d+),(\d+),(\d+)} ? $2 eq ReadingsVal($NAME,&#039;saturation&#039;,&#039;unknown&#039;) ? return : { saturation=&amp;gt;$2 } : return }&lt;br /&gt;
&lt;br /&gt;
=== Perl ===&lt;br /&gt;
Wie am Beispiel der speziellen Funktion &amp;lt;code&amp;gt;json2nameValue()&amp;lt;/code&amp;gt; sowie der Hash-Rückgabe bereits dargestellt, ist es möglich, bei der Auswertung auch Perl-Funktionen einzusetzen, und diverse Variablen an diese zu übergeben. Ebenso ist es möglich, eigenen Perl-Code zu verwenden, der z.B. dann längere Zuordnungstabellen, Event-Reduzierungsmechanismen, ... enthalten kann.&lt;br /&gt;
&lt;br /&gt;
== Events optimieren==&lt;br /&gt;
Leider senden relativ viele Gegenstellen in ihren Standardeinstellungen sehr viele Daten, auch ohne dass sich etwas geändert hätte. Dies erzeugt uU. in FHEM eine erhebliche Last, so dass es dringend zu empfehlen ist, alle Maßnahmen zu prüfen, durch die dieses Verhalten unterbunden oder vermindert werden kann. Dabei sollte möglichst frühzeitig eingegriffen werden, entsprechend den folgenden Handlungsoptionen: Daten, die die firmware gar nicht erst sendet, muss FHEM nicht am Interface-Modul entgegennehmen. Daten, die direkt am Interface-Modul verworfen werden (ignoreRegexp), muss das Client-Modul nicht auswerten. Readings, die man (an einem bestimmten Device) nicht benötigt, sollte man nicht erzeugen, damit keine [[Eventhandler]] aktiv werden müssen, unveränderte, aber gewünschte Daten müssen nicht unbedingt (immer) Events erzeugen.&lt;br /&gt;
&lt;br /&gt;
=== firmware-Einstellungen ===&lt;br /&gt;
Bei manchen firmwares kann man einstellen, ob bzw. wie oft oder aus welchem Anlass Daten gesendet werden sollen. Es wird dringlich empfohlen, bei &amp;quot;gesprächigen&amp;quot; Gegenstellen zu recherchieren, ob und in welcher Weise diese derartige Möglichkeiten bietet. Falls solche nicht vorhanden sind, lohnt es sich, auf den betreffenden Projektseiten nachzufragen, ob es diese Optionen gibt - nicht selten hat sich ein firmware-Autor darüber schlicht noch keine Gedanken gemacht und baut in der nächsten Version ggf. entsprechende Optionen ein?&lt;br /&gt;
&lt;br /&gt;
=== Auswertung unterbinden ===&lt;br /&gt;
(s.o. für Topics/Readings, die gar nicht benötigt werden). Dies ist insbesondere auch zu empfehlen, wenn identische Daten zum gleichen Zeitpunkt sowohl als Klartext wie auch in einem JSON-Format übermittelt werden. In solchen Fällen ist es eher zu empfehlen, die JSON-Zweige zu abonnieren und den Rest (ggf. über einen ignoreRegexp-Eintrag) gar nicht auszuwerten.&lt;br /&gt;
Doppelungen sollten in jedem Fall vermieden werden!&lt;br /&gt;
Grundsätzlich erzeugt jeder Topic eine eigene Event-Loop, mehrere Readings-updates, die aus einer einzigen JSON-Payload abgeleitet werden, erzeugen dagegen eine gemeinsame Event-Loop. Durch solche Maßnahmen läßt sich die Systembelastung deutlich reduzieren.&lt;br /&gt;
Für Daten aus JSON-Payloads besteht darüber hinaus die Möglichkeit, diese komplett auszufiltern (siehe jsonMap weiter oben)&lt;br /&gt;
&lt;br /&gt;
=== event-on-change-reading und Co. ===&lt;br /&gt;
Da die firmwares häufig recht gesprächig programmiert sind, sollte man auf eine sinnvolle Begrenzung der durch Aktualisierungen verursachten Events besonderen Wert legen. Dazu ist in erster Linie das Attribut [[Event-on-change-reading|event-on-change-reading]] zu bearbeiten und ggf. passende threshold-Werte zu setzen, es empfiehlt sich allerdings, dabei auch zu untersuchen, inwieweit die weiteren, funktional ergänzenden Attribute zu setzen sind:&lt;br /&gt;
* [[Event-min-interval|event-min-interval]]&lt;br /&gt;
* [[Event-on-update-reading|event-on-update-reading]]&lt;br /&gt;
* timestamp-on-change-reading und&lt;br /&gt;
* [[Event-aggregator|event-aggregator]]&lt;br /&gt;
&lt;br /&gt;
=== gute Reading-Namen - userReadings ===&lt;br /&gt;
Manchmal werden per MQTT Werte übersendet, die so nicht direkt verwendbar sind. Beispiele hierfür wären:&lt;br /&gt;
* Batteriespannungen in mV (z.B. bei zigbee2mqtt)&lt;br /&gt;
* Farbwerte als Einzelreading (für die Anzeige in FHEM wird aber ein RGB-Wert benötigt)&lt;br /&gt;
In diesen Fällen kann man zwar nicht ohne weiteres den Ausgangswert umrechnen lassen, (über externe Module wie readingsChange sehr wohl), aber es ist über den Weg &amp;quot;userReadings&amp;quot; ohne weiteres möglich, passende Readings zu generieren. Dabei sollte aber zur Verringerung der Systembelastung allgemein sowie ggf. falscher Ergebnisse unbedingt darauf geachtet werden, dass diese auch mit einer &#039;&#039;trigger&#039;&#039;-Angabe versehen sind!&lt;br /&gt;
&lt;br /&gt;
== setList ==&lt;br /&gt;
&lt;br /&gt;
=== Allgemeines ===&lt;br /&gt;
Die setList ist dazu gedacht, Kommandos zu definieren, welche an die Gegenstelle gesendet werden können. &lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
In der Regel besteht jede Zeile aus folgenden, per Leerzeichen getrennten Argumenten: &lt;br /&gt;
* einem setter-Namen, ggf. ergänzt durch ein widget (s.u.)&lt;br /&gt;
* einem Topic, unter dem die Payload gesendet werden soll und&lt;br /&gt;
* der Payload.&lt;br /&gt;
Es können diverse Variablen genutzt werden, u.A. auch $EVENT und $EVTPARTx-Elemente, die der Rückgabe (setter-Name und ggf. gesetzter Wert) aus dem jeweiligen &amp;quot;widget&amp;quot; entsprechen.&lt;br /&gt;
&lt;br /&gt;
=== on und off ===&lt;br /&gt;
Damit die weitergehenden Befehle wie &#039;&#039;on-for-timer&#039;&#039; aus den [[DevelopmentModuleIntro#X_Set|SetExtensions]] funktionieren, muss ein MQTT2_DEVICE die Befehle &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; kennen. Diese sollten also - wenn es eine Art &amp;quot;Hauptschalter&amp;quot; gibt - gesondert für diesen Hauptschalter angegeben werden.&lt;br /&gt;
Hat ein Gerät mehrerer solcher &amp;quot;Hauptschalter&amp;quot;, empfiehlt es sich, für jeden dieser Schalter eine eigene MQTT2_DEVICE-Instanz anzulegen.&lt;br /&gt;
&lt;br /&gt;
==== setStateList ====&lt;br /&gt;
Gibt es in einem Device neben dem &amp;quot;Hauptschalter&amp;quot; weitere setzbare Readings (z.B. für Helligkeit und Farbe oder eine Temperatur), empfiehlt es sich v.a. dann, wenn das Gerät den Empfang (bzw. die Ausführung) von Befehlen bestätigt, nur die auf den jeweiligen Hauptschalter bezogenen &#039;&#039;set&#039;&#039;-Anweisungen in &#039;&#039;state&#039;&#039; zu schreiben. Diese (z.B. on, off und toggle) wären dann in das &#039;&#039;setStateList&#039;&#039;-Attribut aufzunehmen.&lt;br /&gt;
&lt;br /&gt;
==== setExtensionsEvent ====&lt;br /&gt;
Will man per SetExtensions realisierte laufende Timer visualisieren, empfiehlt es sich, dieses Attribut zu setzen. &lt;br /&gt;
&lt;br /&gt;
=== widgets ===&lt;br /&gt;
In der setList können prinzipiell alle in [[FHEMWEB/Widgets|Widgets]] dargestellten Eingabemöglichkeiten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
=== Perl-Kommandos ===&lt;br /&gt;
Eigentlich ist die setList dazu gedacht, eine publish-Anweisungen über das IODev abzusetzen. Da aber generisch auch Perl-Code aufgerufen werden kann, ist dies nicht zwingend, so dass zum einen aus Perl heraus auch mehrfach-Publishes ebenso möglich sind wie beliebige &amp;quot;fhem&amp;quot;-Kommandos, die gar nichts mit MQTT zu tun haben müssen (z.B. das regelmäßige Löschen von evtl. veralteten Readings am betreffenden Gerät). Wird Text zurückgegeben, wird dies als &amp;quot;&amp;lt;topic&amp;gt; &amp;lt;payload&amp;gt;&amp;quot; interpretiert und dies gepublisht, erfolgt gar keine Rückgabe, unterbleibt dies.&lt;br /&gt;
&lt;br /&gt;
== getList ==&lt;br /&gt;
Die getList ist dazu gedacht, asynchrone Abfragen an die Gegenstelle zu ermöglichen. &lt;br /&gt;
Die Syntax dabei ist&lt;br /&gt;
* einem getter-Namen, ggf. ergänzt durch ein widget (s.u.)&lt;br /&gt;
* Reading-Name, unter dem die Antwort erwartet wird&lt;br /&gt;
* einem Topic, unter dem die Payload gesendet werden soll und&lt;br /&gt;
* (optional) der Payload.&lt;br /&gt;
Auch hier können diverse Variablen genutzt werden, und/oder das ganze für die Ausführung von Perl-Code genutzt werden.&lt;br /&gt;
&lt;br /&gt;
== periodicCmd ==&lt;br /&gt;
Für regelmäßige Aufgaben (mit mind. minütlicher Frequenz) kann eine Liste con get- oder set-Kommandos angegeben werden. Dies kann für regelmäßige Abfragen ebenso genutzt werden wie z.B. zum Löschen veralteter Informationen/Readings. &lt;br /&gt;
&lt;br /&gt;
== Abschließende Aufgaben ==&lt;br /&gt;
Um das finale Aussehen des Gerätes zu beeinflussen, stehen dann noch die weiteren allgemeinen Attribute zur Verfügung, die in [[DeviceOverview anpassen]] beschrieben sind.&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:MQTT]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SetList&amp;diff=38659</id>
		<title>SetList</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SetList&amp;diff=38659"/>
		<updated>2023-10-28T13:10:23Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* Einschränkungen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{SEITENTITEL:setList}}  &amp;lt;!-- da richtige Schreibweise kleinen Anfangsbuchstaben hat --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Infobox Attribut sinnvoll? --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Attribut [[setList]] dient dazu, bei generischen Devices die Liste der möglichen set Kommandos zu spezifizieren. &lt;br /&gt;
&lt;br /&gt;
{{Todo|Bitte analog zu [[eventMap]] mit Inhalt füllen.}}&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
Das &#039;&#039;setList&#039;&#039; Attribut wird in der folgenden Weise spezifiziert:&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;attr &amp;lt;device&amp;gt; setList &amp;lt;Reading1&amp;gt;:⟨&amp;lt;Modifier1&amp;gt;,⟩&amp;lt;Value1&amp;gt;,&amp;lt;Value2&amp;gt;,&amp;lt;...&amp;gt; &amp;lt;Reading2&amp;gt;:⟨&amp;lt;Modifier2&amp;gt;,⟩&amp;lt;Value1&amp;gt;,&amp;lt;Value2&amp;gt;,&amp;lt;...&amp;gt; ...&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Es ist auch möglich, zur Verbesserung der Übersichtlichkeit und Lesbarkeit, das setList Attribut mehrzeilig zu formulieren.&lt;br /&gt;
&lt;br /&gt;
== Einschränkungen == &lt;br /&gt;
Dieses Attribut existiert nur bei [[DOIF]]-, [[dummy]]-, [[MSwitch]]- und [[readingsProxy]]-Devices.&lt;br /&gt;
[[MQTT2 DEVICE]] nutzt setList um Änderungen an State bzw. Readings an den Server zu übermitteln, der diese dann an die eigentlichen Geräte weitergibt oder dort vorhält. Für jedes Reading ist eine eigene Zeile erforderlich, das Aussehen in der Detailansicht des Geräts kann direkt über eine entsprechende widget-Definition vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
== Beispiele ==&lt;br /&gt;
&lt;br /&gt;
In diesem ersten Beispiel wird der &#039;&#039;state&#039;&#039; als Schiebebalken (slider) angezeigt. Wobei die erste Zahl den niedrigsten möglichen Wert angibt. Die zweite den Wert, um den jeweils erhöht wird. Und die dritte den maximal möglichen Wert.&lt;br /&gt;
 define Raumtemperatur dummy&lt;br /&gt;
 attr Raumtemperatur setList :slider,10,0.5,30&lt;br /&gt;
&lt;br /&gt;
Hier wird für den &#039;&#039;state&#039;&#039; eine Uhrzeit angegeben. Die kann mit zwei Schiebebalken (einer für die Stunden, einer für die Minuten) gesetzt werden.&lt;br /&gt;
 define Wecker_Uhrzeit dummy&lt;br /&gt;
 attr Wecker_Uhrzeit setList :time&lt;br /&gt;
&lt;br /&gt;
Möchte man Farbwerte einstellen, kann man &#039;&#039;colorpicker&#039;&#039; verwenden. Damit kann dann auf einer Palette eine Farbe gewählt werden.&lt;br /&gt;
 define Farbe dummy&lt;br /&gt;
 attr Farbe setList :colorpicker&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 define Wecker_Uhrzeit dummy&lt;br /&gt;
 attr Wecker_Uhrzeit setList state:AUS,05:00,05:15,05:30,05:45,06:00,06:15,06:30,06:35,06:40,06:45,06:50,06:55,07:00,07:05,07:10,07:15,07:20,07:25,07:30,07:45,08:00,08:15,08:30,08:45,09:00,09:15,09:30,09:45,10:00,10:15,10:30,10:45,11:00,11:15,11:30,11:45,12:00,12:15,12:30,12:45,13:00,13:15,13:30,13:45,14:00,14:15,14:30,14:45,15:00,15:15,15:30,15:45,16:00,16:15,16:30,16:45,17:00,17:15,17:30,17:45,18:00,18:15,18:30,18:45,19:00,19:15,19:30,19:45,20:00,20:15,20:30,20:45,21:00,21:15,21:30,21:45,22:00,22:15,22:30,22:45,23:00,23:15,23:30,23:45,00:00,00:15,00:30,00:45,01:00,01:15,01:30,01:45,02:00,02:15,02:30,02:45,03:00,03:15,03:30,03:45,04:00,04:15,04:30,04:45&lt;br /&gt;
 attr Wecker_Uhrzeit readingList state&lt;br /&gt;
 attr Wecker_Uhrzeit webCmd state&lt;br /&gt;
&lt;br /&gt;
 define Beschattung_auto dummy&lt;br /&gt;
 attr Beschattung_auto setList state:aktiv,passiv&lt;br /&gt;
 attr Beschattung_auto readingList state&lt;br /&gt;
 attr Beschattung_auto webCmd state&lt;br /&gt;
&lt;br /&gt;
 define Heizungsmodus dummy&lt;br /&gt;
 attr Heizungsmodus setList state:auto,FHEM,Frostschutz,AUS&lt;br /&gt;
 attr Heizungsmodus readingList state&lt;br /&gt;
 attr Heizungsmodus webCmd state&lt;br /&gt;
&lt;br /&gt;
 define TV_ProgrammKanal dummy&lt;br /&gt;
 attr TV_ProgrammKanal setList ARD_Ch ZDF_Ch HR_Ch RTL_Ch Sat1_Ch VOX_Ch Pro7_Ch Kabel1_Ch COMEDYCENTRAL_Ch DREISAT_Ch ARTE_Ch EINSPLUS_Ch EINSFESTIVAL_Ch ZDFNEO_Ch NDR_Ch MDR_Ch BR_Ch RBB_Ch SWR_Ch WDR_Ch RTL2_Ch SUPERRTL_Ch SPORT1_Ch EUROSPORT_Ch DMAX_Ch N24_Ch NTV_Ch RTLNITRO_Ch SAT1GOLD_Ch SIXX_Ch TELE5_Ch&lt;br /&gt;
 attr TV_ProgrammKanal readingList state&lt;br /&gt;
&lt;br /&gt;
 define benzinpreis dummy&lt;br /&gt;
 attr benzinpreis readingList SuperE5_2 SuperPlus_2&lt;br /&gt;
 attr benzinpreis setList SuperE5_2:slider,140,1,200 SuperPlus_2:slider,140,1,200&lt;br /&gt;
 attr benzinpreis stateFormat SuperE5, SuperPlus&lt;br /&gt;
 attr benzinpreis userReadings SuperE5 {(ReadingsVal(&amp;quot;oil&amp;quot;,&amp;quot;SuperE5_2&amp;quot;,0) / 100 )}, SuperPlus {(ReadingsVal(&amp;quot;oil&amp;quot;,&amp;quot;SuperPlus_2&amp;quot;,0) / 100 )}&lt;br /&gt;
 attr benzinpreis webCmd SuperE5_2:SuperPlus_2&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Ausführliche Beschreibung (mit Beispielen) zu [[eventMap]], [[devStateIcon]], setList und [[webCmd]] in {{Link2Forum|Topic=12080|LinkText=diesem Forenthread}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Attribut (allgemeingültig)]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SetList&amp;diff=38658</id>
		<title>SetList</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SetList&amp;diff=38658"/>
		<updated>2023-10-28T13:03:50Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* Syntax */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{SEITENTITEL:setList}}  &amp;lt;!-- da richtige Schreibweise kleinen Anfangsbuchstaben hat --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Infobox Attribut sinnvoll? --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Attribut [[setList]] dient dazu, bei generischen Devices die Liste der möglichen set Kommandos zu spezifizieren. &lt;br /&gt;
&lt;br /&gt;
{{Todo|Bitte analog zu [[eventMap]] mit Inhalt füllen.}}&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
Das &#039;&#039;setList&#039;&#039; Attribut wird in der folgenden Weise spezifiziert:&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;attr &amp;lt;device&amp;gt; setList &amp;lt;Reading1&amp;gt;:⟨&amp;lt;Modifier1&amp;gt;,⟩&amp;lt;Value1&amp;gt;,&amp;lt;Value2&amp;gt;,&amp;lt;...&amp;gt; &amp;lt;Reading2&amp;gt;:⟨&amp;lt;Modifier2&amp;gt;,⟩&amp;lt;Value1&amp;gt;,&amp;lt;Value2&amp;gt;,&amp;lt;...&amp;gt; ...&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Es ist auch möglich, zur Verbesserung der Übersichtlichkeit und Lesbarkeit, das setList Attribut mehrzeilig zu formulieren.&lt;br /&gt;
&lt;br /&gt;
== Einschränkungen == &lt;br /&gt;
Dieses Attribut existiert nur bei [[DOIF]]-, [[dummy]]-, [[MSwitch]]- und [[readingsProxy]]-Devices.&lt;br /&gt;
&lt;br /&gt;
== Beispiele ==&lt;br /&gt;
&lt;br /&gt;
In diesem ersten Beispiel wird der &#039;&#039;state&#039;&#039; als Schiebebalken (slider) angezeigt. Wobei die erste Zahl den niedrigsten möglichen Wert angibt. Die zweite den Wert, um den jeweils erhöht wird. Und die dritte den maximal möglichen Wert.&lt;br /&gt;
 define Raumtemperatur dummy&lt;br /&gt;
 attr Raumtemperatur setList :slider,10,0.5,30&lt;br /&gt;
&lt;br /&gt;
Hier wird für den &#039;&#039;state&#039;&#039; eine Uhrzeit angegeben. Die kann mit zwei Schiebebalken (einer für die Stunden, einer für die Minuten) gesetzt werden.&lt;br /&gt;
 define Wecker_Uhrzeit dummy&lt;br /&gt;
 attr Wecker_Uhrzeit setList :time&lt;br /&gt;
&lt;br /&gt;
Möchte man Farbwerte einstellen, kann man &#039;&#039;colorpicker&#039;&#039; verwenden. Damit kann dann auf einer Palette eine Farbe gewählt werden.&lt;br /&gt;
 define Farbe dummy&lt;br /&gt;
 attr Farbe setList :colorpicker&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 define Wecker_Uhrzeit dummy&lt;br /&gt;
 attr Wecker_Uhrzeit setList state:AUS,05:00,05:15,05:30,05:45,06:00,06:15,06:30,06:35,06:40,06:45,06:50,06:55,07:00,07:05,07:10,07:15,07:20,07:25,07:30,07:45,08:00,08:15,08:30,08:45,09:00,09:15,09:30,09:45,10:00,10:15,10:30,10:45,11:00,11:15,11:30,11:45,12:00,12:15,12:30,12:45,13:00,13:15,13:30,13:45,14:00,14:15,14:30,14:45,15:00,15:15,15:30,15:45,16:00,16:15,16:30,16:45,17:00,17:15,17:30,17:45,18:00,18:15,18:30,18:45,19:00,19:15,19:30,19:45,20:00,20:15,20:30,20:45,21:00,21:15,21:30,21:45,22:00,22:15,22:30,22:45,23:00,23:15,23:30,23:45,00:00,00:15,00:30,00:45,01:00,01:15,01:30,01:45,02:00,02:15,02:30,02:45,03:00,03:15,03:30,03:45,04:00,04:15,04:30,04:45&lt;br /&gt;
 attr Wecker_Uhrzeit readingList state&lt;br /&gt;
 attr Wecker_Uhrzeit webCmd state&lt;br /&gt;
&lt;br /&gt;
 define Beschattung_auto dummy&lt;br /&gt;
 attr Beschattung_auto setList state:aktiv,passiv&lt;br /&gt;
 attr Beschattung_auto readingList state&lt;br /&gt;
 attr Beschattung_auto webCmd state&lt;br /&gt;
&lt;br /&gt;
 define Heizungsmodus dummy&lt;br /&gt;
 attr Heizungsmodus setList state:auto,FHEM,Frostschutz,AUS&lt;br /&gt;
 attr Heizungsmodus readingList state&lt;br /&gt;
 attr Heizungsmodus webCmd state&lt;br /&gt;
&lt;br /&gt;
 define TV_ProgrammKanal dummy&lt;br /&gt;
 attr TV_ProgrammKanal setList ARD_Ch ZDF_Ch HR_Ch RTL_Ch Sat1_Ch VOX_Ch Pro7_Ch Kabel1_Ch COMEDYCENTRAL_Ch DREISAT_Ch ARTE_Ch EINSPLUS_Ch EINSFESTIVAL_Ch ZDFNEO_Ch NDR_Ch MDR_Ch BR_Ch RBB_Ch SWR_Ch WDR_Ch RTL2_Ch SUPERRTL_Ch SPORT1_Ch EUROSPORT_Ch DMAX_Ch N24_Ch NTV_Ch RTLNITRO_Ch SAT1GOLD_Ch SIXX_Ch TELE5_Ch&lt;br /&gt;
 attr TV_ProgrammKanal readingList state&lt;br /&gt;
&lt;br /&gt;
 define benzinpreis dummy&lt;br /&gt;
 attr benzinpreis readingList SuperE5_2 SuperPlus_2&lt;br /&gt;
 attr benzinpreis setList SuperE5_2:slider,140,1,200 SuperPlus_2:slider,140,1,200&lt;br /&gt;
 attr benzinpreis stateFormat SuperE5, SuperPlus&lt;br /&gt;
 attr benzinpreis userReadings SuperE5 {(ReadingsVal(&amp;quot;oil&amp;quot;,&amp;quot;SuperE5_2&amp;quot;,0) / 100 )}, SuperPlus {(ReadingsVal(&amp;quot;oil&amp;quot;,&amp;quot;SuperPlus_2&amp;quot;,0) / 100 )}&lt;br /&gt;
 attr benzinpreis webCmd SuperE5_2:SuperPlus_2&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Ausführliche Beschreibung (mit Beispielen) zu [[eventMap]], [[devStateIcon]], setList und [[webCmd]] in {{Link2Forum|Topic=12080|LinkText=diesem Forenthread}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Attribut (allgemeingültig)]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SetList&amp;diff=38657</id>
		<title>SetList</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SetList&amp;diff=38657"/>
		<updated>2023-10-28T12:59:57Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* Syntax */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{SEITENTITEL:setList}}  &amp;lt;!-- da richtige Schreibweise kleinen Anfangsbuchstaben hat --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Infobox Attribut sinnvoll? --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Attribut [[setList]] dient dazu, bei generischen Devices die Liste der möglichen set Kommandos zu spezifizieren. &lt;br /&gt;
&lt;br /&gt;
{{Todo|Bitte analog zu [[eventMap]] mit Inhalt füllen.}}&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
Das &#039;&#039;setList&#039;&#039; Attribut wird in der folgenden Weise spezifiziert:&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;attr &amp;lt;device&amp;gt; setList &amp;lt;Reading1&amp;gt;:⟨&amp;lt;Modifier1&amp;gt;,⟩&amp;lt;Value1&amp;gt;,&amp;lt;Value2&amp;gt;,&amp;lt;...&amp;gt; &amp;lt;Reading2&amp;gt;:⟨&amp;lt;Modifier2&amp;gt;,⟩&amp;lt;Value1&amp;gt;,&amp;lt;Value2&amp;gt;,&amp;lt;...&amp;gt; ...&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Einschränkungen == &lt;br /&gt;
Dieses Attribut existiert nur bei [[DOIF]]-, [[dummy]]-, [[MSwitch]]- und [[readingsProxy]]-Devices.&lt;br /&gt;
&lt;br /&gt;
== Beispiele ==&lt;br /&gt;
&lt;br /&gt;
In diesem ersten Beispiel wird der &#039;&#039;state&#039;&#039; als Schiebebalken (slider) angezeigt. Wobei die erste Zahl den niedrigsten möglichen Wert angibt. Die zweite den Wert, um den jeweils erhöht wird. Und die dritte den maximal möglichen Wert.&lt;br /&gt;
 define Raumtemperatur dummy&lt;br /&gt;
 attr Raumtemperatur setList :slider,10,0.5,30&lt;br /&gt;
&lt;br /&gt;
Hier wird für den &#039;&#039;state&#039;&#039; eine Uhrzeit angegeben. Die kann mit zwei Schiebebalken (einer für die Stunden, einer für die Minuten) gesetzt werden.&lt;br /&gt;
 define Wecker_Uhrzeit dummy&lt;br /&gt;
 attr Wecker_Uhrzeit setList :time&lt;br /&gt;
&lt;br /&gt;
Möchte man Farbwerte einstellen, kann man &#039;&#039;colorpicker&#039;&#039; verwenden. Damit kann dann auf einer Palette eine Farbe gewählt werden.&lt;br /&gt;
 define Farbe dummy&lt;br /&gt;
 attr Farbe setList :colorpicker&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 define Wecker_Uhrzeit dummy&lt;br /&gt;
 attr Wecker_Uhrzeit setList state:AUS,05:00,05:15,05:30,05:45,06:00,06:15,06:30,06:35,06:40,06:45,06:50,06:55,07:00,07:05,07:10,07:15,07:20,07:25,07:30,07:45,08:00,08:15,08:30,08:45,09:00,09:15,09:30,09:45,10:00,10:15,10:30,10:45,11:00,11:15,11:30,11:45,12:00,12:15,12:30,12:45,13:00,13:15,13:30,13:45,14:00,14:15,14:30,14:45,15:00,15:15,15:30,15:45,16:00,16:15,16:30,16:45,17:00,17:15,17:30,17:45,18:00,18:15,18:30,18:45,19:00,19:15,19:30,19:45,20:00,20:15,20:30,20:45,21:00,21:15,21:30,21:45,22:00,22:15,22:30,22:45,23:00,23:15,23:30,23:45,00:00,00:15,00:30,00:45,01:00,01:15,01:30,01:45,02:00,02:15,02:30,02:45,03:00,03:15,03:30,03:45,04:00,04:15,04:30,04:45&lt;br /&gt;
 attr Wecker_Uhrzeit readingList state&lt;br /&gt;
 attr Wecker_Uhrzeit webCmd state&lt;br /&gt;
&lt;br /&gt;
 define Beschattung_auto dummy&lt;br /&gt;
 attr Beschattung_auto setList state:aktiv,passiv&lt;br /&gt;
 attr Beschattung_auto readingList state&lt;br /&gt;
 attr Beschattung_auto webCmd state&lt;br /&gt;
&lt;br /&gt;
 define Heizungsmodus dummy&lt;br /&gt;
 attr Heizungsmodus setList state:auto,FHEM,Frostschutz,AUS&lt;br /&gt;
 attr Heizungsmodus readingList state&lt;br /&gt;
 attr Heizungsmodus webCmd state&lt;br /&gt;
&lt;br /&gt;
 define TV_ProgrammKanal dummy&lt;br /&gt;
 attr TV_ProgrammKanal setList ARD_Ch ZDF_Ch HR_Ch RTL_Ch Sat1_Ch VOX_Ch Pro7_Ch Kabel1_Ch COMEDYCENTRAL_Ch DREISAT_Ch ARTE_Ch EINSPLUS_Ch EINSFESTIVAL_Ch ZDFNEO_Ch NDR_Ch MDR_Ch BR_Ch RBB_Ch SWR_Ch WDR_Ch RTL2_Ch SUPERRTL_Ch SPORT1_Ch EUROSPORT_Ch DMAX_Ch N24_Ch NTV_Ch RTLNITRO_Ch SAT1GOLD_Ch SIXX_Ch TELE5_Ch&lt;br /&gt;
 attr TV_ProgrammKanal readingList state&lt;br /&gt;
&lt;br /&gt;
 define benzinpreis dummy&lt;br /&gt;
 attr benzinpreis readingList SuperE5_2 SuperPlus_2&lt;br /&gt;
 attr benzinpreis setList SuperE5_2:slider,140,1,200 SuperPlus_2:slider,140,1,200&lt;br /&gt;
 attr benzinpreis stateFormat SuperE5, SuperPlus&lt;br /&gt;
 attr benzinpreis userReadings SuperE5 {(ReadingsVal(&amp;quot;oil&amp;quot;,&amp;quot;SuperE5_2&amp;quot;,0) / 100 )}, SuperPlus {(ReadingsVal(&amp;quot;oil&amp;quot;,&amp;quot;SuperPlus_2&amp;quot;,0) / 100 )}&lt;br /&gt;
 attr benzinpreis webCmd SuperE5_2:SuperPlus_2&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Ausführliche Beschreibung (mit Beispielen) zu [[eventMap]], [[devStateIcon]], setList und [[webCmd]] in {{Link2Forum|Topic=12080|LinkText=diesem Forenthread}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Attribut (allgemeingültig)]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=VALVES&amp;diff=38371</id>
		<title>VALVES</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=VALVES&amp;diff=38371"/>
		<updated>2023-05-20T14:23:19Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Link zum Support-Thread hinzu gefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Durchschnitt mit individueller Gewichtung und Ignore&lt;br /&gt;
&amp;lt;!-- |ModCategory= (noch?) nicht verwendet --&amp;gt;&lt;br /&gt;
|ModType=x&lt;br /&gt;
&amp;lt;!-- |ModCmdRef= ---- noch nicht Teil von FHEM --&amp;gt;&lt;br /&gt;
|ModForumArea=codeschnipsel&lt;br /&gt;
|ModTechName=39_VALVES.pm&lt;br /&gt;
|ModOwner=epsrw1,cwagner}}&lt;br /&gt;
[[VALVES]] bietet eine einfache Möglichkeit, den nach flexibel konfigurierbaren Regeln gewichteten Durchschnittswert einer Gruppe von Werten zu berechnen.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
&amp;lt;u&amp;gt;Diese Wiki-Seite beschreibt den Versionsstand 1.0 des VALVES-Moduls.&amp;lt;/u&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Die Namensgebung beruht auf der primären Anwendung des Moduls auf Valve-Position-Readings von Heizungsthermostaten.&lt;br /&gt;
&lt;br /&gt;
Thread im Forum:{{Link2Forum|Topic=24658|Message=177528}}&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
[[Datei:dok39_VALVES.jpg|mini|Funktionsweise]]&lt;br /&gt;
&lt;br /&gt;
VALVES bietet als kleines Helferlein die Möglichkeit, einen halbwegs sinnvollen und individuell gewichteten Durchschnittswert der Readings mehrerer verschiedener Devices zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Für jeden Wert einzeln kann ein Offset definiert werden. Es können dynamisch jeweils die höchsten/niedrigsten 0 bis 3 Werte ignoriert werden. Eine weitere Einstellung ermöglicht, bestimmte Werte doppelt zu zählen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Im Anwendungsbeispiel [[Raumbedarfsabhängige Heizungssteuerung]] wird das Modul zum Beispiel verwendet, um den Durchschnittswert der Ventilöffnungen aller Heizkörper zu berechnen. Die individuelle Gewichtung über Attr ermöglicht hierbei einen virtuellen hydraulischen Abgleich.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Die Liste aller auszulesenden Devices wird in einem ATTR eingestellt, der Name des Readings in einem weiteren. Das Modul prüft dann regelmäßig (attr: poll interval) die Daten der FHEM-Devices und berechnet neu, wenn ein Änderung festgestellt wird.&lt;br /&gt;
&lt;br /&gt;
Für die Beeinflussung des Durchschnittes hat man folgende Attribute:&lt;br /&gt;
&lt;br /&gt;
* ignoriere niedrigste 0...3 Positionen&lt;br /&gt;
&lt;br /&gt;
* ignoriere höchste 0...3 Positionen&lt;br /&gt;
&lt;br /&gt;
* ignoriere namentlich genannte Devices&lt;br /&gt;
&lt;br /&gt;
* priority-device Liste (zählen doppelt)&lt;br /&gt;
&lt;br /&gt;
* valves&amp;lt;Devicename&amp;gt;Gewichtung optionale Einzeleinstellung für jedes Reading, multipliziere mit Attr-Wert (zB:0,95 um 5% abzuziehen). Damit können Unterschiede bekannte gleichbleibende Meßungenauigkeiten kompensiert werden, oder verschieden große Geräte in vergleichbare Rechengrößen konvertiert werden.&lt;br /&gt;
&lt;br /&gt;
== Define ==&lt;br /&gt;
:&amp;lt;code&amp;gt;define &amp;lt;name&amp;gt; VALVES &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Attribute ==&lt;br /&gt;
Alle Attribute sind auch in FHEM durch das Kommando get attrHelp &amp;lt;varname&amp;gt; erklärt, fürs &amp;quot;schnelle Nachschauen zwischendurch&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
valvesInitialDelay -&amp;gt; Startverzögerung&lt;br /&gt;
&lt;br /&gt;
valvesPollInterval -&amp;gt; Berechnungsfrequenz&lt;br /&gt;
&lt;br /&gt;
valvesDeviceList -&amp;gt; &#039;&#039;&#039;Pflicht-Attr&#039;&#039;&#039;, Liste Thermostate mit valve-pos Readings&lt;br /&gt;
&lt;br /&gt;
valvesDeviceReading -&amp;gt; &#039;&#039;&#039;Pflicht-Attr&#039;&#039;&#039;, Bezeichnung valve-pos Reading&lt;br /&gt;
&lt;br /&gt;
valvesIgnoreLowest -&amp;gt; Niedrigste N Werte ignorieren&lt;br /&gt;
&lt;br /&gt;
valvesIgnoreHighest -&amp;gt; Höchste N Werte ignorieren&lt;br /&gt;
&lt;br /&gt;
valvesIgnoreDeviceList -&amp;gt; Device(s) die komplett ignoriert werden, z.B. temporärer Eintrag für Gästezimmer&lt;br /&gt;
&lt;br /&gt;
valvesPriorityDeviceList -&amp;gt; Devices, die doppelt gezählt werden&lt;br /&gt;
&lt;br /&gt;
valves&amp;lt;Devicename&amp;gt; Gewichtung -&amp;gt; Faktor für einzelnes Device für individuelle Gewichtung&lt;br /&gt;
&lt;br /&gt;
== Settings ==&lt;br /&gt;
reset -&amp;gt; Alle Readings zurücksetzen&lt;br /&gt;
&lt;br /&gt;
== Readings ==&lt;br /&gt;
state -&amp;gt; Fehlermeldung oder Mittelwert nach oben beschriebener Berechnung&lt;br /&gt;
&lt;br /&gt;
valve_&amp;lt;Devicename&amp;gt; -&amp;gt; Berechnete virtuelle Ventilstellung pro Gerät&lt;br /&gt;
&lt;br /&gt;
valveDetail_&amp;lt;Devicename&amp;gt; -&amp;gt; Debug-Info mit Details&lt;br /&gt;
&lt;br /&gt;
raw_average -&amp;gt; Simpler Mittelwert ohne Berücksichtigung der Gewichtungen (ignores werden auch hier ignoriert)&lt;br /&gt;
&lt;br /&gt;
valve_average -&amp;gt; Mittelwert nach oben beschriebener Berechnung&lt;br /&gt;
&lt;br /&gt;
valve_max -&amp;gt; Größte aktuelle Ventilöffnung seit letztem Reset&lt;br /&gt;
&lt;br /&gt;
valve_min -&amp;gt; Kleinste aktuelle Ventilöffnung seit letztem Reset&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* {{Link2Forum|Topic=24658|Message=177528}} Thread im Forum, in dem dieses Modul vorgestellt wurde&lt;br /&gt;
* {{Link2Forum|Topic=131849|Message=0}} Support-Thread&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Regelungstechnik]]&lt;br /&gt;
[[Kategorie:Heizungssteuerung]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=OpenWB&amp;diff=38244</id>
		<title>OpenWB</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=OpenWB&amp;diff=38244"/>
		<updated>2023-04-05T06:40:56Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Zur Kategorie &amp;quot;HOWTOS&amp;quot; hinzu gefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Integration der openWB in FHEM - Ladeleistung anzeigen und Umschalten des Lademodus ==&lt;br /&gt;
Ausgangssituation ist ein funktionierendes FHEM, ohne weitere Vorbedingungen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod openwb MQTT &amp;lt;openWBip&amp;gt;:1883&lt;br /&gt;
attr openwb room Auto,MQTT&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dadurch wird der MQTT-Server der openWB angesprochen, FHEM ist der Client.&lt;br /&gt;
&lt;br /&gt;
Ein Ladepunkt wird als MQTT_Device angelegt:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod lp1 MQTT_DEVICE&lt;br /&gt;
attr lp1 IODev openwb&lt;br /&gt;
attr lp1 publishSet_chargeMode openWB/set/ChargeMode&lt;br /&gt;
attr lp1 room Auto,Dashboard,MQTT&lt;br /&gt;
attr lp1 stateFormat power&lt;br /&gt;
attr lp1 subscribeReading_chargeMode openWB/global/ChargeMode&lt;br /&gt;
attr lp1 subscribeReading_plugStat openWB/lp/1/boolPlugStat&lt;br /&gt;
attr lp1 subscribeReading_power openWB/lp/1/W&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Umsetzung basiert auf openWB 1.9.x, der Lademodus &amp;quot;ChargeMode&amp;quot; gilt hier noch global für alle Ladepunkte.&lt;br /&gt;
&lt;br /&gt;
Beispielhaft die Definition des zweiten Ladepunktes, eine zweite openWB, die als &amp;quot;nur Ladepunkt&amp;quot; mit der angesprochenen openWB verbunden ist.&lt;br /&gt;
&lt;br /&gt;
Eine openWB kann derzeit 8 Ladepunkte verwalten, die Nummern müssen entsprechend inkrementiert werden.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod lp2 MQTT_DEVICE&lt;br /&gt;
attr lp2 IODev openwb&lt;br /&gt;
attr lp2 publishSet_chargeMode openWB/set/ChargeMode&lt;br /&gt;
attr lp2 room Auto,Dashboard,MQTT&lt;br /&gt;
attr lp2 stateFormat power&lt;br /&gt;
attr lp2 subscribeReading_chargeMode openWB/global/ChargeMode&lt;br /&gt;
attr lp2 subscribeReading_plugStat openWB/lp/2/boolPlugStat&lt;br /&gt;
attr lp2 subscribeReading_power openWB/lp/2/W&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die MQTT-Topics zum Lesen und Schreiben von Werten sind ganz unten auf dieser Wiki-Seite zu finden.&lt;br /&gt;
&lt;br /&gt;
Die Einbindung in die TabletUI sieht bei mir so aus:&lt;br /&gt;
[[Datei:Ladepunkte in TabletUI.png|alternativtext=Darstellung der openWB Ladepunkte in der TabletUI|mini|488x488px|Beispielhafte Darstellung in der TabletUI]]&lt;br /&gt;
[[Datei:Auswahl des Lademodus.png|alternativtext=Darstellung der openWB Ladepunkte in der TabletUI - Auswahl des Lademodus|mini|486x486px|Auswahl des Lademodus per CircleMenu]]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;cell-60 left-space right-space&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;div data-type=&amp;quot;symbol&amp;quot; data-icon=&amp;quot;fa-car&amp;quot; class=&amp;quot;tall compressed&amp;quot; data-color=&amp;quot;lightgray&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;div data-type=&amp;quot;circlemenu&amp;quot; data-direction=&amp;quot;full&amp;quot; class=&amp;quot;mini&amp;quot; style=&amp;quot;top: -0.5em;&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;ul class=&amp;quot;mini&amp;quot;&amp;gt;&lt;br /&gt;
				&amp;lt;li&amp;gt;&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;lp1&amp;quot; data-get=&amp;quot;chargeMode&amp;quot; data-states=&#039;[0,1,2,3,4]&#039; data-colors=&#039;[&amp;quot;lightgreen&amp;quot;,&amp;quot;greenyellow&amp;quot;,&amp;quot;yellow&amp;quot;,&amp;quot;grey&amp;quot;,&amp;quot;black&amp;quot;]&#039; data-icons=&#039;[&amp;quot;fa-bolt&amp;quot;,&amp;quot;fa-plus-circle&amp;quot;,&amp;quot;fa-sun-o&amp;quot;,&amp;quot;fa-pause-circle-o&amp;quot;,&amp;quot;fa-stop-circle-o&amp;quot;]&#039; data-background-icon=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
				&amp;lt;li&amp;gt;&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;lp1&amp;quot; data-set=&amp;quot;chargeMode&amp;quot; data-get=&amp;quot;chargeMode&amp;quot; data-set-on=&amp;quot;0&amp;quot; data-get-on=&amp;quot;0&amp;quot; data-icon=&amp;quot;fa-bolt&amp;quot; data-color=&amp;quot;lightgreen&amp;quot;  data-background-icon=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
				&amp;lt;li&amp;gt;&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;lp1&amp;quot; data-set=&amp;quot;chargeMode&amp;quot; data-get=&amp;quot;chargeMode&amp;quot; data-set-on=&amp;quot;1&amp;quot; data-get-on=&amp;quot;1&amp;quot; data-icon=&amp;quot;fa-plus-circle&amp;quot; data-color=&amp;quot;greenyellow&amp;quot; data-background-icon=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
				&amp;lt;li&amp;gt;&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;lp1&amp;quot; data-set=&amp;quot;chargeMode&amp;quot; data-get=&amp;quot;chargeMode&amp;quot; data-set-on=&amp;quot;2&amp;quot; data-get-on=&amp;quot;2&amp;quot; data-icon=&amp;quot;fa-sun-o&amp;quot; data-color=&amp;quot;yellow&amp;quot; data-background-icon=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
				&amp;lt;li&amp;gt;&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;lp1&amp;quot; data-set=&amp;quot;chargeMode&amp;quot; data-get=&amp;quot;chargeMode&amp;quot; data-set-on=&amp;quot;3&amp;quot; data-get-on=&amp;quot;3&amp;quot; data-icon=&amp;quot;fa-pause-circle-o&amp;quot; data-color=&amp;quot;grey&amp;quot; data-background-icon=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
				&amp;lt;li&amp;gt;&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;lp1&amp;quot; data-set=&amp;quot;chargeMode&amp;quot; data-get=&amp;quot;chargeMode&amp;quot; data-set-on=&amp;quot;4&amp;quot; data-get-on=&amp;quot;4&amp;quot; data-icon=&amp;quot;fa-stop-circle-o&amp;quot; data-color=&amp;quot;black&amp;quot; data-background-icon=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;/ul&amp;gt;&lt;br /&gt;
		&amp;lt;/div&amp;gt;&lt;br /&gt;
		&amp;lt;div style=&amp;quot;font-size: 30% !important;&amp;quot; class=&amp;quot;mini &amp;quot; data-pre-text=&amp;quot;&amp;quot; data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;lp1&amp;quot; data-get=&amp;quot;power&amp;quot; data-unit=&amp;quot;&amp;quot; data-factor=&amp;quot;1&amp;quot; data-fix=&amp;quot;0&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
		&amp;lt;div data-type=&amp;quot;symbol&amp;quot; data-device=&amp;quot;lp1&amp;quot; data-get=&amp;quot;plugStat&amp;quot; data-states=&#039;[0,1]&#039; data-colors=&#039;[&amp;quot;white&amp;quot;,&amp;quot;black&amp;quot;]&#039; data-icons=&#039;[&amp;quot;&amp;quot;,&amp;quot;fa-plug&amp;quot;]&#039; data-background-icon=&amp;quot;&amp;quot; class=&amp;quot;mini&amp;quot; style=&amp;quot;font-size: 30% !important; top:1em;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Integration OpenWB in FHEM - Übertragung von EVU, PV und Batteriewerten an openWB==&lt;br /&gt;
Ausgangssituation ist ein funktionierendes FHEM-System, bei dem bereits der digitale Stromzähler (&amp;quot;Moderne Meßeinrichtung&amp;quot;) über das Modul 47_OBIS und der PV-Wechselrichter über ein entsprechendes Modul, z.B. ModbusAttr integriert sind. Als OpenWB-System wurde hier eine reale OpenWB-Wallbox angebunden.&lt;br /&gt;
&lt;br /&gt;
=== Datenquellen ===&lt;br /&gt;
Die OpenWB erwartet 1-3 Typen von Datenquellen in dieser Konstellation:&lt;br /&gt;
* Die &#039;&#039;EVU-&#039;&#039;Schnittstelle, mit der als wesentlicher Steuerparameter der Ladeleistung die Leistungsmessung am Hausübergang herangezogen wird, und daneben die Zählerwerte für Netzbezug und Einspeisung zur Visualisierung übertragen werden sollten. Nur, falls phasenbezogenes Lastmanagement erforderlich sein sollte, sind auch die einzelnen Phasenleistungswerte vom Stromzähler nötig (was nicht jede Moderne Meßeinrichtung auf der OBIS-Schnittstelle bereitstellt)&lt;br /&gt;
* Die &#039;&#039;PV-&#039;&#039;Schnittstelle, die ebenfalls primär visualisierende Bedeutung hat.&lt;br /&gt;
* Die &#039;&#039;Batteriespeicher-&#039;&#039;Schnittstelle&lt;br /&gt;
OpenWB kann auch z.B. rein mit einer PV-Schnittstelle betrieben werden, in diesem Fall wird ein konstanter Leistungswert für den Hausbezug angenommen.&lt;br /&gt;
&lt;br /&gt;
=== Kommunikationsprotokoll ===&lt;br /&gt;
Zur Kommunikation mit FHEM bieten sich 2 Methoden an:&lt;br /&gt;
* &#039;&#039;&#039;HTTP&#039;&#039;&#039;-Abfrage durch OpenWB bei FHEM durch das generische HTTP-Modul von OpenWB  Diese Methode beschreibe ich nicht, weil sie mehr Overhead erzeugt und seitens FHEM die Einrichtung eines CSRF-Token-freien Web-Kanals erfordert&lt;br /&gt;
* &#039;&#039;&#039;MQTT&#039;&#039;&#039;-Push durch FHEM zur OpenWB  Diese Methode erscheint mir vorteilhafter, weil auf einer stehenden TCP-Verbindung lediglich Meßwerte gepusht werden.&lt;br /&gt;
&lt;br /&gt;
=== Implementierung ===&lt;br /&gt;
&lt;br /&gt;
==== Vorbereitung ====&lt;br /&gt;
In der OpenWB-Web-UI unter Modulkonfiguration die entsprechenden Module (EVU, PV, Batterie) auf MQTT stellen. Hinweis: Nicht alle dabei erscheinenden MQTT-Topics müssen mit Werten beliefert werden! Sowohl bei der EVU-Schnittstelle wie bei PV reichen Momentanleistung und Zählerstände für eine zufriedenstellende Anbindung!&lt;br /&gt;
&lt;br /&gt;
==== Definition der OpenWB als MQTT-Target ====&lt;br /&gt;
 defmod openwb_mqtt MQTT2_CLIENT &amp;lt;ip-der-openwb&amp;gt;:1883&lt;br /&gt;
 attr openwb_mqtt autocreate simple&lt;br /&gt;
 attr openwb_mqtt subscriptions openWB/lp/1/#&lt;br /&gt;
&lt;br /&gt;
==== Übertragung der EVU-Meßwerte ====&lt;br /&gt;
In diesem Beispiel heißt das die Stromzählerdaten liefernde Device am OBIS-Modul &amp;quot;MT175&amp;quot;. Die Zahlen werden per Notify von diesem Device auf MQTT kopiert:&lt;br /&gt;
 defmod openwb_evu_cons notify MT175:total_consumption:.* { fhem(&amp;quot;set openwb_mqtt publish openWB/set/evu/WhImported &amp;quot; . $EVTPART1); }&lt;br /&gt;
 defmod openwb_evu_feed notify MT175:total_feed:.* { fhem(&amp;quot;set openwb_mqtt publish openWB/set/evu/WhExported &amp;quot; . $EVTPART1); }&lt;br /&gt;
 defmod openwb_evu_w notify MT175:power:.* { fhem(&amp;quot;set openwb_mqtt publish openWB/set/evu/W &amp;quot; . int($EVTPART1)); }&lt;br /&gt;
&lt;br /&gt;
==== Übertragung der PV-Meßwerte ====&lt;br /&gt;
Sofern die Daten für Momentanleistung und Zählerstand direkt in einem Device vorliegen, können analoge Notifys für dieses Device implementiert werden. Die Zielwerte lauten:&lt;br /&gt;
* Für den Momentan-Leistungswert &amp;lt;code&amp;gt;openWB/set/pv/1/W&amp;lt;/code&amp;gt;&lt;br /&gt;
* Für den Zählerstand &amp;lt;code&amp;gt;openWB/set/pv/1/WhCounter&amp;lt;/code&amp;gt;&lt;br /&gt;
Dabei muss beachtet werden, dass - wie bei der EVU-Schnittstelle - nur Integerwerte für die Momentanleistung übertragen werden dürfen.&lt;br /&gt;
&lt;br /&gt;
==== Anbindung an Alexa ====&lt;br /&gt;
Der generische Smarthome-Skill &amp;quot;FHEMConnector&amp;quot; erlaubt nur die leider immer noch sehr limitierte Syntax von Amazon Alexa. Im Folgenden werden die Definitionen für die Befehle:&lt;br /&gt;
* &#039;&#039;&amp;quot;Alexa, schalte Überschussladen ein&amp;quot;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&amp;quot;Alexa, schalte Überschussladen aus&amp;quot;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&amp;quot;Alexa, schalte Überschussladen auf 6 (Prozent)&amp;quot;&#039;&#039;&lt;br /&gt;
dargestellt. &amp;quot;Überschussladen auf 6&amp;quot; bedeutet dabei real den &amp;quot;Min+PV&amp;quot;, also Überschussladen mit Minimalleistung von 6 Ampere. Je nach Tagesform von Amazon ist dabei das Sprechen von &amp;quot;Prozent&amp;quot; nötig, auch wenn dies natürlich sachlich falsch ist.&lt;br /&gt;
 define openwb_ueberschuss dummy&lt;br /&gt;
 attr openwb_ueberschuss alexaName Überschussladen&lt;br /&gt;
 attr openwb_ueberschuss genericDeviceType light&lt;br /&gt;
 attr openwb_ueberschuss readingList pct&lt;br /&gt;
 attr openwb_ueberschuss setList on off pct&lt;br /&gt;
 define openwb_ueberschuss_on notify openwb_ueberschuss:on set openwb_mqtt publish openWB/set/ChargeMode 2&lt;br /&gt;
 define openwb_ueberschuss_off notify openwb_ueberschuss:off set openwb_mqtt publish openWB/set/ChargeMode 3&lt;br /&gt;
 define openwb_ueberschuss_pct notify openwb_ueberschuss:pct:.* set openwb_mqtt publish openWB/config/set/pv/minCurrentMinPv $EVTPART1 ;; set openwb_mqtt publish openWB/set/ChargeMode 1&lt;br /&gt;
&lt;br /&gt;
==Anwendungs Beispiele==&lt;br /&gt;
===Komplexe Anbindung===&lt;br /&gt;
[[Bild:Kia.PNG|mini|700px|rechts|WallBox mit Kia Fahrzeug]]&lt;br /&gt;
Hier mal ein Beispiel mit weiteren Schnittstellen in der Haussteuerung. Im Hintergrund arbeitet ein Wechselrichter Schwarm mit einem Hausspeicher, der beim BEV Laden gesperrt wird. Die openWB kommuniziert direkt mit den zwei Kostal Wechselrichtern, dem KSEM und dem am Master angeschlossenen Speicher. Das BEV ist über Kia Connect angebunden.&lt;br /&gt;
[[Bild:WB_1.PNG|mini|700px|rechts|openWB mit Statistiken]]&lt;br /&gt;
[[Bild:Kostal Flow.PNG|mini|700px|rechts|Sowas könnte am Schluss, inklusive Wechselrichter, raus kommen. Die openWBs sind unten links.]]&lt;br /&gt;
====Verwendete Schnittstellen / Devices====&lt;br /&gt;
=====openWB MQTT=====&lt;br /&gt;
Wie oben beschrieben mit folgender MQTT definition. Im Bild ist das DOIF dargestellt und das MQTT Device als kurze Darstellung unterhalb der Tabelle. Das MQTT wird nur zur Kopplung verwendet, hat jedoch jetzt auch ein stateFormat inklusieve Statistiken erhalten.&lt;br /&gt;
&lt;br /&gt;
RAW des MQTT Device&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod WB_1 MQTT2_DEVICE WB_1_MQTT2&lt;br /&gt;
attr WB_1 DbLogExclude .*&lt;br /&gt;
attr WB_1 DbLogInclude lp_1_.*,.*AllChargePoints.*,ChargeMode&lt;br /&gt;
attr WB_1 IODev WB_1_MQTT2&lt;br /&gt;
attr WB_1 alias WB_1&lt;br /&gt;
attr WB_1 autocreate 0&lt;br /&gt;
attr WB_1 comment Die openWB besteht aus zwei Ladepunkten.&lt;br /&gt;
attr WB_1 devicetopic openWB&lt;br /&gt;
attr WB_1 disable 0&lt;br /&gt;
attr WB_1 event-on-change-reading lp_1_.*,.*AllChargePoints.*,ChargeMode&lt;br /&gt;
attr WB_1 group PV Eigenverbrauch&lt;br /&gt;
attr WB_1 icon fuel&lt;br /&gt;
attr WB_1 readingList $DEVICETOPIC/global/WHouseConsumption:.* WHouseConsumption\&lt;br /&gt;
$DEVICETOPIC/global/WAllChargePoints:.* WAllChargePoints\&lt;br /&gt;
$DEVICETOPIC/global/ChargeMode:.* {my %h=(0=&amp;gt;&#039;SofortLaden&#039;,1=&amp;gt;&#039;MinPV&#039;,2=&amp;gt;&#039;NurPV&#039;,3=&amp;gt;&#039;Stop&#039;,4=&amp;gt;&#039;Standby&#039;);; return {ChargeMode=&amp;gt;$h{$EVENT}}}\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/global/awattar/boolAwattarEnabled:.* boolAwattarEnabled\&lt;br /&gt;
$DEVICETOPIC/global/awattar/ActualPriceForCharging:.* ActualPriceForCharging\&lt;br /&gt;
$DEVICETOPIC/global/awattar/MaxPriceForCharging:.* MaxPriceForCharging\&lt;br /&gt;
$DEVICETOPIC/global/boolRse:.* boolRse\&lt;br /&gt;
$DEVICETOPIC/global/DailyYieldAllChargePointsKwh:.* DailyYieldAllChargePointsKwh\&lt;br /&gt;
$DEVICETOPIC/global/rfidConfigured:.* rfidConfigured\&lt;br /&gt;
$DEVICETOPIC/global/kWhCounterAllChargePoints:.* kWhCounterAllChargePoints\&lt;br /&gt;
$DEVICETOPIC/global/strLastmanagementActive:.* strLastmanagementActive\&lt;br /&gt;
$DEVICETOPIC/global/ETProvider/modulePath:.* modulePath\&lt;br /&gt;
$DEVICETOPIC/global/cpuTemp:.* cpuTemp\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/system/Uptime:.* Uptime\&lt;br /&gt;
$DEVICETOPIC/system/Date:.* Date\&lt;br /&gt;
$DEVICETOPIC/system/Timestamp:.* Timestamp\&lt;br /&gt;
$DEVICETOPIC/system/Version:.* Version\&lt;br /&gt;
$DEVICETOPIC/system/IpAddress:.* IpAddress\&lt;br /&gt;
$DEVICETOPIC/system/lastRfId:.* lastRfId\&lt;br /&gt;
$DEVICETOPIC/system/updateInProgress:.* updateInProgress\&lt;br /&gt;
$DEVICETOPIC/system/ConfiguredChargePoints:.* ConfiguredChargePoints\&lt;br /&gt;
$DEVICETOPIC/system/lastlivevalues:.* lastlivevalues\&lt;br /&gt;
$DEVICETOPIC/system/randomSleep:.* randomSleep\&lt;br /&gt;
$DEVICETOPIC/system/wizzardDone:.* wizzardDone\&lt;br /&gt;
$DEVICETOPIC/system/priceForKWh:.* priceForKWh\&lt;br /&gt;
$DEVICETOPIC/system/reloadDisplay:.* reloadDisplay\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/evu/ASchieflast:.* ASchieflast\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/1/P%Soc:.* lp_1_Pct_Soc\&lt;br /&gt;
$DEVICETOPIC/lp/1/%Soc:.* lp_1_current_Soc\&lt;br /&gt;
$DEVICETOPIC/lp/1/\x25Soc:.* lp_1__Soc\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/1/countPhasesInUse:.* lp_1_countPhasesInUse\&lt;br /&gt;
$DEVICETOPIC/lp/1/ChargePointEnabled:.* lp_1_ChargePointEnabled\&lt;br /&gt;
$DEVICETOPIC/lp/1/ChargeStatus:.* lp_1_ChargeStatus\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/1/kWhDailyCharged:.* lp_1_kWhDailyCharged\&lt;br /&gt;
$DEVICETOPIC/lp/1/kWhCounter:.* lp_1_kWhCounter\&lt;br /&gt;
$DEVICETOPIC/lp/1/kWhActualCharged:.* lp_1_kWhActualCharged\&lt;br /&gt;
$DEVICETOPIC/lp/1/kWhChargedSincePlugged:.* lp_1_kWhChargedSincePlugged\&lt;br /&gt;
$DEVICETOPIC/lp/1/energyConsumptionPer100km:.* lp_1_energyConsumptionPer100km\&lt;br /&gt;
$DEVICETOPIC/lp/1/kmCharged:.* lp_1_kmCharged\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/1/strChargePointName:.* lp_1_strChargePointName\&lt;br /&gt;
$DEVICETOPIC/lp/1/TimeRemaining:.* lp_1_TimeRemaining\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/1/PfPhase2:.* lp_1_PfPhase2\&lt;br /&gt;
$DEVICETOPIC/lp/1/PfPhase3:.* lp_1_PfPhase3\&lt;br /&gt;
$DEVICETOPIC/lp/1/PfPhase1:.* lp_1_PfPhase1\&lt;br /&gt;
$DEVICETOPIC/lp/1/W:.* lp_1_W\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/1/boolPlugStat:.* {my %h=(0=&amp;gt;&#039;no Plug&#039;,1=&amp;gt;&#039;Plugged in&#039;);; return {lp_1_PlugStat=&amp;gt;$h{$EVENT}}}\&lt;br /&gt;
$DEVICETOPIC/lp/1/boolChargeStat:.* {my %h=(0=&amp;gt;&#039;not loading&#039;,1=&amp;gt;&#039;loading&#039;);; return {lp_1_ChargeStat=&amp;gt;$h{$EVENT}}}\&lt;br /&gt;
$DEVICETOPIC/lp/1/AConfigured:.* lp_1_AConfigured\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/1/boolChargePointConfigured:.* lp_1_boolChargePointConfigured\&lt;br /&gt;
$DEVICETOPIC/lp/1/boolSocConfigured:.* lp_1_boolSocConfigured\&lt;br /&gt;
$DEVICETOPIC/lp/1/boolDirectModeChargekWh:.* lp_1_boolDirectModeChargekWh\&lt;br /&gt;
$DEVICETOPIC/lp/1/boolDirectChargeModeSoc:.* lp_1_boolDirectChargeModeSoc\&lt;br /&gt;
$DEVICETOPIC/lp/1/boolFinishAtTimeChargeActive:.* lp_1_boolFinishAtTimeChargeActive\&lt;br /&gt;
$DEVICETOPIC/lp/1/boolChargeAtNight:.* lp_1_boolChargeAtNight\&lt;br /&gt;
$DEVICETOPIC/lp/1/boolSocManual:.* lp_1_boolSocManual\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/1/AutolockStatus:.* lp_1_AutolockStatus\&lt;br /&gt;
$DEVICETOPIC/lp/1/AutolockConfigured:.* lp_1_AutolockConfigured\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/1/lastRfId:.* lp_1_lastRfId\&lt;br /&gt;
$DEVICETOPIC/lp/1/pluggedladungakt:.* lp_1_pluggedladungakt\&lt;br /&gt;
$DEVICETOPIC/lp/1/plugStartkWh:.* lp_1_plugStartkWh\&lt;br /&gt;
$DEVICETOPIC/lp/1/MeterSerialNumber:.* lp_1_MeterSerialNumber\&lt;br /&gt;
\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/2/P%Soc:.* lp_2_Pct_Soc\&lt;br /&gt;
$DEVICETOPIC/lp/2/%Soc:.* lp_2_current_Soc\&lt;br /&gt;
$DEVICETOPIC/lp/2/\x25Soc:.* lp_2__Soc\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/2/countPhasesInUse:.* lp_2_countPhasesInUse\&lt;br /&gt;
$DEVICETOPIC/lp/2/ChargePointEnabled:.* lp_2_ChargePointEnabled\&lt;br /&gt;
$DEVICETOPIC/lp/2/ChargeStatus:.* lp_2_ChargeStatus\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/2/kWhDailyCharged:.* lp_2_kWhDailyCharged\&lt;br /&gt;
$DEVICETOPIC/lp/2/kWhCounter:.* lp_2_kWhCounter\&lt;br /&gt;
$DEVICETOPIC/lp/2/kWhActualCharged:.* lp_2_kWhActualCharged\&lt;br /&gt;
$DEVICETOPIC/lp/2/kWhChargedSincePlugged:.* lp_2_kWhChargedSincePlugged\&lt;br /&gt;
$DEVICETOPIC/lp/2/energyConsumptionPer100km:.* lp_2_energyConsumptionPer100km\&lt;br /&gt;
$DEVICETOPIC/lp/2/kmCharged:.* lp_2_kmCharged\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/2/strChargePointName:.* lp_2_strChargePointName\&lt;br /&gt;
$DEVICETOPIC/lp/2/TimeRemaining:.* lp_2_TimeRemaining\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/2/W:.* lp_2_W\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/2/boolPlugStat:.* {my %h=(0=&amp;gt;&#039;no Plug&#039;,1=&amp;gt;&#039;Plugged in&#039;);; return {lp_2_PlugStat=&amp;gt;$h{$EVENT}}}\&lt;br /&gt;
$DEVICETOPIC/lp/2/boolChargeStat:.* {my %h=(0=&amp;gt;&#039;not loading&#039;,1=&amp;gt;&#039;loading&#039;);; return {lp_2_ChargeStat=&amp;gt;$h{$EVENT}}}\&lt;br /&gt;
$DEVICETOPIC/lp/2/AConfigured:.* lp_2_AConfigured\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/2/boolChargePointConfigured:.* lp_2_boolChargePointConfigured\&lt;br /&gt;
$DEVICETOPIC/lp/2/boolSocConfigured:.* lp_2_boolSocConfigured\&lt;br /&gt;
$DEVICETOPIC/lp/2/boolDirectModeChargekWh:.* lp_2_boolDirectModeChargekWh\&lt;br /&gt;
$DEVICETOPIC/lp/2/boolDirectChargeModeSoc:.* lp_2_boolDirectChargeModeSoc\&lt;br /&gt;
$DEVICETOPIC/lp/2/boolFinishAtTimeChargeActive:.* lp_2_boolFinishAtTimeChargeActive\&lt;br /&gt;
$DEVICETOPIC/lp/2/boolChargeAtNight:.* lp_2_boolChargeAtNight\&lt;br /&gt;
$DEVICETOPIC/lp/2/boolSocManual:.* lp_2_boolSocManual\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/2/AutolockStatus:.* lp_2_AutolockStatus\&lt;br /&gt;
$DEVICETOPIC/lp/2/AutolockConfigured:.* lp_2_AutolockConfigured\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/lp/2/lastRfId:.* lp_2_lastRfId\&lt;br /&gt;
$DEVICETOPIC/lp/2/pluggedladungakt:.* lp_2_pluggedladungakt\&lt;br /&gt;
$DEVICETOPIC/lp/2/plugStartkWh:.* lp_2_plugStartkWh\&lt;br /&gt;
$DEVICETOPIC/lp/2/MeterSerialNumber:.* lp_2_MeterSerialNumber\&lt;br /&gt;
\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/boolChargeAtNight_direct:.* boolChargeAtNight_direct\&lt;br /&gt;
$DEVICETOPIC/boolChargeAtNight_nurpv:.* boolChargeAtNight_nurpv\&lt;br /&gt;
$DEVICETOPIC/boolChargeAtNight_minpv:.* boolChargeAtNight_minpv\&lt;br /&gt;
$DEVICETOPIC/boolDisplayHouseConsumption:.* boolDisplayHouseConsumption\&lt;br /&gt;
$DEVICETOPIC/boolDisplayDailyCharged:.* boolDisplayDailyCharged\&lt;br /&gt;
$DEVICETOPIC/boolEvuSmoothedActive:.* boolEvuSmoothedActive\&lt;br /&gt;
$DEVICETOPIC/pv/bool70PVDynActive:.* bool70PVDynActive\&lt;br /&gt;
$DEVICETOPIC/pv/W70PVDyn:.* W70PVDyn\&lt;br /&gt;
$DEVICETOPIC/pv/bool70PVDynStatus:.* bool70PVDynStatus\&lt;br /&gt;
$DEVICETOPIC/pv/CounterTillStartPvCharging:.* CounterTillStartPvCharging\&lt;br /&gt;
$DEVICETOPIC/pv/W:.* W\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/nurpv70dynact:.* nurpv70dynact\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/nurpv70dynw:.* nurpv70dynw\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/priorityModeEVBattery:.* priorityModeEVBattery\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/lp/1/minSocAlwaysToChargeTo:.* lp_1_minSocAlwaysToChargeTo\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/lp/1/maxSoc:.* lp_1_maxSoc\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/lp/1/minSocAlwaysToChargeToCurrent:.* lp_1_minSocAlwaysToChargeToCurrent\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/lp/1/maxSocToChargeTo:.* lp_1_maxSocToChargeTo\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/lp/1/minCurrent:.* lp_1_minCurrent\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/lp/1/socLimitation:.* lp_1_socLimitation\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/lp/2/minCurrent:.* lp_2_minCurrent\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/lp/2/maxSoc:.* lp_2_maxSoc\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/lp/2/socLimitation:.* lp_2_socLimitation\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/socStopChargeAtMinPv:.* socStopChargeAtMinPv\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/regulationPoint:.* regulationPoint\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/minBatteryDischargeSocAtBattPriority:.* minBatteryDischargeSocAtBattPriority\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/minBatteryChargePowerAtEvPriority:.* minBatteryChargePowerAtEvPriority\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/minFeedinPowerBeforeStart:.* minFeedinPowerBeforeStart\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/boolAdaptiveCharging:.* boolAdaptiveCharging\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/adaptiveChargingFactor:.* adaptiveChargingFactor\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/batteryDischargePowerAtBattPriority:.* batteryDischargePowerAtBattPriority\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/boolShowPriorityIconInTheme:.* boolShowPriorityIconInTheme\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/maxPowerConsumptionBeforeStop:.* maxPowerConsumptionBeforeStop\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/stopDelay:.* stopDelay\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/chargeSubmode:.* chargeSubmode\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/minCurrentMinPv:.* minCurrentMinPv\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/socStartChargeAtMinPv:.* socStartChargeAtMinPv\&lt;br /&gt;
$DEVICETOPIC/config/get/pv/startDelay:.* startDelay\&lt;br /&gt;
$DEVICETOPIC/config/get/sofort/lp/2/energyToCharge:.* lp_2_energyToCharge\&lt;br /&gt;
$DEVICETOPIC/config/get/sofort/lp/2/chargeLimitation:.* lp_2_chargeLimitation\&lt;br /&gt;
$DEVICETOPIC/config/get/sofort/lp/2/socToChargeTo:.* lp_2_socToChargeTo\&lt;br /&gt;
$DEVICETOPIC/config/get/sofort/lp/2/current:.* lp_2_current\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/config/get/sofort/lp/1/socToChargeTo:.* lp_1_socToChargeTo\&lt;br /&gt;
\&lt;br /&gt;
$DEVICETOPIC/config/get/sofort/lp/1/energyToCharge:.* lp_1_energyToCharge\&lt;br /&gt;
$DEVICETOPIC/config/get/sofort/lp/1/chargeLimitation:.* lp_1_chargeLimitation\&lt;br /&gt;
$DEVICETOPIC/config/get/sofort/lp/1/current:.* lp_1_current\&lt;br /&gt;
$DEVICETOPIC/config/get/global/minEVSECurrentAllowed:.* minEVSECurrentAllowed\&lt;br /&gt;
$DEVICETOPIC/config/get/global/maxEVSECurrentAllowed:.* maxEVSECurrentAllowed\&lt;br /&gt;
$DEVICETOPIC/config/get/global/dataProtectionAcknoledged:.* dataProtectionAcknoledged\&lt;br /&gt;
$DEVICETOPIC/config/get/global/slaveMode:.* slaveMode\&lt;br /&gt;
$DEVICETOPIC/config/get/u1p3p/standbyPhases:.* standbyPhases\&lt;br /&gt;
$DEVICETOPIC/config/get/u1p3p/sofortPhases:.* sofortPhases\&lt;br /&gt;
$DEVICETOPIC/config/get/u1p3p/nachtPhases:.* nachtPhases\&lt;br /&gt;
$DEVICETOPIC/config/get/u1p3p/minundpvPhases:.* minundpvPhases\&lt;br /&gt;
$DEVICETOPIC/config/get/u1p3p/nurpvPhases:.* nurpvPhases\&lt;br /&gt;
$DEVICETOPIC/config/get/u1p3p/isConfigured:.* isConfigured\&lt;br /&gt;
$DEVICETOPIC/boolChargeAtNight_standby:.* boolChargeAtNight_standby\&lt;br /&gt;
$DEVICETOPIC/set/system/reloadDisplay:.* reloadDisplay\&lt;br /&gt;
$DEVICETOPIC/set/system/topicSender:.* topicSender\&lt;br /&gt;
$DEVICETOPIC/set/lp/2/faultState:.* lp_2_faultState\&lt;br /&gt;
$DEVICETOPIC/set/lp/2/faultStr:.* lp_2_faultStr\&lt;br /&gt;
$DEVICETOPIC/set/lp/2/ChargePointEnabled:.* lp_2_ChargePointEnabled&lt;br /&gt;
attr WB_1 room MQTT2_DEVICE,Strom-&amp;gt;Photovoltaik&lt;br /&gt;
attr WB_1 setList Lademodus:SofortLaden,Min+PV,NurPV,Stop,Standby { my %h=(SofortLaden=&amp;gt;&#039;0&#039;,&#039;Min+PV&#039;=&amp;gt;&#039;1&#039;,NurPV=&amp;gt;&#039;2&#039;,Stop=&amp;gt;&#039;3&#039;,Standby=&amp;gt;&#039;4&#039;);;qq($DEVICETOPIC/set/ChargeMode $h{$EVTPART1}) }\&lt;br /&gt;
DirectChargeSubMode:Aus,kWh_Laden,SoC_Laden { my %h=(Aus=&amp;gt;&#039;0&#039;,kWh_Laden=&amp;gt;&#039;1&#039;,SoC_Laden=&amp;gt;&#039;2&#039;);;qq($DEVICETOPIC/set/lp1/DirectChargeSubMode $h{$EVTPART1}) }\&lt;br /&gt;
lp_1_socToChargeTo:50,60,70,80,90,100 { qq($DEVICETOPIC/config/set/sofort/lp/1/socToChargeTo $EVTPART1) }&lt;br /&gt;
attr WB_1 sortby 311&lt;br /&gt;
attr WB_1 stateFormat {\&lt;br /&gt;
 my $YearBefore=&#039;LogDBRep_Statistic_previous_Year&#039;;;\&lt;br /&gt;
 my $DUMMY  = &amp;quot;&amp;quot;;;\&lt;br /&gt;
 my $date = POSIX::strftime(&amp;quot;%Y-%m-%d&amp;quot;,localtime(time_str2num(ReadingsTimestamp($name, &amp;quot;lastlivevalues&amp;quot;,0))));;\&lt;br /&gt;
\&lt;br /&gt;
 my $ChargeMode          = ReadingsVal($name,&amp;quot;ChargeMode&amp;quot;,&amp;quot;n/a&amp;quot;);;\&lt;br /&gt;
    $ChargeMode          = ($ChargeMode eq &amp;quot;SofortLaden&amp;quot;)? &amp;quot;&amp;lt;span style=&#039;color:red&#039;&amp;gt;SofortLaden&amp;lt;/span&amp;gt;&amp;quot; : ($ChargeMode eq &amp;quot;MinPV&amp;quot;)?  &amp;quot;&amp;lt;span style=&#039;color:orange&#039;&amp;gt;Min+PV&amp;lt;/span&amp;gt;&amp;quot; : ($ChargeMode eq &amp;quot;NurPV&amp;quot;)?  &amp;quot;&amp;lt;span style=&#039;color:green&#039;&amp;gt;NurPV&amp;lt;/span&amp;gt;&amp;quot; : $ChargeMode;;\&lt;br /&gt;
 \&lt;br /&gt;
 my $lp_1_Name           = ReadingsVal($name,&amp;quot;lp_1_strChargePointName&amp;quot;,&amp;quot;n/a&amp;quot;);;\&lt;br /&gt;
 my $lp_1_Power          = ReadingsVal($name,&amp;quot;lp_1_W&amp;quot;,0).&amp;quot; W&amp;quot;;;\&lt;br /&gt;
 my $lp_1_Power_1        = ReadingsVal($name,&amp;quot;lp_1_countPhasesInUse&amp;quot;,0).&amp;quot;P &amp;quot;.ReadingsVal($name,&amp;quot;lp_1_AConfigured&amp;quot;,0).&amp;quot;A&amp;quot;;;\&lt;br /&gt;
 my $lp_1_Status_1       = ReadingsVal($name,&amp;quot;lp_1_PlugStat&amp;quot;,&amp;quot;n/a&amp;quot;).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;.ReadingsVal($name,&amp;quot;lp_1_ChargeStat&amp;quot;,&amp;quot;n/a&amp;quot;);;\&lt;br /&gt;
 my $lp_1_Status_2       = ReadingsVal($name,&amp;quot;lp_1_TimeRemaining&amp;quot;,&amp;quot;n/a&amp;quot;);;\&lt;br /&gt;
\&lt;br /&gt;
 my $lp_1_Power_d        = ReadingsVal($name,&amp;quot;lp_1_kWhDailyCharged&amp;quot;,0).&amp;quot; kWh&amp;quot;;;\&lt;br /&gt;
 my $lp_1_Power_m        = round(ReadingsVal($name,&amp;quot;lp_1_kWhCounter_Month&amp;quot;,0),0).&amp;quot; kWh&amp;quot;;;\&lt;br /&gt;
 my $lp_1_Power_j        = sprintf(&amp;quot;%04d / %04d&amp;quot;,ReadingsVal($name,&amp;quot;lp_1_kWhCounter_Year&amp;quot;,0),ReadingsVal($YearBefore,&amp;quot;lp_1_kWhCounter_Year&amp;quot;,0));;\&lt;br /&gt;
 my $lp_1_Power_t        = round(ReadingsVal($name,&amp;quot;lp_1_kWhCounter&amp;quot;,0),0).&amp;quot; kWh&amp;quot;;;\&lt;br /&gt;
\&lt;br /&gt;
 my $lp_2_Name           = ReadingsVal($name,&amp;quot;lp_2_strChargePointName&amp;quot;,&amp;quot;n/a&amp;quot;);;\&lt;br /&gt;
 my $lp_2_Power          = ReadingsVal($name,&amp;quot;lp_2_W&amp;quot;,0).&amp;quot; W&amp;quot;;;\&lt;br /&gt;
 my $lp_2_Power_1        = ReadingsVal($name,&amp;quot;lp_2_countPhasesInUse&amp;quot;,0).&amp;quot;P &amp;quot;.ReadingsVal($name,&amp;quot;lp_2_AConfigured&amp;quot;,0).&amp;quot;A&amp;quot;;;\&lt;br /&gt;
 my $lp_2_Status_1       = ReadingsVal($name,&amp;quot;lp_2_PlugStat&amp;quot;,&amp;quot;n/a&amp;quot;).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;.ReadingsVal($name,&amp;quot;lp_2_ChargeStat&amp;quot;,&amp;quot;n/a&amp;quot;);;\&lt;br /&gt;
 my $lp_2_Status_2       = &amp;quot;&amp;lt;br&amp;gt;&amp;quot;.ReadingsVal($name,&amp;quot;lp_2_TimeRemaining&amp;quot;,&amp;quot;n/a&amp;quot;);;\&lt;br /&gt;
\&lt;br /&gt;
 my $lp_2_Power_d        = ReadingsVal($name,&amp;quot;lp_2_kWhDailyCharged&amp;quot;,0).&amp;quot; kWh&amp;quot;;;\&lt;br /&gt;
 my $lp_2_Power_m        = round(ReadingsVal($name,&amp;quot;lp_2_kWhCounter_Month&amp;quot;,0),0).&amp;quot; kWh&amp;quot;;;\&lt;br /&gt;
 my $lp_2_Power_j        = sprintf(&amp;quot;%04d / %04d&amp;quot;,ReadingsVal($name,&amp;quot;lp_2_kWhCounter_Year&amp;quot;,0),ReadingsVal($YearBefore,&amp;quot;lp_2_kWhCounter_Year&amp;quot;,0));;\&lt;br /&gt;
 my $lp_2_Power_t        = round(ReadingsVal($name,&amp;quot;lp_2_kWhCounter&amp;quot;,0),0).&amp;quot; kWh&amp;quot;;;\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;&amp;lt;html&amp;gt;&amp;lt;table border=2 bordercolor=&#039;darkgreen&#039; cellspacing=0 style=&#039;width: 100%&#039;&amp;gt;\&lt;br /&gt;
 &amp;lt;colgroup&amp;gt;\&lt;br /&gt;
   &amp;lt;col span=&#039;1&#039; style=&#039;width: 52%;;&#039;&amp;gt;\&lt;br /&gt;
   &amp;lt;col span=&#039;1&#039; style=&#039;width: 12%;;&#039;&amp;gt;\&lt;br /&gt;
   &amp;lt;col span=&#039;1&#039; style=&#039;width: 12%;;&#039;&amp;gt;\&lt;br /&gt;
   &amp;lt;col span=&#039;1&#039; style=&#039;width: 12%;;&#039;&amp;gt;\&lt;br /&gt;
   &amp;lt;col span=&#039;1&#039; style=&#039;width: 12%;;&#039;&amp;gt;\&lt;br /&gt;
 &amp;lt;/colgroup&amp;gt;\&lt;br /&gt;
 &amp;lt;tr&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;font-weight:bold&#039;&amp;gt;Wallbox&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;font-weight:bold;;text-align:center&#039;&amp;gt;$ChargeMode&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;font-weight:bold;;text-align:center&#039;&amp;gt;Status&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center;;font-weight:bold&#039;&amp;gt;Restladezeit&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center;;font-weight:bold&#039;&amp;gt;Leistung&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;\&lt;br /&gt;
 &amp;lt;tr&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold&#039;&amp;gt;&amp;amp;nbsp;;&amp;amp;nbsp;;&amp;quot;.$lp_1_Name.&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$DUMMY.&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$lp_1_Status_1.&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$lp_1_Status_2.&amp;quot;&amp;lt;br&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$lp_1_Power_1.&amp;quot;&amp;lt;br&amp;gt;&amp;quot;.$lp_1_Power.&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;\&lt;br /&gt;
 &amp;lt;tr&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold&#039;&amp;gt;&amp;amp;nbsp;;&amp;amp;nbsp;;&amp;quot;.$lp_2_Name.&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$DUMMY.&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$lp_2_Status_1.&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$lp_2_Status_2.&amp;quot;&amp;lt;br&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$lp_2_Power_1.&amp;quot;&amp;lt;br&amp;gt;&amp;quot;.$lp_2_Power.&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;\&lt;br /&gt;
 &amp;lt;tr&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;font-weight:bold&#039;&amp;gt;Statistik vom $date&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;font-weight:bold;;text-align:center&#039;&amp;gt;aktuell&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;font-weight:bold;;text-align:center&#039;&amp;gt;Heute&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;font-weight:bold;;text-align:center&#039;&amp;gt;Monat&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;font-weight:bold;;text-align:center&#039;&amp;gt;Jahr/Vorjahr&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;\&lt;br /&gt;
 &amp;lt;tr&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold&#039;&amp;gt;&amp;amp;nbsp;;&amp;amp;nbsp;;&amp;quot;.$lp_1_Name.&amp;quot;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$lp_1_Power.&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$lp_1_Power_d.&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$lp_1_Power_m.&amp;quot;&amp;lt;br&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$lp_1_Power_j.&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;\&lt;br /&gt;
 &amp;lt;tr&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold&#039;&amp;gt;&amp;amp;nbsp;;&amp;amp;nbsp;;&amp;quot;.$lp_2_Name.&amp;quot;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$lp_2_Power.&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$lp_2_Power_d.&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$lp_2_Power_m.&amp;quot;&amp;lt;br&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td style=&#039;padding-right:5px;;padding-left:5px;;text-align:center&#039;&amp;gt;&amp;quot;.$lp_2_Power_j.&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;\&lt;br /&gt;
 &amp;lt;/table&amp;gt;\&lt;br /&gt;
&amp;lt;/html&amp;gt;&amp;quot;\&lt;br /&gt;
}&lt;br /&gt;
attr WB_1 userReadings lp_1_kWhCounter_Month:lp_1_kWhCounter.* {  round(ReadingsVal(&amp;quot;$NAME&amp;quot;,&amp;quot;lp_1_kWhCounter&amp;quot;,0) - ReadingsVal(&amp;quot;$NAME&amp;quot;,&amp;quot;lp_1_kWhCounter_init_Month&amp;quot;,0),0) },\&lt;br /&gt;
lp_1_kWhCounter_Year:lp_1_kWhCounter.* {  round(ReadingsVal(&amp;quot;$NAME&amp;quot;,&amp;quot;lp_1_kWhCounter&amp;quot;,0) - ReadingsVal(&amp;quot;$NAME&amp;quot;,&amp;quot;lp_1_kWhCounter_init_Year&amp;quot;,0),0)  },\&lt;br /&gt;
\&lt;br /&gt;
lp_2_kWhCounter_Month:lp_2_kWhCounter.* {  round(ReadingsVal(&amp;quot;$NAME&amp;quot;,&amp;quot;lp_2_kWhCounter&amp;quot;,0) - ReadingsVal(&amp;quot;$NAME&amp;quot;,&amp;quot;lp_2_kWhCounter_init_Month&amp;quot;,0),0) },\&lt;br /&gt;
lp_2_kWhCounter_Year:lp_2_kWhCounter.* {  round(ReadingsVal(&amp;quot;$NAME&amp;quot;,&amp;quot;lp_2_kWhCounter&amp;quot;,0) - ReadingsVal(&amp;quot;$NAME&amp;quot;,&amp;quot;lp_2_kWhCounter_init_Year&amp;quot;,0),0)  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Kia connect MQTT=====&lt;br /&gt;
Das Kia_connect Device empfängt und sendet die MQTT Nachrichten zum Node-red Flow für das Kia BEV.&lt;br /&gt;
&lt;br /&gt;
RAW des Kia connect&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod Kia_connect MQTT2_DEVICE&lt;br /&gt;
attr Kia_connect DbLogExclude .*&lt;br /&gt;
attr Kia_connect DbLogInclude .*&lt;br /&gt;
attr Kia_connect IODev MQTT2_FHEM_Server&lt;br /&gt;
attr Kia_connect alias Kia_connect&lt;br /&gt;
attr Kia_connect autocreate 1&lt;br /&gt;
attr Kia_connect devicetopic bluelinky&lt;br /&gt;
attr Kia_connect group PV Eigenverbrauch-Steuerung&lt;br /&gt;
attr Kia_connect icon car&lt;br /&gt;
attr Kia_connect readingList $DEVICETOPIC/status:.* { json2nameValue($EVENT) }\&lt;br /&gt;
$DEVICETOPIC/location.* { json2nameValue($EVENT) }\&lt;br /&gt;
$DEVICETOPIC/odometer:.* { json2nameValue($EVENT) }\&lt;br /&gt;
$DEVICETOPIC/req_received:.* req_received\&lt;br /&gt;
$DEVICETOPIC/req_active:.* req_active&lt;br /&gt;
attr Kia_connect room MQTT2_DEVICE,Strom-&amp;gt;Photovoltaik&lt;br /&gt;
attr Kia_connect setList getOdometer req/$DEVICETOPIC/get_odometer get_odometer\&lt;br /&gt;
getStatus req/$DEVICETOPIC/get_status get_status\&lt;br /&gt;
getLocation req/$DEVICETOPIC/get_location get_location\&lt;br /&gt;
getTripinfo req/$DEVICETOPIC/get_tripinfo\&lt;br /&gt;
getAll req/$DEVICETOPIC/get_all get_all\&lt;br /&gt;
setChargeTargetSoc req/$DEVICETOPIC/set_chargetargets\&lt;br /&gt;
startCharge req/$DEVICETOPIC/start_charging start_charging\&lt;br /&gt;
stopCharge req/$DEVICETOPIC/stop_charging stop_charging\&lt;br /&gt;
stopClimate req/$DEVICETOPIC/stop_climate stop_climate\&lt;br /&gt;
startClimate req/$DEVICETOPIC/start_climate&lt;br /&gt;
attr Kia_connect sortby 402&lt;br /&gt;
attr Kia_connect stateFormat req_active&lt;br /&gt;
attr Kia_connect userReadings atHomeStanding:location.* { ((abs(AttrVal(&amp;quot;global&amp;quot;,&amp;quot;latitude&amp;quot;,49.85) - ReadingsVal($NAME,&amp;quot;location_coord_lat&amp;quot;,0)) &amp;lt;= 0.001) &amp;amp;&amp;amp; (abs(AttrVal(&amp;quot;global&amp;quot;,&amp;quot;longitude&amp;quot;,8.49) - ReadingsVal($NAME,&amp;quot;location_coord_lon&amp;quot;,0)) &amp;lt;= 0.001) &amp;amp;&amp;amp; (ReadingsVal($NAME,&amp;quot;location_speed_value&amp;quot;,1) == 0)) ? &#039;true&#039; : &#039;false&#039;;;;; },\&lt;br /&gt;
batSOC:status.* { ReadingsVal($NAME,&amp;quot;status_evStatus_batteryStatus&amp;quot;,0);;;;},\&lt;br /&gt;
connected:status.* { (ReadingsVal($NAME,&amp;quot;status_evStatus_batteryPlugin&amp;quot;,0) != 0) ? &#039;true&#039; : &#039;false&#039;;;;;},\&lt;br /&gt;
charging:status.* { ReadingsVal($NAME,&amp;quot;status_evStatus_batteryCharge&amp;quot;,&#039;false&#039;);;;;},\&lt;br /&gt;
targetSOC:status.* { ReadingsVal($NAME,&amp;quot;status_evStatus_reservChargeInfos_targetSOClist_2_targetSOClevel&amp;quot;,0);;;;},\&lt;br /&gt;
time2targetSOC:status.* { my $t = ReadingsVal($NAME,&amp;quot;status_evStatus_remainTime2_atc_value&amp;quot;,1);;;; sprintf(&amp;quot;%02d:%02d&amp;quot;, $t/60%60, $t%60);;},\&lt;br /&gt;
range:status.* { ReadingsVal($NAME,&amp;quot;status_evStatus_drvDistance_1_rangeByFuel_totalAvailableRange_value&amp;quot;,0);;;;},\&lt;br /&gt;
bat12v:status.* { ReadingsVal($NAME,&amp;quot;status_battery_batSoc&amp;quot;,0);;;;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Node-red=====&lt;br /&gt;
[[Bild:Kia Flow.PNG|mini|900px|rechts|Node-red Kia Flow]]&lt;br /&gt;
Node-red habe ich einfach in einem Docker Container runter geladen und gestartet. Über Port 1880 kommt man direkt in die GUI und kann den ersten Flow laden.&lt;br /&gt;
&lt;br /&gt;
docker-compose .yml Eintrag&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
  node-red:&lt;br /&gt;
    image: nodered/node-red:latest&lt;br /&gt;
    restart: always&lt;br /&gt;
    environment:&lt;br /&gt;
      - TZ=Europe/Berlin&lt;br /&gt;
    ports:&lt;br /&gt;
      - 1880:1880&lt;br /&gt;
    volumes:&lt;br /&gt;
      - ./node-red/data:/data&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach fehlt im Container noch folgende Erweiterung für den Node-red Flow&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
npm install node-red-contrib-bluelinky&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Kia Connect=====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Kia connect ist eine API für Kia und Hyundai E-Autos mit der man Daten vom Auto abfragen kann und auch einige Steuerungen möglich sind.&lt;br /&gt;
Mit Node-red und BlueLinky wird die Schnittstelle bedient.&lt;br /&gt;
Der Flow ist nicht ursprünglich von mir, wurde jedoch noch erweitert.&lt;br /&gt;
Vor dem Laden des Flows sind noch die persönlichen Verbindungsdaten im JSON einzutragen.&lt;br /&gt;
&lt;br /&gt;
Nach dem Laden ist ein Test mit den Inject Symbolen und der Debug Funktionalität möglich und auch sinnvoll.&lt;br /&gt;
Unterhalb der MQTT - und BlueLinky Symbole sollte &amp;quot;Verbunden&amp;quot; oder &amp;quot;Ready&amp;quot; erscheinen.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wichtig beim Kia ist, dass für das Laden über die openWB als SOC Ziel 100% im standard Modus konfiguriert wird.&#039;&#039;&#039; Ansonsten wundert man sich warum das Laden einfach nicht starten möchte. Im Default ist dort bei mir nur 50% eingetragen gewesen :-). Mit jetzt 100% kann die openWB auch selber einen Ziel SOC bestimmen, ansonsten hört das BEV einfach selber auf zu laden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin sollte man darauf achten, dass man nur eine begrenzte Anzahl von Nachrichten mit dem Kia BEV pro Tag austauschen kann. Das wurde im DOIF schon etwas berücksichtigt (1x pro Stunde), kann jedoch bei gleichzeitiger Verwendung der Handy App oder der SOC Abfrage im openWB Kia Modul auch mal zu Fehlern führen. Durch die Stündliche Status Abfrage im DOIF kommt es natürlich zu Verzögerungen im FHEM Status. Dann einfach einmal Manuell abfragen.&lt;br /&gt;
&lt;br /&gt;
Node-red JSON Import&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
[    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;tab&amp;quot;,&lt;br /&gt;
        &amp;quot;label&amp;quot;: &amp;quot;Kia e-Niro&amp;quot;,&lt;br /&gt;
        &amp;quot;disabled&amp;quot;: false,&lt;br /&gt;
        &amp;quot;info&amp;quot;: &amp;quot;&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt-broker&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;mqtt_Server&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;&amp;lt;FHEM MQTT IP Adresse&amp;gt;&amp;quot;,&lt;br /&gt;
        &amp;quot;port&amp;quot;: &amp;quot;1883&amp;quot;,&lt;br /&gt;
        &amp;quot;clientid&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;autoConnect&amp;quot;: true,&lt;br /&gt;
        &amp;quot;usetls&amp;quot;: false,&lt;br /&gt;
        &amp;quot;compatmode&amp;quot;: false,&lt;br /&gt;
        &amp;quot;protocolVersion&amp;quot;: &amp;quot;4&amp;quot;,&lt;br /&gt;
        &amp;quot;keepalive&amp;quot;: &amp;quot;60&amp;quot;,&lt;br /&gt;
        &amp;quot;cleansession&amp;quot;: true,&lt;br /&gt;
        &amp;quot;birthTopic&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;birthQos&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        &amp;quot;birthPayload&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;birthMsg&amp;quot;: {},&lt;br /&gt;
        &amp;quot;closeTopic&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;closeQos&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        &amp;quot;closePayload&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;closeMsg&amp;quot;: {},&lt;br /&gt;
        &amp;quot;willTopic&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;willQos&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        &amp;quot;willPayload&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;willMsg&amp;quot;: {},&lt;br /&gt;
        &amp;quot;sessionExpiry&amp;quot;: &amp;quot;&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;bluelinky&amp;quot;,&lt;br /&gt;
        &amp;quot;username&amp;quot;: &amp;quot;&amp;lt;Mail Adresse bei Kia&amp;gt;&amp;quot;,&lt;br /&gt;
        &amp;quot;password&amp;quot;: &amp;quot;&amp;lt;Passwort&amp;gt;&amp;quot;,&lt;br /&gt;
        &amp;quot;region&amp;quot;: &amp;quot;EU&amp;quot;,&lt;br /&gt;
        &amp;quot;pin&amp;quot;: &amp;quot;&amp;lt;Pin&amp;gt;&amp;quot;,&lt;br /&gt;
        &amp;quot;vin&amp;quot;: &amp;quot;&amp;lt;VIN&amp;gt;&amp;quot;,&lt;br /&gt;
        &amp;quot;brand&amp;quot;: &amp;quot;kia&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;91a345fa.5757a8&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt in&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;req/bluelinky/get_status&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        &amp;quot;datatype&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;inputs&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 260,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 280,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;15dfb508.c6497b&amp;quot;,&lt;br /&gt;
                &amp;quot;ce62ba4f.d86548&amp;quot;,&lt;br /&gt;
                &amp;quot;3f82a275.5a0b6e&amp;quot;,&lt;br /&gt;
                &amp;quot;24d5e0b.3aafc2&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;5ad085b9.05739c&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt in&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;req/bluelinky/start_climate&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        &amp;quot;datatype&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;nl&amp;quot;: false,&lt;br /&gt;
        &amp;quot;rap&amp;quot;: false,&lt;br /&gt;
        &amp;quot;inputs&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 270,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 680,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;b27d74de.38c808&amp;quot;,&lt;br /&gt;
                &amp;quot;33b1bc85.662694&amp;quot;,&lt;br /&gt;
                &amp;quot;ce62ba4f.d86548&amp;quot;,&lt;br /&gt;
                &amp;quot;24d5e0b.3aafc2&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;15dfb508.c6497b&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;car-status&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Get status&amp;quot;,&lt;br /&gt;
        &amp;quot;dorefresh&amp;quot;: true,&lt;br /&gt;
        &amp;quot;parsed&amp;quot;: false,&lt;br /&gt;
        &amp;quot;bluelinky&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1110,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 280,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;cccc9476.d56dd8&amp;quot;,&lt;br /&gt;
                &amp;quot;226ed925.607bb6&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;87abdd88.8ff4d&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;car-odometer&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Get car odometer&amp;quot;,&lt;br /&gt;
        &amp;quot;bluelinky&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1130,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 200,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;40d2361c.579588&amp;quot;,&lt;br /&gt;
                &amp;quot;226ed925.607bb6&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;31100f9a.40008&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;locationWrapper&amp;quot;,&lt;br /&gt;
        &amp;quot;func&amp;quot;: &amp;quot;if(msg.payload.hasOwnProperty(\&amp;quot;body\&amp;quot;)) {\n    msg.payload = {\&amp;quot;error\&amp;quot;:true};\n    return msg;\n}\nelse {\n\n    msg.payload = { \n        \&amp;quot;location\&amp;quot;: msg.payload,\n        \&amp;quot;error\&amp;quot;: false\n    };\n    \n    return msg;\n}&amp;quot;,&lt;br /&gt;
        &amp;quot;outputs&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;noerr&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;initialize&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;finalize&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;libs&amp;quot;: [],&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1490,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 120,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;85a07155.a0f9f&amp;quot;,&lt;br /&gt;
                &amp;quot;262df5dc.57916a&amp;quot;,&lt;br /&gt;
                &amp;quot;f487d6d6.a4d568&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;bea1d927.0f3908&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;car-location&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Get car location&amp;quot;,&lt;br /&gt;
        &amp;quot;bluelinky&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1120,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 120,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;31100f9a.40008&amp;quot;,&lt;br /&gt;
                &amp;quot;226ed925.607bb6&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;3c949d67.0d83b2&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt in&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;req/bluelinky/get_location&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        &amp;quot;datatype&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;nl&amp;quot;: false,&lt;br /&gt;
        &amp;quot;rap&amp;quot;: false,&lt;br /&gt;
        &amp;quot;inputs&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 270,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 120,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;bea1d927.0f3908&amp;quot;,&lt;br /&gt;
                &amp;quot;ce62ba4f.d86548&amp;quot;,&lt;br /&gt;
                &amp;quot;3f82a275.5a0b6e&amp;quot;,&lt;br /&gt;
                &amp;quot;24d5e0b.3aafc2&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;cccc9476.d56dd8&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;analyseStatus&amp;quot;,&lt;br /&gt;
        &amp;quot;func&amp;quot;: &amp;quot;if(msg.payload.hasOwnProperty(\&amp;quot;body\&amp;quot;)) {\n    msg.payload = {\&amp;quot;error\&amp;quot;:true};\n    return msg;\n}\nelse {\n    let status = msg.payload;\n    status.airTemp.value = 14+(parseInt(status.airTemp.value,16)/2);\n    try{\n    status.evStatus.reservChargeInfos.reservChargeInfo.reservChargeInfoDetail.reservFatcSet.airTemp.value = 14+(parseInt(status.evStatus.reservChargeInfos.reservChargeInfo.reservChargeInfoDetail.reservFatcSet.airTemp.value,16)/2);\n    status.evStatus.reservChargeInfos.reserveChargeInfo2.reservChargeInfoDetail.reservFatcSet.airTemp.value = 14+(parseInt(status.evStatus.reservChargeInfos.reserveChargeInfo2.reservChargeInfoDetail.reservFatcSet.airTemp.value,16)/2);\n    } catch(e) {}\n\n    let time = status.evStatus.remainTime2.atc.value/60;\n    let result = { \n                 \&amp;quot;batSOC\&amp;quot;: status.evStatus.batteryStatus,\n                 \&amp;quot;connected\&amp;quot;: (status.evStatus.batteryPlugin !== 0),\n                 \&amp;quot;charging\&amp;quot;: status.evStatus.batteryCharge,\n                 \&amp;quot;targetSOC\&amp;quot;: status.evStatus.reservChargeInfos.targetSOClist[1].targetSOClevel,\n                 \&amp;quot;time2targetSOC\&amp;quot;: (Math.floor(time) + \&amp;quot;:\&amp;quot; + (\&amp;quot;0\&amp;quot; + Math.floor((time % 1)*60)).slice(-2)), // h:mm\n                 \&amp;quot;range\&amp;quot;: status.evStatus.drvDistance[0].rangeByFuel.totalAvailableRange.value,\n                 \&amp;quot;bat12v\&amp;quot;: status.battery.batSoc\n                };\n    \n    //msg.payload = result;\n    msg.payload = {\n        \&amp;quot;status\&amp;quot;: status,\n        \&amp;quot;error\&amp;quot;: false\n        \n    };\n    return msg;\n}&amp;quot;,&lt;br /&gt;
        &amp;quot;outputs&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;noerr&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;initialize&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;finalize&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1480,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 280,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;3efceea0.c81b12&amp;quot;,&lt;br /&gt;
                &amp;quot;262df5dc.57916a&amp;quot;,&lt;br /&gt;
                &amp;quot;f487d6d6.a4d568&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;85a07155.a0f9f&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt out&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;bluelinky/location&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;retain&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1910,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 120,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;3efceea0.c81b12&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt out&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;bluelinky/status&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;retain&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1900,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 280,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;327104fc.71e1bc&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt out&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;bluelinky/odometer&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;retain&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1910,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 200,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;844a32f4.2e029&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt in&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;req/bluelinky/stop_climate&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        &amp;quot;datatype&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;inputs&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 270,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 760,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;7d3ae860.d8c9a8&amp;quot;,&lt;br /&gt;
                &amp;quot;33b1bc85.662694&amp;quot;,&lt;br /&gt;
                &amp;quot;ce62ba4f.d86548&amp;quot;,&lt;br /&gt;
                &amp;quot;24d5e0b.3aafc2&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;57d91e50.7e96&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt in&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;req/bluelinky/start_charging&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        &amp;quot;datatype&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;inputs&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 280,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 820,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;6eebc52c.ee23dc&amp;quot;,&lt;br /&gt;
                &amp;quot;33b1bc85.662694&amp;quot;,&lt;br /&gt;
                &amp;quot;ce62ba4f.d86548&amp;quot;,&lt;br /&gt;
                &amp;quot;24d5e0b.3aafc2&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;6029f0a0.b73e&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt in&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;req/bluelinky/stop_charging&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        &amp;quot;datatype&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;nl&amp;quot;: false,&lt;br /&gt;
        &amp;quot;rap&amp;quot;: false,&lt;br /&gt;
        &amp;quot;inputs&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 280,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 880,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;84a1ae.74912e5&amp;quot;,&lt;br /&gt;
                &amp;quot;33b1bc85.662694&amp;quot;,&lt;br /&gt;
                &amp;quot;ce62ba4f.d86548&amp;quot;,&lt;br /&gt;
                &amp;quot;24d5e0b.3aafc2&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;c5ecf76c.e753c8&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;start-car&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Start car&amp;quot;,&lt;br /&gt;
        &amp;quot;bluelinky&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1100,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 680,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;811aa567.e89f98&amp;quot;,&lt;br /&gt;
                &amp;quot;f487d6d6.a4d568&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;6eebc52c.ee23dc&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;start-charge&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Start Charging&amp;quot;,&lt;br /&gt;
        &amp;quot;bluelinky&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1120,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 820,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;811aa567.e89f98&amp;quot;,&lt;br /&gt;
                &amp;quot;f487d6d6.a4d568&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;84a1ae.74912e5&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;stop-charge&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Stop Charging&amp;quot;,&lt;br /&gt;
        &amp;quot;bluelinky&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1120,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 880,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;811aa567.e89f98&amp;quot;,&lt;br /&gt;
                &amp;quot;f487d6d6.a4d568&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;7d3ae860.d8c9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;stop-car&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Stop car&amp;quot;,&lt;br /&gt;
        &amp;quot;bluelinky&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1100,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 760,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;811aa567.e89f98&amp;quot;,&lt;br /&gt;
                &amp;quot;f487d6d6.a4d568&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;b27d74de.38c808&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;json&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;property&amp;quot;: &amp;quot;payload&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot;: &amp;quot;obj&amp;quot;,&lt;br /&gt;
        &amp;quot;pretty&amp;quot;: false,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 750,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 680,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;c5ecf76c.e753c8&amp;quot;,&lt;br /&gt;
                &amp;quot;33b1bc85.662694&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;45a6a8e6.2abfd8&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt in&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;req/bluelinky/get_odometer&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        &amp;quot;datatype&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;inputs&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 280,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 200,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;87abdd88.8ff4d&amp;quot;,&lt;br /&gt;
                &amp;quot;ce62ba4f.d86548&amp;quot;,&lt;br /&gt;
                &amp;quot;3f82a275.5a0b6e&amp;quot;,&lt;br /&gt;
                &amp;quot;24d5e0b.3aafc2&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;33b1bc85.662694&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;debug&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;active&amp;quot;: false,&lt;br /&gt;
        &amp;quot;tosidebar&amp;quot;: true,&lt;br /&gt;
        &amp;quot;console&amp;quot;: false,&lt;br /&gt;
        &amp;quot;tostatus&amp;quot;: false,&lt;br /&gt;
        &amp;quot;complete&amp;quot;: &amp;quot;payload&amp;quot;,&lt;br /&gt;
        &amp;quot;targetType&amp;quot;: &amp;quot;msg&amp;quot;,&lt;br /&gt;
        &amp;quot;statusVal&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;statusType&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 930,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 920,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;ce62ba4f.d86548&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt out&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;bluelinky/req_received&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;retain&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 860,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 480,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;1babee6c.1c2982&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt in&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;req/bluelinky/get_all&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        &amp;quot;datatype&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;inputs&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 250,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 360,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;ce62ba4f.d86548&amp;quot;,&lt;br /&gt;
                &amp;quot;3f82a275.5a0b6e&amp;quot;,&lt;br /&gt;
                &amp;quot;24d5e0b.3aafc2&amp;quot;,&lt;br /&gt;
                &amp;quot;4375fbb9.00fb44&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;262df5dc.57916a&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;debug&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;active&amp;quot;: false,&lt;br /&gt;
        &amp;quot;tosidebar&amp;quot;: true,&lt;br /&gt;
        &amp;quot;console&amp;quot;: false,&lt;br /&gt;
        &amp;quot;tostatus&amp;quot;: false,&lt;br /&gt;
        &amp;quot;complete&amp;quot;: &amp;quot;payload&amp;quot;,&lt;br /&gt;
        &amp;quot;targetType&amp;quot;: &amp;quot;msg&amp;quot;,&lt;br /&gt;
        &amp;quot;statusVal&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;statusType&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1850,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 80,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;811aa567.e89f98&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;debug&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;active&amp;quot;: false,&lt;br /&gt;
        &amp;quot;tosidebar&amp;quot;: true,&lt;br /&gt;
        &amp;quot;console&amp;quot;: false,&lt;br /&gt;
        &amp;quot;tostatus&amp;quot;: false,&lt;br /&gt;
        &amp;quot;complete&amp;quot;: &amp;quot;payload&amp;quot;,&lt;br /&gt;
        &amp;quot;targetType&amp;quot;: &amp;quot;msg&amp;quot;,&lt;br /&gt;
        &amp;quot;statusVal&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;statusType&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1470,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 1040,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;3f82a275.5a0b6e&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;debug&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;active&amp;quot;: false,&lt;br /&gt;
        &amp;quot;tosidebar&amp;quot;: true,&lt;br /&gt;
        &amp;quot;console&amp;quot;: false,&lt;br /&gt;
        &amp;quot;tostatus&amp;quot;: false,&lt;br /&gt;
        &amp;quot;complete&amp;quot;: &amp;quot;payload&amp;quot;,&lt;br /&gt;
        &amp;quot;targetType&amp;quot;: &amp;quot;msg&amp;quot;,&lt;br /&gt;
        &amp;quot;statusVal&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;statusType&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 930,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 80,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;24d5e0b.3aafc2&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;change&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;rules&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;t&amp;quot;: &amp;quot;set&amp;quot;,&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;payload&amp;quot;,&lt;br /&gt;
                &amp;quot;pt&amp;quot;: &amp;quot;msg&amp;quot;,&lt;br /&gt;
                &amp;quot;to&amp;quot;: &amp;quot;pending&amp;quot;,&lt;br /&gt;
                &amp;quot;tot&amp;quot;: &amp;quot;str&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;action&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;property&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;from&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;to&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;reg&amp;quot;: false,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 790,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 1140,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;4dd1ea4a.52f144&amp;quot;,&lt;br /&gt;
                &amp;quot;fecad185.324f8&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;f487d6d6.a4d568&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;change&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;rules&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;t&amp;quot;: &amp;quot;set&amp;quot;,&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;payload&amp;quot;,&lt;br /&gt;
                &amp;quot;pt&amp;quot;: &amp;quot;msg&amp;quot;,&lt;br /&gt;
                &amp;quot;to&amp;quot;: &amp;quot;idle&amp;quot;,&lt;br /&gt;
                &amp;quot;tot&amp;quot;: &amp;quot;str&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;action&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;property&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;from&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;to&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;reg&amp;quot;: false,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1910,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 760,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;4dd1ea4a.52f144&amp;quot;,&lt;br /&gt;
                &amp;quot;fecad185.324f8&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;4dd1ea4a.52f144&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt out&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;bluelinky/req_active&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;retain&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 2140,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 1100,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;fecad185.324f8&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;debug&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;active&amp;quot;: false,&lt;br /&gt;
        &amp;quot;tosidebar&amp;quot;: true,&lt;br /&gt;
        &amp;quot;console&amp;quot;: false,&lt;br /&gt;
        &amp;quot;tostatus&amp;quot;: false,&lt;br /&gt;
        &amp;quot;complete&amp;quot;: &amp;quot;false&amp;quot;,&lt;br /&gt;
        &amp;quot;statusVal&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;statusType&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 2110,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 1160,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;40d2361c.579588&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;odometerWrapper&amp;quot;,&lt;br /&gt;
        &amp;quot;func&amp;quot;: &amp;quot;if(msg.payload.hasOwnProperty(\&amp;quot;body\&amp;quot;)) {\n    msg.payload = {\&amp;quot;error\&amp;quot;:true};\n    return msg;\n}\nelse {\n    msg.payload = { \n        \&amp;quot;odometer\&amp;quot;: msg.payload,\n        \&amp;quot;error\&amp;quot;: false\n        };\n\n    return msg;\n}&amp;quot;,&lt;br /&gt;
        &amp;quot;outputs&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;noerr&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;initialize&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;finalize&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;libs&amp;quot;: [],&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1490,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 200,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;327104fc.71e1bc&amp;quot;,&lt;br /&gt;
                &amp;quot;262df5dc.57916a&amp;quot;,&lt;br /&gt;
                &amp;quot;f487d6d6.a4d568&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;226ed925.607bb6&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;debug&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;active&amp;quot;: true,&lt;br /&gt;
        &amp;quot;tosidebar&amp;quot;: true,&lt;br /&gt;
        &amp;quot;console&amp;quot;: false,&lt;br /&gt;
        &amp;quot;tostatus&amp;quot;: false,&lt;br /&gt;
        &amp;quot;complete&amp;quot;: &amp;quot;payload&amp;quot;,&lt;br /&gt;
        &amp;quot;targetType&amp;quot;: &amp;quot;msg&amp;quot;,&lt;br /&gt;
        &amp;quot;statusVal&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;statusType&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1430,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 80,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;4375fbb9.00fb44&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;car-fullstatus&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Get full status&amp;quot;,&lt;br /&gt;
        &amp;quot;dorefresh&amp;quot;: true,&lt;br /&gt;
        &amp;quot;bluelinky&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1120,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 360,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;226ed925.607bb6&amp;quot;,&lt;br /&gt;
                &amp;quot;69b6c4df.ea6bcc&amp;quot;,&lt;br /&gt;
                &amp;quot;89681a97.9e24d8&amp;quot;,&lt;br /&gt;
                &amp;quot;92dc3ff4.1d6e3&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;69b6c4df.ea6bcc&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;locationFromFullstatus&amp;quot;,&lt;br /&gt;
        &amp;quot;func&amp;quot;: &amp;quot;if(msg.payload.hasOwnProperty(\&amp;quot;body\&amp;quot;)) {\n    msg.payload = {\&amp;quot;error\&amp;quot;:true};\n    return msg;\n}\nelse {\n\n    msg.payload = { \n        \&amp;quot;location\&amp;quot;: msg.payload.vehicleLocation,\n        \&amp;quot;error\&amp;quot;: false\n    };\n    \n    return msg;\n}\n&amp;quot;,&lt;br /&gt;
        &amp;quot;outputs&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;noerr&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;initialize&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;finalize&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1500,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 360,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;85a07155.a0f9f&amp;quot;,&lt;br /&gt;
                &amp;quot;331e5860.907808&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;92dc3ff4.1d6e3&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;statusFromFullstatus&amp;quot;,&lt;br /&gt;
        &amp;quot;func&amp;quot;: &amp;quot;if(msg.payload.hasOwnProperty(\&amp;quot;body\&amp;quot;)) {\n    msg.payload = {\&amp;quot;error\&amp;quot;:true};\n    return msg;\n}\nelse {\n    let status = msg.payload.vehicleStatus;\n    try{\n        status.airTemp.value = 14+(parseInt(status.airTemp.value,16)/2);\n        status.evStatus.reservChargeInfos.reservChargeInfo.reservChargeInfoDetail.reservFatcSet.airTemp.value = 14+(parseInt(status.evStatus.reservChargeInfos.reservChargeInfo.reservChargeInfoDetail.reservFatcSet.airTemp.value,16)/2);\n        status.evStatus.reservChargeInfos.reserveChargeInfo2.reservChargeInfoDetail.reservFatcSet.airTemp.value = 14+(parseInt(status.evStatus.reservChargeInfos.reserveChargeInfo2.reservChargeInfoDetail.reservFatcSet.airTemp.value,16)/2);\n    } catch(e) {}\n\n    msg.payload = { \n        \&amp;quot;status\&amp;quot;: status,\n        \&amp;quot;error\&amp;quot;: false\n    };\n    \n    return msg;\n}\n&amp;quot;,&lt;br /&gt;
        &amp;quot;outputs&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;noerr&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;initialize&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;finalize&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1500,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 480,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;3efceea0.c81b12&amp;quot;,&lt;br /&gt;
                &amp;quot;f487d6d6.a4d568&amp;quot;,&lt;br /&gt;
                &amp;quot;331e5860.907808&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;89681a97.9e24d8&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;odometerFromFullstatus&amp;quot;,&lt;br /&gt;
        &amp;quot;func&amp;quot;: &amp;quot;if(msg.payload.hasOwnProperty(\&amp;quot;body\&amp;quot;)) {\n    msg.payload = {\&amp;quot;error\&amp;quot;:true};\n    return msg;\n}\nelse {\n\n    msg.payload = { \n        \&amp;quot;odometer\&amp;quot;: msg.payload.odometer,\n        \&amp;quot;error\&amp;quot;: false\n    };\n    \n    return msg;\n}\n&amp;quot;,&lt;br /&gt;
        &amp;quot;outputs&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;noerr&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;initialize&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;finalize&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1510,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 420,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;327104fc.71e1bc&amp;quot;,&lt;br /&gt;
                &amp;quot;331e5860.907808&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;331e5860.907808&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;debug&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;active&amp;quot;: true,&lt;br /&gt;
        &amp;quot;tosidebar&amp;quot;: true,&lt;br /&gt;
        &amp;quot;console&amp;quot;: false,&lt;br /&gt;
        &amp;quot;tostatus&amp;quot;: false,&lt;br /&gt;
        &amp;quot;complete&amp;quot;: &amp;quot;payload&amp;quot;,&lt;br /&gt;
        &amp;quot;targetType&amp;quot;: &amp;quot;msg&amp;quot;,&lt;br /&gt;
        &amp;quot;statusVal&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;statusType&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1850,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 520,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;aa4d220b.f7e19&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;set-chargetargets&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Set charge targets&amp;quot;,&lt;br /&gt;
        &amp;quot;bluelinky&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1130,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 960,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;811aa567.e89f98&amp;quot;,&lt;br /&gt;
                &amp;quot;f487d6d6.a4d568&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;4c03338d.2f15ec&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;login&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Login&amp;quot;,&lt;br /&gt;
        &amp;quot;bluelinky&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1090,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 1040,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;811aa567.e89f98&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;28b868f5.16cb48&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;inject&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;props&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;payload&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;topic&amp;quot;,&lt;br /&gt;
                &amp;quot;vt&amp;quot;: &amp;quot;str&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;repeat&amp;quot;: &amp;quot;43200&amp;quot;,&lt;br /&gt;
        &amp;quot;crontab&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;once&amp;quot;: true,&lt;br /&gt;
        &amp;quot;onceDelay&amp;quot;: &amp;quot;12&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payloadType&amp;quot;: &amp;quot;date&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 950,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 1040,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;4c03338d.2f15ec&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;db9ecdb5.a9683&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt in&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;req/bluelinky/set_chargetargets&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        &amp;quot;datatype&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;nl&amp;quot;: false,&lt;br /&gt;
        &amp;quot;rap&amp;quot;: false,&lt;br /&gt;
        &amp;quot;inputs&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 290,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 960,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;7064a8d53256b646&amp;quot;,&lt;br /&gt;
                &amp;quot;ce62ba4f.d86548&amp;quot;,&lt;br /&gt;
                &amp;quot;24d5e0b.3aafc2&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;44155ad70c47b0dd&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;inject&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;props&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;payload&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;topic&amp;quot;,&lt;br /&gt;
                &amp;quot;vt&amp;quot;: &amp;quot;str&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;repeat&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;crontab&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;once&amp;quot;: false,&lt;br /&gt;
        &amp;quot;onceDelay&amp;quot;: 0.1,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payload&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payloadType&amp;quot;: &amp;quot;date&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 940,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 260,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;15dfb508.c6497b&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;7064a8d53256b646&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;json&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;property&amp;quot;: &amp;quot;payload&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot;: &amp;quot;obj&amp;quot;,&lt;br /&gt;
        &amp;quot;pretty&amp;quot;: false,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 750,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 960,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;33b1bc85.662694&amp;quot;,&lt;br /&gt;
                &amp;quot;aa4d220b.f7e19&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;7064395e56292844&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;inject&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;props&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;payload&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;topic&amp;quot;,&lt;br /&gt;
                &amp;quot;vt&amp;quot;: &amp;quot;str&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;repeat&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;crontab&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;once&amp;quot;: false,&lt;br /&gt;
        &amp;quot;onceDelay&amp;quot;: 0.1,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payload&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payloadType&amp;quot;: &amp;quot;date&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 940,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 340,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;4375fbb9.00fb44&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;5f9ff828080f5fe6&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;lock-car&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Lock car&amp;quot;,&lt;br /&gt;
        &amp;quot;bluelinky&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1100,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 560,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;811aa567.e89f98&amp;quot;,&lt;br /&gt;
                &amp;quot;f487d6d6.a4d568&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;492f5b94a865e47b&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;inject&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;props&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;payload&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;topic&amp;quot;,&lt;br /&gt;
                &amp;quot;vt&amp;quot;: &amp;quot;str&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;repeat&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;crontab&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;once&amp;quot;: false,&lt;br /&gt;
        &amp;quot;onceDelay&amp;quot;: 0.1,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payload&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payloadType&amp;quot;: &amp;quot;date&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 940,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 540,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;5f9ff828080f5fe6&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;d6f3f148e765caf9&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt in&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;req/bluelinky/car_lock&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        &amp;quot;datatype&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;nl&amp;quot;: false,&lt;br /&gt;
        &amp;quot;rap&amp;quot;: false,&lt;br /&gt;
        &amp;quot;inputs&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 260,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 560,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;5f9ff828080f5fe6&amp;quot;,&lt;br /&gt;
                &amp;quot;ce62ba4f.d86548&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;cdc13a486db22b8e&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt in&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;req/bluelinky/car_unlock&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        &amp;quot;datatype&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;nl&amp;quot;: false,&lt;br /&gt;
        &amp;quot;rap&amp;quot;: false,&lt;br /&gt;
        &amp;quot;inputs&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 270,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 620,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;99f5c3a41ac3e754&amp;quot;,&lt;br /&gt;
                &amp;quot;ce62ba4f.d86548&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;99f5c3a41ac3e754&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;unlock-car&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Unlock car&amp;quot;,&lt;br /&gt;
        &amp;quot;bluelinky&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1110,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 620,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;f487d6d6.a4d568&amp;quot;,&lt;br /&gt;
                &amp;quot;811aa567.e89f98&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;ab557a0ea621403a&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;inject&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;props&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;payload&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;topic&amp;quot;,&lt;br /&gt;
                &amp;quot;vt&amp;quot;: &amp;quot;str&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;repeat&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;crontab&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;once&amp;quot;: false,&lt;br /&gt;
        &amp;quot;onceDelay&amp;quot;: 0.1,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payload&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payloadType&amp;quot;: &amp;quot;date&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 940,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 600,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;99f5c3a41ac3e754&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;a525de86e4374518&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;inject&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;props&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;payload&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;topic&amp;quot;,&lt;br /&gt;
                &amp;quot;vt&amp;quot;: &amp;quot;str&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;repeat&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;crontab&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;once&amp;quot;: false,&lt;br /&gt;
        &amp;quot;onceDelay&amp;quot;: 0.1,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payload&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payloadType&amp;quot;: &amp;quot;date&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 940,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 740,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;7d3ae860.d8c9a8&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;0b8cb92c042fe140&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;inject&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;props&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;payload&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;topic&amp;quot;,&lt;br /&gt;
                &amp;quot;vt&amp;quot;: &amp;quot;str&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;repeat&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;crontab&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;once&amp;quot;: false,&lt;br /&gt;
        &amp;quot;onceDelay&amp;quot;: 0.1,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payload&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payloadType&amp;quot;: &amp;quot;date&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 940,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 800,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;6eebc52c.ee23dc&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;ae4c2139b08aaa28&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;inject&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;props&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;payload&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;topic&amp;quot;,&lt;br /&gt;
                &amp;quot;vt&amp;quot;: &amp;quot;str&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;repeat&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;crontab&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;once&amp;quot;: false,&lt;br /&gt;
        &amp;quot;onceDelay&amp;quot;: 0.1,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payload&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payloadType&amp;quot;: &amp;quot;date&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 940,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 860,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;84a1ae.74912e5&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;dd23108ce63f456d&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;get-monthlyreport&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Get monthly report&amp;quot;,&lt;br /&gt;
        &amp;quot;bluelinky&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1130,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 1280,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;e57eb97531129426&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;a6e5e8deb52145f1&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;inject&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;props&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;payload&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;p&amp;quot;: &amp;quot;topic&amp;quot;,&lt;br /&gt;
                &amp;quot;vt&amp;quot;: &amp;quot;str&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;repeat&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;crontab&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;once&amp;quot;: false,&lt;br /&gt;
        &amp;quot;onceDelay&amp;quot;: 0.1,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payload&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;payloadType&amp;quot;: &amp;quot;date&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 940,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 1260,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;dd23108ce63f456d&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;95f1b6f32aafd65b&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;get-tripinfo&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Tripinfo&amp;quot;,&lt;br /&gt;
        &amp;quot;bluelinky&amp;quot;: &amp;quot;452a3304.58c8fc&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1100,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 1220,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;e57eb97531129426&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;fb2b99958bc48593&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;json&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;property&amp;quot;: &amp;quot;payload&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;pretty&amp;quot;: false,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 750,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 1220,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;95f1b6f32aafd65b&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;5230ebe391325b17&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt in&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;req/bluelinky/get_tripinfo&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
        &amp;quot;datatype&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;nl&amp;quot;: false,&lt;br /&gt;
        &amp;quot;rap&amp;quot;: true,&lt;br /&gt;
        &amp;quot;rh&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;inputs&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 270,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 1220,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;fb2b99958bc48593&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;e57eb97531129426&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;debug&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;active&amp;quot;: false,&lt;br /&gt;
        &amp;quot;tosidebar&amp;quot;: true,&lt;br /&gt;
        &amp;quot;console&amp;quot;: false,&lt;br /&gt;
        &amp;quot;tostatus&amp;quot;: false,&lt;br /&gt;
        &amp;quot;complete&amp;quot;: &amp;quot;payload&amp;quot;,&lt;br /&gt;
        &amp;quot;targetType&amp;quot;: &amp;quot;msg&amp;quot;,&lt;br /&gt;
        &amp;quot;statusVal&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;statusType&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 1470,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 1220,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: &amp;quot;4fdf3b1b7811c89f&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;mqtt in&amp;quot;,&lt;br /&gt;
        &amp;quot;z&amp;quot;: &amp;quot;866c75dd.edd9a8&amp;quot;,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;topic&amp;quot;: &amp;quot;req/bluelinky/get_tripinfo&amp;quot;,&lt;br /&gt;
        &amp;quot;qos&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
        &amp;quot;datatype&amp;quot;: &amp;quot;auto&amp;quot;,&lt;br /&gt;
        &amp;quot;broker&amp;quot;: &amp;quot;bb13a99d.68b8f8&amp;quot;,&lt;br /&gt;
        &amp;quot;nl&amp;quot;: false,&lt;br /&gt;
        &amp;quot;rap&amp;quot;: true,&lt;br /&gt;
        &amp;quot;rh&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;inputs&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;x&amp;quot;: 270,&lt;br /&gt;
        &amp;quot;y&amp;quot;: 1280,&lt;br /&gt;
        &amp;quot;wires&amp;quot;: [&lt;br /&gt;
            [&lt;br /&gt;
                &amp;quot;dd23108ce63f456d&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Kia_eNiro_PV DOIF mit uiTable=====&lt;br /&gt;
Mit diesem DOIF Device werden folgende Funktionalitäten abgebildet:&lt;br /&gt;
Nun dann noch das DOIF mit dem uiTable für die Status Anzeige und die Steuerung über Pull Down Menüs.&lt;br /&gt;
&lt;br /&gt;
- Status Abfrage&lt;br /&gt;
     Status jede Stunde zwischen 6 und 23 Uhr (12V min 40%)&lt;br /&gt;
     Status beim Laden alle 15 Minuten (12V min 40%)&lt;br /&gt;
     Anzeige des Kilometerzählers&lt;br /&gt;
     Status des Fahrzeuges zu Hause / unterwegs und beim Laden&lt;br /&gt;
     Fahrzeug Auf/Zu&lt;br /&gt;
&lt;br /&gt;
- Klimatisierung über das Pull Down Menü&lt;br /&gt;
     unterschiedliche Temperaturen für Heizen und Kühlen&lt;br /&gt;
     Aktuelle Temperatur&lt;br /&gt;
     Heizen/Klima Ein/Aus&lt;br /&gt;
     Timer für zeitgesteuertes Klimatisieren für den Resttag oder den Nächsten Tag (vor der aktuellen Zeit)&lt;br /&gt;
     Klimatisierung über &amp;quot;Abfall&amp;quot; Kalender (es geht nur ein Termin pro Tag, dafür aber komfortabel über das Handy)&lt;br /&gt;
&lt;br /&gt;
- Komfort&lt;br /&gt;
     Reifen Überwachung&lt;br /&gt;
     Türen / Motorhaube / Kofferraum Überwachung&lt;br /&gt;
     12V Batterie anzeige, wenn der Ladezustand kleiner 40% ist erfolgt keine weitere Status Abfrage&lt;br /&gt;
&lt;br /&gt;
- ACCU Steuerung&lt;br /&gt;
    Setzen des Ziel SOC beim Standard Laden&lt;br /&gt;
    Start/Stop Laden&lt;br /&gt;
    Accu Stand und berechnete Restkilometer&lt;br /&gt;
&lt;br /&gt;
- Für openWB integratin im uiTable&lt;br /&gt;
    Wählen des Lademodus&lt;br /&gt;
    Vorrang EV oder Bat&lt;br /&gt;
    Sperren des Hausspeichers entweder manuell oder automatisch beim Laden. Der vorherige Zustand wird gespeichert&lt;br /&gt;
        Die Freigabe erfolgt über die Wechselrichter Implementierung, siehe dort [[Kostal_Plenticore_10_Plus#Externe_Speichersteuerung_.28ExternControl.29|&amp;quot;Externe Speicher Steuerung&amp;quot;]]&lt;br /&gt;
    Geschätzte Ladezeit&lt;br /&gt;
    Status Ladepunkt (Plug und Laden)&lt;br /&gt;
    Lade Status Phasen und Leistung   &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung, die Kia connect Abfragen sind auf ca. 200 pro Tag von Kia limitiert! Durch die Stündliche Status Abfrage im DOIF kommt es natürlich zu Verzögerungen im FHEM Status. Dann einfach einmal manuell abfragen.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Die Kommunikation zum Kia BEV ist manchmal sehr träge, z.B. kann eine Status Abfrage auch mal 3 Minuten dauern, deshalb wurde eine Verriegelung implementiert. Es wird ein Status pending/idle angezeigt. Nur wenn der Zustand &amp;quot;idel&amp;quot; ist, können weitere Abfragen gestartet werden. Läuft z.B. die Status Abfrage kann man ein weiteres Kommando anstarten, es wird jedoch erst abgesetzt, wenn das vorherige Kommando fertig ist. Solange bleibt im Pull Down Menü das neue Kommando stehen.&lt;br /&gt;
&lt;br /&gt;
RAW des DOIF&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod Kia_eNiro_PV DOIF ################################################################################################################\&lt;br /&gt;
## 1 Kia Connect Status Abfrage erfolgt mit MQTT2 ==&amp;gt; node-ret ==&amp;gt; Kia Connect\&lt;br /&gt;
##\&lt;br /&gt;
1_Status_getAll\&lt;br /&gt;
{if( !([$SELF:state] eq &amp;quot;off&amp;quot;)                                         ## DOIF enabled\&lt;br /&gt;
     and [Kia_connect:req_active] eq &amp;quot;idle&amp;quot;\&lt;br /&gt;
     and\&lt;br /&gt;
     (  ([+00:15] and                                                  ## alle 15 Minuten\&lt;br /&gt;
         [Kia_connect:atHomeStanding] eq &amp;quot;true&amp;quot; and                    ##   wenn das Auto zuhause ist\&lt;br /&gt;
         [Kia_connect:charging]       eq &amp;quot;true&amp;quot; or                     ##   und es geladen wird\&lt;br /&gt;
         [:58] and [05:00-23:00]                                       ## ansonsten nur jede Stunde\&lt;br /&gt;
        ) and [Kia_connect:bat12v] &amp;gt; 40                                ## aber die 12V Batterie sollte noch genügend Ladung haben\&lt;br /&gt;
      or [$SELF:cmd_event]  eq &amp;quot;set_cmd_1&amp;quot;                             ## Das reagiert auf den Aufruf mit &amp;quot;set &amp;lt;Device&amp;gt; cmd_*&amp;quot;\&lt;br /&gt;
      or [$SELF:ui_command_1] eq &amp;quot;Status_getAll&amp;quot;                       ## Hier wird das uiTable select ausgewertet\&lt;br /&gt;
     )\&lt;br /&gt;
   ) {\&lt;br /&gt;
    if( [$SELF:ui_command_1] eq &amp;quot;Status_getAll&amp;quot; ) {                    ## Hier wurde manuell eingeschaltet\&lt;br /&gt;
      set_Reading(&amp;quot;ui_command_before_1&amp;quot;,[$SELF:ui_command_1]);;\&lt;br /&gt;
    }\&lt;br /&gt;
\&lt;br /&gt;
    fhem_set(&amp;quot;Kia_connect getAll&amp;quot;);;                                    ## beliebige Kommandos für diesen Block\&lt;br /&gt;
\&lt;br /&gt;
    set_Reading(&amp;quot;ui_command_1&amp;quot;,&amp;quot;---&amp;quot;);;                                 ## Hier wird das uiTable select wieder zurückgesetzt, ansonsten\&lt;br /&gt;
                                                                       ## kann das Kommando nicht sofort wiederholt werden\&lt;br /&gt;
  }\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
2_Klima\&lt;br /&gt;
{if( !([$SELF:state] eq &amp;quot;off&amp;quot;)                                         ## DOIF enabled\&lt;br /&gt;
     and [Kia_connect:req_active] eq &amp;quot;idle&amp;quot;\&lt;br /&gt;
     and\&lt;br /&gt;
     (   [$SELF:ui_command_2] eq &amp;quot;stopClimate&amp;quot;                         ## Hier wird das uiTable select ausgewertet\&lt;br /&gt;
      or [$SELF:ui_command_2] eq &amp;quot;startHeating&amp;quot;\&lt;br /&gt;
      or [$SELF:ui_command_2] eq &amp;quot;startCooling&amp;quot;\&lt;br /&gt;
     )\&lt;br /&gt;
   ) {\&lt;br /&gt;
    set_Reading(&amp;quot;ui_command_before_2&amp;quot;,[$SELF:ui_command_2]);;\&lt;br /&gt;
\&lt;br /&gt;
    if ([$SELF:ui_command_2] eq &amp;quot;startHeating&amp;quot;) {\&lt;br /&gt;
      my $airTemp_value= [Kia_connect:status_airTemp_value_target_Winter];;\&lt;br /&gt;
      fhem_set(&#039;Kia_connect startClimate {&amp;quot;defrost&amp;quot;: true, &amp;quot;windscreenHeating&amp;quot;: true, &amp;quot;temperature&amp;quot;: &#039;.$airTemp_value.&#039; , &amp;quot;unit&amp;quot;: &amp;quot;C&amp;quot;}&#039;);;\&lt;br /&gt;
      if (AttrVal(&amp;quot;$SELF&amp;quot;,&amp;quot;verbose&amp;quot;,0) &amp;gt;= 0)\&lt;br /&gt;
         {Log 3, &amp;quot;$SELF 2_Klima       : startHeating&amp;quot;};;\&lt;br /&gt;
    }\&lt;br /&gt;
    if ([$SELF:ui_command_2] eq &amp;quot;startCooling&amp;quot;) {\&lt;br /&gt;
      my $airTemp_value = [Kia_connect:status_airTemp_value_target_Summer];;\&lt;br /&gt;
      fhem_set(&#039;Kia_connect startClimate {&amp;quot;defrost&amp;quot;: false, &amp;quot;windscreenHeating&amp;quot;: false, &amp;quot;temperature&amp;quot;: &#039;.$airTemp_value.&#039; , &amp;quot;unit&amp;quot;: &amp;quot;C&amp;quot;}&#039;);;\&lt;br /&gt;
      if (AttrVal(&amp;quot;$SELF&amp;quot;,&amp;quot;verbose&amp;quot;,0) &amp;gt;= 0)\&lt;br /&gt;
         {Log 3, &amp;quot;$SELF 2_Klima       : startCooling&amp;quot;};;\&lt;br /&gt;
    }\&lt;br /&gt;
    if ([$SELF:ui_command_2] eq &amp;quot;stopClimate&amp;quot;) {\&lt;br /&gt;
      fhem_set(&amp;quot;Kia_connect &amp;quot;.[$SELF:ui_command_2]);;\&lt;br /&gt;
      if (AttrVal(&amp;quot;$SELF&amp;quot;,&amp;quot;verbose&amp;quot;,0) &amp;gt;= 0)\&lt;br /&gt;
         {Log 3, &amp;quot;$SELF 2_Klima       : stopClimate&amp;quot;};;\&lt;br /&gt;
    }\&lt;br /&gt;
    fhem_set(&amp;quot;Abfall update&amp;quot;);;\&lt;br /&gt;
\&lt;br /&gt;
    set_Reading(&amp;quot;ui_command_2&amp;quot;,&amp;quot;---&amp;quot;);;                                 ## Hier wird das uiTable select wieder zurückgesetzt, ansonsten\&lt;br /&gt;
                                                                       ## kann das Kommando nicht sofort wiederholt werden\&lt;br /&gt;
  }\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
3_Laden\&lt;br /&gt;
{if( !([$SELF:state] eq &amp;quot;off&amp;quot;)                                         ## DOIF enabled\&lt;br /&gt;
     and [Kia_connect:req_active] eq &amp;quot;idle&amp;quot;\&lt;br /&gt;
     and\&lt;br /&gt;
     (   [$SELF:ui_command_3] eq &amp;quot;setChargeTargetSoc&amp;quot;                  ## Hier wird das uiTable select ausgewertet\&lt;br /&gt;
      or [$SELF:ui_command_3] eq &amp;quot;startCharge&amp;quot;\&lt;br /&gt;
      or [$SELF:ui_command_3] eq &amp;quot;stopCharge&amp;quot;\&lt;br /&gt;
     )\&lt;br /&gt;
   ) {\&lt;br /&gt;
    set_Reading(&amp;quot;ui_command_before_3&amp;quot;,[$SELF:ui_command_3]);;\&lt;br /&gt;
\&lt;br /&gt;
    if ([$SELF:ui_command_3] eq &amp;quot;setChargeTargetSoc&amp;quot;) {\&lt;br /&gt;
      my $targetSOClist_1_targetSOClevel = [Kia_connect:status_evStatus_reservChargeInfos_targetSOClist_1_targetSOClevel_target];;\&lt;br /&gt;
      my $targetSOClist_2_targetSOClevel = [Kia_connect:status_evStatus_reservChargeInfos_targetSOClist_2_targetSOClevel_target];;\&lt;br /&gt;
      fhem_set(&amp;quot;Kia_connect setChargeTargetSoc {\&amp;quot;fast\&amp;quot;: &amp;quot;.$targetSOClist_1_targetSOClevel.&amp;quot;, \&amp;quot;slow\&amp;quot;: &amp;quot;.$targetSOClist_2_targetSOClevel.&amp;quot;}&amp;quot;);;\&lt;br /&gt;
    } else {\&lt;br /&gt;
      fhem_set(&amp;quot;Kia_connect &amp;quot;.[$SELF:ui_command_3]);;                   ## beliebige Kommandos für diesen Block\&lt;br /&gt;
    }\&lt;br /&gt;
\&lt;br /&gt;
    set_Reading(&amp;quot;ui_command_3&amp;quot;,&amp;quot;---&amp;quot;);;                                 ## Hier wird das uiTable select wieder zurückgesetzt, ansonsten\&lt;br /&gt;
                                                                       ## kann das Kommando nicht sofort wiederholt werden\&lt;br /&gt;
  }\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
4_Klima_timer_heizen\&lt;br /&gt;
{if( !([$SELF:state] eq &amp;quot;off&amp;quot;)                                         ## DOIF enabled\&lt;br /&gt;
     and\&lt;br /&gt;
     (\&lt;br /&gt;
       (    [[Abfall_Abfuhr:Kiaheizen_connect_time]]                   ## Prüfe den Kalender Eintrag\&lt;br /&gt;
        and [Abfall_Abfuhr:Kiaheizen_connect_date] eq $ymd             ##   ist es heute?\&lt;br /&gt;
       )\&lt;br /&gt;
       or\&lt;br /&gt;
       (    [$SELF:ui_timer_mode] eq &amp;quot;heizen&amp;quot;                          ## Timer zum Heizen aktiv?\&lt;br /&gt;
        and [[$SELF:ui_timer_Start]]                                   ##   ist es soweit?\&lt;br /&gt;
       )\&lt;br /&gt;
     )\&lt;br /&gt;
   ) {\&lt;br /&gt;
\&lt;br /&gt;
    if (AttrVal(&amp;quot;$SELF&amp;quot;,&amp;quot;verbose&amp;quot;,0) &amp;gt;= 0)\&lt;br /&gt;
       {Log 3, &amp;quot;$SELF 4_Klima_timer : startHeating&amp;quot;};;\&lt;br /&gt;
    set_Reading(&amp;quot;ui_timer_mode&amp;quot;,&amp;quot;Aus&amp;quot;);;                                ## Schalte die Timer Funktion ab\&lt;br /&gt;
    set_Reading(&amp;quot;ui_command_2&amp;quot;,&amp;quot;startHeating&amp;quot;);;                        ## Es soll geheizt werden\&lt;br /&gt;
    fhem_set(&amp;quot;$SELF 2_Klima&amp;quot;);;                                         ## Aktiviere das Heizen\&lt;br /&gt;
\&lt;br /&gt;
  }\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
5_Klima_timer_kuehlen\&lt;br /&gt;
{if( !([$SELF:state] eq &amp;quot;off&amp;quot;)                                         ## DOIF enabled\&lt;br /&gt;
     and\&lt;br /&gt;
     (\&lt;br /&gt;
       (    [[Abfall_Abfuhr:Kiakuehlen_connect_time]]                  ## Prüfe den Kalender Eintrag\&lt;br /&gt;
        and [Abfall_Abfuhr:Kiakuehlen_connect_date] eq $ymd            ##   ist es heute?\&lt;br /&gt;
       )\&lt;br /&gt;
       or\&lt;br /&gt;
       (    [$SELF:ui_timer_mode] eq &amp;quot;kuehlen&amp;quot;                         ## Timer zum Kühler aktiv?\&lt;br /&gt;
        and [[$SELF:ui_timer_Start]]                                   ##   ist es soweit?\&lt;br /&gt;
       )\&lt;br /&gt;
     )\&lt;br /&gt;
   ) {\&lt;br /&gt;
\&lt;br /&gt;
    if (AttrVal(&amp;quot;$SELF&amp;quot;,&amp;quot;verbose&amp;quot;,0) &amp;gt;= 0)\&lt;br /&gt;
       {Log 3, &amp;quot;$SELF 4_Klima_timer : startCooling&amp;quot;};;\&lt;br /&gt;
    set_Reading(&amp;quot;ui_timer_mode&amp;quot;,&amp;quot;Aus&amp;quot;);;                                ## Schalte die Timer Funktion ab\&lt;br /&gt;
    set_Reading(&amp;quot;ui_command_2&amp;quot;,&amp;quot;startCooling&amp;quot;);;                        ## Es soll gekühlt werden\&lt;br /&gt;
    fhem_set(&amp;quot;$SELF 2_Klima&amp;quot;);;                                         ## Aktiviere das Kühlen\&lt;br /&gt;
\&lt;br /&gt;
  }\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
6_Auf_Zu\&lt;br /&gt;
{if( !([$SELF:state] eq &amp;quot;off&amp;quot;)                                         ## DOIF enabled\&lt;br /&gt;
     and [Kia_connect:req_active] eq &amp;quot;idle&amp;quot;\&lt;br /&gt;
     and\&lt;br /&gt;
     (   [$SELF:ui_command_2] eq &amp;quot;car_lock&amp;quot;                            ## Hier wird das uiTable select ausgewertet\&lt;br /&gt;
      or [$SELF:ui_command_2] eq &amp;quot;car_unlock&amp;quot;\&lt;br /&gt;
     )\&lt;br /&gt;
   ) {\&lt;br /&gt;
    set_Reading(&amp;quot;ui_command_before_2&amp;quot;,[$SELF:ui_command_2]);;\&lt;br /&gt;
\&lt;br /&gt;
    fhem_set(&amp;quot;Kia_connect &amp;quot;.[$SELF:ui_command_2]);;\&lt;br /&gt;
    if (AttrVal(&amp;quot;$SELF&amp;quot;,&amp;quot;verbose&amp;quot;,0) &amp;gt;= 0)\&lt;br /&gt;
       {Log 3, &amp;quot;$SELF 6_Auf_Zu      : &amp;quot;.[$SELF:ui_command_2]};;\&lt;br /&gt;
\&lt;br /&gt;
    set_Reading(&amp;quot;ui_command_2&amp;quot;,&amp;quot;---&amp;quot;);;                                 ## Hier wird das uiTable select wieder zurückgesetzt, ansonsten\&lt;br /&gt;
                                                                       ## kann das Kommando nicht sofort wiederholt werden\&lt;br /&gt;
  }\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
7_WB_1_lp_1\&lt;br /&gt;
{if( !([$SELF:state] eq &amp;quot;off&amp;quot;)                                         ## DOIF enabled\&lt;br /&gt;
     and\&lt;br /&gt;
     (   [$SELF:ui_command_4] eq &amp;quot;SofortLaden&amp;quot;                         ## Hier wird das uiTable select ausgewertet\&lt;br /&gt;
      or [$SELF:ui_command_4] eq &amp;quot;Min+PV&amp;quot;\&lt;br /&gt;
      or [$SELF:ui_command_4] eq &amp;quot;NurPV&amp;quot;\&lt;br /&gt;
      or [$SELF:ui_command_4] eq &amp;quot;Stop&amp;quot;\&lt;br /&gt;
      or [$SELF:ui_command_4] eq &amp;quot;Standby&amp;quot;\&lt;br /&gt;
      or [$SELF:ui_command_4] eq &amp;quot;Vorrang_EV&amp;quot;\&lt;br /&gt;
      or [$SELF:ui_command_4] eq &amp;quot;Vorrang_Bat&amp;quot;\&lt;br /&gt;
     )\&lt;br /&gt;
   ) {\&lt;br /&gt;
    set_Reading(&amp;quot;ui_command_before_4&amp;quot;,[$SELF:ui_command_4]);;\&lt;br /&gt;
\&lt;br /&gt;
    if ([$SELF:ui_command_4] eq &amp;quot;Vorrang_Bat&amp;quot; OR [$SELF:ui_command_4] eq &amp;quot;Vorrang_EV&amp;quot;) {\&lt;br /&gt;
      if ([$SELF:ui_command_4] eq &amp;quot;Vorrang_EV&amp;quot;) {\&lt;br /&gt;
        fhem_set(&amp;quot;WB_1 priorityModeEVBattery 1&amp;quot;);;\&lt;br /&gt;
      } else {\&lt;br /&gt;
        fhem_set(&amp;quot;WB_1 priorityModeEVBattery 0&amp;quot;);;\&lt;br /&gt;
      }\&lt;br /&gt;
      if (AttrVal(&amp;quot;$SELF&amp;quot;,&amp;quot;verbose&amp;quot;,0) &amp;gt;= 0)\&lt;br /&gt;
         {Log 3, &amp;quot;$SELF 7_WB_1_lp_1    : &amp;quot;.[$SELF:ui_command_4]};;\&lt;br /&gt;
    } else {\&lt;br /&gt;
      fhem_set(&amp;quot;WB_1 Lademodus &amp;quot;.[$SELF:ui_command_4]);;\&lt;br /&gt;
      if (AttrVal(&amp;quot;$SELF&amp;quot;,&amp;quot;verbose&amp;quot;,0) &amp;gt;= 0)\&lt;br /&gt;
         {Log 3, &amp;quot;$SELF 7_WB_1_lp_1    : Lademodus &amp;quot;.[$SELF:ui_command_4]};;\&lt;br /&gt;
    }\&lt;br /&gt;
\&lt;br /&gt;
    set_Reading(&amp;quot;ui_command_4&amp;quot;,&amp;quot;---&amp;quot;);;                                 ## Hier wird das uiTable select wieder zurückgesetzt, ansonsten\&lt;br /&gt;
                                                                       ## kann das Kommando nicht sofort wiederholt werden\&lt;br /&gt;
  }\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
8_Speicher_sperren\&lt;br /&gt;
{if( !([$SELF:state] eq &amp;quot;off&amp;quot;)                                         ## DOIF enabled\&lt;br /&gt;
     and\&lt;br /&gt;
     (   [$SELF:ui_command_4]   eq &amp;quot;Hausspeicher_Sperren&amp;quot;              ## Hier wird das uiTable select ausgewertet\&lt;br /&gt;
      or [WB_1:lp_1_ChargeStat] eq &amp;quot;loading&amp;quot; and\&lt;br /&gt;
         [WB_1:lp_1_PlugStat]   eq &amp;quot;Plugged in&amp;quot;\&lt;br /&gt;
     )\&lt;br /&gt;
   ) {\&lt;br /&gt;
    set_Reading(&amp;quot;ui_command_before_4&amp;quot;,[$SELF:ui_command_4]);;\&lt;br /&gt;
\&lt;br /&gt;
    if([$SELF:WR_1_Speicher_1_ExternControl_smart_laden_before] eq &amp;quot;---&amp;quot;) {\&lt;br /&gt;
\&lt;br /&gt;
      if([$SELF:SpeicherExternTrigger] eq &amp;quot;gesperrt&amp;quot; and\&lt;br /&gt;
         [WR_1_API:Battery_InternControl_MinHomeConsumption] eq &amp;quot;30000&amp;quot; ) {\&lt;br /&gt;
        set_Reading(&amp;quot;WR_1_Speicher_1_ExternControl_smart_laden_before&amp;quot;,&amp;quot;aktiv&amp;quot;);;\&lt;br /&gt;
        if (AttrVal(&amp;quot;$SELF&amp;quot;,&amp;quot;verbose&amp;quot;,0) &amp;gt;= 0)\&lt;br /&gt;
           {Log 3, &amp;quot;$SELF 8_Speicher_sperren : smart_laden_before aktiv&amp;quot;};;\&lt;br /&gt;
      } else {\&lt;br /&gt;
        set_Reading(&amp;quot;WR_1_Speicher_1_ExternControl_smart_laden_before&amp;quot;,&amp;quot;inaktiv&amp;quot;);;\&lt;br /&gt;
        if (AttrVal(&amp;quot;$SELF&amp;quot;,&amp;quot;verbose&amp;quot;,0) &amp;gt;= 0)\&lt;br /&gt;
           {Log 3, &amp;quot;$SELF 8_Speicher_sperren : smart_laden_before inaktiv&amp;quot;};;\&lt;br /&gt;
      }\&lt;br /&gt;
\&lt;br /&gt;
      fhem_set(&amp;quot;WR_1_Speicher_1_ExternControl cmd_2&amp;quot;);;\&lt;br /&gt;
      if (AttrVal(&amp;quot;$SELF&amp;quot;,&amp;quot;verbose&amp;quot;,0) &amp;gt;= 0)\&lt;br /&gt;
         {Log 3, &amp;quot;$SELF 8_Speicher_sperren : smart_Laden startet&amp;quot;};;\&lt;br /&gt;
    }\&lt;br /&gt;
\&lt;br /&gt;
    set_Reading(&amp;quot;ui_command_4&amp;quot;,&amp;quot;---&amp;quot;);;                                 ## Hier wird das uiTable select wieder zurückgesetzt, ansonsten\&lt;br /&gt;
                                                                       ## kann das Kommando nicht sofort wiederholt werden\&lt;br /&gt;
  }\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
9_WB_1_Zaehler_Statistiken\&lt;br /&gt;
{if( !([$SELF:state] eq &amp;quot;off&amp;quot;) and                                     ## DOIF enabled\&lt;br /&gt;
     [00:01]\&lt;br /&gt;
   ) {\&lt;br /&gt;
    fhem(&amp;quot;setreading WB_1 lp_1_kWhCounter_init_Day &amp;quot;.[WB_1:lp_1_kWhCounter]);;\&lt;br /&gt;
    fhem(&amp;quot;setreading WB_1 lp_2_kWhCounter_init_Day &amp;quot;.[WB_1:lp_2_kWhCounter]);;\&lt;br /&gt;
\&lt;br /&gt;
    if ($mday eq 1)\&lt;br /&gt;
     {\&lt;br /&gt;
      fhem(&amp;quot;setreading WB_1 lp_1_kWhCounter_init_Month &amp;quot;.[WB_1:lp_1_kWhCounter]);;\&lt;br /&gt;
      fhem(&amp;quot;setreading WB_1 lp_2_kWhCounter_init_Month &amp;quot;.[WB_1:lp_2_kWhCounter]);;\&lt;br /&gt;
\&lt;br /&gt;
      if ($yday eq 0)\&lt;br /&gt;
        {\&lt;br /&gt;
         fhem(&amp;quot;setreading WB_1 lp_1_kWhCounter_init_Year &amp;quot;.[WB_1:lp_1_kWhCounter]);;\&lt;br /&gt;
         fhem(&amp;quot;setreading WB_1 lp_2_kWhCounter_init_Year &amp;quot;.[WB_1:lp_2_kWhCounter]);;\&lt;br /&gt;
        }\&lt;br /&gt;
     }\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
attr Kia_eNiro_PV DbLogExclude .*&lt;br /&gt;
attr Kia_eNiro_PV disable 0&lt;br /&gt;
attr Kia_eNiro_PV group PV Eigenverbrauch-Steuerung&lt;br /&gt;
attr Kia_eNiro_PV icon car&lt;br /&gt;
attr Kia_eNiro_PV room Strom-&amp;gt;Photovoltaik&lt;br /&gt;
attr Kia_eNiro_PV sortby 401&lt;br /&gt;
attr Kia_eNiro_PV uiTable {\&lt;br /&gt;
package ui_Table;;\&lt;br /&gt;
##  $TR{0} = &amp;quot;style=&#039;color:yellow;;text-align:left;;font-weight:bold;;font-size:18px&#039;&amp;quot;;;                                                         ## Reihe 0 für Überschrift\&lt;br /&gt;
  $TABLE = &amp;quot;style=&#039;width:100%;;&#039;&amp;quot;;;\&lt;br /&gt;
\&lt;br /&gt;
  $TD{0..9}{0}     = &amp;quot;align=&#039;center&#039; style=&#039;font-size:16px;;border-right-style:solid;;border-color:darkgreen;;border-right-width:2px;;width:26%&#039;&amp;quot;;;\&lt;br /&gt;
\&lt;br /&gt;
  $TD{0..9}{1} = &amp;quot;style=&#039;border-top-style:solid;;border-bottom-style:solid;;border-right-style:solid;;border-color:darkgreen;;border-top-width:2px;;border-bottom-width:2px;;border-right-width:1px;;width:36%;;font-weight:bold;;&#039;&amp;quot;;;\&lt;br /&gt;
  $TD{0..9}{2..4} = &amp;quot;style=&#039;border-top-style:solid;;border-bottom-style:solid;;border-right-style:solid;;border-color:darkgreen;;border-top-width:2px;;border-bottom-width:2px;;border-right-width:1px;;width:8%;;text-align:center;;&#039;&amp;quot;;;\&lt;br /&gt;
  $TD{0..9}{5} = &amp;quot;style=&#039;border-top-style:solid;;border-bottom-style:solid;;border-right-style:solid;;border-color:darkgreen;;border-top-width:2px;;border-bottom-width:2px;;border-right-width:2px;;width:8%;;text-align:center;;&#039;&amp;quot;;;\&lt;br /&gt;
\&lt;br /&gt;
sub FUNC_batt {\&lt;br /&gt;
    my($val)=@_;;\&lt;br /&gt;
    my $ret=&amp;quot;position:absolute;;left:&amp;quot;.(90*$val/100).&amp;quot;px;;width:90px;;height:20px;;background:linear-gradient( to right,#F8F8E0 &amp;quot;.(90-(90*$val/100)).&amp;quot;px,rgba(0,0,0,0) &amp;quot;.(90-(90*$val/100)).&amp;quot;px);;&amp;quot;;;\&lt;br /&gt;
    return $ret;;\&lt;br /&gt;
  }\&lt;br /&gt;
sub FUNC_Status {\&lt;br /&gt;
    my($value, $min, $colorMin,  $statusMin,  $colorMiddel, $statusMiddle, $max, $colorMax, $statusMax)=@_;;\&lt;br /&gt;
    my $ret = ($value &amp;lt; $min)? &#039;&amp;lt;span style=&amp;quot;color:&#039;.$colorMin.&#039;&amp;quot;&amp;gt;&#039;.$statusMin.&#039;&amp;lt;/span&amp;gt;&#039; : ($value &amp;gt; $max)? &#039;&amp;lt;span style=&amp;quot;color:&#039;.$colorMax.&#039;&amp;quot;&amp;gt;&#039;.$statusMax.&#039;&amp;lt;/span&amp;gt;&#039; : &#039;&amp;lt;span style=&amp;quot;color:&#039;.$colorMiddel.&#039;&amp;quot;&amp;gt;&#039;.$statusMiddle.&#039;&amp;lt;/span&amp;gt;&#039;;;\&lt;br /&gt;
    return $ret;;\&lt;br /&gt;
  }\&lt;br /&gt;
sub FUNC_Status_Laden {\&lt;br /&gt;
   my($car)=@_;;\&lt;br /&gt;
   my $charge = (::ReadingsVal($car,&amp;quot;charging&amp;quot;,&amp;quot;false&amp;quot;) eq &amp;quot;true&amp;quot;);;\&lt;br /&gt;
   my $athome = (::ReadingsVal($car,&amp;quot;atHomeStanding&amp;quot;,&amp;quot;false&amp;quot;) eq &amp;quot;true&amp;quot;);;\&lt;br /&gt;
   my $chargeathome = ($charge &amp;amp;&amp;amp; $athome);;\&lt;br /&gt;
   my $connectedathome = ($athome &amp;amp;&amp;amp; ::ReadingsVal($car,&amp;quot;connected&amp;quot;,&amp;quot;false&amp;quot;) eq &amp;quot;true&amp;quot;);;\&lt;br /&gt;
\&lt;br /&gt;
   my $ret = ($chargeathome ? &amp;quot;lädt zu Hause&amp;quot; : ($connectedathome ? &amp;quot;angeschlossen zu Hause&amp;quot; : ($athome ? &amp;quot;zu Hause&amp;quot; : ($charge ? &amp;quot;Lädt auswärts&amp;quot; : &amp;quot;unterwegs&amp;quot;))));;\&lt;br /&gt;
   return $ret;;\&lt;br /&gt;
  }\&lt;br /&gt;
sub FUNC_tire {\&lt;br /&gt;
   my($car)=@_;;\&lt;br /&gt;
   my $ret = &#039;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;Reifendruck okay&amp;lt;/span&amp;gt;&#039;;;\&lt;br /&gt;
\&lt;br /&gt;
   if (::ReadingsVal($car,&amp;quot;status_tirePressureLamp_tirePressureLampAll&amp;quot;,&amp;quot;1&amp;quot;) != 0) {\&lt;br /&gt;
     my $VL = (::ReadingsVal($car,&amp;quot;status_tirePressureLamp_tirePressureLampFL&amp;quot;,&amp;quot;1&amp;quot;) eq &amp;quot;0&amp;quot;)?0:1;;\&lt;br /&gt;
     my $HL = (::ReadingsVal($car,&amp;quot;status_tirePressureLamp_tirePressureLampRL&amp;quot;,&amp;quot;1&amp;quot;) eq &amp;quot;0&amp;quot;)?0:1;;\&lt;br /&gt;
     my $VR = (::ReadingsVal($car,&amp;quot;status_tirePressureLamp_tirePressureLampFR&amp;quot;,&amp;quot;1&amp;quot;) eq &amp;quot;0&amp;quot;)?0:1;;\&lt;br /&gt;
     my $HR = (::ReadingsVal($car,&amp;quot;status_tirePressureLamp_tirePressureLampRR&amp;quot;,&amp;quot;1&amp;quot;) eq &amp;quot;0&amp;quot;)?0:1;;\&lt;br /&gt;
     $ret = &#039;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;Reifen Störung&amp;lt;br&amp;gt;&#039;;;\&lt;br /&gt;
     if ($VL == 1){$ret.=&#039; /VL&#039;};;\&lt;br /&gt;
     if ($VR == 1){$ret.=&#039; /VR&#039;};;\&lt;br /&gt;
     if ($HL == 1){$ret.=&#039; /HL&#039;};;\&lt;br /&gt;
     if ($HR == 1){$ret.=&#039; /HR&#039;};;\&lt;br /&gt;
     $ret = $ret.&#039;&amp;lt;/span&amp;gt;&#039;;;\&lt;br /&gt;
   }\&lt;br /&gt;
   return $ret;;\&lt;br /&gt;
  }\&lt;br /&gt;
sub FUNC_door {\&lt;br /&gt;
   my($car)=@_;;\&lt;br /&gt;
   my $ret = &#039;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;Türen okay&amp;lt;br&amp;gt;&amp;lt;/span&amp;gt;&#039;;;\&lt;br /&gt;
\&lt;br /&gt;
   if (::ReadingsVal($car,&amp;quot;status_doorLock&amp;quot;,&amp;quot;false&amp;quot;) ne &amp;quot;true&amp;quot;) {\&lt;br /&gt;
     my $VL = (::ReadingsVal($car,&amp;quot;status_doorOpen_frontLeft&amp;quot;,1) == 0)?0:1;;\&lt;br /&gt;
     my $HL = (::ReadingsVal($car,&amp;quot;status_doorOpen_backLeft&amp;quot;,1) == 0)?0:1;;\&lt;br /&gt;
     my $VR = (::ReadingsVal($car,&amp;quot;status_doorOpen_frontRight&amp;quot;,1) == 0)?0:1;;\&lt;br /&gt;
     my $HR = (::ReadingsVal($car,&amp;quot;status_doorOpen_backRight&amp;quot;,1) == 0)?0:1;;\&lt;br /&gt;
     $ret = &#039;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;Tür offen&amp;lt;br&amp;gt;&#039;;;\&lt;br /&gt;
     if ($VL == 1){$ret.=&#039; /VL&#039;};;\&lt;br /&gt;
     if ($VR == 1){$ret.=&#039; /VR&#039;};;\&lt;br /&gt;
     if ($HL == 1){$ret.=&#039; /HL&#039;};;\&lt;br /&gt;
     if ($HR == 1){$ret.=&#039; /HR&#039;};;\&lt;br /&gt;
     $ret = $ret.&#039;&amp;lt;/span&amp;gt;&#039;;;\&lt;br /&gt;
   }\&lt;br /&gt;
   if (::ReadingsVal($car,&amp;quot;status_trunkOpen&amp;quot;,&amp;quot;true&amp;quot;) eq &amp;quot;true&amp;quot;) {\&lt;br /&gt;
     $ret.=&#039;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt; Kofferraum offen&amp;lt;/span&amp;gt;&#039;;;\&lt;br /&gt;
   }\&lt;br /&gt;
   if (::ReadingsVal($car,&amp;quot;status_hoodOpen&amp;quot;,&amp;quot;true&amp;quot;) eq &amp;quot;true&amp;quot;) {\&lt;br /&gt;
     $ret.=&#039;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt; Motorhaube offen&amp;lt;/span&amp;gt;&#039;;;\&lt;br /&gt;
   }\&lt;br /&gt;
   return $ret;;\&lt;br /&gt;
  }\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;$SELF&amp;quot;|&amp;quot;Kommando &amp;quot;.::ReadingsTimestamp(&amp;quot;Kia_connect&amp;quot;,&amp;quot;status_time&amp;quot;,&amp;quot;&amp;quot;).&amp;quot;&amp;lt;dd&amp;gt;Auswahl / Kommunikation / Tacho / Info Status&amp;lt;/dd&amp;gt;&amp;quot; | widget([$SELF:ui_command_1],&amp;quot;uzsuDropDown,---,Status_getAll,car_lock,car_unlock&amp;quot;)|(([Kia_connect:req_active] eq &amp;quot;idle&amp;quot;)?&#039;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;idle&amp;lt;/span&amp;gt;&#039; : &#039;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&#039;.[Kia_connect:req_active].&#039;&amp;lt;/span&amp;gt;&#039;) |::round([Kia_connect:odometer_value],0).&amp;quot; km&amp;quot;|FUNC_Status_Laden(&amp;quot;Kia_connect&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
|&amp;quot;Accu&amp;lt;dd&amp;gt;Steuerung / Target Soc / Accu Status&amp;lt;/dd&amp;gt;&amp;quot; |widget([$SELF:ui_command_3],&amp;quot;uzsuDropDown,---,setChargeTargetSoc,stopCharge,startCharge&amp;quot;)|&amp;quot;Target SOC&amp;quot;.widget([Kia_connect:status_evStatus_reservChargeInfos_targetSOClist_2_targetSOClevel_target],&amp;quot;selectnumbers,50,10,100,0,lin&amp;quot;).&amp;quot; %&amp;quot;|&amp;quot;&amp;quot;| FUNC_Status([Kia_connect:range],150,&amp;quot;red&amp;quot;,[Kia_connect:range],&amp;quot;orange&amp;quot;,[Kia_connect:range],250,&amp;quot;green&amp;quot;,[Kia_connect:range]).&amp;quot; km&amp;quot;.&amp;quot;&amp;lt;div style=&#039;border-width:2px;;border-style:solid;;border-color:gray;;position:relative;;width:90px;;height:20px;;background:linear-gradient( to right, red 0px,yellow 30px,green 50px);;&#039;&amp;gt;&amp;quot;.STY(&amp;quot; &amp;quot;,FUNC_batt([Kia_connect:batSOC])).STY(::round([Kia_connect:batSOC],0).&amp;quot;%&amp;quot;,&amp;quot;font-size:16px;;position:absolute;;top:2px;;left:30px&amp;quot;).&amp;quot;&amp;lt;/div&amp;gt;&amp;quot;\&lt;br /&gt;
\&lt;br /&gt;
|&amp;quot;Komfort&amp;lt;dd&amp;gt;Timer / Klima / Reifen / Türen / Accu Status 12V&amp;lt;/dd&amp;gt;&amp;quot; |widget([$SELF:ui_timer_mode],&amp;quot;uzsuDropDown,Aus,heizen,kuehlen&amp;quot;).widget([$SELF:ui_timer_Start],&amp;quot;time&amp;quot;)|\&lt;br /&gt;
((::ReadingsVal(&amp;quot;Abfall_Abfuhr&amp;quot;,&amp;quot;Kiaheizen_days&amp;quot;,0) != 0)?&amp;quot;Klimatisierung&amp;lt;br&amp;gt;&amp;quot;.[Abfall_Abfuhr:Kiaheizen_connect_date].&amp;quot; &amp;quot;.[Abfall_Abfuhr:Kiaheizen_connect_time]:(([$SELF:ui_timer_mode] ne &amp;quot;Aus&amp;quot;)?&amp;quot;Klimatisierung&amp;lt;br&amp;gt;&amp;quot;.[$SELF:timer_04_c04]:&amp;quot;&amp;quot;))|FUNC_tire(&amp;quot;Kia_connect&amp;quot;).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;.FUNC_door(&amp;quot;Kia_connect&amp;quot;)|\&lt;br /&gt;
&amp;quot;12 V&amp;lt;div style=&#039;border-width:2px;;border-style:solid;;border-color:gray;;position:relative;;width:90px;;height:20px;;background:linear-gradient( to right, red 0px,yellow 30px,green 50px);;&#039;&amp;gt;&amp;quot;.STY(&amp;quot; &amp;quot;,FUNC_batt([Kia_connect:bat12v])).STY(::round([Kia_connect:bat12v],0).&amp;quot;%&amp;quot;,&amp;quot;font-size:16px;;position:absolute;;top:2px;;left:30px&amp;quot;).&amp;quot;&amp;lt;/div&amp;gt;&amp;quot;\&lt;br /&gt;
\&lt;br /&gt;
|&amp;quot;&amp;lt;dd&amp;gt; Auswahl / Temperatur / Klima Status / Temperatur innen&amp;lt;/dd&amp;gt;&amp;quot;| widget([$SELF:ui_command_2],&amp;quot;uzsuDropDown,---,stopClimate,startHeating,startCooling&amp;quot;)|\&lt;br /&gt;
&amp;quot;Heat&amp;quot;.widget([Kia_connect:status_airTemp_value_target_Winter],&amp;quot;selectnumbers,20,1,27,0,lin&amp;quot;).&amp;quot;°C&amp;lt;br&amp;gt;Cool&amp;quot;.widget([Kia_connect:status_airTemp_value_target_Sommer],&amp;quot;selectnumbers,16,1,25,0,lin&amp;quot;).&amp;quot;°C&amp;quot;|(([Kia_connect:status_airCtrlOn] eq &amp;quot;true&amp;quot;)?&#039;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;Klima läuft&amp;lt;/span&amp;gt;&#039;:&#039;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;Klima aus&amp;lt;/span&amp;gt;&#039;).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;.(([Kia_connect:status_defrost] eq &amp;quot;true&amp;quot;)?&#039;Defrost ein&#039;:&#039;Defrost aus&#039;) |&amp;quot;Aktuell&amp;lt;br&amp;gt;&amp;quot;.[Kia_connect:status_airTemp_value].&amp;quot;°C&amp;quot;\&lt;br /&gt;
\&lt;br /&gt;
|&amp;quot;WallBox (WB_1_lp1)&amp;lt;dd&amp;gt;Lademodus / Info Status / Ladezeit / Leistung&amp;lt;/dd&amp;gt;&amp;quot;|[WB_1:ChargeMode].&amp;quot;&amp;lt;br&amp;gt;&amp;quot;.widget([$SELF:ui_command_4],&amp;quot;uzsuDropDown,---,SofortLaden,Min+PV,NurPV,Stop,Standby,Vorrang_EV,Vorrang_Bat,Hausspeicher_Sperren&amp;quot;)|[WB_1:lp_1_PlugStat].&amp;quot; &amp;quot;.[WB_1:lp_1_ChargeStat]|[WB_1:lp_1_TimeRemaining]|[WB_1:lp_1_countPhasesInUse].&amp;quot;P &amp;quot;.[WB_1:lp_1_AConfigured].&amp;quot;A&amp;lt;br&amp;gt;&amp;quot;.[WB_1:lp_1_W].&amp;quot; W&amp;quot;&lt;br /&gt;
&lt;br /&gt;
setstate Kia_eNiro_PV 2022-01-12 13:24:24 ui_command_1 ---&lt;br /&gt;
setstate Kia_eNiro_PV 2022-01-10 09:18:53 ui_command_2 ---&lt;br /&gt;
setstate Kia_eNiro_PV 2021-11-09 07:56:54 ui_command_3 ---&lt;br /&gt;
setstate Kia_eNiro_PV 2022-01-12 13:02:41 ui_command_4 ---&lt;br /&gt;
setstate Kia_eNiro_PV 2022-01-12 13:02:41 ui_command_before_4 ---&lt;br /&gt;
setstate Kia_eNiro_PV 2021-11-29 09:56:58 ui_timer_Start 10:30&lt;br /&gt;
setstate Kia_eNiro_PV 2021-12-02 07:00:00 ui_timer_mode Aus&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Kostal Plenticore mit Speicher=====&lt;br /&gt;
Zu diesem Thema gibt es noch eine andere Wiki Seite, die alles rund um den Wechselrichter und vieles mehr erklärt.&lt;br /&gt;
[[https://wiki.fhem.de/wiki/Kostal_Plenticore_10_Plus|Kostal Plenticore Plus]]&lt;br /&gt;
Die hier beschriebene openWB und Kia connect Anbindung bedient sich der Hausspeichersteuerung, um diesen beim Laden der BEV zu sperren.&lt;br /&gt;
Im DOIF kann an den entsprechenden Stellen natürlich auch ein anders Kommando zum Sperren verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Weiterführende Links ==&lt;br /&gt;
* [https://openwb.de openWB Website]&lt;br /&gt;
* [https://github.com/snaptec/openWB/wiki openWB Wiki bei GitHub]&lt;br /&gt;
* [https://www.openwb.de/forum/viewtopic.php?f=6&amp;amp;t=4159 openWB Forum (Diskussion zu diesem Artikel)]&lt;br /&gt;
* [https://openwb.de/forum/viewtopic.php?t=577 openWB Forum (Liste der MQTT-Topics)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Elektromobilität]]&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=38170</id>
		<title>Einrichten der Bluetooth-Thermostate von eQ-3</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=38170"/>
		<updated>2023-02-25T20:16:53Z</updated>

		<summary type="html">&lt;p&gt;F Klee: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Firma eQ-3 stellt verschiedene elektronische Heizkörperthermostate her. Das Eqiva BLUETOOTH® Smart Heizkörperthermostat (CC-RT-BLE-EQ) kann auch von FHEM gesteuert werden. Voraussetzung ist natürlich ein Bluetooth-Empfänger (RasPi 3+4 oder Bluetooth-Dongle).&lt;br /&gt;
{{Randnotiz|RNText=Hinweis: Es gibt auch Versionen ohne Bluetooth, die genau gleich aussehen. Bei der Bestellung bitte aufpassen.|RNTyp=Warn|style=}}&lt;br /&gt;
== Bluetooth einrichten ==&lt;br /&gt;
Standardmäßig sollte Bluetooth auf dem Raspberry Pi schon eingerichtet sein. Nutzt man einen B+ mit Dongle (z.B. als Verlängerung), so müssen unter Umständen folgende Pakete installiert werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install bluetooth, bluez&amp;lt;/pre&amp;gt;&lt;br /&gt;
Danach ein &amp;lt;code&amp;gt;sudo reboot&amp;lt;/code&amp;gt;. Ein &amp;lt;code&amp;gt;sudo service bluetooth status&amp;lt;/code&amp;gt; sollte zeigen, dass der Daemon läuft.&lt;br /&gt;
Damit der user fhem bzw. pi auf bluetooth zugreifen kann, muss in bluetooth.conf noch folgendes eingetragen werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo nano /etc/dbus-1/system.d/bluetooth.conf&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;policy user=&amp;quot;fhem&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;allow own=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_destination=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattCharacteristic1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattDescriptor1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.ObjectManager&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.Properties&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/policy&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo systemctl restart dbus&amp;lt;/pre&amp;gt;&lt;br /&gt;
Für den User pi muss natürlich fhem durch pi ersetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Thermostat in FHEM definieren ==&lt;br /&gt;
=== Pairing ===&lt;br /&gt;
Die Thermostate müssen mit dem RasPi gepaired werden. Drücke dazu das Rad am Thermostat bis „Pair“ im Display erscheint. Dann führe folgende Schritte aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo bluetoothctl&lt;br /&gt;
[bluetooth]# power on&lt;br /&gt;
[bluetooth]# agent on&lt;br /&gt;
[bluetooth]# default-agent&lt;br /&gt;
[bluetooth]# scan on&lt;br /&gt;
Discovery started&lt;br /&gt;
[CHG] Controller 00:1A:7D:XX:XX:XX Discovering: yes&lt;br /&gt;
[NEW] Device 41:86:FB:XX:XX:XX 41-86-FB-...&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -56&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -70&lt;br /&gt;
[NEW] Device 5A:64:25:XX:XX:XX 5A-64-25-...&lt;br /&gt;
[bluetooth]# scan off&lt;br /&gt;
[bluetooth]# pair 00:1A:22:06:A7:83&lt;br /&gt;
[agent] Enter passkey (number in 0-999999): &amp;lt;enter pin&amp;gt;&lt;br /&gt;
[bluetooth]# trust 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# disconnect 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# exit&lt;br /&gt;
&lt;br /&gt;
Optional steps:&lt;br /&gt;
[bluetooth]# devices - to list all bluetooth devices&lt;br /&gt;
[bluetooth]# info 00:1A:22:06:A7:83&lt;br /&gt;
Device 00:1A:22:06:A7:83 (public)&lt;br /&gt;
        Name: CC-RT-BLE&lt;br /&gt;
        Alias: CC-RT-BLE&lt;br /&gt;
        Paired: yes&lt;br /&gt;
        Trusted: yes&lt;br /&gt;
        Blocked: no&lt;br /&gt;
        Connected: no&lt;br /&gt;
        LegacyPairing: no&lt;br /&gt;
        UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Device Information        (0000180a-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Vendor specific           (3e135142-654f-9090-134a-a6ff5bb77046)&lt;br /&gt;
        UUID: Vendor specific           (9e5d1e47-5c13-43a0-8635-82ad38a1386f)&lt;br /&gt;
        ManufacturerData Key: 0x0000&lt;br /&gt;
        ManufacturerData Value:&lt;br /&gt;
  00 00 00 00 00 00 00 00 00                       .........&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dadurch ist das Thermostat nicht mehr mit der calor BT-App steuerbar (und umgekehrt).&lt;br /&gt;
Unter Umständen wird nicht nach &amp;lt;code&amp;gt;Enter passkey&amp;lt;/code&amp;gt; gefragt. Wichtig ist die Erfolgsmeldung.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Befehle bedeuten im Einzelnen:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo bluetoothctl&amp;lt;/pre&amp;gt;&lt;br /&gt;
Startet das Bluetoothctl-Tool, das eine Befehlszeilenschnittstelle zu BlueZ ist. &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; ist häufig nicht erforderlich. Die Ausgabe sollte ähnlich der folgenden aussehen:&lt;br /&gt;
&amp;lt;pre&amp;gt;[CHG] Controller E4:5F:01:F0:0E:98 Pairable: yes&lt;br /&gt;
[bluetooth]#&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Zeile „[CHG] Controller“ (oder auch [NEW]) zeigt die Informationen zu deinem Bluetooth-Chip an. Die letzte Zeile ist die Eingabeaufforderung von bluetoothctl.&lt;br /&gt;
&lt;br /&gt;
Da der Kopplungsvorgang eine Authentifizierung per PIN beinhaltet, ist eine Registrierung bei einem Authentifizierungsagenten erforderlich. Der Agent bearbeitet die PIN-Abfrage. Gib dazu Folgendes ein:&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# agent on&lt;br /&gt;
Agent registered &lt;br /&gt;
[bluetooth]# default-agent &lt;br /&gt;
Default agent request successful &lt;br /&gt;
[bluetooth]#&amp;lt;/pre&amp;gt;&lt;br /&gt;
Beachte, dass die Registrierung des Agenten während der Kopplung mit einem Gerät, das keine Benutzerbestätigung für den Kopplungsversuch erfordert, keine negativen Auswirkungen hat und sicher ist.&amp;lt;br&amp;gt;&lt;br /&gt;
An dieser Stelle kannst du mit der Suche nach entfernten Bluetooth-Geräten fortfahren:&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# scan on&lt;br /&gt;
Discovery started&lt;br /&gt;
[CHG] Controller 00:1A:7D:XX:XX:XX Discovering: yes&lt;br /&gt;
[NEW] Device 41:86:FB:XX:XX:XX 41-86-FB-...&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -56&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -70&lt;br /&gt;
[NEW] Device 5A:64:25:XX:XX:XX 5A-64-25-...&lt;br /&gt;
[NEW] Device &amp;lt;bluetooth address&amp;gt; &amp;lt;name&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
Stoppt man den Scan mit &amp;lt;code&amp;gt;[bluetooth]# scan off&amp;lt;/code&amp;gt;, so werden die Ergebnisse der Geräteerkennung nach einer gewissen Zeit ungültig.&lt;br /&gt;
&amp;lt;pre&amp;gt;[DEL] Device 00:1A:22:XX:XX:XX CC-RT-BLE&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vorher kann das Pairing gestartet werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# pair 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nun einfach der Anzeige folgen. Am Ende sollte eine Erfolgsmeldung stehen. Falls nicht, die Prozedur ab &amp;lt;code&amp;gt;[bluetooth]# scan on&amp;lt;/code&amp;gt; wiederholen. Danach muss das Gerät noch als Vertrauenswürdig deklariert&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# trust 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
und wieder getrennt werden&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# disconnect 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
Danach kannst du über&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# info 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
nachsehen, ob alles korrekt ist. Das Gerät kann nun in FHEM definiert werden.&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit Perl-Modul 10_EQ3BT ===&lt;br /&gt;
Die eQ-3 Heizkörperthermostate können einfach über&lt;br /&gt;
define &amp;lt;name&amp;gt; EQ3BT &amp;lt;mac address&amp;gt; &lt;br /&gt;
eingebunden werden.&lt;br /&gt;
{{Hinweis|Mittlerweile wird nur noch das fhempy-Modul empfohlen}}&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit fhempy ===&lt;br /&gt;
fhempy ermöglicht das Schreiben von FHEM-Modulen in der Programmiersprache Python. Erforderlich ist Python 3.9 oder höher (NICHT 2!), weshalb Debian Bullseye erforderlich ist. Es ist auch möglich, fhempy auf Peers zu installieren, um dadurch die Bluetooth-Reichweite zu erhöhen. Dadurch ist eine komplette Abdeckung des Hauses möglich. Auf den Peers muss FHEM nicht installiert werden. Neben dem Raspberry Pi Zero eignet sich auch z.B. der Radxa Rock Pi Zero, getestet mit Armbian. Ein Radxa Pi S ist sehr verführerisch. Dabei ist aber auf den SoC zu achten. Der alte RK3308B (ohne S) läuft nur unter dem Radxa debos (buster) mit Bluetooth. Mit Armbian und einem Bluetooth-Dongle geht es aber auch. Die Peers können aus FHEM heraus verwaltet werden.&lt;br /&gt;
&lt;br /&gt;
==== Installation auf FHEM-Server ====&lt;br /&gt;
Um die Heizkörperthermostate unter fhempy einzurichten, sind zunächst einige Vorarbeiten erforderlich. Das Einrichten geht dann genau so simpel.&lt;br /&gt;
Nach dem obligatorischen &amp;lt;code&amp;gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get upgrade&amp;lt;/code&amp;gt; werden die benötigten Python-Pakete mit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git libprotocol-websocket-perl&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das dauert eine Weile. Ich empfehle eine Tasse koffeinhaltiges Heißgetränk.&lt;br /&gt;
Ist die Installation abgeschlossen, geht es an die Konfiguration von FHEM. Zunächst laden wir per Update die benötigten Dateien herunter:&lt;br /&gt;
&amp;lt;pre&amp;gt;update add https://raw.githubusercontent.com/dominikkarall/fhempy/master/controls_pythonbinding.txt&lt;br /&gt;
update&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ist das Update abgeschlossen, können wir fhempy einrichten:&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_local BindingsIo fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Es wird automatisch &#039;&#039;&#039;fhempyserver&#039;&#039;&#039; und &#039;&#039;&#039;fhempy_local&#039;&#039;&#039; eingerichtet. Auch hier gilt: nicht nervös werden, wenn fhempy_local nicht sofort &#039;&#039;connected&#039;&#039; anzeigt.&lt;br /&gt;
&lt;br /&gt;
Hiermit sind die Vorbereitungen abgeschlossen. Das Thermostat kann nun mit&lt;br /&gt;
&amp;lt;pre&amp;gt;define &amp;lt;name&amp;gt; fhempy eq3bt &amp;lt;MAC-Adresse&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
eingebunden werden. Die benötigten Module werden automatisch nachgeladen.&lt;br /&gt;
&lt;br /&gt;
==== Installation des fhempy-Peer ====&lt;br /&gt;
fhempy läuft nicht nur lokal auf dem FHEM-Server. Zur Reichweitenerhöhung kann auch ein fhempy-Peer auf einem oder mehreren RasPi’s installiert und diese über die Wohnung verteilt werden. Geeignet ist natürlich auch ein RasPi, der zur Visualisierung dient.&lt;br /&gt;
{{Hinweis|WICHTIG!! Die folgenden Befehle dürfen nur auf dem Remote-RasPi und nicht auf der FHEM-Instanz ausgeführt werden.}}&lt;br /&gt;
Zunächst müssen die benötigten Python-Pakete wie oben beschrieben installiert werden. Installiere nun fhempy als User pi&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install --upgrade fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Überprüfe, ob die Hauptinstanz auf dem FHEM-Server läuft und starte dann fhempy als User pi auf dem Peer&lt;br /&gt;
&amp;lt;pre&amp;gt;fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nach kurzer Zeit siehst du die ankommende FHEM-Verbindung.&lt;br /&gt;
Nun noch die systemd-Konfiguration, damit fhempy automatisch gestartet wird&lt;br /&gt;
&amp;lt;pre&amp;gt;curl -sL https://raw.githubusercontent.com/fhempy/fhempy/master/install_systemd_fhempy.sh | sudo -E bash -&amp;lt;/pre&amp;gt;&lt;br /&gt;
fhempy läuft nun unter dem User pi. Möchtest du das ändern, so schau in die Datei &amp;lt;code&amp;gt;fhempy.service&amp;lt;/code&amp;gt; im Verzeichnis &amp;lt;code&amp;gt;/etc/systemd/system/&amp;lt;/code&amp;gt;  Hinterher das sudo systemctl daemon-reload nicht vergessen.&lt;br /&gt;
Der Peer sollte in FHEM automatisch erkannt werden (beruht auf Zeroconf). Sollte das nicht der Fall sein, kann der Peer auch manuell definiert werden&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_peer_IP BindingsIo IP:15733 fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
=== Fehlermeldung nach fhempy-Installation ===&lt;br /&gt;
Meldet pip3 folgendes&lt;br /&gt;
&amp;lt;pre&amp;gt;  WARNING: The script normalizer is installed in &#039;/home/myname/.local/bin&#039; which is not on PATH.&lt;br /&gt;
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.&amp;lt;/pre&amp;gt;&lt;br /&gt;
so fehlt der Pfad zu fhempy und fhempy kann nicht aufgerufen werden. Es ist folgender Befehl aufzurufen&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/myname/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
also z.B.&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/pi/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Keine Reaktion auf Einstellen der Offset-Temperatur ===&lt;br /&gt;
Zur Zeit scheint es ein Softwareproblem beim Einstellen der Offset-Temperatur über Bluetooth zu geben (Version 146 oder kleiner). Die Einstellung wird übertragen, wirkt sich aber nicht auf das Thermostat aus. Erst wenn man die Einstellung über das Menü am Thermostat bestätigt (oder gleich dort einstellt), reagiert das Thermostat. Das Problem tritt auch bei der Bedienung über die App auf.&lt;br /&gt;
&lt;br /&gt;
=== Pairing wird hartnäckig verweigert ===&lt;br /&gt;
Manchmal klappt das Pairing nicht, obwohl alles in Ordnung scheint. Ein &amp;lt;code&amp;gt;sudo hciconfig hci0 down&amp;lt;/code&amp;gt;, gefolgt von einem &amp;lt;code&amp;gt;hciconfig hci0 up&amp;lt;/code&amp;gt; eventuell mit einem &amp;lt;code&amp;gt;sudo hciconfig hci0 reset&amp;lt;/code&amp;gt; dazwischen kann helfen.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/fhempy/fhempy fhempy-Projekt auf Github]&lt;br /&gt;
* [https://github.com/rytilahti/python-eq3bt#pairing Pairing der Thermostate]&lt;br /&gt;
* {{Link2Forum|Topic=60595|LinkText=Forums-Beitrag}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Heizungsventile]]&lt;br /&gt;
[[Kategorie:Bluetooth]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=38169</id>
		<title>Einrichten der Bluetooth-Thermostate von eQ-3</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=38169"/>
		<updated>2023-02-25T20:15:15Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Beschreibung der Installation von fhempy auf Bullseye reduziert, Pairing ist immer erforderlich, deshalb an den Anfang verschoben.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Firma eQ-3 stellt verschiedene elektronische Heizkörperthermostate her. Das Eqiva BLUETOOTH® Smart Heizkörperthermostat (CC-RT-BLE-EQ) kann auch von FHEM gesteuert werden. Voraussetzung ist natürlich ein Bluetooth-Empfänger (RasPi 3+4 oder Bluetooth-Dongle).&lt;br /&gt;
{{Randnotiz|RNText=Hinweis: Es gibt auch Versionen ohne Bluetooth, die genau gleich aussehen. Bei der Bestellung bitte aufpassen.|RNTyp=Warn|style=}}&lt;br /&gt;
== Bluetooth einrichten ==&lt;br /&gt;
Standardmäßig sollte Bluetooth auf dem Raspberry Pi schon eingerichtet sein. Nutzt man einen B+ mit Dongle (z.B. als Verlängerung), so müssen unter Umständen folgende Pakete installiert werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install bluetooth, bluez&amp;lt;/pre&amp;gt;&lt;br /&gt;
Danach ein &amp;lt;code&amp;gt;sudo reboot&amp;lt;/code&amp;gt;. Ein &amp;lt;code&amp;gt;sudo service bluetooth status&amp;lt;/code&amp;gt; sollte zeigen, dass der Daemon läuft.&lt;br /&gt;
Damit der user fhem bzw. pi auf bluetooth zugreifen kann, muss in bluetooth.conf noch folgendes eingetragen werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo nano /etc/dbus-1/system.d/bluetooth.conf&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;policy user=&amp;quot;fhem&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;allow own=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_destination=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattCharacteristic1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattDescriptor1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.ObjectManager&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.Properties&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/policy&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo systemctl restart dbus&amp;lt;/pre&amp;gt;&lt;br /&gt;
Für den User pi muss natürlich fhem durch pi ersetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Thermostat in FHEM definieren ==&lt;br /&gt;
=== Pairing ===&lt;br /&gt;
Die Thermostate müssen mit dem RasPi gepaired werden. Drücke dazu das Rad am Thermostat bis „Pair“ im Display erscheint. Dann führe folgende Schritte aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo bluetoothctl&lt;br /&gt;
[bluetooth]# power on&lt;br /&gt;
[bluetooth]# agent on&lt;br /&gt;
[bluetooth]# default-agent&lt;br /&gt;
[bluetooth]# scan on&lt;br /&gt;
Discovery started&lt;br /&gt;
[CHG] Controller 00:1A:7D:XX:XX:XX Discovering: yes&lt;br /&gt;
[NEW] Device 41:86:FB:XX:XX:XX 41-86-FB-...&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -56&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -70&lt;br /&gt;
[NEW] Device 5A:64:25:XX:XX:XX 5A-64-25-...&lt;br /&gt;
[bluetooth]# scan off&lt;br /&gt;
[bluetooth]# pair 00:1A:22:06:A7:83&lt;br /&gt;
[agent] Enter passkey (number in 0-999999): &amp;lt;enter pin&amp;gt;&lt;br /&gt;
[bluetooth]# trust 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# disconnect 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# exit&lt;br /&gt;
&lt;br /&gt;
Optional steps:&lt;br /&gt;
[bluetooth]# devices - to list all bluetooth devices&lt;br /&gt;
[bluetooth]# info 00:1A:22:06:A7:83&lt;br /&gt;
Device 00:1A:22:06:A7:83 (public)&lt;br /&gt;
        Name: CC-RT-BLE&lt;br /&gt;
        Alias: CC-RT-BLE&lt;br /&gt;
        Paired: yes&lt;br /&gt;
        Trusted: yes&lt;br /&gt;
        Blocked: no&lt;br /&gt;
        Connected: no&lt;br /&gt;
        LegacyPairing: no&lt;br /&gt;
        UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Device Information        (0000180a-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Vendor specific           (3e135142-654f-9090-134a-a6ff5bb77046)&lt;br /&gt;
        UUID: Vendor specific           (9e5d1e47-5c13-43a0-8635-82ad38a1386f)&lt;br /&gt;
        ManufacturerData Key: 0x0000&lt;br /&gt;
        ManufacturerData Value:&lt;br /&gt;
  00 00 00 00 00 00 00 00 00                       .........&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dadurch ist das Thermostat nicht mehr mit der calor BT-App steuerbar (und umgekehrt).&lt;br /&gt;
Unter Umständen wird nicht nach &amp;lt;code&amp;gt;Enter passkey&amp;lt;/code&amp;gt; gefragt. Wichtig ist die Erfolgsmeldung.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Befehle bedeuten im Einzelnen:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo bluetoothctl&amp;lt;/pre&amp;gt;&lt;br /&gt;
Startet das Bluetoothctl-Tool, das eine Befehlszeilenschnittstelle zu BlueZ ist. &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; ist häufig nicht erforderlich. Die Ausgabe sollte ähnlich der folgenden aussehen:&lt;br /&gt;
&amp;lt;pre&amp;gt;[CHG] Controller E4:5F:01:F0:0E:98 Pairable: yes&lt;br /&gt;
[bluetooth]#&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Zeile „[CHG] Controller“ (oder auch [NEW]) zeigt die Informationen zu deinem Bluetooth-Chip an. Die letzte Zeile ist die Eingabeaufforderung von bluetoothctl.&lt;br /&gt;
&lt;br /&gt;
Da der Kopplungsvorgang eine Authentifizierung per PIN beinhaltet, ist eine Registrierung bei einem Authentifizierungsagenten erforderlich. Der Agent bearbeitet die PIN-Abfrage. Gib dazu Folgendes ein:&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# agent on&lt;br /&gt;
Agent registered &lt;br /&gt;
[bluetooth]# default-agent &lt;br /&gt;
Default agent request successful &lt;br /&gt;
[bluetooth]#&amp;lt;/pre&amp;gt;&lt;br /&gt;
Beachte, dass die Registrierung des Agenten während der Kopplung mit einem Gerät, das keine Benutzerbestätigung für den Kopplungsversuch erfordert, keine negativen Auswirkungen hat und sicher ist.&amp;lt;br&amp;gt;&lt;br /&gt;
An dieser Stelle kannst du mit der Suche nach entfernten Bluetooth-Geräten fortfahren:&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# scan on&lt;br /&gt;
Discovery started&lt;br /&gt;
[CHG] Controller 00:1A:7D:XX:XX:XX Discovering: yes&lt;br /&gt;
[NEW] Device 41:86:FB:XX:XX:XX 41-86-FB-...&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -56&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -70&lt;br /&gt;
[NEW] Device 5A:64:25:XX:XX:XX 5A-64-25-...&lt;br /&gt;
[NEW] Device &amp;lt;bluetooth address&amp;gt; &amp;lt;name&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
Stoppt man den Scan mit &amp;lt;code&amp;gt;[bluetooth]# scan off&amp;lt;/code&amp;gt;, so werden die Ergebnisse der Geräteerkennung nach einer gewissen Zeit ungültig.&lt;br /&gt;
&amp;lt;pre&amp;gt;[DEL] Device 00:1A:22:XX:XX:XX CC-RT-BLE&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vorher kann das Pairing gestartet werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# pair 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nun einfach der Anzeige folgen. Am Ende sollte eine Erfolgsmeldung stehen. Falls nicht, die Prozedur ab &amp;lt;code&amp;gt;[bluetooth]# scan on&amp;lt;/code&amp;gt; wiederholen. Danach muss das Gerät noch als Vertrauenswürdig deklariert&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# trust 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
und wieder getrennt werden&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# disconnect 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
Danach kannst du über&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# info 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
nachsehen, ob alles korrekt ist. Das Gerät kann nun in FHEM definiert werden.&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit Perl-Modul 10_EQ3BT ===&lt;br /&gt;
Die eQ-3 Heizkörperthermostate können einfach über&lt;br /&gt;
define &amp;lt;name&amp;gt; EQ3BT &amp;lt;mac address&amp;gt; &lt;br /&gt;
eingebunden werden.&lt;br /&gt;
{{Hinweis|Mittlerweile wird nur noch das fhempy-Modul empfohlen}}&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit fhempy ===&lt;br /&gt;
fhempy ermöglicht das Schreiben von FHEM-Modulen in der Programmiersprache Python. Erforderlich ist Python 3.9 oder höher (NICHT 2!), weshalb Debian Bullseye erforderlich ist. Es ist auch möglich, fhempy auf Peers zu installieren, um dadurch die Bluetooth-Reichweite zu erhöhen. Dadurch ist eine komplette Abdeckung des Hauses möglich. Auf den Peers muss FHEM nicht installiert werden. Neben dem Raspberry Pi Zero eignet sich auch z.B. der Radxa Rock Pi Zero, getestet mit Armbian. Ein Radxa Pi S ist sehr verführerisch. Dabei ist aber auf den SoC zu achten. Der alte RK3308B (ohne S) läuft nur unter dem Radxa debos (buster) mit Bluetooth. Mit Armbian und einem Bluetoothdongle geht es aber auch. Die Peers können aus FHEM heraus verwaltet werden.&lt;br /&gt;
&lt;br /&gt;
==== Installation auf FHEM-Server ====&lt;br /&gt;
Um die Heizkörperthermostate unter fhempy einzurichten, sind zunächst einige Vorarbeiten erforderlich. Das Einrichten geht dann genau so simpel.&lt;br /&gt;
Nach dem obligatorischen &amp;lt;code&amp;gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get upgrade&amp;lt;/code&amp;gt; werden die benötigten Python-Pakete mit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git libprotocol-websocket-perl&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das dauert eine Weile. Ich empfehle eine Tasse koffeinhaltiges Heißgetränk.&lt;br /&gt;
Ist die Installation abgeschlossen, geht es an die Konfiguration von FHEM. Zunächst laden wir per Update die benötigten Dateien herunter:&lt;br /&gt;
&amp;lt;pre&amp;gt;update add https://raw.githubusercontent.com/dominikkarall/fhempy/master/controls_pythonbinding.txt&lt;br /&gt;
update&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ist das Update abgeschlossen, können wir fhempy einrichten:&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_local BindingsIo fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Es wird automatisch &#039;&#039;&#039;fhempyserver&#039;&#039;&#039; und &#039;&#039;&#039;fhempy_local&#039;&#039;&#039; eingerichtet. Auch hier gilt: nicht nervös werden, wenn fhempy_local nicht sofort &#039;&#039;connected&#039;&#039; anzeigt.&lt;br /&gt;
&lt;br /&gt;
Hiermit sind die Vorbereitungen abgeschlossen. Das Thermostat kann nun mit&lt;br /&gt;
&amp;lt;pre&amp;gt;define &amp;lt;name&amp;gt; fhempy eq3bt &amp;lt;MAC-Adresse&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
eingebunden werden. Die benötigten Module werden automatisch nachgeladen.&lt;br /&gt;
&lt;br /&gt;
==== Installation des fhempy-Peer ====&lt;br /&gt;
fhempy läuft nicht nur lokal auf dem FHEM-Server. Zur Reichweitenerhöhung kann auch ein fhempy-Peer auf einem oder mehreren RasPi’s installiert und diese über die Wohnung verteilt werden. Geeignet ist natürlich auch ein RasPi, der zur Visualisierung dient.&lt;br /&gt;
{{Hinweis|WICHTIG!! Die folgenden Befehle dürfen nur auf dem Remote-RasPi und nicht auf der FHEM-Instanz ausgeführt werden.}}&lt;br /&gt;
Zunächst müssen die benötigten Python-Pakete wie oben beschrieben installiert werden. Installiere nun fhempy als User pi&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install --upgrade fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Überprüfe, ob die Hauptinstanz auf dem FHEM-Server läuft und starte dann fhempy als User pi auf dem Peer&lt;br /&gt;
&amp;lt;pre&amp;gt;fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nach kurzer Zeit siehst du die ankommende FHEM-Verbindung.&lt;br /&gt;
Nun noch die systemd-Konfiguration, damit fhempy automatisch gestartet wird&lt;br /&gt;
&amp;lt;pre&amp;gt;curl -sL https://raw.githubusercontent.com/fhempy/fhempy/master/install_systemd_fhempy.sh | sudo -E bash -&amp;lt;/pre&amp;gt;&lt;br /&gt;
fhempy läuft nun unter dem User pi. Möchtest du das ändern, so schau in die Datei &amp;lt;code&amp;gt;fhempy.service&amp;lt;/code&amp;gt; im Verzeichnis &amp;lt;code&amp;gt;/etc/systemd/system/&amp;lt;/code&amp;gt;  Hinterher das sudo systemctl daemon-reload nicht vergessen.&lt;br /&gt;
Der Peer sollte in FHEM automatisch erkannt werden (beruht auf Zeroconf). Sollte das nicht der Fall sein, kann der Peer auch manuell definiert werden&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_peer_IP BindingsIo IP:15733 fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
=== Fehlermeldung nach fhempy-Installation ===&lt;br /&gt;
Meldet pip3 folgendes&lt;br /&gt;
&amp;lt;pre&amp;gt;  WARNING: The script normalizer is installed in &#039;/home/myname/.local/bin&#039; which is not on PATH.&lt;br /&gt;
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.&amp;lt;/pre&amp;gt;&lt;br /&gt;
so fehlt der Pfad zu fhempy und fhempy kann nicht aufgerufen werden. Es ist folgender Befehl aufzurufen&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/myname/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
also z.B.&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/pi/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Keine Reaktion auf Einstellen der Offset-Temperatur ===&lt;br /&gt;
Zur Zeit scheint es ein Softwareproblem beim Einstellen der Offset-Temperatur über Bluetooth zu geben (Version 146 oder kleiner). Die Einstellung wird übertragen, wirkt sich aber nicht auf das Thermostat aus. Erst wenn man die Einstellung über das Menü am Thermostat bestätigt (oder gleich dort einstellt), reagiert das Thermostat. Das Problem tritt auch bei der Bedienung über die App auf.&lt;br /&gt;
&lt;br /&gt;
=== Pairing wird hartnäckig verweigert ===&lt;br /&gt;
Manchmal klappt das Pairing nicht, obwohl alles in Ordnung scheint. Ein &amp;lt;code&amp;gt;sudo hciconfig hci0 down&amp;lt;/code&amp;gt;, gefolgt von einem &amp;lt;code&amp;gt;hciconfig hci0 up&amp;lt;/code&amp;gt; eventuell mit einem &amp;lt;code&amp;gt;sudo hciconfig hci0 reset&amp;lt;/code&amp;gt; dazwischen kann helfen.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/fhempy/fhempy fhempy-Projekt auf Github]&lt;br /&gt;
* [https://github.com/rytilahti/python-eq3bt#pairing Pairing der Thermostate]&lt;br /&gt;
* {{Link2Forum|Topic=60595|LinkText=Forums-Beitrag}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Heizungsventile]]&lt;br /&gt;
[[Kategorie:Bluetooth]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=38156</id>
		<title>Einrichten der Bluetooth-Thermostate von eQ-3</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=38156"/>
		<updated>2023-02-22T06:52:42Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Hinweis auf Python3.9 ergänzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Firma eQ-3 stellt verschiedene elektronische Heizkörperthermostate her. Das Eqiva BLUETOOTH® Smart Heizkörperthermostat (CC-RT-BLE-EQ) kann auch von FHEM gesteuert werden. Voraussetzung ist natürlich ein Bluetooth-Empfänger (RasPi 3+4 oder Bluetooth-Dongle).&lt;br /&gt;
{{Randnotiz|RNText=Hinweis: Es gibt auch Versionen ohne Bluetooth, die genau gleich aussehen. Bei der Bestellung bitte aufpassen.|RNTyp=Warn|style=}}&lt;br /&gt;
== Bluetooth einrichten ==&lt;br /&gt;
Standardmäßig sollte Bluetooth auf dem Raspberry Pi schon eingerichtet sein. Nutzt man einen B+ mit Dongle (z.B. als Verlängerung), so müssen unter Umständen folgende Pakete installiert werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install bluetooth, bluez&amp;lt;/pre&amp;gt;&lt;br /&gt;
Danach ein &amp;lt;code&amp;gt;sudo reboot&amp;lt;/code&amp;gt;. Ein &amp;lt;code&amp;gt;sudo service bluetooth status&amp;lt;/code&amp;gt; sollte zeigen, dass der Daemon läuft.&lt;br /&gt;
Damit der user fhem bzw. pi auf bluetooth zugreifen kann, muss in bluetooth.conf noch folgendes eingetragen werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo nano /etc/dbus-1/system.d/bluetooth.conf&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;policy user=&amp;quot;fhem&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;allow own=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_destination=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattCharacteristic1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattDescriptor1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.ObjectManager&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.Properties&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/policy&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo systemctl restart dbus&amp;lt;/pre&amp;gt;&lt;br /&gt;
Für den User pi muss natürlich fhem durch pi ersetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Thermostat in FHEM definieren ==&lt;br /&gt;
Bevor das Thermostat in FHEM eingebunden werden kann, muss die MAC-Adresse ermittelt werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;pi@raspberrypi ~ $ bluetoothctl&lt;br /&gt;
[NEW] Controller 00:1A:7D:XX:XX:XX raspberrypi [default]&lt;br /&gt;
[bluetooth]# scan on&lt;br /&gt;
Discovery started&lt;br /&gt;
[CHG] Controller 00:1A:7D:XX:XX:XX Discovering: yes&lt;br /&gt;
[NEW] Device 41:86:FB:XX:XX:XX 41-86-FB-...&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -56&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -70&lt;br /&gt;
[NEW] Device 5A:64:25:XX:XX:XX 5A-64-25-...&lt;br /&gt;
[bluetooth]# scan off&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Geräte tragen den Namen CC-RT-BLE.&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit Perl-Modul 10_EQ3BT ===&lt;br /&gt;
Die eQ-3 Heizkörperthermostate können einfach über&lt;br /&gt;
define &amp;lt;name&amp;gt; EQ3BT &amp;lt;mac address&amp;gt; &lt;br /&gt;
eingebunden werden.&lt;br /&gt;
{{Hinweis|Mittlerweile wird nur noch das fhempy-Modul empfohlen}}&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit fhempy ===&lt;br /&gt;
fhempy ermöglicht das Schreiben von FHEM-Modulen in der Programmiersprache Python. Erforderlich ist Python 3.8 oder höher (NICHT 2!), weshalb Debian Bullseye empfehlenswert ist. Es ist auch möglich, fhempy auf Peers zu installieren, um dadurch die Bluetooth-Reichweite zu erhöhen. Dadurch ist eine komplette Abdeckung des Hauses möglich. Auf den Peers muss FHEM nicht installiert werden. Neben dem Raspberry Pi Zero eignet sich auch z.B. der Radxa Rock Pi Zero, getestet mit Armbian. Die Peers können aus FHEM heraus verwaltet werden.&lt;br /&gt;
==== Installation auf FHEM-Server ====&lt;br /&gt;
Um die Heizkörperthermostate unter fhempy einzurichten, sind zunächst einige Vorarbeiten erforderlich. Das Einrichten geht dann genau so simpel.&lt;br /&gt;
Nach dem obligatorischen &amp;lt;code&amp;gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get upgrade&amp;lt;/code&amp;gt; werden die benötigten Python-Pakete mit&lt;br /&gt;
&lt;br /&gt;
[Debian 11 (Bullseye)]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git libprotocol-websocket-perl&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNTyp=r|RNText=Inzwischen ist Python3.9 zwingend erforderlich.}}&lt;br /&gt;
[alle anderen]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git&amp;lt;/pre&amp;gt;&lt;br /&gt;
und als nächstes&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo cpan Protocol::WebSocket&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das dauert eine Weile. Ich empfehle eine Tasse koffeinhaltiges Heißgetränk.&lt;br /&gt;
Ist die Installation abgeschlossen, geht es an die Konfiguration von FHEM. Zunächst laden wir per Update die benötigten Dateien herunter:&lt;br /&gt;
&amp;lt;pre&amp;gt;update add https://raw.githubusercontent.com/dominikkarall/fhempy/master/controls_pythonbinding.txt&lt;br /&gt;
update&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ist das Update abgeschlossen, können wir fhempy einrichten:&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_local BindingsIo fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Es wird automatisch &#039;&#039;&#039;fhempyserver&#039;&#039;&#039; und &#039;&#039;&#039;fhempy_local&#039;&#039;&#039; eingerichtet. Auch hier gilt: nicht nervös werden, wenn fhempy_local nicht sofort &#039;&#039;connected&#039;&#039; anzeigt.&lt;br /&gt;
&lt;br /&gt;
Hiermit sind die Vorbereitungen abgeschlossen. Das Thermostat kann nun mit&lt;br /&gt;
&amp;lt;pre&amp;gt;define &amp;lt;name&amp;gt; fhempy eq3bt &amp;lt;MAC-Adresse&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
eingebunden werden. Die benötigten Module werden automatisch nachgeladen.&lt;br /&gt;
&lt;br /&gt;
==== Installation des fhempy-Peer ====&lt;br /&gt;
fhempy läuft nicht nur lokal auf dem FHEM-Server. Zur Reichweitenerhöhung kann auch ein fhempy-Peer auf einem oder mehreren RasPi’s installiert und diese über die Wohnung verteilt werden. Geeignet ist natürlich auch ein RasPi, der zur Visualisierung dient.&lt;br /&gt;
{{Hinweis|WICHTIG!! Die folgenden Befehle dürfen nur auf dem Remote-RasPi und nicht auf der FHEM-Instanz ausgeführt werden.}}&lt;br /&gt;
Zunächst müssen die benötigten Python-Pakete wie oben beschrieben installiert werden. Installiere nun fhempy als User pi&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install --upgrade fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Überprüfe, ob die Hauptinstanz auf dem FHEM-Server läuft und starte dann fhempy als User pi auf dem Peer&lt;br /&gt;
&amp;lt;pre&amp;gt;fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nach kurzer Zeit siehst du die ankommende FHEM-Verbindung.&lt;br /&gt;
Nun noch die systemd-Konfiguration, damit fhempy automatisch gestartet wird&lt;br /&gt;
&amp;lt;pre&amp;gt;curl -sL https://raw.githubusercontent.com/fhempy/fhempy/master/install_systemd_fhempy.sh | sudo -E bash -&amp;lt;/pre&amp;gt;&lt;br /&gt;
fhempy läuft nun unter dem User pi. Möchtest du das ändern, so schau in die Datei &amp;lt;code&amp;gt;fhempy.service&amp;lt;/code&amp;gt; im Verzeichnis &amp;lt;code&amp;gt;/etc/systemd/system/&amp;lt;/code&amp;gt;  Hinterher das sudo systemctl daemon-reload nicht vergessen.&lt;br /&gt;
Der Peer sollte in FHEM automatisch erkannt werden (beruht auf Zeroconf). Sollte das nicht der Fall sein, kann der Peer auch manuell definiert werden&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_peer_IP BindingsIo IP:15733 fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Pairing ==&lt;br /&gt;
Die Thermostate müssen mit dem RasPi gepaired werden. Drücke dazu das Rad am Thermostat bis „Pair“ im Display erscheint. Dann führe folgende Schritte aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo bluetoothctl&lt;br /&gt;
[bluetooth]# power on&lt;br /&gt;
[bluetooth]# agent on&lt;br /&gt;
[bluetooth]# default-agent&lt;br /&gt;
[bluetooth]# scan on&lt;br /&gt;
[bluetooth]# scan off&lt;br /&gt;
[bluetooth]# pair 00:1A:22:06:A7:83&lt;br /&gt;
[agent] Enter passkey (number in 0-999999): &amp;lt;enter pin&amp;gt;&lt;br /&gt;
[bluetooth]# trust 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# disconnect 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# exit&lt;br /&gt;
&lt;br /&gt;
Optional steps:&lt;br /&gt;
[bluetooth]# devices - to list all bluetooth devices&lt;br /&gt;
[bluetooth]# info 00:1A:22:06:A7:83&lt;br /&gt;
Device 00:1A:22:06:A7:83 (public)&lt;br /&gt;
        Name: CC-RT-BLE&lt;br /&gt;
        Alias: CC-RT-BLE&lt;br /&gt;
        Paired: yes&lt;br /&gt;
        Trusted: yes&lt;br /&gt;
        Blocked: no&lt;br /&gt;
        Connected: no&lt;br /&gt;
        LegacyPairing: no&lt;br /&gt;
        UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Device Information        (0000180a-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Vendor specific           (3e135142-654f-9090-134a-a6ff5bb77046)&lt;br /&gt;
        UUID: Vendor specific           (9e5d1e47-5c13-43a0-8635-82ad38a1386f)&lt;br /&gt;
        ManufacturerData Key: 0x0000&lt;br /&gt;
        ManufacturerData Value:&lt;br /&gt;
  00 00 00 00 00 00 00 00 00                       .........&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dadurch ist das Thermostat nicht mehr mit der calor BT-App steuerbar (und umgekehrt).&lt;br /&gt;
Unter Umständen wird nicht nach &amp;lt;code&amp;gt;Enter passkey&amp;lt;/code&amp;gt; gefragt. Wichtig ist die Erfolgsmeldung.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Befehle bedeuten im Einzelnen:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo bluetoothctl&amp;lt;/pre&amp;gt;&lt;br /&gt;
Startet das Bluetoothctl-Tool, das eine Befehlszeilenschnittstelle zu BlueZ ist. &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; ist häufig nicht erforderlich. Die Ausgabe sollte ähnlich der folgenden aussehen:&lt;br /&gt;
&amp;lt;pre&amp;gt;[CHG] Controller E4:5F:01:F0:0E:98 Pairable: yes&lt;br /&gt;
[bluetooth]#&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Zeile „[CHG] Controller“ (oder auch [NEW]) zeigt die Informationen zu deinem Bluetooth-Chip an. Die letzte Zeile ist die Eingabeaufforderung von bluetoothctl.&lt;br /&gt;
&lt;br /&gt;
Da der Kopplungsvorgang eine Authentifizierung per PIN beinhaltet, ist eine Registrierung bei einem Authentifizierungsagenten erforderlich. Der Agent bearbeitet die PIN-Abfrage. Gib dazu Folgendes ein:&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# agent on&lt;br /&gt;
Agent registered &lt;br /&gt;
[bluetooth]# default-agent &lt;br /&gt;
Default agent request successful &lt;br /&gt;
[bluetooth]#&amp;lt;/pre&amp;gt;&lt;br /&gt;
Beachte, dass die Registrierung des Agenten während der Kopplung mit einem Gerät, das keine Benutzerbestätigung für den Kopplungsversuch erfordert, keine negativen Auswirkungen hat und sicher ist.&amp;lt;br&amp;gt;&lt;br /&gt;
An dieser Stelle kannst du mit der Suche nach entfernten Bluetooth-Geräten fortfahren:&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# scan on&lt;br /&gt;
Discovery started&lt;br /&gt;
[CHG] Controller 00:1A:7D:XX:XX:XX Discovering: yes&lt;br /&gt;
[NEW] Device 41:86:FB:XX:XX:XX 41-86-FB-...&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -56&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -70&lt;br /&gt;
[NEW] Device 5A:64:25:XX:XX:XX 5A-64-25-...&lt;br /&gt;
[NEW] Device &amp;lt;bluetooth address&amp;gt; &amp;lt;name&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
Stoppt man den Scan mit &amp;lt;code&amp;gt;[bluetooth]# scan off&amp;lt;/code&amp;gt;, so werden die Ergebnisse der Geräteerkennung nach einer gewissen Zeit ungültig.&lt;br /&gt;
&amp;lt;pre&amp;gt;[DEL] Device 00:1A:22:XX:XX:XX CC-RT-BLE&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vorher kann das Pairing gestartet werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# pair 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nun einfach der Anzeige folgen. Am Ende sollte eine Erfolgsmeldung stehen. Falls nicht, die Prozedur ab &amp;lt;code&amp;gt;[bluetooth]# scan on&amp;lt;/code&amp;gt; wiederholen. Danach muss das Gerät noch als Vertrauenswürdig deklariert&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# trust 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
und wieder getrennt werden&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# disconnect 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
Danach kannst du über&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# info 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
nachsehen, ob alles korrekt ist. Das Gerät kann nun in FHEM definiert werden.&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
=== Fehlermeldung nach fhempy-Installation ===&lt;br /&gt;
Meldet pip3 folgendes&lt;br /&gt;
&amp;lt;pre&amp;gt;  WARNING: The script normalizer is installed in &#039;/home/myname/.local/bin&#039; which is not on PATH.&lt;br /&gt;
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.&amp;lt;/pre&amp;gt;&lt;br /&gt;
so fehlt der Pfad zu fhempy und fhempy kann nicht aufgerufen werden. Es ist folgender Befehl aufzurufen&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/myname/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
also z.B.&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/pi/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Keine Reaktion auf Einstellen der Offset-Temperatur ===&lt;br /&gt;
Zur Zeit scheint es ein Softwareproblem beim Einstellen der Offset-Temperatur über Bluetooth zu geben (Version 146 oder kleiner). Die Einstellung wird übertragen, wirkt sich aber nicht auf das Thermostat aus. Erst wenn man die Einstellung über das Menü am Thermostat bestätigt (oder gleich dort einstellt), reagiert das Thermostat. Das Problem tritt auch bei der Bedienung über die App auf.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/fhempy/fhempy fhempy-Projekt auf Github]&lt;br /&gt;
* [https://github.com/rytilahti/python-eq3bt#pairing Pairing der Thermostate]&lt;br /&gt;
* {{Link2Forum|Topic=60595|LinkText=Forums-Beitrag}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Heizungsventile]]&lt;br /&gt;
[[Kategorie:Bluetooth]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=38053</id>
		<title>Einrichten der Bluetooth-Thermostate von eQ-3</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=38053"/>
		<updated>2023-02-07T15:55:30Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Einzelne Schritte des Pairing erläutert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Firma eQ-3 stellt verschiedene elektronische Heizkörperthermostate her. Das Eqiva BLUETOOTH® Smart Heizkörperthermostat (CC-RT-BLE-EQ) kann auch von FHEM gesteuert werden. Voraussetzung ist natürlich ein Bluetooth-Empfänger (RasPi 3+4 oder Bluetooth-Dongle).&lt;br /&gt;
{{Randnotiz|RNText=Hinweis: Es gibt auch Versionen ohne Bluetooth, die genau gleich aussehen. Bei der Bestellung bitte aufpassen.|RNTyp=Warn|style=}}&lt;br /&gt;
== Bluetooth einrichten ==&lt;br /&gt;
Standardmäßig sollte Bluetooth auf dem Raspberry Pi schon eingerichtet sein. Nutzt man einen B+ mit Dongle (z.B. als Verlängerung), so müssen unter Umständen folgende Pakete installiert werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install bluetooth, bluez&amp;lt;/pre&amp;gt;&lt;br /&gt;
Danach ein &amp;lt;code&amp;gt;sudo reboot&amp;lt;/code&amp;gt;. Ein &amp;lt;code&amp;gt;sudo service bluetooth status&amp;lt;/code&amp;gt; sollte zeigen, dass der Daemon läuft.&lt;br /&gt;
Damit der user fhem bzw. pi auf bluetooth zugreifen kann, muss in bluetooth.conf noch folgendes eingetragen werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo nano /etc/dbus-1/system.d/bluetooth.conf&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;policy user=&amp;quot;fhem&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;allow own=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_destination=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattCharacteristic1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattDescriptor1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.ObjectManager&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.Properties&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/policy&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo systemctl restart dbus&amp;lt;/pre&amp;gt;&lt;br /&gt;
Für den User pi muss natürlich fhem durch pi ersetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Thermostat in FHEM definieren ==&lt;br /&gt;
Bevor das Thermostat in FHEM eingebunden werden kann, muss die MAC-Adresse ermittelt werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;pi@raspberrypi ~ $ bluetoothctl&lt;br /&gt;
[NEW] Controller 00:1A:7D:XX:XX:XX raspberrypi [default]&lt;br /&gt;
[bluetooth]# scan on&lt;br /&gt;
Discovery started&lt;br /&gt;
[CHG] Controller 00:1A:7D:XX:XX:XX Discovering: yes&lt;br /&gt;
[NEW] Device 41:86:FB:XX:XX:XX 41-86-FB-...&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -56&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -70&lt;br /&gt;
[NEW] Device 5A:64:25:XX:XX:XX 5A-64-25-...&lt;br /&gt;
[bluetooth]# scan off&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Geräte tragen den Namen CC-RT-BLE.&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit Perl-Modul 10_EQ3BT ===&lt;br /&gt;
Die eQ-3 Heizkörperthermostate können einfach über&lt;br /&gt;
define &amp;lt;name&amp;gt; EQ3BT &amp;lt;mac address&amp;gt; &lt;br /&gt;
eingebunden werden.&lt;br /&gt;
{{Hinweis|Mittlerweile wird nur noch das fhempy-Modul empfohlen}}&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit fhempy ===&lt;br /&gt;
fhempy ermöglicht das Schreiben von FHEM-Modulen in der Programmiersprache Python. Erforderlich ist Python 3.8 oder höher (NICHT 2!), weshalb Debian Bullseye empfehlenswert ist. Es ist auch möglich, fhempy auf Peers zu installieren, um dadurch die Bluetooth-Reichweite zu erhöhen. Dadurch ist eine komplette Abdeckung des Hauses möglich. Auf den Peers muss FHEM nicht installiert werden. Neben dem Raspberry Pi Zero eignet sich auch z.B. der Radxa Rock Pi Zero, getestet mit Armbian. Die Peers können aus FHEM heraus verwaltet werden.&lt;br /&gt;
==== Installation auf FHEM-Server ====&lt;br /&gt;
Um die Heizkörperthermostate unter fhempy einzurichten, sind zunächst einige Vorarbeiten erforderlich. Das Einrichten geht dann genau so simpel.&lt;br /&gt;
Nach dem obligatorischen &amp;lt;code&amp;gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get upgrade&amp;lt;/code&amp;gt; werden die benötigten Python-Pakete mit&lt;br /&gt;
&lt;br /&gt;
[Debian 11 (Bullseye)]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git libprotocol-websocket-perl&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[alle anderen]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git&amp;lt;/pre&amp;gt;&lt;br /&gt;
und als nächstes&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo cpan Protocol::WebSocket&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das dauert eine Weile. Ich empfehle eine Tasse koffeinhaltiges Heißgetränk.&lt;br /&gt;
Ist die Installation abgeschlossen, geht es an die Konfiguration von FHEM. Zunächst laden wir per Update die benötigten Dateien herunter:&lt;br /&gt;
&amp;lt;pre&amp;gt;update add https://raw.githubusercontent.com/dominikkarall/fhempy/master/controls_pythonbinding.txt&lt;br /&gt;
update&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ist das Update abgeschlossen, können wir fhempy einrichten:&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_local BindingsIo fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Es wird automatisch &#039;&#039;&#039;fhempyserver&#039;&#039;&#039; und &#039;&#039;&#039;fhempy_local&#039;&#039;&#039; eingerichtet. Auch hier gilt: nicht nervös werden, wenn fhempy_local nicht sofort &#039;&#039;connected&#039;&#039; anzeigt.&lt;br /&gt;
&lt;br /&gt;
Hiermit sind die Vorbereitungen abgeschlossen. Das Thermostat kann nun mit&lt;br /&gt;
&amp;lt;pre&amp;gt;define &amp;lt;name&amp;gt; fhempy eq3bt &amp;lt;MAC-Adresse&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
eingebunden werden. Die benötigten Module werden automatisch nachgeladen.&lt;br /&gt;
&lt;br /&gt;
==== Installation des fhempy-Peer ====&lt;br /&gt;
fhempy läuft nicht nur lokal auf dem FHEM-Server. Zur Reichweitenerhöhung kann auch ein fhempy-Peer auf einem oder mehreren RasPi’s installiert und diese über die Wohnung verteilt werden. Geeignet ist natürlich auch ein RasPi, der zur Visualisierung dient.&lt;br /&gt;
{{Hinweis|WICHTIG!! Die folgenden Befehle dürfen nur auf dem Remote-RasPi und nicht auf der FHEM-Instanz ausgeführt werden.}}&lt;br /&gt;
Zunächst müssen die benötigten Python-Pakete wie oben beschrieben installiert werden. Installiere nun fhempy als User pi&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install --upgrade fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Überprüfe, ob die Hauptinstanz auf dem FHEM-Server läuft und starte dann fhempy als User pi auf dem Peer&lt;br /&gt;
&amp;lt;pre&amp;gt;fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nach kurzer Zeit siehst du die ankommende FHEM-Verbindung.&lt;br /&gt;
Nun noch die systemd-Konfiguration, damit fhempy automatisch gestartet wird&lt;br /&gt;
&amp;lt;pre&amp;gt;curl -sL https://raw.githubusercontent.com/fhempy/fhempy/master/install_systemd_fhempy.sh | sudo -E bash -&amp;lt;/pre&amp;gt;&lt;br /&gt;
fhempy läuft nun unter dem User pi. Möchtest du das ändern, so schau in die Datei &amp;lt;code&amp;gt;fhempy.service&amp;lt;/code&amp;gt; im Verzeichnis &amp;lt;code&amp;gt;/etc/systemd/system/&amp;lt;/code&amp;gt;  Hinterher das sudo systemctl daemon-reload nicht vergessen.&lt;br /&gt;
Der Peer sollte in FHEM automatisch erkannt werden (beruht auf Zeroconf). Sollte das nicht der Fall sein, kann der Peer auch manuell definiert werden&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_peer_IP BindingsIo IP:15733 fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Pairing ==&lt;br /&gt;
Die Thermostate müssen mit dem RasPi gepaired werden. Drücke dazu das Rad am Thermostat bis „Pair“ im Display erscheint. Dann führe folgende Schritte aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo bluetoothctl&lt;br /&gt;
[bluetooth]# power on&lt;br /&gt;
[bluetooth]# agent on&lt;br /&gt;
[bluetooth]# default-agent&lt;br /&gt;
[bluetooth]# scan on&lt;br /&gt;
[bluetooth]# scan off&lt;br /&gt;
[bluetooth]# pair 00:1A:22:06:A7:83&lt;br /&gt;
[agent] Enter passkey (number in 0-999999): &amp;lt;enter pin&amp;gt;&lt;br /&gt;
[bluetooth]# trust 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# disconnect 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# exit&lt;br /&gt;
&lt;br /&gt;
Optional steps:&lt;br /&gt;
[bluetooth]# devices - to list all bluetooth devices&lt;br /&gt;
[bluetooth]# info 00:1A:22:06:A7:83&lt;br /&gt;
Device 00:1A:22:06:A7:83 (public)&lt;br /&gt;
        Name: CC-RT-BLE&lt;br /&gt;
        Alias: CC-RT-BLE&lt;br /&gt;
        Paired: yes&lt;br /&gt;
        Trusted: yes&lt;br /&gt;
        Blocked: no&lt;br /&gt;
        Connected: no&lt;br /&gt;
        LegacyPairing: no&lt;br /&gt;
        UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Device Information        (0000180a-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Vendor specific           (3e135142-654f-9090-134a-a6ff5bb77046)&lt;br /&gt;
        UUID: Vendor specific           (9e5d1e47-5c13-43a0-8635-82ad38a1386f)&lt;br /&gt;
        ManufacturerData Key: 0x0000&lt;br /&gt;
        ManufacturerData Value:&lt;br /&gt;
  00 00 00 00 00 00 00 00 00                       .........&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dadurch ist das Thermostat nicht mehr mit der calor BT-App steuerbar (und umgekehrt).&lt;br /&gt;
Unter Umständen wird nicht nach &amp;lt;code&amp;gt;Enter passkey&amp;lt;/code&amp;gt; gefragt. Wichtig ist die Erfolgsmeldung.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Befehle bedeuten im Einzelnen:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo bluetoothctl&amp;lt;/pre&amp;gt;&lt;br /&gt;
Startet das Bluetoothctl-Tool, das eine Befehlszeilenschnittstelle zu BlueZ ist. &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; ist häufig nicht erforderlich. Die Ausgabe sollte ähnlich der folgenden aussehen:&lt;br /&gt;
&amp;lt;pre&amp;gt;[CHG] Controller E4:5F:01:F0:0E:98 Pairable: yes&lt;br /&gt;
[bluetooth]#&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Zeile „[CHG] Controller“ (oder auch [NEW]) zeigt die Informationen zu deinem Bluetooth-Chip an. Die letzte Zeile ist die Eingabeaufforderung von bluetoothctl.&lt;br /&gt;
&lt;br /&gt;
Da der Kopplungsvorgang eine Authentifizierung per PIN beinhaltet, ist eine Registrierung bei einem Authentifizierungsagenten erforderlich. Der Agent bearbeitet die PIN-Abfrage. Gib dazu Folgendes ein:&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# agent on&lt;br /&gt;
Agent registered &lt;br /&gt;
[bluetooth]# default-agent &lt;br /&gt;
Default agent request successful &lt;br /&gt;
[bluetooth]#&amp;lt;/pre&amp;gt;&lt;br /&gt;
Beachte, dass die Registrierung des Agenten während der Kopplung mit einem Gerät, das keine Benutzerbestätigung für den Kopplungsversuch erfordert, keine negativen Auswirkungen hat und sicher ist.&amp;lt;br&amp;gt;&lt;br /&gt;
An dieser Stelle kannst du mit der Suche nach entfernten Bluetooth-Geräten fortfahren:&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# scan on&lt;br /&gt;
Discovery started&lt;br /&gt;
[CHG] Controller 00:1A:7D:XX:XX:XX Discovering: yes&lt;br /&gt;
[NEW] Device 41:86:FB:XX:XX:XX 41-86-FB-...&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -56&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -70&lt;br /&gt;
[NEW] Device 5A:64:25:XX:XX:XX 5A-64-25-...&lt;br /&gt;
[NEW] Device &amp;lt;bluetooth address&amp;gt; &amp;lt;name&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
Stoppt man den Scan mit &amp;lt;code&amp;gt;[bluetooth]# scan off&amp;lt;/code&amp;gt;, so werden die Ergebnisse der Geräteerkennung nach einer gewissen Zeit ungültig.&lt;br /&gt;
&amp;lt;pre&amp;gt;[DEL] Device 00:1A:22:XX:XX:XX CC-RT-BLE&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vorher kann das Pairing gestartet werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# pair 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nun einfach der Anzeige folgen. Am Ende sollte eine Erfolgsmeldung stehen. Falls nicht, die Prozedur ab &amp;lt;code&amp;gt;[bluetooth]# scan on&amp;lt;/code&amp;gt; wiederholen. Danach muss das Gerät noch als Vertrauenswürdig deklariert&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# trust 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
und wieder getrennt werden&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# disconnect 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
Danach kannst du über&lt;br /&gt;
&amp;lt;pre&amp;gt;[bluetooth]# info 00:1A:22:06:A7:83&amp;lt;/pre&amp;gt;&lt;br /&gt;
nachsehen, ob alles korrekt ist. Das Gerät kann nun in FHEM definiert werden.&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
=== Fehlermeldung nach fhempy-Installation ===&lt;br /&gt;
Meldet pip3 folgendes&lt;br /&gt;
&amp;lt;pre&amp;gt;  WARNING: The script normalizer is installed in &#039;/home/myname/.local/bin&#039; which is not on PATH.&lt;br /&gt;
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.&amp;lt;/pre&amp;gt;&lt;br /&gt;
so fehlt der Pfad zu fhempy und fhempy kann nicht aufgerufen werden. Es ist folgender Befehl aufzurufen&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/myname/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
also z.B.&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/pi/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Keine Reaktion auf Einstellen der Offset-Temperatur ===&lt;br /&gt;
Zur Zeit scheint es ein Softwareproblem beim Einstellen der Offset-Temperatur über Bluetooth zu geben (Version 146 oder kleiner). Die Einstellung wird übertragen, wirkt sich aber nicht auf das Thermostat aus. Erst wenn man die Einstellung über das Menü am Thermostat bestätigt (oder gleich dort einstellt), reagiert das Thermostat. Das Problem tritt auch bei der Bedienung über die App auf.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/fhempy/fhempy fhempy-Projekt auf Github]&lt;br /&gt;
* [https://github.com/rytilahti/python-eq3bt#pairing Pairing der Thermostate]&lt;br /&gt;
* {{Link2Forum|Topic=60595|LinkText=Forums-Beitrag}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Heizungsventile]]&lt;br /&gt;
[[Kategorie:Bluetooth]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Knxd&amp;diff=37941</id>
		<title>Knxd</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Knxd&amp;diff=37941"/>
		<updated>2023-01-13T13:50:49Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* Vorbereiten des Raspberry Pi für ROT oder PIGATOR */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== knxd mit einem IP Gateway einrichten ==&lt;br /&gt;
Damit FHEM auf den KNX Bus zugreifen kann, wird ein passendes Interface benötigt. Es gibt:&lt;br /&gt;
* RS232&lt;br /&gt;
* USB&lt;br /&gt;
* IP&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird die Einrichtung von knxd mit einem IP Gateway auf einem Raspberry Pi2 mit Wheezy oder Jessie beschrieben.&lt;br /&gt;
&lt;br /&gt;
=== Installation ===&lt;br /&gt;
&lt;br /&gt;
==== Für Debian Jessie: ====&lt;br /&gt;
&#039;&#039;&#039;als erstes müssen folgende Pakete installiert werden (Referenz Debian Jessie):&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get update&lt;br /&gt;
sudo apt-get install debhelper cdbs automake libtool libusb-1.0-0-dev git-core build-essential libsystemd-daemon-dev dh-systemd libev-dev cmake&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;knxd herunterladen und installieren&#039;&#039;&#039;&lt;br /&gt;
Achtung: Wenn Abhängigkeiten fehlen, dann müssen diese nachinstalliert werden. Nicht einfach mittels &amp;quot;-d&amp;quot; diese übergehen!&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git clone https://github.com/knxd/knxd.git&lt;br /&gt;
cd knxd&lt;br /&gt;
git checkout deb&lt;br /&gt;
dpkg-buildpackage -b -uc&lt;br /&gt;
cd ..&lt;br /&gt;
sudo dpkg -i knxd_*.deb knxd-tools_*.deb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Ab Debian Stretch, Buster, ... ====&lt;br /&gt;
&#039;&#039;&#039;knxd ist in den Debian packages vorhanden, muss daher nicht compiliert werden.&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get update&lt;br /&gt;
sudo apt-get install knxd knxd-tools&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit der Konfiguration &#039;&#039;&#039;mit Systemd weitermachen!&#039;&#039;&#039; &lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
&#039;&#039;&#039;1. Ohne systemd&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es muss als nächstes die Konfigurationsdatei editiert werden, das geht mit:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/default/knxd &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
dann folgende Einträge anpassen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DAEMON_ARGS=&amp;quot;-u /tmp/eib -u /var/run/knx -i -b ipt:192.168.188.XX&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
und&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
START_KNXD=YES&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2. Mit systemd z. B. für Debian Jessie&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Die Konfigurationsdatei bei Jessie hat sich wegen der Nutzung von systemd geändert:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/knxd.conf &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
dann folgende Einträge anpassen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
KNXD_OPTS=&amp;quot;-e 1.2.202 -E 1.2.203:8 -c -DTRS -b ipt:192.168.188.XX&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== knxd Status überprüfen ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
/etc/init.d/knxd status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== knxd als IP-Gateway einrichten ==&lt;br /&gt;
Der knxd kann auch gleich als IP-Gateway eingerichtet und sowohl mit FHEM als auch parallel mit der ETS genutzt werden. Dazu ist, neben einem Raspberry Pi, ein Interface zum KNX-Bus erforderlich. Geeignet sind z.B.:&lt;br /&gt;
* ROT&lt;br /&gt;
* PIGATOR mit PIM-TPUART&lt;br /&gt;
* TUL&lt;br /&gt;
der Fa. [http://busware.de Busware]. Wer einen Rasperry Pi3 benutzen möchte, der sollte zum TUL greifen, da die serielle Schnittstelle UART0 das Bluetooth-Modul des Pi3 bedient und wieder auf die GPIO-Pins umgeleitet werden muss. Der TUL bringt seine eigene serielle Schnittstelle mit, so dass Bluetooth erhalten bleibt.&lt;br /&gt;
&lt;br /&gt;
=== Vorbereiten des TUL ===&lt;br /&gt;
==== TUL flashen ====&lt;br /&gt;
Der TUL wird ohne Software geliefert und kann über den Raspberry Pi programmiert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install dfu-programmer&lt;br /&gt;
wget -O TPUARTtransparent.hex http://busware.de/tiki-download_file.php?fileId=54&lt;br /&gt;
sudo dfu-programmer atmega32u4 erase&lt;br /&gt;
sudo dfu-programmer atmega32u4 flash TPUARTtransparent.hex&lt;br /&gt;
sudo dfu-programmer atmega32u4 reset&lt;br /&gt;
sudo reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Soll der TUL unter Windows programmiert werden, so geht das mit [https://www.microchip.com/developmenttools/ProductDetails/FLIP FLIP]. Die HEX-Datei kann [http://files.busware.de/TUL/Transparent/ hier] herunter geladen werden.&lt;br /&gt;
Der TUL hat an der Unterseite einen winzigen Button. Dieser muss gedrückt werden, während der TUL in die USB-Buchse gesteckt wird.&lt;br /&gt;
In FLIP nun als &#039;&#039;Device=&amp;gt;Select&#039;&#039; ATmega32U4 auswählen und über &#039;&#039;Settings=&amp;gt;Communication=&amp;gt;USB&#039;&#039; die Verbindung herstellen. *.hex-Datei laden und im Rahmen &#039;&#039;Operation-Flow&#039;&#039; auf &#039;&#039;Run&#039;&#039; klicken. Fertig.&lt;br /&gt;
&lt;br /&gt;
==== TUL einen dauerhaften Namen geben ====&lt;br /&gt;
Linux bindet USB-Geräte beim Boot in einer eher zufälligen Reihenfolge ein. Werden mehrere USB-Geräte betrieben, so ist es sinnvoll, dem TUL einen festen Namen zuzuordnen. Dazu wird der TUL zunächst mit dem Befehl&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls -la /dev/serial/by-id/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
identifiziert. Das Ergebnis sollte ungefähr so aussehen&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
usb-busware.de_TPUART_8543934393935171B1C1-if00 -&amp;gt; ../../ttyACM0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Die Seriennummer (8543934393935171B1C1) wird später benötigt. Der Befehl&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
lsusb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
sollte u.a. diese Zeile liefern&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Bus 001 Device 005: ID 03eb:204b Atmel Corp. LUFA USB to Serial Adapter Project&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
03eb ist dabei die Herstellerkennung, 204b die Produktkennung. Nun muss die Datei /etc/udev/rules.d/99-usb-serial.rules&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/udev/rules.d/99-usb-serial.rules&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
erstellt oder erweitert werden mit der Zeile&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
SUBSYSTEM==&amp;quot;tty&amp;quot;, ATTRS{idVendor}==&amp;quot;03eb&amp;quot;, ATTRS{idProduct}==&amp;quot;204b&amp;quot;, ATTRS{serial}==&amp;quot;8543934393935171B1C1&amp;quot;, SYMLINK+=&amp;quot;knx&amp;quot;, OWNER=&amp;quot;knxd&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Der TUL wird dann unter /dev/knx erreichbar sein. Der knxd läuft als Benutzer knxd und hat damit die Berechtigung, auf den TUL zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
=== Vorbereiten des Raspberry Pi für ROT oder PIGATOR ===&lt;br /&gt;
Der Raspberry Pi nutzt standardmäßig die serielle Schnittstelle als Terminal. Dies muss deaktiviert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo raspi-config&lt;br /&gt;
5 Interfaceoption&lt;br /&gt;
P6 Serial&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Der knxd arbeitet als Benutzer knxd. Nach der Installation von knxd muss dieser noch der Gruppe dialout zugeordnet werden, damit er auf ttyAMA0 zugreifen kann:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo usermod -aG dialout knxd&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Die Raspberry Pi 3 und 4 nutzen für die serielle Schnittstelle einen mini UART, der nicht mit dem knxd zusammenarbeitet. Der Hardware UART wird für Bluetooth verwendet. Bluetooth muss deaktiviert werden, damit der Hardware UART wieder unter ttyAMA0 zur Verfügung steht. In der /boot/config.txt muss die Zeile&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dtoverlay=disable-bt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
am Ende eingefügt werden. Nun muss noch der Dienst hciuart deaktiviert werden (initialisiert das Bluetooth-Modem):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo systemctl disable hciuart&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nach einem anschließenden Reboot ist der TPUART unter ttyAMA0 ansprechbar.&lt;br /&gt;
&lt;br /&gt;
Nach dieser Prozedur ist natürlich die Benuzung des Bluetooth-Moduls nicht mehr möglich. Wer das Modul benötigt, findet die Anleitung hier:&lt;br /&gt;
&lt;br /&gt;
[[Raspberry Pi 3: GPIO-Port Module und Bluetooth]]&lt;br /&gt;
&lt;br /&gt;
Der Raspberry Pi 4 besitzt weitere UARTs, die auch für den knxd genutzt werden können. Weitere Informationen dazu gibt es [https://gitlab.com/knx-makerstuff/knx_microbcu2/-/wikis/DualKNX-RaspiHat-Quick-Installation-Guide#uart-configuration hier].&lt;br /&gt;
&lt;br /&gt;
=== Andere BCU&#039;s (BusCouplerUnit) ===&lt;br /&gt;
Natürlich sind auch andere BCU&#039;s geeignet. Wer weiß, an welchem Ende er einen Lötkolben anzufassen hat, ist mit der [https://knx-user-forum.de/forum/projektforen/konnekting/1045398-microbcu-sehr-kleiner-knx-transceiver MicroBCU] gut bedient. Sie kann z.B. über einen ADUM1201 mit dem UART des Raspberry Pi verbunden werden (Tx-&amp;gt;Rx, Rx-&amp;gt;Tx, Konfiguration wie unter [[Knxd#Vorbereiten_des_Raspberry_Pi_f.C3.BCr_ROT_oder_PIGATOR|ROT]] beschrieben) oder über einen USB2Seriell-Konverter (Konfiguration ähnlich [[Knxd#TUL_einen_dauerhaften_Namen_geben|TUL]]).{{Hinweis|Die MicroBCU wird vom Bus gespeist und liefert auch zwei Spannungen, wovon die 3,3V auch für den ADUM genutzt werden kann. Wer den Raspi aus dem KNX-Netzteil versorgen möchte, sollte sich [https://knx-user-forum.de/forum/%C3%B6ffentlicher-bereich/knx-eib-forum/diy-do-it-yourself/1597469-dualknx-microbcu-hat-f%C3%BCr-raspberrypi-mit-dc-dc-netzteil das hier] mal ansehen.}}&lt;br /&gt;
&lt;br /&gt;
=== Installieren des knxd ===&lt;br /&gt;
Die Installation erfolgt nun wie oben unter [[Knxd#Installation|Installation]] beschrieben. Hier noch mal der dringende Hinweis, fehlende Abhängigkeiten nicht mit -d zu überspringen. Jede Abhängigkeit, die als Fehlend moniert wird, nachinstallieren und Kompilierung neu starten. Prozedur notfalls mehrfach wiederholen. Das Kompilieren dauert und manchmal geht es scheinbar nicht weiter. Also Geduld.&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
Die Konfiguration erfolgt wieder in der knxd.conf mit&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/knxd.conf&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nun die Konfiguarionszeile anpassen&amp;lt;br&amp;gt;&lt;br /&gt;
(serielle Schnittstelle)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
KNXD_OPTS=&amp;quot;-e 1.2.202 -E 1.2.203:8 -c -DTRS -b tpuarts:/dev/ttyAMA0&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
(USB)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
KNXD_OPTS=&amp;quot;-e 1.2.202 -E 1.2.203:8 -c -DTRS -b tpuarts:/dev/knx&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Und dann noch&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
START_KNXD=YES&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
um knxd beim Systemstart sofort zu starten.&lt;br /&gt;
&lt;br /&gt;
-e definiert die physikalische Adresse des knxd, -E definiert einen Adressbereich für ETS5 etc. (hier einen Bereich aus acht Adressen). Diese Adressen müssen an das eigene Netz angepasst werden. In FHEM sieht das dann so aus &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
define myKNXGW KNXIO T 127.0.0.1:6720 1.2.203&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
alternativ via Multicast: (siehe auch KNXIO-wiki):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
define myKNXGW KNXIO M 224.0.23.12:3671 1.2.203&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Spätestens jetzt sollte der KNX-Bus angeschlossen werden.{{Hinweis|Da der TPUART (wie auch andere BCU‘s) vom Bus gespeist wird, kann der knxd den TPUART nur initialisieren, wenn der Bus angeschaltet ist.}}&lt;br /&gt;
Wer Multicast nutzen möchte, muss ab Buster dieses noch aktivieren (z.B. für Tasmota-KNX)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts&lt;br /&gt;
&amp;quot;1&amp;quot; durch &amp;quot;0&amp;quot; ersetzen&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nach einem&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
sollte der knxd dann laufen.&lt;br /&gt;
{{Hinweis|Manche KNX-Module bringen zusätzlich eine IP-Gateway-Funktion mit (z.B. sonnenKNX zur Verbindung der sonnenBatterie mit dem KNX-Bus). Hier führt die Option -R in der Konfigurationsdatei zu Problemen (KNX-IP Daten werden mehrfach auf den Bus gespiegelt). Daher muss die Option -R entfernt werden (-DTS), wenn ein solches Modul nachträglich in das System integriert wird.}}&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
&#039;&#039;&#039;Wie wird eibd vorher deinstalliert?&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo rm -r /usr/local/bin/{eibd,knxtool,group*} /usr/local/lib/lib{eib,pthsem}*.so* /usr/local/include/pth*&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Hinweis&#039;&#039;&#039;&amp;lt;/u&amp;gt;: knxd unterstützt im Gegensatz zu eibd die Hilfsprogramme knxtools nur sehr eingeschränkt (Siehe dazu Hinweis unter https://github.com/knxd/knxd#migrating-to-012. &amp;quot;progmode&amp;quot; sowie alle mit &amp;quot;m&amp;quot; beginnenden Kommandos sind entgegen der Doku ab Version 0.12 nicht mehr funktionsfähig. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;folgender Fehler: dpkg-buildpackage: Fehler: Fehler-Exitstatus von debian/rules build war 2&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install git-core build-essential&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
in der datei knxd/debian/rules die Zeile:&lt;br /&gt;
bash tools/test.sh auskommentieren&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Fehler: dpkg-buildpackage: error: fakeroot not found, either install the fakeroot &amp;lt;....&amp;gt; &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install fakeroot dpkg-dev&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[Benutzer:Marthinx]]&lt;br /&gt;
* [https://github.com/knxd/knxd Github knxd]&lt;br /&gt;
* [https://knx-user-forum.de/forum/projektforen/knxd/1049547-grundlagen-zum-knxd-mit-installationsanleitung-vor-dem-schreiben-lesen Forums-Thread zu knxd. Sehr informativ.]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Examples]]&lt;br /&gt;
[[Kategorie:EIB/KNX]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Knxd&amp;diff=37940</id>
		<title>Knxd</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Knxd&amp;diff=37940"/>
		<updated>2023-01-13T13:48:16Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Ergänzung für RasPi 4&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== knxd mit einem IP Gateway einrichten ==&lt;br /&gt;
Damit FHEM auf den KNX Bus zugreifen kann, wird ein passendes Interface benötigt. Es gibt:&lt;br /&gt;
* RS232&lt;br /&gt;
* USB&lt;br /&gt;
* IP&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird die Einrichtung von knxd mit einem IP Gateway auf einem Raspberry Pi2 mit Wheezy oder Jessie beschrieben.&lt;br /&gt;
&lt;br /&gt;
=== Installation ===&lt;br /&gt;
&lt;br /&gt;
==== Für Debian Jessie: ====&lt;br /&gt;
&#039;&#039;&#039;als erstes müssen folgende Pakete installiert werden (Referenz Debian Jessie):&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get update&lt;br /&gt;
sudo apt-get install debhelper cdbs automake libtool libusb-1.0-0-dev git-core build-essential libsystemd-daemon-dev dh-systemd libev-dev cmake&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;knxd herunterladen und installieren&#039;&#039;&#039;&lt;br /&gt;
Achtung: Wenn Abhängigkeiten fehlen, dann müssen diese nachinstalliert werden. Nicht einfach mittels &amp;quot;-d&amp;quot; diese übergehen!&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git clone https://github.com/knxd/knxd.git&lt;br /&gt;
cd knxd&lt;br /&gt;
git checkout deb&lt;br /&gt;
dpkg-buildpackage -b -uc&lt;br /&gt;
cd ..&lt;br /&gt;
sudo dpkg -i knxd_*.deb knxd-tools_*.deb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Ab Debian Stretch, Buster, ... ====&lt;br /&gt;
&#039;&#039;&#039;knxd ist in den Debian packages vorhanden, muss daher nicht compiliert werden.&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get update&lt;br /&gt;
sudo apt-get install knxd knxd-tools&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit der Konfiguration &#039;&#039;&#039;mit Systemd weitermachen!&#039;&#039;&#039; &lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
&#039;&#039;&#039;1. Ohne systemd&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es muss als nächstes die Konfigurationsdatei editiert werden, das geht mit:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/default/knxd &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
dann folgende Einträge anpassen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DAEMON_ARGS=&amp;quot;-u /tmp/eib -u /var/run/knx -i -b ipt:192.168.188.XX&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
und&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
START_KNXD=YES&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2. Mit systemd z. B. für Debian Jessie&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Die Konfigurationsdatei bei Jessie hat sich wegen der Nutzung von systemd geändert:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/knxd.conf &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
dann folgende Einträge anpassen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
KNXD_OPTS=&amp;quot;-e 1.2.202 -E 1.2.203:8 -c -DTRS -b ipt:192.168.188.XX&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== knxd Status überprüfen ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
/etc/init.d/knxd status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== knxd als IP-Gateway einrichten ==&lt;br /&gt;
Der knxd kann auch gleich als IP-Gateway eingerichtet und sowohl mit FHEM als auch parallel mit der ETS genutzt werden. Dazu ist, neben einem Raspberry Pi, ein Interface zum KNX-Bus erforderlich. Geeignet sind z.B.:&lt;br /&gt;
* ROT&lt;br /&gt;
* PIGATOR mit PIM-TPUART&lt;br /&gt;
* TUL&lt;br /&gt;
der Fa. [http://busware.de Busware]. Wer einen Rasperry Pi3 benutzen möchte, der sollte zum TUL greifen, da die serielle Schnittstelle UART0 das Bluetooth-Modul des Pi3 bedient und wieder auf die GPIO-Pins umgeleitet werden muss. Der TUL bringt seine eigene serielle Schnittstelle mit, so dass Bluetooth erhalten bleibt.&lt;br /&gt;
&lt;br /&gt;
=== Vorbereiten des TUL ===&lt;br /&gt;
==== TUL flashen ====&lt;br /&gt;
Der TUL wird ohne Software geliefert und kann über den Raspberry Pi programmiert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install dfu-programmer&lt;br /&gt;
wget -O TPUARTtransparent.hex http://busware.de/tiki-download_file.php?fileId=54&lt;br /&gt;
sudo dfu-programmer atmega32u4 erase&lt;br /&gt;
sudo dfu-programmer atmega32u4 flash TPUARTtransparent.hex&lt;br /&gt;
sudo dfu-programmer atmega32u4 reset&lt;br /&gt;
sudo reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Soll der TUL unter Windows programmiert werden, so geht das mit [https://www.microchip.com/developmenttools/ProductDetails/FLIP FLIP]. Die HEX-Datei kann [http://files.busware.de/TUL/Transparent/ hier] herunter geladen werden.&lt;br /&gt;
Der TUL hat an der Unterseite einen winzigen Button. Dieser muss gedrückt werden, während der TUL in die USB-Buchse gesteckt wird.&lt;br /&gt;
In FLIP nun als &#039;&#039;Device=&amp;gt;Select&#039;&#039; ATmega32U4 auswählen und über &#039;&#039;Settings=&amp;gt;Communication=&amp;gt;USB&#039;&#039; die Verbindung herstellen. *.hex-Datei laden und im Rahmen &#039;&#039;Operation-Flow&#039;&#039; auf &#039;&#039;Run&#039;&#039; klicken. Fertig.&lt;br /&gt;
&lt;br /&gt;
==== TUL einen dauerhaften Namen geben ====&lt;br /&gt;
Linux bindet USB-Geräte beim Boot in einer eher zufälligen Reihenfolge ein. Werden mehrere USB-Geräte betrieben, so ist es sinnvoll, dem TUL einen festen Namen zuzuordnen. Dazu wird der TUL zunächst mit dem Befehl&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls -la /dev/serial/by-id/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
identifiziert. Das Ergebnis sollte ungefähr so aussehen&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
usb-busware.de_TPUART_8543934393935171B1C1-if00 -&amp;gt; ../../ttyACM0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Die Seriennummer (8543934393935171B1C1) wird später benötigt. Der Befehl&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
lsusb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
sollte u.a. diese Zeile liefern&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Bus 001 Device 005: ID 03eb:204b Atmel Corp. LUFA USB to Serial Adapter Project&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
03eb ist dabei die Herstellerkennung, 204b die Produktkennung. Nun muss die Datei /etc/udev/rules.d/99-usb-serial.rules&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/udev/rules.d/99-usb-serial.rules&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
erstellt oder erweitert werden mit der Zeile&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
SUBSYSTEM==&amp;quot;tty&amp;quot;, ATTRS{idVendor}==&amp;quot;03eb&amp;quot;, ATTRS{idProduct}==&amp;quot;204b&amp;quot;, ATTRS{serial}==&amp;quot;8543934393935171B1C1&amp;quot;, SYMLINK+=&amp;quot;knx&amp;quot;, OWNER=&amp;quot;knxd&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Der TUL wird dann unter /dev/knx erreichbar sein. Der knxd läuft als Benutzer knxd und hat damit die Berechtigung, auf den TUL zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
=== Vorbereiten des Raspberry Pi für ROT oder PIGATOR ===&lt;br /&gt;
Der Raspberry Pi nutzt standardmäßig die serielle Schnittstelle als Terminal. Dies muss deaktiviert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo raspi-config&lt;br /&gt;
5 Interfaceoption&lt;br /&gt;
P6 Serial&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Der knxd arbeitet als Benutzer knxd. Nach der Installation von knxd muss dieser noch der Gruppe dialout zugeordnet werden, damit er auf ttyAMA0 zugreifen kann:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo usermod -aG dialout knxd&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Die Raspberry Pi 3 und 4 nutzen für die serielle Schnittstelle einen mini UART, der nicht mit dem knxd zusammenarbeitet. Der Hardware UART wird für Bluetooth verwendet. Bluetooth muss deaktiviert werden, damit der Hardware UART wieder unter ttyAMA0 zur Verfügung steht. In der /boot/config.txt muss die Zeile&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dtoverlay=disable-bt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
am Ende eingefügt werden. Nun muss noch der Dienst hciuart deaktiviert werden (initialisiert das Bluetooth-Modem):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo systemctl disable hciuart&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nach einem anschließenden Reboot ist der TPUART unter ttyAMA0 ansprechbar.&lt;br /&gt;
&lt;br /&gt;
Nach dieser Prozedur ist natürlich die Benuzung des Bluetooth-Moduls nicht mehr möglich. Wer das Modul benötigt, findet die Anleitung hier:&lt;br /&gt;
&lt;br /&gt;
[[Raspberry Pi 3: GPIO-Port Module und Bluetooth]]&lt;br /&gt;
&lt;br /&gt;
Der Raspberry Pi 4 besitzt weitere UARTs, die auch für den knxd genutzt werden können. Weitere Informationen dazu gibt es [https://gitlab.com/knx-makerstuff/knx_microbcu2/-/wikis/DualKNX-RaspiHat-Quick-Installation-Guide hier].&lt;br /&gt;
&lt;br /&gt;
=== Andere BCU&#039;s (BusCouplerUnit) ===&lt;br /&gt;
Natürlich sind auch andere BCU&#039;s geeignet. Wer weiß, an welchem Ende er einen Lötkolben anzufassen hat, ist mit der [https://knx-user-forum.de/forum/projektforen/konnekting/1045398-microbcu-sehr-kleiner-knx-transceiver MicroBCU] gut bedient. Sie kann z.B. über einen ADUM1201 mit dem UART des Raspberry Pi verbunden werden (Tx-&amp;gt;Rx, Rx-&amp;gt;Tx, Konfiguration wie unter [[Knxd#Vorbereiten_des_Raspberry_Pi_f.C3.BCr_ROT_oder_PIGATOR|ROT]] beschrieben) oder über einen USB2Seriell-Konverter (Konfiguration ähnlich [[Knxd#TUL_einen_dauerhaften_Namen_geben|TUL]]).{{Hinweis|Die MicroBCU wird vom Bus gespeist und liefert auch zwei Spannungen, wovon die 3,3V auch für den ADUM genutzt werden kann. Wer den Raspi aus dem KNX-Netzteil versorgen möchte, sollte sich [https://knx-user-forum.de/forum/%C3%B6ffentlicher-bereich/knx-eib-forum/diy-do-it-yourself/1597469-dualknx-microbcu-hat-f%C3%BCr-raspberrypi-mit-dc-dc-netzteil das hier] mal ansehen.}}&lt;br /&gt;
&lt;br /&gt;
=== Installieren des knxd ===&lt;br /&gt;
Die Installation erfolgt nun wie oben unter [[Knxd#Installation|Installation]] beschrieben. Hier noch mal der dringende Hinweis, fehlende Abhängigkeiten nicht mit -d zu überspringen. Jede Abhängigkeit, die als Fehlend moniert wird, nachinstallieren und Kompilierung neu starten. Prozedur notfalls mehrfach wiederholen. Das Kompilieren dauert und manchmal geht es scheinbar nicht weiter. Also Geduld.&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
Die Konfiguration erfolgt wieder in der knxd.conf mit&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/knxd.conf&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nun die Konfiguarionszeile anpassen&amp;lt;br&amp;gt;&lt;br /&gt;
(serielle Schnittstelle)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
KNXD_OPTS=&amp;quot;-e 1.2.202 -E 1.2.203:8 -c -DTRS -b tpuarts:/dev/ttyAMA0&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
(USB)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
KNXD_OPTS=&amp;quot;-e 1.2.202 -E 1.2.203:8 -c -DTRS -b tpuarts:/dev/knx&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Und dann noch&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
START_KNXD=YES&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
um knxd beim Systemstart sofort zu starten.&lt;br /&gt;
&lt;br /&gt;
-e definiert die physikalische Adresse des knxd, -E definiert einen Adressbereich für ETS5 etc. (hier einen Bereich aus acht Adressen). Diese Adressen müssen an das eigene Netz angepasst werden. In FHEM sieht das dann so aus &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
define myKNXGW KNXIO T 127.0.0.1:6720 1.2.203&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
alternativ via Multicast: (siehe auch KNXIO-wiki):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
define myKNXGW KNXIO M 224.0.23.12:3671 1.2.203&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Spätestens jetzt sollte der KNX-Bus angeschlossen werden.{{Hinweis|Da der TPUART (wie auch andere BCU‘s) vom Bus gespeist wird, kann der knxd den TPUART nur initialisieren, wenn der Bus angeschaltet ist.}}&lt;br /&gt;
Wer Multicast nutzen möchte, muss ab Buster dieses noch aktivieren (z.B. für Tasmota-KNX)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts&lt;br /&gt;
&amp;quot;1&amp;quot; durch &amp;quot;0&amp;quot; ersetzen&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nach einem&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
sollte der knxd dann laufen.&lt;br /&gt;
{{Hinweis|Manche KNX-Module bringen zusätzlich eine IP-Gateway-Funktion mit (z.B. sonnenKNX zur Verbindung der sonnenBatterie mit dem KNX-Bus). Hier führt die Option -R in der Konfigurationsdatei zu Problemen (KNX-IP Daten werden mehrfach auf den Bus gespiegelt). Daher muss die Option -R entfernt werden (-DTS), wenn ein solches Modul nachträglich in das System integriert wird.}}&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
&#039;&#039;&#039;Wie wird eibd vorher deinstalliert?&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo rm -r /usr/local/bin/{eibd,knxtool,group*} /usr/local/lib/lib{eib,pthsem}*.so* /usr/local/include/pth*&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Hinweis&#039;&#039;&#039;&amp;lt;/u&amp;gt;: knxd unterstützt im Gegensatz zu eibd die Hilfsprogramme knxtools nur sehr eingeschränkt (Siehe dazu Hinweis unter https://github.com/knxd/knxd#migrating-to-012. &amp;quot;progmode&amp;quot; sowie alle mit &amp;quot;m&amp;quot; beginnenden Kommandos sind entgegen der Doku ab Version 0.12 nicht mehr funktionsfähig. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;folgender Fehler: dpkg-buildpackage: Fehler: Fehler-Exitstatus von debian/rules build war 2&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install git-core build-essential&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
in der datei knxd/debian/rules die Zeile:&lt;br /&gt;
bash tools/test.sh auskommentieren&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Fehler: dpkg-buildpackage: error: fakeroot not found, either install the fakeroot &amp;lt;....&amp;gt; &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install fakeroot dpkg-dev&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[Benutzer:Marthinx]]&lt;br /&gt;
* [https://github.com/knxd/knxd Github knxd]&lt;br /&gt;
* [https://knx-user-forum.de/forum/projektforen/knxd/1049547-grundlagen-zum-knxd-mit-installationsanleitung-vor-dem-schreiben-lesen Forums-Thread zu knxd. Sehr informativ.]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Examples]]&lt;br /&gt;
[[Kategorie:EIB/KNX]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=37923</id>
		<title>Einrichten der Bluetooth-Thermostate von eQ-3</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=37923"/>
		<updated>2023-01-07T14:11:48Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Genaue Typbezeichnung hinzu gefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Firma eQ-3 stellt verschiedene elektronische Heizkörperthermostate her. Das Eqiva BLUETOOTH® Smart Heizkörperthermostat (CC-RT-BLE-EQ) kann auch von FHEM gesteuert werden. Voraussetzung ist natürlich ein Bluetooth-Empfänger (RasPi 3+4 oder Bluetooth-Dongle).&lt;br /&gt;
{{Randnotiz|RNText=Hinweis: Es gibt auch Versionen ohne Bluetooth, die genau gleich aussehen. Bei der Bestellung bitte aufpassen.|RNTyp=Warn|style=}}&lt;br /&gt;
== Bluetooth einrichten ==&lt;br /&gt;
Standardmäßig sollte Bluetooth auf dem Raspberry Pi schon eingerichtet sein. Nutzt man einen B+ mit Dongle (z.B. als Verlängerung), so müssen unter Umständen folgende Pakete installiert werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install bluetooth, bluez&amp;lt;/pre&amp;gt;&lt;br /&gt;
Danach ein &amp;lt;code&amp;gt;sudo reboot&amp;lt;/code&amp;gt;. Ein &amp;lt;code&amp;gt;sudo service bluetooth status&amp;lt;/code&amp;gt; sollte zeigen, dass der Daemon läuft.&lt;br /&gt;
Damit der user fhem bzw. pi auf bluetooth zugreifen kann, muss in bluetooth.conf noch folgendes eingetragen werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo nano /etc/dbus-1/system.d/bluetooth.conf&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;policy user=&amp;quot;fhem&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;allow own=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_destination=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattCharacteristic1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattDescriptor1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.ObjectManager&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.Properties&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/policy&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo systemctl restart dbus&amp;lt;/pre&amp;gt;&lt;br /&gt;
Für den User pi muss natürlich fhem durch pi ersetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Thermostat in FHEM definieren ==&lt;br /&gt;
Bevor das Thermostat in FHEM eingebunden werden kann, muss die MAC-Adresse ermittelt werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;pi@raspberrypi ~ $ bluetoothctl&lt;br /&gt;
[NEW] Controller 00:1A:7D:XX:XX:XX raspberrypi [default]&lt;br /&gt;
[bluetooth]# scan on&lt;br /&gt;
Discovery started&lt;br /&gt;
[CHG] Controller 00:1A:7D:XX:XX:XX Discovering: yes&lt;br /&gt;
[NEW] Device 41:86:FB:XX:XX:XX 41-86-FB-...&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -56&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -70&lt;br /&gt;
[NEW] Device 5A:64:25:XX:XX:XX 5A-64-25-...&lt;br /&gt;
[bluetooth]# scan off&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Geräte tragen den Namen CC-RT-BLE.&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit Perl-Modul 10_EQ3BT ===&lt;br /&gt;
Die eQ-3 Heizkörperthermostate können einfach über&lt;br /&gt;
define &amp;lt;name&amp;gt; EQ3BT &amp;lt;mac address&amp;gt; &lt;br /&gt;
eingebunden werden.&lt;br /&gt;
{{Hinweis|Mittlerweile wird nur noch das fhempy-Modul empfohlen}}&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit fhempy ===&lt;br /&gt;
fhempy ermöglicht das Schreiben von FHEM-Modulen in der Programmiersprache Python. Erforderlich ist Python 3.8 oder höher (NICHT 2!), weshalb Debian Bullseye empfehlenswert ist. Es ist auch möglich, fhempy auf Peers zu installieren, um dadurch die Bluetooth-Reichweite zu erhöhen. Dadurch ist eine komplette Abdeckung des Hauses möglich. Auf den Peers muss FHEM nicht installiert werden. Neben dem Raspberry Pi Zero eignet sich auch z.B. der Radxa Rock Pi Zero, getestet mit Armbian. Die Peers können aus FHEM heraus verwaltet werden.&lt;br /&gt;
==== Installation auf FHEM-Server ====&lt;br /&gt;
Um die Heizkörperthermostate unter fhempy einzurichten, sind zunächst einige Vorarbeiten erforderlich. Das Einrichten geht dann genau so simpel.&lt;br /&gt;
Nach dem obligatorischen &amp;lt;code&amp;gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get upgrade&amp;lt;/code&amp;gt; werden die benötigten Python-Pakete mit&lt;br /&gt;
&lt;br /&gt;
[Debian 11 (Bullseye)]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git libprotocol-websocket-perl&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[alle anderen]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git&amp;lt;/pre&amp;gt;&lt;br /&gt;
und als nächstes&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo cpan Protocol::WebSocket&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das dauert eine Weile. Ich empfehle eine Tasse koffeinhaltiges Heißgetränk.&lt;br /&gt;
Ist die Installation abgeschlossen, geht es an die Konfiguration von FHEM. Zunächst laden wir per Update die benötigten Dateien herunter:&lt;br /&gt;
&amp;lt;pre&amp;gt;update add https://raw.githubusercontent.com/dominikkarall/fhempy/master/controls_pythonbinding.txt&lt;br /&gt;
update&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ist das Update abgeschlossen, können wir fhempy einrichten:&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_local BindingsIo fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Es wird automatisch &#039;&#039;&#039;fhempyserver&#039;&#039;&#039; und &#039;&#039;&#039;fhempy_local&#039;&#039;&#039; eingerichtet. Auch hier gilt: nicht nervös werden, wenn fhempy_local nicht sofort &#039;&#039;connected&#039;&#039; anzeigt.&lt;br /&gt;
&lt;br /&gt;
Hiermit sind die Vorbereitungen abgeschlossen. Das Thermostat kann nun mit&lt;br /&gt;
&amp;lt;pre&amp;gt;define &amp;lt;name&amp;gt; fhempy eq3bt &amp;lt;MAC-Adresse&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
eingebunden werden. Die benötigten Module werden automatisch nachgeladen.&lt;br /&gt;
&lt;br /&gt;
==== Installation des fhempy-Peer ====&lt;br /&gt;
fhempy läuft nicht nur lokal auf dem FHEM-Server. Zur Reichweitenerhöhung kann auch ein fhempy-Peer auf einem oder mehreren RasPi’s installiert und diese über die Wohnung verteilt werden. Geeignet ist natürlich auch ein RasPi, der zur Visualisierung dient.&lt;br /&gt;
{{Hinweis|WICHTIG!! Die folgenden Befehle dürfen nur auf dem Remote-RasPi und nicht auf der FHEM-Instanz ausgeführt werden.}}&lt;br /&gt;
Zunächst müssen die benötigten Python-Pakete wie oben beschrieben installiert werden. Installiere nun fhempy als User pi&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install --upgrade fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Überprüfe, ob die Hauptinstanz auf dem FHEM-Server läuft und starte dann fhempy als User pi auf dem Peer&lt;br /&gt;
&amp;lt;pre&amp;gt;fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nach kurzer Zeit siehst du die ankommende FHEM-Verbindung.&lt;br /&gt;
Nun noch die systemd-Konfiguration, damit fhempy automatisch gestartet wird&lt;br /&gt;
&amp;lt;pre&amp;gt;curl -sL https://raw.githubusercontent.com/fhempy/fhempy/master/install_systemd_fhempy.sh | sudo -E bash -&amp;lt;/pre&amp;gt;&lt;br /&gt;
fhempy läuft nun unter dem User pi. Möchtest du das ändern, so schau in die Datei &amp;lt;code&amp;gt;fhempy.service&amp;lt;/code&amp;gt; im Verzeichnis &amp;lt;code&amp;gt;/etc/systemd/system/&amp;lt;/code&amp;gt;  Hinterher das sudo systemctl daemon-reload nicht vergessen.&lt;br /&gt;
Der Peer sollte in FHEM automatisch erkannt werden (beruht auf Zeroconf). Sollte das nicht der Fall sein, kann der Peer auch manuell definiert werden&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_peer_IP BindingsIo IP:15733 fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Pairing ==&lt;br /&gt;
Die Thermostate mit einer Software größer 120 müssen mit dem RasPi gepaired werden. Drücke dazu das Rad am Thermostat bis „Pair“ im Display erscheint. Dann führe folgende Schritte aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo bluetoothctl&lt;br /&gt;
[bluetooth]# power on&lt;br /&gt;
[bluetooth]# agent on&lt;br /&gt;
[bluetooth]# default-agent&lt;br /&gt;
[bluetooth]# scan on&lt;br /&gt;
[bluetooth]# scan off&lt;br /&gt;
[bluetooth]# pair 00:1A:22:06:A7:83&lt;br /&gt;
[agent] Enter passkey (number in 0-999999): &amp;lt;enter pin&amp;gt;&lt;br /&gt;
[bluetooth]# trust 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# disconnect 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# exit&lt;br /&gt;
&lt;br /&gt;
Optional steps:&lt;br /&gt;
[bluetooth]# devices - to list all bluetooth devices&lt;br /&gt;
[bluetooth]# info 00:1A:22:06:A7:83&lt;br /&gt;
Device 00:1A:22:06:A7:83 (public)&lt;br /&gt;
        Name: CC-RT-BLE&lt;br /&gt;
        Alias: CC-RT-BLE&lt;br /&gt;
        Paired: yes&lt;br /&gt;
        Trusted: yes&lt;br /&gt;
        Blocked: no&lt;br /&gt;
        Connected: no&lt;br /&gt;
        LegacyPairing: no&lt;br /&gt;
        UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Device Information        (0000180a-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Vendor specific           (3e135142-654f-9090-134a-a6ff5bb77046)&lt;br /&gt;
        UUID: Vendor specific           (9e5d1e47-5c13-43a0-8635-82ad38a1386f)&lt;br /&gt;
        ManufacturerData Key: 0x0000&lt;br /&gt;
        ManufacturerData Value:&lt;br /&gt;
  00 00 00 00 00 00 00 00 00                       .........&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dadurch ist das Thermostat nicht mehr mit der calor BT-App steuerbar (und umgekehrt).&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
=== Fehlermeldung nach fhempy-Installation ===&lt;br /&gt;
Meldet pip3 folgendes&lt;br /&gt;
&amp;lt;pre&amp;gt;  WARNING: The script normalizer is installed in &#039;/home/myname/.local/bin&#039; which is not on PATH.&lt;br /&gt;
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.&amp;lt;/pre&amp;gt;&lt;br /&gt;
so fehlt der Pfad zu fhempy und fhempy kann nicht aufgerufen werden. Es ist folgender Befehl aufzurufen&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/myname/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
also z.B.&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/pi/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Keine Reaktion auf Einstellen der Offset-Temperatur ===&lt;br /&gt;
Zur Zeit scheint es ein Softwareproblem beim Einstellen der Offset-Temperatur über Bluetooth zu geben (Version 146 oder kleiner). Die Einstellung wird übertragen, wirkt sich aber nicht auf das Thermostat aus. Erst wenn man die Einstellung über das Menü am Thermostat bestätigt (oder gleich dort einstellt), reagiert das Thermostat. Das Problem tritt auch bei der Bedienung über die App auf.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/fhempy/fhempy fhempy-Projekt auf Github]&lt;br /&gt;
* [https://github.com/rytilahti/python-eq3bt#pairing Pairing der Thermostate]&lt;br /&gt;
* {{Link2Forum|Topic=60595|LinkText=Forums-Beitrag}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Heizungsventile]]&lt;br /&gt;
[[Kategorie:Bluetooth]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Knxd&amp;diff=37902</id>
		<title>Knxd</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Knxd&amp;diff=37902"/>
		<updated>2023-01-02T11:56:06Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Info zum Parameter -R hinzu gefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== knxd mit einem IP Gateway einrichten ==&lt;br /&gt;
Damit FHEM auf den KNX Bus zugreifen kann, wird ein passendes Interface benötigt. Es gibt:&lt;br /&gt;
* RS232&lt;br /&gt;
* USB&lt;br /&gt;
* IP&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird die Einrichtung von knxd mit einem IP Gateway auf einem Raspberry Pi2 mit Wheezy oder Jessie beschrieben.&lt;br /&gt;
&lt;br /&gt;
=== Installation ===&lt;br /&gt;
&lt;br /&gt;
==== Für Debian Jessie: ====&lt;br /&gt;
&#039;&#039;&#039;als erstes müssen folgende Pakete installiert werden (Referenz Debian Jessie):&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get update&lt;br /&gt;
sudo apt-get install debhelper cdbs automake libtool libusb-1.0-0-dev git-core build-essential libsystemd-daemon-dev dh-systemd libev-dev cmake&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;knxd herunterladen und installieren&#039;&#039;&#039;&lt;br /&gt;
Achtung: Wenn Abhängigkeiten fehlen, dann müssen diese nachinstalliert werden. Nicht einfach mittels &amp;quot;-d&amp;quot; diese übergehen!&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git clone https://github.com/knxd/knxd.git&lt;br /&gt;
cd knxd&lt;br /&gt;
git checkout deb&lt;br /&gt;
dpkg-buildpackage -b -uc&lt;br /&gt;
cd ..&lt;br /&gt;
sudo dpkg -i knxd_*.deb knxd-tools_*.deb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Ab Debian Stretch, Buster, ... ====&lt;br /&gt;
&#039;&#039;&#039;knxd ist in den Debian packages vorhanden, muss daher nicht compiliert werden.&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get update&lt;br /&gt;
sudo apt-get install knxd knxd-tools&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit der Konfiguration &#039;&#039;&#039;mit Systemd weitermachen!&#039;&#039;&#039; &lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
&#039;&#039;&#039;1. Ohne systemd&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es muss als nächstes die Konfigurationsdatei editiert werden, das geht mit:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/default/knxd &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
dann folgende Einträge anpassen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DAEMON_ARGS=&amp;quot;-u /tmp/eib -u /var/run/knx -i -b ipt:192.168.188.XX&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
und&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
START_KNXD=YES&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2. Mit systemd z. B. für Debian Jessie&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Die Konfigurationsdatei bei Jessie hat sich wegen der Nutzung von systemd geändert:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/knxd.conf &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
dann folgende Einträge anpassen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
KNXD_OPTS=&amp;quot;-e 1.2.202 -E 1.2.203:8 -c -DTRS -b ipt:192.168.188.XX&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== knxd Status überprüfen ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
/etc/init.d/knxd status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== knxd als IP-Gateway einrichten ==&lt;br /&gt;
Der knxd kann auch gleich als IP-Gateway eingerichtet und sowohl mit FHEM als auch parallel mit der ETS genutzt werden. Dazu ist, neben einem Raspberry Pi, ein Interface zum KNX-Bus erforderlich. Geeignet sind z.B.:&lt;br /&gt;
* ROT&lt;br /&gt;
* PIGATOR mit PIM-TPUART&lt;br /&gt;
* TUL&lt;br /&gt;
der Fa. [http://busware.de Busware]. Wer einen Rasperry Pi3 benutzen möchte, der sollte zum TUL greifen, da die serielle Schnittstelle UART0 das Bluetooth-Modul des Pi3 bedient und wieder auf die GPIO-Pins umgeleitet werden muss. Der TUL bringt seine eigene serielle Schnittstelle mit, so dass Bluetooth erhalten bleibt.&lt;br /&gt;
&lt;br /&gt;
=== Vorbereiten des TUL ===&lt;br /&gt;
==== TUL flashen ====&lt;br /&gt;
Der TUL wird ohne Software geliefert und kann über den Raspberry Pi programmiert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install dfu-programmer&lt;br /&gt;
wget -O TPUARTtransparent.hex http://busware.de/tiki-download_file.php?fileId=54&lt;br /&gt;
sudo dfu-programmer atmega32u4 erase&lt;br /&gt;
sudo dfu-programmer atmega32u4 flash TPUARTtransparent.hex&lt;br /&gt;
sudo dfu-programmer atmega32u4 reset&lt;br /&gt;
sudo reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Soll der TUL unter Windows programmiert werden, so geht das mit [https://www.microchip.com/developmenttools/ProductDetails/FLIP FLIP]. Die HEX-Datei kann [http://files.busware.de/TUL/Transparent/ hier] herunter geladen werden.&lt;br /&gt;
Der TUL hat an der Unterseite einen winzigen Button. Dieser muss gedrückt werden, während der TUL in die USB-Buchse gesteckt wird.&lt;br /&gt;
In FLIP nun als &#039;&#039;Device=&amp;gt;Select&#039;&#039; ATmega32U4 auswählen und über &#039;&#039;Settings=&amp;gt;Communication=&amp;gt;USB&#039;&#039; die Verbindung herstellen. *.hex-Datei laden und im Rahmen &#039;&#039;Operation-Flow&#039;&#039; auf &#039;&#039;Run&#039;&#039; klicken. Fertig.&lt;br /&gt;
&lt;br /&gt;
==== TUL einen dauerhaften Namen geben ====&lt;br /&gt;
Linux bindet USB-Geräte beim Boot in einer eher zufälligen Reihenfolge ein. Werden mehrere USB-Geräte betrieben, so ist es sinnvoll, dem TUL einen festen Namen zuzuordnen. Dazu wird der TUL zunächst mit dem Befehl&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls -la /dev/serial/by-id/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
identifiziert. Das Ergebnis sollte ungefähr so aussehen&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
usb-busware.de_TPUART_8543934393935171B1C1-if00 -&amp;gt; ../../ttyACM0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Die Seriennummer (8543934393935171B1C1) wird später benötigt. Der Befehl&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
lsusb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
sollte u.a. diese Zeile liefern&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Bus 001 Device 005: ID 03eb:204b Atmel Corp. LUFA USB to Serial Adapter Project&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
03eb ist dabei die Herstellerkennung, 204b die Produktkennung. Nun muss die Datei /etc/udev/rules.d/99-usb-serial.rules&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/udev/rules.d/99-usb-serial.rules&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
erstellt oder erweitert werden mit der Zeile&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
SUBSYSTEM==&amp;quot;tty&amp;quot;, ATTRS{idVendor}==&amp;quot;03eb&amp;quot;, ATTRS{idProduct}==&amp;quot;204b&amp;quot;, ATTRS{serial}==&amp;quot;8543934393935171B1C1&amp;quot;, SYMLINK+=&amp;quot;knx&amp;quot;, OWNER=&amp;quot;knxd&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Der TUL wird dann unter /dev/knx erreichbar sein. Der knxd läuft als Benutzer knxd und hat damit die Berechtigung, auf den TUL zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
=== Vorbereiten des Raspberry Pi für ROT oder PIGATOR ===&lt;br /&gt;
Der Raspberry Pi nutzt standardmäßig die serielle Schnittstelle als Terminal. Dies muss deaktiviert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo raspi-config&lt;br /&gt;
5 Interfaceoption&lt;br /&gt;
P6 Serial&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Der knxd arbeitet als Benutzer knxd. Nach der Installation von knxd muss dieser noch der Gruppe dialout zugeordnet werden, damit er auf ttyAMA0 zugreifen kann:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo usermod -aG dialout knxd&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Die Raspberry Pi 3 und 4 nutzen für die serielle Schnittstelle einen mini UART, der nicht mit dem knxd zusammenarbeitet. Der Hardware UART wird für Bluetooth verwendet. Bluetooth muss deaktiviert werden, damit der Hardware UART wieder unter ttyAMA0 zur Verfügung steht. In der /boot/config.txt muss die Zeile&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dtoverlay=disable-bt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
am Ende eingefügt werden. Nun muss noch der Dienst hciuart deaktiviert werden (initialisiert das Bluetooth-Modem):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo systemctl disable hciuart&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nach einem anschließenden Reboot ist der TPUART unter ttyAMA0 ansprechbar.&lt;br /&gt;
&lt;br /&gt;
Nach dieser Prozedur ist natürlich die Benuzung des Bluetooth-Moduls nicht mehr möglich. Wer das Modul benötigt, findet die Anleitung hier:&lt;br /&gt;
&lt;br /&gt;
[[Raspberry Pi 3: GPIO-Port Module und Bluetooth]]&lt;br /&gt;
&lt;br /&gt;
=== Andere BCU&#039;s (BusCouplerUnit) ===&lt;br /&gt;
Natürlich sind auch andere BCU&#039;s geeignet. Wer weiß, an welchem Ende er einen Lötkolben anzufassen hat, ist mit der [https://knx-user-forum.de/forum/projektforen/konnekting/1045398-microbcu-sehr-kleiner-knx-transceiver MicroBCU] gut bedient. Sie kann z.B. über einen ADUM1201 mit dem UART des Raspberry Pi verbunden werden (Tx-&amp;gt;Rx, Rx-&amp;gt;Tx, Konfiguration wie unter [[Knxd#Vorbereiten_des_Raspberry_Pi_f.C3.BCr_ROT_oder_PIGATOR|ROT]] beschrieben) oder über einen USB2Seriell-Konverter (Konfiguration ähnlich [[Knxd#TUL_einen_dauerhaften_Namen_geben|TUL]]).{{Hinweis|Die MicroBCU wird vom Bus gespeist und liefert auch zwei Spannungen, wovon die 3,3V auch für den ADUM genutzt werden kann. Wer den Raspi aus dem KNX-Netzteil versorgen möchte, sollte sich [https://knx-user-forum.de/forum/%C3%B6ffentlicher-bereich/knx-eib-forum/diy-do-it-yourself/1597469-dualknx-microbcu-hat-f%C3%BCr-raspberrypi-mit-dc-dc-netzteil das hier] mal ansehen.}}&lt;br /&gt;
&lt;br /&gt;
=== Installieren des knxd ===&lt;br /&gt;
Die Installation erfolgt nun wie oben unter [[Knxd#Installation|Installation]] beschrieben. Hier noch mal der dringende Hinweis, fehlende Abhängigkeiten nicht mit -d zu überspringen. Jede Abhängigkeit, die als Fehlend moniert wird, nachinstallieren und Kompilierung neu starten. Prozedur notfalls mehrfach wiederholen. Das Kompilieren dauert und manchmal geht es scheinbar nicht weiter. Also Geduld.&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
Die Konfiguration erfolgt wieder in der knxd.conf mit&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/knxd.conf&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nun die Konfiguarionszeile anpassen&amp;lt;br&amp;gt;&lt;br /&gt;
(serielle Schnittstelle)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
KNXD_OPTS=&amp;quot;-e 1.2.202 -E 1.2.203:8 -c -DTRS -b tpuarts:/dev/ttyAMA0&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
(USB)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
KNXD_OPTS=&amp;quot;-e 1.2.202 -E 1.2.203:8 -c -DTRS -b tpuarts:/dev/knx&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Und dann noch&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
START_KNXD=YES&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
um knxd beim Systemstart sofort zu starten.&lt;br /&gt;
&lt;br /&gt;
-e definiert die physikalische Adresse des knxd, -E definiert einen Adressbereich für ETS5 etc. (hier einen Bereich aus acht Adressen). Diese Adressen müssen an das eigene Netz angepasst werden. In FHEM sieht das dann so aus &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
define myKNXGW KNXIO T 127.0.0.1:6720 1.2.203&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
alternativ via Multicast: (siehe auch KNXIO-wiki):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
define myKNXGW KNXIO M 224.0.23.12:3671 1.2.203&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Spätestens jetzt sollte der KNX-Bus angeschlossen werden.{{Hinweis|Da der TPUART (wie auch andere BCU‘s) vom Bus gespeist wird, kann der knxd den TPUART nur initialisieren, wenn der Bus angeschaltet ist.}}&lt;br /&gt;
Wer Multicast nutzen möchte, muss ab Buster dieses noch aktivieren (z.B. für Tasmota-KNX)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts&lt;br /&gt;
&amp;quot;1&amp;quot; durch &amp;quot;0&amp;quot; ersetzen&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nach einem&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
sollte der knxd dann laufen.&lt;br /&gt;
{{Hinweis|Manche KNX-Module bringen zusätzlich eine IP-Gateway-Funktion mit (z.B. sonnenKNX zur Verbindung der sonnenBatterie mit dem KNX-Bus). Hier führt die Option -R in der Konfigurationsdatei zu Problemen (KNX-IP Daten werden mehrfach auf den Bus gespiegelt). Daher muss die Option -R entfernt werden (-DTS), wenn ein solches Modul nachträglich in das System integriert wird.}}&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
&#039;&#039;&#039;Wie wird eibd vorher deinstalliert?&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo rm -r /usr/local/bin/{eibd,knxtool,group*} /usr/local/lib/lib{eib,pthsem}*.so* /usr/local/include/pth*&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Hinweis&#039;&#039;&#039;&amp;lt;/u&amp;gt;: knxd unterstützt im Gegensatz zu eibd die Hilfsprogramme knxtools nur sehr eingeschränkt (Siehe dazu Hinweis unter https://github.com/knxd/knxd#migrating-to-012. &amp;quot;progmode&amp;quot; sowie alle mit &amp;quot;m&amp;quot; beginnenden Kommandos sind entgegen der Doku ab Version 0.12 nicht mehr funktionsfähig. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;folgender Fehler: dpkg-buildpackage: Fehler: Fehler-Exitstatus von debian/rules build war 2&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install git-core build-essential&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
in der datei knxd/debian/rules die Zeile:&lt;br /&gt;
bash tools/test.sh auskommentieren&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Fehler: dpkg-buildpackage: error: fakeroot not found, either install the fakeroot &amp;lt;....&amp;gt; &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install fakeroot dpkg-dev&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[Benutzer:Marthinx]]&lt;br /&gt;
* [https://github.com/knxd/knxd Github knxd]&lt;br /&gt;
* [https://knx-user-forum.de/forum/projektforen/knxd/1049547-grundlagen-zum-knxd-mit-installationsanleitung-vor-dem-schreiben-lesen Forums-Thread zu knxd. Sehr informativ.]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Examples]]&lt;br /&gt;
[[Kategorie:EIB/KNX]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=37880</id>
		<title>Einrichten der Bluetooth-Thermostate von eQ-3</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=37880"/>
		<updated>2022-12-28T16:50:53Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Keine Reaktion auf Einstellen der Offset-Temperatur hinzu gefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Firma eQ-3 stellt verschiedene elektronische Heizkörperthermostate her. Das Eqiva BLUETOOTH® Smart Heizkörperthermostat kann auch von FHEM gesteuert werden. Voraussetzung ist natürlich ein Bluetooth-Empfänger (RasPi 3+4 oder Bluetooth-Dongle).&lt;br /&gt;
{{Randnotiz|RNText=Hinweis: Es gibt auch Versionen ohne Bluetooth. Bei der Bestellung bitte aufpassen.|RNTyp=Warn|style=}}&lt;br /&gt;
== Bluetooth einrichten ==&lt;br /&gt;
Standardmäßig sollte Bluetooth auf dem Raspberry Pi schon eingerichtet sein. Nutzt man einen B+ mit Dongle (z.B. als Verlängerung), so müssen unter Umständen folgende Pakete installiert werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install bluetooth, bluez&amp;lt;/pre&amp;gt;&lt;br /&gt;
Danach ein &amp;lt;code&amp;gt;sudo reboot&amp;lt;/code&amp;gt;. Ein &amp;lt;code&amp;gt;sudo service bluetooth status&amp;lt;/code&amp;gt; sollte zeigen, dass der Daemon läuft.&lt;br /&gt;
Damit der user fhem bzw. pi auf bluetooth zugreifen kann, muss in bluetooth.conf noch folgendes eingetragen werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo nano /etc/dbus-1/system.d/bluetooth.conf&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;policy user=&amp;quot;fhem&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;allow own=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_destination=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattCharacteristic1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattDescriptor1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.ObjectManager&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.Properties&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/policy&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo systemctl restart dbus&amp;lt;/pre&amp;gt;&lt;br /&gt;
Für den User pi muss natürlich fhem durch pi ersetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Thermostat in FHEM definieren ==&lt;br /&gt;
Bevor das Thermostat in FHEM eingebunden werden kann, muss die MAC-Adresse ermittelt werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;pi@raspberrypi ~ $ bluetoothctl&lt;br /&gt;
[NEW] Controller 00:1A:7D:XX:XX:XX raspberrypi [default]&lt;br /&gt;
[bluetooth]# scan on&lt;br /&gt;
Discovery started&lt;br /&gt;
[CHG] Controller 00:1A:7D:XX:XX:XX Discovering: yes&lt;br /&gt;
[NEW] Device 41:86:FB:XX:XX:XX 41-86-FB-...&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -56&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -70&lt;br /&gt;
[NEW] Device 5A:64:25:XX:XX:XX 5A-64-25-...&lt;br /&gt;
[bluetooth]# scan off&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Geräte tragen den Namen CC-RT-BLE.&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit Perl-Modul 10_EQ3BT ===&lt;br /&gt;
Die eQ-3 Heizkörperthermostate können einfach über&lt;br /&gt;
define &amp;lt;name&amp;gt; EQ3BT &amp;lt;mac address&amp;gt; &lt;br /&gt;
eingebunden werden.&lt;br /&gt;
{{Hinweis|Mittlerweile wird nur noch das fhempy-Modul empfohlen}}&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit fhempy ===&lt;br /&gt;
fhempy ermöglicht das Schreiben von FHEM-Modulen in der Programmiersprache Python. Erforderlich ist Python 3.8 oder höher (NICHT 2!), weshalb Debian Bullseye empfehlenswert ist. Es ist auch möglich, fhempy auf Peers zu installieren, um dadurch die Bluetooth-Reichweite zu erhöhen. Dadurch ist eine komplette Abdeckung des Hauses möglich. Auf den Peers muss FHEM nicht installiert werden. Neben dem Raspberry Pi Zero eignet sich auch z.B. der Radxa Rock Pi Zero, getestet mit Armbian. Die Peers können aus FHEM heraus verwaltet werden.&lt;br /&gt;
==== Installation auf FHEM-Server ====&lt;br /&gt;
Um die Heizkörperthermostate unter fhempy einzurichten, sind zunächst einige Vorarbeiten erforderlich. Das Einrichten geht dann genau so simpel.&lt;br /&gt;
Nach dem obligatorischen &amp;lt;code&amp;gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get upgrade&amp;lt;/code&amp;gt; werden die benötigten Python-Pakete mit&lt;br /&gt;
&lt;br /&gt;
[Debian 11 (Bullseye)]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git libprotocol-websocket-perl&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[alle anderen]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git&amp;lt;/pre&amp;gt;&lt;br /&gt;
und als nächstes&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo cpan Protocol::WebSocket&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das dauert eine Weile. Ich empfehle eine Tasse koffeinhaltiges Heißgetränk.&lt;br /&gt;
Ist die Installation abgeschlossen, geht es an die Konfiguration von FHEM. Zunächst laden wir per Update die benötigten Dateien herunter:&lt;br /&gt;
&amp;lt;pre&amp;gt;update add https://raw.githubusercontent.com/dominikkarall/fhempy/master/controls_pythonbinding.txt&lt;br /&gt;
update&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ist das Update abgeschlossen, können wir fhempy einrichten:&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_local BindingsIo fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Es wird automatisch &#039;&#039;&#039;fhempyserver&#039;&#039;&#039; und &#039;&#039;&#039;fhempy_local&#039;&#039;&#039; eingerichtet. Auch hier gilt: nicht nervös werden, wenn fhempy_local nicht sofort &#039;&#039;connected&#039;&#039; anzeigt.&lt;br /&gt;
&lt;br /&gt;
Hiermit sind die Vorbereitungen abgeschlossen. Das Thermostat kann nun mit&lt;br /&gt;
&amp;lt;pre&amp;gt;define &amp;lt;name&amp;gt; fhempy eq3bt &amp;lt;MAC-Adresse&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
eingebunden werden. Die benötigten Module werden automatisch nachgeladen.&lt;br /&gt;
&lt;br /&gt;
==== Installation des fhempy-Peer ====&lt;br /&gt;
fhempy läuft nicht nur lokal auf dem FHEM-Server. Zur Reichweitenerhöhung kann auch ein fhempy-Peer auf einem oder mehreren RasPi’s installiert und diese über die Wohnung verteilt werden. Geeignet ist natürlich auch ein RasPi, der zur Visualisierung dient.&lt;br /&gt;
{{Hinweis|WICHTIG!! Die folgenden Befehle dürfen nur auf dem Remote-RasPi und nicht auf der FHEM-Instanz ausgeführt werden.}}&lt;br /&gt;
Zunächst müssen die benötigten Python-Pakete wie oben beschrieben installiert werden. Installiere nun fhempy als User pi&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install --upgrade fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Überprüfe, ob die Hauptinstanz auf dem FHEM-Server läuft und starte dann fhempy als User pi auf dem Peer&lt;br /&gt;
&amp;lt;pre&amp;gt;fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nach kurzer Zeit siehst du die ankommende FHEM-Verbindung.&lt;br /&gt;
Nun noch die systemd-Konfiguration, damit fhempy automatisch gestartet wird&lt;br /&gt;
&amp;lt;pre&amp;gt;curl -sL https://raw.githubusercontent.com/fhempy/fhempy/master/install_systemd_fhempy.sh | sudo -E bash -&amp;lt;/pre&amp;gt;&lt;br /&gt;
fhempy läuft nun unter dem User pi. Möchtest du das ändern, so schau in die Datei &amp;lt;code&amp;gt;fhempy.service&amp;lt;/code&amp;gt; im Verzeichnis &amp;lt;code&amp;gt;/etc/systemd/system/&amp;lt;/code&amp;gt;  Hinterher das sudo systemctl daemon-reload nicht vergessen.&lt;br /&gt;
Der Peer sollte in FHEM automatisch erkannt werden (beruht auf Zeroconf). Sollte das nicht der Fall sein, kann der Peer auch manuell definiert werden&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_peer_IP BindingsIo IP:15733 fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Pairing ==&lt;br /&gt;
Die Thermostate mit einer Software größer 120 müssen mit dem RasPi gepaired werden. Drücke dazu das Rad am Thermostat bis „Pair“ im Display erscheint. Dann führe folgende Schritte aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo bluetoothctl&lt;br /&gt;
[bluetooth]# power on&lt;br /&gt;
[bluetooth]# agent on&lt;br /&gt;
[bluetooth]# default-agent&lt;br /&gt;
[bluetooth]# scan on&lt;br /&gt;
[bluetooth]# scan off&lt;br /&gt;
[bluetooth]# pair 00:1A:22:06:A7:83&lt;br /&gt;
[agent] Enter passkey (number in 0-999999): &amp;lt;enter pin&amp;gt;&lt;br /&gt;
[bluetooth]# trust 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# disconnect 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# exit&lt;br /&gt;
&lt;br /&gt;
Optional steps:&lt;br /&gt;
[bluetooth]# devices - to list all bluetooth devices&lt;br /&gt;
[bluetooth]# info 00:1A:22:06:A7:83&lt;br /&gt;
Device 00:1A:22:06:A7:83 (public)&lt;br /&gt;
        Name: CC-RT-BLE&lt;br /&gt;
        Alias: CC-RT-BLE&lt;br /&gt;
        Paired: yes&lt;br /&gt;
        Trusted: yes&lt;br /&gt;
        Blocked: no&lt;br /&gt;
        Connected: no&lt;br /&gt;
        LegacyPairing: no&lt;br /&gt;
        UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Device Information        (0000180a-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Vendor specific           (3e135142-654f-9090-134a-a6ff5bb77046)&lt;br /&gt;
        UUID: Vendor specific           (9e5d1e47-5c13-43a0-8635-82ad38a1386f)&lt;br /&gt;
        ManufacturerData Key: 0x0000&lt;br /&gt;
        ManufacturerData Value:&lt;br /&gt;
  00 00 00 00 00 00 00 00 00                       .........&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dadurch ist das Thermostat nicht mehr mit der calor BT-App steuerbar (und umgekehrt).&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
=== Fehlermeldung nach fhempy-Installation ===&lt;br /&gt;
Meldet pip3 folgendes&lt;br /&gt;
&amp;lt;pre&amp;gt;  WARNING: The script normalizer is installed in &#039;/home/myname/.local/bin&#039; which is not on PATH.&lt;br /&gt;
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.&amp;lt;/pre&amp;gt;&lt;br /&gt;
so fehlt der Pfad zu fhempy und fhempy kann nicht aufgerufen werden. Es ist folgender Befehl aufzurufen&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/myname/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
also z.B.&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/pi/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Keine Reaktion auf Einstellen der Offset-Temperatur ===&lt;br /&gt;
Zur Zeit scheint es ein Softwareproblem beim Einstellen der Offset-Temperatur über Bluetooth zu geben (Version 146 oder kleiner). Die Einstellung wird übertragen, wirkt sich aber nicht auf das Thermostat aus. Erst wenn man die Einstellung über das Menü am Thermostat bestätigt (oder gleich dort einstellt), reagiert das Thermostat. Das Problem tritt auch bei der Bedienung über die App auf.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/fhempy/fhempy fhempy-Projekt auf Github]&lt;br /&gt;
* [https://github.com/rytilahti/python-eq3bt#pairing Pairing der Thermostate]&lt;br /&gt;
* {{Link2Forum|Topic=60595|LinkText=Forums-Beitrag}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Heizungsventile]]&lt;br /&gt;
[[Kategorie:Bluetooth]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=37874</id>
		<title>Einrichten der Bluetooth-Thermostate von eQ-3</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=37874"/>
		<updated>2022-12-26T18:41:34Z</updated>

		<summary type="html">&lt;p&gt;F Klee: Ermitteln der MAC-Adresse erweitert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Firma eQ-3 stellt verschiedene elektronische Heizkörperthermostate her. Das Eqiva BLUETOOTH® Smart Heizkörperthermostat kann auch von FHEM gesteuert werden. Voraussetzung ist natürlich ein Bluetooth-Empfänger (RasPi 3+4 oder Bluetooth-Dongle).&lt;br /&gt;
{{Randnotiz|RNText=Hinweis: Es gibt auch Versionen ohne Bluetooth. Bei der Bestellung bitte aufpassen.|RNTyp=Warn|style=}}&lt;br /&gt;
== Bluetooth einrichten ==&lt;br /&gt;
Standardmäßig sollte Bluetooth auf dem Raspberry Pi schon eingerichtet sein. Nutzt man einen B+ mit Dongle (z.B. als Verlängerung), so müssen unter Umständen folgende Pakete installiert werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install bluetooth, bluez&amp;lt;/pre&amp;gt;&lt;br /&gt;
Danach ein &amp;lt;code&amp;gt;sudo reboot&amp;lt;/code&amp;gt;. Ein &amp;lt;code&amp;gt;sudo service bluetooth status&amp;lt;/code&amp;gt; sollte zeigen, dass der Daemon läuft.&lt;br /&gt;
Damit der user fhem bzw. pi auf bluetooth zugreifen kann, muss in bluetooth.conf noch folgendes eingetragen werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo nano /etc/dbus-1/system.d/bluetooth.conf&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;policy user=&amp;quot;fhem&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;allow own=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_destination=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattCharacteristic1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattDescriptor1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.ObjectManager&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.Properties&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/policy&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo systemctl restart dbus&amp;lt;/pre&amp;gt;&lt;br /&gt;
Für den User pi muss natürlich fhem durch pi ersetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Thermostat in FHEM definieren ==&lt;br /&gt;
Bevor das Thermostat in FHEM eingebunden werden kann, muss die MAC-Adresse ermittelt werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;pi@raspberrypi ~ $ bluetoothctl&lt;br /&gt;
[NEW] Controller 00:1A:7D:XX:XX:XX raspberrypi [default]&lt;br /&gt;
[bluetooth]# scan on&lt;br /&gt;
Discovery started&lt;br /&gt;
[CHG] Controller 00:1A:7D:XX:XX:XX Discovering: yes&lt;br /&gt;
[NEW] Device 41:86:FB:XX:XX:XX 41-86-FB-...&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -56&lt;br /&gt;
[NEW] Device 00:1A:22:XX:XX:XX CC-RT-BLE &amp;lt;== EQ3 Device, erkennbar an CC-RT-BLE&lt;br /&gt;
[CHG] Device 41:86:FB:XX:XX:XX RSSI: -70&lt;br /&gt;
[NEW] Device 5A:64:25:XX:XX:XX 5A-64-25-...&lt;br /&gt;
[bluetooth]# scan off&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Geräte tragen den Namen CC-RT-BLE.&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit Perl-Modul 10_EQ3BT ===&lt;br /&gt;
Die eQ-3 Heizkörperthermostate können einfach über&lt;br /&gt;
define &amp;lt;name&amp;gt; EQ3BT &amp;lt;mac address&amp;gt; &lt;br /&gt;
eingebunden werden.&lt;br /&gt;
{{Hinweis|Mittlerweile wird nur noch das fhempy-Modul empfohlen}}&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit fhempy ===&lt;br /&gt;
fhempy ermöglicht das Schreiben von FHEM-Modulen in der Programmiersprache Python. Erforderlich ist Python 3.8 oder höher (NICHT 2!), weshalb Debian Bullseye empfehlenswert ist. Es ist auch möglich, fhempy auf Peers zu installieren, um dadurch die Bluetooth-Reichweite zu erhöhen. Dadurch ist eine komplette Abdeckung des Hauses möglich. Auf den Peers muss FHEM nicht installiert werden. Neben dem Raspberry Pi Zero eignet sich auch z.B. der Radxa Rock Pi Zero, getestet mit Armbian. Die Peers können aus FHEM heraus verwaltet werden.&lt;br /&gt;
==== Installation auf FHEM-Server ====&lt;br /&gt;
Um die Heizkörperthermostate unter fhempy einzurichten, sind zunächst einige Vorarbeiten erforderlich. Das Einrichten geht dann genau so simpel.&lt;br /&gt;
Nach dem obligatorischen &amp;lt;code&amp;gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get upgrade&amp;lt;/code&amp;gt; werden die benötigten Python-Pakete mit&lt;br /&gt;
&lt;br /&gt;
[Debian 11 (Bullseye)]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git libprotocol-websocket-perl&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[alle anderen]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git&amp;lt;/pre&amp;gt;&lt;br /&gt;
und als nächstes&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo cpan Protocol::WebSocket&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das dauert eine Weile. Ich empfehle eine Tasse koffeinhaltiges Heißgetränk.&lt;br /&gt;
Ist die Installation abgeschlossen, geht es an die Konfiguration von FHEM. Zunächst laden wir per Update die benötigten Dateien herunter:&lt;br /&gt;
&amp;lt;pre&amp;gt;update add https://raw.githubusercontent.com/dominikkarall/fhempy/master/controls_pythonbinding.txt&lt;br /&gt;
update&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ist das Update abgeschlossen, können wir fhempy einrichten:&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_local BindingsIo fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Es wird automatisch &#039;&#039;&#039;fhempyserver&#039;&#039;&#039; und &#039;&#039;&#039;fhempy_local&#039;&#039;&#039; eingerichtet. Auch hier gilt: nicht nervös werden, wenn fhempy_local nicht sofort &#039;&#039;connected&#039;&#039; anzeigt.&lt;br /&gt;
&lt;br /&gt;
Hiermit sind die Vorbereitungen abgeschlossen. Das Thermostat kann nun mit&lt;br /&gt;
&amp;lt;pre&amp;gt;define &amp;lt;name&amp;gt; fhempy eq3bt &amp;lt;MAC-Adresse&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
eingebunden werden. Die benötigten Module werden automatisch nachgeladen.&lt;br /&gt;
&lt;br /&gt;
==== Installation des fhempy-Peer ====&lt;br /&gt;
fhempy läuft nicht nur lokal auf dem FHEM-Server. Zur Reichweitenerhöhung kann auch ein fhempy-Peer auf einem oder mehreren RasPi’s installiert und diese über die Wohnung verteilt werden. Geeignet ist natürlich auch ein RasPi, der zur Visualisierung dient.&lt;br /&gt;
{{Hinweis|WICHTIG!! Die folgenden Befehle dürfen nur auf dem Remote-RasPi und nicht auf der FHEM-Instanz ausgeführt werden.}}&lt;br /&gt;
Zunächst müssen die benötigten Python-Pakete wie oben beschrieben installiert werden. Installiere nun fhempy als User pi&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install --upgrade fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Überprüfe, ob die Hauptinstanz auf dem FHEM-Server läuft und starte dann fhempy als User pi auf dem Peer&lt;br /&gt;
&amp;lt;pre&amp;gt;fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nach kurzer Zeit siehst du die ankommende FHEM-Verbindung.&lt;br /&gt;
Nun noch die systemd-Konfiguration, damit fhempy automatisch gestartet wird&lt;br /&gt;
&amp;lt;pre&amp;gt;curl -sL https://raw.githubusercontent.com/fhempy/fhempy/master/install_systemd_fhempy.sh | sudo -E bash -&amp;lt;/pre&amp;gt;&lt;br /&gt;
fhempy läuft nun unter dem User pi. Möchtest du das ändern, so schau in die Datei &amp;lt;code&amp;gt;fhempy.service&amp;lt;/code&amp;gt; im Verzeichnis &amp;lt;code&amp;gt;/etc/systemd/system/&amp;lt;/code&amp;gt;  Hinterher das sudo systemctl daemon-reload nicht vergessen.&lt;br /&gt;
Der Peer sollte in FHEM automatisch erkannt werden (beruht auf Zeroconf). Sollte das nicht der Fall sein, kann der Peer auch manuell definiert werden&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_peer_IP BindingsIo IP:15733 fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Pairing ==&lt;br /&gt;
Die Thermostate mit einer Software größer 120 müssen mit dem RasPi gepaired werden. Drücke dazu das Rad am Thermostat bis „Pair“ im Display erscheint. Dann führe folgende Schritte aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo bluetoothctl&lt;br /&gt;
[bluetooth]# power on&lt;br /&gt;
[bluetooth]# agent on&lt;br /&gt;
[bluetooth]# default-agent&lt;br /&gt;
[bluetooth]# scan on&lt;br /&gt;
[bluetooth]# scan off&lt;br /&gt;
[bluetooth]# pair 00:1A:22:06:A7:83&lt;br /&gt;
[agent] Enter passkey (number in 0-999999): &amp;lt;enter pin&amp;gt;&lt;br /&gt;
[bluetooth]# trust 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# disconnect 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# exit&lt;br /&gt;
&lt;br /&gt;
Optional steps:&lt;br /&gt;
[bluetooth]# devices - to list all bluetooth devices&lt;br /&gt;
[bluetooth]# info 00:1A:22:06:A7:83&lt;br /&gt;
Device 00:1A:22:06:A7:83 (public)&lt;br /&gt;
        Name: CC-RT-BLE&lt;br /&gt;
        Alias: CC-RT-BLE&lt;br /&gt;
        Paired: yes&lt;br /&gt;
        Trusted: yes&lt;br /&gt;
        Blocked: no&lt;br /&gt;
        Connected: no&lt;br /&gt;
        LegacyPairing: no&lt;br /&gt;
        UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Device Information        (0000180a-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Vendor specific           (3e135142-654f-9090-134a-a6ff5bb77046)&lt;br /&gt;
        UUID: Vendor specific           (9e5d1e47-5c13-43a0-8635-82ad38a1386f)&lt;br /&gt;
        ManufacturerData Key: 0x0000&lt;br /&gt;
        ManufacturerData Value:&lt;br /&gt;
  00 00 00 00 00 00 00 00 00                       .........&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dadurch ist das Thermostat nicht mehr mit der calor BT-App steuerbar (und umgekehrt).&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
=== Fehlermeldung nach fhempy-Installation ===&lt;br /&gt;
Meldet pip3 folgendes&lt;br /&gt;
&amp;lt;pre&amp;gt;  WARNING: The script normalizer is installed in &#039;/home/myname/.local/bin&#039; which is not on PATH.&lt;br /&gt;
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.&amp;lt;/pre&amp;gt;&lt;br /&gt;
so fehlt der Pfad zu fhempy und fhempy kann nicht aufgerufen werden. Es ist folgender Befehl aufzurufen&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/myname/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
also z.B.&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/pi/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/fhempy/fhempy fhempy-Projekt auf Github]&lt;br /&gt;
* [https://github.com/rytilahti/python-eq3bt#pairing Pairing der Thermostate]&lt;br /&gt;
* {{Link2Forum|Topic=60595|LinkText=Forums-Beitrag}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Heizungsventile]]&lt;br /&gt;
[[Kategorie:Bluetooth]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=37850</id>
		<title>Einrichten der Bluetooth-Thermostate von eQ-3</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=37850"/>
		<updated>2022-12-25T13:07:47Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* Installation des fhempy-Peer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Firma eQ-3 stellt verschiedene elektronische Heizkörperthermostate her. Das Eqiva BLUETOOTH® Smart Heizkörperthermostat kann auch von FHEM gesteuert werden. Voraussetzung ist natürlich ein Bluetooth-Empfänger (RasPi 3+4 oder Bluetooth-Dongle).&lt;br /&gt;
{{Randnotiz|RNText=Hinweis: Es gibt auch Versionen ohne Bluetooth. Bei der Bestellung bitte aufpassen.|RNTyp=Warn|style=}}&lt;br /&gt;
== Bluetooth einrichten ==&lt;br /&gt;
Standardmäßig sollte Bluetooth auf dem Raspberry Pi schon eingerichtet sein. Nutzt man einen B+ mit Dongle (z.B. als Verlängerung), so müssen unter Umständen folgende Pakete installiert werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install bluetooth, bluez&amp;lt;/pre&amp;gt;&lt;br /&gt;
Danach ein &amp;lt;code&amp;gt;sudo reboot&amp;lt;/code&amp;gt;. Ein &amp;lt;code&amp;gt;sudo service bluetooth status&amp;lt;/code&amp;gt; sollte zeigen, dass der Daemon läuft.&lt;br /&gt;
Damit der user fhem bzw. pi auf bluetooth zugreifen kann, muss in bluetooth.conf noch folgendes eingetragen werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo nano /etc/dbus-1/system.d/bluetooth.conf&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;policy user=&amp;quot;fhem&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;allow own=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_destination=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattCharacteristic1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattDescriptor1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.ObjectManager&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.Properties&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/policy&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo systemctl restart dbus&amp;lt;/pre&amp;gt;&lt;br /&gt;
Für den User pi muss natürlich fhem durch pi ersetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Thermostat in FHEM definieren ==&lt;br /&gt;
Bevor das Thermostat in FHEM eingebunden werden kann, muss die MAC-Adresse ermittelt werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo bluetoothctl&lt;br /&gt;
scan on&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Geräte tragen den Namen CC-RT-BLE.&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit Perl-Modul 10_EQ3BT ===&lt;br /&gt;
Die eQ-3 Heizkörperthermostate können einfach über&lt;br /&gt;
define &amp;lt;name&amp;gt; EQ3BT &amp;lt;mac address&amp;gt; &lt;br /&gt;
eingebunden werden.&lt;br /&gt;
{{Hinweis|Mittlerweile wird nur noch das fhempy-Modul empfohlen}}&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit fhempy ===&lt;br /&gt;
fhempy ermöglicht das Schreiben von FHEM-Modulen in der Programmiersprache Python. Erforderlich ist Python 3.8 oder höher (NICHT 2!), weshalb Debian Bullseye empfehlenswert ist. Es ist auch möglich, fhempy auf Peers zu installieren, um dadurch die Bluetooth-Reichweite zu erhöhen. Dadurch ist eine komplette Abdeckung des Hauses möglich. Auf den Peers muss FHEM nicht installiert werden. Neben dem Raspberry Pi Zero eignet sich auch z.B. der Radxa Rock Pi Zero, getestet mit Armbian. Die Peers können aus FHEM heraus verwaltet werden.&lt;br /&gt;
==== Installation auf FHEM-Server ====&lt;br /&gt;
Um die Heizkörperthermostate unter fhempy einzurichten, sind zunächst einige Vorarbeiten erforderlich. Das Einrichten geht dann genau so simpel.&lt;br /&gt;
Nach dem obligatorischen &amp;lt;code&amp;gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get upgrade&amp;lt;/code&amp;gt; werden die benötigten Python-Pakete mit&lt;br /&gt;
&lt;br /&gt;
[Debian 11 (Bullseye)]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git libprotocol-websocket-perl&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[alle anderen]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git&amp;lt;/pre&amp;gt;&lt;br /&gt;
und als nächstes&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo cpan Protocol::WebSocket&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das dauert eine Weile. Ich empfehle eine Tasse koffeinhaltiges Heißgetränk.&lt;br /&gt;
Ist die Installation abgeschlossen, geht es an die Konfiguration von FHEM. Zunächst laden wir per Update die benötigten Dateien herunter:&lt;br /&gt;
&amp;lt;pre&amp;gt;update add https://raw.githubusercontent.com/dominikkarall/fhempy/master/controls_pythonbinding.txt&lt;br /&gt;
update&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ist das Update abgeschlossen, können wir fhempy einrichten:&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_local BindingsIo fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Es wird automatisch &#039;&#039;&#039;fhempyserver&#039;&#039;&#039; und &#039;&#039;&#039;fhempy_local&#039;&#039;&#039; eingerichtet. Auch hier gilt: nicht nervös werden, wenn fhempy_local nicht sofort &#039;&#039;connected&#039;&#039; anzeigt.&lt;br /&gt;
&lt;br /&gt;
Hiermit sind die Vorbereitungen abgeschlossen. Das Thermostat kann nun mit&lt;br /&gt;
&amp;lt;pre&amp;gt;define &amp;lt;name&amp;gt; fhempy eq3bt &amp;lt;MAC-Adresse&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
eingebunden werden. Die benötigten Module werden automatisch nachgeladen.&lt;br /&gt;
&lt;br /&gt;
==== Installation des fhempy-Peer ====&lt;br /&gt;
fhempy läuft nicht nur lokal auf dem FHEM-Server. Zur Reichweitenerhöhung kann auch ein fhempy-Peer auf einem oder mehreren RasPi’s installiert und diese über die Wohnung verteilt werden. Geeignet ist natürlich auch ein RasPi, der zur Visualisierung dient.&lt;br /&gt;
{{Hinweis|WICHTIG!! Die folgenden Befehle dürfen nur auf dem Remote-RasPi und nicht auf der FHEM-Instanz ausgeführt werden.}}&lt;br /&gt;
Zunächst müssen die benötigten Python-Pakete wie oben beschrieben installiert werden. Installiere nun fhempy als User pi&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install --upgrade fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Überprüfe, ob die Hauptinstanz auf dem FHEM-Server läuft und starte dann fhempy als User pi auf dem Peer&lt;br /&gt;
&amp;lt;pre&amp;gt;fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nach kurzer Zeit siehst du die ankommende FHEM-Verbindung.&lt;br /&gt;
Nun noch die systemd-Konfiguration, damit fhempy automatisch gestartet wird&lt;br /&gt;
&amp;lt;pre&amp;gt;curl -sL https://raw.githubusercontent.com/fhempy/fhempy/master/install_systemd_fhempy.sh | sudo -E bash -&amp;lt;/pre&amp;gt;&lt;br /&gt;
fhempy läuft nun unter dem User pi. Möchtest du das ändern, so schau in die Datei &amp;lt;code&amp;gt;fhempy.service&amp;lt;/code&amp;gt; im Verzeichnis &amp;lt;code&amp;gt;/etc/systemd/system/&amp;lt;/code&amp;gt;  Hinterher das sudo systemctl daemon-reload nicht vergessen.&lt;br /&gt;
Der Peer sollte in FHEM automatisch erkannt werden (beruht auf Zeroconf). Sollte das nicht der Fall sein, kann der Peer auch manuell definiert werden&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_peer_IP BindingsIo IP:15733 fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Pairing ==&lt;br /&gt;
Die Thermostate mit einer Software größer 120 müssen mit dem RasPi gepaired werden. Drücke dazu das Rad am Thermostat bis „Pair“ im Display erscheint. Dann führe folgende Schritte aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo bluetoothctl&lt;br /&gt;
[bluetooth]# power on&lt;br /&gt;
[bluetooth]# agent on&lt;br /&gt;
[bluetooth]# default-agent&lt;br /&gt;
[bluetooth]# scan on&lt;br /&gt;
[bluetooth]# scan off&lt;br /&gt;
[bluetooth]# pair 00:1A:22:06:A7:83&lt;br /&gt;
[agent] Enter passkey (number in 0-999999): &amp;lt;enter pin&amp;gt;&lt;br /&gt;
[bluetooth]# trust 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# disconnect 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# exit&lt;br /&gt;
&lt;br /&gt;
Optional steps:&lt;br /&gt;
[bluetooth]# devices - to list all bluetooth devices&lt;br /&gt;
[bluetooth]# info 00:1A:22:06:A7:83&lt;br /&gt;
Device 00:1A:22:06:A7:83 (public)&lt;br /&gt;
        Name: CC-RT-BLE&lt;br /&gt;
        Alias: CC-RT-BLE&lt;br /&gt;
        Paired: yes&lt;br /&gt;
        Trusted: yes&lt;br /&gt;
        Blocked: no&lt;br /&gt;
        Connected: no&lt;br /&gt;
        LegacyPairing: no&lt;br /&gt;
        UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Device Information        (0000180a-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Vendor specific           (3e135142-654f-9090-134a-a6ff5bb77046)&lt;br /&gt;
        UUID: Vendor specific           (9e5d1e47-5c13-43a0-8635-82ad38a1386f)&lt;br /&gt;
        ManufacturerData Key: 0x0000&lt;br /&gt;
        ManufacturerData Value:&lt;br /&gt;
  00 00 00 00 00 00 00 00 00                       .........&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dadurch ist das Thermostat nicht mehr mit der calor BT-App steuerbar (und umgekehrt).&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
=== Fehlermeldung nach fhempy-Installation ===&lt;br /&gt;
Meldet pip3 folgendes&lt;br /&gt;
&amp;lt;pre&amp;gt;  WARNING: The script normalizer is installed in &#039;/home/myname/.local/bin&#039; which is not on PATH.&lt;br /&gt;
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.&amp;lt;/pre&amp;gt;&lt;br /&gt;
so fehlt der Pfad zu fhempy und fhempy kann nicht aufgerufen werden. Es ist folgender Befehl aufzurufen&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/myname/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
also z.B.&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/pi/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/fhempy/fhempy fhempy-Projekt auf Github]&lt;br /&gt;
* [https://github.com/rytilahti/python-eq3bt#pairing Pairing der Thermostate]&lt;br /&gt;
* {{Link2Forum|Topic=60595|LinkText=Forums-Beitrag}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Heizungsventile]]&lt;br /&gt;
[[Kategorie:Bluetooth]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=37849</id>
		<title>Einrichten der Bluetooth-Thermostate von eQ-3</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Einrichten_der_Bluetooth-Thermostate_von_eQ-3&amp;diff=37849"/>
		<updated>2022-12-25T13:02:55Z</updated>

		<summary type="html">&lt;p&gt;F Klee: /* Bluetooth einrichten */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Firma eQ-3 stellt verschiedene elektronische Heizkörperthermostate her. Das Eqiva BLUETOOTH® Smart Heizkörperthermostat kann auch von FHEM gesteuert werden. Voraussetzung ist natürlich ein Bluetooth-Empfänger (RasPi 3+4 oder Bluetooth-Dongle).&lt;br /&gt;
{{Randnotiz|RNText=Hinweis: Es gibt auch Versionen ohne Bluetooth. Bei der Bestellung bitte aufpassen.|RNTyp=Warn|style=}}&lt;br /&gt;
== Bluetooth einrichten ==&lt;br /&gt;
Standardmäßig sollte Bluetooth auf dem Raspberry Pi schon eingerichtet sein. Nutzt man einen B+ mit Dongle (z.B. als Verlängerung), so müssen unter Umständen folgende Pakete installiert werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install bluetooth, bluez&amp;lt;/pre&amp;gt;&lt;br /&gt;
Danach ein &amp;lt;code&amp;gt;sudo reboot&amp;lt;/code&amp;gt;. Ein &amp;lt;code&amp;gt;sudo service bluetooth status&amp;lt;/code&amp;gt; sollte zeigen, dass der Daemon läuft.&lt;br /&gt;
Damit der user fhem bzw. pi auf bluetooth zugreifen kann, muss in bluetooth.conf noch folgendes eingetragen werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo nano /etc/dbus-1/system.d/bluetooth.conf&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;policy user=&amp;quot;fhem&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;allow own=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_destination=&amp;quot;org.bluez&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattCharacteristic1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.bluez.GattDescriptor1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.ObjectManager&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;allow send_interface=&amp;quot;org.freedesktop.DBus.Properties&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/policy&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo systemctl restart dbus&amp;lt;/pre&amp;gt;&lt;br /&gt;
Für den User pi muss natürlich fhem durch pi ersetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Thermostat in FHEM definieren ==&lt;br /&gt;
Bevor das Thermostat in FHEM eingebunden werden kann, muss die MAC-Adresse ermittelt werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo bluetoothctl&lt;br /&gt;
scan on&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Geräte tragen den Namen CC-RT-BLE.&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit Perl-Modul 10_EQ3BT ===&lt;br /&gt;
Die eQ-3 Heizkörperthermostate können einfach über&lt;br /&gt;
define &amp;lt;name&amp;gt; EQ3BT &amp;lt;mac address&amp;gt; &lt;br /&gt;
eingebunden werden.&lt;br /&gt;
{{Hinweis|Mittlerweile wird nur noch das fhempy-Modul empfohlen}}&lt;br /&gt;
&lt;br /&gt;
=== Einrichten mit fhempy ===&lt;br /&gt;
fhempy ermöglicht das Schreiben von FHEM-Modulen in der Programmiersprache Python. Erforderlich ist Python 3.8 oder höher (NICHT 2!), weshalb Debian Bullseye empfehlenswert ist. Es ist auch möglich, fhempy auf Peers zu installieren, um dadurch die Bluetooth-Reichweite zu erhöhen. Dadurch ist eine komplette Abdeckung des Hauses möglich. Auf den Peers muss FHEM nicht installiert werden. Neben dem Raspberry Pi Zero eignet sich auch z.B. der Radxa Rock Pi Zero, getestet mit Armbian. Die Peers können aus FHEM heraus verwaltet werden.&lt;br /&gt;
==== Installation auf FHEM-Server ====&lt;br /&gt;
Um die Heizkörperthermostate unter fhempy einzurichten, sind zunächst einige Vorarbeiten erforderlich. Das Einrichten geht dann genau so simpel.&lt;br /&gt;
Nach dem obligatorischen &amp;lt;code&amp;gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get upgrade&amp;lt;/code&amp;gt; werden die benötigten Python-Pakete mit&lt;br /&gt;
&lt;br /&gt;
[Debian 11 (Bullseye)]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git libprotocol-websocket-perl&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[alle anderen]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3 python3-pip python3-dev libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libglib2.0-dev libdbus-1-dev bluez libbluetooth-dev git&amp;lt;/pre&amp;gt;&lt;br /&gt;
und als nächstes&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo cpan Protocol::WebSocket&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das dauert eine Weile. Ich empfehle eine Tasse koffeinhaltiges Heißgetränk.&lt;br /&gt;
Ist die Installation abgeschlossen, geht es an die Konfiguration von FHEM. Zunächst laden wir per Update die benötigten Dateien herunter:&lt;br /&gt;
&amp;lt;pre&amp;gt;update add https://raw.githubusercontent.com/dominikkarall/fhempy/master/controls_pythonbinding.txt&lt;br /&gt;
update&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ist das Update abgeschlossen, können wir fhempy einrichten:&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_local BindingsIo fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Es wird automatisch &#039;&#039;&#039;fhempyserver&#039;&#039;&#039; und &#039;&#039;&#039;fhempy_local&#039;&#039;&#039; eingerichtet. Auch hier gilt: nicht nervös werden, wenn fhempy_local nicht sofort &#039;&#039;connected&#039;&#039; anzeigt.&lt;br /&gt;
&lt;br /&gt;
Hiermit sind die Vorbereitungen abgeschlossen. Das Thermostat kann nun mit&lt;br /&gt;
&amp;lt;pre&amp;gt;define &amp;lt;name&amp;gt; fhempy eq3bt &amp;lt;MAC-Adresse&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
eingebunden werden. Die benötigten Module werden automatisch nachgeladen.&lt;br /&gt;
&lt;br /&gt;
==== Installation des fhempy-Peer ====&lt;br /&gt;
Fhempy läuft nicht nur lokal auf dem FHEM-Server. Zur Reichweitenerhöhung kann auch ein fhempy-Peer auf einem oder mehreren RasPi’s installiert und diese über die Wohnung verteilt werden. Geeignet ist natürlich auch ein RasPi, der zur Visualisierung dient.&lt;br /&gt;
{{Hinweis|WICHTIG!! Die folgenden Befehle dürfen nur auf dem Remote-RasPi und nicht auf der FHEM-Instanz ausgeführt werden.}}&lt;br /&gt;
Zunächst müssen die benötigten Python-Pakete wie oben beschrieben installiert werden. Installiere nun fhempy als User pi&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install --upgrade fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Überprüfe, ob die Hauptinstanz auf dem FHEM-Server läuft und starte dann fhempy als User pi auf dem Peer&lt;br /&gt;
&amp;lt;pre&amp;gt;fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nach kurzer Zeit siehst du die ankommende FHEM-Verbindung.&lt;br /&gt;
Nun noch die systemd-Konfiguration, damit fhempy automatisch gestartet wird&lt;br /&gt;
&amp;lt;pre&amp;gt;curl -sL https://raw.githubusercontent.com/fhempy/fhempy/master/install_systemd_fhempy.sh | sudo -E bash -&amp;lt;/pre&amp;gt;&lt;br /&gt;
fhempy läuft nun unter dem User pi. Möchtest du das ändern, so schau in die Datei &amp;lt;code&amp;gt;fhempy.service&amp;lt;/code&amp;gt; im Verzeichnis &amp;lt;code&amp;gt;/etc/systemd/system/&amp;lt;/code&amp;gt;  Hinterher das sudo systemctl daemon-reload nicht vergessen.&lt;br /&gt;
Der Peer sollte in FHEM automatisch erkannt werden (beruht auf Zeroconf). Sollte das nicht der Fall sein, kann der Peer auch manuell definiert werden&lt;br /&gt;
&amp;lt;pre&amp;gt;define fhempy_peer_IP BindingsIo IP:15733 fhempy&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Pairing ==&lt;br /&gt;
Die Thermostate mit einer Software größer 120 müssen mit dem RasPi gepaired werden. Drücke dazu das Rad am Thermostat bis „Pair“ im Display erscheint. Dann führe folgende Schritte aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo bluetoothctl&lt;br /&gt;
[bluetooth]# power on&lt;br /&gt;
[bluetooth]# agent on&lt;br /&gt;
[bluetooth]# default-agent&lt;br /&gt;
[bluetooth]# scan on&lt;br /&gt;
[bluetooth]# scan off&lt;br /&gt;
[bluetooth]# pair 00:1A:22:06:A7:83&lt;br /&gt;
[agent] Enter passkey (number in 0-999999): &amp;lt;enter pin&amp;gt;&lt;br /&gt;
[bluetooth]# trust 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# disconnect 00:1A:22:06:A7:83&lt;br /&gt;
[bluetooth]# exit&lt;br /&gt;
&lt;br /&gt;
Optional steps:&lt;br /&gt;
[bluetooth]# devices - to list all bluetooth devices&lt;br /&gt;
[bluetooth]# info 00:1A:22:06:A7:83&lt;br /&gt;
Device 00:1A:22:06:A7:83 (public)&lt;br /&gt;
        Name: CC-RT-BLE&lt;br /&gt;
        Alias: CC-RT-BLE&lt;br /&gt;
        Paired: yes&lt;br /&gt;
        Trusted: yes&lt;br /&gt;
        Blocked: no&lt;br /&gt;
        Connected: no&lt;br /&gt;
        LegacyPairing: no&lt;br /&gt;
        UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Device Information        (0000180a-0000-1000-8000-00805f9b34fb)&lt;br /&gt;
        UUID: Vendor specific           (3e135142-654f-9090-134a-a6ff5bb77046)&lt;br /&gt;
        UUID: Vendor specific           (9e5d1e47-5c13-43a0-8635-82ad38a1386f)&lt;br /&gt;
        ManufacturerData Key: 0x0000&lt;br /&gt;
        ManufacturerData Value:&lt;br /&gt;
  00 00 00 00 00 00 00 00 00                       .........&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dadurch ist das Thermostat nicht mehr mit der calor BT-App steuerbar (und umgekehrt).&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
=== Fehlermeldung nach fhempy-Installation ===&lt;br /&gt;
Meldet pip3 folgendes&lt;br /&gt;
&amp;lt;pre&amp;gt;  WARNING: The script normalizer is installed in &#039;/home/myname/.local/bin&#039; which is not on PATH.&lt;br /&gt;
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.&amp;lt;/pre&amp;gt;&lt;br /&gt;
so fehlt der Pfad zu fhempy und fhempy kann nicht aufgerufen werden. Es ist folgender Befehl aufzurufen&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/myname/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
also z.B.&lt;br /&gt;
&amp;lt;pre&amp;gt;export PATH=$PATH:/home/pi/.local/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/fhempy/fhempy fhempy-Projekt auf Github]&lt;br /&gt;
* [https://github.com/rytilahti/python-eq3bt#pairing Pairing der Thermostate]&lt;br /&gt;
* {{Link2Forum|Topic=60595|LinkText=Forums-Beitrag}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Heizungsventile]]&lt;br /&gt;
[[Kategorie:Bluetooth]]&lt;/div&gt;</summary>
		<author><name>F Klee</name></author>
	</entry>
</feed>