Site updated at 2016-08-16 12:19:13 UTC

This commit is contained in:
Travis CI 2016-08-16 12:19:14 +00:00
parent 1f30de63d9
commit 1c238c653a
130 changed files with 1898 additions and 1273 deletions

154
atom.xml
View file

@ -4,7 +4,7 @@
<title><![CDATA[Home Assistant]]></title>
<link href="https://home-assistant.io/atom.xml" rel="self"/>
<link href="https://home-assistant.io/"/>
<updated>2016-08-16T09:54:54+00:00</updated>
<updated>2016-08-16T12:17:59+00:00</updated>
<id>https://home-assistant.io/</id>
<author>
<name><![CDATA[Home Assistant]]></name>
@ -13,6 +13,143 @@
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[We Have Apps Now]]></title>
<link href="https://home-assistant.io/blog/2016/08/16/we-have-apps-now/"/>
<updated>2016-08-16T10:00:00+00:00</updated>
<id>https://home-assistant.io/blog/2016/08/16/we-have-apps-now</id>
<content type="html"><![CDATA[<p>I have been working on a new subsystem to complement Home Assistants Automation and Scripting components. <code>AppDaemon</code> is a python daemon that consumes events from Home Assistant and feeds them to snippets of python code called “Apps”. An App is a Python class that is instantiated possibly multiple times from <code>AppDaemon</code> and registers callbacks for various system events. It is also able to inspect and set state and call services. The API provides a rich environment suited to home automation tasks that can also leverage all the power of Python.</p>
<!--more-->
<h2><a class="title-link" name="another-take-on-automation" href="#another-take-on-automation"></a> Another Take on Automation</h2>
<p>If you havent yet read Paulus excellent Blog entry on <a href="https://home-assistant.io/blog/2016/01/19/perfect-home-automation/">Perfect Home Automation</a> I would encourage you to take a look. As a veteran of several Home Automation systems with varying degrees success, it was this article more than anything else that convinced me that Home Assistant had the right philosophy behind it and was on the right track. One of the most important points made is that being able to control your lights from your phone, 9 times out of 10 is harder than using a lightswitch - where Home Automation really comes into its own is when you start removing the need to use a phone or the switch - the “Automation” in Home Automation. A surprisingly large number of systems out there miss this essential point and have limited abilities to automate anything which is why a robust and open system such as Home Assistant is such an important part of the equation to bring this all together in the vast and chaotic ecosystem that is the “Internet of Things”.</p>
<p>So given the importance of Automation, what should Automation allow us to do? I am a pragmatist at heart so I judge individual systems by the ease of accomplishing a few basic but representative tasks:</p>
<ul>
<li>Can the system respond to presence or absence of people?</li>
<li>Can I turn a light on at Sunset +/- a certain amount of time?</li>
<li>Can I arrive home in light or dark and have the lights figure out if they should be on or off?</li>
<li>As I build my system out, can I get the individual pieces to co-operate and use and re-use (potentially complex) logic to make sure everything works smoothly?</li>
<li>Is it open and expandable?</li>
<li>Does it run locally without any reliance on the cloud?</li>
</ul>
<p>In my opinion, Home Assistant accomplishes the majority of these very well with a combination of Automations, Scripts and Templates, and its Restful API.</p>
<p>So why <code>AppDaemon</code>? <code>AppDaemon</code> is not meant to replace Home Assistant Automations and Scripts, rather complement them. For a lot of things, automations work well and can be very succinct. However, there is a class of more complex automations for which they become harder to use, and appdeamon then comes into its own. It brings quite a few things to the table:</p>
<ul>
<li>New paradigm - some problems require a procedural and/or iterative approach, and <code>AppDaemon</code> Apps are a much more natural fit for this. Recent enhancements to Home Assistant scripts and templates have made huge strides, but for the most complex scenarios, Apps can do things that Automations cant</li>
<li>Ease of use - <code>AppDaemon</code>s API is full of helper functions that make programming as easy and natural as possible. The functions and their operation are as “Pythonic” as possible, experienced Python programmers should feel right at home.</li>
<li>Reuse - write a piece of code once and instantiate it as an app as many times as you need with different parameters e.g. a motion light program that you can use in 5 different places around your home. The code stays the same, you just dynamically add new instances of it in the config file</li>
<li>Dynamic - <code>AppDaemon</code> has been designed from the start to enable the user to make changes without requiring a restart of Home Assistant, thanks to its loose coupling. However, it is better than that - the user can make changes to code and <code>AppDaemon</code> will automatically reload the code, figure out which Apps were using it and restart them to use the new code without the need to restart <code>AppDaemon</code> itself. It is also possible to change parameters for an individual or multiple apps and have them picked up dynamically, and for a final trick, removing or adding apps is also picked up dynamically. Testing cycles become a lot more efficient as a result.</li>
<li>Complex logic - Pythons If/Else constructs are clearer and easier to code for arbitrarily complex nested logic</li>
<li>Durable variables and state - variables can be kept between events to keep track of things like the number of times a motion sensor has been activated, or how long it has been since a door opened</li>
<li>All the power of Python - use any of Pythons libraries, create your own modules, share variables, refactor and re-use code, create a single app to do everything, or multiple apps for individual tasks - nothing is off limits!</li>
</ul>
<p>It is in fact a testament to Home Assistants open nature that a component like <code>AppDaemon</code> can be integrated so neatly and closely that it acts in all ways like an extension of the system, not a second class citizen. Part of the strength of Home Assistants underlying design is that it makes no assumptions whatever about what it is controlling or reacting to, or reporting state on. This is made achievable in part by the great flexibility of Python as a programming environment for Home Assistant, and carrying that forward has enabled me to use the same philosophy for <code>AppDaemon</code> - it took surprisingly little code to be able to respond to basic events and call services in a completely open ended manner - the bulk of the work after that was adding additonal functions to make things that were already possible easier.</p>
<h2><a class="title-link" name="how-it-works" href="#how-it-works"></a> How it Works</h2>
<p>The best way to show what <code>AppDaemon</code> does is through a few simple examples.</p>
<h3><a class="title-link" name="sunrisesunset-lighting" href="#sunrisesunset-lighting"></a> Sunrise/Sunset Lighting</h3>
<p>Lets start with a simple App to turn a light on every night at sunset and off every morning at sunrise. Every App when first started will have its <code>initialize()</code> function called which gives it a chance to register a callback for <code>AppDaemons</code>s scheduler for a specific time. In this case we are using <code>run_at_sunrise()</code> and <code>run_at_sunset()</code> to register 2 separate callbacks. The argument <code>0</code> is the number of seconds offset from sunrise or sunset and can be negative or positive. For complex intervals it can be convenient to use Pythons <code>datetime.timedelta</code> class for calculations. When sunrise or sunset occurs, the appropriate callback function, <code>sunrise_cb()</code> or <code>sunset_cb()</code> is called which then makes a call to Home Assistant to turn the porch light on or off by activating a scene. The variables <code>args["on_scene"]</code> and <code>args["off_scene"]</code> are passed through from the configuration of this particular App, and the same code could be reused to activate completely different scenes in a different version of the App.</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre><span class="keyword">import</span> <span class="include">appapi</span>
<span class="keyword">class</span> <span class="class">OutsideLights</span>(appapi.AppDaemon):
<span class="keyword">def</span> <span class="function">initialize</span>(<span class="predefined-constant">self</span>):
<span class="predefined-constant">self</span>.run_at_sunrise(<span class="predefined-constant">self</span>.sunrise_cb, <span class="integer">0</span>)
<span class="predefined-constant">self</span>.run_at_sunset(<span class="predefined-constant">self</span>.sunset_cb, <span class="integer">0</span>)
<span class="keyword">def</span> <span class="function">sunrise_cb</span>(<span class="predefined-constant">self</span>, args, kwargs):
<span class="predefined-constant">self</span>.turn_on(<span class="predefined-constant">self</span>.args[<span class="string"><span class="delimiter">&quot;</span><span class="content">off_scene</span><span class="delimiter">&quot;</span></span>])
<span class="keyword">def</span> <span class="function">sunset_cb</span>(<span class="predefined-constant">self</span>, args, kwargs):
<span class="predefined-constant">self</span>.turn_on(<span class="predefined-constant">self</span>.args[<span class="string"><span class="delimiter">&quot;</span><span class="content">on_scene</span><span class="delimiter">&quot;</span></span>])
</pre></div>
</div>
</div>
<p>This is also fairly easy to achieve with Home Assistant automations, but we are just getting started.</p>
<h3><a class="title-link" name="motion-light" href="#motion-light"></a> Motion Light</h3>
<p>Our next example is to turn on a light when motion is detected and it is dark, and turn it off after a period of time. This time, the <code>initialize()</code> function registers a callback on a state change (of the motion sensor) rather than a specific time. We tell <code>AppDaemon</code> that we are only interested in state changes where the motion detector comes on by adding an additional parameter to the callback registration - <code>new = "on"</code>. When the motion is detected, the callack function <code>motion()</code> is called, and we check whether or not the sun has set using a built-in convenience function: <code>sun_down()</code>. Next, we turn the light on with <code>turn_on()</code>, then set a timer using <code>run_in()</code> to turn the light off after 60 seconds, which is another call to the scheduler to execute in a set time from now, which results in <code>AppDaemon</code> calling <code>light_off()</code> 60 seconds later using the <code>turn_off()</code> call to actually turn the light off. This is still pretty simple in code terms:</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre><span class="keyword">import</span> <span class="include">appapi</span>
<span class="keyword">class</span> <span class="class">MotionLights</span>(appapi.AppDaemon):
<span class="keyword">def</span> <span class="function">initialize</span>(<span class="predefined-constant">self</span>):
<span class="predefined-constant">self</span>.listen_state(<span class="predefined-constant">self</span>.motion, <span class="string"><span class="delimiter">&quot;</span><span class="content">binary_sensor.drive</span><span class="delimiter">&quot;</span></span>, new = <span class="string"><span class="delimiter">&quot;</span><span class="content">on</span><span class="delimiter">&quot;</span></span>)
<span class="keyword">def</span> <span class="function">motion</span>(<span class="predefined-constant">self</span>, entity, attribute, old, new, kwargs):
<span class="keyword">if</span> <span class="predefined-constant">self</span>.sun_down():
<span class="predefined-constant">self</span>.turn_on(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.drive</span><span class="delimiter">&quot;</span></span>)
<span class="predefined-constant">self</span>.run_in(<span class="predefined-constant">self</span>.light_off, <span class="integer">60</span>)
<span class="keyword">def</span> <span class="function">light_off</span>(<span class="predefined-constant">self</span>, kwargs):
<span class="predefined-constant">self</span>.turn_off(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.drive</span><span class="delimiter">&quot;</span></span>)
</pre></div>
</div>
</div>
<p>This is starting to get a little more complex in Home Assistant automations requiring an Automation rule and two separate scripts.</p>
<p>Now lets extend this with a somewhat artificial example to show something that is simple in <code>AppDaemon</code> but very difficult if not impossible using automations. Lets warn someone inside the house that there has been motion outside by flashing a lamp on and off 10 times. We are reacting to the motion as before by turning on the light and setting a timer to turn it off again, but in addition, we set a 1 second timer to run <code>flash_warning()</code> which when called, toggles the inside light and sets another timer to call itself a second later. To avoid re-triggering forever, it keeps a count of how many times it has been activated and bales out after 10 iterations.</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre><span class="keyword">import</span> <span class="include">appapi</span>
<span class="keyword">class</span> <span class="class">FlashyMotionLights</span>(appapi.AppDaemon):
<span class="keyword">def</span> <span class="function">initialize</span>(<span class="predefined-constant">self</span>):
<span class="predefined-constant">self</span>.listen_state(<span class="predefined-constant">self</span>.motion, <span class="string"><span class="delimiter">&quot;</span><span class="content">binary_sensor.drive</span><span class="delimiter">&quot;</span></span>, new = <span class="string"><span class="delimiter">&quot;</span><span class="content">on</span><span class="delimiter">&quot;</span></span>)
<span class="keyword">def</span> <span class="function">motion</span>(<span class="predefined-constant">self</span>, entity, attribute, old, new, kwargs):
<span class="keyword">if</span> <span class="predefined-constant">self</span>.self.sun_down():
<span class="predefined-constant">self</span>.turn_on(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.drive</span><span class="delimiter">&quot;</span></span>)
<span class="predefined-constant">self</span>.run_in(<span class="predefined-constant">self</span>.light_off, <span class="integer">60</span>)
<span class="predefined-constant">self</span>.flashcount = <span class="integer">0</span>
<span class="predefined-constant">self</span>.run_in(<span class="predefined-constant">self</span>.flash_warning, <span class="integer">1</span>)
<span class="keyword">def</span> <span class="function">light_off</span>(<span class="predefined-constant">self</span>, kwargs):
<span class="predefined-constant">self</span>.turn_off(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.drive</span><span class="delimiter">&quot;</span></span>)
<span class="keyword">def</span> <span class="function">flash_warning</span>(<span class="predefined-constant">self</span>, kwargs):
<span class="predefined-constant">self</span>.toggle(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.living_room</span><span class="delimiter">&quot;</span></span>)
<span class="predefined-constant">self</span>.flashcount += <span class="integer">1</span>
<span class="keyword">if</span> <span class="predefined-constant">self</span>.flashcount &lt; <span class="integer">10</span>:
<span class="predefined-constant">self</span>.run_in(<span class="predefined-constant">self</span>.flash_warning, <span class="integer">1</span>)
</pre></div>
</div>
</div>
<p>Of course if I wanted to make this App or its predecessor reusable I would have provided parameters for the sensor, the light to activate on motion, the warning light and even the number of flashes and delay between flashes.</p>
<p>In addition, Apps can write to <code>AppDaemon</code>s logfiles, and there is a system of constraints that allows yout to control when and under what circumstances Apps and callbacks are active to keep the logic clean and simple.</p>
<p>I have spent the last few weeks moving all of my (fairly complex) automations over to <code>APPDaemon</code> and so far it is working very reliably.</p>
<p>Some people will maybe look at all of this and say “what use is this, I can already do all of this”, and that is fine, as I said this is an alternative not a replacement, but I am hopeful that for some users this will seem a more natural, powerful and nimble way of building potentially very complex automations.</p>
<p>If this has whet your appetite, feel free to give it a try. You can find it, <a href="https://github.com/acockburn/appdaemon">here</a>, including full installation instructions, an API reference, and a number of fully fleshed out examples.</p>
<p>Happy Automating!</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[0.26: Foursquare, Fast.com, FFMPEG and GPSD]]></title>
<link href="https://home-assistant.io/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/"/>
@ -1600,21 +1737,6 @@ target_dir /tmp
<p>So there it is, the reason why we use Polymer.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Video: How To Configure Home Assistant]]></title>
<link href="https://home-assistant.io/blog/2016/05/12/video-configuring-home-assistant/"/>
<updated>2016-05-12T00:09:00+00:00</updated>
<id>https://home-assistant.io/blog/2016/05/12/video-configuring-home-assistant</id>
<content type="html"><![CDATA[<p>Ben from <a href="http://www.bruhautomation.com">BRUH Automation</a> authors a lot of great videos about how he is using Home Assistant and how you can get started with it too. The video below will walk you through how to configure Home Assistant. Enjoy!</p>
<p>Make sure to subscribe to <a href="https://www.youtube.com/channel/UCLecVrux63S6aYiErxdiy4w">his YouTube channel</a> for more Home Assistant videos.</p>
<div class="videoWrapper">
<iframe width="560" height="315" src="https://www.youtube.com/embed/hFDVB2H6TNo" frameborder="0" allowfullscreen=""></iframe>
</div>
]]></content>
</entry>

View file

@ -169,6 +169,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -192,12 +198,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -224,6 +224,12 @@ This article will try to explain how they all relate.</p>
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -247,12 +253,6 @@ This article will try to explain how they all relate.</p>
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -208,6 +208,12 @@ api_key=ABCDEFGHJKLMNOPQRSTUVXYZ
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -231,12 +237,6 @@ api_key=ABCDEFGHJKLMNOPQRSTUVXYZ
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -183,6 +183,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -206,12 +212,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -186,6 +186,12 @@ password=YOUR_PASSWORD
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -209,12 +215,6 @@ password=YOUR_PASSWORD
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -192,6 +192,12 @@ Home Assistant now supports <code>--open-ui</code> and <code>--demo-mode</code>
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -215,12 +221,6 @@ Home Assistant now supports <code>--open-ui</code> and <code>--demo-mode</code>
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -200,6 +200,12 @@ Events are saved in a local database. Google Graphs is used to draw the graph. D
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -223,12 +229,6 @@ Events are saved in a local database. Google Graphs is used to draw the graph. D
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -185,6 +185,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -208,12 +214,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -175,6 +175,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -198,12 +204,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -176,6 +176,12 @@ The old logo, the new detailed logo and the new simple logo.
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -199,12 +205,6 @@ The old logo, the new detailed logo and the new simple logo.
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -215,6 +215,12 @@ An initial version of voice control for Home Assistant has landed. The current i
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -238,12 +244,6 @@ An initial version of voice control for Home Assistant has landed. The current i
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -252,6 +252,12 @@ I (Paulus) have contributed a scene component. A user can create scenes that cap
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -275,12 +281,6 @@ I (Paulus) have contributed a scene component. A user can create scenes that cap
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -263,6 +263,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -286,12 +292,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -198,6 +198,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -221,12 +227,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -290,6 +290,12 @@ Before diving into the newly supported devices and services, I want to highlight
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -313,12 +319,6 @@ Before diving into the newly supported devices and services, I want to highlight
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -343,6 +343,12 @@ This switch platform allows you to control your motion detection setting on your
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -366,12 +372,6 @@ This switch platform allows you to control your motion detection setting on your
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -295,6 +295,12 @@ Fabian has added support for <a href="https://forecast.io/">Forecast.io</a> to g
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -318,12 +324,6 @@ Fabian has added support for <a href="https://forecast.io/">Forecast.io</a> to g
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -284,6 +284,12 @@ Support for Temper temperature sensors has been contributed by <a href="https://
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -307,12 +313,6 @@ Support for Temper temperature sensors has been contributed by <a href="https://
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -194,6 +194,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -217,12 +223,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -307,6 +307,12 @@ The automation and script syntax here is using a deprecated and no longer suppor
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -330,12 +336,6 @@ The automation and script syntax here is using a deprecated and no longer suppor
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -281,6 +281,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -304,12 +310,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -484,6 +484,12 @@ PubSubClient client(ethClient);
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -507,12 +513,6 @@ PubSubClient client(ethClient);
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -343,6 +343,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -366,12 +372,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -244,6 +244,12 @@ Glances web server started on http://0.0.0.0:61208/
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -267,12 +273,6 @@ Glances web server started on http://0.0.0.0:61208/
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -223,6 +223,12 @@ Automation has gotten a lot of love. It now supports conditions, multiple trigge
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -246,12 +252,6 @@ Automation has gotten a lot of love. It now supports conditions, multiple trigge
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -199,6 +199,12 @@ Map in Home Assistant showing two people and three zones (home, school, work)
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -222,12 +228,6 @@ Map in Home Assistant showing two people and three zones (home, school, work)
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -543,6 +543,12 @@ Adafruit_HDC1000 hdc = Adafruit_HDC1000();
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -566,12 +572,6 @@ Adafruit_HDC1000 hdc = Adafruit_HDC1000();
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -188,6 +188,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -211,12 +217,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -210,6 +210,12 @@ This makes more sense as most people run Home Assistant as a daemon</p>
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -233,12 +239,6 @@ This makes more sense as most people run Home Assistant as a daemon</p>
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -206,6 +206,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -229,12 +235,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -246,6 +246,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -269,12 +275,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -181,6 +181,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -204,12 +210,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -188,6 +188,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -211,12 +217,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -279,6 +279,12 @@ $ sudo systemctl status grafana-server
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -302,12 +308,6 @@ $ sudo systemctl status grafana-server
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -229,6 +229,12 @@ requests.get(<span class="string"><span class="delimiter">'</span><span class="c
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -252,12 +258,6 @@ requests.get(<span class="string"><span class="delimiter">'</span><span class="c
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -201,6 +201,12 @@ Philips Hue FAQ entries regarding 3rd party light bulbs.
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -224,12 +230,6 @@ Philips Hue FAQ entries regarding 3rd party light bulbs.
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -268,6 +268,12 @@ sudo docker run -it --rm -p 80:80 --name certbot \
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -291,12 +297,6 @@ sudo docker run -it --rm -p 80:80 --name certbot \
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -222,6 +222,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -245,12 +251,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -202,6 +202,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -225,12 +231,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -206,6 +206,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -229,12 +235,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -208,6 +208,12 @@ Example of the new views in the frontend. <a href="/components/group/">Learn mor
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -231,12 +237,6 @@ Example of the new views in the frontend. <a href="/components/group/">Learn mor
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -395,6 +395,12 @@ Z-Wave light bulb |
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -418,12 +424,6 @@ Z-Wave light bulb |
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -345,6 +345,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -368,12 +374,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -211,6 +211,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -234,12 +240,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -313,6 +313,12 @@ output = audioresample ! audio/x-raw,rate=48000,channels=2,format=S16LE ! audioc
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -336,12 +342,6 @@ output = audioresample ! audio/x-raw,rate=48000,channels=2,format=S16LE ! audioc
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -221,6 +221,12 @@ Hold your NFC tag against the belly of Garfield to unlock the alarm.
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -244,12 +250,6 @@ Hold your NFC tag against the belly of Garfield to unlock the alarm.
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -210,6 +210,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -233,12 +239,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -216,6 +216,12 @@ player state attributes. This change affects automations, scripts and scenes.</l
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -239,12 +245,6 @@ player state attributes. This change affects automations, scripts and scenes.</l
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -227,6 +227,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -250,12 +256,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -179,6 +179,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -202,12 +208,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -185,6 +185,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -208,12 +214,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -193,6 +193,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -216,12 +222,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -177,6 +177,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -200,12 +206,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -194,6 +194,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -217,12 +223,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -212,6 +212,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -235,12 +241,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -303,6 +303,12 @@ For example, my wife works next door - and I couldnt detect whether shes a
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -326,12 +332,6 @@ For example, my wife works next door - and I couldnt detect whether shes a
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -175,6 +175,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -198,12 +204,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -265,6 +265,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -288,12 +294,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -175,6 +175,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -198,12 +204,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -189,6 +189,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -212,12 +218,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -210,6 +210,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -233,12 +239,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -181,6 +181,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -204,12 +210,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -319,6 +319,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -342,12 +348,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -195,6 +195,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -218,12 +224,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -229,6 +229,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -252,12 +258,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -200,6 +200,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -223,12 +229,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -224,6 +224,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -247,12 +253,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -290,6 +290,12 @@ target_dir /tmp
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -313,12 +319,6 @@ target_dir /tmp
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -223,6 +223,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -246,12 +252,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -226,6 +226,12 @@ $ hass --open-ui
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -249,12 +255,6 @@ $ hass --open-ui
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -230,6 +230,12 @@ $ hass --script db_migrator --config /path/to/config
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -253,12 +259,6 @@ $ hass --script db_migrator --config /path/to/config
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -278,6 +278,12 @@ plt.savefig(<span class="string"><span class="delimiter">'</span><span class="co
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -301,12 +307,6 @@ plt.savefig(<span class="string"><span class="delimiter">'</span><span class="co
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -235,6 +235,12 @@ One of the graphs created with this tutorial.
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -258,12 +264,6 @@ One of the graphs created with this tutorial.
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -336,6 +336,12 @@ PIN = <span class="integer">5</span>
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -359,8 +365,6 @@ PIN = <span class="integer">5</span>
</li>
</ul>
</section>

View file

@ -237,6 +237,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -256,12 +262,6 @@
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -276,6 +276,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -295,12 +301,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -312,6 +312,12 @@ document.body.appendChild(spinner);
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -331,12 +337,6 @@ document.body.appendChild(spinner);
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -232,6 +232,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
@ -251,12 +257,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -0,0 +1,378 @@
<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>We Have Apps Now - Home Assistant</title>
<meta name="author" content="Andrew Cockburn">
<meta name="description" content="A new subsystem that allows automations to be coded using Python">
<meta name="viewport" content="width=device-width">
<link rel="canonical" href="https://home-assistant.io/blog/2016/08/16/we-have-apps-now/">
<meta property="fb:app_id" content="338291289691179">
<meta property="og:title" content="We Have Apps Now">
<meta property="og:site_name" content="Home Assistant">
<meta property="og:url" content="https://home-assistant.io/blog/2016/08/16/we-have-apps-now/">
<meta property="og:type" content="article">
<meta property="og:description" content="A new subsystem that allows automations to be coded using Python">
<meta property="og:image" content="https://home-assistant.io/images/blog/default-social.png">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@home_assistant">
<meta name="twitter:title" content="We Have Apps Now">
<meta name="twitter:description" content="A new subsystem that allows automations to be coded using Python">
<meta name="twitter:image" content="https://home-assistant.io/images/blog/default-social.png">
<link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet">
<link href="/atom.xml" rel="alternate" title="Home Assistant" type="application/atom+xml">
<link rel='shortcut icon' href='/images/favicon.ico' />
<link rel='icon' type='image/png' href='/images/favicon-192x192.png' sizes='192x192' />
</head>
<body >
<header>
<div class="grid-wrapper">
<div class="grid">
<div class="grid__item three-tenths lap-two-sixths palm-one-whole ha-title">
<a href="/" class="site-title">
<img width='40' src='/demo/favicon-192x192.png'>
<span>Home Assistant</span>
</a>
</div>
<div class="grid__item seven-tenths lap-four-sixths palm-one-whole">
<nav>
<input type="checkbox" id="toggle">
<label for="toggle" class="toggle" data-open="Main Menu" data-close="Close Menu"></label>
<ul class="menu pull-right">
<li><a href='/getting-started/'>Getting started</a></li>
<li><a href='/components/'>Components</a></li>
<li><a href='/cookbook/'>Examples</a></li>
<li><a href="/developers/">Developers</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/help/">Need help?</a></li>
</ul>
</nav>
</div>
</div>
</div>
</header>
<div class="grid-wrapper">
<div class="grid grid-center">
<div class="grid__item two-thirds lap-one-whole palm-one-whole">
<article class="post">
<header>
<h1 class="title indent">We Have Apps Now</h1>
<div class="meta clearfix">
<time datetime="2016-08-16T10:00:00+00:00" pubdate data-updated="true"><i class="icon-calendar"></i> August 16, 2016</time>
<span class="byline author vcard"><i class='icon-user'></i> Andrew Cockburn</span>
<span><i class='icon-time'></i> 10 minutes reading time</span>
<span>
<i class="icon-tags"></i>
<ul class="tags unstyled">
<li><a class='category' href='/blog/categories/how-to/'>How-To</a></li>
</ul>
</span>
<a class='comments'
href="#disqus_thread"
>Comments</a>
</div>
</header>
<p>I have been working on a new subsystem to complement Home Assistants Automation and Scripting components. <code>AppDaemon</code> is a python daemon that consumes events from Home Assistant and feeds them to snippets of python code called “Apps”. An App is a Python class that is instantiated possibly multiple times from <code>AppDaemon</code> and registers callbacks for various system events. It is also able to inspect and set state and call services. The API provides a rich environment suited to home automation tasks that can also leverage all the power of Python.</p>
<a name="read-more"></a>
<h2><a class="title-link" name="another-take-on-automation" href="#another-take-on-automation"></a> Another Take on Automation</h2>
<p>If you havent yet read Paulus excellent Blog entry on <a href="https://home-assistant.io/blog/2016/01/19/perfect-home-automation/">Perfect Home Automation</a> I would encourage you to take a look. As a veteran of several Home Automation systems with varying degrees success, it was this article more than anything else that convinced me that Home Assistant had the right philosophy behind it and was on the right track. One of the most important points made is that being able to control your lights from your phone, 9 times out of 10 is harder than using a lightswitch - where Home Automation really comes into its own is when you start removing the need to use a phone or the switch - the “Automation” in Home Automation. A surprisingly large number of systems out there miss this essential point and have limited abilities to automate anything which is why a robust and open system such as Home Assistant is such an important part of the equation to bring this all together in the vast and chaotic ecosystem that is the “Internet of Things”.</p>
<p>So given the importance of Automation, what should Automation allow us to do? I am a pragmatist at heart so I judge individual systems by the ease of accomplishing a few basic but representative tasks:</p>
<ul>
<li>Can the system respond to presence or absence of people?</li>
<li>Can I turn a light on at Sunset +/- a certain amount of time?</li>
<li>Can I arrive home in light or dark and have the lights figure out if they should be on or off?</li>
<li>As I build my system out, can I get the individual pieces to co-operate and use and re-use (potentially complex) logic to make sure everything works smoothly?</li>
<li>Is it open and expandable?</li>
<li>Does it run locally without any reliance on the cloud?</li>
</ul>
<p>In my opinion, Home Assistant accomplishes the majority of these very well with a combination of Automations, Scripts and Templates, and its Restful API.</p>
<p>So why <code>AppDaemon</code>? <code>AppDaemon</code> is not meant to replace Home Assistant Automations and Scripts, rather complement them. For a lot of things, automations work well and can be very succinct. However, there is a class of more complex automations for which they become harder to use, and appdeamon then comes into its own. It brings quite a few things to the table:</p>
<ul>
<li>New paradigm - some problems require a procedural and/or iterative approach, and <code>AppDaemon</code> Apps are a much more natural fit for this. Recent enhancements to Home Assistant scripts and templates have made huge strides, but for the most complex scenarios, Apps can do things that Automations cant</li>
<li>Ease of use - <code>AppDaemon</code>s API is full of helper functions that make programming as easy and natural as possible. The functions and their operation are as “Pythonic” as possible, experienced Python programmers should feel right at home.</li>
<li>Reuse - write a piece of code once and instantiate it as an app as many times as you need with different parameters e.g. a motion light program that you can use in 5 different places around your home. The code stays the same, you just dynamically add new instances of it in the config file</li>
<li>Dynamic - <code>AppDaemon</code> has been designed from the start to enable the user to make changes without requiring a restart of Home Assistant, thanks to its loose coupling. However, it is better than that - the user can make changes to code and <code>AppDaemon</code> will automatically reload the code, figure out which Apps were using it and restart them to use the new code without the need to restart <code>AppDaemon</code> itself. It is also possible to change parameters for an individual or multiple apps and have them picked up dynamically, and for a final trick, removing or adding apps is also picked up dynamically. Testing cycles become a lot more efficient as a result.</li>
<li>Complex logic - Pythons If/Else constructs are clearer and easier to code for arbitrarily complex nested logic</li>
<li>Durable variables and state - variables can be kept between events to keep track of things like the number of times a motion sensor has been activated, or how long it has been since a door opened</li>
<li>All the power of Python - use any of Pythons libraries, create your own modules, share variables, refactor and re-use code, create a single app to do everything, or multiple apps for individual tasks - nothing is off limits!</li>
</ul>
<p>It is in fact a testament to Home Assistants open nature that a component like <code>AppDaemon</code> can be integrated so neatly and closely that it acts in all ways like an extension of the system, not a second class citizen. Part of the strength of Home Assistants underlying design is that it makes no assumptions whatever about what it is controlling or reacting to, or reporting state on. This is made achievable in part by the great flexibility of Python as a programming environment for Home Assistant, and carrying that forward has enabled me to use the same philosophy for <code>AppDaemon</code> - it took surprisingly little code to be able to respond to basic events and call services in a completely open ended manner - the bulk of the work after that was adding additonal functions to make things that were already possible easier.</p>
<h2><a class="title-link" name="how-it-works" href="#how-it-works"></a> How it Works</h2>
<p>The best way to show what <code>AppDaemon</code> does is through a few simple examples.</p>
<h3><a class="title-link" name="sunrisesunset-lighting" href="#sunrisesunset-lighting"></a> Sunrise/Sunset Lighting</h3>
<p>Lets start with a simple App to turn a light on every night at sunset and off every morning at sunrise. Every App when first started will have its <code>initialize()</code> function called which gives it a chance to register a callback for <code>AppDaemons</code>s scheduler for a specific time. In this case we are using <code>run_at_sunrise()</code> and <code>run_at_sunset()</code> to register 2 separate callbacks. The argument <code>0</code> is the number of seconds offset from sunrise or sunset and can be negative or positive. For complex intervals it can be convenient to use Pythons <code>datetime.timedelta</code> class for calculations. When sunrise or sunset occurs, the appropriate callback function, <code>sunrise_cb()</code> or <code>sunset_cb()</code> is called which then makes a call to Home Assistant to turn the porch light on or off by activating a scene. The variables <code>args["on_scene"]</code> and <code>args["off_scene"]</code> are passed through from the configuration of this particular App, and the same code could be reused to activate completely different scenes in a different version of the App.</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre><span class="keyword">import</span> <span class="include">appapi</span>
<span class="keyword">class</span> <span class="class">OutsideLights</span>(appapi.AppDaemon):
<span class="keyword">def</span> <span class="function">initialize</span>(<span class="predefined-constant">self</span>):
<span class="predefined-constant">self</span>.run_at_sunrise(<span class="predefined-constant">self</span>.sunrise_cb, <span class="integer">0</span>)
<span class="predefined-constant">self</span>.run_at_sunset(<span class="predefined-constant">self</span>.sunset_cb, <span class="integer">0</span>)
<span class="keyword">def</span> <span class="function">sunrise_cb</span>(<span class="predefined-constant">self</span>, args, kwargs):
<span class="predefined-constant">self</span>.turn_on(<span class="predefined-constant">self</span>.args[<span class="string"><span class="delimiter">&quot;</span><span class="content">off_scene</span><span class="delimiter">&quot;</span></span>])
<span class="keyword">def</span> <span class="function">sunset_cb</span>(<span class="predefined-constant">self</span>, args, kwargs):
<span class="predefined-constant">self</span>.turn_on(<span class="predefined-constant">self</span>.args[<span class="string"><span class="delimiter">&quot;</span><span class="content">on_scene</span><span class="delimiter">&quot;</span></span>])
</pre></div>
</div>
</div>
<p>This is also fairly easy to achieve with Home Assistant automations, but we are just getting started.</p>
<h3><a class="title-link" name="motion-light" href="#motion-light"></a> Motion Light</h3>
<p>Our next example is to turn on a light when motion is detected and it is dark, and turn it off after a period of time. This time, the <code>initialize()</code> function registers a callback on a state change (of the motion sensor) rather than a specific time. We tell <code>AppDaemon</code> that we are only interested in state changes where the motion detector comes on by adding an additional parameter to the callback registration - <code>new = "on"</code>. When the motion is detected, the callack function <code>motion()</code> is called, and we check whether or not the sun has set using a built-in convenience function: <code>sun_down()</code>. Next, we turn the light on with <code>turn_on()</code>, then set a timer using <code>run_in()</code> to turn the light off after 60 seconds, which is another call to the scheduler to execute in a set time from now, which results in <code>AppDaemon</code> calling <code>light_off()</code> 60 seconds later using the <code>turn_off()</code> call to actually turn the light off. This is still pretty simple in code terms:</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre><span class="keyword">import</span> <span class="include">appapi</span>
<span class="keyword">class</span> <span class="class">MotionLights</span>(appapi.AppDaemon):
<span class="keyword">def</span> <span class="function">initialize</span>(<span class="predefined-constant">self</span>):
<span class="predefined-constant">self</span>.listen_state(<span class="predefined-constant">self</span>.motion, <span class="string"><span class="delimiter">&quot;</span><span class="content">binary_sensor.drive</span><span class="delimiter">&quot;</span></span>, new = <span class="string"><span class="delimiter">&quot;</span><span class="content">on</span><span class="delimiter">&quot;</span></span>)
<span class="keyword">def</span> <span class="function">motion</span>(<span class="predefined-constant">self</span>, entity, attribute, old, new, kwargs):
<span class="keyword">if</span> <span class="predefined-constant">self</span>.sun_down():
<span class="predefined-constant">self</span>.turn_on(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.drive</span><span class="delimiter">&quot;</span></span>)
<span class="predefined-constant">self</span>.run_in(<span class="predefined-constant">self</span>.light_off, <span class="integer">60</span>)
<span class="keyword">def</span> <span class="function">light_off</span>(<span class="predefined-constant">self</span>, kwargs):
<span class="predefined-constant">self</span>.turn_off(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.drive</span><span class="delimiter">&quot;</span></span>)
</pre></div>
</div>
</div>
<p>This is starting to get a little more complex in Home Assistant automations requiring an Automation rule and two separate scripts.</p>
<p>Now lets extend this with a somewhat artificial example to show something that is simple in <code>AppDaemon</code> but very difficult if not impossible using automations. Lets warn someone inside the house that there has been motion outside by flashing a lamp on and off 10 times. We are reacting to the motion as before by turning on the light and setting a timer to turn it off again, but in addition, we set a 1 second timer to run <code>flash_warning()</code> which when called, toggles the inside light and sets another timer to call itself a second later. To avoid re-triggering forever, it keeps a count of how many times it has been activated and bales out after 10 iterations.</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre><span class="keyword">import</span> <span class="include">appapi</span>
<span class="keyword">class</span> <span class="class">FlashyMotionLights</span>(appapi.AppDaemon):
<span class="keyword">def</span> <span class="function">initialize</span>(<span class="predefined-constant">self</span>):
<span class="predefined-constant">self</span>.listen_state(<span class="predefined-constant">self</span>.motion, <span class="string"><span class="delimiter">&quot;</span><span class="content">binary_sensor.drive</span><span class="delimiter">&quot;</span></span>, new = <span class="string"><span class="delimiter">&quot;</span><span class="content">on</span><span class="delimiter">&quot;</span></span>)
<span class="keyword">def</span> <span class="function">motion</span>(<span class="predefined-constant">self</span>, entity, attribute, old, new, kwargs):
<span class="keyword">if</span> <span class="predefined-constant">self</span>.self.sun_down():
<span class="predefined-constant">self</span>.turn_on(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.drive</span><span class="delimiter">&quot;</span></span>)
<span class="predefined-constant">self</span>.run_in(<span class="predefined-constant">self</span>.light_off, <span class="integer">60</span>)
<span class="predefined-constant">self</span>.flashcount = <span class="integer">0</span>
<span class="predefined-constant">self</span>.run_in(<span class="predefined-constant">self</span>.flash_warning, <span class="integer">1</span>)
<span class="keyword">def</span> <span class="function">light_off</span>(<span class="predefined-constant">self</span>, kwargs):
<span class="predefined-constant">self</span>.turn_off(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.drive</span><span class="delimiter">&quot;</span></span>)
<span class="keyword">def</span> <span class="function">flash_warning</span>(<span class="predefined-constant">self</span>, kwargs):
<span class="predefined-constant">self</span>.toggle(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.living_room</span><span class="delimiter">&quot;</span></span>)
<span class="predefined-constant">self</span>.flashcount += <span class="integer">1</span>
<span class="keyword">if</span> <span class="predefined-constant">self</span>.flashcount &lt; <span class="integer">10</span>:
<span class="predefined-constant">self</span>.run_in(<span class="predefined-constant">self</span>.flash_warning, <span class="integer">1</span>)
</pre></div>
</div>
</div>
<p>Of course if I wanted to make this App or its predecessor reusable I would have provided parameters for the sensor, the light to activate on motion, the warning light and even the number of flashes and delay between flashes.</p>
<p>In addition, Apps can write to <code>AppDaemon</code>s logfiles, and there is a system of constraints that allows yout to control when and under what circumstances Apps and callbacks are active to keep the logic clean and simple.</p>
<p>I have spent the last few weeks moving all of my (fairly complex) automations over to <code>APPDaemon</code> and so far it is working very reliably.</p>
<p>Some people will maybe look at all of this and say “what use is this, I can already do all of this”, and that is fine, as I said this is an alternative not a replacement, but I am hopeful that for some users this will seem a more natural, powerful and nimble way of building potentially very complex automations.</p>
<p>If this has whet your appetite, feel free to give it a try. You can find it, <a href="https://github.com/acockburn/appdaemon">here</a>, including full installation instructions, an API reference, and a number of fully fleshed out examples.</p>
<p>Happy Automating!</p>
</article>
<section id="disqus">
<h3 class="indent title">Comments</h3>
<div id="disqus_thread" aria-live="polite"><noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript></div>
</section>
</div>
<aside id="sidebar" class="grid__item one-third lap-one-whole palm-one-whole">
<div class="grid">
<section class="aside-module grid__item one-whole lap-one-half">
<h1 class="title delta">About Home Assistant</h1>
<ul class="divided">
<li>
Home Assistant is an open-source home automation platform running on Python 3. Track and control all devices at home and automate control.
</li>
<li><a href='/getting-started/'>Get started with Home Assistant</a></li>
<li><a href='/demo/'>Try the online demo</a></li>
<li><a class="twitter-follow-button" href="https://twitter.com/Home_Assistant">Follow Home Assistant on Twitter</a></li>
<li><div class="fb-like" data-href="https://www.facebook.com/homeassistantio/" data-layout="standard" data-action="like" data-size="small" data-show-faces="true" data-share="false"></div></li>
</ul>
</section>
<div id="fb-root"></div>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.async=true;js.src='//platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
<script>(function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(d.getElementById(id)){return;}js=d.createElement(s);js.id=id;js.async=true;js.src="//connect.facebook.net/en_US/all.js#appId=338291289691179&xfbml=1";fjs.parentNode.insertBefore(js,fjs);}(document,'script','facebook-jssdk'));</script>
<section class="sharing aside-module grid__item one-whole lap-one-half">
<h1 class="title delta">Share this post</h1>
<a href="//twitter.com/share"
class="twitter-share-button"
data-via="home_assistant"
data-related="home_assistant"
data-url="https://home-assistant.io/blog/2016/08/16/we-have-apps-now/"
data-counturl="https://home-assistant.io/blog/2016/08/16/we-have-apps-now/" >Tweet</a>
<div class="fb-share-button" style='top: -6px;'
data-href="https://home-assistant.io/blog/2016/08/16/we-have-apps-now/"
data-layout="button_count">
</div>
<div class="g-plusone" data-size="standard"></div>
</section>
<script src="https://apis.google.com/js/platform.js" async defer></script>
<section id="recent-posts" class="aside-module grid__item one-whole lap-one-half">
<h1 class="title delta">Recent Posts</h1>
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
<li class="post">
<a href="/blog/2016/08/07/optimizing-the-home-assistant-mobile-web-app/">Optimizing the Home Assistant mobile web app</a>
</li>
<li class="post">
<a href="/blog/2016/08/03/laundry-automation-update/">Laundry Sensors with NodeMCU and Home Assistant</a>
</li>
<li class="post">
<a href="/blog/2016/07/30/custom-frontend-panels-jupyter-notebooks-directv/">0.25: Custom frontend panels, Jupyter notebooks, DirecTV.</a>
</li>
</ul>
</section>
</div>
</aside>
</div>
</div>
<footer>
<div class="grid-wrapper">
<div class="grid">
<div class="grid__item">
<div class="copyright">
<a rel="me" href='https://twitter.com/home_assistant'><i class="icon-twitter"></i></a>
<a rel="me" href='https://facebook.com/homeassistantio'><i class="icon-facebook"></i></a>
<a rel="me" href='https://plus.google.com/110560654828510104551'><i class="icon-google-plus"></i></a>
<a rel="me" href='https://github.com/home-assistant/home-assistant'><i class="icon-github"></i></a>
<div class="credit">
Contact us at <a href='mailto:hello@home-assistant.io'>hello@home-assistant.io</a>.<br>
Website powered by <a href='http://jekyllrb.com/'>Jekyll</a> and the <a href='https://github.com/coogie/oscailte'>Oscalite theme</a>.<br />
Hosted by <a href='https://pages.github.com/'>GitHub</a> and served by <a href='https://cloudflare.com'>CloudFlare</a>.
</div>
</div>
</div>
</div>
</div>
</footer>
<script>
var _gaq=[['_setAccount','UA-57927901-1'],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>
<script>
var disqus_shortname = 'home-assistant';
// var disqus_developer = 1;
var disqus_identifier = 'https://home-assistant.io/blog/2016/08/16/we-have-apps-now/';
var disqus_url = 'https://home-assistant.io/blog/2016/08/16/we-have-apps-now/';
var disqus_script = 'embed.js';
(function () {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = '//' + disqus_shortname + '.disqus.com/' + disqus_script;
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
}());
</script>
</body>
</html>

View file

@ -98,6 +98,38 @@
<h2>2016</h2>
<article>
<div class="grid">
<div class="grid__item one-fifth palm-one-whole">
<time datetime="2016-08-16T10:00:00+00:00" pubdate>
<span class='month'>Aug</span> <span class='day'>16</span>
</time>
</div>
<div class="grid__item four-fifths palm-one-whole">
<h1 class="gamma"><a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a></h1>
<footer class="meta">
<span>
<i class="icon-tags"></i>
<ul class="tags unstyled">
<li><a class='category' href='/blog/categories/how-to/'>How-To</a></li>
</ul>
</span>
</footer>
<hr class="divider">
</div>
</div>
</article>
<article>
<div class="grid">
@ -2685,6 +2717,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -2708,12 +2746,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -4,7 +4,7 @@
<title><![CDATA[Category: Community | Home Assistant]]></title>
<link href="https://home-assistant.io/blog/categories/community/atom.xml" rel="self"/>
<link href="https://home-assistant.io/"/>
<updated>2016-08-16T09:54:54+00:00</updated>
<updated>2016-08-16T12:17:59+00:00</updated>
<id>https://home-assistant.io/</id>
<author>
<name><![CDATA[Home Assistant]]></name>

View file

@ -258,6 +258,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -281,12 +287,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -4,7 +4,7 @@
<title><![CDATA[Category: Device-Tracking | Home Assistant]]></title>
<link href="https://home-assistant.io/blog/categories/device-tracking/atom.xml" rel="self"/>
<link href="https://home-assistant.io/"/>
<updated>2016-08-16T09:54:54+00:00</updated>
<updated>2016-08-16T12:17:59+00:00</updated>
<id>https://home-assistant.io/</id>
<author>
<name><![CDATA[Home Assistant]]></name>

View file

@ -189,6 +189,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -212,12 +218,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -4,7 +4,7 @@
<title><![CDATA[Category: ESP8266 | Home Assistant]]></title>
<link href="https://home-assistant.io/blog/categories/esp8266/atom.xml" rel="self"/>
<link href="https://home-assistant.io/"/>
<updated>2016-08-16T09:54:54+00:00</updated>
<updated>2016-08-16T12:17:59+00:00</updated>
<id>https://home-assistant.io/</id>
<author>
<name><![CDATA[Home Assistant]]></name>

View file

@ -189,6 +189,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -212,12 +218,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -4,7 +4,7 @@
<title><![CDATA[Category: How-To | Home Assistant]]></title>
<link href="https://home-assistant.io/blog/categories/how-to/atom.xml" rel="self"/>
<link href="https://home-assistant.io/"/>
<updated>2016-08-16T09:54:54+00:00</updated>
<updated>2016-08-16T12:17:59+00:00</updated>
<id>https://home-assistant.io/</id>
<author>
<name><![CDATA[Home Assistant]]></name>
@ -13,6 +13,143 @@
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[We Have Apps Now]]></title>
<link href="https://home-assistant.io/blog/2016/08/16/we-have-apps-now/"/>
<updated>2016-08-16T10:00:00+00:00</updated>
<id>https://home-assistant.io/blog/2016/08/16/we-have-apps-now</id>
<content type="html"><![CDATA[<p>I have been working on a new subsystem to complement Home Assistants Automation and Scripting components. <code>AppDaemon</code> is a python daemon that consumes events from Home Assistant and feeds them to snippets of python code called “Apps”. An App is a Python class that is instantiated possibly multiple times from <code>AppDaemon</code> and registers callbacks for various system events. It is also able to inspect and set state and call services. The API provides a rich environment suited to home automation tasks that can also leverage all the power of Python.</p>
<!--more-->
<h2><a class='title-link' name='another-take-on-automation' href='#another-take-on-automation'></a> Another Take on Automation </h2>
<p>If you havent yet read Paulus excellent Blog entry on <a href="https://home-assistant.io/blog/2016/01/19/perfect-home-automation/">Perfect Home Automation</a> I would encourage you to take a look. As a veteran of several Home Automation systems with varying degrees success, it was this article more than anything else that convinced me that Home Assistant had the right philosophy behind it and was on the right track. One of the most important points made is that being able to control your lights from your phone, 9 times out of 10 is harder than using a lightswitch - where Home Automation really comes into its own is when you start removing the need to use a phone or the switch - the “Automation” in Home Automation. A surprisingly large number of systems out there miss this essential point and have limited abilities to automate anything which is why a robust and open system such as Home Assistant is such an important part of the equation to bring this all together in the vast and chaotic ecosystem that is the “Internet of Things”.</p>
<p>So given the importance of Automation, what should Automation allow us to do? I am a pragmatist at heart so I judge individual systems by the ease of accomplishing a few basic but representative tasks:</p>
<ul>
<li>Can the system respond to presence or absence of people?</li>
<li>Can I turn a light on at Sunset +/- a certain amount of time?</li>
<li>Can I arrive home in light or dark and have the lights figure out if they should be on or off?</li>
<li>As I build my system out, can I get the individual pieces to co-operate and use and re-use (potentially complex) logic to make sure everything works smoothly?</li>
<li>Is it open and expandable?</li>
<li>Does it run locally without any reliance on the cloud?</li>
</ul>
<p>In my opinion, Home Assistant accomplishes the majority of these very well with a combination of Automations, Scripts and Templates, and its Restful API.</p>
<p>So why <code>AppDaemon</code>? <code>AppDaemon</code> is not meant to replace Home Assistant Automations and Scripts, rather complement them. For a lot of things, automations work well and can be very succinct. However, there is a class of more complex automations for which they become harder to use, and appdeamon then comes into its own. It brings quite a few things to the table:</p>
<ul>
<li>New paradigm - some problems require a procedural and/or iterative approach, and <code>AppDaemon</code> Apps are a much more natural fit for this. Recent enhancements to Home Assistant scripts and templates have made huge strides, but for the most complex scenarios, Apps can do things that Automations cant</li>
<li>Ease of use - <code>AppDaemon</code>s API is full of helper functions that make programming as easy and natural as possible. The functions and their operation are as “Pythonic” as possible, experienced Python programmers should feel right at home.</li>
<li>Reuse - write a piece of code once and instantiate it as an app as many times as you need with different parameters e.g. a motion light program that you can use in 5 different places around your home. The code stays the same, you just dynamically add new instances of it in the config file</li>
<li>Dynamic - <code>AppDaemon</code> has been designed from the start to enable the user to make changes without requiring a restart of Home Assistant, thanks to its loose coupling. However, it is better than that - the user can make changes to code and <code>AppDaemon</code> will automatically reload the code, figure out which Apps were using it and restart them to use the new code without the need to restart <code>AppDaemon</code> itself. It is also possible to change parameters for an individual or multiple apps and have them picked up dynamically, and for a final trick, removing or adding apps is also picked up dynamically. Testing cycles become a lot more efficient as a result.</li>
<li>Complex logic - Pythons If/Else constructs are clearer and easier to code for arbitrarily complex nested logic</li>
<li>Durable variables and state - variables can be kept between events to keep track of things like the number of times a motion sensor has been activated, or how long it has been since a door opened</li>
<li>All the power of Python - use any of Pythons libraries, create your own modules, share variables, refactor and re-use code, create a single app to do everything, or multiple apps for individual tasks - nothing is off limits!</li>
</ul>
<p>It is in fact a testament to Home Assistants open nature that a component like <code>AppDaemon</code> can be integrated so neatly and closely that it acts in all ways like an extension of the system, not a second class citizen. Part of the strength of Home Assistants underlying design is that it makes no assumptions whatever about what it is controlling or reacting to, or reporting state on. This is made achievable in part by the great flexibility of Python as a programming environment for Home Assistant, and carrying that forward has enabled me to use the same philosophy for <code>AppDaemon</code> - it took surprisingly little code to be able to respond to basic events and call services in a completely open ended manner - the bulk of the work after that was adding additonal functions to make things that were already possible easier.</p>
<h2><a class='title-link' name='how-it-works' href='#how-it-works'></a> How it Works </h2>
<p>The best way to show what <code>AppDaemon</code> does is through a few simple examples.</p>
<h3><a class='title-link' name='sunrisesunset-lighting' href='#sunrisesunset-lighting'></a> Sunrise/Sunset Lighting </h3>
<p>Lets start with a simple App to turn a light on every night at sunset and off every morning at sunrise. Every App when first started will have its <code>initialize()</code> function called which gives it a chance to register a callback for <code>AppDaemons</code>s scheduler for a specific time. In this case we are using <code>run_at_sunrise()</code> and <code>run_at_sunset()</code> to register 2 separate callbacks. The argument <code>0</code> is the number of seconds offset from sunrise or sunset and can be negative or positive. For complex intervals it can be convenient to use Pythons <code>datetime.timedelta</code> class for calculations. When sunrise or sunset occurs, the appropriate callback function, <code>sunrise_cb()</code> or <code>sunset_cb()</code> is called which then makes a call to Home Assistant to turn the porch light on or off by activating a scene. The variables <code>args["on_scene"]</code> and <code>args["off_scene"]</code> are passed through from the configuration of this particular App, and the same code could be reused to activate completely different scenes in a different version of the App.</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre><span class="keyword">import</span> <span class="include">appapi</span>
<span class="keyword">class</span> <span class="class">OutsideLights</span>(appapi.AppDaemon):
<span class="keyword">def</span> <span class="function">initialize</span>(<span class="predefined-constant">self</span>):
<span class="predefined-constant">self</span>.run_at_sunrise(<span class="predefined-constant">self</span>.sunrise_cb, <span class="integer">0</span>)
<span class="predefined-constant">self</span>.run_at_sunset(<span class="predefined-constant">self</span>.sunset_cb, <span class="integer">0</span>)
<span class="keyword">def</span> <span class="function">sunrise_cb</span>(<span class="predefined-constant">self</span>, args, kwargs):
<span class="predefined-constant">self</span>.turn_on(<span class="predefined-constant">self</span>.args[<span class="string"><span class="delimiter">&quot;</span><span class="content">off_scene</span><span class="delimiter">&quot;</span></span>])
<span class="keyword">def</span> <span class="function">sunset_cb</span>(<span class="predefined-constant">self</span>, args, kwargs):
<span class="predefined-constant">self</span>.turn_on(<span class="predefined-constant">self</span>.args[<span class="string"><span class="delimiter">&quot;</span><span class="content">on_scene</span><span class="delimiter">&quot;</span></span>])
</pre></div>
</div>
</div>
<p>This is also fairly easy to achieve with Home Assistant automations, but we are just getting started.</p>
<h3><a class='title-link' name='motion-light' href='#motion-light'></a> Motion Light </h3>
<p>Our next example is to turn on a light when motion is detected and it is dark, and turn it off after a period of time. This time, the <code>initialize()</code> function registers a callback on a state change (of the motion sensor) rather than a specific time. We tell <code>AppDaemon</code> that we are only interested in state changes where the motion detector comes on by adding an additional parameter to the callback registration - <code>new = "on"</code>. When the motion is detected, the callack function <code>motion()</code> is called, and we check whether or not the sun has set using a built-in convenience function: <code>sun_down()</code>. Next, we turn the light on with <code>turn_on()</code>, then set a timer using <code>run_in()</code> to turn the light off after 60 seconds, which is another call to the scheduler to execute in a set time from now, which results in <code>AppDaemon</code> calling <code>light_off()</code> 60 seconds later using the <code>turn_off()</code> call to actually turn the light off. This is still pretty simple in code terms:</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre><span class="keyword">import</span> <span class="include">appapi</span>
<span class="keyword">class</span> <span class="class">MotionLights</span>(appapi.AppDaemon):
<span class="keyword">def</span> <span class="function">initialize</span>(<span class="predefined-constant">self</span>):
<span class="predefined-constant">self</span>.listen_state(<span class="predefined-constant">self</span>.motion, <span class="string"><span class="delimiter">&quot;</span><span class="content">binary_sensor.drive</span><span class="delimiter">&quot;</span></span>, new = <span class="string"><span class="delimiter">&quot;</span><span class="content">on</span><span class="delimiter">&quot;</span></span>)
<span class="keyword">def</span> <span class="function">motion</span>(<span class="predefined-constant">self</span>, entity, attribute, old, new, kwargs):
<span class="keyword">if</span> <span class="predefined-constant">self</span>.sun_down():
<span class="predefined-constant">self</span>.turn_on(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.drive</span><span class="delimiter">&quot;</span></span>)
<span class="predefined-constant">self</span>.run_in(<span class="predefined-constant">self</span>.light_off, <span class="integer">60</span>)
<span class="keyword">def</span> <span class="function">light_off</span>(<span class="predefined-constant">self</span>, kwargs):
<span class="predefined-constant">self</span>.turn_off(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.drive</span><span class="delimiter">&quot;</span></span>)
</pre></div>
</div>
</div>
<p>This is starting to get a little more complex in Home Assistant automations requiring an Automation rule and two separate scripts.</p>
<p>Now lets extend this with a somewhat artificial example to show something that is simple in <code>AppDaemon</code> but very difficult if not impossible using automations. Lets warn someone inside the house that there has been motion outside by flashing a lamp on and off 10 times. We are reacting to the motion as before by turning on the light and setting a timer to turn it off again, but in addition, we set a 1 second timer to run <code>flash_warning()</code> which when called, toggles the inside light and sets another timer to call itself a second later. To avoid re-triggering forever, it keeps a count of how many times it has been activated and bales out after 10 iterations.</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre><span class="keyword">import</span> <span class="include">appapi</span>
<span class="keyword">class</span> <span class="class">FlashyMotionLights</span>(appapi.AppDaemon):
<span class="keyword">def</span> <span class="function">initialize</span>(<span class="predefined-constant">self</span>):
<span class="predefined-constant">self</span>.listen_state(<span class="predefined-constant">self</span>.motion, <span class="string"><span class="delimiter">&quot;</span><span class="content">binary_sensor.drive</span><span class="delimiter">&quot;</span></span>, new = <span class="string"><span class="delimiter">&quot;</span><span class="content">on</span><span class="delimiter">&quot;</span></span>)
<span class="keyword">def</span> <span class="function">motion</span>(<span class="predefined-constant">self</span>, entity, attribute, old, new, kwargs):
<span class="keyword">if</span> <span class="predefined-constant">self</span>.self.sun_down():
<span class="predefined-constant">self</span>.turn_on(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.drive</span><span class="delimiter">&quot;</span></span>)
<span class="predefined-constant">self</span>.run_in(<span class="predefined-constant">self</span>.light_off, <span class="integer">60</span>)
<span class="predefined-constant">self</span>.flashcount = <span class="integer">0</span>
<span class="predefined-constant">self</span>.run_in(<span class="predefined-constant">self</span>.flash_warning, <span class="integer">1</span>)
<span class="keyword">def</span> <span class="function">light_off</span>(<span class="predefined-constant">self</span>, kwargs):
<span class="predefined-constant">self</span>.turn_off(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.drive</span><span class="delimiter">&quot;</span></span>)
<span class="keyword">def</span> <span class="function">flash_warning</span>(<span class="predefined-constant">self</span>, kwargs):
<span class="predefined-constant">self</span>.toggle(<span class="string"><span class="delimiter">&quot;</span><span class="content">light.living_room</span><span class="delimiter">&quot;</span></span>)
<span class="predefined-constant">self</span>.flashcount += <span class="integer">1</span>
<span class="keyword">if</span> <span class="predefined-constant">self</span>.flashcount &lt; <span class="integer">10</span>:
<span class="predefined-constant">self</span>.run_in(<span class="predefined-constant">self</span>.flash_warning, <span class="integer">1</span>)
</pre></div>
</div>
</div>
<p>Of course if I wanted to make this App or its predecessor reusable I would have provided parameters for the sensor, the light to activate on motion, the warning light and even the number of flashes and delay between flashes.</p>
<p>In addition, Apps can write to <code>AppDaemon</code>s logfiles, and there is a system of constraints that allows yout to control when and under what circumstances Apps and callbacks are active to keep the logic clean and simple.</p>
<p>I have spent the last few weeks moving all of my (fairly complex) automations over to <code>APPDaemon</code> and so far it is working very reliably.</p>
<p>Some people will maybe look at all of this and say “what use is this, I can already do all of this”, and that is fine, as I said this is an alternative not a replacement, but I am hopeful that for some users this will seem a more natural, powerful and nimble way of building potentially very complex automations.</p>
<p>If this has whet your appetite, feel free to give it a try. You can find it, <a href="https://github.com/acockburn/appdaemon">here</a>, including full installation instructions, an API reference, and a number of fully fleshed out examples.</p>
<p>Happy Automating!</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[ESP8266 and MicroPython - Part 1]]></title>
<link href="https://home-assistant.io/blog/2016/07/28/esp8266-and-micropython-part1/"/>
@ -444,137 +581,6 @@ $ hass --open-ui
<p>Well, with PocketCHIP and Home Assistant you could run your home automation on a 49 USD device with a touchscreen, an integrated USP, and a keyboard. With the GPIO available on top of the display you could even connect your PocketCHIP directly to sensors and actuators.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Using USB webcams with Home Assistant]]></title>
<link href="https://home-assistant.io/blog/2016/06/23/usb-webcams-and-home-assistant/"/>
<updated>2016-06-23T06:00:00+00:00</updated>
<id>https://home-assistant.io/blog/2016/06/23/usb-webcams-and-home-assistant</id>
<content type="html"><![CDATA[<p><img src="https://home-assistant.io/images/blog/2016-06-cranberry/motion.png" style="clear: right; border:none; box-shadow: none; float: right; margin-bottom: 12px;" width="200" /><br />
In the past month I was thinking about ways to integrate USB webcams into Home Assistant again. The main reason was that this would give those devices a second life and enable one to benefit from low-cost video surveillance. There are a couple of options available like <a href="http://www.pygame.org/hifi.html">pygame</a> or <a href="http://www.simplecv.org/">SimpleCV</a> but I never finished something. With the <a href="https://home-assistant.io/components/camera.local_file/">Local File camera platform</a> by <a href="https://github.com/Landrash">Landrash</a> and <a href="http://lavrsen.dk/foswiki/bin/view/Motion/WebHome">motion</a> you could integrate a local USB webcam with a few very easy steps.</p>
<p>In this blog post I am using a Fedora 24 (will most likely work on other distributions too) installation with Home Assistant 0.22.1 on a Foxconn nT-330i with an old <a href="http://support.logitech.com/en_us/product/quickcam-sphere-af">Logitech QuickCam Orbit AF</a> and a <a href="http://support.logitech.com/en_us/product/hd-webcam-c270">Logitech HD Webcam C270</a>. As a start only the Quickcam is used. No multi-camera setup for now.</p>
<!--more-->
<p>Check first if the your operating system lists your cameras.</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre>$ lsusb
[...]
Bus 002 Device 016: ID 046d:08cc Logitech, Inc. Mic (PTZ)
[...]
</pre></div>
</div>
</div>
<p>The camera we are going to use is available at <code>/dev/video1</code>. The C270 is the one on <code>/dev/video0</code>.</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre>$ ls -al /dev/video*
crw-rw----+ 1 root video 81, 0 Jun 23 08:05 /dev/video0
crw-rw----+ 1 root video 81, 1 Jun 23 08:36 /dev/video1
</pre></div>
</div>
</div>
<p>We need an additional software part to handle the cameras. <a href="http://lavrsen.dk/foswiki/bin/view/Motion/WebHome">motion</a> is capable of monitoring the video signal from USB and network cameras, do motion detection, and other nifty stuff like saving images, add text, or basic image manipulations. Make sure that you have the <a href="http://rpmfusion.org/">RPM Fusion respository</a> enabled.</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre>$ sudo dnf -y install motion
</pre></div>
</div>
</div>
<p>For our setup we need to modify the file <code>/etc/motion/motion.conf</code>. For now the most important parameters are <code>videodevice</code>, <code>snapshot_interval</code>, and <code>target_dir</code>. The other settings can be left to their defaults. We are going to use the device <code>/dev/video1</code>, use a 30 seconds interval, and set the path to <code>/tmp</code>.</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre>[...]
###########################################################
# Capture device options
############################################################
# Videodevice to be used for capturing (default /dev/video0)
# for FreeBSD default is /dev/bktr0
videodevice /dev/video1
[..]
############################################################
# Snapshots (Traditional Periodic Webcam File Output)
############################################################
# Make automated snapshot every N seconds (default: 0 = disabled)
snapshot_interval 30
[...]
############################################################
# Target Directories and filenames For Images And Films
# For the options snapshot_, picture_, movie_ and timelapse_filename
# you can use conversion specifiers
# %Y = year, %m = month, %d = date,
# %H = hour, %M = minute, %S = second,
# %v = event, %q = frame number, %t = thread (camera) number,
# %D = changed pixels, %N = noise level,
# %i and %J = width and height of motion area,
# %K and %L = X and Y coordinates of motion center
# %C = value defined by text_event
# Quotation marks round string are allowed.
############################################################
# Target base directory for pictures and films
# Recommended to use absolute path. (Default: current working directory)
target_dir /tmp
[...]
</pre></div>
</div>
</div>
<p>Its suggested that you adjust at least <code>width</code> and <code>height</code> to get a bigger image from your camera. If you are done, fire up <code>motion</code>.</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre>$ sudo motion
[0] [NTC] [ALL] conf_load: Processing thread 0 - config file /etc/motion/motion.conf
[0] [ALR] [ALL] conf_cmdparse: Unknown config option &quot;sdl_threadnr&quot;
[0] [NTC] [ALL] motion_startup: Motion 3.3.0 Started
[0] [NTC] [ALL] motion_startup: Logging to file (/var/log/motion.log)
</pre></div>
</div>
</div>
<p>Your <code>target_dir</code> will start filling up with images from your camera. <code>motion</code> will create a symlink called <code>lastsnap.jpg</code> which always point to the latest snapshot. We will setup the <a href="https://home-assistant.io/components/camera.local_file/">Local File camera platform</a> to use this file.</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre><span class="key">camera</span>:
- <span class="string"><span class="content">platform: local_file</span></span>
<span class="key">name</span>: <span class="string"><span class="content">Cranberry cam</span></span>
<span class="key">file_path</span>: <span class="string"><span class="content">/tmp/lastsnap.jpg</span></span>
</pre></div>
</div>
</div>
<p class="img">
<img src="https://home-assistant.io/images/blog/2016-06-cranberry/cam.png" />
The “Cranberry cam” in action
</p>
<p>The machine with the attached USB camera will become a webcam server as well because <code>motion</code>s built-in HTTP server is enabled by default. This means that you could connect your USB webcams to a different machine in your network, run <code>motion</code> there, adjust your firewall rules, and use Home Assistant to display the videos. Just check http://[IP of your webcam host]:8081/ to see the stream. This required more powerful hardware than using snapshots, of course.</p>
<p>In a scenario like this needs a <a href="https://home-assistant.io/components/camera.mjpeg/">Generic MJPEG IP Camera </a> in your <code>configuration.yaml</code> file.</p>
<div class="highlighter-coderay"><div class="CodeRay">
<div class="code"><pre><span class="key">camera</span>:
- <span class="string"><span class="content">platform: mjpeg</span></span>
<span class="key">mjpeg_url</span>: <span class="string"><span class="content">http://[IP of your webcam host]:8081</span></span>
<span class="key">name</span>: <span class="string"><span class="content">Cranberry Live cam</span></span>
</pre></div>
</div>
</div>
<p><a href="http://lavrsen.dk/foswiki/bin/view/Motion/WebHome">motion</a> is a powerful tool and this blog post only showed two very simple use cases. Take a look at the <a href="http://www.lavrsen.dk/foswiki/bin/view/Motion/MotionGuide">documentation</a> of <code>motion</code> to unleash its potential.</p>
]]></content>
</entry>

View file

@ -98,6 +98,38 @@
<h2>2016</h2>
<article>
<div class="grid">
<div class="grid__item one-fifth palm-one-whole">
<time datetime="2016-08-16T10:00:00+00:00" pubdate>
<span class='month'>Aug</span> <span class='day'>16</span>
</time>
</div>
<div class="grid__item four-fifths palm-one-whole">
<h1 class="gamma"><a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a></h1>
<footer class="meta">
<span>
<i class="icon-tags"></i>
<ul class="tags unstyled">
<li><a class='category' href='/blog/categories/how-to/'>How-To</a></li>
</ul>
</span>
</footer>
<hr class="divider">
</div>
</div>
</article>
<article>
<div class="grid">
@ -650,6 +682,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -673,12 +711,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -4,7 +4,7 @@
<title><![CDATA[Category: iBeacons | Home Assistant]]></title>
<link href="https://home-assistant.io/blog/categories/ibeacons/atom.xml" rel="self"/>
<link href="https://home-assistant.io/"/>
<updated>2016-08-16T09:54:54+00:00</updated>
<updated>2016-08-16T12:17:59+00:00</updated>
<id>https://home-assistant.io/</id>
<author>
<name><![CDATA[Home Assistant]]></name>

View file

@ -225,6 +225,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -248,12 +254,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -4,7 +4,7 @@
<title><![CDATA[Category: Internet-of-Things | Home Assistant]]></title>
<link href="https://home-assistant.io/blog/categories/internet-of-things/atom.xml" rel="self"/>
<link href="https://home-assistant.io/"/>
<updated>2016-08-16T09:54:54+00:00</updated>
<updated>2016-08-16T12:17:59+00:00</updated>
<id>https://home-assistant.io/</id>
<author>
<name><![CDATA[Home Assistant]]></name>

View file

@ -284,6 +284,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -307,12 +313,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -4,7 +4,7 @@
<title><![CDATA[Category: IoT-Data | Home Assistant]]></title>
<link href="https://home-assistant.io/blog/categories/iot-data/atom.xml" rel="self"/>
<link href="https://home-assistant.io/"/>
<updated>2016-08-16T09:54:54+00:00</updated>
<updated>2016-08-16T12:17:59+00:00</updated>
<id>https://home-assistant.io/</id>
<author>
<name><![CDATA[Home Assistant]]></name>

View file

@ -221,6 +221,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -244,12 +250,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -4,7 +4,7 @@
<title><![CDATA[Category: MQTT | Home Assistant]]></title>
<link href="https://home-assistant.io/blog/categories/mqtt/atom.xml" rel="self"/>
<link href="https://home-assistant.io/"/>
<updated>2016-08-16T09:54:54+00:00</updated>
<updated>2016-08-16T12:17:59+00:00</updated>
<id>https://home-assistant.io/</id>
<author>
<name><![CDATA[Home Assistant]]></name>

View file

@ -260,6 +260,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -283,12 +289,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -4,7 +4,7 @@
<title><![CDATA[Category: Organisation | Home Assistant]]></title>
<link href="https://home-assistant.io/blog/categories/organisation/atom.xml" rel="self"/>
<link href="https://home-assistant.io/"/>
<updated>2016-08-16T09:54:54+00:00</updated>
<updated>2016-08-16T12:17:59+00:00</updated>
<id>https://home-assistant.io/</id>
<author>
<name><![CDATA[Home Assistant]]></name>

View file

@ -220,6 +220,12 @@
<ul class="divided">
<li class="post">
<a href="/blog/2016/08/16/we-have-apps-now/">We Have Apps Now</a>
</li>
<li class="post">
<a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26: Foursquare, Fast.com, FFMPEG and GPSD</a>
</li>
@ -243,12 +249,6 @@
</li>
<li class="post">
<a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython - Part 1</a>
</li>
</ul>
</section>

View file

@ -4,7 +4,7 @@
<title><![CDATA[Category: OwnTracks | Home Assistant]]></title>
<link href="https://home-assistant.io/blog/categories/owntracks/atom.xml" rel="self"/>
<link href="https://home-assistant.io/"/>
<updated>2016-08-16T09:54:54+00:00</updated>
<updated>2016-08-16T12:17:59+00:00</updated>
<id>https://home-assistant.io/</id>
<author>
<name><![CDATA[Home Assistant]]></name>

Some files were not shown because too many files have changed in this diff Show more