<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0"
    xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Home Assistant on jbetzen.net</title>
    <link>https://jbetzen.net/topics/home-assistant/</link>
    <description>Recent content in Home Assistant on jbetzen.net</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>de</language>
    
    <lastBuildDate>Tue, 03 Feb 2026 12:29:27 +0200</lastBuildDate><atom:link href="https://jbetzen.net/topics/home-assistant/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Automation Templates</title>
      <link>https://jbetzen.net/posts/automation-templates/</link>
      <pubDate>Tue, 03 Feb 2026 12:29:27 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/automation-templates/</guid>
      <description>Automationen in Home Assistant haben einen Trigger, der eben jene auslöst. Zusätzlich werden Informationen bereit gestellt, bspw. welche Platform die Automation getriggert hat oder welcher numerische Ausgangswert zuvor vorhanden war.</description>
      <content:encoded><![CDATA[ <p>Im Post <a href="/posts/pixelclock-custom-app-collection/#bitcoin" >Pixelclock: Custom App Collection</a> wurde bereits eine Custom App zur Anzeige des Bitcoin Kurses auf der <a href="/tags/ulanzi-pixelclock/" >Ulanzi Pixelclock</a> vorgestellt. Diese nutzt die <a href="https://www.home-assistant.io/integrations/bitcoin/"  target="_blank" rel="noreferrer">Bitcoin Integration</a> und stellt den aktuellen Kurs auf dem Display dar:</p>


  

<figure class="centered"><img src="/posts/pixelclock-custom-app-collection/bitcoin.jpg"
    alt="Foto der Custom Bitcoin App auf der Ulanzi Pixelclock">
</figure>



<h2 class="relative group">Vorhaben
    <div id="vorhaben" class="anchor"></div>
    
</h2>
<p>Ziel dieses Beitrags ist Home Assistants mächtige Funktion der <a href="https://www.home-assistant.io/docs/automation/templating"  target="_blank" rel="noreferrer">Automation Templates</a> näherzubringen und diese zu nutzen, um die bestehende Custom App zu optimieren. Dazu wird die Automation erweitert und die <a href="https://www.home-assistant.io/docs/automation/templating/#available-trigger-data"  target="_blank" rel="noreferrer">Trigger Data</a> verwendet, um den dargestellten Text des Bitcoin Kurse einzufärben. Steigt der Kurs, gegenüber dem zuletzt gelieferten Ausgangswert, wird der Text grün dargestellt. Fällt der Kurs, wird er in roter Textfarbe ausgegeben. Ist der Wert gleichbleibend erfolgt eine Ausgabe in Gelb:</p>


  

<figure class="centered"><img src="/posts/automation-templates/pixelclock.gif"
    alt="Animiertes GIF des aktuellen Bitcoin Kurses in gefärbter Ausgabe auf der Ulanzi Pixeclock">
</figure>


<p>Zur Einfärbung des Texts muss die <a href="https://www.home-assistant.io/docs/automation/templating/#state"  target="_blank" rel="noreferrer">State Trigger Data</a> herangezogen werden, die zwei Variablen namens <code>trigger.from_state</code> und <code>trigger.to_state</code> bereitstellt:</p>


  

<figure class="centered"><img src="/posts/automation-templates/state-trigger-data.png"
    alt="Tabelle mit den Variablen für Home Assistants State Trigger Data">
</figure>



<h2 class="relative group">Automation anpassen
    <div id="automation-anpassen" class="anchor"></div>
    
</h2>
<p>Die Farbausgabe auf dem Display wird über den Payload Key <a href="https://blueforcer.github.io/awtrix3/#/api?id=json-properties"  target="_blank" rel="noreferrer"><code>color</code></a> definiert. Zuvor muss jedoch ermittelt werden, ob der letzte gelieferte Wert des Sensors <code>sensor.exchange_rate_1_btc</code> größer oder kleiner ist als der aktuelle Wert:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">notify_pixelclock_bitcoin</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">trigger</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.exchange_rate_1_btc</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/bitcoin</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">        {
</span></span></span><span class="line"><span class="cl"><span class="sd">          &#34;text&#34;: &#34;{{ states(&#39;sensor.exchange_rate_1_btc&#39;) | round(0) }}&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">          &#34;icon&#34;: &#34;bitcoin&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">          &#34;color&#34;:  {% if is_number(trigger.from_state.state) and (float(trigger.to_state.state,default=0) &gt; float(trigger.from_state.state,default=0)) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">                      &#34;#006400&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">                    {% elif is_number(trigger.from_state.state) and (float(trigger.to_state.state,default=0) &lt; float(trigger.from_state.state,default=0)) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">                      &#34;#FF0000&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">                    {% else %}
</span></span></span><span class="line"><span class="cl"><span class="sd">                      &#34;#FFCC00&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">                    {% endif %}
</span></span></span><span class="line"><span class="cl"><span class="sd">        }</span></span></span></code></pre></div></div>
<p>Handelt es sich beim aktuellen Sensorwert um einen numerischen Wert (<code>is_number()</code>) und ist dieser größer als der vorherige Wert wird der Text nun in Grün ausgegeben:</p>


  

<figure class="centered"><img src="/posts/automation-templates/awtrix-green.png"
    alt="Grüne Textausgabe des Bitcoin Kurs auf der Ulanzi Pixelclock">
</figure>


<p>Fällt der aktuelle Kurs, wird der Text Rot ausgegeben:</p>


  

<figure class="centered"><img src="/posts/automation-templates/awtrix-red.png"
    alt="Rote Textausgabe des Bitcoin Kurs auf der Ulanzi Pixelclock">
</figure>


<p>Im Falle eines gleichbleibenden Werts, wird der Text in gelber Farbe ausgegeben.</p>


  

<figure class="centered"><img src="/posts/automation-templates/awtrix-yellow.png"
    alt="Gelbe Textausgabe des Bitcoin Kurs auf der Ulanzi Pixelclock">
</figure>


 ]]></content:encoded>
    </item>
    
    <item>
      <title>Zigbee Rauchmelder</title>
      <link>https://jbetzen.net/posts/smoke-detector/</link>
      <pubDate>Tue, 30 Dec 2025 12:29:27 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/smoke-detector/</guid>
      <description>Die Marke Honeywell bietet Zigbee kompatible Rauchmelder für unter 30€ an, die in Homeassistant integriert werden können. Somit kann, im Falle eines Brandes, eine Push Benachrichtigung abgesetzt werden.</description>
      <content:encoded><![CDATA[ <p>Die Marke <strong>Honeywell</strong> bietet günstige Zigbee Rauchmelder an, die in Homeassistant integriert werden können. In diesem Beispiel nutze ich das Modell <a href="https://de.aliexpress.com/item/1005009046923297.html"  target="_blank" rel="noreferrer">Honeywell Smoke Detector</a>, das für unter 30€ bei AliExpress erworben werden kann.</p>

<h2 class="relative group">Einbindung über Phoscon App
    <div id="einbindung-über-phoscon-app" class="anchor"></div>
    
</h2>
<p>Der Rauchmelder kann über die <a href="https://www.home-assistant.io/integrations/deconz/"  target="_blank" rel="noreferrer">deCONZ Integration</a> eingebunden und muss zuvor über die Phoscon App verbunden werden. Wie bereits in allen anderen Beiträgen zum Thema <a href="/categories/zigbee/" >Zigbee Geräte</a> nutze ich dafür das offizielle <a href="https://www.home-assistant.io/integrations/deconz/#recommended-way-of-running-deconz"  target="_blank" rel="noreferrer">deCONZ Add-On</a>.</p>
<p>Der <strong>Pairing Mode</strong> des Rauchmelders wird über <a href="https://github.com/Koenkk/zigbee2mqtt/issues/136"  target="_blank" rel="noreferrer">drei schnelle kurze Klicks</a> auf den einzigen Button des Geräts aktiviert. Anschließend steht der Rauchmelder in der Phoscon App in der Sektion <strong>Sensoren</strong> zur Verfügung:</p>


  

<figure class="centered"><img src="/posts/smoke-detector/phoscon.png"
    alt="Screenshot of Smoke Detector in Phoscon App">
</figure>


<p>Der Rauchmelder erscheint in Homeassistant als <a href="https://www.home-assistant.io/integrations/binary_sensor/"  target="_blank" rel="noreferrer">Binary Sensor</a>, der detektierten Rauch mit einem State <code>on</code> anzeigt. Zusätzlich sind drei weitere Sensoren vorhanden:</p>
<ol>
<li>Ein Binary Sensor, der einen niedrigen Batteriestand mit dem State <code>on</code> anzeigt.</li>
<li>Ein Binary Sensor, der die Ausführung des Test-Modus mit dem State <code>on</code> anzeigt.</li>
<li>Ein numerischer Sensor, der den Batteriestand in Prozent anzeigt.</li>
</ol>


  

<figure class="centered"><img src="/posts/smoke-detector/sensors.png"
    alt="Screenshot of Smoke Detector Sensors in Homeassistant">
</figure>



<h2 class="relative group">Rauchmelder Gruppe erstellen
    <div id="rauchmelder-gruppe-erstellen" class="anchor"></div>
    
</h2>
<p>Da ein Rauchmelder selten alleine daherkommt, werden alle Geräte in einer Gruppe mittels <a href="https://www.home-assistant.io/integrations/group/"  target="_blank" rel="noreferrer">Group Integration</a> zusammengefasst. Dazu folgenden Eintrag in der <code>group.yaml</code> erstellen und die Namen der Entities entsprechend anpassen:</p>
<div class="highlight-wrapper"><div class="codeblock-title">group.yml</div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">rauchmelder</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Rauchmelder</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">entities</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">binary_sensor.rauchmelder_flur</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">binary_sensor.rauchmelder_ballsaal</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">binary_sensor.rauchmelder_schlafzimmer</span></span></span></code></pre></div></div>
<p>Der Eintrag erzeugt in Homeassistant nun eine Gruppe:</p>


  

<figure class="centered"><img src="/posts/smoke-detector/group.png"
    alt="Screenshot of grouped Smoke Detectors in Homeassistant">
</figure>


<p>Der Vorteil der Group Integration liegt darin, dass nur einer der Sensoren einen Feueralarm melden muss, um den State der Gruppe auf <code>on</code> zu setzen. Dieser State der Gruppe wird in der nun zu erstellenden Automation genutzt.</p>

<h2 class="relative group">Automation für Push-Message
    <div id="automation-für-push-message" class="anchor"></div>
    
</h2>
<p>Die folgende Automation erzeugt eine Push-Nachricht, die den Namen des Rauchmelders enthält, der einen Brand/Rauch detektiert hat. Trigger ist der State der anglegten <a href="/posts/smoke-detector/#rauchmelder-gruppe-erstellen" >Gruppe</a>. Im Falle eines Brandes werden alle Lichter des Hauses blinkend geschaltet, mittels des Parameters <code>flash: long</code> der Action <a href="https://www.home-assistant.io/integrations/light#action-lightturn_on"  target="_blank" rel="noreferrer"><code>light.turn_on</code></a>.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Feueralarm</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">trigger</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">group.rauchmelder</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">to</span><span class="p">:</span><span class="w">  </span><span class="s1">&#39;on&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">notify.mobile_app_iphone</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;🔥 Feueralarm 🔥&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">message</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ states | selectattr(&#39;entity_id&#39;,&#39;in&#39;, state_attr(&#39;group.rauchmelder&#39;,&#39;entity_id&#39;)) | selectattr(&#39;state&#39;,&#39;eq&#39;,&#39;on&#39;) | map(attribute=&#39;name&#39;) | join(&#39;, &#39;) }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;push_feueralarm&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">channel</span><span class="p">:</span><span class="w"> </span><span class="l">Alarm</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">light.turn_on</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="l">light.deconz_licht_wohnzimmer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="l">light.deconz_licht_flur</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="l">light.deconz_licht_schlafzimmer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="l">light.deconz_licht_ballsaal</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">flash</span><span class="p">:</span><span class="w"> </span><span class="l">long</span></span></span></code></pre></div></div>

<h3 class="relative group">Automation Testen
    <div id="automation-testen" class="anchor"></div>
    
</h3>
<p>Hält man den Button des Rauchmelders lange gedrückt, wird der Test-Modus aktiviert. Die erzeugte Gruppe wechselt in den State <code>on</code> und die Automation wird getriggert:</p>


  

<figure class="centered"><img src="/posts/smoke-detector/push.png"
    alt="Screenshot of Push Notification indicating smoke detection">
</figure>



<h3 class="relative group">Nachricht auf Ulanzi Pixelclock
    <div id="nachricht-auf-ulanzi-pixelclock" class="anchor"></div>
    
</h3>
<p>Wer eine <a href="/tags/ulanzi-pixelclock/" >Ulanzi Pixelclock</a> im Eigenheim betreibt, kann zusätzlich auf dieser eine Warnung ausgeben:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;text&#34;: &#34;Feuer!&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;icon&#34;: &#34;fire&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;hold&#34;: true
</span></span></span><span class="line"><span class="cl"><span class="sd">          }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/notify</span></span></span></code></pre></div></div>
<p>Als <a href="https://developer.lametric.com/icons"  target="_blank" rel="noreferrer">Icon</a> nutze ich dafür die animierte Flamme mit der Icon ID <code>7756</code>, die unter dem Dateinamen <code>fire.gif</code> auf der Pixelclock abgespeichert ist:</p>


  

<figure class="centered"><img src="/posts/smoke-detector/pixelclock-icon.png"
    alt="Screenshot of Pixelclock Flame Icon">
</figure>


 ]]></content:encoded>
    </item>
    
    <item>
      <title>Last Motion Sensor</title>
      <link>https://jbetzen.net/posts/last-motion-sensor/</link>
      <pubDate>Thu, 04 Dec 2025 11:29:27 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/last-motion-sensor/</guid>
      <description>Befindet sich im trauten Eigenheim in jedem Raum ein Bewegungssensor, kann man über diesen ermitteln, in welchem Raum zuletzt eine Bewegung detektiert wurde. In einem Single-Haushalt entspricht diese Information dem Raum, in dem man sich gerade aufhält.</description>
      <content:encoded><![CDATA[ 
  
  
  
  



<div
  
    class="flex px-4 py-3 rounded-md shadow bg-primary-100 dark:bg-primary-900"
  
  >
  <span
    
      class="text-primary-400 pe-3 flex items-center"
    
    >
    <span class="relative block icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 128c17.67 0 32 14.33 32 32c0 17.67-14.33 32-32 32S224 177.7 224 160C224 142.3 238.3 128 256 128zM296 384h-80C202.8 384 192 373.3 192 360s10.75-24 24-24h16v-64H224c-13.25 0-24-10.75-24-24S210.8 224 224 224h32c13.25 0 24 10.75 24 24v88h16c13.25 0 24 10.75 24 24S309.3 384 296 384z"/></svg>
</span>
  </span>

  <span
    
      class="dark:text-neutral-300"
    
    >Dieser Beitrag enthält eine optimierte Methode zur Erstellung eines Last Motion Sensors, wie bereits im Post <a href="/posts/room-based-presence/">Room Based Presence mit Motion Sensoren</a> erläutert. Dieser Sensor wurde auch im Beitrag <a href="/posts/autopause-mediaplayer/">Automatisch pausierender Media Player</a> verwendet.</span>
</div>

<p>Home Assistant hat die Konfiguration für <a href="https://www.home-assistant.io/integrations/template/#sensor"  target="_blank" rel="noreferrer">Template Sensoren</a> überarbeitet und mich mit haufenweise Warnmeldungen überschüttet. Siehe: <a href="https://community.home-assistant.io/t/deprecation-of-legacy-template-entities-in-2025-12/955562"  target="_blank" rel="noreferrer">Deprecation of legacy template entities in 2025.12</a></p>
<p>Die <em>Deprecation Warnings</em> betrafen unter Anderem den Post <a href="/posts/room-based-presence/">Room Based Presence mit Motion Sensoren</a>, was ich als Anlass genommen habe das Setup neu zu überdenken. Da ich vor kurzem <a href="/posts/ilogic-serienende/" >arbeitsfrei geworden</a> bin, ist die Zeit dafür vorhanden.</p>


  

<figure class="centered"><img src="/posts/last-motion-sensor/arno.png"
    alt="Ein Bild von Arno Dübel. Dem Schutzpatrin der Hedonisten und Hartzer.">
</figure>



<h2 class="relative group">Vorhaben
    <div id="vorhaben" class="anchor"></div>
    
</h2>
<p>Befindet sich im trauten Eigenheim ein Bewegungssensor in jedem Raum, kann man über diese ermitteln, in welchem Raum zuletzt eine Bewegung erkannt wurde. In einem Single-Haushalt entspricht diese Information dem Raum, in dem man sich gerade aufhält. Diese Information kann zielführend genutzt werden, wie bereits im Post <a href="/posts/room-based-presence/">Room Based Presence mit Motion Sensoren</a> erläutert wurde.</p>
<p>An meinem aktuellen Setup hat mir nie gefallen, dass ich auf eine zusätzliche Custom Component namens <a href="https://github.com/snarky-snark/home-assistant-variables"  target="_blank" rel="noreferrer">home-assistant-variables</a> angewiesen war. Im Kern war dies immer eine Lösung, die zuverlässig funktioniert hat und mich vor der Auseinandersetzung mit <a href="https://www.home-assistant.io/integrations/template/#sensor"  target="_blank" rel="noreferrer">Template Sensoren</a> freigesprochen hat.</p>
<p>Template Sensoren nutzen eine sperrige Syntax aus der Hölle, die durch die Python Template Engine <a href="https://github.com/noirbizarre/jinja2"  target="_blank" rel="noreferrer">Jinja2</a> bereitgestellt wird. Im <a href="https://community.home-assistant.io"  target="_blank" rel="noreferrer">Home Assistant Forum</a> gibt es herausstechende Planetenbürger wie <a href="https://community.home-assistant.io/u/petro/summary"  target="_blank" rel="noreferrer">Petro</a>, die diese Syntax mit einer Leichtigkeit beherrschen, als würde man Pfannkuchen backen. Zu diesen Menschen zähle ich jedoch nicht. Nichtsdestotrotz habe ich noch einmal das Forum durchforstet und eine funktionierende Lösung in diesem Thread <a href="https://community.home-assistant.io/t/quick-sensor-template-question-last-active-motion-sensor/396458/1"  target="_blank" rel="noreferrer">Quick sensor/template question - Last active motion sensor</a> gefunden.</p>
<p>Aus einer vordefinierten Liste an <a href="/categories/motion-sensor/" >Bewegungssensoren</a> soll jener ermittelt werden, der als letztes den State <code>on</code> gemeldet hat. Die Bewegungssensoren sind naturgemäß als <a href="https://www.home-assistant.io/integrations/binary_sensor/"  target="_blank" rel="noreferrer">Binary Sensors</a> in Home Assistant eingebunden, das sie lediglich die States <code>on</code> und <code>off</code> besitzen können. Bewegung wird detektiert oder eben nicht.</p>
<p>Als Beispiel eingesetzter Bewegungsmelder werden folgende Entities und Namen verwendet:</p>
<table>
	<thead>
			<tr>
					<th>Entity Name</th>
					<th>Friendly Name</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>binary_sensor.hue_motion_kueche</code></td>
					<td>Hue Motion Küche</td>
			</tr>
			<tr>
					<td><code>binary_sensor.hue_motion_schlafzimmer</code></td>
					<td>Hue Motion  Schlafzimmmer</td>
			</tr>
			<tr>
					<td><code>binary_sensor.hue_motion_wohnzimmer</code></td>
					<td>Hue Motion Wohnzimmer</td>
			</tr>
			<tr>
					<td><code>binary_sensor.hue_motion_flur</code></td>
					<td>Hue Motion Flur</td>
			</tr>
	</tbody>
</table>


  

<figure class="centered"><img src="/posts/last-motion-sensor/entities.png">
</figure>



<h2 class="relative group">Last Motion Sensor
    <div id="last-motion-sensor" class="anchor"></div>
    
</h2>
<p>Der Code des Template Sensors macht folgendes:</p>
<ul>
<li>Er definiert die Entity Names der Bewegungssensoren in einer Liste <code>sensors</code>.</li>
<li>Er ermittelt alle Entities in der Liste <code>sensors</code>, die den State <code>on</code> besitzen und speichert diese als eine Liste.</li>
<li>Wenn mehr als ein Bewegungssensor in dieser Liste den State <code>on</code> besitzt, wird der Name des zuletzt getriggerten Sensors zurückgegeben.</li>
<li>Für meinen persönlichen Fall habe ich noch einen <code>regex_replace()</code> gesetzt, der mir den Präfix <code>Hue Motion </code> aus dem Rückgabewert entfernt. Somit bleibt lediglich der Raumname über, bspw. <code>Hue Motion Flur</code> wird reduziert auf <code>Flur</code>.</li>
<li>Für jeden Raum wird ein <a href="https://www.home-assistant.io/integrations/template/#common-device-configuration-options"  target="_blank" rel="noreferrer">Custom Icon</a> definiert, das sich dynamisch anpasst, je nachdem wo zuletzt eine Bewegung registriert wurde.</li>
</ul>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">sensor</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">last_motion</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {%- set sensors = &#39;binary_sensor.hue_motion_flur&#39;, &#39;binary_sensor.hue_motion_kueche&#39;, &#39;binary_sensor.hue_motion_schlafzimmer&#39;, &#39;binary_sensor.hue_motion_wohnzimmer&#39; %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% set sensors_on = expand(sensors) | selectattr(&#39;state&#39;, &#39;eq&#39;, &#39;on&#39;) | map(attribute=&#39;name&#39;) | list %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% if sensors_on | count &gt; 0 %}
</span></span></span><span class="line"><span class="cl"><span class="sd">            {{ expand(sensors) | selectattr(&#39;state&#39;, &#39;eq&#39;, &#39;on&#39;) | sort(reverse=true, attribute=&#34;last_changed&#34;) | map(attribute=&#39;name&#39;) | list | first | default(none) | regex_replace(find=&#39;Hue Motion &#39;, replace=&#39;&#39;) }}
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% else %}
</span></span></span><span class="line"><span class="cl"><span class="sd">            {{ expand(sensors) | sort(reverse=true, attribute=&#34;last_changed&#34;) | map(attribute=&#39;name&#39;) | list | first | default(none) | regex_replace(find=&#39;Hue Motion &#39;, replace=&#39;&#39;) }}
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% endif %}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% if is_state(&#39;sensor.last_motion&#39;, &#39;Küche&#39;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">            mdi:food-variant
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% elif is_state(&#39;sensor.last_motion&#39;, &#39;Wohnzimmer&#39;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">            mdi:sofa
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% elif is_state(&#39;sensor.last_motion&#39;, &#39;Flur&#39;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">            mdi:cube-unfolded
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% elif is_state(&#39;sensor.last_motion&#39;, &#39;Schlafzimmer&#39;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">            mdi:bed
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% else %}
</span></span></span><span class="line"><span class="cl"><span class="sd">            mdi:account-question
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% endif %}</span></span></span></code></pre></div></div>
<p>Der Sensor ersetzt nahtlos das alte Setup, reduziert unnötige Komplexität und liefert identische Rückgabewerte, wie die alte Lösung mittels <a href="https://github.com/snarky-snark/home-assistant-variables"  target="_blank" rel="noreferrer">home-assistant-variables</a>:</p>


  

<figure class="centered"><img src="/posts/last-motion-sensor/result.gif"
    alt="Resultat des Sensors in der HASS UI">
</figure>


<p>Er kann für viele Automationen genutzt werden, bspw. wenn ein Media-Player bei aktiver Wiedergabe <a href="/posts/autopause-mediaplayer/" >pausiert</a> werden soll, wenn man den Raum verlässt oder aber, wenn das Licht in einem Raum nicht ausgeschaltet werden soll, wenn man sich darin aufhält.</p>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Pixelclock: Custom App Collection</title>
      <link>https://jbetzen.net/posts/pixelclock-custom-app-collection/</link>
      <pubDate>Sat, 29 Apr 2023 11:29:27 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/pixelclock-custom-app-collection/</guid>
      <description>Da die Entwicklung der Custom Firmware AWTRIX3 schleunig voranschreitet und fortlaufend neue Features eingebaut werden, soll dieser Post als Sammler für derzeitige und zukünftige Custom Apps dienen.</description>
      <content:encoded><![CDATA[ 
<h2 class="relative group">Grundsätzliches
    <div id="grundsätzliches" class="anchor"></div>
    
</h2>
<p>Bei Custom Apps ist es, je nach Anwendungsfall, sinnvoll das MQTT-Flag <code>retain: true</code> zu setzen. Nur so ist gewährleistet, dass eine Custom App den Neustart der Pixelclock übersteht und persistent angezeigt wird. Custom Apps <em>leben</em> ansonsten nur im RAM des ESP32 und werden bei einem Neustart gelöscht. Das Retain-Flag bewirkt, dass der MQTT-Broker bei einer Neuverbindung der Pixelclock erneut, die zuletzt gesendete Message an diese übermittelt.</p>
<p><strong>Wann macht es Sinn das Retain-Flag zu nutzen:</strong><br>
Wenn Sensor Daten sich nicht häufig aktualisieren und somit der Trigger in Homeassistant nicht häufig auslöst. Startet man in diesem Fall die Pixelclock neu, kann es unter Umständen sehr lange dauern, bis ein neuer Wert gesendet wird. Die Custom App wäre bis zu diesem Zeitpunkt nicht aktiv.</p>
<p><strong>Wann macht es keinen Sinn das Retain-Flag zu setzen:</strong><br>
Wenn Custom Apps automatisch bei einem Trigger X entfernt werden, siehe Beispiel der Spotify App. Es macht keinen Sinn die letzten Wiedergabeinformationen eines Songs am Broker vorzuhalten, da diese Info <em>flüchtig</em> ist und sich häufig ändert und der Song ggf. gar nicht mehr abgespielt wird, wenn die Pixelclock neugestartet wird.</p>

<h2 class="relative group">Custom Apps
    <div id="custom-apps" class="anchor"></div>
    
</h2>
<p>Folgend eine List an Custom App, die im Zusammenspiel mit Homeassistant an die Pixelclock gesendet werden können. Alle Daten werden direkt aus Homeassistant generiert und benötigen keinerlei externe Add-Ons, wie bspw. Node Red.</p>
<p>Zu jeder Custom App ist ein Icon von der <a href="https://developer.lametric.com/icons"  target="_blank" rel="noreferrer">LaMetric Developer Website</a> verlinkt. Der nachfolgende Dateiname entspricht der Benennung im Filesystem der Pixelclock.</p>

<h3 class="relative group">Spotify
    <div id="spotify" class="anchor"></div>
    
</h3>
<p>Dargestellt wird der aktuell abgespielte Künstler und Songname, sowie ein Fortschrittsanzeige (<em>Progressbar</em>) für den aktuell abgespielten Song. Die Progressbar wird aus zwei Attributen des Media-Players errechnet. Der Name des Media-Players muss entsprechend an den Namen der eigenen <em>Entity</em> in Homeassistant angepasst werden.</p>
<p>Die App wird automatisch entfernt, wenn der State des Media-Player auf <code>idle</code> oder <code>paused</code> wechselt und keine Wiedergabe mehr erfolgt.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock-custom-app-collection/spotify.gif"
          alt="Animated GIF of currently played song on Spotify shown on Pixelclock"
        />
  
  
  </figure>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th></th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>LaMetric Icon</td>
					<td>18207 / spotify.jpg</td>
			</tr>
			<tr>
					<td>Integration</td>
					<td><a href="https://www.home-assistant.io/integrations/spotify/"  target="_blank" rel="noreferrer">Spotify</a></td>
			</tr>
			<tr>
					<td>Sensor</td>
					<td>media_player.spotify</td>
			</tr>
	</tbody>
</table>
</div>
<p><strong>Automation:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">notify_pixelclock_spotify</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.spotify</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">choose</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.spotify</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;playing&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">sequence</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">                  {
</span></span></span><span class="line"><span class="cl"><span class="sd">                    &#34;text&#34;: &#34;{{ state_attr(&#39;media_player.spotify&#39;, &#39;media_artist&#39;) }} - {{ state_attr(&#39;media_player.spotify&#39;, &#39;media_title&#39;) }}&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">                    &#34;icon&#34;: &#34;spotify&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">                    &#34;rainbow&#34;: false,
</span></span></span><span class="line"><span class="cl"><span class="sd">                    &#34;duration&#34;: 10,
</span></span></span><span class="line"><span class="cl"><span class="sd">                    &#34;pushIcon&#34;: 0,
</span></span></span><span class="line"><span class="cl"><span class="sd">                    &#34;textCase&#34;: 2,
</span></span></span><span class="line"><span class="cl"><span class="sd">                    &#34;progress&#34;: {{ ( states.media_player.spotify.attributes.media_position / states.media_player.spotify.attributes.media_duration * 100 ) | round() }},
</span></span></span><span class="line"><span class="cl"><span class="sd">                    &#34;progressC&#34;: &#34;18B04C&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">                  }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/spotify</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">template</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ not states.media_player.spotify.state == &#39;playing&#39; }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">sequence</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/spotify</span></span></span></code></pre></div></div>

<h3 class="relative group">pr0gramm
    <div id="pr0gramm" class="anchor"></div>
    
</h3>
<p>Zeigt den <em>Benis</em> eines beliebigen Accounts auf einem großen deutschen Imageboard, über das niemand spricht. Der Username, beispielhaft <code>horst</code>, muss entsprechend im API-Call angepasst werden.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock-custom-app-collection/pr0.jpg"
          alt="Pixelclock showing Benis status of pr0gramm"
        />
  
  
  </figure>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th></th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>LaMetric Icon</td>
					<td>26807 / pr0.jpg</td>
			</tr>
			<tr>
					<td>Integration</td>
					<td><a href="https://www.home-assistant.io/integrations/sensor.rest/"  target="_blank" rel="noreferrer">RESTful Sensor</a></td>
			</tr>
			<tr>
					<td>Sensor</td>
					<td>sensor.pr0</td>
			</tr>
	</tbody>
</table>
</div>
<p><strong>Sensor:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">rest</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">scan_interval</span><span class="p">:</span><span class="w"> </span><span class="m">3600</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Pr0 Benis&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">unit_of_measurement</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ value_json[&#34;user&#34;][&#34;score&#34;] | int }}&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">resource</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;https://pr0gramm.com/api/profile/info?name=horst&#39;</span></span></span></code></pre></div></div>
<p><strong>Automation:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">notify_pixelclock_pr0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.pr0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;text&#34;: &#34;{{ states.sensor.pr0.state }}&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;icon&#34;: &#34;pr0&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">          }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/pr0</span></span></span></code></pre></div></div>

<h3 class="relative group">Wetter
    <div id="wetter" class="anchor"></div>
    
</h3>
<p>Für diese Custom App sind diverse Icons erforderlich. Das exakte Vorgehen wurde bereits im vorhergehenden Post <a href="/posts/pixelclock/">Ulanzi Smart Pixel Clock TC001</a> im Detail erläutert.</p>
<p>Die Temperatur wird ganzzahlig gerundet dargestellt.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock-custom-app-collection/weather.gif"
          alt="Pixelclock showing current weather"
        />
  
  
  </figure>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th></th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>LaMetric Icon</td>
					<td>Zu viele</td>
			</tr>
			<tr>
					<td>Integration</td>
					<td><a href="https://www.home-assistant.io/integrations/weather/"  target="_blank" rel="noreferrer">Weather</a></td>
			</tr>
			<tr>
					<td>Sensor</td>
					<td>weather.openweathermap</td>
			</tr>
	</tbody>
</table>
</div>
<p><strong>Automation:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">notify_pixelclock_weather</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">weather.openweathermap</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">template</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ states.weather.openweathermap.attributes.temperature }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;text&#34;: &#34;{{ states.weather.openweathermap.attributes.temperature | round(0) }} {{ states.weather.openweathermap.attributes.temperature_unit }}&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;icon&#34;: &#34;{{ states(&#39;weather.openweathermap&#39;) }}&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;rainbow&#34;: false
</span></span></span><span class="line"><span class="cl"><span class="sd">          }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/weather</span></span></span></code></pre></div></div>

<h3 class="relative group">Bitcoin
    <div id="bitcoin" class="anchor"></div>
    
</h3>

  
  
  
  



<div
  
    class="flex px-4 py-3 rounded-md shadow bg-primary-100 dark:bg-primary-900"
  
  >
  <span
    
      class="text-primary-400 pe-3 flex items-center"
    
    >
    <span class="relative block icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 128c17.67 0 32 14.33 32 32c0 17.67-14.33 32-32 32S224 177.7 224 160C224 142.3 238.3 128 256 128zM296 384h-80C202.8 384 192 373.3 192 360s10.75-24 24-24h16v-64H224c-13.25 0-24-10.75-24-24S210.8 224 224 224h32c13.25 0 24 10.75 24 24v88h16c13.25 0 24 10.75 24 24S309.3 384 296 384z"/></svg>
</span>
  </span>

  <span
    
      class="dark:text-neutral-300"
    
    >Im Post <a href="/posts/automation-templates/">Automation Templates</a> ist eine erweiterte Variante dieser Custom App zu finden, die, je nach steigendem oder fallenden Kurs, den aktuellen Kurswert farblich ausgibt.</span>
</div>

<p>Der aktuelle Kursstand des Bitcoins. Der Name des Sensors muss entsprechend angepasst werden.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock-custom-app-collection/bitcoin.jpg"
          alt="Pixelclock showing Bitcoin price"
        />
  
  
  </figure>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th></th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>LaMetric Icon</td>
					<td>10814 / bitcoin.jpg</td>
			</tr>
			<tr>
					<td>Integration</td>
					<td><a href="https://www.home-assistant.io/integrations/bitcoin/"  target="_blank" rel="noreferrer">Bitcoin</a></td>
			</tr>
			<tr>
					<td>Sensor</td>
					<td>sensor.exchange_rate_1_btc</td>
			</tr>
	</tbody>
</table>
</div>
<p><strong>Automation:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">notify_pixelclock_bitcoin</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.exchange_rate_1_btc</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;text&#34;: &#34;{{ states.sensor.exchange_rate_1_btc.state | round(0) }}&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;icon&#34;: &#34;bitcoin&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">          }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/bitcoin</span></span></span></code></pre></div></div>

<h3 class="relative group">Hochwasserportal
    <div id="hochwasserportal" class="anchor"></div>
    
</h3>
<p>Als echte Nordblume ist der Pegelstand der Ostsee natürlich essentiell. Diese Custom App nutzt eine Custom Integration namens <a href="https://github.com/stephan192/hochwasserportal"  target="_blank" rel="noreferrer">Hochwasserportal</a>, die über HACS installiert werden kann. Drei variable Icons kommen für die Pegelstände zum Einsatz. Bei Hochwasser wird der Text in rot ausgegeben, bei Niedrigwasser in gelb.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock-custom-app-collection/hochwasser.gif"
          alt="Pixelclock showing water level"
        />
  
  
  </figure>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th></th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>LaMetric Icon</td>
					<td>24114 / water-level-low.gif</td>
			</tr>
			<tr>
					<td>LaMetric Icon</td>
					<td>24117 / water-level-normal.gif</td>
			</tr>
			<tr>
					<td>LaMetric Icon</td>
					<td>24120 / water-level-high.gif</td>
			</tr>
			<tr>
					<td>Custom Integration</td>
					<td><a href="https://github.com/stephan192/hochwasserportal"  target="_blank" rel="noreferrer">Hochwasserportal</a></td>
			</tr>
			<tr>
					<td>Sensor</td>
					<td>sensor.ostsee_level</td>
			</tr>
	</tbody>
</table>
</div>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">notify_pixelclock_hochwasser</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.ostsee_level</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/hochwasser</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">        {
</span></span></span><span class="line"><span class="cl"><span class="sd">          &#34;text&#34;: &#34;{{ states.sensor.ostsee_level.state }} cm&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">          &#34;textCase&#34;: 2,
</span></span></span><span class="line"><span class="cl"><span class="sd">          &#34;icon&#34;: {% if (states.sensor.ostsee_level.state | int &lt;= 379) %} &#34;water-level-low&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">                  {% elif (states.sensor.ostsee_level.state | int &gt;= 624) %} &#34;water-level-high&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">                  {% else %}&#34;water-level-normal&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">                  {% endif %},
</span></span></span><span class="line"><span class="cl"><span class="sd">          &#34;color&#34;:  {% if (states.sensor.ostsee_level.state | int &lt;= 379) %} &#34;#FFFF00&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">                    {% elif (states.sensor.ostsee_level.state | int &gt;= 624) %} &#34;#FF0000&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">                    {% else %} &#34;#FFFFFF&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">                    {% endif %}
</span></span></span><span class="line"><span class="cl"><span class="sd">        }</span></span></span></code></pre></div></div>

<h3 class="relative group">Instagram Follower
    <div id="instagram-follower" class="anchor"></div>
    
</h3>
<p>Angepasst werden muss der Name des Accounts in dem Parameter <code>ressource</code>. Verwendet wird eine Custom Component, die das <em>Scrapen</em> von Webseiten ermöglicht und weitaus mehr Funktionsumfang bietet als die native <a href="https://www.home-assistant.io/integrations/scrape/"  target="_blank" rel="noreferrer">Scrape Integration</a> von Homeassistant. Die Custom Component kann aus dem HACS Store installiert werden.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock-custom-app-collection/instagram.jpg"
          alt="Pixelclock showing Instagram follower count"
        />
  
  
  </figure>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th></th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>LaMetric Icon</td>
					<td>3741 / instagram.jpg</td>
			</tr>
			<tr>
					<td>Custom Integration</td>
					<td><a href="https://github.com/danieldotnl/ha-multiscrape"  target="_blank" rel="noreferrer">ha-multiscrape</a></td>
			</tr>
			<tr>
					<td>Sensor</td>
					<td>sensor.ig_followers_davidhasselhoff</td>
			</tr>
	</tbody>
</table>
</div>
<p><strong>Sensor:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">multiscrape</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">intagram_followers</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">resource</span><span class="p">:</span><span class="w"> </span><span class="l">https://www.picnob.com/profile/davidhasselhoff/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">scan_interval</span><span class="p">:</span><span class="w"> </span><span class="m">1800</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">sensor</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">unique_id</span><span class="p">:</span><span class="w"> </span><span class="l">ig_followers_davidhasselhoff</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;D.Hasselhoff Instagram Followers&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">select</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;.item_followers &gt; div:nth-child(2)&#34;</span></span></span></code></pre></div></div>
<p><strong>Automation</strong>:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">notify_pixelclock_instagram</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.ig_followers_davidhasselhoff</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;text&#34;: &#34;{{ states.sensor.ig_followers_davidhasselhoff.state | int() }}&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;icon&#34;: &#34;instagram&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">          }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/thehoff</span></span></span></code></pre></div></div>

<h3 class="relative group">Octoprint
    <div id="octoprint" class="anchor"></div>
    
</h3>
<p>Die Custom App zeigt den aktuellen Druckfortschritt in Prozent an. Wenn Octoprint während des Druckvorgangs in einen Fehler läuft, wird eine Nachricht dauerhaft auf der Pixelclock angezeigt, die aktiv durch einen Klick auf den mittleren Button entfernt werden muss. Ist der Druckvorgang beendet, wir die Custom App automatisch entfernt.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock-custom-app-collection/octoprint.gif"
          alt="Pixelclock showing Octoprint progress"
        />
  
  
  </figure>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th></th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>LaMetric Icon</td>
					<td>51841 / 3dprinter.jpg</td>
			</tr>
			<tr>
					<td>Integration</td>
					<td><a href="https://www.home-assistant.io/integrations/octoprint/"  target="_blank" rel="noreferrer">Octoprint</a></td>
			</tr>
			<tr>
					<td>Sensor</td>
					<td>sensor.octoprint_current_state</td>
			</tr>
			<tr>
					<td>Sensor</td>
					<td>sensor.octoprint_job_percentage</td>
			</tr>
			<tr>
					<td>Sensor</td>
					<td>binary_sensor.octoprint_printing_error</td>
			</tr>
	</tbody>
</table>
</div>
<p><strong>Automation:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">notify_pixelclock_octoprint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">initial_state</span><span class="p">:</span><span class="w"> </span><span class="kc">True</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">template</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ not state(&#39;sensor.octoprint_current_state&#39;) == &#39;Printing&#39; }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;idle&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.octoprint_job_percentage</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;printing&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">binary_sensor.octoprint_printing_error</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;on&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;error&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">choose</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">trigger</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;printing&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.octoprint_current_state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Printing&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">sequence</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">                {
</span></span></span><span class="line"><span class="cl"><span class="sd">                  &#34;text&#34;: &#34;{{ (states(&#39;sensor.octoprint_job_percentage&#39;) | round(1) ) }}{{ state_attr(&#39;sensor.octoprint_job_percentage&#39;, &#39;unit_of_measurement&#39;) }}&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">                  &#34;icon&#34;: &#34;3dprinter&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">                  &#34;duration&#34;: 10
</span></span></span><span class="line"><span class="cl"><span class="sd">                }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/octoprint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">trigger</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;idle&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">sequence</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/octoprint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">trigger</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;error&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">sequence</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/octoprint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">                {
</span></span></span><span class="line"><span class="cl"><span class="sd">                  &#34;text&#34;: &#34;Error&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">                  &#34;icon&#34;: &#34;3dprinter&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">                  &#34;textCase&#34;: 2,
</span></span></span><span class="line"><span class="cl"><span class="sd">                  &#34;hold&#34;: true
</span></span></span><span class="line"><span class="cl"><span class="sd">                }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/octoprint</span></span></span></code></pre></div></div>

<h3 class="relative group">NINA Warnungen
    <div id="nina-warnungen" class="anchor"></div>
    
</h3>
<p>Das <a href="https://www.bbk.bund.de/"  target="_blank" rel="noreferrer">Bundesamt für Bevölkerungsschutz und Katastrophenhilfe</a> stellt über die <a href="https://www.home-assistant.io/integrations/nina/"  target="_blank" rel="noreferrer">NINA Integration</a> ortsbezogene Warnmeldungen für die Bevölkerung bereit. Diese Custom App prüft, ob eine Warnung vorliegt und nutzt das <a href="https://blueforcer.github.io/awtrix-light/#/api?id=colored-indicators"  target="_blank" rel="noreferrer">Indicator Feature</a> von AWTRIX Light. Liegt eine Warnung vor, leuchtet der Indicator so lange über allen anderen Custom Apps rot, bis die Warnung aufgehoben wird. Bei Aufhebung der Warnung wird die Custom App automatisch entfernt.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock-custom-app-collection/nina.gif"
          alt="Pixelclock showing warnings from NINA warn app"
        />
  
  
  </figure>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th></th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>LaMetric Icon</td>
					<td>9335 / warning.gif</td>
			</tr>
			<tr>
					<td>Integration</td>
					<td><a href="https://www.home-assistant.io/integrations/nina/"  target="_blank" rel="noreferrer">NINA</a></td>
			</tr>
			<tr>
					<td>Sensor</td>
					<td>binary_sensor.warning_kiel</td>
			</tr>
	</tbody>
</table>
</div>
<p><strong>Automation:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">notify_pixelclock_warning</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">binary_sensor.warning_kiel</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">choose</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">binary_sensor.warning_kiel</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;on&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">sequence</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">                  {
</span></span></span><span class="line"><span class="cl"><span class="sd">                    &#34;text&#34;: &#34;{{ state_attr(&#34;binary_sensor.warning_kiel&#34;, &#34;headline&#34;) }}&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">                    &#34;icon&#34;: &#34;warning&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">                    &#34;pushIcon&#34;: 2
</span></span></span><span class="line"><span class="cl"><span class="sd">                  }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/nina</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">                  {
</span></span></span><span class="line"><span class="cl"><span class="sd">                    &#34;color&#34;: [255,0,0]
</span></span></span><span class="line"><span class="cl"><span class="sd">                  }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/indicator1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">binary_sensor.warning_kiel</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;off&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">sequence</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/nina</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/indicator1</span></span></span></code></pre></div></div>

<h3 class="relative group">Homeassistant Timer
    <div id="homeassistant-timer" class="anchor"></div>
    
</h3>
<p>Homeassistant hat eine <a href="https://www.home-assistant.io/integrations/timer/"  target="_blank" rel="noreferrer">Timer Integration</a>, die auf dem Eventbus feuert, wenn ein Timer abgelaufen ist. Wie bereits im Beitrag <a href="/posts/controllerx/">ControllerX und Home Assistant</a> beschrieben, nutze ich diese für meine Waschmaschine.</p>
<p>Verwendet wird ein <a href="https://www.ikea.com/de/de/p/tradfri-shortcut-button-weiss-smart-40356381/"  target="_blank" rel="noreferrer">Tradfri Shortcut Button</a>. Wenn der Button einfach gedrückt wird startet ein Timer für eine 40° Wäsche, wird er gedrückt gehalten startet ein Timer für die 60° Wäsche.</p>
<p>Ist einer der beiden Timer abgelaufen lauscht eine Automation auf dem Eventbus</p>
<p><strong>Timer Configuration:</strong></p>
<p>Die Werte müssen entsprechend der Waschdauer des eigenen Geräts angepasst werden.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">laundry_40</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">duration</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;01:58:00&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">laundry_60</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">duration</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;02:09:00&#39;</span></span></span></code></pre></div></div>
<p><strong>Automation:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">notify_pixelclock_laundy_finished</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">event</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">event_type</span><span class="p">:</span><span class="w"> </span><span class="l">timer.finished</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">event_data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">timer.laundry_40</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">event</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">event_type</span><span class="p">:</span><span class="w"> </span><span class="l">timer.finished</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">event_data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">timer.laundry_60</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;text&#34;: &#34;Fertig&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;icon&#34;: &#34;laundry&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;hold&#34;: true
</span></span></span><span class="line"><span class="cl"><span class="sd">          }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/notify</span></span></span></code></pre></div></div>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th></th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>LaMetric Icon</td>
					<td>26671 / laundry.gif</td>
			</tr>
			<tr>
					<td>Integration</td>
					<td><a href="https://www.home-assistant.io/integrations/timer/"  target="_blank" rel="noreferrer">Timer</a></td>
			</tr>
	</tbody>
</table>
</div>

<h3 class="relative group">Rauchmelder Warnung
    <div id="rauchmelder-warnung" class="anchor"></div>
    
</h3>
<p>Im Post <a href="/posts/smoke-detector/">Zigbee Rauchmelder</a> ist eine weitere Custom App <a href="/posts/smoke-detector/#nachricht-auf-ulanzi-pixelclock" >beschrieben</a>, die auf der Pixelclock eine Warnung ausgibt, wenn ein Zigbee Rauchmelder einen Brand/Rauch detektiert.</p>

<h3 class="relative group">Spritpreise
    <div id="spritpreise" class="anchor"></div>
    
</h3>
<p>Mit der <a href="https://www.home-assistant.io/integrations/tankerkoenig/"  target="_blank" rel="noreferrer">Tankerkönig Integration</a>, können die Spritpreise nahegelegener Tankstellen angezeigt werden. Dafür muss zuvor ein <a href="https://creativecommons.tankerkoenig.de/"  target="_blank" rel="noreferrer">API-Key</a> erstellt werden.</p>


  

<figure class="centered"><img src="/posts/pixelclock-custom-app-collection/spritpreis.png">
</figure>


<p>Der nachfolgende Automationscode nutzt beispielhaft den Sensor mit dem Namen <code>sensor.shell_pansenstrasse_15_super</code> und entfernt den Tankstellenpfennig/Zehntelpfennig <code>9</code>. Aus <code>2.059 €</code> wird <code>2.05 €</code>.</p>
<p><strong>Automation:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">notify_pixelclock_gasprice</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Spritpreis ohne Tankstellencent 9&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">trigger</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.shell_adelheidstr_15_super</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;text&#34;: &#34;{{ &#34;%.2f&#34; | format((states(&#39;sensor.shell_pansenstrasse_15_super&#39;) | float * 100) | int / 100) }} €&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;icon&#34;: &#34;fuel&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">          }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/gasprice</span></span></span></code></pre></div></div>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th></th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>LaMetric Icon</td>
					<td>55274 / fuel.gif</td>
			</tr>
			<tr>
					<td>Integration</td>
					<td><a href="https://www.home-assistant.io/integrations/tankerkoenig/"  target="_blank" rel="noreferrer">Tankerkönig</a></td>
			</tr>
	</tbody>
</table>
</div>

<h2 class="relative group">Links
    <div id="links" class="anchor"></div>
    
</h2>
<table>
	<thead>
			<tr>
					<th></th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>hivemq.com</td>
					<td><a href="https://www.hivemq.com/blog/mqtt-essentials-part-8-retained-messages/"  target="_blank" rel="noreferrer">MQTT Retained Messages</a></td>
			</tr>
			<tr>
					<td>developer.lametric.com</td>
					<td><a href="https://developer.lametric.com/icons"  target="_blank" rel="noreferrer">LaMetric Icons</a></td>
			</tr>
	</tbody>
</table>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Ulanzi Smart Pixel Clock TC001</title>
      <link>https://jbetzen.net/posts/pixelclock/</link>
      <pubDate>Thu, 30 Mar 2023 20:33:58 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/pixelclock/</guid>
      <description>Die Ulanzi Pixelclock ist eine kleine Pixelmatrix, die über die Installation der Custom Firmware AWTRIX3 und deren Integration als Notifier in Homeassistant genutzt werden kann. Die Clock eignet sich hervorragend als stationäres Display für Statusupdates.</description>
      <content:encoded><![CDATA[ <p>Die <a href="https://www.ulanzi.de/products/ulanzi-pixel-smart-uhr-2882"  target="_blank" rel="noreferrer">Ulanzi Pixel Clock TC001</a> ist für ca. 40€ zu erwerben und besitzt eine 8x32 RGB-Pixelmatrix. Verbaut ist in ihr ein ESP32 Mikrokontroller, der wahlweise mit ESPHome oder mit einer Custom-Firmware geflasht werden kann. Somit kann die Pixel Clock als universeller Notifier für Homeassistant eingesetzt werden. Neben der Möglichkeit animierte GIFs und statische Icons anzuzeigen, besitzt die Pixel Clock eine Reihe weiterer verbauter Sensoren für Helligkeit, Luftfeuchte und Temperatur und kann darüber hinaus auch (furchtbar klingende) 


<abbr title="Ring Tones Text Transfer Language">RTTTL</abbr> Sounds abspielen. Ein fest verbauter Akku mit 4400mAh erlaubt den kurzzeitigen Betrieb ohne Stromversorgung.</p>

<h2 class="relative group">Custom Firmware: AWTRIX3
    <div id="custom-firmware-awtrix3" class="anchor"></div>
    
</h2>
<p>Obwohl für die Pixel Clock eine <a href="https://blakadder.com/esphome-pixel-clock/"  target="_blank" rel="noreferrer">ausführliche Anleitung</a> zur Verwendung mit <a href="/categories/esphome/" >ESPHome</a> existiert, habe ich mich für die Verwendung mit der Custom Firmware <a href="https://github.com/Blueforcer/awtrix3"  target="_blank" rel="noreferrer">AWTRIX3</a> entschieden.</p>
<p>Die Firmware ist quelloffen und unterstützt <em>Homeassistant Discovery</em>, das eine unkomplizierte Integration mittels MQTT ermöglicht. Vorrausetzung ist, dass ein MQTT-Broker betrieben wird - bspw. mittels des Homeassistant Add-On <a href="https://github.com/home-assistant/addons/tree/master/mosquitto"  target="_blank" rel="noreferrer">Mosquitto Broker</a>.</p>

<h3 class="relative group">Firmware flashen
    <div id="firmware-flashen" class="anchor"></div>
    
</h3>
<p>AWTRIX3 kann sehr einfach mittels ESP Web Tools direkt aus dem Chrome/Edge Browser auf das Gerät geflasht werden. Dazu muss die Pixel Clock lediglich mittels USB-C Kabel mit einem Rechner verbunden werden und der zugehörige <a href="https://blueforcer.github.io/awtrix3/#/flasher"  target="_blank" rel="noreferrer">Online Flasher</a> im Browser aufgerufen werden. Nach einem erfolgreichen Flashen wechselt die Pixel Clock in den AP-Modus und spannt ein WiFi mit dem Namen <code>awtrix_XXXXX</code> auf, das mit dem Passwort <code>12345678</code> verbunden werden kann. Nachdem die Verbindungsdaten zum heimischen WiFi hinterlegt wurden, startet die Pixel Clock neu und ist fortan im eigenen Netzwerk erreichbar. Die vergebene IP wird praktischerweise auf dem Display dargestellt.</p>

<h3 class="relative group">Ersteinrichtung
    <div id="ersteinrichtung" class="anchor"></div>
    
</h3>
<p>Ruft man nun das Webinterface der Pixel Clock im Browser auf erscheint eine Oberfläche zur Konfiguration:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock/awtrix-light-menu.png"
          alt=""
        />
  
  
  </figure>
<p>Die Menupunkte und ihre Einstellungsmöglichkeiten im Detail:</p>
<table>
	<thead>
			<tr>
					<th>Menüpunkt</th>
					<th>Einstellungsmöglichkeiten</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>WiFi Setup</td>
					<td>Hier können bei Bedarf neue WiFi Credentials hinterlegt werden.</td>
			</tr>
			<tr>
					<td>Network</td>
					<td>Netzwerkeinstellungen, wie DNS Server oder Vergabe einer statischen IP.</td>
			</tr>
			<tr>
					<td>MQTT</td>
					<td>Hier müssen die MQTT-Broker Einstellungen hinterlegt und Homeassistant Discovery aktiviert werden. Auch kann hier der Prefix für MQTT festgelegt werden, über den die Pixel Clock angesprochen werden kann.</td>
			</tr>
			<tr>
					<td>Time</td>
					<td>NTP Server zur zeitsynchronisation und Zeitzoneneinstellungen.</td>
			</tr>
			<tr>
					<td>Icons</td>
					<td>Hierüber können Icons und animierte Gifs auf das lokale Dateisystem des ESP32 geladen werden, die in den dargstellten Nachrichten angezeigt werden können.</td>
			</tr>
			<tr>
					<td>General</td>
					<td>Hier kann festgelegt werden, ob Text nur in Großbuchstaben (<em>Uppercase</em>) dargestellt werden soll.</td>
			</tr>
			<tr>
					<td>Files</td>
					<td>Öffnet ein weiteres Browserfenster zur einfachen Verwaltung von Icons, RTTTL-Melodien, Alarmen oder der globalen Konfigurationsdatei von AWTRIX3.</td>
			</tr>
			<tr>
					<td>Update</td>
					<td>Erlaubt das Flashen von Firmware Updates direkt aus dem Webbrowser.</td>
			</tr>
	</tbody>
</table>
<p>Sind alle Einstellungen getätigt und die MQTT-Konfigurationswerte korrekt eingegeben worden, erkennt Homeassistant automatisch alle Sensoren und Funktionen der Pixel Clock:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock/hass-discovery.png"
          alt=""
        />
  
  
  </figure>

<h3 class="relative group">Bedienung
    <div id="bedienung" class="anchor"></div>
    
</h3>
<p>Im Gegensatz zur Standardfirmware von Ulanzi ermöglicht AWTRIX3 die Standardfunktionen, bspw. welche Infos dargestellt werden sollen, wie lange eine Info sichtbar sein soll oder wie schnell die Transition beim Bildschirmwechsel erfolgen soll, direkt über die 3 Buttons auf der Oberseite der Pixel Clock einzustellen. Dazu muss der mittlere Knopf 2 Sekunden gedrückt werden. Anschließend kann mit dem linken und rechten Button navigiert werden. Möchte man ein Untermenüpunkt aktivieren erfolgt dies über einen einfachen Klick auf den mittleren Button. Möchte man zurück ins Menü kehren erfolgt dies wieder durch ein zweisekündiges Gedrückthalten des mittleren Buttons.</p>

<h3 class="relative group">Icons herunterladen
    <div id="icons-herunterladen" class="anchor"></div>
    
</h3>
<p>Icons können von der Konkurrenz von <a href="https://lametric.com/en-US"  target="_blank" rel="noreferrer">LaMetric</a> genutzt und heruntergeladen werden. Neben vielen existierenden Icons und Gifs können auf der <a href="https://developer.lametric.com/icons"  target="_blank" rel="noreferrer">Herstellerseite</a> auch eigene Icons generiert werden.</p>
<p>Hat man ein passendes Icon gefunden, muss lediglich die <code>ID</code> des Icons im Webinterface von AWTRIX3 im Menüpunkt <em>Icons</em> eingegeben werden. Es kann ein Preview generiert und die Datei direkt ins Dateisystem heruntergeladen werden. Die Icons liegen im Ordner <code>/ICONS/</code>und haben standardmäßig das Namensschema <code>$ID.jpg</code> oder <code>$ID.gif</code>. Die Dateinamen können direkt im Webinterface mit einem Rechtsklick und der Funktion <code>Rename/Move</code> in sprechende Namen umbenannt werden:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock/awtrix-light-filesystem.png"
          alt=""
        />
  
  
  </figure>

<h3 class="relative group">RTTTL Soundfiles speichern
    <div id="rtttl-soundfiles-speichern" class="anchor"></div>
    
</h3>
<p><em>Ring Tone Text Transfer Language</em>, kurz RTTTL, Soundfiles können im Ordner <code>/MELODIES/</code> im <code>txt</code>-Format abgelegt werden. Ein kleiner Fundus an RTTTL-Soundfiles kann <a href="https://www.laub-home.de/wiki/RTTTL_Songs"  target="_blank" rel="noreferrer">hier</a> entdeckt und verwendet werden. Möchte man beispielsweise die Titelmelodie der TV Serie <em>Die Simpsons</em> erklingen lassen, legt man die Datei <code>/MELODIES/simpsons.txt</code> an und fügt dort den folgenden Inhalt ein:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">The Simpsons:d=4,o=5,b=160:c.6,e6,f#6,8a6,g.6,e6,c6,8a,8f#,8f#,8f#,2g,8p,8p,8f#,8f#,8f#,8g,a#.,8c6,8c6,8c6,c6</span></span></code></pre></div></div>

<h2 class="relative group">Nutzen als Notifier in Homeassistant
    <div id="nutzen-als-notifier-in-homeassistant" class="anchor"></div>
    
</h2>
<p>Über MQTT können nun Notifications direkt aus Homeassistant an die Pixel Clock gesendet werden. Entscheidend ist hierfür das vom Benutzer vergebene MQTT Präfix, welches in der Ersteinrichtung gewählt wurde. Ich habe an dieser Stelle den Präfix <code>pixelclock</code> gewählt. Möchte man grundsätzlich erst einmal testen wie Notifications auf der Clock aussehen, kann dies sehr einfach in den <em>Developer Tools</em> von Homeassistant erfolgen. Dazu den Menüpunkt <code>Services</code> auswählen und dann den Service <code>mqtt.publish</code>:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock/hass-devtools.png"
          alt=""
        />
  
  
  </figure>
<p>Es stehen grundsätzlich <strong>zwei Arten</strong> der Notification mit diversen <em>Payload Parametern</em> zur Verfügung, die in der Sektion <a href="https://blueforcer.github.io/awtrix3/#/api?id=custom-apps-and-notifications"  target="_blank" rel="noreferrer">Custom Apps and Notifications</a> beschrieben werden:</p>
<ol>
<li><strong>Notification:</strong> Eine Textnachricht, ggf. mit Icon, die für eine definierbare Dauer dargestellt wird. Es besteht auch die Möglichkeit eine Notification solange darzustellen, bis sie durch einen Klick auf den mittleren Button entfernt wird.</li>
<li><strong>Custom Page:</strong> Standardmäßig wechselt die Pixel Clock durch ein definierte Liste an Infobildschirmen. Ist das Ende der Liste erreicht, beginnt sie von vorne. Diese Liste kann mit einer (oder mehreren) Custom Page erweitert werden.</li>
</ol>

<h3 class="relative group">Fall 1: Notification
    <div id="fall-1-notification" class="anchor"></div>
    
</h3>
<p><strong>Fiktiver Fall:</strong> Ein Rauchmelder in der Wohnung meldet einen Brand. Hierzu habe ich das Feuer-Icon mit der LaMetric-ID <code>24873</code> über das Webinterface von AWTRIX3 heruntergeladen und anschließend in <code>feuer.gif</code> umbenannt. Um nun dieses Icon und den Text <code>Feuer!</code> auf dem Display anzuzeigen wird der folgende Service Call gesendet:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">    {
</span></span></span><span class="line"><span class="cl"><span class="sd">      &#34;icon&#34;: &#34;fire&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">      &#34;text&#34;: &#34;Feuer!&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">      &#34;hold&#34;: true
</span></span></span><span class="line"><span class="cl"><span class="sd">    }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/notify</span></span></span></code></pre></div></div>
<p>Der Parameter <code>hold</code> bewirkt dabei, dass die Darstellung erst beendet wird wenn sie durch einen Klick auf den mittleren Button bestätigt wird.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock/feuer.gif"
          alt=""
        />
  
  
  </figure>

<h3 class="relative group">Fall 2: Custom Page
    <div id="fall-2-custom-page" class="anchor"></div>
    
</h3>
<p><strong>Fiktiver Fall:</strong> Der Wert eines Sensors in Homeassistant soll kontinuierlich auf der Pixel Clock angezeigt werden. Ändert sich der Wert, soll auch die Info auf der Pixelclock aktuell sein. Als Beispiel dient ein REST-Sensor für ein deutsches Bilderbrett, das im <a href="https://community.home-assistant.io/t/pr0gramm-com-benis-sensor/76946"  target="_blank" rel="noreferrer">Homeassistant Forum</a> zu finden ist. Verwendet wird das Icon mit der LaMetric ID <code>26807</code>, das anschließend unter dem Dateinamen <code>pr0.jpg</code> gespeichert wurde. Der Sensor hat den Namen <code>sensor.pr0</code>. Zu beachten ist, dass jede Custom Page einen eindeutigen Namen erhält. In diesem Fall ist es <code>pr0</code>. Die Automation in Homeassistant sieht wie folgt aus:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">notify_pixelclock_pr0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.pr0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">        {
</span></span></span><span class="line"><span class="cl"><span class="sd">          &#34;text&#34;: &#34;{{ states.sensor.pr0.state }}&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">          &#34;icon&#34;: &#34;pr0&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">        }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/pr0</span></span></span></code></pre></div></div>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock/pr0.gif"
          alt=""
        />
  
  
  </figure>
<p>Custom Pages sollten ggf. mit dem parameter <code>retain: true</code> gesendet werden. Der MQTT-Broker speichert somit das letzte gesendete <code>mqtt.publish</code> Kommando und stellt dieses bei einem Neustart der Pixel Clock wieder zur Verfügung. Nähere Erläuterungen zum Thema <strong>Retained Messages</strong> sind im Folgepost <a href="/posts/pixelclock-custom-app-collection/">Pixelclock: Custom App Collection</a> zu finden.</p>





  
  
    
  
  


  <section class="space-y-10 w-full">
    
    











  
  
  








  
  
    
    

    
    
      
      
        
      
        
      
        
      
    

    
    

    
    
      
        
        
      
    
  



<article class="article-link--shortcode flex flex-col md:flex-row relative">
  
    <div class="flex-none relative overflow-hidden  thumbnail-shadow md:mr-7 thumbnail">
      <img
        src="/posts/pixelclock-custom-app-collection/featured.png"
        role="presentation"
        loading="lazy"
        decoding="async"
        class="not-prose absolute inset-0 w-full h-full object-cover">
    </div>
  
  <div class=" mt-3 md:mt-0">
    <header class="items-center text-start text-xl font-semibold">
      <a
        
          href="/posts/pixelclock-custom-app-collection/"
        
        class="not-prose before:absolute before:inset-0 decoration-primary-500 dark:text-neutral text-xl font-bold text-neutral-800 hover:underline hover:underline-offset-2">
        <h2>
          Pixelclock: Custom App Collection
          
        </h2>
      </a>
      
      
    </header>
    <div class="text-sm text-neutral-500 dark:text-neutral-400">
      







  

  
  
  
    
  

  

  
    
  

  
    
  

  
    
  

  
    
  

  

  

  

  

  


  <div class="flex flex-row flex-wrap items-center">
    
    
      <time datetime="2023-04-29T11:29:27&#43;02:00">29.04.2023</time><span class="px-2 text-primary-500">&middot;</span><time datetime="2026-03-05T00:00:00&#43;00:00">Aktualisiert: 05.03.2026</time><span class="px-2 text-primary-500">&middot;</span><span>1556 Wörter</span><span class="px-2 text-primary-500">&middot;</span><span title="Lesezeit">8 min</span>
    

    
    
  </div>

  

  
  
    <div class="flex flex-row flex-wrap items-center">
      
        
      
        
          
            
              
                <a class="relative mt-[0.5rem] me-2" href="/categories/mqtt/">
                  
                  <span class="flex cursor-pointer">
  
  
  
    
    
  
  
    <span
      class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal text-primary-700 dark:border-primary-600 dark:text-primary-400">
  
    MQTT
  </span>
</span>

                </a>
              
            
            
          
            
              
                <a class="relative mt-[0.5rem] me-2" href="/categories/microcontroller/">
                  
                  <span class="flex cursor-pointer">
  
  
  
    
    
  
  
    <span
      class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal text-primary-700 dark:border-primary-600 dark:text-primary-400">
  
    Microcontroller
  </span>
</span>

                </a>
              
            
            
          
            
              
                <a class="relative mt-[0.5rem] me-2" href="/categories/media-player/">
                  
                  <span class="flex cursor-pointer">
  
  
  
    
    
  
  
    <span
      class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal text-primary-700 dark:border-primary-600 dark:text-primary-400">
  
    media-player
  </span>
</span>

                </a>
              
            
            
          
            
              
                <a class="relative mt-[0.5rem] me-2" href="/categories/notification/">
                  
                  <span class="flex cursor-pointer">
  
  
  
    
    
  
  
    <span
      class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal text-primary-700 dark:border-primary-600 dark:text-primary-400">
  
    Notification
  </span>
</span>

                </a>
              
            
            
          
        
      
        
      
        
          
            
              
            
            
          
            
              
            
            
          
            
              
            
            
          
        
      
        
          
            
              
            
            
          
        
      
    </div>
  


    </div>
    
      
      <div
        class="article-link__summary prose dark:prose-invert max-w-fit mt-1 ">
        Da die Entwicklung der Custom Firmware AWTRIX3 schleunig voranschreitet und fortlaufend neue Features eingebaut werden, soll dieser Post als Sammler für derzeitige und zukünftige Custom Apps dienen.
      </div>
    
  </div>
</article>

  </section>


<p>Möchte man die Custom Page wieder entfernen, erfolgt dies über das erneute adressieren des App-Topics, jedoch mit einer leeren <em>Payload</em>:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/pr0</span></span></span></code></pre></div></div>

<h2 class="relative group">Sounds Wiedergeben
    <div id="sounds-wiedergeben" class="anchor"></div>
    
</h2>
<p>Generell kann jeder Art von Notification auch eine <a href="https://blueforcer.github.io/awtrix3/#/api?id=sound-playback"  target="_blank" rel="noreferrer">Soundwiedergabe</a> zugewiesen werden, wovon man nur abraten kann. Verwendet wird exemplarisch die bereits erwähnte <code>simpsons.txt</code> RTTTL-File:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">    {
</span></span></span><span class="line"><span class="cl"><span class="sd">      &#34;sound&#34;: &#34;simpsons&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">    }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/sound</span></span></span></code></pre></div></div>
<p>Alternativ kann auch direkt ein RTTTL-String über die API-Endpoint <code>/RTTTL</code> abgespielt werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">    {
</span></span></span><span class="line"><span class="cl"><span class="sd">      &#34;sound&#34;: &#34;d=4,o=5,b=160:c.6,e6,f#6,8a6,g.6,e6,c6,8a,8f#,8f#,8f#,2g,8p,8p,8f#,8f#,8f#,8g,a#.,8c6,8c6,8c6,c6&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">    }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/rtttl</span></span></span></code></pre></div></div>
<p>Der Timer ist nach 3 Sekunden abgelaufen und spielt anschließend die Melodie so lange, bis der mittlere Button auf der Clock gedrückt wird.</p>

<h2 class="relative group">Automation: Spotify Media Player
    <div id="automation-spotify-media-player" class="anchor"></div>
    
</h2>
<p>Die Pixel Clock eignet sich hervorragend Informationen zum aktuell wiedergegebenen Interpreten und Song darzustellen. Genutzt wird in diesem Beispiel die <a href="https://www.home-assistant.io/integrations/spotify/"  target="_blank" rel="noreferrer">Spotify Integration</a>. Analog wird erneut ein passendes Icon gesucht und als <code>spotify.gif</code> oder <code>spotify.jpg</code> auf der Clock gespeichert.</p>
<p>Als <strong>Trigger</strong> wird der <em>State</em> des Spotify Media Player verwendet. Erfolgt eine aktive Wiedergabe wechselt dessen State auf <code>playing</code> und stellt zusätzlich die Attribute <code>media_artist</code> (Interpret) und <code>media-title</code> (Songname) bereit. Wird die Wiedergabe pausiert wechselt der State zu <code>idle</code> und die Attribute stehen nicht länger zur Verfügung, daher muss dieser Fall als Ausnahme über eine <em>Condition</em> ausgeschlossen werden.</p>
<p>Da die dargestellte Textinformation unter Umständen sehr lang ausfallen, macht es Sinn einen höheren Wert für die <code>duration</code> (Anzeigedauer) zu wählen. Auch ist in diesem Fall die Option <code>pushIcon</code> mit dem Wert <code>2</code> gesetzt. Dies bewirkt, dass das Icon mit dem Scrollen des Textes <em>mitfährt</em> und anschließend beim nächsten Durchlauf erneut erscheint.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">notify_pixelclock_spotify</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.spotify</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">condition</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">not</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.spotify</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;idle&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;text&#34;: &#34; {{ state_attr(&#39;media_player.spotify&#39;, &#39;media_artist&#39;) }} - {{ state_attr(&#39;media_player.spotify&#39;, &#39;media_title&#39;) }}&#34;, 
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;icon&#34;: &#34;spotify&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;duration&#34;: 10,
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;pushIcon&#34;: 2
</span></span></span><span class="line"><span class="cl"><span class="sd">          }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/notify</span></span></span></code></pre></div></div>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/pixelclock/spotify.gif"
          alt=""
        />
  
  
  </figure>

<h2 class="relative group">Wetteranzeige
    <div id="wetteranzeige" class="anchor"></div>
    
</h2>
<p>Die Pixelclock lässt sich hervorragend als Wetteranzeiger nutzen. Voraussetzung ist eine eingerichtete <a href="https://www.home-assistant.io/integrations/weather/"  target="_blank" rel="noreferrer">Weather Integration</a> bspw. <a href="https://www.home-assistant.io/integrations/openweathermap/"  target="_blank" rel="noreferrer">OpenWeatherMap</a>. Die <em>Weather Integration</em> hat, ungeachtet des gewählten Wetterdatenproviders, ein festes <a href="https://www.home-assistant.io/integrations/openweathermap/"  target="_blank" rel="noreferrer">Condition Mapping</a>:</p>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th>State</th>
					<th>Erläuterung</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>clear-night</code></td>
					<td>Klare Nacht ohne Wolken</td>
			</tr>
			<tr>
					<td><code>cloudy</code></td>
					<td>Bewölkt</td>
			</tr>
			<tr>
					<td><code>fog</code></td>
					<td>Nebel</td>
			</tr>
			<tr>
					<td><code>hail</code></td>
					<td>Hagel</td>
			</tr>
			<tr>
					<td><code>lightning</code></td>
					<td>Gewitter</td>
			</tr>
			<tr>
					<td><code>lightning-rainy</code></td>
					<td>Gewitter mit Regen</td>
			</tr>
			<tr>
					<td><code>partlycloudy</code></td>
					<td>Teilweise bewölkt</td>
			</tr>
			<tr>
					<td><code>pouring</code></td>
					<td>Starkregen</td>
			</tr>
			<tr>
					<td><code>rainy</code></td>
					<td>Regen</td>
			</tr>
			<tr>
					<td><code>snowy</code></td>
					<td>Schneefall</td>
			</tr>
			<tr>
					<td><code>snowy-rainy</code></td>
					<td>Schneeregen</td>
			</tr>
			<tr>
					<td><code>sunny</code></td>
					<td>Sonnig</td>
			</tr>
			<tr>
					<td><code>windy</code></td>
					<td>Windig</td>
			</tr>
			<tr>
					<td><code>windy-variant</code></td>
					<td>Windig mit Wolken</td>
			</tr>
			<tr>
					<td><code>exceptional</code></td>
					<td>Keine exakt zuordbare Wetterkondition</td>
			</tr>
	</tbody>
</table>
</div>
<p>Damit eine eindeutige Zuordnung der dargestellten Icons zu der aktuellen Wetterlage möglich ist, sollte für jeden State ein passendes Icon auf die Pixel Clock geladen werden, dass genau den Namen des <em>States</em> trägt, bspw. <code>fog.jpg</code> oder <code>lightning-rainy.gif</code>.</p>
<p>Anschließend kann unter Hilfenahme von Templates eine Automation für eine Custom Page zur Anzeige des Wetters erstellt werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">notify_pixelclock_weather</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">weather.openweathermap</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt.publish</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">qos</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">retain</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;text&#34;: &#34;{{ states.weather.openweathermap.attributes.temperature | round(0) }} {{ states.weather.openweathermap.attributes.temperature_unit }}&#34;,
</span></span></span><span class="line"><span class="cl"><span class="sd">            &#34;icon&#34;: &#34;{{ states(&#39;weather.openweathermap&#39;) }}&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">          }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">pixelclock/custom/weather</span></span></span></code></pre></div></div>
<p>Die Temperaturwerte werden ganzzahlig gerundet und die Temperatureinheit, bspw. <code>°C</code>, an den Wert angehangen.</p>

<h2 class="relative group">Resources
    <div id="resources" class="anchor"></div>
    
</h2>
<table>
	<thead>
			<tr>
					<th></th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>AWTRIX3 Firmware</td>
					<td><a href="https://github.com/Blueforcer/awtrix3/releases"  target="_blank" rel="noreferrer">Github Releases</a></td>
			</tr>
			<tr>
					<td>AWTRIX3 Doku</td>
					<td><a href="https://blueforcer.github.io/awtrix3/#/README"  target="_blank" rel="noreferrer">blueforcer.github.io</a></td>
			</tr>
			<tr>
					<td>LaMetric Icon Gallery</td>
					<td><a href="https://developer.lametric.com/icons"  target="_blank" rel="noreferrer">lametric.com</a></td>
			</tr>
			<tr>
					<td>Weather Condition Mapping</td>
					<td><a href="https://developers.home-assistant.io/docs/core/entity/weather/#recommended-values-for-state-and-condition"  target="_blank" rel="noreferrer">developers.homeassistant.com</a></td>
			</tr>
	</tbody>
</table>
<lite-youtube videoid="N0NKPJzGHuA" playlabel="N0NKPJzGHuA" params=""></lite-youtube>

 ]]></content:encoded>
    </item>
    
    <item>
      <title>Stromkosten mit Tasmota errechnen</title>
      <link>https://jbetzen.net/posts/tasmota-stromkosten/</link>
      <pubDate>Sat, 03 Sep 2022 21:11:51 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/tasmota-stromkosten/</guid>
      <description>Mit Tasmota geflashte Steckdosen stellen Statistiken für den täglichen Stromverbrauch bereit. In Kombination mit einer Variable, die den Strompreis beinhaltet, kann somit Verbrauch in monetäre Beträge gewandelt werden.</description>
      <content:encoded><![CDATA[ <p>Mit großer Freude erreichte mich die frohe Kunde, dass mein lokaler Stromanbieter eine Anhebung der Strompreise vorsieht. Die vormalig geltenden 23,21c/kWh werden auf den Betrag von 36,15c/kWh erhöht.</p>
<p>Um den täglichen Verbrauch aller Tasmota-Steckdosen in den real anfallenden Geldbetrag zu wandeln, wird die Custom Component <a href="https://github.com/rogro82/hass-variables"  target="_blank" rel="noreferrer">hass-variables</a> benötigt. Diese kann aus dem HACS-Store installiert werden und kam unter anderem bereits in diesen Posts zum einsatz:</p>

  
      <ul>
        
          <li><a href="/posts/room-based-presence/">Room Based Presence mit Motion Sensoren</a></li>
        
          <li><a href="/posts/fritzbox-callmon/">Homeassistant, FritzBox und Anrufbenachrichtigung per Push-Nachricht</a></li>
        
      </ul>
  



<h2 class="relative group">Zur Theorie des Vorhabens
    <div id="zur-theorie-des-vorhabens" class="anchor"></div>
    
</h2>
<p>Die Tasmota-Steckdosen liefern einen Wert zum täglichen Stromverbrauch (<code>Energy Today</code>), der um Mitternacht auf <code>0</code> gesetzt wird. Tagsüber kann also dieser kumulierende Wert mit dem aktuellen Strompreis multipliziert werden und man erhält den anfallenden Geldbetrag.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/tasmota-stromkosten/tasmota-stats.png"
          alt=""
        />
  
  
  </figure>
<p>Den Strompreis möchte ich zentral in einer Variable festhalten. So kann bei Verwendung mehrerer Tasmota-Steckdosen zentral auf diesen Wert zugegriffen und bei der nächsten anstehenden Erhöhung muss nur an einer Stelle der Strompreis geändert werden.</p>

<h2 class="relative group">Strompreisvariable anlegen
    <div id="strompreisvariable-anlegen" class="anchor"></div>
    
</h2>
<p>Nachdem <em>hass-variable</em> installiert wurde, muss folgender Eintrag in der <code>configuration.yaml</code> erfolgen:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">var</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">strompreis</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restore</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">initial_value</span><span class="p">:</span><span class="w"> </span><span class="m">0.3615</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">mdi:currency-eur</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">friendly_name</span><span class="p">:</span><span class="w"> </span><span class="l">Strompreis</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">unit_of_measurement</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;€/kwh&#39;</span></span></span></code></pre></div></div>
<p>Anschließend steht die Variable mit der Entity ID <code>var.strompreis</code> in Homeassistant zur Verfügung.</p>

<h2 class="relative group">Template Sensor
    <div id="template-sensor" class="anchor"></div>
    
</h2>
<p>Nun muss nur noch ein Sensor erstellt werden, der den Tagesverbrauch von einer beliebigen Tasmota Steckdose ausließt und mit dem Strompreis multipliziert. In diesem Beispiel dient mein Kühlschrank mit der Entity ID <code>sensor.kuehlschrank_energy_today</code> als Beispiel parat. Der Sensor muss ebenfalls in der <code>configuration.yaml</code> angelegt werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">sensor</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">kuehlschrank_kosten_heute</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ &#34;%.2f&#34; | format(states.sensor.kuehlschrank_energy_today.state | float | multiply(states.var.strompreis.state | float)) }}&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">unit_of_measurement</span><span class="p">:</span><span class="w"> </span><span class="l">€</span></span></span></code></pre></div></div>
<p>Der Sensor liefert einen zweistelligen Nachkommawert à la <code>0,07€</code>.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/tasmota-stromkosten/sensor-stromkosten.png"
          alt=""
        />
  
  
  </figure>

<h2 class="relative group">Kumulierte Kosten mehrerer Steckdosen
    <div id="kumulierte-kosten-mehrerer-steckdosen" class="anchor"></div>
    
</h2>
<p>Wer mehrere Tasmota-Steckdosen im Eigenheim betreibt, kann den obigen Sensor für alle weiteren Steckdosen einrichten und am Ende die Gesamtsummer errechnen:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">sensor</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">kosten_gesamt_elektrische_verbraucher</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ &#39;%.2f&#39; | format( (states(&#39;sensor.kuehlschrank_kosten_heute&#39;) | float) + (states(&#39;sensor.heimserver_kosten_heute&#39;) | float) }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">unit_of_measurement</span><span class="p">:</span><span class="w"> </span><span class="l">€</span></span></span></code></pre></div></div>

<h2 class="relative group">Monats- &amp; Jahreskosten
    <div id="monats---jahreskosten" class="anchor"></div>
    
</h2>
<p>Da Tasmota nur einen Wert für den Tagesverbrauch liefert, muss zur Ermittlung von monatlichen oder jährlichen Kosten auf bordeigene Mittel in Homeassistant zugegriffen werden. Dafür steht die <a href="https://www.home-assistant.io/integrations/utility_meter/"  target="_blank" rel="noreferrer">Utitlity Meter</a> Integration zur Verfügung, die auch schon im <a href="/posts/fitness-tracker/" >Post zum Homeassistant Fitness Tracker</a> zum Einsatz kam:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">utility_meter</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">kuehlschrank_kosten_monatlich</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.kuehlschrank_kosten_heute</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">cycle</span><span class="p">:</span><span class="w"> </span><span class="l">monthly</span></span></span></code></pre></div></div>





  
  
    
  
  


  <section class="space-y-10 w-full">
    
    











  
  
  








  
  
    
    

    
    
      
      
        
      
        
      
        
      
    

    
    

    
    
      
        
        
      
    
  



<article class="article-link--shortcode flex flex-col md:flex-row relative">
  
    <div class="flex-none relative overflow-hidden  thumbnail-shadow md:mr-7 thumbnail">
      <img
        src="/posts/fitness-tracker/featured.png"
        role="presentation"
        loading="lazy"
        decoding="async"
        class="not-prose absolute inset-0 w-full h-full object-cover">
    </div>
  
  <div class=" mt-3 md:mt-0">
    <header class="items-center text-start text-xl font-semibold">
      <a
        
          href="/posts/fitness-tracker/"
        
        class="not-prose before:absolute before:inset-0 decoration-primary-500 dark:text-neutral text-xl font-bold text-neutral-800 hover:underline hover:underline-offset-2">
        <h2>
          Homeassistant Fitness Tracker
          
        </h2>
      </a>
      
      
    </header>
    <div class="text-sm text-neutral-500 dark:text-neutral-400">
      







  

  
  
  
    
  

  

  
    
  

  

  
    
  

  
    
  

  

  

  

  

  


  <div class="flex flex-row flex-wrap items-center">
    
    
      <time datetime="2021-01-23T23:42:13&#43;02:00">23.01.2021</time><span class="px-2 text-primary-500">&middot;</span><span>531 Wörter</span><span class="px-2 text-primary-500">&middot;</span><span title="Lesezeit">3 min</span>
    

    
    
  </div>

  

  
  
    <div class="flex flex-row flex-wrap items-center">
      
        
      
        
          
            
              
                <a class="relative mt-[0.5rem] me-2" href="/categories/utility-meter/">
                  
                  <span class="flex cursor-pointer">
  
  
  
    
    
  
  
    <span
      class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal text-primary-700 dark:border-primary-600 dark:text-primary-400">
  
    Utility Meter
  </span>
</span>

                </a>
              
            
            
          
            
              
                <a class="relative mt-[0.5rem] me-2" href="/categories/companion-app/">
                  
                  <span class="flex cursor-pointer">
  
  
  
    
    
  
  
    <span
      class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal text-primary-700 dark:border-primary-600 dark:text-primary-400">
  
    Companion App
  </span>
</span>

                </a>
              
            
            
          
        
      
        
      
        
      
        
          
            
              
            
            
          
        
      
    </div>
  


    </div>
    
      
      <div
        class="article-link__summary prose dark:prose-invert max-w-fit mt-1 ">
        Die Homeassistant Companion App liefert Fitnessdaten, die direkt vom Smartphone OS generiert werden. Diese können in Langzeitstatistiken mittels dem Utility Meter in Homeassistant getrackt und ausgewertet werden.
      </div>
    
  </div>
</article>

  </section>


 ]]></content:encoded>
    </item>
    
    <item>
      <title>ESP32-CAM mit ESPHome</title>
      <link>https://jbetzen.net/posts/esp32-cam/</link>
      <pubDate>Fri, 18 Mar 2022 14:21:34 +0100</pubDate>
      
      <guid>https://jbetzen.net/posts/esp32-cam/</guid>
      <description>Wer auf der Suche nach einer kostengünstigen experimentellen Webcam ist, wird mit der ESP32-CAM fündig. Diese basiert auf dem Microcontroller ESP32 und lässt sich kinderleicht mittels ESPHome in Homeassistant einbinden.</description>
      <content:encoded><![CDATA[ <p>Mit der ESP32-CAM ist eine günstige internetfähige Webcam auf dem Markt positioniert. Sie basiert auf dem <a href="/tags/esp32/" >ESP32</a> und lässt sich daher einfach mit <a href="/categories/esphome/" >ESPHome</a> in Homeassistant integrieren. Die kosten für die kleine Kamera belaufen sich bei <a href="https://de.aliexpress.com/wholesale?catId=0&amp;initiative_id=AS_20220318053930&amp;SearchText=esp32&#43;cam"  target="_blank" rel="noreferrer">Aliexpress</a> lediglich auf 5-6€.</p>
<p>Das Vorgehen ist einfach erklärt. Mit dem <a href="https://www.home-assistant.io/integrations/esphome/"  target="_blank" rel="noreferrer">ESPHome Add-On</a> wird eine Firmware für den ESP32 generiert und diese mittels eines <a href="https://www.amazon.de/s?k=usb&#43;ttl"  target="_blank" rel="noreferrer">USB-TTL-Adapters</a> oder alternativ einem <a href="https://www.amazon.de/LYEAA-ESP32-CAM-MB-Seriell-Adapter-Spannungsregler-Schwarz/dp/B0CVTHZFJP"  target="_blank" rel="noreferrer">USB-Adapter-Board</a> auf den Microcontroller geflasht. Das Flashen funktioniert seit kurzem reibungslos direkt über einen Webkit-basierten Browser, also Chrome oder Safari und kann daher auch von unbedarften Users einfach vorgenommen werden. Genaueres dazu kann <a href="https://esphome.github.io/esp-web-tools/"  target="_blank" rel="noreferrer">hier</a> nachgelesen werden.</p>

<h2 class="relative group">ESPHome: Firmware generieren
    <div id="esphome-firmware-generieren" class="anchor"></div>
    
</h2>
<p>Über das ESPHome Add-On muss eine neue Firmware generiert werden. Das Add-On bietet dazu einen Wizard, der den Microcontrollertypen, Ausführungen, Gerätenamen und WLan-Credentials abfragt.</p>
<p>Der Platzhalter <code>YOUR_GENERATED_ID</code> muss durch eine selbstgenerierte ID ersetzt werden. Diese kann direkt auf der <a href="https://esphome.io/components/api.html#configuration-variables"  target="_blank" rel="noreferrer">ESPHome Webseite</a> generiert und kopiert werden.</p>
<p>Die Config sollte anschließend wie folgt aussehen. Neben der Camera wird noch die eingebaute LED als eigene Entity in Homeassistant bereitgestellt:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">esphome</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">gockelcam</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">ESP32</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">board</span><span class="p">:</span><span class="w"> </span><span class="l">esp32cam</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">wifi</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">ssid</span><span class="p">:</span><span class="w"> </span>!<span class="l">secret wifi_ssid</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">password</span><span class="p">:</span><span class="w"> </span>!<span class="l">secret wifi_passwd</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># Enable fallback hotspot (captive portal) in case wifi connection fails</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">ap</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">ssid</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Gockelcam Fallback Hotspot&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">password</span><span class="p">:</span><span class="w"> </span>!<span class="l">secret ap_passwd</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">captive_portal</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># Enable logging</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">logger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># Enable Home Assistant API</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">api</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">encryption</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;YOUR_GENERATED_ID&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">ota</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">password</span><span class="p">:</span><span class="w"> </span>!<span class="l">secret ota_passwd</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">esp32_camera</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">external_clock</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">pin</span><span class="p">:</span><span class="w"> </span><span class="l">GPIO0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">frequency</span><span class="p">:</span><span class="w"> </span><span class="l">20MHz</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">i2c_pins</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">sda</span><span class="p">:</span><span class="w"> </span><span class="l">GPIO26</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">scl</span><span class="p">:</span><span class="w"> </span><span class="l">GPIO27</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">data_pins</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">GPIO5, GPIO18, GPIO19, GPIO21, GPIO36, GPIO39, GPIO34, GPIO35]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">vsync_pin</span><span class="p">:</span><span class="w"> </span><span class="l">GPIO25</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">href_pin</span><span class="p">:</span><span class="w"> </span><span class="l">GPIO23</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">pixel_clock_pin</span><span class="p">:</span><span class="w"> </span><span class="l">GPIO22</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">power_down_pin</span><span class="p">:</span><span class="w"> </span><span class="l">GPIO32</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">horizontal_mirror</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">vertical_flip</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">gockelcam</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">output</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">gpio</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">pin</span><span class="p">:</span><span class="w"> </span><span class="l">GPIO4</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="l">gpio_4</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">light</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">binary</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">output</span><span class="p">:</span><span class="w"> </span><span class="l">gpio_4</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">gockelcam light</span></span></span></code></pre></div></div>
<p>Zur Verwendung einer <code>secrets.yaml</code>-Datei mit ESPHome kann dieser Post erläuternd zu Rate gezogen werden:</p>





  
  
    
  
  


  <section class="space-y-10 w-full">
    
    











  
  
  








  
  
    
    

    
    
      
      
        
      
        
      
        
      
    

    
    

    
    
      
        
        
      
    
  



<article class="article-link--shortcode flex flex-col md:flex-row relative">
  
    <div class="flex-none relative overflow-hidden  thumbnail-shadow md:mr-7 thumbnail">
      <img
        src="/posts/esphome-btle-hub/featured.png"
        role="presentation"
        loading="lazy"
        decoding="async"
        class="not-prose absolute inset-0 w-full h-full object-cover">
    </div>
  
  <div class=" mt-3 md:mt-0">
    <header class="items-center text-start text-xl font-semibold">
      <a
        
          href="/posts/esphome-btle-hub/"
        
        class="not-prose before:absolute before:inset-0 decoration-primary-500 dark:text-neutral text-xl font-bold text-neutral-800 hover:underline hover:underline-offset-2">
        <h2>
          ESPHome Bluetooth Low Energy Hub
          
        </h2>
      </a>
      
      
    </header>
    <div class="text-sm text-neutral-500 dark:text-neutral-400">
      







  

  
  
  
    
  

  

  
    
  

  
    
  

  
    
  

  
    
  

  

  

  

  

  


  <div class="flex flex-row flex-wrap items-center">
    
    
      <time datetime="2022-01-13T23:11:40&#43;01:00">13.01.2022</time><span class="px-2 text-primary-500">&middot;</span><time datetime="2025-08-07T00:00:00&#43;00:00">Aktualisiert: 07.08.2025</time><span class="px-2 text-primary-500">&middot;</span><span>1121 Wörter</span><span class="px-2 text-primary-500">&middot;</span><span title="Lesezeit">6 min</span>
    

    
    
  </div>

  

  
  
    <div class="flex flex-row flex-wrap items-center">
      
        
      
        
          
            
              
                <a class="relative mt-[0.5rem] me-2" href="/categories/esphome/">
                  
                  <span class="flex cursor-pointer">
  
  
  
    
    
  
  
    <span
      class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal text-primary-700 dark:border-primary-600 dark:text-primary-400">
  
    ESPHome
  </span>
</span>

                </a>
              
            
            
          
            
              
                <a class="relative mt-[0.5rem] me-2" href="/categories/bluetooth/">
                  
                  <span class="flex cursor-pointer">
  
  
  
    
    
  
  
    <span
      class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal text-primary-700 dark:border-primary-600 dark:text-primary-400">
  
    Bluetooth
  </span>
</span>

                </a>
              
            
            
          
            
              
                <a class="relative mt-[0.5rem] me-2" href="/categories/xiaomi/">
                  
                  <span class="flex cursor-pointer">
  
  
  
    
    
  
  
    <span
      class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal text-primary-700 dark:border-primary-600 dark:text-primary-400">
  
    Xiaomi
  </span>
</span>

                </a>
              
            
            
          
        
      
        
      
        
          
            
              
            
            
          
            
              
            
            
          
            
              
            
            
          
            
              
            
            
          
        
      
        
          
            
              
            
            
          
        
      
    </div>
  


    </div>
    
      
      <div
        class="article-link__summary prose dark:prose-invert max-w-fit mt-1 ">
        Dieser Post beschreibt, wie man mittels ESPHome und einem ESP32 Microcontroller ein Bluetooth Low Energy Hub aufsetzt, das alle Bluetooth IoT-Geräte ausliest und als Broker an Homeassistant sendet.
      </div>
    
  </div>
</article>

  </section>


<p>Das initiale <em>Flashen</em> der Firmware muss einmalig über eine Kabelverbindung erfolgen. Anschließend kann die Konfiguration einfach und unkompliziert <em>Over the air</em> angepasst werden.</p>
<p>Wurden alle Schritte erfolgreich durchlaufen erkennt Homeassistant automatisch die neue ESPHome-Node und bietet an diese einzubinden. Anschließend stehen zwei neue <em>Entities</em> zur Verfügung:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/esp32-cam/esp32-cam-entities.png"
          alt=""
        />
  
  
  </figure>

<h2 class="relative group">USB-Stromversorgung
    <div id="usb-stromversorgung" class="anchor"></div>
    
</h2>
<p>Da das ESP32-CAM-Modul keinen eigenen Micro-USB-Anschluss auf der Platine enthält, empfiehlt es sich einen altes USB-Ladegerät am Steckerende abzutrennen, die einzelnen Kabel freizulegen und direkt mit der Platinenanschlüssen zu verlöten oder auf ein <em>USB-Breakout-Board</em> zurückzugreifen, wie bspw. in diesem <a href="https://www.instructables.com/Wireless-Security-Camera-in-a-Matchbox/"  target="_blank" rel="noreferrer">Post</a> beschrieben.</p>

<h2 class="relative group">Gehäuse drucken
    <div id="gehäuse-drucken" class="anchor"></div>
    
</h2>
<p>Da eine nackte Platine nicht sonderlich ansehnlich erscheint, kann der heimische <a href="/categories/3d-drucker/" >3D-Drucker</a> angeworfen werden und bei Thingiverse ein <a href="https://www.thingiverse.com/search?q=esp32-cam&amp;type=things&amp;sort=relevant"  target="_blank" rel="noreferrer">passendes Gehäuse</a> gewählt werden. Die vorhandene Auswahl ist groß.</p>

<h2 class="relative group">ESP32-CAM in Lovelace UI
    <div id="esp32-cam-in-lovelace-ui" class="anchor"></div>
    
</h2>
<p>Ich habe meine ESP32-CAM mit einer <a href="https://www.home-assistant.io/dashboards/picture-glance/"  target="_blank" rel="noreferrer">Picture Glance Card</a> in die UI eingebunden. Diese erlaubt neben dem direkten betrachten des Videostream auch das einfach Ein- und Ausschalten der LED auf der Platine des ESP32. Der Code dafür:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">picture-glance</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">Gockelcam</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">camera_view</span><span class="p">:</span><span class="w"> </span><span class="l">auto</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">camera_image</span><span class="p">:</span><span class="w"> </span><span class="l">camera.gockelcam</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">entities</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">light.gockelcam_light</span></span></span></code></pre></div></div>
<p>In der Lovelace UI sieht dies dann folgendermaßen aus. Die LED kann mit einem Klick auf das Lampen-Icon einfach geschaltet werden:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/esp32-cam/esp32-cam-lovelace.png"
          alt=""
        />
  
  
  </figure>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Morgendlicher Newsflash</title>
      <link>https://jbetzen.net/posts/morgendlicher-newsflash/</link>
      <pubDate>Sun, 13 Mar 2022 11:04:11 +0100</pubDate>
      
      <guid>https://jbetzen.net/posts/morgendlicher-newsflash/</guid>
      <description>Wer werktags morgens in die Küche läuft, kann sich im Handumdrehen einen morgendlichen Newsflash, bspw. Tagesschau in 100 Sekunden über einen Media Player anspielen lassen.</description>
      <content:encoded><![CDATA[ <p>Wer in seinem trauten Heim in jedem Raum einen Bewegungssensor hat, kann diese nicht nur zum automatischen Einschalten von Beleuchtung verwenden, wie bspw. in <a href="/categories/motion-sensor/" >diesen Posts</a> beschrieben.</p>
<p>In diesem Post erkläre ich, wie man einen Bewegungssensor nutzen kann, um automatisiert die <em>Tagesschau in 100 Sekunden</em> beim morgendlichen Betreten der Küche abzuspielen.</p>

<h2 class="relative group">Hardware
    <div id="hardware" class="anchor"></div>
    
</h2>
<p>Ich verwende bei mir die Motion-Sensoren von Philips Hue in meiner Küche und dort steht auch ein <a href="/tags/bose-soundtouch/" >Bose Soundtouch 10</a> zur räumlichen Beschallung. Für das folgende Beispiel werden diese <em>Entity IDs</em> verwendet:</p>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th>Device</th>
					<th>Entity ID</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Bose Soundtouch 10</td>
					<td>media_player.soundtouch_kueche</td>
			</tr>
			<tr>
					<td>Hue Motion Sensor</td>
					<td>binary_sensor.hue_motion_kueche</td>
			</tr>
	</tbody>
</table>
</div>

<h2 class="relative group">Setup Bose Mediaplayer
    <div id="setup-bose-mediaplayer" class="anchor"></div>
    
</h2>
<p>Die Bose Soundtouch App erlaubt das Belegen von sechs Shortcuts, die schnell und unkompliziert über die physischen Buttons auf dem Lautsprecher und der zugehörigen Fernbedienung aktiviert werden können. Gleichzeitig erlaubt die <a href="https://www.home-assistant.io/integrations/soundtouch/"  target="_blank" rel="noreferrer">Bose Soundtouch Integration</a> für Homeassistant die Shortcuts automatisiert abzuspielen. In Kombination mit der <a href="https://www.home-assistant.io/integrations/spotify/"  target="_blank" rel="noreferrer">Spotify Integration</a> lassen sich so leicht vordefinierte Songs, Playlisten und Podcasts automatisiert wiedergeben.</p>
<p>Ich habe den täglichen &ldquo;Podcast&rdquo; der <em>Tagesschau in 100 Sekunden</em> auf den <code>Shortcut 4</code> gelegt.</p>

<h2 class="relative group">Die Automation
    <div id="die-automation" class="anchor"></div>
    
</h2>
<p>Wenn morgens die Küche betreten wird, soll automatisch die Wiedergabe der <em>Tagesschau in 100 Sekunden</em> erfolgen, jedoch nur unter bestimmten Bedingungen (<em>Conditions</em>):</p>
<ul>
<li>Die Wiedergabe soll ausschließlich <em>nach</em> einer vordefinierten Uhrzeit erfolgen. In diesem Beispiel wird der Zeitpunkt nach <code>05:30h</code> gewählt.
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">time</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">after</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;05:30:00&#39;</span></span></span></code></pre></div></div>
</li>
<li>Die Wiedergabe soll nur einmal am Tag erfolgen und nicht jedes mal, wenn die Küche betreten wird. Dafür wird auf das Attribute <code>last_triggered</code> der Automation zurückgegriffen, wie im <a href="https://community.home-assistant.io/t/only-allow-automation-to-trigger-once-a-day/390097/6"  target="_blank" rel="noreferrer">Homeassistant Forum</a> beschrieben:
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="s2">&#34;{{ state_attr(&#39;automation.wecker_tagesschau_auto_play&#39;, &#39;last_triggered&#39;) | default(today_at(), true) &lt; today_at(&#39;05:30&#39;) }}&#34;</span></span></span></code></pre></div></div>
</li>
</ul>

<h3 class="relative group">Code für Automation
    <div id="code-für-automation" class="anchor"></div>
    
</h3>
<p>Der Code für die beschriebenen Bedingungen sieht folgender Maßen aus. Er stellt zusätzlich noch eine annehmbare Lautstärke für den Bose Soundtouch ein, damit man in aller Früh nicht zu laut beschallt wird:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Wecker Tagesschau auto play</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">initial_state</span><span class="p">:</span><span class="w"> </span><span class="kc">True</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">binary_sensor.hue_motion_kueche</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;on&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">condition</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">time</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">after</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;05:30:00&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="s2">&#34;{{ state_attr(&#39;automation.wecker_tagesschau_auto_play&#39;, &#39;last_triggered&#39;) | default(today_at(), true) &lt; today_at(&#39;05:30&#39;) }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.play_media</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.soundtouch_kueche</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">media_content_id</span><span class="p">:</span><span class="w"> </span><span class="m">4</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">media_content_type</span><span class="p">:</span><span class="w"> </span><span class="l">PLAYLIST</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.volume_set</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.soundtouch_kueche</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">volume_level</span><span class="p">:</span><span class="w"> </span><span class="m">0.4</span></span></span></code></pre></div></div>

<h3 class="relative group">Optimierungen
    <div id="optimierungen" class="anchor"></div>
    
</h3>
<p>Dieser Code funktioniert eigenständig, kann natürlich aber noch optimiert und den eigenen Bedürfnissen angepasst werden. Wer beispielsweise nur unter der Woche am Morgen mit einem Newsflash begrüßt werden will und am Wochenende seine Ruhe haben möchte, kann auf die <a href="https://www.home-assistant.io/integrations/workday/"  target="_blank" rel="noreferrer">Workday Integration</a> zurückgreifen und diese als eine weitere Bedingung hinzufügen:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">binary_sensor.workday_sensor</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;on&#39;</span></span></span></code></pre></div></div>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>ESPHome Bluetooth Low Energy Hub</title>
      <link>https://jbetzen.net/posts/esphome-btle-hub/</link>
      <pubDate>Thu, 13 Jan 2022 23:11:40 +0100</pubDate>
      
      <guid>https://jbetzen.net/posts/esphome-btle-hub/</guid>
      <description>Dieser Post beschreibt, wie man mittels ESPHome und einem ESP32 Microcontroller ein Bluetooth Low Energy Hub aufsetzt, das alle Bluetooth IoT-Geräte ausliest und als Broker an Homeassistant sendet.</description>
      <content:encoded><![CDATA[ 
  
  
  
  



<div
  
    class="flex px-4 py-3 rounded-md shadow bg-primary-100 dark:bg-primary-900"
  
  >
  <span
    
      class="text-primary-400 pe-3 flex items-center"
    
    >
    <span class="relative block icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 128c17.67 0 32 14.33 32 32c0 17.67-14.33 32-32 32S224 177.7 224 160C224 142.3 238.3 128 256 128zM296 384h-80C202.8 384 192 373.3 192 360s10.75-24 24-24h16v-64H224c-13.25 0-24-10.75-24-24S210.8 224 224 224h32c13.25 0 24 10.75 24 24v88h16c13.25 0 24 10.75 24 24S309.3 384 296 384z"/></svg>
</span>
  </span>

  <span
    
      class="dark:text-neutral-300"
    
    ><p>Dieser Post enthält Themen, die bereits in zwei vorherigen Posts beschrieben wurden. In den vorherigen Anleitungen wurden die Daten der Geräte über eine Software namens BT-MQTT-Gateway ermittelt:</p>
<ul>
<li><a href="/posts/xiaomi-scale/">Xiaomi MiScale Waage in Homeassistant integrieren</a></li>
<li><a href="/posts/xiaomi-mithermometer/">Xiaomi Thermometer in Homeassistant einbinden</a></li>
</ul>
<p>Die Einbindung der Xiaomi MiScale und dem Mithermometer über ESPHome ist den Methoden der alten Posts vorzuziehen.</p>
</span>
</div>

<hr>
<p>Viele IoT-Geräte funken ihre Daten über <a href="https://de.wikipedia.org/wiki/Bluetooth_Low_Energy"  target="_blank" rel="noreferrer">Bluetooth LE</a>. Um diese ins Smarthome integrieren zu können benötigt man ein Gerät mit Bluetooth-Schnittstelle, das als Broker fungiert. Ich nutze dafür seit Jahren zuverlässig einen <a href="https://www.raspberrypi.com/products/raspberry-pi-zero/"  target="_blank" rel="noreferrer">Raspberry Pi Zero</a>, der in Anbetracht des schlichten Abfangens und Weiterleitens von Paketdaten, unterfordert und überdimensioniert ist. Ein solches Bluetooth Hub lässt sich mittels eines <a href="https://de.wikipedia.org/wiki/ESP32"  target="_blank" rel="noreferrer">ESP32</a> und <a href="https://esphome.io/"  target="_blank" rel="noreferrer">ESPHome</a> mit deutlich geringerem Stromverbrauch und Konfigurationsaufwand realisieren.</p>
<p>Umgezogen werden bei mir die folgenden Bluetooth Sensoren, die nun vom ESP32 ausgelesen und an Homeassistant weitergereicht werden:</p>
<ul>
<li><a href="https://esphome.io/components/sensor/xiaomi_ble.html#lywsd03mmc"  target="_blank" rel="noreferrer">Xiaomi Mithermometer</a></li>
<li><a href="https://esphome.io/components/sensor/xiaomi_miscale.html?highlight=miscale"  target="_blank" rel="noreferrer">Xiaomi Miscale v1</a></li>
<li><a href="https://esphome.io/components/sensor/xiaomi_ble.html#hhccjcy01"  target="_blank" rel="noreferrer">Xiaomi Miflora Pflanzensensoren</a></li>
</ul>

<h2 class="relative group">Vorraussetzungen
    <div id="vorraussetzungen" class="anchor"></div>
    
</h2>
<p>Benötigt werden:</p>
<ul>
<li>ESP32 bspw. die Variante <em>ESP32 D1 Mini</em>, die ich für dieses Projekt verwendet habe</li>
<li><a href="https://esphome.io/guides/getting_started_hassio.html"  target="_blank" rel="noreferrer">ESPHome Add-On</a> für Hass.io</li>
<li>Chrome bzw. Edge Browser oder <a href="https://github.com/esphome/esphome-flasher/releases"  target="_blank" rel="noreferrer">ESPHome Flasher</a> zum einmaligen flashen der Firmware</li>
</ul>

<h2 class="relative group">Konfiguration
    <div id="konfiguration" class="anchor"></div>
    
</h2>

<h3 class="relative group">ESPHome Add-On
    <div id="esphome-add-on" class="anchor"></div>
    
</h3>
<p>Im ersten Schritt muss das ESPHome Add-On installiert, aktiviert und gestartet werden. Anschließend kann über SMB oder das VS-Code-Add-On eine Datei namens <code>secrets.yaml</code> angelegt werden, in der alle sensitiven Daten, wie WiFi-Passwörter oder Atomraketenstartcodes hinterlegt werden können. Diese Einträge können mittels Variablen bei der Konfiguration verwendet werden.</p>
<p>Die Datei muss im Pfad <code>./config/esphome/secrets.yaml</code> erstellt und kann anschließend diesem Schema und Beispieleinträgen gefüllt werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">wifi_ssid</span><span class="p">:</span><span class="w"> </span><span class="l">LanSolo</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">wifi_passwd</span><span class="p">:</span><span class="w"> </span><span class="l">Wurstjunge12</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">ota_passwd</span><span class="p">:</span><span class="w"> </span><span class="l">S4mtpf0te</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">ap_passwd</span><span class="p">:</span><span class="w"> </span><span class="l">GoBBerw4rz3</span></span></span></code></pre></div></div>
<p>Nach der Anlage der Datei, kann diese auch direkt aus dem ESPHome Dashboard in Homeassistant editiert werden. Dafür steht das Schlosssymbol neben dem Button <code>SECRETS</code> zur verfügung:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/esphome-btle-hub/esphome-dashboard.png"
          alt="ESPHome Dashboard Screenshot"
        />
  
  
  </figure>
<p>Damit ist die Basis geschaffen, um die Konfiguration des Microcontrollers anzulegen. Im ESPHome Dashboard wird mit einem Klick auf das (+)-Icon eine neue <em>Node</em> erzeugt. So heißen die einzelnen eingebundenen Microcontroller, auf denen ESPHome läuft.</p>

<h3 class="relative group">MiFlora Pflanzensensoren
    <div id="miflora-pflanzensensoren" class="anchor"></div>
    
</h3>
<p>Benötigt wird lediglich die MAC-Adresse des Sensors, um die Daten zu empfangen. In Firmwareversionen <a href="https://github.com/esphome/esphome/pull/1288#issuecomment-695809481"  target="_blank" rel="noreferrer">vor 2.3.1</a> sendeten die Pflanzensensoren noch ihren Batteriestand. Dies ist mit neueren Firmwares leider nicht mehr möglich.</p>
<p>Eine Beispielkonfiguration:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">xiaomi_hhccjcy01</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">mac_address</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;C4:7C:23:69:63:08&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">temperature</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Vietnamchili Temperature&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">moisture</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Vietnamchili Moisture&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">illuminance</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Vietnamchili Illuminance&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">conductivity</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Vietnamchili Soil Conductivity&#34;</span></span></span></code></pre></div></div>
<p><strong>Ein kleiner Tipp noch zum Troubleshooting:</strong><br>
Meine Sensoren liefen auf der Firmware <code>2.7.0</code>. Damit konnten nicht zuverlässig Werte empfangen werden. Man kann die Firmware der Sensoren leicht mit der App <strong>Flower Care</strong> (<a href="https://play.google.com/store/apps/details?id=com.huahuacaocao.flowercare"  target="_blank" rel="noreferrer">Android </a>/<a href="https://apps.apple.com/de/app/flower-care/id1095274672"  target="_blank" rel="noreferrer"> iOS</a>) updaten. Die App setzt jedoch einen Account bei Xiaomi voraus.</p>

<h3 class="relative group">MiScale v1
    <div id="miscale-v1" class="anchor"></div>
    
</h3>
<p>Für die Waage von Xiaomi sollte der ESP32 das aktuelle Gewicht auslesen und zeitgleich noch einen weiteren Sensor für den BMI berechnen und an Homeassistant Senden. Die Berechnung des BMI hatte ich zuvor on Homeassitant mit einem Template Sensor gelöst. Diese Aufgabe kann nun der Mikrocontroller übernehmen. Auch für die Waage muss die MAC-Adresse bekannt sein:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">xiaomi_miscale</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">mac_address</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;C4:3F:13:E0:AC:82&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">weight</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;miscale_weight&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Miscale Weight&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">mdi:scale-bathroom</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">accuracy_decimals</span><span class="p">:</span><span class="w"> </span><span class="m">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">on_value</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">then</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">lambda</span><span class="p">:</span><span class="w"> </span><span class="p">|-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">            const float bmi_factor = 0.29860551;
</span></span></span><span class="line"><span class="cl"><span class="sd">            return id(miscale_bmi).publish_state(x * bmi_factor);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    
</span></span></span><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">template</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;miscale_bmi&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Miscale BMI&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">mdi:human-pregnant</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">unit_of_measurement</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">accuracy_decimals</span><span class="p">:</span><span class="w"> </span><span class="m">1</span></span></span></code></pre></div></div>
<p>Diese Konfiguration enthält zwei Sensoren für Gewicht und BMI. Wird das Gewicht ausgelesen erfolgt automatisch die Berechnung des BMI. Der Faktor <code>0.29860551</code> muss gemäß der eigenen Körperwerte angepasst werden und setzt sich aus dem Kehrwert des Quadrats der Körperhöhe [m] zusammen:</p>
<!-- 
<figure>
      <img class="my-0 rounded-md centered" src="/posts/xiaomi-scale/bmi-formula.svg" alt="BMI-Formel" />
  
  
  </figure> -->
<p>

$$BMI = \frac{m}{h^{2}} = m \times \frac{1}{h^{2}}$$</p>
<p><strong>Tipp zum Abschluss:</strong><br>
Für die Xiaomi Waage gibt es eine <a href="https://github.com/dckiller51/bodymiscale"  target="_blank" rel="noreferrer">Custom Component</a>, die es erlaubt mehrere Benutzer zu tracken und einen erweiterten Fundus an generierten Fitnessdaten liefert.</p>

<h3 class="relative group">Mithermometer
    <div id="mithermometer" class="anchor"></div>
    
</h3>
<p>Auch die Mithermometer lassen sich einfach über die MAC-Adresse einbinden. Am einfachsten lassen sie sich auslesen, wenn man den <a href="https://github.com/pvvx/ATC_MiThermometer#bluetooth-advertising-formats"  target="_blank" rel="noreferrer">Advertising Type</a> auf den Wert <code>Custom</code> setzt. Wie das geht, habe ich in dem ursprünglichen <a href="/posts/xiaomi-mithermometer#methode-2-bt-mqtt-gateway" >Post zu dem Thermometer</a> bereits beschrieben. Dort wurde jedoch der Funkstandard (<em>Advertising Type</em>) <code>ATC1441</code> genutzt. Im gleichen Menü kann der Standard gewechselt werden.</p>
<p>Ein Konfiguration für ESPHome sieht dann wie folgt aus:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">pvvx_mithermometer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">mac_address</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;A6:C3:23:E0:A8:42&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">temperature</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Mithermometer Kueche Temperature&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">humidity</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Mithermometer Kueche Humidity&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">battery_level</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Mithermometer Kueche Battery Level&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">battery_voltage</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Mithermometer Kueche Battery Voltage&#34;</span></span></span></code></pre></div></div>

<h2 class="relative group">Vollständige ESP32 Konfiguration
    <div id="vollständige-esp32-konfiguration" class="anchor"></div>
    
</h2>
<p>Nun müssen nur noch alle drei Teilkonfigurationen zusammengeführt, kompiliert und auf den Mikrocontroller geflasht werden. In dieser Konfiguration können die Variablen aus der <code>secrets.yaml</code> verwendet werden. Eine vollständige Konfiguration könnte wie folgend aussehen. Wichtig ist, dass ggf. der Eintrag im Feld <code>board:</code> angepasst wird, wenn eine abweichende Variante vom ESP32 verwendet wird.</p>
<p>Der Platzhalter <code>YOUR_GENERATED_ID</code> muss durch eine selbstgenerierte ID ersetzt werden. Diese kann direkt auf der <a href="https://esphome.io/components/api.html#configuration-variables"  target="_blank" rel="noreferrer">ESP Home Webseite</a> erzeugt und kopiert werden.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">esphome</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">esp32-btle-hub</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">comment</span><span class="p">:</span><span class="w"> </span><span class="l">ESP32 Bluetooth LE Hub</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">esp32</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">board</span><span class="p">:</span><span class="w"> </span><span class="l">esp32dev</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">framework</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">esp-idf</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># Enable logging</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">logger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># Enable Home Assistant API</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">api</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">encryption</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;YOUR_GENERATED_ID&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">ota</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">password</span><span class="p">:</span><span class="w"> </span>!<span class="l">secret ota_passwd</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">wifi</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">ssid</span><span class="p">:</span><span class="w"> </span>!<span class="l">secret wifi_ssid</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">password</span><span class="p">:</span><span class="w"> </span>!<span class="l">secret wifi_passwd</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">fast_connect</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># Enable fallback hotspot (captive portal)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># in case wifi connection fails</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">ap</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">ssid</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Btle-Hub Fallback Hotspot&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">password</span><span class="p">:</span><span class="w"> </span>!<span class="l">secret ap_passwd</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">captive_portal</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">esp32_ble_tracker</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">sensor</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># XIAOMI MISCALE</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">xiaomi_miscale</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">mac_address</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;C4:3F:13:E0:AC:82&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">weight</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;miscale_weight&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Miscale Weight&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">mdi:scale-bathroom</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">accuracy_decimals</span><span class="p">:</span><span class="w"> </span><span class="m">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">on_value</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">then</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">lambda</span><span class="p">:</span><span class="w"> </span><span class="p">|-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">              const float bmi_factor = 0.29860551;
</span></span></span><span class="line"><span class="cl"><span class="sd">              return id(miscale_bmi).publish_state(x * bmi_factor);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">template</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;miscale_bmi&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Miscale BMI&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">mdi:human-pregnant</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">unit_of_measurement</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">accuracy_decimals</span><span class="p">:</span><span class="w"> </span><span class="m">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># XIAOMI THERMOMETER</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">pvvx_mithermometer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">mac_address</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;A6:C3:23:E0:A8:42&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">temperature</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Mithermometer Kueche Temperature&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">humidity</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Mithermometer Kueche Humidity&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">battery_level</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Mithermometer Kueche Battery Level&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">battery_voltage</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Mithermometer Kueche Battery Voltage&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># XIAOMI MIFLORA PLANT SENSOR</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">xiaomi_hhccjcy01</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">mac_address</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;C4:7C:23:69:63:08&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">temperature</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Vietnamchili Temperature&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">moisture</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Vietnamchili Moisture&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">illuminance</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Vietnamchili Illuminance&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">conductivity</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Vietnamchili Soil Conductivity&#34;</span></span></span></code></pre></div></div>
<p>Dieser Code muss im ESPHome Add-On im Editor zur Node eingegeben, gespeichert und kompiliert werden.</p>

<h2 class="relative group">Firmware flashen
    <div id="firmware-flashen" class="anchor"></div>
    
</h2>
<p>Im ESPHome Add-On gibt es mehrere Möglichkeiten eine Firmware auf den ESP32 zu installieren:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/esphome-btle-hub/esphome-flashen.png"
          alt="ESPHome auf Mikrocontroller flashen"
        />
  
  
  </figure>
<p>Der einfachste Weg ist die erste Option den Mikrocontroller direkt aus dem Browser heraus zu flashen. Voraussetzung dafür ist der Browser Chrome oder Edge. Mit Firefox klappt es nicht.</p>
<p>Ich nutze immer die letzte Option des manuellen Downloads und lade die Firmware herunter und flashe sie anschließend mit dem <a href="https://github.com/esphome/esphome-flasher/releases"  target="_blank" rel="noreferrer">ESPHome Flasher</a>. Dieser Vorgang muss nur einmal erfolgen, da Nodes später <em>Over-The-Air</em> geupdated werden können.</p>
<p>Ist der Flashvorgang erfolgreich durchlaufen wird der ESP32 automatisch neu starten.</p>

<h1 class="relative group">ESP32 Node in Hass einbinden
    <div id="esp32-node-in-hass-einbinden" class="anchor"></div>
    
</h1>
<p>Homeassistant erkennt nach dem erfolgreichen Flashvorgang den ESP32 automatisch und bietet an diesen zu integrieren. Beim initialen Verbinden mit dem Controller muss dann das definierte Passwort, welches in der Variable <code>!secret api_passwd</code> hinterlegt ist, eingegeben werden. Anschließend stehen alle Sensoren in Homeassistant zur Verfügung.</p>
<p>Sollte die automatischer Erkennung der Node nicht klappen, kann diese auch manuell eingebunden werden indem man im Menü <code>Configuration &gt; Devices &amp; Services</code> den Button <code>Add Integration</code> klickt und dort den Eintrag <code>ESPHome</code> auswählt.</p>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>iOS Actions, Shortcuts und die Apple Watch</title>
      <link>https://jbetzen.net/posts/ios-actions/</link>
      <pubDate>Tue, 21 Dec 2021 15:22:26 +0100</pubDate>
      
      <guid>https://jbetzen.net/posts/ios-actions/</guid>
      <description>iOS Actions sind Aktionen, die per Push-Nachrichten getriggert werden können. Diese können sowohl auf dem iPhone als auch mit der Apple Watch genutzt werden. Dieser Post legt den Fokus auf die Nutzung mit der Apple Watch.</description>
      <content:encoded><![CDATA[ 
  



<div
  
    class="flex px-4 py-3 rounded-md shadow bg-primary-100 dark:bg-primary-900"
  
  >
  <span
    
      class="text-primary-400 pe-3 flex items-center"
    
    >
    <span class="relative block icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M506.3 417l-213.3-364c-16.33-28-57.54-28-73.98 0l-213.2 364C-10.59 444.9 9.849 480 42.74 480h426.6C502.1 480 522.6 445 506.3 417zM232 168c0-13.25 10.75-24 24-24S280 154.8 280 168v128c0 13.25-10.75 24-23.1 24S232 309.3 232 296V168zM256 416c-17.36 0-31.44-14.08-31.44-31.44c0-17.36 14.07-31.44 31.44-31.44s31.44 14.08 31.44 31.44C287.4 401.9 273.4 416 256 416z"/></svg>
</span>
  </span>

  <span
    
      class="dark:text-neutral-300"
    
    ><strong>iOS Actions</strong> sind mittlerweile im Status Deprecated/Legacy und sollen nicht länger verwendet werden. Siehe: <a href="https://companion.home-assistant.io/docs/apple-watch/watch-actions"  target="_blank" rel="noreferrer">(Legacy) iOS Actions</a></span>
</div>

<p><a href="https://companion.home-assistant.io/docs/core/actions"  target="_blank" rel="noreferrer">iOS Actions</a> sind eine Funktion von Homeassistant, die speziell für das iOS-Ökosystem genutzt werden kann. Im Kern ähneln sie den <a href="https://companion.home-assistant.io/docs/notifications/actionable-notifications/"  target="_blank" rel="noreferrer">Actionable Notification</a>, wobei letztere - unabhängig davon, ob man die Homeassistant <a href="/categories/companion-app/" >Companion App</a> auf dem Smartphone installiert hat - genutzt werden können, wie in dem Post <a href="/posts/notificaton-appdaemon/">Homeassistant, Actionable Notifications und Appdaemon</a> <a href="/posts/notificaton-appdaemon/" >über Appaemon Notifications</a> bereits beschrieben wurde.</p>
<p>iOS Actions können nach initialem Setup in der iOS Shortcuts App und auch auf der Apple Watch genutzt werden. Wie dies einfach möglich ist, möchte ich in diesem Post zeigen.</p>

<h2 class="relative group">Das Vorgehen
    <div id="das-vorgehen" class="anchor"></div>
    
</h2>
<p>Für mein Setup definiere ich alle iOS Actions direkt in Homeassistant. Wird eine dieser Actions ausgeführt, bspw. über einen Shortcut oder einen Tap auf der Apple Watch, wird auf dem <em>Eventbus</em> von Homeassistant ein Event mit dem Namen <code>ios.action_fired</code> gefeuert. Diesen fange ich mit einer <a href="https://community.home-assistant.io/t/home-assistant-community-add-on-appdaemon-4/163259"  target="_blank" rel="noreferrer">Appdaemon</a> App ab und weise in der App an, welche Action erfolgen soll.</p>

<h2 class="relative group">Konfiguration Homeassistant
    <div id="konfiguration-homeassistant" class="anchor"></div>
    
</h2>
<p>In der <code>configuration.yaml</code> muss zuerst die <a href="https://companion.home-assistant.io/docs/core/actions#creating-actions-in-home-assistant"  target="_blank" rel="noreferrer">iOS-Integration</a> aktiviert werden. Da ich ungern meine <code>configuration.yaml</code> zumülle habe ich im ersten Schritt im Ordner <code>./config/</code> eine Datei mit dem Namen <code>ios.yaml</code> angelegt und diese anschließend so in der <code>configuration.yaml</code> eingebunden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">ios</span><span class="p">:</span><span class="w"> </span>!<span class="l">include ios.yaml</span></span></span></code></pre></div></div>
<p>In der Datei <code>ios.yaml</code> habe ich vier Einträge eingefügt, die für diesen Post als Beispiel herhalten sollen:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">actions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">blind_toggle</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">background_color</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;#000000&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">label</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">text</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Rollo&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;4BA7EE&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">icon</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">blinds</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;#ffffff&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">sleepmode</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">background_color</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;#000000&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">label</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">text</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Schlafmodus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;4BA7EE&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">icon</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">bed</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;#ffffff&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">christmastree</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">background_color</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;#000000&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">label</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">text</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Weihnachtsbaum&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;4BA7EE&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">icon</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">pine-tree</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;#ffffff&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">cast_toggle</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">background_color</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;#000000&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">label</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">text</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Chromecast&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;4BA7EE&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">icon</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">cast</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;#ffffff&#34;</span></span></span></code></pre></div></div>
<p>Entscheidend sind an dieser Stelle die Namen der Actions in den Einträgen <code>name:</code>, da diese auf dem Eventbus abgefangen werden müssen.</p>

<h3 class="relative group">Erläuterung Beispiele
    <div id="erläuterung-beispiele" class="anchor"></div>
    
</h3>
<table>
	<thead>
			<tr>
					<th>Name</th>
					<th>Action</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>blind_toggle</td>
					<td>Fährt mein Ikea Fyrtur Rollo entweder hoch oder herunter. Siehe: <a href="../ikea-rollo" >Post</a></td>
			</tr>
			<tr>
					<td>sleepmode</td>
					<td>Ein Script, das den Schlafmodus einschaltet.</td>
			</tr>
			<tr>
					<td>christmastree</td>
					<td>Schaltet meinen Weihnachtsbaum ein oder aus. Siehe <a href="../wled-weihnachtsbaum" >Post</a></td>
			</tr>
			<tr>
					<td>cast_toggle</td>
					<td>Schaltet eine Steckdose ein oder aus, an der mein Chromecast samt Monitor und Boxen angeschlossen ist.</td>
			</tr>
	</tbody>
</table>
<p>Ist diese Einrichtung erfolgt, muss Homeassistant neugestartet werden. Anschließend stehen diese Actions bereits in der Companion App, der Watch App und der iOS Shortcuts App zur Verfügung, können aber zu dem jetzigen Zeitpunkt noch keine Actions ausführen.</p>

<h3 class="relative group">Screenshots
    <div id="screenshots" class="anchor"></div>
    
</h3>

<h4 class="relative group">Apple Watch Companion App
    <div id="apple-watch-companion-app" class="anchor"></div>
    
</h4>


  

<figure class="centered"><img src="/posts/ios-actions/iosactions-screenshot-watch.png"
    alt="Screenshot Apple Watch">
</figure>



<h4 class="relative group">iOS Shortcut App
    <div id="ios-shortcut-app" class="anchor"></div>
    
</h4>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/ios-actions/iosactions-screenshot-app.png"
          alt="Screenshot Shortcuts App"
        />
  
  
  </figure>

<h2 class="relative group">Konfiguration Appdaemon
    <div id="konfiguration-appdaemon" class="anchor"></div>
    
</h2>
<p>Damit die vier Beispiele auch Aktionen ausführen können, bspw. das Rollo oder den Weihnachtsbaum schalten, nutze ich Appdaemon. Dazu muss im ersten Schritt die Datei <code>./config/appdaemon/apps/iosactions.py</code> angelegt werden und folgendes in diese geschrieben werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">appdaemon.plugins.hass.hassapi</span> <span class="k">as</span> <span class="nn">hass</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">iOSActions</span><span class="p">(</span><span class="n">hass</span><span class="o">.</span><span class="n">Hass</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">listen_event</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">handle_event</span><span class="p">,</span> <span class="s2">&#34;ios.action_fired&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">handle_event</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event_name</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;actionName&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;blind_toggle&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">call_service</span><span class="p">(</span><span class="s2">&#34;cover/toggle&#34;</span><span class="p">,</span> <span class="n">entity_id</span> <span class="o">=</span> <span class="s2">&#34;cover.rollo_schlafzimmer&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">elif</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;actionName&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;sleepmode&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">call_service</span><span class="p">(</span><span class="s2">&#34;script/turn_on&#34;</span><span class="p">,</span> <span class="n">entity_id</span> <span class="o">=</span> <span class="s2">&#34;script.schlafzimmer_readytosleep&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">elif</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;actionName&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;christmastree&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">call_service</span><span class="p">(</span><span class="s2">&#34;light/toggle&#34;</span><span class="p">,</span> <span class="n">entity_id</span> <span class="o">=</span> <span class="s2">&#34;light.wled&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">elif</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;actionName&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;cast_toggle&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">call_service</span><span class="p">(</span><span class="s2">&#34;switch/toggle&#34;</span><span class="p">,</span> <span class="n">entity_id</span> <span class="o">=</span> <span class="s2">&#34;switch.schlafzimmer_steckdose_cast&#34;</span><span class="p">)</span></span></span></code></pre></div></div>
<p>Diese Appdaemon App lauscht kontinuierlich nach dem Event <code>ios.action_fired</code>. Ist ein solcher Event erkannt, wird anschließend nach dem <code>actionName</code> gesucht und die zugewiesene Action ausgeführt. Die App muss im letzten Schritt noch für Appdaemon zugänglich gemacht werden. Dazu muss in der Datei <code>./config/appdaemon/apps/apps.yaml</code> der folgende Eintrag hinzugefügt werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># Handling iOS Actions</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">iOSActions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">module</span><span class="p">:</span><span class="w"> </span><span class="l">iosactions</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">class</span><span class="p">:</span><span class="w"> </span><span class="l">iOSActions</span></span></span></code></pre></div></div>
<p>Nach dem Speichern registriert Appdaemon automatisch die neue Konfiguration. Anschließend können die iOS Actions genutzt werden.</p>

<h2 class="relative group">Tipp zum Abschluss
    <div id="tipp-zum-abschluss" class="anchor"></div>
    
</h2>
<p>iOS erlaubt auf dem iPhone unter <em>Einstellungen &gt; Bedienungshilfen &gt; Tippen &gt; Auf Rückseite tippen</em> die Möglichkeit einen Shortcut direkt mit einem Doppel- oder Dreifachtipp auf die Rückseite des iPhones auszuführen. Da die iOS Shortcut App auch auf die iOS Actions zugreifen kann, kann man also auch mit einem Doppeltipp auf die Rückseite seinen Weihnachtsbaum ein- oder ausschalten.</p>
<p>Viel Spaß damit!</p>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>WLED-Weihnachtsbaum in Homeassistant</title>
      <link>https://jbetzen.net/posts/wled-weihnachtsbaum/</link>
      <pubDate>Sat, 18 Dec 2021 18:59:06 +0100</pubDate>
      
      <guid>https://jbetzen.net/posts/wled-weihnachtsbaum/</guid>
      <description>Die Custom Firmware WLED ermöglicht das Steuern von LEDs und kann somit hervorragend zur Automatisierung des Weihnachtsbaums eingesetzt werden. WLED bietet eine Integration für Homeassistant und kann somit im Handumdrehen eingebunden werden.</description>
      <content:encoded><![CDATA[ <p>Die Integration von <a href="https://www.home-assistant.io/integrations/wled/"  target="_blank" rel="noreferrer">WLED</a> in Homeassistant wurde im vergangenen Jahr kontinuierlich verbessert. Während man vorher noch auf umständliche Weise mittels Service Calls gewünschte Presets aufrufen musst, bringt die Integration nun eine handvoll nützlicher Entities mit, die auch unbedarften Usern eine einfache Einbindung in eine Lovelace Card ermöglichen. Die Auswahl von Presets, Effekt-Intensität und Effekt-Geschwindigkeit stehen nun als vordefinierte Entities automatisch in Homeassistant zur Verfügung.</p>
<p>Da sich das jährliche Weihnachtsfest nähert möchte ich in diesem Post zeigen, wie ich WLED für meinen Weihnachtsbaum nutze und in Homeassistant einbinde.</p>

<h2 class="relative group">Verwendete Hardware
    <div id="verwendete-hardware" class="anchor"></div>
    
</h2>
<p>Herzstück meines Setups ist ein <em>QuinLED Dig Uno</em>, der mit einem ESP8266 bestückt ist und die angeschlossenen LED-Strips steuert. Auf den ESP8266 wurde widerum <a href="https://kno.wled.ge/"  target="_blank" rel="noreferrer">WLED</a> geflasht. Ich habe dabei auch 5V-LED-Strips des Typs WS2811 gesetzt. Es gibt diese auch in 12V-Varianten, was dann aber in der Wahl des Netzteils berücksichtigt werden muss. Der QuinLED Dig Uno kann sowohl 5V, als auch 12V LEDs steuern.</p>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th>Bauteil</th>
					<th>Preis</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://quinled.info/pre-assembled-quinled-dig-uno/"  target="_blank" rel="noreferrer">QuinLED Dig Uno</a></td>
					<td>35,00€</td>
			</tr>
			<tr>
					<td><a href="https://de.aliexpress.com/item/32625011824.html"  target="_blank" rel="noreferrer">2x WS2811 LED Strip</a></td>
					<td>20,00€</td>
			</tr>
			<tr>
					<td><a href="https://de.aliexpress.com/item/32810906485.html"  target="_blank" rel="noreferrer">5V/10A-Netzteil</a></td>
					<td>18,50€</td>
			</tr>
			<tr>
					<td><a href="https://de.aliexpress.com/item/33004595253.html"  target="_blank" rel="noreferrer">LED Adapter</a></td>
					<td>1,50€</td>
			</tr>
	</tbody>
</table>
</div>

<h2 class="relative group">Setup
    <div id="setup" class="anchor"></div>
    
</h2>

<h3 class="relative group">QuinLED Dig Uno
    <div id="quinled-dig-uno" class="anchor"></div>
    
</h3>
<p>Nachdem der QuinLED Dig Uno korrekt mit den LED-Strips, dem Adapter und dem Netzteil verdrahtet ist, liefert er automatisch die nötige Betriebsspannung für den aufgesetzten ESP8266. Dieser muss zunächst mit dem WLan verbunden werden. Die vorgefertigten Bausätze haben bereits WLED installiert und müssen nur mit dem Netzteil verbunden werden. Anschließend erzeugt WLED einen <em>Access Point</em> mit dem man sich verbinden und die Zugangsdaten für das Heimnetz eintragen kann. Es sollte eine statische IP-Adresse zugewiesen werden.</p>

<h3 class="relative group">WLED in Homeassistant Integrieren
    <div id="wled-in-homeassistant-integrieren" class="anchor"></div>
    
</h3>
<p>In Homeassistant kann unter <code>Configuration &gt; Devices &amp; Services</code> über den Button <code>Add Integration</code> WLED hinzugefügt werden. Homeassistant erkennt im Idealfall direkt automatisch das neue Gerät im Netzwerk. Alternativ kann manuell die zuvor vergebene statische IP angegeben werden.</p>
<p>In meiner Kofiguration wurde folgender Entity-Name für WLED eingerichtet: <code>light.wled</code>. Dieses wird für die anschließenden Beispiele verwendet.</p>

<h2 class="relative group">Lovelace Custom Card
    <div id="lovelace-custom-card" class="anchor"></div>
    
</h2>
<p>Über HACS sollte die <a href="https://github.com/ofekashery/vertical-stack-in-card"  target="_blank" rel="noreferrer">custom-vertical-stack-in-card</a> installiert werden. Sie sorgt dafür, dass man mehrere Cards ohne visuellen Abstand zueinander Stapeln kann. Unterschiedliche Lovelace-Cards erscheinen in der UI dann als eine zusammengehörige Card.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/wled-weihnachtsbaum/wled-lovelacecard.png"
          alt="WLED Lovelace Card"
        />
  
  
  </figure>
<p>Ich verwende für meinen Weihnachtsbaum eine <a href="https://www.home-assistant.io/lovelace/picture-glance/"  target="_blank" rel="noreferrer">Picture Glance Card</a>. Diese hat den Vorteil, dass ich direkt auf das Bild klicken kann, um den Baum mittels <code>light.toggle</code> ein und auszuschalten. Zusätzlich kann im Footer der Karte mit einem Klick der <code>more-info</code>-Dialog für WLED aufgerufen werden, der eine detailliertere Auswahl der Farben und Effekte erlaubt</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/wled-weihnachtsbaum/wled-toggle.gif"
          alt="WLED toggle LED Gif"
        />
  
  
  </figure>
<p>Die Card hat des Weiteren noch eine Listenauswahl für Effekte, die in WLED als Preset festgelegt wurden und zwei weitere Slider für die Intensität und die Geschwindigkeit des gewählten Effekts.</p>

<h3 class="relative group">Hintergrundbild
    <div id="hintergrundbild" class="anchor"></div>
    
</h3>
<p>Als Hintergrundbild für die Picture Glance Card muss das folgende Bild über <code>Speichern unter</code> im Homeassistant Config-Pfad gespeichert werden.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/wled-weihnachtsbaum/wled-background.jpeg"
          alt="Background Image for Lovelace Card"
        />
  
  
  </figure>
<p>Im folgenden Beispiel nutze ich dafür den Pfad <code>./config/www/entitypictures/weihnachtsbaum.jpeg</code></p>

<h3 class="relative group">Code für die Card
    <div id="code-für-die-card" class="anchor"></div>
    
</h3>
<p>Der folgende Code erzeugt die oben dargestellte Card:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">custom:vertical-stack-in-card</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">cards</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">picture-glance</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">/local/entitypictures/weihnachtsbaum.jpeg</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">tap_action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">toggle</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entities</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">light.wled</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">tap_action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">more-info</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">light.wled</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">Weihnachtsbaum</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">entities</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entities</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">select.wled_preset</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Preset</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">number.wled_intensity</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">number.wled_speed</span></span></span></code></pre></div></div>

<h2 class="relative group">Advanced Lovelace Card
    <div id="advanced-lovelace-card" class="anchor"></div>
    
</h2>
<p>Alternativ kann der Footer direkt mit weiteren Presets versehen werden, die sich mit einem Klick direkt aktivieren lassen ohne vorher in das Dropdown Menü wechseln zu müssen. Die Sache hat einen Haken und erfordert ein wenig kreatives Umdenken. Als Entities können nur bereits existierende Entities eingebunden werden. Die Picture Glance Card biete leider keine Möglichkeit ein Platzhalter zu platzieren.</p>
<p><strong>Ein Umweg:</strong><br>
Man kann auf schnellem Wege ein paar Scenes unter <code>Configuration &gt; Automations &amp; Scenes</code> anlegen und ein Icon zuweisen, dass dem Effekt entspricht. Als Gerät wird dann einfach <code>light.wled</code> angegeben. Diese Scenes dienen nur als Icons im Footer. Bei einem Klick werden sie nicht aktiviert, sondern stattdessen ein dedizierter Service Call ausgeführt. Die Karte sieht dann so aus:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/wled-weihnachtsbaum/wled-lovelacecard-advanced.png"
          alt="Advanced Lovelace Card"
        />
  
  
  </figure>

<h3 class="relative group">Code
    <div id="code" class="anchor"></div>
    
</h3>
<p><strong>Wichtig:</strong><br>
Im Service Call muss als <code>option</code> der exakte Name des Presets aus der WLED-UI gewählt werden. Die Namen können unter den <em>Developer Tools</em> eingesehen werden, wenn man nach der Entity <code>select.wled_preset</code> sucht und diese anklickt.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">custom:vertical-stack-in-card</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">cards</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">picture-glance</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">/local/entitypictures/weihnachtsbaum.jpeg</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">light.wled</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">X-Mas</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">tap_action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">toggle</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entities</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">scene.wled_running</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">tap_action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">call-service</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">select.select_option</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">service_data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">select.wled_preset</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">option</span><span class="p">:</span><span class="w"> </span><span class="m">1</span><span class="w"> </span><span class="l">Running XMas</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">scene.wled_fireflicker</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">tap_action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">call-service</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">select.select_option</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">service_data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">select.wled_preset</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">option</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w"> </span><span class="l">Fireflicker</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">scene.wled_flow</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">tap_action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">call-service</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">select.select_option</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">service_data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">select.wled_preset</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">option</span><span class="p">:</span><span class="w"> </span><span class="m">3</span><span class="w"> </span><span class="l">Flow</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">scene.wled_lake</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">tap_action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">call-service</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">select.select_option</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">service_data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">select.wled_preset</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">option</span><span class="p">:</span><span class="w"> </span><span class="m">4</span><span class="w"> </span><span class="l">Lake</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">scene.wled_colorwinkles</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">tap_action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">call-service</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">select.select_option</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">service_data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">select.wled_preset</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">option</span><span class="p">:</span><span class="w"> </span><span class="m">5</span><span class="w"> </span><span class="l">Colorwinkles</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">scene.wled_saw</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">tap_action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">call-service</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">select.select_option</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">service_data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">select.wled_preset</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">option</span><span class="p">:</span><span class="w"> </span><span class="m">6</span><span class="w"> </span><span class="l">Saw</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">light.wled</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">tap_action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">more-info</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">entities</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entities</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">select.wled_preset</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Preset</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">number.wled_intensity</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">number.wled_speed</span></span></span></code></pre></div></div>
<p>Viel Spaß beim automatisieren des Weihnachtsbaums.</p>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Automatisch pausierender Media Player</title>
      <link>https://jbetzen.net/posts/autopause-mediaplayer/</link>
      <pubDate>Sun, 08 Aug 2021 16:13:05 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/autopause-mediaplayer/</guid>
      <description>Wer zu Hause Bewegungssensoren installiert hat, kann automatisiert einen Media Player pausieren und wieder starten sobald man den Raum verlässt und wieder betritt.</description>
      <content:encoded><![CDATA[ 
  
  
  
  



<div
  
    class="flex px-4 py-3 rounded-md shadow bg-primary-100 dark:bg-primary-900"
  
  >
  <span
    
      class="text-primary-400 pe-3 flex items-center"
    
    >
    <span class="relative block icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 128c17.67 0 32 14.33 32 32c0 17.67-14.33 32-32 32S224 177.7 224 160C224 142.3 238.3 128 256 128zM296 384h-80C202.8 384 192 373.3 192 360s10.75-24 24-24h16v-64H224c-13.25 0-24-10.75-24-24S210.8 224 224 224h32c13.25 0 24 10.75 24 24v88h16c13.25 0 24 10.75 24 24S309.3 384 296 384z"/></svg>
</span>
  </span>

  <span
    
      class="dark:text-neutral-300"
    
    >Der neue Post <a href="/posts/last-motion-sensor/">Last Motion Sensor</a> enthält eine verbesserte Methode für den Last Motion Sensor, der ohne die Custom Component <a href="https://github.com/snarky-snark/home-assistant-variables"  target="_blank" rel="noreferrer">home-assistant-variables</a> funktioniert.</span>
</div>

<p>Lebt man in seiner Wohnung überwiegend allein, kann über Bewegungssensoren verlässlich ermittelt werden, in welchem Raum man sich aufhält. Wie das geht wurde bereits im <a href="/posts/room-based-presence/" >Post über Room Based Presence</a> erläutert. Schaut man einen Film oder hört ein Hörbuch, geschieht das über einen Media Player, der klar einem Raum zugeordnet ist. Verlässt man den Raum, in dem gerade eine Wiedergabe erfolgt, bspw. um eine Tüte Chips zu holen, kann der Media Player automatisch pausiert und beim Wiedereintreten in den Raum automatisch fortgesetzt werden.</p>

<h2 class="relative group">Voraussetzungen
    <div id="voraussetzungen" class="anchor"></div>
    
</h2>
<p>Für diese Automation wird der <code>sensor.last_motion</code> benötigt, der in dem <a href="/posts/room-based-presence/" >Post über Room Based Presence</a> ausgiebig erläutert wurde. Durch diesen Sensor weiß Homeassistant in welchem Raum man sich derzeit aufhält.</p>





  
  
    
  
  


  <section class="space-y-10 w-full">
    
    











  
  
  








  
  
    
    

    
    
      
      
        
      
        
      
        
      
    

    
    

    
    
      
        
        
      
    
  



<article class="article-link--shortcode flex flex-col md:flex-row relative">
  
    <div class="flex-none relative overflow-hidden  thumbnail-shadow md:mr-7 thumbnail">
      <img
        src="/posts/room-based-presence/featured.png"
        role="presentation"
        loading="lazy"
        decoding="async"
        class="not-prose absolute inset-0 w-full h-full object-cover">
    </div>
  
  <div class=" mt-3 md:mt-0">
    <header class="items-center text-start text-xl font-semibold">
      <a
        
          href="/posts/room-based-presence/"
        
        class="not-prose before:absolute before:inset-0 decoration-primary-500 dark:text-neutral text-xl font-bold text-neutral-800 hover:underline hover:underline-offset-2">
        <h2>
          Room Based Presence mit Motion Sensoren
          
        </h2>
      </a>
      
      
    </header>
    <div class="text-sm text-neutral-500 dark:text-neutral-400">
      







  

  
  
  
    
  

  

  
    
  

  
    
  

  
    
  

  
    
  

  

  

  

  

  


  <div class="flex flex-row flex-wrap items-center">
    
    
      <time datetime="2020-03-30T23:42:13&#43;02:00">30.03.2020</time><span class="px-2 text-primary-500">&middot;</span><time datetime="2025-12-04T00:00:00&#43;00:00">Aktualisiert: 04.12.2025</time><span class="px-2 text-primary-500">&middot;</span><span>637 Wörter</span><span class="px-2 text-primary-500">&middot;</span><span title="Lesezeit">3 min</span>
    

    
    
  </div>

  

  
  
    <div class="flex flex-row flex-wrap items-center">
      
        
      
        
          
            
              
                <a class="relative mt-[0.5rem] me-2" href="/categories/zigbee/">
                  
                  <span class="flex cursor-pointer">
  
  
  
    
    
  
  
    <span
      class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal text-primary-700 dark:border-primary-600 dark:text-primary-400">
  
    Zigbee
  </span>
</span>

                </a>
              
            
            
          
            
              
                <a class="relative mt-[0.5rem] me-2" href="/categories/motion-sensor/">
                  
                  <span class="flex cursor-pointer">
  
  
  
    
    
  
  
    <span
      class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal text-primary-700 dark:border-primary-600 dark:text-primary-400">
  
    Motion Sensor
  </span>
</span>

                </a>
              
            
            
          
            
              
                <a class="relative mt-[0.5rem] me-2" href="/categories/hass-variables/">
                  
                  <span class="flex cursor-pointer">
  
  
  
    
    
  
  
    <span
      class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal text-primary-700 dark:border-primary-600 dark:text-primary-400">
  
    hass-variables
  </span>
</span>

                </a>
              
            
            
          
        
      
        
      
        
          
            
              
            
            
          
        
      
        
          
            
              
            
            
          
        
      
    </div>
  


    </div>
    
      
      <div
        class="article-link__summary prose dark:prose-invert max-w-fit mt-1 ">
        Wer im Eigenheim Bewegungssensoren installiert hat, kann schnell und einfach einen Sensor erstellen, der aufzeigt in welchem Raum die letzte Bewegung registriert wurde. Wie man diese Info sinnvoll nutzen kann, wird in diesem Post erläutert.
      </div>
    
  </div>
</article>

  </section>


<p>Es gelten die erläuterten Grundsätze, die im verlinkten Post erläutert wurden:</p>
<ul>
<li>Jeder Raum des Hauses benötigt einen Bewegungssensor</li>
<li>Diese Automation funktioniert nur, wenn sich nur eine Person im Haus aufhält</li>
<li>Es sollte ein <code>input_boolean</code> als <em>Condition</em> in der Automation verwendet werden für den Fall, dass mehrere Personen im Haus anwesend sind</li>
</ul>

<h2 class="relative group">Die Automation
    <div id="die-automation" class="anchor"></div>
    
</h2>
<p>Benötigt wird ein Media Player. In diesem Beispiel verwendete ich meinen Beelink GT-King Pro, der mit CoreElec geflasht wurde und das kostenlose Media Center Kodi ausführt. Wie man diesen Media Player mit CoreElec flasht, habe ich in <a href="/posts/gtkingprop-coreelec/" >diesem Post</a> ausgeführt.</p>





  
  
    
  
  


  <section class="space-y-10 w-full">
    
    











  
  
  








  
  
    
    

    
    
      
      
        
      
        
      
        
      
    

    
    

    
    
      
        
        
      
    
  



<article class="article-link--shortcode flex flex-col md:flex-row relative">
  
    <div class="flex-none relative overflow-hidden  thumbnail-shadow md:mr-7 thumbnail">
      <img
        src="/posts/gtkingprop-coreelec/featured.png"
        role="presentation"
        loading="lazy"
        decoding="async"
        class="not-prose absolute inset-0 w-full h-full object-cover">
    </div>
  
  <div class=" mt-3 md:mt-0">
    <header class="items-center text-start text-xl font-semibold">
      <a
        
          href="/posts/gtkingprop-coreelec/"
        
        class="not-prose before:absolute before:inset-0 decoration-primary-500 dark:text-neutral text-xl font-bold text-neutral-800 hover:underline hover:underline-offset-2">
        <h2>
          Beelink GT-King Pro und CoreELEC
          
        </h2>
      </a>
      
      
    </header>
    <div class="text-sm text-neutral-500 dark:text-neutral-400">
      







  

  
  
  
    
  

  

  
    
  

  

  
    
  

  
    
  

  

  

  

  

  


  <div class="flex flex-row flex-wrap items-center">
    
    
      <time datetime="2020-02-01T23:42:13&#43;02:00">01.02.2020</time><span class="px-2 text-primary-500">&middot;</span><span>193 Wörter</span><span class="px-2 text-primary-500">&middot;</span><span title="Lesezeit">1 min</span>
    

    
    
  </div>

  

  
  
    <div class="flex flex-row flex-wrap items-center">
      
        
      
        
          
            
              
                <a class="relative mt-[0.5rem] me-2" href="/categories/media-player/">
                  
                  <span class="flex cursor-pointer">
  
  
  
    
    
  
  
    <span
      class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal text-primary-700 dark:border-primary-600 dark:text-primary-400">
  
    media-player
  </span>
</span>

                </a>
              
            
            
          
        
      
        
      
        
          
            
              
            
            
          
            
              
            
            
          
            
              
            
            
          
        
      
        
      
    </div>
  


    </div>
    
      
      <div
        class="article-link__summary prose dark:prose-invert max-w-fit mt-1 ">
        Der Hersteller Beelink bietet mit dem GT-King Pro eine Streaming Box an, die sowohl mit Android als auch mit dem freie Media Center Kodi betrieben werden kann. Dieser Post beschreibt, wie man Kodi mittels dem CoreELEC Projekt installiert.
      </div>
    
  </div>
</article>

  </section>


<p>Der Media Player für dieses Beispiel hat den Namen <code>media_player.beelink</code> und befindet sich in meinem Wohnzimmer.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Kodi Auto Pause</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Automatically pauses and resumes playback when living room is left or entered&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.last_motion</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">condition</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">and</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">input_boolean.besuchermodus</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;off&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.current_av_receiver_source</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Kodi&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% if not is_state(&#34;sensor.last_motion&#34;, &#34;Wohnzimmer&#34;) and is_state(&#34;media_player.beelink&#34;, &#34;playing&#34;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          media_player.media_pause
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% elif is_state(&#34;sensor.last_motion&#34;, &#34;Wohnzimmer&#34;) and is_state(&#34;media_player.beelink&#34;, &#34;paused&#34;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          media_player.media_play
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% endif %}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.beelink</span></span></span></code></pre></div></div>

<h2 class="relative group">Erläuterung der Automation
    <div id="erläuterung-der-automation" class="anchor"></div>
    
</h2>

<h3 class="relative group">Trigger
    <div id="trigger" class="anchor"></div>
    
</h3>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.last_motion</span></span></span></code></pre></div></div>
<p>Trigger ist der Sensor <code>sensor.last_motion</code>, der den Aufenthalt in Haus angibt. Ändert sich der Aufenthalt, werden zwei <code>conditions</code> geprüft.</p>

<h3 class="relative group">Conditions
    <div id="conditions" class="anchor"></div>
    
</h3>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">input_boolean.besuchermodus</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;off&#39;</span></span></span></code></pre></div></div>
<p>Diese <em>Condition</em> prüft den <em>State</em> eines <code>input_boolean</code>, der von mir gesetzt wird, wenn Besuch anwesend ist. Für diesen Fall soll die Automation nicht ausgeführt werden.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.current_av_receiver_source</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Kodi&#39;</span></span></span></code></pre></div></div>
<p>Diese <em>Condition</em> prüft, ob mein AV-Receiver auf den Eingang des Media Players geschaltet ist, damit die Automation nicht <em>triggert</em>, wenn ich bspw. über das Gerät Musik höre.</p>

<h3 class="relative group">Action
    <div id="action" class="anchor"></div>
    
</h3>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">    {% if not is_state(&#34;sensor.last_motion&#34;, &#34;Wohnzimmer&#34;) and is_state(&#34;media_player.beelink&#34;, &#34;playing&#34;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">      media_player.media_pause
</span></span></span><span class="line"><span class="cl"><span class="sd">    {% elif is_state(&#34;sensor.last_motion&#34;, &#34;Wohnzimmer&#34;) and is_state(&#34;media_player.beelink&#34;, &#34;paused&#34;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">      media_player.media_play
</span></span></span><span class="line"><span class="cl"><span class="sd">    {% endif %}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.beelink</span></span></span></code></pre></div></div>
<p>Für die <em>Action</em> kommt eine <em>service_template</em> zum Einsatz, die basierend auf dem Zustand des <code>sensor.last_motion</code> und des Media Players <code>media_player.beelink</code> zwei Unterschiedliche Aktionen ausführt:</p>
<ul>
<li><strong>Pause:</strong> Wenn eine Bewegung <em>außerhalb</em> des Wohnzimmers detektiert wird UND der Media Player gerade etwas abspielt</li>
<li><strong>Resume:</strong> Wenn eine Bewegung <em>im</em> Wohnzimmer detektiert wird UND der Media Player pausiert ist.</li>
</ul>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>ControllerX und Home Assistant</title>
      <link>https://jbetzen.net/posts/controllerx/</link>
      <pubDate>Thu, 08 Jul 2021 14:19:40 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/controllerx/</guid>
      <description>ControllerX ist eine mächtige AppDaemon App um Zigbee-Eingabegeräte, wie bspw. Aqara- und IKEA-Buttons, Lichtschalter- oder Rollosteuerungen zu verwalten und in Homeassistant zu nutzen. Anhand ein paar Beispielen zeige ich, wie ControllerX bei mir in Verwendung ist.</description>
      <content:encoded><![CDATA[ 
  



<div
  
    class="flex px-4 py-3 rounded-md shadow bg-primary-100 dark:bg-primary-900"
  
  >
  <span
    
      class="text-primary-400 pe-3 flex items-center"
    
    >
    <span class="relative block icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M506.3 417l-213.3-364c-16.33-28-57.54-28-73.98 0l-213.2 364C-10.59 444.9 9.849 480 42.74 480h426.6C502.1 480 522.6 445 506.3 417zM232 168c0-13.25 10.75-24 24-24S280 154.8 280 168v128c0 13.25-10.75 24-23.1 24S232 309.3 232 296V168zM256 416c-17.36 0-31.44-14.08-31.44-31.44c0-17.36 14.07-31.44 31.44-31.44s31.44 14.08 31.44 31.44C287.4 401.9 273.4 416 256 416z"/></svg>
</span>
  </span>

  <span
    
      class="dark:text-neutral-300"
    
    ><p>Das Themenfeld ControllerX und AppDaemon ist aktuell ein Minenfeld und die <a href="https://github.com/xaviml/controllerx/discussions/874"  target="_blank" rel="noreferrer">zukünftige Kompatibilität</a> ist derzeit nicht gesichert. Der Post wurde aktualisiert und gilt nun für die folgenden Minimalversionen:</p>
<ul>
<li>ControllerX: <code>5.2.2</code></li>
<li>AppDaemon Add-On: <code>0.17.13</code></li>
</ul></span>
</div>

<p><a href="https://github.com/xaviml/controllerx"  target="_blank" rel="noreferrer">ControllerX</a> ist ein mächtiges und <a href="https://xaviml.github.io/controllerx/"  target="_blank" rel="noreferrer">sehr gut dokumentiertes</a> Tool, um <a href="https://de.wikipedia.org/wiki/ZigBee"  target="_blank" rel="noreferrer">Zigbee</a>-Eingabegeräte in Homeassistant zu verwenden. ControllerX greift dabei auf die Funktionalitäten von <a href="https://appdaemon.readthedocs.io/en/latest/"  target="_blank" rel="noreferrer">AppDaemon</a> zurück und erlaubt es <a href="https://xaviml.github.io/controllerx/controllers/"  target="_blank" rel="noreferrer">nahezu jedes auf dem Markt verfügbare Eingabegerät</a> nahtlos mit Homeassistant zu verwenden.</p>

<h2 class="relative group">Vorraussetzungen zur Nutzung
    <div id="vorraussetzungen-zur-nutzung" class="anchor"></div>
    
</h2>

<h3 class="relative group">AppDaemon
    <div id="appdaemon" class="anchor"></div>
    
</h3>
<p><a href="https://appdaemon.readthedocs.io"  target="_blank" rel="noreferrer">AppDaemon</a> ist essentiell für die Nutzung von ControllerX und steht als eigenes <a href="https://www.home-assistant.io/addons/"  target="_blank" rel="noreferrer">Add-On</a> im <a href="https://www.home-assistant.io/integrations/hassio/"  target="_blank" rel="noreferrer">Supervisor</a> von Homeassistant zur Installation bereit. Ist die Installation erfolgt, muss das Add-On manuell gestartet werden.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/controllerx/controllerx-appdaemon-addon.png"
          alt="Screenshot vom AppDaemon Add-on"
        />
  
  
  </figure>
<p>Damit ControllerX und AppDaemon im Zusammenspiel funktionieren, muss zusätzlich die Datei <code>appdaemon.yaml</code> angepasst werden. Siehe dazu die <a href="https://xaviml.github.io/controllerx/start/installation/#appdaemon-addon"  target="_blank" rel="noreferrer">ControllerX Dokumentation</a>. Wichtig ist der Eintrag für <code>app_dir</code>, der Anweist in welchem Pfadd AppDaemon nach Anwendungen sucht.</p>

<h3 class="relative group">HACS
    <div id="hacs" class="anchor"></div>
    
</h3>
<p><a href="https://hacs.xyz/"  target="_blank" rel="noreferrer">HACS</a>, kurz für <em>Home Assistant Community Store</em>, ist ein Appstore zur Erweiterung von Homeassistants Basisfunktionen.</p>

<h3 class="relative group">ControllerX
    <div id="controllerx" class="anchor"></div>
    
</h3>
<p>ControllerX kann über HACS installiert und aktualisiert werden. Es wird unter dem Menüpunkt <code>Automation</code> gelistet und mit einem Klick auf <kbd>Install</kbd> installiert werden.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/controllerx/controllerx-hacs-install.png"
          alt="Screenshot von ControllerX in HACS"
        />
  
  
  </figure>

<h3 class="relative group">Zigbee-Hub
    <div id="zigbee-hub" class="anchor"></div>
    
</h3>
<p>Ein <em>Zigbee-Hub</em> dient als Router für alle Zigbee-Geräte. Über diese Hardware wird jedes Gerät eingebunden und in Homeassistant als <em>Entity</em> zur Verfügung gestellt. Als Universalhub für alle Hersteller spreche ich eine klare Empfehlung für den <a href="https://phoscon.de/de/conbee2"  target="_blank" rel="noreferrer">Conbee 2</a> von Dresden Elektronik aus. Der Conbee 2 kann zusammen mit dem offiziellen <a href="https://www.home-assistant.io/integrations/deconz/"  target="_blank" rel="noreferrer">deCONZ Add-On</a> genutzt werden und stellt zum <em>Pairing</em> der Geräte eine <em>Web UI</em> namens <a href="https://phoscon.de/de/app/doc"  target="_blank" rel="noreferrer">Phoscon</a> zur Verfügung. Über diese kann im Browser ein neues Gerät eingebunden, benannt und gruppiert werden.</p>

<h2 class="relative group">Zigbee Events und der Event Bus
    <div id="zigbee-events-und-der-event-bus" class="anchor"></div>
    
</h2>
<p>Im Herzen von Homeassistant schlägt der <em>Event Bus</em>. Jede Änderung eines <em>States</em> wird dort in einem fortlaufenden Stream dargestellt und im <a href="https://www.home-assistant.io/integrations/recorder/"  target="_blank" rel="noreferrer">Recorder</a> festgehalten. Nutzt man die deCONZ-Integration, kann explizit nach Events von Zigbee-Geräten gefiltert werden. Dazu muss unter <code>DEVELOPER TOOLS &gt; EVENTS</code> in der Sektion <code>Listen to Events</code> im Eingabefeld <code>deconz_event</code> eingegeben und auf den Button <kbd>Start listening</kbd> geklickt werden. Für andere Integrationen als deCONZ sei auf die <a href="https://xaviml.github.io/controllerx/others/extract-controller-id"  target="_blank" rel="noreferrer">Docs</a> von ControllerX verwiesen.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/controllerx/controllerx-deconzevent.png"
          alt="Screenshot des Event Bus"
        />
  
  
  </figure>
<p>Drückt man nun einen Knopf an einem Zigbee-Eingabegerät, wie bspw. einem Aqara Button, erscheint - exemplarisch - eine Ausgabe im JSON-Format:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;event_type&#34;</span><span class="p">:</span> <span class="s2">&#34;deconz_event&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;button_wohnzimmer&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;unique_id&#34;</span><span class="p">:</span> <span class="s2">&#34;00:15:8d:00:01:e8:7f:26&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;event&#34;</span><span class="p">:</span> <span class="mi">1002</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;device_id&#34;</span><span class="p">:</span> <span class="s2">&#34;6f7383674eed4fb3b0aabca03e9a32e1&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;origin&#34;</span><span class="p">:</span> <span class="s2">&#34;LOCAL&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;time_fired&#34;</span><span class="p">:</span> <span class="s2">&#34;2021-07-08T19:23:01.451187+00:00&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;context&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;89f14979b86490040adef6588e0789d8&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;parent_id&#34;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;user_id&#34;</span><span class="p">:</span> <span class="kc">null</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<p>Interessant für die Automationen sind die Daten im Objekt <code>data: {}</code>. Zur Erläuterung:</p>
<table>
	<thead>
			<tr>
					<th>Key</th>
					<th>Funktion</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>id</code></td>
					<td>Ist der Name des Zigbee-Geräts, den die Deconz-Integration an Homeassistant durchreicht.</td>
			</tr>
			<tr>
					<td><code>unique_id</code></td>
					<td>Ist die eindeutige Hardware-Adresse des Zigbee-Geräts.</td>
			</tr>
			<tr>
					<td><code>event</code></td>
					<td>Der Event-Code entspricht einer bestimmten Aktion des Geräts, bspw. einem einfach Klick oder dem Gedrückthalten eines Tasters.</td>
			</tr>
			<tr>
					<td><code>device_id</code></td>
					<td>Eine interne ID, die Homeassistant führt und automatisch dem Gerät zuweist. Im Gegensatz zur <code>unique_id</code> ist sie nicht persistent und kann wechseln, wenn das Gerät nach einem <em>Unpairing</em> neu verbunden wird.</td>
			</tr>
	</tbody>
</table>
<p>Die <code>id</code> und <code>unique_id</code> sind essentiell für die Nutzung des Geräts mit ControllerX. Mit einem der beiden Parameter kann jedes Gerät eindeutig ermittelt und der gesendete <code>event_code</code> zugeordnet werden. Dieser kann dann als <em>Trigger</em> für Aktionen benutzt werden. Per <em>default</em> verwendet ControllerX die <code>id</code>.</p>

<h2 class="relative group">Controller einbinden
    <div id="controller-einbinden" class="anchor"></div>
    
</h2>
<p>Nach der Installation von AppDaemon ist unter <code>./config/appdaemon/apps/</code> eine Datei namens <code>apps.yaml</code> verfügbar, in der alle Eingabegeräte konfiguriert werden.</p>
<p>Als einfaches Beispiel sei hier die Konfiguration für die <a href="https://xaviml.github.io/controllerx/controllers/E1766"  target="_blank" rel="noreferrer">Fernbedienung E1766</a> meines IKEA Fyrtur Rollos dargestellt, dem zuvor schon ein <a href="../ikea-rollo" >Post</a> gewidmet wurde:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">rollo_schlafzimmer</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">module</span><span class="p">:</span><span class="w"> </span><span class="l">controllerx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">class</span><span class="p">:</span><span class="w"> </span><span class="l">E1766CoverController</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">controller</span><span class="p">:</span><span class="w"> </span><span class="l">tradfri_open_close_remote</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">integration</span><span class="p">:</span><span class="w"> </span><span class="l">deconz</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">cover</span><span class="p">:</span><span class="w"> </span><span class="l">cover.rollo_schlafzimmer</span></span></span></code></pre></div></div>
<p>Die einzelnen Konfigurationsparameter im Detail:</p>
<table>
	<thead>
			<tr>
					<th>Parameter</th>
					<th>Funktion</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>rollo_schlafzimmer</code></td>
					<td>Ein eindeutiger Name, der vergeben werden muss.</td>
			</tr>
			<tr>
					<td><code>module</code></td>
					<td>Weist AppDaemon an, dass ControllerX verwendet werden soll.</td>
			</tr>
			<tr>
					<td><code>class</code></td>
					<td>ControllerX hat unterschiedliche Standardanweisungen für jeden Controller parat. Der E1766-Controller kann bspw. auch zur Steuerung eines Lichts oder eines Schalters verwendet werden.</td>
			</tr>
			<tr>
					<td><code>controller</code></td>
					<td>Der <em>Entity Name</em> der Fernbedienung in Homeassistant.</td>
			</tr>
			<tr>
					<td><code>integration</code></td>
					<td>Neben der deCONZ-Integration beherrscht ControllerX noch weitere Integrationen, wie <a href="https://www.home-assistant.io/integrations/zha/"  target="_blank" rel="noreferrer">Zigbee Home Automation</a> (<code>zha</code>) oder <a href="https://www.zigbee2mqtt.io/"  target="_blank" rel="noreferrer">Zigbee2MQTT</a> (<code>z2m</code>)</td>
			</tr>
			<tr>
					<td><code>cover</code></td>
					<td>Der <code>Entity Name</code> des Rollos in Homeassistant.</td>
			</tr>
	</tbody>
</table>
<p>Eine große Stärke von ControllerX ist, dass jede vordefinierte Aktion überschrieben werden kann. Dabei wird unterschieden zwischen:</p>
<ul>
<li><code>mapping</code>: Überschreibt die Grundfunktionen des Controllers komplett. Nicht definierte Events werden ignoriert.</li>
<li><code>merge_mapping</code>: Behält die Grundfunktionen und überschreibt nur bestimmte Events.</li>
</ul>

<h2 class="relative group">Beispielkonfigurationen
    <div id="beispielkonfigurationen" class="anchor"></div>
    
</h2>
<p>Da es dem Menschen zu gerne an Phantasie mangelt, möchte ich ein paar Beispiele präsentieren, wie ich Zigbee-Eingabegeräte in meinem Alltag nutze. Alle Beispiele zur Nutzung von ControllerX erfolgen unter der Verwendung der deCONZ-Integration und müssen ggf. angepasst werden, wenn ZHA oder Z2M verwendet werden.</p>

<h3 class="relative group">Hue Dimmer Switch
    <div id="hue-dimmer-switch" class="anchor"></div>
    
</h3>
<p>In jedem meiner Räume hängt eine <a href="https://xaviml.github.io/controllerx/controllers/324131092621"  target="_blank" rel="noreferrer">Hue Dimmer Switch</a>. Sämtliche Lichter eines Raumes sind über die Phoscon App gruppiert und erscheinen als eine einzige steuerbare <em>Entity</em> in Homeassistant. Ich nutze die Dimmschalter zum Einschalten und Dimmen der Lampen und habe jeweils den Einschalt- und den Ausschaltknopf mit einem <code>merge_mapping</code> angepasst. Geändert wurden die folgenden <em>Event Codes</em>:</p>
<table>
	<thead>
			<tr>
					<th>Event</th>
					<th>Aktion</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>1000</code></td>
					<td>Ein einfacher Click auf die I-Taste startet eine Szene, in der alle Leuchten mit voller Leuchtstärke erstrahlen.</td>
			</tr>
			<tr>
					<td><code>1001</code></td>
					<td>Das Gedrückthalten der I-Taste startet eine Szene, in der alle Leuchten gedimmt erstrahlen.</td>
			</tr>
			<tr>
					<td><code>4001</code></td>
					<td>Das Gedrückthalten der O-Taste startet ein Script, das ausgeführt wird wenn ich das Haus verlasse und alle Lichter und Media Player ausschaltet.</td>
			</tr>
	</tbody>
</table>
<p>Der entsprechende Eintrag in der <code>.config/appdaemon/apps/apps.yaml</code> sieht dann folgendermaßen aus:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">hue_dimmer_flur</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">module</span><span class="p">:</span><span class="w"> </span><span class="l">controllerx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">class</span><span class="p">:</span><span class="w"> </span><span class="l">HueDimmerController</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">controller</span><span class="p">:</span><span class="w"> </span><span class="l">flur_dimmschalter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">integration</span><span class="p">:</span><span class="w"> </span><span class="l">deconz</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">light</span><span class="p">:</span><span class="w"> </span><span class="l">light.deconz_licht_flur</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">merge_mapping</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">1000</span><span class="p">:</span><span class="w"> </span><span class="c"># Click I</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">scene</span><span class="p">:</span><span class="w"> </span><span class="l">scene.flur_hell</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">1001</span><span class="p">:</span><span class="w"> </span><span class="c"># Hold I</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">scene</span><span class="p">:</span><span class="w"> </span><span class="l">scene.flur_gedimmt</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">4001</span><span class="p">:</span><span class="w"> </span><span class="c"># Hold O</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">script.turn_on</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">script.leaving_home</span></span></span></code></pre></div></div>

<h3 class="relative group">Aqara Buttons
    <div id="aqara-buttons" class="anchor"></div>
    
</h3>
<p>Für kleines Geld können simple Buttons von Aqara erstanden werden. Diese gibt es jedoch in zwei unterschiedlichen Varianten:</p>
<table>
	<thead>
			<tr>
					<th>Variante</th>
					<th>Eigenschaften</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>WXKG11LM <a href="https://xaviml.github.io/controllerx/controllers/WXKG11LM-sensor_switch"  target="_blank" rel="noreferrer">lumi.sensor_switch.aq2</a></td>
					<td>4 unterschiedliche Aktionen verfügbar</td>
			</tr>
			<tr>
					<td>WXKG11LM <a href="https://xaviml.github.io/controllerx/controllers/WXKG11LM-remote"  target="_blank" rel="noreferrer">lumi.remote.b1acn01</a></td>
					<td>3 Unterschiedliche Aktionen verfügbar</td>
			</tr>
	</tbody>
</table>
<p>In diesem Beispiel kommt die erste Variante mit 4 möglichen Aktionen zum Tragen und es werden alle Standardfunktion des Buttons mittels <code>mapping</code> überschrieben. Das zugewiesene Licht <code>light.schlafzimmer_decke</code> ist also nur ein Alibi-Eintrag, denn ein Licht wird in diesem Fall nicht direkt gesteuert.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">button_schlafzimmer</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">module</span><span class="p">:</span><span class="w"> </span><span class="l">controllerx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">class</span><span class="p">:</span><span class="w"> </span><span class="l">WXKG11LMSensorSwitchLightController</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">controller</span><span class="p">:</span><span class="w"> </span><span class="l">button_schlafzimmer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">integration</span><span class="p">:</span><span class="w"> </span><span class="l">deconz</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">light</span><span class="p">:</span><span class="w"> </span><span class="l">light.schlafzimmer_decke</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">mapping</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">1002</span><span class="p">:</span><span class="w"> </span><span class="c"># 1 Click</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">switch.toggle</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">switch.scene_schlafzimmer_nachtlicht</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">1004</span><span class="p">:</span><span class="w"> </span><span class="c"># 2 Clicks</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">switch.toggle</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">switch.schlafzimmer_steckdose_cast</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">1005</span><span class="p">:</span><span class="w"> </span><span class="c"># 3 Clicks</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">script.turn_on</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">script.schlafzimmer_readytosleep</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">1006</span><span class="p">:</span><span class="w"> </span><span class="c"># 4 Clicks</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">script.turn_on</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">script.sz_soundtouch_aus_1h</span></span></span></code></pre></div></div>
<p>Das neu festgelegte Mapping der Events führt folgende Aktionen aus:</p>
<table>
	<thead>
			<tr>
					<th>Event</th>
					<th>Aktion</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>1002</code></td>
					<td>Ein einfacher Klick wechselt über einen <a href="https://www.home-assistant.io/integrations/switch.template/"  target="_blank" rel="noreferrer">Template Switch</a> zwischen meiner Nachtbeleuchtung oder ganz ausgeschaltetem Licht im Schlafzimmer.</td>
			</tr>
			<tr>
					<td><code>1004</code></td>
					<td>Ein doppelter Klick schaltet ebenfalls einen Template Switch für eine Steckdose, an der ein Monitor, ein Chromecast und ein paar Boxen hängen.</td>
			</tr>
			<tr>
					<td><code>1005</code></td>
					<td>Ein dreifacher Klick startet ein Script, das den Schlafmodus einleitet. Das Rollo wird heruntergefahen, alle Mediaplayer ausgeschaltet und das Licht geht nicht mehr automatisch über den Bewegungssensor an.</td>
			</tr>
			<tr>
					<td><code>1006</code></td>
					<td>Ein vierfacher Klick startet einen Timer von 1h für meine Schlafzimmeranlage. Ist der Timer abgelaufen schaltet sich die Box automatisch aus.</td>
			</tr>
	</tbody>
</table>

<h3 class="relative group">Aqara Magic Cube
    <div id="aqara-magic-cube" class="anchor"></div>
    
</h3>
<p>Der <a href="https://xaviml.github.io/controllerx/controllers/MFKZQ01LM"  target="_blank" rel="noreferrer">Magic Cube</a> ist ein merkwürdiges Gerät. Es hat so viel Funktionen, dass ich jedes mal nach fünf Minuten vergesse, womit ich sie belegt habe. Trotzdem lässt er sich wunderbar mit ControllerX verwenden. In diesem Fall wird aber nicht ein Event ausgelesen, sondern eine bereits interpretierte Geste (<code>gesture</code>), wie bspw. das Schütteln, Drehen oder das Schieben des Würfels verwendet. Den Magic Cube nutze ich für meine Lichter im Wohnzimmer und zur Steuerung meines Fernsehers und AV-Receivers.</p>
<p>Die <em>Gestures</em> und gewählten Aktionen im Detail:</p>
<table>
	<thead>
			<tr>
					<th>Event</th>
					<th>Gesture</th>
					<th>Aktion</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>1</code></td>
					<td>Schütteln</td>
					<td>Schaltet den Fernseher ein</td>
			</tr>
			<tr>
					<td><code>3</code></td>
					<td>90° Flip</td>
					<td>Aktiviert Szene</td>
			</tr>
			<tr>
					<td><code>4</code></td>
					<td>180° Flip</td>
					<td>Aktiviert weitere Szene</td>
			</tr>
			<tr>
					<td><code>6</code></td>
					<td>Doppelt tippen auf Oberfläche</td>
					<td>Schaltet den Eingang des AV-Receivers auf <code>HDMI2</code></td>
			</tr>
			<tr>
					<td><code>7</code></td>
					<td>Rotation Rechts</td>
					<td>Erhöht die Lautstärke des AV-Receivers</td>
			</tr>
			<tr>
					<td><code>8</code></td>
					<td>Rotation Links</td>
					<td>Reduziert die Lautstärke des AV-Receivers</td>
			</tr>
	</tbody>
</table>
<p>Der zugehörige Eintrag in der <code>.config/appdaemon/apps/apps.yaml</code> lautet:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">magiccube_wohnzimmer</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">module</span><span class="p">:</span><span class="w"> </span><span class="l">controllerx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">class</span><span class="p">:</span><span class="w"> </span><span class="l">MFKZQ01LMLightController</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">controller</span><span class="p">:</span><span class="w"> </span><span class="l">zauberwurfel_wohnzimmer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">integration</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">deconz</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">gesture</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">light</span><span class="p">:</span><span class="w"> </span><span class="l">light.wohzimmer_esstisch</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">mapping</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">1</span><span class="p">:</span><span class="w"> </span><span class="c"># Shake</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.toggle</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.sony_bravia</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">3</span><span class="p">:</span><span class="w"> </span><span class="c"># Flip 90°</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">scene</span><span class="p">:</span><span class="w"> </span><span class="l">scene.wohnzimmer_fernsehen</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">4</span><span class="p">:</span><span class="w"> </span><span class="c"># Flip 180°</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">scene</span><span class="p">:</span><span class="w"> </span><span class="l">scene.wohnzimmer_chill</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">6</span><span class="p">:</span><span class="w"> </span><span class="c"># Double Tap on Surface</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.select_source</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.av_receiver</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;HDMI2&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">7</span><span class="p">:</span><span class="w"> </span><span class="c"># Rotate Right</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.volume_up</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.av_receiver</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">8</span><span class="p">:</span><span class="w"> </span><span class="c"># Rotate Left</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.volume_down</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.av_receiver</span></span></span></code></pre></div></div>

<h3 class="relative group">Tradfri Shortcut Button
    <div id="tradfri-shortcut-button" class="anchor"></div>
    
</h3>
<p>IKEA hat vor kurzem sein Sortiment an Zigbee-Geräten um einen simplen <a href="https://www.ikea.com/de/de/p/tradfri-shortcut-button-weiss-40356381/"  target="_blank" rel="noreferrer">Shortcut Button</a> (E1812) erweitert. Dieser sendet folgende <em>Event Codes</em> auf Homeassistants <a href="https://www.home-assistant.io/docs/configuration/events/"  target="_blank" rel="noreferrer">Event Bus</a>:</p>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th>Event</th>
					<th>Aktion</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>1001</code></td>
					<td>Button wird gedrückt und gehalten</td>
			</tr>
			<tr>
					<td><code>1002</code></td>
					<td>Button wird einmal gedrückt</td>
			</tr>
			<tr>
					<td><code>1003</code></td>
					<td>Button wird nach dem gedrückt halten wieder losgelassen</td>
			</tr>
	</tbody>
</table>
</div>
<p>Ich nutze den Button für meine Waschmaschine. Meine Waschmaschine hat gefühlt 32 Millionen unterschiedliche Waschprogramme. Da ich aber ein einfacher Mann bin, verwende ich immer nur 2 davon: 40°-Wäsche und 60°-Wäsche. Beide Waschvorgänge dauern unterschiedlich lange.</p>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th>Waschvorgang</th>
					<th>Dauer</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>40°-Wäsche</td>
					<td>01:58:00</td>
			</tr>
			<tr>
					<td>60°-Wäsche</td>
					<td>01:48:00</td>
			</tr>
	</tbody>
</table>
</div>
<p>Ich habe meinen Button direkt neben der Waschmaschine an die Wand geklebt und kann mit einem einfachen <em>Click</em> einen Timer für die 40°-Wäsche in Homeassistant starten. Wird der Button gedrückt gehalten, startet der Timer für die 60°-Wäsche. Ist einer der beiden Timer abgelaufen, bekomme ich eine Pushnachricht auf mein iPhone.</p>
<p>Dafür werden in Homeassistant zwei <a href="https://www.home-assistant.io/integrations/timer/"  target="_blank" rel="noreferrer">Timer</a> benötigt:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">timer</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">laundry_40</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">duration</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;01:48:00&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">laundry_60</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">duration</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;01:58:00&#39;</span></span></span></code></pre></div></div>
<p>Des weiteren die Automation für die Benachrichtigung per Push-Nachricht:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Notify Waschmaschine fertig</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">event</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">event_type</span><span class="p">:</span><span class="w"> </span><span class="l">timer.finished</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">event_data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">timer.laundry_40</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">event</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">event_type</span><span class="p">:</span><span class="w"> </span><span class="l">timer.finished</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">event_data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">timer.laundry_60</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">notify.mobile_app_mizar</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Waschmaschine 🧺&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">message</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Die Waschmaschine ist fertig&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">channel</span><span class="p">:</span><span class="w"> </span><span class="l">Info</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;PUSH_WASCHMASCHINE_FERTIG&#34;</span></span></span></code></pre></div></div>
<p>Und im finalen Schritt muss eine Konfiguration in <code>.config/appdaemon/apps/apps.yaml</code> eingetragen werden. Der Tradfri Shortcut Button ist unter den Zigbee-Geräten in Verbindung mit der Phoscon-App ein Sonderfall. Er wird in der App nicht aufgeführt. Daher besteht keine Möglichkeit den Namen und somit seine <code>id</code> zu ändern. Besitzt man mehrere Shortcut Buttons, senden sie also alle unter der gleichen ID <code>tradfri_shortcut_button</code> und können somit von ControllerX nicht auseinandergehalten werden. Ich habe daraufhin den Entwickler von ControllerX <a href="https://github.com/xaviml"  target="_blank" rel="noreferrer">xaviml</a> angeschrieben und er hat mit dem <a href="https://github.com/xaviml/controllerx/releases/tag/v4.14.0"  target="_blank" rel="noreferrer">Release 4.14.0</a> eine Möglichkeit geschaffen die unterschiedlichen Shortcut Buttons über einen weiteren <em>Identifier</em> zu unterscheiden. Dieser Identifier ist die hardware-basierte <code>unique_id</code>, die einmalig für jeden Button ist:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">tradfri_button_laundry</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">module</span><span class="p">:</span><span class="w"> </span><span class="l">controllerx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">class</span><span class="p">:</span><span class="w"> </span><span class="l">E1812LightController</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">controller</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;58:8e:81:ff:fe:3f:05:fc&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">integration</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">deconz</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">listen_to</span><span class="p">:</span><span class="w"> </span><span class="l">unique_id</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">light</span><span class="p">:</span><span class="w"> </span><span class="l">light.wohnzimmer_couch</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">mapping</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">1002</span><span class="p">:</span><span class="w"> </span><span class="c"># Click</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">timer.start</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">timer.laundry_40</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">timer.cancel</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">timer.laundry_60</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">1001</span><span class="p">:</span><span class="w"> </span><span class="c"># Hold</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">timer.start</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">timer.laundry_60</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">timer.cancel</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">timer.laundry_40</span></span></span></code></pre></div></div>
<p>Da ich manchmal schusselig bin und dazu tendiere den falschen Timer zu starten, habe ich für jeden Timer noch die Funktion <code>timer.cancel</code> eingebaut, der bei einer Korrekturangabe den falschen Timer wieder beendet und den richtigen startet.</p>
<p>Viel Spaß beim experimentieren mit ControllerX.</p>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Sony PS-LX310BT: Plattenspieler mit Bose Soundtouch und Homeassistant nutzen</title>
      <link>https://jbetzen.net/posts/sony-pslx310bt/</link>
      <pubDate>Fri, 26 Mar 2021 09:19:12 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/sony-pslx310bt/</guid>
      <description>Sony bietet mit dem PS-LX310BT einen Bluetooth fähigen Plattenspieler an, der einfach in ein bestehendes Audio Setup mit Bose Soundtouch Lautsprechern eingebunden und automatisiert werden kann.</description>
      <content:encoded><![CDATA[ <p>Seit kurzem befindet sich ein recht drolliger Plattenspieler aus dem Hause Sony in meinem Besitz. Er schimpft sich <a href="https://www.sony.de/electronics/audio-komponenten/ps-lx310bt"  target="_blank" rel="noreferrer">PS-LX310BT</a> und hat eine Eigenschaft, die jedem Audiophilen vermutlich die Zehennägel hochstehen lässt: Der Plattenspieler hat eingebaute Bluetooth-Konnektivität.</p>
<p>Da ich in meinem trauten Heim ein Bose Soundtouch Multi Room Audio System nutze, das ebenfalls Bluetooth als Eingangsquelle unterstützt, habe ich mich daran gemacht und den Plattenspieler in Homeassistant eingebunden.</p>

<h2 class="relative group">Das Audio-Setup
    <div id="das-audio-setup" class="anchor"></div>
    
</h2>
<p>Kern meiner heimischen Beschallung ist ein <a href="https://de.yamaha.com/de/products/audio_visual/av_receivers_amps/rx-v577/features.html"  target="_blank" rel="noreferrer">Yamaha RX-V577 AV-Receiver</a>. An diesem ist über koaxiales Cinch ein <a href="https://www.bose.de/de_de/support/products/bose_speakers_support/bose_smarthome_speakers_support/soundtouch-adapter.html"  target="_blank" rel="noreferrer">Bose Soundtouch Wireless Adapter</a> angeschlossen, der zusammen mit 4 weiteren <a href="https://www.bose.de/de_de/support/products/bose_speakers_support/bose_smarthome_speakers_support/soundtouch-10-wireless-system.html"  target="_blank" rel="noreferrer">Bose Soundtouch 10</a> im Verbund arbeitet und die gesamte Wohnung mit Klang bespielt. Sämtliche Bose Soundtouch-Geräte haben Bluetooth eingebaut und können daher das Signal des Plattenspielers entgegen nehmen.</p>

<h2 class="relative group">Integration des Plattenspielers
    <div id="integration-des-plattenspielers" class="anchor"></div>
    
</h2>
<p>Mein Ziel war es den Plattenspieler so simpel wie möglich in Homeassistant zu integrieren. Grundproblem ist, dass der Soundtouch Adapter von Bose über analoges Cinch verbunden ist und der AV-Receiver daher, aufgrund der analogen Natur der Steckerverbindung, keinen sauberen State zugespielt bekommt, der aussagt ob gerade etwas auf dem AnalGen Eingang abgespielt wird oder nicht. Dieses Problem lässt sich sehr leicht lösen, da der Soundlink Adapter von Bose gut in Homeassistant integriert ist und zuverlässig mitteilt, ob gerade eine Wiedergabe erfolgt und welche Eingangsquelle aktuell benutzt wird, z.B. Spotify, Bluetooth oder lokale Musikwiedergabe über LAN.</p>

<h3 class="relative group">Ziel der Integration
    <div id="ziel-der-integration" class="anchor"></div>
    
</h3>
<ol>
<li>Sobald der Plattenspieler eingeschaltet wird, soll er sich mit dem Wireless Link Adapter von Bose verbinden</li>
<li>Sobald die Verbindung hergestellt ist, soll der AV-Receiver automatisch auf den korrekten Eingang umschalten und die Lautstärke auf ein brauchbares Maß einstellen</li>
</ol>

<h2 class="relative group">Sensoren und Automation in Homeassistant
    <div id="sensoren-und-automation-in-homeassistant" class="anchor"></div>
    
</h2>
<p>Es wird in Homeassistant ein Sensor benötigt, der registriert ob der Plattenspieler eine Bluetooth-Verbindung zum Bose Wireless Link Adapter aufgenommen hat. Anschließend wird eine Automation erstellt, die dies dem AV-Receiver mitteilt.</p>

<h3 class="relative group">Binary Sensor für den Plattenspieler
    <div id="binary-sensor-für-den-plattenspieler" class="anchor"></div>
    
</h3>
<p>Nachdem der Plattenspieler initial mit dem Soundlink Adapter gekoppelt und eine LP erstmals abgespielt wurde, zeichnete sich folgender State für den Soundlink Adapter in Homeassistant ab:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/sony-pslx310bt/Sony-PSLX310BT-attributes.png"
          alt="Attribute des Plattenspieler in den Hass Dev Tools"
        />
  
  
  </figure>
<p>Wie man sehen kann, gibt sich der Plattenspieler über das Attribut <code>media_title</code> mit seinem Namen <code>PS-LX310BT</code> zu erkennen. Dieses Attribut kann mit einem <a href="https://www.home-assistant.io/integrations/binary_sensor.template/"  target="_blank" rel="noreferrer">Template Binary Sensor</a> ausgelesen werden und somit Auskunft darüber geben, ob der Plattenspieler verbunden ist und Musik abspielt:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">binary_sensor</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">template</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">sensors</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">plattenspieler_on</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">friendly_name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Plattenspieler spielt&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ is_state_attr(&#34;media_player.soundtouch_wohnzimmer&#34;, &#34;media_title&#34;, &#34;PS-LX310BT&#34;) }}&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">icon_template</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% if is_state(&#34;plattenspieler_on&#34;, &#34;on&#34;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">            mdi:record-player
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% else %}
</span></span></span><span class="line"><span class="cl"><span class="sd">            mdi:volume-off
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% endif %}</span></span></span></code></pre></div></div>

<h3 class="relative group">Automation für AV-Receiver
    <div id="automation-für-av-receiver" class="anchor"></div>
    
</h3>
<p>Wenn der neu erstellte Binary Sensor nun auf <code>On/True</code> schaltet, muss der AV-Receiver auf den entsprechenden analogen Eingang schalten, an dem der Bose Soundlink Adapter angestöpselt ist. In meinem Fall ist das der <code>AV5</code>. Zusätzlich soll der Bose Adapter und der AV-Receiver eine vordefinierte Lautstärke voreinstellen.</p>
<p>Die passende Automation sieht so aus:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Set AV5 for Soundtouch</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">initial_state</span><span class="p">:</span><span class="w"> </span><span class="kc">True</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">binary_sensor.plattenspieler_on</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;on&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.turn_on</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.av_receiver</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.select_source</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.av_receiver</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">AV5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.volume_set</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.av_receiver</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">volume_level</span><span class="p">:</span><span class="w"> </span><span class="m">0.8</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.volume_set</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">media_player.soundtouch_wohnzimmer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">volume_level</span><span class="p">:</span><span class="w"> </span><span class="m">0.84</span></span></span></code></pre></div></div>
<p>Wenn nun der Plattenspieler eingeschaltet wird, baut er automatisch eine Bluetooth-Verbindung zum Bose Adapter auf. Der AV-Receiver schaltet sich darauf ein und regelt die Lautstärke.</p>

<h2 class="relative group">Weiterführendes
    <div id="weiterführendes" class="anchor"></div>
    
</h2>
<p>Die Bluetooth-Funktionalität des Plattenspielers lässt sich wunderbar mit Multi-Room-Audio-Feature der <a href="/tags/bose-soundtouch/" >Bose Soundtouch</a> Boxen kombinieren. Somit kann man sein Vinyl synchron im gesamten Haus erklingen lassen:</p>





  
  
    
  
  


  <section class="space-y-10 w-full">
    
    











  
  
  








  
  
    
    

    
    
      
      
        
      
        
      
        
      
    

    
    

    
    
      
        
        
      
    
  



<article class="article-link--shortcode flex flex-col md:flex-row relative">
  
    <div class="flex-none relative overflow-hidden  thumbnail-shadow md:mr-7 thumbnail">
      <img
        src="/posts/soundtouch-multi-room-audio/featured.png"
        role="presentation"
        loading="lazy"
        decoding="async"
        class="not-prose absolute inset-0 w-full h-full object-cover">
    </div>
  
  <div class=" mt-3 md:mt-0">
    <header class="items-center text-start text-xl font-semibold">
      <a
        
          href="/posts/soundtouch-multi-room-audio/"
        
        class="not-prose before:absolute before:inset-0 decoration-primary-500 dark:text-neutral text-xl font-bold text-neutral-800 hover:underline hover:underline-offset-2">
        <h2>
          Bose Soundtouch Multi-Room Audio
          
        </h2>
      </a>
      
      
    </header>
    <div class="text-sm text-neutral-500 dark:text-neutral-400">
      







  

  
  
  
    
  

  

  
    
  

  

  
    
  

  
    
  

  

  

  

  

  


  <div class="flex flex-row flex-wrap items-center">
    
    
      <time datetime="2020-04-11T23:42:13&#43;02:00">11.04.2020</time><span class="px-2 text-primary-500">&middot;</span><span>404 Wörter</span><span class="px-2 text-primary-500">&middot;</span><span title="Lesezeit">2 min</span>
    

    
    
  </div>

  

  
  
    <div class="flex flex-row flex-wrap items-center">
      
        
      
        
          
            
              
                <a class="relative mt-[0.5rem] me-2" href="/categories/media-player/">
                  
                  <span class="flex cursor-pointer">
  
  
  
    
    
  
  
    <span
      class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal text-primary-700 dark:border-primary-600 dark:text-primary-400">
  
    media-player
  </span>
</span>

                </a>
              
            
            
          
        
      
        
      
        
          
            
              
            
            
          
        
      
        
          
            
              
            
            
          
        
      
    </div>
  


    </div>
    
      
      <div
        class="article-link__summary prose dark:prose-invert max-w-fit mt-1 ">
        Seit Homeassistant 0.107 erhält die Bose Soundtouch Integration die Fähigkeit für Multi-Room-Audio und das Zusammenschließen einzelner Lautsprecher zu eine Zone. Wie man eine praktische Lovelace Card mit dem Custom Mini Media Player erstellt wird in diesem Post gezeigt.
      </div>
    
  </div>
</article>

  </section>


 ]]></content:encoded>
    </item>
    
    <item>
      <title>Homeassistant Fitness Tracker</title>
      <link>https://jbetzen.net/posts/fitness-tracker/</link>
      <pubDate>Sat, 23 Jan 2021 23:42:13 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/fitness-tracker/</guid>
      <description>Die Homeassistant Companion App liefert Fitnessdaten, die direkt vom Smartphone OS generiert werden. Diese können in Langzeitstatistiken mittels dem Utility Meter in Homeassistant getrackt und ausgewertet werden.</description>
      <content:encoded><![CDATA[ <p>Die <a href="https://companion.home-assistant.io/"  target="_blank" rel="noreferrer">Homeassistant Companion App</a> für <a href="https://play.google.com/store/apps/details?id=io.homeassistant.companion.android"  target="_blank" rel="noreferrer">Android</a> kann diverse Sensoren bereitstellen, bspw. die Anzahl der registrierten Schritte oder die derzeitige Aktivität, wie bspw. Radfahren. Diese Daten können mit der <a href="https://github.com/custom-cards/circle-sensor-card"  target="_blank" rel="noreferrer">Circle-Sensor-Card</a> anschaulich in der Lovelace UI dargestellt werden.</p>

<h2 class="relative group">Sensoren in der App aktivieren
    <div id="sensoren-in-der-app-aktivieren" class="anchor"></div>
    
</h2>
<p>In der App muss unter dem Menüpunkt App <code>Configuration &gt; Verwalte Sensoren</code> die folgenden Einträge aktiviert werden:</p>
<ul>
<li><code>Erkannte Aktivität</code></li>
<li><code>Schrittzähler</code></li>
</ul>
<p>Diese Sensoren erscheinen anschließend in Homeassistant als <em>Entities</em>.</p>

<h2 class="relative group">Homeassistant Konfiguration
    <div id="homeassistant-konfiguration" class="anchor"></div>
    
</h2>

<h3 class="relative group">Schrittzähler
    <div id="schrittzähler" class="anchor"></div>
    
</h3>
<p>Im folgenden Beispiel hat der Sensor meine Oneplus 7T die bezeichnung <code>sensor.op7t_steps_sensor</code>.</p>
<p>Der Schrittzähler-Sensor, den die App bereitstellt, hat leider ein inhärentes Problem. Er zählt sämtliche Schritte, die das Smartphone registriert hat, seit dem letzten Neustart des Geräts. Wird also während eines Spaziergangs das Gerät neugestartet, beginnt der Zähler erneut bei <code>0</code>. Dies ist natürlich nicht förderlich, wenn man die Anzahl der täglichen Schritte ermitteln will. Es gibt jedoch eine einfache Lösung für dieses Problem, mittels der <a href="https://www.home-assistant.io/integrations/utility_meter/"  target="_blank" rel="noreferrer">Utility Meter Integration</a>. Diese ist eigentlich zur Aufsummierung von Verbrauchswerten über längere Zeiträume gedacht, kann aber für die Ermittlung der Schrittanzahl zweckentfremdet werden.
Dazu muss die <code>configuration.yaml</code> um folgenden Eintrag erweitert werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">utility_meter</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">fitness_schritte_heute</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.op7t_steps_sensor</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">cycle</span><span class="p">:</span><span class="w"> </span><span class="l">daily</span></span></span></code></pre></div></div>
<p>Diese Konfiguration summiert sämtliche Schritte im täglichen Intervall auf, ungeachtet davon ob der Sensor zeitweilig wieder auf <code>0</code> springt. Durch diesen Eintrag wird ein neuer Sensor erzeugt, der die Bezeichnung <code>sensor.fitness_schritte_heute</code> trägt.</p>
<p><strong>ACHTUNG:</strong> Der Sensor steht erst nach einem vollen Messintervall zur Verfügung, also nach einem Tag.</p>

<h3 class="relative group">Aktivitätssensor
    <div id="aktivitätssensor" class="anchor"></div>
    
</h3>
<p>Der Aktivitätssensor in diesem Beispiel trägt die Bezeichnung <code>sensor.op7t_erkannte_aktivitat</code>. Dieser kann unterschiedliche States besitzen, bspw. <code>on_bicyle</code> (Radfahren) oder <code>walking</code> (Spazieren).</p>
<p>Wenn ermittelt werden soll, wie lange eine der Aktivitäten ausgeführt wurde, kann man die <a href="https://www.home-assistant.io/integrations/history_stats/"  target="_blank" rel="noreferrer">History Stats Integration</a> benutzen, die einen definierten State über einen festgelegten Zeitraum analysiert:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">history_stats</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Fitness gehen heute</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.op7t_erkannte_aktivitat</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;walking&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">time</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">start</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">end</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ now() }}&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">history_stats</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Fitness fahrradfahren heute</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.op7t_erkannte_aktivitat</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;on_bicycle&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">time</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">start</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">end</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ now() }}&#39;</span></span></span></code></pre></div></div>
<p>Diese zwei Einträge erzeigen zwei neue Sensoren:</p>
<ul>
<li><code>sensor.fitness_gehen_heute</code>, der anzeigt wie viele Stunden am aktuellen Tag spazieren gegangen wurde</li>
<li><code>sensor.fitness_fahrradfahren_heute</code>, der anzeigt wie viele Stunden am aktuellen Tag Rad gefahren wurde</li>
</ul>

<h3 class="relative group">Visualisieren der Daten
    <div id="visualisieren-der-daten" class="anchor"></div>
    
</h3>
<p>Die eingangs erwähnte <a href="https://github.com/custom-cards/circle-sensor-card"  target="_blank" rel="noreferrer">Circle-Sensor-Card</a> eignet sich hervorragend zur Darstellung der neuen Sensoren. Der Sensorwert steht zentral in der Mitte und außen herum befindet sich ein radiale farbliche Kontour, die bei festgelegten Werten bestimmte Farben annimmt. So lassen sich Tagesziele definieren und anschaulich darstellen.</p>
<p>Im ersten Schritt sollte die Circle-Sensor-Card aus <a href="https://hacs.xyz/"  target="_blank" rel="noreferrer">HACS</a> installiert werden. Anschließend kann diese in einem <a href="https://www.home-assistant.io/lovelace/horizontal-stack/"  target="_blank" rel="noreferrer">Horizontal-Stack</a> verwendet werden.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">horizontal-stack</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">Fitness</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">cards</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;custom:circle-sensor-card&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.fitness_schritte_heute</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Schritte</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">max</span><span class="p">:</span><span class="w"> </span><span class="m">10000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">min</span><span class="p">:</span><span class="w"> </span><span class="m">0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">show_card</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">stroke_width</span><span class="p">:</span><span class="w"> </span><span class="m">14</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">gradient</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">units</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39; &#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">font_style</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="l">black</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">font-size</span><span class="p">:</span><span class="w"> </span><span class="m">1.</span><span class="l">2em</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">color_stops</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#39;0&#39;</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#f08080&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#39;6000&#39;</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#ff9966&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#39;8000&#39;</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#90ee90&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;custom:circle-sensor-card&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.fitness_gehen_heute</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Spazieren</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">max</span><span class="p">:</span><span class="w"> </span><span class="m">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">min</span><span class="p">:</span><span class="w"> </span><span class="m">0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">show_card</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">stroke_width</span><span class="p">:</span><span class="w"> </span><span class="m">14</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">gradient</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">units</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">font_style</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="l">black</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">font-size</span><span class="p">:</span><span class="w"> </span><span class="m">1.</span><span class="l">2em</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">color_stops</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#39;0&#39;</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#f08080&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#39;1&#39;</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#90ee90&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#39;0.5&#39;</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#ff9966&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;custom:circle-sensor-card&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.fitness_fahrradfahren_heute</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Rad</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">max</span><span class="p">:</span><span class="w"> </span><span class="m">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">min</span><span class="p">:</span><span class="w"> </span><span class="m">0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">show_card</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">stroke_width</span><span class="p">:</span><span class="w"> </span><span class="m">14</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">gradient</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">units</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">font_style</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="l">black</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">font-size</span><span class="p">:</span><span class="w"> </span><span class="m">1.</span><span class="l">2em</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">color_stops</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#39;0&#39;</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#f08080&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#39;0.8&#39;</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#90ee90&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#39;0.4&#39;</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#ff9966&#39;</span></span></span></code></pre></div></div>
<p>Das Ergebnis sieht anschließend folgendermaßen aus:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/fitness-tracker/fitness-lovelacecard.png"
          alt="Lovelace Card mit Fitness Werten"
        />
  
  
  </figure>
<p>Viel Spaß beim Tracken der eigenen Werte.</p>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Xiaomi Thermometer in Homeassistant einbinden</title>
      <link>https://jbetzen.net/posts/xiaomi-mithermometer/</link>
      <pubDate>Sun, 17 Jan 2021 23:42:13 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/xiaomi-mithermometer/</guid>
      <description>Xiaomi bietet für kleines Geld ein Bluetooth LE fähiges Thermometer namens LYWSD03MMC an. Dieses kann einfach mit einer Custom Firmware geflasht und über ESPHome oder die Software BT-MQTT-Gateway ausgelesen und in Homeassistant eingebunden werden.</description>
      <content:encoded><![CDATA[ 
  
  
  
  



<div
  
    class="flex px-4 py-3 rounded-md shadow bg-primary-100 dark:bg-primary-900"
  
  >
  <span
    
      class="text-primary-400 pe-3 flex items-center"
    
    >
    <span class="relative block icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 128c17.67 0 32 14.33 32 32c0 17.67-14.33 32-32 32S224 177.7 224 160C224 142.3 238.3 128 256 128zM296 384h-80C202.8 384 192 373.3 192 360s10.75-24 24-24h16v-64H224c-13.25 0-24-10.75-24-24S210.8 224 224 224h32c13.25 0 24 10.75 24 24v88h16c13.25 0 24 10.75 24 24S309.3 384 296 384z"/></svg>
</span>
  </span>

  <span
    
      class="dark:text-neutral-300"
    
    >Zu diesem Artikel ist ein Update verfügbar, in dem gezeigt wird wie das Thermometer mittels ESPHome ausgelesen werden kann: <a href="/posts/esphome-btle-hub/">ESPHome Bluetooth Low Energy Hub</a></span>
</div>

<p>Xiaomi bietet seit längerem ein kleines aber feines Thermometer an, das für unter 5€ bei <a href="https://de.aliexpress.com/item/4001042009489.html?spm=a2g0o.productlist.0.0.134255a6e8cD4B&amp;algo_pvid=573f573c-d1ae-4b96-b7f3-92178d477e1b&amp;algo_expid=573f573c-d1ae-4b96-b7f3-92178d477e1b-1&amp;btsid=2100bdde16108977175744368ebd56&amp;ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_"  target="_blank" rel="noreferrer">AliExpress</a> erstanden werden kann. Die genaue Modellbezeichnung lautet <code>LYWSD03MMC</code>. Neben der Temperatur kann dieses zusätzlich noch die Luftfeuchtigkeit messen und seinen Batteriestand mitteilen.</p>
<p>Die Daten des Geräts werden über Bluetooth LE (<em>Low Energy</em>) gesendet und mit der Standard-Firmware von Xiaomi leider nur verschlüsselt übertragen. Zur Dekodierung wird ein sogenannter <code>bind_key</code> benötigt, der sich aber mit kleinem Aufwand auslesen lässt. Alternativ lässt sich eine Custom-Firmware über eine Bluetooth-Verbindung auf die Thermometer flashen, die zusätzlich zur bind_key-Methode einen unverschlüsselten Empfang der Daten ermöglicht.</p>

<h2 class="relative group">Einbindung in Homeassistant
    <div id="einbindung-in-homeassistant" class="anchor"></div>
    
</h2>
<p>Zur Einbindung in Homeassistant stehen prinzipiell 2 Wege zur Verfügung, die ich kurz erläutern möchte:</p>
<ol>
<li>Wer direkten Zugriff auf die Bluetooth-Schnittstelle der Hardware hat, die Homeassistant ausführt - etwa auf einem Raspberry Pi mit Hass.io -, kann direkt die gesendeten Daten mit der nativen Integration <a href="https://www.home-assistant.io/integrations/mitemp_bt/"  target="_blank" rel="noreferrer">mitemp_bt</a> abgreifen oder auf die Custom Component <a href="https://github.com/custom-components/ble_monitor"  target="_blank" rel="noreferrer">ble_monitor</a> zurückgreifen.</li>
<li>Wer keine direkten Zugriff auf die Bluetooth-Schnittstelle besitzt, muss einen Umweg gehen und ein weiteres Gerät nutzen, das diese Daten abgreifen kann, bspw. ein ESP32-Mikrocontroller oder ein Raspberry Pi Zero.</li>
</ol>
<p>In diesem Post möchte ich auf den <strong>Fall 2</strong> eingehen und zeigen, wie ein ESP32 mit ESPHome oder ein Raspberry Pi mit einem Bluetooth2MQTT-Gateway genutzt werden kann.</p>

<h2 class="relative group">Was benötigt wird
    <div id="was-benötigt-wird" class="anchor"></div>
    
</h2>
<ol>
<li>Ein Mobiltelefon mit aktivierten Bluetooth und installierten Chrome-Browser, zum flashen der Custom Firmware</li>
<li>Die aktuellste <a href="https://github.com/pvvx/ATC_MiThermometer/releases/"  target="_blank" rel="noreferrer">Custom-Firmware</a> für das Thermometer. Diese Datei muss auf das Smartphone heruntergeladen werden.</li>
<li>Eine App, um die MAC-Adresse des Thermometers auszulesen, z.B. <a href="https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp"  target="_blank" rel="noreferrer">NRF Connect</a> (Android)</li>
</ol>

<h2 class="relative group">Flashen der Custom-Firmware
    <div id="flashen-der-custom-firmware" class="anchor"></div>
    
</h2>
<p>Mit dem Smartphone muss die Webseite des <a href="https://pvvx.github.io/ATC_MiThermometer/TelinkMiFlasher.html"  target="_blank" rel="noreferrer">Telink Flashers</a> aufgerufen werden. Ist dies erfolgt, muss der Button <code>Connect</code> geklickt werden. Es erscheint eine Liste an Bluetooth-Geräten, die in Empfangsreichweite sind. An dieser Stelle wird das Thermometer ausgewählt. Unter dem Punkt <code>Select Firmware</code> wird nun die zuvor heruntergeladene Custom Firmware Datei ausgewählt und mit einem Klick auf <code>Start Flashing</code> auf das Thermometer übertragen.</p>
<p>Anschließend trennt sich die Bluetooth-Verbindung und das Thermometer erhält einen neuen Bluetooth-Gerätenamen. Erneut muss sich mittels Teelink Flasher mit dem Thermometer verbunden werden. Nun erscheint ein weitaus umfangreicheres Menü zum Einstellen des Thermometers.</p>
<p>Wer das kleine Gesicht unten links im Display vermisst, kann dieses unter dem Menüpunkt <code>Smiley:</code> durch aktivieren der Option <code>Comfort</code> wieder auf dem Display sichtbar machen. Wurde die Einstellung gesetzt, muss diese mit <code>Send Config</code> an das Gerät gesendet werden.</p>

<h2 class="relative group">Bind-Key auslesen
    <div id="bind-key-auslesen" class="anchor"></div>
    
</h2>
<p>Im Menü des Teelink Flashers gibt es den Button <code>Show all mi keys</code>. Klickt man auf diesen, erscheint dort unter dem Punkt <code>Mi Bind Key</code> die benötigte Zahlen- und Ziffernfolge. Diese wird für die Konfiguration von ESHhome benötigt und muss kopiert werden.</p>

<h2 class="relative group">MAC-Adresse des Thermometers
    <div id="mac-adresse-des-thermometers" class="anchor"></div>
    
</h2>
<p>Die MAC-Adresse kann mit der NRF Connect App ausgelesen werden. Alternativ kann dies auch unter Linux mit dem Terminal erfolgen:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">sudo hcitool lescan
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">LE Scan ...
</span></span><span class="line"><span class="cl">A4:C1:38:B1:CD:7F ATC_838293</span></span></code></pre></div></div>
<p>Mit der MAC-Adresse und dem Bind-Key sind alle Informationen vorhanden, um mit ESPHome fortzufahren.</p>

<h2 class="relative group">Integration in Homeassistant
    <div id="integration-in-homeassistant" class="anchor"></div>
    
</h2>

<h3 class="relative group">Methode 1: ESPHome
    <div id="methode-1-esphome" class="anchor"></div>
    
</h3>
<p>Esphome hat sich zu einem wahren schweizer Taschenmesser im Umgang mit Homeassistant entwickelt. Seit kurzem ist auch das zugehörige Add-On offiziell im Hass.io Repository vorhanden. Dieses Add-On übernimmt mit einem Wizard die initiale Konfiguration des ESP32 und muss dann lediglich um die <a href="https://esphome.io/components/sensor/xiaomi_ble.html#lywsd03mmc"  target="_blank" rel="noreferrer">folgenden Zeilen</a> ergänzt werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">sensor</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">xiaomi_lywsd03mmc</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">mac_address</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;A4:C1:38:B1:CD:7F&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">bindkey</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;eef418daf699a0c188f3bfd17e4565d9&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">temperature</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;LYWSD03MMC Temperature&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">humidity</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;LYWSD03MMC Humidity&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">battery_level</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;LYWSD03MMC Battery Level&#34;</span></span></span></code></pre></div></div>
<p>Diese Werte dürfen natürlich nicht 1:1 übernommen werden und die MAC-Adresse, sowie der Bind-Key müssen durch die zuvor ermittelten Angaben ausgetauscht werden.</p>
<p>ESPHome exportiert anschließend eine vorkompilierte Binärdatei, die nun auf den ESP32 geflasht werden muss, bspw. mit dem bewährten <a href="https://github.com/esphome/esphome-flasher/releases"  target="_blank" rel="noreferrer">ESPHome Flasher</a>.</p>
<p>Anschließend muss der geflashte Mikrokontroller im ESPHome Add-On als Node hinzugefügt werden und die Werte für Temperatur, Luftfeuchtigkeit und den Batteriestand stehen in Homeassistant zur Verfügung.</p>

<h3 class="relative group">Methode 2: BT-MQTT-Gateway
    <div id="methode-2-bt-mqtt-gateway" class="anchor"></div>
    
</h3>

  
  
  
  



<div
  
    class="flex px-4 py-3 rounded-md shadow bg-primary-100 dark:bg-primary-900"
  
  >
  <span
    
      class="text-primary-400 pe-3 flex items-center"
    
    >
    <span class="relative block icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 128c17.67 0 32 14.33 32 32c0 17.67-14.33 32-32 32S224 177.7 224 160C224 142.3 238.3 128 256 128zM296 384h-80C202.8 384 192 373.3 192 360s10.75-24 24-24h16v-64H224c-13.25 0-24-10.75-24-24S210.8 224 224 224h32c13.25 0 24 10.75 24 24v88h16c13.25 0 24 10.75 24 24S309.3 384 296 384z"/></svg>
</span>
  </span>

  <span
    
      class="dark:text-neutral-300"
    
    >Die Methode ist nicht länger zu empfehlen und eine Integration über ESPHome ist klar zu bevorzugen: <a href="/posts/esphome-btle-hub/">ESPHome Bluetooth Low Energy Hub</a></span>
</div>

<p>Wer diesen Blog schon länger verfolgt, erinnert sich evtl. an meinen <a href="/posts/xiaomi-scale/" >Post zur Xiaomi Miscale</a>. Dort kam ein Bluetooth Gateway zum Einsatz, das die gelesen Werte mittels MQTT an Homeassistant sendet. Dieses Gateway läuft stabil und zuverlässig auf einem Raspberry Pi Zero und unterstützt auch das Auslesen des Thermometers. Bevor dieses jedoch eingebunden werden kann, muss noch eine Einstellung in der Custom Firmware des Thermometers vorgenommen werden.</p>

<h4 class="relative group">Advertising Type ändern
    <div id="advertising-type-ändern" class="anchor"></div>
    
</h4>
<p>Das BT-MQTT-Gateway erwartet die zugesandten Daten ausschließlich im <code>ATC1441</code>-Format (Stand: 17.01.2021) . Dieses Format muss im Teelink Flasher unter dem Menüpunkt <code>Advertising type:</code> ausgewählt werden und anschließend mit <code>Send Config</code> an das Gerät gesendet werden.</p>

<h4 class="relative group">Gateway Worker konfigurieren
    <div id="gateway-worker-konfigurieren" class="anchor"></div>
    
</h4>
<p>In der <code>config.yaml</code> von BT-MQTT-Gateway muss ein sogenannter <em>Worker</em> angelegt werden. Dieser funktioniert im Kern exakt wie bei der Xiaomi Personenwaage, hat aber eine ausführlichere Konfiguration:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">lywsd03mmc</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">args</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">devices</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">kueche</span><span class="p">:</span><span class="w"> </span><span class="l">a4:c1:38:b1:cd:7f</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">topic_prefix</span><span class="p">:</span><span class="w"> </span><span class="l">mithermometer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">passive</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c">#command_timeout: 30</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">scan_timeout</span><span class="p">:</span><span class="w"> </span><span class="m">30</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">update_interval</span><span class="p">:</span><span class="w"> </span><span class="m">120</span></span></span></code></pre></div></div>
<p><strong>ACHTUNG:</strong> Im Gegensatz zu ESPHome muss die MAC-Adresse <em>zwingend</em> in Kleinbuchstaben eingegeben werden. Ansonsten werden keine Werte ausgelesen und übermittelt.</p>

<h4 class="relative group">MQTT-Sensoren anlegen
    <div id="mqtt-sensoren-anlegen" class="anchor"></div>
    
</h4>
<p>Das Gateway funkt nun die Werte unter dem MQTT-Topic <code>mithermometer/kueche</code> über MQTT. Damit Homeassistant diese verwenden kann, müssen 3 Sensoren für Temperatur, Luftfeuchtigkeit und Batteriestand angelegt werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Mithermometer Kueche Temperature&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">state_topic</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;mithermometer/kueche&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">unit_of_measurement</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;°C&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ value_json.temperature }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">mdi:thermometer</span><span class="w">
</span></span></span><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Mithermometer Kueche Humidity&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">state_topic</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;mithermometer/kueche&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">unit_of_measurement</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;%&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ value_json.humidity }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">mdi:water-percent</span><span class="w">
</span></span></span><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Mithermometer Kueche Battery Level&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">state_topic</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;mithermometer/kueche&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">unit_of_measurement</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;%&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ value_json.battery }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">mdi:battery-80</span></span></span></code></pre></div></div>
<p>Voilà! Nun muss nur noch einmal Homeassistant neu gestartet werden und die Werte können fortan in der Lovelace-UI dargestellt werden.</p>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Aqara Fenster- und Türsensoren</title>
      <link>https://jbetzen.net/posts/aqara-windowsensor/</link>
      <pubDate>Fri, 28 Aug 2020 23:42:13 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/aqara-windowsensor/</guid>
      <description>Aqara bietet in ihrem Smarthome Sortiment preisgünstige Fenster- und Türensensoren an, die über Zigbee funken und den Conbee II in Homeassistant eingebunden werden können. Dieser Post enthält ein paar Beispiele, wie man die Sensordaten nutzen kann.</description>
      <content:encoded><![CDATA[ <p>Die Fenster- und Türkontaksensoren von Aqara lassen sich für kleines Geld erwerben. Sie funktionieren, wie die meisten Zigbee-Geräte, einwandfrei im Zusammenspiel mit der <a href="https://www.home-assistant.io/integrations/deconz/"  target="_blank" rel="noreferrer">Deconz-Integration</a>. Nach erfolgreicher Einbindung tauchen die Kontaktsensoren als Binärsensoren auf und überliefern zusätzlich noch den Wert des Batteriestands, sowie der Umgebungstemperatur. Wie man diese Sensoren sinnvoll einsetzen kann, zeige ich anhand von 2 Beispielen.</p>

<h2 class="relative group">Nutzungsbeispiele
    <div id="nutzungsbeispiele" class="anchor"></div>
    
</h2>

<h3 class="relative group">Beispiel 1: Benachrichtigung bei Regen wenn Fenster offen
    <div id="beispiel-1-benachrichtigung-bei-regen-wenn-fenster-offen" class="anchor"></div>
    
</h3>
<p>Möchte man eine Nachricht erhalten, wenn es zu regnen beginnt und noch Außenfenster geöffnet sind, kann man das folgendermaßen erreichen:</p>

<h4 class="relative group">Gruppe für Fenster anlegen
    <div id="gruppe-für-fenster-anlegen" class="anchor"></div>
    
</h4>
<p>Ist auch nur ein Fenster geöffnet ändert sich der Status der Gruppe auf <code>on</code>. Somit muss nicht jedes Fenster abgefragt werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">group</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">fenster</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Außenfenster</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entities</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">binary_sensor.fenster_kueche</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">binary_sensor.fenster_ballsaal</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">binary_sensor.fenster_schlafzimmer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">binary_sensor.fenster_wohnzimmer</span></span></span></code></pre></div></div>

<h4 class="relative group">Automation zum Senden der Pushnachricht
    <div id="automation-zum-senden-der-pushnachricht" class="anchor"></div>
    
</h4>
<p>Diese Automation setzt vorraus, dass ein Wettersensor vorhanden ist. Ich verwende in dem Beispiel <a href="https://www.home-assistant.io/integrations/openweathermap/"  target="_blank" rel="noreferrer">Openweathermaps</a>. Ändert sich der Sensor auf den state <code>rainy</code> wird geprüft ob noch ein Außenfenster geöffnet ist. Sollte dies der Fall sein, wird eine Pushnachricht auf das Smartphone gesendet, in der die noch geöffneten Fenster aufgelistet werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Warnung Regen Fenster offen</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">weather.owm</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">to</span><span class="p">:</span><span class="w">  </span><span class="s1">&#39;rainy&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">condition</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">group.fenster</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">state</span><span class="p">:</span><span class="w">  </span><span class="s1">&#39;on&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">notify.mobile_app_op7t</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Es regnet und es sind Fenster offen&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">message</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ states | selectattr(&#39;entity_id&#39;,&#39;in&#39;, state_attr(&#39;group.fenster&#39;,&#39;entity_id&#39;)) | selectattr(&#39;state&#39;,&#39;eq&#39;,&#39;on&#39;) | map(attribute=&#39;name&#39;) | join(&#39;, &#39;) }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;push_regenwarnung_fenster&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">channel</span><span class="p">:</span><span class="w"> </span><span class="l">Alarm</span></span></span></code></pre></div></div>

<h4 class="relative group">Pushnachricht automatisch entfernen, wenn Fenster geschlossen
    <div id="pushnachricht-automatisch-entfernen-wenn-fenster-geschlossen" class="anchor"></div>
    
</h4>
<p>Wer gerne faul ist und die Push-Nachricht nicht manuell vom Smartphone wischen möchte, kann das über eine Automation erledigen. Werden alle Fenster geschlossen während es regnet, verschwindet die Push-Nachricht automatisch vom Smartphone:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Warnung Regen Fenster offen dismiss</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">group.fenster</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;off&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">condition</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">weather.owm</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">state</span><span class="p">:</span><span class="w">  </span><span class="l">rainy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">notify.mobile_app_op7t</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">message</span><span class="p">:</span><span class="w"> </span><span class="l">clear_notification</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;push_regenwarnung_fenster&#34;</span></span></span></code></pre></div></div>

<h3 class="relative group">Beispiel: 2: Benachrichtigung Lüften vor dem Schlafen gehen
    <div id="beispiel-2-benachrichtigung-lüften-vor-dem-schlafen-gehen" class="anchor"></div>
    
</h3>
<p>Ich vergesse oftmals vor dem Schlafen gehen mein Schlafzimmer zu lüften und habe mir dafür eine Automation angelegt. Diese triggert abends um 20:00h und auch nur, wenn ich wirklich zu Hause bin und das Schlafzimmerfenster geschlossen ist:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Schlafzimmer lueften</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">initial_state</span><span class="p">:</span><span class="w"> </span><span class="kc">True</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">time</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">at</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;20:00:00&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">condition</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">and</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">binary_sensor.fenster_schlafzimmer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;off&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">person.ingeborg</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;home&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">notify.mobile_app_op7t</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Lüften?&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">message</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Das Fenster im Schlafzimmer ist geschlossen. Nochmal lüften vor dem luschern?&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;push_sz_lueften&#34;</span></span></span></code></pre></div></div>
<p>Auch in diesem zweiten Beispiel gilt als optionaler Obolus: Wer Faulheit liebt, kann noch eine zweite Automation anlegen, die die gesendete Push-Nachricht vom Smartphone entfernt, sobald das Fenster geöffnet wird:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Schlafzimmer lueften dismiss</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">initial_state</span><span class="p">:</span><span class="w"> </span><span class="kc">True</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">binary_sensor.fenster_schlafzimmer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;on&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">notify.mobile_app_op7t</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">message</span><span class="p">:</span><span class="w"> </span><span class="l">clear_notification</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;push_sz_lueften&#34;</span></span></span></code></pre></div></div>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Homeassistant und Octoprint</title>
      <link>https://jbetzen.net/posts/octoprint/</link>
      <pubDate>Wed, 15 Jul 2020 23:42:13 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/octoprint/</guid>
      <description>Die freie Software Octoprint erlaubt es 3D-Drucker zu steuern und kann zeitgleich über eine Integration in Homeassistant eingebunden werden. Wie man den aktuellen Druckstatus in einer Lovelace Card darstellen kann, wird in diesem Post erläutert.</description>
      <content:encoded><![CDATA[ <p><a href="https://octoprint.org/"  target="_blank" rel="noreferrer">Octoprint</a> ist eine freie open-source Software, die es Laien ermöglicht in einer webbasierten Oberfläche 3D-Drucker anzusteuern und zu überwachen. Sie stellt eine vielseitige API zum monitoren des 3D-Druckers bereit, die einfach und unkompliziert in Homeassistant mit der offiziellen <a href="https://www.home-assistant.io/integrations/octoprint/"  target="_blank" rel="noreferrer">Octoprint Integration</a> genutzt werden kann.</p>

<h2 class="relative group">Heimisches Setup
    <div id="heimisches-setup" class="anchor"></div>
    
</h2>
<ul>
<li>Mein Raspberry Pi mit Octoprint hängt an einer Gosund SP111 Steckdose, die mit Tasmota geflasht wurde und in Homeassistant eingebunden ist. Diese hat den Namen <code>switch.strom_octoprint</code>. Ist diese Steckdose ausgeschaltet ist logischerweise auch Octoprint nicht verfügbar. Ziel war es Octoprint sauber auf dem Pi herunterzufahren, bevor er vom Strom getrennt wird. Dafür wird ein REST-Command und ein Template-Switch benötigt.</li>
<li>Mein Anycubic 3D-Drucker bezieht ebenfalls über eine Gosund SP111 seinen Strom und ist in Homeassistant über den Switch <code>switch.strom_anycubic</code> erreichbar.</li>
</ul>

<h2 class="relative group">Octoprint API-Key generieren
    <div id="octoprint-api-key-generieren" class="anchor"></div>
    
</h2>
<p>Zur erfolgreichen Einbindung der Octoprint Integration muss ein Eintrag in der <code>configuration.yaml</code> erfolgen, die anschließend Sensoren zum Drucker und weitere Binary Sensoren bereitstellt.
Im ersten Schritt muss jedoch ein <em>API-Key</em> in der Octoprint Weboberfläche erstellt werden. Dazu muss im Browser zum Eintrag <code>Einstellungen &gt; API</code> navigiert werden und der API-Key in die Zwischenablage kopiert werden.</p>

<h2 class="relative group">Homeassistant konfigurieren
    <div id="homeassistant-konfigurieren" class="anchor"></div>
    
</h2>
<p>In der <code>configuration.yaml</code> muss zwingend die IP-Adresse des Octoprint Servers angegeben werden. Diese sollte idealerweise statisch sein und sich nicht bei jedem Neustart ändern:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">octoprint</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">host</span><span class="p">:</span><span class="w"> </span><span class="l">IP-ADDRESSE</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">api_key</span><span class="p">:</span><span class="w"> </span><span class="l">API-KEY</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Anycubic</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">number_of_tools</span><span class="p">:</span><span class="w"> </span><span class="m">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">bed</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span></span></span></code></pre></div></div>
<p>Je nach Druckermodell können mehrere Druckdüsen (Nozzles) vorhanden sein. Die Anzahl der Düsen sollte in der Konfiguration generell gesetzt werden, da sonst kein Sensor zur Überwachung der Temperatur bereitgestellt wird. Ebenso verhält es sich mit dem Eintrag <code>bed: true</code>. Wenn ein beheiztes Druckbett vorhanden ist, sollte also der boolsche Wert auf <code>true</code> gesetzt werden.</p>

<h3 class="relative group">Rest Command erstellen
    <div id="rest-command-erstellen" class="anchor"></div>
    
</h3>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">octopi_shutdown</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">url</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;http://OCTOPRINT-IP/api/system/commands/core/shutdown&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">method</span><span class="p">:</span><span class="w"> </span><span class="l">POST</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">headers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">content-type</span><span class="p">:</span><span class="w"> </span><span class="l">application/json</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">X-Api-Key</span><span class="p">:</span><span class="w"> </span>!<span class="l">secret octoprint_api_key</span></span></span></code></pre></div></div>
<p>In der <code>secrets.yaml</code> sollte ein Eintrag für den Octoprint-API-Key angelegt werden. Die IP von der Octoprint Instanz muss in dem API-Aufruf entsprechend angepasst werden.</p>

<h3 class="relative group">Zwei Template-Switches anlegen
    <div id="zwei-template-switches-anlegen" class="anchor"></div>
    
</h3>
<p>Der erste Template-Switch, schaut ob die Steckdose des Raspberry Pis mit Octoprint bereits eingeschaltet ist. Wird der Switch auf <code>off</code> geschaltet, wird der Pi über die Octoprint API heruntergefahren. Nach weiteren 45 Sekunden schaltet sich die Steckdose auf <code>aus</code>. Der Switch erscheint in Homeassistant unter dem Name <code>switch.octopi_shutdown</code>.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">template</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">switches</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">octopi_shutdown</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">friendly_name</span><span class="p">:</span><span class="w"> </span><span class="l">Octopi Shutdown</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ is_state(&#39;switch.strom_octoprint&#39;, &#39;on&#39;) }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">turn_on</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">switch.turn_on</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">switch.strom_octoprint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">turn_off</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">rest_command.octopi_shutdown</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">delay</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;00:00:45&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">switch.turn_off</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">switch.strom_octoprint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon_template</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% if is_state(&#39;switch.strom_octoprint&#39;, &#39;on&#39;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          mdi:power-plug
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% else %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          mdi:power-plug-off
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% endif %}</span></span></span></code></pre></div></div>
<p>Ein weiterer Template Switch für das Gesamtsystem 3D-Drucker + Raspberry Pi wird zusätzlich angelegt. Dieser kann sowohl 3D-Drucker, als auch den Pi mit einem Klick an und ausschalten:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">template</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">switches</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">3dprinter_setup</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">friendly_name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;3D Printer Setup&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ is_state(&#39;switch.strom_octoprint&#39;, &#39;on&#39;) and is_state(&#39;switch.strom_anycubic&#39;, &#39;on&#39;) }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">turn_on</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">switch.turn_on</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">switch.strom_octoprint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">switch.turn_on</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">switch.strom_anycubic</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">turn_off</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">switch.turn_off</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">switch.strom_anycubic</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">rest_command.octopi_shutdown</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">delay</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;00:00:45&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">switch.turn_off</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">switch.strom_octoprint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon_template</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% if is_state(&#39;switch.strom_octoprint&#39;, &#39;on&#39;) and is_state(&#39;switch.strom_anycubic&#39;, &#39;on&#39;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          mdi:power-plug
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% else %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          mdi:power-plug-off
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% endif %}</span></span></span></code></pre></div></div>
<p>Dieser Switch erscheint in Homeassistant unter dem Name <code>switch.3dprinter_setup</code>.</p>

<h2 class="relative group">Lovelace Card: Picture-Elements
    <div id="lovelace-card-picture-elements" class="anchor"></div>
    
</h2>
<p>Was nützen einem Sensorwerte, wenn sie nicht auch anschaulich dargestellt werden. Ich nutze dafür eine <a href="https://www.home-assistant.io/lovelace/picture-elements/"  target="_blank" rel="noreferrer">Picture Elements Card</a>, die folgendermaßen aussieht:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/octoprint/octoprint-card.png"
          alt="Lovelace Card für 3D-Drucker-Setup"
        />
  
  
  </figure>

<h3 class="relative group">Bildvorlage für Picture-Elements Card
    <div id="bildvorlage-für-picture-elements-card" class="anchor"></div>
    
</h3>
<p>Entsprechend meines Druckermodells (Anycubic i3 Mega), habe ich eine Bilddatei erstellt und diese in der Lovelace UI eingebunden. Dieses Bild kann mit einem Rechtsklick gespeichert und in Homeassistant <code>/config/www/</code>-Ordner platziert werden. In meinem Beispiel lautet der Pfad zum Bild <code>/config/www/entitypictures/octoprint-ui-template.png</code>.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/octoprint/octoprint-ui-template.png"
          alt="Template File für 3D-Drucker-Setup"
        />
  
  
  </figure>

<h3 class="relative group">Custom Cards aus HACS installieren
    <div id="custom-cards-aus-hacs-installieren" class="anchor"></div>
    
</h3>
<p>Zur Darstellung der Lovelace Card verwende ich drei Custom Cards, die einfach über HACS installiert werden können:</p>
<ul>
<li><a href="https://github.com/custom-cards/bar-card"  target="_blank" rel="noreferrer">custom:bar-card</a>, zur Darstellung der Fortschrittsbalken</li>
<li><a href="https://github.com/custom-cards/button-card"  target="_blank" rel="noreferrer">custom:button-card</a>, zur Darstellung der unteren 4 Icons</li>
<li><a href="https://github.com/ofekashery/vertical-stack-in-card"  target="_blank" rel="noreferrer">custom:vertical-stack-in-card</a>, zur Anordnung der Karten übereinander, ohne sichtbare Abgrenzung zueinander</li>
</ul>

<h3 class="relative group">Code für Lovelace
    <div id="code-für-lovelace" class="anchor"></div>
    
</h3>
<p>Dargestellt werden Informationen zum Druckfortschritt, der Bett- und Düsentemperatur, zum Druckstatus, zur Fehlerindikation und zur verbleibenden Druckzeit. Darüber hinaus gibt es einen Service Button zum Ein- und Ausschalten von Drucker und Pi.</p>
<p>Die gesamte Config der Card sieht wie folgend aus:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">/local/entitypictures/octoprint-ui-template.png</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">picture-elements</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">elements</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">conditional</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">switch.3dprinter_setup</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;off&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">elements</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">service-button</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">Turn On</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">switch.turn_on</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">service_data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">switch.3dprinter_setup</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">style</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">left</span><span class="p">:</span><span class="w"> </span><span class="m">86</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">top</span><span class="p">:</span><span class="w"> </span><span class="m">14</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">width</span><span class="p">:</span><span class="w"> </span><span class="m">20</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">conditional</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">switch.3dprinter_setup</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;on&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">elements</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">service-button</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">Turn Off</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">switch.turn_off</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">service_data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">switch.3dprinter_setup</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">style</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">left</span><span class="p">:</span><span class="w"> </span><span class="m">86</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">top</span><span class="p">:</span><span class="w"> </span><span class="m">14</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">width</span><span class="p">:</span><span class="w"> </span><span class="m">20</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">state-icon</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">switch.octopi_shutdown</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">style</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">top</span><span class="p">:</span><span class="w"> </span><span class="m">14</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">left</span><span class="p">:</span><span class="w"> </span><span class="m">68</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">tap_action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">toggle</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">conditional</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">switch.strom_anycubic</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;on&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">elements</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">state-icon</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">binary_sensor.anycubic_printing_error</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">style</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">top</span><span class="p">:</span><span class="w"> </span><span class="m">22</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">left</span><span class="p">:</span><span class="w"> </span><span class="m">14</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">state-icon</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">switch.strom_anycubic</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;mdi:power-plug&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">style</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">top</span><span class="p">:</span><span class="w"> </span><span class="m">22</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">left</span><span class="p">:</span><span class="w"> </span><span class="m">31</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">tap_action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">toggle</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">conditional</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">switch.strom_anycubic</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;on&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">elements</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">state-label</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.anycubic_current_state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">style</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">top</span><span class="p">:</span><span class="w"> </span><span class="m">55</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">left</span><span class="p">:</span><span class="w"> </span><span class="m">23</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">animation</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#90ee90&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.anycubic_job_percentage</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity_row</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">height</span><span class="p">:</span><span class="w"> </span><span class="l">36px</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Progress</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">positions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;off&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">indicator</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;off&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">minmax</span><span class="p">:</span><span class="w"> </span><span class="l">inside</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">outside</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">speed</span><span class="p">:</span><span class="w"> </span><span class="m">1000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">style</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">left</span><span class="p">:</span><span class="w"> </span><span class="m">72</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">top</span><span class="p">:</span><span class="w"> </span><span class="m">40</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">width</span><span class="p">:</span><span class="w"> </span><span class="m">48</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;custom:bar-card&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">animation</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.anycubic_actual_bed_temp</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity_row</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">height</span><span class="p">:</span><span class="w"> </span><span class="l">36px</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">max</span><span class="p">:</span><span class="w"> </span><span class="m">60</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Bed</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">positions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;off&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">indicator</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;off&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">minmax</span><span class="p">:</span><span class="w"> </span><span class="l">inside</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">outside</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">severity</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#f08080&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">from</span><span class="p">:</span><span class="w"> </span><span class="m">0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="m">40</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#ff9966&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">from</span><span class="p">:</span><span class="w"> </span><span class="m">40</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="m">55</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#90ee90&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">from</span><span class="p">:</span><span class="w"> </span><span class="m">55</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="m">65</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">style</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">left</span><span class="p">:</span><span class="w"> </span><span class="m">72</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">top</span><span class="p">:</span><span class="w"> </span><span class="m">62</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">width</span><span class="p">:</span><span class="w"> </span><span class="m">48</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;custom:bar-card&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">animation</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.anycubic_actual_tool0_temp</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entity_row</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">height</span><span class="p">:</span><span class="w"> </span><span class="l">36px</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">max</span><span class="p">:</span><span class="w"> </span><span class="m">200</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Nozzle</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">positions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;off&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">indicator</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;off&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">minmax</span><span class="p">:</span><span class="w"> </span><span class="l">inside</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">outside</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">severity</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#f08080&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">from</span><span class="p">:</span><span class="w"> </span><span class="m">0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="m">120</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#ff9966&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">from</span><span class="p">:</span><span class="w"> </span><span class="m">120</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="m">180</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#90ee90&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">from</span><span class="p">:</span><span class="w"> </span><span class="m">180</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="m">220</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">style</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">left</span><span class="p">:</span><span class="w"> </span><span class="m">72</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">top</span><span class="p">:</span><span class="w"> </span><span class="m">84</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">width</span><span class="p">:</span><span class="w"> </span><span class="m">48</span><span class="l">%</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;custom:bar-card&#39;</span></span></span></code></pre></div></div>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Bose Soundtouch Multi-Room Audio</title>
      <link>https://jbetzen.net/posts/soundtouch-multi-room-audio/</link>
      <pubDate>Sat, 11 Apr 2020 23:42:13 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/soundtouch-multi-room-audio/</guid>
      <description>Seit Homeassistant 0.107 erhält die Bose Soundtouch Integration die Fähigkeit für Multi-Room-Audio und das Zusammenschließen einzelner Lautsprecher zu eine Zone. Wie man eine praktische Lovelace Card mit dem Custom Mini Media Player erstellt wird in diesem Post gezeigt.</description>
      <content:encoded><![CDATA[ <p>Mit dem Release 0.107 erhielt die <a href="https://www.home-assistant.io/integrations/soundtouch/"  target="_blank" rel="noreferrer">Bose Soundtouch Integration</a> nach langer Zeit ein nützliches Feature für die heimliche Beschallung über mehrere Räume. Das Soundtouch System von Bose kann auf einfachem Weg mehrere Lautsprecher zu einem Verbund zusammenschließen und Audio synchron ausgeben. Das funktionierte in Homeassistant auch seit geraumer Zeit, jedoch gab die State Machine keinerlei Infos/Attribute preis, ob aktuell ein Lautsprecherverbund aktiv und welcher Lautsprecher der Master des Verbunds war. Diese fehlenden Attribute wurden im Release 0.107 ergänzt und nach einer anfänglich fehlerhaften Implementierung mit dem Release 0.108 komplettiert. Existiert ein Zonenverbund steht nun unter den Soundtouch Media Playern das Attribut <code>is_master: true/false</code> zur Verfügung.</p>
<p>Zeitgleich zu dem Release erfuhr auch die grandiose Custom Lovelace Card <a href="https://github.com/kalkih/mini-media-player"  target="_blank" rel="noreferrer">Mini-Media-Player</a> ein Update, um einfach einen Verbund (Zone) von Lautsprechern erstellen und auflösen zu können. Diese Custom Card kann einfach über HACS in Homeassistant installiert werden. Für die Nutzung von Multi-Room-Audio in der Lovelace Card gibt es einen <a href="https://github.com/kalkih/mini-media-player#speaker-group-management"  target="_blank" rel="noreferrer">eigenen Abschnitt</a> in der README.</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/soundtouch-multi-room-audio/soundtouch-lovelace-card.png"
          alt="Speaker Group Management in Lovelace Card"
        />
  
  
  </figure>

<h2 class="relative group">Sensor zur Ausgabe des aktuellen Masters
    <div id="sensor-zur-ausgabe-des-aktuellen-masters" class="anchor"></div>
    
</h2>
<p>Wer in seiner Homeassistant UI nun einen Sensor haben möchte, der angibt welcher Lautsprecher gerade der Master ist oder ob überhaupt eine Zone aus mehreren Lautsprechern besteht, kann das auf folgende Weise mit einem Template Sensor und einer zugehörigen Automation, die diesen Sensor updated, lösen. In dem folgenden Beispiel nutze ich meine drei <a href="https://www.bose.de/de_de/products/speakers/smart_home/soundtouch-10-wireless-system.html#v=soundtouch_10_black_eu_gb_ie"  target="_blank" rel="noreferrer">Soundtouch 10</a> Lautsprecher und einen <a href="https://www.bose.de/de_de/products/speakers/smart_home/soundtouch-adapter.html"  target="_blank" rel="noreferrer">Wireless Link Adapter</a>, die mit dem Namensschema <code>media_player.soundtouch_RAUMNAME</code> benannt sind.</p>

<h3 class="relative group">Template Sensor erstellen
    <div id="template-sensor-erstellen" class="anchor"></div>
    
</h3>
<p>Der <a href="https://community.home-assistant.io/t/template-sensor-to-find-master-in-multi-room-audio-setup/179467"  target="_blank" rel="noreferrer">Template Sensor</a> iteriert über alle Lautsprecher, prüft ob eine Zone existiert und sucht anschließend nach dem Attribut <code>is_master</code>. Anschließend gibt er den Namen des Lautsprechers aus. Existiert keine Zone gibt er <code>No Master</code> aus.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">template</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">sensors</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">soundtouch_master</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% set master = states.media_player | selectattr(&#39;attributes.soundtouch_zone&#39;, &#39;defined&#39;) | selectattr(&#39;attributes.soundtouch_zone.is_master&#39;,&#39;eq&#39;,True) | map(attribute=&#39;name&#39;) | list | first %}
</span></span></span><span class="line"><span class="cl"><span class="sd">        {{ master if master else &#34;No Master&#34; }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">friendly_name</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Multiroom Master&#39;</span></span></span></code></pre></div></div>

<h3 class="relative group">Update des Template Sensors
    <div id="update-des-template-sensors" class="anchor"></div>
    
</h3>
<p>In der nachfolgenden Automation müssen die Namen der Lautsprecher entsprechend den von euch vergebenen angepasst werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Soundtouch update master sensors</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">initial_state</span><span class="p">:</span><span class="w"> </span><span class="kc">True</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">media_player.soundtouch_kuche</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">media_player.soundtouch_room2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">media_player.soundtouch_schlafzimmer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">media_player.soundtouch_wohnzimmer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">homeassistant.update_entity</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.soundtouch_master</span></span></span></code></pre></div></div>

<h2 class="relative group">Ergebnis
    <div id="ergebnis" class="anchor"></div>
    
</h2>
<p>Der erstellte Sensor mit dem Namen <code>sensor.soundtouch_master</code> kann nun in jeder Lovelace Card eingebunden werden:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/soundtouch-multi-room-audio/soundtouch-result.png"
          alt="Lovelace Card zum Managen mehrerer Speaker"
        />
  
  
  </figure>

<h2 class="relative group">Weiterführendes
    <div id="weiterführendes" class="anchor"></div>
    
</h2>
<p>Das Multi-Room-Audio Feature der Bose Soundtouch Boxen habe ich mit meinem Sony Plattenspieler mit Bluetooth-Konnektivität genutzt, um Vinyl im gesamten Haus abzuspielen. Der Post dazu: <a href="/posts/sony-pslx310bt/">Sony PS-LX310BT: Plattenspieler mit Bose Soundtouch und Homeassistant nutzen</a></p>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Room Based Presence mit Motion Sensoren</title>
      <link>https://jbetzen.net/posts/room-based-presence/</link>
      <pubDate>Mon, 30 Mar 2020 23:42:13 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/room-based-presence/</guid>
      <description>Wer im Eigenheim Bewegungssensoren installiert hat, kann schnell und einfach einen Sensor erstellen, der aufzeigt in welchem Raum die letzte Bewegung registriert wurde. Wie man diese Info sinnvoll nutzen kann, wird in diesem Post erläutert.</description>
      <content:encoded><![CDATA[ 
  
  
  
  



<div
  
    class="flex px-4 py-3 rounded-md shadow bg-primary-100 dark:bg-primary-900"
  
  >
  <span
    
      class="text-primary-400 pe-3 flex items-center"
    
    >
    <span class="relative block icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 128c17.67 0 32 14.33 32 32c0 17.67-14.33 32-32 32S224 177.7 224 160C224 142.3 238.3 128 256 128zM296 384h-80C202.8 384 192 373.3 192 360s10.75-24 24-24h16v-64H224c-13.25 0-24-10.75-24-24S210.8 224 224 224h32c13.25 0 24 10.75 24 24v88h16c13.25 0 24 10.75 24 24S309.3 384 296 384z"/></svg>
</span>
  </span>

  <span
    
      class="dark:text-neutral-300"
    
    >Der neue Post <a href="/posts/last-motion-sensor/">Last Motion Sensor</a> enthält eine verbesserte Methode für den Last Motion Sensor, der ohne die Custom Component <a href="https://github.com/snarky-snark/home-assistant-variables"  target="_blank" rel="noreferrer">home-assistant-variables</a> funktioniert.</span>
</div>

<p>In jedem meiner Räume befindet sich ein <a href="https://www2.meethue.com/de-de/p/hue-bewegungssensor/8718696743171"  target="_blank" rel="noreferrer">Hue Motion</a> Bewegungsmelder aus dem Hause Philips, die ich in Homeassistant über das Deconz Addon eingebunden habe. Diese triggern - neben dem obligatorischem Einschalten von Lichtern - in meinem Alltag diverse Automationen, z.B:</p>
<ul>
<li>Automatisch die Tagesschau auf dem Bose Lautsprecher anmachen, wenn ich wochentags das Bett verlassen habe und in die Küche laufe</li>
<li>Automatisch die Rollos hochfahren, wenn ich aufgestanden bin</li>
<li>Automatisch den Wecker ausschalten, wenn ich wochentags das Schlafzimmer verlassen habe</li>
</ul>
<p>Da ich alleine in meiner Wohnung lebe, eignen sich die Bewegungsmelder auch hervorragend, um Homeassistant mitzuteilen in welchem Raum man sich gerade befindet. Dies lässt sich hervorragend nutzen, um bspw. Lichter in Räumen auszuschalten in denen man sich gerade nicht aufhält oder automatisch den Fernseher zu pausieren, wenn man den Raum verlässt. Wie man einen solchen <code>Last Motion Sensor</code> erstellt, erkläre ich im Folgenden.</p>

<h2 class="relative group">Die Theorie des Vorgehens
    <div id="die-theorie-des-vorgehens" class="anchor"></div>
    
</h2>
<p>Wird ein Bewegungssensor getriggert (state = on), muss Homeassistant schauen welcher es war und anschließend den Namen des Raumes in eine Variable schreiben. Anschließend kann ein optionaler <em>Template Sensor</em> erstellt werden, der diese Variable ausließt und ein passendes Icon zu jedem Raum zuordnet.</p>

<h2 class="relative group">Praktische Umsetzung
    <div id="praktische-umsetzung" class="anchor"></div>
    
</h2>
<p>Variablen sind kein natürliches Konzept von Homeassistant und müssen über eine <em>Custom Component</em> namens <a href="https://github.com/snarky-snark/home-assistant-variables"  target="_blank" rel="noreferrer">home-assistant-variables</a> installiert werden.</p>

<h3 class="relative group">Variable anlegen
    <div id="variable-anlegen" class="anchor"></div>
    
</h3>
<p>Es wird eine <a href="https://github.com/snarky-snark/home-assistant-variables#configuration"  target="_blank" rel="noreferrer">Variable konfiguriert</a>. In meinem Fall habe ich sie <code>last_motion</code> genannt:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">last_motion</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">restore</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">mdi:map-marker</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">friendly_name</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Last Motion&#39;</span></span></span></code></pre></div></div>

<h3 class="relative group">Automation: Letzter Aufenthaltsraum
    <div id="automation-letzter-aufenthaltsraum" class="anchor"></div>
    
</h3>
<p>Als Trigger dienen die Bewegungssensoren, die in Homeassistant als <em>Binary Sensors</em> erscheinen:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Set Last Motion Variable</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">initial_state</span><span class="p">:</span><span class="w"> </span><span class="kc">True</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">binary_sensor.hue_motion_flur</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">binary_sensor.hue_motion_kueche</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">binary_sensor.hue_motion_room2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">binary_sensor.hue_motion_schlafzimmer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">binary_sensor.hue_motion_wohnzimmer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">binary_sensor.aqara_motion_bad</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">binary_sensor.aqara_motion_klo</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;on&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">var.set</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data_template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="l">var.last_motion</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% if trigger.entity_id == &#34;binary_sensor.hue_motion_flur&#34; %} Flur
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% elif trigger.entity_id == &#34;binary_sensor.hue_motion_kueche&#34; %} Küche
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% elif trigger.entity_id == &#34;binary_sensor.hue_motion_room2&#34; %} Room2
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% elif trigger.entity_id == &#34;binary_sensor.hue_motion_schlafzimmer&#34; %} Schlafzimmer
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% elif trigger.entity_id == &#34;binary_sensor.hue_motion_wohnzimmer&#34; %} Wohnzimmer
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% elif trigger.entity_id == &#34;binary_sensor.aqara_motion_klo&#34; %} Klo
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% elif trigger.entity_id == &#34;binary_sensor.aqara_motion_bad&#34; %} Bad
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% endif %}</span></span></span></code></pre></div></div>
<p>Anschließend steht eine Variable mit dem Namen <code>var.last_motion</code> zur Verfügung. Der <em>State</em> dieser Variable kann - analog zu einem Sensor - ausgelesen und in Automationen genutzt werden.</p>

<h3 class="relative group">Template Sensor mit Icon für jeden Raum
    <div id="template-sensor-mit-icon-für-jeden-raum" class="anchor"></div>
    
</h3>
<p>Optional kann zusätzlich noch ein Template Sensor erstellt werden, der jedem State/Raum ein passendes Icon zuweist:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">template</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">sensors</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">last_motion</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">friendly_name</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Wo bin ich?&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ states.var.last_motion.state }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon_template</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% if is_state(&#39;var.last_motion&#39;, &#39;Küche&#39;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          mdi:food-variant
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% elif is_state(&#39;var.last_motion&#39;, &#39;Wohnzimmer&#39;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          mdi:sofa
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% elif is_state(&#39;var.last_motion&#39;, &#39;Flur&#39;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          mdi:cube-unfolded
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% elif is_state(&#39;var.last_motion&#39;, &#39;Room2&#39;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          mdi:guitar-electric
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% elif is_state(&#39;var.last_motion&#39;, &#39;Schlafzimmer&#39;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          mdi:bed
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% elif is_state(&#39;var.last_motion&#39;, &#39;Bad&#39;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          mdi:shower
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% elif is_state(&#39;var.last_motion&#39;, &#39;Klo&#39;) %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          mdi:toilet
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% else %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          mdi:account-question
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% endif %}</span></span></span></code></pre></div></div>

<h2 class="relative group">Licht im Raum aufblinken, wenn Smartphone geladen
    <div id="licht-im-raum-aufblinken-wenn-smartphone-geladen" class="anchor"></div>
    
</h2>
<p>Nutzt man die offizielle <a href="https://companion.home-assistant.io/"  target="_blank" rel="noreferrer">Homeassistant App</a>, kann diese Auskunft über den Batteriestand des Telefons und auch darüber, ob das Smartphone gerade geladen wird, ausgeben. Die folgende Automation prüft, ob das Telefon sich am Lader befindet und lässt ein Licht im aktuellen Raum kurz aufblinken, wenn der Akkustand über 90% erreicht hat:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Flash Light when Smartphone fully charged</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">initial_state</span><span class="p">:</span><span class="w"> </span><span class="kc">True</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">numeric_state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.mizar_battery_level</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">above</span><span class="p">:</span><span class="w"> </span><span class="m">90</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">condition</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">time</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">after</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;09:00:00&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">before</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;22:00:00&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">person.jonas</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;home&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">light.turn_on</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data_template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% if is_state(&#39;var.last_motion&#39;,&#39;Schlafzimmer&#39;) %} light.schlafzimmer_kommode
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% elif is_state(&#39;var.last_motion&#39;,&#39;Wohnzimmer&#39;) %} light.wohnzimmer_regal
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% elif is_state(&#39;var.last_motion&#39;,&#39;Room2&#39;) %} light.room2_decke
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% elif is_state(&#39;var.last_motion&#39;,&#39;Küche&#39;) %} light.kuche_kuhlschrank
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% endif %}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">flash</span><span class="p">:</span><span class="w"> </span><span class="l">short</span></span></span></code></pre></div></div>
<p>Ein weiteres Beispiel habe ich in dem separaten Post <a href="/posts/autopause-mediaplayer/">Automatisch pausierender Media Player</a> aufgeführt. Dort wird erläutert, wie man einen beliebigen Media Player pausiert, wenn man den Raum verlässt und die Wiedergabe automatisch fortsetzt, sobald man den Raum erneut betritt.</p>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Homeassistant, FritzBox und Anrufbenachrichtigung per Push-Nachricht</title>
      <link>https://jbetzen.net/posts/fritzbox-callmon/</link>
      <pubDate>Fri, 28 Feb 2020 23:42:12 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/fritzbox-callmon/</guid>
      <description>Die Fritzboxen von AVM lassen sich einfach in Homeassistant einbinden und stellen einen Call Monitor (Callmon) bereit, der über ein- und ausgehende Anrufe informiert. Wie man diese Daten bei Abwesenheit vom Heim per Push-Nachricht senden kann wird in diesem Post erläutert.</description>
      <content:encoded><![CDATA[ <p>FritzBox-Router aus dem Hause AVM sind speziell in Deutschland sehr beliebt und aus Erfahrung eine gute Wahl. Neben zahlreichen Funktionen wie einem NAS, Netzwerkstreaming, Anrufbeantworter, etc. stellt eine wichtige Kernfunktion die Telefonie dar. Diese Anrufinformationen können mit der offiziellen <a href="https://www.home-assistant.io/integrations/fritzbox_callmonitor/"  target="_blank" rel="noreferrer">FritzBox Callmonitor</a> Integration in Homeassistant integriert und entsprechend automatisiert werden. Somit ist Homeassistant fähig zu erkennen, ob sich das Telefon gerade im Leerlauf, im Telefonat oder im Zustand des Klingelns oder Wählens befindet.</p>
<p>Im Folgenden möchte ich erläutern, wie man sich automatisch eine Push-Nachricht mit einem beliebigen Notify-Service senden lassen kann, wenn die Fritzbox einen Anruf empfangen hat, der jedoch nicht entgegen genommen wurde, bspw. wenn man außer Haus ist. Hierzu wird vorausgesetzt, dass die Fritzbox bereits erfolgreich in Homeassistant integriert wurde.</p>

<h2 class="relative group">Theorie zum Callmonitor
    <div id="theorie-zum-callmonitor" class="anchor"></div>
    
</h2>
<p>Nach der Integration der Fritzbox steht eine Sensor zur Verfügung, der die folgenden states ausgibt:</p>
<ul>
<li><code>idle</code>: Die Fritzbox befindet sich im Leerlauf. Es wird nicht telefoniert, gewählt oder ein Telefonat geführt.</li>
<li><code>ringing</code>: Die Fritzbox klingelt. Ein Anrufer wartet auf die Abnahme des Hörers.</li>
<li><code>talking</code>: Ein aktives Telefonat wird geführt.</li>
<li><code>dialing</code>: Ein Telefonat wird aufgebaut und die ausgehende Nummer gewählt.</li>
</ul>
<p>Der Punkt <code>dialing</code> kann für das Vorhaben des Erhalts einer Push-Nachricht vernachlässigt werden, da dies nicht der Fall ist, wenn man sich außer Haus befindet.</p>
<p>Wer denkt, dass nun der einfachste Weg wäre eine Automation zu schreiben, die den State des Callmonitors überwacht und einfach die Daten des Anrufers (Name, Nummer, Uhrzeit, Datum) per Push-Nachricht sendet, ist leider auf dem Holzweg. Diese Daten stehen nämlich nur zur Verfügung, wenn der Callmonitor den State <code>ringing</code> hat, <em>nicht</em> aber bei <code>idle</code>.
Es muss also ein Zwischenschritt erfolgen, der die Anruferdaten zwischenspeichert und wieder zur Verfügung stellt, wenn der State des Callmonitors von <code>ringing</code> auf <code>idle</code> wechselt. Hierfür greife ich auf die Custom Component mit dem Namen <a href="https://github.com/snarky-snark/home-assistant-variables"  target="_blank" rel="noreferrer">home-assistant-variables</a> zurück</p>

<h2 class="relative group">Variablen als Zwischenspeicher einrichten
    <div id="variablen-als-zwischenspeicher-einrichten" class="anchor"></div>
    
</h2>
<p>Nachdem die neue Variablen-Component aus HACS installiert wurde, müssen folgende Einträge in der <code>configuration.yaml</code> erfolgen. Diese speichern die relevanten Informationen des Anrufers:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">var</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">callmon_name</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restore</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">mdi:phone-classic</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">friendly_name</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Anrufername&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ states.sensor.callmon.attributes.from_name }}&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">callmon_number</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restore</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">mdi:card-account-phone</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">friendly_name</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Anrufernummer&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ states.sensor.callmon.attributes.from }}&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">callmon_time</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restore</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">mdi:clock-time-three-outline</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">friendly_name</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Anrufzeit&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ now().strftime(&#34;%H:%M&#34;) }}&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">callmon_date</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restore</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">mdi:calendar-today</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">friendly_name</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Anrufdatum&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ now().strftime(&#34;%d.%m.%Y&#34;) }}&#39;</span></span></span></code></pre></div></div>

<h2 class="relative group">Automation, um Variblen zu füllen
    <div id="automation-um-variblen-zu-füllen" class="anchor"></div>
    
</h2>
<p>Diese Automation aktualisiert die zuvor definierten <code>value_templates</code> der Variablen und speicher die relevanten Informationen über den Verpassten Anruf:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">festnetz_set_caller_info_variable</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">initial_state</span><span class="p">:</span><span class="w"> </span><span class="kc">True</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.callmon</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;ringing&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">var.update</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entity_id</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="l">var.callmon_name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="l">var.callmon_number</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="l">var.callmon_time</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="l">var.callmon_date</span></span></span></code></pre></div></div>

<h2 class="relative group">Automation für Push-Benachrichtigung
    <div id="automation-für-push-benachrichtigung" class="anchor"></div>
    
</h2>
<p>Jetzt muss nur noch eine Automation erstellt werden, die schaut wann der Callmonitor von <code>ringing</code> auf <code>idle</code> wechselt, anschließend die Anruferinformationen aus den Variablen ausliest und diese per Push-Nachricht sendet. Als Beispiel nehme ich mein Smartphone auf dem die offizielle Homeassitant Android App läuft und die über die Mobile Integration eingebunden ist. Es kann jedoch jeder beliebige Notification Service, wie beispielweise Slack, Jabber oder Matrix verwendet werden.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Festnetzbenachrichtigung Hass App</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">initial_state</span><span class="p">:</span><span class="w"> </span><span class="kc">True</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.callmon</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">state</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">from</span><span class="p">:</span><span class="w"> </span><span class="l">ringing</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="l">idle</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">notify.mobile_app_mizar</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Festnetzanruf 📞&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">message</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {{ states.var.callmon_name.state }} ({{ states.var.callmon_number.state }})
</span></span></span><span class="line"><span class="cl"><span class="sd">          hat am {{ states.var.callmon_date.state }} um {{ states.var.callmon_time.state }}h angerufen.</span></span></span></code></pre></div></div>
<p>Diese Automation sendet eine Nachricht mit dem Schema: <code>Horst (0174-123456) hat am 23.05.2020 um 23:42h angerufen.</code></p>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Homeassistant 0.106: Neues Feature zum Dimmen von Lichtern</title>
      <link>https://jbetzen.net/posts/dimmen/</link>
      <pubDate>Thu, 27 Feb 2020 23:42:13 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/dimmen/</guid>
      <description>Mit dem Release 0.106 bietet Homeassistant eine neue granulare Möglichkeit zum Dimmen von Lichtern, die das Ein- und Ausschaltverhalten deutlich angenehmer gestaltet. Dieser Post beinhaltet ein Beispiel, wie dieses neue Feature benutzt werden kann.</description>
      <content:encoded><![CDATA[ <p>Homeassistant hat mit dem Release 0.106 ein praktisches <a href="https://www.home-assistant.io/blog/2020/02/26/release-106/#stepping-up-and-down-the-brightness-of-lights"  target="_blank" rel="noreferrer">neues Feature zum Dimmen von Lichtern</a> erhalten. Ursprünglich herrschte stets das Problem vor, dass ein Licht bereits eingeschaltet sein musste, um eine Dimm-Funktion zu automatisieren. Es musste über Templates der aktuelle Helligkeitswert ausgelesen und ein Wert x substrahiert oder addiert werden. Dies ist nun deutlich einfacher geworden und soll im Folgenden anhand eines Tradfri Dimmers aus dem Hause IKEA aufgezeigt werden.</p>

<h2 class="relative group">Beispiel: IKEA Dimmer mit Deconz und Conbee II
    <div id="beispiel-ikea-dimmer-mit-deconz-und-conbee-ii" class="anchor"></div>
    
</h2>
<p>Der Dimmer sendet die Codes <code>2002</code> und <code>3002</code> unter der ID <code>tradfri_dimmer.room_2</code> auf dem Event-Bus. Diese müssen durch eine Automation ausgelesen und anschließend die neue Dimmfunktion als Action zugewiesen werden. Zum Dimmen stehen zwei Methoden zur Auswahl:</p>
<ul>
<li><code>brightness_step</code>: Dieser Parameter akzeptiert Schrittwerte zwischen -255 und 255. Der Wert 255 steht in diesem Zusammenhang für eine Licht mit voller Leuchstärke.</li>
<li><code>brightness_step_pct</code>: Dieser Parameter gibt einen prozentualen Dimmwert als Stufe an. Es können werte zwischen <code>-100</code> und <code>100</code> zugewiesen werden. Der Wert 100 steht hier analog ebenfalls für die höchstmögliche Leuchtkraft einer Leuchte.</li>
</ul>

<h2 class="relative group">Beispielautomation
    <div id="beispielautomation" class="anchor"></div>
    
</h2>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="l">Tradfri Dimmer Room2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Tradfri Dimmer Room2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">event</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">event_type</span><span class="p">:</span><span class="w"> </span><span class="l">deconz_event</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">event_data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="l">tradfri_dimmer_room2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">action</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">light.turn_on</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">entity_id</span><span class="p">:</span><span class="w"> </span><span class="l">light.room2_decke</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">data_template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">brightness_step_pct</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% if trigger.event.data.event == 2002 %}
</span></span></span><span class="line"><span class="cl"><span class="sd">            +10
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% elif trigger.event.data.event == 3002 %}
</span></span></span><span class="line"><span class="cl"><span class="sd">            -10
</span></span></span><span class="line"><span class="cl"><span class="sd">          {% endif %}</span></span></span></code></pre></div></div>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Homeassistant, Actionable Notifications und Appdaemon</title>
      <link>https://jbetzen.net/posts/notificaton-appdaemon/</link>
      <pubDate>Sun, 09 Feb 2020 23:42:13 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/notificaton-appdaemon/</guid>
      <description>Homeassistant bietet die Möglichkeit Push-Nachrichten an die Companion App zu senden und darüber direkt Actions auszulösen. Dieser Post beschreibt, wie man die Push-Nachrichten über Appdaemon ausliest und darüber Aktionen ausführt.</description>
      <content:encoded><![CDATA[ <p>Seit kurzem wird die Entwicklung der offiziellen Android App für Homeassistant eifrig voran getrieben. Seit dem Release 1.6 hat diese ein nützliches Feature hinzugewonnen, das sich <a href="https://companion.home-assistant.io/en/notifications/actionable"  target="_blank" rel="noreferrer">Actionable Notifications</a> nennt. Actionable Notifications ermöglichen es maximal 3 Aktionen an Push-Nachrichten zu binden und diese quasi wie ein Shortcut zu triggern:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/notificaton-appdaemon/notifications-appdaemon-example.jpg"
          alt="Beispiel Actionable Notification"
        />
  
  <figcaption>Beispiel Actionable Notification</figcaption>
  </figure>
<p>Wie man diese Notification aus Homeassistant heraus sendet und den gewählte Aktion in Appdaemon nutzen kann zeige ich in den folgenden Schritten. Voraussetzungen hierfür sind, dass die <a href="https://www.home-assistant.io/integrations/mobile_app/"  target="_blank" rel="noreferrer">Mobile App Integration</a> von Homeassistant in der <code>configuration.yaml</code> eingetragen, die offizielle Android App installiert und erfolgreich mit der Instanz verbunden und diese aus dem Internet erreichbar ist. Sind alle Voraussetzungen erfüllt, erstellt Homeassistant automatisch einen Service zum Senden von Push-Nachrichten. Dieser lautet <code>notify.mobile_app_TELEFONNAME</code>. Wer sich nicht sicher ist, wie der Dienst für sein Smartphone heißt, kann den genauen Namen unter <code>DEVELOPER TOOLS &gt; SERVICES</code> im Dropdown Menü nachschauen.</p>

<h2 class="relative group">Beispielscript für Notification
    <div id="beispielscript-für-notification" class="anchor"></div>
    
</h2>
<p>Als Beispiel wird ein Script erstellt, dass eine Pushnachricht mit drei Aktionen sendet:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">script</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">test_notification</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">sequence</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">notify.mobile_app_oneplus</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">message</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Was möchtest du tun?&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Testnachricht&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">data</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">actions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span>- <span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;PN_LICHT&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Licht an&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span>- <span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;PN_STECKDOSE&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Steckdose an&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span>- <span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;PN_SCENE&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Scene Hell&#39;</span></span></span></code></pre></div></div>
<p>Wichtig ist, dass jede angelegte Aktion einen eindeutigen Namen erhält, z.B. <code>PN_LICHT</code>. Nach dem anlegen des Script, müssen in Homeassitant die Scripte neu eingelesen werden oder ein Neustart von Hass erfolgen. Anschließend kann unter den <code>DEVELOPER TOOLS &gt; STATES</code> das Script gesucht werden. Klickt man auf das kleine rund umrandete <code>i</code> vor dem Script, öffnet sich ein Menü mit dem man es auslösen kann. Unmittelbar danach sollte eine Push-Nachricht auf dem Handy erscheinen.</p>

<h2 class="relative group">Appdaemon konfigurieren
    <div id="appdaemon-konfigurieren" class="anchor"></div>
    
</h2>
<p>Da Pushnotifications einen Haufen unterschiedlicher Services triggern können, habe ich mich entschlossen diese über Appdaemon ausführen zu lassen. Im Ordner <code>config/appdaemon/apps/</code> wird nun eine Datei mit dem Namen <code>pushactions.py</code> erzeugt und folgender Inhalt eingefügt:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-py" data-lang="py"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">appdaemon.plugins.hass.hassapi</span> <span class="k">as</span> <span class="nn">hass</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">PushActions</span><span class="p">(</span><span class="n">hass</span><span class="o">.</span><span class="n">Hass</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">listen_event</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">handle_event</span><span class="p">,</span> <span class="s2">&#34;mobile_app_notification_action&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">handle_event</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event_name</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;action&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;PN_LICHT&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">call_service</span><span class="p">(</span><span class="s2">&#34;light/turn_on&#34;</span><span class="p">,</span> <span class="n">entity_id</span> <span class="o">=</span> <span class="s2">&#34;light.decke&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">elif</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;action&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;PN_STECKDOSE&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">call_service</span><span class="p">(</span><span class="s2">&#34;switch/turn_on&#34;</span><span class="p">,</span> <span class="n">entity_id</span> <span class="o">=</span> <span class="s2">&#34;switch.lampe&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">elif</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;action&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;PN_SCENE&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">call_service</span><span class="p">(</span><span class="s2">&#34;scene/turn_on&#34;</span><span class="p">,</span> <span class="n">entity_id</span> <span class="o">=</span> <span class="s2">&#34;scene.hell&#34;</span><span class="p">)</span></span></span></code></pre></div></div>
<p>Die Namen der Scenen, Switches und Lights sind exemplarisch und müssen selbstverständlich an die eigenen Belange angepasst werden.</p>
<p>Nun muss die neue App noch Appdaemon bekannt gemacht werden. Dazu wird die Datei <code>config/appdaemon/apps.yaml</code> aufgerufen und folgender Eintrag hinzugefügt:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">ActionableNotifications</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">module</span><span class="p">:</span><span class="w"> </span><span class="l">pushactions</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">class</span><span class="p">:</span><span class="w"> </span><span class="l">PushActions</span></span></span></code></pre></div></div>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Ikea Rollo mit dem Conbee 2 in Homeassistant nutzen</title>
      <link>https://jbetzen.net/posts/ikea-rollo/</link>
      <pubDate>Sat, 28 Dec 2019 23:42:13 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/ikea-rollo/</guid>
      <description>Ikea bietet im Rahmen des Tradfri Smarthome Sortiments ein neues Rollo an, dass über Zigbee gesteuert werden kann. Dieser Post beschreibt, wie das Rollo mittels Conbee II in Homeassistant integrieren und gesteuert werden kann.</description>
      <content:encoded><![CDATA[ <p>Seit einigen Monaten bietet Ikea zwei Modelle für Smarte Rollos an, die über ZigBee kommunizieren. Zur Auswahl stehen das lichtundurchlässige Modell <a href="https://www.ikea.com/de/de/p/fyrtur-verdunklungsrollo-kabellos-batteriebetrieben-grau-20408178/"  target="_blank" rel="noreferrer">Fyrtur</a> und das lediglich abdunkelnde <a href="https://www.ikea.com/de/de/p/kadrilj-rollo-kabellos-batteriebetrieben-grau-60408119/"  target="_blank" rel="noreferrer">Kadrilj</a>.
Im Lieferumfang der beiden Modelle sind ein Zigbee Repeater und eine Fernbedienung enthalten. Diese können mittels <a href="https://phoscon.de/de/conbee2"  target="_blank" rel="noreferrer">Conbee 2</a> in Homeassistant eingebunden werden.</p>
<p><strong>Tipp:</strong> Wer bei der Rollomontage keine Lust auf das Setzen von Bohrungen hat, kann die smarten Rollos mittels dem Montageset <a href="https://www.ikea.com/de/de/p/klamby-beschlag-f-rollo-jalousie-weiss-90149761/"  target="_blank" rel="noreferrer">Klamby</a> direkt am Fenster anbringen. Hierfür wird lediglich ein Kreuzschlitz-Schraubendreher benötigt.</p>

<h2 class="relative group">Pairing des Rollos mit Deconz
    <div id="pairing-des-rollos-mit-deconz" class="anchor"></div>
    
</h2>
<p>Das Rollo kann in der Deconz UI als Licht eingebunden werden und erscheint danach in Homeassistant als <a href="https://www.home-assistant.io/integrations/cover/"  target="_blank" rel="noreferrer">Cover</a> mit den entsprechenden Services.
Zum Pairen müssen beide Buttons auf dem Rollo gedrückt gehalten werden. Anschließend wird das Rollo in die Nähe des Conbee 2 geführt und und der Pairing-Prozess in der Deconz UI gestartet.</p>
<lite-youtube videoid="1b3j39tYcgc" playlabel="1b3j39tYcgc" params=""></lite-youtube>


<h2 class="relative group">Ausfahrlänge des Rollos einstellen
    <div id="ausfahrlänge-des-rollos-einstellen" class="anchor"></div>
    
</h2>
<p>Das Rollo kann mittels der zwei darauf befindlichen Buttons auf die gewünscht Ausfahrlänge eingestellt werden. Ist die gewünschte Länge erreicht, muss zweimal der untere Button gedrückt werden. Das Rollo merkt sich fortan die maximale Ausfahrlänge.</p>
<lite-youtube videoid="ru-gxsVjnjE" playlabel="ru-gxsVjnjE" params=""></lite-youtube>


<h2 class="relative group">Pairen der Fernbedienung mit Deconz
    <div id="pairen-der-fernbedienung-mit-deconz" class="anchor"></div>
    
</h2>
<p>Dieser Vorgang erschloss sich mir nicht gänzlich, wurde aber gemeistert. Die Fernbedienung muss dazu aufgeschraubt und die Batterie eingesetzt werden. Im Aufgeschraubten Zustand ist der Pairing Button erreichbar. Da alle Fernbedienung von Ikea im Lieferzustand bereits mit dem Rollo gepaired sind, muss die Fernbedienung zunächst auf Werkszustand gesetzt werden, damit sie in Deconz nutzbar ist. Dazu muss in der Deconz UI das Pairing für einen Sensor aktiviert werden. Anschließend muss der Button der Fernbedienung 4 mal innerhalb von 5 Sekunden gedrückt werden. Die eingebaute LED leuchtet dann pulsierend rot.
<lite-youtube videoid="UYz9ixxZz6U" playlabel="UYz9ixxZz6U" params=""></lite-youtube>
</p>

<h2 class="relative group">Fernbedienung mit ControllerX nutzen
    <div id="fernbedienung-mit-controllerx-nutzen" class="anchor"></div>
    
</h2>
<p>Über HACS lässt sich <a href="https://github.com/xaviml/controllerx"  target="_blank" rel="noreferrer">ControllerX</a> installieren. Es stellt ein wahrhaftiges Schweizer Taschenmesser für alle Zigbee-Geräte dar.</p>
<p>Der mitgelieferte Controller namens E1743 zum Steuern des Rollos hat einen <a href="https://xaviml.github.io/controllerx/controllers/E1743"  target="_blank" rel="noreferrer">eigenen Abschnitt</a> in der Dokumentation.</p>
<p>Eine ausführliche Anleitung zur Einrichtung und Verwendung von ControllerX ist ebenfalls auf diesem Blog vorhanden. Siehe: <a href="/posts/controllerx/">ControllerX und Home Assistant</a></p>

<h2 class="relative group">Template Sensor für Öffnungsgrad
    <div id="template-sensor-für-öffnungsgrad" class="anchor"></div>
    
</h2>
<p>Die aktuelle Position des Rollos kann mit einem Template Sensor ausgelesen werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">template</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">sensors</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">rollo_schlafzimmer_open_percent</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ states.cover.rollo_schlafzimmer.attributes.current_position }}&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">friendly_name</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;Geöffnet&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">unit_of_measurement</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;%&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon_template</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% if states(&#39;sensor.rollo_schlafzimmer_open_percent&#39;) | int &lt; 50 %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          mdi:blinds
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% else %}
</span></span></span><span class="line"><span class="cl"><span class="sd">          mdi:blinds-open
</span></span></span><span class="line"><span class="cl"><span class="sd">        {% endif %}</span></span></span></code></pre></div></div>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Feinstaubsensor selber bauen</title>
      <link>https://jbetzen.net/posts/feinstaubsensor/</link>
      <pubDate>Fri, 21 Dec 2018 00:08:25 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/feinstaubsensor/</guid>
      <description>Dieser Post handelt davon, wie man einen Feinstaubsensor des luftdaten.info Projekts auf Basis des Microcontrollers ESP8266 und einem SDS011 Sensors bastelt. Die gewonnenen Daten können über eine Custom Integration in Homeassistant eingebunden werden.</description>
      <content:encoded><![CDATA[ <p>Vor Kurzem bin ich über die Webseite <a href="https://luftdaten.info/"  target="_blank" rel="noreferrer">luftdaten.info</a> gestolpert auf der es eine einfache Bauanleitung für einen Feinstaubsensor gibt. Ich habe kurzerhand alle Teile über AliExpress bestellt und einen solchen Sensor zusammengebastelt. Als Gehäuse habe ich jedoch nicht auf die Marley-Silent-Bögen zurückgegriffen, sondern den 3D-Drucker angeworfen und <a href="https://www.thingiverse.com/thing:2503257"  target="_blank" rel="noreferrer">dieses Gehäuse</a> gedruckt.
Das faszinierende am Luftdatenprojekt ist, dass diese Sensoren mit wenigen Handgriffen Teil eines globalen Netzwerks hunderter anderer Sensoren werden können. Die so aggregierten Daten können dann grafisch sehr anschaulich auf einer <a href="http://deutschland.maps.sensor.community/#6/51.165/10.455"  target="_blank" rel="noreferrer">Karte</a> dargestellt werden.</p>

<h2 class="relative group">Teileliste
    <div id="teileliste" class="anchor"></div>
    
</h2>
<p>Die benötigten Hardware-Komponenten können für ca. 25€ erworben werden:</p>
<div style="display:table; margin:auto">
<table>
	<thead>
			<tr>
					<th>Bauteil</th>
					<th>Bauteilkategorie</th>
					<th style="text-align: right">Kosten</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://de.aliexpress.com/w/wholesale-esp8266.html"  target="_blank" rel="noreferrer">ESP8266</a></td>
					<td>Mikrokontroller</td>
					<td style="text-align: right">3 €</td>
			</tr>
			<tr>
					<td><a href="https://de.aliexpress.com/w/wholesale-sds011.html"  target="_blank" rel="noreferrer">Feinstaubsensor SDS011</a></td>
					<td>Sensor</td>
					<td style="text-align: right">20 €</td>
			</tr>
			<tr>
					<td><a href="https://de.aliexpress.com/w/wholesale-dht22-sensor.html"  target="_blank" rel="noreferrer">DHT22 Sensor</a></td>
					<td>Sensor</td>
					<td style="text-align: right">1 €</td>
			</tr>
	</tbody>
</table>
</div>
<p>Der DHT22 Sensor, kann auch durch einen DHT11 ersetzt werden. Dieser liefert Temperatur- und Luftfeuchtigkeitsangaben jedoch mit schlechterer Genauigkeit. Wer es genauer mag, sollte auf einen DHT22 zurückgreifen.</p>

<h2 class="relative group">Feinstaubwerte
    <div id="feinstaubwerte" class="anchor"></div>
    
</h2>
<p>Die gelieferten Feinstaubwerte beschränken sich auf die Werte für <strong>PM10</strong> und <strong>PM2.5</strong>. Diese sind <a href="https://www.umweltbundesamt.de/themen/luft/luftschadstoffe-im-ueberblick/feinstaub"  target="_blank" rel="noreferrer">laut Umweltbundesamt</a> wie folgt definiert:</p>
<blockquote><p><em>PM10 kann beim Menschen in die Nasenhöhle, PM2,5 bis in die Bronchien und Lungenbläschen und ultrafeine Partikel bis in das Lungengewebe und sogar in den Blutkreislauf eindringen. Je nach Größe und  Eindringtiefe der Teilchen sind die gesundheitlichen Wirkungen von Feinstaub verschieden. Sie reichen von Schleimhautreizungen und lokalen Entzündungen in der Luftröhre und den Bronchien oder den Lungenalveolen bis zu verstärkter Plaquebildung in den Blutgefäßen, einer erhöhten Thromboseneigung oder Veränderungen der Regulierungsfunktion des vegetativen Nervensystems (Herzfrequenzvariabilität).</em></p>
</blockquote><p>Zu den geltenden <strong>Grenzwerten</strong> sind auf der Seite des Umweltbundesamtes folgende Aussagen zu finden:</p>
<blockquote><p><em>Zum Schutz der menschlichen Gesundheit gelten seit dem 1. Januar 2005 europaweit Grenzwerte für die Feinstaubfraktion PM10. Der Tagesgrenzwert beträgt 50 µg/m3 und darf nicht öfter als 35mal im Jahr überschritten werden. Der zulässige Jahresmittelwert beträgt 40 µg/m3. Für die noch kleineren Partikel PM2,5 gilt seit 2008 europaweit ein Zielwert von 25 µg/m3 im Jahresmittel, der bereits seit dem 1. Januar 2010 eingehalten werden soll. Seit 1. Januar 2015 ist dieser Wert verbindlich einzuhalten.</em></p>
</blockquote>
<h2 class="relative group">Integration in Homeassistant
    <div id="integration-in-homeassistant" class="anchor"></div>
    
</h2>
<p>Für die Integration der Sensorwerte steht für Homeassistant eine <em>Custom Component</em> namens <a href="https://github.com/lichtteil/local_luftdaten"  target="_blank" rel="noreferrer">Local Luftdaten</a> zur Verfügung. Diese kann über HACS installiert und muss anschließend konfiguriert werden.</p>

<h3 class="relative group">Konfiguration der Custom Component
    <div id="konfiguration-der-custom-component" class="anchor"></div>
    
</h3>
<p>Die Custom Component verlangt eine IP-Adresse des Feinstaubsensors, ein Scan Interval zur Häufigkeit der Datenabfrage und eine Liste der der Werte, die Ausgelesen werden sollen. Die IP-Adresse sollte statisch vergeben werden, damit sie sich nicht ändert:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">sensor</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">local_luftdaten</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">host</span><span class="p">:</span><span class="w"> </span><span class="m">192.168.0.123</span><span class="w">         </span><span class="c"># IP Adresse hier eintragen</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">scan_interval</span><span class="p">:</span><span class="w"> </span><span class="m">180</span><span class="w">          </span><span class="c"># Scan alle 3 Minuten</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Feinstaubsensor</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">monitored_conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">SDS_P1                 </span><span class="w"> </span><span class="c"># Wert für PM10</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">SDS_P2                 </span><span class="w"> </span><span class="c"># Wert für PM2.5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">temperature</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">humidity</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">signal                 </span><span class="w"> </span><span class="c"># Wert für WiFi-Signalstärke</span></span></span></code></pre></div></div>

<h3 class="relative group">Lovelace UI
    <div id="lovelace-ui" class="anchor"></div>
    
</h3>
<p>Zur Integration in die Lovelace UI empfehle ich die vielseitige <a href="https://github.com/kalkih/mini-graph-card"  target="_blank" rel="noreferrer">Mini-Graph-Card</a>. Im Verbund mit einem Vertical-Stack kann folgendes dargestellt werden:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/feinstaubsensor/feinstaubsensor-lovelacecard.png"
          alt="Lovelace Card zur Anzeige der Feinstaubwerte"
        />
  
  
  </figure>
<p>Der Code zur Darstellung der Lovelace Card:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">vertical-stack</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">cards</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">horizontal-stack</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">cards</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">custom:mini-graph-card</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">animate</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">color_thresholds</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#f08080&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="m">50</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#ff9966&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="m">40</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#90ee90&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="m">30</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entities</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.feinstaubsensor_pm10</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">index</span><span class="p">:</span><span class="w"> </span><span class="m">0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">hours_to_show</span><span class="p">:</span><span class="w"> </span><span class="m">6</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">PM10 | ◷ 6h</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">points_per_hour</span><span class="p">:</span><span class="w"> </span><span class="m">6</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">show</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">fill</span><span class="p">:</span><span class="w"> </span><span class="l">fade</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">graph</span><span class="p">:</span><span class="w"> </span><span class="l">bar</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">custom:mini-graph-card</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">animate</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">color_thresholds</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#f08080&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="m">25</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#ff9966&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="m">15</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#90ee90&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="m">10</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entities</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.feinstaubsensor_pm2_5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">index</span><span class="p">:</span><span class="w"> </span><span class="m">0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">hours_to_show</span><span class="p">:</span><span class="w"> </span><span class="m">6</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">PM2.5 | ◷ 6h</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">points_per_hour</span><span class="p">:</span><span class="w"> </span><span class="m">6</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">show</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">fill</span><span class="p">:</span><span class="w"> </span><span class="l">fade</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">graph</span><span class="p">:</span><span class="w"> </span><span class="l">bar</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">horizontal-stack</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">cards</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">custom:mini-graph-card</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">animate</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">color_thresholds</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#f08080&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="m">23</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#90ee90&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="m">20</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#00bfff&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="m">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entities</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.feinstaubsensor_temperature</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">index</span><span class="p">:</span><span class="w"> </span><span class="m">0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">hours_to_show</span><span class="p">:</span><span class="w"> </span><span class="m">24</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Temperatur | ◷24h</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">points_per_hour</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">show</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">custom:mini-graph-card</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">animate</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">color_thresholds</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#00ffff&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="m">60</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#00bfff&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="m">40</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;#00ffff&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="m">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">entities</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.feinstaubsensor_humidity</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">index</span><span class="p">:</span><span class="w"> </span><span class="m">0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">hours_to_show</span><span class="p">:</span><span class="w"> </span><span class="m">24</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Luftfeuchte | ◷24h</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">points_per_hour</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">show</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">fill</span><span class="p">:</span><span class="w"> </span><span class="l">fade</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span></span></span></code></pre></div></div>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Matomo Besucherstatistik in Homeassistant einbinden</title>
      <link>https://jbetzen.net/posts/matomo/</link>
      <pubDate>Tue, 18 Dec 2018 23:42:13 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/matomo/</guid>
      <description>Matomo ist eine datenschutzfreundliche Software zum Tracken von Besuchern auf Webseiten. Die ermittelten Metriken können über Matomos API in Homeassistant ausgelesen, dargestellt und per TTS vorgelesen werden.</description>
      <content:encoded><![CDATA[ <p>Wer Matomo als Analytics-Tool zur Auswertung der Besucherstatistiken auf seinem Blog oder Webseite nutzt, kann diese Daten über die <a href="https://developer.matomo.org/api-reference/reporting-api"  target="_blank" rel="noreferrer">Matomo API</a>, mittels eines <a href="https://www.home-assistant.io/components/sensor.rest/"  target="_blank" rel="noreferrer">REST-Sensors</a>, in Homeassistant integrieren. Im Folgenden zeige ich wie man die täglichen, wöchentlichen und monatlichen Besucherstatistiken (Unique Visitors) in Homeassistant darstellen kann. Dazu muss wie folgt vorgegangen werden:</p>

<h2 class="relative group">Auth-Token im Matomo Dashboard suchen
    <div id="auth-token-im-matomo-dashboard-suchen" class="anchor"></div>
    
</h2>
<p>Als erster Schritt in das Dashboard von Matomo gewechselt werden. Dort findet man in den Einstellungen unter der Sektion Platform den Menüpunkt <code>API</code>. Hier präsentiert Matomo den benötigten Token der wie folgt aussieht:
<code>&amp;token_auth=c7a98***************************</code></p>
<p>Dieser muss notiert werden, da er für den REST-Sensor in Homeassistant benötigt wird.</p>

<h2 class="relative group">REST-Sensor in Homeassistant erstellen
    <div id="rest-sensor-in-homeassistant-erstellen" class="anchor"></div>
    
</h2>
<p>In Homeassistant müssen folgende drei Sensoren angelegt werden. Der Platzhalter <code>URL_MATOMO</code> muss durch die entsprechende URL ersetzt werden unter der Matomo erreichbar ist. Zu beachten ist der Eintrag <code>idSite</code> in der URL, wenn mehrere Blogs mittels Matomo getrackt werden. An dieser Stelle muss dann die gewünschte <code>ID</code> eingetragen werden.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">rest</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">resource</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https://URL_MATOMO/?module=API&amp;method=VisitsSummary.getUniqueVisitors&amp;idSite=1&amp;period=day&amp;date=today&amp;format=JSON&amp;token_auth=c7a98***************************&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Blog Visitors Today</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ value_json.value | int }}&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">unit_of_measurement</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Visitors&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">rest</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">resource</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https://URL_MATOMO/?module=API&amp;method=VisitsSummary.getUniqueVisitors&amp;idSite=1&amp;period=week&amp;date=today&amp;format=JSON&amp;token_authc7a98***************************4&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Blog Visitors Week</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ value_json.value | int }}&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">unit_of_measurement</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Visitors&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">rest</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">resource</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https://URL_MATOMO/?module=API&amp;method=VisitsSummary.getUniqueVisitors&amp;idSite=1&amp;period=month&amp;date=today&amp;format=JSON&amp;token_auth=c7a98***************************&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Blog Visitors Month</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{{ value_json.value | int }}&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">unit_of_measurement</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Visitors&#34;</span></span></span></code></pre></div></div>

<h2 class="relative group">Lovelace Card
    <div id="lovelace-card" class="anchor"></div>
    
</h2>
<p>Zu aller Letzt wird jetzt noch eine Card in der Lovelace-UI erstellt:</p>

<figure>
        <img
          class="my-0 rounded-md centered"
          src="/posts/matomo/matomo-card.png"
          alt="Lovelace Card mit Matomo-Statistiken"
        />
  
  
  </figure>
<p>Der zugehörige Code lautet:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">glance</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">Triumvirat.org | Statistik</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">entities</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.blog_visitors_today</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;mdi:calendar-today&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Today</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.blog_visitors_week</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Week</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;mdi:calendar-week&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">entity</span><span class="p">:</span><span class="w"> </span><span class="l">sensor.blog_visitors_month</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Month</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">icon</span><span class="p">:</span><span class="w"> </span><span class="l">&#39;mdi:calendar-week-begin</span></span></span></code></pre></div></div>

<h2 class="relative group">Gesprochenene Blogstatistik mittels TTS-Service
    <div id="gesprochenene-blogstatistik-mittels-tts-service" class="anchor"></div>
    
</h2>
<p>Wer die Blogstatistik gerne mittels 


<abbr title="Text to Speech">TTS</abbr> ausgeben lassen möchte, kann dies mittels eines Scripts bewerkstelligen:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">tts_blogstatistik</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">alias</span><span class="p">:</span><span class="w"> </span><span class="l">Blogstatistik</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">sequence</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">notify.alexa</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">data_template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">message</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">        &#39;Heute haben {{ states.sensor.blog_visitors_today.state }} Menschen den Blog gelesen. Die gesamte Woche waren es {{ states.sensor.blog_visitors_week.state }} und im gesamten Monat {{ states.sensor.blog_visitors_month.state }} Besucher.&#39;</span></span></span></code></pre></div></div>
 ]]></content:encoded>
    </item>
    
    <item>
      <title>Xiaomi MiScale Waage in Homeassistant integrieren</title>
      <link>https://jbetzen.net/posts/xiaomi-scale/</link>
      <pubDate>Sat, 28 Jul 2018 23:42:13 +0200</pubDate>
      
      <guid>https://jbetzen.net/posts/xiaomi-scale/</guid>
      <description>Xiaomi hat eine Personenwaage im Sortiment, die MiScale heißt und über Bluetooth LE die gemessenen Metriken funkt. Die Daten können über eine Software namens BT-MQTT-Gateway in Homeassistant eingelesen und dargestellt werden.</description>
      <content:encoded><![CDATA[ 
  
  
  
  



<div
  
    class="flex px-4 py-3 rounded-md shadow bg-primary-100 dark:bg-primary-900"
  
  >
  <span
    
      class="text-primary-400 pe-3 flex items-center"
    
    >
    <span class="relative block icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 128c17.67 0 32 14.33 32 32c0 17.67-14.33 32-32 32S224 177.7 224 160C224 142.3 238.3 128 256 128zM296 384h-80C202.8 384 192 373.3 192 360s10.75-24 24-24h16v-64H224c-13.25 0-24-10.75-24-24S210.8 224 224 224h32c13.25 0 24 10.75 24 24v88h16c13.25 0 24 10.75 24 24S309.3 384 296 384z"/></svg>
</span>
  </span>

  <span
    
      class="dark:text-neutral-300"
    
    >Zu diesem Artikel ist ein Update verfügbar, in dem gezeigt wird wie die Waage mittels ESPHome ausgelesen werden kann: <a href="/posts/esphome-btle-hub/">ESPHome Bluetooth Low Energy Hub</a></span>
</div>

<p>Homeassistant unterstützt von Haus aus mehr als 1100 Komponenten. Leider zählt die Xiaomi MiScale Personenwaage nicht dazu. Das ist fürs Erste ärgerlich, aber gleichzeitig auch Ansporn kreative Wege einzuschlagen. Wer also gerne seinen Gewicht und ggf. dessen Verlauf im Frontend sehen möchte, braucht ein Programm, das Homeassistant die Daten der Waage in verwertbarer Weise zuspielt. Ich nutze dafür <a href="https://github.com/zewelor/bt-mqtt-gateway"  target="_blank" rel="noreferrer">bt-mqtt-gateway</a>. Das Gateway extrahiert die Daten <a href="https://github.com/zewelor/bt-mqtt-gateway#supported-devices"  target="_blank" rel="noreferrer">diverser</a> Bluetooth-Geräte und sendet sie über <a href="/categories/mqtt/" >MQTT</a> an Homeassistant.</p>

<h2 class="relative group">MAC-Adresse der Waage herausfinden
    <div id="mac-adresse-der-waage-herausfinden" class="anchor"></div>
    
</h2>
<p>Das geht am einfachsten mit dem <code>hcitool</code> auf Linux. Einfach sicherstellen, dass Bluetooth am Gerät eingeschaltet ist und dann das Kommando ins Terminal tippen:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">sudo hcitool lescan</span></span></code></pre></div></div>
<p>Nun werden alle Bluetooth-Geräte mit MAC-Adresse und Namen gelistet. Die Xiaomi-Waage hat bspw. den Namen <code>MI_SCALE</code>. Die MAC-Adresse wird später benötigt und muss notiert werden.</p>

<h2 class="relative group">BT-MQTT-GATEWAY
    <div id="bt-mqtt-gateway" class="anchor"></div>
    
</h2>

<h3 class="relative group">Installation
    <div id="installation" class="anchor"></div>
    
</h3>
<p>Die Installation wird auf der zugehörigen Github-Seite ausführlich beschrieben. Zuerst müssen ein paar Abhängigkeiten auf Systemebene installiert werden. Anschließend wird ein <code>virtualenv</code> angelegt, um die Installation der Python-Pakete sauber von den Systempaketen zu trennen.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">sudo apt-get install git python3 python3-pip python3-wheel bluetooth bluez libglib2.0-dev
</span></span><span class="line"><span class="cl">sudo pip3 install virtualenv
</span></span><span class="line"><span class="cl">git clone https://github.com/zewelor/bt-mqtt-gateway.git
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> bt-mqtt-gateway
</span></span><span class="line"><span class="cl">virtualenv -p python3 .venv
</span></span><span class="line"><span class="cl"><span class="nb">source</span> .venv/bin/activate
</span></span><span class="line"><span class="cl">sudo pip3 install -r requirements.txt</span></span></code></pre></div></div>

<h3 class="relative group">Konfiguration
    <div id="konfiguration" class="anchor"></div>
    
</h3>
<p>Das Gateway benötigt eine Konfigurationsdatei. Ein Beispiel wird mit dem Gateway mitgeliefert. Dieses kann kopiert werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">cp config.yaml.example config.yaml
</span></span><span class="line"><span class="cl">nano config.yaml</span></span></code></pre></div></div>
<p>Es müssen die Zugangsdaten zum MQTT-Broker und die MAC-Adresse der Waage eingetragen werden. Auch kann das Polling-Intervall angepasst werden, das bestimmt wie oft die Waage ausgelesen werden soll. Die config.yaml sollte am Ende so aussehen:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">mqtt</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">host</span><span class="p">:</span><span class="w"> </span><span class="l">localhost/IP</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">username</span><span class="p">:</span><span class="w"> </span><span class="l">USERNAME_MQTT_BROKER</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">password</span><span class="p">:</span><span class="w"> </span><span class="l">PASSWORD_MQTT_BROKER</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">manager</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">topic_subscription</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">update_all</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">homeassistant/status</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">payload</span><span class="p">:</span><span class="w"> </span><span class="l">online</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">workers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">miscale</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">args</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">mac</span><span class="p">:</span><span class="w"> </span><span class="l">XX:XX:XX:XX:XX:XX</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">topic_prefix</span><span class="p">:</span><span class="w"> </span><span class="l">miscale</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">update_interval</span><span class="p">:</span><span class="w"> </span><span class="m">3600</span></span></span></code></pre></div></div>
<p>Sind alle Daten eingetragen und gespeichert, kann die erstellte Konfiguration getestet werden um zu schauen, ob die Waage erfolgreich ausgelesen wird:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">sudo ./gateway.py</span></span></code></pre></div></div>

<h3 class="relative group">Systemd Service anlegen
    <div id="systemd-service-anlegen" class="anchor"></div>
    
</h3>
<p>Es wird eine Beispielkonfiguration für einen Systemd Service mitgeliefert, die jedoch angepasst werden muss. Es muss der korrekte Pfad zum bt-mqtt-gateyway angepasst werden:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">sudo cp bt-mqtt-gateway.service /etc/systemd/system/
</span></span><span class="line"><span class="cl">sudo nano /etc/systemd/system/bt-mqtt-gateway.service</span></span></code></pre></div></div>
<p>Anschließend wird der Dienst registriert und aktiviert:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">sudo systemctl daemon-reload
</span></span><span class="line"><span class="cl">sudo systemctl start bt-mqtt-gateway
</span></span><span class="line"><span class="cl">sudo systemctl status bt-mqtt-gateway
</span></span><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> bt-mqtt-gateway</span></span></code></pre></div></div>

<h2 class="relative group">Homeassistant
    <div id="homeassistant" class="anchor"></div>
    
</h2>

<h3 class="relative group">MQTT-Sensor für Gewicht
    <div id="mqtt-sensor-für-gewicht" class="anchor"></div>
    
</h3>
<p>Homeassistant benötigt lediglich einen <a href="https://www.home-assistant.io/components/sensor.mqtt/"  target="_blank" rel="noreferrer">MQTT-Sensor</a>, um den übermittelten Gewichtswert des Gateways entgegenzunehmen:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Gewicht&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">state_topic</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;miscale/weight/kg&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">unit_of_measurement</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;kg&#34;</span></span></span></code></pre></div></div>

<h3 class="relative group">Template Sensor für BMI
    <div id="template-sensor-für-bmi" class="anchor"></div>
    
</h3>
<p>Der <a href="https://de.wikipedia.org/wiki/Body-Mass-Index"  target="_blank" rel="noreferrer">Body-Mass-Index</a> ergibt sich wie folgt aus dem Quotienten des Gewichts in Kilogramm und der Körpergröße in Metern zum Quadrat:</p>
<p>

$$BMI = \frac{m}{h^{2}} = m \times \frac{1}{h^{2}}$$</p>
<p>Da das Gewicht in Kilogramm bereits in Homeassistant vorhanden ist, muss lediglich der hinten angestellte Faktor \(\frac{1}{h^{2}}\) ausrechnet werden. Bei einer Größe von bspw. <code>1,84m</code> ergibt sich im Kehrwert also <code>0,29536862</code>. Diesen Wert benötigen wird für den BMI-Sensor in Homeassistant. Der Sensor muss so aussehen und gibt den BMI-Wert auf eine Nachkommastelle heraus:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">template</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">sensors</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">bmi</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">friendly_name</span><span class="p">:</span><span class="w"> </span><span class="l">BMI</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">value_template</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ &#39;%.1f&#39; | format(states(&#39;sensor.gewicht&#39;) | float * 0.29536862) }}&#34;</span></span></span></code></pre></div></div>
 ]]></content:encoded>
    </item>
    
  </channel>
</rss>
