How to create a robust configuration by defining a function to compute device state? + ideas for a triggerless paradigm

Hey all, I’m quite new to Home Assistant, just set it up yesterday. I’m trying to figure out how to structure my automations to reliably match desired behavior.

Example automation + problem

As an example, one simple automation is to turn on some lights a bit before sunset and turn them off at 11pm. This is straightforward to do with two automations, one that turns them on with the sun trigger, and another that turns them off with the time trigger. However, this solution has some imperfections that bug me:

  • If there is a power outage or persistent network glitch, such time triggers can get skipped. This forum comment suggests that you would also need to have triggers for HA start - what a laborious pain! And it is very hard to tell if you got it right because these circumstances are hard to test.
  • You need to keep the automations in sync - if I add a new light I need to remember to add it to both.
  • There is no concise definition of how a given entity will behave, instead it is spread across the effects of all your automations that act on it. I read somewhere that one thing people like about node-red is that it makes it clear when there are cross-automation interactions.
  • When initially configuring this light behavior, and it is in the time interval the light is on, it would be reassuring if the lights came on. Of course, they do not with the trigger-based scheme, as something has gotten lost in translating the desired behavior of “the lights are on between these two times”

Solution sketch

What I want to be able to write is simply:

switch.light_socket_1 = now_is_between('sunset - 00:30:00', '23:00:00')

The system would then ensure that the light’s state matches this. A simple way to do this might be to trigger frequently, say every minute, and run turn_on or turn_off.

Question: is it ok to spam off / on?

Are there any bad effects of spamming turn_on / turn_off all the time, say every second? Do they always turn into commands sent to the device, or are they no-ops if the device’s state already matches?

Listening to the state_changed event in developer tools seems to suggest that this might actually be ok to do, even though I have AppDaemon running a turn_on every second.

Misc thoughts on Efficiency

For efficiency, we might look at approaches like in the popular React JS library, which is used for making applications for the browser. With React, components define what state they depend on, and when this changes, their rendering function gets run. After rendering, React cleverly figures out the minimum change needed in the browser to make it match the function’s output, leading to huge efficiency gains. My question above is related - I’m essentially wondering if HA implements this sort of optimization.

If it is ok to spam turn_on / turn_off and similar state change actions, then I’m not sure if it matters if I poll every second and run all the logic. The logic for my house’s automations should be able to run in a few milliseconds.

Inspiration for nice ways to write efficient declarative behaviors for devices might also be taken from various FRP (functional reactive programming) libraries like reflex-frp.

Manual override

I can think of one thing this paradigm does not handle so gracefully - manual override from the dashboard / cellphone. A literal implementation of “The system would then ensure that the light’s state matches” such as the polling described above would immediately switch the light back after it is manually set by some other system.

One approach might be to ask the user for a time interval to apply the override.

Another approach might be to store the original value at the time of the override. Once the behavior computes a different value than this old value, the override is cleared.

I see from this discussion (https://community.home-assistant.io/t/person-entity-how-to-use-user-id/324935/2) that it is possible to use the user_id from the context to check if the originator of a state or event is a human user. So, I think it should be feasible to implement this override semantics.

Question: Does a solution to this already exist?

Generally curious if this post makes you think “oh that reminds me of X”.

If a solution to this doesn’t exist I might try to make one. Probably just a few functions in AppDaemon.

End

I realize this is a weird and long first post. A bit of sweet and salty to end it:

Salty: I think lack of alternatives to the trigger paradigm is leading to lots of mostly-working automations which are tricky to maintain, and this problem extends far beyond Home Assistant.

Sweet: Overall I’ve been impressed by Home Assistant, it seems really awesome!

I hope some of you found this interesting! I’m curious to hear y’alls thoughts.

If there was a power outage then you likely wouldn’t care that the light wasn’t on or could do anything about it.

network glitches won’t prevent HA running an automation at the prescribed trigger time and unless the light is wifi based and the network glitch was with your LAN then the lights should get reliably operated.

besides unless these things happen all the time in your area the likelihood of these anomalous behaviors having a huge effect is probably not something to really worry about unless it truly is “mission critical”. If a time trigger is missed only very rarely because of those rare events then it doesn’t take much to just turn the light on if needed.

Again it’s really not that much of a pain unless you really have these things above happening all the time. And for most things that are just a minor inconvenience to fix (turn on the light) you wouldn’t need to add that extra layer of testing.

I only have a few automations that use HA restart as a trigger because I only REALLY care if the thing happens for only a few devices/situations.

I find that restarting of HA or reloading automations when developing is far more impactful on automations than anything else. And even then I don’t see any effects most of the time.

But again most things aren’t “mission critical” either and if a trigger gets missed at those EXACT times then it’s usually not a big deal.

there are ways to mitigate this depending on the use case.

for one you can just use one automation with two triggers and then play with the conditions to get the desired behavior (on or off).

Or you could just create a group of lights you want to act on and then you can use that group in the automations. Then if you add another light to the system then you just need to update the group to include the light.

I don’t think that’s just limited to HA or even home automation in general.

even in industrial PLC programming if the programmer acts on a device in different parts of the program there’s no way to cross reference that unless you manually do a search for it.

The system has no way of knowing what the programmer wants to do so it’s up to the programmer to ensure their code doesn’t collide unexpectedly.

HA is no different in that respect. It’s up to you to program your system correctly.

And the concern is probably overstated anyway since the vast majority of devices won’t be operated from a multitude of automations.

And HA has a feature if you look at the device in the dev tools integration page it will tell you where the device is actually referenced. So the work is already half done for you. You won’t have that for every device but most will.

sure but it’s usually not very good programming practice to need to do that since there are usually better ways to write the code.

And it’s not very efficient as far as system resources. Especially if you write every automation that way.

That is one I agree with. And there’s not really a good/easy way to deal with that.

TBH, I almost never automate lights in living spaces (unless those lights desired behaviors are VERY predictable). Lighting is too organic to reliably automate for every situation. There are way too many variables to consider as you already alluded to.

Of course you can do this with the existing automation system and without needing to run the automation every second. You just need to set the triggers and conditions correctly.

But then you lose the ability to do any manual overrides. Which leads back to the discussion above.

Not that there aren’t edge cases that get tricky sometimes but the majority of the automations aren’t nearly this complicated and work pretty darn reliably.

I have over 300 automations waiting/running and I can honestly say there are only a couple of them that give me troubles (mostly work fine but not 100%) and only because I haven’t been able to figure out the anomaly yet.

All of that said it’s hard to know what your expectation is for HA.

Every system, even expensive industrial software, relies on the programmer to write the code so it meets the desired outcome.

1 Like

Thank you so much for your detailed response!

If a time trigger is missed only very rarely because of those rare events then it doesn’t take much to just turn the light on if needed.

That’s true. It is probably because I work on distributed systems for work, and so it just irks me when things are not failure tolerant.

An example of an automation that matters more to me and may be more subtle is a ventillation fan to pull fresh air into my bedroom. It’s easy to not notice that it isn’t running, but it makes a huge difference for my sleep quality / respiratory health.

Again it’s really not that much of a pain unless you really have these things above happening all the time

I’m really more concerned on what this means systemically for users. I have the technical background to notice the flaws and hopefully address them in my setup. However, for less technical users it may not be so obvious when their setup is not fault tolerant.

Or you could just create a group of lights you want to act on

Ahh, good to know, thanks!

even in industrial PLC programming if the programmer acts on a device in different parts of the program there’s no way to cross reference that unless you manually do a search for it.

Yes, it’s true that the property I seek here is unusual in most programming environments. A way to have local definitions of the entire behavior of a state! It turns out there is already a rich exploration of this idea, dubbed functional reactive programming - here is a pretty good talk about it if you are curious. The good implementations of such systems are quite efficient and protect you from things like inadvertent feedback loops.

is it ok to spam off / on?

sure but it’s usually not very good programming practice to need to do that since there are usually better ways to write the code.

I discovered that it is not ok, at least with the abomination that is the official Tuya integration. I got an email from Tuya saying my trial quota was exceeded. And indeed, running iftop revealed that it was sending traffic to some ec2 instance.

Installed Local Tuya and now cooking with gas again. However, even in that case I can see from iftop that the turn_on is indeed sending network traffic directly to the device on turn_on / turn_off.

So yes, it is not efficient, I’d rather not load my wifi router with even kb/s of bogus traffic.

However, with logic to notice the state is already correct, I don’t think the polling is that bad. Yeah, it’s a bit smelly, but practically speaking this logic should take a few milliseconds, it’s a blip compared to all the other stuff the computer is doing even when passive.

You’re right that there are more efficient ways to do it, but these require you to manually perform the optimization of determining the triggers, leading to more complexity. To me it’s worth it to spend some inefficiency to gain code clarity. Like choosing Python instead of C.

All of that said it’s hard to know what your expectation is for HA.

I think my hope was to just write a single short python file where the behavior will be very clear and concise. I think I’ve figured out how to get there with AppDaemon! Will try to do something more efficient than polling eventually, mostly for the craftsmanship aspect.

1 Like

Also, 300 automations?!? Very impressive! That only a couple of them are flaky is good evidence that the current paradigm is decent enough for most use

1 Like