<?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>Alarm &#8211; SmartHomeNG | smarthome knx homematic mqtt hue 1wire home automation</title>
	<atom:link href="https://www.smarthomeng.de/tag/alarm/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, 24 Jan 2021 11:54:51 +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>Alarm &#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>Blinken &#8211; per Logik</title>
		<link>https://www.smarthomeng.de/blinken-per-logik</link>
					<comments>https://www.smarthomeng.de/blinken-per-logik#comments</comments>
		
		<dc:creator><![CDATA[gama]]></dc:creator>
		<pubDate>Sun, 04 Nov 2018 09:16:27 +0000</pubDate>
				<category><![CDATA[Beispiel-Implementierungen]]></category>
		<category><![CDATA[Logics]]></category>
		<category><![CDATA[Tipps & Tricks]]></category>
		<category><![CDATA[Alarm]]></category>
		<category><![CDATA[Blinklicht]]></category>
		<category><![CDATA[Logiken]]></category>
		<guid isPermaLink="false">https://www.smarthomeng.de/?p=2188</guid>

					<description><![CDATA[Die Idee für die Logik kam aus meinem Alarmmodul. Dort sollten im Alarm-/Feuer-/Panikfall die Lichter an der Hauswand und die Gartenbeleuchtung im Wechsel blinken. Aber auch für die Signalisieren auf Taster LEDs könnte die Logik ihren Einsatz finden. Beispielsweise um im Schlafzimmer einen Status per LED auszugeben, ohne dass die<a class="moretag" href="https://www.smarthomeng.de/blinken-per-logik"> Weiterlesen&#8230;</a>]]></description>
										<content:encoded><![CDATA[<p>Die Idee für die Logik kam aus meinem Alarmmodul. Dort sollten im Alarm-/Feuer-/Panikfall die Lichter an der Hauswand und die Gartenbeleuchtung im Wechsel blinken. Aber auch für die Signalisieren auf Taster LEDs könnte die Logik ihren Einsatz finden. Beispielsweise um im Schlafzimmer einen Status per LED auszugeben, ohne dass die LED die ganze Nacht leuchtet.</p>
<p>Somit war der Grundstein für die Logik gelegt, die möglichst flexibel, für unterschiedliche Anwendungen, konfigurierbar sein soll.</p>
<h4>Funktion:</h4>
<p>Gesteuert wird die Logik über ein control-item, welches zugleich in der Logik Konfiguration als watch-item dient. Wir das control-item auf True gesetzt, so läuft die Logik. False stoppt die Blinkroutine.</p>
<p><span><strong>blink_cycles</strong> setzt Initial den Countdown, der mit jedem Aufruf um 1 nach unten zählt. Bei 0 stoppt die Logik und setzt zudem das control-item auf False. </span></p>
<p><span><strong>blink_interval</strong> bestimmt die Blinkabstand in Sekunden. </span></p>
<p><span>Mit <strong>items_cyclic</strong> und </span><span><strong>items_anticyclic</strong> werden die Items übergeben, die blinken sollen. Antizyklische Items werden immer dann aus/an wenn die zyklischen Items an/aus sind. </span></p>
<p>Bevor die items zum blinken gebracht werden, sichert die Logik die ursprünglichen Werte, die auch am Ende wieder hergestellt werden.</p>
<p>Um die Routine ohne aktives schalten der Items testen zu können, wurde noch dry_run aufgenommen.</p>
<p>Zusammengefasst ergibt sich folgende Beispiel-Konfiguration für <strong>../etc/logic.yaml</strong>:</p>
<pre class="line-numbers"><code class="language-yaml">visual_alarm:
    filename: blinker.py
    watch_item: HOME.alarm.action.blinkinglight
    set_items_cyclic:
        - AUSSEN.south.light.outer
        - AUSSEN.west.light.outer
    set_items_anticyclic:
        - AUSSEN.south.light.inner
        - AUSSEN.east.light.door
        - AUSSEN.west.light.nested
    set_blink_cycles: 4 # -1 for endless loop 
    set_blink_interval: 4
    dry_run: 1</code></pre>
<p>Alle items müssen vom Typ boolean sein, da nur einfache Schaltoperationen durchgeführt werden.</p>
<p>Die Logik lässt sich relativ einfach nutzen, indem das im watch_item verbundene Item, also im Beispiel <code class="language-python">HOME.alarm.action.blinkinglight</code>, auf True gesetzt wird. Die Logik ruft sich selbst solange auf, bis <code class="language-python">set_blink_cycles</code> erreicht ist oder vorher das watch_item auf False gesetzt wurde. Am Ende wird das watch_item auf von der Logik auf False gesetzt.</p>
<p>Die Logik selbst ist in <strong>../logics/blinker.py</strong>:</p>
<pre class="line-numbers"><code class="language-python">
#!/usr/bin/env python3
# vim: tabstop=2 softtabstop=2 shiftwidth=2 expandtab

# Logic blinker.py

# LOGIC config
# -------------------------------------------------------
# visual_alarm:
#   filename: blinker.py
#   watch_item: HOME.alarm.action.blinkinglight
#   set_items_cyclic:
#     - AUSSEN.south.light.outer
#     - AUSSEN.west.light.outer
#   set_items_anticyclic: 
#     - AUSSEN.south.light.inner
#     - AUSSEN.east.light.door 
#     - AUSSEN.west.light.nested
#   set_blink_cycles: -1 " -1: endless 
#   set_blink_interval: 2
#   dry_run: 0 

control_item_name = trigger['source'] 
control_item = sh.return_item(control_item_name)
triggered_by = trigger['by'] 


if control_item is not None:
  logger.info("LOGIC blinker.py: {0} triggered from source {1} by {2}".format(logic.name, control_item_name, triggered_by))

  # control_item_active = trigger['value']
  control_item_active = control_item()

  # set parameters from logic config
  if hasattr(logic, 'set_items_cyclic'):
    blink_items_cyclic = logic.set_items_cyclic

  if hasattr(logic, 'set_items_anticyclic'):
    blink_items_anticyclic = logic.set_items_anticyclic

  if hasattr(logic, 'set_blink_cycles'):
    blink_cycles = int(logic.set_blink_cycles)
  else:
    blink_cycles = 2
    logger.info("LOGIC blinker.py: no blink cycles set, setting to default: {2}".format(blink_cycles))

  if hasattr(logic, 'set_blink_interval'):
    blink_interval = int(logic.set_blink_interval)
  else:
    blink_interval = 2
    logger.info("LOGIC blinker.py: no blink interval set, setting to default: {2}".format(blink_interval))

  if hasattr(logic, 'dry_run'):
    dry_run = (int(logic.dry_run) &gt; 0)
  else:
    dry_run = False

  if control_item_active == True:

    # first call?
    if not hasattr(logic, 'blink_init'):
      logger.info("LOGIC blinker.py: initiating {0} blinks for {1} cyclic and {2} anti-cyclic items".format(blink_cycles, len(blink_items_cyclic), len(blink_items_anticyclic)))
      logic.blink_init = True

      blink_items = blink_items_cyclic + blink_items_anticyclic
      if len(blink_items) &gt; 0:
        # SAVE item states
        logic.saved_items = {}
        for item_name in blink_items:
          item = sh.return_item(item_name)
          logic.saved_items[item_name] = item()
          logger.info("LOGIC blinker.py: save {0} = {1}".format(item_name, item()))

      if dry_run == True:
        logger.warn("LOGIC blinker.py: test mode, dry run active")

      else:
        logger.warn("LOGIC blinker.py: no blink items set")
 

    # prepare blink
    if hasattr(logic, 'blink_value'):
      logic.blink_value = not logic.blink_value
    else:
      logic.blink_value = True

    if hasattr(logic, 'blink_countdown'):
      logic.blink_countdown -= 1
    else:
      logic.blink_countdown = blink_cycles
     
    # any blinks left?
    if logic.blink_countdown &gt; 0 or blink_cycles == -1:
      if blink_cycles == -1:
        logger.info("LOGIC blinker.py BLINK (endless)")
      else:
        logger.info("LOGIC blinker.py BLINK ({0} cycles remaining)".format(logic.blink_countdown))

      # set all cyclic items
      for item_name in blink_items_cyclic:
        item = sh.return_item(item_name)
        logger.info("LOGIC blinker.py SET {item} to {value})".format(item=item_name, value=logic.blink_value))
        if dry_run == False:
          item(logic.blink_value)

      # set all anti-cyclic items
      for item_name in blink_items_anticyclic:
        item = sh.return_item(item_name)
        logger.info("LOGIC blinker.py SET {item} to {value})".format(item=item_name, value=(not logic.blink_value)))
        if dry_run == False:
          item(not logic.blink_value)

      sh.trigger("logics.{0}".format(logic.name), by=trigger['by'], source=trigger['source'], value=trigger['value'], dt=sh.now() + datetime.timedelta(seconds=blink_interval))

    else:
      logger.info("LOGIC blinker.py countdown finished, set control item to False")
      control_item(False) # this triggers logic again!

  else:
    logger.info("LOGIC blinker.py control item set to false: stop blink logic, restore saved item values")

    # RESTORE item states
    if hasattr(logic, 'saved_items'):
      for item_name in logic.saved_items:
        item = sh.return_item(item_name)
        value = logic.saved_items[item_name]
        logger.info("LOGIC blinker.py: restore {0} = {1}".format(item_name, item()))
        if dry_run == False:
          item(value)
      
    # reset persistent values
    if hasattr(logic, 'saved_items'):
      delattr(logic, 'saved_items')  
    if hasattr(logic, 'blink_countdown'):
      delattr(logic, 'blink_countdown')  
    if hasattr(logic, 'blink_value'):
      delattr(logic, 'blink_value')  
    if hasattr(logic, 'blink_init'):
      delattr(logic, 'blink_init')  
    
else:
  logger.info("LOGIC blinker.py triggered without source... ignoring...")</code></pre>
<p>&nbsp;</p>
<h4>Überarbeitung im Januar 2021:</h4>
<p>Diese Logik wurde aufgrund weitere Anforderungen im Januar 2021 ergänzt. (siehe <a href="https://knx-user-forum.de/forum/supportforen/smarthome-py/1600954-blinker-py-konfigurieren">Thread im Forum</a>) Die folgende Version vom 18. Januar 2021 blinkt mit einem oder zwei Items:</p>
<p>&nbsp;</p>
<pre class="line-numbers"><code class="language-python">
#!/usr/bin/env python3
# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab

# Logic blinker2.py

# LOGIC config
# -------------------------------------------------------
# visual_alarm:
#     filename: blinker2.py
#     watch_item: HOME.alarm.action.blinkinglight
#     set_items_cyclic:
#         - AUSSEN.south.light.outer
#         - AUSSEN.west.light.outer
#     set_items_anticyclic:
#         - AUSSEN.south.light.inner
#         - AUSSEN.east.light.door
#         - AUSSEN.west.light.nested
#     set_blink_cycles: -1 ' -1: endless
#     set_blink_interval: 2
#     dry_run: 0

control_item_name = trigger['source']
control_item = sh.return_item(control_item_name)
triggered_by = trigger['by']

if control_item is not None:
    logger.info(f'LOGIC blinker.py: {logic.name} triggered from source {control_item_name} by {triggered_by}')

    # control_item_active = trigger['value']
    control_item_active = control_item()

    # set parameters from logic config
    blink_items_cyclic = []
    if hasattr(logic, 'set_items_cyclic'):
        blink_items_cyclic = logic.set_items_cyclic
    if blink_items_cyclic == 'None':
        blink_items_cyclic = []
    if isinstance(blink_items_cyclic, str):
        blink_items_cyclic = [blink_items_cyclic, ]

    # do we have blink items?
    if not isinstance(blink_items_cyclic, list) or len(blink_items_cyclic) == 0:
        logger.info('LOGIC blinker.py: error, no cyclic blink items set. Aborting')
    else:

        blink_items_anticyclic = []
        if hasattr(logic, 'set_items_anticyclic'):
            blink_items_anticyclic = logic.set_items_anticyclic
        if blink_items_anticyclic == 'None':
            blink_items_anticyclic = []
        elif isinstance(blink_items_anticyclic, str):
            blink_items_anticyclic = [blink_items_anticyclic, ]

        # did we get strange data?
        if not isinstance(blink_items_anticyclic, list):
            blink_items_anticyclic = []

        if hasattr(logic, 'set_blink_cycles'):
            blink_cycles = int(logic.set_blink_cycles)
        else:
            blink_cycles = 2
            logger.info(f'LOGIC blinker.py: no blink cycles set, setting to default: {blink_cycles}')

        if hasattr(logic, 'set_blink_interval'):
            blink_interval = int(logic.set_blink_interval)
        else:
            blink_interval = 2
            logger.info(f'LOGIC blinker.py: no blink interval set, setting to default: {blink_interval}')

        if hasattr(logic, 'dry_run'):
            dry_run = (int(logic.dry_run) &gt; 0)
        else:
            dry_run = False

        if control_item_active:

            # first call?
            if not hasattr(logic, 'blink_init'):
                logger.info(f'LOGIC blinker.py: initiating {blink_cycles} blinks for {len(blink_items_cyclic)} cyclic and {len(blink_items_anticyclic)} anti-cyclic items')
                logic.blink_init = True

                blink_items = blink_items_cyclic + blink_items_anticyclic
                if len(blink_items) &gt; 0:
                    # SAVE item states
                    logic.saved_items = {}
                    for item_name in blink_items:
                        item = sh.return_item(item_name)
                        if item:
                            logic.saved_items[item_name] = item()
                            logger.info(f'LOGIC blinker.py: save {item_name} = {item()}')

                    if dry_run:
                        logger.warn('LOGIC blinker.py: test mode, dry run active')

                else:
                    logger.warn('LOGIC blinker.py: no blink items set')

            # prepare blink
            if hasattr(logic, 'blink_value'):
                logic.blink_value = not logic.blink_value
            else:
                logic.blink_value = True

            if hasattr(logic, 'blink_countdown'):
                logic.blink_countdown -= 1
            else:
                logic.blink_countdown = blink_cycles

            # any blinks left?
            if logic.blink_countdown &gt; 0 or blink_cycles == -1:
                if blink_cycles == -1:
                    logger.info('LOGIC blinker.py BLINK (endless)')
                else:
                    logger.info(f'LOGIC blinker.py BLINK ({logic.blink_countdown} cycles remaining)')

                # set all cyclic items
                for item_name in blink_items_cyclic:
                    item = sh.return_item(item_name)
                    logger.info(f'LOGIC blinker.py SET {item_name} to {logic.blink_value}')
                    if not dry_run:
                        item(logic.blink_value)
                        print(f'    - {item.id()}:{item()}')

                # set all anti-cyclic items
                for item_name in blink_items_anticyclic:
                    item = sh.return_item(item_name)
                    logger.info(f'LOGIC blinker.py SET {item_name} to {not logic.blink_value}')
                    if not dry_run:
                        item(not logic.blink_value)
                        print(f'    - {item.id()}:{item()}')

                sh.trigger(f'logics.{logic.name}', by=trigger['by'], source=trigger['source'], value=trigger['value'], dt=sh.now() + datetime.timedelta(seconds=blink_interval))

            else:
                logger.info('LOGIC blinker.py countdown finished, set control item to False')
                control_item(False)  # this triggers logic again!

        else:
            logger.info('LOGIC blinker.py control item set to false: stop blink logic, restore saved item values')

            # RESTORE item states
            if hasattr(logic, 'saved_items'):
                for item_name in logic.saved_items:
                    item = sh.return_item(item_name)
                    value = logic.saved_items[item_name]
                    logger.info(f'LOGIC blinker.py: restore {item_name} = {item()}')
                    if not dry_run:
                        item(value)

            # reset persistent values
            if hasattr(logic, 'saved_items'):
                delattr(logic, 'saved_items')
            if hasattr(logic, 'blink_countdown'):
                delattr(logic, 'blink_countdown')
            if hasattr(logic, 'blink_value'):
                delattr(logic, 'blink_value')
            if hasattr(logic, 'blink_init'):
                delattr(logic, 'blink_init')

else:
    logger.info('LOGIC blinker.py triggered without source... ignoring...')
</code></pre>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.smarthomeng.de/blinken-per-logik/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Das Traffic Plugin am Beispiel eines Staualarms</title>
		<link>https://www.smarthomeng.de/das-traffic-plugin-am-beispiel-eines-staualarms</link>
					<comments>https://www.smarthomeng.de/das-traffic-plugin-am-beispiel-eines-staualarms#respond</comments>
		
		<dc:creator><![CDATA[Marc René Frieß]]></dc:creator>
		<pubDate>Sat, 21 Apr 2018 16:04:27 +0000</pubDate>
				<category><![CDATA[Plugins]]></category>
		<category><![CDATA[Tipps & Tricks]]></category>
		<category><![CDATA[Alarm]]></category>
		<category><![CDATA[Fahrzeit]]></category>
		<category><![CDATA[Google Directions]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[Traffic]]></category>
		<category><![CDATA[Traffic Plugin]]></category>
		<guid isPermaLink="false">https://www.smarthomeng.de/?p=1574</guid>

					<description><![CDATA[Pendeln in deutschen Großstädten ist kein Spaß. Laut einem Artikel von Spiegel Online stehen deutsche Autofahrer im Jahr 475.000 Stunden im Stau. Mit dem Traffic Plugin bietet SmartHomeNG die Möglichkeit, Fahrzeiten über die Google Directions API zu berechnen. So lässt sich auf einfache Art und Weise ein Alarmsystem bauen, dass<a class="moretag" href="https://www.smarthomeng.de/das-traffic-plugin-am-beispiel-eines-staualarms"> Weiterlesen&#8230;</a>]]></description>
										<content:encoded><![CDATA[<p>Pendeln in deutschen Großstädten ist kein Spaß. Laut einem Artikel von <a href="http://www.spiegel.de/auto/aktuell/adac-autofahrer-stehen-475-000-stunden-im-stau-a-1189334.html" target="_blank" rel="noopener">Spiegel Online</a> stehen deutsche Autofahrer im Jahr 475.000 Stunden im Stau.</p>
<p>Mit dem Traffic Plugin bietet SmartHomeNG die Möglichkeit, Fahrzeiten über die Google Directions API zu berechnen.</p>
<p><span id="more-1574"></span></p>
<p>So lässt sich auf einfache Art und Weise ein Alarmsystem bauen, dass einem im Büro Bescheid gibt, wenn es Zeit wird zu fahren (oder man länger bleiben sollte, damit sich der Stau wieder auflösen kann).</p>
<p>Die Erkennung, wo man sich gerade befindet, wird dabei, wie in <a href="https://www.smarthomeng.de/geozonen-basierte-services-mit-der-egigeozone-app-und-dem-network-plugin" target="_blank" rel="noopener">https://www.smarthomeng.de/geozonen-basierte-services-mit-der-egigeozone-app-und-dem-network-plugin</a> beschrieben, über EgiGeoZone und das Network Plugin umgesetzt.</p>
<h1>Das Traffic Plugin</h1>
<p>Die automatisch generierte Doku zum Traffic Plugin findet sich unter <a href="https://www.smarthomeng.de/user/plugins_doc/config/traffic.html" target="_blank" rel="noopener">https://www.smarthomeng.de/user/plugins_doc/config/traffic.html</a>.</p>
<p>Die Readme liegt unter <a href="https://www.smarthomeng.de/user/plugins/traffic/README.html" target="_blank" rel="noopener">https://www.smarthomeng.de/user/plugins/traffic/README.html</a>, der Quellcode auf Github unter <a href="https://github.com/smarthomeNG/plugins/tree/master/traffic" target="_blank" rel="noopener">https://github.com/smarthomeNG/plugins/tree/master/traffic</a>.</p>
<p>Der Support-Thread im Forum findet sich unter <a href="https://knx-user-forum.de/forum/supportforen/smarthome-py/1048446-traffic-plugin-support-thread" target="_blank" rel="noopener">https://knx-user-forum.de/forum/supportforen/smarthome-py/1048446-traffic-plugin-support-thread</a>.</p>
<p>Das Plugin ist schnell in der <code>etc/plugin.yaml</code> konfiguriert:</p>
<pre><code class=" language-yaml">
traffic:
    class_name: Traffic
    class_path: plugins.traffic
    apikey: your own api key
    language: de (optional)
</code></pre>
<p>Der persönliche API Key für die Directions API von Google kann unter <a href="https://developers.google.com/maps/documentation/directions/intro?hl=de" target="_blank" rel="noopener">https://developers.google.com/maps/documentation/directions/intro?hl=de</a> beantragt werden.</p>
<h1>Die Items</h1>
<p>Wichtig sind dabei folgende drei Items zur Erfassung des aktuellen Orts, an dem man sich aufhält. Die Items wurden bereits in dem oben genanntem Artikel zu EgiGeoZone eingeführt, und werden, wie im Artikel beschrieben, von EgiGeoZone bedatet:</p>
<pre class="language-yaml code-toolbar"><code class=" language-yaml"><span class="token key atrule">location</span><span class="token punctuation">:</span>

        <span class="token key atrule">lat</span><span class="token punctuation">:</span>
            <span class="token key atrule">type</span><span class="token punctuation">:</span> str
            <span class="token key atrule">visu_acl</span><span class="token punctuation">:</span> ro
            <span class="token key atrule">cache</span><span class="token punctuation">:</span> <span class="token string">'yes'</span>

        <span class="token key atrule">lon</span><span class="token punctuation">:</span>
            <span class="token key atrule">type</span><span class="token punctuation">:</span> str
            <span class="token key atrule">visu_acl</span><span class="token punctuation">:</span> ro
            <span class="token key atrule">cache</span><span class="token punctuation">:</span> <span class="token string">'yes'</span>

        <span class="token key atrule">zone</span><span class="token punctuation">:</span>
            <span class="token key atrule">type</span><span class="token punctuation">:</span> str
            <span class="token key atrule">visu_acl</span><span class="token punctuation">:</span> ro
            <span class="token key atrule">cache</span><span class="token punctuation">:</span> <span class="token string">'yes'</span>
</code></pre>
<p>Wichtig dabei ist, dass der Zonenname in EgiGeoZone für die Arbeitsstätte (oder mehrere Arbeitsstätten) den String &#8222;Arbeit&#8220; enthält und der Zonenname für daheim &#8222;Home&#8220;. Alternative Namen gehen auch, müssen dann aber in der Logik weiter unten angepasst werden.</p>
<p>Zusätzlich müssen noch die Home Koordinaten jeweils als Item definiert werden.<br />
<strong>Tipp:</strong> Alternativ können auch die Attribute <code>_lat</code> und <code>_lon</code> direkt auf dem SmartHome Objekt (<code>bin/smarthome.py</code>) genutzt werden.</p>
<pre class="language-yaml code-toolbar"><code class=" language-yaml"><span>location:
</span><span>
</span><span>    home:
</span><span>        lat:
</span><span>            type: </span>str
            <span>visu_acl: </span>ro
            <span>value: </span>48.xxxxxxx
            <span>cache: </span><span>'yes'
</span><span>
</span><span>        </span><span>lon:
</span><span>            type: </span>str
            <span>visu_acl: </span>ro
            <span>value: </span>11.xxxxxxx
            <span>cache: </span><span>'yes'</span></code></pre>
<p>Für die Speicherung der Reisedaten, die vom Traffic Plugin zurückgegeben werden, werden folgende Items benötigt:</p>
<pre class="language-yaml code-toolbar"><code class=" language-yaml">travel_info:

    calculate_way_home:
       type: bool
       cache: 'yes'
    
    calculate_way_work:
        type: bool
        cache: 'yes'

    travel_time:
        type: num
        
        in_traffic:
            type: num

    travel_distance:
        type: num
        
    travel_summary:
        type: str</code></pre>
<h1>Die Logik traffic_info.py</h1>
<p>Als nächstes muss die aktuelle Fahrzeit zyklisch jede Minute über eine Logik vom Plugin abgefragt werden.</p>
<pre><code class="language-yaml">TrafficInfo:
    filename: traffic_info.py
    crontab: '* * * *'</code></pre>
<p>Der Code der Logik sieht wie folgt aus:</p>
<pre><code class="language-yaml">
# Codeblock 1 - Fahrt von der Arbeit nach Hause
if sh.now().hour &lt; 20 and sh.now().hour &gt; 14 and sh.now().weekday() in [0, 1, 2, 3, 4] and ('Arbeit' in sh.location.zone()):
    sh.location.calculate_way_home(1)
    destination = sh.location.home.lat() + "," + sh.location.home.lon()
    origin = sh.location.lat() + "," + sh.location.lon()
else:
    sh.location.calculate_way_home(0)

# Codeblock 2 - Fahrt von zu Hause in die Arbeit
if sh.now().hour &lt; 10 and sh.now().hour &gt; 4 and sh.now().weekday() in [0, 1, 2, 3, 4] and sh.location.zone() == 'Home':
    sh.location.calculate_way_work(1)
    destination = "Musterstraße 5, München"
    origin = sh.location.home.lat() + "," + sh.location.home.lon()
else:
    sh.location.calculate_way_work(0)

# Codeblock 3 - Default: Fahrt nach Hause von "irgendwo".
if not sh.location.calculate_way_work() and sh.location.zone() != 'Home':
    destination = sh.location.home.lat() + "," + sh.location.home.lon()
    origin = sh.location.lat() + "," + sh.location.lon()
    sh.location.calculate_way_home(1)

# Codeblock 4 - Wege- und Zeitbestimmung, ggf. Alarmmeldung oder Reset der Items
if sh.location.calculate_way_work() or sh.location.calculate_way_home():
    route = sh.traffic.get_route_info(origin, destination, False)
    if route is not None:
        summary = route['summary'] + ": %.1f km in %.0f min" % (round(route['distance'] / 1000, 2), round(route['duration_in_traffic'] / 60, 2))
        sh.location.travel_time(route['duration'])
        if 'duration_in_traffic' in route:
            sh.location.travel_time.in_traffic(route['duration_in_traffic'])
        sh.location.travel_distance(route['distance'])
        sh.location.travel_summary(summary)
        if 'Arbeit' in sh.location.zone() and sh.location.travel_time.in_traffic() &gt;= 2500 &gt; sh.location.travel_time.in_traffic.prev_value() and sh.now().hour &lt; 20 and sh.now().hour &gt; 14:
            sh.pushbullet.note("Alarm: Verkehr", "%s Min. Fahrzeit nach Hause!" % round((sh.location.travel_time.in_traffic() / 60), 2))
else:
    sh.location.travel_time('')
    sh.location.travel_time.in_traffic('')
    sh.location.travel_distance('')
    sh.location.travel_summary('-')
</code></pre>
<p>Im ersten Block wird geprüft, ob die aktuelle Uhrzeit zwischen 14:00 und 20:00 liegt (Zeitraum für die Prüfung bzgl. &#8222;Weg von der Arbeit nach Hause&#8220;) und, ob der aktuelle Tag Montag &#8211; Freitag ist. Zusätzlich wird geprüft, ob man sich in einer Zone befindet, deren Name  die Zeichenkette &#8222;Arbeit&#8220; enthält. Ist dies der Fall, so werden das boolsche Item <code>calculate_way_home</code> auf <code>True</code> und als <code>destination</code> die Home-Koordinate gesetzt.</p>
<p>Der zweite Codeblock macht das Gleiche, aber für die (bevorstehende) Anfahrt in die Arbeit von zu Hause aus (4:00-10:00 als Zeitintervall). Die aktuelle Zone enthält den String &#8222;Home&#8220;, als Destination wird die Adresse der Arbeitsstätte gesetzt. <code>calculate_way_work</code> wird auf <code>True</code> gesetzt.</p>
<p>Im dritten Codeblock wird nun geprüft, ob man auf dem Weg zur Arbeit und nicht zu Hause ist. Ist man dies nicht, so wird auf Basis der aktuellen Position (die nicht zwingend die Arbeitsstätte ist) immer die Fahrzeit nach Hause berechnet. Diese kann bspw. in der Visu angezeigt werden. <code>calculate_way_home</code> wird für die nachfolgende Berechnung ebenfalls auf <code>True</code> gesetzt.</p>
<p>Im vierten Codeblock wird nun das Traffic Plugin aufgerufen. Über <code>get_route_info(origin, destination, False)</code> werden die Daten zur Route von der aktuellen Position zum Ziel abgefragt. Das Item <code>location.travel_time</code> wird mit der reinen Fahrzeit <em><strong>ohne</strong> Berücksichtigung der aktuellen Verkehrlage</em>, das Unteritem <code>location.travel_time.in_traffic</code> <em><strong>mit</strong> Berücksichtigung der aktuellen Verkehrslage</em> befüllt.<br />
In das Item <code>location.travel_distance</code> wird die aktuellen Distanz geschrieben.<br />
In <code>location.travel_summary</code> landet ein kurzes Summary als String.<br />
Zuletzt wird eine Alarmmeldung über das <a href="https://www.smarthomeng.de/user/plugins_doc/config/pushbullet.html" target="_blank" rel="noopener">Pushbullet Plugin</a> versendet: <code>sh.pushbullet.note("Alarm: Verkehr", "%s Min. Fahrzeit nach Hause!" % round((sh.location.travel_time.in_traffic() / 60), 2))</code></p>
<p>Das Ergebnis ist hier zu sehen:<br />
<img fetchpriority="high" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/04/Screenshot_20180422-072146.png" alt="" class="alignnone wp-image-1629" width="332" height="590" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/04/Screenshot_20180422-072146.png 1440w, https://www.smarthomeng.de/wp-content/uploads/2018/04/Screenshot_20180422-072146-169x300.png 169w, https://www.smarthomeng.de/wp-content/uploads/2018/04/Screenshot_20180422-072146-768x1365.png 768w, https://www.smarthomeng.de/wp-content/uploads/2018/04/Screenshot_20180422-072146-576x1024.png 576w" sizes="(max-width: 332px) 100vw, 332px" /></p>
<p>Neben der in diesem Artikel gezeigten Grundfunktionalität, lassen sich mit dem Plugin bzw. der Directions API auch noch deutlich mehr Informationen, wie bspw. die vollständigen Routing-Informationen zum Zielort, bestimmen.</p>
<p>Ich persönlich kombiniere einige dieser Daten mit der Anzeige meiner Position und der Wegstrecke nach Hause in Google Maps. Hierfür habe ich ein <a href="https://www.smartvisu.de" target="_blank" rel="noopener">smartVISU</a> Widget geschrieben. Dies ist Thema eines zukünftigen Artikels.</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/das-traffic-plugin-am-beispiel-eines-staualarms/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
