<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Home Assistant on mhemeryck</title><link>https://mhemeryck.xyz/tags/home-assistant/</link><description>Recent content in Home Assistant on mhemeryck</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Tue, 03 Aug 2021 00:00:00 +0000</lastBuildDate><atom:link href="https://mhemeryck.xyz/tags/home-assistant/index.xml" rel="self" type="application/rss+xml"/><item><title>Service</title><link>https://mhemeryck.xyz/posts/2021-08-03-home_automation_service/</link><pubDate>Tue, 03 Aug 2021 00:00:00 +0000</pubDate><guid>https://mhemeryck.xyz/posts/2021-08-03-home_automation_service/</guid><description>&lt;p&gt;Up to this point, I did already lay out all of the tidbits concerning the electricity, the I/O hardware units, even some custom software to provide an event-based API to address all of the various components in the overall system.
The final fundamental piece to bring everything together is what I call the &lt;em&gt;service&lt;/em&gt; layer, and specifically &lt;a href="https://www.home-assistant.io/"&gt;home assistant&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This post is a part of a larger series of posts on my home automation setup.
See the &lt;a href="https://mhemeryck.xyz/posts/2021-06-15-home_automation_why/"&gt;home automation overview post&lt;/a&gt;, to learn about the rationale and a description of the other posts!&lt;/p&gt;</description><content:encoded>&lt;p&gt;Up to this point, I did already lay out all of the tidbits concerning the electricity, the I/O hardware units, even some custom software to provide an event-based API to address all of the various components in the overall system.
The final fundamental piece to bring everything together is what I call the &lt;em&gt;service&lt;/em&gt; layer, and specifically &lt;a href="https://www.home-assistant.io/"&gt;home assistant&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This post is a part of a larger series of posts on my home automation setup.
See the &lt;a href="https://mhemeryck.xyz/posts/2021-06-15-home_automation_why/"&gt;home automation overview post&lt;/a&gt;, to learn about the rationale and a description of the other posts!&lt;/p&gt;
&lt;h2 id="architecture"&gt;Architecture&lt;/h2&gt;
&lt;p&gt;To recap, have a look at this drawing from the earlier &lt;a href="https://mhemeryck.xyz/posts/2021-06-22-home_automation_architecture/"&gt;home automation architecture post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://mhemeryck.xyz/2021-06-22/architecture.png" alt="architecture"&gt;&lt;/p&gt;
&lt;p&gt;In summary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a central MQTT broker: this component takes in &lt;em&gt;events&lt;/em&gt; on a &lt;em&gt;topic&lt;/em&gt; from the various &lt;em&gt;publishers&lt;/em&gt; and forwards them to any of the &lt;em&gt;subscribers&lt;/em&gt; for that topic&lt;/li&gt;
&lt;li&gt;all the unipi units: can take in any MQTT event to handle as &lt;em&gt;commands&lt;/em&gt; and pushes out events as &lt;em&gt;state&lt;/em&gt; updates.&lt;/li&gt;
&lt;li&gt;home assistant: has logic to trigger specific events on other events incoming&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that for this publish / subscribe system, all of the clients can (and will) function as both publisher and subscriber.&lt;/p&gt;
&lt;h2 id="home-assistant"&gt;home assistant&lt;/h2&gt;
&lt;p&gt;I already did mention home assistant, but what is it really?&lt;/p&gt;
&lt;p&gt;Home assistant is an open source software platform that was created with the vision of being able to integrate all sorts of IoT solutions.&lt;/p&gt;
&lt;p&gt;It is bundled with a huge amount of &lt;em&gt;integrations&lt;/em&gt; for various different vendors; check out the &lt;a href="https://www.home-assistant.io/integrations/"&gt;home assistant integrations&lt;/a&gt; page for an overview.
The way the platform is structured is via a number of &lt;a href="https://developers.home-assistant.io/docs/core/entity/"&gt;entities&lt;/a&gt;, e.g. a generic switch, light, etc &amp;hellip;
Each integration can then implement such entities.
The home assistant community would typically encourage new contributors to put the interfacing logic (e.g. an API client) in its own, open source library, to be called from the custom integration.
The added value of this approach is twofold:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the community rapidly gets more of these open source libraries&lt;/li&gt;
&lt;li&gt;the home assistant installation only needs to pull in the source libraries it needs, instead of having of a big blob of code.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The advantage of running your own platform is that you are more in control of your own hardware, less reliant on cloud solutions.&lt;/p&gt;
&lt;p&gt;Though not required, I did find it interesting to learn about more about the way home assistant itself is structured, check the &lt;a href="https://developers.home-assistant.io/docs/architecture_index"&gt;home assistant architecture dev docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The integration I have been mostly using is &lt;a href="https://www.home-assistant.io/integrations/mqtt/"&gt;home assistant MQTT integration&lt;/a&gt;.
At this point, this means that all of the I/O that is provided by the unipi units via an MQTT interface can now be readily represented as entities directly in home assistant!&lt;/p&gt;
&lt;h2 id="scenario"&gt;Scenario&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s make it more tangible by presenting the scenario from the &lt;a href="https://mhemeryck.xyz/posts/2021-06-22-home_automation_architecture/"&gt;home automation architecture post&lt;/a&gt; again, where a push button triggers a light.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://mhemeryck.xyz/2021-06-22/flow.png" alt="flow"&gt;&lt;/p&gt;
&lt;p&gt;In terms of the home assistant MQTT integration, the notion of &lt;em&gt;command&lt;/em&gt; and &lt;em&gt;state&lt;/em&gt; topics are quite relevant:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;command topic: this is a specific MQTT topic, e.g. &lt;code&gt;/{device}/{io}/set&lt;/code&gt; which accepts and incoming command to update the I/O. This scenario is typically coming from home assistant to the IO module.&lt;/li&gt;
&lt;li&gt;state topic: this topic is specific for reporting state updates back to any listeners, e.g. &lt;code&gt;/{device}/{io}/state&lt;/code&gt;. This is for the opposite scenario where the IO module itself updates its state back again to home assistant.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With this pair of topics for each entity, a typical flow combining command and state topics means:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;home assistant requesting a state update on the command topic of the IO module&lt;/li&gt;
&lt;li&gt;the IO module updates its value (e.g. toggles a relay for a light)&lt;/li&gt;
&lt;li&gt;the IO module sends out an update on the corresponding state topic&lt;/li&gt;
&lt;li&gt;home assistant then updates its matching entity according to the state topic&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In relation to the flow diagram above:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;on the push of the button, an MQTT event is pushed out to the &lt;em&gt;state&lt;/em&gt; topic&lt;/li&gt;
&lt;li&gt;the MQTT broker pushes the state update to home assistant&lt;/li&gt;
&lt;li&gt;home assistant updates the matching &lt;a href="https://www.home-assistant.io/integrations/switch.mqtt/"&gt;home assistant MQTT switch&lt;/a&gt; entity&lt;/li&gt;
&lt;li&gt;home assistant triggers an &lt;em&gt;automation&lt;/em&gt; which connects a state update for the push button entity to a matching light entity&lt;/li&gt;
&lt;li&gt;to update the light entity, an event is published on that &lt;a href="https://www.home-assistant.io/integrations/light.mqtt/"&gt;home assistant MQTT light&lt;/a&gt; entity&lt;/li&gt;
&lt;li&gt;the MQTT broker pushes the command to the subscribed I/O module&lt;/li&gt;
&lt;li&gt;the I/O module takes in the command to update its state and toggles the light accordingly&lt;/li&gt;
&lt;li&gt;after that, the I/O module triggers the relay, it pushes back an update on its state topic&lt;/li&gt;
&lt;li&gt;the MQTT broker forwards the state update again to home assistant&lt;/li&gt;
&lt;li&gt;home assistant sees the state update for that light entity and updates its internal state&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="containers-and-services"&gt;Containers and services&lt;/h2&gt;
&lt;p&gt;Home assistant has multiple ways of installing and running the platform, see the &lt;a href="https://www.home-assistant.io/installation/"&gt;home assistant installation&lt;/a&gt; page.&lt;/p&gt;
&lt;p&gt;First of all, you should be aware that the overall platform consists of multiple layers and the meaning of each of those has changed over time.
I would refer to the following diagram from the &lt;a href="https://developers.home-assistant.io/docs/architecture_index"&gt;home assistant architecture dev docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://developers.home-assistant.io/img/en/architecture/full.svg" alt="home assistant layers img"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;core: at the center, there&amp;rsquo;s the main home assistant software.&lt;/li&gt;
&lt;li&gt;supervisor: this component manages the core software, but it also has the capability to run other services besides home assistant, yet integrating them in a single UI&lt;/li&gt;
&lt;li&gt;operating system: the way I understand this, this is a minimal linux-based OS just to be able to run the supervisor for you. The idea is that at this level, you can just download a disk image, flash an SD-card and fire it up in a raspberry pi.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The core itself is actually a &lt;em&gt;containerized&lt;/em&gt; version of the main home assistant software, which in turn is a python application.
Check out the &lt;a href="https://hub.docker.com/r/homeassistant/home-assistant"&gt;home assistant core docker container&lt;/a&gt; on docker hub.
The rationale behind containerization is that you specify an image that contains an isolated environment for your application to run in.
Containers are different from &lt;em&gt;virtual machines&lt;/em&gt; in that multiple containers would share the same underlying OS kernel, which is better in terms of performance.&lt;/p&gt;
&lt;p&gt;Containerization has become dominant in current-day software development and infrastructure management; I use it on a daily basis.
A lot can be said on the topic of containerization and IT infrastructure, but I would like to keep this out of the discussion here.
If you would be considering gaining more knowledge on this, before anything, understand that containers are there to support a particular model of software development, i.e. &lt;em&gt;service-based&lt;/em&gt; development.
This typically means &lt;em&gt;stateless&lt;/em&gt;, &lt;em&gt;web-based&lt;/em&gt;, &lt;em&gt;services&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Apart from the container itself, you typically need something like a &lt;em&gt;supervisor&lt;/em&gt; or &lt;em&gt;container orchestrator&lt;/em&gt; to run the containers.
The orchestrator is responsible for e.g. starting the containers, making sure the correct amount of containers are running at the same time (redundancy, scaling), moving containers between hosts (in a multi-node setup), resource allocation, external networking, &amp;hellip;&lt;/p&gt;
&lt;p&gt;As mentioned, home assistant has its own orchestrator; the supervisor.
An orchestrator I often use for quick-and-dirty local development is &lt;a href="https://docs.docker.com/compose/"&gt;docker-compose&lt;/a&gt;.
The current de-facto industry standard is the google-backed &lt;a href="https://kubernetes.io/"&gt;kubernetes&lt;/a&gt;, abbreviated to k8s.
The lightweight version of this is &lt;a href="https://k3s.io/"&gt;k3s&lt;/a&gt;.
This probably not the end of the list, others like &lt;a href="https://www.nomadproject.io/"&gt;hashicorp nomad&lt;/a&gt; also exist.&lt;/p&gt;
&lt;p&gt;All of these have their own merits and disadvantages:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;orchestrator&lt;/th&gt;
&lt;th&gt;pros&lt;/th&gt;
&lt;th&gt;cons&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;home assistant supervisor&lt;/td&gt;
&lt;td&gt;built into the eco-system of home assistant&lt;/td&gt;
&lt;td&gt;container orchestration is &lt;em&gt;hard&lt;/em&gt; to do right, why roll your own?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;allows extra functionality in the same UI&lt;/td&gt;
&lt;td&gt;to me, this indicates a bad design, where a supervisor is responsible for more than what it&amp;rsquo;s intended&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;supposedly more suited for embedded platforms (raspi 3)&lt;/td&gt;
&lt;td&gt;low-memory footprint k8s alternatives exist, like the k3s mentioned before.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;docker-compose&lt;/td&gt;
&lt;td&gt;simple syntax&lt;/td&gt;
&lt;td&gt;only supports a subset of features&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;easy to get up an running&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;k8s&lt;/td&gt;
&lt;td&gt;the de-facto standard&lt;/td&gt;
&lt;td&gt;standard for web-based services and IT infrastructure management, might be overkill for IoT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;a lot of features, e.g. zero-downtime deployments!&lt;/td&gt;
&lt;td&gt;lots of concepts to grasp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Over the course of time, I think I have actually ran home assistant in all of these configurations (even including directly from source).
Like everything in IT, there is no real &lt;em&gt;right&lt;/em&gt; or &lt;em&gt;wrong&lt;/em&gt; solution, it depends on your specific situation.
My current approach is based on k3s &amp;ndash; but this is better left as the topic of a future post.&lt;/p&gt;
&lt;h2 id="sample-setup"&gt;Sample setup&lt;/h2&gt;
&lt;p&gt;All of the theoretical babble about containers and orchestration is just to come to this point where I can actually show something to run.
For this sample setup, I will build part of the service layer using only &lt;code&gt;docker-compose&lt;/code&gt; and a set of related home assistant configuration files.&lt;/p&gt;
&lt;p&gt;The final folder structure will look like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;├── automations.yaml
├── blueprints
│   ├── automation
│   │   └── homeassistant
│   │   ├── motion_light.yaml
│   │   └── notify_leaving_zone.yaml
│   └── script
│   └── homeassistant
│   └── confirmable_notification.yaml
├── configuration.yaml
├── deps
├── docker-compose.yaml
├── groups.yaml
├── home-assistant.log
├── scenes.yaml
├── scripts.yaml
├── secrets.yaml
├── tts
└── ui-lovelace.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For those interested, have a look at &lt;a href="https://mhemeryck.xyz/2021-08-03/hass.zip"&gt;&lt;code&gt;hass.zip&lt;/code&gt;&lt;/a&gt; for all of the source files.&lt;/p&gt;
&lt;p&gt;Most of these files were actually generated automatically when home assistant started the first time.
The format for all of the most relevant files is YAML, which stands for &amp;ldquo;Yet Another Markup Language&amp;rdquo;.
YAML is fairly widespread nowadays as a format for configuration files.
To me, one of the most obvious advantages of the format is its conciseness and readability.
Indentation matters though, so be sure you use a proper (plain text) editor when editing in this format.&lt;/p&gt;
&lt;p&gt;I will go over the most important files in here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker-compose.yaml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;configuration.yaml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ui-lovelace.yaml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="docker-composeyaml"&gt;&lt;code&gt;docker-compose.yaml&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This the main file that will start all of the required containers.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;version&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;3.8&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;homeassistant&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;homeassistant/home-assistant:2021.6.3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;8123:8123&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;.:/config&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;links&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;mosquitto&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;db&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;mosquitto&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;eclipse-mosquitto:1.6.14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;1883:1883&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;db&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;postgres:13.3-alpine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;POSTGRES_DB&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;hass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;POSTGRES_USER&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;hass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;POSTGRES_PASSWORD&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;hass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;hass-db:/var/lib/postgresql/data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hass-db&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This file defines 3 &lt;em&gt;services&lt;/em&gt;, &lt;code&gt;homeassistant&lt;/code&gt; (the main home assistant service), &lt;code&gt;mosquitto&lt;/code&gt; (an MQTT broker) and &lt;code&gt;db&lt;/code&gt; (a database &amp;ndash; although this isn&amp;rsquo;t strictly required).
Some notes on the keys used in the configuration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ports&lt;/strong&gt;: this is a mapping of the ports within the container to the outside world, e.g. &lt;code&gt;&amp;quot;8123:8123&amp;quot;&lt;/code&gt; means &amp;ldquo;maps the port 8123 inside the container to the host on port 812 &amp;ldquo;. Port 8123 is the port home assistant runs on by default.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;volumes&lt;/strong&gt;: this is mapping of the folder structure inside the container to the outside host. For the &lt;code&gt;homeassistant&lt;/code&gt; service, this means to map the configuration folder to the location where &lt;code&gt;docker-compose&lt;/code&gt; is executed. This also means it&amp;rsquo;s easy to put your own configuration inside the container this way. Volumes needn&amp;rsquo;t be mapped to an explicit host folder though, see the example for the &lt;code&gt;db&lt;/code&gt; service where there&amp;rsquo;s just a named volume called &lt;code&gt;hass-db&lt;/code&gt;, managed by docker.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;links&lt;/strong&gt;: links take care of the networking between containers. A link from &lt;code&gt;homeassistant&lt;/code&gt; to &lt;code&gt;mosquitto&lt;/code&gt; means that the home assistant instance will be able to reach that other service with the name &lt;code&gt;mosquitto&lt;/code&gt;. &lt;code&gt;docker-compose&lt;/code&gt; takes care of creating the proper docker network for that. It also means that if the &lt;code&gt;homeassistant&lt;/code&gt; service is started, the other 2 services are also automatically started.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At this point, you can actually already just fire up home assistant using &lt;code&gt;docker-compose up&lt;/code&gt;!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ docker-compose up
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Starting hass_mosquitto_1 ... &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Starting hass_db_1 ... &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Starting hass_homeassistant_1 ... &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Attaching to hass_mosquitto_1, hass_db_1, hass_homeassistant_1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_1 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_1 | PostgreSQL Database directory appears to contain a database; Skipping initialization
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_1 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_1 | 2021-06-10 19:19:56.893 UTC &lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: starting PostgreSQL 13.3 on x86_64-pc-linux-musl, compiled by gcc &lt;span style="color:#f92672"&gt;(&lt;/span&gt;Alpine 10.2.1_pre1&lt;span style="color:#f92672"&gt;)&lt;/span&gt; 10.2.1 20201203, 64-bit
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_1 | 2021-06-10 19:19:56.893 UTC &lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: listening on IPv4 address &lt;span style="color:#e6db74"&gt;&amp;#34;0.0.0.0&amp;#34;&lt;/span&gt;, port &lt;span style="color:#ae81ff"&gt;5432&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_1 | 2021-06-10 19:19:56.893 UTC &lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: listening on IPv6 address &lt;span style="color:#e6db74"&gt;&amp;#34;::&amp;#34;&lt;/span&gt;, port &lt;span style="color:#ae81ff"&gt;5432&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_1 | 2021-06-10 19:19:56.902 UTC &lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: listening on Unix socket &lt;span style="color:#e6db74"&gt;&amp;#34;/var/run/postgresql/.s.PGSQL.5432&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_1 | 2021-06-10 19:19:56.912 UTC &lt;span style="color:#f92672"&gt;[&lt;/span&gt;21&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: database system was interrupted; last known up at 2021-06-08 20:37:13 UTC
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mosquitto_1 | 1623352796: mosquitto version 1.6.14 starting
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mosquitto_1 | 1623352796: Config loaded from /mosquitto/config/mosquitto.conf.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mosquitto_1 | 1623352796: Opening ipv4 listen socket on port 1883.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mosquitto_1 | 1623352796: Opening ipv6 listen socket on port 1883.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mosquitto_1 | 1623352796: mosquitto version 1.6.14 running
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_1 | 2021-06-10 19:19:57.219 UTC &lt;span style="color:#f92672"&gt;[&lt;/span&gt;21&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: database system was not properly shut down; automatic recovery in progress
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_1 | 2021-06-10 19:19:57.227 UTC &lt;span style="color:#f92672"&gt;[&lt;/span&gt;21&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: redo starts at 0/1920BF0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_1 | 2021-06-10 19:19:57.231 UTC &lt;span style="color:#f92672"&gt;[&lt;/span&gt;21&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: invalid record length at 0/1931478: wanted 24, got &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_1 | 2021-06-10 19:19:57.231 UTC &lt;span style="color:#f92672"&gt;[&lt;/span&gt;21&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: redo &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt; at 0/1931450
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;homeassistant_1 | &lt;span style="color:#f92672"&gt;[&lt;/span&gt;s6-init&lt;span style="color:#f92672"&gt;]&lt;/span&gt; making user provided files available at /var/run/s6/etc...exited 0.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_1 | 2021-06-10 19:19:57.298 UTC &lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: database system is ready to accept connections
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;homeassistant_1 | &lt;span style="color:#f92672"&gt;[&lt;/span&gt;s6-init&lt;span style="color:#f92672"&gt;]&lt;/span&gt; ensuring user provided files have correct perms...exited 0.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;homeassistant_1 | &lt;span style="color:#f92672"&gt;[&lt;/span&gt;fix-attrs.d&lt;span style="color:#f92672"&gt;]&lt;/span&gt; applying ownership &amp;amp; permissions fixes...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;homeassistant_1 | &lt;span style="color:#f92672"&gt;[&lt;/span&gt;fix-attrs.d&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;homeassistant_1 | &lt;span style="color:#f92672"&gt;[&lt;/span&gt;cont-init.d&lt;span style="color:#f92672"&gt;]&lt;/span&gt; executing container initialization scripts...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;homeassistant_1 | &lt;span style="color:#f92672"&gt;[&lt;/span&gt;cont-init.d&lt;span style="color:#f92672"&gt;]&lt;/span&gt; udev.sh: executing...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;homeassistant_1 | &lt;span style="color:#f92672"&gt;[&lt;/span&gt;cont-init.d&lt;span style="color:#f92672"&gt;]&lt;/span&gt; udev.sh: exited 0.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;homeassistant_1 | &lt;span style="color:#f92672"&gt;[&lt;/span&gt;cont-init.d&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;homeassistant_1 | &lt;span style="color:#f92672"&gt;[&lt;/span&gt;services.d&lt;span style="color:#f92672"&gt;]&lt;/span&gt; starting services
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;homeassistant_1 | &lt;span style="color:#f92672"&gt;[&lt;/span&gt;services.d&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This should actually have created the other configuration files for you.&lt;/p&gt;
&lt;h3 id="configurationyaml"&gt;&lt;code&gt;configuration.yaml&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The next file to discuss is the main home assistant configuration file.&lt;/p&gt;
&lt;p&gt;Here is my final adapted version:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Configure a default setup of Home Assistant (frontend, api, etc)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;default_config&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Text to speech&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;tts&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;platform&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;google_translate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;group&lt;/span&gt;: !&lt;span style="color:#ae81ff"&gt;include groups.yaml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;: !&lt;span style="color:#ae81ff"&gt;include scripts.yaml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;scene&lt;/span&gt;: !&lt;span style="color:#ae81ff"&gt;include scenes.yaml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;lovelace&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;mode&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;yaml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;recorder&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;db_url&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;postgresql://hass:hass@db/hass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;mqtt&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;broker&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;mosquitto&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Entities representing push buttons&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;switch&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;platform&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;mqtt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;study room&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;command_topic&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;tesla/input/2_01/set&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;state_topic&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;tesla/input/2_01/state&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Entities representing lights&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;light&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;platform&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;mqtt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;study room&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;command_topic&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;edison/relay/2_05/set&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;state_topic&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;edison/relay/2_05/state&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;optimistic&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; &lt;span style="color:#75715e"&gt;# only needed because of demo now&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Automation to link the two together&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;automation&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;alias&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Toggle study room&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;trigger&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;platform&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;state&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;entity_id&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;switch.study_room&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;from&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;off&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;to&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;on&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;action&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;service&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;light.toggle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;entity_id&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;light.study_room&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The top part of the file contains mostly &lt;strong&gt;boilerplate code&lt;/strong&gt; that was added by homeassistant itself, e.g. the &lt;code&gt;default_config&lt;/code&gt; and &lt;code&gt;tts&lt;/code&gt;.
The &lt;code&gt;group&lt;/code&gt;, &lt;code&gt;script&lt;/code&gt; and &lt;code&gt;scene&lt;/code&gt; blocks were also added automatically and use the &lt;code&gt;!include&lt;/code&gt; keyword, which home assistant would interpret as including those other yaml files within this main configuration file.
When you have a large number of entities to add, this would be the typical way to structure them.
For the discussion here, I did not do that though.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;&lt;code&gt;recorder&lt;/code&gt;&lt;/strong&gt; part is about the &lt;a href="https://www.home-assistant.io/integrations/recorder/#custom-database-engines"&gt;home assistant database integration&lt;/a&gt;.
This contains the connection URL (including the credentials).
If you compare this again with the &lt;code&gt;docker-compose.yaml&lt;/code&gt; file, you will see those credentials which were set from the &lt;code&gt;environment&lt;/code&gt; key for the &lt;code&gt;db&lt;/code&gt; postgres service.
In a proper setup, you&amp;rsquo;d use the &lt;a href="https://www.home-assistant.io/docs/configuration/secrets/"&gt;secrets system&lt;/a&gt;, but as the database integration isn&amp;rsquo;t that important here, I did not do that.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;&lt;code&gt;mqtt&lt;/code&gt;&lt;/strong&gt; integration is quite relevant here.
This should point to your MQTT broker.
Checking &lt;code&gt;docker-compose.yaml&lt;/code&gt;, this service was called &lt;code&gt;mosquitto&lt;/code&gt; and should be reachable with just thus name from inside the docker container network&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;The following entry is a configuration for a &lt;strong&gt;push button&lt;/strong&gt; using the &lt;a href="https://www.home-assistant.io/integrations/switch.mqtt/"&gt;home assistant MQTT switch&lt;/a&gt; integration.
It minimally needs the integration platform, the name (which is relevant for later referring to the entity) and a command and state topic, the meaning of which was described earlier.&lt;/p&gt;
&lt;p&gt;Next would be the matching &lt;strong&gt;light&lt;/strong&gt; which we would like to have triggered whenever the push button is toggled, based on the &lt;a href="https://www.home-assistant.io/integrations/light.mqtt/"&gt;home assistant MQTT light&lt;/a&gt; integration.
It also has the MQTT platform, name (which matches now, but needn&amp;rsquo;t really), command and state topic.
I also configured the light to be in &lt;code&gt;optimistic&lt;/code&gt; mode.
This means the that the state of the light internally in home assistant is updated regardless of changes on the state topic.
I did this because this is a dummy setup and this light is not linked to an actual device that will acknowledge commands with a matching update on the state topic.
In my real setup, this is obviously omitted.&lt;/p&gt;
&lt;p&gt;At this point, both push button and light are known to home assistant, but they are not linked.
The &lt;strong&gt;automation&lt;/strong&gt; takes care of that.
The general outline of an &lt;a href="https://www.home-assistant.io/docs/automation/basics/"&gt;home assistant automation&lt;/a&gt; is:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;| trigger | when the switch state changes |
| condition | and it&amp;#39;s nighttime |
| action | then toggle the light |
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;condition&lt;/code&gt; part is optional for the automation, and for the example given here quite nonsensical indeed.
Important here is that we only allow toggles when the push buttons gets toggled from off to on, not the other way around &amp;ndash; otherwise if would follow the push buttons state, which means the light would only be on for the duration the button is pressed.
The &lt;code&gt;light.toggle&lt;/code&gt; is an action that is built-in to home assistant and does just take: if the light was off, it will turn it on, and vice versa.&lt;/p&gt;
&lt;p&gt;Check the &lt;a href="https://www.home-assistant.io/docs/configuration/"&gt;home assistant configuration&lt;/a&gt; for more extensive documentation and further links.&lt;/p&gt;
&lt;h3 id="ui-lovelaceyaml"&gt;&lt;code&gt;ui-lovelace.yaml&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This file contains the visual outline for home assistant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;views&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;title&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Home&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;icon&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;mdi:home&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;cards&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;type&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;entities&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;title&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Entities&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;entities&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;switch.study_room&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;light.study_room&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;automation.toggle_study_room&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This just makes the demo a bit easier to look at.&lt;/p&gt;
&lt;h2 id="demo"&gt;Demo&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s see it in action!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://mhemeryck.xyz/2021-08-03/demo.gif" alt="demo"&gt;&lt;/p&gt;
&lt;p&gt;The top left terminal just shows the &lt;code&gt;docker-compose&lt;/code&gt; output, containing the aggregated log output of the different services.
The right hand part shows the simplified home assistant UI, containing (top to bottom) the switch state, the light state and the automation.
The middle left terminal uses the &lt;a href="https://mosquitto.org/man/mosquitto_sub-1.html"&gt;&lt;code&gt;mosquitto_sub&lt;/code&gt;&lt;/a&gt; tool to read all events from the broker; the left one subscribes to &lt;code&gt;tesla/#&lt;/code&gt; meaning any topic below &lt;code&gt;tesla/&lt;/code&gt; (for the push button) and the right for &lt;code&gt;edison/&lt;/code&gt; (the light).&lt;/p&gt;
&lt;p&gt;The bottom left terminal is used to simulate the push of a button by sending out events directly to the push button&amp;rsquo;s state topic, using another tool called &lt;a href="https://mosquitto.org/man/mosquitto_pub-1.html"&gt;&lt;code&gt;mosquitto_pub&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The commands themselves are:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;mosquitto_pub -h localhost -t tesla/input/2_01/state -m ON
mosquitto_pub -h localhost -t tesla/input/2_01/state -m OFF
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Each of the lines represent a push to &lt;em&gt;host&lt;/em&gt; &amp;ldquo;&lt;code&gt;h&lt;/code&gt;&amp;rdquo; &lt;code&gt;localhost&lt;/code&gt;, on &lt;em&gt;topic&lt;/em&gt; &amp;ldquo;&lt;code&gt;t&lt;/code&gt;&amp;rdquo; &lt;code&gt;tesla/input/2_01/state&lt;/code&gt; with &lt;em&gt;message&lt;/em&gt; &amp;ldquo;&lt;code&gt;m&lt;/code&gt;&amp;rdquo; &lt;code&gt;ON&lt;/code&gt; or &lt;code&gt;OFF&lt;/code&gt;.
By rapidly firing them off shortly after each other, this simulates the push of a button (first on, then off again).&lt;/p&gt;
&lt;p&gt;When the push button state updates are pushed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;home assistant updates the internal state of the push button entity&lt;/li&gt;
&lt;li&gt;the automation kicks in, and updates the matching light entity is toggled&lt;/li&gt;
&lt;li&gt;the light entity sends out the update on the command topic&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Apart from controlling the light with the push button, it can also be controlled directly from home assistant; when toggling the light entity directly in home assistant, it just sends out the command on the MQTT topic directly.&lt;/p&gt;
&lt;h2 id="closing-thoughts"&gt;Closing thoughts&lt;/h2&gt;
&lt;p&gt;This concludes my approach to using (abusing?) home assistant and the MQTT integration as the central part of my home automation setup.&lt;/p&gt;
&lt;p&gt;I did use MQTT as the standard to centralize all my components on, have a look at the other posts presented in the &lt;a href="https://mhemeryck.xyz/posts/2021-06-15-home_automation_why/"&gt;home automation overview post&lt;/a&gt; of how to get there.
Examples of other components that use MQTT in the same fashion are window contacts, PIR, smoke and water detectors, motorized blinds, etc.&lt;/p&gt;
&lt;p&gt;The advantage of home assistant though is that it does not need to all be the same protocol, so it is quite easy to add other integrations in the mix as well.
A notable example of this is an automation where I link one of these push buttons to a &lt;a href="https://www.home-assistant.io/integrations/hue/"&gt;Philips Hue light&lt;/a&gt;; as far as home assistant is concerned, both of these are light entities.&lt;/p&gt;
&lt;p&gt;A disadvantage of using home assistant this way and by extent the overall approach is the &lt;em&gt;centralized&lt;/em&gt; nature of it.
Home assistant needs to be online all the time for everything to work.
Initially, I did run home assistant using &lt;code&gt;docker-compose&lt;/code&gt;, which was quite stable.
However, doing updates was never fun, since it meant that one container needs to go down before the next comes up, leaving in a short (but stressful) period of downtime.
Using k3s as the supervisor certainly fixed that.
Given that the majority of my interfacing hardware is actually all on MQTT, I might at some point add another service in the mix that mimics the automation engine as a backup.&lt;/p&gt;
&lt;p&gt;A similar argument can be made about the &lt;code&gt;mosquitto&lt;/code&gt; broker.
Currently, I actually run that as a dedicated service on the host itself.
Alternative solutions such as &lt;a href="https://www.emqx.com/en/blog/emqx-mqtt-broker-k8s-cluster"&gt;emqx&lt;/a&gt; exist though, which would run MQTT in a high-availability mode (multiple, load balanced instances).&lt;/p&gt;
&lt;p&gt;Currently though, the system works quite fine and everyone at home has gotten so accustomed to it, they only really notice when not being at home.
The backlog of improvements and extra bells and whistles is still quite long, so I&amp;rsquo;ll hope to write more on this later!&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;the &lt;code&gt;mosquitto&lt;/code&gt; version used in the &lt;code&gt;docker-compose.yaml&lt;/code&gt; version was explicitly pinned to a version &amp;lt; 2.x, which did not enforce authentication, hence why the broker configuration just needs a host name to connect to.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item></channel></rss>