<?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>Logik &#8211; SmartHomeNG | smarthome knx homematic mqtt hue 1wire home automation</title>
	<atom:link href="https://www.smarthomeng.de/tag/logik/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>Mon, 12 Nov 2018 18:43:43 +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>Logik &#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>Vom Winde verweht</title>
		<link>https://www.smarthomeng.de/vom-winde-verweht</link>
					<comments>https://www.smarthomeng.de/vom-winde-verweht#comments</comments>
		
		<dc:creator><![CDATA[Marc René Frieß]]></dc:creator>
		<pubDate>Thu, 19 Apr 2018 17:55:38 +0000</pubDate>
				<category><![CDATA[Beispiel-Implementierungen]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[Beaufort]]></category>
		<category><![CDATA[Logik]]></category>
		<category><![CDATA[smartVISU]]></category>
		<category><![CDATA[Windrichtung]]></category>
		<category><![CDATA[Windstärke]]></category>
		<category><![CDATA[Wundergrund]]></category>
		<guid isPermaLink="false">https://www.smarthomeng.de/?p=1516</guid>

					<description><![CDATA[Dieser Artikel beschäftigt sich mit dem Thema Wind und was sich daraus alles über Plugins und Logiken am Ende in der smartVISU realisieren lässt. Anmerkung: mittlerweile sind die API Keys für Wundergrund leider nicht mehr kostenlos! Die Anleitung muss also mit einem alternativen Plugin wie Darksky oder OpenWeatherMap durchgeführt werden!<a class="moretag" href="https://www.smarthomeng.de/vom-winde-verweht"> Weiterlesen&#8230;</a>]]></description>
										<content:encoded><![CDATA[<p>Dieser Artikel beschäftigt sich mit dem Thema Wind und was sich daraus alles über Plugins und Logiken am Ende in der smartVISU realisieren lässt.</p>
<p><strong>Anmerkung:</strong> mittlerweile sind die API Keys für Wundergrund leider nicht mehr kostenlos! Die Anleitung muss also mit einem alternativen Plugin wie <a href="https://github.com/smarthomeNG/plugins/tree/master/darksky" target="_blank" rel="noopener">Darksky</a> oder <a href="https://github.com/smarthomeNG/plugins/tree/develop/openweathermap" target="_blank" rel="noopener">OpenWeatherMap</a> durchgeführt werden!</p>
<p>Basis des Artikels sind Daten zu Windrichtung und Windgeschwindigkeit über das Wundergrund Plugin. Es lassen sich aber bspw. auch Daten der KNX Wetterstation verwenden, sofern vorhanden.</p>
<h1>Das Wundergrund Plugin konfigurieren</h1>
<p>Die automatisch generierte Doku zum Wundergrund Plugin findet sich unter <a href="https://www.smarthomeng.de/user/plugins_doc/config/wunderground.html" target="_blank" rel="noopener">https://www.smarthomeng.de/user/plugins_doc/config/wunderground.html</a>.</p>
<p>Das Plugin liegt auf Github unter <a href="https://github.com/smarthomeNG/plugins/tree/master/wunderground" target="_blank" rel="noopener">https://github.com/smarthomeNG/plugins/tree/master/wunderground</a>.</p>
<p>Als Erstes muss das Plugin in der <code>etc/plugin.yaml</code> eingetragen werden. Der <code>apikey</code> kann kostenlos <span style="color: #ff0000;">(Update: leider sind die API Keys inzwischen nicht mehr kostenlos!)</span> über <a href="https://www.wunderground.com/weather/api/d/pricing.html" target="_blank" rel="noopener">https://www.wunderground.com/weather/api/d/pricing.html</a> beantragt werden. Es ist darauf zu achten, dass das Updateintervall eine bestimmte Zeitdauer nicht überschreitet, speziell, wenn man Wundergrund auch direkt in der smartVISU nutzt. Das Limit sind 500 Calls pro Tag bzw. 10 Calls pro Minute. Das Default-Updateintervall für das Plugin sind 600 Sekunden, also einmal in 10 Minuten. Per <code>cycle</code> Attribut ließe sich dieses in der <code>plugin.yaml</code> anpassen.</p>
<p>Als <code>location</code> setzt man bspw. seinen Ort, es sind hier neben dem Namen aber auch Geokoordinaten möglich.</p>
<pre><code class="language-yaml">
wundergrund_wetter:
    class_name: Wunderground
    class_path: plugins.wunderground
    apikey: 'xxxxyyyyxxxxyyyy'
    language: 'de'
    location: 'Germany/Hamburg'
    item_subtree: weather.wundergrund
    # cycle: 600
</code></pre>
<p><code>item_subtree</code> ist der Ast im Itemtree, unter dem die Wundergrund-relevanten Items liegen. Im Beispiel ist es <code>weather.wundergrund</code>.<br />
Die notwendigen Items sehen wie folgt aus:</p>
<pre><code class="language-yaml">
%YAML 1.1
---
# items/wetter.yaml
weather:

    wundergrund:

        windrichtung:
            type: str
            wug_matchstring: current_observation/wind_dir

        windrichtung_grad:
            type: num
            wug_matchstring: current_observation/wind_degrees

        windgeschwindigkeit:
            type: num
            value: -9999
            wug_matchstring: current_observation/wind_kph
            wug_datatype: positive

            ms:
                type: num
                eval: (sh.weather.wundergrund.windgeschwindigkeit()/3.6)
                eval_trigger: weather.wundergrund.windgeschwindigkeit

            beaufort:
                type: num

            string:
                type: str
               
        windboeen:
            type: num
            value: -9999
            wug_matchstring: current_observation/wind_gust_kph
            wug_datatype: positive
</code></pre>
<p><strong>Tipp:</strong> Neben dem Wind gibt es über Wundergrund noch viele weitere Wetterdaten.</p>
<h1>Anzeige der Windrichtung in der smartVISU</h1>
<p>Die Windrichtung lässt sich nun in der smartVISU 2.9 sehr einfach ausgeben:</p>
<pre><code class="language-twig">
{{ icon.compass('weather.wundergrund.windrichtung_compass', '', 'weather.wundergrund.windrichtung_grad',  '0', '360', '') }}
{{ basic.print('weather.wundergrund.windrichtung', 'weather.wundergrund.windrichtung', 'text') }}
</code></pre>
<p>Das Ergebnis ist eine sehr schöne Darstellung der Windrichtung:</p>
<p><img decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/04/windrichtung.jpg" alt="" class="alignnone size-full wp-image-1521" width="124" height="66" /></p>
<h1>Windstärke auswerten und in der smartVISU anzeigen</h1>
<p>Als nächstes soll die Windstärke ausgewertet werden. Dafür dient die nach Sir Francis Beaufort benannte Beaufortskala, die Windstärken in 13 Bereichte von 0 (Windstille) bis 12 (Orkan) klassifiziert.</p>
<p>Für diese Skala ist der Wert im Item <code>weather.wundergrund.windgeschwindigkeit.ms</code> notwendig, das via Eval-Ausdruck die Windgeschwindigkeit von Kilometer pro Stunde in Meter pro Sekunde umrechnet (<code>sh.weather.wundergrund.windgeschwindigkeit()/3.6</code>). Die Umrechnung triggert jedes Mal, wenn sich <code>weather.wundergrund.windgeschwindigkeit</code> verändert.</p>
<p>Für die Auswertung der Windstärke muss unter <code>logics/wind.py</code> eine neue Logik erstellt werden, die die Items <code>weather.wundergrund.windgeschwindigkeit.string</code> und <code>weather.wundergrund.windgeschwindigkeit.beaufort</code> befüllt:<br />
Der Eintrag in der <code>etc/logic.yaml</code> sieht wie folgt aus:</p>
<pre><code class="language-yaml">
WindLogic:
    crontab: init
    filename: wind.py
    watch_item: weather.wundergrund.windgeschwindigkeit.ms
</code></pre>
<p>Die Logik löst also jedes Mal aus, wenn sich <code>weather.wundergrund.windgeschwindigkeit.ms</code> ändert.</p>
<p>Der Code der Logik in der Datei <code>logics/wind.py</code> mappt nun die Windgeschwindigkeit in Meter pro Sekunde auf die Beaufortskala:</p>
<pre><code class="language-python">
if sh.weather.wundergrund.windgeschwindigkeit.ms() &lt; 0.3:
    sh.weather.wundergrund.windgeschwindigkeit.string("Windstille")
    sh.weather.wundergrund.windgeschwindigkeit.beaufort(0)
elif 0.3 &lt;= sh.weather.wundergrund.windgeschwindigkeit.ms() &lt; 1.6:
    sh.weather.wundergrund.windgeschwindigkeit.string("leiser Zug")
    sh.weather.wundergrund.windgeschwindigkeit.beaufort(1)
elif 1.6 &lt;= sh.weather.wundergrund.windgeschwindigkeit.ms() &lt; 3.4:
    sh.weather.wundergrund.windgeschwindigkeit.string("leichte Brise")
    sh.weather.wundergrund.windgeschwindigkeit.beaufort(2)
elif 3.4 &lt;= sh.weather.wundergrund.windgeschwindigkeit.ms() &lt; 5.5:
    sh.weather.wundergrund.windgeschwindigkeit.string("schwacher Wind")
    sh.weather.wundergrund.windgeschwindigkeit.beaufort(3)
elif 5.5 &lt;= sh.weather.wundergrund.windgeschwindigkeit.ms() &lt; 8.0:
    sh.weather.wundergrund.windgeschwindigkeit.string("mäßiger Wind")
    sh.weather.wundergrund.windgeschwindigkeit.beaufort(4)
elif 8.0 &lt;= sh.weather.wundergrund.windgeschwindigkeit.ms() &lt; 10.8:
    sh.weather.wundergrund.windgeschwindigkeit.string("frischer Wind")
    sh.weather.wundergrund.windgeschwindigkeit.beaufort(5)
elif 10.8 &lt;= sh.weather.wundergrund.windgeschwindigkeit.ms() &lt; 13.9:
    sh.weather.wundergrund.windgeschwindigkeit.string("starker Wind")
    sh.weather.wundergrund.windgeschwindigkeit.beaufort(6)
elif 13.9 &lt;= sh.weather.wundergrund.windgeschwindigkeit.ms() &lt; 17.2:
    sh.weather.wundergrund.windgeschwindigkeit.string("steifer Wind")
    sh.weather.wundergrund.windgeschwindigkeit.beaufort(7)
elif 17.2 &lt;= sh.weather.wundergrund.windgeschwindigkeit.ms() &lt; 20.8:
    sh.weather.wundergrund.windgeschwindigkeit.string("stürmischer Wind")
    sh.weather.wundergrund.windgeschwindigkeit.beaufort(8)
elif 20.8 &lt;= sh.weather.wundergrund.windgeschwindigkeit.ms() &lt; 24.5:
    sh.weather.wundergrund.windgeschwindigkeit.string("Sturm")
    sh.weather.wundergrund.windgeschwindigkeit.beaufort(9)
elif 24.5 &lt;= sh.weather.wundergrund.windgeschwindigkeit.ms() &lt; 28.5:
    sh.weather.wundergrund.windgeschwindigkeit.string("schwerer Sturm")
    sh.weather.wundergrund.windgeschwindigkeit.beaufort(10)
elif 28.5 &lt;= sh.weather.wundergrund.windgeschwindigkeit.ms() &lt; 32.7:
    sh.weather.wundergrund.windgeschwindigkeit.ms.string("orkanartiger Sturm")
    sh.weather.wundergrund.windgeschwindigkeit.beaufort(11)
else:
    sh.weather.wundergrund.windgeschwindigkeit.string("Orkan")
    sh.weather.wundergrund.windgeschwindigkeit.beaufort(12)
</code></pre>
<p>Damit die Logik effektiv wird, muss SmartHomeNG neu gestartet oder die Logik via Backend-Plugin aktiviert werden.</p>
<p>Sinnvollerweise kann diese Logik auch in einer Funktion gekapselt werden. Dies ist an einem Alternativansatz, der mit einer Lookup-Tabelle arbeitet, im Folgenden dargestellt:</p>
<pre><code class="language-python"><span class="pl-c">#!/usr/bin/env python3</span>
<span class="pl-c"># beaufort3.py</span>

<span class="pl-k">def</span> <span class="pl-en">get_beaufort</span>(<span class="pl-smi">speed</span>):
    <span class="pl-s"><span class="pl-pds">"""</span></span>
<span class="pl-s">    :parameter speed: windspeed in meter per second</span>
<span class="pl-s">    :return: a tuple of a string with the (german) description and an integer with beaufort speed</span>
<span class="pl-s">    <span class="pl-pds">"""</span></span>
    table <span class="pl-k">=</span> [ 
        (  <span class="pl-c1">0.3</span>, <span class="pl-s"><span class="pl-pds">"</span>Windstille<span class="pl-pds">"</span></span>,<span class="pl-c1">0</span>),
        (  <span class="pl-c1">1.6</span>, <span class="pl-s"><span class="pl-pds">"</span>leiser Zug<span class="pl-pds">"</span></span>,<span class="pl-c1">1</span>),
        (  <span class="pl-c1">3.4</span>, <span class="pl-s"><span class="pl-pds">"</span>leichte Brise<span class="pl-pds">"</span></span>,<span class="pl-c1">2</span>),
        (  <span class="pl-c1">5.5</span>, <span class="pl-s"><span class="pl-pds">"</span>schwacher Wind<span class="pl-pds">"</span></span>,<span class="pl-c1">3</span>),
        (  <span class="pl-c1">8.0</span>, <span class="pl-s"><span class="pl-pds">"</span>mäßiger Wind<span class="pl-pds">"</span></span>,<span class="pl-c1">4</span>),
        ( <span class="pl-c1">10.8</span>, <span class="pl-s"><span class="pl-pds">"</span>frischer Wind <span class="pl-pds">"</span></span>,<span class="pl-c1">5</span>),
        ( <span class="pl-c1">13.9</span>, <span class="pl-s"><span class="pl-pds">"</span>starker Wind<span class="pl-pds">"</span></span>,<span class="pl-c1">6</span>),
        ( <span class="pl-c1">17.2</span>, <span class="pl-s"><span class="pl-pds">"</span>steifer Wind<span class="pl-pds">"</span></span>,<span class="pl-c1">7</span>),
        ( <span class="pl-c1">20.8</span>, <span class="pl-s"><span class="pl-pds">"</span>stürmischer Wind<span class="pl-pds">"</span></span>,<span class="pl-c1">8</span>),
        ( <span class="pl-c1">24.5</span>, <span class="pl-s"><span class="pl-pds">"</span>Sturm<span class="pl-pds">"</span></span>,<span class="pl-c1">9</span>),
        ( <span class="pl-c1">28.5</span>, <span class="pl-s"><span class="pl-pds">"</span>schwerer Sturm<span class="pl-pds">"</span></span>,<span class="pl-c1">10</span>),
        ( <span class="pl-c1">32.7</span>, <span class="pl-s"><span class="pl-pds">"</span>orkanartiger Sturm<span class="pl-pds">"</span></span>,<span class="pl-c1">11</span>),
        ( <span class="pl-c1">999</span>,  <span class="pl-s"><span class="pl-pds">"</span>Orkan<span class="pl-pds">"</span></span>,<span class="pl-c1">12</span>) ]
    
    <span class="pl-k">try</span>:
        description <span class="pl-k">=</span> <span class="pl-c1">min</span>(<span class="pl-c1">filter</span>(<span class="pl-k">lambda</span> <span class="pl-smi">x</span>: x[<span class="pl-c1">0</span>] <span class="pl-k">&gt;=</span> speed, table))[<span class="pl-c1">1</span>]
        bft <span class="pl-k">=</span> <span class="pl-c1">min</span>(<span class="pl-c1">filter</span>(<span class="pl-k">lambda</span> <span class="pl-smi">x</span>: x[<span class="pl-c1">0</span>] <span class="pl-k">&gt;=</span> speed, table))[<span class="pl-c1">2</span>]
        <span class="pl-k">return</span> description,bft
    <span class="pl-k">except</span> <span class="pl-c1">ValueError</span>:
        <span class="pl-k">return</span> <span class="pl-c1">None</span>, <span class="pl-c1">None</span>

decription, bft <span class="pl-k">=</span> get_beaufort(sh.weather.wundergrund.windgeschwindigkeit.ms())
sh.weather.wundergrund.windgeschwindigkeit.string(description)
sh.weather.wundergrund.windgeschwindigkeit.beaufort(bft)
</code></pre>
<p>&nbsp;</p>
<p>In der smartVISU können diese Werte nun wie folgt angezeigt werden:</p>
<pre><code class="language-twig">
{{ basic.symbol('', '', '', 'weather_wind_speed_bft') }}                       
Bft: {{ basic.print('wind_weatherstation_bfvalue', 'knx.weather.wind.beaufort') }}, 
{{ basic.print('wind_weatherstation_string', 'knx.weather.wind.string', 'text') }}
</code></pre>
<p>Das Ergebnis:</p>
<p><img decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/04/beaufort.jpg" alt="" class="alignnone size-full wp-image-1544" width="180" height="55" /></p>
<p><em>(Die in diesem Artikel verwendeten Screenshots wurden selber erstellt. 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/vom-winde-verweht/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>
