422 lines
33 KiB
HTML
422 lines
33 KiB
HTML
<!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>AppDaemon - Home Assistant</title>
|
||
<meta name="author" content="Home Assistant">
|
||
<meta name="description" content="AppDaemon is a loosely coupled, multithreaded, sandboxed Python execution environment for writing automation apps for Home Assistant">
|
||
<meta name="viewport" content="width=device-width">
|
||
<link rel="canonical" href="https://home-assistant.io/docs/ecosystem/appdaemon/">
|
||
<meta property="fb:app_id" content="338291289691179">
|
||
<meta property="og:title" content="AppDaemon">
|
||
<meta property="og:site_name" content="Home Assistant">
|
||
<meta property="og:url" content="https://home-assistant.io/docs/ecosystem/appdaemon/">
|
||
<meta property="og:type" content="article">
|
||
<meta property="og:description" content="AppDaemon is a loosely coupled, multithreaded, sandboxed Python execution environment for writing automation apps for Home Assistant">
|
||
<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="AppDaemon">
|
||
<meta name="twitter:description" content="AppDaemon is a loosely coupled, multithreaded, sandboxed Python execution environment for writing automation apps for Home Assistant">
|
||
<meta name="twitter:image" content="https://home-assistant.io/images/default-social.png">
|
||
<link href="/stylesheets/screen.css" media="screen, projection, print" 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 class='site-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="/docs/">Docs</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>
|
||
<li><a href='#' class='show-search'><i class="icon-search"></i></a></li>
|
||
</ul>
|
||
</nav>
|
||
<div class='search-container' style='display: none'>
|
||
<div class='search'>
|
||
<i class="icon-search"></i>
|
||
<input id='search' placeholder='Search the docs…'>
|
||
<a href='#' class='close'><i class="icon-remove-sign"></i></a>
|
||
</div>
|
||
</div>
|
||
</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="page">
|
||
<div class='edit-github'><a href='https://github.com/home-assistant/home-assistant.github.io/tree/current/source/_docs/ecosystem/appdaemon.markdown'>Edit this page on GitHub</a></div>
|
||
<header>
|
||
<h1 class="title indent">
|
||
AppDaemon
|
||
</h1>
|
||
</header>
|
||
<hr class="divider">
|
||
<p>AppDaemon is a loosely coupled, multithreaded, sandboxed python execution environment for writing automation apps for Home Assistant.</p>
|
||
<h1>Another Take on Automation</h1>
|
||
<p>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:</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 can’t.</li>
|
||
<li>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.</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 five 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 - AppDaemon 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 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 <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. 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 - Python’s 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 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!</li>
|
||
</ul>
|
||
<p>It is in fact a testament to Home Assistant’s 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 Assistant’s underlying design is that it makes no assumptions whatsoever about what it is controlling, 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 additional functions to make things that were already possible easier.</p>
|
||
<h1>How it Works</h1>
|
||
<p>The best way to show what AppDaemon does is through a few simple examples.</p>
|
||
<h2>Sunrise/Sunset Lighting</h2>
|
||
<p>Let’s 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 AppDaemons’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 two 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 Python’s <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">appdaemon.appapi</span> <span class="kn">as</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="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="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">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">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>
|
||
<h2>Motion Light</h2>
|
||
<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 AppDaemon 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 callback 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">appdaemon.appapi</span> <span class="kn">as</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="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 let’s extend this with a somewhat artificial example to show something that is simple in AppDaemon but very difficult if not impossible using automations. Let’s warn someone inside the house that there has been motion outside by flashing a lamp on and off ten 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 ten iterations.</p>
|
||
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">appdaemon.appapi</span> <span class="kn">as</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="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"><</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 provide 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 log files, and there is a system of constraints that allows you to control when and under what circumstances Apps and callbacks are active to keep the logic clean and simple.</p>
|
||
<p>For full installation instructions, see the <a href="http://appdaemon.readthedocs.io/en/stable/">AppDaemon Project Documentation pages</a>.</p>
|
||
</article>
|
||
</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">
|
||
<div class='section'>
|
||
<h1 class="title delta">Topics</h1>
|
||
<ul class='divided sidebar-menu'>
|
||
<li>
|
||
<b><a href='/faq/'>FAQ </a></b> |
|
||
<b><a href='/docs/glossary/'>Glossary </a></b>
|
||
</li>
|
||
<li>
|
||
<b><a href='/docs/installation/'>Installation </a></b>
|
||
<ul>
|
||
<li><a href='/hassio/'>Hass.io </a></li>
|
||
<li><a href='/docs/installation/virtualenv/'>Python Virtual Env </a></li>
|
||
<li><a href='/docs/installation/hassbian/'>Hassbian </a></li>
|
||
<!--<li><a href='/docs/installation/raspberry-pi-all-in-one/'>Raspberry Pi All-in-One </a></li>-->
|
||
<li><a href='/docs/installation/updating/'>Updating </a></li>
|
||
<li><a href='/docs/installation/troubleshooting/'>Troubleshooting </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<b><a href='/docs/configuration/'>Configuration </a></b>
|
||
<ul>
|
||
<li><a href='/docs/configuration/yaml/'>YAML </a></li>
|
||
<li><a href='/docs/configuration/basic/'>Basic information </a></li>
|
||
<li><a href='/docs/configuration/devices/'>Setting up devices </a></li>
|
||
<li><a href='/docs/configuration/customizing-devices/'>Customizing entities </a></li>
|
||
<li><a href='/docs/configuration/troubleshooting/'>Troubleshooting </a></li>
|
||
<li><a href='/docs/configuration/securing/'>Security Check Points </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<b>Advanced Configuration</b>
|
||
<ul>
|
||
<li><a href='/docs/configuration/remote/'>Remote access </a></li>
|
||
<li><a href='/docs/configuration/packages/'>Packages </a></li>
|
||
<li><a href='/docs/configuration/splitting_configuration/'>Splitting up the configuration </a></li>
|
||
<li><a href='/docs/configuration/secrets/'>Storing Secrets </a></li>
|
||
<li><a href='/docs/configuration/templating/'>Templating </a></li>
|
||
<li><a href='/docs/configuration/group_visibility/'>Group Visibility </a></li>
|
||
<li><a href='/docs/configuration/platform_options/'>Entity component platform options </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<b>Core objects</b>
|
||
<ul>
|
||
<li><a href='/docs/configuration/events/'>Events </a></li>
|
||
<li><a href='/docs/configuration/state_object/'>State Objects </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<b><a href='/docs/automation/'>Automation </a></b>
|
||
<ul>
|
||
<li><a href='/docs/automation/examples/'>Examples </a></li>
|
||
<li><a href='/docs/automation/editor/'>Editor </a></li>
|
||
<li><a href='/docs/automation/trigger/'>Triggers </a></li>
|
||
<li><a href='/docs/automation/condition/'>Conditions </a></li>
|
||
<li><a href='/docs/automation/action/'>Actions </a></li>
|
||
<li><a href='/docs/automation/templating/'>Templates </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<b><a href='/docs/frontend/'>Frontend </a></b>
|
||
<ul>
|
||
<li><a href='/docs/frontend/mobile/'>Android/iOS Homescreen </a></li>
|
||
<li><a href='/docs/frontend/webserver/'>Web server fingerprint </a></li>
|
||
<li><a href='/docs/frontend/browsers/'>Browser Compatibility List </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<b><a href='/docs/backend/'>Backend </a></b>
|
||
<ul>
|
||
<li><a href='/docs/backend/database/'>Database </a></li>
|
||
<li><a href='/docs/backend/updater/'>Updater </a></li>
|
||
<li><a href='/developers/api/'>API </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<b><a href='/docs/scripts/'>Scripts </a></b>
|
||
<ul>
|
||
<li><a href='/docs/scripts/service-calls/'>Service Calls </a></li>
|
||
<li><a href='/docs/scripts/conditions/'>Conditions </a></li>
|
||
<li><a href='/docs/scripts/editor/'>Editor </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<b><a href='/docs/tools/'>Tools and Helpers </a></b>
|
||
<ul>
|
||
<li><a href='/docs/tools/dev-tools/'>Developer Tools </a></li>
|
||
<li><a href='/docs/tools/hass/'>hass </a></li>
|
||
<li><a href='/docs/tools/benchmark/'>benchmark </a></li>
|
||
<li><a href='/docs/tools/check_config/'>check_config </a></li>
|
||
<li><a href='/docs/tools/credstash/'>credstash </a></li>
|
||
<li><a href='/docs/tools/db_migrator/'>db_migrator </a></li>
|
||
<li><a href='/docs/tools/ensure_config/'>ensure_config </a></li>
|
||
<li><a href='/docs/tools/influxdb_import/'>influxdb_import </a></li>
|
||
<li><a href='/docs/tools/influxdb_migrator/'>influxdb_migrator </a></li>
|
||
<li><a href='/docs/tools/keyring/'>keyring </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<b><a href='/docs/z-wave/'>Z-Wave </a></b>
|
||
<ul>
|
||
<li><a href='/docs/z-wave/installation/'>Configuring the Z-Wave component </a></li>
|
||
<li><a href='/docs/z-wave/adding/'>Adding devices </a></li>
|
||
<li><a href='/docs/z-wave/control-panel/'>The Z-Wave control panel </a></li>
|
||
<li><a href='/docs/z-wave/controllers/'>Controllers </a></li>
|
||
<li><a href='/docs/z-wave/devices/'>Devices </a> and <a href='/docs/z-wave/entities/'>Entities </a></li>
|
||
<li><a href='/docs/z-wave/query-stage/'>Query Stages </a> for devices</li>
|
||
<li><a href='/docs/z-wave/device-specific/'>Device Specific </a> configuration</li>
|
||
<li><a href='/docs/z-wave/events/'>Events </a> and <a href='/docs/z-wave/services/'>Services </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<b><a href='/docs/mqtt/'>MQTT </a></b>
|
||
<ul>
|
||
<li><a href='/docs/mqtt/broker/'>Broker </a></li>
|
||
<li><a href='/docs/mqtt/certificate/'>Certificate </a></li>
|
||
<li><a href='/docs/mqtt/discovery/'>Discovery </a></li>
|
||
<li><a href='/docs/mqtt/service/'>Publish service </a></li>
|
||
<li><a href='/docs/mqtt/birth_will/'>Birth and last will messages </a></li>
|
||
<li><a href='/docs/mqtt/testing/'>Testing your setup </a></li>
|
||
<li><a href='/docs/mqtt/logging/'>Logging </a></li>
|
||
<li><a href='/docs/mqtt/processing_json/'>Processing JSON </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<b><a href='/docs/ecosystem/ios/'>iOS </a></b>
|
||
<ul>
|
||
<li><a href='/docs/ecosystem/ios/notifications/basic/'>Basic notifications </a></li>
|
||
<ul>
|
||
<li><a href='/docs/ecosystem/ios/notifications/sounds/'>Sounds </a></li>
|
||
<li><a href='/docs/ecosystem/ios/notifications/architecture/'>Architecture </a></li>
|
||
<li><a href='/docs/ecosystem/ios/notifications/privacy_security_rate_limits/'>Privacy, rate limiting and security </a></li>
|
||
</ul>
|
||
<li>Advanced notifications</li>
|
||
<ul>
|
||
<li><a href='/docs/ecosystem/ios/notifications/attachments/'>Attachments </a></li>
|
||
<li><a href='/docs/ecosystem/ios/notifications/content_extensions/'>Dynamic content </a></li>
|
||
<li><a href='/docs/ecosystem/ios/notifications/actions/'>Actionable notifications </a></li>
|
||
<li><a href='/docs/ecosystem/ios/notifications/requesting_location_updates/'>Requesting location updates </a></li>
|
||
</ul>
|
||
<li><a href='/docs/ecosystem/ios/location/'>Location Tracking </a></li>
|
||
<li><a href='/docs/ecosystem/ios/integration/'>Integration with other apps </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<a href='/docs/ecosystem/'>Ecosystem </a>
|
||
<ul>
|
||
<li>
|
||
<a href='/docs/autostart/'>Autostart </a>
|
||
<ul>
|
||
<li><a href='/docs/autostart/systemd/'>systemd (Linux) </a></li>
|
||
<li><a href='/docs/autostart/upstart/'>Upstart (Linux) </a></li>
|
||
<li><a href='/docs/autostart/init.d/'>init.d (Linux) </a></li>
|
||
<li><a href='/docs/autostart/macos/'>macOS </a></li>
|
||
<li><a href='/docs/autostart/synology/'>Synology NAS </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<a class='active' href='/docs/ecosystem/appdaemon/'>AppDaemon </a>
|
||
</li>
|
||
<li>
|
||
<a href='/docs/ecosystem/hadashboard/'>HADashboard </a>
|
||
</li>
|
||
<li>
|
||
<a href='/docs/ecosystem/notebooks/'>Notebooks </a>
|
||
<ul>
|
||
<li><a href='/docs/ecosystem/notebooks/'>Introduction </a></li>
|
||
<li><a href='/docs/ecosystem/notebooks/installation/'>Installation </a></li>
|
||
<li><a href='/docs/ecosystem/notebooks/graph/'>Graph </a></li>
|
||
<li><a href='/docs/ecosystem/notebooks/api/'>Home Assistant API </a></li>
|
||
<li><a href='/docs/ecosystem/notebooks/database/'>Database </a></li>
|
||
<li><a href='/docs/ecosystem/notebooks/stats/'>Statistics </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
Remote access
|
||
<ul>
|
||
<li><a href='/docs/ecosystem/apache/'>Apache </a></li>
|
||
<li><a href='/docs/ecosystem/caddy/'>Caddy Server </a></li>
|
||
<li><a href='/docs/ecosystem/nginx/'>NGINX </a></li>
|
||
<li><a href='/docs/ecosystem/nginx_subdomain/'>NGINX with subdomain</a></li>
|
||
<li><a href='/docs/ecosystem/tor/'>Tor Onion Service </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<a href='/docs/ecosystem/certificates/'>Certificates </a>
|
||
<ul>
|
||
<li><a href='/docs/ecosystem/certificates/tls_self_signed_certificate/'>Self-signed certificate </a></li>
|
||
<li><a href='/docs/ecosystem/certificates/tls_domain_certificate/'>Certificate domain owners </a></li>
|
||
<li><a href='/docs/ecosystem/certificates/lets_encrypt/'>Let's Encrypt (detailed) </a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
Backup
|
||
<ul>
|
||
<li><a href='/docs/ecosystem/backup/backup_github/'>Backup to GitHub </a></li>
|
||
<li><a href='/docs/ecosystem/backup/backup_dropbox/'>Backup to Dropbox </a></li>
|
||
<li><a href='/docs/ecosystem/backup/backup_usb/'>Backup to USB device </a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href='/docs/ecosystem/scenegen/'>scenegen </a></li>
|
||
<li><a href='/docs/ecosystem/synology/'>Synology </a></li>
|
||
<li><a href='/docs/ecosystem/hass-configurator/'>HASS Configurator </a></li>
|
||
</ul>
|
||
</ul>
|
||
</div>
|
||
</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> (no support!).<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>
|
||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">home-assistant.io</span> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.
|
||
</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>
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.css" />
|
||
<script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js"></script>
|
||
<script type="text/javascript">
|
||
docsearch({
|
||
apiKey: 'ae96d94b201c5444c8a443093edf3efb',
|
||
indexName: 'home-assistant',
|
||
inputSelector: '#search',
|
||
debug: false // Set debug to true if you want to inspect the dropdown
|
||
});
|
||
document.querySelector('.search .close').addEventListener('click', function(ev) {
|
||
ev.preventDefault();
|
||
document.querySelector('.search-container').style.display = 'none';
|
||
});
|
||
document.querySelector('.show-search').addEventListener('click', function(ev) {
|
||
ev.preventDefault();
|
||
document.querySelector('.search-container').style.display = 'block';
|
||
document.getElementById('toggle').checked = false;
|
||
document.querySelector('.search-container input').focus();
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|