<?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=Caldir65</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=Caldir65"/>
	<link rel="alternate" type="text/html" href="http://wiki.fhem.de/wiki/Spezial:Beitr%C3%A4ge/Caldir65"/>
	<updated>2026-04-11T05:25:38Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=39368</id>
		<title>Mi vacuum</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=39368"/>
		<updated>2024-06-16T15:25:57Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: Link zu fhempy zum Auslesen des Tokens hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Todo|Aktualiserung / Text weniger flapsig formulieren / Einbindung Info-Box. Information, die generell für das Modul [[XiaomiDevice]] gilt, sollte auf die Modulseite &amp;quot;verschoben&amp;quot; werden.}}&lt;br /&gt;
=Mi Vacuum=&lt;br /&gt;
Wie der preiswerte Staubsaugerroboter auch auf FHEM hört...&lt;br /&gt;
&lt;br /&gt;
==Für wen ist die Anleitung gedacht?==&lt;br /&gt;
Ich gehe davon aus, dass ihr ein funktionierendes FHEM auf einem Linux Rechner (Debian) betreibt.&lt;br /&gt;
&lt;br /&gt;
Weiterhin denke ich, dass euer Hauptarbeitsrechner unter Windows läuft.&lt;br /&gt;
&lt;br /&gt;
Als Smartphone OS Android (wer Apple hat, kann gerne die Token-Auslese-Geschichte hier beschreiben).&lt;br /&gt;
&lt;br /&gt;
Um das Teil auch von Alexa aus ein und aus zu schalten, sollte auch die Installation von Alexa in FHEM fertig sein.&lt;br /&gt;
&lt;br /&gt;
==Die Einrichtung des Moduls==&lt;br /&gt;
===Vorarbeiten (Linux)===&lt;br /&gt;
Zunächst fangen wir mal auf unserem FHEM Rechner an. Mit Putty verbinden wir uns per SSH mit dem FHEM Computer (Todo: Das ist hier ist für Windows-Nutzer...)&lt;br /&gt;
&lt;br /&gt;
Folgende Befehle können benötigt werden (Debian):&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libjson-perl&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libdigest-md5-perl&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libcrypt-cbc-perl&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt install libcryptx-perl&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libcrypt-ecb-perl&amp;lt;/code&amp;gt; (nur nötig, wenn ihr einen verschlüsselten Token mit 96 Zeichen habt)&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo cpan Crypt::Rijndael_PP&amp;lt;/code&amp;gt; (nur nötig, wenn libcryptx-perl aus irgendwelchen Gründen nicht funktioniert)&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo cpan Crypt::Cipher::AES&amp;lt;/code&amp;gt; (nur nötig, wenn Crypt::Rijndael_PP aus irgendwelchen Gründen nicht funktioniert)&lt;br /&gt;
&lt;br /&gt;
Wenn bei dem ein oder anderen Modul die Meldung kommt, dass es schon installiert ist, einfach mit dem nächsten Befehl weiter machen. Das CPAN Teil würde ich am Schluss machen, das braucht ziemlich lang zum installieren.&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten am Smartphone (Token)===&lt;br /&gt;
Das Problem ist folgendes:&lt;br /&gt;
&lt;br /&gt;
Wenn der Roboter mit dem WLAN verbunden wird, generiert er einen Token. Das ist ein Schlüssel, ohne den er sich nicht steuern lässt. Damit FHEM drauf zugreifen kann, benötigt man diesen Token.&lt;br /&gt;
&lt;br /&gt;
Mit den neueren Versionen der MiHome App klappt das Auslesen der Tokens leider nicht mehr.&lt;br /&gt;
&lt;br /&gt;
====Auslesen bei Android Endgeräten====&lt;br /&gt;
&lt;br /&gt;
Ich gehe davon aus, dass der Staubsauger mit der original MiHome App eingebunden ist und funktioniert. (Ich habe bei der Einrichtung des Servers =&amp;gt; &amp;quot;other&amp;quot; gewählt. Offenbar wollen neuere Staubsauger sich mit &amp;quot;China Mainland&amp;quot; nicht mehr verbinden. Tut hier an dieser Stelle zwar nichts zur Sache, aber vielleicht hilft es dem ein oder anderen. Wenn man die Region gewechselt hat, muss man auch den Staubsauger neu einbinden)&lt;br /&gt;
&lt;br /&gt;
* MiHome löschen&lt;br /&gt;
* alte MiHome suchen (APKMirror z.B., Version 5.0.19 hat bei mir funktioniert, unsichere Quellen müssen erlaubt sein)&lt;br /&gt;
* runtergeladene MiHome App öffnen und anmelden (sollte ganz normal den Sauger finden)&lt;br /&gt;
* USB-Debugging am Handy einschalten (Entwickleroptionen...)&lt;br /&gt;
* Handy mit USB Kabel und PC verbinden&lt;br /&gt;
* [https://github.com/ultrara1n/MiToolkit/releases MiToolkit] 1.6 runterladen und öffnen&lt;br /&gt;
* [https://github.com/ultrara1n/MiToolkit/releases MiToolkit] erzeugt nun am Handy ein Backup&lt;br /&gt;
* anschließend zeigt es den Token direkt am PC an&lt;br /&gt;
&lt;br /&gt;
====Auslesen bei iOS Endgeräten====&lt;br /&gt;
&lt;br /&gt;
Zum Auslesen des Tokens mit iOS Endgeräten kann die Anleitung unter folgendem Link befolgt werden: [https://forum.smartapfel.de/forum/thread/370-xiaomi-token-auslesen/]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Auslesen mit fhem / fhempy&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In fhem gibt es auch noch das [https://github.com/fhempy/fhempy/blob/master/README.md fhempy-System], dafür gibt es auch ein Modul zum Auslesen von Xiaomi-Token aus deren Cloud, u.a. auch das Token für unseren Mi-Vacuum.&lt;br /&gt;
&lt;br /&gt;
===Installation des inoffiziellen Moduls===&lt;br /&gt;
Das Modul ist seit 28.02.2018 ein offizielles Modul. Eine separates Installation ist nicht (mehr) notwendig.&lt;br /&gt;
&lt;br /&gt;
==Einrichten des Moduls [[XiaomiDevice]] ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Mi_Vacuum XiaomiDevice 192.168.222.77 55387753545937326a33396943557999&lt;br /&gt;
&lt;br /&gt;
attr Mi_Vacuum subType VacuumCleaner&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und schon (=etwa nach 10 Sekunden) sollte euer Roboter in FHEM mit ganz vielen Readings auftauchen.&lt;br /&gt;
&lt;br /&gt;
==Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus)==&lt;br /&gt;
Wie bindet man das jetzt schnell in Alexa ein?&lt;br /&gt;
&lt;br /&gt;
Wir legen uns in FHEM einen Dummy an. Dieser wird ein Switch (on off). Dazu noch ein DOIF oder ein notify, welches diesen Switch überwacht. Je nach Status des Dummys schalten wir den Roboter.&lt;br /&gt;
&lt;br /&gt;
Ein List meines Dummys:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CFGFN &lt;br /&gt;
   NAME       Mi_Vacuum_Staubsauger &lt;br /&gt;
   NR         719473 &lt;br /&gt;
   STATE      on &lt;br /&gt;
   TYPE       dummy &lt;br /&gt;
   Readings: &lt;br /&gt;
     2017-09-18 21:10:12   state           on &lt;br /&gt;
 Attributes: &lt;br /&gt;
   alexaName  Mi_Vacuum_Staubsauger &lt;br /&gt;
   genericDeviceType switch &lt;br /&gt;
   room       alexa &lt;br /&gt;
   setList    on off &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mein DOIF:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define di_Mi_Vacuum DOIF ([Mi_Vacuum_Staubsauger:&amp;quot;on&amp;quot;]) (set Mi_Vacuum start) DOELSE (set Mi_Vacuum charge)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Attribut do always nicht vergessen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Dummy setzen wir in den Raum, der unsere Alexa Geräte beinhaltet. Nun den Alexa FHEM Service neu starten. Anschließend sollte eine Suche nach neuen Geräten in Alexa unseren Dummy finden. Für diesen legen wir in Alexa einen neuen Raum an, z.B. Staubsauger.&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
Ein &amp;quot;Alexa schaltet den Staubsauger ein&amp;quot; lässt unseren Mi-Vacuum loslegen. &amp;quot;Alexa schalte den Staubsauger aus&amp;quot; schickt ihn wieder zurück zu seiner Station.&lt;br /&gt;
&lt;br /&gt;
==Zonenreinigung==&lt;br /&gt;
Um nur Teilbereiche einer Wohnung zu reinigen, ist es möglich über das Modul Zonen zu definieren. Hierzu ist es notwendig, die Koordinaten der gewünschten Zone zu ermitteln. Hierzu eignet sich die [https://xiaomi.flole.de/ FloleVac App] die entweder auf einem Android Device oder auf einem Android Emulator (z.B. [https://www.bluestacks.com/download.html BlueStacks]) verwendet werden kann. In der App kann man in der Karte eine Zone für die Reinigung markieren und durch langes Gedrückthalten des &amp;quot;Reinigen-Buttons&amp;quot; in der FloleVac App die Koordinaten dieser Zone in die Zwischenablage kopieren. &lt;br /&gt;
&lt;br /&gt;
Mit diesen Koordindaten im Format [16200,27250,31650,27650,1] kann man dann loslegen die Zonen in FHEM zu definieren:&lt;br /&gt;
&lt;br /&gt;
Entweder direkt über die Werte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set vacuum zone 16200,27250,31650,27650,1 23700,23050,25200,24200,2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oder über die passenden Attribute erst ein Alias anlegen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr vacuum zone_names home:[16200,27250,31650,27650,1],[23700,23050,25200,24200,2] livingroom:[16200,26250,23000,30150,1]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein Alias kann dann wie folgt genutzt werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set vacuum zone home&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Probleme und Lösungen==&lt;br /&gt;
===Crypt::Cipher::AES or Crypt::Rijndael_PP is required!===&lt;br /&gt;
Die Meldung im STATE des Devices bedeutet, dass noch einige Debian/Perl-Module installiert werden müssen. Siehe [[#Vorarbeiten (Linux)]].&lt;br /&gt;
&lt;br /&gt;
Danach ist darauf zu achten, dass das Device wieder aktiviert wird.&lt;br /&gt;
 attr &amp;lt;devicename&amp;gt; disable 0&lt;br /&gt;
==Quellen==&lt;br /&gt;
* {{Link2Forum|Topic=73052|LinkText=Forums-Thread}}&lt;br /&gt;
* {{Link2Forum|Topic=76940|LinkText=Diskussionsthread}}&lt;br /&gt;
* [http://miniweb.sourceforge.net/ MiniWeb], kleiner WebServer für Windows&lt;br /&gt;
* [https://xiaomi.flole.de/ Flole], alternative App für Android, die das Token nach GoogleDrive exportiert&lt;br /&gt;
* [http://www.roboter-forum.com/forumdisplay.php?130-Xiaomi Roboter-Forum] deutschsprachiges Forum, welches sich mit dem Mi Vacuum beschäftigt (auch vor dem Kauf des Roboters lohnt sich ein Besuch dort)&lt;br /&gt;
[[Kategorie:Other Components]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DbLog&amp;diff=38859</id>
		<title>DbLog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DbLog&amp;diff=38859"/>
		<updated>2024-01-07T08:18:40Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: Bei Synology mit DSM 7.2 (z.B. beim DS923+) ist z.B. der Port der MariaDB wieder von Haus aus auf Standard gesetzt ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Protokolliert Ereignisse in einer Datenbank&lt;br /&gt;
|ModType=h&lt;br /&gt;
|ModForumArea=Automatisierung&lt;br /&gt;
|ModTechName=93_DbLog.pm&lt;br /&gt;
|ModOwner=tobiasfaust ({{Link2FU|118|Forum}}/[[Benutzer Diskussion:Tobias.faust|Wiki]])&amp;lt;br /&amp;gt;DS_Starter ({{Link2FU|16933|Forum}}/[[Benutzer Diskussion:DS_Starter|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
Mit der Zeit entstehen in FHEM recht umfangreiche Log-Daten für die verschiedensten konfigurierten Devices. Die übliche Einstiegs-[[Konfiguration]] sieht vor, dass die Logs als {{Link2CmdRef|Lang=de|Anker=FileLog|Label=FileLog}} gespeichert werden - je nach Einstellung in wenigen sehr großen oder vielen kleineren Dateien. Der Datei-basierte Zugriff ist allerdings nicht wirklich performant und kann schnell zum Flaschenhals werden (z.B. bei der Darstellung von Graphen über einen längeren Zeitraum).&lt;br /&gt;
&lt;br /&gt;
Alternativ kann FHEM die Log-Daten mittels {{Link2CmdRef|Lang=de|Anker=DbLog|Label=DbLog}} in einer Datenbank speichern. Diese kann lokal als einfache SQLite- oder als zentrale Server-Datenbank (s.u.) gestaltet sein. Schon eine lokale einfache SQLite-Datenbank ist in der Regel deutlich performanter als File-basierte Logs.&lt;br /&gt;
&lt;br /&gt;
Damit eine Datenbank-Nutzung möglich ist, müssen folgende Anpassungen gemacht werden:&lt;br /&gt;
# [[#Datenbank|Erstellen einer entsprechenden Datenbank]]&lt;br /&gt;
# [[#Datenbank-Anbindung mittels db.conf|Konfiguration der Datenbank-Anbindung in FHEM]]&lt;br /&gt;
# [[#Konfiguration als Device in fhem.cfg|Anpassen aller (oder einzelner) Konfigurationen von FileLog nach DbLog]]&lt;br /&gt;
# [[#Anpassen der gplot-Konfigurationen|Ggf. Anpassen der gplot-Konfigurationen]]&lt;br /&gt;
&lt;br /&gt;
Eine weitere Alternative bietet das Modul [[InfluxDBLogger]].&lt;br /&gt;
&lt;br /&gt;
Reporting und Management von DbLog-Datenbankinhalten kann mit dem Modul [[DbRep - Reporting und Management von DbLog-Datenbankinhalten|DbRep]] stattfinden.&lt;br /&gt;
&lt;br /&gt;
== Konfiguration ==&lt;br /&gt;
=== Datenbank-Anbindung mittels db.conf ===&lt;br /&gt;
{{Randnotiz|RNTyp=y|RNText=&#039;&#039;&#039;Anmerkung&#039;&#039;&#039;: MariaDB10 nutzt nicht Port 3306 sondern 3307. Dies ist zum Beispiel bei einigen Synology NAS der Fall.}}&lt;br /&gt;
DbLog wird durch 2 verschiedene Einträge aktiviert/definiert. In einer Datei namens &#039;&#039;&#039;db.conf&#039;&#039;&#039; werden die Parameter für eine Verbindung zur Datenbank (host, username, password, etc.) hinterlegt. Diese Datei kann in einem beliebigen Verzeichnis angelegt werden. Für eine MySQL-Datenbank sieht die db.conf folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
 %dbconfig= (&lt;br /&gt;
     connection =&amp;gt; &amp;quot;mysql:database=fhem;host=db;port=3306&amp;quot;,&lt;br /&gt;
     user =&amp;gt; &amp;quot;fhemuser&amp;quot;,&lt;br /&gt;
     password =&amp;gt; &amp;quot;fhempassword&amp;quot;,&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
Im Verzeichnis &#039;&#039;&#039;contrib/dblog&#039;&#039;&#039; der FHEM-Installation befindet sich eine Beispielkonfiguration mit der Syntax für jeden unterstützen Datenbanktyp.&lt;br /&gt;
Es wird empfohlen, diese Datei zu kopieren und erst dann entsprechend zu bearbeiten. Am Besten kopiert man diese Datei in das FHEM Home Directory /opt/fhem/ und achtet auf die entsprechenden Rechte!&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;chown fhem:dialout /opt/fhem/db.conf&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration als Device ===&lt;br /&gt;
Das DbLog Device wird dann definiert mit&lt;br /&gt;
:&amp;lt;code&amp;gt;define &amp;lt;name&amp;gt; DbLog &amp;lt;configfilename&amp;gt; &amp;lt;regexp&amp;gt; &amp;lt;/code&amp;gt;&lt;br /&gt;
wobei &#039;&#039;&amp;lt;configfilename&amp;gt;&#039;&#039; dem Pfad zur zuvor angelegten db.conf entspricht.&lt;br /&gt;
Ein Beispiel hierfür wäre:&lt;br /&gt;
:&amp;lt;code&amp;gt;define logdb DbLog ./db.conf .*:.* &amp;lt;/code&amp;gt;&lt;br /&gt;
Die Angabe von &amp;lt;code&amp;gt;.*:.*&amp;lt;/code&amp;gt; bedeutet, dass sämtliche DeviceMessages (Messwerte, Batteriestatus, KeepAlives, etc.) in die Datenbank geschrieben werden. Dies führt u.U. dazu, dass die Datenbank auch mit vielen teils irrelevanten Werten gefüllt wird. Man kann daher die zu loggenden Werte einschränken, indem man genau angibt welche Werte übertragen werden sollen. Dies ist in [[#Finetuning des Loggings]] beschrieben.&lt;br /&gt;
&lt;br /&gt;
Unbedingt beachten: bei Verwendung des Moduls configdb wird die Konfigurationsdatei aus der &#039;&#039;&#039;&#039;&#039;Datenbank&#039;&#039;&#039;&#039;&#039; gelesen. Deshalb ist es erforderlich, die Datei mittels &amp;lt;code&amp;gt;configdb fileimport db.conf &amp;lt;/code&amp;gt; vorher zu importieren !&lt;br /&gt;
&lt;br /&gt;
=== Finetuning des Loggings ===&lt;br /&gt;
Bei der Konfiguration des Log-Devices werden die zu loggenden Daten definiert - in der einfachsten Form sieht das so aus: &amp;lt;code&amp;gt;define logdb DbLog ./db.conf .*:.* &amp;lt;/code&amp;gt;. Die Angabe von &amp;lt;code&amp;gt;.*:.*&amp;lt;/code&amp;gt; bedeutet, dass sämtliche DeviceMessages (Messwerte, Batteriestatus, KeepAlives, etc.) in die Datenbank geschrieben werden. Dies führt u.U. dazu, dass die Datenbank auch mit sehr vielen und teils nicht benötigten Werten gefüllt wird und schnell wächst. Die Datenbank ist zwar deutlich leistungsfähiger, was große Datenmengen angeht, Datensparsamkeit kann aber schnell sinnvoll werden...&lt;br /&gt;
&lt;br /&gt;
Um das Log-Aufkommen einzugrenzen gibt es mehrere Ansätze:&lt;br /&gt;
* Einschränkung über den &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Eintrag&lt;br /&gt;
* Einschränkung über DbLogExclude-Einträge der jeweiligen Devices&lt;br /&gt;
* Einschränkung über DbLogInclude-Einträge des jeweiligen Devices&lt;br /&gt;
* Ausschluß von Device/Reading-Kombinationen über das Attribut &amp;quot;excludeDevs&amp;quot;. Es können {{Link2CmdRef|Anker=devspec|Lang=de|Label=devspec}} verwendet werden. &lt;br /&gt;
&lt;br /&gt;
==== Einschränkung über den zentralen &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Eintrag ====&lt;br /&gt;
Man kann die zu loggenden Werte einschränken, indem man genau angibt welche Werte übertragen werden sollen. Die erste Wildcard, also das erste &amp;lt;code&amp;gt;.*&amp;lt;/code&amp;gt;, entspricht dem in FHEM verwendeten Device-Namen. Die zweite Wildcard entspricht dem vom Device ausgegebenen zu loggenden Wert. Separiert werden beiden Angaben durch einen Doppelpunkt. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel, um zwar alle definierten Devices zu erfassen, aber nur die Werte Temperatur, Ventilposition und Luftfeuchte in die Datenbank zu schreiben wäre:&lt;br /&gt;
:&amp;lt;code&amp;gt;define myDbLog DbLog ./db.conf .*:(temperature|valveposition|humidity).* &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Einschränkung über die jeweiligen Devices ====&lt;br /&gt;
Man kann die zu loggenden Werte für einzelne Devices separat einschränken, ohne dies im zentralen define-Eintrag machen zu müssen. Dies kann interessant sein, wenn beispielsweise ein Device Fehlerwerte meldet, die uninteressant sind, oder es meldet unnötig häufig Werte - beides ist z.B. bei 1-wire-Temperatursensoren gerne der Fall.&lt;br /&gt;
&lt;br /&gt;
Um das einzuschränken gibt es 2 Stellparameter, die als Attribute direkt zum jeweiligen Device konfiguriert werden:&lt;br /&gt;
* DbLogExclude - definiert Werte, die nicht geloggt werden sollen&lt;br /&gt;
* DbLogInclude - definiert Werte, die geloggt werden sollen ( siehe attr DbLogSelectionMode )&lt;br /&gt;
* event-min-interval, event-on-change-reading und event-on-update-reading beeinflussen, wie häufig Werte geloggt werden (vgl. {{Link2CmdRef|Lang=de|Anker=event-on-update-reading}})&lt;br /&gt;
&lt;br /&gt;
Eine konkrete Konfiguration für einen sehr gesprächigen 1-wire-Temperatursensor könnte wie folgt aussehen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define EG_Balkon GPIO4 BUSMASTER&lt;br /&gt;
attr EG_Balkon DbLogExclude failures,T,85     # logge keine &amp;quot;failures&amp;quot;, &amp;quot;T&amp;quot;-Werte und &amp;quot;85&amp;quot;-Werte (default-Werte, wenn keine Temperatur gelesen werden kann)&lt;br /&gt;
attr EG_Balkon event-on-change-reading state  # logge nur, wenn sich ein Wert ändert (wenn sich die Temperatur nicht ändert, logge das nicht)&lt;br /&gt;
attr EG_Balkon event-min-interval state:900   # logge spätestens alle 900sec = 15min&lt;br /&gt;
attr EG_Balkon event-on-update-reading .*     # logge alle Werte, die aktualisiert werden&lt;br /&gt;
&lt;br /&gt;
attr &amp;lt;1-Wire-Device vom Typ OWTHERM oder OWSWITCH&amp;gt; DbLogExclude data.*      # verhindert das Logging der state-Eintragungen&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine in diesem {{Link2Forum|Topic=33697|Message=264127}} vorgestellte Strategie zur Vermeidung unnötigen Loggings ist, dass bei der Definition von Devices durch das nachfolgende &amp;lt;code&amp;gt;notify&amp;lt;/code&amp;gt; automatisch ein DbLogExclude für alle Werte (.*) des Devices zugewiesen wird und dies nur bei Interesse an geloggten Werten gelöscht bzw. angepasst wird:&lt;br /&gt;
&amp;lt;code&amp;gt;define nDbLogExclude notify global:DEFINED.* attr $EVTPART1 DbLogExclude .*&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ebenso ist es mittlerweile möglich, lediglich erwünschte Werte (Positiv-Liste) zu loggen und alle anderen zu verwerfen. Hierfür wird im LogDevice das attribut DbLogSelectionMode Include verwendet. Nun kann für jedes Device mit DbLogInclude &amp;lt;Reading1&amp;gt;,&amp;lt;Reading2&amp;gt;,... angegeben werden, welche Readings geloggt werden sollen. &lt;br /&gt;
Integriert ist ebenfalls ein &amp;quot;min-interval&amp;quot;, siehe {{Link2CmdRef}}.&lt;br /&gt;
&lt;br /&gt;
== Datenbank ==&lt;br /&gt;
Unterstützte Datenbanksysteme (Auswahl):&lt;br /&gt;
* Sqlite&lt;br /&gt;
* MySQL&lt;br /&gt;
* PostGreSql&lt;br /&gt;
&lt;br /&gt;
=== Tabellen ===&lt;br /&gt;
Die Datenbank ist relativ simpel gestaltet und besteht lediglich aus den folgenden beiden Tabellen:&lt;br /&gt;
* current&lt;br /&gt;
* history&lt;br /&gt;
&lt;br /&gt;
DbLog ist auf eine feste Tabellenstruktur angewiesen. Man muss daher in seiner Datenbank eine Tabelle mit folgenden Spalten anlegen:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Spalte&lt;br /&gt;
! Beschreibung (en)&lt;br /&gt;
! Beschreibung (de)&lt;br /&gt;
! Beispiel&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;TIMESTAMP&#039;&#039;&#039;&lt;br /&gt;
| timestamp of event&lt;br /&gt;
| Zeitstempel&lt;br /&gt;
| 2007-12-30 21:45:22 &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;DEVICE&#039;&#039;&#039;&lt;br /&gt;
| device name&lt;br /&gt;
| Device-Name&lt;br /&gt;
| Wetterstation&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;TYPE&#039;&#039;&#039;&lt;br /&gt;
| device type&lt;br /&gt;
| Device-Typ&lt;br /&gt;
| KS300&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;EVENT&#039;&#039;&#039;&lt;br /&gt;
| event specification as full string&lt;br /&gt;
| Eventspezifikation als Text&lt;br /&gt;
| humidity: 71 (%)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;READING&#039;&#039;&#039;&lt;br /&gt;
| name of reading extracted from event&lt;br /&gt;
| Bezeichnung des Readings&lt;br /&gt;
| humidity&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;VALUE&#039;&#039;&#039;&lt;br /&gt;
| actual reading extracted from event&lt;br /&gt;
| Wert des Readings&lt;br /&gt;
| 71&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;UNIT&#039;&#039;&#039;&lt;br /&gt;
| unit extracted from event&lt;br /&gt;
| Einheit des Readings&lt;br /&gt;
| %&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Vorlagen zur Anlage von Tabellen und Indizes sind für jeden unterstützten Datenbanktyp im Verzeichnis &#039;&#039;&#039;contrib/dblog&#039;&#039;&#039; der FHEM-Installation, oder hier zu finden: [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/dblog/ Link]. Das MySQL-Skript (db_create_mysql.sql) legt eine neue Datenbank, das PostGres-Skript (db_create_postgresql.sql) ein neues Schema mit Namen &amp;quot;fhem&amp;quot; an.&lt;br /&gt;
&lt;br /&gt;
==== current ====&lt;br /&gt;
Die Tabelle current enthält für jedes zu loggende Device lediglich den letzten Wert. Falls noch kein Wert geloggt wurde, ist diese Tabelle leer. &lt;br /&gt;
Falls der Inhalt gelöscht wird, bauen sich die Daten automatisch wieder auf. Es gehen durch das löschen der Tabelle current keine Log-Informationen verloren.&lt;br /&gt;
Der Inhalt wird aber u.a. für die Dropdown-Felder beim Plot-Editor verwendet.&lt;br /&gt;
&lt;br /&gt;
Um doppelte Einträge in der Tabelle zu vermeiden, wurden die Möglichkeit geschaffen Primary Keys zu definieren. Da in der Spalte &amp;lt;code&amp;gt;READING&amp;lt;/code&amp;gt; u.U. bei verschiedenen Geräten gleiche Namen vorkommen können, sollte der Primary Key um den Gerätenamen erweitert werden. Der Primary Key sollte also aus &amp;lt;code&amp;gt;DEVICE&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;READING&amp;lt;/code&amp;gt; bestehen. Um in der Datenbank &#039;&#039;fhem&#039;&#039; diesen PK zu setzen, kann folgender SQL Code verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
ALTER TABLE `fhem`.`current` &lt;br /&gt;
CHANGE COLUMN `DEVICE` `DEVICE` VARCHAR(64) CHARACTER SET &#039;utf8&#039; COLLATE &#039;utf8_bin&#039; NOT NULL ,&lt;br /&gt;
CHANGE COLUMN `READING` `READING` VARCHAR(64) CHARACTER SET &#039;utf8&#039; COLLATE &#039;utf8_bin&#039; NOT NULL ,&lt;br /&gt;
ADD PRIMARY KEY (`DEVICE`, `READING`);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Achtung: Die Tabelle &amp;quot;current&amp;quot; wird nur befüllt, wenn das Attribut DbLogType auf Current oder Current/History gesetzt ist.&lt;br /&gt;
&lt;br /&gt;
==== history ====&lt;br /&gt;
Die Tabelle history enthält alle bisher geloggten Daten. Löschen in dieser Tabelle bedeutet automatisch Datenverlust (gewollt oder nicht ... )&lt;br /&gt;
Der Inhalt dieser Tabelle wird verwendet, um die Plots zu zeichnen oder Auswertungen mit [[DbRep - Reporting und Management von DbLog-Datenbankinhalten|DbRep]] anzufertigen&lt;br /&gt;
&lt;br /&gt;
{{Todo|Ausbauen}}&lt;br /&gt;
&lt;br /&gt;
Um Problem beim Import von cacheFiles zu vermeiden, kann in der Datenbank ein PK angelegt werden, welcher Timestamp, Device und Reading umfasst. Dadurch werden doppelte Einträge wirksam verhindert.&lt;br /&gt;
&lt;br /&gt;
== Anpassen der gplot-Konfigurationen ==&lt;br /&gt;
Die meisten gplot-Konfigurationen sind bisher lediglich auf FileLog-Konfigurationen ausgelegt. Deshalb müssen sie für die Verwendung mit DbLog angepasst werden. Glücklicherweise beschränkt sich dies auf die reinen FileLog-Zeilen - es müssen die DbLog-Äquivalente hinzugefügt werden. Die FileLog-Einträge müssen zwar nicht gelöscht werden, wenn man aber FileLog und DbLog parallel betreibt, sollte man getrennte gplot-Dateien für beide Logging-Typen haben um Auswertungsprobleme erkennen zu können.&lt;br /&gt;
&lt;br /&gt;
Für die fht.gplot Konfiguration sähe die Anpassung wie folgt aus (lediglich die vier DbLog-Zeilen wurden hinzugefügt):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2014-12-25 21:53:30&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 nomirror&lt;br /&gt;
set y2tics &lt;br /&gt;
set grid y2tics&lt;br /&gt;
set ylabel &amp;quot;Actuator/Window (%)&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Temperature in C&amp;quot;&lt;br /&gt;
set yrange 0:100&lt;br /&gt;
set y2range 5:25&lt;br /&gt;
&lt;br /&gt;
#FileLog 4:.measured-temp\x3a:0:&lt;br /&gt;
#FileLog 4:.actuator\x3a:0:int&lt;br /&gt;
#FileLog 4:.desired-temp::&lt;br /&gt;
#FileLog 4:.window\x3a::&lt;br /&gt;
&lt;br /&gt;
#DbLog &amp;lt;SPEC1&amp;gt;:.measured-temp:0:&lt;br /&gt;
#DbLog &amp;lt;SPEC1&amp;gt;:.actuator:0:int&lt;br /&gt;
#DbLog &amp;lt;SPEC1&amp;gt;:.desired-temp::&lt;br /&gt;
#DbLog &amp;lt;SPEC1&amp;gt;:.window::&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Measured temperature&#039; ls l0 lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Actuator (%)&#039; ls l1 lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Desired Temperature&#039; ls l2 lw 1 with steps,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Window&#039; ls l3 lw 1 with steps&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Des Weiteren ist zu beachten: &lt;br /&gt;
&lt;br /&gt;
On-Off-Plots&lt;br /&gt;
&lt;br /&gt;
 EG_Bad:window:::$val=~s/(on|off)(\d*).*/$1eq&amp;quot;on&amp;quot;?1:0/eg&lt;br /&gt;
&lt;br /&gt;
unter Berücksichtigung von dim-Werten:&lt;br /&gt;
&lt;br /&gt;
 EG_WoZi_Licht:value:::$val=~s/(on|off)(\d*).*/$1eq&amp;quot;on&amp;quot;?1:($1eq&amp;quot;dim&amp;quot;?$2*0.01:0)/eg&lt;br /&gt;
&lt;br /&gt;
== Beispiel: Anlegen und Nutzung einer SQLite-Datenbank ==&lt;br /&gt;
Im folgenden wird eine lokale SQLite-Datenbank auf einen Ubuntu-System angelegt (nach Quelle: http://www.tatsch-it.de/fhem-dblog/)&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;Installation von SQLite:&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo aptitude install sqlite3 libdbi-perl libdbd-sqlite3-perl&lt;br /&gt;
&lt;br /&gt;
oder auf aktuellerem Stand&lt;br /&gt;
&lt;br /&gt;
sudo apt install sqlite3&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;Anlegen der SQLite-Datenbank fhem.db&#039;&#039; (öffnet auch direkt eine SQL-Kommandozeile):&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo sqlite3 /opt/fhem/fhem.db&amp;lt;/pre&amp;gt;&lt;br /&gt;
In der geöffneten SQL-Kommandozeile eingeben:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE history (TIMESTAMP TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, DEVICE varchar(64), TYPE varchar(64), EVENT varchar(512), READING varchar(64), VALUE varchar(128), UNIT varchar(32));&lt;br /&gt;
CREATE TABLE current (TIMESTAMP TIMESTAMP, DEVICE varchar(64), TYPE varchar(64), EVENT varchar(512), READING varchar(64), VALUE varchar(128), UNIT varchar(32));&lt;br /&gt;
CREATE INDEX Search_Idx ON `history` (DEVICE, READING, TIMESTAMP);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Kommandozeile verlässt man mit &amp;lt;code&amp;gt;.exit&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;Anpassen des Besitzers und der Rechte der Datenbank-Datei:&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo chown fhem /opt/fhem/fhem.db&lt;br /&gt;
sudo chmod 600 /opt/fhem/fhem.db&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;Datenbank-Anbindung des FHEM konfigurieren:&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo nano /opt/fhem/db.conf&amp;lt;/pre&amp;gt;&lt;br /&gt;
Inhalt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%dbconfig= (&lt;br /&gt;
  connection =&amp;gt; &amp;quot;SQLite:dbname=/opt/fhem/fhem.db&amp;quot;,&lt;br /&gt;
  user =&amp;gt; &amp;quot;&amp;quot;,&lt;br /&gt;
  password =&amp;gt; &amp;quot;&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;Logging des FHEM auf die Datenbank konfigurieren:&#039;&#039; (hier sind nur die Anpassungen aufgeführt)&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo nano /opt/fhem/fhem.cfg&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
attr global userattr DbLogExclude ...  # erlaubt es einzelne Einträge nicht zu loggen&lt;br /&gt;
...&lt;br /&gt;
define logdb DbLog ./db.conf .*:.*     # logt alle(!) auflaufenden Events aller Konfigurationen&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Da durch diese &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Definition alle auflaufenden Events gelogt werden, müssen keine weiteren Anpassungen in der Konfiguration gemacht werden. Die FileLog-Einträge können bedenkenlos bestehen bleiben - dann wird in Datenbank und FileLog gelogt und man verliert keine Daten, falls etwas nicht klappt. Wenn alles wie geplant läuft, können die FileLog-Definitionen gelöscht werden (ebenso die Log-Dateien). Ebenso können die zu loggenden Daten später eingegrenzt werden (s. [[#Finetuning des Loggings]]).&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;FHEM neu starten:&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo service fhem stop&lt;br /&gt;
sudo service fhem start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;Kontrollieren, ob Logs in die Datenbank geschrieben werden:&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo sqlite3 /opt/fhem/fhem.db&amp;lt;/pre&amp;gt;&lt;br /&gt;
In der geöffneten SQL-Kommandozeile eingeben:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
select * from history order by TIMESTAMP;       # dies gibt alle(!) Logs chronologisch aus (kann nach längerem Betrieb recht lange dauern)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Kommandozeile verlässt man mit &amp;lt;code&amp;gt;.exit&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;Anpassung der glot-Dateien:&#039;&#039; siehe [[#Anpassen der gplot-Konfigurationen]]&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Beispiel: Anlegen und Nutzung einer Mysql-Datenbank ==&lt;br /&gt;
Hierfür gibt es eine [[DbLog-MySQL|extra Seite]], die die Unterschiede und Feinheiten zwischen den verschiedenen Versionen berücksichtigt&lt;br /&gt;
&lt;br /&gt;
Anstatt nano kann jeder andere kompatible Editor verwendet werden. Weiterhin bitte beachten, dass die hier genannten Befehle teilweise root-Rechte voraussetzen. Entweder komplett als root arbeiten, oder mittels sudo.&lt;br /&gt;
&lt;br /&gt;
Unter Ubuntu/debian: &lt;br /&gt;
 apt-get update &amp;amp;&amp;amp; apt-get install mysql-server mariadb-client libdbd-mysql libdbd-mysql-perl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei der Installation sollte man aus Sicherheitsgründen ein Passwort für den mysql-root vergeben, wenn man nicht sogar ganz den Login verbietet.&lt;br /&gt;
&lt;br /&gt;
Hinweis: im Folgenden ist &amp;quot;#&amp;quot; der normale Prompt und &amp;quot;mysql&amp;gt;&amp;quot; der prompt innerhalb mysql, dieser kann mit exit verlassen werden.  &lt;br /&gt;
&lt;br /&gt;
Eine erste Konfiguration von MariaDB / mySQL kann mit &amp;lt;pre&amp;gt;&lt;br /&gt;
# sudo mysql_secure_installation&lt;br /&gt;
&amp;lt;/pre&amp;gt;vorgenommen werden. &lt;br /&gt;
&lt;br /&gt;
Zum Test mal mit mysql verbinden: &lt;br /&gt;
 # mysql -p -u root&lt;br /&gt;
 Enter password:&lt;br /&gt;
 mysql&amp;gt; exit&lt;br /&gt;
&lt;br /&gt;
Jetzt die Tabellenstruktur anlegen. &lt;br /&gt;
Hierfür kann die Datei /opt/fhem/contrib/dblog/db_create_mysql.sql als Vorlage verwendet und das Passwort und der Benutzername geändert werden. &lt;br /&gt;
 cd /opt/fhem/contrib/dblog/&lt;br /&gt;
 nano db_create_mysql.sql&lt;br /&gt;
Dann wird die Datei eingelesen (root Passwort wird abgefragt): &lt;br /&gt;
&lt;br /&gt;
 # mysql -u root -p &amp;lt; db_create_mysql.sql&lt;br /&gt;
&lt;br /&gt;
Jetzt kann man den Zugang testen: &lt;br /&gt;
&lt;br /&gt;
 # mysql -p -u &amp;lt;fhemuser&amp;gt;&lt;br /&gt;
 Enter password: &amp;lt;fhempassword&amp;gt;&lt;br /&gt;
 mysql&amp;gt; show databases;&lt;br /&gt;
&lt;br /&gt;
Nun müsste eine Datenbank &amp;quot;fhem&amp;quot; angezeigt werden, die die Tabellen current und history enthält.&lt;br /&gt;
&lt;br /&gt;
Nun in der Datei db.conf den mysql-Block auskommentieren und ebenfalls Benutzername, Passwort UND HOST anpassen. Leider ist hier nicht standardmäßig localhost eingestellt.&lt;br /&gt;
 nano /opt/fhem/db.conf&lt;br /&gt;
&lt;br /&gt;
Jetzt kann unter FHEM ein DbLog-Device angelegt werden (mit dem beispiel wird alles geloggt: &lt;br /&gt;
 define logdb DbLog ./db.conf .*:.*&lt;br /&gt;
Als State muss ein &amp;quot;connected&amp;quot; angezeigt werden. &lt;br /&gt;
&lt;br /&gt;
Ein rereadcfg in FHEM stellt sicher, dass die neue Konfiguration übernommen wird - ein Neustart ist nicht erforderlich.&lt;br /&gt;
&lt;br /&gt;
Nun kann die Funktion noch einmal überprüft werden: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
 # mysql -u &amp;lt;fhemuser&amp;gt; -p&lt;br /&gt;
 Enter password: &amp;lt;fhempassword&amp;gt;&lt;br /&gt;
 mysql&amp;gt; use fhem;&lt;br /&gt;
 Database changed&lt;br /&gt;
 mysql&amp;gt; show tables;&lt;br /&gt;
 +----------------+&lt;br /&gt;
 | Tables_in_fhem |&lt;br /&gt;
 +----------------+&lt;br /&gt;
 | current        |&lt;br /&gt;
 | history        |&lt;br /&gt;
 +----------------+&lt;br /&gt;
 2 rows in set (0,00 sec)&lt;br /&gt;
 mysql&amp;gt; select * from history; # Achtung, kann sehr groß werden .... #&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anscheinend gibt es bei der neuen Version MariaDB (im Gegensatz zu mysql) ein neues Anmeldeverfahren, so dass in der Datenbank selbst Veränderungen vorgenommen werden müssen, damit der Zugriff durch FHEM funktioniert: https://kofler.info/root-login-problem-mit-mariadb/&lt;br /&gt;
&lt;br /&gt;
Die Daten im MySQL können auch für die längere Aufbewahrung partitioniert werden. Dabei wird pro Partition eine Datei erzeugt statt einer gemeinsamen Datei für alle Daten. Je nach Wunsch zum Beispiel partitioniert nach Jahr.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
Alter table history PARTITION BY RANGE ( UNIX_TIMESTAMP(timestamp) ) (&lt;br /&gt;
    PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP(&#039;2019-01-01 00:00:00&#039;) ),&lt;br /&gt;
    PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP(&#039;2020-01-01 00:00:00&#039;) ),&lt;br /&gt;
    PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP(&#039;2021-01-01 00:00:00&#039;) ),&lt;br /&gt;
    PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP(&#039;2022-01-01 00:00:00&#039;) ),&lt;br /&gt;
    PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP(&#039;2023-01-01 00:00:00&#039;) ),&lt;br /&gt;
    PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP(&#039;2024-01-01 00:00:00&#039;) ),&lt;br /&gt;
    PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP(&#039;2025-01-01 00:00:00&#039;) ),&lt;br /&gt;
    PARTITION p7 VALUES LESS THAN (MAXVALUE) );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Beispiel: Abfragescript PHP/MySQL ==&lt;br /&gt;
Um eine schnelle Übersicht zu bekommen habe ich mir dieses Script geschrieben:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php $pdo = new PDO(&#039;mysql:host=localhost;dbname=fhem&#039;, &#039;fhemuser&#039;, &#039;fhempasswort&#039;);&lt;br /&gt;
echo &#039;&amp;lt;h2&amp;gt;Tabelle Current&amp;lt;/h1&amp;gt;&amp;lt;br&amp;gt;&amp;lt;table border=&amp;quot;1&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
  echo &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Anzahl&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Name&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Readings&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;;&lt;br /&gt;
$sql = &amp;quot;SELECT COUNT(*), DEVICE, GROUP_CONCAT(DISTINCT READING ORDER BY READING DESC SEPARATOR &#039;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&#039;) FROM current GROUP BY DEVICE;&amp;quot;; foreach ($pdo-&amp;gt;query($sql) as&lt;br /&gt;
$row) {&lt;br /&gt;
  echo &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;quot; . $row[0] . &amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;quot; . $row[1] . &amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;&amp;quot; . $row[2] . &amp;quot;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
echo &amp;quot;&amp;lt;/table&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
echo &#039;&amp;lt;h2&amp;gt;Tabelle History&amp;lt;/h1&amp;gt;&amp;lt;br&amp;gt;&amp;lt;table border=&amp;quot;1&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
  echo &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Anzahl&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Name&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;;&lt;br /&gt;
$sql = &amp;quot;SELECT COUNT(*), DEVICE FROM history GROUP BY DEVICE;&amp;quot;; foreach ($pdo-&amp;gt;query($sql) as&lt;br /&gt;
$row) {&lt;br /&gt;
  echo &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;quot; . $row[0] . &amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;quot; . $row[1] . &amp;quot;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
echo &amp;quot;&amp;lt;/table&amp;gt;&amp;quot;;&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bitte passt &#039;&#039;fhemuser&#039;&#039; und &#039;&#039;fhempasswort&#039;&#039; an. Das Ganze kommt dann nach &amp;lt;code&amp;gt;/var/www/html/fhemdb.php&amp;lt;/code&amp;gt; und ist mit &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;IP&amp;gt;/fhemdb.php&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; aufrufbar. Wenn ihr den zweiten Block für die history Tabelle ausklammert oder entfernt, läuft das Script viel schneller ab - klar die history Tabelle ist meist randvoll.&lt;br /&gt;
&lt;br /&gt;
== Integration von DBLog in eigene Module ==&lt;br /&gt;
=== Bereitstellung der UNITS ===&lt;br /&gt;
Mit der DbLog_splitFn kann der Modulautor selbst festlegen, wie die Events des Moduls in die Bestandteile Reading/Value/Unit zerlegt werden um ein korrektes Logging per DbLog zu gewährleisten.&lt;br /&gt;
&lt;br /&gt;
Dazu muss der Modulautor in der [[DevelopmentModuleIntro#X_Initialize|Initialize-Funktion]] eine &amp;lt;code&amp;gt;DbLog_splitFn&amp;lt;/code&amp;gt; bereitstellen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	...&lt;br /&gt;
	$hash-&amp;gt;{DbLog_splitFn}      = &amp;quot;X_DbLog_splitFn&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die genaue Aufrufsyntax und Funktionweise einer DbLog_split-Funktion findet man [[DevelopmentModuleIntro#X_DbLog_split|hier]].&lt;br /&gt;
&lt;br /&gt;
== Werte auslesen ==&lt;br /&gt;
Manchmal möchte man Daten aus den Logs abrufen ohne händisch in der Datenbank herumzuwühlen (s.u.). Dies ist insbesondere auch dann hilfreich, wenn man eigene Funktionen, Notifys oder spezielle Plots entwirft, bei denen man auf Logdaten zugreifen möchte.&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich beschrieben ist dies in der {{Link2CmdRef|Lang=de|Anker=DbLog}} und unterscheidet sich minimal (aber entscheidend) von der Struktur bei [[FileLog#Werte_auslesen|FileLogs]].&lt;br /&gt;
&lt;br /&gt;
Hier ein paar Beispiele, was man damit anstellen kann:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;get meineDB - - 2016-10-01 2016-10-03 meinSensor&amp;lt;/code&amp;gt; alle Einträge des meinSensor vom 01.10.-03.10.2016&lt;br /&gt;
* &amp;lt;code&amp;gt;get meineDB - - 2016-10-01_08:00:00 2016-10-01_16:00:00 meinSensor&amp;lt;/code&amp;gt; alle Einträge des meinSensor von 8-16 Uhr am 01.10.2016&lt;br /&gt;
* &amp;lt;code&amp;gt;get meineDB - - 2016-10-01_08:00:00 2016-10-01_16:00:00 meinSensor:temperature&amp;lt;/code&amp;gt; nur die temperature Werte&lt;br /&gt;
* &amp;lt;code&amp;gt;{ ReadingsTimestamp(&amp;quot;meinSensor&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;0&amp;quot;) }&amp;lt;/code&amp;gt; Timestamp des aktuellen state des meinSensor&lt;br /&gt;
* &amp;lt;code&amp;gt;{ OldTimestamp(&amp;quot;meinSensor&amp;quot;) }&amp;lt;/code&amp;gt; Timestamp des letzten state des FHT_3a32&lt;br /&gt;
* &amp;lt;code&amp;gt;{ time_str2num(OldTimestamp(&amp;quot;meinSensor&amp;quot;)) }&amp;lt;/code&amp;gt; Timestamp in Sekunden des letzten state des meinSensor&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== Bearbeitung von Datenbank-Einträgen ==&lt;br /&gt;
{{Hinweis|Dieser Abschnitt soll lediglich eine kleine Einführung in die Datenbank-Bearbeitung liefern. Für vertiefende Informationen sollte man sich grundsätzlich mit SQL beschäftigen. Eine umfassende und gut verständliche Anleitung zu SQL bietet bspw. [http://www.w3schools.com/sql/default.asp w3schools].}}&lt;br /&gt;
Irgendwann wird der Fall eintreten, dass in der Datenbank Einträge drinstehen, die geändert oder gelöscht werden sollen (zB. fehlerhafte Sensor-Rückmeldungen, umbenannte Readings). In klassischen Log-Dateien würde man diese einfach bearbeiten und löschen/anpassen (wobei man aber tunlichst zuvor FHEM stoppt, um Datenfehler zu vermeiden). Eine Datenbank kann bearbeitet werden, ohne FHEM stoppen zu müssen. &lt;br /&gt;
&lt;br /&gt;
Datenbanken kann man ohne weitere Hilfsmittel direkt von der Kommandozeile/Shell aus bearbeiten. Alternativ gibt es auch verschiedenste Tools (webbasiert oder als Applikation), die einen dabei unterstützen (Bsp. findet man u.a. [https://wiki.ubuntuusers.de/SQLite/#Grafische-Benutzeroberflaechen hier]). Für einfache Arbeiten reicht allerdings idR. Shell.&lt;br /&gt;
&lt;br /&gt;
=== SQLite-Datenbanken ===&lt;br /&gt;
&#039;&#039;&#039;Öffnen der DB unter Linux:&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
(Es werden Schreibrechte benötigt,ohne kann man die DB zwar öffnen, aber nichts machen)&lt;br /&gt;
 sudo sqlite3 fhem.db&lt;br /&gt;
Dadurch öffnet sich ein SQL-Konsole, auf der alle weiteren Befehle ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Schliessen der DB:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 sqlite&amp;gt; .exit&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hilfe anzeigen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 sqlite&amp;gt; .help&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Alle Tabellen anzeigen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 sqlite&amp;gt; .tables&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Das Schema der DB anzeigen:&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
(vgl. oben [[DbLog#Datenbanken]] und [[DbLog#Beispiel: Anlegen und Nutzung einer SQLite-Datenbank]])&lt;br /&gt;
&lt;br /&gt;
 sqlite&amp;gt; .schema&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Alle Eintäge anzeigen:&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Die Einträge liegen alle in der Tabelle &amp;quot;History&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ganz wichtig&#039;&#039;&#039; ist immer das &amp;quot;;&amp;quot; am Ende Zeile (bei allen Kommandos, die nicht mit einem &amp;quot;.&amp;quot; anfangen). Wenn es vergessen wurde zeigt die Konsole solange neue Zeilen bis ein &amp;quot;;&amp;quot; eingegeben wird. So kann ein Befehl auch bequem über mehrere Zeilen geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
 sqlite&amp;gt; select * from HISTORY;&lt;br /&gt;
&lt;br /&gt;
Dies kann sehr lange dauern und kann ggf. mit &amp;lt;code&amp;gt;STRG-C&amp;lt;/code&amp;gt; abgebrochen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Alle Einträge eines Geräts anzeigen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;where&amp;lt;/code&amp;gt;-Statements werden Strings in einfache Anführungsstriche gesetzt, Zahlen nicht.&lt;br /&gt;
&lt;br /&gt;
 sqlite&amp;gt; select * from HISTORY where DEVICE=&#039;Pollenflug&#039;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Alle Einträge eines Readings eines Geräts anzeigen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 sqlite&amp;gt; select * from HISTORY where DEVICE=&#039;Pollenflug&#039; and READING=&#039;Graeser&#039;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Alle Einträge eines bestimmten Wertes eines Readings eines Geräts anzeigen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 sqlite&amp;gt; select * from HISTORY where DEVICE=&#039;Pollenflug&#039; and READING=&#039;Graeser&#039; and VALUE&amp;gt;1;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LÖSCHEN aller Einträge eines bestimmten Wertes eines Readings eines Geräts anzeigen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039; Löschen kann nicht rückgängig gemacht werden!! Also IMMER erst die entsprechenden SELECT-Statements solange verfeinern bis wirklich nur die gewünschten Einträge angezeigt werden. Dann das &amp;lt;code&amp;gt;select *&amp;lt;/code&amp;gt; durch &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; ersetzen.&lt;br /&gt;
&lt;br /&gt;
 sqlite&amp;gt; delete from HISTORY where DEVICE=&#039;Pollenflug&#039; and READING=&#039;Graeser&#039; and VALUE&amp;gt;1;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Datenbank reparieren ==&lt;br /&gt;
Es kann immer wieder mal vorkommen, dass Datenbanken Fehler enthalten. Das muss im Alltag garnicht auffallen und auch nicht immer schlimm enden. Wenn man auf der SQL-Konsole aber bspw. eine Meldung &amp;lt;code&amp;gt;Error: database disk image is malformed&amp;lt;/code&amp;gt; erhält, sollte man ein Reparatur vornehmen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Ist ein DbRep-Device definiert, kann eine Reparatur einfach mit dem eingebauten Befehl &#039;&#039;&#039;set &amp;lt;name&amp;gt; repairSQlite&#039;&#039;&#039; ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
=== SQLite-Datenbanken ===&lt;br /&gt;
Die folgenden Schritte beschreiben, wie man eine SQLite-DB reparieren kann (Quelle: [http://techblog.dorogin.com/2011/05/sqliteexception-database-disk-image-is.html]):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;DB öffnen:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo sqlite3 fhem.db&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Integritäts-Check durchführen:&lt;br /&gt;
&amp;lt;pre&amp;gt;sqlite&amp;gt; pragma integrity_check;&amp;lt;/pre&amp;gt;&lt;br /&gt;
Kommt hier ein &amp;quot;ok&amp;quot; ist die DB gesund. Ansonsten erscheint etwas wie&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*** in database main ***&lt;br /&gt;
On tree page 118786 cell 1: Rowid 75 out of order (previous was 816660)&lt;br /&gt;
On tree page 118786 cell 4: Rowid 815704 out of order (previous was 816727)&lt;br /&gt;
Corruption detected in cell 0 on page 118786&lt;br /&gt;
Multiple uses for byte 132 of page 118786&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Datenbank-Dump erstellen (Export gesamten DB in die Datei &amp;quot;dump_all_20160516_1043.sql&amp;quot;) und DB verlassen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sqlite&amp;gt; .mode insert&lt;br /&gt;
sqlite&amp;gt; .output dump_all_20160516_1043.sql&lt;br /&gt;
sqlite&amp;gt; .dump&lt;br /&gt;
sqlite&amp;gt; .exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Neue Datenbank erstellen und den Dump einlesen, Integritäts-Check machen und verlassen:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo sqlite3 fhem-neu.db&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sqlite&amp;gt; .read dump_all_20160516_1043.sql&lt;br /&gt;
sqlite&amp;gt; pragma integrity_check;&lt;br /&gt;
ok&lt;br /&gt;
sqlite&amp;gt; .exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Spätestens jetzt FHEM stoppen:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo service fhem stop&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Alte DB sichern und neue aktivieren:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo mv fhem.db fhem.db.sv_20160516&lt;br /&gt;
sudo mv fhem-neu.db fhem.db&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Kontrollieren, dass die neue DB die gleichen Rechte wie die alte DB hat (und ggf. korrigieren):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
~/fhem$ ls -lha&lt;br /&gt;
insgesamt 6,3G&lt;br /&gt;
drwxr-xr-x 12 fhem root    4,0K Mai 16 11:07 .&lt;br /&gt;
drwxr-xr-x  4 root root    4,0K Dez 25 17:50 ..&lt;br /&gt;
...&lt;br /&gt;
-rw-r--r--  1 root root    1,4G Mai 16 11:04 fhem.db&lt;br /&gt;
-rw-r--r--  1 fhem root    2,6G Mai 16 10:59 fhem.db.sv_20160516&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
~/fhem$ sudo chown fhem:root fhem.db&lt;br /&gt;
&lt;br /&gt;
~/fhem$ ls -lha&lt;br /&gt;
insgesamt 6,3G&lt;br /&gt;
drwxr-xr-x 12 fhem root    4,0K Mai 16 11:07 .&lt;br /&gt;
drwxr-xr-x  4 root root    4,0K Dez 25 17:50 ..&lt;br /&gt;
...&lt;br /&gt;
-rw-r--r--  1 fhem root    1,4G Mai 16 11:04 fhem.db&lt;br /&gt;
-rw-r--r--  1 fhem root    2,6G Mai 16 10:59 fhem.db.sv_20160516&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;FHEM wieder starten (und natürlich kontrollieren):&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo service fhem start&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Hinweise für sehr große Datenbanken ===&lt;br /&gt;
Wenn die SQLite-DB sehr groß wird, kann es sein, dass der oben beschriebene Weg nicht ohne manuelle Anpassungen funktioniert. Konkret war dies bei einem Nutzer für eine 15 GB große DB nicht möglich, der Prozess hat sich immer nach mehreren Stunden aufgehängt. Die Ursache liegt darin, dass ein Dump alle Daten in einer einzigen Transaktion einfügt. Das Problem kann man lösen, indem man den Dump in mehreren Transaktionen einfügt, also aufteilt. Konkret konnte eine 23GB große DB erfolgreich eingelesen und damit repariert werden, indem alle 10.000.000 Zeilen folgende 2 Zeilen eingefügt wurden:&lt;br /&gt;
&amp;lt;pre&amp;gt;BEGIN TRANSACTION;&lt;br /&gt;
COMMIT;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Hinweis 1: Mit dem Editor joe kann man unter Linux auch sehr große Dateien flüssig bearbeiten, das Springen zu hohen Zeilennumer dauert trotzdem. &lt;br /&gt;
* Hinweis 2: joe verwendet eine temporäre Kopie der Datei. Diese liegt per default unter /tmp. Der Ort kann aber auch durch &amp;lt;code&amp;gt;export TEMP=...&amp;lt;/code&amp;gt; geändert werden. Falls also unter /tmp nicht Platz für eine Kopie des Datenbank-Dumps ist, sollte diese Variable vor dem Starten von joe entsprechend gesetzt werden. &lt;br /&gt;
* Hinweis 3: Beim Speichern legt joe im gleichen Verzeichnis eine Sicherungskopie an, d.h. im Verzeichnis des Datenbank-Dumps sollte weiterer Platz in Höhe der Dateigröße frei sein. &lt;br /&gt;
* Hinweis 4: Der reopen Mechanismus von DbLog kann verwendet werden, um eine manuelle Datenbankreparatur ohne Logunterbrechung durchzuführen (vor dem Wieder-Öffnen der DbLog Datei- und Verzeichnisrechte prüfen!). Damit kann man das harte Stoppen und Starten von FHEM in obiger Anleitung umgehen.&lt;br /&gt;
* Letzter Hinweis: Weiter gilt: bei großen DbLog-Datenbanken sollte man immer darüber nachdenken,&lt;br /&gt;
** Welche dieser Logdaten man wirklich braucht und im Zweifel per DbRep ausdünnen&lt;br /&gt;
** Zu einer echten Datenbank wie MySQL/MariaDB zu wechseln.&lt;br /&gt;
&lt;br /&gt;
== Datenbank migrieren ==&lt;br /&gt;
Eine schöne Anleitung zur Migration von SQLite zu MySQL/MariaDB mit Hilfe von [[DbRep - Reporting und Management von DbLog-Datenbankinhalten|DbRep]] findet sich hier: [https://demaya.de/fhem-umzug-sqlite-mysql-mariadb/].&lt;br /&gt;
&lt;br /&gt;
== Nützliche Codeschnipsel ==&lt;br /&gt;
Anbei ein paar nützliche Codeschnipsel rund um DbLog&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Dateigrösse mitloggen ===&lt;br /&gt;
Da die Datenbank ins Unermessliche wachsen kann, empfiehlt es sich - je nach Speicherplatz - ab einer bestimmten Grösse tätig zu werden. Dazu muss diese Grösse allerdings ermittelt werden. Diese geschieht mittels des Userreadings, welches man vorteilshafterweise mit im DbLog-device anlegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;attr myDbLog userReadings DbFileSize:reduceLogState.* { (split(&#039; &#039;,`du -m fhem.db`))[0] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mittels dieses Attributs wird die Grösse der .db-Datei immer nach dem Ausführen des ReduceLog in das Reading &amp;quot;DbFileSize&amp;quot; in ganzzahligen MByte abgelegt.&lt;br /&gt;
&lt;br /&gt;
Basierend auf diesem Reading können dann weitere Aktionen, beispielsweise ein Plot, erstellt werden.&lt;br /&gt;
&lt;br /&gt;
Die oben beschriebene Möglichkeit ist für SQLite verwendbar. Zur Ermittlung der DB-Größe andere DB-Typen (aber auch für SQLite nutzbar) kann wie [[DbRep_-_Reporting_und_Management_von_DbLog-Datenbankinhalten#Gr.C3.B6.C3.9Fe_der_FHEM-Datenbank_ermitteln | hier]] beschrieben vorgegangen werden.&lt;br /&gt;
&lt;br /&gt;
== Performance-Optimierung ==&lt;br /&gt;
Auch eine Datenbank kann mit der Zeit langsamer werden. Dies hängt von mehreren Faktoren ab:&lt;br /&gt;
* Menge der gelogten Daten (zB. &amp;gt; 4-5 GB)&lt;br /&gt;
* Eingesetzte Hardware (zB. langsame SD-Karte vs. schnelle SSD)&lt;br /&gt;
* Eingesetztes Datenbanksystem (zB. SQLite, MySQL)&lt;br /&gt;
* Komplexität der Abfragen (zB. für aufwändige Graphen oder Berechnungen)&lt;br /&gt;
&lt;br /&gt;
Diese Punkte sollen im folgenden diskutiert werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Komplexität der Abfragen ===&lt;br /&gt;
Dies ist kein Problem der Datenbank, sondern rein der Abfrage. Dem entsprechend muss die Optimierung auch in der Abfrage oder im Skript gesucht werden. Dies ist nicht Ziel dieses Abschnittes und wird hier nicht weiter behandelt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Eingesetztes Datenbanksystem ===&lt;br /&gt;
Welches Datenbanksystem eingesetzt wird (zB. SQLite oder MySQL) hat auf die Performance der Datenbank gar keinen so großen Einfluss, wie vielleicht zuerst gedacht. Selbst SQLite kann problemlos Datenbanken mit etlichen GB Größe performant verarbeiten. Der Flaschenhals ist hier viel mehr die darunter liegende Hardware (s.u.).&lt;br /&gt;
&lt;br /&gt;
Die Performance der Datenbank an sich, kann aber durch verschiedene Maßnahmen verbessert werden:&lt;br /&gt;
* Pflegemaßnahmen bzgl. der Daten&lt;br /&gt;
* &#039;&#039;&#039;Erstellung von Indizes&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Menge der Daten und Pflegemaßnahmen bzgl. der Daten ====&lt;br /&gt;
Die Menge der geloggten Daten hat natürlich Einfluss auf die Geschwindigkeit von Abfragen - je mehr Daten vorhanden sind, desto mehr Daten müssen auch durchforstet werden um eine Abfrage zu bedienen. Die Reduzierung der geloggten Datenmenge hat also direkten Einfluss auf die Größe und damit auch die Geschwindigkeit der Datenbank. Die Menge der zu loggenden Daten lässt sich an zwei Stellen einschränken:&lt;br /&gt;
* bei der Definition jedes Devices (s. Kapitel oben)&lt;br /&gt;
* bei der Festlegung des FHEM-weiten Log-Levels (s. [[Loglevel]])&lt;br /&gt;
&lt;br /&gt;
Die Menge der bereits geloggten Daten kann zB. mit Hilfe von [[DbRep - Reporting und Management von DbLog-Datenbankinhalten|DbRep]] verringert und optimiert werden, bspw.&lt;br /&gt;
* löschen unnötiger Daten&lt;br /&gt;
* vacuum der Datenbank&lt;br /&gt;
&lt;br /&gt;
Insgesamt haben diese Maßnahmen aber nur einen eingeschränkten Effekt auf die Performance der DB. Deutlich effektiver ist die Erstellung eines Index (s.u.).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Erstellung von Indizes ====&lt;br /&gt;
Die Erstellung von Indizes hat mit Abstand den größten Einfluss auf die Performance einer Datenbank (auf unveränderter Hardware). Extrem zusammengefasst ist ein Index eine extrem optimiertes Nachschlageverzeichnis für einen bestimmten Typ Daten (ein Index wie im Buch halt). Eine wunderbare Einführung in Indizes bietet [[https://use-the-index-luke.com/de|https://use-the-index-luke.com]].&lt;br /&gt;
&lt;br /&gt;
In FHEM sind Indizes sogar sehr einfach einzurichten da die Datenbank-Nutzung sehr stark vorgegeben ist. Nahezu jede Abfrage folgt dem Schema &#039;&#039;Device -&amp;gt; Reading -&amp;gt; Datum -&amp;gt; Wert&#039;&#039;. Ein Index kann genau diese Abfrage bedienen und beschleunigen. Ein Index nur über die Devices wäre ein erster Schritt, brächte aber noch keinen großen Gewinn (wie um Link oben gut beschrieben). Über die gesamten ersten drei Schritte erstellt (Device -&amp;gt; Reading -&amp;gt; Datum) bringt der Index aber sofort eine deutliche Geschwindigkeitssteigerung.&lt;br /&gt;
&lt;br /&gt;
Die Erstellung eines Index erfolgt direkt in der Datenbank (und nicht aus FHEM heraus), hier am Beispiel einer SQLite-DB:&lt;br /&gt;
&lt;br /&gt;
Öffnen der DB:&lt;br /&gt;
&amp;lt;pre&amp;gt; sudo sqlite3 fhem.db &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Erzeugen des Index auf der DB-Konsole (das Semikolon am Ende ist wichtig):&lt;br /&gt;
&amp;lt;pre&amp;gt; create index idx_device_reading_timestamp on history (device, reading, timestamp); &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verlassen der DB:&lt;br /&gt;
&amp;lt;pre&amp;gt; .exit &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Einzig zu berücksichtigen ist, dass dieser Index die Datenbank um bis zu 1/3 vergrößert. Er kann aber bei Bedarf auch wieder entfernt werden. Bei meiner 15 GB SQLite-Datei (auf einem Mac Mini mit SSD) hat dies ca. 15 min gedauert (den FHEM hatte ich vorsichtshalber währenddessen deaktiviert).&lt;br /&gt;
&lt;br /&gt;
Sollte jemand spezielle Berechnungen oder Skripte ausführen, die nach einem anderen Abfrage-Schema arbeiten, könnte man dafür spezialisierte zusätzliche Indizes erstellen. Das sollte aber dann mit dem Wissen des obigen Links erarbeitet werden, da dann etwas mehr Hintergrundwissen sehr hilfreich ist.&lt;br /&gt;
&lt;br /&gt;
==== DB-Backup ====&lt;br /&gt;
Ein anderer Aspekt, der eigentlich nichts mit der Performance der DB zu tun hat, ist der Einfluss aufs Backup. Wird bspw. ein Systembackup per RSYNC gemacht, muss bei SQLite immer die komplette ggf. riesige Datei gesynct werden - bei MySQL würden nur die veränderten DB-Elemente gesynct. Dies soll hier nicht weiter vertieft werden, sollte aber bei einer Gesamtstrategie bedacht werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Eingesetzte Hardware ===&lt;br /&gt;
FHEM hat grundsätzlich sehr viele kleine Datenzugriffe, unabhängig davon ob FileLog oder DbLog eingesetzt wird. Deshalb ist der absolut größte Performance-Gewinn durch den Einsatz schneller Festplatten zu erreichen - ganz einfache Aussage: &#039;&#039;je schneller desto besser ;-)&#039;&#039;. Konkret bietet eine SSD mit mind. 250MB/s Datenzugriff eine ordentliche Basis für jedes datengestützte System, wie den FHEM.&lt;br /&gt;
&lt;br /&gt;
Wenn die Datenmenge größer und die Abfragen komplexer werden, müssen natürlich irgendwann auch die Prozessorleistung und der Arbeitsspeicher mit wachsen. Aber auch an einem Raspi wird eine SSD deutlich performanter sein, als eine einfache SD-Karte oder eine klassische rotierende Festplatte.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[Heizleistung_und_Gasverbrauch|Beispiel das DbLog-Daten für SVG-Plots verwendet]]&lt;br /&gt;
* [[SVG-Plots von FileLog auf DbLog umstellen]]&lt;br /&gt;
* Manchmal bereitet die Engine von mysql auf einem Raspberry Probleme: [https://forum.fhem.de/index.php/topic,131164.msg1253589.html#msg1253589|Link zum Forum]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Logging]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEM_User_Interface_Painter&amp;diff=37465</id>
		<title>FHEM User Interface Painter</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEM_User_Interface_Painter&amp;diff=37465"/>
		<updated>2022-06-04T05:38:47Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: Hinweis auf FTUI-Version 2 eingefügt, da es mittlerweile eine V3 gibt...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Datei:FUIP_Symbolbild.png|mini|400px|FUIP in Aktion]]&lt;br /&gt;
Der &#039;&#039;&#039;FHEM User Interface Painter (FUIP)&#039;&#039;&#039; ist ein FHEM-Modul, mit dem man [[FHEM Tablet UI]] (FTUI) Seiten graphisch (&amp;quot;klickibunti&amp;quot;) erstellen kann. D.h. man kann sich ein UI zusammenklicken, welches die Tablet UI Technik verwendet, aber ohne sich selbst unbedingt mit HTML und CSS herumschlagen zu müssen.&lt;br /&gt;
Hier ist ein kurzes Video, welches FUIP in Aktion zeigt:&lt;br /&gt;
&lt;br /&gt;
[https://forum.fhem.de/index.php?action=dlattach;topic=85869.0;attach=98455 Einführungsvideo]&lt;br /&gt;
&lt;br /&gt;
(Das Video zeigt nicht unbedingt den neusten Stand, aber es dürfte klar werden, wofür FUIP gut sein soll.)&lt;br /&gt;
&lt;br /&gt;
== Installation und Upgrade in FHEM ==&lt;br /&gt;
Genau wie FTUI ist auch FUIP nicht automatisch Teil von FHEM. Es muss explizit installiert bzw. hinzugefügt werden. Die Installation funktioniert folgendermaßen:&lt;br /&gt;
* FUIP verwendet FTUI (v2.x - es gibt inzwischen auch eine FTUI v3.x). D.h. man sollte zuerst einmal FTUI installieren, falls noch nicht passiert. Wie das geht steht bei [[FHEM Tablet UI#Installation|FHEM Tablet UI]]. Dabei reicht der erste Schritt aus, da lediglich die FTUI-Dateien von FUIP benötigt werden.&lt;br /&gt;
* Dann das FUIP-Repository zum FHEM Update hinzufügen: &lt;br /&gt;
** &amp;lt;code&amp;gt;update add https://raw.githubusercontent.com/ThorstenPferdekaemper/FHEM-FUIP/master/controls_fuip.txt&amp;lt;/code&amp;gt;&lt;br /&gt;
* Jetzt &amp;lt;code&amp;gt;update all fuip&amp;lt;/code&amp;gt; machen.&lt;br /&gt;
* Warten, bis man ganz sicher ist, dass alles installiert ist. Das sieht man normalerweise an der Meldung &amp;lt;code&amp;gt;update finished, &amp;quot;shutdown restart&amp;quot; is needed to activate the changes.&amp;lt;/code&amp;gt;. Das ganze kann etwas länger dauern, da FUIP aus einige Dateien besteht, von denen ein paar etwas größer sind. &lt;br /&gt;
* Jetzt erst &amp;lt;code&amp;gt;shutdown restart&amp;lt;/code&amp;gt;. &lt;br /&gt;
* FUIP sollte jetzt installiert sein.&lt;br /&gt;
&lt;br /&gt;
Zum Upgrade reicht ein &amp;lt;code&amp;gt;update&amp;lt;/code&amp;gt;, wenn man FUIP wie oben beschrieben installiert hat. Will man nur den FUIP-Teil aktualisieren und nicht alles in FHEM, dann geht das mit &amp;lt;code&amp;gt;update all fuip&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Falls es bei oder nach der Installation oder dem Upgrade Probleme gibt (welcher Art auch immer), sollten die folgenden Punkte geprüft werden:&lt;br /&gt;
* Wird das richtige Repository benutzt? Man kann das mit &amp;lt;code&amp;gt;update list&amp;lt;/code&amp;gt; überprüfen. Wenn der Eintrag für fuip nicht genau so aussieht wie oben beschrieben, dann sollte er per &amp;lt;code&amp;gt;update delete&amp;lt;/code&amp;gt; gelöscht werden und dann genau so eingetragen werden wie oben beschrieben. &lt;br /&gt;
* Ist der update-Prozess wirklich komplett durchgelaufen? Auch wenn es etwas länger dauert, muss man auf die Meldung &amp;lt;code&amp;gt;update finished, &amp;quot;shutdown restart&amp;quot; is needed to activate the changes.&amp;lt;/code&amp;gt; warten, bevor man durchstartet. Im Zweifelsfall einfach noch einmal &amp;lt;code&amp;gt;update all fuip&amp;lt;/code&amp;gt; machen und diesmal mehr Geduld haben.&lt;br /&gt;
* FHEM braucht Schreibrechte im Verzeichnis &amp;lt;fhem&amp;gt;/FHEM/lib/FUIP/config (&amp;lt;fhem&amp;gt; steht meistens für /opt/fhem) und allen enthaltenen Dateien. Auf Betriebssystemebene (Linux) kann man das mit &amp;lt;code&amp;gt;ls -ls&amp;lt;/code&amp;gt; überprüfen. Meistens kann es mit folgendem Befehl repariert werden: &amp;lt;code&amp;gt;chown -R fhem:dialout /opt/fhem/FHEM/lib/FUIP/config&amp;lt;/code&amp;gt;. (Dieser Punkt gilt nicht bzw. nicht genau so, wenn man die configDB benutzt.)&lt;br /&gt;
* Steht etwas verdächtiges im Logfile?&lt;br /&gt;
&lt;br /&gt;
== Erste Schritte ==&lt;br /&gt;
Zuerst legt man ein &amp;quot;FUIP Device&amp;quot; an, also etwa &amp;lt;code&amp;gt;define ui FUIP&amp;lt;/code&amp;gt;. Dieses Device meldet sich sozusagen als Webserver bei FHEM an (wie z.B. auch [[HTTPSRV]]), d.h. es erscheint im Menu oben links (über den Räumen) ein Link &amp;quot;ui&amp;quot;. Beim Klick auf diesen Link generiert FUIP eine FTUI Übersichtsseite aus den Räumen im FHEM System. (Das kann ein bisschen dauern, wenn man viele Devices hat.) Nun kann man durch Verschieben und größer/kleiner-Ziehen der einzelnen Zellen bzw. durch Verschieben des Zelleninhalts die Gestaltung ändern. Außerdem kann man über das Zahnrad rechts oben in den Zellen neuen Inhalt hinzufügen, den bestehenden Inhalt ändern und vieles mehr.&lt;br /&gt;
Durch Klicken auf die Räume im Menu der Übersichtsseite werden einzelne Raum-Seiten generiert. Diese kann man ebenfalls entsprechend bearbeiten. Natürlich können auch eigene Seiten hinzugefügt werden. Wie das geht sieht man im Video, welches oben verlinkt ist.&lt;br /&gt;
&lt;br /&gt;
Nachdem man die Seiten entsprechend bearbeitet hat sollte man ein &amp;lt;code&amp;gt;set ui save&amp;lt;/code&amp;gt; machen. Ansonsten gehen die Änderungen beim nächsten FHEM-Neustart verloren. Ein normales &amp;lt;code&amp;gt;save config&amp;lt;/code&amp;gt; reicht nicht aus und ist auch nicht notwendig.&lt;br /&gt;
&lt;br /&gt;
Die folgenden detaillierten Informationen können zum Teil veraltet sein, da FUIP noch weitereintwickelt wird. Es sollten allerdings keine Funktionen verschwinden.&lt;br /&gt;
&lt;br /&gt;
== Das Konfigurations-Popup ==&lt;br /&gt;
=== ...für Zellen ===&lt;br /&gt;
[[Datei:FUIP_KonfigZelle.png|mini|600px]]&lt;br /&gt;
Beim Klick auf das Zahnrad rechts oben in einer Zelle wird der Konfigurations-Dialog für diese Zelle geöffnet. Im Folgenden werden die Funktionen der einzelnen Elemente erklärt.&lt;br /&gt;
;Zur Seiten-Konfiguration: Damit kann man zum Konfig-Dialog für die ganze Seite wechseln. &lt;br /&gt;
;Zellen-Überschrift: Hier wird die Überschrift der Zelle festgelegt. Eine Zelle muss keine Überschrift haben. (Die Zahlen hinter der Überschrift in der Zelle selbst verschwinden, wenn man das Attribut &#039;&#039;locked&#039;&#039; setzt.)&lt;br /&gt;
;Neuer View: Hiermit fügt man einen neuen View, also neuen Inhalt, zu einer Zelle hinzu. Man wählt dann aus, welcher Art View angelegt werden soll und füllt die Details, wie z.B. das zugehörige Device. Der neue View wird an einer freien Stelle (falls möglich) in der Zelle eingefügt. Nach schließen des Konfig-Dialogs kann man den View dann per Drag&amp;amp;Drop geeignet positionieren.&lt;br /&gt;
;Neuer View (Device): Dies dient ebenfalls dazu, neue Views in die Zelle zu packen. Allerdings wählt man nicht die Art des Views aus, sondern die FHEM-Devices, die dargestellt werden sollen. Das System sucht dann jeweils einen geeigneten View aus. Bisher funktioniert das nur sehr eingeschränkt, hat aber den Vorteil, dass man gleich mehrere Devices auswählen kann.&lt;br /&gt;
;Abbrechen: Damit schließt man den Dialog ohne die Änderungen zu übernehmen.&lt;br /&gt;
;Details zum View: Hier klappt man die Details zum View aus und kann diese ändern. Was man damit genau machen kann kommt auf die Art des View an. Per Drag&amp;amp;Drop kann man auch die Reihenfolge der Views im Konfig-Dialog ändern. Das hat allerdings keinen Effekt auf die Positonierung bereits existierender Views in der Zelle. &lt;br /&gt;
;View löschen: Das löscht den View aus der Zelle. Wenn man den View eigentlich nicht löschen, sondern in einer anderen Zelle haben will, dann kann man ihn auch per Drag&amp;amp;Drop in die andere Zelle verschieben. Lässt man einen View in einer anderen Zelle &amp;quot;fallen&amp;quot;, dann wird dieser automatisch der neuen Zelle zugeordnet.&lt;br /&gt;
;Übernehmen: Das schließt den Dialog und übernimmt die Änderungen. Dadurch kann man die Auswirkungen auf dem UI selbst sehen. Um die Änderungen allerdings den nächsten FHEM Neustart überleben zu lassen muss man noch ein &amp;lt;code&amp;gt;set ui save&amp;lt;/code&amp;gt; machen.&lt;br /&gt;
;Auto-Anordnen: Hiermit kann man die einzelnen Views in der Zelle automatisch anordnen. Es kann momentan sein, dass dadurch Änderungen verloren gehen. D.h. dieser Button sollte nur benutzt werden, wenn man seit dem Öffnen des Dialogs keine Änderungen gemacht hat. Außerdem schließt der Button dan Dialog. FUIP ordnet die Views in der Reihenfolge an, in der sie im Konfig-Popup erscheinen. Das zugrunde liegende Layout ist sehr einfach gehalten und kann sich auch noch ändern. Diese Funktion ist vor Allem brauchbar für mehrere gleichartige Views in derselben Zelle, wie z.B. bei Menus. &lt;br /&gt;
;Neue Zelle: Legt eine neue (leere) Zelle auf der aktuellen Seite an. Der Konfig-Dialog wird dabei geschlossen und Änderungen gehen verloren.&lt;br /&gt;
;Zelle kopieren: Kopiert die aktuelle Zelle. Man muss eine Seite angeben, zu der die kopierte Zelle gehören soll. Das entsprechende Feld ist mit der aktuellen Seite vorbelegt. Falls man dies nicht ändert, wird einfach eine Kopie der Zelle auf derselben Seite erzeugt. Ansonsten wird die Zelle auf die angegebene Seite kopiert. Die Funktion schließt den Konfig-Dialog und Änderungen gehen verloren. Falls man eine andere Seite angegeben hat, wird zu dieser gewechselt.&lt;br /&gt;
;Zelle exportieren: Dies erlaubt die Definition der Zelle herunterzuladen und auf dem Client (also dem Rechner, auf dem der Browser läuft) zu speichern.&lt;br /&gt;
;Zelle importieren: Damit lädt man eine exportierte Zelle wieder hoch. FUIP erzeugt dann auf der aktuellen Seite eine neue Zelle mit dem entsprechenden Inhalt. Das funktioniert auch mit Zellen, die von einer anderen FUIP-Seite, einem anderen FUIP-Device oder von einer anderen FHEM-Installation kommen.&lt;br /&gt;
;Zelle löschen: Damit löscht man die aktuelle Zelle. Sie verschwindet dann von der aktuellen Seite.&lt;br /&gt;
;Toggle editOnly: Bei manchen Views ist es schwierig, sie mit der Maus &amp;quot;anzufassen&amp;quot;, da sie sofort eine Aktion auslösen (z.B. bei Links). Mit &amp;quot;Toggle editOnly&amp;quot; wird eine graue &amp;quot;Schicht&amp;quot; über die Views gelegt. Dadurch weiß man besser, wo man den View anfassen kann und Mausklicks haben keine Wirkung mehr, außer Drag&amp;amp;Drop.&lt;br /&gt;
&lt;br /&gt;
=== ...für Seiten ===&lt;br /&gt;
[[Datei:FUIP_SeitenKonfig.png|mini|600px]]&lt;br /&gt;
Drückt man im Konfig-Dialog für Zellen auf &amp;quot;Cell/Page&amp;quot; kommt man auf den Konfig-Dialog für ganze Seiten. Die Bedeutung der Einzelnen Elemente ist wie folgt.&lt;br /&gt;
;Zur Zellen-Konfiguration:Das bringt einen zurück zum Konfig-Dialog für Zellen.&lt;br /&gt;
;Seiten-Überschrift:Hier kann ein Titel für die Seite eingetragen werden. Das erscheint dann je nach Browser irgendwo oben. (Technisch ist es der Inhalt des &amp;lt;title&amp;gt; Tags in &amp;lt;head&amp;gt;.)&lt;br /&gt;
;Abbrechen:Damit schließt man den Dialog ohne die Änderungen zu übernehmen.&lt;br /&gt;
;Übernehmen: Das schließt den Dialog und übernimmt die Änderungen. Dadurch kann man die Auswirkungen auf dem UI selbst sehen. Um die Änderungen allerdings den nächsten FHEM Neustart überleben zu lassen muss man noch ein &amp;lt;code&amp;gt;set ui save&amp;lt;/code&amp;gt; machen.&lt;br /&gt;
;Seite kopieren:Dadurch wird eine neue Seite angelegt, die so aussieht wie die aktuelle. Der Dialog wird dann geschlossen und automatisch zur neuen Seite gesprungen.&lt;br /&gt;
;Seite exportieren:Das ist dasselbe wie für Zellen, nur für die ganze aktuelle Seite.&lt;br /&gt;
;Seite importieren:Das ist im Prinzip auch wie für Zellen, nur dass eine neue Seite angelegt wird. Exportierte Zellen können nur als Zellen importiert werden und exportierte Seiten nur als Seiten.&lt;br /&gt;
&lt;br /&gt;
== Das FUIP-Device ==&lt;br /&gt;
Wie in [[#Erste Schritte|Erste Schritte]] bereits beschrieben, muss man zur Verwendung von FUIP zuerst ein FUIP-Device anlegen. Alles, was man mit FUIP macht (bzw. was das System macht) passiert in Bezug auf ein FUIP-Device. Man kann auch jederzeit mehrere FUIP-Devices anlegen. Verschiedene Instanzen von FUIP stören sich nicht gegenseitig, man kann aber (z.B. in einem Menu) auf eine andere FUIP-Instanz verweisen (verlinken).&lt;br /&gt;
&lt;br /&gt;
Das FUIP-Device hat die folgenden Eigenschaften.&lt;br /&gt;
=== Sets ===&lt;br /&gt;
Die folgenden set-Kommandos sind für den Benutzer gedacht. Es gibt noch weitere set-Kommandos, welche aber vor Allem für FUIP-interne Zwecke gedacht sind. &lt;br /&gt;
;save: Mit &amp;lt;code&amp;gt;set &amp;lt;name&amp;gt; save&amp;lt;/code&amp;gt; wird der momentane Zustand der FUIP-Seiten zu diesem FUIP-Device gespeichert. Das betrifft nicht die Definition des FUIP-Device selbst (also auch nicht dessen Attribute). Diese müssen nach wie vor über &amp;lt;code&amp;gt;save&amp;lt;/code&amp;gt; (also &amp;quot;Save config&amp;quot;) gespeichert werden. Die FUIP-Seiten stehen in der Datei &amp;lt;fhem&amp;gt;/FHEM/lib/FUIP/config/FUIP_&amp;lt;name&amp;gt;.cfg. Dabei steht &amp;lt;fhem&amp;gt; in der Regel für /opt/fhem und &amp;lt;name&amp;gt; für den Namen des FUIP-Devices. Ohne ein &amp;lt;code&amp;gt;set &amp;lt;name&amp;gt; save&amp;lt;/code&amp;gt; gehen alle Änderungen beim nächsten FHEM Restart verloren. &lt;br /&gt;
;load: Mit &amp;lt;code&amp;gt;set &amp;lt;name&amp;gt; load&amp;lt;/code&amp;gt; stellt man den Zustand wieder her, der mit &amp;lt;code&amp;gt;set &amp;lt;name&amp;gt; save&amp;lt;/code&amp;gt; gespeichert wurde. Das ist vor Allem dann nützlich, wenn man sich beim Bearbeiten der Seiten vertan hat. Ansonsten wird beim FHEM Start das &amp;quot;load&amp;quot; automatisch ausgeführt.  &lt;br /&gt;
;pagedelete: Mit &amp;lt;code&amp;gt;set &amp;lt;name&amp;gt; pagedelete &amp;lt;page&amp;gt;&amp;lt;/code&amp;gt; wird die Seite &amp;lt;page&amp;gt; gelöscht. Das kann auch dazu genutzt werden, FUIP zum Neugenerieren einer Seite zu &amp;quot;zwingen&amp;quot;, indem man die Seite nach dem Löschen einfach wieder aufruft. Auch das Löschen einer Seite geht ohne ein &amp;quot;save&amp;quot; verloren, d.h. die Seite ist dann nach einem FHEM Neustart wieder da. &lt;br /&gt;
;refreshBuffer: FUIP verwendet Informationen aus dem &amp;quot;eigentlichen&amp;quot; FHEM, wie z.B. die Liste aller Devices sowie bestimmte Readings, Internals und Attribute. Insbesondere bei &amp;quot;entferntem&amp;quot; FUIP, also bei Verwendung des Attributs &#039;&#039;fhemwebUrl&#039;&#039;, kann die Ermittlung dieser Daten länger dauern. Daher wird praktisch alles durch FUIP zwischengespeichert (&amp;quot;gepuffert&amp;quot;). Wenn man nun neue Devices anlegt bzw. bestehende Devices ändert, dann bekommt das FUIP-Device davon unter Umständen nichts mit. In so einem Fall kann man mit &amp;lt;code&amp;gt;set &amp;lt;name&amp;gt; refreshBuffer&amp;lt;/code&amp;gt; den Zwischenspeicher löschen, um FUIP dazu zu zwingen, die Informationen erneut zu ermitteln.&lt;br /&gt;
&lt;br /&gt;
=== Gets ===&lt;br /&gt;
Alle Get-Kommandos sind nur für FUIP-interne Zwecke bestimmt.&lt;br /&gt;
&lt;br /&gt;
=== Internals ===&lt;br /&gt;
;editOnly: Hier wird der &amp;quot;editOnly-Modus&amp;quot; gespeichert, der auf der Konfig-Oberfläche ein- und ausgeschaltet werden kann. Siehe auch [[#Das Konfigurations-Popup|Das Konfigurations-Popup]].&lt;br /&gt;
&lt;br /&gt;
=== Readings ===&lt;br /&gt;
FUIP-Devices haben keine Readings.&lt;br /&gt;
&lt;br /&gt;
=== Attribute ===&lt;br /&gt;
;baseHeight: Basishöhe einer Zelle, d.h. eine 1x1-Zelle ist &#039;&#039;baseHeight&#039;&#039; Pixel hoch. Standardwert ist 108.&lt;br /&gt;
;baseWidth: Basisbreite einer Zelle, d.h. eine 1x1-Zelle ist &#039;&#039;baseWidth&#039;&#039; Pixel breit. Standardwert ist 142. Diese Abmessungen beziehen sich nur auf die Zelle selbst, nicht auf den Zwischenraum zwischen zwei Zellen. Der Zwischenraum beträgt (horizontal und vertikal) 10 Pixel.&lt;br /&gt;
;pageWidth: Seitenbreite in Pixel. Wenn &#039;&#039;pageWidth&#039;&#039; nicht gesetzt ist (das ist der Default), dann wird die Seitenbreite nicht festgelegt. Sie ergibt sich dann aus &#039;&#039;baseWidth&#039;&#039; (d.h. die Breite einer 1er-Zelle) und der Anzahl der verwendeten Spalten plus die Breite der Zwischenräume. D.h. in der Regel muss man &#039;&#039;pageWidth&#039;&#039; nicht angeben.&lt;br /&gt;
:Die Angabe in &#039;&#039;pageWidth&#039;&#039; beeinflusst auch die Darstellung des Hintergrundbilds, falls das Attribut &#039;&#039;styleBackgroundImage&#039;&#039; gesetzt ist. Siehe &#039;&#039;styleBackgroundImage&#039;&#039; für Details.&lt;br /&gt;
;fhemwebUrl: Mit FUIP kann man sich auch an ein &amp;quot;entferntes&amp;quot; FHEM ankoppeln. Das Attribut &#039;&#039;fhemwebUrl&#039;&#039; hat dabei in etwa die Bedeutung wie &#039;&#039;fhemweb_url&#039;&#039; bei FTUI. (Siehe auch hier: [[FHEM Tablet UI#Verbindung zu FHEM|Verbindung zu FHEM (FTUI)]].) Genau wie beim &amp;quot;normalen&amp;quot; FTUI muss das Attribut &#039;&#039;CORS&#039;&#039; der FHEMWEB-Instanz des Ziels auf &amp;quot;1&amp;quot; stehen. Ansonsten würde schon FTUI nicht funktionieren. Außerdem darf die FHEMWEB-Instanz keine Passwort-Prüfung haben. Stattdessen kann man mit dem Attribut &#039;&#039;allowedfrom&#039;&#039; oder einer allowed-Instanz den Zugriff einschränken. &lt;br /&gt;
:Man darf &#039;&#039;fhemwebUrl&#039;&#039; auf keinen Fall setzen (auch nicht auf 127.0.0.1 oder so), wenn sich die FUIP-Instanz auf das lokale FHEM beziehen soll. In dem Fall würde FHEM ewig auf sich selbst warten.&lt;br /&gt;
:Wenn man ein &amp;quot;entferntes&amp;quot; FHEM benutzt, dann können einige Funktionen der Konfigurationsoberfläche etwas Zeit brauchen. Zum Beispiel müssen für die Eingabehilfe für Devices alle Devices aus dem entfernten FHEM gelesen werden. Das ist so implementiert, dass das entfernte FHEM möglichst wenig belastet wird, was aber zu Lasten des FUIP-FHEM geht. Siehe auch das Set-Kommando &#039;&#039;refreshBuffer&#039;&#039; zu diesem Thema.&lt;br /&gt;
;locked: Wenn &#039;&#039;locked&#039;&#039; auf &amp;quot;1&amp;quot; gesetzt wird, dann sind die FUIP-Seiten gegen Bearbeitung gesperrt. Das Zahnrad-Icon oben rechts erscheint dann nicht mehr. Dadurch kann ein reiner &amp;quot;Tablet-UI Benutzer&amp;quot; die Seiten nicht mehr ändern und die Oberfläche sieht komplett wie normalerweise bei FTUI aus. Zusätzlich verschwinden auch die Zellennummern rechts neben den Zellenüberschriften und Zellen ohne Überschrift haben dann auch keinen &amp;quot;Titelbalken&amp;quot; mehr.&lt;br /&gt;
;styleBackgroundImage: Dateiname des Hintergrundbilds. Die Bilddatei muss sich im Verzeichnis &amp;lt;fhem&amp;gt;/FHEM/lib/FUIP/images befinden. (&amp;lt;fhem&amp;gt; steht meistens für /opt/fhem) Unterstützt werden jpg- und png- Dateien. Nachdem eine neue Datei hochgeladen wurde, muss man im Browser (in FHEMWEB) die Seite einmal auffrischen (neu laden), um die neue Datei verwenden zu können.   &lt;br /&gt;
:Falls das Attribut &#039;&#039;pageWidth&#039;&#039; gesetzt ist, dann wird die Breite des Hintergrundbilds auf die angegebene Größe gesetzt. Ansonsten (ohne &#039;&#039;pageWidth&#039;&#039;) nimmt das Bild die Breite des Browser-Fensters ein. Die Höhe des Bilds wird entsprechend skaliert, man muss sich also selbst darum kümmern, dass das Bild ein passendes Seitenverhältnis hat.&lt;br /&gt;
:Bei Verwendung eines Hintergrundbilds werden die Zellenhintergründe automatisch auf halbtransparent gesetzt, so dass das Bild durchscheint. &lt;br /&gt;
;styleColor: Standard-Textfarbe (Vordergrundfarbe) für alle Views. Der Defaultwert ist #808080, also ein helles Grau. Man kann die Farbe nicht für alle FTUI-Widgets festlegen. D.h. &#039;&#039;styleColor&#039;&#039; funktioniert nicht unbedingt überall.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* {{Link2Forum|Topic=85869|LinkText=Foren-Thread zur Geburt von FUIP}}&lt;br /&gt;
* [https://www.youtube.com/watch?v=9DPrMOvZ1wo Youtube-Webinar von Thorsten]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Frontends]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-LC-Sw4-SM_4fach_Schaltaktor_Aufputz&amp;diff=37289</id>
		<title>HM-LC-Sw4-SM 4fach Schaltaktor Aufputz</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-LC-Sw4-SM_4fach_Schaltaktor_Aufputz&amp;diff=37289"/>
		<updated>2022-03-11T17:21:44Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: Link zum Manual angepasst&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Features ==&lt;br /&gt;
* Funkfrequenz 868,3 MHz&lt;br /&gt;
* Typ. Freifeldreichweite: 300 m&lt;br /&gt;
* Spannungsversorgung: 230 V / 50 Hz&lt;br /&gt;
* Standby-Verbrauch: 0,5 W &lt;br /&gt;
* Schutzart: IP65&lt;br /&gt;
* Schutzklasse: II&lt;br /&gt;
* Gehäuse: PC, lichtgrau&lt;br /&gt;
* Relais: 4 Wechsler (potentialfreie Kontakte)&lt;br /&gt;
* Schaltvermögen: 16 A (ohmsche Last)&lt;br /&gt;
* Abm. (B x H x T): 171 x 55 x 121 mm&lt;br /&gt;
&lt;br /&gt;
== Hinweise zum Betrieb mit FHEM ==&lt;br /&gt;
&lt;br /&gt;
Das Pairing sollte wie unter HomeMatic Devices pairen beschrieben durchgeführt werden.&lt;br /&gt;
Das Gerät und seine 4 Kanäle werden vom Autodetect einwandfrei erkannt und initialisiert.&lt;br /&gt;
&lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
Bisher keine. &lt;br /&gt;
&lt;br /&gt;
== FHEM Config-Auszug ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt; folgt &amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Event-Monitor ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt; folgt &amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parameter-Liste ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt; folgt &amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== FHEM Log-Auszug  ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt; folgt &amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
https://www.eq-3.com/downloads/download/homematic/bda/hm-lc-sw4-sm-2_um_ge_eq-3_web.pdf&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Schalter (Empfänger)‏‎]]&lt;br /&gt;
[[Kategorie:868MHz]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DbRep_-_Reporting_und_Management_von_DbLog-Datenbankinhalten&amp;diff=34519</id>
		<title>DbRep - Reporting und Management von DbLog-Datenbankinhalten</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DbRep_-_Reporting_und_Management_von_DbLog-Datenbankinhalten&amp;diff=34519"/>
		<updated>2021-01-01T19:11:46Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: Perl-Modul Time::HiRes bei Voraussetzungen doppelt vorhanden&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Reporting und Management von DbLog-Datenbankinhalten&lt;br /&gt;
|ModType=h&lt;br /&gt;
|ModCmdRef=DbRep&lt;br /&gt;
|ModForumArea=Sonstiges&lt;br /&gt;
|ModTechName=93_DbRep.pm&lt;br /&gt;
|ModOwner=DS_Starter ({{Link2FU|16933|Forum}}/[[Benutzer Diskussion:DS Starter|Wiki]])}}&lt;br /&gt;
&lt;br /&gt;
== Zweck und Einsatz des Moduls ==&lt;br /&gt;
Zweck des Moduls ist es, den Inhalt von [[DbLog]]-Datenbanken nach bestimmten Kriterien zu durchsuchen, zu managen, das Ergebnis hinsichtlich verschiedener Aggregationen auszuwerten und als Readings darzustellen. Die Abgrenzung der zu berücksichtigenden Datenbankinhalte erfolgt durch die Angabe von Device, Reading und die Zeitgrenzen für Auswertungsbeginn bzw. Auswertungsende.&lt;br /&gt;
&lt;br /&gt;
Alle Datenbankoperationen werden nichtblockierend ausgeführt. Die Ausführungszeit der (SQL)-Hintergrundoperationen kann optional ebenfalls als Reading bereitgestellt werden (siehe Attribute).&lt;br /&gt;
Alle vorhandenen Readings werden vor einer neuen Operation gelöscht. Durch das Attribut &amp;quot;readingPreventFromDel&amp;quot; kann eine Komma separierte Liste von Readings angegeben werden die nicht gelöscht werden sollen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Zur Zeit ist das Modul durch folgende Leistungsmerkmale gekennzeichnet:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Selektion und Anzeige aller Datensätze innerhalb einstellbarer Zeitgrenzen.&lt;br /&gt;
* Darstellung der Datensätze einer Device/Reading-Kombination innerhalb einstellbarer Zeitgrenzen.&lt;br /&gt;
* Selektion der Datensätze unter Verwendung von dynamisch berechneter Zeitgrenzen zum Ausführungszeitpunkt.&lt;br /&gt;
* Dubletten-Hervorhebung bei Datensatzanzeige (fetchrows) &lt;br /&gt;
* Berechnung der Anzahl von Datensätzen einer Device/Reading-Kombination unter Berücksichtigung von Zeitgrenzen und verschiedenen Aggregationen.&lt;br /&gt;
* Die Berechnung von Summen-, Differenz-, Maximum-, Minimum- und Durchschnittswerten numerischer Readings in Zeitgrenzen und verschiedenen Aggregationen.&lt;br /&gt;
* Speichern von Summen-, Differenz- , Maximum- , Minimum- und Durchschnittswertberechnungen in der Datenbank&lt;br /&gt;
* Löschung von Datensätzen. Die Eingrenzung der Löschung kann durch Device und/oder Reading sowie fixer oder dynamisch berechneter Zeitgrenzen zum Ausführungszeitpunkt erfolgen.&lt;br /&gt;
* Export von Datensätzen in ein File im CSV-Format. &lt;br /&gt;
* Import von Datensätzen aus File im CSV-Format.&lt;br /&gt;
* Umbenennen von Device/Readings in Datenbanksätzen &lt;br /&gt;
* Änderung von gespeicherten Reading-Werten (VALUES) in der Datenbank (changeValue)  &lt;br /&gt;
* automatisches Umbenennen (Autorename) von Device-Namen in Datenbanksätzen und DbRep-Definitionen nach FHEM &amp;quot;rename&amp;quot; Befehl (siehe [[#DbRep_Agent_-_automatisches_.C3.84ndern_von_Device-Namen_in_Datenbanken_und_DbRep-Definitionen_nach_FHEM_.22rename.22 | DbRep-Agent]]) &lt;br /&gt;
* Ausführen von beliebigen benutzerspezifischen SQL-Kommandos &lt;br /&gt;
* Backups der FHEM-Datenbank im laufenden Betrieb erstellen (MySQL, SQLite) mit/ohne Komprimierung der Dumpfiles&lt;br /&gt;
* senden und versionieren Dumpfiles nach dem Backup an einen FTP-Server&lt;br /&gt;
* Restore von SQLite-Dumps und MySQL serverSide-Backups &lt;br /&gt;
* Optimierung der angeschlossenen Datenbank (optimizeTables, vacuum) &lt;br /&gt;
* Ausgabe der existierenden Datenbankprozesse (MySQL) &lt;br /&gt;
* leeren der current-Tabelle&lt;br /&gt;
* Auffüllen der current-Tabelle mit einem (einstellbaren) Extrakt der history-Tabelle&lt;br /&gt;
* Bereinigung sequentiell aufeinander folgender Datensätze (sequentielle Dublettenbereinigung) &lt;br /&gt;
* Reparatur einer korrupten SQLite Datenbank (&amp;quot;database disk image is malformed&amp;quot;)&lt;br /&gt;
* Übertragung von Datensätzen aus der Quelldatenbank in eine andere (Standby) Datenbank (syncStandby)&lt;br /&gt;
* Reduktion der Anzahl von Datensätzen in der Datenbank (reduceLog)&lt;br /&gt;
* Löschen von doppelten Datensätzen (delDoublets)&lt;br /&gt;
* Löschen und (Wieder)anlegen der für DbLog und DbRep benötigten Indizes (index) &lt;br /&gt;
&lt;br /&gt;
Zur Aktivierung der Funktion &amp;quot;Autorename&amp;quot; wird dem definierten DbRep-Device mit dem Attribut &amp;quot;role&amp;quot; die Rolle &amp;quot;Agent&amp;quot; zugewiesen. Die Standardrolle nach Definition ist &amp;quot;Client&amp;quot;. Mehr ist dazu im Abschnitt [[#DbRep_Agent_-_automatisches_.C3.84ndern_von_Device-Namen_in_Datenbanken_und_DbRep-Definitionen_nach_FHEM_.22rename.22 | DbRep-Agent]] beschrieben. &lt;br /&gt;
&lt;br /&gt;
DbRep stellt dem Nutzer einen UserExit zur Verfügung. Über diese Schnittstelle kann der Nutzer in Abhängigkeit von frei definierbaren Reading/Value-Kombinationen (Regex) eigenen Code zur Ausführung bringen. Diese Schnittstelle arbeitet unabhängig von einer Eventgenerierung. Weitere Informationen dazu ist unter [[#Attribute | Attribut]] &amp;quot;userExitFn&amp;quot; beschrieben.&lt;br /&gt;
&lt;br /&gt;
FHEM-Forum:&lt;br /&gt;
{{Link2Forum|Topic=53584|Message=452567|LinkText=Modul 93_DbRep - Reporting und Management von Datenbankinhalten (DbLog)}}&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen und Abgrenzungen ==&lt;br /&gt;
Das Modul setzt den Einsatz einer oder mehrerer DBLog-Instanzen voraus (bisher getestet mit PostgreSQL, MySQL und SQLite). Es werden die Zugangsdaten dieser Datenbankdefinition aus der Konfiguration des entsprechenden DbLog-Device genutzt.&lt;br /&gt;
Es werden nur Inhalte der Tabelle &amp;quot;history&amp;quot; berücksichtigt (Ausnahme Kommando &amp;quot;sqlCmd&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Überblick, welche anderen Perl-Module DbRep verwendet:&lt;br /&gt;
&lt;br /&gt;
::POSIX&lt;br /&gt;
::Time::HiRes&lt;br /&gt;
::Time::Local&lt;br /&gt;
::Scalar::Util&lt;br /&gt;
::DBI&lt;br /&gt;
::Blocking (FHEM-Modul)&lt;br /&gt;
::Encode&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 define &amp;lt;name&amp;gt; DbRep &amp;lt;Name der DbLog-instanz&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(*) &#039;&#039;&#039;&amp;lt;Name der DbLog-Instanz&amp;gt;:&#039;&#039;&#039; Es wird der Name der auszuwertenden DbLog-Datenbankdefinition angegeben, &#039;&#039;&#039;NICHT&#039;&#039;&#039; die Datenbank selbst.&lt;br /&gt;
&lt;br /&gt;
Aus Performancegründen sollte der Index &amp;quot;Report_Idx&amp;quot; in der Datenbank (Tabelle history) angelegt sein. Ab der DbRep-Version 8.20.0 kann dieser Index, sowie die für DbLog benötigten Indizes, verwaltet werden.&lt;br /&gt;
Der Index &amp;quot;Report_Idx&amp;quot; wird einfach mit dem DbRep-Befehl:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 set &amp;lt;name&amp;gt; index recreate_Report_Idx &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
auf der Datenbank angelegt. Ist er bereits vorhanden, wird er gelöscht und erneut angelegt.&lt;br /&gt;
&lt;br /&gt;
== Set ==&lt;br /&gt;
Siehe {{Link2CmdRef|Lang=de|Anker=DbRepset}}&lt;br /&gt;
&lt;br /&gt;
== Get ==&lt;br /&gt;
Siehe {{Link2CmdRef|Lang=de|Anker=DbRepget}}&lt;br /&gt;
&lt;br /&gt;
== Attribute ==  &lt;br /&gt;
Siehe {{Link2CmdRef|Lang=de|Anker=DbRepattr}}&lt;br /&gt;
&lt;br /&gt;
== Readings ==&lt;br /&gt;
Siehe {{Link2CmdRef|Lang=de|Anker=DbRepreadings}}&lt;br /&gt;
&lt;br /&gt;
== DbRep Agent - automatisches Ändern von Device-Namen in Datenbanken und DbRep-Definitionen nach FHEM &amp;quot;rename&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &amp;quot;role&amp;quot; wird die Rolle des DbRep-Device festgelegt. Die Standardrolle ist &amp;quot;Client&amp;quot;. Mit der Änderung der Rolle in &amp;quot;Agent&amp;quot; wird das Device veranlasst auf Umbenennungen von Geräten in der FHEM Installation zu reagieren.&lt;br /&gt;
&lt;br /&gt;
Durch den DbRep-Agenten werden folgende Features aktiviert wenn ein Gerät in FHEM mit &amp;quot;rename&amp;quot; umbenannt wird: &lt;br /&gt;
&lt;br /&gt;
*  in der dem DbRep-Agenten zugeordneten Datenbank (Internal Database) wird nach Datensätzen mit dem alten Gerätenamen gesucht und dieser Gerätename in allen betroffenen Datensätzen in den neuen Namen geändert.&lt;br /&gt;
&lt;br /&gt;
* in dem DbRep-Agenten zugeordneten DbLog-Device wird in der Definition das alte durch das umbenannte Device ersetzt. Dadurch erfolgt ein weiteres Logging des umbenannten Device in der Datenbank. &lt;br /&gt;
&lt;br /&gt;
* in den existierenden DbRep-Definitionen vom Typ &amp;quot;Client&amp;quot; wird ein evtl. gesetztes Attribut &amp;quot;device = alter Devicename&amp;quot; in &amp;quot;device = neuer Devicename&amp;quot; geändert. Dadurch werden Auswertungsdefinitionen bei Geräteumbenennungen automatisch konsistent gehalten. &lt;br /&gt;
&lt;br /&gt;
Mit der Änderung in einen Agenten sind folgende Restriktionen verbunden, die mit dem Setzen des Attributes &amp;quot;role = Agent&amp;quot; eingeschaltet und geprüft werden: &lt;br /&gt;
&lt;br /&gt;
*  es kann nur einen Agenten pro Datenbank in der FHEM-Installation geben. Ist mehr als eine Datenbank mit DbLog definiert, können ebenso viele DbRep-Agenten eingerichtet werden&lt;br /&gt;
&lt;br /&gt;
* mit der Umwandlung in einen Agenten wird nur noch das Set-Komando &amp;quot;renameDevice&amp;quot; verfügbar sein sowie nur ein eingeschränkter Satz von DbRep-spezifischen Attributen zugelassen. Wird ein DbRep-Device vom bisherigen Typ &amp;quot;Client&amp;quot; in einen Agenten geändert, werden evtl. gesetzte und nun nicht mehr zugelassene Attribute glöscht. &lt;br /&gt;
&lt;br /&gt;
Die Aktivitäten wie Datenbankänderungen bzw. Änderungen an anderen DbRep-Definitionen werden im Logfile mit verbose=3 protokolliert. Damit die renameDevice-Funktion bei großen Datenbanken nicht in ein timeout läuft, sollte das Attribut &amp;quot;timeout&amp;quot; entsprechend dimensioniert werden. Wie alle Datenbankoperationen des Moduls wird auch das Autorename nonblocking ausgeführt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel&#039;&#039;&#039; für die Definition eines DbRep-Device als Agent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Agent DbRep LogDB&lt;br /&gt;
attr Rep.Agent devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Agent icon security&lt;br /&gt;
attr Rep.Agent role Agent&lt;br /&gt;
attr Rep.Agent room DbLog&lt;br /&gt;
attr Rep.Agent showproctime 1&lt;br /&gt;
attr Rep.Agent stateFormat { ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;state&amp;quot;, undef) eq &amp;quot;running&amp;quot; ? &amp;quot;renaming&amp;quot; : ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;state&amp;quot;, undef). &amp;quot; » ProcTime: &amp;quot;.ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;sql_processing_time&amp;quot;, undef).&amp;quot; sec&amp;quot;}&lt;br /&gt;
attr Rep.Agent timeout 86400&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== hilfreiche SQL Statements ==&lt;br /&gt;
&lt;br /&gt;
In dieser Rubrik werden SQL-Statements zusammengetragen, die User für ihre Auswertungen hilfreich fanden und anderen Anwendern zur Verfügung stellen.&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird MySQL auch stellvertretend für MariaDB verwendet.&lt;br /&gt;
&lt;br /&gt;
Die Statements können mit dem Befehl:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;DbRep&amp;gt; sqlCmd &amp;lt;SQL-Statement&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ausgeführt werden. Für die Anpassung der Ergebnisdarstellung ist das Attribut &#039;&#039;&#039;sqlResultFormat&#039;&#039;&#039; verfügbar.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis: &amp;lt;br&amp;gt; &#039;&#039;&#039;&lt;br /&gt;
Die Statements sind durch den DbRep-Modulautor nicht in jedem Fall getestet und dem Anwender obliegt vor Anwendung der Statements eine Datenbanksicherung durchzuführen um im Fehlerfall diese wieder herstellen zu können.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Den ersten und den letzten Wert eines Zeitraums selektieren bzw. deren Differenz (MySQL) ===&lt;br /&gt;
Beispiel 1:&lt;br /&gt;
&lt;br /&gt;
Den ersten und letzten Wert der durch die DB-Variablen bestimmten Parameter ausgegeben. &lt;br /&gt;
&lt;br /&gt;
Verwendete DB-Variablen (@) : begin_time, end_time, device und reading&lt;br /&gt;
 SET @begin_time=&#039;2020-06-02 12:30:00&#039;;SET @end_time=&#039;2020-06-02 18:00:00&#039;;&lt;br /&gt;
 SET @device=&#039;shelly02&#039;;SET @reading=&#039;energy_0&#039;;&lt;br /&gt;
 &lt;br /&gt;
 SELECT TIMESTAMP,READING,round(VALUE/1000,0) AS VALUE&lt;br /&gt;
    FROM (&lt;br /&gt;
      (SELECT TIMESTAMP,READING,VALUE FROM history WHERE DEVICE = @device AND READING = @reading AND TIMESTAMP &amp;gt;= @begin_time and TIMESTAMP &amp;lt;= @end_time ORDER BY TIMESTAMP LIMIT 1)&lt;br /&gt;
      UNION ALL &lt;br /&gt;
      (SELECT TIMESTAMP,READING,VALUE FROM history WHERE DEVICE = @device AND READING = @reading AND TIMESTAMP &amp;gt;= @begin_time and TIMESTAMP &amp;lt;= @end_time ORDER BY TIMESTAMP DESC LIMIT 1)&lt;br /&gt;
   ) AS X1;&lt;br /&gt;
 &lt;br /&gt;
 +---------------------+----------+-------+&lt;br /&gt;
 | TIMESTAMP           | READING  | VALUE |&lt;br /&gt;
 +---------------------+----------+-------+&lt;br /&gt;
 | 2020-06-02 12:31:01 | energy_0 |    69 |&lt;br /&gt;
 | 2020-06-02 16:31:05 | energy_0 |    73 |&lt;br /&gt;
 +---------------------+----------+-------+&lt;br /&gt;
Beispiel 2:&lt;br /&gt;
&lt;br /&gt;
Berechnung der Differenz vom 1. Beispiel&lt;br /&gt;
&lt;br /&gt;
Verwendete DB-Variablen (@) : begin_time, end_time, device und reading&lt;br /&gt;
&lt;br /&gt;
Hierbei ist zu beachten, dass die einzelnen Selects vertauscht wurden um den TIMESTAMP des ersten Select zu bekommen.&lt;br /&gt;
&lt;br /&gt;
Die Subtraktion wurde durch &amp;quot;mal Minus Eins&amp;quot; des kleineren Wertes erreicht.&amp;lt;pre&amp;gt;&lt;br /&gt;
SET @begin_time=&#039;2020-06-02 12:30:00&#039;;SET @end_time=&#039;2020-06-02 18:00:00&#039;;&lt;br /&gt;
SET @device=&#039;shelly02&#039;;SET @reading=&#039;energy_0&#039;;&lt;br /&gt;
&lt;br /&gt;
SELECT TIMESTAMP,READING,round(sum(VALUE)/1000,0) AS VALUE&lt;br /&gt;
   FROM (&lt;br /&gt;
     (SELECT TIMESTAMP,READING,VALUE FROM history WHERE DEVICE = @device AND READING = @reading AND TIMESTAMP &amp;gt;= @begin_time and TIMESTAMP &amp;lt;= @end_time ORDER BY TIMESTAMP DESC LIMIT 1)&lt;br /&gt;
     UNION ALL &lt;br /&gt;
     (SELECT TIMESTAMP,READING,(VALUE * -1) AS VALUE FROM history WHERE DEVICE = @device  AND  READING = @reading AND TIMESTAMP &amp;gt;= @begin_time and TIMESTAMP &amp;lt;= @end_time ORDER BY TIMESTAMP LIMIT 1)&lt;br /&gt;
  ) AS X1;&lt;br /&gt;
&lt;br /&gt;
+---------------------+----------+-------+&lt;br /&gt;
| TIMESTAMP           | READING  | VALUE |&lt;br /&gt;
+---------------------+----------+-------+&lt;br /&gt;
| 2020-06-02 16:31:05 | energy_0 |     4 |&lt;br /&gt;
+---------------------+----------+-------+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Formatierung &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 round(sum(VALUE)/1000,0) AS VALUE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sollte eventuell angepasst werden, da diese natürlich zum zu erwartenden Ergebnis passen muss.&lt;br /&gt;
&lt;br /&gt;
=== Temperaturdifferenz eines Pufferspeichers über die Zeit ermitteln (MySQL) ===&lt;br /&gt;
Beispiel 1:&lt;br /&gt;
&lt;br /&gt;
Temperaturdifferenz des Pufferspeichers über die Zeit in Minuten&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;Referenz zum DBRep : set [device] sqlSpecial readingsDifferenceByTimeDelta&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verwendete DB-Variablen (@) :  device und reading, diff und delta werden für Berechnungen benötigt und sind bei erneutem Aufruf zurück zu setzen&lt;br /&gt;
&lt;br /&gt;
Anmerkungen:&lt;br /&gt;
&lt;br /&gt;
- Der Zeitraum wird in diesem Beispiel als die letzten 24 Stunden festgelegt&lt;br /&gt;
&lt;br /&gt;
- Die Zeitdifferenz für die Änderung steht in der Spalte DELTA in Minuten&lt;br /&gt;
&lt;br /&gt;
- In FHEM wurde mit event-on-change-reading ins DBLog geschrieben&lt;br /&gt;
&lt;br /&gt;
- Bei dieser Ausgabe kann man erkennen, dass die Temperaturänderung im Wärmespeicher oft sehr klein ist, was ja auch so gewollt ist&lt;br /&gt;
&lt;br /&gt;
- Um 14:00 Uhr beginnt die Wärmepumpe das Warmwasser wieder aufzuheizen&amp;lt;pre&amp;gt;&lt;br /&gt;
SET @device=&#039;Heizung&#039;;SET @reading=&#039;hotWaterTemperature&#039;;&lt;br /&gt;
SET @diff=0;SET @delta=NULL;&lt;br /&gt;
&lt;br /&gt;
SELECT t1.TIMESTAMP,t1.READING,t1.VALUE,t1.DIFF,t1.DELTA&lt;br /&gt;
  FROM&lt;br /&gt;
    (&lt;br /&gt;
SELECT TIMESTAMP,READING,VALUE,&lt;br /&gt;
       if(@diff = 0,NULL, cast((VALUE-@diff) AS DECIMAL(3,1))) AS DIFF,&lt;br /&gt;
       @diff:=VALUE                                            AS curr_V,&lt;br /&gt;
       TIMESTAMPDIFF(MINUTE,@delta,TIMESTAMP)                  AS DELTA,&lt;br /&gt;
       @delta:=TIMESTAMP                                       AS curr_T&lt;br /&gt;
  FROM  history&lt;br /&gt;
  WHERE DEVICE     = @device  AND&lt;br /&gt;
        READING    = @reading AND&lt;br /&gt;
        TIMESTAMP &amp;gt;= NOW() - INTERVAL 1 DAY&lt;br /&gt;
  ORDER BY TIMESTAMP&lt;br /&gt;
    ) t1;&lt;br /&gt;
+---------------------+---------------------+-------+------+-------+&lt;br /&gt;
| TIMESTAMP           | READING             | VALUE | DIFF | DELTA |&lt;br /&gt;
+---------------------+---------------------+-------+------+-------+&lt;br /&gt;
| 2020-06-04 10:05:20 | hotWaterTemperature | 46.5  | NULL |  NULL |&lt;br /&gt;
| 2020-06-04 10:35:31 | hotWaterTemperature | 46.4  | -0.1 |    30 |&lt;br /&gt;
| 2020-06-04 11:00:31 | hotWaterTemperature | 46.2  | -0.2 |    25 |&lt;br /&gt;
snip...&lt;br /&gt;
| 2020-06-04 13:50:42 | hotWaterTemperature | 44.5  | -1.0 |     5 |&lt;br /&gt;
| 2020-06-04 13:55:42 | hotWaterTemperature | 44.0  | -0.5 |     5 |&lt;br /&gt;
| 2020-06-04 14:00:42 | hotWaterTemperature | 43.9  | -0.1 |     5 |&lt;br /&gt;
| 2020-06-04 14:10:42 | hotWaterTemperature | 41.7  | -1.8 |     5 |&lt;br /&gt;
snip...&lt;br /&gt;
| 2020-06-04 14:51:05 | hotWaterTemperature | 51.3  |  0.1 |     5 |&lt;br /&gt;
| 2020-06-04 17:01:15 | hotWaterTemperature | 51.2  | -0.1 |   130 |&lt;br /&gt;
snip...&lt;br /&gt;
| 2020-06-04 22:10:30 | hotWaterTemperature | 50.5  | -0.2 |     5 |&lt;br /&gt;
snip...&lt;br /&gt;
| 2020-06-05 11:30:45 | hotWaterTemperature | 46.1  | -0.1 |    25 |&lt;br /&gt;
+---------------------+---------------------+-------+------+-------+&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;Beispiel 2:&lt;br /&gt;
&lt;br /&gt;
Summieren der Temperaturdifferenz auf Stundenbasis&lt;br /&gt;
&lt;br /&gt;
Verwendete DB-Variablen (@) :  device und reading, diff und delta werden für Berechnungen benötigt und sind bei erneutem Aufruf zurück zu setzen&lt;br /&gt;
&lt;br /&gt;
Anmerkungen:&lt;br /&gt;
&lt;br /&gt;
- Der Zeitraum wird in diesem Beispiel als die letzten 24 Stunden festgelegt&lt;br /&gt;
&lt;br /&gt;
- Die Zeitdifferenz wird bei diesem Beispiel nicht ausgegeben&lt;br /&gt;
&lt;br /&gt;
- Alle Differenzen nach der Vollen Stunde werden der nächsten Stunde zugeschlagen&lt;br /&gt;
&lt;br /&gt;
- In FHEM wurde mit event-on-change-reading ins DBLog geschrieben&lt;br /&gt;
&lt;br /&gt;
- Um 14:00 Uhr beginnt die Wärmepumpe das Warmwasser wieder aufzuheizen&lt;br /&gt;
&lt;br /&gt;
- Bei diesem Wärmespeicher sind Temperaturschwankungen im Bereich von Null Komma irgendwas, als Messwert recht ungenau, was im Beispiel 1 zu der Vielzahl an Messwerten geführt hat. Durch Beispiel 2 auf Stundenbasis lässt sich bereits mehr erkennen.  Hier wäre der Wärmepumpeneinsatz um 14:00 Uhr mit dem Pumpenvorlauf (-1.8) und der Lauf der Zirkulationspumpe um 8:00 und 8:30 Uhr zu sehen, was den Wärmespeicher um 1,2 Grad abgekühlt hat.&amp;lt;pre&amp;gt;&lt;br /&gt;
SET @device=&#039;Heizung&#039;;SET @reading=&#039;hotWaterTemperature&#039;;&lt;br /&gt;
SET @diff=0;SET @delta=NULL;&lt;br /&gt;
&lt;br /&gt;
SELECT xTIMESTAMP AS TIMESTAMP,READING,xVALUE AS VALUE,xDIFF AS DIFF&lt;br /&gt;
  FROM&lt;br /&gt;
    (SELECT DATE_FORMAT(DATE_ADD(t1.TIMESTAMP,INTERVAL (IF(MINUTE(t1.TIMESTAMP) &amp;gt; 0, 60, 0)-MINUTE(t1.TIMESTAMP)) MINUTE),&#039;%Y-%m-%d %H:00:00&#039;) AS xTIMESTAMP,&lt;br /&gt;
            t1.READING,&lt;br /&gt;
            round(t1.VALUE) AS xVALUE,&lt;br /&gt;
            sum(t1.DIFF)    AS xDIFF,&lt;br /&gt;
            sum(t1.DELTA)   AS xDELTA&lt;br /&gt;
       FROM&lt;br /&gt;
         (SELECT TIMESTAMP,READING,VALUE,&lt;br /&gt;
                 if(@diff = 0,NULL, cast((VALUE-@diff) AS DECIMAL(3,1))) AS DIFF,&lt;br /&gt;
                 @diff:=VALUE                                            AS curr_V,&lt;br /&gt;
                 TIMESTAMPDIFF(MINUTE,@delta,TIMESTAMP)                  AS DELTA,&lt;br /&gt;
                 @delta:=TIMESTAMP                                       AS curr_T&lt;br /&gt;
            FROM  history&lt;br /&gt;
            WHERE DEVICE     = @device  AND&lt;br /&gt;
                  READING    = @reading AND&lt;br /&gt;
                  TIMESTAMP &amp;gt;= NOW() - INTERVAL 1 DAY&lt;br /&gt;
            ORDER BY TIMESTAMP&lt;br /&gt;
         ) t1&lt;br /&gt;
       GROUP BY xTIMESTAMP WITH ROLLUP) x1&lt;br /&gt;
&lt;br /&gt;
   WHERE xDELTA     IS NOT NULL AND&lt;br /&gt;
         xTIMESTAMP IS NOT NULL;&lt;br /&gt;
+---------------------+---------------------+-------+------+&lt;br /&gt;
| TIMESTAMP           | READING             | VALUE | DIFF |&lt;br /&gt;
+---------------------+---------------------+-------+------+&lt;br /&gt;
| 2020-06-04 12:00:00 | hotWaterTemperature |    46 | -0.1 |&lt;br /&gt;
| 2020-06-04 13:00:00 | hotWaterTemperature |    46 | -0.4 |&lt;br /&gt;
| 2020-06-04 14:00:00 | hotWaterTemperature |    44 | -1.8 |&lt;br /&gt;
| 2020-06-04 15:00:00 | hotWaterTemperature |    51 |  7.4 |&lt;br /&gt;
| 2020-06-04 18:00:00 | hotWaterTemperature |    51 | -0.1 |&lt;br /&gt;
snip...&lt;br /&gt;
| 2020-06-05 07:00:00 | hotWaterTemperature |    48 | -0.3 |&lt;br /&gt;
| 2020-06-05 08:00:00 | hotWaterTemperature |    48 | -0.2 |&lt;br /&gt;
| 2020-06-05 09:00:00 | hotWaterTemperature |    48 | -1.2 |&lt;br /&gt;
| 2020-06-05 10:00:00 | hotWaterTemperature |    47 | -0.3 |&lt;br /&gt;
snip...&lt;br /&gt;
+---------------------+---------------------+-------+------+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Alle aktuellsten readings eines Device im letzten Tagesverlauf (MySQL) ===&lt;br /&gt;
Beispiel :&lt;br /&gt;
&lt;br /&gt;
Verwendete DB-Variablen (@) :  device&lt;br /&gt;
&lt;br /&gt;
Anmerkungen:&lt;br /&gt;
&lt;br /&gt;
- Der Zeitraum wird in diesem Beispiel als die letzten 24 Stunden festgelegt&lt;br /&gt;
&lt;br /&gt;
- In FHEM wurde mit event-on-change-reading ins DBLog geschrieben, wodurch nicht alle readings immer zeitlich in der DB aufeinander folgen oder einige im Zeitraum mehrfach geschrieben wurden. Mit diesem Aufruf erscheinen immer die letzten Aktualisierungen.&lt;br /&gt;
&lt;br /&gt;
- Sollten einige readings nicht erscheinen, so wurden diese vor dem Zeitraum letztmalig aktualisiert. Mit &amp;quot;INTERVAL [n] DAY könnten diese eventuell auch noch gefunden werden. Bitte hier die Laufzeit beachten!&amp;lt;pre&amp;gt;&lt;br /&gt;
SET @device = &#039;Heizung&#039;;&lt;br /&gt;
&lt;br /&gt;
SELECT t1.TIMESTAMP,t1.DEVICE,t1.READING,t1.VALUE&lt;br /&gt;
  FROM history t1&lt;br /&gt;
  INNER JOIN&lt;br /&gt;
   (select max(TIMESTAMP) AS TIMESTAMP,DEVICE,READING&lt;br /&gt;
      from history&lt;br /&gt;
      where DEVICE    = @device and&lt;br /&gt;
            TIMESTAMP &amp;gt; NOW() - INTERVAL 1 DAY&lt;br /&gt;
      group by READING) x&lt;br /&gt;
  ON x.TIMESTAMP = t1.TIMESTAMP AND&lt;br /&gt;
     x.DEVICE    = t1.DEVICE    AND&lt;br /&gt;
     x.READING   = t1.READING;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Device / Reading Daten in eine CSV-Datei exportieren (MySQL) ===&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich gibt es für diesen Zweck das eingebaute Set-Kommando &#039;&#039;&#039;exportToFile&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist die Verwendung von spezifischen Datenbankkommandos, die mit Set &#039;&#039;&#039;sqlCmd&#039;&#039;&#039; ausgeführt werden können.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel wird ein CSV File geschrieben, welches die Daten des Devices &#039;SMA_Energymeter&#039; enthält.&lt;br /&gt;
Wichtig ist, nicht zur Trennung von SQL-Befehlen dienende Semikolons durch Verdopplung zu escapen (z.B. im String &amp;quot;...TERMINATED BY &#039;;;&#039;...&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SET @TS = DATE_FORMAT(NOW(),&#039;_%Y_%m_%d&#039;);&lt;br /&gt;
&lt;br /&gt;
SET @FOLDER = &#039;/volume1/ApplicationBackup/&#039;;&lt;br /&gt;
SET @PREFIX = &#039;export&#039;;&lt;br /&gt;
SET @EXT    = &#039;.csv&#039;;&lt;br /&gt;
&lt;br /&gt;
SET @CMD = CONCAT(&amp;quot;	SELECT *&lt;br /&gt;
			FROM `fhemtest`.`history`&lt;br /&gt;
			WHERE `DEVICE`=&#039;SMA_Energymeter&#039; AND TIMESTAMP &amp;gt; DATE_SUB(CURRENT_DATE(),INTERVAL 1 DAY)&lt;br /&gt;
			INTO OUTFILE &#039;&amp;quot;,@FOLDER,@PREFIX,@TS,@EXT,&amp;quot;&#039;&lt;br /&gt;
			FIELDS ENCLOSED BY &#039;\&amp;quot;&#039;&lt;br /&gt;
			TERMINATED BY &#039;;;&#039;&lt;br /&gt;
			ESCAPED BY &#039;\&amp;quot;&#039;&amp;quot;,&amp;quot; &lt;br /&gt;
			LINES TERMINATED BY &#039;\r\n&#039;;;&lt;br /&gt;
		&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
PREPARE statement FROM @CMD;&lt;br /&gt;
&lt;br /&gt;
EXECUTE statement;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039;  der verwendete Datenbank-User benötigt das &#039;&#039;&#039;FILE&#039;&#039;&#039; Recht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele / Hinweise und Lösungsansätze für verschiedene Aufgaben ==&lt;br /&gt;
=== Definieren eines DbRep-Devices ===&lt;br /&gt;
[[Bild:DbRep_initialized.PNG|right|thumb|400px|]]&lt;br /&gt;
&lt;br /&gt;
Das DbRep-Device wird bei der Definition mit der DbLog-Instanz verbunden, in deren angeschlossener Datenbank später die Auswertungen und Operationen stattfinden sollen. Es ist also nicht die Datenbank selbst, sondern das vorher definierte DbLog-Device anzugeben.&lt;br /&gt;
Die Definition erfolgt z.B. durch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Energy DbRep LogDB       #LogDB ist das zu verbindende DbLog-Device&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei der Definition werden die Zugangsdaten aus der DbLog-Instanz gelesen und das DbRep-Device mit der Datenbank verbunden. Nach der Definition ist der Status &amp;quot;initialized&amp;quot;. Nach ca. 5 Sekunden wechselt er nach &amp;quot;connected&amp;quot; sofern die Verbindung zur Datenbank erfolgreich war. Zu welcher Datanbank das DbRep-Device sich verbunden hat, zeigt das &#039;&#039;Internal&#039;&#039; DATABASE.&lt;br /&gt;
&lt;br /&gt;
Damit ist das DbRep-Device grundsätzlich einsatzbereit, aber noch nicht praxistauglich. Werden keine weiteren Eingrenzungen angegeben, kann mit dem so definierten Device mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set Rep.Energy countEntries&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
die gesamte Anzahl der Datensätze in der Datenbank ermittelt werden.&lt;br /&gt;
Für eine weitere Verwendung sind weitere &#039;&#039;Attribute&#039;&#039; zu setzen.&lt;br /&gt;
Um die Funktionen von &amp;quot;Rep.Energy&amp;quot; nur auf z.B. Datensätze in der Datenbank anzuwenden die &amp;quot;STP_5000&amp;quot; im Feld &amp;quot;DEVICE&amp;quot; enthalten, wird das &#039;&#039;&#039;Attribut&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Rep.Energy device STP_5000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
gesetzt. Weitere Begrenzungen der gerätespezifischen Selektion erfolgt durch das &#039;&#039;&#039;Attribut&#039;&#039;&#039; &amp;quot;reading&amp;quot;. So wird durch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Rep.Energy reading etotal&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Rep_configured.PNG|right|thumb|300px|]]&lt;br /&gt;
festgelegt, dass sich die (allermeisten) Operationen auf die Kombination aus dem &amp;quot;device STP_5000&amp;quot; und dem &amp;quot;reading etotal&amp;quot; beziehen.&lt;br /&gt;
Eine zeitliche Eingrenzung der Ergebnisse erfolgt durch die &#039;&#039;&#039;Attribute&#039;&#039;&#039; &amp;quot;timeDiffToNow&amp;quot;, &amp;quot;timeOlderThan&amp;quot;, &amp;quot;timestamp_begin&amp;quot;, &amp;quot;timestamp_end&amp;quot;.&lt;br /&gt;
In dem Beispiel sollen sich die Selektionsergebnisse immer auf die letzten 120 Minuten beziehen.&lt;br /&gt;
Dazu wird das Attribut&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Rep.Energy timeDiffToNow 7200    #Der Wert für timeDiffToNow ist in Sekunden anzugeben&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
gesetzt. Es wird dynamisch bei jeder Operation &amp;quot;&amp;lt;Selektionsbeginn&amp;gt; = &amp;lt;aktuelle Zeit&amp;gt; - 3600s&amp;quot; berechnet und die Datensätze bis zu &amp;lt;aktuelle Zeit&amp;gt; berücksichtigt. &lt;br /&gt;
Die gesamten Datenbankoperationen und teilweise auch Auswertungen von Selektionen erfolgt mit Blockingcall im Hintergrund. Der Timeout für die Operationen ist per Default auf 86400 Sekunden gesetzt. Über das &#039;&#039;Attribut&#039;&#039; &amp;quot;timeout&amp;quot; kann es den eigenen Bedingungen angepasst werden. In dem Beispiel wird timeout auf 300s geändert um auch bei sehr großen Selektionen und Auswertungen nicht in einen timeout zu laufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Rep.Energy timeout 300&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um auch die Verarbeitungszeiten im Hintergrund als Reading anzeigen zu lassen wird mit mit dem &#039;&#039;Attribut&#039;&#039;          &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Rep.Energy showproctime 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
erreicht. &lt;br /&gt;
Mit diesen Einstellungen ist das Device für den konfiguriert und man kann sich zum Beispiel mit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set Rep.Energy fetchrows&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
die Datensätze mit der Gesamtenergierzeugung &amp;quot;etotal&amp;quot; des Wechselrichters &amp;quot;STP_5000&amp;quot; die in den letzten 2 Stunden in die DB geschrieben wurden.&lt;br /&gt;
Nachdem der Befehl in der Gerätedetailsicht ausgeführt wurde, wechselt der state im DeviceOverview auf &amp;quot;running&amp;quot;. Sobald im DeviceOverview &amp;quot;done&amp;quot; angezeigt wird sieht man die Ergebnisse nach einem Browserrefresh.&lt;br /&gt;
Bei der Ausführung einer erneuten Operation werden alle Readings gelöscht. Sollen bestimmte Readings davon ausgenommen werden, kann dem &#039;&#039;Attribut&#039;&#039; eine kommaseparierte Liste von zu schützenden Readings übergeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Allgemein wird empfohlen sich für jede Aufgabe eine separates DbRep-Device anzulegen und entsprechend zu konfigurieren anstatt die Einstellungen ständig den neuen Aufgaben anzupassen. &lt;br /&gt;
Um den Prozess zu vereinfachen, kann das einmal angelegte Device für eine neue Selektionsaufgabe (zum Beispiel die Datensätze eines SMA Energymeters anzuzeigen bzw. auszuwerten) auf ein neues DbRep-Device kopiert&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
copy Rep.Energy Rep.SMAMeter&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und entsprechend angepasst werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis zur Eventgenerierung:&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
Je nach genutzter Funktion können sehr viele Readings als Ergebnis generiert werden. Zum Beispiel können mit &amp;quot;fetchrows&amp;quot;, wobei jedes Reading einer selektierte Zeile aus der Datenbank entspricht, durchaus mehrere hundert Readings entstehen.&lt;br /&gt;
Sollte man nicht durch die Attribute &amp;quot;event-on-update-reading&amp;quot; bzw. &amp;quot;event-on-change-reading&amp;quot; die Eventerzeugung auf nur relevante Readings begrenzt haben, können in diesem Fall ebenso viele Events enstehen die das System entsprechend belasten können. &amp;lt;br&amp;gt;&lt;br /&gt;
Deswegen wird empfohlen die &#039;&#039;&#039;Eventerzeugung sofort&#039;&#039;&#039; auf z.B. &amp;quot;state&amp;quot; zu &#039;&#039;&#039;begrenzen&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Datensätze (Devices) von einer Datenbank in eine andere umziehen (Export/Import)===&lt;br /&gt;
==== Zweck ====&lt;br /&gt;
&lt;br /&gt;
Oft ist es so, dass man zunächst eine DbLog-Datenbank anlegt um alle zu loggenden Events dort aufzuzeichnen. Mit zunehmender Größe bzw. mit dem Wunsch nach einer höheren Strukturierung werden weitere DbLog-Instanzen angelegt.&lt;br /&gt;
Die bereits geschriebenen Datensätze eines Gerätes müssen nun in eine andere Datenbank verlagert werden, weil das Device nunmehr in dieser Datenbank geloggt und ausgewertet werden soll.&lt;br /&gt;
&lt;br /&gt;
Für das Beispielszenario gilt folgendes:&lt;br /&gt;
&lt;br /&gt;
* Quelldatenbank aus der das Device entfernt werden soll ist &amp;quot;fhem&amp;quot; mit der DbLog-Instanz &amp;quot;LogDB&amp;quot;&lt;br /&gt;
* Zieldatenbank ist &amp;quot;fhemshort&amp;quot; mit der DbLog-Instanz &amp;quot;LogDBShort&amp;quot;&lt;br /&gt;
* das umzuziehende Device ist &amp;quot;MelderCP1&amp;quot;&lt;br /&gt;
* das definierte DbRep-Device ist &amp;quot;Rep.MelderCP1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Vorbereitung ====&lt;br /&gt;
&lt;br /&gt;
Zunächst wird ein DbRep-Device definiert (falls es noch nicht existiert) und für den Verwendungszweck vorbereitet (zur Definition siehe [[#Definieren_eines_DbRep-Devices | Definieren eines DbRep-Devices]]).&lt;br /&gt;
&lt;br /&gt;
Das Attribut &amp;quot;reading&amp;quot; bzw. eventuell gesetzte Attribute zur Zeiteingrenzung werden gelöscht, damit alle Datensätze des Devices erfasst werden können.&lt;br /&gt;
Für den bevorstehenden Export wird mit dem Attribut &amp;quot;expimpFile&amp;quot; der (beschreibbare) Pfad und Dateiname festgelegt, hier im Beispiel ist es &amp;quot;/media/sf_Backup_FHEM/meldercp1.txt&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Rep_MelderCP1_count.PNG|right|thumb|200px|Anzahl Einträge von MelderCP1]]&lt;br /&gt;
&lt;br /&gt;
Mit &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set Rep.MelderCP1 countEntries&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
kann man sich nun einen Überblick verschaffen, wie viele Datensätze in der Quelldatenbank für &amp;quot;MelderCP1&amp;quot; enthalten sind und wie viele auch exportiert werden müssen. In dem Beispiel sind es, wie in dem Screenshot zu sehen, 1144 Datensätze.&lt;br /&gt;
&lt;br /&gt;
Falls noch nicht geschehen, wird in der bisherigen DbLog-Definition das zu loggende Device entfernt und in der neuen DbLog-Definition aufgenommen, damit nun keine neuen Datensätze mehr für &amp;quot;MelderCP1&amp;quot; in die bisherige Datenbank geschrieben werden. Hierzu siehe die {{Link2CmdRef|Lang=de|Anker=DbLog}} zu DbLog.&lt;br /&gt;
&lt;br /&gt;
==== Export ====&lt;br /&gt;
Nun werden die Datensätze des Devices &amp;quot;MelderCP1&amp;quot; mit dem folgenden set-Kommando in die Datei &amp;quot;/media/sf_Backup_FHEM/meldercp1.txt&amp;quot; exportiert.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set Rep.MelderCP1 exportToFile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach dem Export sollte natürlich im Reading von &amp;quot;Rep.MelderCP1&amp;quot; die gleiche Anzahl von exportierten Datensätzen ausgegeben werden wie vorher mit &amp;quot;countEntries&amp;quot; ermittelt wurde (siehe Screenshot). &lt;br /&gt;
&lt;br /&gt;
[[Datei:Rep_MelderCP1_exported.PNG|right|thumb|300px|Anzahl exportierter Dataensätze]]&lt;br /&gt;
&lt;br /&gt;
In der Export-Datei sind nun die Datensätze im CVS-Format enthalten. &lt;br /&gt;
&lt;br /&gt;
Ein Ausschnitt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
............&lt;br /&gt;
&amp;quot;2016-07-04 17:32:03&amp;quot;,&amp;quot;MelderCP1&amp;quot;,&amp;quot;FS20&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;&amp;quot;&lt;br /&gt;
&amp;quot;2016-07-05 07:47:50&amp;quot;,&amp;quot;MelderCP1&amp;quot;,&amp;quot;FS20&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;&amp;quot;&lt;br /&gt;
&amp;quot;2016-07-05 08:27:57&amp;quot;,&amp;quot;MelderCP1&amp;quot;,&amp;quot;FS20&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;&amp;quot;&lt;br /&gt;
&amp;quot;2016-07-05 08:28:25&amp;quot;,&amp;quot;MelderCP1&amp;quot;,&amp;quot;FS20&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;&amp;quot;&lt;br /&gt;
&amp;quot;2016-07-05 10:23:42&amp;quot;,&amp;quot;MelderCP1&amp;quot;,&amp;quot;FS20&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;&amp;quot;&lt;br /&gt;
&amp;quot;2016-07-05 10:27:35&amp;quot;,&amp;quot;MelderCP1&amp;quot;,&amp;quot;FS20&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;&amp;quot;&lt;br /&gt;
&amp;quot;2016-07-05 17:26:30&amp;quot;,&amp;quot;MelderCP1&amp;quot;,&amp;quot;FS20&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;&amp;quot;&lt;br /&gt;
&amp;quot;2016-07-06 07:46:31&amp;quot;,&amp;quot;MelderCP1&amp;quot;,&amp;quot;FS20&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;&amp;quot;&lt;br /&gt;
&amp;quot;2016-07-06 11:24:04&amp;quot;,&amp;quot;MelderCP1&amp;quot;,&amp;quot;FS20&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;&amp;quot;&lt;br /&gt;
&amp;quot;2016-07-06 11:25:43&amp;quot;,&amp;quot;MelderCP1&amp;quot;,&amp;quot;FS20&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;&amp;quot;&lt;br /&gt;
&amp;quot;2016-07-06 11:26:52&amp;quot;,&amp;quot;MelderCP1&amp;quot;,&amp;quot;FS20&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;on-old-for-timer 60&amp;quot;,&amp;quot;&amp;quot;&lt;br /&gt;
...........&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In der bisherigen Datenbank &amp;quot;fhem&amp;quot; können die Datensätze nun gelöscht werden. Dazu versehen wir das DbRep-Device &amp;quot;Rep.MelderCP1&amp;quot; mit dem Attribut &amp;quot;allowDeletion&amp;quot; um die Löschfunktion des Moduls freizuschalten. &lt;br /&gt;
Nun werden die vorher exportierten Datensätze gelöscht mit:  &lt;br /&gt;
&lt;br /&gt;
[[Bild:Rep_MelderCP1_delrows.PNG|right|thumb|300px|Anzahl gelöschter Datensätze]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set Rep.MelderCP1 delEntries&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auch jetzt ist wieder sicherzustellen dass in der Ausgabe der gelöschten Rows dieselbe Anzahl (1144) der exportierten Datensätze enthalten ist.&lt;br /&gt;
&lt;br /&gt;
==== Import ====&lt;br /&gt;
Im nächsten Schritt werden die exportierten Daten in die neue Datenbank importiert. Dazu wird in unserem DbRep-Device &amp;quot;Rep.MelderCP1&amp;quot; zunächst das &amp;quot;allowDeletion&amp;quot;-Attribut sicherheitshalber gelöscht. &lt;br /&gt;
Zur Umstellung des DbRep-Devices auf die neue Datenbank wird die Definition von &amp;quot;Rep.MelderCP1&amp;quot; editiert und dort die neue DbLog-Instanz &amp;quot;LogDBShort&amp;quot; angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modify Rep.MelderCP1 LogDBShort&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach einem kurzen Moment wird der state von &amp;quot;Rep.MelderCP1&amp;quot; sich wieder von &amp;quot;initialized&amp;quot; auf &amp;quot;connected&amp;quot; ändern sofern die Umstellung funktioniert hat. Mit einem Vergleichslauf durch&lt;br /&gt;
[[Datei:Rep_MelderCP1_Vergleichslauf.PNG|right|thumb|300px|Anzahl Einträge von MelderCP1 in neuer Datenbank nach Umstellung]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set Rep.MelderCP1 countEntries&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wird ersichtlich, dass sich in dieser Datenbank noch keine (oder vllt. bereits neu geloggte) Einträge von &amp;quot;MelderCP1&amp;quot; befinden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nun kann der Import erfolgen. Mit &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set Rep.MelderCP1 importFromFile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
werden die Daten aus der immer noch im Attribut &amp;quot;expimpFile&amp;quot; hinterlegten Datei &amp;quot;/media/sf_Backup_FHEM/meldercp1.txt&amp;quot; in die Datenbank &amp;quot;fhemshort&amp;quot; importiert. Dieser Vorgang wird als Transaktion ausgeführt. Es werden immer alle Daten oder, im Falle eines Fehlers, &#039;&#039;&#039;KEINE&#039;&#039;&#039; Daten importiert. Damit ist sichergestellt dass der Datenimport immer einen definierten Zustand hat. Sollte der Datenimport sehr umfangreiche Datensätze enthalten und somit schon absehbar sein dass der voreingestellte timeout-Wert von 86400 Sekunden nicht ausreichen wird, kann man vorsorglich das Attribut &amp;quot;timeout&amp;quot; höher setzen, z.B. auf das Doppelte).&lt;br /&gt;
&lt;br /&gt;
Hier in dem Beispiel sind es lediglich 1144 Datensätze die sehr schnell importiert werden. Somit ist keine Anpassung des timeout-Parameters notwendig.&lt;br /&gt;
Auch nach dem Import wird wieder die Anzahl der verarbeiteten Dataensätze ausgegeben. Sie sollte natürlich ebenfalls mit den vorab ermittelten Zahlen der exportierten Datensätze übereinstimmen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Rep_MelderCP1_importedrows.PNG|right|thumb|300px|Anzahl importierter Datensätze]]&lt;br /&gt;
&lt;br /&gt;
==== Abschluss ====&lt;br /&gt;
&lt;br /&gt;
Nach dem erfolgreichen Import sollte das Attribut &amp;quot;expimpFile&amp;quot; wieder entfernt werden damit man nicht versehentlich einen erneuten Import durchführt.&lt;br /&gt;
Das verwendete Rep.MelderCP1 kann nun wieder mit Zeitbegrenzungsattributen usw. versehen werden um die ursprüngliche Verwendung wieder herzustellen.&lt;br /&gt;
&lt;br /&gt;
Die dargestellte Prozedur stellt einen Komplettumzug eines Devices dar, kann jedoch durch die Angabe der bekannten Attribute auch auf bestimmte Readings in der Datenbank oder Zeitgrenzen eingeschränkt werden. Dadurch würden nur bestimmte Datensätze exportiert und wieder importiert werden. Weiterhin sollte man daran denken die vorhandenen Auswertungsszenarien mit DbRep-Devices bzw. SVG-Diagrammen usw. auch auf die neue Datanbank umzustellen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Inhalte einer primären Datenbank in eine andere Standby-Datenbank übertragen (syncStandby) ===&lt;br /&gt;
&lt;br /&gt;
==== Zweck ====&lt;br /&gt;
&lt;br /&gt;
Mit dem Export/Import Verfahren kann man, wie oben beschrieben, Daten zwischen verschiedenen Datenbanken austauschen. Mit dem Befehl &amp;quot;syncStandby&amp;quot; ist es aber mit relativ wenig Aufwand möglich, ein regelmäßig automatisch laufendes Übertragungsverfahren zwischen zwei Datenbanken zu etablieren. &lt;br /&gt;
&lt;br /&gt;
Im vorliegenden Beispiel werden Datenbanken des gleichen Typs verwendet. Das Verfahren ist aber auch zwischen Datenbanken unterschiedlichen Typs anwendbar.&lt;br /&gt;
&lt;br /&gt;
Anwendungsfälle dafür sind zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
* die Einrichtung eines Archivsystems &lt;br /&gt;
* die längerfristge Datenhaltung von Datensätzen eines bestimmten Devices/Readings in einer weiteren Datenbank um sie dort für umfangreiche Auswertungen zu nutzen (z.B. Daten einer PV-Anlage)&lt;br /&gt;
* Wechsel des Datenbanksystems, z.B. von SQLite zu MySQL/MariaDB&lt;br /&gt;
* säubern der Quelldaten von doppelten Datensätzen und nicht mehr benötigten Daten, Weiternutzung der aufgebauten Standbydatenbank als primäre Datenbank nach der Syncronisierung&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Für das hier gezeigte Beispielszenario sollen Daten einer MariaDB-Quelldatenbank in einer andere MariaDB-Datenbank regelmäßig übertragen werden. Auf der Quelldatenbank werden die Daten aber nicht gelöscht, d.h. es entstehen zwei Datenbanken mit gleicher Datenbasis.&lt;br /&gt;
&lt;br /&gt;
* Quelldatenbank ist eine MariaDB &amp;quot;fhemtest1&amp;quot; mit der DbLog-Instanz &amp;quot;LogDB1&amp;quot;&lt;br /&gt;
* Zieldatenbank ist eine MariaDB &amp;quot;fhemtest&amp;quot; mit der DbLog-Instanz &amp;quot;LogStby&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Quelldatenbank ====&lt;br /&gt;
&lt;br /&gt;
Im vorliegenden Beispiel sind die Quelldatenbank und die Standby-Datenbank vom gleichen Typ MariaDB. Das Verfahren funktioniert ebenso zwischen Datenbanken unterschiedlichen Typs, also z.B. zur Übertragung von SQLite Daten in eine MariaDB.&lt;br /&gt;
&lt;br /&gt;
Die Quelldatenbank ist im normalen Kontext die produktive FHEM-Logdatenbank. D.h. sie ist bereits eingerichtet und läuft mit einem entsprechenden DbLog-Device.&lt;br /&gt;
Die hier verwendete Quelldatenbank heißt &amp;quot;fhemtest1&amp;quot;. Die Definition des dazu gehörenden DbLog-Devices &amp;quot;LogDB1&amp;quot; sei der Vollständigkeit halber hier erwähnt, wird aber natürlich bei jedem Nutzer individuell aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define LogDB1 DbLog ./fhemtest1maria10.conf .*:(?!done).*&lt;br /&gt;
attr LogDB1 DbLogInclude CacheUsage&lt;br /&gt;
attr LogDB1 DbLogSelectionMode Exclude/Include&lt;br /&gt;
attr LogDB1 DbLogType History&lt;br /&gt;
attr LogDB1 addStateEvent 0&lt;br /&gt;
attr LogDB1 asyncMode 1&lt;br /&gt;
attr LogDB1 bulkInsert 1&lt;br /&gt;
attr LogDB1 cacheEvents 2&lt;br /&gt;
attr LogDB1 cacheLimit 2000&lt;br /&gt;
attr LogDB1 dbSchema fhemtest1&lt;br /&gt;
attr LogDB1 devStateIcon .*active:10px-kreis-gelb connected:10px-kreis-gruen .*disconnect:10px-kreis-rot&lt;br /&gt;
attr LogDB1 disable 0&lt;br /&gt;
attr LogDB1 room DbLog&lt;br /&gt;
attr LogDB1 showproctime 1&lt;br /&gt;
attr LogDB1 syncInterval 120&lt;br /&gt;
attr LogDB1 useCharfilter 1&lt;br /&gt;
attr LogDB1 verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Standby Datenbank ====&lt;br /&gt;
&lt;br /&gt;
Die Standby Datenbank ist das Synchronisationsziel. &lt;br /&gt;
Die Erstellung der Datenbank und die nachfolgende Definition des dazu gehörigen DbLog-Devices erfolgt weitgehend wie für eine &amp;quot;normale&amp;quot; Log-Datenbank wie in der Commandref beschrieben mit geringfügigen Anpassungen.&lt;br /&gt;
&lt;br /&gt;
; 1. Anlegen der DB und Tabellen: wie in diesem [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/dblog Link] hinterlegt, erfolgt die Erstellung mit den Befehlen  für MySQL:&lt;br /&gt;
::: CREATE DATABASE `fhemtest` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;&lt;br /&gt;
::: CREATE USER &#039;fhemuser&#039;@&#039;%&#039; IDENTIFIED BY &#039;fhempassword&#039;;&lt;br /&gt;
::: CREATE TABLE `fhemtest`.`history` (TIMESTAMP TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, DEVICE varchar(64), TYPE varchar(64), EVENT varchar(512), READING varchar(64), VALUE varchar(128), UNIT varchar(32));&lt;br /&gt;
::: ALTER TABLE `fhemtest`.`history` ADD PRIMARY KEY(TIMESTAMP, DEVICE, READING);&lt;br /&gt;
::: CREATE TABLE `fhemtest`.`current` (TIMESTAMP TIMESTAMP, DEVICE varchar(64), TYPE varchar(64), EVENT varchar(512), READING varchar(64), VALUE varchar(128), UNIT varchar(32));&lt;br /&gt;
::: GRANT SELECT, INSERT, DELETE, UPDATE ON `fhemtest`.* TO &#039;fhemuser&#039;@&#039;%&#039;;&lt;br /&gt;
&lt;br /&gt;
Es wird zusätzlich zu der normalen Erstellung der history-Tabelle ein primary Key für die Tabelle erstellt. Dieser Key verhindert dass Duplikate in der Tabelle erstellt werden und erleichtert dadurch sehr das Verfahren der Datenübertragung in der Folge.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:stb1.PNG|right|thumb|300px|DbLog-Device für Standby-Datenbank]]&lt;br /&gt;
; 2. Erstellung der Konfigurationsdatei und Definition des DbLog-Devices für die Standby-Datenbank: Die Konfigurationsdatei (mariastby.conf) beinhaltet die Verbindunginformationen für das DbLog-Device und wird genau wie in der DbLog-Commandref beschrieben angelegt. Das DbLog-Device für die Standby-Datenbank wird nur für die nachfolgende Definition des benötigten DbRep-Devices gebraucht und wird so definiert, dass keinerlei Events geloggt werden. Das kann auf verschiedenen Wegen erreicht werden. Im Beispiel wird der Regex im DEF entsprechend aufgebaut.&lt;br /&gt;
::: define LogStby DbLog ./mariastby.conf aaaaaa:bbbbbb&lt;br /&gt;
::: attr LogStby DbLogType History&lt;br /&gt;
::: attr LogStby asyncMode 1&lt;br /&gt;
::: attr LogStby bulkInsert 1&lt;br /&gt;
::: attr LogStby cacheEvents 2&lt;br /&gt;
::: attr LogStby devStateIcon .*active:10px-kreis-gelb connected:10px-kreis-gruen .*disconnect:10px-kreis-rot&lt;br /&gt;
::: attr LogStby disable 0&lt;br /&gt;
::: attr LogStby room DbLog&lt;br /&gt;
::: attr LogStby showNotifyTime 1&lt;br /&gt;
::: attr LogStby showproctime 1&lt;br /&gt;
::: attr LogStby syncEvents 1 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Erstellung der current-Tabelle ist für den vorgesehenen Zweck eigentlich nicht nötig, wird der Vollständigkeit halber mit dokumentiert.&lt;br /&gt;
Ist das DbLog-Device definiert und erfolgreich verbunden, ist dessen state &amp;quot;connected&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Definition des DbRep-Devices zur Synchronisation Quell- und Standby-Datenbank ====&lt;br /&gt;
&lt;br /&gt;
Es existieren nun das DbLog Device &amp;quot;LogDB1&amp;quot; für die produktive Quelldatenbank und das DbLog Device &amp;quot;LogStby&amp;quot; für die Standby-Datenbank.&lt;br /&gt;
Für die Synchronisation wird ein DbRep-Device erstellt, welches mit dem DbLog-Device der &#039;&#039;&#039;produktiven Quelldatenbank&#039;&#039;&#039;, also LogDB1, verbunden wird.&lt;br /&gt;
Wie üblich, wird im DEF der Name des entsprechenden DbLog-Devices angegeben, hier &amp;quot;LogDB1&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod Rep.LogDB1.syncStandby DbRep LogDB1&lt;br /&gt;
attr Rep.LogDB1.syncStandby aggregation no&lt;br /&gt;
attr Rep.LogDB1.syncStandby event-on-update-reading state&lt;br /&gt;
attr Rep.LogDB1.syncStandby fastStart 1&lt;br /&gt;
attr Rep.LogDB1.syncStandby role Client&lt;br /&gt;
attr Rep.LogDB1.syncStandby room DbLog&lt;br /&gt;
attr Rep.LogDB1.syncStandby showproctime 1&lt;br /&gt;
attr Rep.LogDB1.syncStandby stateFormat { (ReadingsVal($name,&amp;quot;state&amp;quot;, &amp;quot;&amp;quot;)).&amp;quot; : SQL-Zeit: &amp;quot;.(ReadingsVal($name,&amp;quot;sql_processing_time&amp;quot;, &amp;quot;&amp;quot;)) }&lt;br /&gt;
attr Rep.LogDB1.syncStandby timeDiffToNow d:6&lt;br /&gt;
attr Rep.LogDB1.syncStandby verbose 3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den verschiedenen möglichen Zeitattributen (&#039;&#039;&#039;time.*&#039;&#039;&#039;) und den Attributen &#039;&#039;&#039;device&#039;&#039;&#039; und &#039;&#039;&#039;reading&#039;&#039;&#039; wird abgegrenzt, welche Datensätze in die Standby-Datenbak übertragen werden sollen. In dem vorliegenden Beispiel werden mit jedem Synchronisationslauf alle in der DB vorhandenen Datensätze, die nicht älter als 6 Tage Tage sind, in die Standby-Datenbank übertragen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
Würde man einen solchen Lauf z.B. alle 4 Stunden durchführen, würden viele doppelte Datensätze in der  Datenbank entstehen. Der bei der Tabellenerstellung für die history-Tabelle angelegte primary Key verhindert das !&lt;br /&gt;
[[Datei:stb2.PNG|right|thumb|300px|syncStandby gestartet]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ein Synchronisationslauf wird nun gestartet mit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 set &amp;lt;DbRep-Name&amp;gt; syncStandby &amp;lt;DbLog-Device Standby&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dem vorliegenden Beispiel ist das:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 set Rep.LogDB1.syncStandby syncStandby LogStby&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:stb3.PNG|right|thumb|300px|syncStandby erfolgreich ausgeführt]]&lt;br /&gt;
Der Fortschritt der Datenübertragung sowie die evtl. eingefügten Datensätze (number of lines inserted) ist im Logfile mit verbose 3 ersichtlich:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2020.01.24 17:12:41.186 3: DbRep Rep.LogDB1.syncStandby - total lines transfered to standby database: 6177&lt;br /&gt;
2020.01.24 17:12:46.411 3: DbRep Rep.LogDB1.syncStandby - total lines transfered to standby database: 23957&lt;br /&gt;
2020.01.24 17:12:51.710 3: DbRep Rep.LogDB1.syncStandby - total lines transfered to standby database: 24048&lt;br /&gt;
2020.01.24 17:12:57.733 3: DbRep Rep.LogDB1.syncStandby - total lines transfered to standby database: 24092&lt;br /&gt;
2020.01.24 17:13:03.505 3: DbRep Rep.LogDB1.syncStandby - total lines transfered to standby database: 24059&lt;br /&gt;
2020.01.24 17:13:08.891 3: DbRep Rep.LogDB1.syncStandby - total lines transfered to standby database: 23969&lt;br /&gt;
2020.01.24 17:13:13.420 3: DbRep Rep.LogDB1.syncStandby - total lines transfered to standby database: 17871&lt;br /&gt;
2020.01.24 17:13:13.421 3: DbRep Rep.LogDB1.syncStandby - number of lines inserted into &amp;quot;LogStby&amp;quot;: 104&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:stb4.PNG|right|thumb|300px|nur Daten der Devices SMA_Energymeter,MySTP_5000 werden übertragen]]&lt;br /&gt;
Nach dem erfolgreichen Sync-Lauf wird die benötigte Laufzeit und die Anzahl der übertragenen Datensätze in Readings angezeigt.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;aggragation&#039;&#039;&#039; wird gesteuert, in welchen &#039;&#039;&#039;Zeitscheiben&#039;&#039;&#039; die Selektion der Daten aus der Quelldatenbank und die Übertragung ausgeführt wird. Im Standard ohne gesetztes aggregation-Attribut ist es ein Tag. Stehen genügend Ressourcen zur Verfügung, kann dieser Wert auch auf &amp;quot;week&amp;quot; oder &amp;quot;month&amp;quot; gesetzt werden. Der Wert &amp;quot;hour&amp;quot; zur Verkleinerung des Datenpaketes ist ebenfalls möglich. &lt;br /&gt;
&lt;br /&gt;
Bei jedem Lauf wird die Anzahl der eingefügten Datensätze im Reading &#039;&#039;&#039;number_lines_inserted_Standby&#039;&#039;&#039; angezeigt.&lt;br /&gt;
&lt;br /&gt;
Die zu übertragenden Daten können natürlich sehr granular bestimmt werden. Sollen zum Beispiel nur die Daten der Devices SMA_Energymeter und MySTP_5000 übertragen werden, wird das Attribut &#039;&#039;&#039;device&#039;&#039;&#039; entsprechend gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr Rep.LogDB1.syncStandby SMA_Energymeter,MySTP_5000&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin bietet das Attribut &#039;&#039;&#039;reading&#039;&#039;&#039; eine Eingrenzung auf die gewünschten Readings und mit dem Attribut &#039;&#039;&#039;valueFilter&#039;&#039;&#039; kann eine Eingrenzung nur auf bestimmte vorkommende Werte vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
Der Erfolg der Synchronisationsläufe kann sehr einfach mit einem separaten DbRep-Device (mit dem &#039;&#039;&#039;fetchrows&#039;&#039;&#039; Kommando) oder dem Tool phpMyAdmin (nebenstehend) überprüft werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== regelmäßige Ausführung der Synchronisation ====&lt;br /&gt;
&lt;br /&gt;
Ein einfaches AT kann dazu dienen den Synchronisationslauf mit dem Device &#039;&#039;&#039;Rep.LogDB1.syncStandby&#039;&#039;&#039; regelmäßig alle x-Stunden/Minuten auszuführen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Sync.Stby at +*04:00:00 set Rep.LogDB1.syncStandby syncStandby LogStby&lt;br /&gt;
attr At.Sync.Stby room DbLog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ermittlung und Darstellung der täglichen Energieerzeugung eines Wechselrichters ===&lt;br /&gt;
&lt;br /&gt;
Gegeben sei dass die Energiedaten eines Wechselrichters (STP_5000) mit SMAUtils in Verbindung mit SBFSpot in die Datenbank geschrieben werden.&lt;br /&gt;
Neben vielen anderen Werten liefert SMAUtils die Tageserzeugung in kWh als Reading &amp;quot;etoday&amp;quot;. Der Wert dieses Readings wird alle paar Minuten in der Datenbank gespeichert.&lt;br /&gt;
&lt;br /&gt;
Zur Auswertung wird ein DbRep-Device angelegt wie unter [[#Definieren_eines_DbRep-Devices | Definieren eines DbRep-Devices]]) beschrieben (z.B. Rep.etoday.STP_5000).&lt;br /&gt;
&lt;br /&gt;
[[Datei:Rep.STP_5000.configured.PNG|right|thumb|300px|Rep.STP_5000 konfiguriert]]&lt;br /&gt;
&lt;br /&gt;
Es soll die täglich erzeugte Energiemenge beginnend ab dem 01.10.2016 0 Uhr bis zum 13. Oktober angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Rep.etoday.STP_5000 timestamp_begin 2016-10-01 00:00:00&lt;br /&gt;
attr Rep.etoday.STP_5000 timestamp_end 2016-10-13 23:59:59&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es sich um eine tägliche Aggregation handelt (es soll pro Auswertung der Tag von 00:00:00 bis 23:59:59 betrachtet werden) und die Hintergrundverarbeitungszeit dargestellt werden soll, wird eingestellt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Rep.etoday.STP_5000 aggregation day&lt;br /&gt;
attr Rep.etoday.STP_5000 showproctime 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Eingrenzung der auszuwertenden Devices und der dazu gehörigen Readings wird durch die entsprechenden Attribute gewährleistet.&lt;br /&gt;
Es soll nur das Device &amp;quot;STP_5000&amp;quot; mit dem Reading &amp;quot;etoday&amp;quot; berücksichtigt werden. Dazu stellen wir ein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Rep.etoday.STP_5000 reading etoday&lt;br /&gt;
attr Rep.etoday.STP_5000 device STP_5000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
DbRep ist nun grundsätzlich zur Auswertung konfiguriert (siehe Screenshot).&lt;br /&gt;
&lt;br /&gt;
Zur Selektion und Berechnung von numerischen Daten stehen die Funktionen average-, max-, min-, sum- und diffValue zur Verfügung.&lt;br /&gt;
Bei den in diesem Beispiel verwendeten Daten handelt es sich um einen täglich neu erzeugten und über 24 Stunden stetig steigenden Wert.&lt;br /&gt;
Demnach ist für diese Art Daten die Funktion &amp;quot;maxValue&amp;quot; geeignet. Sie gibt den maximalen Wert des Readings im eingestellten Aggregationszeitraum (day) aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Rep.STP_5000.max.PNG|right|thumb|300px|Rep.STP_5000 maxValue]]&lt;br /&gt;
&lt;br /&gt;
Die Berechnung wird ausgeführt durch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set Rep.etoday.STP_5000 maxValue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach kurzer Zeit ist die Berechnung erfolgt (state=done in DeviceOverview). Nach einem Browserrefresh in der Detailansicht sind die erzeugten Readings sichtbar.&lt;br /&gt;
&lt;br /&gt;
Jedes Reading hat einen bestimmten Aufbau. Die Funktion &amp;quot;maxValue&amp;quot; erzeugt Readings folgenden Aufbaus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2016-10-07_18-19-03__STP_5000__etoday__MAX__2016-10-07&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zunächst wird der Timestring &amp;quot;2016-10-07_18-19-03&amp;quot; ausgegeben der in diesem Kontext den höchsten (d.h. letzten) Wert von &amp;quot;etotal&amp;quot; an dem Tag markiert.&lt;br /&gt;
Bei dem Wechselrichter ist es damit auch der Zeitpunkt zu dem die Energieerzeugung eingestellt wurde (in dem Fall 07.10.2016 um 18:19:03).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Anmerkung:&#039;&#039;&#039; Die Notation des Timestrings wurde so gewählt, um die Regeln für in Readings erlaubte Zeichen einzuhalten. Wenn keine auswertbaren Daten vorliegen und berechnet werden konnten, werden Readings mit &amp;quot;-&amp;quot; ausgegeben. Im Beispiel sind es die Tagesaggregate 10.10.-13.10. da diese Tage in der Zukunft liegen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Danach folgt im Reading die Angabe des Devices (STP_5000), des augewerteten Readings (etoday) und der Funktion die dieses Ergebnis ermittelt hat (MAX für maxValue).&lt;br /&gt;
Die letzte Angabe, hier &amp;quot;2016-10-07&amp;quot; definiert den Auswertungszeitraum. In dem Beispiel ist es der 07.10.2016. Würde die Berechnung mit aggregation=week durchgeführt werden, würde man als an dieser Stelle den Auswertungszeitraum &amp;quot;week_39&amp;quot; erhalten, also die Kalenderwoche 39.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um die Auswertungsergebniss etwas benutzerfreundlicher zu gestalten, steht das Attribut &amp;quot;readingNameMap&amp;quot; zur Verfügung. [[Datei:Rep.STP_5000.max.namemap.PNG|right|thumb|300px|Rep.STP_5000 maxValue mit readingNameMap]]&lt;br /&gt;
Im Beispiel setzen wir es auf:   &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Rep.etoday.STP_5000 readingNameMap Tageserzeugung_kWh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein erneuter maxValue-Lauf erzeugt Readings des folgenden Aufbaus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2016-10-01_18-03-13__Tageserzeugung_kWh__2016-10-01   4.9870&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== (regelmäßiges) Löschen von Datenbanksätzen ===&lt;br /&gt;
&lt;br /&gt;
Dieses DbRep-Device dient dazu einmalig oder verbunden mit einem AT-Device Einträge aus einer Datenbank zu löschen.&lt;br /&gt;
Zunächst wird das Device wie im Abschnitt [[#Definieren_eines_DbRep-Devices | &amp;quot;Definieren eines DbRep-Devices&amp;quot;]] beschrieben definiert. &lt;br /&gt;
Dadurch wird das DbRep-Device mit einem DbLog-Device assoziiert und mit der Datenbank des DbLogs verbunden. Alle weiteren Operationen werden mit dieser Datenbank durchgeführt. In diesem Beispiel heißt das DbRep-Device &amp;quot;Rep.Del.DbShort&amp;quot; und das DbLog-Device &amp;quot;LogDBShort&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
In diesem Beispiel sollen alle Datensätze gelöscht werden die älter als 180 Tage sind. Die Löschfunktion des Moduls ist standardmäßig ausgeschaltet und muß per Attribut enabled werden.&lt;br /&gt;
Dazu werden die Attribute                                      [[Datei:Rep.Del.DbShort.PNG|right|thumb|300px|Rep.Del.DbShort konfiguriert]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr Rep.Del.DbShort timeOlderThan d:180&lt;br /&gt;
 attr Rep.Del.DbShort allowDeletion 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
gesetzt. Die Zeitangabe erfolgt in Sekunden.&lt;br /&gt;
&lt;br /&gt;
Insbesondere bei SQLite sollte während des Löschens kein paralleler Schreibprozess in Form des normalen Eventloggings stattfinden. MySQL/MariaDB kann es durchaus parallel verarbeiten. Um einen parallelen Zugriff durch DbLog-Loggging zu verhindern, kann das Logging vor der Löschung geschlossen und danach wieder geöffnet werden.&lt;br /&gt;
Dafür werden die Attribute mit z.B. diesen Werten gesetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr Rep.Del.DbShort executeBeforeProc set LogDBShort reopen 7200&lt;br /&gt;
 attr Rep.Del.DbShort executeAfterProc set LogDBShort reopen&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei ist &amp;quot;LogDB&amp;quot; das mit dem DbRep-Device assoziierte DbLog-Device.&lt;br /&gt;
 &lt;br /&gt;
Der Löschvorgang wird mit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 set Rep.Del.DbShort delEntries&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
gestartet. Nach Abschluß der Datenlöschung wird die Anzahl der deleted rows als Reading ausgegeben und auch im Log mit verbose=3 geschrieben.&lt;br /&gt;
&lt;br /&gt;
Müssen sehr viele Datensätze gelöscht werden, könnte nach 86400 Sekunden der Standardtimeout erreicht werden und der Vorgang mit &amp;quot;error&amp;quot; enden.&lt;br /&gt;
In diesem Fall ist der timout mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr Rep.Del.DbShort timeout &amp;lt;timeout in Sekunden&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
entsprechend angepasst werden.&lt;br /&gt;
&lt;br /&gt;
Ein fhem.cfg Eintrag für das beschriebene Beispieldevice sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Del.DbShort DbRep LogDBShort&lt;br /&gt;
attr Rep.Del.DbShort allowDeletion 1&lt;br /&gt;
attr Rep.Del.DbShort comment löschen aller Einträge in LogDBShort älter als 180 Tage&lt;br /&gt;
attr Rep.Del.DbShort devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Del.DbShort event-on-update-reading state&lt;br /&gt;
attr Rep.Del.DbShort room DbLog&lt;br /&gt;
attr Rep.Del.DbShort timeOlderThan 15552000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Löschung der relevanten Datensätze kann weiterhin über Attribute &amp;quot;device&amp;quot; bzw. &amp;quot;reading&amp;quot; kann selektiv auf bestimmte Device- und/oder Readingloggings beschränkt werden. Wird keine Zeitbeschränkung (z.B. durch &amp;quot;timeOlderThan&amp;quot;) vorgenommen, erfolgt die Löschung aller Datensätze der durch &amp;quot;device&amp;quot; bzw. &amp;quot;reading&amp;quot; spezifizierten Datenbankinhalte.&lt;br /&gt;
&lt;br /&gt;
Als Argument der Attribute &amp;quot;device&amp;quot; bzw. &amp;quot;reading&amp;quot; kann SQL-Wildcard &amp;quot;%&amp;quot; verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%     substituiert ein oder mehrere Zeichen&lt;br /&gt;
_     Platzhalter für ein einzelnes Zeichen&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr Rep.Del.DbShort device %5000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit dieser Spezifikation werden alle Devices gelöscht die auf &amp;quot;5000&amp;quot; enden, also z.B. STP_5000 und MySTP_5000.&lt;br /&gt;
(siehe auch Attribut &amp;quot;reading&amp;quot; in der {{Link2CmdRef|Anker=DbRepattr|Lang=de|Label=Commandref}}).&lt;br /&gt;
&lt;br /&gt;
Ein einfaches AT kann dazu dienen den Löschjob über das Device Rep.Del.DbShort regelmäßig alle x-Stunden/Minuten auszuführen. Dadurch werden nicht mehr benötigte Datenbankeinträge automatisiert und nicht FHEM blockierend im Hintergrund entfernt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Del.DbShort at +*23:45:00 set Rep.Del.DbShort delEntries&lt;br /&gt;
attr At.Del.DbShort room DbLog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== erweiterte Anwendung von Selektionsbedingungen zur Löschung ====&lt;br /&gt;
&lt;br /&gt;
Wie bei allen selektiven Funktionen im DbRep kann auch bei der Löschfunktion über die Attribute &#039;&#039;&#039;device&#039;&#039;&#039; und &#039;&#039;&#039;reading&#039;&#039;&#039; eine Beschränkung der zu löschenden Datensätze erfolgen. D.h. es werden nur Datensätze gelöscht, wenn die Selektionskriterien dieser Attribute erfüllt sind.&lt;br /&gt;
&lt;br /&gt;
Im Attribut &#039;&#039;&#039;device&#039;&#039;&#039; können einzelne Geräte, Geräte-Spezifikationen ({{Link2CmdRef|Anker=devspec|Lang=de|Label=devspec}}) sowie Geräte mit Wildcards angegeben werden.&lt;br /&gt;
Ist eine devspec angegeben, werden die Devicenamen vor der Selektion aus der Geräte-Spezifikationen und den aktuell in FHEM vorhandenen Devices aufgelöst sofern möglich.&lt;br /&gt;
Wird dem Device bzw. der Device-Liste oder Geräte-Spezifikation ein &amp;quot;EXCLUDE=&amp;quot; vorangestellt, werden diese Devices von der Selektion und damit von dem Löschvorgang ausgeschlossen.   &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;name&amp;gt; device TYPE=DbRep                    # es werden nur Datensätze der Geräte vom Modul-Typ &amp;quot;DbRep&amp;quot; &lt;br /&gt;
                                                   eingeschlossen&lt;br /&gt;
attr &amp;lt;name&amp;gt; device MySTP_5000                    # nur Datensätze des Gerätes &amp;quot;MySTP_5000&amp;quot; werden selektiert/gelöscht&lt;br /&gt;
attr &amp;lt;name&amp;gt; device SMA.*,MySTP.*                 # Daten von Geräten die mit &amp;quot;SMA&amp;quot; oder &amp;quot;MySTP&amp;quot; beginnen, werden &lt;br /&gt;
                                                   selektiert/gelöscht&lt;br /&gt;
attr &amp;lt;name&amp;gt; device SMA_Energymeter,MySTP_5000    # nur Daten der beiden angegebenen Geräten werden selektiert/gelöscht&lt;br /&gt;
attr &amp;lt;name&amp;gt; device %5000                         # Daten von Geräten die mit &amp;quot;5000&amp;quot; enden werden in die Operation &lt;br /&gt;
                                                   eingeschlossen&lt;br /&gt;
attr &amp;lt;name&amp;gt; device TYPE=SSCam EXCLUDE=SDS1_SVS   # es werden Datensätze der Geräte vom Modul-Typ &amp;quot;SSCam&amp;quot; eingeschlossen, &lt;br /&gt;
                                                   aber das Gerät &amp;quot;SDS1_SVS&amp;quot; (auch vom Typ SSCam) wird ausgeschlosssen&lt;br /&gt;
attr &amp;lt;name&amp;gt; device EXCLUDE=SDS1_SVS              # Datensätze aller Geräte mit Ausnahme des Gerätes &amp;quot;SDS1_SVS&amp;quot; werden          &lt;br /&gt;
                                                   selektiert/gelöscht&lt;br /&gt;
attr &amp;lt;name&amp;gt; device EXCLUDE=TYPE=SSCam            # Datensätze aller Geräte mit Ausnahme der Geräte vom Typ &amp;quot;SSCam&amp;quot; werden          &lt;br /&gt;
                                                   selektiert/gelöscht&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ähnlich erfolgt die Abgrenzung der DB-Selektionen auf ein bestimmtes oder mehrere Readings sowie exkludieren von Readings. Mehrere Readings werden als Komma separierte Liste angegeben. Es können SQL Wildcard (%) verwendet werden, aber &#039;&#039;&#039;keine Perl-Regex&#039;&#039;&#039;.&lt;br /&gt;
Wird dem Reading bzw. der Reading-Liste ein &amp;quot;EXCLUDE=&amp;quot; vorangestellt, werden diese Readings von der Selektion ausgeschlossen. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;name&amp;gt; reading etotal                                     # Datensätze mit dem Reading &amp;quot;etotal&amp;quot; werden eingeschlossen &lt;br /&gt;
attr &amp;lt;name&amp;gt; reading et%                                        # Datensätze deren Reading mit &amp;quot;et&amp;quot; beginnt werden &lt;br /&gt;
                                                                 eingeschlossen&lt;br /&gt;
attr &amp;lt;name&amp;gt; reading etotal,etoday                              # Datensätze mit den Readings &amp;quot;etotal&amp;quot; und &amp;quot;etoday&amp;quot; werden &lt;br /&gt;
                                                                 in die Selektion eingeschlossen&lt;br /&gt;
attr &amp;lt;name&amp;gt; reading eto%,Einspeisung EXCLUDE=etoday            # Datensätze mit Readings beginnend mit &amp;quot;eto&amp;quot; sowie das &lt;br /&gt;
                                                                 Reading &amp;quot;Einspeisung&amp;quot; werden selektiert, aber das Reading &lt;br /&gt;
                                                                 &amp;quot;etoday&amp;quot; wiederum ausgeschlossen&lt;br /&gt;
attr &amp;lt;name&amp;gt; reading etotal,etoday,Ein% EXCLUDE=%Wirkleistung   # Datensätze mit Readings beginnend mit &amp;quot;Ein&amp;quot; sowie die &lt;br /&gt;
                                                                 Readings &amp;quot;etotal&amp;quot; und &amp;quot;etoday&amp;quot; werden selektiert, wobei &lt;br /&gt;
                                                                 Readings, die auf &amp;quot;Wirkleistung&amp;quot; enden, von der Löschung&lt;br /&gt;
                                                                 ausgeschlossen werden&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Natürlich werden die Selektionsbedingungen durch eventuell gesetzte Zeiteingrenzungen mit den time*- Attributen ergänzt.&lt;br /&gt;
Die time*- Attribute sind mehrere im DbRep vorhandene Attribute, die alle mit &amp;quot;time&amp;quot; beginnen, z.B. timeOlderThan.&lt;br /&gt;
&lt;br /&gt;
=== Auffinden von alten Devicenamen in der DB und versenden/loggen einer Negativliste ===&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datenbank längere Zeit gelaufen ist, Devices in FHEM hinzugefügt, geändert oder gelöscht wurden oder auch das DEF des DbLog-Devices angepasst wurde, befinden sich aller Wahrscheinlichkeit nach nicht mehr gewünschte/gebrauchte Datensätze von nicht mehr bestehenden Devices in der Datenbank.&lt;br /&gt;
&lt;br /&gt;
Dieses Beispiel soll einen Weg zeigen, wie man mit Hilfe der DbRep-sqlCmd Funktion (ab Version 4.14.0) alle in der DB enthältenen Devicenamen ermitteln und mit einer Positivliste vergleichen kann. &lt;br /&gt;
Die Negativliste der nicht gewünschten Devices wird im Logfile ausgegeben bzw. mit TelegramBot versendet.&lt;br /&gt;
&lt;br /&gt;
Zunächst wird das Device wieder wie im Abschnitt [[#Definieren_eines_DbRep-Devices | &amp;quot;Definieren eines DbRep-Devices&amp;quot;]] beschrieben definiert. &lt;br /&gt;
Dadurch wird das DbRep-Device mit einem DbLog-Device assoziiert und mit der Datenbank des DbLog-Device verbunden. In diesem Beispiel heißt das DbRep-Device &amp;quot;Report&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Nach der Definition setzen wir die Attribute:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Report event-on-update-reading state&lt;br /&gt;
attr Report sqlResultFormat separated&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es werden nun nur noch Events für &amp;quot;state&amp;quot; generiert. Das Attribut &amp;quot;sqlResultFormat = separated&amp;quot; bewirkt, dass das Ergebnis des SQL-Statements zeilenweise in Einzelreadings zur Verfügung gestellt wird.&lt;br /&gt;
&lt;br /&gt;
Nun kann getestet werden, ob die Abfrage grundsätzlich funktioniert. Dazu wird das benutzerspezifische Kommando &amp;quot;sqlCmd&amp;quot; verwendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set Report sqlCmd select device, count(*) from history group by DEVICE;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sollte nun eine entsprechende Anzahl von Readings erzeugt werden (Browserrefresh), die als Wert eine Kombination aus &amp;lt;Device&amp;gt;|&amp;lt;Anzahl Datensätze in DB&amp;gt; enthalten wie im nebenstehenden Screenshot ersichtlich.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sqlCmd.PNG|right|thumb|300px|sqlCmd ausgeführt]]&lt;br /&gt;
&lt;br /&gt;
Wenn das Ergebnis wie gewünscht vorliegt, wird nun die Benutzerschnittstelle aktiviert.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Report userExitFn NaDevs .*:.*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;NaDevs&amp;quot; ist die Funktion in 99_myUtils.pm die aufgerufen werden soll. Die Angabe des Regex &amp;quot;.*:.*&amp;quot; ist optional. Nähere Informationen zur Funktionsweise sind in der {{Link2CmdRef|Lang=de|Anker=DbRep}} zu finden.&lt;br /&gt;
&lt;br /&gt;
Die &amp;quot;Positivliste&amp;quot; der in der Datenbank erlaubten Devices wird für das Beispiel in dem Attribut &amp;quot;comment&amp;quot; für den späteren Vergleich als String angegeben. Es ist natürlich auch z.B. eine Ableitung der im DEF-Regex des zugeordneten DbLog-Devices enthaltenen Device-Definitionen vorstellbar, sodass immer der aktuelle Stand dieser Definition als Grundlage für den Vergleich herangezogen wird. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Report comment (sysmon|MyWetter|SMA_Energymeter|STP_5000|Cam.*)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Somit werden die Devices &amp;quot;sysmon&amp;quot;, &amp;quot;MyWetter&amp;quot;, &amp;quot;SMA_Energymeter&amp;quot;, &amp;quot;STP_5000&amp;quot; und alle Cam-Devices als in der DB erlaubt definiert.&lt;br /&gt;
Alle anderen gefundenen Devices sollen in einer Negativliste aufgeführt werden.&lt;br /&gt;
&lt;br /&gt;
Im weiteren Schritt wird die aufzurufende Funktion in der vorhandenen 99_myUtils.pm ergänzt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
# $Id: myUtilsTemplate.pm 7570 2015-01-14 18:31:44Z rudolfkoenig $&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_myUtils.pm, and create your own functions in the new&lt;br /&gt;
# file. They are then available in every Perl expression.&lt;br /&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;
sub&lt;br /&gt;
myUtils_Initialize($$)&lt;br /&gt;
{&lt;br /&gt;
  my ($hash) = @_;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Enter you functions below _this_ line.&lt;br /&gt;
&lt;br /&gt;
my @dna;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
######################################################&lt;br /&gt;
########    Not allowed Devs in DB ermitteln&lt;br /&gt;
########          UserExitFn in DbRep           &lt;br /&gt;
######################################################&lt;br /&gt;
sub NaDevs {&lt;br /&gt;
 my ($name,$reading,$value) = @_;&lt;br /&gt;
 my $hash   = $defs{$name};&lt;br /&gt;
 &lt;br /&gt;
 # DB Namen ermitteln&lt;br /&gt;
 my $dbconn = $hash-&amp;gt;{dbloghash}{dbconn};&lt;br /&gt;
 my $db = (split(&amp;quot;=&amp;quot;,(split(&amp;quot;;&amp;quot;,$dbconn))[0]))[1];&lt;br /&gt;
 &lt;br /&gt;
 # Liste der erlaubten Devices aus Attribut &amp;quot;comment&amp;quot; lesen&lt;br /&gt;
 my $adevs = AttrVal($name, &amp;quot;comment&amp;quot;,&amp;quot;-&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 if($reading eq &amp;quot;state&amp;quot; &amp;amp;&amp;amp; $value eq &amp;quot;running&amp;quot;) {&lt;br /&gt;
     # der Select wurde gestartet&lt;br /&gt;
     Log3 $name, 1, &amp;quot;UserExitFn called by $name - new Select has been startet. Allowed devices in database are: $adevs&amp;quot;; &lt;br /&gt;
     @dna=();&lt;br /&gt;
     return;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 my $d = (split(&amp;quot;\\|&amp;quot;,$value))[0];&lt;br /&gt;
 &lt;br /&gt;
 # das Selektionsergebnis bewerten und ggf. dem Ergebnisarray hinzufügen&lt;br /&gt;
 if ( $reading =~ m/SqlResultRow.*/ &amp;amp;&amp;amp; $d !~ m/$adevs/) {&lt;br /&gt;
   push(@dna,$d.&amp;quot;\n&amp;quot;)&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 if ($reading eq &amp;quot;state&amp;quot; &amp;amp;&amp;amp; $value eq &amp;quot;done&amp;quot;) {&lt;br /&gt;
     # Ergebnis versenden bzw. loggen&lt;br /&gt;
     Log3 $name, 1, &amp;quot;UserExitFn called by $name - Devices not allowd found in $db: @dna&amp;quot;; &lt;br /&gt;
     fhem(&amp;quot;set teleBot message Devices are not allowed found in $db: \n @dna&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Schnittstelle übergibt der aufgerufenen Funktion den Namen des DbRep-Devices, den Namen des erstellten Readings und dessen Wert.&lt;br /&gt;
Der Aufruf erfolgt nach jeder Readingserstellung. Die Schnittstelle arbeitet OHNE Eventgenerierung bzw. benötigt keine Events.&lt;br /&gt;
Über den Namen des DbRep-Devices kann auf dessen Hash zugegriffen werden bzw. über $hash-&amp;gt;{dbloghash}{...} ebenfalls auf den Hash des angeschlossenen DbLog-Devices.&lt;br /&gt;
&lt;br /&gt;
In der Funktion &amp;quot;NaDevs&amp;quot; wird der Device-Teilstring des erzeugten Readings mit dem Wertevorrat aus dem &amp;quot;comment&amp;quot;-Attribut verglichen und bei einem negativen Ergebnis der Negativliste @dna hinzugefügt.&lt;br /&gt;
&lt;br /&gt;
Nach Abschluss der Operation (signalisiert durch Reading &amp;quot;state = done&amp;quot;) wird die erzeugte Liste im Logfile ausgegeben bzw. ein TelgramBot-Device versendet.&lt;br /&gt;
&lt;br /&gt;
=== Größe der FHEM-Datenbank ermitteln ===&lt;br /&gt;
&lt;br /&gt;
Zunächst wird das Device wie im Abschnitt [[#Definieren_eines_DbRep-Devices | &amp;quot;Definieren eines DbRep-Devices&amp;quot;]] beschrieben definiert. &lt;br /&gt;
Dadurch wird das DbRep-Device mit einem DbLog-Device assoziiert und mit der Datenbank des DbLogs verbunden. Alle weiteren Operationen werden mit dieser Datenbank durchgeführt. In diesem Beispiel heißt das DbRep-Device &amp;quot;Rep.Fhem.Size&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Um die Größe der Datenbank beziehungsweise der Tabellen &amp;quot;history&amp;quot; und &amp;quot;current&amp;quot; zu ermitteln steht das Kommando:&lt;br /&gt;
                                                                        [[Datei:tableinfo.PNG|right|thumb|300px|get Rep.Fhem.Size tableinfo]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 get Rep.Fhem.Size tableinfo  (MySQL, PostgreSQL)&lt;br /&gt;
 get Rep.Fhem.Size svrinfo    (SQLite)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
zur Verfügung. &lt;br /&gt;
&lt;br /&gt;
Mit diesem Befehl werden sehr viele Informationen bezüglich der Tabellen des FHEM-Schemas (MySQL) als Readings ausgegeben.&lt;br /&gt;
&lt;br /&gt;
Um nur die relevanten bzw. interessierenden Selektionsergebnisse auszugeben, kann mit dem Attribut showTableInfo (MySQL, PostgreSQL) bzw. showSvrInfo (SQLite) eine kommaseparierte Liste der relevanten Tabellen angegeben werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Rep.Fhem.Size showTableInfo %history%,%current%    (MySQL, PostgreSQL)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wie in diesem Beispiel gesetzt, werden nur Informationen der Tabellen &amp;quot;history&amp;quot; und &amp;quot;current&amp;quot; ausgegeben.&lt;br /&gt;
Diese Ausgabe ich bereits recht übersichtlich, kann aber durch die Verwendung des Attributs suppressReading&lt;br /&gt;
weiter eingegrenzt werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Rep.Fhem.Size suppressReading ^(?!.*INFO_history.data_index_length_MB).*$&lt;br /&gt;
attr Rep.Fhem.Size suppressReading ^(?!.*(INFO_history.data_index_length_MB)|(state)).*$&lt;br /&gt;
attr Rep.Fhem.Size suppressReading ^(?!.*(INFO_history.data_index_length_MB)|(background_processing_time)|(state)).*$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit diesen Attributwerten wird nur das Reading &amp;quot;INFO_history.data_index_length_MB&amp;quot; oder aber &amp;quot;INFO_history.data_index_length_MB&amp;quot;&lt;br /&gt;
und &amp;quot;state&amp;quot; bzw. &amp;quot;INFO_history.data_index_length_MB&amp;quot;, &amp;quot;state&amp;quot; und &amp;quot;background_processing_time&amp;quot; dargestellt.&lt;br /&gt;
&lt;br /&gt;
Die Datenbankgröße (MB) ist je nach DB-Typ in den Readings:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
INFO_current.data_index_lenth_MB&lt;br /&gt;
INFO_history.data_index_lenth_MB&lt;br /&gt;
SQLITE_FILE_SIZE_MB&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
enhalten. &lt;br /&gt;
&lt;br /&gt;
Wird z.B. über ein AT dieser Befehl regelmäßig durch Rep.Fhem.Size ausgeführt und die Ergebnisse wiederum in DbLog gespeichert kann die Größenentwicklung der Datenbank mittels SVG-Diagrammen dargestellt werden.                                                                            [[Datei:tableinfo_SVG.PNG|left|thumb|300px|get Rep.Fhem.Size tableinfo]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
=== Readingwerte von DbRep in ein anderes Device übertragen ===&lt;br /&gt;
&lt;br /&gt;
Um Readings aus DbRep in einen Dummy zu übertragen, können verschiedene Verfahren angewendet werden. Allen Verfahren ist gemeinsam, dass sie auf die Arbeitsweise der Funktionen von DbRep Rücksicht nehmen. Alle Funktionen von DbRep arbeiten, von Ausnahmen abgesehen, asynchron (non-blocking). Das hat den Vorteil, dass die Datenbankverarbeitungszeit bzw. eine Nichtverfügbarkeit der DB nicht hemmend auf FHEM wirkt, hat andererseits aber den Nachteil, dass die Ergebnisse einer Funktion nicht direkt nach dem Funktionsaufruf zur Verfügung stehen und somit nicht trivial innerhalb der FHEM-Hauptschleife weiterverarbeitet werden können.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Werte automatisch durch DbRep übertragen lassen (ab Version 8.40.0) ====&lt;br /&gt;
&lt;br /&gt;
Ab DbRep Version 8.40.0 gibt es das Attribut &#039;&#039;&#039;autoForward&#039;&#039;&#039; mit dem eine integrierte Übertragung der DbRep-Ergebnissreadings in andere Devices (z.B. Dummy) eingerichtet werden kann. Diese Variante wird hier beschrieben.&lt;br /&gt;
&lt;br /&gt;
Die weiteren manuellen Varianten werden in den nachfolgenden Abschnitten behandelt.&lt;br /&gt;
&lt;br /&gt;
Um die integrierte Reading-Weiterleitung zu aktivieren wird des Attribut autoForward nach folgender Systematik gesetzt:&lt;br /&gt;
[[Datei:aforw1.PNG|right|thumb|300px|Übertragung aller Readings nach Dum.Rep.all]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;&amp;lt;source-reading&amp;gt; =&amp;gt; &amp;quot;&amp;lt;destination device&amp;gt; [=&amp;gt; &amp;lt;destination-reading&amp;gt;]&amp;quot;,&lt;br /&gt;
  &amp;quot;&amp;lt;source-reading&amp;gt; =&amp;gt; &amp;quot;&amp;lt;destination device&amp;gt; [=&amp;gt; &amp;lt;destination-reading&amp;gt;]&amp;quot;,&lt;br /&gt;
  ...&lt;br /&gt;
}          &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Datei:aforw2.PNG|right|thumb|300px|Übertragung Readings mit &amp;quot;SUM&amp;quot; nach Dum.Rep.Sum]]&lt;br /&gt;
In der Spezifikation von &#039;&#039;&#039;&amp;lt;source-reading&amp;gt;&#039;&#039;&#039; können Wildcards (.*) verwendet werden um nur eine Auswahl der erzeugten Readings an das Zieldevice &#039;&#039;&#039;&amp;lt;destination device&amp;gt;&#039;&#039;&#039; weiterzuleiten. Ist der optionale Zusatz &#039;&#039;&#039;&amp;lt;destination-reading&amp;gt;&#039;&#039;&#039; angegeben, erfolgt die Speicherung der übertragenen Readings im Zieldevice mit dem angegebenen Namen. &amp;lt;br&amp;gt;&lt;br /&gt;
Der angegebene Readingname muss den Regularien zur Namensgebung von Readings genügen. Eventuell vorhandene nicht erlaubte Zeichen werden durch &amp;quot;_&amp;quot; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Fehlt der Zusatz &amp;lt;destination-reading&amp;gt;, werden die in DbRep erzeugten Readings 1:1 in das Zieldevice übertragen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr DbRepDev autoForward {&lt;br /&gt;
                            &amp;quot;.*&amp;quot;        =&amp;gt; &amp;quot;Dum.Rep.All&amp;quot;,     &lt;br /&gt;
                            &amp;quot;.*AVGAM.*&amp;quot; =&amp;gt; &amp;quot;Dum.Rep     =&amp;gt; average&amp;quot;,&lt;br /&gt;
                            &amp;quot;.*SUM.*&amp;quot;   =&amp;gt; &amp;quot;Dum.Rep.Sum =&amp;gt; summary&amp;quot;,&lt;br /&gt;
                          }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Spezifikation erfüllt folgende Ziele:&lt;br /&gt;
&lt;br /&gt;
# alle Readings werden zum Device &amp;quot;Dum.Rep.All&amp;quot; übertragen, der ursprüngliche Readingname bleibt im Ziel erhalten (Screenshot 1)&lt;br /&gt;
# Readings mit &amp;quot;AVGAM&amp;quot; im Namen werden zum Device &amp;quot;Dum.Rep&amp;quot; in das Reading &amp;quot;average&amp;quot; übertragen&lt;br /&gt;
# Readings mit &amp;quot;SUM&amp;quot; im Namen werden zum Device &amp;quot;Dum.Rep.Sum&amp;quot; in das Reading &amp;quot;summary&amp;quot; übertragen (Screenshot 2)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Werte mittels Event übetragen ====&lt;br /&gt;
&lt;br /&gt;
Es sollen zum Beispiel die erzeugten Readings aus einem DbRep-Device in einen Dummy übetragen werden, die den Term &amp;quot;Grid&amp;quot; im Wortstamm tragen.&lt;br /&gt;
&lt;br /&gt;
Ein Reading-Name der fetchrows-Funktion in DbRep ist immer nach folgendem Schema aufgebaut:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt;__&amp;lt;Unique-Index&amp;gt;__&amp;lt;Device&amp;gt;__&amp;lt;Reading&amp;gt;__&amp;lt;Dopplerindex&amp;gt;&lt;br /&gt;
 z.B.: 2018-10-14_18-30-25__1__MyWetter__humidity&lt;br /&gt;
&lt;br /&gt;
Datum und Zeit entsprechen dem Timestamp des gespeicherten Events in der Datenbank. Der Unique-Index identifiziert eventuell vorhandene Doubletten in der DB und der Dopplerindex ist ein Hilfsmittel, Datensätze die sich allein durch den Value-Wert unterscheiden, auch als unterschiedliche Readings erstellen zu können. Dieser Index wird nur bei Bedarf erstellt. &lt;br /&gt;
&lt;br /&gt;
Im folgenden Beispiel werden alle erzeugten Readings mit &amp;quot;Grid&amp;quot; im Namen des DbRep-Devices &amp;quot;Rep.SMAEM&amp;quot; in den Dummy übertragen und heißen dann genauso. Zunächst wird der Dummy angelegt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Dum.Rep dummy&lt;br /&gt;
attr Dum.Rep room DbLog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit dem nachfolgend angelegten Notify wird auf die z.B. von fetchrows erzeugten Events reagiert, der Event entsprechend gesplittet und verarbeitet in den Dummy übertragen. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define N.Dum.Rep notify Rep.SMAEM:(\d).*Grid.* { fhem &amp;quot;setreading Dum.Rep &amp;quot;.(split(&amp;quot;:&amp;quot;,$EVTPART0))[0].&amp;quot; $EVTPART1&amp;quot;}&lt;br /&gt;
attr N.Dum.Rep room DbLog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soll im Dummy ein Reading mit eigenem Namen gefüllt werden, sieht das Notify z.B. so aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define N.Dum.Rep notify Rep.SMAEM:(\d).*Grid.* { fhem &amp;quot;setreading Dum.Rep DeinReading&amp;quot;.&amp;quot; $EVTPART1&amp;quot;}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Werte mittels Funktion DbReadingsVal übertragen ====&lt;br /&gt;
&lt;br /&gt;
Sobald ein DbRep-Device definiert ist, wird die Funktion DbReadingsVal zur Verfügung gestellt. Mit dieser Funktion läßt sich, ähnlich dem allgemeinen ReadingsVal, der Wert eines Readings aus der Datenbank abrufen.  Die Befehlssyntax ist:&lt;br /&gt;
&lt;br /&gt;
    DbReadingsVal(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;,&amp;quot;&amp;lt;device:reading&amp;gt;&amp;quot;,&amp;quot;&amp;lt;timestamp&amp;gt;&amp;quot;,&amp;quot;&amp;lt;default&amp;gt;&amp;quot;) &lt;br /&gt;
&lt;br /&gt;
Mit dieser Funktion kann ein Device/Reading-Wert aus der Datenbank gelesen und in einen Dummy gesetzt werden. &amp;quot;Name&amp;quot; ist dabei das abzufragende DbRep-Device. &lt;br /&gt;
Der Timestamp muss nicht genau bekannt sein. Es wird der zeitlich zu &amp;lt;timestamp&amp;gt; passendste Readingwert zurück geliefert, falls kein Wert exakt zu dem angegebenen Zeitpunkt geloggt wurde. &lt;br /&gt;
Um den aktuellsten in der Datenbank gespeicherten Wert eines Readings abzurufen, kann als Timestamp die aktuelle Zeit entsprechend formatiert verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Es soll z.B. der aktuellste Datenbankwert des Readings &amp;quot;etoday&amp;quot; vom Device &amp;quot;MySTP_5000&amp;quot; ausgelesen und im Dummy &amp;quot;Dum.Rep&amp;quot; als Reading &amp;quot;EnergyToday&amp;quot; gespeichert werden. Das beteilgte DbRep-Device heißt &amp;quot;Rep.Energy&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Für die Formatierung des aktuellen Timestamps kann die FHEM-Funktion FmtDateTime verwendet werden, welcher der aktuelle UNIX-Timestamp übergeben wird:&lt;br /&gt;
&lt;br /&gt;
 FmtDateTime(time)&lt;br /&gt;
&lt;br /&gt;
Der Datenabruf aus der Datenbank sieht dann folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
 DbReadingsVal(&amp;quot;Rep.Energy&amp;quot;,&amp;quot;MySTP_5000:etoday&amp;quot;,FmtDateTime(time),&amp;quot;&amp;quot;) &lt;br /&gt;
&lt;br /&gt;
Mit dem Befehl setreading kann der abgerufene Wert in dem Dummy-Device gespeichert werden:&lt;br /&gt;
&lt;br /&gt;
 { fhem &amp;quot;setreading Dum.Rep EnergyToday &amp;quot;.DbReadingsVal(&amp;quot;Rep.Energy&amp;quot;,&amp;quot;MySTP_5000:etoday&amp;quot;,FmtDateTime(time),&amp;quot;&amp;quot;) }&lt;br /&gt;
&lt;br /&gt;
Damit der Datenabruf regelmäßig erfolgt und immer der aktuellste Wert von &amp;quot;etoday&amp;quot; in den Dummy eingtragen wird, kann dieses AT verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 define set.Dum.Rep_EnergyToday at +*00:01:00 { fhem &amp;quot;setreading Dum.Rep EnergyToday &amp;quot;.DbReadingsVal(&amp;quot;Rep.Energy&amp;quot;,&amp;quot;MySTP_5000:etoday&amp;quot;,FmtDateTime(time),&amp;quot;&amp;quot;) }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Somit erfogt eine Aktualisierung des Readings &amp;quot;EnergyToday&amp;quot; im Dummy &amp;quot;Dum.Rep&amp;quot; jede Minute.&lt;br /&gt;
Es ist zu beachten, dass die Funktionsausführung von DbReadingsVal blockierend erfolgt. Sollte die Datenbank nicht verfügbar sein oder lange Antwortzeiten besitzen, hat dies negative Auswirkungen auf FHEM, was sich in Blockierungszuständen äußert.&lt;br /&gt;
Möchte man solche eventuell möglichen Zustände vermeiden, kann die Befehlsausführung in die 99_myUtils unter Verwendung von [[Blocking_Call | Blocking Call]] ausgelagert werden.&lt;br /&gt;
&lt;br /&gt;
Diese non-blocking Variante der Verwendung von DbReadingsVal wird nachfolgend skizziert.&lt;br /&gt;
In der 99_myUtils wird dazu der nachfolgende Code eingefügt, der drei kleine Subroutinen enthält:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################################################&lt;br /&gt;
#         DumRepEnergyToday (Reading mittels DbReadingsVal non-blocking setzen)    &lt;br /&gt;
############################################################################################################&lt;br /&gt;
sub DumRepEnergyToday ($$$$$) {&lt;br /&gt;
 # initiale Routine zum Aufruf von BlockingCall unter Berücksichtigung von &amp;quot;RUNNING_SET_READING&amp;quot;&lt;br /&gt;
 my ($name,$device,$reading,$destdev,$destread) = @_;&lt;br /&gt;
 my $hash = $defs{$name};&lt;br /&gt;
&lt;br /&gt;
 return if($hash-&amp;gt;{HELPER}{RUNNING_SET_READING});&lt;br /&gt;
 $hash-&amp;gt;{HELPER}{RUNNING_SET_READING} = BlockingCall(&amp;quot;DumRepEnergyTodayNbl&amp;quot;, &amp;quot;$name|$device|$reading|$destdev|$destread&amp;quot;, &amp;quot;DumRepEnergyTodayNblDone&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub DumRepEnergyTodayNbl($) {&lt;br /&gt;
 # die eigentliche Routine in der die potentiell blockierende Funktion ausgeführt wird&lt;br /&gt;
 my ($string) = @_;&lt;br /&gt;
 my ($name,$device,$reading,$destdev,$destread) = split(&amp;quot;\\|&amp;quot;, $string);&lt;br /&gt;
 my $hash = $defs{$name};&lt;br /&gt;
&lt;br /&gt;
 my $val = DbReadingsVal($name,&amp;quot;$device:$reading&amp;quot;,FmtDateTime(time),&amp;quot;&amp;quot;);&lt;br /&gt;
 $val = encode_base64($val,&amp;quot;&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
return &amp;quot;$name|$val|$destdev|$destread&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub DumRepEnergyTodayNblDone($) {&lt;br /&gt;
 # Rückkherfunktion zur Ergebnisauswertung und Löschen von &amp;quot;RUNNING_SET_READING&amp;quot;&lt;br /&gt;
 my ($string) = @_;&lt;br /&gt;
 my @a    = split(&amp;quot;\\|&amp;quot;,$string);&lt;br /&gt;
 my $hash = $defs{$a[0]};&lt;br /&gt;
 my $name = $hash-&amp;gt;{NAME};&lt;br /&gt;
 my $val  = decode_base64($a[1]);&lt;br /&gt;
 my $destdev  = $a[2];&lt;br /&gt;
 my $destread = $a[3];&lt;br /&gt;
 &lt;br /&gt;
 fhem &amp;quot;setreading $destdev $destread $val&amp;quot;;&lt;br /&gt;
 delete $hash-&amp;gt;{HELPER}{RUNNING_SET_READING};&lt;br /&gt;
 &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der oben gezeigte Code stellt die einfachste Form der BlockingCall-Implementierung dar. Weitere Informationen dazu sind im weiter oben angegebenen Link zum BlockingCall-Wiki enthalten.&lt;br /&gt;
&lt;br /&gt;
Um non-blocking Funktion aufzurufen, ist das bereits beschriebene AT-Device wie folgt zu ändern:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define set.Dum.Rep_EnergyTodayNbl at +*00:01:00 { DumRepEnergyToday(&amp;quot;Rep.Energy&amp;quot;,&amp;quot;MySTP_5000&amp;quot;,&amp;quot;etoday&amp;quot;,&amp;quot;Dum.Rep&amp;quot;,&amp;quot;EnergyToday&amp;quot;) }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der aufgerufenen Funktion &amp;quot;DumRepEnergyToday&amp;quot; werden hierbei der Name des abzufragenden DbRep-Devices, der Name des auszuwertenden Devices, der Name des auszuwertenden Readings sowie das Ziel-Device und das Ziel-Reading als Argumente mitgegeben. Dieser Aufruf kann dadurch universell zum Abruf und Setzen verschiedener auszuwertender Device/Reading-Kombinationen verwendet werden.&lt;br /&gt;
&lt;br /&gt;
=== Ein Userreading anlegen und für stateformat verwenden ===&lt;br /&gt;
&lt;br /&gt;
Eine Besonderheit beim Modul DbRep besteht darin, dass sich die Namen der generierten Readings ändern können. Dadurch kann man für die Erstellung eines eigenen Userreading nicht einfach den Namen eines erstellten Readings, z.B. in der Funktion ReadingsVal, verwenden um dessen Wert zu ermitteln.&lt;br /&gt;
&lt;br /&gt;
Eine Möglichkeit besteht darin eine Funktion in 99_myUtils anzulegen und mit dem Attribut &amp;quot;userExitFn&amp;quot; diese Funktion zu aktivieren/zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Für das Beispiel soll ein Reading &amp;quot;power_max&amp;quot; für den erreichten Maximalwert im Monat und der Timestamp des Maximalwertes aus einem Beispielreading &amp;quot;2018-06-01_13-23-02__STP_5000__total_pac__MAX__no_aggregation&amp;quot; (Name kann sich durch das jeweilige Datum ändern) extrahiert werden.&lt;br /&gt;
&lt;br /&gt;
Zunächst wird die Funktion &amp;quot;calcpomax&amp;quot; in 99_myUtils angelegt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################################################&lt;br /&gt;
########           power_max in DbRep erstellen   &lt;br /&gt;
############################################################################################################&lt;br /&gt;
sub calcpomax {&lt;br /&gt;
 my ($name,$reading,$value) = @_;&lt;br /&gt;
 my $hash = $defs{$name};&lt;br /&gt;
 &lt;br /&gt;
 if($reading =~ /^.*total_pac__MAX.*$/) {&lt;br /&gt;
     $reading =~ /^(\d+)-(\d+)-(\d+)_(\d+)-(\d+)-(\d+)_.*$/;&lt;br /&gt;
     my $pmts = &amp;quot;$3.$2.$1 $4:$5:$6&amp;quot;;&lt;br /&gt;
     my $fmtDateTime = FmtDateTime(gettimeofday());&lt;br /&gt;
     setReadingsVal($hash,&amp;quot;power_max&amp;quot;,$value,$fmtDateTime);&lt;br /&gt;
     setReadingsVal($hash,&amp;quot;power_max_ts&amp;quot;,$pmts,$fmtDateTime);&lt;br /&gt;
 }&lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie in der Commandref zu {{Link2CmdRef|Anker=DbRep|Lang=de|Label=DbRep}} zu lesen ist, werden der im Attribut &amp;quot;userExitFn&amp;quot; hinterlegten Funktion jeweils der Name des aufrufenden Devices, das Reading und dessen Wert übergeben. Mit ein paar Zeilen Code wird der übergebene Readingsname auf das Vorhandensein des statischen Namensteils (total_pac__MAX) geprüft und dementsprechend der Readingname &amp;quot;power_max&amp;quot; mit dem Wert angelegt, wenn der Regex auf den Readingnamen matched.&lt;br /&gt;
Gleiches gilt für das Reading &amp;quot;power_max_ts&amp;quot;, welches den Zeitpunkt des erreichten Maximalwertes enthalten soll.&lt;br /&gt;
&lt;br /&gt;
Die Aktivierung der Schnittstelle erfolgt im DbRep-Device mit &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;name&amp;gt; userExitFn calcpomax .*:.*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit jedem Lauf von &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set &amp;lt;name&amp;gt; maxvalue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wird nun das neue Reading mit angelegt und kann z.B. in einem stateformat verwendet werden:  &lt;br /&gt;
 [[Datei:Rep.powmax.PNG|right|thumb|500px|]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;name&amp;gt; stateformat&lt;br /&gt;
{  &lt;br /&gt;
 if(ReadingsVal($name,&amp;quot;power_max&amp;quot;,0)) {&lt;br /&gt;
   (ReadingsVal($name,&amp;quot;power_max&amp;quot;,0)*1000).&amp;quot; Watt (erreicht am &amp;quot;.ReadingsVal($name,&amp;quot;power_max_ts&amp;quot;,&amp;quot;&amp;quot;).&amp;quot;)&amp;quot;;&lt;br /&gt;
 } else {&lt;br /&gt;
   ReadingsVal($name,&amp;quot;state&amp;quot;,&amp;quot;done&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nachfolgend noch die Definition des verwendeten DbRep-Devices für diese Auswertung:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod Rep.total_pac.currmonth DbRep LogDB&lt;br /&gt;
attr Rep.total_pac.currmonth aggregation no&lt;br /&gt;
attr Rep.total_pac.currmonth alias Peak WR-Leistung aktueller Monat&lt;br /&gt;
attr Rep.total_pac.currmonth allowDeletion 0&lt;br /&gt;
attr Rep.total_pac.currmonth devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.total_pac.currmonth device STP_5000&lt;br /&gt;
attr Rep.total_pac.currmonth disable 0&lt;br /&gt;
attr Rep.total_pac.currmonth event-on-update-reading state&lt;br /&gt;
attr Rep.total_pac.currmonth group SMA Inverter&lt;br /&gt;
attr Rep.total_pac.currmonth reading total_pac&lt;br /&gt;
attr Rep.total_pac.currmonth room Energie&lt;br /&gt;
attr Rep.total_pac.currmonth showproctime 1&lt;br /&gt;
attr Rep.total_pac.currmonth stateFormat {  \&lt;br /&gt;
 if(ReadingsVal($name,&amp;quot;power_max&amp;quot;,0)) {\&lt;br /&gt;
   (ReadingsVal($name,&amp;quot;power_max&amp;quot;,0)*1000).&amp;quot; Watt (erreicht am &amp;quot;.ReadingsVal($name,&amp;quot;power_max_ts&amp;quot;,&amp;quot;&amp;quot;).&amp;quot;)&amp;quot;;;\&lt;br /&gt;
 } else {\&lt;br /&gt;
   ReadingsVal($name,&amp;quot;state&amp;quot;,&amp;quot;done&amp;quot;);;\&lt;br /&gt;
 }\&lt;br /&gt;
}&lt;br /&gt;
attr Rep.total_pac.currmonth timestamp_begin current_month_begin&lt;br /&gt;
attr Rep.total_pac.currmonth timestamp_end current_month_end&lt;br /&gt;
attr Rep.total_pac.currmonth userExitFn calcpomax .*:.*&lt;br /&gt;
attr Rep.total_pac.currmonth verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== datenbankgestützte Erstellung der Energiebilanz einer SMA PV-Anlage mit Überschußeinspeisung ===&lt;br /&gt;
[[datenbankgestützte Erstellung der Energiebilanz einer SMA PV-Anlage mit Überschußeinspeisung | Hier]] geht&#039;s zum Beitrag.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== DbRep-Kommandos regelmäßig mit einem at-Device ausführen ===&lt;br /&gt;
&lt;br /&gt;
Sollen DbRep-Kommandos regelmäßig zu bestimmten Zeiten bzw. Intervallen ausgeführt werden, kann ein at-Device (alternativ z.B. DOIF) dafür definiert und verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Als Beispiel soll die regelmäßige Ausführung des SQL-Statements &lt;br /&gt;
&lt;br /&gt;
 select device, count(*) from history group by DEVICE&lt;br /&gt;
&lt;br /&gt;
über das Set-Kommando &#039;&#039;&#039;sqlCmd&#039;&#039;&#039; dienen.&lt;br /&gt;
&lt;br /&gt;
Zunächst wird das DbRep-Device definiert welches zur Ausführung des Kommandos dienen soll.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.LogDB.sqlResult DbRep LogDB&lt;br /&gt;
attr Rep.LogDB.sqlResult devStateIcon initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.LogDB.sqlResult event-on-update-reading state&lt;br /&gt;
attr Rep.LogDB.sqlResult fastStart 1&lt;br /&gt;
attr Rep.LogDB.sqlResult room Datenbank&lt;br /&gt;
attr Rep.LogDB.sqlResult showproctime 1&lt;br /&gt;
attr Rep.LogDB.sqlResult sqlResultFormat table&lt;br /&gt;
attr Rep.LogDB.sqlResult verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Definition Syntax wurde bereits weiter oben erläutert. Das Attribut &#039;&#039;&#039;sqlResultFormat&#039;&#039;&#039; legt fest in welcher Art und Weise das Ergebnis präsentiert werden soll. Auch andere Formate wie JSON sind implementiert.&lt;br /&gt;
&lt;br /&gt;
Um das oben angegbene SQL-Statement zum Beispiel alle 6 Stunden 20 Minuten auszuführen, dient die folgende at-Definition: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.LogDB.sqlResult at +*06:20:00 set Rep.LogDB.sqlResult sqlCmd select device, count(*) from history group by DEVICE&lt;br /&gt;
attr At.LogDB.sqlResult icon clock&lt;br /&gt;
attr At.LogDB.sqlResult room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen sind in der [https://fhem.de/commandref_DE.html#at at-CommandRef] beschrieben.&lt;br /&gt;
&lt;br /&gt;
Natürlich sind alle verfügbaren DbRep Set/Get-Befehle über diesen Weg ausführbar.&lt;br /&gt;
Es wird empfohlen das definierte DbRep-Device nur für Auswertungsaufgaben zu verwenden die eine gleiche Attributierung des Devices verlangen. &lt;br /&gt;
Für weitere Aufgaben sollten weitere DbRep-Devices definiert und entsprechend eingestellt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Abarbeitung einer sequentiellen Befehlskette mittels non-blocking sqlCmd-Kommandos ===&lt;br /&gt;
Ein Vorteil von DbRep ist die nicht blockierende Arbeitsweise fast aller DbRep-Befehle (auf Ausnahmen wird in der Commandref hingewiesen).&lt;br /&gt;
Daraus ergibt sich aber auch das Merkmal, dass nach dem Funktionsaufruf nicht auf das Ergebnis gewartet wird und die FHEM-Schleife  &lt;br /&gt;
unmittelbar nach dem Start des Befehls weiterläuft. Um mehrere voneinander abhängige Befehle, die eine festgelegte Reihenfolge erfüllen müssen, abzuarbeiten, kann die nachfolgend beschriebene Technik zur Kettenbildung angewendet werden. Diese Technik wird anhand einer einfachen Demo erläutert. &lt;br /&gt;
&lt;br /&gt;
Das konstruierte Ziel der Kette ist folgendes:&lt;br /&gt;
&lt;br /&gt;
* Es soll nacheinander der Insert eines Datensatzes durchgeführt, danach ein Select dieses Datensatzes, ein Update auf ein Feld und zuletzt ein delete dieses Datensatzes in dieser Reihenfolge ausgeführt werden&lt;br /&gt;
&lt;br /&gt;
Demnach sich insgesamt vier SQL-Befehle nacheinander auszuführen (Insert, Select, Update, Delete).&lt;br /&gt;
Zunächst werden vier identische DbRep-Devices angelegt, die sich lediglich durch ihren Namen unterscheiden. Das wären die Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rep.insert, Rep.select, Rep.update, Rep.delete&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zur Anlage kann ein DbRep-Device als Vorlage erstellt und nachfolgend dreimal kopiert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.insert DbRep LogDB&lt;br /&gt;
attr Rep.insert allowDeletion 1&lt;br /&gt;
attr Rep.insert showproctime 1&lt;br /&gt;
attr Rep.insert userExitFn chain&lt;br /&gt;
&lt;br /&gt;
copy Rep.insert Rep.select&lt;br /&gt;
copy Rep.insert Rep.update&lt;br /&gt;
copy Rep.insert Rep.delete&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das wichtige Detail dieser Devices ist das gesetzte Attribut &amp;quot;userExitFn = chain&amp;quot;. Dieses Attribut aktiviert eine Schnittstelle zum Aufruf von benutzereigenem Code nach dem Abschluß eines Datenbank-Calls (siehe Commandref).&lt;br /&gt;
&lt;br /&gt;
Der benutzereigene Code wird nach folgendem Schema in die 99_myUtils.pm eingebaut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#############################################################################################&lt;br /&gt;
#  sqlCmd Commandchain zur sequentiellen Abarbeitung von non-blocking DbRep-Befehlen&lt;br /&gt;
#&lt;br /&gt;
#  genutzte werden vier DbRep-Devices:  Rep.insert, Rep.select, Rep.update, Rep.delete&lt;br /&gt;
#       &lt;br /&gt;
#############################################################################################&lt;br /&gt;
sub chain {&lt;br /&gt;
 my ($name,$reading,$value) = @_;&lt;br /&gt;
 my $hash   = $defs{$name};&lt;br /&gt;
 my $device = &amp;quot;Testdevice&amp;quot;;&lt;br /&gt;
 my $model  = &amp;quot;Testmodel&amp;quot;;&lt;br /&gt;
 my $rc;&lt;br /&gt;
 &lt;br /&gt;
 if ($name eq &amp;quot;Rep.insert&amp;quot; &amp;amp;&amp;amp; $reading eq &amp;quot;chainstart&amp;quot;) {&lt;br /&gt;
     # Start der 1. Operation (insert)&lt;br /&gt;
     CommandSet(undef,&amp;quot;Rep.insert sqlCmd insert into history (DEVICE, TYPE, EVENT, READING, VALUE, UNIT)&lt;br /&gt;
	   values (\&amp;quot;$device\&amp;quot;, \&amp;quot;$model\&amp;quot;, \&amp;quot;definition\&amp;quot;, \&amp;quot;DEF\&amp;quot;, \&amp;quot;Hugo\&amp;quot;, \&amp;quot;Emma\&amp;quot;)&amp;quot;);&lt;br /&gt;
     Log3 $name, 1, &amp;quot;$name - Start chain with insert&amp;quot;;&lt;br /&gt;
     return;   &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 if($reading eq &amp;quot;state&amp;quot; &amp;amp;&amp;amp; $value eq &amp;quot;done&amp;quot;) {&lt;br /&gt;
     if ($name eq &amp;quot;Rep.insert&amp;quot;) {&lt;br /&gt;
         # Auswertung der 1. Operation (insert)&lt;br /&gt;
         $rc = ReadingsVal($name, &amp;quot;SqlResultRow_1&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
         Log3 $name, 1, &amp;quot;$name - number of inserts: $rc&amp;quot;;&lt;br /&gt;
         &lt;br /&gt;
         # Start der 2. Operation (select)&lt;br /&gt;
         CommandSet(undef,&amp;quot;Rep.select sqlCmd select VALUE from history where device=\&amp;quot;$device\&amp;quot; and READING=\&amp;quot;DEF\&amp;quot; LIMIT 1;&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
   &lt;br /&gt;
     if ($name eq &amp;quot;Rep.select&amp;quot;) {&lt;br /&gt;
         # Auswertung der 2. Operation (select)&lt;br /&gt;
         $rc = ReadingsVal($name, &amp;quot;SqlResultRow_1&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
         Log3 $name, 1, &amp;quot;$name - return of select: $rc&amp;quot;;&lt;br /&gt;
         &lt;br /&gt;
         # Start der 3. Operation (update)&lt;br /&gt;
         CommandSet(undef,&amp;quot;Rep.update sqlCmd update history set UNIT=\&amp;quot;neu\&amp;quot; where DEVICE=\&amp;quot;$device\&amp;quot;;&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
     if ($name eq &amp;quot;Rep.update&amp;quot;) {&lt;br /&gt;
         # Auswertung der 3. Operation (update)&lt;br /&gt;
         $rc = ReadingsVal($name, &amp;quot;SqlResultRow_1&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
         Log3 $name, 1, &amp;quot;$name - number of updates: $rc&amp;quot;;&lt;br /&gt;
         &lt;br /&gt;
         # Start der 4. Operation (delete)&lt;br /&gt;
         CommandSet(undef,&amp;quot;Rep.delete sqlCmd delete from history where device = \&amp;quot;$device\&amp;quot; and UNIT = \&amp;quot;neu\&amp;quot;;&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
     if ($name eq &amp;quot;Rep.delete&amp;quot;) {&lt;br /&gt;
         # Auswertung der 4. Operation (delete)&lt;br /&gt;
         $rc = ReadingsVal($name, &amp;quot;SqlResultRow_1&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
         Log3 $name, 1, &amp;quot;$name - number of deletes: $rc&amp;quot;;&lt;br /&gt;
     } &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die gesamte Abarbeitung wird gestartet mit dem Aufruf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chain(&amp;quot;Rep.insert&amp;quot;, &amp;quot;chainstart&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
bzw. in der Kommandozeile im FHEMWEB mit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{chain(&amp;quot;Rep.insert&amp;quot;, &amp;quot;chainstart&amp;quot;)}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach dem initialen Aufruf des Insert wird die sub &amp;quot;chain&amp;quot; beendet und nach dem insert-Befehl durch das Device &amp;quot;Rep.insert&amp;quot; wieder aufgerufen. Dabei wird diese sub nach jedem erstellten Reading aufgerufen und dabei neben dem eigenen Devicenamen auch der Readingname sowie dessen Wert zur Auswertung übergeben. &lt;br /&gt;
Durch die if-Zweige wird bei jedem Durchlauf der richtige Entrypoint für den nachfolgenden Funktionsaufruf ermittelt und ausgeführt.&lt;br /&gt;
&lt;br /&gt;
Nach der Abarbeitung aller vorgesehenen SQL-Statements ist die erfolgreiche Chainverkettung anhand der Ergebnisse im Logfile ersichtlich:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2018.10.24 23:57:37.602 1: Rep.insert - Start chain with insert&lt;br /&gt;
2018.10.24 23:57:37.815 1: Rep.insert - number of inserts: 1&lt;br /&gt;
2018.10.24 23:57:37.901 1: Rep.select - return of select: Hugo&lt;br /&gt;
2018.10.24 23:57:38.033 1: Rep.update - number of updates: 1&lt;br /&gt;
2018.10.24 23:57:38.176 1: Rep.delete - number of deletes: 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summe aller Einschaltzeiten eines Gerätes ===&lt;br /&gt;
&lt;br /&gt;
[[Summe aller Einschaltzeiten eines Gerätes | Hier]] geht&#039;s zum Beitrag.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Welche Device/Reading-Kombinationen gibt es in der Datenbank ? ===&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Im aktuellen DbRep-Release kann die nachfolgend beschriebene Auswertung alternativ durch die eingebauten Kommmandos:&lt;br /&gt;
 set &amp;lt;DbRep-Device&amp;gt; sqlSpecial allDevCount&lt;br /&gt;
 set &amp;lt;DbRep-Device&amp;gt; sqlSpecial allDevReadCount&lt;br /&gt;
ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datenbank längere Zeit gelaufen ist und die zu loggenden Devices bzw. Readings immer mal wieder geändert wurden, wächst der Wunsch einen Überblick über die in der DB enthaltenen Devices/Reading-Kombinationen zu erhalten.&lt;br /&gt;
Dadurch können wiederum gezielt Auswertungen auf eine bestimmte Device/Reading-Kombination durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
Um dieses Ziel zu erreichen, wird ein DbRep-Device erstellt welches für die Verwendung eines User-Command eingerichtet wird.&lt;br /&gt;
Je nach dem gewünschten Ergebnis wird eines der nachfolgenden SQL-Kommandos verwendet.&lt;br /&gt;
&lt;br /&gt;
Selektion aller Device/Reading-Kombinationen in der Datenbank:&lt;br /&gt;
 select device, reading, count(*) from history group by DEVICE, READING&lt;br /&gt;
&lt;br /&gt;
Nur die geloggten Devices in der Datenbank reporten:&lt;br /&gt;
 select device, count(*) from history group by DEVICE&lt;br /&gt;
&lt;br /&gt;
Zur Einrichtung wird zunächst das DbRep-Device definiert:&lt;br /&gt;
&lt;br /&gt;
 define Rep.LogDB.sqlResult DbRep LogDB&lt;br /&gt;
&lt;br /&gt;
Dabei ist &amp;quot;LogDB&amp;quot; &#039;&#039;&#039;nicht&#039;&#039;&#039; die Datenbank, sondern das DbLog-Device mit dem das DbRep-Device assoziiert und derüber mit der Datenbank verbunden wird !&lt;br /&gt;
 &lt;br /&gt;
Um die Ausgabe des späteren Ergebnisses zu formatieren wird das Attribut &amp;quot;sqlResultFormat&amp;quot; auf &amp;quot;table&amp;quot; gesetzt. Dadurch wird das Selektergebnis als Tabelle mit den Spalten Device, Reading und der Anzahl der enthaltenen Datensätze der jeweiligen Kombination erzeugt.&lt;br /&gt;
&lt;br /&gt;
 attr Rep.LogDB.sqlResult sqlResultFormat table&lt;br /&gt;
&lt;br /&gt;
Natürlich kann auch ein anderes Ausgabeformat gewählt werden wenn gewünscht oder benötigt. Bei großen Ergebnismengen ist zur Erhöhung der Übersichtlichkeit das Attribut &amp;quot;sqlResultFormat = separated&amp;quot; wahrscheinlich eher geeignet.&lt;br /&gt;
&lt;br /&gt;
Das Attribut stateFormat wird entsprechend gesetzt um nach einem erfolgten Selektionslauf die erzeugte Tabelle in der Raumansicht bzw. im DeviceOverview anzuzeigen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr Rep.LogDB.sqlResult stateFormat { if (defined($defs{$name}{READINGS}{SqlResult})) {&lt;br /&gt;
                                            ReadingsVal($name,&amp;quot;SqlResult&amp;quot;,undef);&lt;br /&gt;
                                        } else {&lt;br /&gt;
                                            ReadingsVal($name,&amp;quot;state&amp;quot;,undef);&lt;br /&gt;
                                        } &lt;br /&gt;
                                      }                                        &lt;br /&gt;
&amp;lt;/pre&amp;gt;                                   &lt;br /&gt;
&lt;br /&gt;
Damit ist das DbRep-Device vorbereitet und der Auswertungslauf kann gestartet werden mit:&lt;br /&gt;
&lt;br /&gt;
 set Rep.LogDB.sqlResult sqlCmd select device, reading, count(*) from history group by DEVICE, READING;&lt;br /&gt;
&lt;br /&gt;
bzw. wenn nur die in der Datenbank enthaltenen Devices zu erhalten:&lt;br /&gt;
&lt;br /&gt;
 set Rep.LogDB.sqlResult sqlCmd select device, count(*) from history group by DEVICE;&lt;br /&gt;
&lt;br /&gt;
[[Datei:sqlResult.PNG|right|thumb|600px|set Rep.LogDB.sqlResult sqlCmd select device, count(*) from history group by DEVICE;]]&lt;br /&gt;
&lt;br /&gt;
Nebenstehender Screenshot zeigt das Ergebnis der Auswertung aller in der Datenbank enthalteten Devices und deren Anzahl von Datensätzen.&lt;br /&gt;
&lt;br /&gt;
Zum leichteren Nachnutzung hier noch die Raw-Definition des fertigen DbRep-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod Rep.LogDB.sqlResult DbRep LogDB&lt;br /&gt;
attr Rep.LogDB.sqlResult aggregation no&lt;br /&gt;
attr Rep.LogDB.sqlResult comment Device zum freien Report mit sqlCmd.\&lt;br /&gt;
- Auswahl von Statements -\&lt;br /&gt;
\&lt;br /&gt;
Device/Reading-Kombinationen in der Datenbank:\&lt;br /&gt;
select device, reading, count(*) from history group by DEVICE, READING\&lt;br /&gt;
\&lt;br /&gt;
geloggte Devices in der Datenbank:\&lt;br /&gt;
select device, count(*) from history group by DEVICE\&lt;br /&gt;
&lt;br /&gt;
attr Rep.LogDB.sqlResult devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.LogDB.sqlResult disable 0&lt;br /&gt;
attr Rep.LogDB.sqlResult event-on-update-reading state&lt;br /&gt;
attr Rep.LogDB.sqlResult group Datenbankauswertungen&lt;br /&gt;
attr Rep.LogDB.sqlResult room DbLog&lt;br /&gt;
attr Rep.LogDB.sqlResult showproctime 1&lt;br /&gt;
attr Rep.LogDB.sqlResult sqlResultFormat table&lt;br /&gt;
attr Rep.LogDB.sqlResult stateFormat { if (defined($defs{$name}{READINGS}{SqlResult})) {\&lt;br /&gt;
   ReadingsVal($name,&amp;quot;SqlResult&amp;quot;,undef);;\&lt;br /&gt;
  } else {\&lt;br /&gt;
   ReadingsVal($name,&amp;quot;state&amp;quot;,undef);;\&lt;br /&gt;
  } \&lt;br /&gt;
}&lt;br /&gt;
attr Rep.LogDB.sqlResult timeout 1000&lt;br /&gt;
attr Rep.LogDB.sqlResult verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Die current-Tabelle mit einem Extrakt der history-Tabelle füllen (tableCurrentFillup) ===&lt;br /&gt;
&lt;br /&gt;
Diese Funktion erweitert die Möglichkeiten der Verwendung der current-Tabelle des DbLog-Devices. In den meisten Fällen wird im DbLog das Attribut &amp;quot;DbLogType = Current/History&amp;quot; gesetzt sein um bei der Erstellung von SVG&#039;s entsprechende Vorschläge in der DropDown-Liste des Editors zur Verfügung zu haben. &lt;br /&gt;
&lt;br /&gt;
Bei dieser Betriebsart werden in der current-Tabelle neu auftretende Events von Device/Reading-Kombinationen eingetragen, sofern sie noch nicht enthalten sind. Werden neue Geräte definiert, erscheinen deren Events in der current-Tabelle, auch wenn man später nicht benötigte Readings mit den Attributen &amp;quot;event-on-change-reading&amp;quot; oder &amp;quot;event-on-update-reading&amp;quot; ausgrenzt. &lt;br /&gt;
Die einmal gespeicherten Werte bleiben in der current Tabelle erhalten. Sicherlich wird deswegen der eine oder andere User den Inhalt der current Tabelle löschen um wieder eine leere und saubere current-Tabelle zu haben. Das führt dann natürlich dazu, dass nur die ab diesem Zeitpunkt auftretenden Events in der Vorschlagsliste aufgenommen werden und nur selten auftretende Device/Reading-Kombinationen erst nach längerer Zeit wieder in der Tabelle current gespeichert werden. &lt;br /&gt;
&lt;br /&gt;
Darüber hinaus möchte man vielleicht nur für SVG-Diagramme relevante Device/Reading-Einträge in der Vorschagsliste vorfinden oder dort nur Einträge vorhalten, die in den letzten drei Monaten aufgetreten sind. Die Beweggründe können sehr vielfältig sein.&lt;br /&gt;
Um diesem Wunsch zu entsprechen, gibt es im DbRep die Funktion &amp;quot;set &amp;lt;DbRep-Device&amp;gt; tableCurrentFillup&amp;quot;, die eng mit dem dem DbLog-Attribut &amp;quot;DbLogType = SampleFill/History&amp;quot; zusammenarbeitet. &lt;br /&gt;
&lt;br /&gt;
Nachfolgend wird an einem Beispiel erläutert, welche Konfigurationen vorgenommen werden können, um aus der history-Tabelle alle vorhandenen Device/Reading-Kombinationen zu extrahieren und sie zur Verwendung als SVG-Vorschlagsliste in die current-Tabelle einzufügen.  &lt;br /&gt;
&lt;br /&gt;
Für das Beispiel wird folgendes angenommen:&lt;br /&gt;
&lt;br /&gt;
* es gibt ein definiertes DbLog-Device &amp;quot;LogDB&amp;quot; welches in die Datenbank &amp;quot;fhem&amp;quot; loggt&lt;br /&gt;
* das DbRep-Device zur Ausführung der Funktion wird &amp;quot;Rep.FillCurr.fhem&amp;quot; genannt&lt;br /&gt;
* es sollen alle in der history-Tabelle vorkommenden Device/Reading-Kombinationen extrahiert und in die current-Tabelle eingetragen werden (Einschränkungen auf bestimmte Devices / Readings oder zeitliche Abgrenzungen werden nicht vorgenommen, aber es wird darauf hingewiesen, wie es gemacht werden kann)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== a) Anlegen des DbRep-Devices ====&lt;br /&gt;
&lt;br /&gt;
Die Definition des DbRep-Devices erfolgt unter Angabe des zu verbindenden DbLog-Devices (nicht der Datenbank selbst): &lt;br /&gt;
&lt;br /&gt;
 define Rep.FillCurr.fhem DbRep LogDB&lt;br /&gt;
&lt;br /&gt;
In dem so definierten neuen Device sind die Attribute zu setzen, die für die beabsichtigte Funktion wichtig sind.&lt;br /&gt;
Da dieses Device auch für die Löschung der in der current-Tabelle gespeicherten Datensätze verwendet wird, muss das Attribut &amp;quot;allowDeletion = 1&amp;quot; gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
 attr Rep.FillCurr.fhem allowDeletion 1&lt;br /&gt;
&lt;br /&gt;
Ebenfalls wichtig ist die Erzeugung eines Events sobald der Löschvorgang der current-Tabelle abgeschlossen ist. Dazu wird im Beispiel &amp;quot;event-on-update-reading&amp;quot; verwendet:&lt;br /&gt;
&lt;br /&gt;
 attr Rep.FillCurr.fhem event-on-update-reading state,--DELETED_ROWS_CURRENT-- &lt;br /&gt;
&lt;br /&gt;
[[Datei:currdelete.PNG|right|thumb|300px|set Rep.FillCurr.fhem tableCurrentPurge]]&lt;br /&gt;
Für die Funktion nicht wichtig, aber durchaus interessant zu wissen wie lange die Laufzeit der Funktionen ist, wird noch das Attribut &amp;quot;showproctime = 1&amp;quot; gesetzt. Damit werden die Readings &amp;quot;background_processing_time&amp;quot; und &amp;quot;sql_processing_time&amp;quot; erzeugt welche die jeweilige Bearbeitungszeit in Sekunden darstellen.&lt;br /&gt;
&lt;br /&gt;
 attr Rep.FillCurr.fhem showproctime 1&lt;br /&gt;
&lt;br /&gt;
Mit dem so vorbereiteten Device können schon die Funktionen &amp;quot;tableCurrentPurge&amp;quot; und &amp;quot;tableCurrentFillup&amp;quot; manuell getestet werden. Mit dem Kommando:&lt;br /&gt;
&lt;br /&gt;
 set Rep.FillCurr.fhem tableCurrentPurge&lt;br /&gt;
&lt;br /&gt;
wird der gesamte aktuelle Inhalt der current-Tabelle gelöscht. Wie im nebenstehenden Screenshot sichtbar, wurden in dem Beispiel 170 Datensätze gelöscht und dazu rund 30ms benötigt. Mit Abschluß der Operation wird der Delete-Event erzeugt:&lt;br /&gt;
&lt;br /&gt;
 2018-01-05 13:38:14.596 DbRep Rep.FillCurr.fhem --DELETED_ROWS_CURRENT--: 170&lt;br /&gt;
&lt;br /&gt;
[[Datei:currfillup.PNG|right|thumb|300px|set Rep.FillCurr.fhem tableCurrentFillup]]&lt;br /&gt;
Dieser Event wird später in einem Notify für die automatisierte Current-Auffüllung verwendet.&lt;br /&gt;
Eine Zählug der current-EInträge mit &amp;quot;set Rep.FillCurr.fhem countEntries current&amp;quot; ergibt &amp;quot;-&amp;quot;, d.h. der Löschbefehl war erfolgreich. Im jetzigen Zustand würde bei der Erstellung eines SVG keine DropDown-Liste angezeigt werden und statt dessen die Felder im SVG-Editor frei bearbeitbar sein, weil die current-Tabelle keine Werte enthält. &lt;br /&gt;
Gleichermaßen kann bereits die Auffüllung der current-Tabelle getestet werden mit dem Befehl:&lt;br /&gt;
&lt;br /&gt;
 set Rep.FillCurr.fhem tableCurrentFillup&lt;br /&gt;
&lt;br /&gt;
Je nach Größe der Datenbank kann diese Operation einige Zeit in Anspruch nehmen. Da dieser Befehl wie bei DbRep üblich non-blocking abgearbeitet wird, hat die Laufzeit keinen Einfluss auf die sonstige FHEM-Verfügbarkeit. &lt;br /&gt;
&lt;br /&gt;
[[Datei:svgfillup.PNG|left|thumb|300px|set Rep.FillCurr.fhem tableCurrentFillup]]&lt;br /&gt;
Wie bereits erwähnt, wird in dem Beispiel die gesamte history-Tabelle ausgewertet. Sollen zum Beispiel nur die letzten 90 Tage zur Auswertung herangezogen werden, kann das &#039;&#039;&#039;Attribut &amp;quot;timeDiffToNow = d:90&amp;quot;&#039;&#039;&#039; gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
Weitere Eingrenzungen bzgl. der auszuwertenden Devices bzw. Readings können über die &#039;&#039;&#039;Attribute &amp;quot;device&amp;quot; und &amp;quot;reading&amp;quot;&#039;&#039;&#039; vorgenommen werden. Die Syntax für die genannten Attribute und deren Auswirkung entnehme bitte der {{Link2CmdRef|Lang=de|Anker=DbRepattr}}.&lt;br /&gt;
&lt;br /&gt;
In unserem Beispiel wurde die current-Tabelle mit 170 Datensätzen aufgefüllt. Dazu wurden 291 Sekunden benötigt (die Tabelle history enthält insgesamt rund 11 Mio. Einträge)&lt;br /&gt;
&lt;br /&gt;
Wird jetzt ein neues SVG erstellt, erscheinen alle in selektierten Device/Reading-Kombinationen alphabetisch sortiert als DopDown-Liste im SVG-Editor.&lt;br /&gt;
&lt;br /&gt;
==== b) Konfiguration des DbLog-Devices ==== &lt;br /&gt;
&lt;br /&gt;
In dem bestehen DbLog-Device &amp;quot;LogDB&amp;quot; ist zur Vorbereitung lediglich das Attribut &amp;quot;DbLogType = SampleFill/History&amp;quot; zu setzen:&lt;br /&gt;
&lt;br /&gt;
 attr LogDB DbLogType SampleFill/History&lt;br /&gt;
&lt;br /&gt;
Entgegen der Arebeitsweise mit &amp;quot;Current/History&amp;quot; wird die current-Tabelle nicht mehr durch die Logging-Engine aktiv mit jedem relevanten Event gefüllt, sondern kann durch externe Tools, in dem Fall dem DbRep-Device, beschrieben werden.&lt;br /&gt;
Die current-Tabelle wird aber, ob leer oder gefüllt, bei der Erstellung eines SVG-Devices ausgewertet und in Abhängigeit des Ergebnisses eine DropDown-Liste zur Verfügung gestellt, oder frei editierbare Felder angeboten falls die current-Tabelle leer ist.&lt;br /&gt;
&lt;br /&gt;
==== c) Definition der at/notify-Devices zum automatisierten Ablauf ==== &lt;br /&gt;
&lt;br /&gt;
Die Löschung des Inhaltes der current-Tabelle und die erneute Ausffüllung soll natürlich autmatisiert regelmäßig erfolgen. Zu diesem Zweck wird ein at-Device (At.LogDB.currentPurge) und ein notify-Device angelegt. Das AT-Device soll alle 8 Stunden und 15 Minuten das Löschen des current-Inhaltes steuern und nach Abschluß der Löschung soll getriggert durch das &amp;quot;--DELETED_ROWS_CURRENT--&amp;quot;-Event die Neubefüllung der current-Tabelle veranlasst werden.&lt;br /&gt;
&lt;br /&gt;
Zur Definition dieser Devices gibt es nicht viel zu erläutern. Die entsprechende Syntax kann bei {{Link2CmdRef|Lang=de|Anker=at|Label=at}} bzw. {{Link2CmdRef|Lang=de|Anker=notify|Label=notify}} in der {{Link2CmdRef|Lang=de}} nachgelesen werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;at-Device:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 define At.LogDB.currentPurge at +*08:15:00 set Rep.FillCurr.fhem tableCurrentPurge&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;notify-Device:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 define N.LogDB.Fillup notify Rep.FillCurr.fhem:.*DELETED_ROWS_CURRENT.*  sleep 5;set Rep.FillCurr.fhem tableCurrentFillup&lt;br /&gt;
&lt;br /&gt;
Das nichtblockierende FHEM-sleep (sleep gefolgt von einem weiteren Befehl) wird lediglich dazu verwendet, um zwischen der Delete- und Auffüll-Operation eine kleine Pause einzufügen.&lt;br /&gt;
 &lt;br /&gt;
==== d) Arbeitsweise und Raw-Definitionen ====&lt;br /&gt;
&lt;br /&gt;
Durch das &amp;quot;At.LogDB.currentPurge&amp;quot;-Device wird alle 8 Stunden und 15 Minuten ein Löschlauf der current-Tabelle gestartet. Dadurch wird dem darauf folgenden Auffüllprozess immer eine saubere leere current-Tabelle zur Verfügung gestellt. Nach dem Löschlauf wird durch das &amp;quot;N.LogDB.Fillup&amp;quot;-Device, getriggert durch den Event &amp;quot;Rep.FillCurr.fhem:.*DELETED_ROWS_CURRENT.*&amp;quot;, die erneute Auffüllung der current-Tabelle gestartet.&lt;br /&gt;
Die Daten werden aus der histrory-Tabelle gelesen, wobei der Zeitraum der Selektion und die zu betrachtenden Devices / Readings durch die Zeit-Attribute bzw. device / reading-Attribute des DbRep-Devices &amp;quot;Rep.FillCurr.fhem&amp;quot; individuell beeinflußt werden können.&lt;br /&gt;
&lt;br /&gt;
Hilfreich ist es auch, wenn das DbLog-Device &amp;quot;LogDB&amp;quot; im asynchronen Modus betrieben wird.&lt;br /&gt;
&lt;br /&gt;
Abschließend sind hier noch die Raw-Definitionen der beteiligten Devices (außer LogDB) angehängt, um das Beispiel leicht nachvollziehbar zu gestalten.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DbRep-Device &amp;quot;Rep.FillCurr.fhem&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod Rep.FillCurr.fhem DbRep LogDB&lt;br /&gt;
attr Rep.FillCurr.fhem allowDeletion 1&lt;br /&gt;
attr Rep.FillCurr.fhem comment Current Fillup für DB fhem&lt;br /&gt;
attr Rep.FillCurr.fhem devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.FillCurr.fhem event-on-update-reading state,--DELETED_ROWS_CURRENT--&lt;br /&gt;
attr Rep.FillCurr.fhem icon icoTool&lt;br /&gt;
attr Rep.FillCurr.fhem room DbLog&lt;br /&gt;
attr Rep.FillCurr.fhem showproctime 1&lt;br /&gt;
attr Rep.FillCurr.fhem verbose 3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;at-Device &amp;quot;At.LogDB.currentPurge&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod At.LogDB.currentPurge at +*08:15:00 set Rep.FillCurr.fhem tableCurrentPurge&lt;br /&gt;
attr At.LogDB.currentPurge comment Zeitgesteuertes Löschen der Current Tabelle. Nach dem Löschen wird \&lt;br /&gt;
Eventgesteuert (Notify N.LogDB.Fillup) ein tableCurrentFillup gestartet.&lt;br /&gt;
attr At.LogDB.currentPurge room DbLog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;notify-Device &amp;quot;N.LogDB.Fillup&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod N.LogDB.Fillup notify Rep.FillCurr.fhem:.*DELETED_ROWS_CURRENT.*  sleep 5;;set Rep.FillCurr.fhem tableCurrentFillup&lt;br /&gt;
attr N.LogDB.Fillup disable 1&lt;br /&gt;
attr N.LogDB.Fillup room DbLog&lt;br /&gt;
attr N.LogDB.Fillup verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== Backup/Restore einer SQLite Datenbank im laufenden Betrieb ===&lt;br /&gt;
&lt;br /&gt;
In diesem Beitrag wird erläutert, wie man mit DbRep ein Backup der SQLite-Datenbank erstellen kann, welche Möglichkeiten es dabei gibt und wie man eine Datenbank aus einem Backup wieder herstellen kann. &lt;br /&gt;
Die Backup-Funktion nutzt die SQLite Online Backup API und ermöglicht es, konsistente Backups der SQLite-DB in laufenden Betrieb zu erstellen ohne die Datenbank schließen zu müssen. &lt;br /&gt;
&lt;br /&gt;
Neben dem eigentlichen Backup kann optional einstellt werden, dass:&lt;br /&gt;
&lt;br /&gt;
* vor dem Backup eine Datenbankoptimierung (Vacuum) ausgeführt werden soll. Dadurch wird Plattenplatz freigegeben sofern möglich.&lt;br /&gt;
* vor und nach dem Backup kann ein FHEM-Kommando oder eine Perl-Routine ausgeführt werden (eine Perl-Routine ist in {} einzuschließen)&lt;br /&gt;
* das erstellte Dumpfile kann über FTP(S) an einen FTP-Server übertragen werden&lt;br /&gt;
* über die interne Versionsverwaltung kann festgelegt werden, wieviele erstellte Backups auf dem Datenträger erhalten bleiben sollen (default: 3)&lt;br /&gt;
&lt;br /&gt;
Für die Erläuterung des Beispiels soll ein DbRep-Device erstellt werden, welches:&lt;br /&gt;
&lt;br /&gt;
* die SQLite Datenbank im Betrieb (Online) sichert&lt;br /&gt;
* vor dem Dump einen Vacuum-Lauf durchführt&lt;br /&gt;
* das erstellte Dumpfile auf einen FTP-Server überträgt&lt;br /&gt;
* 2 Versionen (Dumpfiles) nach einem erfolgreichen Backuplauf im Dumpverzeichnis verbleiben sollen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== 1. Anlegen des DbRep-Devices ====&lt;br /&gt;
&lt;br /&gt;
Das anzulegende Device wird sowohl für das (regelmäßige) Backup als auch für einen eventuellen Restore verwendet.&lt;br /&gt;
Die Definition des DbRep-Devices erfolgt unter Angabe des zu verbindenden DbLog-Devices (nicht der Datenbank selbst): &lt;br /&gt;
&lt;br /&gt;
 define Rep.SQLite DbRep LogSQLITE&lt;br /&gt;
&lt;br /&gt;
Ist das Device definiert, verbindet es sich zu der Datenbank und wechselt in den state &amp;quot;connected&amp;quot;, sofern die Verbindung erfolgreich verlief.&lt;br /&gt;
Prinzipiell funktioniert der hier beschriebene Backup-Prozess mit einem im synchronous Mode betriebenen DbLog-Device, aber es ist dringend angeraten das DbLog-Device (LogSQLITE) in den asynchronen Modus umzuschalten. Dadurch werden Blockierungen von FHEM und Verluste von Daten verhindert.&lt;br /&gt;
&lt;br /&gt;
==== 2. Einstellungen des DbRep-Devices (Attribute) ====&lt;br /&gt;
&lt;br /&gt;
Für die gewünschte Funktion müssen in diesem neu definierten Device einige relevante Attribute gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;a) dumpDirLocal&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das zu erstellende Backupfile wird per default im log-Verzeichnis ./log (meist /opt/fhem/log) des FHEM-Rechners gespeichert. Um es an einer anderen Stelle zu speichern kann das Attribut &amp;quot;dumpDirLocal&amp;quot; gesetzt werdden. Dieses Verzeichnis kann sich auf dem lokalen Datenträger befinden, oder ein per NFS gemountetes Verzeichnis sein. In jedem Fall muss der User unter dem FHEM läuft Schreibrechte auf dieses Verzeichnis besitzen.&lt;br /&gt;
&lt;br /&gt;
Für das Beispiel sollen die Dump-Files auf einen NFS-Mount einer Synology Diskstation gespeichert werden. Dazu wurde ein Mount in /etc/fstab erstellt um den Pfad &amp;quot;/sds1/backup&amp;quot; lokal verfügbar zu machen:&lt;br /&gt;
&lt;br /&gt;
 sds1.&amp;lt;fqdn&amp;gt;:/volume1/ApplicationBackup /sds1/backup nfs auto,defaults,tcp,intr 0 0&lt;br /&gt;
&lt;br /&gt;
In diesem Verzeichnis exsitiert das Directory &amp;quot;dumps_FHEM&amp;quot;, in dem die Backup-Files gespeichert werden sollen. Das Attribut wird entsprechend gesetzt auf:&lt;br /&gt;
&lt;br /&gt;
 attr Rep.SQLite dumpDirLocal /sds1/backup/dumps_FHEM&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;&#039;b) dumpFilesKeep&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Parameter stellt die Anzahl der aufzubewahrenden Backup-Files ein. Es werden immer die &amp;quot;x&amp;quot; neuesten bzw. letzten Files im Verzeichnis gehalten, wobei nur die zu der jeweiligen Datenbank gehörenden Files betrachtet werden. &lt;br /&gt;
Die Zugehörigkeit des Dump-Files zur Quelldatenbank wird anhand des Filenamens ermittelt, der sich zusammensetzt aus &amp;lt;DB-Name ohne Endung&amp;gt;_&amp;lt;Erstellungsdatum und Uhrzeit&amp;gt;.sqlitebkp&lt;br /&gt;
&lt;br /&gt;
 Beispiel: fhem_2018_01_12_17_15.sqlitebkp&lt;br /&gt;
&lt;br /&gt;
Ist dieses Attribut nicht gesetzt, werden die 3 neuesten Backup-Files im Verzeichnis behalten.&lt;br /&gt;
Um nur 2 Files zu behalten wird das Attribut gesetzt auf:&lt;br /&gt;
&lt;br /&gt;
 attr Rep.SQLite dumpFilesKeep 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;c) Aktionen vor und nach dem Backup ausführen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Vor und nach der Dump-Ausführung kann ein FHEM-Kommando bzw. Perl-Befehle ausgeführt werden. Perl-Befehle müssen in {} eingeschlossen werden.&lt;br /&gt;
Für das Beispiel soll vor dem Backup die Verbindung des DbLog-Devices LogSQLITE zur Datenbank getrennt werden. Dadurch werden keine neuen Daten in die Datenbank geschrieben. Wenn das DbLog-Device LogSQLITE im asynchronen Modus wie empfohlen betrieben wird, tritt auch kein Datenverlust ein, da die zu loggenden Daten im Cache verbleiben bis die Verbindung zur DB wieder hergestellt wird.&lt;br /&gt;
&lt;br /&gt;
Es sei noch einmal darauf hingewiesen, dass das Backup-Verfahren ebenso im synchronen Modus und ohne das DbLog-Device von der Datenbank zu trennen, funktioniert und nur im Beispiel zur Demonstation der Möglichkeiten dient. &lt;br /&gt;
&lt;br /&gt;
Um die Verbindung zu trennen wird ein &amp;quot;set LogSQLITE reopen &amp;lt;Zeit in Sekunden&amp;gt;&amp;quot; verwendet. Die Zeitspanne wird sehr großzügig gewählt und soll sicherstellen, dass innerhalb dieser Zeit das Backup abgeschlossen ist. Nach dem Backup wird sofort ein &amp;quot;set LogSQLITE reopen&amp;quot; ausgeführt, was die Verbindung des DbLog-Devices LogSQLITE zur Datenbank unmittelbar wieder herstellt..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 attr Rep.SQLite executeBeforeProc set LogSQLITE reopen 3600&lt;br /&gt;
 attr Rep.SQLite executeAfterProc set LogSQLITE reopen&lt;br /&gt;
	&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;d) vor dem Backup Datenbank verkleinern (vacuum)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Diese optionale Funktion wird durch das Attribut &amp;quot;optimizeTablesBeforeDump&amp;quot; eingeschaltet. Dadurch die Vacuum-Funktion wird Platz innerhalb der Datenbank freigegeben der durch Löschvorgänge entstanden ist und dadurch die Größe des Datenbankfiles verringert.&lt;br /&gt;
&lt;br /&gt;
 attr Rep.SQLite optimizeTablesBeforeDump 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;e) das Dump-File nach dem Backup zum FTP-Server übertragen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
DbRep bietet die Möglichkeit, das erstellte Dump-File per FTP oder verschlüsselt per FTP(S) zum Server zu übertragen. Dazu gibt es einen Satz von Attributen um dem Device alle notwendigen Angaben für den FTP-Transfer zur Verfügung zu stellen. Es gibt dafür folgende Attribute:&lt;br /&gt;
&lt;br /&gt;
* ftpUse 	: FTP Transfer nach dem Dump wird eingeschaltet (bzw. ftpUseSSL mit SSL Verschlüsselung)&lt;br /&gt;
* ftpUser 	: User zur Anmeldung am FTP-Server, default: anonymous&lt;br /&gt;
* ftpPwd 	: Passwort des FTP-Users, default nicht gesetzt&lt;br /&gt;
* ftpDir 	: Verzeichnis auf dem FTP-Server in welches das File übertragen werden soll (default: FTP-root)&lt;br /&gt;
* ftpPort 	: FTP-Port, default: 21&lt;br /&gt;
* ftpServer 	: Name oder IP-Adresse des FTP-Servers&lt;br /&gt;
* ftpTimeout 	: Timeout für die FTP-Verbindung in Sekunden (default: 30)&lt;br /&gt;
* ftpPassive 	: setzen wenn passives FTP verwendet werden soll&lt;br /&gt;
* ftpDebug 	: Debugging des FTP Verkehrs zur Fehlersuche&lt;br /&gt;
&lt;br /&gt;
Gemäß dieser Beschreibung und dem Ziel dieses Beispiels werden die für FTP-Transfer relevanten Attribute wie folgt gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr Rep.SQLite ftpDir /ftp                # Subdirectory ftp unter FTP-root als Zielverzeichnis&lt;br /&gt;
 attr Rep.SQLite ftpPwd ftpftp1&lt;br /&gt;
 attr Rep.SQLite ftpServer sds1.&amp;lt;fqdn&amp;gt;&lt;br /&gt;
 attr Rep.SQLite ftpUse 1&lt;br /&gt;
 attr Rep.SQLite ftpUser ftpuser&lt;br /&gt;
&lt;br /&gt;
Der FTP-Server muss natürlich vorab eingerichtet und funktionsfähig sein. Sollten beim FTP-Transfer Fehler auftreten, kann das Attribut ftpDebug = 1 gesetzt werden um entsprechende Ausgaben zur Analyse des Problems im Log zu erhalten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:repsqlite_defined.PNG|right|thumb|300px|Fertig definiertes Device Rep.SQLite]]&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;f) Hilfsattribute&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Für die Funktion nicht relevant aber informativ ist das Attribut &amp;quot;showproctime = 1&amp;quot;. Ist das Attribut gesetzt, wird das Reading &amp;quot;background_processing_time&amp;quot; angelegt. Es enthält nach der Ausführung die verbrauchte Prozesszeit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das fertig konfigurierte Device hier als RAW-Definition zur einfachen Nachnutzung. Die Angaben sind natürlich anzupassen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.SQLite DbRep LogSQLITE&lt;br /&gt;
attr Rep.SQLite devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.SQLite dumpDirLocal /sds1/backup/dumps_FHEM&lt;br /&gt;
attr Rep.SQLite dumpFilesKeep 2&lt;br /&gt;
attr Rep.SQLite event-on-update-reading state&lt;br /&gt;
attr Rep.SQLite executeAfterProc set LogSQLITE reopen&lt;br /&gt;
attr Rep.SQLite executeBeforeProc set LogSQLITE reopen 3600&lt;br /&gt;
attr Rep.SQLite ftpDir /ftp&lt;br /&gt;
attr Rep.SQLite ftpPwd ftpftp1&lt;br /&gt;
attr Rep.SQLite ftpServer sds1.&amp;lt;fqdn&amp;gt;&lt;br /&gt;
attr Rep.SQLite ftpUse 1&lt;br /&gt;
attr Rep.SQLite ftpUser ftpuser&lt;br /&gt;
attr Rep.SQLite optimizeTablesBeforeDump 1&lt;br /&gt;
attr Rep.SQLite room DbLog&lt;br /&gt;
attr Rep.SQLite showproctime 1&lt;br /&gt;
attr Rep.SQLite verbose 3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 3. Backup durchführen ====&lt;br /&gt;
 &lt;br /&gt;
Mit dem wie beschrieben eingerichteten DbRep-Device kann das Buckup gestartet werden mit:&lt;br /&gt;
&lt;br /&gt;
 set Rep.SQLite dumpSQLite&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:logsqlite_closeduntil.PNG|right|thumb|500px|LogSQLITE ist geschlossen bis ...]]&lt;br /&gt;
&lt;br /&gt;
Zu Beginn des Vorgangs wird sofort die Verbindung des DbLog-Devices zur Datenbank getrennt.&lt;br /&gt;
Ein laufendes Backup kann mit &amp;quot;set Rep.SQLite cancelDump&amp;quot; abgebrochen werden.&lt;br /&gt;
Das laufende Backup wird im state angezeigt mit &amp;quot;SQLite Dump is running - be patient and see Logfile !&amp;quot;. Dieser Satz ist ernst gemeint, wobei der Dump über die Online-API sehr schnell arbeitet. Im Logfile mit (mindestens) verbose 3 werden die relevanten Informationen zur Verfügung gestellt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2018.01.13 08:35:10.745 3: DbRep Rep.SQLite - ################################################################           &lt;br /&gt;
2018.01.13 08:35:10.746 3: DbRep Rep.SQLite - ###                    New SQLite dump                       ###&lt;br /&gt;
2018.01.13 08:35:10.747 3: DbRep Rep.SQLite - ################################################################&lt;br /&gt;
2018.01.13 08:35:10.748 3: DbRep Rep.SQLite - execute command before dump: &#039;set LogSQLITE reopen 3600&#039; &lt;br /&gt;
2018.01.13 08:35:10.883 2: DbLog LogSQLITE: Connection closed until 09:35:10 (3600 seconds).&lt;br /&gt;
2018.01.13 08:35:10.917 3: DbRep Rep.SQLite - Size of database /opt/fhem/fhem.db before optimize (MB): 2554&lt;br /&gt;
2018.01.13 08:35:10.918 3: DbRep Rep.SQLite - VACUUM database /opt/fhem/fhem.db....&lt;br /&gt;
2018.01.13 08:44:04.216 3: DbRep Rep.SQLite - Size of database /opt/fhem/fhem.db after optimize (MB): 2554&lt;br /&gt;
2018.01.13 08:44:04.280 3: DbRep Rep.SQLite - Starting dump of database &#039;fhem.db&#039;&lt;br /&gt;
2018.01.13 08:45:03.810 3: DbRep Rep.SQLite - Size of backupfile: 2553.64 MB&lt;br /&gt;
2018.01.13 08:45:04.579 3: DbRep Rep.SQLite - FTP: transferring /sds1/backup/dumps_FHEM/fhem_2018_01_13_08_44.sqlitebkp&lt;br /&gt;
2018.01.13 08:45:48.838 3: DbRep Rep.SQLite - FTP: fhem_2018_01_13_08_44.sqlitebkp transferred successfully to sds1.myds.me into dir /ftp&lt;br /&gt;
2018.01.13 08:45:48.844 3: DbRep Rep.SQLite - Deleting old dumpfile &#039;fhem_2018_01_13_08_13.sqlitebkp&#039; &lt;br /&gt;
2018.01.13 08:45:49.273 3: DbRep Rep.SQLite - Finished backup of database fhem - total time used: 638 seconds&lt;br /&gt;
2018.01.13 08:45:49.358 2: DbRep Rep.SQLite - command after dump message: &amp;quot;Reopen executed.&amp;quot; &lt;br /&gt;
2018.01.13 08:45:49.370 3: DbRep Rep.SQLite - Database dump finished successfully. &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:repsqlite_dumprunning.PNG|right|thumb|400px|das Backup läuft]]&lt;br /&gt;
&lt;br /&gt;
Setzt man das Attribut &amp;quot;ftpDebug=1&amp;quot;, erhält man im Log zusätzliche Informationen zum FTP-Transfer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2018.01.13 08:50:22.385 3: DbRep Rep.SQLite - Size of backupfile: 2553.82 MB&lt;br /&gt;
Net::FTP&amp;gt;&amp;gt;&amp;gt; Net::FTP(2.79)&lt;br /&gt;
Net::FTP&amp;gt;&amp;gt;&amp;gt;   Exporter(5.72)&lt;br /&gt;
Net::FTP&amp;gt;&amp;gt;&amp;gt;   Net::Cmd(2.30)&lt;br /&gt;
Net::FTP&amp;gt;&amp;gt;&amp;gt;   IO::Socket::INET(1.35)&lt;br /&gt;
Net::FTP&amp;gt;&amp;gt;&amp;gt;     IO::Socket(1.38)&lt;br /&gt;
Net::FTP&amp;gt;&amp;gt;&amp;gt;       IO::Handle(1.35)&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;lt;&amp;lt;&amp;lt; 220 SDS1 FTP server ready.&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;gt;&amp;gt;&amp;gt; USER ftpuser&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;lt;&amp;lt;&amp;lt; 331 Password required for ftpuser.&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;gt;&amp;gt;&amp;gt; PASS ....&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;lt;&amp;lt;&amp;lt; 230 User ftpuser logged in, access restrictions apply.&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;gt;&amp;gt;&amp;gt; TYPE I&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;lt;&amp;lt;&amp;lt; 200 Type set to I.&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;gt;&amp;gt;&amp;gt; CWD /ftp&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;lt;&amp;lt;&amp;lt; 250 CWD command successful.&lt;br /&gt;
2018.01.13 08:50:22.880 3: DbRep Rep.SQLite - FTP: transferring /sds1/backup/dumps_FHEM/fhem_2018_01_13_08_49.sqlitebkp&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;gt;&amp;gt;&amp;gt; PORT 192,168,2,45,145,42&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;lt;&amp;lt;&amp;lt; 200 PORT command successful.&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;gt;&amp;gt;&amp;gt; ALLO 2677867520&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;lt;&amp;lt;&amp;lt; 202 ALLO command ignored.&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;gt;&amp;gt;&amp;gt; STOR fhem_2018_01_13_08_49.sqlitebkp&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;lt;&amp;lt;&amp;lt; 150 Opening BINARY mode data connection for &#039;fhem_2018_01_13_08_49.sqlitebkp&#039;.&lt;br /&gt;
Net::FTP=GLOB(0xb12ed20)&amp;lt;&amp;lt;&amp;lt; 226 Transfer complete.&lt;br /&gt;
2018.01.13 08:51:06.859 3: DbRep Rep.SQLite - FTP: fhem_2018_01_13_08_49.sqlitebkp transferred successfully to sds1.myds.me into dir /ftp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:repsqlite_dumpfinished.PNG|right|thumb|500px|Backup ist erfolgreich abgeschlossen]]&lt;br /&gt;
&lt;br /&gt;
In vorliegenden Beispiel wird nach einem erfolgreichen Backup im state &amp;quot;Warning - dump finished, but command after dump message appeared&amp;quot; angezeigt. Diese Warnung rührt daher, dass das Reopen-Kommando eine Rückkehrinfo mitteilt, die als Problem gewertet und im Reading &amp;quot;afterdump_message&amp;quot; ausgegeben wird. In diesem Fall ist es nur eine Information.&lt;br /&gt;
&lt;br /&gt;
In den erstellten Readings wird zusammengetragen welches File mit welcher Größe ertsellt wurde, welche alten Files gelöscht wurden, Informationen zum FTP-Transfer und welche Zeit der Gesamtprozess benötgt hat.&lt;br /&gt;
 &lt;br /&gt;
Das so vorbereitete Backup kann nun z.B. täglich oder auch mit einer wesentlich kürzeren Wiederholungsperiode (alle x Stunden) über ein at-Device eingeplant werden:&lt;br /&gt;
&lt;br /&gt;
 define At.SQLite.Dump at *23:52:00 set Rep.SQLite dumpSQLite&lt;br /&gt;
&lt;br /&gt;
==== 4. Restore ====&lt;br /&gt;
&lt;br /&gt;
Sollte es einmal zur Korruption des Datenbankfiles kommen (database disk image is malformed) und Reparaturversuche erfolglos bleiben, kann ein Restore die einzigste oder vielleicht auch einfachste Möglichkeit sein die Datenbank wieder herzustellen.&lt;br /&gt;
&lt;br /&gt;
Das kann mit dem angelegten DbRep-Device im laufenden Betrieb geschehen. Auch hier ist wieder wichtig, dass das DbLog-Device LogSQLITE im asynchronen Modus betrieben wird und die Reopen-Zeit (siehe Einstellung Attribut &amp;quot;executeBeforeProc&amp;quot;) sehr großzügig eingestellt ist. &lt;br /&gt;
&lt;br /&gt;
Zum Restore gibt es den Befehl &amp;quot;set ... restoreSQLite &amp;lt;File&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
[[Datei:sqliterestore_auswahl.PNG|right|thumb|500px|Auswahlmenü Files für Restore ]]&lt;br /&gt;
&lt;br /&gt;
Im FHEMWEB öffnet sich dazu eine DropDown-Liste die alle vorhandenen und zur Quelldatenbank passenden Dumpfiles auflistet. Das herzustellende File&lt;br /&gt;
kann so bequem ausgewählt werden. Die Dumpfiles müssen sich in dem Verzeichnis befinden, welches durch das Attribut &amp;quot;dumpDirLocal&amp;quot; festgelegt wurde (default (./log).  [[Datei:sqliterestore_running.PNG|left|thumb|500px|Restore läuft]]&lt;br /&gt;
&lt;br /&gt;
Der restore wird demzufolge gestartet mit:&lt;br /&gt;
&lt;br /&gt;
 set Rep.SQLite restoreSQLite &amp;lt;File&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wieder wird zu Beginn des Vorgangs das verbundene DbLog-Device von der Datenbank abgekoppelt und nach dem Restore wieder automatisch verbunden. Eine Datenbankoptimierung bzw. FTP-Transfer wird bei diesem Vorgang natürlich nicht ausgeführt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Log zeigt den Prozessverlauf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2018.01.13 09:21:55.435 3: DbRep Rep.SQLite - ################################################################&lt;br /&gt;
2018.01.13 09:21:55.437 3: DbRep Rep.SQLite - ###             New database Restore/Recovery                ###&lt;br /&gt;
2018.01.13 09:21:55.437 3: DbRep Rep.SQLite - ################################################################&lt;br /&gt;
2018.01.13 09:21:55.438 3: DbRep Rep.SQLite - execute command before restore: &#039;set LogSQLITE reopen 3600&#039; &lt;br /&gt;
2018.01.13 09:21:55.448 2: DbLog LogSQLITE: Connection closed until 10:21:55 (3600 seconds).&lt;br /&gt;
2018.01.13 09:21:55.477 3: DbRep Rep.SQLite - Starting restore of database &#039;fhem.db&#039;&lt;br /&gt;
2018.01.13 09:30:12.533 3: DbRep Rep.SQLite - Restore of /sds1/backup/dumps_FHEM/fhem_2018_01_13_08_49.sqlitebkp into &#039;fhem.db&#039; finished - total time used: 497 seconds.&lt;br /&gt;
2018.01.13 09:30:12.685 2: DbRep Rep.SQLite - command after restore message: &amp;quot;Reopen executed.&amp;quot; &lt;br /&gt;
2018.01.13 09:30:12.700 3: DbRep Rep.SQLite - Database restore finished successfully.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Restore wurde erfolgreich abgeschlossen und die Verbindung des DbLog-Device LogSQLITE zur Datenbank wiederhergestellt. Das Logging wird nahtlos fortgeführt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sqliterestore_finished.PNG|right|thumb|300px|Restore erfolgreich abgeschlossen]]&lt;br /&gt;
&lt;br /&gt;
Es ist natürlich zu beachten, dass die Daten zwischen dem Erstellungszeitpunkt des eingespielten Backups und der aktuellen Zeit verloren sind !&lt;br /&gt;
Die bestehende (korrupte) Datenbank wird überschrieben. Deswegen ist es ratsam immer ein aktuelles (zeitnahes) Backup zu haben um den Datenverlust möglichst gering zu halten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 5. Links ====&lt;br /&gt;
&lt;br /&gt;
Diskussionsthread im Forum:  https://forum.fhem.de/index.php/topic,82674.0.html&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Backup/Restore einer MySQL/MariaDB Datenbank im laufenden Betrieb ===&lt;br /&gt;
&lt;br /&gt;
Das Backup einer MySQL/MariaDB Datenbank (im Folgenden stellvertretend als MySQL bezeichnet) kann als Varianten&lt;br /&gt;
&lt;br /&gt;
* clientSide&lt;br /&gt;
* serverSide&lt;br /&gt;
&lt;br /&gt;
Beim &#039;&#039;&#039;clientSide&#039;&#039;&#039; Backup werden die Daten über SQL-Statements aus der Datenbank gelesen, auf dem Client (dem FHEM-Server) verarbeitet und das Dumpfile geschrieben. Es werden history- und current-Tabelle gesichert, sowie eventuell weitere angelegte Tabellen und Views. Allerdings benötigt dieser Modus umfangreichere RAM und CPU-Ressorcen auf dem Client.&lt;br /&gt;
&lt;br /&gt;
Die &#039;&#039;&#039;serverSide&#039;&#039;&#039; Option wird nachfolgend beispielhaft genauer erläutert. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== serverSide Backup Option ====&lt;br /&gt;
&lt;br /&gt;
Neben dem eigentlichen Backup kann optional einstellt werden, dass:&lt;br /&gt;
&lt;br /&gt;
* vor dem Backup eine Tabellenoptimierung (optimizeTables) ausgeführt werden soll. Dadurch wird Plattenplatz freigegeben sofern möglich.&lt;br /&gt;
* vor und nach dem Backup kann ein FHEM-Kommando oder eine Perl-Routine ausgeführt werden (eine Perl-Routine ist in &#039;&#039;&#039;{ }&#039;&#039;&#039; einzuschließen)&lt;br /&gt;
* das erstellte Dumpfile kann komprimiert werden&lt;br /&gt;
* das erstellte Dumpfile kann über FTP(S) an einen FTP-Server übertragen werden&lt;br /&gt;
* über die interne Versionsverwaltung kann die Anzahl der im Backupverzeichnis zu verbleibenden Backup-Files festgelegt werden (default: 3)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Erläuterung des Beispiels soll ein DbRep-Device erstellt werden, welches:&lt;br /&gt;
&lt;br /&gt;
* die MySQL Datenbank im Betrieb (Online) sichert&lt;br /&gt;
* vor dem Dump die history-Tabelle optimiert&lt;br /&gt;
* das erstellte Dumpfile auf einen FTP-Server überträgt&lt;br /&gt;
* drei Versionen (Dumpfiles) nach der Übertragung auf dem FTP-Server belässt, ältere Files werden vom FTP-Server gelöscht&lt;br /&gt;
* eine Version (Dumpfile) nach einem erfolgreichen Backuplauf im Dumpverzeichnis verbleiben sollen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== 1. Anlegen des DbRep-Devices =====&lt;br /&gt;
&lt;br /&gt;
Das anzulegende Device wird sowohl für das (regelmäßige) Backup als auch für ein eventuelles Restore verwendet.&lt;br /&gt;
Die Definition des DbRep-Devices erfolgt unter Angabe des zu verbindenden DbLog-Devices (nicht der Datenbank selbst): &lt;br /&gt;
&lt;br /&gt;
 define Rep.fhemtest.Dump.ServerSide DbRep LogDB&lt;br /&gt;
&lt;br /&gt;
Ist das Device definiert, verbindet es sich zu der Datenbank und wechselt in den state &amp;quot;connected&amp;quot;, sofern die Verbindung erfolgreich verlief.&lt;br /&gt;
Prinzipiell funktioniert der hier beschriebene Backup-Prozess mit einem im synchronous Mode betriebenen DbLog-Device, aber es ist dringend angeraten das DbLog-Device (LogDB) in den asynchronen Modus umzuschalten. Dadurch werden FHEM-Blockierungen vermieden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== 2. Einstellungen des DbRep-Devices (Attribute) ===== &lt;br /&gt;
&lt;br /&gt;
Für die gewünschte Funktion müssen in diesem neu definierten Device einige relevante Attribute gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;a) dumpDirRemote&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Der Dump wird durch den MySQL-Server erstellt und per default im Home-Verzeichnis des MySQL-Servers gespeichert.&lt;br /&gt;
Es wird die gesamte history-Tabelle (nicht current-Tabelle) im &#039;&#039;&#039;CSV-Format&#039;&#039;&#039; ohne Einschränkungen exportiert. &lt;br /&gt;
&lt;br /&gt;
Um es an einer anderen Stelle zu speichern, wird das Attribut &amp;quot;dumpDirRemote&amp;quot; gesetzt. &lt;br /&gt;
&lt;br /&gt;
Auch wenn der MySQL-Server mit auf dem FHEM-Server läuft, also lokal, wird dieses Attribut zur Veränderung des Zielverzeichnisses verwendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;b) dumpDirLocal&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Soll die interne Versionsverwaltung und die Dumpfilekompression des Moduls genutzt, sowie die Größe des erzeugten Dumpfiles ausgegeben werden, ist das Verzeichnis &amp;quot;dumpDirRemote&amp;quot; des MySQL-Servers auf dem Client zu mounten und im Attribut &amp;quot;dumpDirLocal&amp;quot; dem DbRep-Device bekannt zu machen.&lt;br /&gt;
Gleiches gilt wenn der FTP-Transfer nach dem Dump genutzt werden soll (Attribut &amp;quot;ftpUse&amp;quot; bzw. &amp;quot;ftpUseSSL&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Im Beispiel läuft der MySQL-Server auf einer Synology Diskstation und die Dump-Files werden dort im Verzeichnis&lt;br /&gt;
&lt;br /&gt;
 /volume1/ApplicationBackup/dumps_FHEM&lt;br /&gt;
&lt;br /&gt;
angelegt. Dieses Verzeichnis wird auf dem FHEM-Server als Verzeichnis &amp;quot;/sds1/backup&amp;quot; gemountet.&lt;br /&gt;
Dazu wird ein Eintrag in /etc/fstab erstellt:&lt;br /&gt;
&lt;br /&gt;
 sds1.&amp;lt;fqdn&amp;gt;:/volume1/ApplicationBackup /sds1/backup nfs auto,defaults,tcp,intr 0 0&lt;br /&gt;
&lt;br /&gt;
In diesem Verzeichnis existiert das Directory &amp;quot;dumps_FHEM&amp;quot;, in dem die Backup-Files gespeichert werden sollen. Das Attribut wird entsprechend gesetzt auf:&lt;br /&gt;
&lt;br /&gt;
 attr Rep.fhemtest.Dump.ServerSide dumpDirLocal /sds1/backup/dumps_FHEM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
Läuft der MySQL-Server mit FHEM lokal auf dem gleichen Server, zeigen die Attribute &#039;&#039;&#039;dumpDirRemote und dumpDirLocal&#039;&#039;&#039; auf das &#039;&#039;&#039;identische Verzeichnis&#039;&#039;&#039;. Trotzdem sind beide Attribute zu definieren.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
:&#039;&#039;&#039;b) dumpFilesKeep&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Parameter stellt die Anzahl der aufzubewahrenden Backup-Files ein. Es werden immer die &amp;quot;x&amp;quot; neuesten bzw. letzten Files im Verzeichnis gehalten, wobei nur die zu der jeweiligen Datenbank gehörenden Files betrachtet werden. &lt;br /&gt;
Die Zugehörigkeit des Dump-Files zur Quelldatenbank wird anhand des Filenamens ermittelt.&lt;br /&gt;
&lt;br /&gt;
Er setzt sich zusammen aus &amp;lt;Datenbankname&amp;gt;_history_&amp;lt;Erstellungsdatum_Uhrzeit&amp;gt;.csv&lt;br /&gt;
&lt;br /&gt;
 Beispiel: fhemtest_history_2020_05_14_03_42.csv (+.gzip falls Dumpfiles komprimiert werden) &lt;br /&gt;
&lt;br /&gt;
Ist dieses Attribut nicht gesetzt, werden die 3 neuesten Backup-Files im Verzeichnis behalten.&lt;br /&gt;
Um nur 2 Files zu behalten wird das Attribut gesetz:&lt;br /&gt;
&lt;br /&gt;
 attr Rep.fhemtest.Dump.ServerSide dumpFilesKeep 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;c) Aktionen vor und nach dem Backup ausführen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Vor und nach der Dump-Ausführung kann ein FHEM-Kommando bzw. Perl-Befehle ausgeführt werden. Perl-Befehle müssen in &#039;&#039;&#039;{ }&#039;&#039;&#039; eingeschlossen werden.&lt;br /&gt;
&lt;br /&gt;
Für das Beispiel soll vor dem Backup die Verbindung des DbLog-Devices LogDB zur Datenbank getrennt werden. Dadurch werden keine neuen Daten in die Datenbank geschrieben. Wenn das DbLog-Device LogDB im asynchronen Modus wie empfohlen betrieben wird, tritt auch kein Datenverlust ein, da die zu loggenden Daten im Cache verbleiben bis die Verbindung zur DB wiederhergestellt wird.&lt;br /&gt;
&lt;br /&gt;
Um die Verbindung zu trennen wird ein &lt;br /&gt;
&lt;br /&gt;
 set LogDB reopen &amp;lt;Zeit in Sekunden&amp;gt; &lt;br /&gt;
&lt;br /&gt;
verwendet. Die Zeitspanne wird sehr großzügig gewählt und soll sicherstellen, dass innerhalb dieser Zeit das Backup abgeschlossen ist. Nach dem Backup wird sofort &lt;br /&gt;
&lt;br /&gt;
 set LogDB reopen &lt;br /&gt;
&lt;br /&gt;
ausgeführt, was die Verbindung des DbLog-Devices LogDB zur Datenbank unmittelbar wiederherstellt.&lt;br /&gt;
&lt;br /&gt;
 attr Rep.fhemtest.Dump.ServerSide executeBeforeProc set LogDB reopen 3600&lt;br /&gt;
 attr Rep.fhemtest.Dump.ServerSide executeAfterProc set LogDB reopen&lt;br /&gt;
	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;d) vor dem Backup Datenbank verkleinern (optimizeTables)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Diese optionale Funktion wird durch das Attribut &amp;quot;optimizeTablesBeforeDump&amp;quot; eingeschaltet. Dadurch diese Funktion wird Platz innerhalb der Datenbank freigegeben der durch Löschvorgänge entstanden ist und dadurch die Größe des Datenbankfiles verringert.&lt;br /&gt;
&lt;br /&gt;
 attr Rep.fhemtest.Dump.ServerSide optimizeTablesBeforeDump 1&lt;br /&gt;
&lt;br /&gt;
Durch die Tabellenoptimierung verlängert sich die Dumpzeit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;e) das angelegte Dump-File nach dem Backup zum FTP-Server übertragen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
DbRep bietet die Möglichkeit, das erstellte Dump-File per FTP oder verschlüsselt per FTPS zum FTP-Server zu übertragen. Dazu gibt es einen Satz von Attributen um dem Device alle notwendigen Angaben für den FTP-Transfer zur Verfügung zu stellen. Es gibt dafür folgende Attribute:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ftpUse 	: FTP Transfer nach dem Dump wird eingeschaltet (bzw. ftpUseSSL mit SSL Verschlüsselung)&lt;br /&gt;
* ftpUser 	: User zur Anmeldung am FTP-Server, default: anonymous&lt;br /&gt;
* ftpPwd 	: Passwort des FTP-Users, default nicht gesetzt&lt;br /&gt;
* ftpDir 	: Verzeichnis auf dem FTP-Server in welches das File übertragen werden soll (default: FTP-root)&lt;br /&gt;
* ftpPort 	: FTP-Port, default: 21&lt;br /&gt;
* ftpServer 	: Name oder IP-Adresse des FTP-Servers&lt;br /&gt;
* ftpTimeout 	: Timeout für die FTP-Verbindung in Sekunden (default: 30)&lt;br /&gt;
* ftpPassive 	: setzen wenn passives FTP verwendet werden soll&lt;br /&gt;
* ftpDebug 	: Debugging des FTP Verkehrs zur Fehlersuche&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Gemäß dieser Beschreibung und dem Ziel dieses Beispiels werden die für FTP-Transfer relevanten Attribute wie folgt gesetzt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 attr Rep.fhemtest.Dump.ServerSide ftpDir /ftp                # Subdirectory ftp unter FTP-root als Zielverzeichnis&lt;br /&gt;
 attr Rep.fhemtest.Dump.ServerSide ftpPwd ftpftp1&lt;br /&gt;
 attr Rep.fhemtest.Dump.ServerSide ftpServer sds1.&amp;lt;fqdn&amp;gt;&lt;br /&gt;
 attr Rep.fhemtest.Dump.ServerSide ftpUse 1&lt;br /&gt;
 attr Rep.fhemtest.Dump.ServerSide ftpUser ftpuser&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der FTP-Server muss natürlich vorab eingerichtet und funktionsfähig sein. Sollten beim FTP-Transfer Fehler auftreten, kann das Attribut ftpDebug = 1 gesetzt werden um entsprechende Ausgaben zur Analyse des Problems im Log zu erhalten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:dumpmysql1.PNG|right|thumb|300px|Fertig definiertes Device Rep.fhemtest.Dump.ServerSide]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
:&#039;&#039;&#039;f) Hilfsattribute&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Für die Funktion nicht relevant aber informativ ist das Attribut &amp;quot;showproctime = 1&amp;quot;. Ist das Attribut gesetzt, wird das Reading &amp;quot;background_processing_time&amp;quot; angelegt. Es enthält nach der Ausführung die verbrauchte Prozesszeit.&lt;br /&gt;
&lt;br /&gt;
Im Attribut &amp;quot;userExitFn&amp;quot; kann eine Perl-Routine hinterlegt werden, um zum Beispiel nach dem Backup eine Mail oder Telegram-Message mit dem Erfolgsstatus zu versenden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das fertig konfigurierte Device hier als RAW-Definition zur einfachen Nachnutzung. Die Angaben sind natürlich anzupassen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.fhemtest.Dump.ServerSide DbRep LogDB&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen .*Dump.*is.*running.*:remotecontrol/black_btn_PLAYgreen Database.*backup.*finished.*:remotecontrol/black_btn_GREEN tn_GREEN error.*:remotecontrol/black_btn_RED&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide dumpCompress 1&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide dumpDirLocal /sds1/backup/dumps_FHEM&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide dumpDirRemote /volume1/ApplicationBackup/dumps_FHEM&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide dumpFilesKeep 1&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide event-on-update-reading state&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide executeAfterProc set LogDB reopen&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide executeBeforeProc set LogDB reopen 3600&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide fastStart 1&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide ftpDebug 0&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide ftpDir /ftp&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide ftpDumpFilesKeep 3&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide ftpPwd ftpftp1&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide ftpServer sds1.&amp;lt;fqdn&amp;gt;&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide ftpUse 0&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide ftpUser ftpuser&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide optimizeTablesBeforeDump 1&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide showproctime 1&lt;br /&gt;
attr Rep.fhemtest.Dump.ServerSide userExitFn doafterdump&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== 3. Backup durchführen ===== &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voraussetzung ist, dass der verwendete Datenbankuser das globale Privileg &#039;&#039;&#039;FILE&#039;&#039;&#039; besitzt. &lt;br /&gt;
Falls der User dieses Recht nicht hat, kann man es mit dem definierten DbRep-Device wie folgt erledigen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;(optional) dem Datenbankuser das FILE Privileg zuweisen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Da die Rechtezuweisung nur mit einem administrativen DB-User (i.A. root) funktioniert, wird dieser User im DbRep-Device angelegt und aktiviert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 set  Rep.fhemtest.Dump.ServerSide adminCredentials &amp;lt;Admin-User&amp;gt; &amp;lt;Passwort&amp;gt;&lt;br /&gt;
 attr Rep.fhemtest.Dump.ServerSide useAdminCredentials 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun kann dem verwendeten Datenbankuser das FILE Privileg zugeordnet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set  Rep.fhemtest.Dump.ServerSide sqlCmd GRANT FILE ON *.* TO &#039;&amp;lt;DB-User&amp;gt;&#039;@&#039;%&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei ist &#039;&#039;&#039;&amp;lt;DB-User&amp;gt;&#039;&#039;&#039; durch den in der DbLog-Konfiguration angegebenen User zu ersetzen da die gesamte Datenbankarbeit mit diesem User erfolgt.&lt;br /&gt;
&lt;br /&gt;
Nach der Ausführung schaltet man die Nutzung des administrativen Users wieder ab mit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr Rep.fhemtest.Dump.ServerSide useAdminCredentials 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Rechte können nun überprüft werden mit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set  Rep.fhemtest.Dump.ServerSide sqlCmd show grants;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und werden im Ergebnis dargestellt (z.B. für den DB-User fhemtest):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SqlResultRow_1  GRANTS FOR FHEMTEST@%&lt;br /&gt;
SqlResultRow_2  GRANT PROCESS, FILE, INDEX ON *.* TO &#039;fhemtest&#039;@&#039;%&#039; IDENTIFIED BY PASSWORD &#039;*...............&#039;&lt;br /&gt;
SqlResultRow_3  GRANT SELECT, INSERT, UPDATE, DELETE, ALTER, EXECUTE, SHOW VIEW ON `fhemtest`.* TO &#039;fhemtest&#039;@&#039;%&#039;&lt;br /&gt;
SqlResultRow_4  GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX ON `fhemtest`.`fhemtest` TO &#039;fhemtest&#039;@&#039;%&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
:&#039;&#039;&#039;Backup starten&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:dumpmysql2.PNG|right|thumb|400px|Backup läuft ...]]&lt;br /&gt;
Mit dem wie beschrieben eingerichteten DbRep-Device kann das Backup gestartet werden mit:&lt;br /&gt;
&lt;br /&gt;
 set Rep.fhemtest.Dump.ServerSide dumpMySQL serverSide&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zu Beginn des Vorgangs wird sofort die Verbindung des DbLog-Devices zur Datenbank getrennt.&lt;br /&gt;
Ein laufendes serverSide Backup kann mit FHEM-Mitteln nicht abgebrochen werden !&lt;br /&gt;
&lt;br /&gt;
Das laufende Backup wird im state angezeigt mit &amp;quot;serverSide Dump is running - be patient and see Logfile !&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Logfile mit (mindestens) verbose 3 werden die relevanten Informationen zur Verfügung gestellt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2020.05.14 22:59:18.610 3: DbRep Rep.fhemtest.Dump.ServerSide - ########################################&lt;br /&gt;
2020.05.14 22:59:18.611 3: DbRep Rep.fhemtest.Dump.ServerSide - ###   New database serverSide dump   ###&lt;br /&gt;
2020.05.14 22:59:18.611 3: DbRep Rep.fhemtest.Dump.ServerSide - ########################################&lt;br /&gt;
2020.05.14 22:59:18.612 3: DbRep Rep.fhemtest.Dump.ServerSide - execute command before dump: &#039;set LogDB reopen 3600&#039; &lt;br /&gt;
2020.05.14 22:59:18.613 2: DbLog LogDB: Connection closed until 23:59:18 (3600 seconds).&lt;br /&gt;
2020.05.14 22:59:18.660 3: DbRep Rep.fhemtest.Dump.ServerSide - Searching for tables inside database fhemtest....&lt;br /&gt;
2020.05.14 22:59:18.664 3: DbRep Rep.fhemtest.Dump.ServerSide - Size of database fhemtest before optimize (MB): 8298.98&lt;br /&gt;
2020.05.14 22:59:18.665 3: DbRep Rep.fhemtest.Dump.ServerSide - Optimizing tables&lt;br /&gt;
2020.05.14 22:59:18.665 3: DbRep Rep.fhemtest.Dump.ServerSide - Optimizing table `current` (INNODB). It will take a while.&lt;br /&gt;
2020.05.14 22:59:19.560 3: DbRep Rep.fhemtest.Dump.ServerSide - Table 1 `current` optimized successfully.&lt;br /&gt;
2020.05.14 22:59:19.560 3: DbRep Rep.fhemtest.Dump.ServerSide - Optimizing table `history` (INNODB). It will take a while.&lt;br /&gt;
2020.05.14 23:30:09.183 3: DbRep Rep.fhemtest.Dump.ServerSide - Table 2 `history` optimized successfully.&lt;br /&gt;
2020.05.14 23:30:09.186 3: DbRep Rep.fhemtest.Dump.ServerSide - 2 tables have been optimized.&lt;br /&gt;
2020.05.14 23:30:09.253 3: DbRep Rep.fhemtest.Dump.ServerSide - Size of database fhemtest after optimize (MB): 8298.98&lt;br /&gt;
2020.05.14 23:30:09.254 3: DbRep Rep.fhemtest.Dump.ServerSide - Starting dump of database &#039;fhemtest&#039;, table &#039;history&#039;&lt;br /&gt;
2020.05.14 23:39:47.566 3: DbRep Rep.fhemtest.Dump.ServerSide - compress file /sds1/backup/dumps_FHEM/fhemtest_history_2020_05_14_23_30.csv&lt;br /&gt;
2020.05.14 23:42:33.138 3: DbRep Rep.fhemtest.Dump.ServerSide - file compressed to output file: /sds1/backup/dumps_FHEM/fhemtest_history_2020_05_14_23_30.csv.gzip&lt;br /&gt;
2020.05.14 23:42:34.784 3: DbRep Rep.fhemtest.Dump.ServerSide - input file deleted: /sds1/backup/dumps_FHEM/fhemtest_history_2020_05_14_23_30.csv&lt;br /&gt;
2020.05.14 23:42:34.785 3: DbRep Rep.fhemtest.Dump.ServerSide - Number of exported datasets: 49032159&lt;br /&gt;
2020.05.14 23:42:34.787 3: DbRep Rep.fhemtest.Dump.ServerSide - Size of backupfile: 419.73 MB&lt;br /&gt;
2020.05.14 23:42:37.082 3: DbRep Rep.fhemtest.Dump.ServerSide - FTP: transferring /sds1/backup/dumps_FHEM/fhemtest_history_2020_05_14_23_30.csv.gzip&lt;br /&gt;
2020.05.14 23:42:47.511 3: DbRep Rep.fhemtest.Dump.ServerSide - FTP: fhemtest_history_2020_05_14_23_30.csv.gzip transferred successfully to sds1.myds.me into dir /ftp&lt;br /&gt;
2020.05.14 23:42:47.558 3: DbRep Rep.fhemtest.Dump.ServerSide - Deleting old dumpfile &#039;fhemtest_history_2020_05_14_22_12.csv.gzip&#039; &lt;br /&gt;
2020.05.14 23:42:47.857 3: DbRep Rep.fhemtest.Dump.ServerSide - Finished backup of database fhemtest - total time used (hh:mm:ss): 00:43:29&lt;br /&gt;
2020.05.14 23:42:47.948 2: DbRep Rep.fhemtest.Dump.ServerSide - command message after dump: &amp;quot;Reopen executed.&amp;quot; &lt;br /&gt;
2020.05.14 23:42:47.973 3: DbRep Rep.fhemtest.Dump.ServerSide - Database dump finished successfully. &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:dumpmysql3.PNG|right|thumb|500px|Backup ist erfolgreich abgeschlossen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In vorliegenden Beispiel wird nach einem erfolgreichen Backup im state &#039;&#039;&#039;&amp;quot;Warning - dump finished, but command after dump message appeared&amp;quot;&#039;&#039;&#039; angezeigt. &lt;br /&gt;
&lt;br /&gt;
Diese Warnung rührt daher, dass das Reopen-Kommando eine Rückkehrinfo mitteilt, die als Issue gewertet und im Reading &amp;quot;afterdump_message&amp;quot; ausgegeben wird. In diesem Fall ist es nur eine Information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In den erstellten Readings wird zusammengetragen welches File mit welcher Größe erstellt wurde, welche alten Files gelöscht wurden, Informationen zum FTP-Transfer und welche Zeit der Gesamtprozess benötgt hat.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das so vorbereitete Backup kann nun z.B. täglich oder auch mit einer wesentlich kürzeren Wiederholungsperiode (alle x Stunden) über ein at-Device eingeplant werden:&lt;br /&gt;
&lt;br /&gt;
 define At.MySQL.Dump at *23:52:00 set Rep.fhemtest.Dump.ServerSide dumpMySQL serverSide&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== 4. Restore ===== &lt;br /&gt;
&lt;br /&gt;
Voraussetzung für das Restore ist, dass der verwendete Datenbankuser das globale Privileg &#039;&#039;&#039;FILE&#039;&#039;&#039; besitzt. &lt;br /&gt;
Falls der User dieses Recht nicht hat, kann man es mit dem definierten DbRep-Device wie folgt erledigen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;(optional) dem Datenbankuser das FILE Privileg zuweisen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Da die Rechtezuweisung nur mit einem administrativen DB-User (i.A. root) funktioniert, wird dieser User im DbRep-Device angelegt und aktiviert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 set  Rep.fhemtest.Dump.ServerSide adminCredentials &amp;lt;Admin-User&amp;gt; &amp;lt;Passwort&amp;gt;&lt;br /&gt;
 attr Rep.fhemtest.Dump.ServerSide useAdminCredentials 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun kann dem verwendeten Datenbankuser das FILE Privileg zugeordnet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set  Rep.fhemtest.Dump.ServerSide sqlCmd GRANT FILE ON *.* TO &#039;&amp;lt;DB-User&amp;gt;&#039;@&#039;%&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei ist &#039;&#039;&#039;&amp;lt;DB-User&amp;gt;&#039;&#039;&#039; durch den in der DbLog-Konfiguration angegebenen User zu ersetzen da die gesamte Datenbankarbeit mit diesem User erfolgt.&lt;br /&gt;
&lt;br /&gt;
Nach der Ausführung schaltet man die Nutzung des administrativen Users wieder ab mit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr Rep.fhemtest.Dump.ServerSide useAdminCredentials 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Alternativ&#039;&#039;&#039; kann die Rechtezuweisung auf der Konsole des MySQL-Servers ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo mysql -u root -p&lt;br /&gt;
GRANT File ON *.* TO &#039;&amp;lt;DB-User&amp;gt;&#039;@&#039;%&#039;;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Rechte können nun überprüft werden mit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set  Rep.fhemtest.Dump.ServerSide sqlCmd show grants;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nun kann der Restore ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ein mit der Option &#039;&#039;&#039;serverSide&#039;&#039;&#039; erstellter Dump enthält ausschließlich die Daten der history-Tabelle. &lt;br /&gt;
Der Restore kann nur in eine bestehende Datenabank und entsprechend angelegte history Tabelle erfolgen.&lt;br /&gt;
Ist nach einem Datenbankfehler die Tabelle/Datenbank zerstört, must sie zunächst mit den vorbereiteten Befehlen in den &lt;br /&gt;
[https://svn.fhem.de/trac/browser/trunk/fhem/contrib/dblog/db_create_mysql.sql SVN-Skripten] bereitgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Ist die history-Tabelle noch intakt und soll nur der Inhalt ersetzt werden, muss die Tabelle vorab geleert werden da sonst unter Umständen doppelte Datensätze enstehen wenn kein primary Key verwendet ist.&lt;br /&gt;
Das kann einfach mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; sqlCmd truncate table history&lt;br /&gt;
&lt;br /&gt;
erreicht werden. Damit werden &#039;&#039;&#039;alle&#039;&#039;&#039; Daten der history-Tabelle hochperformant gelöscht. Die Tabelle selbst bleibt erhalten. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sollte der truncate Befehl wegen nicht ausreichender Rechte des DB-Users mit Fehler enden, kann ein administrativer Datenbankuser (i.A. &#039;root&#039;) mit dem Kommando und Attribut&lt;br /&gt;
&lt;br /&gt;
 set  &amp;lt;Name&amp;gt; adminCredentials &amp;lt;Name&amp;gt; &amp;lt;Passwort&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; useAdminCredentials 1&lt;br /&gt;
&lt;br /&gt;
hinterlegt und aktiviert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ein Restore kann mit dem angelegten DbRep-Device im laufenden Betrieb geschehen. Auch hier ist wieder wichtig, dass das DbLog-Device  im asynchronen Modus betrieben wird und die Reopen-Zeit (siehe Einstellung Attribut &amp;quot;executeBeforeProc&amp;quot;) sehr großzügig eingestellt ist. &lt;br /&gt;
&lt;br /&gt;
Zum Restore dient der Befehl &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; restoreMySQL &amp;lt;File&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:dumpmysql4.PNG|right|thumb|500px|Auswahlmenü Files für Restore ]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im FHEMWEB öffnet sich dazu eine DropDown-Liste die alle vorhandenen und zur Quelldatenbank passenden Dumpfiles auflistet. &lt;br /&gt;
Das herzustellende File kann so bequem ausgewählt werden. Die Dumpfiles müssen sich in dem Verzeichnis befinden, welches durch das Attribut &#039;&#039;&#039;dumpDirLocal&#039;&#039;&#039; festgelegt wurde (default (./log).  [[Datei:dumpmysql5.PNG|left|thumb|500px|Restore läuft]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der restore wird demzufolge gestartet mit:&lt;br /&gt;
&lt;br /&gt;
 set Rep.fhemtest.Dump.ServerSide restoreMySQL &amp;lt;File&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Restore der history-Tabelle kann nun online im laufenden FHEM-Betrieb erfolgen.&lt;br /&gt;
Wieder wird zu Beginn des Vorgangs das verbundene DbLog-Device von der Datenbank abgekoppelt und nach dem Restore wieder automatisch verbunden. Eine Datenbankoptimierung bzw. FTP-Transfer wird bei diesem Vorgang natürlich nicht ausgeführt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:dumpmysql6.PNG|left|thumb|500px|Fortschrittsanzeige in einem zweiten DbRep Device]]&lt;br /&gt;
In einem zweiten (z.B. kopierten) DbRep Device kann mit Hilfe des Befehls&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 get Rep.fhemtest.Dump.ServerSide procinfo&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
der Fortschritt des Restores überwacht werden. In der Spalte &#039;&#039;&#039;PROGRESS&#039;&#039;&#039; wird der Fortschritt in &#039;&#039;&#039;%&#039;&#039;&#039; angegeben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Log zeigt den Ablauf des Restores:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2020.05.15 13:07:24.369 3: DbRep Rep.fhemtest.Dump.ServerSide - #######################################&lt;br /&gt;
2020.05.15 13:07:24.370 3: DbRep Rep.fhemtest.Dump.ServerSide - ###   New database Restore/Recovery ###&lt;br /&gt;
2020.05.15 13:07:24.371 3: DbRep Rep.fhemtest.Dump.ServerSide - #######################################&lt;br /&gt;
2020.05.15 13:07:24.371 3: DbRep Rep.fhemtest.Dump.ServerSide - execute command before restore: &#039;set LogDB reopen 3600&#039; &lt;br /&gt;
2020.05.15 13:07:24.429 3: DbRep Rep.fhemtest.Dump.ServerSide - uncompress file /sds1/backup/dumps_FHEM/fhemtest_history_2020_05_15_11_47.csv.gzip&lt;br /&gt;
2020.05.15 13:09:31.152 3: DbRep Rep.fhemtest.Dump.ServerSide - file uncompressed to output file: /sds1/backup/dumps_FHEM/fhemtest_history_2020_05_15_11_47.csv&lt;br /&gt;
2020.05.15 13:09:31.237 3: DbRep Rep.fhemtest.Dump.ServerSide - Size of uncompressed file: 5511.52 MB&lt;br /&gt;
2020.05.15 13:09:31.242 3: DbRep Rep.fhemtest.Dump.ServerSide - Starting restore of database &#039;fhemtest&#039;, table &#039;history&#039;. &lt;br /&gt;
2020.05.15 14:42:28.566 2: DbLog LogDB: Connection closed until 16:42:28 (7200 seconds).&lt;br /&gt;
2020.05.15 14:46:22.391 3: DbRep Rep.fhemtest.Dump.ServerSide - Restore of /volume1/ApplicationBackup/dumps_FHEM/fhemtest_history_2020_05_15_11_47.csv into &#039;fhemtest&#039;, &#039;history&#039; finished - total time used (hh:mm:ss): 01:38:57&lt;br /&gt;
2020.05.15 14:46:22.457 2: DbRep Rep.fhemtest.Dump.ServerSide - command message after restore: &amp;quot;Reopen executed.&amp;quot; &lt;br /&gt;
2020.05.15 14:46:22.481 3: DbRep Rep.fhemtest.Dump.ServerSide - Database restore finished successfully.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:dumpmysql7.PNG|right|thumb|300px|Restore erfolgreich abgeschlossen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Restore wurde erfolgreich abgeschlossen und die Verbindung des DbLog-Device LogDB zur Datenbank wiederhergestellt. Das Logging wird nahtlos fortgeführt.&lt;br /&gt;
&lt;br /&gt;
Es ist natürlich zu beachten, dass die Daten zwischen dem Erstellungszeitpunkt des eingespielten Backups und der aktuellen Zeit verloren sind !&lt;br /&gt;
Eventuell in der Tabelle &#039;&#039;&#039;history&#039;&#039;&#039; noch vorhandene Daten werden &#039;&#039;&#039;nicht&#039;&#039;&#039; überschrieben. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speichern von Berechnungswerten in der Datenbank und Erstellen eines Plots (ab Version 7.5.1) ===&lt;br /&gt;
&lt;br /&gt;
Es sollen aus in der Datenbank vorhandenen minütlichen Leistungswerten eines Wechselrichters die maximal-, minimal- und durchschnittlichen Leistungswerte pro Tag berechnet werden und diese Ergebnisse wieder in die Datenbank geschrieben werden um daraus einen Plot zu erstellen.&lt;br /&gt;
Diese Berechnung soll immer aktuell für den laufenden Monat erfolgen.&lt;br /&gt;
&lt;br /&gt;
Die Ausgangswerte liegen in der Datenbank als minütliche kW-Einträge vor (Auszug DbRep fetchrows):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2018-01-18_15-55-49__MySTP_5000__total_pac 0.200&lt;br /&gt;
2018-01-18_15-56-50__MySTP_5000__total_pac 0.218&lt;br /&gt;
2018-01-18_16-00-14__MySTP_5000__total_pac 0.209&lt;br /&gt;
2018-01-18_16-00-39__MySTP_5000__total_pac 0.198&lt;br /&gt;
2018-01-18_16-01-39__MySTP_5000__total_pac 0.142&lt;br /&gt;
2018-01-18_16-02-39__MySTP_5000__total_pac 0.130&lt;br /&gt;
2018-01-18_16-03-39__MySTP_5000__total_pac 0.117&lt;br /&gt;
2018-01-18_16-05-39__MySTP_5000__total_pac 0.087&lt;br /&gt;
2018-01-18_16-06-39__MySTP_5000__total_pac 0.071&lt;br /&gt;
2018-01-18_16-07-39__MySTP_5000__total_pac 0.076&lt;br /&gt;
2018-01-18_16-08-39__MySTP_5000__total_pac 0.065&lt;br /&gt;
2018-01-18_16-09-39__MySTP_5000__total_pac 0.069&lt;br /&gt;
2018-01-18_16-10-39__MySTP_5000__total_pac 0.060&lt;br /&gt;
2018-01-18_16-12-39__MySTP_5000__total_pac 0.065&lt;br /&gt;
2018-01-18_16-13-39__MySTP_5000__total_pac 0.068&lt;br /&gt;
2018-01-18_16-14-39__MySTP_5000__total_pac 0.054&lt;br /&gt;
2018-01-18_16-15-39__MySTP_5000__total_pac 0.041&lt;br /&gt;
2018-01-18_16-16-39__MySTP_5000__total_pac 0.027&lt;br /&gt;
2018-01-18_16-17-39__MySTP_5000__total_pac 0.026&lt;br /&gt;
2018-01-18_16-18-39__MySTP_5000__total_pac 0.021&lt;br /&gt;
2018-01-18_16-19-39__MySTP_5000__total_pac 0.018&lt;br /&gt;
2018-01-18_16-20-39__MySTP_5000__total_pac 0.012&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für die Berechnung der Ergenisse stehen in DbRep die Kommandos maxValue, minValue und averageValue zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== 1. Anlegen des DbRep-Devices ====&lt;br /&gt;
&lt;br /&gt;
Das anzulegende Device wird für alle notwendigen Berechnungen verwendet.&lt;br /&gt;
Die Definition des DbRep-Devices erfolgt unter Angabe des zu verbindenden DbLog-Devices (nicht der Datenbank selbst): &lt;br /&gt;
&lt;br /&gt;
 define Rep.total_pac DbRep LogDB&lt;br /&gt;
&lt;br /&gt;
Ist das Device definiert, verbindet es sich zu der Datenbank und wechselt in den state &amp;quot;connected&amp;quot;, sofern die Verbindung erfolgreich verlief.&lt;br /&gt;
Prinzipiell funktioniert der hier Ablauf mit einem im synchronous Mode betriebenen DbLog-Device, aber es ist dringend angeraten das DbLog-Device (LogDB) in den asynchronen Modus umzuschalten. Dadurch werden Blockierungen von FHEM verhindert.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 2. Einstellungen des DbRep-Devices (Attribute) ====&lt;br /&gt;
[[Datei:Rep.total_pac.PNG|right|thumb|400px|Device definiert]]&lt;br /&gt;
Für die gewünschte Funktion müssen in diesem neu definierten Device einige relevante Attribute gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
Da die Berechnungen immer für den aktuellen Monat erstellt werden sollen, wird das Attribut &amp;quot;timestamp_begin&amp;quot; so definiert, dass immer der Beginn des aktuellen Monats dynamisch ermittelt wird. Das ist gegeben durch den Eintrag:&lt;br /&gt;
&lt;br /&gt;
 attr Rep.total_pac timestamp_begin current_month_begin&lt;br /&gt;
&lt;br /&gt;
Es soll ein Ergebniswert pro Tag erzeugt werden. Damit dies erreicht werden kann, wird das Attribut &amp;quot;aggregation&amp;quot; verwendet und auf den Wert &amp;quot;day&amp;quot; eingestellt. Würde zum Beispiel ein stündlicher Ergebniswert gewünscht sein, hätte &amp;quot;aggregation = hour&amp;quot; den benötigten Effekt.&lt;br /&gt;
&lt;br /&gt;
 attr Rep.total_pac aggregation day&lt;br /&gt;
&lt;br /&gt;
Die Attribute &amp;quot;device&amp;quot; und &amp;quot;reading&amp;quot; legen das auszuwertende Device und Reading fest. Dabei ist zu beachten, dass im Gegensatz zur allgemein gültigen Möglichkeit devspec bzw. SQL-Wildcards zu verwenden bei dieser speziellen Detailfunktion dies nicht der Fall ist. Das heißt. es muß immer ein eindeutiges Device und ein eindeutiges Reading angegeben werden. Der Grund liegt in der Notwendigkeit, bei der Speicherung der Ergebnisdaten der Datenbank ebenfalls ein eindeutiges Device und Reading zu übergeben. In dem Beispiel wird das Device &amp;quot;MySTP_5000&amp;quot; und das Reading &amp;quot;total_pac&amp;quot; ausgewertet.&lt;br /&gt;
&lt;br /&gt;
 attr Rep.total_pac device MySTP_5000&lt;br /&gt;
 attr Rep.total_pac reading total_pac&lt;br /&gt;
&lt;br /&gt;
Hilfreiche Attribute sind noch &amp;quot;event-on-update-reading&amp;quot; zur Begrenzung der Events, &amp;quot;showproctime&amp;quot; zur Bestimmung der Prozesszeiten und &amp;quot;allowDeletion&amp;quot; um die Möglichkeit zu haben, irrtümlich gespeicherte Berechnungsergebnisse wieder über das DbRep-Device zu löschen.&lt;br /&gt;
&lt;br /&gt;
 attr Rep.total_pac event-on-update-reading state&lt;br /&gt;
 attr Rep.total_pac showproctime 1&lt;br /&gt;
 attr Rep.total_pac allowDeletion 1&lt;br /&gt;
&lt;br /&gt;
Das so vorbereitete Device ist für die benötigten Funktionen ausreichend eingestellt. &lt;br /&gt;
Zur einfachen Nachnutzung nochfolgend die Raw-Definition des DbRep-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.total_pac DbRep LogDB&lt;br /&gt;
attr Rep.total_pac aggregation day&lt;br /&gt;
attr Rep.total_pac allowDeletion 1&lt;br /&gt;
attr Rep.total_pac device MySTP_5000&lt;br /&gt;
attr Rep.total_pac event-on-update-reading state&lt;br /&gt;
attr Rep.total_pac reading total_pac&lt;br /&gt;
attr Rep.total_pac room DbLog&lt;br /&gt;
attr Rep.total_pac showproctime 1&lt;br /&gt;
attr Rep.total_pac timestamp_begin current_month_begin&lt;br /&gt;
attr Rep.total_pac verbose 3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== 3. Berechnung ausführen und Speicherung der Ergebnisse ====&lt;br /&gt;
[[Datei:average.PNG|right|thumb|300px|Average Berechnung]]&lt;br /&gt;
Die benötigten Funktionen sind:&lt;br /&gt;
&lt;br /&gt;
 averageValue - Berechnung des täglichen Durchschnittswert der Wechselrichterleistung (kW)&lt;br /&gt;
 maxValue - Berechnung des täglichen Maximalwertes der Wechselrichterleistung (kW)&lt;br /&gt;
 minValue - Berechnung des täglichen Minimalwertes der Wechselrichterleistung (kW)&lt;br /&gt;
&lt;br /&gt;
[[Datei:minval.PNG|right|thumb|300px|MinVal Berechnung]]&lt;br /&gt;
Für jede dieser Kommandos stehen im DbRep die Optionen &amp;quot;display&amp;quot; und &amp;quot;writeToDB&amp;quot; zur Verfügung. Die Option &amp;quot;display&amp;quot; stellt die Ergenisse lediglich im Browser dar und kann dazu die Ergebnisse vor der Speicherung zu bewerten.&lt;br /&gt;
So ergeben die Kommandos:&lt;br /&gt;
&lt;br /&gt;
 set Rep.total_pac minValue display &lt;br /&gt;
 set Rep.total_pac maxValue display &lt;br /&gt;
 set Rep.total_pac avarageValue display &lt;br /&gt;
&lt;br /&gt;
die täglichen Min-, Max- und Durchschnittswerte der WR-Leistung.&lt;br /&gt;
&lt;br /&gt;
[[Datei:maxval.PNG|right|thumb|300px|MaxVal Berechnung]]&lt;br /&gt;
Entsprechen die Ergebnisse den Erwartungen bzw. dem Ziel, können die folgenden Kommandos verwendet werden um die Berechnung durchzuführen und dabei gleichzeitig in die Datenbank zu schreiben. &lt;br /&gt;
&lt;br /&gt;
 set Rep.total_pac minValue writeToDB&lt;br /&gt;
 set Rep.total_pac maxValue writeToDB&lt;br /&gt;
 set Rep.total_pac avarageValue writeToDB&lt;br /&gt;
&lt;br /&gt;
Die Daten werden in der history-Tabelle gespeichert und, sofern das DbLog-Device das Attribut &amp;quot;DbLogType = Current...&amp;quot; gestzt hat, auch in der current-Tabelle gespeichert. Im letzteren Fall kann das Ergebnisreading bei der Erstellung des Plots sofort aus der DropDown-Liste ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
Bei der Datenspeicherung wird der neue Readingnamen aus einem Präfix und dem originalen Readingnamen gebildet. Der Präfix setzt sich aus der Bildungsfunktion und der gewählten Aggregation zusammen, d.h. im Fall des Beispiels aus &amp;quot;min&amp;quot;,&amp;quot;max&amp;quot;,&amp;quot;avg&amp;quot; und &amp;quot;day&amp;quot;.&lt;br /&gt;
Der Timestamp der neuen Readings in der Datenbank wird von der eingestellten Aggregationsperiode abgeleitet, sofern kein eindeutiger Zeitpunkt des Ergebnisses bestimmt werden kann. So kann der Zeitpunkt des Maximalwertes eines Tages wertes genau bestimmt werden und der resultierende Datensatz wird mit diesem Timestamp gespeichert.&lt;br /&gt;
&lt;br /&gt;
Die resultierende Readingnamen werden somit wie folgt in der Datenbank gespeichert:&lt;br /&gt;
&lt;br /&gt;
 max_day_total_pac&lt;br /&gt;
 min_day_total_pac&lt;br /&gt;
 avg_day_total_pac&lt;br /&gt;
&lt;br /&gt;
Die Berechnungen können regelmäßig über ein at eingeplant werden. Die Funktionen vermeiden dabei die Speicherung von doppelten Datensätzen. Wurde bei einem Berechnungslauf der Datensatz bereits gespeichert, wird dieser Datensatz beim nächsten Durchlauf nicht noch einmal gespeichert.&lt;br /&gt;
&lt;br /&gt;
==== 4. Erstellung des Plots ====&lt;br /&gt;
[[Datei:dropdown.PNG|right|thumb|300px|Drop-Down Liste SVG]]&lt;br /&gt;
Wird durch das DbLog-Device die current-Tabelle genutzt, das Attribut &amp;quot;DbLogType = Current...&amp;quot; ist gesetzt, können die Ergebnisreadings max_day_total_pac, min_day_total_pac und avg_day_total_pac im SVG-Editor ausgewählt werden (siehe {{Link2CmdRef|Lang=de|Anker=SVG}} bei SVG).&lt;br /&gt;
&lt;br /&gt;
Durch die Wahl des Plot-Typ &amp;quot;bars&amp;quot; und dem SVG-Attribut &amp;quot;fixedrange = month&amp;quot; entsteht der gewünschte Tageswert-Plot über den aktuellen Monat.&lt;br /&gt;
&lt;br /&gt;
[[Datei:svg_calc.PNG|right|thumb|300px|Ergebnis SVG]]&lt;br /&gt;
Hier wiederum die Raw-Definition des SVG-Device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod SVG_LogDB_16 SVG LogDB:SVG_LogDB_16:HISTORY&lt;br /&gt;
attr SVG_LogDB_16 fixedrange month&lt;br /&gt;
attr SVG_LogDB_16 room Energie,SVG_MySQL&lt;br /&gt;
attr SVG_LogDB_16 title &amp;quot;Max Leistung: $data{max1} kW, Min Leistung: $data{min3} kW,Max. Durchschnittsleistung: $data{max2} kW &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sowie des gplot-Files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2018-01-18 21:45:27&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;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;kW&amp;quot;&lt;br /&gt;
set y2label &amp;quot;kW&amp;quot;&lt;br /&gt;
set yrange [0:6]&lt;br /&gt;
set y2range [0:6]&lt;br /&gt;
&lt;br /&gt;
#LogDB MySTP_5000:max_day_total_pac&lt;br /&gt;
#LogDB MySTP_5000:avg_day_total_pac&lt;br /&gt;
#LogDB MySTP_5000:min_day_total_pac&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Max-Leistung / Tag&#039; ls l0fill lw 1 with bars,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Average / Tag&#039; ls l2fill lw 1 with bars,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Min-Leistung / Tag&#039; ls l1fill lw 1 with bars&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Öffnungszeiten von Fenster/Türen aus der Datenbank ermitteln ===&lt;br /&gt;
&lt;br /&gt;
Ziel ist es, die Öffnungszeit eines Fensters oder einer Tür zu ermitteln sobald es wieder geschlossen wird und ein Reading mit der Zeit in dem entsprechenden Device (Fensterkontakt) zu setzen.&lt;br /&gt;
&lt;br /&gt;
Für das Beispiel wird angenommen dass:&lt;br /&gt;
&lt;br /&gt;
* der Status der Sensoren als &amp;quot;open&amp;quot; und &amp;quot;close&amp;quot; in der Datenbank gespeichert ist&lt;br /&gt;
* das verwendetet DbRep-Device &amp;quot;Rep.WindowOpenTime&amp;quot; heißt&lt;br /&gt;
* das verwendete DbLog-Device &amp;quot;LogDBShort&amp;quot; heißt (wird mit dem DbRep-Device bei der Definition assoziiert)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zunächst wird zur Auswertung von closed-Events ein entsprechendes Notify definiert (Raw-Format):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod N.WindowClosed notify (.*fenster.*|.*terrasse.tuer.*):closed \&lt;br /&gt;
  { \&lt;br /&gt;
    if($NAME =~ /(.*fenster.*|.*terrasse.tuer.*)/) {\&lt;br /&gt;
      fhem(&amp;quot;set LogDBShort commitCache;; defmod calcse at +00:00:10 {SwitchEvent(\&amp;quot;$NAME\&amp;quot;)};;&amp;quot;);; \&lt;br /&gt;
    }\&lt;br /&gt;
  }&lt;br /&gt;
attr N.WindowClosed alias Starte Ermittlung der Fenster Öffnungszeiten&lt;br /&gt;
attr N.WindowClosed comment Wird verwendet um die letzte Öffnungszeit der Fenster aus der Datenbank zu ermitteln und im Reading &amp;quot;LastOpenTime&amp;quot; abzulegen.&lt;br /&gt;
attr N.WindowClosed room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die zusätzlich if-Abfrage im Notify behob ein Problem bei den Fensterkontakten die mit einem Thermostat gepeert sind, da in diesem Fall der Event mehrfach auftrat. Der Teil &#039;&#039;&#039;&amp;quot;set LogDBShort commitCache&amp;quot;&#039;&#039;&#039; speichert den Cache der Datenbank vor der Berechnung sofern sie im asynchronen Modus betrieben wird (kann entfallen wenn im synchronen Mode betrieben). Um der DB Zeit zur Abspeicherung zu geben, wird die Berechnung über ein AT mit einer entsprechenden Verzögerung (hier 10 Sekunden) angestartet. Die Zeit im AT bitte entsprechend der eigenen Systembedingungen anpassen.  &lt;br /&gt;
&lt;br /&gt;
Im Notify wird die Funktion &#039;&#039;&#039;SwitchEvent($NAME)&#039;&#039;&#039; aufgerufen. Diese Funktion wird in der 99_myUtils.pm eingefügt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
##########################################################################################################&lt;br /&gt;
#  This function is used to start an SQL query for the given device &amp;quot;$name&amp;quot; and check&lt;br /&gt;
#  how much time the device was in state defined by $usedVal1 today.&lt;br /&gt;
#  The query is done by a DbRep device.&lt;br /&gt;
# &lt;br /&gt;
#  In this example the name of the DbRep device is &amp;quot;Rep.WindowOpenTime&amp;quot;&lt;br /&gt;
##########################################################################################################&lt;br /&gt;
sub SwitchEvent($) {&lt;br /&gt;
  my ($name) = @_;&lt;br /&gt;
 &lt;br /&gt;
  Log3 $name , 5, &amp;quot;$name - SwitchEvent called&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
  my $usedReading = &amp;quot;\&amp;quot;state\&amp;quot;&amp;quot;;           # name of the reading which holds the state which has to be checked&lt;br /&gt;
  my $usedVal1 = &amp;quot;\&amp;quot;open\&amp;quot;&amp;quot;;               # reading value which starts the time measuerement&lt;br /&gt;
  my $usedVal2 = &amp;quot;\&amp;quot;closed\&amp;quot;&amp;quot;;             # reading value which stops the time measurement&lt;br /&gt;
  my $device = &amp;quot;\&amp;quot;$name\&amp;quot;&amp;quot;;                # name of the device which state has to be checked&lt;br /&gt;
  my $dbRepDevice = &amp;quot;Rep.WindowOpenTime&amp;quot;;  # name of the DbRep device&lt;br /&gt;
 &lt;br /&gt;
  # The query will check for the current day the cumulated time difference between $usedVal1 and $usedVal2&lt;br /&gt;
  # the example here is a homemetic threeStateSensor (window contact) and the result of the query is&lt;br /&gt;
  # the cumulated time which the window was open (in seconds) and the name of the device whic is&lt;br /&gt;
  # used by the function SwitchQueryResult()&lt;br /&gt;
  # Example:  AZ_Fensterkontakt|433.2&lt;br /&gt;
  my $sql = &amp;quot;SET \@topen = NULL,\@closed = NULL, \@popen = NULL;;&amp;quot;.&lt;br /&gt;
            &amp;quot; SELECT  DEVICE ,SUM(TIMEDIFF(tclosed, topen)) AS duration FROM (&amp;quot;.&lt;br /&gt;
            &amp;quot; SELECT TIMESTAMP, VALUE, DEVICE,&amp;quot;.&lt;br /&gt;
            &amp;quot; \@topen   := \@popen AS topen,&amp;quot;.&lt;br /&gt;
            &amp;quot; \@closed  := IF(VALUE = $usedVal2,  TIMESTAMP, NULL) AS tclosed,&amp;quot;.&lt;br /&gt;
            &amp;quot; \@popen   := IF(VALUE = $usedVal1, TIMESTAMP, NULL) AS prev_open&amp;quot;.&lt;br /&gt;
            &amp;quot; FROM history WHERE&amp;quot;.&lt;br /&gt;
            &amp;quot; DATE(TIMESTAMP) = CURDATE() AND&amp;quot;.&lt;br /&gt;
            &amp;quot; DEVICE = $device AND&amp;quot;.&lt;br /&gt;
            &amp;quot; READING = $usedReading AND &amp;quot;.&lt;br /&gt;
            &amp;quot; (VALUE = $usedVal1 OR VALUE = $usedVal2)&amp;quot;.&lt;br /&gt;
            &amp;quot; ORDER BY  TIMESTAMP&amp;quot;.&lt;br /&gt;
            &amp;quot; ) AS tmp&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
  Log3 $name , 5, &amp;quot;$name - SwitchEvent start query: $sql&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
  fhem(&amp;quot;set $dbRepDevice sqlCmd $sql&amp;quot;); # start the query now. Result will be processed in the function SwitchQueryResult() below&lt;br /&gt;
 &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Funktion &#039;&#039;&#039;SwitchEvent()&#039;&#039;&#039; bekommt den Namen des Gerätes übergeben welches Event ausgelöst hat. Damit wird eine SQL-Abfrage für dieses Gerät gestartet und ermittelt,  wieviel Zeit (in Sekunden) für das übergebene Gerät zwischen dem Zustand &amp;quot;open&amp;quot; und &amp;quot;closed&amp;quot; verbracht wurde. &lt;br /&gt;
&lt;br /&gt;
Das verwendete DbRep-Device wird wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.WindowOpenTime DbRep LogDBShort&lt;br /&gt;
attr Rep.WindowOpenTime aggregation no&lt;br /&gt;
attr Rep.WindowOpenTime comment Öffnungszeit der Fenster ermitteln&lt;br /&gt;
attr Rep.WindowOpenTime initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.WindowOpenTime reading state&lt;br /&gt;
attr Rep.WindowOpenTime showproctime 1&lt;br /&gt;
attr Rep.WindowOpenTime sqlResultFormat sline&lt;br /&gt;
attr Rep.WindowOpenTime event-on-update-reading state&lt;br /&gt;
attr Rep.WindowOpenTime userExitFn SwitchQueryResult&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ganz wichtig ist die Zeile &#039;&#039;&#039;attr Rep.powerOnTime userExitFn SwitchQueryResult&#039;&#039;&#039;. Hier ist die Funktion &#039;&#039;&#039;SwitchQueryResult()&#039;&#039;&#039; angegeben, die nach erfolgreicher Bearbeitung der SQL-Query aufgerufen wird. Diese Funktion wird ebenfalls in der 99_myUtils.pm eingefügt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
##########################################################################################################&lt;br /&gt;
# This function will be called from the DbRep device if the attribute&lt;br /&gt;
# attr Name_of_your_DbRep_device userExitFn SwitchQueryResult is set.&lt;br /&gt;
# This function create a new reading &amp;quot;LastOpenTime&amp;quot; at the device for which the query is done and&lt;br /&gt;
# set the cumulated time difference in seconds to the reading.&lt;br /&gt;
##########################################################################################################&lt;br /&gt;
sub SwitchQueryResult($$$) {&lt;br /&gt;
   my ($name,$reading,$value) = @_;  # $name is the name of the DbRep device which is calling this function&lt;br /&gt;
   my $hash = $defs{$name};&lt;br /&gt;
 &lt;br /&gt;
   # DbRep calls this function several times with different informations.&lt;br /&gt;
   # if $reading is SqlResult, $value will hold the result of the query&lt;br /&gt;
   if ($reading eq &amp;quot;SqlResult&amp;quot;) {&lt;br /&gt;
       my ($dev,$val) = split(&#039;\|&#039;,$value);                   # split the result in two parts&lt;br /&gt;
       $dev = $dev?$dev:&amp;quot;&amp;quot;;&lt;br /&gt;
       $val = $val?$val:&amp;quot;&amp;quot;;&lt;br /&gt;
       if (!$val) {&lt;br /&gt;
           $val = 0;&lt;br /&gt;
       }&lt;br /&gt;
       $val = DbRep_sec2hms($val);                            # calculate seconds to hms&lt;br /&gt;
       Log3 $name , 5, &amp;quot;DbRep $name - SwitchQueryResult splitted result: $dev $val&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
       fhem(&amp;quot;setreading $dev LastOpenTime $val&amp;quot;) if($dev);    # set the reading &amp;quot;LastOpenTime&amp;quot; with the time if device-Log was found&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Funktion SwitchQueryResult() rechnet das Ergebnis der query aus dem DbRep Device von Sekunden in das Format hh:mm:ss um und trägt die berechnete Zeit als Reading &amp;quot;&#039;&#039;&#039;LastOpenTime&#039;&#039;&#039;&amp;quot; im jeweiligen Fensterkontakt ein.&lt;br /&gt;
&lt;br /&gt;
So kann man z.B. im Device mit dem Namen &amp;quot;eg.bad.fenster&amp;quot; das Reading &amp;quot;&#039;&#039;&#039;LastOpenTime 00:03:58&#039;&#039;&#039;&amp;quot; finden.&lt;br /&gt;
Die vorliegende Berechnung liefert immer die Zeit des letzten Öffnungszyklus des aktuellen Tages. Möchte man die Zeiten des gesamten Tages akkumulieren, kann nach der Beschreibung &amp;quot;[[Summe aller Einschaltzeiten eines Gerätes]]&amp;quot; verfahren werden.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Logging]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Batterie%C3%BCberwachung&amp;diff=23533</id>
		<title>Batterieüberwachung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Batterie%C3%BCberwachung&amp;diff=23533"/>
		<updated>2017-12-12T08:10:12Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Verschiedene batteriebetriebene Geräte ([[:Kategorie:HomeMatic Components|Homematic]], RFXtrx, ZWave,..) übermitteln unter anderem den Zustand der eingelegten Batterie. Bei diesen kann der Batteriestatus übersichtlich dargestellt und / oder aktiv überwacht werden. Bei Geräten ohne eigenen Batteriestatus muss man diesen &amp;quot;nachrüsten&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Geräte mit Batteriestatus ==&lt;br /&gt;
=== Übersichtsdarstellung per readingsGroup ===&lt;br /&gt;
Mit Hilfe einer ReadingsGroup kann einfach eine Übersicht aller Geräte mit &amp;quot;battery&amp;quot;-Reading erstellt werden, s. [[ReadingsGroup#Auswahl_.C3.BCber_Reading-Namen.2C_Status_als_Symbol_dargestellt|hier]].&lt;br /&gt;
&lt;br /&gt;
=== Benachrichtigung per notify ===&lt;br /&gt;
Um Ausfälle frühzeitig zu erkennen, kann man sich per E-Mail benachrichtigen lassen, sobald eine Batteriemeldung mit etwas anderem als &amp;quot;ok&amp;quot; gesendet wird (z.B. &amp;quot;low&amp;quot;). Zusätzlich erzeugt der unten stehende Code einen Eintrag im Logfile.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define n_batt_chk notify .*:[Bb]attery.* { if ($EVENT !~ m/ok/) { \&lt;br /&gt;
  { FB_mail(&#039;recipient@internet.de&#039;, &#039;FHEM Batteriewarnung&#039;, $NAME.&#039;: &#039;.$EVENT)};; \&lt;br /&gt;
   Log 3, &amp;quot;$NAME : Batteriewarnung $EVENT&amp;quot;;; \&lt;br /&gt;
  } \&lt;br /&gt;
 }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039; Für Nutzer eines [[HM-CC-RT-DN_Funk-Heizk%C3%B6rperthermostat|HM-CC-RT-DN]] muss der Code anders aussehen, da mit diesem Thermostat erstmalig der aktuelle Spannungswert der Batterie gesendet wird, also z.B.:&lt;br /&gt;
&lt;br /&gt;
 UG.Treppe.Heizung batteryLevel: 3.1 V&lt;br /&gt;
&lt;br /&gt;
Man würde bei der Verwendung des o.g. Codes bei jeder Batteriemeldung eines HM-CC-RT-DN eine E-Mail erhalten. Daher muss der o.g. Code wie folgt geändert werden (Doppelpunkt hinter &amp;quot;[Bb]attery&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define n_batt_chk notify .*:[Bb]attery:.* { if($EVENT !~ m/ok/) { \&lt;br /&gt;
  { FB_mail(&#039;recipient@internet.de&#039;, &#039;FHEM Batteriewarnung&#039;, $NAME.&#039;: &#039;.$EVENT)};; \&lt;br /&gt;
   Log 3, &amp;quot;$NAME: Batteriewarnung $EVENT&amp;quot;;; \&lt;br /&gt;
  } \&lt;br /&gt;
 }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Achtung: FB_mail setzt die Installation auf einer FritzBox voraus. Für andere Hardware-/OS-Plattformen ist die Vorgehensweise unter dem Titel [[E-Mail_senden]] beschrieben.&lt;br /&gt;
&lt;br /&gt;
Wer statt einer email lieber eine Pushover-Nachricht auf sein Smartphone bekommen möchte, kann diesen Code benutzen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define n_batt_chk notify .*:[Bb]attery:.* { if($EVENT !~ m/ok/) { \                                                                                                                                        &lt;br /&gt;
  { fhem (&amp;quot;set PushoverChristoph msg FHEM Batteriewarnung, $NAME: $EVENT:\nBatterien sollten demnächst gewechselt werden!&amp;quot;);; \                                                                            &lt;br /&gt;
   Log 3, &amp;quot;$NAME: Batteriewarnung $EVENT&amp;quot;;; \                                                                                                                                                              &lt;br /&gt;
   } \&lt;br /&gt;
  } \&lt;br /&gt;
 }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich muß dafür eine Pushover-Installation in fhem vorhanden sein - sonst bitte gem. [[Pushover]] nachholen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Testen kann man dies z.B. mit &amp;lt;code&amp;gt;trigger HeizungWZ Battery:low&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man sollte auch darauf achten, dass sich das Ereignis, auf das man triggert, nicht zu häufig wiederholt (z.B. durch das Attribut &amp;lt;code&amp;gt;event-on-change-reading&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Geräte ohne Batteriestatus ==&lt;br /&gt;
Bei Geräten ohne Reading für den Batteriestatus kann man diesen auf verschiedene Weisen schätzen und als Reading eintragen. Dies funktioniert aber natürlich nur, wenn das Gerät sendet - bei einem rein empfangenden Aktor wie dem [[FHT 8v direkt ansprechen|FHT Stellantrieb]] klappt es also nicht... &lt;br /&gt;
&lt;br /&gt;
=== Erweiterung des Geräts um battery-Reading ===&lt;br /&gt;
Mit Hilfe von [http://fhem.de/commandref_DE.html#userReadings userReadings] kann man recht einfach einen Batteriestatus schätzen und als Reading bereitstellen. Dann greift auch direkt die oben beschriebene Auswertung.&lt;br /&gt;
&lt;br /&gt;
Die Idee ist, den zeitlichen Abstand des aktuellen Timestamps mit dem letzten geloggten Timestamp zu vergleichen und daraus auf den Batteriestatus zu schliessen - bspw. Abstand &amp;gt; 10min = Batterie low.&lt;br /&gt;
&lt;br /&gt;
Dazu muss lediglich folgendes userReading für jedes batteriebetriebene Device (ohne Batteriestatus) angelegt werden (um bei &amp;gt;10min &amp;quot;low&amp;quot; zu setzen): &lt;br /&gt;
&lt;br /&gt;
; Konfiguration:&lt;br /&gt;
Lediglich der Schwellwert (600) braucht nach Wunsch angepasst zu werden, alles andere passt automatisch (vgl. [[Notify#Hinweise]]).&lt;br /&gt;
&lt;br /&gt;
; Im Webinterface:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
battery { return &amp;quot;ok&amp;quot; if ( (time_str2num(ReadingsTimestamp($NAME,&amp;quot;state&amp;quot;,&amp;quot;0&amp;quot;)) - time_str2num(OldTimestamp($NAME))) &amp;lt; 600 ); return &amp;quot;low&amp;quot; }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Alternativ im Config-File:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr MeinSensor userReadings battery { return &amp;quot;ok&amp;quot; if ( (time_str2num(ReadingsTimestamp($NAME,&amp;quot;state&amp;quot;,&amp;quot;0&amp;quot;)) - time_str2num(OldTimestamp($NAME))) &amp;lt; 600 ); return &amp;quot;low&amp;quot; }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Erläuterung:&lt;br /&gt;
: &amp;lt;code&amp;gt;$NAME&amp;lt;/code&amp;gt; - ist die Variable für das Device (und braucht nicht angepasst zu werden)&lt;br /&gt;
: &amp;lt;code&amp;gt;battery {...}&amp;lt;/code&amp;gt; - Name des userreadings mit Spezifikation, vgl. [http://fhem.de/commandref_DE.html#userReadings]&lt;br /&gt;
: &amp;lt;code&amp;gt;return &amp;quot;ok&amp;quot; if ( ... ); return &amp;quot;low&amp;quot;&amp;lt;/code&amp;gt; - Spezifikation: Reading = &amp;quot;ok&amp;quot;, wenn if erfüllt, sonst &amp;quot;low&amp;quot;&lt;br /&gt;
: &amp;lt;code&amp;gt;time_str2num(ReadingsTimestamp($NAME,&amp;quot;state&amp;quot;,&amp;quot;0&amp;quot;)&amp;lt;/code&amp;gt; - Aktueller Timestamp in Sekunden, vgl. [http://fhem.de/commandref_DE.html#perl], [[Notify#Hinweise]]&lt;br /&gt;
: &amp;lt;code&amp;gt;time_str2num(OldTimestamp($NAME))&amp;lt;/code&amp;gt; - Letzter Timestamp im Log in Sekunden (egal ob FileLog oder DbLog), vgl. [http://fhem.de/commandref_DE.html#perl], [[Notify#Hinweise]]&lt;br /&gt;
: &amp;lt;code&amp;gt;600&amp;lt;/code&amp;gt; - Schwellwert für &amp;quot;low&amp;quot; (600 sec = 10 min), nach Bedarf anpassen&lt;br /&gt;
&lt;br /&gt;
=== Alternativ per Skript ===&lt;br /&gt;
Andere Komponenten, wie z. B. [[:Kategorie:FS20 Components|FS20 Komponenten]], übermitteln keinen Batteriestatus. &lt;br /&gt;
&lt;br /&gt;
Um dort dennoch einen Test darauf zu machen, ob die Batterie evtl. leer ist, kann man z. B. prüfen, wann der letzte Status des jeweiligen Gerätes empfangen wurde, etwa mit folgender Funktion in [[99_myUtils_anlegen|99_myUtils.pm]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sub check_if_alive($$) {&lt;br /&gt;
  # Expects:&lt;br /&gt;
  # 1. Devicename to be checked&lt;br /&gt;
  # 2. Age in hours, after the expiry of which with no new state the device will be considered as dead.&lt;br /&gt;
  # Returns:&lt;br /&gt;
  # 0 -&amp;gt; Device dead&lt;br /&gt;
  # 1 -&amp;gt; Device alive&lt;br /&gt;
  # 2 -&amp;gt; Error&lt;br /&gt;
  my ($Device,$hours_threshold) = @_;&lt;br /&gt;
  my ($Device) = @_;&lt;br /&gt;
  my $now = time;&lt;br /&gt;
  my $Timestamp = ReadingsTimestamp($Device,&amp;quot;state&amp;quot;,&amp;quot;0&amp;quot;);&lt;br /&gt;
  if ($Timestamp eq &amp;quot;0&amp;quot;) {&lt;br /&gt;
    return 2;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my @splitdatetime = split(/ /,$Timestamp);&lt;br /&gt;
  my @splitdate = split(/-/, $splitdatetime[0]);&lt;br /&gt;
  my @splittime = split(/:/, $splitdatetime[1]);&lt;br /&gt;
  my $last_state_time =  timelocal($splittime[2], $splittime[1], $splittime[0], $splitdate[2], $splitdate[1]-1, $splitdate[0]);&lt;br /&gt;
  my $age_in_hours = ($now - $last_state_time) / 3600;&lt;br /&gt;
&lt;br /&gt;
  if ($age_in_hours &amp;gt; $hours_threshold) {&lt;br /&gt;
    Log 1, (&amp;quot;check_if_alive: $Device dead, last state was $age_in_hours hours ago&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  } else {&lt;br /&gt;
    return 1;&lt;br /&gt;
  }&lt;br /&gt;
   &lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktion kann man z.B. in einem at je zu prüfendem Gerät regelmäßig (z. B. einmal am Tag um 05:55 Uhr) aufrufen, und testen, ob die letzten 12 Stunden etwas empfangen wurde:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;*05:55:55 { &lt;br /&gt;
  check_if_alive(&amp;quot;KS300&amp;quot;, 12);&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
KS300 ist dabei der Name des Devices in fhem. &lt;br /&gt;
&lt;br /&gt;
Wenn das Gerät nicht geantwortet hat, erzeugt die oben vorgeschlagene Funktion einen Logeintrag.&lt;br /&gt;
&lt;br /&gt;
Hinweis: Dieser Batterietest schlägt natürlich auch an, wenn die FS20 Geräte noch funktionieren, aber der CUL zum Empfangen der Signale nicht mehr funktioniert. In dem Fall sind dann auf einen Schlag angeblich alle Batterien leer. Um dies zumindest teilweise abzufangen, könnte man vor dem Erzeugen des Logeintrags noch auf den state des CUL testen, dass dieser nicht &amp;quot;disconnected&amp;quot; ist.&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung ====&lt;br /&gt;
Der Abschnitt Links unten enthält einen Verweis, wie man den Batteriestatus visuell anzeigen kann. Das funktioniert mit der oben vorgeschlagenen Funktion mit einigen Ergänzungen auch, wenn das Gerät selbst keinen Batteriestatus anzeigt.&lt;br /&gt;
&lt;br /&gt;
Dafür braucht man einen zusätzlichen Dummy je zu überwachendem Gerät, mit dem Namen dum_&amp;lt;zu_überwachendes_Gerät&amp;gt;_dead. Für das Gerät KS300 heißt dieser dummy also z. B. dum_KS300_dead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Internals: &lt;br /&gt;
   NAME       dum_KS300_dead &lt;br /&gt;
   NR         795 &lt;br /&gt;
   STATE      nein &lt;br /&gt;
   TYPE       dummy &lt;br /&gt;
   Readings: &lt;br /&gt;
     2015-04-28 07:47:48   state           nein &lt;br /&gt;
Attributes: &lt;br /&gt;
   devStateIcon ja:measure_battery_50@red nein:measure_battery_100@green&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser dummy soll hier die Zustände &amp;quot;ja&amp;quot; und &amp;quot;nein&amp;quot; annehmen können. Bei ja ist ihm über devStateIcon ein rotes Icon einer eher leeren Batterie zugewiesen, bei nein ein grünes Icon einer vollen Batterie. &lt;br /&gt;
&lt;br /&gt;
Nun muss noch die oben vorgeschlagene Funktion angepasst werden, um den Zustand des dummy entsprechend dem ermittelten Batteriestatus neu zu setzen. Dafür wird die Abfrage des Alters am Ende der Funktion um eine Zeile erweitert, die den Status des dummy setzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  if ($age_in_hours &amp;gt; $hours_threshold) {&lt;br /&gt;
    Log 1, (&amp;quot;check_if_alive: $Device dead, last state was $age_in_hours hours ago&amp;quot;);&lt;br /&gt;
    fhem(&amp;quot;set dum_&amp;quot;.$Device.&amp;quot;_dead ja&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  } else {&lt;br /&gt;
    fhem(&amp;quot;set dum_&amp;quot;.$Device.&amp;quot;_dead nein&amp;quot;);&lt;br /&gt;
    return 1;&lt;br /&gt;
  }&amp;lt;/pre&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
Den Dummy mit diesem devStateIcon kann man so der unter &amp;quot;Links&amp;quot; unten vorgeschlagenen readingsGroup hinzufügen, und damit auch Geräte ohne eigenen Batteriestatus überwachen.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[ReadingsGroup#Auswahl_.C3.BCber_Reading-Namen.2C_Status_als_Symbol_dargestellt|visuelle Batterieüberwachung mit readingsGroup]]&lt;br /&gt;
* [http://fhem.de/commandref_DE.html#userReadings commandref - userReadings]&lt;br /&gt;
* [http://fhem.de/commandref_DE.html#perl commandref - Perl specials]&lt;br /&gt;
* [[Notify#Hinweise|Hinweise zu Variablen]] (ansonsten auch an div. Stellen in der [http://fhem.de/commandref_DE.html commandref])&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-ES-TX-WM_Z%C3%A4hlersensor_f%C3%BCr_Strom-_und_Gasz%C3%A4hler&amp;diff=14233</id>
		<title>HM-ES-TX-WM Zählersensor für Strom- und Gaszähler</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-ES-TX-WM_Z%C3%A4hlersensor_f%C3%BCr_Strom-_und_Gasz%C3%A4hler&amp;diff=14233"/>
		<updated>2016-02-17T15:03:24Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: Bsp. für usereadings GAS etwas verallgemeinert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Hardware&lt;br /&gt;
|Bild=HM-EM-TX-WM.jpg&lt;br /&gt;
|Bildbeschreibung=HomeMatic Zählersensor&lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=Powersensor&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868&amp;amp;nbsp;MHz&lt;br /&gt;
|HWChannels=1&lt;br /&gt;
|HWVoltage=6 V&lt;br /&gt;
|HWPowerConsumption=30 mA&lt;br /&gt;
|HWPoweredBy=4 Batterien LR6/AA/Mignon&lt;br /&gt;
|HWSize=68x105x30mm&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#CUL_HM CUL_HM]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dieses Device ist seit Anfang Feb. 2015 als Bausatz auf dem Markt - dieser Artikel ist im Aufbau - bitte Verständnis für Unvollständigkeiten und fehlende Bereiche &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Der Zählersensor ist ein Datenerfassungssystem, das den Energieverbräuche (Strom, Gas) direkt am Zähler erfasst und in FHEM als laufender Saldo und als Momentanwerte verfügbar macht.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gewicht: 195 g (inkl. 4 LR6/Mignon/AA-Batterien)&lt;br /&gt;
&lt;br /&gt;
== Anwendungsszenarien ==&lt;br /&gt;
Mit den erfassten und gesammelten Daten lassen sich Aktionen beim Erreichen bestimmter Schwellwerte auslösen, Verbrauchs- und Kostenstatistiken ableiten sowie beliebige weitere Abhängigkeiten bilden. Durch die Funkdatenübertragung sowie den Batteriebetrieb (1 bis 2 Jahre Betriebsdauer verspricht der Hersteller mit einem Satz) ist die Installation denkbar einfach und erfordert lediglich beim Anbringen der Leseeinheit Genauigkeit.&lt;br /&gt;
&lt;br /&gt;
Aktuell (Feb. 2015) hat die Auslieferung der Geräte als (einfacher) Bausatz begonnen, zu dem es einen Ferraris-Sensor (für Stromzähler mit den markanten Laufscheiben), LED-Sensor (für neue Zähler mit S0-Schnittstelle) sowie BK-G4-Gaszähler von Elster-Kromschröder, die an einer Ziffernrolle einen kleinen Magneten haben, der über einen Sensor mit Reedkontakt erfasst wird. Es ist laut Hersteller [http://www.elv.de/homematic-zaehlersensor-strom-gas-bausatz.html ELV] nur der Bausatz verfügbar. Ein Fertiggerät ist aktuell nicht geplant.&lt;br /&gt;
&lt;br /&gt;
Die Zähler werden mit rückstandslos entfernbaren Klebepads angebracht.&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
 &#039;&#039;&#039;list:        register | range              | peer     | description&#039;&#039;&#039; &lt;br /&gt;
   0: pairCentral      |   0 to 16777215    |          | pairing to central &lt;br /&gt;
   1: mtrConstGas      |   0 to 655.36      |          | constant gas &lt;br /&gt;
   1: mtrConstIr       |   0 to 65536       |          | constant IR &lt;br /&gt;
   1: mtrConstLed      |   0 to 65536       |          | constant led &lt;br /&gt;
   1: mtrSensIr        | -99 to 99          |          | sensiblity IR &lt;br /&gt;
   1: mtrType          |     literal        |          | type of measurement options:LED,gas,unknown,IR &lt;br /&gt;
&lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
Der HM-ES-TX-WM sendet zyklisch im 3-Minuten Takt die aktuellsten Verbrauchsdaten. Dabei ist für das Reading &amp;quot;power&amp;quot; (aktuelle Stromleistung in Watt) zu beachten, dass aller 3 Minuten nur der zuletzt bekannte Wert gesendet. Das heisst im besonderen:&lt;br /&gt;
&lt;br /&gt;
* sollten innerhalb der 3 Minuten mehrfache Impulse auftreten mit unterschiedlichen Leistungswerten, wird nur der zuletzt bekannte Wert genommen. Es findet keine Aggregation aller Impulse wie z.B. Mittelwert o.ä. statt.&lt;br /&gt;
* sollten innerhalb der 3 Minuten keinerlei Impulse auftreten, wird dennoch der zuletzt bekannte Leistungswert gesendet, auch wenn er mehrere Minuten/Stunden/Tage alt ist.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
Der Sensor wird mit einem FHEM im Update-Stand vom (mindestens) 7.2.2015 funktionsfähig eingebunden (getestet in der Variante mit Feraris-Fühler). Es werden der Fühlertyp und die Fühlerkonstante richtig ausgelesen und im Reading Energy die errechnete Energiemenge ausgegeben (bei Strom: Wattstunden, Wh).&lt;br /&gt;
&lt;br /&gt;
Für die perfekte Konfiguration wird auf [[Heizleistung_und_Gasverbrauch]] verwiesen, wo eine vollständige Lösung für die Umrechnung von Gasverbrauch in kW/h, Graphen und Hilfsprogramme vorgestellt wird.&lt;br /&gt;
&lt;br /&gt;
=== Readings ===&lt;br /&gt;
 &#039;&#039;&#039;Reading:       |Beispiel&#039;&#039;&#039;   &lt;br /&gt;
 D-firmware     |1.0&lt;br /&gt;
 D-serialNr     |MEQ0025452 &lt;br /&gt;
 battery        |ok&lt;br /&gt;
 boot           |off &lt;br /&gt;
 current        |0 &lt;br /&gt;
 eState         |E: 6199.9 P: 1713 I: 0 U: 0 f: 50 &lt;br /&gt;
 energy         |6199.9 &lt;br /&gt;
 energyOffset   |84413.2&lt;br /&gt;
 frequency      |50 &lt;br /&gt;
 power          |1713 &lt;br /&gt;
 powerOn        |2015-03-26 14:57:48&lt;br /&gt;
 voltage        |0&lt;br /&gt;
&lt;br /&gt;
=== Events Auszug ===&lt;br /&gt;
 &#039;&#039;&#039;Event     |Beispielswert&#039;&#039;&#039;&lt;br /&gt;
 battery*  |ok&lt;br /&gt;
 energy    |10186.6&lt;br /&gt;
 power     |283&lt;br /&gt;
 current   |0&lt;br /&gt;
 voltage   |0&lt;br /&gt;
 frequency |50&lt;br /&gt;
 eState    |E: 10186.6 P: 283 I: 0 U: 0 f: 50&lt;br /&gt;
 boot      |off&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;*&amp;lt;/nowiki&amp;gt;  -  Ein battery-Event wird nicht zyklisch getriggert. Erst wenn die Batterie tatsächlich leer ist, wird eine entsprechende Meldung vom Gerät selber gesendet und ein battery-Event getriggert (battery: low).&lt;br /&gt;
&lt;br /&gt;
Mit einem Userreading lässt sich die Angabe aus Energy zum Beispiel für einen Stromzähler (Wh) in die auf dem Zähler übliche Angabe kWh umrechnen und zugleich mit dem Aufaddieren des Unterschieds beim Start (das Zählermodul beginnt ja mit 0 Wh, während der Zähler meist schon einige Jahre auf der &amp;quot;Rolle&amp;quot; hat) die Angaben gleichziehen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;DeviceName&amp;gt; userReadings kWh {sprintf(&amp;quot;%.1f&amp;quot;,ReadingsVal(&amp;quot;&amp;lt;DeviceName&amp;gt;&amp;quot;,&amp;quot;energy&amp;quot;,&amp;quot;???&amp;quot;)/1000+72031.5639)}&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
Nach dem Erkennen durch [[autocreate]] wird der Zählersensor mit diesen Angaben eingebunden:&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_TX_WM_353594 CUL_HM 353594&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 IODev CUL_0&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 actCycle 000:10&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 actStatus alive&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 expert 2_full&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 firmware 1.0&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 model HM-ES-TX-WM&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 subType powerSensor&lt;br /&gt;
&lt;br /&gt;
Für den Betrieb mit den verschiedenen Zählern muß eines der Readings &#039;&#039;&#039;R-mtrConst&#039;&#039;&#039;XXX auf den jeweiligen verwendeten Zähler konfiguriert werden. Z.B. kann ein Ferraris-Stromzähler 100, 150 oder 200 Umdrehungen je kWh benötigen. Dies geschieht z.B. für 150 Meldungen je Einheit für einen Ferraris-Zähler mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 set CUL_HM_HM_ES_TX_WM_353594 regSet mtrConstIr 150&lt;br /&gt;
&lt;br /&gt;
oder für einen Gaszähler auf der 1. Rolle (d.h. 1 Impuls je 0.1 m^3)&lt;br /&gt;
&lt;br /&gt;
 set CUL_HM_HM_ES_TX_WM_353594 regSet mtrConstGas 0.1&lt;br /&gt;
&lt;br /&gt;
In fhem bis zum Anfang November 2015 war hier ein kleiner Bug enthalten, der diesen Wert nicht akzeptierte. In diesem Fall läßt sich die Anzahl der Impulse direkt am Gerät über das Display einstellen.&lt;br /&gt;
&lt;br /&gt;
== Logging/Graph. Darstellung ==&lt;br /&gt;
[[Datei:PlotStromverbrauchProStunde.png|mini|400px|rechts|Beispiel der graph. Darstellung]]&lt;br /&gt;
Der Zähler wird ja fortlaufend aufaddiert. Mit der delta-Funktion von SVG-Plot können die Verbräuche sehr gut visualisiert werden. &lt;br /&gt;
Beispiel Stromzähler:&lt;br /&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;Stündlicher Stromverbrauch | aktuell: $data{currval1} ($data{min1} / $data{avg1} / $data{max1}) kWh&#039;&lt;br /&gt;
 set ytics &lt;br /&gt;
 set y2tics &lt;br /&gt;
 set grid ytics&lt;br /&gt;
 set ylabel &amp;quot;kWh/h&amp;quot;&lt;br /&gt;
 set y2label &amp;quot;kWh/h&amp;quot;&lt;br /&gt;
 #FileLog 4:CUL_HM_HM_ES_TX_WM_353594.kWh\x3a:0:delta-h&lt;br /&gt;
 plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Line 1&#039; ls l0 lw 2 with bars&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Handbuch: [http://files.elv.de/Assets/Produkte/14/1401/140143/Downloads/140143_sensor_um.pdf]&lt;br /&gt;
* Produktseite ELV: [http://www.elv.de/homematic-zaehlersensor-strom-gas-bausatz.html] &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-ES-TX-WM_Z%C3%A4hlersensor_f%C3%BCr_Strom-_und_Gasz%C3%A4hler&amp;diff=14232</id>
		<title>HM-ES-TX-WM Zählersensor für Strom- und Gaszähler</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-ES-TX-WM_Z%C3%A4hlersensor_f%C3%BCr_Strom-_und_Gasz%C3%A4hler&amp;diff=14232"/>
		<updated>2016-02-17T14:59:53Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Hardware&lt;br /&gt;
|Bild=HM-EM-TX-WM.jpg&lt;br /&gt;
|Bildbeschreibung=HomeMatic Zählersensor&lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=Powersensor&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868&amp;amp;nbsp;MHz&lt;br /&gt;
|HWChannels=1&lt;br /&gt;
|HWVoltage=6 V&lt;br /&gt;
|HWPowerConsumption=30 mA&lt;br /&gt;
|HWPoweredBy=4 Batterien LR6/AA/Mignon&lt;br /&gt;
|HWSize=68x105x30mm&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#CUL_HM CUL_HM]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dieses Device ist seit Anfang Feb. 2015 als Bausatz auf dem Markt - dieser Artikel ist im Aufbau - bitte Verständnis für Unvollständigkeiten und fehlende Bereiche &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Der Zählersensor ist ein Datenerfassungssystem, das den Energieverbräuche (Strom, Gas) direkt am Zähler erfasst und in FHEM als laufender Saldo und als Momentanwerte verfügbar macht.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gewicht: 195 g (inkl. 4 LR6/Mignon/AA-Batterien)&lt;br /&gt;
&lt;br /&gt;
== Anwendungsszenarien ==&lt;br /&gt;
Mit den erfassten und gesammelten Daten lassen sich Aktionen beim Erreichen bestimmter Schwellwerte auslösen, Verbrauchs- und Kostenstatistiken ableiten sowie beliebige weitere Abhängigkeiten bilden. Durch die Funkdatenübertragung sowie den Batteriebetrieb (1 bis 2 Jahre Betriebsdauer verspricht der Hersteller mit einem Satz) ist die Installation denkbar einfach und erfordert lediglich beim Anbringen der Leseeinheit Genauigkeit.&lt;br /&gt;
&lt;br /&gt;
Aktuell (Feb. 2015) hat die Auslieferung der Geräte als (einfacher) Bausatz begonnen, zu dem es einen Ferraris-Sensor (für Stromzähler mit den markanten Laufscheiben), LED-Sensor (für neue Zähler mit S0-Schnittstelle) sowie BK-G4-Gaszähler von Elster-Kromschröder, die an einer Ziffernrolle einen kleinen Magneten haben, der über einen Sensor mit Reedkontakt erfasst wird. Es ist laut Hersteller [http://www.elv.de/homematic-zaehlersensor-strom-gas-bausatz.html ELV] nur der Bausatz verfügbar. Ein Fertiggerät ist aktuell nicht geplant.&lt;br /&gt;
&lt;br /&gt;
Die Zähler werden mit rückstandslos entfernbaren Klebepads angebracht.&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
 &#039;&#039;&#039;list:        register | range              | peer     | description&#039;&#039;&#039; &lt;br /&gt;
   0: pairCentral      |   0 to 16777215    |          | pairing to central &lt;br /&gt;
   1: mtrConstGas      |   0 to 655.36      |          | constant gas &lt;br /&gt;
   1: mtrConstIr       |   0 to 65536       |          | constant IR &lt;br /&gt;
   1: mtrConstLed      |   0 to 65536       |          | constant led &lt;br /&gt;
   1: mtrSensIr        | -99 to 99          |          | sensiblity IR &lt;br /&gt;
   1: mtrType          |     literal        |          | type of measurement options:LED,gas,unknown,IR &lt;br /&gt;
&lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
Der HM-ES-TX-WM sendet zyklisch im 3-Minuten Takt die aktuellsten Verbrauchsdaten. Dabei ist für das Reading &amp;quot;power&amp;quot; (aktuelle Stromleistung in Watt) zu beachten, dass aller 3 Minuten nur der zuletzt bekannte Wert gesendet. Das heisst im besonderen:&lt;br /&gt;
&lt;br /&gt;
* sollten innerhalb der 3 Minuten mehrfache Impulse auftreten mit unterschiedlichen Leistungswerten, wird nur der zuletzt bekannte Wert genommen. Es findet keine Aggregation aller Impulse wie z.B. Mittelwert o.ä. statt.&lt;br /&gt;
* sollten innerhalb der 3 Minuten keinerlei Impulse auftreten, wird dennoch der zuletzt bekannte Leistungswert gesendet, auch wenn er mehrere Minuten/Stunden/Tage alt ist.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
Der Sensor wird mit einem FHEM im Update-Stand vom (mindestens) 7.2.2015 funktionsfähig eingebunden (getestet in der Variante mit Feraris-Fühler). Es werden der Fühlertyp und die Fühlerkonstante richtig ausgelesen und im Reading Energy die errechnete Energiemenge ausgegeben (bei Strom: Wattstunden, Wh).&lt;br /&gt;
&lt;br /&gt;
Für die perfekte Konfiguration wird auf [[Heizleistung_und_Gasverbrauch]] verwiesen, wo eine vollständige Lösung für die Umrechnung von Gasverbrauch in kW/h, Graphen und Hilfsprogramme vorgestellt wird.&lt;br /&gt;
&lt;br /&gt;
=== Readings ===&lt;br /&gt;
 &#039;&#039;&#039;Reading:       |Beispiel&#039;&#039;&#039;   &lt;br /&gt;
 D-firmware     |1.0&lt;br /&gt;
 D-serialNr     |MEQ0025452 &lt;br /&gt;
 battery        |ok&lt;br /&gt;
 boot           |off &lt;br /&gt;
 current        |0 &lt;br /&gt;
 eState         |E: 6199.9 P: 1713 I: 0 U: 0 f: 50 &lt;br /&gt;
 energy         |6199.9 &lt;br /&gt;
 energyOffset   |84413.2&lt;br /&gt;
 frequency      |50 &lt;br /&gt;
 power          |1713 &lt;br /&gt;
 powerOn        |2015-03-26 14:57:48&lt;br /&gt;
 voltage        |0&lt;br /&gt;
&lt;br /&gt;
=== Events Auszug ===&lt;br /&gt;
 &#039;&#039;&#039;Event     |Beispielswert&#039;&#039;&#039;&lt;br /&gt;
 battery*  |ok&lt;br /&gt;
 energy    |10186.6&lt;br /&gt;
 power     |283&lt;br /&gt;
 current   |0&lt;br /&gt;
 voltage   |0&lt;br /&gt;
 frequency |50&lt;br /&gt;
 eState    |E: 10186.6 P: 283 I: 0 U: 0 f: 50&lt;br /&gt;
 boot      |off&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;*&amp;lt;/nowiki&amp;gt;  -  Ein battery-Event wird nicht zyklisch getriggert. Erst wenn die Batterie tatsächlich leer ist, wird eine entsprechende Meldung vom Gerät selber gesendet und ein battery-Event getriggert (battery: low).&lt;br /&gt;
&lt;br /&gt;
Mit einem Userreading lässt sich die Angabe aus Energy zum Beispiel für einen Stromzähler (Wh) in die auf dem Zähler übliche Angabe kWh umrechnen und zugleich mit dem Aufaddieren des Unterschieds beim Start (das Zählermodul beginnt ja mit 0 Wh, während der Zähler meist schon einige Jahre auf der &amp;quot;Rolle&amp;quot; hat) die Angaben gleichziehen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;DeviceName&amp;gt; userReadings kWh {sprintf(&amp;quot;%.1f&amp;quot;,ReadingsVal(&amp;quot;CUL_HM_HM_ES_TX_WM_353594&amp;quot;,&amp;quot;energy&amp;quot;,&amp;quot;???&amp;quot;)/1000+72031.5639)}&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
Nach dem Erkennen durch [[autocreate]] wird der Zählersensor mit diesen Angaben eingebunden:&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_TX_WM_353594 CUL_HM 353594&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 IODev CUL_0&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 actCycle 000:10&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 actStatus alive&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 expert 2_full&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 firmware 1.0&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 model HM-ES-TX-WM&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 subType powerSensor&lt;br /&gt;
&lt;br /&gt;
Für den Betrieb mit den verschiedenen Zählern muß eines der Readings &#039;&#039;&#039;R-mtrConst&#039;&#039;&#039;XXX auf den jeweiligen verwendeten Zähler konfiguriert werden. Z.B. kann ein Ferraris-Stromzähler 100, 150 oder 200 Umdrehungen je kWh benötigen. Dies geschieht z.B. für 150 Meldungen je Einheit für einen Ferraris-Zähler mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 set CUL_HM_HM_ES_TX_WM_353594 regSet mtrConstIr 150&lt;br /&gt;
&lt;br /&gt;
oder für einen Gaszähler auf der 1. Rolle (d.h. 1 Impuls je 0.1 m^3)&lt;br /&gt;
&lt;br /&gt;
 set CUL_HM_HM_ES_TX_WM_353594 regSet mtrConstGas 0.1&lt;br /&gt;
&lt;br /&gt;
In fhem bis zum Anfang November 2015 war hier ein kleiner Bug enthalten, der diesen Wert nicht akzeptierte. In diesem Fall läßt sich die Anzahl der Impulse direkt am Gerät über das Display einstellen.&lt;br /&gt;
&lt;br /&gt;
== Logging/Graph. Darstellung ==&lt;br /&gt;
[[Datei:PlotStromverbrauchProStunde.png|mini|400px|rechts|Beispiel der graph. Darstellung]]&lt;br /&gt;
Der Zähler wird ja fortlaufend aufaddiert. Mit der delta-Funktion von SVG-Plot können die Verbräuche sehr gut visualisiert werden. &lt;br /&gt;
Beispiel Stromzähler:&lt;br /&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;Stündlicher Stromverbrauch | aktuell: $data{currval1} ($data{min1} / $data{avg1} / $data{max1}) kWh&#039;&lt;br /&gt;
 set ytics &lt;br /&gt;
 set y2tics &lt;br /&gt;
 set grid ytics&lt;br /&gt;
 set ylabel &amp;quot;kWh/h&amp;quot;&lt;br /&gt;
 set y2label &amp;quot;kWh/h&amp;quot;&lt;br /&gt;
 #FileLog 4:CUL_HM_HM_ES_TX_WM_353594.kWh\x3a:0:delta-h&lt;br /&gt;
 plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Line 1&#039; ls l0 lw 2 with bars&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Handbuch: [http://files.elv.de/Assets/Produkte/14/1401/140143/Downloads/140143_sensor_um.pdf]&lt;br /&gt;
* Produktseite ELV: [http://www.elv.de/homematic-zaehlersensor-strom-gas-bausatz.html] &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Diskussion:HM-EM-TX-WM_Z%C3%A4hlersensor_f%C3%BCr_Strom-_und_Gasz%C3%A4hler&amp;diff=14231</id>
		<title>Diskussion:HM-EM-TX-WM Zählersensor für Strom- und Gaszähler</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Diskussion:HM-EM-TX-WM_Z%C3%A4hlersensor_f%C3%BCr_Strom-_und_Gasz%C3%A4hler&amp;diff=14231"/>
		<updated>2016-02-17T14:57:41Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: Caldir65 verschob die Seite Diskussion:HM-EM-TX-WM Zählersensor für Strom- und Gaszähler nach Diskussion:HM-ES-TX-WM Zählersensor für Strom- und Gaszähler: HM-Bezeichnung im Seiten-Namen korrigiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#WEITERLEITUNG [[Diskussion:HM-ES-TX-WM Zählersensor für Strom- und Gaszähler]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Diskussion:HM-ES-TX-WM_Z%C3%A4hlersensor_f%C3%BCr_Strom-_und_Gasz%C3%A4hler&amp;diff=14230</id>
		<title>Diskussion:HM-ES-TX-WM Zählersensor für Strom- und Gaszähler</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Diskussion:HM-ES-TX-WM_Z%C3%A4hlersensor_f%C3%BCr_Strom-_und_Gasz%C3%A4hler&amp;diff=14230"/>
		<updated>2016-02-17T14:57:41Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: Caldir65 verschob die Seite Diskussion:HM-EM-TX-WM Zählersensor für Strom- und Gaszähler nach Diskussion:HM-ES-TX-WM Zählersensor für Strom- und Gaszähler: HM-Bezeichnung im Seiten-Namen korrigiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Falscher Seitentitel? / Graphenerstellung ==&lt;br /&gt;
Sollte der Sensor nicht HM-ES-TX-WM heißen?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Frage: im Graphen wird der Titel auf&lt;br /&gt;
&lt;br /&gt;
  aktuell: $data{curval1} ($data{min1} / $data{avg1} / $data{max1}) kWh&lt;br /&gt;
&lt;br /&gt;
gesetzt. Welches Modul erzeugt wie diesen Titel? Mit dem Einbinden des Statistik-Moduls alleine scheint es ja nicht getan zu sein....?&lt;br /&gt;
--[[Benutzer:Morgennebel|Morgennebel]] ([[Benutzer Diskussion:Morgennebel|Diskussion]]) 14:19, 29. Sep. 2015 (CEST)&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
:Der Seitentitel=Sensorname ist auch mMn falsch (http://www.elv.de/HomeMatic%C2%AE-Energiez%C3%A4hler-Erfassungssystem/x.aspx/cid_726/detail_50043). Sie Seite müsste verschoben werden. (Peter?)&lt;br /&gt;
:&lt;br /&gt;
:Das sind &amp;quot;normale&amp;quot; get-Abfragen für FileLog ([[Creating_Plots#Data_Extraction]])&lt;br /&gt;
:Gruß, --[[Benutzer:Krikan|Christian]] ([[Benutzer Diskussion:Krikan|Diskussion]]) 14:53, 29. Sep. 2015 (CEST)&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-EM-TX-WM_Z%C3%A4hlersensor_f%C3%BCr_Strom-_und_Gasz%C3%A4hler&amp;diff=14229</id>
		<title>HM-EM-TX-WM Zählersensor für Strom- und Gaszähler</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-EM-TX-WM_Z%C3%A4hlersensor_f%C3%BCr_Strom-_und_Gasz%C3%A4hler&amp;diff=14229"/>
		<updated>2016-02-17T14:57:41Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: Caldir65 verschob die Seite HM-EM-TX-WM Zählersensor für Strom- und Gaszähler nach HM-ES-TX-WM Zählersensor für Strom- und Gaszähler: HM-Bezeichnung im Seiten-Namen korrigiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#WEITERLEITUNG [[HM-ES-TX-WM Zählersensor für Strom- und Gaszähler]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-ES-TX-WM_Z%C3%A4hlersensor_f%C3%BCr_Strom-_und_Gasz%C3%A4hler&amp;diff=14228</id>
		<title>HM-ES-TX-WM Zählersensor für Strom- und Gaszähler</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-ES-TX-WM_Z%C3%A4hlersensor_f%C3%BCr_Strom-_und_Gasz%C3%A4hler&amp;diff=14228"/>
		<updated>2016-02-17T14:57:41Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: Caldir65 verschob die Seite HM-EM-TX-WM Zählersensor für Strom- und Gaszähler nach HM-ES-TX-WM Zählersensor für Strom- und Gaszähler: HM-Bezeichnung im Seiten-Namen korrigiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Hardware&lt;br /&gt;
|Bild=HM-ES-TX-WM.jpg&lt;br /&gt;
|Bildbeschreibung=HomeMatic Zählersensor&lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=Powersensor&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868&amp;amp;nbsp;MHz&lt;br /&gt;
|HWChannels=1&lt;br /&gt;
|HWVoltage=6 V&lt;br /&gt;
|HWPowerConsumption=30 mA&lt;br /&gt;
|HWPoweredBy=4 Batterien LR6/AA/Mignon&lt;br /&gt;
|HWSize=68x105x30mm&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#CUL_HM CUL_HM]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dieses Device ist seit Anfang Feb. 2015 als Bausatz auf dem Markt - dieser Artikel ist im Aufbau - bitte Verständnis für Unvollständigkeiten und fehlende Bereiche &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Der Zählersensor ist ein Datenerfassungssystem, das den Energieverbräuche (Strom, Gas) direkt am Zähler erfasst und in FHEM als laufender Saldo und als Momentanwerte verfügbar macht.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gewicht: 195 g (inkl. 4 LR6/Mignon/AA-Batterien)&lt;br /&gt;
&lt;br /&gt;
== Anwendungsszenarien ==&lt;br /&gt;
Mit den erfassten und gesammelten Daten lassen sich Aktionen beim Erreichen bestimmter Schwellwerte auslösen, Verbrauchs- und Kostenstatistiken ableiten sowie beliebige weitere Abhängigkeiten bilden. Durch die Funkdatenübertragung sowie den Batteriebetrieb (1 bis 2 Jahre Betriebsdauer verspricht der Hersteller mit einem Satz) ist die Installation denkbar einfach und erfordert lediglich beim Anbringen der Leseeinheit Genauigkeit.&lt;br /&gt;
&lt;br /&gt;
Aktuell (Feb. 2015) hat die Auslieferung der Geräte als (einfacher) Bausatz begonnen, zu dem es einen Ferraris-Sensor (für Stromzähler mit den markanten Laufscheiben), LED-Sensor (für neue Zähler mit S0-Schnittstelle) sowie BK-G4-Gaszähler von Elster-Kromschröder, die an einer Ziffernrolle einen kleinen Magneten haben, der über einen Sensor mit Reedkontakt erfasst wird. Es ist laut Hersteller [http://www.elv.de/homematic-zaehlersensor-strom-gas-bausatz.html ELV] nur der Bausatz verfügbar. Ein Fertiggerät ist aktuell nicht geplant.&lt;br /&gt;
&lt;br /&gt;
Die Zähler werden mit rückstandslos entfernbaren Klebepads angebracht.&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
 &#039;&#039;&#039;list:        register | range              | peer     | description&#039;&#039;&#039; &lt;br /&gt;
   0: pairCentral      |   0 to 16777215    |          | pairing to central &lt;br /&gt;
   1: mtrConstGas      |   0 to 655.36      |          | constant gas &lt;br /&gt;
   1: mtrConstIr       |   0 to 65536       |          | constant IR &lt;br /&gt;
   1: mtrConstLed      |   0 to 65536       |          | constant led &lt;br /&gt;
   1: mtrSensIr        | -99 to 99          |          | sensiblity IR &lt;br /&gt;
   1: mtrType          |     literal        |          | type of measurement options:LED,gas,unknown,IR &lt;br /&gt;
&lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
Der HM-ES-TX-WM sendet zyklisch im 3-Minuten Takt die aktuellsten Verbrauchsdaten. Dabei ist für das Reading &amp;quot;power&amp;quot; (aktuelle Stromleistung in Watt) zu beachten, dass aller 3 Minuten nur der zuletzt bekannte Wert gesendet. Das heisst im besonderen:&lt;br /&gt;
&lt;br /&gt;
* sollten innerhalb der 3 Minuten mehrfache Impulse auftreten mit unterschiedlichen Leistungswerten, wird nur der zuletzt bekannte Wert genommen. Es findet keine Aggregation aller Impulse wie z.B. Mittelwert o.ä. statt.&lt;br /&gt;
* sollten innerhalb der 3 Minuten keinerlei Impulse auftreten, wird dennoch der zuletzt bekannte Leistungswert gesendet, auch wenn er mehrere Minuten/Stunden/Tage alt ist.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
Der Sensor wird mit einem FHEM im Update-Stand vom (mindestens) 7.2.2015 funktionsfähig eingebunden (getestet in der Variante mit Feraris-Fühler). Es werden der Fühlertyp und die Fühlerkonstante richtig ausgelesen und im Reading Energy die errechnete Energiemenge ausgegeben (bei Strom: Wattstunden, Wh).&lt;br /&gt;
&lt;br /&gt;
Für die perfekte Konfiguration wird auf [[Heizleistung_und_Gasverbrauch]] verwiesen, wo eine vollständige Lösung für die Umrechnung von Gasverbrauch in kW/h, Graphen und Hilfsprogramme vorgestellt wird.&lt;br /&gt;
&lt;br /&gt;
=== Readings ===&lt;br /&gt;
 &#039;&#039;&#039;Reading:       |Beispiel&#039;&#039;&#039;   &lt;br /&gt;
 D-firmware     |1.0&lt;br /&gt;
 D-serialNr     |MEQ0025452 &lt;br /&gt;
 battery        |ok&lt;br /&gt;
 boot           |off &lt;br /&gt;
 current        |0 &lt;br /&gt;
 eState         |E: 6199.9 P: 1713 I: 0 U: 0 f: 50 &lt;br /&gt;
 energy         |6199.9 &lt;br /&gt;
 energyOffset   |84413.2&lt;br /&gt;
 frequency      |50 &lt;br /&gt;
 power          |1713 &lt;br /&gt;
 powerOn        |2015-03-26 14:57:48&lt;br /&gt;
 voltage        |0&lt;br /&gt;
&lt;br /&gt;
=== Events Auszug ===&lt;br /&gt;
 &#039;&#039;&#039;Event     |Beispielswert&#039;&#039;&#039;&lt;br /&gt;
 battery*  |ok&lt;br /&gt;
 energy    |10186.6&lt;br /&gt;
 power     |283&lt;br /&gt;
 current   |0&lt;br /&gt;
 voltage   |0&lt;br /&gt;
 frequency |50&lt;br /&gt;
 eState    |E: 10186.6 P: 283 I: 0 U: 0 f: 50&lt;br /&gt;
 boot      |off&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;*&amp;lt;/nowiki&amp;gt;  -  Ein battery-Event wird nicht zyklisch getriggert. Erst wenn die Batterie tatsächlich leer ist, wird eine entsprechende Meldung vom Gerät selber gesendet und ein battery-Event getriggert (battery: low).&lt;br /&gt;
&lt;br /&gt;
Mit einem Userreading lässt sich die Angabe aus Energy zum Beispiel für einen Stromzähler (Wh) in die auf dem Zähler übliche Angabe kWh umrechnen und zugleich mit dem Aufaddieren des Unterschieds beim Start (das Zählermodul beginnt ja mit 0 Wh, während der Zähler meist schon einige Jahre auf der &amp;quot;Rolle&amp;quot; hat) die Angaben gleichziehen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;DeviceName&amp;gt; userReadings kWh {sprintf(&amp;quot;%.1f&amp;quot;,ReadingsVal(&amp;quot;CUL_HM_HM_ES_TX_WM_353594&amp;quot;,&amp;quot;energy&amp;quot;,&amp;quot;???&amp;quot;)/1000+72031.5639)}&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
Nach dem Erkennen durch [[autocreate]] wird der Zählersensor mit diesen Angaben eingebunden:&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_TX_WM_353594 CUL_HM 353594&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 IODev CUL_0&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 actCycle 000:10&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 actStatus alive&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 expert 2_full&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 firmware 1.0&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 model HM-ES-TX-WM&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 subType powerSensor&lt;br /&gt;
&lt;br /&gt;
Für den Betrieb mit den verschiedenen Zählern muß eines der Readings &#039;&#039;&#039;R-mtrConst&#039;&#039;&#039;XXX auf den jeweiligen verwendeten Zähler konfiguriert werden. Z.B. kann ein Ferraris-Stromzähler 100, 150 oder 200 Umdrehungen je kWh benötigen. Dies geschieht z.B. für 150 Meldungen je Einheit für einen Ferraris-Zähler mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 set CUL_HM_HM_ES_TX_WM_353594 regSet mtrConstIr 150&lt;br /&gt;
&lt;br /&gt;
oder für einen Gaszähler auf der 1. Rolle (d.h. 1 Impuls je 0.1 m^3)&lt;br /&gt;
&lt;br /&gt;
 set CUL_HM_HM_ES_TX_WM_353594 regSet mtrConstGas 0.1&lt;br /&gt;
&lt;br /&gt;
In fhem bis zum Anfang November 2015 war hier ein kleiner Bug enthalten, der diesen Wert nicht akzeptierte. In diesem Fall läßt sich die Anzahl der Impulse direkt am Gerät über das Display einstellen.&lt;br /&gt;
&lt;br /&gt;
== Logging/Graph. Darstellung ==&lt;br /&gt;
[[Datei:PlotStromverbrauchProStunde.png|mini|400px|rechts|Beispiel der graph. Darstellung]]&lt;br /&gt;
Der Zähler wird ja fortlaufend aufaddiert. Mit der delta-Funktion von SVG-Plot können die Verbräuche sehr gut visualisiert werden. &lt;br /&gt;
Beispiel Stromzähler:&lt;br /&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;Stündlicher Stromverbrauch | aktuell: $data{currval1} ($data{min1} / $data{avg1} / $data{max1}) kWh&#039;&lt;br /&gt;
 set ytics &lt;br /&gt;
 set y2tics &lt;br /&gt;
 set grid ytics&lt;br /&gt;
 set ylabel &amp;quot;kWh/h&amp;quot;&lt;br /&gt;
 set y2label &amp;quot;kWh/h&amp;quot;&lt;br /&gt;
 #FileLog 4:CUL_HM_HM_ES_TX_WM_353594.kWh\x3a:0:delta-h&lt;br /&gt;
 plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Line 1&#039; ls l0 lw 2 with bars&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Handbuch: [http://files.elv.de/Assets/Produkte/14/1401/140143/Downloads/140143_sensor_um.pdf]&lt;br /&gt;
* Produktseite ELV: [http://www.elv.de/homematic-zaehlersensor-strom-gas-bausatz.html] &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-ES-TX-WM_Z%C3%A4hlersensor_f%C3%BCr_Strom-_und_Gasz%C3%A4hler&amp;diff=14227</id>
		<title>HM-ES-TX-WM Zählersensor für Strom- und Gaszähler</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-ES-TX-WM_Z%C3%A4hlersensor_f%C3%BCr_Strom-_und_Gasz%C3%A4hler&amp;diff=14227"/>
		<updated>2016-02-17T14:56:46Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: Korrektur Type-Bezeichnung in der Infobox&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Hardware&lt;br /&gt;
|Bild=HM-ES-TX-WM.jpg&lt;br /&gt;
|Bildbeschreibung=HomeMatic Zählersensor&lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=Powersensor&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868&amp;amp;nbsp;MHz&lt;br /&gt;
|HWChannels=1&lt;br /&gt;
|HWVoltage=6 V&lt;br /&gt;
|HWPowerConsumption=30 mA&lt;br /&gt;
|HWPoweredBy=4 Batterien LR6/AA/Mignon&lt;br /&gt;
|HWSize=68x105x30mm&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#CUL_HM CUL_HM]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dieses Device ist seit Anfang Feb. 2015 als Bausatz auf dem Markt - dieser Artikel ist im Aufbau - bitte Verständnis für Unvollständigkeiten und fehlende Bereiche &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Der Zählersensor ist ein Datenerfassungssystem, das den Energieverbräuche (Strom, Gas) direkt am Zähler erfasst und in FHEM als laufender Saldo und als Momentanwerte verfügbar macht.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gewicht: 195 g (inkl. 4 LR6/Mignon/AA-Batterien)&lt;br /&gt;
&lt;br /&gt;
== Anwendungsszenarien ==&lt;br /&gt;
Mit den erfassten und gesammelten Daten lassen sich Aktionen beim Erreichen bestimmter Schwellwerte auslösen, Verbrauchs- und Kostenstatistiken ableiten sowie beliebige weitere Abhängigkeiten bilden. Durch die Funkdatenübertragung sowie den Batteriebetrieb (1 bis 2 Jahre Betriebsdauer verspricht der Hersteller mit einem Satz) ist die Installation denkbar einfach und erfordert lediglich beim Anbringen der Leseeinheit Genauigkeit.&lt;br /&gt;
&lt;br /&gt;
Aktuell (Feb. 2015) hat die Auslieferung der Geräte als (einfacher) Bausatz begonnen, zu dem es einen Ferraris-Sensor (für Stromzähler mit den markanten Laufscheiben), LED-Sensor (für neue Zähler mit S0-Schnittstelle) sowie BK-G4-Gaszähler von Elster-Kromschröder, die an einer Ziffernrolle einen kleinen Magneten haben, der über einen Sensor mit Reedkontakt erfasst wird. Es ist laut Hersteller [http://www.elv.de/homematic-zaehlersensor-strom-gas-bausatz.html ELV] nur der Bausatz verfügbar. Ein Fertiggerät ist aktuell nicht geplant.&lt;br /&gt;
&lt;br /&gt;
Die Zähler werden mit rückstandslos entfernbaren Klebepads angebracht.&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
 &#039;&#039;&#039;list:        register | range              | peer     | description&#039;&#039;&#039; &lt;br /&gt;
   0: pairCentral      |   0 to 16777215    |          | pairing to central &lt;br /&gt;
   1: mtrConstGas      |   0 to 655.36      |          | constant gas &lt;br /&gt;
   1: mtrConstIr       |   0 to 65536       |          | constant IR &lt;br /&gt;
   1: mtrConstLed      |   0 to 65536       |          | constant led &lt;br /&gt;
   1: mtrSensIr        | -99 to 99          |          | sensiblity IR &lt;br /&gt;
   1: mtrType          |     literal        |          | type of measurement options:LED,gas,unknown,IR &lt;br /&gt;
&lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
Der HM-ES-TX-WM sendet zyklisch im 3-Minuten Takt die aktuellsten Verbrauchsdaten. Dabei ist für das Reading &amp;quot;power&amp;quot; (aktuelle Stromleistung in Watt) zu beachten, dass aller 3 Minuten nur der zuletzt bekannte Wert gesendet. Das heisst im besonderen:&lt;br /&gt;
&lt;br /&gt;
* sollten innerhalb der 3 Minuten mehrfache Impulse auftreten mit unterschiedlichen Leistungswerten, wird nur der zuletzt bekannte Wert genommen. Es findet keine Aggregation aller Impulse wie z.B. Mittelwert o.ä. statt.&lt;br /&gt;
* sollten innerhalb der 3 Minuten keinerlei Impulse auftreten, wird dennoch der zuletzt bekannte Leistungswert gesendet, auch wenn er mehrere Minuten/Stunden/Tage alt ist.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
Der Sensor wird mit einem FHEM im Update-Stand vom (mindestens) 7.2.2015 funktionsfähig eingebunden (getestet in der Variante mit Feraris-Fühler). Es werden der Fühlertyp und die Fühlerkonstante richtig ausgelesen und im Reading Energy die errechnete Energiemenge ausgegeben (bei Strom: Wattstunden, Wh).&lt;br /&gt;
&lt;br /&gt;
Für die perfekte Konfiguration wird auf [[Heizleistung_und_Gasverbrauch]] verwiesen, wo eine vollständige Lösung für die Umrechnung von Gasverbrauch in kW/h, Graphen und Hilfsprogramme vorgestellt wird.&lt;br /&gt;
&lt;br /&gt;
=== Readings ===&lt;br /&gt;
 &#039;&#039;&#039;Reading:       |Beispiel&#039;&#039;&#039;   &lt;br /&gt;
 D-firmware     |1.0&lt;br /&gt;
 D-serialNr     |MEQ0025452 &lt;br /&gt;
 battery        |ok&lt;br /&gt;
 boot           |off &lt;br /&gt;
 current        |0 &lt;br /&gt;
 eState         |E: 6199.9 P: 1713 I: 0 U: 0 f: 50 &lt;br /&gt;
 energy         |6199.9 &lt;br /&gt;
 energyOffset   |84413.2&lt;br /&gt;
 frequency      |50 &lt;br /&gt;
 power          |1713 &lt;br /&gt;
 powerOn        |2015-03-26 14:57:48&lt;br /&gt;
 voltage        |0&lt;br /&gt;
&lt;br /&gt;
=== Events Auszug ===&lt;br /&gt;
 &#039;&#039;&#039;Event     |Beispielswert&#039;&#039;&#039;&lt;br /&gt;
 battery*  |ok&lt;br /&gt;
 energy    |10186.6&lt;br /&gt;
 power     |283&lt;br /&gt;
 current   |0&lt;br /&gt;
 voltage   |0&lt;br /&gt;
 frequency |50&lt;br /&gt;
 eState    |E: 10186.6 P: 283 I: 0 U: 0 f: 50&lt;br /&gt;
 boot      |off&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;*&amp;lt;/nowiki&amp;gt;  -  Ein battery-Event wird nicht zyklisch getriggert. Erst wenn die Batterie tatsächlich leer ist, wird eine entsprechende Meldung vom Gerät selber gesendet und ein battery-Event getriggert (battery: low).&lt;br /&gt;
&lt;br /&gt;
Mit einem Userreading lässt sich die Angabe aus Energy zum Beispiel für einen Stromzähler (Wh) in die auf dem Zähler übliche Angabe kWh umrechnen und zugleich mit dem Aufaddieren des Unterschieds beim Start (das Zählermodul beginnt ja mit 0 Wh, während der Zähler meist schon einige Jahre auf der &amp;quot;Rolle&amp;quot; hat) die Angaben gleichziehen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;DeviceName&amp;gt; userReadings kWh {sprintf(&amp;quot;%.1f&amp;quot;,ReadingsVal(&amp;quot;CUL_HM_HM_ES_TX_WM_353594&amp;quot;,&amp;quot;energy&amp;quot;,&amp;quot;???&amp;quot;)/1000+72031.5639)}&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
Nach dem Erkennen durch [[autocreate]] wird der Zählersensor mit diesen Angaben eingebunden:&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_TX_WM_353594 CUL_HM 353594&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 IODev CUL_0&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 actCycle 000:10&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 actStatus alive&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 expert 2_full&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 firmware 1.0&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 model HM-ES-TX-WM&lt;br /&gt;
 attr CUL_HM_HM_ES_TX_WM_353594 subType powerSensor&lt;br /&gt;
&lt;br /&gt;
Für den Betrieb mit den verschiedenen Zählern muß eines der Readings &#039;&#039;&#039;R-mtrConst&#039;&#039;&#039;XXX auf den jeweiligen verwendeten Zähler konfiguriert werden. Z.B. kann ein Ferraris-Stromzähler 100, 150 oder 200 Umdrehungen je kWh benötigen. Dies geschieht z.B. für 150 Meldungen je Einheit für einen Ferraris-Zähler mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 set CUL_HM_HM_ES_TX_WM_353594 regSet mtrConstIr 150&lt;br /&gt;
&lt;br /&gt;
oder für einen Gaszähler auf der 1. Rolle (d.h. 1 Impuls je 0.1 m^3)&lt;br /&gt;
&lt;br /&gt;
 set CUL_HM_HM_ES_TX_WM_353594 regSet mtrConstGas 0.1&lt;br /&gt;
&lt;br /&gt;
In fhem bis zum Anfang November 2015 war hier ein kleiner Bug enthalten, der diesen Wert nicht akzeptierte. In diesem Fall läßt sich die Anzahl der Impulse direkt am Gerät über das Display einstellen.&lt;br /&gt;
&lt;br /&gt;
== Logging/Graph. Darstellung ==&lt;br /&gt;
[[Datei:PlotStromverbrauchProStunde.png|mini|400px|rechts|Beispiel der graph. Darstellung]]&lt;br /&gt;
Der Zähler wird ja fortlaufend aufaddiert. Mit der delta-Funktion von SVG-Plot können die Verbräuche sehr gut visualisiert werden. &lt;br /&gt;
Beispiel Stromzähler:&lt;br /&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;Stündlicher Stromverbrauch | aktuell: $data{currval1} ($data{min1} / $data{avg1} / $data{max1}) kWh&#039;&lt;br /&gt;
 set ytics &lt;br /&gt;
 set y2tics &lt;br /&gt;
 set grid ytics&lt;br /&gt;
 set ylabel &amp;quot;kWh/h&amp;quot;&lt;br /&gt;
 set y2label &amp;quot;kWh/h&amp;quot;&lt;br /&gt;
 #FileLog 4:CUL_HM_HM_ES_TX_WM_353594.kWh\x3a:0:delta-h&lt;br /&gt;
 plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Line 1&#039; ls l0 lw 2 with bars&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Handbuch: [http://files.elv.de/Assets/Produkte/14/1401/140143/Downloads/140143_sensor_um.pdf]&lt;br /&gt;
* Produktseite ELV: [http://www.elv.de/homematic-zaehlersensor-strom-gas-bausatz.html] &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEM_auf_Raspberry_PI_mit_COC_betreiben&amp;diff=11583</id>
		<title>FHEM auf Raspberry PI mit COC betreiben</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEM_auf_Raspberry_PI_mit_COC_betreiben&amp;diff=11583"/>
		<updated>2015-07-05T11:55:28Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: /* FHEM Installieren */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Um einen [[COC]] mit einem Raspberry Pi und FHEM zu nutzen sind mehrere Schnitte notwendig. Die folgende Anleitung zeigt diese entsprechend auf.&lt;br /&gt;
&lt;br /&gt;
== Vorausetzung ==&lt;br /&gt;
Erforderliche Hardware:&lt;br /&gt;
* [[Raspberry Pi]]&lt;br /&gt;
* Busware [[COC]]&lt;br /&gt;
&lt;br /&gt;
Erforderliche Software:&lt;br /&gt;
* Raspbian OS (Debian Wheezy Version June 2014, oder aktueller)&lt;br /&gt;
&lt;br /&gt;
Notwendige Vorbereitungen:&lt;br /&gt;
* Busware [[COC]] ist auf dem [[Raspberry Pi]] montiert&lt;br /&gt;
* [[Raspberry Pi]] ist per LAN Kabel an den Router angeschlossen und hat eine IP via DHCP bekommen und kann in das Internet (keine Firewall Restriktion)&lt;br /&gt;
&lt;br /&gt;
== Raspberry OS auf die Speicherkarte übertragen ==&lt;br /&gt;
# Raspberry OS als Image von der Raspberry PI Webseite http://downloads.raspberrypi.org/raspbian_latest herunterladen&lt;br /&gt;
# Mit win32diskimager http://win32diskimager.sourceforge.net auf die Speicherkarte übertragen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FHEM Installieren ==&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=Hier wird die &amp;quot;manuelle&amp;quot; Installationsvariante von Fhem (11.-13.) angewendet. Mittlerweile ist auch die Installation aus einem [[Raspberry_Pi#Debian-Repository|Debian-Repository ]] möglich.}}&lt;br /&gt;
# Raspberry Pi booten&lt;br /&gt;
# Einloggen als User: pi mit dem Password: raspberry&lt;br /&gt;
# Danach sollte das Raspberry OS upgedatet werden: &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get upgrade -y &amp;amp;&amp;amp; sudo apt-get autoremove -y &amp;amp;&amp;amp; sudo reboot&amp;lt;/code&amp;gt;&lt;br /&gt;
# nach dem neustart sollte auch kurz die Firmware aktuallisiert werden. Das geht wie folgt: &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;sudo apt-get install rpi-update&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;sudo rpi-update&amp;lt;/code&amp;gt;&lt;br /&gt;
# Anschließend sollte der Raspberry PI neu gestarted werden mittels &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;sudo shutdown -r now&amp;lt;/code&amp;gt;&lt;br /&gt;
# Danach muss die richtige Zeitzone für unseren RPI eingestellt werden, das geht mittels &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;sudo dpkg-reconfigure tzdata&amp;lt;/code&amp;gt;&lt;br /&gt;
# Damit der RPI den gesamten Speicherplatz der SD-Karte nutzt, kann man (sofern noch nicht nach dem ersten Start getan) das Filesystem mit folgendem Menü erweitern&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;sudo raspi-config&amp;lt;/code&amp;gt;&lt;br /&gt;
# Anschließend rebooten wir den RPI mittels &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;sudo shutdown -r now&amp;lt;/code&amp;gt;&lt;br /&gt;
# Einloggen als User: Pi mit dem Password: Raspberry&lt;br /&gt;
# Da wir davon ausgehen das wir FHEM mit Zeitprofilen verwenden werden ist das korrekte Datum sehr wichtig. Daher installieren wir einen NTP Client, der die Zeit aktuell hält und richten ihn für Deutschland ein. Dies geht wie folgt: &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;sudo apt-get install ntpdate&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;sudo ntpdate -u de.pool.ntp.org&amp;lt;/code&amp;gt;&lt;br /&gt;
# Da der FHEM auf Perl basiert müssen jetzt die notwendigen Packete installiert werden:&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;sudo apt-get -f install &amp;amp;&amp;amp; sudo apt-get install perl libdevice-serialport-perl libio-socket-ssl-perl libwww-perl libxml-simple-perl -y&amp;lt;/code&amp;gt;&lt;br /&gt;
# Jetzt können wir FHEM herunterladen und zwischenspeichern: &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;sudo wget http://fhem.de/fhem-5.5.deb -O /tmp/fhem-5.5.deb&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt; Es ist darüber hinaus sinvoll kurz zu kontrollieren, ob die Version aktuell ist. Das kann auf der FHEM Webseite http://fhem.de/fhem.html getan werden.&lt;br /&gt;
# Anschließend kann FHEM installiert werden:&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;sudo dpkg -i /tmp/fhem-5.5.deb&amp;lt;/code&amp;gt;&lt;br /&gt;
# Da FHEM automatisch gestarted hat, müssen wir ihn jetzt kurz beenden via:&amp;lt;code&amp;gt;/etc/init.d/fhem stop&amp;lt;/code&amp;gt;&lt;br /&gt;
# Jetzt müssen wir noch die Rechte des FHEM Verzeichnisses anpassen.&amp;lt;br&amp;gt;Dafür vergeben wir auf alle Dateien unter /opt/fhem Schreibrechte&amp;lt;code&amp;gt;sudo chmod -R a+w /opt/fhem&amp;lt;/code&amp;gt;&lt;br /&gt;
# Nun fügen wir die Benutzer pi und fhem der Gruppe tty hinzu (Zugriffsrechte auf Serial- und USB-Ports)&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;sudo usermod -aG tty pi &amp;amp;&amp;amp; sudo usermod -aG tty fhem&amp;lt;/code&amp;gt;&lt;br /&gt;
# Jetzt müssen wir den Speicherort des Logfiles anpassen. Dafür editieren wir die FHEM config via &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;nano fhem.cfg&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;und ändern alle einträge der art &amp;quot;./log/&amp;quot; nach &amp;quot;/opt/fhem/log&amp;quot;&lt;br /&gt;
# Jetzt starten wir FHEM kurz neu &amp;lt;code&amp;gt;/etc/init.d/fhem stop&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;/etc/init.d/fhem start&amp;lt;/code&amp;gt;&lt;br /&gt;
# Anschließend können wir uns über &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://&amp;lt;dieRaspberryIP&amp;gt;:8083/fhem&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; am FHEM anmelden. In der Dialogbox oben geben wir nun folgendes ein, um FHEM zu aktualisieren &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;attr global sendStatistics onUpdate&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;update&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt; und wenn uns FHEM nach einem Neustart fragt, kommen wir dem mittels &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;shutdown restart&amp;lt;/code&amp;gt; nach.&lt;br /&gt;
&lt;br /&gt;
== COC in Betrieb nehmen ==&lt;br /&gt;
# Nun muss der serielle Port für den Raspberry freigegeben werden. Dazu muss die Datei /etc/inittab mittels &amp;lt;code&amp;gt;sudo nano /etc/inittab&amp;lt;/code&amp;gt; angepasst werden und folgende Zeile löschen &amp;lt;code&amp;gt;T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100&amp;lt;/code&amp;gt; oder auskommentieren&lt;br /&gt;
# Ähnlich verfahren wir mit der /boot/cmdline.txt. Sie wird mittels &amp;lt;code&amp;gt;sudo nano /boot/cmdline.txt&amp;lt;/code&amp;gt; editiert und Referenzen auf ttyAMA0 entfernt &amp;lt;code&amp;gt;console=ttyAMA0,115200 kgdboc=ttyAMA0,115200&amp;lt;/code&amp;gt;&lt;br /&gt;
# Damit der COC beim Start vom FHEM initialisiert wird, muss die /etc/init.d/fhem editiert werden. Dies machen wir mittels &amp;lt;code&amp;gt;sudo nano /etc/init.d/fhem&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;und fügen unterhalb von &amp;quot;Start)&amp;quot; folgendes in die Datei ein &amp;lt;br /&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt;echo &amp;quot;resetting 868MHz extension...&amp;quot; &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt;	if test ! -d /sys/class/gpio/gpio17; then echo 17 &amp;gt; /sys/class/gpio/export; fi &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt;	if test ! -d /sys/class/gpio/gpio18; then echo 18 &amp;gt; /sys/class/gpio/export; fi &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt;	echo out &amp;gt; /sys/class/gpio/gpio17/direction &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt;	echo out &amp;gt; /sys/class/gpio/gpio18/direction &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt;	echo 1 &amp;gt; /sys/class/gpio/gpio18/value &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt;	echo 0 &amp;gt; /sys/class/gpio/gpio17/value &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt;	sleep 1 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt;	echo 1 &amp;gt; /sys/class/gpio/gpio17/value &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt;	sleep 1 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;Achtung: Nach einem Update von FHEM könnte diese Datei überschrieben werden. Dann muss die Änderung oben wieder hinzugefügt werden.&lt;br /&gt;
# nun wird der COC in die Fhem [[Konfiguration]] eingefügt. Dafür wird (z.B., aber nicht die empfohlene Vorgehensweise) die Konfigurationsdatei editiert: &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;&amp;quot;sudo nano /opt/fhem/fhem.cfg&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;und ganz zum Schluss folgendes hinzugefügt: &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;&amp;quot;define COC CUL /dev/ttyAMA0@38400 1234&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
# Nun wird der Raspberry PI vollständig neu gestarted &amp;lt;code&amp;gt;sudo shutdown -r now&amp;lt;/code&amp;gt;&lt;br /&gt;
# Der Raspberry PI sollte nun via auto detect die Komponenten auffinden&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Raspberry Pi]]&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SMAWechselrichter&amp;diff=10703</id>
		<title>SMAWechselrichter</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SMAWechselrichter&amp;diff=10703"/>
		<updated>2015-03-30T15:12:15Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: Installationsbefehl für die BT-Pakete zusammen gefasst ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einbindung eines Wechselrichters von SMA in FHEM ==&lt;br /&gt;
&lt;br /&gt;
Basierend auf diesem [http://forum.fhem.de/index.php/topic,14624.0.html Thread] im Fhem-Forum wird erklärt wie man seinen Wechselrichter von SMA in FHEM einbinden kann. Dafür kommt das Tool [http://sbfspot.codeplex.com/ SBFspot] (alter Name: SMASpot) zum Einsatz.&lt;br /&gt;
&lt;br /&gt;
=== Vorbedingungen ===&lt;br /&gt;
Für die weitere Anleitung wird angenommen, dass FHEM auf einem RaspberryPi installiert wurde, funktioniert und genügend Platz für das kompilieren und die notwendigen Libraries zur Verfügung steht.&lt;br /&gt;
&lt;br /&gt;
Die Tools make und g++ müssen installiert sein. Falls noch nicht vorhanden, müssen diese mit &lt;br /&gt;
:&amp;lt;code&amp;gt;sudo apt-get install make&amp;lt;/code&amp;gt; und &lt;br /&gt;
:&amp;lt;code&amp;gt;sudo apt-get install g++&amp;lt;/code&amp;gt; installiert werden.&lt;br /&gt;
&lt;br /&gt;
=== Installation ===&lt;br /&gt;
&lt;br /&gt;
==== Schritt 1 - Installation der notwendigen Libraries ====&lt;br /&gt;
Der Wechselrichter kann entweder per Bluetooth oder per Speedwire (Ethernet) ausgelesen werden. Unabhängig davon, wie der WR ausgelesen wird, müssen die folgenden Pakete installiert werden:&lt;br /&gt;
(Quelle: [http://sbfspot.codeplex.com/wikipage?title=SBFspot%20on%20Raspberry%20Pi&amp;amp;referringTitle=Documentation SBFSpot-Doku])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install bluetooth libbluetooth-dev libcurl3-dev libboost-all-dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anschließend muss die Bluetooth Adresse des Wechselrichters ermittelt werden:&lt;br /&gt;
:&amp;lt;code&amp;gt;hcitool scan&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Schritt 2 - Installation von SBFSpot ====&lt;br /&gt;
Als erstes wird ein Verzeichnis erstellt, in das die Quellcode-Dateien heruntergeladen und anschließend kompiliert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /home/pi&lt;br /&gt;
mkdir sbfspot&lt;br /&gt;
cd sbfspot &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun kann SBFSpot heruntergeladen,&lt;br /&gt;
:&amp;lt;code&amp;gt;wget [URL of latest version]&amp;lt;/code&amp;gt;&lt;br /&gt;
entpackt,&lt;br /&gt;
:&amp;lt;code&amp;gt;tar -xvf [Dateiname]&amp;lt;/code&amp;gt;&lt;br /&gt;
und abschließend kompiliert werden:&lt;br /&gt;
:&amp;lt;code&amp;gt;make release&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach werden das Programm SBFSpot und die Konfigurationsdatei noch in das FHEM Verzeichnis kopiert:&lt;br /&gt;
:&amp;lt;code&amp;gt;sudo cp SBFspot SBFspot.cfg /opt/fhem/FHEM/sbfspot/bin/Release&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und die Rechte setzen:&lt;br /&gt;
:&amp;lt;code&amp;gt;sudo chown -R fhem /opt/fhem/FHEM/sbfspot&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um die Kompatibilität mit den diversen im Forum herumgeisternden Modulen zu gewährleisten, empfiehlt es sich ein paar Links zu erzeugen:&lt;br /&gt;
:&amp;lt;code&amp;gt;cd /opt/fhem/FHEM/; sudo ln -s  sbfspot smaspot&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;cd /opt/fhem/FHEM/sbfspot; sudo ln -s  SBFspot SMAspot&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Möchte man nun Bluetooth nutzen, muss man schliesslich noch in der Datei &#039;&#039;/opt/fhem/FHEM/sbfspot/bin/Release/SBFspot.cfg&#039;&#039; die vorher mit &#039;&#039;hcitool&#039;&#039; gefundene Bluetooth-Adresse eintragen.&lt;br /&gt;
&lt;br /&gt;
=== Einbindung in FHEM ===&lt;br /&gt;
==== Konfiguration in FHEM ====&lt;br /&gt;
&lt;br /&gt;
Nun benötigen wir noch das Modul [http://forum.fhem.de/index.php/topic,14624.msg153006.html#msg153006 99_SMAUtils.pm] aus dem o.g. Thread. Dieses wird in das FHEM Verzeichnis (default wäre hier: /opt/fhem/FHEM) kopiert.&lt;br /&gt;
&lt;br /&gt;
Als nächsten editieren wir die fhem.cfg und fügen die folgenden Zeilen hinzu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Solar Wechselrichter&lt;br /&gt;
#&lt;br /&gt;
define Solar SMAUtils 00:80:25:2D:46:16 600&lt;br /&gt;
attr Solar delay 600&lt;br /&gt;
attr Solar icon measure_photovoltaic_inst&lt;br /&gt;
attr Solar room Energie&lt;br /&gt;
#&lt;br /&gt;
# FileLog Definition&lt;br /&gt;
#&lt;br /&gt;
define FileLog_Solar FileLog ./log/Solar-%Y-%m.log Solar:.*etod.*|Solar:.*string.*_pdc|Solar:.*total_pac|Solar:.*usage.*&lt;br /&gt;
attr FileLog_Solar icon icoLog&lt;br /&gt;
attr FileLog_Solar nrarchive 12&lt;br /&gt;
attr FileLog_Solar room Logfiles&lt;br /&gt;
#&lt;br /&gt;
# Chart&lt;br /&gt;
#&lt;br /&gt;
define SVG_FileLog_Solar_1 SVG FileLog_Solar:SVG_FileLog_Solar_1:CURRENT&lt;br /&gt;
attr SVG_FileLog_Solar_1 room Energie&lt;br /&gt;
attr SVG_FileLog_Solar_1 title &amp;quot;Solarleistung Min $data{min1}, Max $data{max1}, Last $data{currval1}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:String performance.PNG|mini|400px|Beispielplot (SVG_FileLog_Solar_1.gplot)]] &lt;br /&gt;
&lt;br /&gt;
In der ersten Zeile wird aktuell noch eine gültige Bluetooth Adresse benötigt, da das Modul SMAUtils diesen Parameter erwartet. Dies ist unabhängig davon, ob man den Wechselrichter per Bluetooth oder Ethernet anspricht. In letzterem Fall muss es nicht die richtige Bluetooth-Adresse des Wechselrichters sein, irgendeine Adresse ist ausreichend. Die eventuell auftretende Fehlermeldung &amp;quot;Solar: unknown attribute delay. Type &#039;attr Solar ?&#039; for a detailed list.&amp;quot; kann ignoriert werden.&lt;br /&gt;
&lt;br /&gt;
==== Konfiguration des Plots ====&lt;br /&gt;
nun muss noch die Plotterkonfig für die Grafik erstellt werden. Dazu wird die Datei &amp;quot;&#039;&#039;SVG_FileLog_Solar_1.gplot&#039;&#039;&amp;quot; im FHEM Verzeichnis &amp;quot;&#039;&#039;/opt/fhem/www/gplot&#039;&#039;&amp;quot; mit folgendem Inhalt erzeugt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2014-04-03 11:08:53&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;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;kW&amp;quot;&lt;br /&gt;
set y2label &amp;quot;kW&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#FileLog 4:Solar.string_1_pdc\x3a:0:&lt;br /&gt;
#FileLog 4:Solar.string_2_pdc\x3a:0:&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;String 1&#039; ls l2 lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;String 2&#039; ls l0 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und nun sollte es im FHEM einen weiteren Menüpunkt &amp;quot;Energie&amp;quot; mit einer schönen Grafik geben :-)&lt;br /&gt;
&lt;br /&gt;
=== Alternativen zum Auslesen der Daten ===&lt;br /&gt;
Es gibt ein Tool [https://github.com/Tommy-LSA/supoxy suproxy], welches die Daten des Sunny Portals ausliest. Damit erhält man nicht nur die Daten des Wechselrichters, sondern auch die Daten des Stromzählers. &lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://forum.fhem.de/index.php/topic,14624.0.html Forenthread], in dem die Lösung vorgestellt / diskutiert wird&lt;br /&gt;
* [http://forum.fhem.de/index.php/topic,24876.0.html Forenthread], indem suproxy vorgestellt / diskutiert wird&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-SEC-KEY_KeyMatic&amp;diff=7726</id>
		<title>HM-SEC-KEY KeyMatic</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-SEC-KEY_KeyMatic&amp;diff=7726"/>
		<updated>2014-09-06T09:32:21Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: /* Links */  korrigiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Features ==&lt;br /&gt;
Das Gerät dient zum motorgesteuerten Betätigen von Zylinderschlössern in Türen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zum Betrieb mit FHEM ==&lt;br /&gt;
Der HM-SEC-KEY Keymatic  verwendet ausschließlich die AES authentifizierte Kommunikation. Daher kann die Steuerung nur zusammen mit dem [[HMLAN Konfigurator]] erfolgen.&lt;br /&gt;
Mit dem [[CUL]] ist jedoch auch eine Statusanzeige und das reagieren auf Events möglich.&lt;br /&gt;
&lt;br /&gt;
Das Pairing sollte wie in [[HomeMatic Devices pairen]] beschrieben durchgeführt werden. An der KeyMatic muss dafür die Anlerntaste (Taste Schloss öffnen) betätigt werden.&lt;br /&gt;
&lt;br /&gt;
Die KeyMatic-Unterstützung existiert derzeit in der aktuellen Entwicklerversion von FHEM&lt;br /&gt;
&lt;br /&gt;
=== Sicherheitshinweis ===&lt;br /&gt;
Wenn die KeyMatic an einem aktiven HMLAN Konfigurator angelernt wurde, kann die entsprechende Tür per FHEM ver- / entriegelt bzw. geöffnet werden. Somit sollte das Netzwerk in dem FHEM läuft entsprechend gesichert sein. (Nicht nach Außen geöffnet, kein unsicheres WLAN usw.)&lt;br /&gt;
&lt;br /&gt;
=== FHEM Config-Auszug ===&lt;br /&gt;
Beispiel für die Konfiguration:&lt;br /&gt;
&lt;br /&gt;
ssssss -&amp;amp;gt; 6-Stellige hexadezimale Seriennummer. (Siehe Logfile: CUL_HM Unknown device CUL_HM_keyMatic_ssssss, please define it)&lt;br /&gt;
xxxxxxx -&amp;amp;gt; Seriennummer (vom Aufkleber auf dem Gerät)&lt;br /&gt;
&lt;br /&gt;
 define keymatic CUL_HM ssssss&lt;br /&gt;
 attr keymatic devInfo 010100&lt;br /&gt;
 attr keymatic firmware 2.4&lt;br /&gt;
 attr keymatic hmClass receiver&lt;br /&gt;
 attr keymatic model HM-SEC-KEY-S&lt;br /&gt;
 attr keymatic room Flur&lt;br /&gt;
 attr keymatic serialNr JEQxxxxxxx&lt;br /&gt;
 attr keymatic subType keyMatic&lt;br /&gt;
 attr keymatic webCmd lock:unlock:open&lt;br /&gt;
&lt;br /&gt;
== Mögliche Zustände ==&lt;br /&gt;
KeyMatic hat folgende Schaltzustände:&lt;br /&gt;
&lt;br /&gt;
  locked -&amp;amp;gt; Der Riegel des Türschlosses ist an die vorher festgelegte Verschlussstellung gefahren (Tür verschlossen)&lt;br /&gt;
  unlocked -&amp;amp;gt; Der Riegel des Türschlosses ist &amp;quot;eingefahren&amp;quot; (Tür nicht verschlossen)&lt;br /&gt;
  uncertain (locked / unlocked) -&amp;amp;gt; Das Schloss wurde am Handrad gedreht. Die Schlossposition ist somit nicht mehr als &amp;quot;zuverlässig erkannt&amp;quot; gemeldet.&lt;br /&gt;
== Links ==&lt;br /&gt;
Anleitung [http://www.eq-3.de/Downloads/eq3/pdf_produkte/HM-Sec-Key_UM_GE_eQ-3_081218.pdf] PDF&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-LC-Sw4-SM_4fach_Schaltaktor_Aufputz&amp;diff=7592</id>
		<title>HM-LC-Sw4-SM 4fach Schaltaktor Aufputz</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-LC-Sw4-SM_4fach_Schaltaktor_Aufputz&amp;diff=7592"/>
		<updated>2014-08-30T18:20:26Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: /* Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Features ==&lt;br /&gt;
* Funkfrequenz 868,3 MHz&lt;br /&gt;
* Typ. Freifeldreichweite: 300 m&lt;br /&gt;
* Spannungsversorgung: 230 V / 50 Hz&lt;br /&gt;
* Standby-Verbrauch: 0,5 W &lt;br /&gt;
* Schutzart: IP65&lt;br /&gt;
* Schutzklasse: II&lt;br /&gt;
* Gehäuse: PC, lichtgrau&lt;br /&gt;
* Relais: 4 Wechsler (potentialfreie Kontakte)&lt;br /&gt;
* Schaltvermögen: 16 A (ohmsche Last)&lt;br /&gt;
* Abm. (B x H x T): 171 x 55 x 121 mm&lt;br /&gt;
&lt;br /&gt;
== Hinweise zum Betrieb mit FHEM ==&lt;br /&gt;
&lt;br /&gt;
Das Pairing sollte wie unter HomeMatic Devices pairen beschrieben durchgeführt werden.&lt;br /&gt;
Das Gerät und seine 4 Kanäle werden vom Autodetect einwandfrei erkannt und initialisiert.&lt;br /&gt;
&lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
Bisher keine. &lt;br /&gt;
&lt;br /&gt;
== FHEM Config-Auszug ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt; folgt &amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Event-Monitor ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt; folgt &amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parameter-Liste ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt; folgt &amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== FHEM Log-Auszug  ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt; folgt &amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
http://www.eq-3.de/Downloads/eq3/pdf_produkte/73951_HM-Aufputzaktoren_GE_V2.1_20140521_web.pdf&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Schalter (Empfänger)‏‎]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-CC-VD_Funk-Stellantrieb&amp;diff=6583</id>
		<title>HM-CC-VD Funk-Stellantrieb</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-CC-VD_Funk-Stellantrieb&amp;diff=6583"/>
		<updated>2014-06-19T12:12:41Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: Anleitung zum Modul eingebunden&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;HM-CC-VD Funk-Stellantrieb&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung: Dieses Gerät ist abgekündigt (wird nicht mehr hergestellt). Nachfolgeprodukt ist der [[HM-CC-RT-DN]].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Allgemeines =&lt;br /&gt;
&lt;br /&gt;
Stellantrieb für den [[HM-CC-TC Funk-Wandthermostat|HM-CC-TC]]. Es können maximal 4 HM-CC-VD an ein HM-CC-TC angelernt werden.&lt;br /&gt;
&lt;br /&gt;
Aktuelle Firmware: 2.0&lt;br /&gt;
&lt;br /&gt;
Der HM-CC-VD &#039;&#039;&#039;misst nicht selbst&#039;&#039;&#039; die Temperatur. Diese wird von dem HM-CC-TC, mit dem der Stellantrieb gepairt wurde, gemessen.&lt;br /&gt;
&lt;br /&gt;
= Probleme =&lt;br /&gt;
&lt;br /&gt;
Bei Firmwareversionen vor 2.0 kann es vorkommen, dass sich der Stellantrieb bei einer bestimmten Stellung &amp;quot;festfährt&amp;quot; (z.B. 4%) und der Raum sich kontinuierlich erhitzt, obwohl eine niedrigere Temperatur am Wandthermostat eingestellt ist. Erst nach einem Reset des Stellantriebs oder manuellen Erhöhung der Temperatur am Wandthermostat/FHEM verrichtet der Stellantrieb wieder wie gewohnt seine Arbeit.&lt;br /&gt;
&lt;br /&gt;
Quelle: [http://www.elv.de/output/controller.aspx?cid=834&amp;amp;detail=2&amp;amp;detail2=582 [1]]&lt;br /&gt;
&lt;br /&gt;
Ein Firmwareupdate kann derzeit nur mittels Einschicken des Stellantriebs erfolgen.&lt;br /&gt;
&lt;br /&gt;
Ist der Stellantrieb mit dem HM-CC-TC gepairt (zu sehen im Menü des HM-CC-TC als VST Nummer X), erscheint aber nicht in Fhem (hier mit HMLAN), dann hilft der Befehl &#039;&#039;set &amp;lt;HMLAN-Name&amp;gt; hmPairForSec 300&#039;&#039; und das Drücken des Anlernknopfes am HM-CC-VD für mind. 5 Sekunden.&lt;br /&gt;
&lt;br /&gt;
= Betrieb mit FHEM =&lt;br /&gt;
&lt;br /&gt;
HM-CC-VDs werden mit dem für ihren Betrieb/Raum zuständigen HM-CC-TC gepeert. Dadurch ist der TC für die Ansteuerung der Ventiltriebe da.&lt;br /&gt;
&lt;br /&gt;
== Log-Daten ==&lt;br /&gt;
=== Device-Log ===&lt;br /&gt;
&lt;br /&gt;
Zur Behebung des &amp;quot;1 bzw. 4 % Fehlers&amp;quot; wurde die Raumtemperatur über die Ansteuerung des HM-CC-TC temporär auf 28 °C erhöht. Nachdem das Thermostat (VD) laut Logs das Ventil auf hier 68 % geöffnet hat, wurde die Temperatur wieder auf die gewünschte (desired) Temperatur (am TC) gesetzt. Diese Befehle mussten allerdings einige Male wiederholt werden und es bedurfte einiger Minuten Wartezeit zwischen den Umstellungen.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2013-03-18_22:34:57 OG.AZ.Thermostat set_0 %&lt;br /&gt;
2013-03-18_22:34:57 OG.AZ.Thermostat ValveDesired: 0 %&lt;br /&gt;
2013-03-18_22:34:58 OG.AZ.Thermostat ValvePosition: 1 %&lt;br /&gt;
2013-03-18_22:34:58 OG.AZ.Thermostat 1 %&lt;br /&gt;
2013-03-18_22:34:58 OG.AZ.Thermostat battery: ok&lt;br /&gt;
2013-03-18_22:34:58 OG.AZ.Thermostat motorErr: ok&lt;br /&gt;
2013-03-18_22:34:58 OG.AZ.Thermostat motor: stop&lt;br /&gt;
2013-03-18_22:34:58 OG.AZ.Thermostat operState: errorTargetNotMet&lt;br /&gt;
2013-03-18_22:34:58 OG.AZ.Thermostat operStateErrCnt: 1&lt;br /&gt;
2013-03-18_22:37:42 OG.AZ.Thermostat set_68 %&lt;br /&gt;
2013-03-18_22:37:42 OG.AZ.Thermostat ValveDesired: 68 %&lt;br /&gt;
2013-03-18_22:37:43 OG.AZ.Thermostat ValvePosition: 1 %&lt;br /&gt;
2013-03-18_22:37:43 OG.AZ.Thermostat 1 %&lt;br /&gt;
2013-03-18_22:40:20 OG.AZ.Thermostat set_68 %&lt;br /&gt;
2013-03-18_22:40:20 OG.AZ.Thermostat ValveDesired: 68 %&lt;br /&gt;
2013-03-18_22:40:22 OG.AZ.Thermostat ValvePosition: 68 %&lt;br /&gt;
2013-03-18_22:40:22 OG.AZ.Thermostat 68 %&lt;br /&gt;
2013-03-18_22:40:22 OG.AZ.Thermostat battery: ok&lt;br /&gt;
2013-03-18_22:40:22 OG.AZ.Thermostat motorErr: ok&lt;br /&gt;
2013-03-18_22:40:22 OG.AZ.Thermostat motor: stop&lt;br /&gt;
2013-03-18_22:40:22 OG.AZ.Thermostat operState: onTarget&lt;br /&gt;
2013-03-18_22:42:31 OG.AZ.Thermostat set_0 %&lt;br /&gt;
2013-03-18_22:42:31 OG.AZ.Thermostat ValveDesired: 0 %&lt;br /&gt;
2013-03-18_22:42:33 OG.AZ.Thermostat ValvePosition: 68 %&lt;br /&gt;
2013-03-18_22:42:33 OG.AZ.Thermostat 68 %&lt;br /&gt;
2013-03-18_22:42:33 OG.AZ.Thermostat battery: ok&lt;br /&gt;
2013-03-18_22:42:33 OG.AZ.Thermostat motorErr: ok&lt;br /&gt;
2013-03-18_22:42:33 OG.AZ.Thermostat motor: closing&lt;br /&gt;
2013-03-18_22:42:33 OG.AZ.Thermostat operState: adjusting&lt;br /&gt;
2013-03-18_22:44:34 OG.AZ.Thermostat set_0 %&lt;br /&gt;
2013-03-18_22:44:34 OG.AZ.Thermostat ValveDesired: 0 %&lt;br /&gt;
2013-03-18_22:44:36 OG.AZ.Thermostat ValvePosition: 0 %&lt;br /&gt;
2013-03-18_22:44:36 OG.AZ.Thermostat 0 %&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Event monitor ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2013-03-18 22:42:33 CUL_HM OG.AZ.Thermostat motor: closing&lt;br /&gt;
2013-03-18 22:42:33 CUL_HM OG.AZ.Thermostat operState: adjusting&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Batteriealarme des HM-CC-VD in Verbindung mit HM-CC-TC ==&lt;br /&gt;
1. bei U-Bat. &amp;lt; 2,4 V erscheint im Display des VD und des TC das Batteriesymbol mit battery: low in den Readings und Events!&lt;br /&gt;
2. bei U-Bat. &amp;lt; 2,3 V erscheint im Display des VD zusätzlich F4 mit battery: critical in den Readings und Events!&lt;br /&gt;
Es wird dringend geraten, die Batterien bei battery: low zu tauschen!&lt;br /&gt;
&lt;br /&gt;
= Links =&lt;br /&gt;
Anleitung: [http://www.eq-3.de/Downloads/eq3/pdf_produkte/HM-CC-VD_UM_GE_eQ-3_081013.pdf HM-CC-VD Funk-Stellantrieb]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Heizungsventile]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=E-Mail_senden&amp;diff=5580</id>
		<title>E-Mail senden</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=E-Mail_senden&amp;diff=5580"/>
		<updated>2014-03-27T09:55:46Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: /* Keine Mail mit TLS Verschlüsselung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Um aus FHEM heraus &#039;&#039;&#039;E-Mail senden&#039;&#039;&#039; zu können, sind abhängig von der verwendeten Platform unterschiedliche Vorgehensweisen erforderlich.&lt;br /&gt;
&lt;br /&gt;
== Linux ==&lt;br /&gt;
=== FritzBox 7170 (non-chroot) oder &amp;quot;reine&amp;quot; Linuxe ===&lt;br /&gt;
Datei 99_email.pm im Modul-Verzeichnis mit folgender Funktion anlegen (oder in bestehende 99_irgendwas.pm kopieren):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;sub fb_mail {&lt;br /&gt;
 my $rcpt = $_[0];&lt;br /&gt;
 my $subject = $_[1];&lt;br /&gt;
 my $text = $_[2];&lt;br /&gt;
 system(&amp;amp;quot;/bin/echo \&amp;amp;quot;$text\&amp;amp;quot; | /usr/bin/mail send -i - -s \&amp;amp;quot;$subject\&amp;amp;quot; -t \&amp;amp;quot;$rcpt\&amp;amp;quot;&amp;amp;quot;);&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Aufruf dann mittels &lt;br /&gt;
:&amp;lt;code&amp;gt;{ fb_mail(&#039;empfaenger@@mail.de&#039;,&#039;Subject&#039;,&#039;text 123&#039;) }&amp;lt;/code&amp;gt;&lt;br /&gt;
Darauf achten, dass der fhem-User Mails senden darf (in richtige Gruppe eintragen. Ggf. vorher einmal su fhem und probieren).&lt;br /&gt;
&lt;br /&gt;
=== Fritz!Box 7390 ===&lt;br /&gt;
Auf der [[AVM Fritz!Box|FritzBox 7390]] ist diese Funktion seit 10/2012 Bestandteil der Fhem Standardauslieferung. Sie ist untergebracht in FritzBoxUtils.pm und heisst dort FB_mail($$$) (Groß-Kleinschreibung beachten).&lt;br /&gt;
&lt;br /&gt;
Da der Dateiname von FritzBoxUtils.pm nicht mit 99_ beginnt, wird diese Programmdatei nicht automatisch beim Start von Fhem geladen. Fhem muss zum Laden dieser Programmdatei aufgefordert werden. Dazu (z.&amp;amp;nbsp;B. in 99_myUtils.pm) die Zeile &#039;&#039;use FritzBoxUtils;&#039;&#039; einfügen.&lt;br /&gt;
&lt;br /&gt;
Mit dem Install von AVM.de wird fhem in einer chroot-Umgebung ausgeführt, die den Zugriff auf die Mailfunktion der Fritzbox nicht zulässt. Daher muss Fhem in der [http://fhem.de/fhem.html#Download Version von fhem.de] installiert sein. Sollte Ihre Fritzbox bisher mit dem install von AVM laufen, kann (nach einem backup!) das image von fhem.de einfach drüberinstalliert werden. Es sollten dabei alle Einstellungen erhalten bleiben.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;sub fb_mail {&lt;br /&gt;
 my $rcpt = $_[0];&lt;br /&gt;
 my $subject = $_[1];&lt;br /&gt;
 my $text = $_[2];&lt;br /&gt;
 system(&amp;amp;quot;/bin/echo \&amp;amp;quot;$text\&amp;amp;quot; &amp;amp;gt; /var/tmp/fhem_nachricht.txt&amp;amp;quot;);&lt;br /&gt;
 system(&amp;amp;quot;/sbin/mailer send -i &#039;/var/tmp/fhem_nachricht.txt&#039; -s \&amp;amp;quot;$subject\&amp;amp;quot; -t \&amp;amp;quot;$rcpt\&amp;amp;quot;&amp;amp;quot;);&lt;br /&gt;
 system(&amp;amp;quot;rm /var/tmp/fhem_nachricht.txt&amp;amp;quot;);&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aufruf dann mittels &lt;br /&gt;
:&amp;lt;code&amp;gt;{ fb_mail(&#039;empfaenger@mail.de&#039;,&#039;Subject&#039;,&#039;text 123&#039;) }&amp;lt;/code&amp;gt;&lt;br /&gt;
bzw. &lt;br /&gt;
:&amp;lt;code&amp;gt;{ FB_mail(&#039;empfaenger@mail.de&#039;,&#039;Subject&#039;,&#039;text 123&#039;) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Wenn der Aufruf der Mailfunktion aus einem notify oder at erfolgt, muss das @@ in der Adresse des Mailempfängers verdoppelt werden, da ein einfaches @ sonst durch den Namen des getriggerten Devices  ersetzt würde. Bei Verwendung in der fhem-Kommandozeile oder einem eigenen *Utils.pm ist diese Doppelung nicht erforderlich. Bitte bei den ersten Mails ins Log schauen, ob die Mailadresse wie gewünscht verwendet wird.&lt;br /&gt;
&lt;br /&gt;
Dem Mailer können noch weitere Parameter hinzugefügt werden. Mehr dazu siehe: [http://www.wehavemorefun.de/fritzbox/Mailer Mailer]&lt;br /&gt;
&lt;br /&gt;
=== OpenWRT  ===&lt;br /&gt;
Die Anleitung wurde mit einer frühen Beta von Barrier Breaker (r391xx) mit einem TP_Lind WDR 4900 getestet. Da &amp;quot;sendEmail&amp;quot; nicht als Package vorliegt wird in dieser Anleitung &amp;quot;ssmtp&amp;quot; verwendet.&lt;br /&gt;
Die Installation erfolgt mittels:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
opkg update&lt;br /&gt;
opkg install ssmtp_2.64-4_mpc85xx.ipk  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hierbei werden die Packete libopenssl und zlib mit installiert. Damit ssmtp funktioniert müssen die Dateien /etc/ssmtp/ssmtp.conf und /etc/ssmtp/revaliases angepasst werden.&lt;br /&gt;
&lt;br /&gt;
/etc/ssmtp/ssmtp.conf &lt;br /&gt;
 &amp;lt;nowiki&amp;gt;root=arnold@gmx.net&lt;br /&gt;
mailhub=mail.gmx.net:465&lt;br /&gt;
rewriteDomain=gmx.net&lt;br /&gt;
hostname=gmx.net&lt;br /&gt;
FromLineOverride=YES&lt;br /&gt;
UseTLS=YES&lt;br /&gt;
#UseSTARTTLS=YES&lt;br /&gt;
AuthUser=arnold@gmx.net&lt;br /&gt;
AuthPass=Passwort_von_arnold@gmx.net&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/etc/ssmtp/revaliases&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
root:arnold@gmx.net:mail.gmx.net:465&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In der [[99_myUtils_anlegen|99_myUtils]] folgende Unterroutine einfügen (von der RPi-Anleitung übernommen):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;sub &lt;br /&gt;
OpenWRTMail &lt;br /&gt;
{ &lt;br /&gt;
 my $rcpt = shift;&lt;br /&gt;
 my $subject = shift; &lt;br /&gt;
 my $text = shift; &lt;br /&gt;
 my $ret = &amp;quot;&amp;quot;;&lt;br /&gt;
 my $sender = &amp;quot;dockstar\@heye-tammo.de&amp;quot;; &lt;br /&gt;
 Log 1, &amp;quot;sendEmail RCP: $rcpt, Subject: $subject, Text: $text&amp;quot;;&lt;br /&gt;
 $ret .= qx(echo -e &#039;to:$rcpt\n from:$sender\nsubject:$subject\n$text\n&#039; | ssmtp $rcpt);&lt;br /&gt;
 $ret =~ s,[\r\n]*,,g;    # remove CR from return-string &lt;br /&gt;
 Log 1, &amp;quot;sendEmail returned: $ret&amp;quot;; &lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab hier den entsprechenden Abschnitt unter &amp;quot;Raspberry Pi&amp;quot; lesen.&lt;br /&gt;
&lt;br /&gt;
=== Synology DiskStation ===&lt;br /&gt;
Beim DSM 3.2 gab es keinen &amp;lt;code&amp;gt;sendmail&amp;lt;/code&amp;gt;-Befehl, sondern nur eine Funktion für den Versand der System-Benachrichtigungen. Interessanterweise funktionierte aber der &amp;lt;code&amp;gt;php-mail&amp;lt;/code&amp;gt;-Befehl, so dass man mittels folgendem Modul Mails frei versenden kann:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;sub sendmail($$$) {&lt;br /&gt;
 my($empf, $subj, $nachricht) = @_;&lt;br /&gt;
 system(&amp;amp;quot;php -r &#039;mail(\&amp;amp;quot;$empf\&amp;amp;quot;,\&amp;amp;quot;$subj\&amp;amp;quot;,\&amp;amp;quot;$nachricht\&amp;amp;quot;);&#039;&amp;amp;quot;);&lt;br /&gt;
 undef;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Raspberry Pi ===&lt;br /&gt;
In der weezy-Version, wie sie von busware zur Verfügung gestellt wird, muss auf einem [[Raspberry Pi]] noch sendEmail nachinstalliert werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get update&lt;br /&gt;
sudo apt-get install sendEmail&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in der [[99_myUtils_anlegen|99_myUtils]] folgende Unterroutine einfügen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;######## DebianMail  Mail auf dem RPi versenden ############ &lt;br /&gt;
sub &lt;br /&gt;
DebianMail &lt;br /&gt;
{ &lt;br /&gt;
 my $rcpt = shift;&lt;br /&gt;
 my $subject = shift; &lt;br /&gt;
 my $text = shift; &lt;br /&gt;
 my $ret = &amp;amp;quot;&amp;amp;quot;;&lt;br /&gt;
 my $sender = &amp;amp;quot;absender\@account.de&amp;amp;quot;; &lt;br /&gt;
 my $konto = &amp;amp;quot;kontoname\@account.de&amp;amp;quot;;&lt;br /&gt;
 my $passwrd = &amp;amp;quot;passwrd&amp;amp;quot;;&lt;br /&gt;
 my $provider = &amp;amp;quot;smtp.provider.de&amp;amp;quot;;&lt;br /&gt;
 Log 1, &amp;amp;quot;sendEmail RCP: $rcpt&amp;amp;quot;;&lt;br /&gt;
 Log 1, &amp;amp;quot;sendEmail Subject: $subject&amp;amp;quot;;&lt;br /&gt;
 Log 1, &amp;amp;quot;sendEmail Text: $text&amp;amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 $ret .= qx(sendEmail -f &#039;$sender&#039; -t &#039;$rcpt&#039; -u &#039;$subject&#039; -m &#039;$text&#039; -s &#039;$provider&#039; -xu &#039;$konto&#039; -xp &#039;$passwrd&#039; -o tls=no);&lt;br /&gt;
 $ret =~ s,[\r\n]*,,g;    # remove CR from return-string &lt;br /&gt;
 Log 1, &amp;amp;quot;sendEmail returned: $ret&amp;amp;quot;; &lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um die TLS Verschlüsselung (ehem. SSL) zu nutzen, muss in der 4. letzten Zeile tls=auto verwendet werden. Sollte anschließend keine Mail verschickt werden, siehe Probleme.&lt;br /&gt;
&lt;br /&gt;
Beim Aufruf der Funktion gibt es zwei unterschiedliche Verhaltensweisen zu beachten. Wird DebianMail durch ein Fhem-Ereignis als Makro mit &amp;quot;Transferzeichen&amp;quot;, wie @ oder&amp;amp;#160;% aufgerufen, so sind diese innerhalb des Aufrufs von DebianMail zu maskieren.&lt;br /&gt;
&lt;br /&gt;
Siehe auch commandref:&lt;br /&gt;
* The character @ will be replaced with the device name. To use @ in the text itself, use the double mode (@@).&lt;br /&gt;
* The macro&amp;amp;#160;%&amp;amp;lt;parameter&amp;amp;gt; will expand to the current value of the named parameter. This can be either a parameter from the device definition or a parameter from the set or get command.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define Sonstiges notify Fenster:Window:.*,.*Low.Batt*. {\&lt;br /&gt;
 DebianMail(&#039;email@@email.domain&#039;,&#039;Subject&#039;,&#039;Text&#039;);;\&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in allen anderen Fällen muss die Maskierung entfallen:&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define Sonstiges at *01:00:00 {\&lt;br /&gt;
 DebianMail(&#039;email@email.domain&#039;,&#039;Subject&#039;,&#039;Text&#039;);;\&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== BeagleBoard-xM ===&lt;br /&gt;
Auf einem [[:Kategorie:BeagleBoard-xM|BeagleBoard-xM]] mit einem [http://en.opensuse.org/HCL:BeagleBoard-xM OpenSUSE 12.2] kann man ebenfalls das Perl-Programm &#039;&#039;sendEmail&#039;&#039; wie beim RPi nutzen. Dies gibt es aber nicht in den Repositories von openSUSE, sondern man muss sich &#039;&#039;sendEmail&#039;&#039; als Source herunterladen. Das geht am einfachsten per &#039;&#039;wget&#039;&#039;, welches man ebenfalls erst installieren muss (aber aus einem Repository).&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;$ zypper in wget&lt;br /&gt;
$ cd /opt&lt;br /&gt;
$ wget http://caspian.dotconf.net/menu/Software/SendEmail/sendEmail-v1.56.tar.gz&lt;br /&gt;
$ tar xvfz sendEmail-v1.56.tar.gz&lt;br /&gt;
$ cd sendEmail-v1.56&lt;br /&gt;
$ cp sendMail /usr/local/bin&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Dann geht man weiter vor wie unter RPi beschrieben (anlegen der SUB-Routine in 99_myUtils usw.).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Version 1.56 von &#039;&#039;sendEmail&#039;&#039; ist Stand Januar 2013 die aktuelle. Da diese Programmversion von 2009 stammt, ist mit neuen Versionen selten zu rechnen. Vielleicht schauen Sie trotzdem vorher auf der [http://caspian.dotconf.net/menu/Software/SendEmail/ Homepage von sendEmail] nach.&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
# Kopiere die Datei sendEmail.exe* in Dein FHEM Verzeichnis (hier c:\fhem-5.0\); Quelle: [http://caspian.dotconf.net/menu/Software/SendEmail/ http://caspian.dotconf.net/menu/Software/SendEmail/]&lt;br /&gt;
# Erstelle im FHEM Verzeichnis die Datei wmail.bat mit folgendem Inhalt (eine Zeile): &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;sendEmail -f absender@domain.de -u &amp;quot;%1&amp;quot; -m &amp;quot; &amp;quot; -s SMTP-SERVERAdresse -xu SMTP_USERNAME -xp SMTP_PASSWORT -t empfänger@domain.de -o message-header=&amp;quot;X-Message-Flag: FHEM&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
# Beispiel fhem.cfg&lt;br /&gt;
## Mail wenn sich der Status von Heizung.* oder Hzg.* ändert &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;define Mail_Heizung notify Heizung.*|Hzg.* { system(&amp;quot;wmail @:%&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
## Mail bei Signal Aussentemperatur (für dieses Beispiel wird [http://fhem.de/commandref.html#getstate http://fhem.de/commandref.html#getstate getstate] benötigt) &amp;lt;br&amp;gt;&amp;lt;code&amp;gt;define Mail_Aussentemperatur notify Aussentemperatur {\&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;my ($val);;\&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;$val = fhem &amp;quot;getstate @&amp;quot;;;\&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;system(&amp;quot;wmail \&amp;quot;@: $val\&amp;quot;&amp;quot;);;\&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Probleme ==&lt;br /&gt;
=== sendEmail ===&lt;br /&gt;
Falls man keine E-Mails verschicken kann, kann man in einem ersten Test prüfen, ob sendEmail als solches funktioniert und die Konfiguration (Benutzer, Passwort, Server-Name usw.) des Mail-Kontos, über das die Mails abgesetzt werden sollen, richtig ist.&lt;br /&gt;
&lt;br /&gt;
Hierzu setzt man in der FHEM-Befehlszeile die folgende Anweisung ab:&lt;br /&gt;
:&amp;lt;code&amp;gt;{ SUB-Routinen-Name(&#039;EMailAdresse@Mail.Domain&#039;,&#039;Test&#039;,&#039;Test-Text&#039;);; }&amp;lt;/code&amp;gt;&lt;br /&gt;
und ersetzt &#039;&#039;SUB-Routinen-Name&#039;&#039; durch den Namen der in 99_myUtils erzeugten Prozedur. Statt &#039;&#039;EMailAdresse@Mail.Domain&#039;&#039; trägt man noch eine gültige E-Mail-Adresse ein und bestätigt den Befehl dann mittels &amp;amp;lt;Enter&amp;amp;gt; (nicht &amp;quot;save&amp;quot;). Empfangen Sie nicht kurzfristig eine entsprechende E-Mail, ist sehr wahrscheinlich an den Zugangsdaten etwas verkehrt. &lt;br /&gt;
&lt;br /&gt;
Vor dem testen der Routine oben kann sendEmail auch über die Konsole (z.&amp;amp;nbsp;B. via Putty) getestet werden:&lt;br /&gt;
:&amp;lt;code&amp;gt;sendEmail -f &#039;fhemsystem@meinedomain.tld&#039; -t &#039;ich@meinedomain.tld&#039; -u &#039;subject&#039; -m &#039;body&#039; -s &#039;meinmailserver.meinedomain.de&#039; -xu &#039;fhemmailer&#039; -xp &#039;geheimespassword&#039; -o tls=no&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Keine Mail mit TLS Verschlüsselung ===&lt;br /&gt;
Den Test über die Konsole durchführen. Erhält man folgende Fehlermeldung:&lt;br /&gt;
&#039;&#039;invalid SSL_version specified at /usr/share/perl5/IO/Socket/SSL.pm line 332&#039;&#039;&lt;br /&gt;
muss auf dem Raspberry folgende Datei angepasst werden: &#039;&#039;/usr/share/perl5/IO/Socket/SSL.pm&#039;&#039;.&lt;br /&gt;
In Zeile 1490 muss das &#039;&#039;&#039;$&#039;&#039;&#039; am Ende entfernt werden: m{^(!?)(?:(SSL(?:v2|v3|v23|v2/3))|(TLSv1[12]?))&#039;&#039;&#039;$&#039;&#039;&#039;}i&lt;br /&gt;
&lt;br /&gt;
== Email laut Log gesendet aber nicht angekommen? ==&lt;br /&gt;
Dann bitte in der Fritzbox Oberfläche überpüfen, ob unter &amp;quot;System&amp;quot; -&amp;gt; &amp;quot;Push Service&amp;quot; selbiger eingerichtet und aktiviert wurde. &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:FritzBox]]&lt;br /&gt;
[[Kategorie:BeagleBoard-xM]]&lt;br /&gt;
[[Kategorie:Raspberry Pi]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Anwesenheitserkennung_-_Remote_Fritzbox&amp;diff=4482</id>
		<title>Anwesenheitserkennung - Remote Fritzbox</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Anwesenheitserkennung_-_Remote_Fritzbox&amp;diff=4482"/>
		<updated>2014-01-20T16:51:37Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: Ergänzung zweite FB als Repeater&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In Erweiterung des Beitrages [[Anwesenheitserkennung|Anwesenheitserkennung]] wird eine Beispiel-Lösung für folgendes Szenario vorgestellt:&lt;br /&gt;
&lt;br /&gt;
* Eine (nicht modifizierte) Fritzbox wird als WLAN Access Point und Router genutzt, jedoch läuft auf dieser Box kein FHEM oder Perl.&lt;br /&gt;
* Ein Linux Rechner (in diesem Beispiel ein RPI) wird als FHEM host verwendet.&lt;br /&gt;
* Device Erkennung mittels PRESENCE - ident mit PRESENCE fritzbox&lt;br /&gt;
&lt;br /&gt;
Die Lösung basiert auf dem PRESENCE Modul und nutzt die Funktion &#039;&#039;&#039;PRESENCE function { }&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Auch bei einem Repeater-Einsatz im WLan (zweite Fritzbox) kann diese Lösung eingesetzt werden - es ist nur eine Installation auf der Haupt-Fritzbox notwendig, nicht auf dem Repeater.&lt;br /&gt;
&lt;br /&gt;
== Background / Motivation ==&lt;br /&gt;
Ich hatte während der letzten 12 Monate ein modifiziertes PRESENCE Modul im Einsatz, das jedoch immer wieder ein Hängen oder Reboots der Fritzbox verursacht hatte (speziell bei 7270), daher hatte ich es nicht veröffentlicht. Die Vermutung liegt nahe, dass das ständige Telnet ein/aus-loggen die Hänger/Reboots verursacht hat.&lt;br /&gt;
&lt;br /&gt;
Diese Lösung basiert (wie auch die &#039;&#039;&#039;PRESENCE fritzbox&#039;&#039;&#039; Funktion) auf dem Fritzbox Befehl &#039;&#039;ctlmgr_ctl&#039;&#039;, der jedoch von der &amp;quot;Ferne&amp;quot; ausgelöst werden muß, da FHEM ja nicht auf der Fritzbox läuft. Weiters wurden Ideen/Konzepte des presenced/collectord verwendet.&lt;br /&gt;
&lt;br /&gt;
Die Lösung läuft bei mir seit Anfang Dez. 2013 stabil mit 12 abgefragten Devices / 120 Sekunden Intervall. (Env: FHEM auf RPI, Fritzbox 7390)&lt;br /&gt;
&lt;br /&gt;
== Konzept ==&lt;br /&gt;
&lt;br /&gt;
* Auf der Fritzbox wird ein &#039;&#039;&#039;shellscript&#039;&#039;&#039; installiert, dass von remote gestartet wird,  Kommandos lokal ausführt und das Ergebniss zurückschickt.&lt;br /&gt;
* Am FHEM host läuft ein &#039;&#039;&#039;perl basierender daemon&#039;&#039;&#039; der Kommandos von FHEM empfängt, aufbereitet und das shellscript auf der Fritzbox (mit parameter) startet. Dieser Daemon hält auch die Telnet Verbindung zur Fritzbox permanent aufrecht. Gestartet wird dieser Daemon automatisch beim ersten Aufruf durch FHEM.  &lt;br /&gt;
* ein Modul &#039;&#039;&#039;99_RFritzBox.pm&#039;&#039;&#039; ist die Schnittstelle zwischen FHEM und dem daemon.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Installation / Debug ==&lt;br /&gt;
Der code ist als zip-file im thread [http://forum.fhem.de/index.php/topic,17957.0.html PRESENCE-RemoteFritzbox] abgelegt. Bitte in diesem thread auch Fragen/Feedback/Wünsche posten.&lt;br /&gt;
&lt;br /&gt;
=== Voraussetzungen: ===&lt;br /&gt;
* Telnet auf der Fritzbox aktiviert &lt;br /&gt;
* perl NET::Telnet Modul auf dem Host wo FHEM läuft installiert. Beim Raspberry-PI geht das so:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install libnet-telnet-perl&amp;lt;/pre&amp;gt;&lt;br /&gt;
Folgende Reihenfolge ist empfehlenswert:&lt;br /&gt;
=== kopieren von  Rpresence.sh in die Fritzbox === &lt;br /&gt;
z.B. mittels FTP in folgendes Verzeichnis:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/var/media/ftp/FRITZ/bin # Der Verzeichnispfad muß angepaßt werden! In diesem Beispiel ist das eine FB7390 im Internen Speicher.&lt;br /&gt;
chmod +x Rpresence.sh # shell script ausführbar machen.&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ein erster Test von der Telnet Konsole der Fritzbox:&lt;br /&gt;
&amp;lt;pre&amp;gt;./Rpresence.sh &amp;lt;FBdevicename&amp;gt;&amp;lt;/pre&amp;gt; sollte folgendes Ergebnis liefern: &amp;lt;pre&amp;gt;RFritzBox: &amp;lt;FBdevicename&amp;gt; y z&amp;lt;/pre&amp;gt; wobei für &amp;lt;FBdevicename&amp;gt; der Name eines Gerätes, so wie in der Fritzbox Weboberfläche definert einzusetzen ist. y ist die Fritzbox interne Devicenummer dieses Gerätes (es sollte jedenfalls nicht 999 hier stehen, in diesem Fall hat die FB den Namen nicht gefunden. z ist der Status (0==abwesend/1==anwesend).&lt;br /&gt;
Falls bis hierher alles geklappt hat, ist die Einrichtung auf der Fritzbox fertig.&lt;br /&gt;
&lt;br /&gt;
=== installation / konfig / test Daemon am FHEM host === &lt;br /&gt;
kopieren von RFritzBoxScan.pl ins FHEM Verzeichnis (dort wo alle Module 00_xxx.pm - 99_yyy.pm sind)&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo chmod +x RFritzBoxScan.pl # ausführbar machen&lt;br /&gt;
sudo chown fhem:root RFritzBoxScan.pl #for user fhem &amp;lt;/pre&amp;gt;&lt;br /&gt;
Erstellen eines config- files für den daemon:&lt;br /&gt;
im root FHEM-Verzeichnis ( dort wo üblicherweise auch die fhem.pl zu finden ist )&lt;br /&gt;
ein file: &#039;&#039;&#039;credentials.cfg&#039;&#039;&#039; mit folgendem Inhalt erstellen (Adressen/User/Passwort/pfad anpassen):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# PRESENCE credentials (only required for function RemoteFritzBox)&lt;br /&gt;
$credentials{RemoteFritzBox}{ipadress} = &amp;quot;192.168.1.254&amp;quot;; # FB LAN Adress&lt;br /&gt;
$credentials{RemoteFritzBox}{username} = &amp;quot;FritzBoxusername&amp;quot;;&lt;br /&gt;
$credentials{RemoteFritzBox}{password} = &amp;quot;FritzboxPasswort&amp;quot;;&lt;br /&gt;
$credentials{RemoteFritzBox}{shellcmd} = &amp;quot;/var/media/ftp/FRITZ/bin/Rpresence.sh&amp;quot;; # pfad anpassen!&lt;br /&gt;
$credentials{RemoteFritzBox}{serverhost} = &amp;quot;localhost&amp;quot;;  #  RFritzBoxScan.pl provides this service&lt;br /&gt;
$credentials{RemoteFritzBox}{serverport} = 7777;&lt;br /&gt;
$credentials{RemoteFritzBox}{serverbin} = &amp;quot;RFritzBoxScan.pl&amp;quot;; # Fritzbox daemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Das Format dieser cfg-file entspricht dem im Modul Webcam. &lt;br /&gt;
Ein erster Test:&lt;br /&gt;
&amp;lt;pre&amp;gt;./RFritzBoxScan.pl &amp;lt;fullpath and name&amp;gt; # of credentials.cfg  eg: /opt/fhem/credentials.cfg&amp;lt;/pre&amp;gt; &lt;br /&gt;
Damit wir der Daemon von Hand gestartet und alle debug-Meldungen kommen auf diese Konsole.&lt;br /&gt;
Beim Start sollte der Output so aussehen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
RFritzBoxScan: server waiting for client connection on port 7777&lt;br /&gt;
RFritzBoxScan: Fritzbox login ok&lt;br /&gt;
### die folgenden Zeilen kommen erst ab dem nächsten Schritt !&lt;br /&gt;
### und zwar jedesmal wenn ein request von FHEM an den daemon kommt...&lt;br /&gt;
RFritzBoxScan: connection from 127.0.0.1:57595&lt;br /&gt;
RFritzBoxScan: ..from FHEM received data: Nokia-N810&lt;br /&gt;
RFritzBoxScan: ..sending to Fritzbox: Nokia-N810 17&lt;br /&gt;
RFritzBoxScan: ..cmdresult: RFritzBox: Nokia-N810 17 1&lt;br /&gt;
RFritzBoxScan: ..result to fhem: 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== installation und konfiguration FHEM-Module ===&lt;br /&gt;
kopieren von 99_RFritzBox.pm ins FHEM Verzeichnis&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo chown fhem:root 99_RFritzBox.pm # for user fhem&amp;lt;/pre&amp;gt;&lt;br /&gt;
Im FHEM command-feld: &amp;lt;pre&amp;gt;reload 99_RFritzBox.pm&amp;lt;/pre&amp;gt; eintippen (oder FHEM neu starten)&lt;br /&gt;
Die FHEM-PRESENCE Definition:&lt;br /&gt;
&amp;lt;pre&amp;gt;define &amp;lt;myName&amp;gt; PRESENCE function {RemoteFritzBox(&amp;quot;&amp;lt;FBdevicename&amp;gt;&amp;quot;)} 120 120&amp;lt;/pre&amp;gt;&lt;br /&gt;
damit wird in 120 sec Abständen der Status abgefragt.&lt;br /&gt;
im Telnet Fenster sollten jetzt die requests / response - Meldungen kommen.&lt;br /&gt;
&lt;br /&gt;
Zum Abschluß:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;Strg-C&amp;gt;&amp;lt;/pre&amp;gt; im telnet Fenster eingeben, der Daemon wird dadurch gestoppt. Auf den nächsten Aufruf durch FHEM warten, der Daemon wird automatisch (im Hintergrund) gestartet. Überprüfen durch Eingabe von &amp;lt;pre&amp;gt;ps -e | grep RFritzBoxScan&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Debug Tip ==&lt;br /&gt;
Log Meldungen vom Daemon bekommt man im FHEM Log durch anlegen eines dummy devices mit dem Namen &#039;&#039;&#039;RemoteFritzBox&#039;&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define RemoteFritzBox dummy&lt;br /&gt;
attr RemoteFritzBox verbose 5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Den Daemon beenden, falls er im Hintergrund läuft:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo killall RFritzBoxScan.pl&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
have fun&lt;br /&gt;
erwin&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;br /&gt;
[[Kategorie:Glossary]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-CC-TC_Funk-Wandthermostat&amp;diff=2938</id>
		<title>HM-CC-TC Funk-Wandthermostat</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-CC-TC_Funk-Wandthermostat&amp;diff=2938"/>
		<updated>2013-09-20T12:45:48Z</updated>

		<summary type="html">&lt;p&gt;Caldir65: /* Temperaturlisten */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;HM-CC-TC Funk-Wandthermostat&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;&#039;Achtung: Dieses Gerät ist abgekündigt (wird nicht mehr hergestellt). Nachfolgeprodukt ist der [[HM-CC-RT-DN]].&#039;&#039;&#039;&lt;br /&gt;
Programmierbarer Raumthermostat, der bis zu 4 [[HM-CC-VD Funk-Stellantrieb]] steuern kann.&lt;br /&gt;
= Features =&lt;br /&gt;
* Am Raumthermostat programmierbare Tages- und Nachttemperatur.&lt;br /&gt;
* Pro Wochentag können bis zu 24 Schaltpunkte definiert werden.&lt;br /&gt;
* Anbindung von &amp;lt;ins&amp;gt;jeweils&amp;lt;/ins&amp;gt; &#039;&#039;&#039;maximal&#039;&#039;&#039; 4 Tür- bzw. Fensterkontakten ([[HM-Sec-RHS]]) zur Absenkung der Temperatur auf einen eigens eingestellten Temperaturwert (ab Werk: 12°C) bei offenem Fenster bzw. offener Tür.&lt;br /&gt;
* Anzeige der Temperatur und Luftfeuchtigkeit im Raum und Hintergrundbeleuchtung des Displays.&lt;br /&gt;
&lt;br /&gt;
Alle 120 bis 184 Sekunden überträgt der Wandthermostat vorhandene Befehle zu den Stellantrieben. Jeder empfangene Befehl wird vom Stellantrieb bestätigt und dann ausgeführt. Täglich gegen Mitternacht synchronisiert ein HM-CC-TC seine Uhrzeit mit der HomeMatic-Zentrale (CCU, HMLAN).&lt;br /&gt;
&lt;br /&gt;
= Hinweise zum Betrieb mit FHEM =&lt;br /&gt;
Vor dem Einsatz mit einer Zentrale sind erst alle Stellantriebe und Tür-/Fensterkontakte mit dem HM-CC-TC zu verbinden (P&#039;&#039;&#039;ee&#039;&#039;&#039;r).&lt;br /&gt;
Damit das ganze dann in FHEM auftaucht, muss der TC noch mit dem [[HMLAN Konfigurator]] gep&#039;&#039;&#039;ai&#039;&#039;&#039;rt werden.&lt;br /&gt;
&lt;br /&gt;
Mit &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;set CUL hmPairForSec 300&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
setzt man das CUL / den HMLAN-Konfigurator für 5 Minuten in den Anlernmodus. Danach am Thermostaten 5 Sekunden lang die OK-Taste drücken und es wird eine Zeit von 20 auf 0 Sekunden gezählt:&lt;br /&gt;
&lt;br /&gt;
* Klappt das Anlernen in diesen 20 Sekunden, wird der Countdown sofort beendet, anschließend für ca. 2-3 Sekunden &amp;quot;OK&amp;quot; angezeigt und der Thermostat ist in FHEM eingebunden.&lt;br /&gt;
* Gelingt das Anlernen nicht in den 20 Sekunden, erscheint nach Erreichen der &amp;quot;0&amp;quot; noch für 2 bis 3 Sekunden ein &amp;quot;NOK&amp;quot; (&#039;&#039;&#039;N&#039;&#039;&#039;ot &#039;&#039;&#039;OK&#039;&#039;&#039;) im Display des TCs.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Alternativ&#039;&#039;&#039;(und so vom Entwickler des Fhem-HomeMatic-Moduls empfohlen) kann wie folgt vorgegangen werden:&lt;br /&gt;
&lt;br /&gt;
* Alle Stellantriebe und Tür-/Fensterkontakte sowie den HM-CC-TC mit Fhem p&#039;&#039;&#039;ai&#039;&#039;&#039;ren (also &#039;&#039;set CUL hmPairForSec 300&#039;&#039; und an allen Devices den Anlernknopf drücken innerhalb des Zeitfensters von 300 Sekunden).&lt;br /&gt;
* Die Stellantriebe und Tür-/Fensterkontakte mit den &#039;&#039;Channels&#039;&#039; (siehe unten) p&#039;&#039;&#039;ee&#039;&#039;&#039;ren (siehe &amp;lt;nowiki&amp;gt;[http://fhem.de/commandref.html#CUL_HMpeerChan commandref :peerChan]&amp;lt;/nowiki&amp;gt;). Hierzu werden die entsprechenden Fhem-Befehle über das Webinterface von Fhem erteilt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039;&lt;br /&gt;
* Alle in der FHEM-Eingabezeile eingegebenen &#039;&#039;attr&#039;&#039;-, &#039;&#039;define&#039;&#039;-Befehle usw. müssen zum Schluss noch per Klick auf den &amp;quot;Save&amp;quot;-Button dauerhaft in der &#039;&#039;fhem.cfg&#039;&#039; gespeichert werden, sonst sind sie nach z.B. einem Systemabsturz verloren.&lt;br /&gt;
* Falls in der FHEM-Weboberfläche für ihren HM-CC-TC etwas wie &#039;&#039;X CMDs pending&#039;&#039; steht, sollten Sie ihren HM-CC-TC zur Hand nehmen und für 20 Sekunden auf die OK-Taste drücken. Dadurch werden alle noch ausstehenden Befehle eingelesen.&lt;br /&gt;
== Auszug aus der fhem.cfg ==&lt;br /&gt;
Die nachfolgenden Einstellungen zum HM-CC-TC werden von FHEM &amp;lt;ins&amp;gt;weitestgehend&amp;lt;/ins&amp;gt; automatisch gesetzt. Die Pfadangaben für die Log-Dateien sind system-, die Raumbenennungen benutzerabhängig. Zu &#039;&#039;autoReadReg&#039;&#039;und &#039;&#039;expert&#039;&#039;siehe unten. Neben dem eigentlichen Basis-Gerät (HM-CC-TC) werden in FHEM automatisch noch 3 weitere &amp;quot;Unter&amp;quot;-Geräte (Channels/Kanäle), nämlich &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;_Weather&#039;&#039;&lt;br /&gt;
* &#039;&#039;_Climate&#039;&#039;&lt;br /&gt;
* &#039;&#039;_WindowRec&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
definiert (durch das Anlernen des TC an FHEM; siehe unten), deren Benennung sich (jeweils mit einem vorangestellten Unterstrich &amp;quot;_&amp;quot;) am Namen des Basis-Gerätes orientiert. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Anmerkung:&#039;&#039;&#039;Die in den unten gezeigten &#039;&#039;fhem.cfg&#039;&#039;-Auszügen markierten &amp;lt;ins&amp;gt;Peer&amp;lt;/ins&amp;gt;-Einträge tauchen erst auf, sobald man die Daten aus dem TC mit &#039;&#039;set HM-CC-TC-Basisname getConfig&#039;&#039;bzw. &#039;&#039;autoReadReg&#039;&#039;ausgelesen hat.&lt;br /&gt;
&lt;br /&gt;
=== Hauptgerät ===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung CUL_HM 1DA491&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung actCycle 000:10&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung actStatus alive&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung autoReadReg 1&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung devInfo 00FFFF&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung expert 2_full&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung firmware 2.1&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung hmClass receiver&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung model HM-CC-TC&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung room &amp;amp;lt;IhrRaum&amp;amp;gt;&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung serialNr JE********&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung subType thermostat&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
=== Channel (Kanal) 01 _Weather ===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Weather CUL_HM 1DA49101               &amp;amp;lt;&amp;amp;lt;&amp;amp;lt;=== 01 = Kanal 1&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Weather model HM-CC-TC&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Weather peerIDs &lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Weather room &amp;amp;lt;IhrRaum&amp;amp;gt;&lt;br /&gt;
define FileLog_&amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Weather FileLog /opt/fhem/log/&amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Weather-%Y-%m.log &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Weather&lt;br /&gt;
attr FileLog_&amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Weather logtype text&lt;br /&gt;
attr FileLog_&amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Weather room CUL_HM,&amp;amp;lt;IhrRaum&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
=== Channel (Kanal) 02 _Climate ===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Climate CUL_HM 1DA49102               &amp;amp;lt;&amp;amp;lt;&amp;amp;lt;=== 02 = Kanal 2&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Climate model HM-CC-TC&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Climate peerIDs 1AD52B01,1B7A4C01,1C4CD101,1C48EC01,  &amp;amp;lt;&amp;amp;lt;&amp;amp;lt;=== gepeerte HM-CC-VDs&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Climate room &amp;amp;lt;IhrRaum&amp;amp;gt;&lt;br /&gt;
define FileLog_&amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Climate FileLog /opt/fhem/log/&amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Climate-%Y-%m.log &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Climate&lt;br /&gt;
attr FileLog_&amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Climate logtype text&lt;br /&gt;
attr FileLog_&amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_Climate room CUL_HM,&amp;amp;lt;IhrRaum&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
=== Channel (Kanal) 03 _WindowRec ===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_WindowRec CUL_HM 1DA49103              &amp;amp;lt;&amp;amp;lt;&amp;amp;lt;=== 03 = Kanal 3&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_WindowRec model HM-CC-TC&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_WindowRec peerIDs 1CFBB001,              &amp;amp;lt;&amp;amp;lt;&amp;amp;lt;=== gepeerte HM-Sec-SCs&lt;br /&gt;
attr &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_WindowRec room &amp;amp;lt;IhrRaum&amp;amp;gt;&lt;br /&gt;
define FileLog_&amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_WindowRec FileLog /opt/fhem/log/&amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_WindowRec-%Y-%m.log &amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_WindowRec&lt;br /&gt;
attr FileLog_&amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_WindowRec logtype text&lt;br /&gt;
attr FileLog_&amp;amp;lt;HM-CC-TC&amp;amp;gt;.Heizung_WindowRec room CUL_HM,&amp;amp;lt;IhrRaum&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
== Einstellungen eines HM-CC-TC lesen, anzeigen und sichern ==&lt;br /&gt;
=== expert ===&lt;br /&gt;
Anfang Februar 2013 wurde eine Änderung bei der Anzeige der so genannten &#039;&#039;Readings&#039;&#039;(Register usw.), also der Einstellungen bzw. Eigenschaften eines HM-Devices, eingeführt. &#039;&#039;&#039;Alle&#039;&#039;&#039;Werte sieht man nur noch, wenn man am HM-CC-TC das Attribut &#039;&#039;expert&#039;&#039;auf &#039;&#039;2_all&#039;&#039;setzt. Per &#039;&#039;&#039;default&#039;&#039;&#039;(nicht in &#039;&#039;fhem.cfg&#039;&#039;gesetzt) steht dieser Wert auf &#039;&#039;0_off&#039;&#039;(nur die notwendigsten Readings/Eigenschaften werden angezeigt). Mittelweg ist der Wert &#039;&#039;1_on&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Mittels&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;attr &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt; expert 2_full&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
in der FHEM-Befehlszeile mit anschließendem &amp;amp;lt;Enter&amp;amp;gt; setzt man diesen Level.&lt;br /&gt;
&lt;br /&gt;
Falls man mit &#039;&#039;&#039;Temperaturlisten&#039;&#039;&#039;arbeitet (siehe unten), dann kann man die komplette Liste im &amp;quot;Channel&amp;quot; (Kanal) &#039;&#039;&amp;amp;lt;HM-CC-TC-Name&amp;amp;gt;__Climate&#039;&#039;einsehen. Auch für diesen Kanal ist evtl. ein setzen des Attributes &#039;&#039;expert 2_full&#039;&#039;angeraten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ins&amp;gt;Anmerkung:&amp;lt;/ins&amp;gt; Es gibt auch noch sogenannte &amp;quot;hidden datas&amp;quot; (versteckte interne Werte, Register oder Eigenschaften deren Namen mit einem &amp;quot;.&amp;quot; beginnen). Diese sieht man nur dann, wenn auch das Attribut &#039;&#039;showInternalValues 1&#039;&#039;gesetzt ist (default: 0 bzw. nicht gesetzt).&lt;br /&gt;
&lt;br /&gt;
=== autoReadReg ===&lt;br /&gt;
Mitte Januar 2013 wurde das neue Attribut &#039;&#039;autoReadReg&#039;&#039;eingeführt, welches auf &#039;&#039;0&#039;&#039;voreingestellt ist (kein Eintrag in der &#039;&#039;fhem.cfg&#039;&#039;). Das setzen dieses Attributes auf &#039;&#039;1&#039;&#039;bewirkt, dass &amp;lt;ins&amp;gt;beim Neustart von FHEM&amp;lt;/ins&amp;gt; die Einstellungen des entsprechenden HM-Gerätes ausgelesen werden. Dies wird bei mehreren &#039;&#039;autoReadReg&#039;&#039;s automatisch zeitversetzt vorgenommen, um die Funk-Kommunikation nicht unnötig zu belasten.&lt;br /&gt;
&lt;br /&gt;
Mittels&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;attr &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt; autoReadReg 1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
in der FHEM-Befehlszeile mit anschließendem &amp;amp;lt;Enter&amp;amp;gt; setzt man diesen Wert.&lt;br /&gt;
&lt;br /&gt;
=== list ===&lt;br /&gt;
Um sich alle Eigenschaften/Readings eines Gerätes anzusehen, gibt es den Befehl &#039;&#039;list&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Mittels&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;list &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
und Bestätigung mit &amp;amp;lt;Enter&amp;amp;gt; erhalten Sie die gewünschte Anzeige Ihres TCs &amp;lt;ins&amp;gt;incl.&amp;lt;/ins&amp;gt; seiner 3 Channels. Über&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;list &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt;_&amp;amp;lt;Channel-Name&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
werden nur die Daten des angegebenen Channels angezeigt.&lt;br /&gt;
&lt;br /&gt;
=== Einstellungen sichern ===&lt;br /&gt;
Die Durchführung von &#039;&#039;autoReadReg&#039;&#039;kann durchaus mehrere Minuten dauern. Anschließend besteht die Möglichkeit, diese per&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;get HM-CC-TC-Basisname saveConfig [/Verzeichnis/mit/Schreibrechten/]&amp;amp;lt;Dateiname&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
für jedes HM-CC-TC getrennt zu sichern (für eine später notwendige Wiederherstellung). Die Sicherungsdatei wird regulär im &#039;&#039;modpath&#039;&#039;(siehe &#039;&#039;fhem.cfg&#039;&#039;) abgelegt. Falls dies nicht zum Erfolg führt (es wird - ohne Fehlermeldungen bei regulärem &#039;&#039;verbose&#039;&#039;und &#039;&#039;loglevel&#039;&#039;- im &#039;&#039;modpath&#039;&#039;keine Datei angelegt), müssen Sie vor dem Dateinamen einen vollständigen Pfad mit Schreibrechten für den Benutzer, unter dem FHEM läuft, angeben.&lt;br /&gt;
&lt;br /&gt;
In der &amp;lt;ins&amp;gt;Log-Datei&amp;lt;/ins&amp;gt; von FHEM erscheinen danach Meldungen folgender Art&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;amp;lt;Datum&amp;amp;gt;_&amp;amp;lt;Zeit&amp;amp;gt; 2: CUL_HM set &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt; statusRequest rxt:12&lt;br /&gt;
&amp;amp;lt;Datum&amp;amp;gt;_&amp;amp;lt;Zeit&amp;amp;gt; 2: CUL_HM set &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt; getConfig rxt:12&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Hierbei kann es (im &amp;lt;ins&amp;gt;Event monitor&amp;lt;/ins&amp;gt; von FHEM) zu folgenden Fehlermeldungen kommen&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;amp;lt;Datum&amp;amp;gt;_&amp;amp;lt;Zeit&amp;amp;gt; CUL_HM &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt; RESPONSE TIMEOUT:RegisterRead&lt;br /&gt;
&amp;amp;lt;Datum&amp;amp;gt;_&amp;amp;lt;Zeit&amp;amp;gt; CUL_HM &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt; RESPONSE TIMEOUT:PeerList&lt;br /&gt;
&amp;amp;lt;Datum&amp;amp;gt;_&amp;amp;lt;Zeit&amp;amp;gt; CUL_HM &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt; RESPONSE TIMEOUT:StatusReq&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Diese Meldungen können auch mehrfach pro Gerät auftreten. Dann hat das Auslesen der Einstellungen nicht geklappt und sollte nochmals durchgeführt werden. Dafür muss man FHEM aber nicht neu starten, sondern das HM-Device per &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;set &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt; getConfig&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
in der Befehlszeile von FHEM und anschließendem &amp;amp;lt;Enter&amp;amp;gt; (nicht &amp;quot;save&amp;quot;) darauf einstellen.&lt;br /&gt;
&lt;br /&gt;
Die Channels (z.B. &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt;_Climate, _Weather, _WindowRec) eines HM-Gerätes brauchen nicht (können aber bei Bedarf) separat ausgelesen bzw. gesichert zu werden, da sie Bestandteil der Basisabfrage sind.&lt;br /&gt;
&lt;br /&gt;
== Funkprobleme auffangen ==&lt;br /&gt;
Der wohl am häufigsten an den HM-CC-TC gesendete Befehl ist &amp;quot;set desired-temp&amp;quot;, mit dem die Wunschtemperatur neu gesetzt wird.&lt;br /&gt;
Funktioniert dieser Befehl jedoch nicht zuverlässig, wird die Wohnung ggf. zu lange oder nicht rechtzeitig beheizt.&lt;br /&gt;
Der folgende Mechanismus soll die Sicherheit erhöhen, indem die Antworten des HM-CC-TC geprüft werden und ggf. das Funktelegramm erneut gesendet wird.&lt;br /&gt;
&lt;br /&gt;
Um den Sollwert zum erneuten Senden des Funktelegramms verfügbar zu haben, wird ein dummy definiert:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define HM_TC_Solltemperatur dummy&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Wann immer die Solltemperatur geändert wird, setzt man die neue desired-temp nicht nur auf dem HM-TC-CC (hier HM_TC genannt), sondern auch auf dem dummy. Der Befehl (z.B. in der [http://www.fhemwiki.de/wiki/Zuhause-Status Routine zum HomeStatus]) sieht dann so aus:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;set HM_TC desired-temp 21;set HM_TC_Solltemperatur 21&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Falls das ausgehende Funktelegramm verlorengeht, fehlt die Antwort &amp;quot;command accepted&amp;quot;. Dies kann mit einem watchdog aufgefangen werden, der dann den Befehl an den HM-CC-TC erneut sendet:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define w_HM_TC watchdog HM_TC:set_desired-temp.* 00:02:30 HM_TC_Climate:CommandAccepted:.yes { \&lt;br /&gt;
   Log 1, &amp;quot;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt; w_HM_TC desired temp - missing response.&amp;quot;;\&lt;br /&gt;
   fhem(&amp;quot;set HM_TC desired-temp &amp;quot;.Value(&amp;quot;HM_TC_Solltemperatur&amp;quot;));\&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Falls ein Fehler bei der Funkkommunikation auftritt, erhält man die Antwort &amp;quot;missing ACK&amp;quot; oder &amp;quot;NACK&amp;quot;. Auch in diesem Fall soll das Telegramm zum Ändern der Wunschtemperatur erneut an den HM-CC-TC gesendet werden:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define n_HM_TC_err notify HM_TC:(MISSING.ACK.*|.*NACK.*) {\&lt;br /&gt;
   Log 1, &amp;quot;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt; n_HM_TC desired temp - missing ack/nack.\n&amp;quot;;\&lt;br /&gt;
   fhem(&amp;quot;set HM_TC desired-temp &amp;quot;.Value(&amp;quot;HM_TC_Solltemperatur&amp;quot;));\&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Mit diesen beiden Helfern ist die Funkkommunikation zum HM-CC-TC sehr zuverlässig.&lt;br /&gt;
&lt;br /&gt;
== Plots / Grafiken ==&lt;br /&gt;
=== Problem ===&lt;br /&gt;
Durch &#039;&#039;autocreate&#039;&#039;wird zwar ein Log angelegt, aber kein Plot (Grafische Auswertung). Dem kann man aber abhelfen (siehe unten).&lt;br /&gt;
&lt;br /&gt;
=== Plots erzeugen ===&lt;br /&gt;
&#039;&#039;PGM2&#039;&#039;ist die Standardansicht des Fhem-Web-Interfaces. Um hier Plots/Grafiken zu erzeugen einfach unter dem &#039;&#039;Filelog&#039;&#039;des Thermostaten das &#039;&#039;attr logtype&#039;&#039;auf &#039;&#039;temp4hum6:Plot,text&#039;&#039;setzen und es wird ein Plot-Link neben dem Text-Link angezeigt. Nun können Sie auf diesen Plot-Link klicken und ...&lt;br /&gt;
&lt;br /&gt;
=== alternative Plots ===&lt;br /&gt;
Mit dem fht.gplot funktioniert die Anzeige der Ventilstellung (actuator) nicht.&lt;br /&gt;
&lt;br /&gt;
Mit folgendem angepassten .gplot File wird die gemessene Temperatur und Ventilstellung angezeigt. &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;############################ &lt;br /&gt;
 # Display the measured temp and the actuator. &lt;br /&gt;
 # Corresponding FileLog definition: &lt;br /&gt;
 # define &amp;amp;lt;filelogname&amp;amp;gt; FileLog /var/log/fhem/actuator_name-%Y.log &amp;amp;lt;actuator_name&amp;amp;gt;:(measured-temp|actuator).* &lt;br /&gt;
 &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;
 &lt;br /&gt;
 set y2label &amp;amp;quot;Temperatur in C&amp;amp;quot; &lt;br /&gt;
 set ylabel &amp;amp;quot;Ventil (%)&amp;amp;quot; &lt;br /&gt;
 &lt;br /&gt;
 #FileLog 4:measured:10: &lt;br /&gt;
 #FileLog 4:actuator:50: &lt;br /&gt;
 &lt;br /&gt;
 plot \ &lt;br /&gt;
  &amp;amp;quot;&amp;amp;lt; egrep &#039;temperature&#039; &amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot;\ &lt;br /&gt;
     using 1:4 axes x1y2 title &#039;Temperatur in C&#039; with lines,\ &lt;br /&gt;
  &amp;amp;quot;&amp;amp;lt; egrep &#039;actuator&#039; &amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot;\ &lt;br /&gt;
     using 1:4 axes x1y1 title &#039;Ventil (%)&#039; with lines\&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
=== Alles-drin-Plot ===&lt;br /&gt;
dazu nimmt man folgendes .gplot. Man/Fra beachte, dass hierfür alle Parameter nach der define-Anweisung in das Logfile geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;############################&lt;br /&gt;
# Display the measured temp and the actuator.&lt;br /&gt;
# Corresponding FileLog definition: &lt;br /&gt;
# define &amp;amp;lt;filelogname&amp;amp;gt; FileLog /var/log/fhem/HM_CC_TC-%Y.log &amp;amp;lt;HM_CC_TC-name&amp;amp;gt;&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;Temperature in C&amp;amp;quot;&lt;br /&gt;
set ylabel &amp;amp;quot;Actuator (%)&amp;amp;quot;&lt;br /&gt;
#FileLog 4:temperature:0:&lt;br /&gt;
#FileLog 4:desired:0:&lt;br /&gt;
#FileLog 4:humidity:0:&lt;br /&gt;
#FileLog 4:actuator:0:int&lt;br /&gt;
plot \&lt;br /&gt;
 &amp;amp;quot;&amp;amp;lt; awk &#039;/temperature/{print $1, $4}&#039; &amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot;\&lt;br /&gt;
   using 1:2 axes x1y2 title &#039;Measured temperature&#039; with lines lw 2,\&lt;br /&gt;
 &amp;amp;quot;&amp;amp;lt; awk &#039;/desired/{print $1, $4}&#039; &amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot;\&lt;br /&gt;
   using 1:2 axes x1y2 title &#039;Desired temperature&#039; with steps,\&lt;br /&gt;
 &amp;amp;quot;&amp;amp;lt; awk &#039;/humidity/ {print $1, $4+0}&#039; &amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot;\&lt;br /&gt;
   using 1:2 axes x1y1 title &#039;Humidity (%)&#039; with lines,\&lt;br /&gt;
 &amp;amp;quot;&amp;amp;lt; awk &#039;/actuator/ {print $1, $4+0}&#039; &amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot;\&lt;br /&gt;
   using 1:2 axes x1y1 title &#039;Actuator (%)&#039; with lines\&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
== Steuerungsmodi ==&lt;br /&gt;
Das Wandthermostat hat 4 verschiedene Steuerungsmöglichkeiten:&lt;br /&gt;
&lt;br /&gt;
* Auto (automatisch)&lt;br /&gt;
* Cent (Zentrale)&lt;br /&gt;
* Manu (manuell)&lt;br /&gt;
* Prog / Koffer-Symbol (Urlaubs/Party-Modus, wird hier nicht näher erörtert)&lt;br /&gt;
&lt;br /&gt;
Der Steuerungsmodus wird über wiederholtes Drücken der linken Taste des HM-CC-TC ausgewählt bzw. gewechselt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039;Durch das P&#039;&#039;&#039;ai&#039;&#039;&#039;ren des HM-CC-TC &amp;lt;ins&amp;gt;und&amp;lt;/ins&amp;gt; der Stellantrieb sowie Tür-/Fensterkontakte an Fhem verlieren Sie &#039;&#039;&#039;nicht&#039;&#039;&#039;die Steuerungsmöglichkeiten. Im Gegenteil: Nur wenn auch die VDs usw. an Fhem gep&#039;&#039;&#039;ai&#039;&#039;&#039;rt sind, haben Sie die Möglichkeit, auch diese zu überwachen. Die Steuerung &#039;&#039;&#039;können&#039;&#039;&#039;Sie dennoch allein dem HM-CC-TC überlassen.&lt;br /&gt;
&lt;br /&gt;
=== Auto-Modus ===&lt;br /&gt;
Im Modus &#039;&#039;&#039;Auto&#039;&#039;&#039;wird die Temperaturregelung über die im TC hinterlegten Temperaturlisten vorgenommen. Das Thermostat arbeitet also selbständig, somit unabhängig von einer Zentrale / FHEM. Nur in diesem Modus werden die evtl. per FHEM an das TC übermittelten &amp;quot;templist&amp;quot; abgearbeitet. Über das Senden von angepassten Temperatur-Listen kann eine indirekte Steuerung per FHEM erfolgen. &#039;&#039;&#039;Jederzeit&#039;&#039;&#039;kann zudem die Raumtemperatur über das Drehrad des Wandthermostaten oder die FHEM-Web-Oberfläche verändert werden. Diese &#039;&#039;Übersteuerung&#039;&#039;der Temperaturliste gilt bis zur nächsten Temperaturänderung nach der vorgenannten Liste.&lt;br /&gt;
&lt;br /&gt;
=== Cent-Modus ===&lt;br /&gt;
Im Modus &#039;&#039;&#039;Cent&#039;&#039;&#039;steuert eine HomeMatic-Zentrale (CCU) oder eben ein FHEM-Server mit z.B. [[HMLAN Konfigurator]] zu den in der FHEM-Config hinterlegten Zeiten und mit den dort festgelegten Temperaturen. Fällt also die HM-Zentrale aus, erfolgt keine Steuerung der Thermostaten bzw. Heizungsventile mehr.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ins&amp;gt;Anmerkung&amp;lt;/ins&amp;gt;: Der Modus &#039;&#039;cent&#039;&#039;erscheint nur dann im Display des HM-CC-TC, wenn er an eine Zentrale bzw. das [[CUL]] angelernt (gepairt) wurde.&lt;br /&gt;
&lt;br /&gt;
=== Manu-Modus ===&lt;br /&gt;
Der Modus &#039;&#039;&#039;Manu&#039;&#039;&#039;übersteuert die im TC hinterlegten Temperaturlisten und die evtl. von der HM-Zentrale / dem FHEM &amp;lt;ins&amp;gt;vor Umstellung auf &#039;&#039;Manu&#039;&#039;&amp;lt;/ins&amp;gt; gesendeten Einstellungen. Es wird also bis zur nächsten Modusumstellung bzw. manuellen Temperaturverstellung der per Einstellrad gesetzte Temperaturwert gefahren. &lt;br /&gt;
&lt;br /&gt;
Aber auch in diesem Modus kann man die &#039;&#039;desired-temperature&#039;&#039;per FHEM verstellen. Der dadurch eingestellte Wert gilt ab sofort als der neue im &#039;&#039;Manu-Modus&#039;&#039;zu haltende Wert.&lt;br /&gt;
&lt;br /&gt;
=== Auslesen des eingestellten Steuerungsmodus ===&lt;br /&gt;
Der eingestellte Steuerungsmodus erscheint normalerweise in den &#039;&#039;Readings&#039;&#039; des HM-CC-TC unter &#039;&#039;controlMode&#039;&#039;. Zusätzlich haben Sie die Möglichkeit, diesen Modus auch in der FHEM-Weboberfläche &#039;&#039;everything&#039;&#039; =&amp;amp;gt; Abschnitt &#039;&#039;thermostat&#039;&#039;zu sehen, &#039;&#039;&#039;wenn&#039;&#039;&#039; Sie für den HM-CC-TC das folgende Attribut setzen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;attr &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt; stateFormat T:measured-temp, H:humidity, VD:actuator, controlMode&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Erscheint dort selbst nach einem &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;set &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt; getConfig&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
kein &amp;quot;Reading&amp;quot; &#039;&#039;controlMode&#039;&#039;oder keine Angabe des aktuell eingestellten Modus bzw. nur das Wort &amp;quot;controlMode&amp;quot;, dann setzen Sie ihren HM-CC-TC von Hand in einen anderen Kontrollmodus und machen einen Browser-Refresh. Klappt dies nicht, geben Sie bitte erneut den Befehl&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;set &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt; getConfig&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
ein. Halten Sie anschließend die Taste &amp;amp;lt;OK&amp;amp;gt; am HM-CC-TC für 5 Sekunden gedrückt (oder warten ca. 5 Minuten) und machen in der FHEM-Weboberfläche einen Refresh (FF =&amp;amp;gt; &amp;amp;lt;F5&amp;amp;gt;). Jetzt sollte der manuell eingestellte Kontrollmodus erscheinen (ggfls. muss dieser Vorgang ein Mal wiederholt werden). Jetzt können Sie wieder den gewünschten Modus einstellen, erneut ein &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;set &amp;amp;lt;HM-CC-TC-Name&amp;amp;gt; getConfig&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
absetzen und nach erneutem Drücken der &amp;amp;lt;OK&amp;amp;gt;-Taste für 5 Sekunden mit nachfolgendem Browser-Refresh sollte alles richtig angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Dies setzt natürlich voraus, dass der HM-CC-TC richtig gepairt ist.&lt;br /&gt;
&lt;br /&gt;
== Temperaturlisten ==&lt;br /&gt;
Eine Temperaturliste für die Steuerung der Raumtemperatur im o.a. &#039;&#039;&#039;Auto-Modus&#039;&#039;&#039;kann man wie folgt erzeugen:&lt;br /&gt;
&lt;br /&gt;
* Man legt sich eine eigene &#039;&#039;99_MyUtils.pm&#039;&#039; an (siehe &amp;lt;nowiki&amp;gt;[http://www.fhemwiki.de/wiki/99_myUtils_anlegen Link]&amp;lt;/nowiki&amp;gt;). Dies ist wichtig, da es bei FHEM-Updates durchaus sein kann, dass die vorhandene &#039;&#039;99_Utils.pm&#039;&#039; erneuert und damit überschrieben wird und dann sind all ihre eigenen Subroutinen weg.&lt;br /&gt;
* Dort trägt man für &#039;&#039;&#039;jedes&#039;&#039;&#039; HM-CC-TC, dessen Werte man individuell einstellen will, eine &#039;&#039;&#039;eigene&#039;&#039;&#039; Subroutine ein, die z.B. wie folgt aussehen kann:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;######################################################&lt;br /&gt;
# Temperatur-Liste für das Wohnzimmer&lt;br /&gt;
# setzen per Aufruf von &amp;amp;quot;{SetTempList_EG_WZ_Heizung}&amp;amp;quot;&lt;br /&gt;
######################################################&lt;br /&gt;
sub&lt;br /&gt;
SetTempList_EG_WZ_Heizung()&lt;br /&gt;
 {&lt;br /&gt;
  { fhem (&amp;amp;quot;set EG.WZ.Heizung_Climate tempListMon 05:30 17.0 07:00 21.0 16:00 19.0 20:30 20.5 24:00 17.0&amp;amp;quot;)};&lt;br /&gt;
  { fhem (&amp;amp;quot;set EG.WZ.Heizung_Climate tempListTue 05:30 17.0 07:00 21.0 16:00 19.0 20:30 20.5 24:00 17.0&amp;amp;quot;)};&lt;br /&gt;
  { fhem (&amp;amp;quot;set EG.WZ.Heizung_Climate tempListWed 05:30 17.0 07:00 21.0 16:00 19.0 20:30 20.5 24:00 17.0&amp;amp;quot;)};&lt;br /&gt;
  { fhem (&amp;amp;quot;set EG.WZ.Heizung_Climate tempListThu 05:30 17.0 07:00 21.0 16:00 19.0 20:30 20.5 24:00 17.0&amp;amp;quot;)};&lt;br /&gt;
  { fhem (&amp;amp;quot;set EG.WZ.Heizung_Climate tempListFri 05:30 17.0 07:00 21.0 15:00 19.0 20:30 20.5 24:00 17.0&amp;amp;quot;)};&lt;br /&gt;
  { fhem (&amp;amp;quot;set EG.WZ.Heizung_Climate tempListSat 07:00 17.0 09:00 21.0 15:00 19.0 21:00 21.0 24:00 17.0&amp;amp;quot;)};&lt;br /&gt;
  { fhem (&amp;amp;quot;set EG.WZ.Heizung_Climate tempListSun 07:00 17.0 09:00 21.0 15:00 19.0 21:00 21.0 24:00 17.0&amp;amp;quot;)};&lt;br /&gt;
}&lt;br /&gt;
# End SetTempList_EG_WZ_Heizung&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* die Änderungen in der &#039;&#039;99_MyUtils.pm&#039;&#039; müssen jetzt abgespeichert werden&lt;br /&gt;
* in der FHEM-Befehlszeile ist ein &#039;&#039;reload 99_MyUtils.pm&#039;&#039; mit &amp;amp;lt;Enter&amp;amp;gt; / &amp;amp;lt;Return&amp;amp;gt; abzusetzen (erst dadurch werden die Eintragungen / Änderungen aktiviert)&lt;br /&gt;
* nun kann man in der Kommandozeile von FHEM den Befehl &#039;&#039;{SetTempList_EG_WZ_Heizung}&#039;&#039; eingeben und mit &amp;amp;lt;Return&amp;amp;gt; bzw. &amp;amp;lt;Enter&amp;amp;gt; bestätigen&lt;br /&gt;
&lt;br /&gt;
Im FHEM-Logfile (das man vorher in einem weiteren Browser-Tab geöffnet hat) taucht danach folgendes auf:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;amp;lt;Datum&amp;amp;gt; &amp;amp;lt;Zeit&amp;amp;gt; CUL_HM EG.WZ.Heizung set_tempListMon 05:30 17.0 07:00 21.0 16:00 19.0 20:30 20.5 24:00 17.0&lt;br /&gt;
&amp;amp;lt;Datum&amp;amp;gt; &amp;amp;lt;Zeit&amp;amp;gt; CUL_HM EG.WZ.Heizung_Climate set_tempListTue 05:30 17.0 07:00 21.0 16:00 19.0 20:30 20.5 24:00 17.0&lt;br /&gt;
&amp;amp;lt;Datum&amp;amp;gt; &amp;amp;lt;Zeit&amp;amp;gt; CUL_HM EG.WZ.Heizung_Climate set_tempListWed 05:30 17.0 07:00 21.0 16:00 19.0 20:30 20.5 24:00 17.0&lt;br /&gt;
&amp;amp;lt;Datum&amp;amp;gt; &amp;amp;lt;Zeit&amp;amp;gt; CUL_HM EG.WZ.Heizung_Climate set_tempListThu 05:30 17.0 07:00 21.0 16:00 19.0 20:30 20.5 24:00 17.0&lt;br /&gt;
&amp;amp;lt;Datum&amp;amp;gt; &amp;amp;lt;Zeit&amp;amp;gt; CUL_HM EG.WZ.Heizung_Climate set_tempListFri 05:30 17.0 07:00 21.0 15:00 19.0 20:30 20.5 24:00 17.0&lt;br /&gt;
&amp;amp;lt;Datum&amp;amp;gt; &amp;amp;lt;Zeit&amp;amp;gt; CUL_HM EG.WZ.Heizung_Climate set_tempListSat 07:00 17.0 09:00 21.0 15:00 19.0 21:00 21.0 24:00 17.0&lt;br /&gt;
&amp;amp;lt;Datum&amp;amp;gt; &amp;amp;lt;Zeit&amp;amp;gt; CUL_HM EG.WZ.Heizung_Climate set_tempListSun 07:00 17.0 09:00 21.0 15:00 19.0 21:00 21.0 24:00 17.0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Zur Erläuterung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Mittels &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;set EG.WZ.Heizung_Climate tempListMon 05:30 17.0 07:00 21.0 16:00 19.0 20:30 20.5 24:00 17.0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
setzt man das HM-CC-TC-Channel mit dem Namen &#039;&#039;EG.WZ.Heizung_Climate&#039;&#039; für jeden folgenden Montag&lt;br /&gt;
&lt;br /&gt;
von 00:00 bis 05:30 Uhr auf 17,0 °C&lt;br /&gt;
von 05:31 bis 07:00 Uhr auf 21,0 °C&lt;br /&gt;
von 07:31 bis 16:00 Uhr auf 19,0 °C&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
und so weiter. Dabei kann bei der Temperatur als Nachkommawert entweder eine 0 oder eine 5 stehen, ein Wert von z.B. 20,1 ist nicht erlaubt.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass am Schluss der Liste immer eine Einstellung für 24:00 notiert sein muss. Ansonsten quittiert FHEM das Setzen der Liste mit einem solchen Eintrag im Logfile:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Last time spec must be 24:00&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Im FHEM-Logfile-Browser-Tab sollten nach einigen Minuten folgende mehrfach wiederholten Einträge auftauchen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;amp;lt;Datum&amp;amp;gt; &amp;amp;lt;Zeit&amp;amp;gt; CUL_HM EG.WZ.Heizung_Climate CommandAccepted: yes&lt;br /&gt;
&amp;amp;lt;Datum&amp;amp;gt; &amp;amp;lt;Zeit&amp;amp;gt; CUL_HM EG.WZ.Heizung_Climate CommandAccepted: yes&lt;br /&gt;
...&lt;br /&gt;
&amp;amp;lt;Datum&amp;amp;gt; &amp;amp;lt;Zeit&amp;amp;gt; CUL_HM EG.WZ.Heizung_Climate CommandAccepted: yes&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Wichtig ist ein nachfolgendes &amp;quot;ACK&amp;quot;. Steht dort &amp;quot;MISSING ACK&amp;quot;, dann wurde der Empfang der Werte vom HM-CC-TC nicht bestätigt und man sollte die TempList noch einmal schicken. Kommt auch nach mehreren Sendeversuchen kein &amp;quot;ACK&amp;quot; sollten Sie in den &#039;&#039;Readings&#039;&#039;des Devices die &#039;&#039;TempList&#039;&#039;überprüfen (siehe unten), denn es kann sein, dass diese Antwort schlicht nicht empfangen werden konnte, weil der Empfänger gerade anderweitig beschäftigt war, die Einstellungen aber dennoch übernommen wurden. Wird jedoch ein &amp;quot;NACK&amp;quot; vom HM-CC-TC gesendet, dann wurde die Temperaturliste explizit nicht akzeptiert. Kontrollieren Sie in diesem Fall die Korrektheit der Temperaturliste.&lt;br /&gt;
&lt;br /&gt;
Welche Werte &#039;&#039;&#039;aktuell eingestellt&#039;&#039;&#039;sind, sieht man in den &amp;quot;Readings&amp;quot; des jeweiligen Devices; im obigen Fall also z.B. im linken Menü von FHEM auf den default-Eintrag &#039;&#039;Everything&#039;&#039;klicken und dann auf den Eintrag mit dem Namen &#039;&#039;EG.WZ.Heizung&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Batteriealarme des HM-CC-VD in Verbindung mit HM-CC-TC ==&lt;br /&gt;
1. bei U-Bat. &amp;amp;lt; 2,4 V erscheint im Display des VD und des TC das Batteriesymbol mit &#039;&#039;&#039;battery: low&#039;&#039;&#039; in den Readings und Events!&lt;br /&gt;
&lt;br /&gt;
2. bei U-Bat. &amp;amp;lt; 2,3 V erscheint im Display des VD zusätzlich &#039;&#039;&#039;F4&#039;&#039;&#039; mit &#039;&#039;&#039;battery: critical&#039;&#039;&#039; in den Readings und Events!&lt;br /&gt;
&lt;br /&gt;
Es wird dringend geraten, die Batterien bei battery: low zu tauschen!&lt;br /&gt;
&lt;br /&gt;
== Log-Auszug ==&lt;br /&gt;
HM-CC-TC sendet alle 2 Minuten folgenden Statusbericht:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Datum-Zeit &amp;amp;lt;Device Name&amp;amp;gt; T: 17.3 H: 66&amp;amp;lt;br&amp;amp;gt;&lt;br /&gt;
Datum-Zeit &amp;amp;lt;Device Name&amp;amp;gt; measured-temp: 17.3&amp;amp;lt;br&amp;amp;gt;&lt;br /&gt;
Datum-Zeit &amp;amp;lt;Device Name&amp;amp;gt; temperature: 17.3&amp;amp;lt;br&amp;amp;gt;&lt;br /&gt;
Datum-Zeit &amp;amp;lt;Device Name&amp;amp;gt; humidity: 66&amp;amp;lt;br&amp;amp;gt;&lt;br /&gt;
Datum-Zeit &amp;amp;lt;Device Name&amp;amp;gt; actuator: 96&amp;amp;#160;%&amp;amp;lt;br&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Bei Status-Änderungen sendet HM-CC-TC auch entsprechende Meldungen, z.b.:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Datum-Zeit &amp;amp;lt;Device Name&amp;amp;gt; desired-temp: 15.5&amp;amp;lt;br&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
= Firmware =&lt;br /&gt;
Aktuelle Firmware-Version: 2.1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Links =&lt;br /&gt;
Anleitung [http://www.elv-downloads.de/service/manuals/76787_76175_HM_Wandthermostat_UM.pdf PDF]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Feuchtigkeitssensor]]&lt;br /&gt;
[[Kategorie:Temperatursensor]]&lt;/div&gt;</summary>
		<author><name>Caldir65</name></author>
	</entry>
</feed>