Hi everyone,
15/04/2025: Since this post became a useful ressource, I updated it to fix typos, merge comments, update the synthaxe, etc.
After using HA for 7 years, I felt like sharing some wisdoms. Beyond the “if it ain’t broken, don’t fix it”, here are some things I learned both from eureka, WTF moments, and miserable failures. HA is part of our domestic life and 88 automations are making our daily routines more comfortable, secure, and enjoyable.
Those 20 points come without a specific order (but with a number so we can exchange on them in comments). Don’t hesitate to share your own experience and tips for newcomers.
-
A simple way in HA
1/ Install HA using HAOS (the most supported, easiest, straightforward way into HA)
2/ Identify your first great work. AC automation, home security, energy consumption dashboard, automating your remotes or curtains. Whatever.
3/ Select and buy the proper product to do the job, using the right protocols
4/ Install (just) the necessary integrations & components, then create your dashboards or automation
5/ Enjoy a victory, you progressed on the learning curve
6/ Post your solutions or questions, because this forum is incredibly useful to everyone. Most of times, you’ll get timely & helpful answers. In one word: share questions, pain & victories
7/ Tackle the next challenge -
Home Approval Factor (Significant Other Approval Rate)
I cannot stress enough how your Significant Others approval is critical here. If your partner (or kids) just get pissed once at automation, it could become a deal breaker in terms of time & investment. Whereas when HA serves the purpose of making their life easier, it’s all well accepted. Try to bring victories for them as much as for you, automation is a mean, not an end. Keep a physical button (or way of doing whatever you’re automating). This way, if your HA is down or malfunctioning, they don’t feel trapped. Agree altogether on the next steps to take, next automation to build. -
Choose the right protocol and product
Since I started automating, I’ve only ordered products with API access. If you’re serious about automation, now on, anything you buy is either supported already in HA or has an API you can tinker with. Don’t be cheap on dependable of safety hardware (smoke or water leak sensor), make arbitration on others devices. For cams Dahua is cheap but great, for Wifi, use solid AP, not the cheap, faulty and insecure one embedded in your Internet provider’s router. Wireless protocoles like zigbee, zwave, matter, etc all offer different advantages: price, consistency, range, etc. I massively adopted Zwave because it is standardized and manufacturers have to comply to Zwave consortium requirements, whereas Zigbee leaves a lot to interpretation. I chose Zwave to avoid integration issue, get consistency, and have a good meshing system. Now Zigbee is also used a lot for lighting, where Zwave is less prominent and it’s also notoriously less expensive. But if you are to invest $500 in detectors or relays or lights, be sure to pick something resilient over time. After 5 years, my Zwave network is aging very well and still is kicking. Before I include a new protocole, it’s gonna go through solid scrutiny. If you are going for Wifi based product, remember to host them on a sub-network, if possible isolated with real physical Vlans. -
Don’t clutter. Make baby steps
When I first entered HACS, I was like a toddler in a candy store and started to install everything. Next thing you know, 20 javascripts were loading and crushed my mobile APP, which stopped working. Likewise, I’ve installed a lot of add-ons (which run on containers) and started to cripple my raspberry pi4 performances. Now after cleaning everything, it’s running smoothly again. The point here is you have time. Don’t try to tackle all the features you want to implement in HA at once. So roaming through integration, addons or HACS and add everything you think you will one day need is the wrong way to do it. First, those integrations will bring more noise to what you’re trying to tackle now. Second, there will be bugs and updates in those, so when you’ll eventually be using them, they’ll be different already. So in the meantime, you’ll carry buggy integrations for nothing. Opposed to this, every little victory will drive up your skills and motivation. -
Open source is the rule
I use Frigate for my camera’s NVR. Coupled with a Google Coral TPU, this software is doing wonders. It’s evolving fast, is dependable and far superior on every point to Blue Iris I used before. The same is true of almost every software component. Open source is eating the world (HA is an example, but I’m also leading an open-source editor, so I’m partial but informed). If you have the option between an open-source component or a proprietary one: there is no doubt. Faster iteration, better support, quality code, tons of dev, fewer costs, etc. You can bet on HA to be around forever. Such a brilliant piece of FOSS, with such a vibrant community is immortal and survives even its leaders. So you can safely invest your time, I bet HA will still be here in 2040 and probably beyond whereas your limited, proprietary, “smart” hub will be long forgotten. Corps have a vested interest in phasing out their hardware to make you buy the newest one, whereas Open source works in the exact opposite direction. -
Secure it
Now if you’re serious about home automation, start on the right foot. Have a good (adapted, powerful) power supply for your Pi and its peripherals. I use a fast charging USB one, that delivers up to 140W. Btw disable WPS on your Wifi router, a non neglictible portion of them are vulnerable and allow to recover your wifi key. Prefer specialized protocols like Zigbee or Zwave over Wifi to avoid cluttering (and weakening) your wifi where possible. I’ve made an entire post on how to secure your HA and your home network here.If you’re using a Raspberry Pi, don’t rely on an SDCard which WILL corrupt over time and ruin everything. On top of that it’s slow and probably the worst physical support to host a database. A Raspi 4 will do the job nicely, but grant it a SSD or if you go for a Raspberry PI 5, a NVME. Backup on a different location than you host machine. It could be another server or on the cloud (like on the Cloud with this addon). Using HA when not at home is an absolute comfort, but you don’t want anyone to break hell into your house, on distance. Hence, secure the connexion. You can use CrowdSec to avoid password bruteforce (HA addon). Install yourself Tailscale on both Home assistant and your phones for remote access, it’s… a bliss. It brings so much comfort will still securing the whole system, it’s incredible. HA has an addon for it, it’s free and your position will be sent to your system way before your phones hook to the Wifi to open you the door. Priceless. (Advanced: If you have the skills, isolate your IoT on a different Wifi SSID on your smart AP, tag them with a different Vlan ID, have a trunk on your switch and connect them to another port of your firewall. Then you can apply network separation or allowance based on SSID, PM me if you want a post on this). Add a small UPS (as proposed by @FriedCheese) to adequately protect your host machine from surges or power cuts. -
Update confidently, but backup often
There was a time when I was nervous about every upgrade. Things would break or malfunction. Those times are gone; I have never had any issues for the last 12 months. If you stay many versions behind, you’ll be more likely to have a major breakdown when upgrading. Just remember to read the changelogs to check if there are any breaking changes and to update often to avoid being caught in massive upgrades all at once. The day it becomes simply too critical not to have it up & running, have another Pi + SSD to spin up if things get awry. -
Don’t underestimate MQTT
At first, I wondered why to use an extra protocol whereas Zwave would do the job for detection, report & action, Wifi for the rest, etc. Well as a matter of fact, anything not standard can be MQTTed. I’ve an example here with my universal remote project (and yes, you can really convert ANY remote to be MQTT / HA enabled). I also have custom ESP detecting curtain positions, activating relays and more. My cams alert are sent to HA using MQTT, a reciprocally, HA sends a lot of data to MQTT to inform other components of my home network. MQTT is your gateway to DIY and 3rd party integration. A nice example is this integration I made for my Imeon solar inverter, that had no support in HA so far, but an API. So adding it through MQTT was fairly easy. -
Careful with running a load of automations
I used to run around 150 automation and my average CPU load was 0.6 (on an RPi4). Meaningful but not critical either, given the workload. Now I lowered it to 88 and it’s much more reactive. Most automation are based on state changes (like a sensor going from off to on), some on-time patterns (like every 10 min), some at fix hours, etc. The point is to avoid having tons of them running simultaneously, like every minute. Because HA internal “cron” table will kick them all at once, and delay can occur on because of that high CPU load. I think that if you’re correctly scheduling and coding, a PI5 can run hundreds of automation without any problems.
The following card for your lovelace inferface will give you a macro overview of Containers activities and running Scripts & Automations. I use the auto-entities card you can install it from HACS. Keep an eye on your database size too, try to keep it under 3GB when possible.
type: vertical-stack
cards:
- type: custom:auto-entities
card:
type: entities
title: Running Automations
filter:
exclude:
- state: unavailable
- attributes:
current: "= 0"
include:
- domain: automation
show_empty: true
sort:
ignore_case: true
method: name
- type: custom:auto-entities
card:
type: entities
title: Running Scripts
filter:
exclude:
- state: "off"
include:
- domain: script
show_empty: true
sort:
ignore_case: true
method: name
- type: custom:auto-entities
card:
type: entities
title: Containers CPU
filter:
exclude:
- entity_id: sensor.z_wave_js_cpu_percent
- entity_id: sensor.ring_mqtt_with_video_streaming_cpu_percent
- entity_id: sensor.z_wave_js_memory_percent
- entity_id: sensor.ring_mqtt_with_video_streaming_memory_percent
include:
- name: CPU
- entity_id: sensor.*_cpu_percent
sort:
ignore_case: true
method: name
- Simplify, don’t minify
Once you get familiar with automations, you’ll likely iterate and get back to your previous work, refactor it and simplify, beautify, reorganize. That’s all cool but don’t fall in the trap of “One line to rule them all”. Because what sound smart (and maybe even is) will backfire later on, with a tricky race condition or what not and you’ll be forced to debug. This is where minifying gets dirty. Separate triggers and conditions properly so that if one fails, you can see it faster. One example here:
triggers:
- trigger: time_pattern
minutes: '/30'
conditions:
- "{{ today_at('09:30') <= now() <= today_at('22:30') }}"
- condition: state
entity_id:sensor.whatever
state: off
vs
triggers:
- trigger: template
value_template: >
{{ now() >= today_at('09:30') and now() <= today_at('22:30') and now().minute % 30 == 0 and states('sensor.whatever') == "off") }}
Supposedly, the two versions do precisely the same work. But in the former, trigger and condition are adequately separated. If one fails, it’s easier to debug. In the second, a form of “minification” you intertwine trigger and condition. The whole thing can fail for one or the other reason. The example is voluntarily simplistic here, but think about a several-line template, this can get very messy.
- Use proxy variables and be careful about renaming
When you change your phone, your device tracker name changes and all your automation related to it may fail. As well if you use, say one standard HA Daikin integration and then replace it by a HACS Daikin integration that provides support for the latest Daikin API, you may see all your climate device being renamed with an _2. And all your related automation will fail accordingly, or rather do nothing.
An exemple here could be a templated sensor, simply using the mobile phone entity you need to track and when you change your phone for a new model, since all your automations will be using the templated sensor and not the original device entity, you simple need to update your templated sensor and not all your 20 automations relying on it.
There is a little trick around this problem. Say your device tracker is used in 20 automations. When changing your phone, you’d need to update 20 automation, except if you’ve used a group or a proxy variable instead. Let’s say you added our phone tracker in a group.awesome_people, along with your kids and hubby/wifey’s one. The day one of them changed, if your automation are using the group (or a proxy variable) instead of your phone, you only need to update the tracker name in the group and not the 20 automation by hands.
- Create a dashboard per use cases
My dashboard for desktop is very different from the one for mobile. This is lighter and focuses on what I need to see/use when I’m on distance. The latter is lighter, compact, and simple. (you can assign a dashboard to each user on their device in the profile section and you can create new dashboards in the settings tab).
Mobile:
Desktop:
- Keep it clean & tidy
You’ll regret every shortcut you’ll take. Not renaming before using, not de-installing, not cleaning up one thing or another. Call it Karma, but it ALWAYS stings you back. Rename entities or hardware just after adding them, take time to exclude / reinclude if you haven’t been able to get the highest security level in zwave, etc. Never work something before it’s clean. Don’t. Just don’t.
The goal is to enter the “meditative-iterative” state, where you can quickly, confidently and incrementally add new automations while being confident that any reload, reboot or unforeseen issue won’t ruin your setup. Once you reach this levitation-like state, you’ll be able to create anything quickly, efficiently, and reliably. And “Clean” is a prerequisite.
- Keep it ordered
Your configuration.yaml and global directories organization can help you over time.
I used to organize mine in what I would call the “old HA” fashion. It’s not a bad way, it’s not going to be phased out so far I know and youy can totally still use it. Now in 2024, I fully transitionned to what is called “packages” and I find it much more convenient. The “Old” way is to separate your sensors, automations, scenes, scripts, utility meters, input whatever in different files or directories. The “New” way, is to package everything related to a specific topic, say air conditioning or solar panel in one file. I suspect there are schools of thoughts one this one, my personnal recommendation would be the “package” route since it’s easier to debug and proved very efficient overtime, but both will do. I’ll present both ways here:
The “Old” way:
logger: !include logger.yaml
scene: !include scenes.yaml
zone: !include zones.yaml
history: !include history.yaml
automation ui: !include automations.yaml
automation manual: !include_dir_merge_list automations
group: !include groups.yaml
script: !include scripts.yaml
input_boolean: !include input_boolean.yaml
input_number: !include input_number.yaml
input_select: !include input_select.yaml
input_text: !include input_text.yaml
template: !include_dir_merge_list sensors/templated
sensor: !include_dir_merge_list sensors/legacy
utility_meter: !include utility_meters.yaml
switch: !include switches.yaml
cover: !include cover.yaml
counter: !include counter.yaml
mqtt:
cover: !include_dir_merge_list mqtt/cover
sensor: !include_dir_merge_list mqtt/sensor
switch: !include_dir_merge_list mqtt/switches
binary_sensor: !include_dir_merge_list mqtt/binary_sensor
This means, for example, that HA will read all the files in the directories after !include_dir_merge_list. So in my mqtt/sensor for example, I’ve:
and in my automation directory:
So if I add a new automation or sensor file to describe something, it’s automatically parsed, I don’t have to think about it. Also, in automations, try to give a structure that will not vary too much overtime. Because if you rename an automation alias, the name of the automation will change and eventually, if you call it by name in another one (like to pause it), this won’t work anymore.
I use a numbering system like this:
#---------------------------------------------------------------------------------------
# If many sensors trip at night or when OOH, trigger a big alarm (anti-false positives)
#---------------------------------------------------------------------------------------
- id: "110020"
alias: Alarm - Combined (3+) tiggers
description: Combine 3 different camera and PIR motion sensors triggers within 90s before setting off Alarm
[...]
110020: So it’s group 1 (security), batch 1 (alarms), two 0 if I need to create new ones, then the number of the automation in the current file (here 20).
The “New” way (packages):
All switches, sensors, automation, scripts, etc. are now in the packages files nested in the “packages” directory, and it looks like this:
And one package file like this:
- Experiment with dev.tools / services / states and automation traces
You can find the name of all entities in the development tab. There is a wealth of information and a sandbox to test your templates live. They’ll soon be your best friends. Also, in settings → automation, you can click any automation and check “traces” to analyze what went wrong. You can also monitor your MQTT trafic with the Developper tab.
The only thing I found tricky so far is to understand what is exactly consumming CPU. Between the various containers and the main instance of HA, it’s often complicated to see occupies your ressource and Python isn’t really helpful either. I tried to use a python profiler but it’s not maintained anymore, so we are left with few options here.
You can still dig in the database with SQL light web to assess which events are cluttering your DB with a querie like:
SELECT
COUNT(*) as cnt,
COUNT(*) * 100 / (SELECT COUNT(*) FROM events) AS cnt_pct,
event_types.event_type
FROM events
INNER JOIN event_types ON events.event_type_id = event_types.event_type_id
GROUP BY event_types.event_type
ORDER BY cnt ASC
or explore the containers by using something like docker exec -it homeassistant bash and then use classical tools like “ps aux”.
- Don’t under-estimate groups
Groups are great for reading a state or enumerating their members.
So if you have a group with all device trackers, if one is “home”, the group is switching to “home”. Cool hey. The same applies for a security group for example, if one security device trips, all the group goes to “on” and you can act. Groups can make your life so much easier. If need be, you can enumerate group members and act on one:
actions:
- action: notify.info
data:
message: >
{{ "At least 2 PIRs triggered:" }}
{% for sensor in expand('group.pirs') -%}
{%- if sensor.state == "on" %}
{% if now() - sensor.last_changed < timedelta(seconds=60) -%}
{{- " * " + state_attr(sensor.entity_id, 'friendly_name').partition(' ')[0] + "\n" -}}
{% endif %}
{% endif %}
{%- endfor %}
- Don’t be Cloud dependent
Where to start here? Data privacy, reliability, vendor locking?
Anyway, pragmatic example, I had a Neato. They defunct their API support, the thing isn’t automable anymore. I had old Daikin with local control now the new ones are API only, Cloud dependent. When Daikin will lose my credentials, I’ll be upset, but when a criminal will take control of all my A/C remotely, I’ll be seriously pissed.
I don’t need their app, it’s useless, I don’t need their cloud it’s an unwanted liability and an error source. I’ve some appliances like Daikin, Ondilo, and a few other because I’ve no alternative, but for my cams for example, it’s out of the question. Don’t want to be spied upon by unknowns. And sorry for NSA’s wet-dream of people planting a connected mic in their home by themselves (and at their cost), but no Google / Alexa / Siri for me. By the way, I removed all Wifi chipset from all my Daikin and replaced them with Faikin (from RevK) and it works a charm.
- Templates are God mode
Diving into templates is has important has knowing how to draw a 3D object when you have a 3D printer.
You can live without it, but you’d miss on a lot. Arguably, they look scary. But they hold the infinite power of HA, its absolute versatility is packed in templates. You can do absolutely wonders with those. You can create custom sensors using them as well, not only automation. They are basically Python logic snippets embedded in your automation. The forum is packed with examples. Ie this anti-false positive alarm system I made a while back is mostly based on templates.
Here are a few to get inspiration:
actions:
- action: utility_meter.calibrate
target:
entity_id: sensor.daily_pool_consumption
data:
value: "{{ states('sensor.daily_pool_consumption') | float + (states('sensor.sonoff_100153d4ec_power') | float / 60) | round(1) }}"
This one maintains a utility meter (that the integration doesn’t provide naturally). I count the amount of power spent by the pool pump.
conditions:
- "{{ now().hour - (states('sensor.pool_temp') | float /2 | round(0)) == 8 }}"
My pool pump starts at 8am every day. This one snippet counts if the current hour minus the length of the cycle (basically, nb of hours pump should run = temperature in celcius/2). If he current hours minus the temp/2 (say 14 for example) = 8 then the filtering ran for enough time and can be stopped.
conditions:
- "{{ expand('group.security') | map(attribute='last_changed') | select('gt', now() - timedelta(seconds=90)) | list | count > 2 }}"
This one counts the number of security devices that triggered to on over the last 90s and add them. If at least 3 PIRs and Cameras tilted in less than 90 seconds, I’m sure it’s not a false positive.
conditions:
- "{{ now() - as_datetime(states('sensor.uptime')) > timedelta(days=0,hours=0,minutes=15) }}"
This one prevents one of my automation actions to trigger if HA rebooted in the last 15 mins.
conditions:
condition: >
{% if state_attr("automation.pool_leak_sensor_triggered", "last_triggered") %}
{{ (as_timestamp(now()) - as_timestamp(state_attr('automation.pool_leak_sensor_triggered', 'last_triggered'))) > 600 }}
{% endif %}
This one checks that automation hasn’t triggered in the last 10 mins.
triggers:
- trigger: template
value_template: "{{ now() >= today_at('09:30') and now() <= today_at('22:30') and now().minute % 30 == 0 }}"
This one triggers at 00 and 30 of every hours, only between 9:30 and 22:30.
- conditions:
condition: "{{ now().month in [4,5,6,7,8,9] }}"
This one automates anti-mosquito plugged on a wifi-enabled-power plug, to only power them if we are in warm months.
- name: hourly_energy_cost
state: "{{ (states('sensor.hourly_offpeak_filtered') | float * 0.14657 + states('sensor.hourly_peak_filtered') | float * 0.18365) }}"
This templated sensor adds in peak / off-peak hours consumptions and multiply them by the proper euro cost. So that one is the actual cost of electricity pulled from the grid per hours. (that you can then feed into a utility_meter for day/weeks/month/year cycles)
You can even create & maintain a utility meter using templates if a specific device doesn’t provide them. As an exemple, I’ve an Imeon solar inverter with my IT bay connected to its batteries. It’s not offering any long term stat and even less HA integration. So I “maintain” a utility meter of my own by updating it manually using an automation and templates:
The utility meter declaration:
utility_meter:
daily_it_bay:
source: sensor.fake
cycle: daily
delta_values: true
weekly_it_bay:
source: sensor.fake
cycle: weekly
delta_values: true
monthly_it_bay:
source: sensor.fake
cycle: monthly
delta_values: true
The automation to update them:
- id: "210005"
alias: Energy - AC backup IT bay consumption
description: Imeon AC backup daily consumption counting
triggers:
- trigger: time_pattern
minutes: "/10"
actions:
- if: "{{ now().hour==0 and now().minute==0 }}"
then:
- if: "{{ now().day == 1 }}"
then:
- action: utility_meter.calibrate
target:
entity_id: sensor.monthly_it_bay
data:
value: 0
else:
- action: utility_meter.calibrate
target:
entity_id: sensor.monthly_it_bay
data:
value: "{{ states('sensor.monthly_it_bay') | int + states('sensor.daily_it_bay') | int }}"
- if: "{{ now().weekday()==6 }}"
then:
- action: utility_meter.calibrate
target:
entity_id: sensor.weekly_it_bay
data:
value: 0
else:
- action: utility_meter.calibrate
target:
entity_id: sensor.weekly_it_bay
data:
value: "{{ states('sensor.weekly_it_bay') | int + states('sensor.daily_it_bay') | int }}"
- if: "{{ not(now().weekday()==6) and not(now().day == 1) }}"
then:
- action: utility_meter.calibrate
target:
entity_id: sensor.daily_it_bay
data:
value: 0
else:
- action: utility_meter.calibrate
target:
entity_id: sensor.daily_it_bay
data:
value: "{{ states('sensor.daily_it_bay') | float + ((states('sensor.imeon_consumption_from_ac_backup_watts') | float) /6) /1000 | round(5) }}"
-
It’s a marathon, not a sprint
HA isn’t a one-WE project. It’s a multi-year endeavor if you want to push the limits.
So take your time, and enjoy the ride. You’ll get unbelievable results, but not in a month. You need to order things, install them, understand some concepts, try some Yaml config, fail, rinse, repeat. This all takes time. -
Simple automation tricks to remember
1/ Trigger can be anything, but by default, an OR logic applies if you list several triggers, meaning any trigger will start the automation.
2/ Conditions, by default, work as AND. All conditions have to be true for the automation to proceed. You can adjust this with or: and and: statement when you’re advanced
3/ Condition can be added to actions:
actions:
- if: "{{ states('binary_sensor.garage_home_security_motion_detection') == 'on' }}"
then:
- action: script.notify_and_log
data:
title: "Garage door is likely opened"
logger: "ALARM"
message: "Garage door is likely opened"
What I use (broadly)
Hardware: Raspberry pi5 + NVME disk, solid power supply (140W), Qubino (zwave meters & blind controllers), Aeotec Zwave stick, ESP8266 & 32 (mostly wemos D1), Coolcam (zwave Pirs and door open sensors), Fibaro leak sensor (zwave), Zwave smoke sensor (Heiman technology), ICO ondilo for pool monitoring, Shelly EM for power monitoring, Sonoff for smart AC plugs, Daikin ACs, Onvif compatible cams (here Dahua), Overkiz (cozytouch) for controlling my regular heaters and water balloon, Sure catflap, a Wallbox charger (copper sb), Unifi APs, Sonos. Faikin ESP for my Daikin HVAC.
Software: Frigate, Tailscale, MQTT (mosquito on my gateway), Pushover.
Add ons: advanced SSH, aircast, airsonos, check home assistant config, Crowdsec, Crowdsec firewall bouncer, Tailscale, HA google drive backup, let’s encrypt, mariaDB, Nginx, samba, spotify connect, studio code server, z-wave JS.
HACS integrations: overkiz, font awesome, iPhone device tracker, average sensor, sonoff lan.
HACS Frontend: button card, vertical stack in card, mini graph, ha floorplan, simple thermostat, layout card, multiple entity row, tesla style power card, weather card, apexcharts-card.
PS: Support Open source if you can. Donate time to the community or some dollars to the authors. You can also buy their hardware or cloud subscription if you feel like they’re helping you out.
(My other posts: Integrate any remote in home assistant || Anti false positive PIR+camera alarm system || Automation from zero to hero || Securing & segregating your home network || Solar panel supervision || Daikin full automation)








and I may not care by then.



But pe prepared, it is like doing it all over again. 