Site updated at 2017-04-25 09:16:46 UTC

This commit is contained in:
Travis CI 2017-04-25 09:16:46 +00:00
parent a918280d3a
commit e23b04f8c9
177 changed files with 1469 additions and 1149 deletions

View file

@ -4,7 +4,7 @@
<title><![CDATA[Category: How-To | Home Assistant]]></title>
<link href="https://home-assistant.io/blog/categories/how-to/atom.xml" rel="self"/>
<link href="https://home-assistant.io/"/>
<updated>2017-04-25T07:26:49+00:00</updated>
<updated>2017-04-25T09:12:40+00:00</updated>
<id>https://home-assistant.io/</id>
<author>
<name><![CDATA[Home Assistant]]></name>
@ -13,6 +13,60 @@
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Setting up InfluxDB and Grafana using Docker]]></title>
<link href="https://home-assistant.io/blog/2017/04/25/influxdb-grafana-docker/"/>
<updated>2017-04-25T08:04:05+00:00</updated>
<id>https://home-assistant.io/blog/2017/04/25/influxdb-grafana-docker</id>
<content type="html"><![CDATA[Home Assistant collects volumes of (time series) data that are well suited for some fancy graphs. Although the [History](https://home-assistant.io/components/history/) component provides some nice plots, I am sure you have always wanted those fancy [Grafana](https://grafana.com/) plots. The problem, however, is that low-powered device such as Raspberry Pi that most of us use for our Home Assistant setup are not well suited for such operation.
Instead of running [InfluxDB](https://www.influxdata.com/) and Grafana on a Raspberry Pi or a different system and go through the [classic approach of installing both tools separately](/blog/2015/12/07/influxdb-and-grafana/), you can run them in a Docker container on another machine. For this tutorial, I am using a Synology NAS, but the instructions should apply to other devices that can run Docker. Just follow the steps below:
1. SSH into your NAS. You may have to run `sudo su` if you are getting permission errors.
2. Download the [docker-statsd-influxdb-grafana]( https://hub.docker.com/r/samuelebistoletti/docker-statsd-influxdb-grafana/) image using the command:
`docker pull samuelebistoletti/docker-statsd-influxdb-grafana`
3. To start the container for the first-time launch:
```
docker run -d \
--name docker-statsd-influxdb-grafana \
-p 3003:3003 \
-p 3004:8083 \
-p 8086:8086 \
-p 22022:22 \
-p 8125:8125/udp \
samuelebistoletti/docker-statsd-influxdb-grafana:latest
```
4. The image should now be running and both InfluxBD and Grafana should be now up and running.
5. You can access InfluxDB at http://NAS_IP_ADDRESS:3004/ and Grafana at http://NAS_IP_ADDRESS:3003/
6. Navigate to http://NAS_IP_ADDRESS:3004/ and create the database `home_assistant` using the command `CREATE DATABASE home_assistant`.
<p class='img'>
<img src='https://home-assistant.io/images/blog/2017-04-influxdb-grafana/create_HA_database.png' />
</p>
7. Now, you need to configure Home Assistant to use InfluxDB. Since, we did not add any username/password to our database, we can simply add the following to our configuration.yaml (replace the IP address with that of the device running Docker) and restart Home Assistant to setup InfluxDB (you will have to fine tune it based on your preferences):
```
influxdb:
host: 192.168.2.113
```
8. Next, we need to configure Grafana to use InfluxDB. Navigate to http://NAS_IP_ADDRESS:3003/ to access Grafana (login with username and password `root`) and add your first data source. Heres how you can configure Grafana to use InfluxDB database. Note that 192.168.2.113 is the IP address of my NAS.
<p class='img'>
<img src='https://home-assistant.io/images/blog/2017-04-influxdb-grafana/add_data_source.png' />
</p>
9. You should see `Data source is working` if you have configured everything correctly.
10. With all that configured, you are now ready for the fun stuff. You can create as many dashboards as you want and then import the same in Home Assistant.
11. To add the Grafana dashboard in HA, use the following config:
```
panel_iframe:
router:
title: 'Temperature'
url: 'http://192.168.2.113:3003/dashboard/db/temperature?edit&tab=time%20range'
```
The URL can be obtained by clicking Share Dashboard link on your dashboard:
<p class='img'>
<img src='https://home-assistant.io/images/blog/2017-04-influxdb-grafana/share_dashboard.png' />
</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[HTTP to MQTT bridge]]></title>
<link href="https://home-assistant.io/blog/2017/03/28/http-to-mqtt-bridge/"/>
@ -339,132 +393,6 @@ Heatmap
[Jupyter notebook]: https://jupyter.org/
[nb-prev]: http://nbviewer.jupyter.org/github/home-assistant/home-assistant-notebooks/blob/master/DataExploration-2/DataExploration-2.ipynb
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[We Have Apps Now]]></title>
<link href="https://home-assistant.io/blog/2016/08/16/we-have-apps-now/"/>
<updated>2016-08-16T10:00:00+00:00</updated>
<id>https://home-assistant.io/blog/2016/08/16/we-have-apps-now</id>
<content type="html"><![CDATA[I have been working on a new subsystem to complement Home Assistant's Automation and Scripting components. `AppDaemon` 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 `AppDaemon` 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.
<!--more-->
## <a class='title-link' name='another-take-on-automation' href='#another-take-on-automation'></a> Another Take on Automation
If you haven't yet read Paulus' excellent Blog entry on [Perfect Home Automation](https://home-assistant.io/blog/2016/01/19/perfect-home-automation/) 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".
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:
- Can the system respond to presence or absence of people?
- Can I turn a light on at Sunset +/- a certain amount of time?
- Can I arrive home in light or dark and have the lights figure out if they should be on or off?
- 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?
- Is it open and expandable?
- Does it run locally without any reliance on the cloud?
In my opinion, Home Assistant accomplishes the majority of these very well with a combination of Automations, Scripts and Templates, and it's Restful API.
So why `AppDaemon`? `AppDaemon` 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:
- New paradigm - some problems require a procedural and/or iterative approach, and `AppDaemon` 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 can't
- Ease of use - `AppDaemon`'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.
- 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
- Dynamic - `AppDaemon` has been designed from the start to enable the user to make changes without requiring a restart of Home Assistant, thanks to it's loose coupling. However, it is better than that - the user can make changes to code and `AppDaemon` 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 `AppDaemon` 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.
- Complex logic - Python's If/Else constructs are clearer and easier to code for arbitrarily complex nested logic
- 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
- All the power of Python - use any of Python's 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!
It is in fact a testament to Home Assistant's open nature that a component like `AppDaemon` 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 Assistant's 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 `AppDaemon` - 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.
## <a class='title-link' name='how-it-works' href='#how-it-works'></a> How it Works
The best way to show what `AppDaemon` does is through a few simple examples.
### <a class='title-link' name='sunrisesunset-lighting' href='#sunrisesunset-lighting'></a> Sunrise/Sunset Lighting
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 `initialize()` function called which gives it a chance to register a callback for `AppDaemons`'s scheduler for a specific time. In this case we are using `run_at_sunrise()` and `run_at_sunset()` to register 2 separate callbacks. The argument `0` 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 Python's `datetime.timedelta` class for calculations. When sunrise or sunset occurs, the appropriate callback function, `sunrise_cb()` or `sunset_cb()` is called which then makes a call to Home Assistant to turn the porch light on or off by activating a scene. The variables `args["on_scene"]` and `args["off_scene"]` 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.
```python
import appapi
class OutsideLights(appapi.AppDaemon):
def initialize(self):
self.run_at_sunrise(self.sunrise_cb, 0)
self.run_at_sunset(self.sunset_cb, 0)
def sunrise_cb(self, args, kwargs):
self.turn_on(self.args["off_scene"])
def sunset_cb(self, args, kwargs):
self.turn_on(self.args["on_scene"])
```
This is also fairly easy to achieve with Home Assistant automations, but we are just getting started.
### <a class='title-link' name='motion-light' href='#motion-light'></a> Motion Light
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 `initialize()` function registers a callback on a state change (of the motion sensor) rather than a specific time. We tell `AppDaemon` that we are only interested in state changes where the motion detector comes on by adding an additional parameter to the callback registration - `new = "on"`. When the motion is detected, the callack function `motion()` is called, and we check whether or not the sun has set using a built-in convenience function: `sun_down()`. Next, we turn the light on with `turn_on()`, then set a timer using `run_in()` 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 `AppDaemon` calling `light_off()` 60 seconds later using the `turn_off()` call to actually turn the light off. This is still pretty simple in code terms:
```python
import appapi
class MotionLights(appapi.AppDaemon):
def initialize(self):
self.listen_state(self.motion, "binary_sensor.drive", new = "on")
def motion(self, entity, attribute, old, new, kwargs):
if self.sun_down():
self.turn_on("light.drive")
self.run_in(self.light_off, 60)
def light_off(self, kwargs):
self.turn_off("light.drive")
```
This is starting to get a little more complex in Home Assistant automations requiring an Automation rule and two separate scripts.
Now lets extend this with a somewhat artificial example to show something that is simple in `AppDaemon` 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 `flash_warning()` 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.
```python
import appapi
class FlashyMotionLights(appapi.AppDaemon):
def initialize(self):
self.listen_state(self.motion, "binary_sensor.drive", new = "on")
def motion(self, entity, attribute, old, new, kwargs):
if self.self.sun_down():
self.turn_on("light.drive")
self.run_in(self.light_off, 60)
self.flashcount = 0
self.run_in(self.flash_warning, 1)
def light_off(self, kwargs):
self.turn_off("light.drive")
def flash_warning(self, kwargs):
self.toggle("light.living_room")
self.flashcount += 1
if self.flashcount < 10:
self.run_in(self.flash_warning, 1)
```
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.
In addition, Apps can write to `AppDaemon`'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.
I have spent the last few weeks moving all of my (fairly complex) automations over to `APPDaemon` and so far it is working very reliably.
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.
If this has whet your appetite, feel free to give it a try. You can find it, [here](https://github.com/acockburn/appdaemon), including full installation instructions, an API reference, and a number of fully fleshed out examples.
Happy Automating!
]]></content>
</entry>

View file

@ -71,6 +71,27 @@
<h2>2017</h2>
<article>
<div class="grid">
<div class="grid__item one-fifth palm-one-whole">
<time datetime="2017-04-25T08:04:05+00:00" pubdate>
<span class='month'>Apr</span> <span class='day'>25</span>
</time>
</div>
<div class="grid__item four-fifths palm-one-whole">
<h1 class="gamma"><a href="/blog/2017/04/25/influxdb-grafana-docker/">Setting up InfluxDB and Grafana using Docker</a></h1>
<footer class="meta">
<span>
<i class="icon-tags"></i>
<ul class="tags unstyled">
<li><a class='category' href='/blog/categories/how-to/'>How-To</a></li>
</ul>
</span>
</footer>
<hr class="divider">
</div>
</div>
</article>
<article>
<div class="grid">
<div class="grid__item one-fifth palm-one-whole">
<time datetime="2017-03-28T06:00:00+00:00" pubdate>
<span class='month'>Mar</span> <span class='day'>28</span>
@ -542,6 +563,9 @@
<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/2017/04/25/influxdb-grafana-docker/">Setting up InfluxDB and Grafana using Docker</a>
</li>
<li class="post">
<a href="/blog/2017/04/24/hardware-contest-2017/">Hardware Contest 2017</a>
</li>
@ -554,9 +578,6 @@
<li class="post">
<a href="/blog/2017/04/15/ios/">1 year and 22 days ago I had an idea...</a>
</li>
<li class="post">
<a href="/blog/2017/04/08/eddystone-beacons-lockitron-locks-total-connect/">Home Assistant 0.42: Eddystone Beacons, Lockitron locks and Total Connect alarm systems</a>
</li>
</ul>
</section>
</div>