<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Database &#8211; SmartHomeNG | smarthome knx homematic mqtt hue 1wire home automation</title>
	<atom:link href="https://www.smarthomeng.de/tag/database/feed" rel="self" type="application/rss+xml" />
	<link>https://www.smarthomeng.de</link>
	<description>Die Device Integrations-Plattform für Dein Smart Home</description>
	<lastBuildDate>Sun, 29 Mar 2020 09:23:53 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.5.5</generator>

<image>
	<url>https://www.smarthomeng.de/wp-content/uploads/global/logo_small_152x152-150x150.png</url>
	<title>Database &#8211; SmartHomeNG | smarthome knx homematic mqtt hue 1wire home automation</title>
	<link>https://www.smarthomeng.de</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Zusätzliche und hilfreiche Zeitdaten über eine Logik berechnen</title>
		<link>https://www.smarthomeng.de/zeitdaten-ueber-eine-logik-berechnen</link>
					<comments>https://www.smarthomeng.de/zeitdaten-ueber-eine-logik-berechnen#comments</comments>
		
		<dc:creator><![CDATA[Marc René Frieß]]></dc:creator>
		<pubDate>Tue, 01 May 2018 10:12:40 +0000</pubDate>
				<category><![CDATA[Beispiel-Implementierungen]]></category>
		<category><![CDATA[ohne Kategorie]]></category>
		<category><![CDATA[Beispiel]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Logik]]></category>
		<category><![CDATA[Logiken]]></category>
		<category><![CDATA[Shtime API]]></category>
		<category><![CDATA[Zeitdaten]]></category>
		<guid isPermaLink="false">https://www.smarthomeng.de/?p=1643</guid>

					<description><![CDATA[Mit SmartHomeNG existiert bereits eine Reihe zeitbezogener Daten über Shtime.get_instance().now(). Speziell für Datenbankabfragen kann es aber hilfreich sein, noch einige Zusatzitems zu haben. Diese werden im Rahmen dieses Artikels gezeigt. Die Items date: month: since: year: type: num cache: 'yes' dbstr: type: str cache: 'yes' eval_trigger: date.month.since.year eval: str(sh.date.month.since.year()) +<a class="moretag" href="https://www.smarthomeng.de/zeitdaten-ueber-eine-logik-berechnen"> Weiterlesen&#8230;</a>]]></description>
										<content:encoded><![CDATA[<p>Mit SmartHomeNG existiert bereits eine Reihe zeitbezogener Daten über <code>Shtime.get_instance().now()</code>. Speziell für Datenbankabfragen kann es aber hilfreich sein, noch einige Zusatzitems zu haben. Diese werden im Rahmen dieses Artikels gezeigt.</p>
<h1>Die Items</h1>
<pre><code class="language-yaml">
date:

    month:
        since:
            year:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.month.since.year
                    eval: str(sh.date.month.since.year()) + 'm'

        until:
            year:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.month.until.year
                    eval: str(sh.date.month.until.year()) + 'm'

    week:
        since:
            month:
                type: num
                cache: 'yes'
            year:
                type: num
                cache: 'yes'
        until:
            month:
                type: num
                cache: 'yes'
            year:
                type: num
                cache: 'yes'

    day:
        since:
            week:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.day.since.week
                    eval: str(sh.date.day.since.week()) + 'd'

            month:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.day.since.month
                    eval: str(sh.date.day.since.month()) + 'd'
            year:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.day.since.year
                    eval: str(sh.date.day.since.year()) + 'd'

        until:
            week:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.day.since.week
                    eval: str(sh.date.day.since.week()) + 'd'

            month:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.day.until.month
                    eval: str(sh.date.day.until.month()) + 'd'

            year:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.day.until.year
                    eval: str(sh.date.day.until.year()) + 'd'

    hour:
        since:
            midnight:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.hour.since.midnight
                    eval: str(sh.date.hour.since.midnight()) + 'h'

            week:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.hour.since.week
                    eval: str(sh.date.hour.since.week()) + 'h'

            month:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.hour.since.month
                    eval: str(sh.date.hour.since.month()) + 'h'

            year:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.hour.since.year
                    eval: str(sh.date.hour.since.year()) + 'h'

        until:
            midnight:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.hour.until.midnight
                    eval: str(sh.date.hour.until.midnight()) + 'h'

            week:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.hour.until.week
                    eval: str(sh.date.hour.until.week()) + 'h'

            month:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.hour.until.month
                    eval: str(sh.date.hour.until.month()) + 'h'

            year:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.hour.until.year
                    eval: str(sh.date.hour.until.year()) + 'h'

    minute:
        since:
            hour:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.minute.since.hour
                    eval: str(sh.date.minute.since.hour()) + 'i'

            midnight:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.minute.since.midnight
                    eval: str(sh.date.minute.since.midnight()) + 'i'

            week:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.minute.since.week
                    eval: str(sh.date.minute.since.week()) + 'i'

            month:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.minute.since.month
                    eval: str(sh.date.minute.since.month()) + 'i'

            year:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.minute.since.year
                    eval: str(sh.date.minute.since.year()) + 'i'

        until:
            hour:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.minute.until.hour
                    eval: str(sh.date.minute.until.hour()) + 'i'

            midnight:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.minute.until.midnight
                    eval: str(sh.date.minute.until.midnight()) + 'i'

            week:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.minute.until.week
                    eval: str(sh.date.minute.until.week()) + 'i'

            month:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.minute.until.month
                    eval: str(sh.date.minute.until.month()) + 'i'

            year:
                type: num
                cache: 'yes'
                dbstr:
                    type: str
                    cache: 'yes'
                    eval_trigger: date.minute.until.year
                    eval: str(sh.date.minute.until.year()) + 'i'

    second:
        since:
            minute:
                type: num

            hour:
                type: num

            midnight:
                type: num

            week:
                type: num

            month:
                type: num

            year:
                type: num

        until:

            minute:
                type: num

            hour:
                type: num

            midnight:
                type: num

            week:
                type: num

            month:
                type: num

            year:
                type: num
</code></pre>
<h1>Die Logik</h1>
<p>Als Logik wird unter <code>logics/zeit.py</code> die nachfolgende Datei angelegt.</p>
<pre><code class="language-python">
<span># /logics/zeit.py
</span><span># !/usr/bin/env python3
</span><span>
</span>
from lib.shtime import Shtime<br/>
sh_now = Shtime.get_instance().now()
<span>
</span><span># Funktionen
</span><span>
</span><span>def </span><span>days_of_month</span>(month<span>, </span>year):
    <span>if </span>month <span>in </span>[<span>1</span><span>, </span><span>3</span><span>, </span><span>5</span><span>, </span><span>7</span><span>, </span><span>8</span><span>, </span><span>10</span><span>, </span><span>12</span>]:
        days = <span>31
</span><span>    </span><span>elif </span>month <span>in </span>[<span>4</span><span>, </span><span>6</span><span>, </span><span>9</span><span>, </span><span>11</span>]:
        days = <span>30
</span><span>    </span><span>elif </span>(year % <span>400 </span>== <span>0</span>) <span>or </span>((year % <span>4 </span>== <span>0</span>) <span>and not </span>(year % <span>100 </span>== <span>0</span>)):  <span># Schaltjahr
</span><span>        </span>days = <span>29
</span><span>    </span><span>else</span>:
        days = <span>28
</span><span>    </span><span>return </span>days

<span>def </span><span>days_of_year</span>(year):
    period_end = datetime.datetime(year<span>, </span><span>12</span><span>, </span><span>31</span>)
    days_of_year = (period_end - datetime.datetime(period_end.year<span>, </span><span>1</span><span>, </span><span>1</span>)).days + <span>1
</span><span>    </span><span>return </span>(days_of_year)

<span>def </span><span>day_of_year</span>(year<span>, </span>month<span>, </span>day):
    period_end = datetime.datetime(year<span>, </span>month<span>, </span>day)
    day_of_year = (period_end - datetime.datetime(period_end.year<span>, </span><span>1</span><span>, </span><span>1</span>)).days + <span>1
</span><span>    </span><span>return </span>(day_of_year)
<span>
</span><span># Sekunde/Minute
</span>sh.date.second.since.minute(sh_now.second)
sh.date.second.until.minute(<span>60 </span>- sh_now.second - <span>1</span>)

<span># Minute/Stunde
</span>sh.date.minute.since.hour(sh_now.minute)
sh.date.minute.until.hour(<span>60 </span>- sh_now.minute - <span>1</span>)

<span># Stunde/Tag
</span>sh.date.hour.since.midnight(sh_now.hour)
sh.date.hour.until.midnight(<span>24 </span>- sh_now.hour - <span>1</span>)

<span># Tag/Woche
</span>sh.date.day.since.week(sh_now.isoweekday())
sh.date.day.until.week(<span>7 </span>- sh_now.isoweekday())

<span># Stunde/Woche
</span>sh.date.hour.since.week(sh.date.hour.since.midnight() + (<span>24 </span>* (sh.date.day.since.week() - <span>1</span>)))
sh.date.hour.until.week(sh.date.hour.until.midnight() + (<span>24 </span>* sh.date.day.until.week()))

<span># Kalenderwoche/Jahr
</span>sh.date.week.since.year(sh_now.isocalendar()[<span>1</span>])
sh.date.week.until.year(<span>52</span>-sh_now.isocalendar()[<span>1</span>])

<span># Monat/Jahr
</span>sh.date.month.since.year(sh_now.month)
sh.date.month.until.year(<span>12 </span>- sh_now.month)

<span># Sekunde/Stunde
</span>sh.date.second.since.hour(sh.date.second.since.minute() + (<span>60 </span>* sh.date.minute.since.hour()))
sh.date.second.until.hour(sh.date.second.until.minute() + (<span>60 </span>* sh.date.minute.until.hour()))

<span># Sekunde/Tag
</span>sh.date.second.since.midnight(sh.date.second.since.minute() + (<span>3600 </span>* sh.date.hour.since.midnight()))
sh.date.second.until.midnight(sh.date.second.until.minute() + (<span>3600 </span>* sh.date.hour.until.midnight()))

<span># Minute/Tag
</span>sh.date.minute.since.midnight(sh.date.minute.since.hour() + (<span>60 </span>* sh.date.hour.since.midnight()))
sh.date.minute.until.midnight(sh.date.minute.until.hour() + (<span>60 </span>* sh.date.hour.until.midnight()))

<span># Minute/Woche
</span>sh.date.minute.since.week(sh.date.minute.since.hour() + (<span>60 </span>* sh.date.hour.since.week()))
sh.date.minute.until.week(sh.date.minute.until.hour() + (<span>60 </span>* sh.date.hour.until.week()))

<span># Sekunde/Woche
</span>sh.date.second.since.week(sh.date.second.since.minute() + (<span>60 </span>* sh.date.minute.since.week()))
sh.date.second.until.week(sh.date.second.until.minute() + (<span>60 </span>* sh.date.minute.until.week()))

<span># Tage/Monat
</span>sh.date.day.since.month(sh_now.day)
sh.date.day.until.month(days_of_month(sh_now.month<span>, </span>sh_now.year) - sh.date.day.since.month() - <span>1</span>)

<span># Wochen/Monat
</span>sh.date.week.since.month((sh.date.day.since.month()-<span>1</span>)//<span>7</span>+<span>1</span>)
sh.date.week.until.month((sh.date.day.until.month())//<span>7</span>)

<span># Tage/Jahr
</span>sh.date.day.since.year(day_of_year(sh_now.year<span>, </span>sh_now.month<span>, </span>sh_now.day) - <span>1</span>)
sh.date.day.until.year(days_of_year(sh_now.year) - sh.date.day.since.year() - <span>1</span>)

<span># Stunde/Monat
</span>sh.date.hour.since.month((<span>24 </span>* sh.date.day.since.month()) + sh.date.hour.since.midnight())
sh.date.hour.until.month((<span>24 </span>* days_of_month(sh_now.month<span>, </span>sh_now.year)) - sh.date.hour.since.month() - <span>1</span>)

<span># Stunde/Jahr
</span>sh.date.hour.since.year((<span>24 </span>* sh.date.day.since.year()) + sh.date.hour.since.midnight())
sh.date.hour.until.year((<span>24 </span>* days_of_year(sh_now.year)) - sh.date.hour.since.year() - <span>1</span>)

<span># Minute/Monat
</span>sh.date.minute.since.month((<span>60 </span>* sh.date.hour.since.month()) + sh.date.minute.since.hour())
sh.date.minute.until.month(sh.date.minute.since.month() - (<span>60 </span>* sh.date.hour.until.month()) - <span>1</span>)

<span># Minute/Jahr
</span>sh.date.minute.since.year((<span>60 </span>* sh.date.hour.since.year()) + sh.date.minute.since.hour())
sh.date.minute.until.year((<span>60 </span>* sh.date.hour.until.year()) + sh.date.minute.until.hour())

<span># Sekunde/Monat
</span>sh.date.second.since.month((<span>60 </span>* sh.date.minute.since.month()) + sh.date.second.since.minute())
sh.date.second.until.month((<span>60 </span>* sh.date.minute.until.month()) + sh.date.second.until.minute())

<span># Sekunde/Jahr
</span>sh.date.second.since.year((<span>60 </span>* sh.date.minute.since.year()) + sh.date.second.since.minute())
sh.date.second.until.year((<span>60 </span>* sh.date.minute.until.year()) + sh.date.second.until.minute())</code></pre>
<p>In der <code>etc/logic.yaml</code> wird sie wie folgt eingebunden:</p>
<pre><code class="language-yaml">
zeitberechnung:
    filename: zeit.py
    crontab:
        -   init
        -   '* * * *'
</code></pre>
<h1>Anwendungsbeispiel: Database Plugin</h1>
<p>Neben der Anzeige der Daten, macht es vor allem Sinn, die Werte im Zusammenspiel mit (historischen) Datenbank-Daten zu verwenden. Ein Beispiel wäre wie folgt:</p>
<pre><code class="language-yaml">
consumption_since_midnight:
	type: num
	eval: sh.knx.cellar.utility_room.water_meter.db('count&gt;0', sh.date.minute.since.midnight.dbstr(), 'now')
	eval_trigger: knx.cellar.utility_room.water_meter
	database@mysqldb: init
</code></pre>
<p>Im Eval-Ausdruck wird die Anzahl der Werte &gt; 0 ermittelt, die zwischen Mitternacht und dem IST-Zeitpunkt erfasst wurden. Da für 1 Liter jedes Mal ein Impuls mit einer &#8222;1&#8220; erfasst wird, erhält man so minutengenau die Anzahl der Liter seit Mitternacht. Die Methode <code>dbstr()</code> in <code>sh.date.minute.since.midnight.dbstr()</code> liefert direkt den Wert, den das Database-Plugin benötigt. Präziser gesagt, hängt sie dem numerischen Wert <anzahl der="" minuten=""> noch ein &#8222;i&#8220; an, so dass die Angabe auf Ebene des Plugins korrekt interpretiert wird.<br />
Über die Methode <code>.db</code> auf dem Item, wird die Datenbankabfrage gestartet. Das Item muss dazu mit dem Database-Plugin verknüpft sein <code>database@mysqldb: init</code> und bereits Daten im abgefragten Zeitraum erfasst haben.</anzahl></p>
<p><em>(Das Titelbild ist unter der Creative Commons Zero (CC0) Lizenz veröffentlicht und wurde von www.pexels.com bezogen.)</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.smarthomeng.de/zeitdaten-ueber-eine-logik-berechnen/feed</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Welches Datenbank Plugin sollte ich verwenden?</title>
		<link>https://www.smarthomeng.de/welches-datenbank-plugin-sollte-ich-verwenden</link>
					<comments>https://www.smarthomeng.de/welches-datenbank-plugin-sollte-ich-verwenden#comments</comments>
		
		<dc:creator><![CDATA[Martin Sinn]]></dc:creator>
		<pubDate>Fri, 30 Mar 2018 07:35:26 +0000</pubDate>
				<category><![CDATA[FAQ]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Datenbank]]></category>
		<category><![CDATA[smartVISU]]></category>
		<category><![CDATA[sqlite]]></category>
		<category><![CDATA[sqlite_visu2_8]]></category>
		<guid isPermaLink="false">https://www.smarthomeng.de/?p=866</guid>

					<description><![CDATA[Datenbank Plugins Es gibt zurzeit drei verschiedene Datenbank Plugins: database sqlite sqlite_visu2_8 Wenn Du neu mit SmartHomeNG beginnst, solltest Du das Plugin database verwenden. Das database Plugin unterstützt sowohl MySQL Datenbanken, als auch SQLite Datenbanken. Welcher Datenbank-Typ verwendet wird, wird in ../etc/plugin.yaml konfiguriert. sqlite und sqlite_visu2_8 Die beiden SQLite Plugins dienen<a class="moretag" href="https://www.smarthomeng.de/welches-datenbank-plugin-sollte-ich-verwenden"> Weiterlesen&#8230;</a>]]></description>
										<content:encoded><![CDATA[<h3>Datenbank Plugins</h3>
<p>Es gibt zurzeit drei verschiedene Datenbank Plugins:</p>
<ul>
<li>database</li>
<li>sqlite</li>
<li>sqlite_visu2_8</li>
</ul>
<p>Wenn Du neu mit SmartHomeNG beginnst, solltest Du das Plugin <strong>database</strong> verwenden. Das <strong>database</strong> Plugin unterstützt sowohl MySQL Datenbanken, als auch SQLite Datenbanken. Welcher Datenbank-Typ verwendet wird, wird in <code>../etc/plugin.yaml</code> konfiguriert.</p>
<h3>sqlite und sqlite_visu2_8</h3>
<p>Die beiden SQLite Plugins dienen nur der Rückwärts-Kompatibilität für bestehende SmartHomeNG bzw. smarthome.py Umgebungen und werden nicht mehr weiterentwickelt.</p>
<p>Das Plugin <strong>sqlite</strong> unterstützt smartVISU bis zur Version v2.7.</p>
<p>Zur Unterstützung von smartVISU v2.8 und v2.9 muss das Plugin <strong>sqlite_visu2_8</strong> verwendet werden. Das Plugin führt beim ersten Start eine Konvertierung der Datenbank von <strong>sqlite</strong> auf das <strong>sqlite_visu2_8</strong> Format durch. Einen Weg zurück gibt es dann nicht. Es sollte also vorher eine Sicherung der Datenbank Datei <code>../var/db/smarthome.db</code> durchgeführt werden.</p>
<p><strong>Wichtig</strong>: Vor Beginn der Sicherung SmartHomeNG beenden.</p>
<p>&nbsp;</p>
<p>Eine Routine zur Konvertierung der Datenbanken der sqlite Plugins zu einer Datenbank für das database Plugin gibt es (noch) nicht.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.smarthomeng.de/welches-datenbank-plugin-sollte-ich-verwenden/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Database Plugin Guide für MySQL/MariaDB</title>
		<link>https://www.smarthomeng.de/database-plugin-guide-fuer-mysql-mariadb</link>
					<comments>https://www.smarthomeng.de/database-plugin-guide-fuer-mysql-mariadb#respond</comments>
		
		<dc:creator><![CDATA[Marc René Frieß]]></dc:creator>
		<pubDate>Sun, 30 Jul 2017 15:26:02 +0000</pubDate>
				<category><![CDATA[Plugins]]></category>
		<category><![CDATA[Tipps & Tricks]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Datenbank]]></category>
		<guid isPermaLink="false">http://test.smarthomeng.de/?p=213</guid>

					<description><![CDATA[Leitfaden zur Umstellung auf das Database Plugin in Kombination mit MySQL/MariaDB Motivation Das Database Plugin setzt auf einer Neuimplementierung der Datenbankanbindung auf, bei der nicht wie beim bisherigen SQLite Plugin alte Daten &#8222;aufgeräumt&#8220; werden, sondern jeder Datensatz behalten wird. Dies kann zu sehr großen Datenbeständen führen, für die eine &#8222;echte&#8220;<a class="moretag" href="https://www.smarthomeng.de/database-plugin-guide-fuer-mysql-mariadb"> Weiterlesen&#8230;</a>]]></description>
										<content:encoded><![CDATA[<div class="markdown-body">
<h3>Leitfaden zur Umstellung auf das Database Plugin in Kombination mit MySQL/MariaDB</h3>
<h2>Motivation</h2>
<p>Das Database Plugin setzt auf einer Neuimplementierung der Datenbankanbindung auf, bei der nicht wie beim bisherigen SQLite Plugin alte Daten &#8222;aufgeräumt&#8220; werden, sondern jeder Datensatz behalten wird. Dies kann zu sehr großen Datenbeständen führen, für die eine &#8222;echte&#8220; Datenbank wie MySQL oder MariaDB sinnvoller ist. Auch können diese Datenbanken mit PhpMyAdmin sehr leicht administriert / betrachtet werden.</p>
<p><strong>Wichtig:</strong> Eine Nutzung mit SQLite ist auch weiterhin mit dem Database Plugin möglich, so dass ein Wechsel zu anderen Datenbanken nicht zwingend notwendig ist.</p>
<p>Dieser Leitfaden soll trotzdem dazu dienen, den Umstieg zu erleichtern und motivieren.</p>
<h2>Installation von MariaDB</h2>
<p>Eine sinnvolle Alternative zu SQLite ist Maria DB (ein Fork von MySQL). Mit dem Database Plugin sind jedoch auch andere Datenbanken mit Kompatibilität zur Python DB API 2 möglich. Auch das klassische MySQL kann verwendet werden.</p>
<pre><code class="language-bash">
sudo apt-get update
sudo apt-get install mariadb-server
# alternativ
# sudo apt-get install mysql-server
</code></pre>
<p>Die Installationsroutine fordert dabei zur Eingabe eines Passworts für den User &#8222;root&#8220; auf. Hier ist darauf zu achten, ein möglichst sicheres Passwort zu wählen.</p>
<h2>Einrichtung einer DB und eines DB Users für SmartHomeNG</h2>
<p>Als nächstes sollte eine eigene MariaDB Datenbank mit eigenem User für SmartHomeNG erstellt werden, da die Verwendung des Root Users aus Sicherheitsgründen (globale root Rechte) nicht zu empfehlen ist.</p>
<p>Dazu sollte wie folgt vorgegangen werden:</p>
<h3>Einloggen in MariaDB als root (befehl &#8222;mysql&#8220;) mit vergebenem Passwort</h3>
<pre><code class="language-bash">
mysql -u root -p
</code></pre>
<h3>Datenbank / User für SmartHomeNG erstellen</h3>
<p>In der nun folgenden Shell &#8211; jede Zeile mit den jeweiligen Werten befüllen und mit ENTER bestätigen:</p>
<pre><code class="language-sql">
CREATE DATABASE smarthome_db;
CREATE USER 'smarthome'@'<mark>«ip of your SmartHomeNG server»</mark>' IDENTIFIED BY '<mark>«password»</mark>';
GRANT ALL PRIVILEGES ON smarthome_db.* TO 'smarthome'@'<mark>«ip of your SmartHomeNG server»</mark>';
FLUSH PRIVILEGES;
</code></pre>
<p><strong>Wichtig:</strong> Falls die Datenbank auf dem gleichen Server wie SmartHomeNG betrieben wird, muss anstatt der IP die <code>127.0.0.1</code> und ggf. <code>localhost</code> via jeweiligen <code>GRANT ALL ...</code> Statements freigegeben werden.</p>
<h3>(Optional) Prüfen der Einstellungen:</h3>
<p>Auf die Datenbank lokal als root einloggen, <code>mysql -u root -p</code>. Mittels <code>show databases;</code> kann man nun prüfen, ob eine Datenbank namens <code>smarthome_db</code> erstellt wurde. Der neue User ist in der Datenbank <code>mysql</code> in der Tabelle <code>users</code> zu finden:</p>
<pre><code class="language-sql">
use mysql;
select Host, User from user;
</code></pre>
<p>Im Output sollte nun eine Zeile mit IP des SmartHomeNG Servers und dem User &#8222;smarthome&#8220; sichtbar sein.</p>
<p>Die vergebenen PRIVILEGES auf die smarthome_db sind via</p>
<pre><code class="language-sql">
select Host, Db, USer from db; 
</code></pre>
<p>zu sehen. Auch hier sollten der Username, die IP und die Datenbank auftauchen.</p>
<p>Mit <code>exit</code> geht es zurück zur Shell.</p>
<h3>SmartHomeNG und Datenbank auf <strong>getrennten</strong> Maschinen/IPs</h3>
<p>Sind SmartHomeNG und Datenbank getrennt, muss zusätzlich der Eintrag <code>bind-address</code> in der <code>/etc/mysql/my.cnf</code> angepasst werden. Dieser kann entweder auskommentiert werden (jeder Rechner kann mit Angabe von User und Passwort auf die DB verbinden) oder explizit die IP des SmartHomeNG Servers gesetzt werden. Mehrere IPs sind nicht möglich. Soll daher auch vom Datenbank-Server zugegriffen werden (bspw. für ein dort installiertes PhpMyAdmin) hilft nur auskommentieren und das setzen entsprechender Firewall Regeln.</p>
<pre><code class="language-ini">
...
[mysqld]
...
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
#bind-address           = 127.0.0.1 (auskommentiert)
#oder alternativ
bind-address            = «IP des SmartHomeNG Servers»
...
</code></pre>
<p>Nach dem Speichern muss der Dienst mit <code>sudo service mysql restart</code> neu gestartet werden.</p>
<h2>Vorbereitung des SmartHomeNG Servers für die Nutzung via Database Plugin:</h2>
<p>Detaillierte Informationen siehe <a href="https://github.com/smarthomeNG/plugins/tree/master/database" title="https://github.com/smarthomeNG/plugins/tree/master/database" rel="noreferrer">https://github.com/smarthomeNG/plugins/tree/master/database</a></p>
<p>Nach erfolgter Installation der Datenbank, muss auf dem SmartHomeNG Server das entsprechende Paket für Python3 installiert werden:</p>
<pre><code class="language-bash">
sudo pip3 install --upgrade pymysql
</code></pre>
<p>Achtung: Das sehr ähnlich klingende pymsql3 sollte nicht mehr verwendet werden (würde theoretisch mit dem Plugin aber auch funktionieren).</p>
<p>Das Database Plugin wird nun wie folgt in der <code>plugin.yaml</code> eingerichtet:</p>
<pre><code class="language-yaml">database:
    plugin_name: database
    driver: pymysql
    connect:
      - 'host:«ip des mariadb/mysql servers»'
      - 'user:smarthome'
      - 'passwd:«passwort des users smarthome»'
      - 'db:smarthome_db'

</code></pre>
<p>In den jeweiligen Items muss dann ein <code>database@mysqldb: init</code> erfolgen (oder das alte <code>sqlite: init</code> ersetzen).</p>
<h2>Datenkonvertierung von SQLite</h2>
<p>Das Datenbank Plugin nutzt intern ein anderes Format als die alte smarthome.db Datenbank. Wenn die Daten weiterhin genutzt werden sollen (historische Daten), dann müssen sie konvertiert werden ins neue Format.</p>
<p>Dazu muß auf der Shell ins SmartHomeNG Basisverzeichnis gewechselt und dann ein Konvertierungsscript aufgerufen werden:</p>
<pre><code class="language-bash">
cd /usr/local/smarthome
python3 plugins/database/&gt;convert ./var/db/smarthome.db ... . # gibt es leider noch nicht ;)
</code></pre>
<p>todo: Skript schreiben für die Migration</p>
<h2>Abschluß</h2>
<p>Nachdem die Änderungen an den Items durchgeführt sind und die Konvertierung erfolgt ist, muß SmartHomeNG neu gestartet werden.</p>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://www.smarthomeng.de/database-plugin-guide-fuer-mysql-mariadb/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
