<?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>Logiken &#8211; SmartHomeNG | smarthome knx homematic mqtt hue 1wire home automation</title>
	<atom:link href="https://www.smarthomeng.de/tag/logiken/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>Logiken &#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>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>Anzahl eingeschalteter Lampen ermitteln</title>
		<link>https://www.smarthomeng.de/anzahl-eingeschalteter-lampen-ermitteln</link>
					<comments>https://www.smarthomeng.de/anzahl-eingeschalteter-lampen-ermitteln#comments</comments>
		
		<dc:creator><![CDATA[Martin Sinn]]></dc:creator>
		<pubDate>Sun, 08 Apr 2018 10:08:56 +0000</pubDate>
				<category><![CDATA[Tipps & Tricks]]></category>
		<category><![CDATA[Items]]></category>
		<category><![CDATA[Logiken]]></category>
		<guid isPermaLink="false">https://www.smarthomeng.de/?p=1457</guid>

					<description><![CDATA[Ziel Anzahl und Position der eingeschalteten Lampen ermitteln und visualisieren. Logik Es werden alle Lichter gesucht, die nicht auf Taster oder Level enden und die nicht in Zentral definiert sind. Die eingeschalteten Lichter werden als Link zum Ausschalten gespeichert, so dass sie bequem später ausgeschaltet werden können. /usr/local/smarthome/logics/light.py #!/usr/bin/env python<a class="moretag" href="https://www.smarthomeng.de/anzahl-eingeschalteter-lampen-ermitteln"> Weiterlesen&#8230;</a>]]></description>
										<content:encoded><![CDATA[<h3>Ziel</h3>
<p>Anzahl und Position der eingeschalteten Lampen ermitteln und visualisieren.</p>
<h3>Logik</h3>
<p>Es werden alle Lichter gesucht, die nicht auf Taster oder Level enden und die nicht in Zentral definiert sind. Die eingeschalteten Lichter werden als Link zum Ausschalten gespeichert, so dass sie bequem später ausgeschaltet werden können.</p>
<h4>/usr/local/smarthome/logics/light.py</h4>
<pre><code class="language-python">#!/usr/bin/env python

counter = []

# finde alle Lichter, die eingeschaltet sind (und nicht auf taster oder level enden)
for item in sh.match_items('*.licht.*'):
	if item() and not item.id().endswith('taster') and not item.id().endswith('level') and not item.id().startswith('zentral') and not item.id().endswith('aussen'):
		counter.append(item)

# ermittle licht bool wert
if len(counter) &gt; 0:
	sh.zentral.zaehler.licht(1)
else:
	sh.zentral.zaehler.licht(0)

# setze licht anzahl wert
sh.zentral.zaehler.licht.anzahl(len(counter))
	
# ermittle Namen der Lichter, die eingeschaltet sind
namen = "&lt;ul class='logik_licht'&gt;"
for item in counter:
	parent_item = item.return_parent()
	namen += "&lt;li&gt;&lt;a href=\"#\" class=\"ui-link\" onclick=\"io.write(\'"+item.id()+"\',0);\"&gt;{0} {1}&lt;/a&gt;&lt;/li&gt;".format(str(parent_item), str(item))
	
namen += "&lt;/ul&gt;"
	
# setze Namen der eingeschalteten Lichter
sh.zentral.zaehler.licht.namen(namen.strip())
		
# Logging
logger.info("Es sind {0} Lichter an. ( {1})".format(str(sh.zentral.zaehler.licht.anzahl()), sh.zentral.zaehler.licht.namen()))</code></pre>
<p>Die Logik aktiviert man unter etc/logic.conf mit dem Eintrag von:</p>
<p>&nbsp;</p>
<h4>/usr/local/smarthome/etc/logic.yaml</h4>
<p>In der Zentral.conf habe ich Elemente definiert, die die ermittelten Werte aufnehmen.</p>
<pre><code class="language-yaml">lichter:
    filename: light.py
    watch_item: *.licht.*</code></pre>
<p>&nbsp;</p>
<h4>/usr/local/smarthome/items/Zentral.yaml</h4>
<pre><code class="language-yaml"># /usr/local/smarthome/items/Zentral.conf
zentral:
    name: Zentral

    zaehler:
        name: Zähler
        sv_page: room

        licht:
            name: Licht an
            type: bool
            visu: yes

            anzahl:
                name: Anzahl eingeschalteter Lichter
                type: num
                visu: yes

            namen:
                name: Eingeschaltete Lichter
                type: str
                visu: yes</code></pre>
<p>&nbsp;</p>
<h3>Items</h3>
<p>Folgende Items werden benötigt.</p>
<h4>/usr/local/smarthome/items/EG.yaml</h4>
<pre><code class="language-yaml">eg:
    name: Erdgeschoß

    flur:
        name: Flur
        sv_page: room
        sv_img: scene_hall.png

        licht:
            name: Flur

            decke:
                name: Dimmer
                type: bool
                visu: yes
                visu_acl: rw
                sv_img: light_ceiling_light.png

                level:
                    type: num
                    visu: yes
                    visu_acl: rw</code></pre>
<p>&nbsp;</p>
<h3>HTML-Seite</h3>
<p>Die ermittelten Werte können nun in einer HTML-Seite wie folgt angezeigt werden:</p>
<pre><code class="language-twig">Es sind &lt;strong&gt;{{ basic.value('zentral.zaehler.licht.anzahl.1', 'zentral.zaehler.licht.anzahl', '', '') }}&lt;/strong&gt; Lichter an
&lt;br/&gt;
( {{ basic.value('zentral.zaehler.licht.namen.1', 'zentral.zaehler.licht.namen', '', '') }} )</code></pre>
<p>&nbsp;</p>
<hr />
<p><small>15.02.2014: Original Wiki Beitrag von <strong>ReneHezser<br />
</strong></small><small>19.05.2015: Überarbeitung durch <strong>cstrassburg</strong> </small></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.smarthomeng.de/anzahl-eingeschalteter-lampen-ermitteln/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Scheduler Änderungen funktionieren nicht mehr nach 1.4.x Umstellung</title>
		<link>https://www.smarthomeng.de/sh-trigger-funktioniert-nicht-mehr-nach-1-4-2-umstellung</link>
					<comments>https://www.smarthomeng.de/sh-trigger-funktioniert-nicht-mehr-nach-1-4-2-umstellung#comments</comments>
		
		<dc:creator><![CDATA[Martin Sinn]]></dc:creator>
		<pubDate>Fri, 30 Mar 2018 14:03:20 +0000</pubDate>
				<category><![CDATA[FAQ]]></category>
		<category><![CDATA[Items]]></category>
		<category><![CDATA[Logiken]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[Scheduler]]></category>
		<guid isPermaLink="false">https://www.smarthomeng.de/?p=926</guid>

					<description><![CDATA[Um Namenskonflikte innerhalb von SmartHomeNG zu vermeiden, sind mit der Version 1.4.x von SmartHomeNG für Scheduler mehrere separate Namensräume eingeführt worden. Es gibt jeweils einen eigenen Namensraum für Scheduler, die durch Items Logiken Scheduler erzeugt wurden. Die Scheduler sind im Backend auf unterschiedlichen Reitern auf der Seite Scheduler zu sehen.<a class="moretag" href="https://www.smarthomeng.de/sh-trigger-funktioniert-nicht-mehr-nach-1-4-2-umstellung"> Weiterlesen&#8230;</a>]]></description>
										<content:encoded><![CDATA[<p>Um Namenskonflikte innerhalb von SmartHomeNG zu vermeiden, sind mit der Version 1.4.x von SmartHomeNG für Scheduler mehrere separate Namensräume eingeführt worden.</p>
<p>Es gibt jeweils einen eigenen Namensraum für Scheduler, die durch</p>
<ul>
<li>Items</li>
<li>Logiken</li>
<li>Scheduler</li>
</ul>
<p>erzeugt wurden. Die Scheduler sind im Backend auf unterschiedlichen Reitern auf der Seite <strong>Scheduler</strong> zu sehen. Auf einem vierten Reiter sind die Scheduler zu sehen, die nicht in diese drei Namensräume fallen.</p>
<p>Das erweiterte API um diese Scheduler sauber anzusprechen ist noch auf der To Do Liste.</p>
<p>Zur Zeit können diese Scheduler über die bisherigen Scheduler Methoden angesprochen werden. Den Namen muss dabei jeweils ein Präfix vorangestellt werden.</p>
<p>Für:</p>
<ul>
<li>items   -&gt;   items.&lt;scheduler name&gt;</li>
<li>Logiken   -&gt;   logics.&lt;scheduler name&gt;</li>
<li>Plugins   -&gt;   plugins.&lt;scheduler name&gt;</li>
</ul>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.smarthomeng.de/sh-trigger-funktioniert-nicht-mehr-nach-1-4-2-umstellung/feed</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Gleichzeitiges Ein- oder Ausschalten</title>
		<link>https://www.smarthomeng.de/gleichzeitiges-ein-oder-ausschalten</link>
					<comments>https://www.smarthomeng.de/gleichzeitiges-ein-oder-ausschalten#comments</comments>
		
		<dc:creator><![CDATA[Martin Sinn]]></dc:creator>
		<pubDate>Thu, 22 Mar 2018 06:53:09 +0000</pubDate>
				<category><![CDATA[Tipps & Tricks]]></category>
		<category><![CDATA[Logiken]]></category>
		<guid isPermaLink="false">http://test.smarthomeng.de/?p=150</guid>

					<description><![CDATA[Ziel Mit einem Schaltbefehl ein anderes Objekt mit Ein- oder Aussschalten. Der jeweilig andere Schaltzustand wird ignoriert. Anstonsten hätte ich ja ein Gruppenobjekt mehrfach zuordnen können. Ich nutze die beiden Logiken z.B. im Badezimmer um die Rollladen herunterzufahren wenn der Bewegungsmelder das Licht einschaltet. Wenn ich dann manuell noch Zusatzlicht<a class="moretag" href="https://www.smarthomeng.de/gleichzeitiges-ein-oder-ausschalten"> Weiterlesen&#8230;</a>]]></description>
										<content:encoded><![CDATA[<div class="markdown-body">
<h3>Ziel</h3>
<p>Mit einem Schaltbefehl ein anderes Objekt mit Ein- oder Aussschalten. Der jeweilig andere Schaltzustand wird ignoriert. Anstonsten hätte ich ja ein Gruppenobjekt mehrfach zuordnen können.</p>
<p>Ich nutze die beiden Logiken z.B. im Badezimmer um die Rollladen herunterzufahren wenn der Bewegungsmelder das Licht einschaltet. Wenn ich dann manuell noch Zusatzlicht Einschalte, wird dieses automatisch vom Bewegungsmelder wieder mit dem Hauptlicht ausgeschaltet. Die Logik sendet jeweils ein 0 oder 1 an das mittels <strong>switchon</strong> oder <strong>switchon</strong> referenzierte Item. Somit können Lampen aus und Rollladen heruntergefahren werden.</p>
<h3>Logik</h3>
<p>Zuerst die beiden Logiken, die im logics Verzeichnis gespeichert werden.</p>
<h4>switchoff.py</h4>
<pre><code class="language-python">#!/usr/bin/env python

# get triggering item
trigger_source = trigger['source']
logger.debug('SwitchOff triggered by '+trigger_source)
trigger_item = sh.return_item(trigger_source)

if not trigger_item():
    # switch off associated item
    item_to_switchoff = sh.return_item(trigger_item.conf['switchoff'])
    logger.info('Switching off '+str(item_to_switchoff))
    item_to_switchoff(0)
else:
    logger.debug('SwitchOff trigger item is switched on. Nothing to do.')
</code></pre>
<h4>switchon.py</h4>
<pre><code class="language-python">#!/usr/bin/env python

# get triggering item
trigger_source = trigger['source']
logger.debug('SwitchOn triggered by '+trigger_source)
trigger_item = sh.return_item(trigger_source)

if trigger_item():
    # switch on associated item
    item_to_switchon = sh.return_item(trigger_item.conf['switchon'])
    logger.info('Switching on '+str(item_to_switchon))
    item_to_switchon(1)
else:
    logger.debug('SwitchOn trigger item is switched off. Nothing to do.')
</code></pre>
<p>In der Zentral.config habe ich Elemente definiert, die die ermittelten Werte aufnehmen.</p>
<h4>logic.yaml</h4>
<p>Registriert werden die beiden Logiken in der logic.yaml im ../etc Ordner von SmartHomeNG. Die Logiken werden auf alle Items registriert, die die Eigenschaften switchon/switchoff definiert haben.</p>
<pre><code class="language-yaml">SwitchOff:
    filename: switchoff.py
    watch_item: '*:switchoff'

SwitchOn:
    filename: switchon.py
    watch_item: '*:switchon'
</code></pre>
<h3>Items</h3>
<p>Die Zuordnung der Logiken zu Items geschieht in yaml-Dateien im items Ordner.</p>
<pre><code class="language-yaml">og:
    badezimmer:
        name: Badezimmer
        sv_page: room
        sv_img: scene_bathroom.svg
        
        licht:
            name: Badezimmer
            
            spiegel:
                name: Licht Spiegel
                ...
            
            decke:
                name: Licht
                type: bool
                ...
                switchon: og.badezimmer.rollo.fenster.lang
                switchoff: og.badezimmer.licht.spiegel
</code></pre>
<p>Das Auslösende Element wird ermittelt und über ein zusätzliches Attribut das zugeordnete Objekt gefunden und geschaltet.</p>
<p>&nbsp;</p>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://www.smarthomeng.de/gleichzeitiges-ein-oder-ausschalten/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
