Site updated at 2016-11-13 11:27:46 UTC

This commit is contained in:
Travis CI 2016-11-13 11:27:46 +00:00
parent 3ec1ea6ce7
commit 3bab881d0a
1303 changed files with 226 additions and 223035 deletions

View file

@ -1,360 +0,0 @@
<!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>Laundry Sensors with NodeMCU and Home Assistant - Home Assistant</title>
<meta name="author" content="Nolan Gilley">
<meta name="description" content="Nolan describes how he gets notified when laundry is done.">
<meta name="viewport" content="width=device-width">
<link rel="canonical" href="https://home-assistant.io/blog/2016/08/03/laundry-automation-update/">
<meta property="fb:app_id" content="338291289691179">
<meta property="og:title" content="Laundry Sensors with NodeMCU and Home Assistant">
<meta property="og:site_name" content="Home Assistant">
<meta property="og:url" content="https://home-assistant.io/blog/2016/08/03/laundry-automation-update/">
<meta property="og:type" content="article">
<meta property="og:description" content="Nolan describes how he gets notified when laundry is done.">
<meta property="og:image" content="https://home-assistant.io/images/blog/2016-07-laundry-automation/protoboard.jpg">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@home_assistant">
<meta name="twitter:title" content="Laundry Sensors with NodeMCU and Home Assistant">
<meta name="twitter:description" content="Nolan describes how he gets notified when laundry is done.">
<meta name="twitter:image" content="https://home-assistant.io/images/blog/2016-07-laundry-automation/protoboard.jpg">
<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="/ecosystem/">Ecosystem</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">Laundry Sensors with NodeMCU and Home Assistant</h1>
<div class="meta clearfix">
<time datetime="2016-08-03T17:22:00+00:00" pubdate data-updated="true"><i class="icon-calendar"></i> August 2, 2016</time>
<span class="byline author vcard"><i class='icon-user'></i> Nolan Gilley</span>
<span><i class='icon-time'></i> four minutes reading time</span>
<span>
<i class="icon-tags"></i>
<ul class="tags unstyled">
<li>User-Stories</li>
</ul>
</span>
<a class='comments'
href="#disqus_thread"
>Comments</a>
</div>
</header>
<p><em>This is a guest post by Home Assistant user and contributor <a href="https://github.com/nkgilley">Nolan Gilley</a>.</em></p>
<p>Today Ill show you how I used Home Assistant, a NodeMCU (ESP8266), and a couple of accelerometers to automate our laundry room. This is a rewrite of an <a href="https://home-assistant.io/blog/2015/08/26/laundry-automation-with-moteino-mqtt-and-home-assistant/">old post</a> where I did the same thing using a Moteino &amp; Raspberry Pi. This version only requires a NodeMCU.</p>
<p>We have an older washer and dryer which doesnt have any form of notification when cycles complete. Home Assistant was the obvious solution, I just needed to create sensors for the washer and dryer. I tried using sound sensors but found them unreliable. I ended up using an accelerometer attached to the back of each appliance. I also added magnetic reed switches on the doors of the washer and dryer to detect whether theyre open or closed. I connected the accelerometers and reed switches to an NodeMCU which will relay the data to my MQTT broker.</p>
<p class="img">
<img src="/images/blog/2016-07-laundry-automation/block-diagram.png" />
Block diagram of schematic
</p>
<a name="read-more"></a>
<p>After taking some sample data from the accelerometers while each appliance was in operation, I decided to plot the data to help determine the proper thresholds of when the devices were running or off. I had to do this in order to get precise ranges so the dryer sensor wouldnt get tripped by the washer or vice versa. In the plot below you can see the acceleration in each direction for the accelerometer connected to the dryer. Its easy to see when the dryer is in operation here. I used the same technique for the washers accelerometer.</p>
<p class="img">
<img src="/images/blog/2016-07-laundry-automation/data-graph.png" />
Graph showing the accelerometer data
</p>
<p>Next it was just a matter of integrating everything with Home Assistant. I was able to use the <a href="/components/mqtt/">MQTT component</a> to read the washer and dryer states from the Moteino and display it in Home Assistant.</p>
<p class="img">
<img src="/images/blog/2016-07-laundry-automation/screenshot-ha.png" />
Status of the dryer and washer in Home Assistant
</p>
<p>Next I wrote <a href="/components/script/">scripts</a> that are run whenever the washer or dryer completes a load. This is triggered by the <a href="/getting-started/automation/">automation component</a>. When the laundry is complete I have the lights in the house turn red and <a href="/components/notify.joaoapps_join/">notify me via Join</a>. Once the door is opened and laundry emptied another script runs that sets the lights back to normal. So far it has been very helpful and very reliable.</p>
<p class="img">
<a href="/images/blog/2016-07-laundry-automation/protoboard.jpg">
<img src="/images/blog/2016-07-laundry-automation/protoboard.jpg" />
</a>
NodeMCU connected to MPU-6050 accelerometer.
</p>
<p>Materials used:</p>
<ul>
<li><a href="https://www.amazon.com/gp/product/B010O1G1ES">NodeMCU</a></li>
<li><a href="http://www.amazon.com/gp/product/B008BOPN40">2 x Accelerometers</a></li>
<li><a href="http://www.amazon.com/gp/product/B004PARDRO">2 x Reed switch</a></li>
</ul>
<p><a href="https://github.com/nkgilley/nodemcu-laundry/blob/master/nodemcu-laundry.ino">Sketch for the NodeMCU is available here.</a></p>
<p>Home Assistant Configuration:</p>
<div class="language-yaml highlighter-rouge"><pre class="highlight"><code><span class="s">mqtt</span><span class="pi">:</span>
<span class="s">broker</span><span class="pi">:</span> <span class="s">192.168.1.100</span>
<span class="s">port</span><span class="pi">:</span> <span class="s">1883</span>
<span class="s">keepalive</span><span class="pi">:</span> <span class="s">60</span>
<span class="s">qos</span><span class="pi">:</span> <span class="s">0</span>
<span class="s">sensor</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">platform</span><span class="pi">:</span> <span class="s">mqtt</span>
<span class="s">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Dryer</span><span class="nv"> </span><span class="s">Status"</span>
<span class="s">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">sensor/dryer"</span>
<span class="s">unit_of_measurement</span><span class="pi">:</span> <span class="s2">"</span><span class="s">"</span>
<span class="pi">-</span> <span class="s">platform</span><span class="pi">:</span> <span class="s">mqtt</span>
<span class="s">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Washer</span><span class="nv"> </span><span class="s">Status"</span>
<span class="s">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">sensor/washer"</span>
<span class="s">unit_of_measurement</span><span class="pi">:</span> <span class="s2">"</span><span class="s">"</span>
<span class="s">automation</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">alias</span><span class="pi">:</span> <span class="s">Washer complete</span>
<span class="s">trigger</span><span class="pi">:</span>
<span class="s">platform</span><span class="pi">:</span> <span class="s">state</span>
<span class="s">entity_id</span><span class="pi">:</span> <span class="s">sensor.washer_status</span>
<span class="s">from</span><span class="pi">:</span> <span class="s1">'</span><span class="s">Running'</span>
<span class="s">to</span><span class="pi">:</span> <span class="s1">'</span><span class="s">Complete'</span>
<span class="s">action</span><span class="pi">:</span>
<span class="s">service</span><span class="pi">:</span> <span class="s">script.turn_on</span>
<span class="s">entity_id</span><span class="pi">:</span> <span class="s">script.washer_complete</span>
<span class="pi">-</span> <span class="s">alias</span><span class="pi">:</span> <span class="s">Washer emptied</span>
<span class="s">trigger</span><span class="pi">:</span>
<span class="s">platform</span><span class="pi">:</span> <span class="s">state</span>
<span class="s">entity_id</span><span class="pi">:</span> <span class="s">sensor.washer_status</span>
<span class="s">from</span><span class="pi">:</span> <span class="s1">'</span><span class="s">Complete'</span>
<span class="s">to</span><span class="pi">:</span> <span class="s1">'</span><span class="s">Empty'</span>
<span class="s">action</span><span class="pi">:</span>
<span class="s">service</span><span class="pi">:</span> <span class="s">scene.turn_on</span>
<span class="s">entity_id</span><span class="pi">:</span> <span class="s">scene.normal</span>
<span class="s">script</span><span class="pi">:</span>
<span class="s">washer_complete</span><span class="pi">:</span>
<span class="s">alias</span><span class="pi">:</span> <span class="s">Washer Complete</span>
<span class="s">sequence</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">alias</span><span class="pi">:</span> <span class="s">Join Notification</span>
<span class="s">service</span><span class="pi">:</span> <span class="s">notify.join</span>
<span class="s">data</span><span class="pi">:</span>
<span class="s">message</span><span class="pi">:</span> <span class="s2">"</span><span class="s">The</span><span class="nv"> </span><span class="s">washing</span><span class="nv"> </span><span class="s">machine</span><span class="nv"> </span><span class="s">has</span><span class="nv"> </span><span class="s">finished</span><span class="nv"> </span><span class="s">its</span><span class="nv"> </span><span class="s">cycle,</span><span class="nv"> </span><span class="s">please</span><span class="nv"> </span><span class="s">empty</span><span class="nv"> </span><span class="s">it!"</span>
<span class="pi">-</span> <span class="s">alias</span><span class="pi">:</span> <span class="s">Living Room Lights Blue</span>
<span class="s">service</span><span class="pi">:</span> <span class="s">scene.turn_on</span>
<span class="s">data</span><span class="pi">:</span>
<span class="s">entity_id</span><span class="pi">:</span> <span class="s">scene.blue</span>
</code></pre>
</div>
<p>Resources used:</p>
<ul>
<li><a href="http://www.instructables.com/id/Uber-Home-Automation-w-Arduino-Pi/step13/Washer-Dryer-Smartifier-Water-Leak-Sensor/">Inspiration and Help with Arduino code</a></li>
</ul>
</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/03/laundry-automation-update/"
data-counturl="https://home-assistant.io/blog/2016/08/03/laundry-automation-update/" >Tweet</a>
<div class="fb-share-button" style='top: -6px;'
data-href="https://home-assistant.io/blog/2016/08/03/laundry-automation-update/"
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/11/05/hacktoberfest-influxdb-weather/">0.32: Hacktoberfest, InfluxDB sensor, Error reporting, and Weather</a>
</li>
<li class="post">
<a href="/blog/2016/10/25/explaining-the-updater/">Explaining the Updater</a>
</li>
<li class="post">
<a href="/blog/2016/10/22/flash-briefing-updater-hacktoberfest/">0.31: Reading you the news, some serious business, spooky hackery and a breaking Z-Wave change</a>
</li>
<li class="post">
<a href="/blog/2016/10/08/hassbian-rest-digital-ocean/">0.30: More Async, HASSbian, Digital Ocean, statistics, REST</a>
</li>
<li class="post">
<a href="/blog/2016/10/02/hacktoberfest/">Participating in Hacktoberfest</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/03/laundry-automation-update/';
var disqus_url = 'https://home-assistant.io/blog/2016/08/03/laundry-automation-update/';
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

@ -1,396 +0,0 @@
<!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>Optimizing the Home Assistant mobile web app - Home Assistant</title>
<meta name="author" content="Paulus Schoutsen">
<meta name="description" content="A comprehensive list of optimizations done to improve our mobile web application.">
<meta name="viewport" content="width=device-width">
<link rel="canonical" href="https://home-assistant.io/blog/2016/08/07/optimizing-the-home-assistant-mobile-web-app/">
<meta property="fb:app_id" content="338291289691179">
<meta property="og:title" content="Optimizing the Home Assistant mobile web app">
<meta property="og:site_name" content="Home Assistant">
<meta property="og:url" content="https://home-assistant.io/blog/2016/08/07/optimizing-the-home-assistant-mobile-web-app/">
<meta property="og:type" content="article">
<meta property="og:description" content="A comprehensive list of optimizations done to improve our mobile web application.">
<meta property="og:image" content="https://home-assistant.io/images/blog/2016-08-optimizing-web-app/performance-diagram.png">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@home_assistant">
<meta name="twitter:title" content="Optimizing the Home Assistant mobile web app">
<meta name="twitter:description" content="A comprehensive list of optimizations done to improve our mobile web application.">
<meta name="twitter:image" content="https://home-assistant.io/images/blog/2016-08-optimizing-web-app/performance-diagram.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="/ecosystem/">Ecosystem</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">Optimizing the Home Assistant mobile web app</h1>
<div class="meta clearfix">
<time datetime="2016-08-07T19:36:00+00:00" pubdate data-updated="true"><i class="icon-calendar"></i> August 7, 2016</time>
<span class="byline author vcard"><i class='icon-user'></i> Paulus Schoutsen</span>
<span><i class='icon-time'></i> 11 minutes reading time</span>
<span>
<i class="icon-tags"></i>
<ul class="tags unstyled">
<li>Technology</li>
</ul>
</span>
<a class='comments'
href="#disqus_thread"
>Comments</a>
</div>
</header>
<p><em>This blog post will go into detail about the recent performance optimizations that went into the Home Assistant front end. For people not familiar with the app, check out <a href="https://home-assistant.io/demo">the demo</a> and <a href="https://github.com/home-assistant/home-assistant-polymer">the source</a>.</em></p>
<p>TL; DR: Dont hack the framework, separate responsibilities, ship less, use service workers, use (future) web standards.</p>
<p>This year at Google I/O I saw Monica from the Polymer team talk about web components and performance. In her talk <a href="https://www.youtube.com/watch?v=zfQoleQEa4w&amp;feature=youtu.be&amp;t=1380">she mentions a mantra</a> that they use in the Polymer team to make things fast: <strong>Do less and be lazy</strong>.</p>
<p>Do less and be lazy. It sounds so obvious and it took a while before it started to dawn on me. I think most of the code I write is pretty fast, but I dont often stop to take a harder look at how and when it runs in practice. When do we need the result, can it be postponed?</p>
<p>And thus started my journey to take a critical look at how the Home Assistant app was working and how to make things faster. Below is the list of the different things that I did to make it fast.</p>
<p>I hope this list can be useful to other people, as a guide for optimizing their own apps or for avoiding pitfalls when building a new one.</p>
<p>The first thing to do is to measure. The Home Assistant front end is a mobile web app, so we shouldnt measure this on a machine with 8 cores and gigabytes of ram but instead measure on devices you expect a mobile web app to run: phones. Below are two timelines recorded with Home Assistant 0.18.2 (pre-optimizations) and Google Chrome 53. <strong>On my Mac the app starts in 1400 miliseconds and on my Nexus 5x in ~6500 miliseconds (~4.5 times slower!).</strong></p>
<p class="img">
<img src="/images/blog/2016-08-optimizing-web-app/performance-timeline-0.18.2.png" alt="Timeline of loading the front end in Home Assistant 0.18.2" />
</p>
<p>Although the app takes 6500 milliseconds to load on my phone, it would perform well afterwards. Still, that initial load is unacceptable. You expect to open an app on your phone and be able to use it, quickly. After I applied all the changes described below, I managed to reduce startup time to 900 miliseconds (-35%) on my Mac and 2400 miliseconds (-63%) on my Nexus 5x. <a href="https://home-assistant.io/demo">Check out the demo here.</a></p>
<p class="img">
<img src="/images/blog/2016-08-optimizing-web-app/performance-diagram.png" alt="diagram showing old and new loading times next to one another" />
<img src="/images/blog/2016-08-optimizing-web-app/performance-timeline-0.26.png" alt="Timeline of loading the front end in Home Assistant 0.26" />
</p>
<a name="read-more"></a>
<h2><a class="title-link" name="technology" href="#technology"></a> Technology</h2>
<p>The Home Assistant front end consists of two parts. There is <a href="https://github.com/home-assistant/home-assistant-js">Home Assistant JS</a>, which controls all data and interaction between JavaScript and the server. It is a Flux architecture using <a href="https://optimizely.github.io/nuclear-js/">NuclearJS</a> and <a href="https://facebook.github.io/immutable-js/">ImmutableJS</a>. The UI is implemented by <a href="https://github.com/home-assistant/home-assistant-polymer">Home Assistant Polymer</a> using <a href="https://www.polymer-project.org/">Polymer</a> and web components.</p>
<h1><a class="title-link" name="dont-hack-the-framework" href="#dont-hack-the-framework"></a> Dont hack the framework</h1>
<p>I thought to be smart. I split out the JavaScript part of all web components and bundled them separately using Webpack so that I could use ES2015 via BabelJS (<a href="https://github.com/home-assistant/home-assistant-polymer/wiki/Using-Polymer-with-ES2015,-Babel-and-NPM">architecture</a>). This is not how Polymer components are written and it meant that I was unable to use any of the tooling that is available in the community or easily split up the bundle (more on this later).</p>
<p>So I went ahead and backported all my web components back from shiny beautiful ES6 to ES5. And you know what? Its not that bad. Yes, not being able to use the concise object notation and arrow functions make your code more verbose. But in the end it is the same code that is running in browsers.</p>
<p>Another benefit of having each web component contain their own script tag is that the browser will process them one by one, allowing the browser to render our loading spinner animation in between.</p>
<p>As you can see in the timelines, we were able to get rid of most of the blocking component loading.</p>
<p class="img">
<img src="/images/blog/2016-08-optimizing-web-app/timeline-no-more-es2015.png" alt="Timeline of loading the front end before and after the optimization" />
</p>
<h1><a class="title-link" name="separate-responsibilities" href="#separate-responsibilities"></a> Separate responsibilities</h1>
<p>Whenever you learn a new technology, you feel like youve learned a new superpower. Wow, I can do all this with only 2 lines?! I had the same with bundling.</p>
<p>I was initially very focused on shipping just a single file with everything that my app needed. The entry point would be my main component which would require all of its Flux and UI dependencies. Then, just before it all would be rendered, it would check if there is authentication and start the data fetching.</p>
<p>This is a very bad pattern. This means that you will not start any data fetching until your UI is ready to render. Instead, you want your data to be fetched as soon as possible, and while the request is out to the server you want the page to load all your UI components.</p>
<p>To accomplish this I extracted the application core out of the main bundle. In the current optimized version its 31.1kb gzipd. It is loaded before any other scripts so that it can start fetching data as soon as possible.</p>
<p class="img">
<img src="/images/blog/2016-08-optimizing-web-app/timeline-corejs.png" alt="Timeline of loading the front end before and after the optimization" />
</p>
<p>When the data does come back before the UI is done loading, we can process it before we start rendering the UI because of all the web components being processed individually. This means that we dont have to show a loading screen the first time our components render we can just render the components with the data they require.</p>
<h1><a class="title-link" name="ship-less" href="#ship-less"></a> Ship less</h1>
<p>The theory behind this one is simple: if we manage to ship less code, the browser has to process less code and it will start faster.</p>
<h2><a class="title-link" name="only-include-the-components-for-the-page-that-you-will-show" href="#only-include-the-components-for-the-page-that-you-will-show"></a> Only include the components for the page that you will show</h2>
<p>The Home Assistant mobile web application has 10 different panels (pages). Besides that, it also has a dialog for each type of device to show more info. Thats a lot of components and screens of which only a very small set is needed at the start. That means that we are shipping a lot of unnecessary data that the browser has to process before our initial render!</p>
<p>I broke up each panel of the app into a separate bundle that will be loaded on demand. This saved 250 kilobytes (pre-gzip) on just the embedded map alone! This change, however, required some significant changes to our build process.</p>
<p>Breaking up an app in JavaScript is complex because each module explicitly imports their dependencies. This has to continue to work in your browser after breaking it up in multiple files. Web components do not have this problem as its part of the platform and thus your browser is the registry! An unregistered web component will be rendered as an empty span element until the element gets registered. Loading order is not important.</p>
<div class="language-javascript highlighter-rouge"><pre class="highlight"><code><span class="c1">// Example of the flexibility of web components.</span>
<span class="kd">var</span> <span class="nx">spinner</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">'paper-spinner'</span><span class="p">);</span>
<span class="nx">spinner</span><span class="p">.</span><span class="nx">active</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">spinner</span><span class="p">);</span>
</code></pre>
</div>
<p>Because the browser tracks your web components, creating standalone bundles for parts of the app is easy:</p>
<ul>
<li>Find all dependencies included in the main bundle (using <a href="https://github.com/Polymer/hydrolysis">hydrolysis</a>)</li>
<li>Create individual bundles of each panel (page) but filter out the dependencies included in main bundle.</li>
</ul>
<p>The <a href="https://github.com/home-assistant/home-assistant-polymer/blob/master/script/vulcanize.js">build script</a> that bundles and minifies the main bundle and panel bundles is &lt;100 lines.</p>
<h2><a class="title-link" name="change-the-javascript-bundler-to-rollup" href="#change-the-javascript-bundler-to-rollup"></a> Change the JavaScript bundler to Rollup</h2>
<p>Core.js is still pure JavaScript and requires bundling. In my journey to get a smaller bundle, I went from <a href="https://webpack.github.io/">Webpack</a> to Webpack 2 to <a href="http://rollupjs.org/">Rollup</a>. At each step the bundle got smaller. Rollup is the big winner here because it doesnt wrap all your modules in function calls but instead concatenates all files with minimal changes to make it work. This not only reduces the file size but also the loading speed. This is because the JavaScript engine will no longer have to invoke a function to resolve each import, its doing less work. This might not mean much for a computer but on a phone, everything counts.</p>
<h2><a class="title-link" name="scrutinize-dependencies" href="#scrutinize-dependencies"></a> Scrutinize dependencies</h2>
<p>If the goal is to ship less, its time to take a good look at dependencies. Its so often that we decide to fall back to yet another NPM package that makes our life a little easier but comes at the cost of size size usually taken up by functionality that you might never need.</p>
<h3><a class="title-link" name="remove-lodash" href="#remove-lodash"></a> Remove Lodash</h3>
<p>I realized that I only used a few methods of lodash. Lodash (and previously underscore) used to be one of the dependencies that would always be one of the first things that I would add to any project I start. But I could no longer justify it in the case of Home Assistant. Even with dead tree shaking it was not worth including it. Yes, they support a lot of edge cases but those were not relevant to my use case. And standalone lodash packages are <a href="https://github.com/lodash/lodash/blob/3.1.7-npm-packages/lodash.range/index.js">still huge</a>. The only thing that I couldnt replace with a few lines of my own code was debounce. However I found <a href="https://github.com/component/debounce">a 40 line replacement</a>.</p>
<h3><a class="title-link" name="replace-momentjs-with-fecha" href="#replace-momentjs-with-fecha"></a> Replace moment.js with Fecha</h3>
<p>Moment.js is one of those power libraries. It is able to handle any date problem that you can throw at it. But this obviously comes at the cost of size. <a href="https://github.com/taylorhakes/fecha">Fecha</a> is a date formatting library at ~8% the size of moment.js (only 4.7kb pre-gzip). The only thing that it does not contain is date manipulation, which was something that was not being used.</p>
<h1><a class="title-link" name="use-service-worker-to-instantly-load-the-app" href="#use-service-worker-to-instantly-load-the-app"></a> Use Service worker to instantly load the app</h1>
<p>Using a service worker were able to store all app components and core javascript in the browser. This means that after their first visit, the browser will only have to go to the network to fetch the latest data from the server.</p>
<p>Creating a service worker is easy using <a href="https://github.com/GoogleChrome/sw-precache">sw-precache</a>, a service worker generation tool.</p>
<p>When a browser does not support service workers, Home Assistant will serve fingerprinted assets that are aggressively cached. Only when the content changes will the client redownload the asset.</p>
<p>Using fingerprinting with sw-precache required jumping through a few hoops. <a href="https://github.com/home-assistant/home-assistant-polymer/blob/master/script/sw-precache.js">The final build script can be found here.</a></p>
<h1><a class="title-link" name="make-it-feel-fast" href="#make-it-feel-fast"></a> Make it feel fast</h1>
<p>This one is more psychological: no one likes staring at a white screen because white screens are ambiguous: are we loading something, is there a crappy connection or maybe even a script error? Thats why it is very important to render something on the screen to show that the rest is being loaded, and as quickly as possible.</p>
<p>The Home Assistant landing page contains just enough CSS and HTML to render the loading screen minus the animations.</p>
<p>Now that the app is fast enough, I might swap out moving from a lite loading screen to drawing an empty toolbar. This makes it look like the UI is almost there.</p>
<h1><a class="title-link" name="using-a-framework-build-on-web-standards" href="#using-a-framework-build-on-web-standards"></a> Using a framework build on web standards</h1>
<p><em>I left this to the end of the list, mainly because I had no influence on this. Polymer just happened to ship an update while I was optimizing the application which gave a big boost to the loading time.</em></p>
<p>By using Polymer we have the ability to use tomorrows web standards today. This is powered by polyfills. A polyfill will use JavaScript to simulate the behavior that the web standard would have taken care of. As browsers progress, more work can move from the polyfills back to the browsers. This is great because browsers will be able to optimize the work better and thus be faster.</p>
<p>Polymer 1.6 was introduced at the end of June and allowed the app to take advantage of native <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables">CSS variables</a> in Chrome and Firefox. It also introduced lazy registration. Both greatly sped up our loading times.</p>
<h1><a class="title-link" name="future-optimizations" href="#future-optimizations"></a> Future optimizations</h1>
<p>A lot of optimizations have been applied but this journey will never be over. There are still a lot of opportunities to make things even faster. Some ideas that are on my list to explore:</p>
<ul>
<li>Use shadow DOM instead of shady DOM polyfill.</li>
<li>Use <a href="https://developers.google.com/closure/compiler/">closure compiler</a> to optimize the JavaScript.</li>
<li>Reduce the number of icons that are loaded.</li>
<li>Embed initial API response in served page if not using a service worker.</li>
<li>Reduce size of initial bundle by moving out all things that are not visible for initial paint. For example the dialogs that show more info about entities.</li>
<li>Prefetch the other pages using <code class="highlighter-rouge">&lt;link rel="preload" …&gt;</code></li>
</ul>
</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/07/optimizing-the-home-assistant-mobile-web-app/"
data-counturl="https://home-assistant.io/blog/2016/08/07/optimizing-the-home-assistant-mobile-web-app/" >Tweet</a>
<div class="fb-share-button" style='top: -6px;'
data-href="https://home-assistant.io/blog/2016/08/07/optimizing-the-home-assistant-mobile-web-app/"
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/11/05/hacktoberfest-influxdb-weather/">0.32: Hacktoberfest, InfluxDB sensor, Error reporting, and Weather</a>
</li>
<li class="post">
<a href="/blog/2016/10/25/explaining-the-updater/">Explaining the Updater</a>
</li>
<li class="post">
<a href="/blog/2016/10/22/flash-briefing-updater-hacktoberfest/">0.31: Reading you the news, some serious business, spooky hackery and a breaking Z-Wave change</a>
</li>
<li class="post">
<a href="/blog/2016/10/08/hassbian-rest-digital-ocean/">0.30: More Async, HASSbian, Digital Ocean, statistics, REST</a>
</li>
<li class="post">
<a href="/blog/2016/10/02/hacktoberfest/">Participating in Hacktoberfest</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/07/optimizing-the-home-assistant-mobile-web-app/';
var disqus_url = 'https://home-assistant.io/blog/2016/08/07/optimizing-the-home-assistant-mobile-web-app/';
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

@ -1,322 +0,0 @@
<!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>0.26: Foursquare, Fast.com, FFMPEG and GPSD - Home Assistant</title>
<meta name="author" content="Paulus Schoutsen">
<meta name="description" content="Automate based on check ins, slow internet speed or just stream a camera using FFMPEG.">
<meta name="viewport" content="width=device-width">
<link rel="canonical" href="https://home-assistant.io/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">
<meta property="fb:app_id" content="338291289691179">
<meta property="og:title" content="0.26: Foursquare, Fast.com, FFMPEG and GPSD">
<meta property="og:site_name" content="Home Assistant">
<meta property="og:url" content="https://home-assistant.io/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">
<meta property="og:type" content="article">
<meta property="og:description" content="Automate based on check ins, slow internet speed or just stream a camera using FFMPEG.">
<meta property="og:image" content="https://home-assistant.io/images/default-social.png">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@home_assistant">
<meta name="twitter:creator" content="@balloob">
<meta name="twitter:title" content="0.26: Foursquare, Fast.com, FFMPEG and GPSD">
<meta name="twitter:description" content="Automate based on check ins, slow internet speed or just stream a camera using FFMPEG.">
<meta name="twitter:image" content="https://home-assistant.io/images/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="/ecosystem/">Ecosystem</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">0.26: Foursquare, Fast.com, FFMPEG and GPSD</h1>
<div class="meta clearfix">
<time datetime="2016-08-13T19:00:00+00:00" pubdate data-updated="true"><i class="icon-calendar"></i> August 13, 2016</time>
<span class="byline author vcard"><i class='icon-user'></i> Paulus Schoutsen</span>
<span><i class='icon-time'></i> three minutes reading time</span>
<span>
<i class="icon-tags"></i>
<ul class="tags unstyled">
<li>Release-Notes</li>
</ul>
</span>
<a class='comments'
href="#disqus_thread"
>Comments</a>
</div>
</header>
<p>Its time for 0.26 and its again full of new features and fixes. First I want to highlight that we are now having 500 000 monthly pageviews on the website. A big milestone for us! Its been an amazing journey. Big thanks to the Home Assistant community for being such a delightful bunch.</p>
<p>This release includes code contributed by 31 different people. The biggest change in this release is a new unit system. Instead of picking Celsius or Fahrenheit youll have to pick imperial or metric now. This influences the units for your temperature, distance, and weight. This will simplify any platform or component that needs to know this information. Big thanks to <a href="https://github.com/Teagan42">@Teagan42</a> for her hard work on this!</p>
<p><img src="/images/supported_brands/foursquare.png" style="clear: right; margin-left: 5px; border:none; box-shadow: none; float: right; margin-bottom: 16px;" width="100" /><img src="/images/supported_brands/ohmconnect.png" style="clear: right; margin-left: 5px; border:none; box-shadow: none; float: right; margin-bottom: 16px;" width="100" /><img src="/images/supported_brands/fastdotcom.png" style="clear: right; margin-left: 5px; border:none; box-shadow: none; float: right; margin-bottom: 16px;" width="100" /><img src="/images/supported_brands/gpsd.png" style="clear: right; margin-left: 5px; border:none; box-shadow: none; float: right; margin-bottom: 16px;" width="100" /><img src="/images/supported_brands/ffmpeg.png" style="clear: right; margin-left: 5px; border:none; box-shadow: none; float: right; margin-bottom: 16px;" width="100" /></p>
<ul>
<li>Core: Introduce notion of unit system (deprecates temperature unit option) (<a href="https://github.com/Teagan42">@Teagan42</a>)</li>
<li>Front end: Speed improvements (<a href="https://github.com/balloob">@balloob</a>)</li>
<li>Front end: Improve layout of state dev tool (<a href="https://github.com/balloob">@balloob</a>)</li>
<li><a href="/components/proximity/">Proximity</a>: Allow definition of unit of measurement (<a href="https://github.com/Teagan42">@Teagan42</a>)</li>
<li><a href="/components/switch.flux/">Flux</a>: Add mired and kelvin mode (<a href="https://github.com/HBDK">@HBDK</a>)</li>
<li>Thermostat - <a href="/components/thermostat.proliphix/">Proliphix</a>: Support for cooling (<a href="https://github.com/sdague">@sdague</a>)</li>
<li>Media Player - <a href="/components/media_player.lg_netcast/">LG Netcast TV</a>: Show screenshot of what is currently playing (<a href="https://github.com/shmuelzon">@shmuelzon</a>)</li>
<li>Z-Wave improvements (<a href="https://github.com/jnewland">@jnewland</a>, <a href="https://github.com/turbokongen">@turbokongen</a>)</li>
<li>Thermostat - <a href="/components/thermostat.heat_control/">heat control</a>: now also able to control an AC (<a href="https://github.com/mtreinish">@mtreinish</a>)</li>
<li>Thermostat - <a href="/components/thermostat.heat_control/">heat control</a>: allow specifying a minimum duration before switching (<a href="https://github.com/mtreinish">@mtreinish</a>)</li>
<li><a href="/components/influxdb/">InfluxDB</a>: Whitelist entities option added (<a href="https://github.com/tchellomello">@tchellomello</a>)</li>
<li>Sensor: Serial <a href="/components/sensor.serial_pm/">particulate matters</a> sensors now supported (<a href="https://github.com/open-homeautomation">@open-homeautomation</a>)</li>
<li>Sensor - <a href="/components/sensor.fitbit/">Fitbit</a>: Fix unit system (<a href="https://github.com/tchellomello">@tchellomello</a>)</li>
<li>Light - <a href="/components/light.flux_led/">Flux LED</a>: Add support for [color and brightness][color] (<a href="https://github.com/Danielhiversen">@Danielhiversen</a>)</li>
<li>Media Player - <a href="/components/media_player.plex/">Plex</a>: Now able to report on music (<a href="https://github.com/abcminiuser">@abcminiuser</a>)</li>
<li>Alarm Control Panel - <a href="/components/alarm_control_panel.verisure/">Verisure</a>: Now able to see who changed the alarm (<a href="https://github.com/persandtrom">@persandtrom</a>)</li>
<li>Thermostat - <a href="/components/thermostat.honeywell/">Honeywell</a>: Add option to read and control HVAC mode (<a href="https://github.com/Teagan42">@Teagan42</a>)</li>
<li><a href="/components/foursquare/">Foursquare</a> component to receive instant notifications of checkins (<a href="https://github.com/robbiet480">@robbiet480</a>)</li>
<li>Camera: New <a href="/components/camera.ffmpeg/">FFMPEG</a> platform allows to stream anything through front end (<a href="https://github.com/pvizeli">@pvizeli</a>)</li>
<li>Manage <a href="/topics/secrets/">secrets</a> with new command line script (<a href="https://github.com/kellerza">@kellerza</a>)</li>
<li>Notify - <a href="/components/notify.smtp/">SMTP</a>: Allow embedding of images (<a href="https://github.com/partofthething">@partofthething</a>)</li>
<li>Sensor: <a href="/components/sensor.ohmconnect/">OhmConnect</a> is now supported (<a href="https://github.com/robbiet480">@robbiet480</a>)</li>
<li><a href="/components/panel_custom/">panel_custom</a> component allows the registering of new panels (<a href="https://github.com/balloob">@balloob</a>)</li>
<li>Light: New <a href="/components/light.mqtt_json/">mqtt_json</a> platform for working with JSON payload (<a href="https://github.com/corbanmailloux">@corbanmailloux</a>)</li>
<li>Sensor: New <a href="/components/sensor.fastdotcom/">Fast.com</a> platform to measure network bandwidth performance (<a href="https://github.com/nkgilley">@nkgilley</a>)</li>
<li>New <a href="/components/pilight/">pilight</a> component to control 433 Mz devices (<a href="https://github.com/DavidLP">@DavidLP</a>)</li>
<li>Sensor: <a href="/components/sensor.gpsd/">GPSD</a> now supported (<a href="https://github.com/fabaff">@fabaff</a>)</li>
</ul>
<h3><a class="title-link" name="hotfix-0261---august-14" href="#hotfix-0261---august-14"></a> Hotfix 0.26.1 - August 14</h3>
<ul>
<li>Fix serial_pm config validation (<a href="https://github.com/open-homeautomation">@open-homeautomation</a>)</li>
<li>Check for existence of system mode on Honeywell thermostats (<a href="https://github.com/mKeRix">@mKeRix</a>)</li>
<li>Fix unknown unit of measurement for hvac and thermostat component (<a href="https://github.com/turbokongen">@turbokongen</a>)</li>
</ul>
<h3><a class="title-link" name="hotfix-0262---august-15" href="#hotfix-0262---august-15"></a> Hotfix 0.26.2 - August 15</h3>
<ul>
<li>Fix Wemo: have PyWemo play nicely with the latest Requests (<a href="https://github.com/pavoni">@pavoni</a>)</li>
</ul>
<h3><a class="title-link" name="hotfix-0263---august-19" href="#hotfix-0263---august-19"></a> Hotfix 0.26.3 - August 19</h3>
<ul>
<li>Media Player cover art would not work when an API password was set. Thanks to <a href="https://github.com/maddox">@maddox</a> for reporting it and <a href="https://github.com/balloob">@balloob</a> for the fix.</li>
</ul>
<h3><a class="title-link" name="breaking-changes" href="#breaking-changes"></a> Breaking changes</h3>
<ul>
<li>A new unit system has superseded the temperature unit option in the core configuration. For now it is backwards compatible, but you should update soon:</li>
</ul>
<div class="language-yaml highlighter-rouge"><pre class="highlight"><code><span class="c1"># Configuration.yaml example</span>
<span class="s">homeassistant</span><span class="pi">:</span>
<span class="c1"># 'metric' for the metric system, 'imperial' for the imperial system</span>
<span class="s">unit_system</span><span class="pi">:</span> <span class="s">metric</span>
</code></pre>
</div>
</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/13/foursquare-fast-com-ffmpeg-gpsd/"
data-counturl="https://home-assistant.io/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/" >Tweet</a>
<div class="fb-share-button" style='top: -6px;'
data-href="https://home-assistant.io/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/"
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/11/05/hacktoberfest-influxdb-weather/">0.32: Hacktoberfest, InfluxDB sensor, Error reporting, and Weather</a>
</li>
<li class="post">
<a href="/blog/2016/10/25/explaining-the-updater/">Explaining the Updater</a>
</li>
<li class="post">
<a href="/blog/2016/10/22/flash-briefing-updater-hacktoberfest/">0.31: Reading you the news, some serious business, spooky hackery and a breaking Z-Wave change</a>
</li>
<li class="post">
<a href="/blog/2016/10/08/hassbian-rest-digital-ocean/">0.30: More Async, HASSbian, Digital Ocean, statistics, REST</a>
</li>
<li class="post">
<a href="/blog/2016/10/02/hacktoberfest/">Participating in Hacktoberfest</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/13/foursquare-fast-com-ffmpeg-gpsd/';
var disqus_url = 'https://home-assistant.io/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/';
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

@ -1,376 +0,0 @@
<!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/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/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="/ecosystem/">Ecosystem</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> 11 minutes reading time</span>
<span>
<i class="icon-tags"></i>
<ul class="tags unstyled">
<li>How-To</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 class="highlighter-rouge">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 class="highlighter-rouge">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 class="highlighter-rouge">AppDaemon</code>? <code class="highlighter-rouge">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 class="highlighter-rouge">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 class="highlighter-rouge">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 class="highlighter-rouge">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 class="highlighter-rouge">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 class="highlighter-rouge">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 class="highlighter-rouge">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 class="highlighter-rouge">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 class="highlighter-rouge">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 class="highlighter-rouge">initialize()</code> function called which gives it a chance to register a callback for <code class="highlighter-rouge">AppDaemons</code>s scheduler for a specific time. In this case we are using <code class="highlighter-rouge">run_at_sunrise()</code> and <code class="highlighter-rouge">run_at_sunset()</code> to register 2 separate callbacks. The argument <code class="highlighter-rouge">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 class="highlighter-rouge">datetime.timedelta</code> class for calculations. When sunrise or sunset occurs, the appropriate callback function, <code class="highlighter-rouge">sunrise_cb()</code> or <code class="highlighter-rouge">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 class="highlighter-rouge">args["on_scene"]</code> and <code class="highlighter-rouge">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="language-python highlighter-rouge"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">appapi</span>
<span class="k">class</span> <span class="nc">OutsideLights</span><span class="p">(</span><span class="n">appapi</span><span class="o">.</span><span class="n">AppDaemon</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">run_at_sunrise</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sunrise_cb</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">run_at_sunset</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sunset_cb</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">sunrise_cb</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">turn_on</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="s">"off_scene"</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">sunset_cb</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">turn_on</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="s">"on_scene"</span><span class="p">])</span>
</code></pre>
</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 class="highlighter-rouge">initialize()</code> function registers a callback on a state change (of the motion sensor) rather than a specific time. We tell <code class="highlighter-rouge">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 class="highlighter-rouge">new = "on"</code>. When the motion is detected, the callack function <code class="highlighter-rouge">motion()</code> is called, and we check whether or not the sun has set using a built-in convenience function: <code class="highlighter-rouge">sun_down()</code>. Next, we turn the light on with <code class="highlighter-rouge">turn_on()</code>, then set a timer using <code class="highlighter-rouge">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 class="highlighter-rouge">AppDaemon</code> calling <code class="highlighter-rouge">light_off()</code> 60 seconds later using the <code class="highlighter-rouge">turn_off()</code> call to actually turn the light off. This is still pretty simple in code terms:</p>
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">appapi</span>
<span class="k">class</span> <span class="nc">MotionLights</span><span class="p">(</span><span class="n">appapi</span><span class="o">.</span><span class="n">AppDaemon</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">listen_state</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">motion</span><span class="p">,</span> <span class="s">"binary_sensor.drive"</span><span class="p">,</span> <span class="n">new</span> <span class="o">=</span> <span class="s">"on"</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">motion</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entity</span><span class="p">,</span> <span class="n">attribute</span><span class="p">,</span> <span class="n">old</span><span class="p">,</span> <span class="n">new</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">sun_down</span><span class="p">():</span>
<span class="bp">self</span><span class="o">.</span><span class="n">turn_on</span><span class="p">(</span><span class="s">"light.drive"</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">run_in</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">light_off</span><span class="p">,</span> <span class="mi">60</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">light_off</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">turn_off</span><span class="p">(</span><span class="s">"light.drive"</span><span class="p">)</span>
</code></pre>
</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 class="highlighter-rouge">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 class="highlighter-rouge">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="language-python highlighter-rouge"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">appapi</span>
<span class="k">class</span> <span class="nc">FlashyMotionLights</span><span class="p">(</span><span class="n">appapi</span><span class="o">.</span><span class="n">AppDaemon</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">listen_state</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">motion</span><span class="p">,</span> <span class="s">"binary_sensor.drive"</span><span class="p">,</span> <span class="n">new</span> <span class="o">=</span> <span class="s">"on"</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">motion</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entity</span><span class="p">,</span> <span class="n">attribute</span><span class="p">,</span> <span class="n">old</span><span class="p">,</span> <span class="n">new</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="bp">self</span><span class="o">.</span><span class="n">sun_down</span><span class="p">():</span>
<span class="bp">self</span><span class="o">.</span><span class="n">turn_on</span><span class="p">(</span><span class="s">"light.drive"</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">run_in</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">light_off</span><span class="p">,</span> <span class="mi">60</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">flashcount</span> <span class="o">=</span> <span class="mi">0</span>
<span class="bp">self</span><span class="o">.</span><span class="n">run_in</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">flash_warning</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">light_off</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">turn_off</span><span class="p">(</span><span class="s">"light.drive"</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">flash_warning</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">toggle</span><span class="p">(</span><span class="s">"light.living_room"</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">flashcount</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">flashcount</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">run_in</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">flash_warning</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</code></pre>
</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 class="highlighter-rouge">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 class="highlighter-rouge">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/11/05/hacktoberfest-influxdb-weather/">0.32: Hacktoberfest, InfluxDB sensor, Error reporting, and Weather</a>
</li>
<li class="post">
<a href="/blog/2016/10/25/explaining-the-updater/">Explaining the Updater</a>
</li>
<li class="post">
<a href="/blog/2016/10/22/flash-briefing-updater-hacktoberfest/">0.31: Reading you the news, some serious business, spooky hackery and a breaking Z-Wave change</a>
</li>
<li class="post">
<a href="/blog/2016/10/08/hassbian-rest-digital-ocean/">0.30: More Async, HASSbian, Digital Ocean, statistics, REST</a>
</li>
<li class="post">
<a href="/blog/2016/10/02/hacktoberfest/">Participating in Hacktoberfest</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

@ -1,262 +0,0 @@
<!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>Github-style calendar heatmap of device data - Home Assistant</title>
<meta name="author" content="Fabian Affolter">
<meta name="description" content="Generating a Github-style calendar heatmap from your device data.">
<meta name="viewport" content="width=device-width">
<link rel="canonical" href="https://home-assistant.io/blog/2016/08/19/github-style-calendar-heatmap-of-device-data/">
<meta property="fb:app_id" content="338291289691179">
<meta property="og:title" content="Github-style calendar heatmap of device data">
<meta property="og:site_name" content="Home Assistant">
<meta property="og:url" content="https://home-assistant.io/blog/2016/08/19/github-style-calendar-heatmap-of-device-data/">
<meta property="og:type" content="article">
<meta property="og:description" content="Generating a Github-style calendar heatmap from your device data.">
<meta property="og:image" content="https://home-assistant.io/images/blog/2016-08-data-exploration/heatmap.png">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@home_assistant">
<meta name="twitter:creator" content="@fabaff">
<meta name="twitter:title" content="Github-style calendar heatmap of device data">
<meta name="twitter:description" content="Generating a Github-style calendar heatmap from your device data.">
<meta name="twitter:image" content="https://home-assistant.io/images/blog/2016-08-data-exploration/heatmap.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="/ecosystem/">Ecosystem</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">Github-style calendar heatmap of device data</h1>
<div class="meta clearfix">
<time datetime="2016-08-19T06:00:00+00:00" pubdate data-updated="true"><i class="icon-calendar"></i> August 19, 2016</time>
<span class="byline author vcard"><i class='icon-user'></i> Fabian Affolter</span>
<span><i class='icon-time'></i> Less than one minute reading time</span>
<span>
<i class="icon-tags"></i>
<ul class="tags unstyled">
<li>How-To</li>
<li>IoT-Data</li>
</ul>
</span>
<a class='comments'
href="#disqus_thread"
>Comments</a>
</div>
</header>
<p>Thanks to <a href="https://github.com/kireyeu">Anton Kireyeu</a> we are able to present another awesome <a href="https://jupyter.org/">Jupyter notebook</a>. I guess that you all know the graph which Github is using to visualize your commits per day over a time-line. Its a so-called <a href="https://en.wikipedia.org/wiki/Heat_map">heatmap</a>. If there are more commits, its getting hotter. The latest <a href="http://nbviewer.jupyter.org/github/home-assistant/home-assistant-notebooks/blob/master/DataExploration-2/DataExploration-2.ipynb">notebook</a> is capable to do the same thing for your devices. To be more precise, for the hours your devices are home.</p>
<p class="img">
<img src="/images/blog/2016-08-data-exploration/heatmap.png" />
Heatmap
</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/19/github-style-calendar-heatmap-of-device-data/"
data-counturl="https://home-assistant.io/blog/2016/08/19/github-style-calendar-heatmap-of-device-data/" >Tweet</a>
<div class="fb-share-button" style='top: -6px;'
data-href="https://home-assistant.io/blog/2016/08/19/github-style-calendar-heatmap-of-device-data/"
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/11/05/hacktoberfest-influxdb-weather/">0.32: Hacktoberfest, InfluxDB sensor, Error reporting, and Weather</a>
</li>
<li class="post">
<a href="/blog/2016/10/25/explaining-the-updater/">Explaining the Updater</a>
</li>
<li class="post">
<a href="/blog/2016/10/22/flash-briefing-updater-hacktoberfest/">0.31: Reading you the news, some serious business, spooky hackery and a breaking Z-Wave change</a>
</li>
<li class="post">
<a href="/blog/2016/10/08/hassbian-rest-digital-ocean/">0.30: More Async, HASSbian, Digital Ocean, statistics, REST</a>
</li>
<li class="post">
<a href="/blog/2016/10/02/hacktoberfest/">Participating in Hacktoberfest</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/19/github-style-calendar-heatmap-of-device-data/';
var disqus_url = 'https://home-assistant.io/blog/2016/08/19/github-style-calendar-heatmap-of-device-data/';
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

@ -1,457 +0,0 @@
<!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>0.27 is here to break eggs and take names: notifications, Hue fakery, safety and unification come to Home Assistant - Home Assistant</title>
<meta name="author" content="Robbie Trencheny">
<meta name="description" content="HTML5 push notifications and grouping support, Configuration validations and checking, cover, climate and fan.">
<meta name="viewport" content="width=device-width">
<link rel="canonical" href="https://home-assistant.io/blog/2016/08/28/notifications-hue-fake-unification/">
<meta property="fb:app_id" content="338291289691179">
<meta property="og:title" content="0.27 is here to break eggs and take names: notifications, Hue fakery, safety and unification come to Home Assistant">
<meta property="og:site_name" content="Home Assistant">
<meta property="og:url" content="https://home-assistant.io/blog/2016/08/28/notifications-hue-fake-unification/">
<meta property="og:type" content="article">
<meta property="og:description" content="HTML5 push notifications and grouping support, Configuration validations and checking, cover, climate and fan.">
<meta property="og:image" content="https://home-assistant.io/images/default-social.png">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@home_assistant">
<meta name="twitter:creator" content="@Robbie">
<meta name="twitter:title" content="0.27 is here to break eggs and take names: notifications, Hue fakery, safety and unification come to Home Assistant">
<meta name="twitter:description" content="HTML5 push notifications and grouping support, Configuration validations and checking, cover, climate and fan.">
<meta name="twitter:image" content="https://home-assistant.io/images/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="/ecosystem/">Ecosystem</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">0.27 is here to break eggs and take names: notifications, Hue fakery, safety and unification come to Home Assistant</h1>
<div class="meta clearfix">
<time datetime="2016-08-28T03:30:25+00:00" pubdate data-updated="true"><i class="icon-calendar"></i> August 27, 2016</time>
<span class="byline author vcard"><i class='icon-user'></i> Robbie Trencheny</span>
<span><i class='icon-time'></i> 12 minutes reading time</span>
<span>
<i class="icon-tags"></i>
<ul class="tags unstyled">
<li>Release-Notes</li>
</ul>
</span>
<a class='comments'
href="#disqus_thread"
>Comments</a>
</div>
</header>
<p>This weeks blog post could only be possibly described by exactly one hashtag:</p>
<h1>#Amazing</h1>
<p><sup>or <sup>maybe<sup>#supersized</sup></sup></sup></p>
<p>Keep reading to see what <strong>#Amazing</strong> things we have in store for you this week 😄! And make sure you read all the way to the end, because I left a present down there for those committed few among you :)</p>
<p>But first…</p>
<h2><a class="title-link" name="some-general-housekeeping" href="#some-general-housekeeping"></a> Some general housekeeping</h2>
<p>Paulus (<a href="https://github.com/balloob">@balloob</a>) is on vacation in Europe this week, so you will all have to deal with me, Robbie (<a href="https://github.com/robbiet480">@robbiet480</a>) for this release blog post. Dont worry, Paulus will be back to tearing apart your pull requests in no time 😈.</p>
<p>Special thanks to my awesome helpers for this weeks release who are looking over my shoulder to make sure Im crossing my ts and dotting my is: <a href="https://github.com/Teagan42">@Teagan42</a>, <a href="https://github.com/infamy">@infamy</a> and <a href="https://github.com/fabaff">@fabaff</a>.</p>
<p>For my next trick, lets hand out some…</p>
<h2><a class="title-link" name="trophies" href="#trophies"></a> Trophies</h2>
<p>I felt that I had to 1-up Paulus (<a href="https://github.com/balloob">@balloob</a>) somehow with his 500,000 pageviews stat he shared in the <a href="/blog/2016/08/13/foursquare-fast-com-ffmpeg-gpsd/">0.26 blog post</a>, so I pushed myself and our development community as a whole super hard the last two weeks to put a lot of love into Home Assistant to bring you not just one, but six <strong>#Amazing</strong> stats for this release. As of 0.27, we have now surpassed the following milestones:</p>
<ul>
<li><a href="https://travis-ci.org/home-assistant/home-assistant/builds/154660811">10,000</a> builds on Travis (congrats to <a href="https://github.com/BluGeni">@BluGeni</a>)</li>
<li><a href="https://github.com/home-assistant/home-assistant/pull/3000">3,000</a> issues and pull requests (thanks <a href="https://github.com/kellerza">@kellerza</a>!)</li>
<li><a href="https://github.com/home-assistant/home-assistant/pull/2991">2,000</a> pull requests alone (awesome <a href="https://github.com/fabaff">@fabaff</a>!!)</li>
<li>900 forks on Github!</li>
</ul>
<p>In addition,</p>
<ul>
<li>We are very close to 4,000 stars on Github!</li>
<li><a href="https://github.com/home-assistant/home-assistant/graphs/contributors">Im now #5 contributor by most commits!!!</a> Hey wait, howd this get in here 😳…</li>
</ul>
<p>Now that we have that great news out of the way, onto this weeks release which is going to keep the <strong>#Amazing</strong> gravy train rolling right along and get to the stuff you all <em>really</em> are here for.</p>
<h2><a class="title-link" name="027" href="#027"></a> 0.27</h2>
<p>While this release is <strong>#Amazing</strong>, we had to break a few eggs (now you understand the title reference!) to make a beautiful omelette (using home automation obviously) so some platforms and components have needed to introduce breaking changes. Please make sure to read the <a href="#breaking-changes">Breaking Changes</a> section below.</p>
<h3><a class="title-link" name="hue-bridge-emulation" href="#hue-bridge-emulation"></a> Hue Bridge Emulation</h3>
<p>Thanks to <a href="https://github.com/mgbowen">@mgbowen</a> we now have the functionality previously provided by <a href="https://github.com/blocke">@blocke</a>s <a href="https://github.com/blocke/ha-local-echo">ha-local-echo</a> <a href="/components/emulated_hue/">built right into Home Assistant</a>! This means that for those of you with devices that either lack or have a subpar integration with Home Assistant (looking at you Amazon Echo) you can now have a better experience by having your Home Assistant pretend to be a Hue Bridge. Personally, I have used <a href="https://github.com/auchter">@auchter</a>s <a href="https://github.com/auchter/haaska">Haaska</a> previously but found that it was slow to respond and sometimes failed entirely. With the new <a href="/components/emulated_hue/"><code class="highlighter-rouge">emulated_hue</code></a> component, you can have local control of entities through Amazon Echo.</p>
<h3><a class="title-link" name="notification-improvements" href="#notification-improvements"></a> Notification improvements</h3>
<p>We have some excellent upgrades to the notification system coming to you in 0.27, courtesy of me, <a href="https://github.com/robbiet480">@robbiet480</a>.</p>
<h4><a class="title-link" name="html5-push-notifications" href="#html5-push-notifications"></a> HTML5 Push Notifications</h4>
<p>This release adds support for <a href="/components/notify.html5/">HTML5</a> push notifications on Chrome/Firefox/Opera on both desktop and Android devices. This means that you can send a notification to your phone even when your Home Assistant is not open in your mobile browser. When using Chrome you can even include 2 action buttons so that you can control your Home Assistant from your phones lock screen, allowing you to do things like sound alarms or unlock your front door, all without leaving the notification. Thanks again to me (<a href="https://github.com/robbiet480">@robbiet480</a>) and Paulus (<a href="https://github.com/balloob">@balloob</a>) for all the hard work on this!</p>
<p class="img">
<img src="/images/screenshots/html5-notify.png" />
</p>
<h4><a class="title-link" name="notification-groups" href="#notification-groups"></a> Notification Groups</h4>
<p>Using the new notify <code class="highlighter-rouge">group</code> platform allows you to cut down a lot of duplicate automation logic by combining multiple notification platforms and <code class="highlighter-rouge">target</code>s into a single notify service. Check out the <a href="/components/notify.group/">docs</a> for more info.</p>
<h4><a class="title-link" name="target-is-no-longer-needed" href="#target-is-no-longer-needed"></a> <code class="highlighter-rouge">target</code> is no longer needed!</h4>
<p>For platforms that support it, starting with the new HTML5 platform, any <code class="highlighter-rouge">target</code>s that are available will be exposed as individual services, so no more having to remember which <code class="highlighter-rouge">target</code>s to use. Please note that the existing services also still exist so you can keep using <code class="highlighter-rouge">target</code> if you wish.</p>
<h3><a class="title-link" name="validate-configuration-before-restarting-home-assistant" href="#validate-configuration-before-restarting-home-assistant"></a> Validate configuration before restarting Home Assistant</h3>
<p>Ever restarted Home Assistant to test a configuration change just to find out there is a validation error? Well, not anymore! <a href="https://github.com/kellerza">@kellerza</a> has added a command line script that will validate your configuration as if you started Home Assistant.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>hass --script check_config
</code></pre>
</div>
<h3><a class="title-link" name="configuration-validation" href="#configuration-validation"></a> Configuration validation</h3>
<p>This release includes a big push on making sure all platforms contain proper configuration validation. This should help in getting your configuration right. Thanks to <a href="https://github.com/fabaff">@fabaff</a>, <a href="https://github.com/pavoni">@pavoni</a>, <a href="https://github.com/pvizeli">@pvizeli</a>, <a href="https://github.com/nkgilley">@nkgilley</a> for all the hard work on this, you all rock!</p>
<p class="img">
<img src="/images/screenshots/config-validation.png" />
</p>
<h3><a class="title-link" name="ffmpeg-motionnoise-sensing" href="#ffmpeg-motionnoise-sensing"></a> FFMpeg motion/noise sensing</h3>
<p>Its now possible to use <a href="/components/binary_sensor.ffmpeg/">FFMpeg</a> to monitor a video stream and detect motion thanks to a new binary sensor platform by <a href="https://github.com/pvizeli">@pvizeli</a>.</p>
<h3><a class="title-link" name="component-clean-up---thermostat--hvac---climate-rollershutter--garage-door---cover" href="#component-clean-up---thermostat--hvac---climate-rollershutter--garage-door---cover"></a> Component clean up - Thermostat &amp; HVAC -&gt; Climate. Rollershutter &amp; Garage Door -&gt; Cover.</h3>
<p>Due to our wild growth we ended up with a few components that had a lot of overlapping functionality. <a href="https://github.com/turbokongen">@turbokongen</a> took on the hard job on merging them. Thermostat and HVAC platforms are now combined under the new Climate component. Rollershutter and Garage Door platforms are now combined under the new Cover component. You can easily upgrade by just swapping out the name. For example replace <code class="highlighter-rouge">thermostat</code> with <code class="highlighter-rouge">climate</code>. The old components have been deprecated and will be removed in the near future.</p>
<h3><a class="title-link" name="a-new-fan-component" href="#a-new-fan-component"></a> A new <code class="highlighter-rouge">fan</code> component</h3>
<p>Along with the new <code class="highlighter-rouge">climate</code> component, <a href="https://github.com/Teagan42">@Teagan42</a> and I (<a href="https://github.com/robbiet480">@robbiet480</a>) decided we needed something simpler to just control a fan. Currently it has support for controlling Insteon fans. MQTT support will appear in 0.28.0. I tried to get it implemented before 0.27.0 but spent too long writing this blog post 😢.</p>
<h3><a class="title-link" name="all-changes" href="#all-changes"></a> All changes</h3>
<p><img src="/images/supported_brands/html5.png" style="clear: right; margin-left: 5px; border:none; box-shadow: none; float: right; margin-bottom: 16px;" width="100" /><img src="/images/supported_brands/mqtt.png" style="clear: right; margin-left: 5px; border:none; box-shadow: none; float: right; margin-bottom: 16px;" width="100" /><img src="/images/supported_brands/hewlett_packard_enterprise.png" style="clear: right; margin-left: 5px; border:none; box-shadow: none; float: right; margin-bottom: 16px;" width="100" /><img src="/images/supported_brands/wunderground.png" style="clear: right; margin-left: 5px; border:none; box-shadow: none; float: right; margin-bottom: 16px;" width="100" /></p>
<ul>
<li>Merge thermostat and HVAC components into new <a href="/components/climate/">climate</a> component (<a href="https://github.com/turbokongen">@turbokongen</a>)</li>
<li>Merge rollershutter and garage door components into new <a href="/components/cover/">cover</a> component (<a href="https://github.com/turbokongen">@turbokongen</a>)</li>
<li>Alarm Control Panel - Manual: Allow returning to previous state after <a href="/components/alarm_control_panel.manual/">trigger</a> (<a href="https://github.com/tobiebooth">@tobiebooth</a>)</li>
<li>Sensor - DHT: Allow range <a href="/components/sensor.dht/">checking</a> (<a href="https://github.com/open-homeautomation">@open-homeautomation</a>)</li>
<li>Light entities will now <a href="/components/light/">expose</a> their features (<a href="https://github.com/shmuelzon">@shmuelzon</a>)</li>
<li>Sensor: Monitor HP ILO sensors on <a href="/components/sensor.hp_ilo/">HP</a> servers (<a href="https://github.com/Juggels">@Juggels</a>)</li>
<li>Sensor: Monitor <a href="/components/sensor.fritzbox_callmonitor/">Fritzbox</a> Calls (<a href="https://github.com/DavidMStraub">@DavidMStraub</a>)</li>
<li>Notify: LlamaLab <a href="/components/notify.llamalab_automate/">Automate</a> is now supported (<a href="https://github.com/danielperna84">@danielperna84</a>)</li>
<li>Sensor: Serial <a href="/components/sensor.mhz19/">CO2</a> sensors now supported (<a href="https://github.com/open-homeautomation">@open-homeautomation</a>)</li>
<li>Sensor: MQTT room <a href="/components/sensor.mqtt_room">presence</a> detection (<a href="https://github.com/mKerix">@mKerix</a>)</li>
<li>Notify: New group platform allows <a href="/components/notify.group/">grouping</a> notify targets across platforms (<a href="https://github.com/robbiet480">@robbiet480</a>)</li>
<li><a href="/components/notify.html5/">HTML5</a> push notifications (<a href="https://github.com/robbiet480">@robbiet480</a>, <a href="https://github.com/balloob">@balloob</a>)</li>
<li>Weather: <a href="/components/sensor.wunderground/">Wunderground</a> now supported (<a href="https://github.com/arsaboo">@arsaboo</a>, <a href="https://github.com/Teagan42">@Teagan42</a>)</li>
<li>New check config script to test validity before restarting HA (<a href="https://github.com/kellerza">@kellerza</a>)</li>
<li>Binary Sensor: Allow <a href="/components/binary_sensor.ffmpeg/">monitoring</a> a camera feed using FFMpeg (<a href="https://github.com/pvizeli">@pvizeli</a>)</li>
<li>Cover: Z-Wave platform now supports <a href="/components/cover.zwave/">positions</a> (<a href="https://github.com/nunofgs">@nunofgs</a>)</li>
<li>Device tracker: allow using <a href="/components/device_tracker/">Gravatar</a> for entity picture (<a href="https://github.com/robbiet480">@robbiet480</a>)</li>
<li>Notify: platforms with known targets will expose them as standalone services (<a href="https://github.com/robbiet480">@robbiet480</a>)</li>
<li>Camera: <a href="/components/camera.mjpeg/">MJPEG</a> and <a href="/components/camera.generic/">Generic</a> cameras can now authenticate using digest auth (<a href="https://github.com/meatz">@meatz</a>)</li>
<li>Weather: Forecast.io now can show daily temp/precip <a href="/components/sensor.forecast/">forecast</a> values (<a href="https://github.com/DavidMStraub">@DavidMStraub</a>)</li>
<li>Media Player: WebOS TV now allows <a href="/components/media_player.webostv/">customizing</a> the sources (<a href="ttps://github.com/roidayan">@roidayan</a>)</li>
<li>Device tracker: Allow tracking devices using <a href="/components/device_tracker.bluetooth_le_tracker/">Bluetooth</a> Low-Energy (<a href="https://github.com/open-homeautomation">@open-homeautomation</a>)</li>
<li>Notify: Ensure <a href="/components/notify.slack/">Slack</a> messages appear as correct user (<a href="https://github.com/technicalpickles">@technicalpickles</a>)</li>
<li>YAML: <a href="/topics/secrets/">Secrets</a> will look for values in all parents folders up to the config root folder (<a href="https://github.com/Teagan42">@Teagan42</a>)</li>
<li>Camera: Generic camera now supports <a href="/components/camera.generic/">template</a> support (<a href="https://github.com/balloob">@balloob</a>)</li>
<li>Slack: Allow sending <a href="/components/notify.slack/">attachments</a> (<a href="https://github.com/technicalpickles">@technicalpickles</a>)</li>
<li>Device Tracking: TP-Link Archer C7 5 GHz devices will now also be <a href="/components/device_tracker.tplink/">found</a> (<a href="https://github.com/dpford">@dpford</a>)</li>
<li>Z-Wave: New rename <a href="/components/zwave/">node</a> service added (<a href="https://github.com/jnewland">@jnewland</a>)</li>
<li>Wink: <a href="/components/wink/">Bug</a> fixes (<a href="https://github.com/w1ll1am23">@w1ll1am23</a>)</li>
<li>Homematic: new device and controller variable <a href="/components/homematic/">support</a> (<a href="https://github.com/danielperna84">@danielperna84</a>, <a href="https://github.com/pvizeli">@pvizeli</a>, <a href="https://github.com/mcdeck">@mcdeck</a>)</li>
<li>Allow emulating a <a href="/components/emulated_hue/">Hue</a> bridge to control entities (<a href="https://github.com/mgbowen">@mgbowen</a>)</li>
<li>New <a href="/components/fan/">Fan</a> component (<a href="https://github.com/Teagan42">@Teagan42</a>, <a href="https://github.com/robbiet480">@robbiet480</a>)</li>
</ul>
<h3><a class="title-link" name="breaking-changes" href="#breaking-changes"></a> Breaking changes</h3>
<ul>
<li>Ecobee3 occupancy sensors have moved from sensor platform to binary sensor platform.</li>
<li>Forecast.io entity IDs are now like <code class="highlighter-rouge">sensor.forecastio_temperature</code>. Previously they were like <code class="highlighter-rouge">sensor.weather_temperature</code>. Apologies for this change, but we needed to make Forecast.io more generic now that we have many weather platforms.</li>
<li>The <a href="/components/sensor.loop_energy/">Loop Energy</a> sensor configuration format changed slightly, please reformat based on the revised documentation.</li>
<li>The configuration for the <a href="/components/sensor.sabnzbd/">SABnzbd</a> sensor has slightly changed. The prefix <code class="highlighter-rouge">type:</code> is no longer required for monitored variables.</li>
<li>The <a href="/components/sensor.imap/">IMAP</a> sensor now uses <code class="highlighter-rouge">username</code> instead of <code class="highlighter-rouge">user</code>.</li>
<li>The <a href="/components/sensor.nzbget/">NZBGet</a> sensor has had so many changes I cant list them all. Please refer to the documentation for more info.</li>
</ul>
<h3><a class="title-link" name="deprecations" href="#deprecations"></a> Deprecations</h3>
<ul>
<li>Using the <code class="highlighter-rouge">thermostat</code> and <code class="highlighter-rouge">hvac</code> components has been deprecated. Please migrate to the new <code class="highlighter-rouge">climate</code> component. (just change the component name, the configurations are compatible)</li>
<li>Using the <code class="highlighter-rouge">rollershutter</code> and <code class="highlighter-rouge">garage_door</code> components have also been deprecated. Please migrate to the new <code class="highlighter-rouge">cover</code> component. (just change the component name, the configurations are compatible)</li>
</ul>
<h2><a class="title-link" name="finishing-up" href="#finishing-up"></a> Finishing up</h2>
<p>Thanks all for sticking with me to the end. Ill be taking over a lot of Pauluss (<a href="https://github.com/balloob">@balloob</a>) work while he is gone, but as I said, dont worry because hell be back well before 0.28.0 comes out. Hopefully you didnt find this jovial blog post too jarring from our standard style, I just wrote a lot of this at 2am after being awake for almost 20 hours, so Im a little loopy hahaha 😴.</p>
<p>Also, thanks as always to our developer contributors, documentation contributors, but most of all our users! This wouldve just been a script that Paulus (@balloob) used to control his lights at home if we didnt have your enthusiasm.</p>
<p>Feel free to let me know what you thought of this blog post and release on Gitter or my <a href="https://twitter.com/robbie">Twitter</a>, or even the <a href="https://twitter.com/home_assistant">Home Assistant Twitter</a>. Did I mention we have a brand new <a href="https://www.facebook.com/homeassistantio">Facebook page</a> that you should absolutely Like? Theres a convenient Facebook Like and Twitter follow button right on the sidebar.</p>
<p>I almost forgot about your 🎁 for reading all the way to here: a 🍪! Hope you enjoy it in good health 😄.</p>
<p>Talk to you soon on Gitter and in your pull request comments!</p>
<p> Robbie</p>
<p>(p.s. To those of you that scrolled directly to the bottom to get your present, just know that you didnt earn it like the others did. 😄)</p>
<h2><a class="title-link" name="hotfix-0271---august-30" href="#hotfix-0271---august-30"></a> Hotfix 0.27.1 - August 30</h2>
<ul>
<li>Migrate APCUPSd to voluptuous (<a href="https://github.com/fabaff">@fabaff</a>)</li>
<li>Ecobee operation mode fix (<a href="https://github.com/turbokongen">@turbokongen</a>)</li>
<li>update ha-ffmpeg version to 0.9 (<a href="https://github.com/pvizeli">@pvizeli</a>)</li>
<li>Device tracker component &amp; platform validation. No more home_range. (<a href="https://github.com/kellerza">@kellerza</a>)</li>
<li>Added option to use effect:random for Flux Led light bulbs (<a href="https://github.com/tchellomello">@tchellomello</a>)</li>
<li>Use voluptuous for smtp (<a href="https://github.com/pvizeli">@pvizeli</a>)</li>
<li>Upgrade sendgrid to 3.2.10 (<a href="https://github.com/fabaff">@fabaff</a>)</li>
<li>Upgrade TwitterAPI to 2.4.2 (<a href="https://github.com/fabaff">@fabaff</a>)</li>
<li>Fix bug in wemo discovery caused by voluptuous addition. (<a href="https://github.com/pavoni">@pavoni</a>)</li>
<li>Bug fix for asuswrt device_tracker. (<a href="https://github.com/Danielhiversen">@Danielhiversen</a>)</li>
<li>Remove units for humidity in Wundeground sensor (<a href="https://github.com/arsaboo">@arsaboo</a>)</li>
<li>Fix media_player descriptions and select_source (<a href="https://github.com/MartinHjelmare">@MartinHjelmare</a>)</li>
<li>Allow user to configure server id to perform speed test against (<a href="https://github.com/Teagan42">@Teagan42</a>)</li>
<li>Bug fix for asuswrt device_tracker. (<a href="https://github.com/Danielhiversen">@Danielhiversen</a>)</li>
<li>More Ecobee operation mode fixes (<a href="https://github.com/turbokongen">@turbokongen</a>)</li>
<li>Map Modes to setpoint indexes (<a href="https://github.com/turbokongen">@turbokongen</a>)</li>
<li>fix voluptuous and cover autodiscovery (<a href="https://github.com/pvizeli">@pvizeli</a>)</li>
<li>Fixes wrong statevalue and problem with zwave setpoint (<a href="https://github.com/turbokongen">@turbokongen</a>)</li>
</ul>
<h2><a class="title-link" name="hotfix-0272---september-3" href="#hotfix-0272---september-3"></a> Hotfix 0.27.2 - September 3</h2>
<h3>home-assistant</h3>
<ul>
<li>Ble fix (<a href="https://github.com/home-assistant/home-assistant/pull/3019">#3019</a>) - (<a href="https://github.com/open-homeautomation">@open-homeautomation</a>)</li>
<li>Reset insteon hub (<a href="https://github.com/home-assistant/home-assistant/pull/3062">#3062</a>) - (<a href="https://github.com/Teagan42">@Teagan42</a>)</li>
<li>Host should be optional for apcupsd component (<a href="https://github.com/home-assistant/home-assistant/pull/3072">#3072</a>) - (<a href="https://github.com/Danielhiversen">@Danielhiversen</a>)</li>
<li>Zwave climate Bugfix: if some setpoints have different units, we should fetch the o… (<a href="https://github.com/home-assistant/home-assistant/pull/3078">#3078</a>) - (<a href="https://github.com/turbokongen">@turbokongen</a>)</li>
<li>Bugfix unit fix (<a href="https://github.com/home-assistant/home-assistant/pull/3083">#3083</a>) - (<a href="https://github.com/turbokongen">@turbokongen</a>)</li>
<li>Ecobee humidity slider (<a href="https://github.com/home-assistant/home-assistant/pull/3088">#3088</a>) - (<a href="https://github.com/turbokongen">@turbokongen</a>)</li>
<li>Zwave Climate Bugfix: If device was off target temp was null. Default to Heating setpoint (<a href="https://github.com/home-assistant/home-assistant/pull/3091">#3091</a>) - (<a href="https://github.com/turbokongen">@turbokongen</a>)</li>
<li>Climate and cover bugfix (<a href="https://github.com/home-assistant/home-assistant/pull/3097">#3097</a>) - (<a href="https://github.com/turbokongen">@turbokongen</a>)</li>
<li>Add missing docstrings (fix PEP257 issues) (<a href="https://github.com/home-assistant/home-assistant/pull/3098">#3098</a>) - (<a href="https://github.com/fabaff">@fabaff</a>)</li>
<li>Allow None MAC to be loaded from known_devices (<a href="https://github.com/home-assistant/home-assistant/pull/3102">#3102</a>) - (<a href="https://github.com/kellerza">@kellerza</a>)</li>
<li>fix homematic climate implementation (<a href="https://github.com/home-assistant/home-assistant/pull/3114">#3114</a>) - (<a href="https://github.com/pvizeli">@pvizeli</a>)</li>
<li>Fixed Homematic cover (<a href="https://github.com/home-assistant/home-assistant/pull/3116">#3116</a>) - (<a href="https://github.com/danielperna84">@danielperna84</a>)</li>
<li>Bugfix. climate and covermqt (<a href="https://github.com/home-assistant/home-assistant/pull/3130">#3130</a>) - (<a href="https://github.com/turbokongen">@turbokongen</a>)</li>
</ul>
<h3>home-assistant-polymer</h3>
<ul>
<li>Fix missing attributes on the climate and HVAC more info cards (<a href="https://github.com/home-assistant/home-assistant-polymer/commit/7e455e2be1cb7cc4f55628b063019bea548a3182">7e455e2</a>) - (<a href="https://github.com/robbiet480">@robbiet480</a>)</li>
<li>Add a default icon for the fan component (<a href="https://github.com/home-assistant/home-assistant-polymer/pull/101">#101</a>) - (<a href="https://github.com/robbiet480">@robbiet480</a>)</li>
</ul>
</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/28/notifications-hue-fake-unification/"
data-counturl="https://home-assistant.io/blog/2016/08/28/notifications-hue-fake-unification/" >Tweet</a>
<div class="fb-share-button" style='top: -6px;'
data-href="https://home-assistant.io/blog/2016/08/28/notifications-hue-fake-unification/"
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/11/05/hacktoberfest-influxdb-weather/">0.32: Hacktoberfest, InfluxDB sensor, Error reporting, and Weather</a>
</li>
<li class="post">
<a href="/blog/2016/10/25/explaining-the-updater/">Explaining the Updater</a>
</li>
<li class="post">
<a href="/blog/2016/10/22/flash-briefing-updater-hacktoberfest/">0.31: Reading you the news, some serious business, spooky hackery and a breaking Z-Wave change</a>
</li>
<li class="post">
<a href="/blog/2016/10/08/hassbian-rest-digital-ocean/">0.30: More Async, HASSbian, Digital Ocean, statistics, REST</a>
</li>
<li class="post">
<a href="/blog/2016/10/02/hacktoberfest/">Participating in Hacktoberfest</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/28/notifications-hue-fake-unification/';
var disqus_url = 'https://home-assistant.io/blog/2016/08/28/notifications-hue-fake-unification/';
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

@ -1,352 +0,0 @@
<!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>ESP8266 and MicroPython - Part 2 - Home Assistant</title>
<meta name="author" content="Fabian Affolter">
<meta name="description" content="Using MicroPython and MQTT on ESP8266 based devices and Home Assistant.">
<meta name="viewport" content="width=device-width">
<link rel="canonical" href="https://home-assistant.io/blog/2016/08/31/esp8266-and-micropython-part2/">
<meta property="fb:app_id" content="338291289691179">
<meta property="og:title" content="ESP8266 and MicroPython - Part 2">
<meta property="og:site_name" content="Home Assistant">
<meta property="og:url" content="https://home-assistant.io/blog/2016/08/31/esp8266-and-micropython-part2/">
<meta property="og:type" content="article">
<meta property="og:description" content="Using MicroPython and MQTT on ESP8266 based devices and Home Assistant.">
<meta property="og:image" content="https://home-assistant.io/images/blog/2016-07-micropython/social.png">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@home_assistant">
<meta name="twitter:title" content="ESP8266 and MicroPython - Part 2">
<meta name="twitter:description" content="Using MicroPython and MQTT on ESP8266 based devices and Home Assistant.">
<meta name="twitter:image" content="https://home-assistant.io/images/blog/2016-07-micropython/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="/ecosystem/">Ecosystem</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">ESP8266 and MicroPython - Part 2</h1>
<div class="meta clearfix">
<time datetime="2016-08-31T04:17:25+00:00" pubdate data-updated="true"><i class="icon-calendar"></i> August 31, 2016</time>
<span class="byline author vcard"><i class='icon-user'></i> Fabian Affolter</span>
<span><i class='icon-time'></i> three minutes reading time</span>
<span>
<i class="icon-tags"></i>
<ul class="tags unstyled">
<li>ESP8266</li>
<li>How-To</li>
<li>MQTT</li>
<li>Micropython</li>
</ul>
</span>
<a class='comments'
href="#disqus_thread"
>Comments</a>
</div>
</header>
<p><img src="/images/blog/2016-07-micropython/micropython.png" style="clear: right; border:none; box-shadow: none; float: right; margin-bottom: 12px;" width="200" />
So, part 1 of <a href="/blog/2016/07/28/esp8266-and-micropython-part1/">ESP8266 and MicroPython</a> was pretty lame, right? Instead of getting information out of Home Assistant we are going a step forward and create our own sensor which is sending details about its state to a Home Assistant instance.</p>
<a name="read-more"></a>
<p>Beside <a href="https://en.wikipedia.org/wiki/POST_(HTTP)">HTTP POST</a> requests, MQTT is the quickest way (from the authors point of view) to publish information with DIY devices.</p>
<p>You have to make a decision: Do you want to pull or to poll? For slowly changing values like temperature its perfectly fine to wait a couple of seconds to retrieve the value. If its a motion detector the state change should be available instantly. This means the sensor must take initiative.</p>
<p>An example for pulling is <a href="/components/sensor.arest/">aREST</a>. This is a great way to work with the ESP8266 based units and the Ardunio IDE.</p>
<h3><a class="title-link" name="mqtt" href="#mqtt"></a> MQTT</h3>
<p>You can find a simple examples for publishing and subscribing with MQTT in the <a href="https://github.com/micropython/micropython-lib">MicroPython</a> library overview in the section for <a href="https://github.com/micropython/micropython-lib/tree/master/umqtt.simple">umqtt</a>.</p>
<p>The example below is adopted from the work of <a href="https://github.com/davea">@davea</a> as we dont want to re-invent the wheel. The configuration feature is crafty and simplyfies the code with the usage of a file called <code class="highlighter-rouge">/config.json</code> which stores the configuration details. The ESP8266 device will send the value of a pin every 5 seconds.</p>
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">machine</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">import</span> <span class="nn">ubinascii</span>
<span class="kn">import</span> <span class="nn">webrepl</span>
<span class="kn">from</span> <span class="nn">umqtt.simple</span> <span class="kn">import</span> <span class="n">MQTTClient</span>
<span class="c"># These defaults are overwritten with the contents of /config.json by load_config()</span>
<span class="n">CONFIG</span> <span class="o">=</span> <span class="p">{</span>
<span class="s">"broker"</span><span class="p">:</span> <span class="s">"192.168.1.19"</span><span class="p">,</span>
<span class="s">"sensor_pin"</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="s">"client_id"</span><span class="p">:</span> <span class="n">b</span><span class="s">"esp8266_"</span> <span class="o">+</span> <span class="n">ubinascii</span><span class="o">.</span><span class="n">hexlify</span><span class="p">(</span><span class="n">machine</span><span class="o">.</span><span class="n">unique_id</span><span class="p">()),</span>
<span class="s">"topic"</span><span class="p">:</span> <span class="n">b</span><span class="s">"home"</span><span class="p">,</span>
<span class="p">}</span>
<span class="n">client</span> <span class="o">=</span> <span class="bp">None</span>
<span class="n">sensor_pin</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">def</span> <span class="nf">setup_pins</span><span class="p">():</span>
<span class="k">global</span> <span class="n">sensor_pin</span>
<span class="n">sensor_pin</span> <span class="o">=</span> <span class="n">machine</span><span class="o">.</span><span class="n">ADC</span><span class="p">(</span><span class="n">CONFIG</span><span class="p">[</span><span class="s">'sensor_pin'</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">load_config</span><span class="p">():</span>
<span class="kn">import</span> <span class="nn">ujson</span> <span class="kn">as</span> <span class="nn">json</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"/config.json"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">config</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
<span class="k">except</span> <span class="p">(</span><span class="nb">OSError</span><span class="p">,</span> <span class="nb">ValueError</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Couldn't load /config.json"</span><span class="p">)</span>
<span class="n">save_config</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">CONFIG</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">config</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Loaded config from /config.json"</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">save_config</span><span class="p">():</span>
<span class="kn">import</span> <span class="nn">ujson</span> <span class="kn">as</span> <span class="nn">json</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"/config.json"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">CONFIG</span><span class="p">))</span>
<span class="k">except</span> <span class="nb">OSError</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Couldn't save /config.json"</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">client</span> <span class="o">=</span> <span class="n">MQTTClient</span><span class="p">(</span><span class="n">CONFIG</span><span class="p">[</span><span class="s">'client_id'</span><span class="p">],</span> <span class="n">CONFIG</span><span class="p">[</span><span class="s">'broker'</span><span class="p">])</span>
<span class="n">client</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Connected to {}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">CONFIG</span><span class="p">[</span><span class="s">'broker'</span><span class="p">]))</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">sensor_pin</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<span class="n">client</span><span class="o">.</span><span class="n">publish</span><span class="p">(</span><span class="s">'{}/{}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">CONFIG</span><span class="p">[</span><span class="s">'topic'</span><span class="p">],</span>
<span class="n">CONFIG</span><span class="p">[</span><span class="s">'client_id'</span><span class="p">]),</span>
<span class="nb">bytes</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">),</span> <span class="s">'utf-8'</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Sensor state: {}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">data</span><span class="p">))</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">load_config</span><span class="p">()</span>
<span class="n">setup_pins</span><span class="p">()</span>
<span class="n">main</span><span class="p">()</span>
</code></pre>
</div>
<p>Subscribe to the topic <code class="highlighter-rouge">home/#</code> or create a <a href="/components/sensor.mqtt/">MQTT sensor</a> to check if the sensor values are published.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>mosquitto_sub -h 192.168.1.19 -v -t <span class="s2">"home/#"</span>
</code></pre>
</div>
<div class="language-yaml highlighter-rouge"><pre class="highlight"><code><span class="s">sensor</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">platform</span><span class="pi">:</span> <span class="s">mqtt</span>
<span class="s">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">home/esp8266_[last</span><span class="nv"> </span><span class="s">part</span><span class="nv"> </span><span class="s">of</span><span class="nv"> </span><span class="s">the</span><span class="nv"> </span><span class="s">MAC</span><span class="nv"> </span><span class="s">address]"</span>
<span class="s">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">MicroPython"</span>
</code></pre>
</div>
<p><a href="https://github.com/davea">@davea</a> created <a href="https://github.com/davea/sonoff-mqtt">sonoff-mqtt</a>. This code will work on ESP8622 based devices too and shows how to use a button to control a relay.</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/31/esp8266-and-micropython-part2/"
data-counturl="https://home-assistant.io/blog/2016/08/31/esp8266-and-micropython-part2/" >Tweet</a>
<div class="fb-share-button" style='top: -6px;'
data-href="https://home-assistant.io/blog/2016/08/31/esp8266-and-micropython-part2/"
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/11/05/hacktoberfest-influxdb-weather/">0.32: Hacktoberfest, InfluxDB sensor, Error reporting, and Weather</a>
</li>
<li class="post">
<a href="/blog/2016/10/25/explaining-the-updater/">Explaining the Updater</a>
</li>
<li class="post">
<a href="/blog/2016/10/22/flash-briefing-updater-hacktoberfest/">0.31: Reading you the news, some serious business, spooky hackery and a breaking Z-Wave change</a>
</li>
<li class="post">
<a href="/blog/2016/10/08/hassbian-rest-digital-ocean/">0.30: More Async, HASSbian, Digital Ocean, statistics, REST</a>
</li>
<li class="post">
<a href="/blog/2016/10/02/hacktoberfest/">Participating in Hacktoberfest</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/31/esp8266-and-micropython-part2/';
var disqus_url = 'https://home-assistant.io/blog/2016/08/31/esp8266-and-micropython-part2/';
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>