Frustration: how to set mutually exclusive timers? [SOLVED: change a single timer with timer.start]

TL;DR: I wanted to use timers (plural) to visualize the running time of two scripts which are mutually exclusive, and bashed my head against the wall in the process. Turns out it’s possible to have a single timer and change its duration before you start it with timer.start (not timer.change).

<rant>
As many times it goes, my idea is simple but HA doesn’t seem to help out :sigh:

I have a simple towel heater and I bought with it a smart plug and a button.
The idea is to have actions to run it for 2 and 4 hours, both on the HA panel and with the button.
This is a common feature on “end user” systems, such as the eWeLink (sonoff) or SmartLife (Tuya) apps, and some people have already thought this should be baked in HA.

This was straightforward at first with the knowledge I already had; I had created scripts with delays between on and off, and it was triggered directly by the UI and automations related to the physical buttons. However… delays doesn’t make it easy to see how much time is left. Then I discovered timers, and thought it would be easy to replace the script with a timer…

Oh boy, I was wrong in so many ways.
Here’s the tiny list of issues I stumbled upon through the many hours I spent trying to get a simple idea going:

  • it doesn’t seem possible to have a timer turn off the other in this scenario. When a timer goes off, the heater goes off too; making a timer turn the other off while turning the heater on doesn’t seem to work, not even with a small time delay in between - I guess the consecutive actions cause the last to be ignored.
  • It gets VERY complicated to setup the UI since there’s no timer.toggle action, and thus I have to create two buttons for each action (start and stop), and you got to repeat yourself between them.
  • I also tried using timer.change to set a single timer entity and set its duration on demand, but then I discovered the service should actually be named timer.add or timer.subtract.
    • EDIT: as explained below, you can only freely change the duration of the timer before you start it with timer.start. Definitely not straightforward.
  • not to mention it’s possible to add triggers for multiple events at once, but not for multiple entities - what means every timer must have its own on and off triggers on the automation; again, repetition.

I thought that adding a timer to my flow would make it cleaner and better; turns out, as with many things in HA, going with workarounds is sadly better. I wish I had made a backup of the script, interface and automation before trying “something new” (not that you can really make an easy backup of UI code, since friendly Lovelace strips out any comments you leave, unless by “backup” you mean “copy stuff into notepad”).

This also reminds me of an old topic where someone was being heavily criticized when he criticized HA for being so complicated in so many ways when there was an opportunity to be smarter. I understand this is probably due to giving people options, but then you end up complicating so much it scares people off.
</rant>

How would you create two timers which turn something on/off and also cancel each other?

This seems simple to achieve with a timer. However, maybe I have misunderstood the requirements because you wrote several paragraphs about the perceived deficiencies of timers.

Can you explain how you want to control the towel heater? For example, perhaps an Input Select with on/2/4/off to control the heater? (Where 2 and 4 represent the number of hours to run the heater; switching between the two values cancels the previous one)

I intentionally didn’t set constraints on the implementation - your idea isn’t something I thought of, for instance :slight_smile:
(I can already think of how your idea would work, but I won’t interfere haha)

The “requirements” are:

  • be able to set those different time options from the UI
  • be able to see how much time is left (so I can use something pretty like timer-bar-card)
  • be able to toggle those time options from an automation (which would be triggered by events coming from a physical button like “button short pressed” / “button double pressed”)

Your first and third requirements can be fulfilled using the suggested Input Select. The timer can fulfill the second requirement. Only a single timer is needed; the 2/4 options in the Input Select set the timer’s duration.

How would one use the input_select to set the timer duration? That’s one of the things I tried, but, as mentioned in the rant you skimmed through (I totally get you LOL), timer.change doesn’t work that way and the other timer services only turn it on/off, basically.

I read your rant; it’s filled with erroneous conclusions and not worth my time to comment on it.

timer.start with a given duration will restart a running timer with the new duration. An automation with a State Trigger monitors the Input Select and controls the heater either directly (options on/off) or indirectly via the timer (options 2/4).

Reference: Timer integration


EDIT

Added link to documentation and screenshot of relevant paragraph.

2 Likes

Ohh, right, I will use start to change the timer. That makes sense. I guess I got one more confusing thing to add to the original list :joy:
I didn’t even thought about that since my tries with change caused a bunch of constraint errors, such as “you can’t change a timer to be bigger than the main duration” (so why would I be able to do that with start? etc)

That helps with the interaction issue between the two timers, and also scales better if I want to add more options. The only issue left is, if the user interacts directly with the timer, it will be kept in the last time it ran, instead of allowing the user to decide a time (which is only possible through the input_select). This is a minor issue, though, since the timer is mostly for viewing and it’s easy to fix if you end up running the timer with the wrong duration.


EDIT
Yep, I saw that doc section after you mentioned start. I just didn’t give that service much attention at first because the name doesn’t imply you can change the timer :upside_down_face:

I also updated the main post with the solution; I started editing it to reflect your idea, but then noticed it’s a complete solution to the issue and I was indeed going in a wrong direction, trying to create a timer MMA :joy:

Thanks!!!