20 things I wished I knew when I started with Home Assistant

Hi everyone,

After using it for around 5 years, I felt like sharing some bits of wisdom about HA. In Karate, I would self-rank myself as a brown belt. Not yet part of the elite, still quite experienced. I’m persistent and tinkerer at heart. I’ve an IT education and DIY mindset, but HA evolved so much over the years that those aren’t required anymore IMHO.

So, beyond the “if it ain’t broken, don’t fix it”, here are some things I learned from eureka, WTF moments, and miserable failures. To date, 150 automations are making our lives more comfortable. HA is part of our family life, and we couldn’t imagine running, securing, and enjoying a large house without it.

So here are 20 points, 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.

  1. A simple way in HA
    1/ Install HA using HAOS (the most supported, easiest, straightforward way into HA)
    2/ Identify your first great work. Say AC automation or 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 the amazing gold mine that is this forum is incredibly useful to everyone. (most of time) you’ll get timely & helpful answers and it’s an inspiration source for others, in one word: share (questions, pain & victories)
    7/ Tackle the next challenge

  2. Significant Other Approval Rate
    Aka Home ApprovaI Factor in HA community.
    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. 1/ Try to bring victories for them as much as for you. Automation is a mean, not an end. 2/ Keep a physical button (or way of doing whatever you’re automating) if your HA is down or malfunctioning. That way, they don’t feel trapped. 3/ Agree on the next steps to take, next automation to build.

  3. Choose the right protocol and product
    Ok, polemic incoming. Zwave is superior to Zigbee. This is mainly because Zwave is standardized and manufacturers have to comply to the requirement of the Zwave consortium, whereas Zigbee leaves a lot to interpretation. Now Zigbee is also used a lot for lighting and Zwave is less prominent on that front but more or less, they are supposed to cover similar use cases. In this case, I chose Zwave. Less headaches, fewer integration issues, etc. This can be true for other protocols, so if you are to invest $500 in detectors or relays or lights, be sure to pick something resilient over time. I chose Zwave and had no issue, it’s aging well and still is kicking. I never switched to the over hyped “matter” protocol and before I include a new one, it’s gonna go through solid scrutiny. Since I started home automation, I’ve only ordered products with API access. Exceptions are my car (VW group has severe limitations here) and Neato, which stopped supporting their product and API. 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 hardware (smoke or water leak sensor), but there is good arbitration to make on others, like 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. (and, yes, IKEA zigbee button looks fancy, but they’re painful to integrate)

  4. 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 js were loading and crushed my mobile APP loading time and it stopped working. Likewise, I’ve installed a lot of add-ons (which run on containers) and started to cripple my machines 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. 1st, those integrations will bring more noise to what you’re trying to tackle now, and 2nd, 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.

  5. Open source is the rule
    I used Blue Iris for my cam back then. I’ll switch to Frigate. And the same is true of almost every 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 invest your time, I bet HA will still be here in 2040 and probably beyond whereas your proprietary, limited whatever proprietary hub will be long forgotten.

[11/2024 Edit] I switched to Frigate. The level of integration in HA and the exquisite level of detail you can configure make it a no brainer, it’s far superior.

  1. Secure it
    I’ve made an entire post on how to secure your HA and your home network here. Now if you’re serious about home automation, start on the right foot, and if you’re using a Raspberry Pi, don’t rely on the 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. Raspi4 will do the job nicely, but grant it a SSD. As well backup it elsewhere (like on the Cloud with this addon) and have a spare disk or Raspi the day it becomes simply too critical not to have it up & running. Finally, 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) and other shenanigans or port knocking on your firewall (requires you to have a Linux gateway and configure the knockd daemon and then add the knockond app on your iOS device or port knocking app on Android). 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. (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.

[11/2024 edit] I also switched to Tailscale for all my mobile 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.

  1. 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. Now, 1/ I read the update notes to check if there are any breaking changes 2/ I often update to get caught in many changes occurring at once 3/ I always have a fresh update 4/ If necessary, I’ve another Pi + SSD to spin up if things get awry. If you stay many versions behind, you’ll be more likely to have a major breakdown when upgrading.

  2. 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.

  3. Careful with running a load of automations
    I run around 150 automation and my average CPU load is 0.6 (on an RPi4). Meaningful but not that bad either, given the workload. Many of my 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 your “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, your PI4 can run 200+ automation without any problems.

[11/2024 edit] 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
  1. 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:

[EDITED after @123 accurate point]

  trigger:
    - platform: time_pattern
      minutes: '/30'
  condition:
   - "{{ today_at('09:30') <= now() <= today_at('22:30') }}"
   - platform: state
     entity_id:sensor.whatever
     state: off

vs

  trigger:
    - platform: 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 simple form of “minifyin”) you intertwined 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.

  1. 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.

[11/2024 edit] 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.

  1. 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:


  1. 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.

  2. Keep it ordered
    your configuration.yaml and global directories organization can help you over time.
    Mine looks like this:

logger: !include logger.yaml
group: !include groups.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
zone: !include zones.yaml
history: !include history.yaml
input_boolean: !include input_boolean.yaml
input_number: !include input_number.yaml
input_select: !include input_select.yaml
automation ui: !include automations.yaml
automation manual: !include_dir_merge_list automations
template: !include_dir_merge_list sensors/templated
sensor: !include_dir_merge_list sensors/legacy
switch: !include switches.yaml
utility_meter: !include utility_meters.yaml
cover: !include cover.yaml
counter: !include counter.yaml
input_text: !include input_text.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:
Screenshot 2023-05-29 at 12.52.45
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).

  1. 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.

  2. 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:

 action:
    - service: 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 %}
  1. Don’t be Cloud dependent
    [Updated: it was about making triggers predictable but the point on Cloud dependency is more important]

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.

  1. Templates are God mode
    Okay, they look scary, but 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. This anti-false positive alarm system I made is mostly templates & groups.

Here are a few to get inspiration:

  action:
    - service: 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.

    - condition: template
      value_template: >
        {{ 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.

      - condition: template
        value_template: >
          {{ 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.

  condition:
    - condition: template
      value_template: "{{ 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.

    - condition: template
      value_template: >
        {% 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.

  trigger:
    - platform: 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.

    - condition: template
      value_template: "{{ 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) | round(2) }}"

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)

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.

[11/2024 edit] 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) }}"
  1. 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.

  2. Simple automation tricks to remember
    1/ Trigger can be anything, but 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. So if you want many things to happen but one only in certain conditions, you put that condition at then end of your actions list and the last action after it. The logic if that condition if false, the actions will not be further processed.

  action:
    - service: cover.close_cover
      target:
        entity_id: cover.somfy_blinds
    - service: notify.info
      data:
        message: Last friend left home, closing blinds.
    - condition: state
      entity_id: input_boolean.home_away_mode
      state: "on"
    - service: switch.turn_on
      entity_id: switch.alarm

Here if the “away mode” is one (homeowners are out for more than 24h), when the last friend leaves home, turn on the alarm. If not true, the last action won’t be executed.

[11/2024 edit] You can also have a if directly embedded in an action now:

      - 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 pi4, 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, Selly 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.
Software: Frigate, mqtt (mosquito on my gateway), pushover.
Add ons: advanced SSH, aircast, airsonos, check home assistant config, crowdsec, crowdsec firewall bouncer, duck DNS, HA google drive backup, let’s encrpt, mariaDB, Nginx, samba, spotify connect, studio code server, z-wave JS.
HACS integrations: overkiz, font awesome, iPhone device tracker, daikin residential controller, blueiris nvr, average sensor, sonoff lan.
HACS integrations: 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)

157 Likes

Thanks. Very interesting. I have been using the Universal Devices’ hubs (994i / Polisy / Eisy) for many years and about a year ago I added HA with the 994i Integration. The Universal Devices hubs are excellent and their customer support is out-of-this-world, but their nr 1 focus has always been on Insteon, which I do not use. Their ZWave support is good but still secondary to Insteon. After ordering and receiving the HA Yellow Box I switched entirely to HA. The move with my 80+ Zwave devices took a lot of work, but it now all works to my great satisfaction. All the devices and all the programs I had on UD work the same or better on HA. UD has far fewer “nodeservers” than the “Integrations” that HA has.
However, my biggest (and maybe only) concern is that I can now no longer rely on customer support. Over the years I had to rely numerous times on UD for technical support, with 9 out of 10 times because I messed up something in programing. There is no technical support with HA and I would depend entirely on this forum or Discord, which is somewhat scary for me.
This brings me to one of your comments. I agree with you that HA is no longer just for the sophisticated techies and HA is also a great product for people like me with no technical background but a lot of enthusiasm.
There is a lot in your 20 points that exceed my understanding with technical terms that totally escape me. HA is a learning process and it will take me a few years to be able to make optimal use of HA. As an example, I do not yet understand and use either Templates or Scripts and I struggle
tremendously with YAML . My plan is to watch YouTube videos and learn but some of these videos are still too technical for me. However, even without Templates and Scripts, I have well over a hundred Automations running lights, motion sensors, curtains, Chromecast, Google Home, Alexa and more.
My only possible disagreement with you is when you say that HA will still exist in 2040. I doubt that, not because any negative I can think of HA, but because the speed of technical evolution is such that I even have doubts on the role Google, Amazon Echo etc may play 20 years ahead. Something new and different is bound to come up. However in 2040 I will be 88 :grinning: and I may not care by then.
In conclusion, thanks again for your expertise and summary, but don’t forget the lower level techies such as me.

8 Likes

There’s lots of hard-won experience in your post, which I’m going to have to bookmark and re-read more than once. Thanks!

Your use of sub-directories for YAML is particularly neat, and something I’ve been meaning to do after hearing Frenk give DrZZs a tutorial on YAML syntax many live streams ago. Groups are a similar simple idea which are likely underused.

#5 is interesting as I’m a Solutions Architect and believe choices are informed by understanding the trade-offs behind a product/ platform/ protocol. My own take on comparing Z-Wave/ Zigbee/ Matter/ latest shiny might therefore be of interest:

Of course there are exceptions. Z-Wave’s mandatory testing doesn’t always work - Fibaro’s FGD-212 early firmware connected well but worked functioned very badly and they force you to buy their hardware for updates!

Even after building custom automation hardware for years (BASIC script on a '286 plus triacs!), the ESP* self-build idea initially seemed hard work. After many Tasmota and ESPhome builds, they work well for non-standard things to automate, but are best used with mains power as WLAN is still too energy intensive for battery devices.

Careful though, as one moment you’re hitting BUY on a Wemos D1 Mini board for £3; the next there’s a shipment arriving with a 3D printer, filament, Octoprint server, IR camera, … :slight_smile:

1 Like

This is a really useful list. Maybe I’ve missed this but if I was going to add one thing it would be to implement a naming convention and stick to it.

I think that every time you add a device you should invest time in naming it and all is entities. I’d also say that the names should not contain manufacturer names or model names. This makes replacing devices easier.

I’d also stay away from using devices in automations. Stick to entities. Then, when you replace a device, you can give it, and its entities, the same names. This will save you having to alter all the affected automations.

10 Likes

Correct me if I’m wrong but the goal of the “anti-minification” example you posted is to trigger the automation every half-hour within a desired time period (9:30-22:30). Is that correct?

  • In your example, the Template Trigger is evaluated every minute (because it employs the now() function) so 1440 times a day.
  • It’s designed to evaluate to true every 30 minutes between 9:30 and 22:30.
  • Out of 1440 daily evaluations of the template, it triggers just 15 times (and the condition is evaluated 15 times).
trigger:
   - platform: template
     value_template: >
       {{ now() >= today_at('09:30') and now() <= today_at('22:30') and now().minute % 30 == 0 }}
  condition:
   - platform: state
     entity_id: sensor.whatever
     state: 'off'

The following achieves the same result more efficiently yet isn’t guilty of what you described as “minification”. The Time Pattern Trigger triggers only 23 times a day and the condition is evaluated 15 times a day.

Trigger every half hour within a desired time period by checking the time every 30 minutes (on the hour and half-hour) and confirming it’s within the desired range (and the sensor is off).

trigger:
  - platform: time_pattern
    minutes: '/30'
 condition:
  - "{{ today_at('09:30') <= now() <= today_at('22:30') }}"
  - platform: state
    entity_id: sensor.whatever
    state: 'off'

If the Template Condition is deemed to be less legible, one can use a Time Condition:

  condition:
   - platform: time
     after: '09:30'
     before: '22:31'
11 Likes

Really good write up and a lot of sound advice in there. I’ve also learned a lot of these same tricks/tips over the years.

I also recommend a naming scheme. It just really helps with some of my more advanced automations/templates etc.

For example, my devices names are “[area] [object] [device type]” and for the entities I just tack on what its measuring.

ex.

  • Device: binary_sensor.master_bathroom_window_contact_sensor
  • Entity: binary_sensor.master_bathroom_window_contact_sensor_battery

But in the end use what works for you.

The other thing I like to do is when I add a device, review the settings and disable anything I don’t use (like power reporting) and disable any entities I won’t need to keep it clean. Those entities build up fast.

7 Likes

You’re absolutely correct sir. Great Thinking.
I’m just unsure of one point: I need that automation to run at 00 and 30, not anywhere based on latest HA reboot spaced by 30 mins. I was wondering if the /30 time pattern takes as a starting point the exact hour or the moment where HA started? Likewise, hours: “*/2” would trigger every 30 mins or exactly at 30 & 00 in your experience?

Very nice, thanks for taking the time!

I don’t follow all that advice myself, but there’s a lot of good info there. Just figure out which ones apply to your own use case and environment.

I’m glad the issue of “minifying” came up again. That one really hit home. I think we (coders and tinkerers, collectively) love to seek the most “compact” solution. If we can cram all the logic on one line, we will. I’m learning to embrace white space and wordiness. Makes it so much easier to figure out when you come back to it later. Not to mention debugging.

2 Likes

I’ll say I’m extremely grateful for this. I’m a recent Hubitat convert and am finding there’s different thought processes to doing similar things. Especially when it comes to automations.

Finding something to manage cloud backups has been on my to-do list, so definitely appreciate that tip.

1 Like

And sometimes it’s an illusion. Four automations are crammed into one, but automations.yaml is acutally longer because of all the conditions etc. :grinning_face_with_smiling_eyes:

2 Likes

Some asked for the Apex chart code on the dashboard:

type: custom:apexcharts-card
chart_type: donut
update_interval: 10min
apex_config:
  dataLabels:
    enabled: true
    dropShadow:
      enabled: true
    formatter: |
      EVAL:function(value) {
        return value.toFixed(0) + " %";
      }
  plotOptions:
    pie:
      customScale: 0.9
      donut:
        size: 35%
        background: transparent
        labels:
          show: true
          total:
            show: true
            label: kWh
            formatter: |
              EVAL:function(w) {
                return Math.round(w.globals.seriesTotals.reduce((a, b) => 
                { return (a + b) } , 0)) }
header:
  show: false
  title: Daily energy used
  show_states: false
  colorize_states: true
series:
  - entity: sensor.daily_ev_charge_energy
    transform: return x/1000;
    name: EV cars
    color: green
    unit: kWh
    show:
      datalabels: percent
      legend_value: false
  - entity: sensor.daily_baloon_energy
    transform: return x/1000;
    name: Baloon
    color: rgb(135, 221, 66)
    unit: kWh
    show:
      datalabels: percent
      legend_value: false
  - entity: sensor.daily_pac_consumption
    name: PAC1
    color: rgb(245, 221, 66)
    unit: kWh
    show:
      datalabels: percent
      legend_value: false
  - entity: sensor.daily_pac2_consumption
    name: PAC2
    color: orange
    unit: kWh
    show:
      datalabels: percent
      legend_value: false
  - entity: sensor.daily_it_bay
    name: IT bay
    color: rgb(255, 105, 0)
    unit: kWh
    show:
      datalabels: percent
      legend_value: false
  - entity: sensor.daily_heater_energy
    name: Heaters
    color: rgb(255, 0, 90)
    unit: kWh
    show:
      datalabels: percent
      legend_value: false
  - entity: sensor.daily_office_consumption
    name: Office
    color: rgb(169, 60, 244)
    unit: kWh
    show:
      datalabels: percent
      legend_value: false
  - entity: sensor.daily_pool_consumption
    transform: return x/1000;
    name: Pool
    color: rgb(70, 10, 186)
    unit: kWh
    show:
      datalabels: percent
      legend_value: false
  - entity: sensor.energy_various
    name: Other
    color: gray
    unit: kWh
    show:
      datalabels: percent
      legend_value: false

And as well for the Tesla style graph:

  - type: custom:tesla-style-solar-power-card
    house_icon: mdi:home
    battery_icon: mdi:battery
    generation_icon: mdi:solar-power-variant
    grid_icon: mdi:transmission-tower
    show_w_not_kw: 1
    grid_to_house_entity: sensor.teleinfo_power
    grid_extra_entity: sensor.teleinfo_periode_tarifaire
    house_extra_entity: sensor.daily_energy_cost_euro
    generation_extra_entity: sensor.solar_spot_percentage_tesla_graph
    generation_to_house_entity: sensor.solar_spot_production_watts_filtered
    appliance1_consumption_entity: sensor.wallbox_charger_wh
    battery_extra_entity: sensor.imeon_battery_charge
    generation_to_battery_entity: sensor.imeon_power_to_battery
1 Like

For “once a day” values, you can avoid the repeated time patterns completely, by triggering triggering when HASS has been restarted on event_template_reloaded:

# templates.yaml
# no "template:" here as in configuration.yaml

- trigger:
    - event: start
      platform: homeassistant
    - platform: event
      event_type: event_template_reloaded
    - platform: time_pattern
      # only needs to change once a day
      hours:   05
      minutes: 05
  unique_id: 1234567890
  sensor:
    - name: Date in Text
      #description: "Date in text format suitable for TTS"
      state: >
          {% set dayofweek = ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'][now().weekday()] %}
          {% set day = ['1st','2nd','3rd','4th','5th','6th','7th','8th','9th','10th','11th','12th','13th','14th','15th','16th','17th','18th','19th','20th','21th','22th','23th','24th','25th','26th','27th','28th','29th','30th','31th' ][ now().day-1] %}
          {% set month = ['January','February','March','April','May','June','July','August','September','October','November','December'][now().month-1] %}
          {{ dayofweek +', '+ day + ' ' + month + ' '+ now().strftime('%Y') }}
      icon: "mdi:CalendarRange"
3 Likes

Great write-up with a lot of useful information! :slight_smile: :+1:

I just wanted to add another possibility on your #14. You should really think about using packages. :smiley:

What you’re doing with directories and organization can be done much easier with packages. What you’re doing here, is dividing everything into files depending on the type, whereas packages are a more logical approach to divide things. Like into rooms or areas, or even with some specific things, like window covers.

The idea behind packages is the combination of all different things like sensors, groups, automations, scripts or whatever into one logical structured file. Let me give you an example: I’m using a few modes for our home, like “bed_mode” (when we are going to bed, turning this mode on turns off the lights, sets the blinds to specific positions, arm the alarm and so on) or “work_mode” (for the work-from-home office set the volume of the private telephone to 0, turn off the door bell while having a Zoom or Teams meeting…).

To make use of these modes, one needs a few helpers and automations:

As you can see, everything is in one shiny, nice place, ready to be maintained. In the end, there might be some more files with this way, but it is easier than working with a whole different files.
And one thing I like most about packages, you don’t need to setup the different integrations. Just set a sensor in a package file, and the sensor integration is called automatically.

If something new comes up in term of devices, you just need to add either a new file or put it in an already there package file. For example, I’m currently trying to build a new dashboard, and as it turns out, I needed an input_select to change the views. So it is just the creation of one file, “frontend_package.yml”, and in there are all the needed input helpers.

To be fair, packages are not the one-thing-fits-all approach, but they are worth mentioning, as they are a very underestimated and underrated component in HA.

5 Likes

I would say that this is a nice write up and will receive plenty of responses, but…

  1. Look at supporting the future development of HA and use Nabu Casa, especially for the simplicity for new and veteran users.

I myself use it… why? Because it’s one important thing I don’t have to mess with

3 Likes

From the Time Pattern Trigger’s documentation:

With the time pattern trigger, you can match if the hour, minute or second of the current time matches a specific value. You can prefix the value with a / to match whenever the value is divisible by that number.

In other words, when the value is evenly divisible by a number from 0 to 59. For /30 that means on the hour and half-hour.
0/30
30/30

2 Likes

I didn’t know about them indeed, will pay a look definitely :slight_smile:

I learned a whole lot from this so thank you for writing it all up.

My one addition to this from experience is to diversity your container platform. You have a whole lot of services running within HA and it sounds like it’s working well, but what happens if HA crashes? Now your nginx, crowdsec and potentially other services are down. If you are home no biggie, but outside the home that might be a problem.

I’ve seen a lot of people rely on HA to host their VPN or reverse proxy (I did this to start) and it can cause all sorts of headaches.

Moving a handful of those services over to a simple docker install on another Pi or Ubuntu (or my fave proxmox) on a mini pc can grant a lot more flexibility, fault tolerance and room to grow both home assistant and other services.

1 Like

You really should. :smiley: :rofl: But pe prepared, it is like doing it all over again. :rofl: If you want to add something about packages to your really great guide, let me know, I can write up some lines to add. :wink:

Then it may have been poorly designed/consolidated.

Consolidating multiple related automations into one ought to result in something that’s more streamlined, concise, efficient, and easier to read and debug (pick any three). If the result is the opposite then it was either poorly done or there was no good reason for consolidation.

sure, that’d be helpful I think