I’m very new to hass and I’m trying to create a script to turn on a socket, it should be on only when I’m home and even when I’m home only between 19 to 23h. The script I currently have will turn on the socket when these conditions are met, but once that happend the socket will never turn off again. I have a feeling nested conditions will be required for this but I’m not quite sure what the best approach is. Any suggestions? Also, the trigger I have for this is just checking if these conditions are met on a time interval, is that the best approach?
The way I’d approach this is the create a binary sensor with the elements you list as conditions then trigger the switch based on the sensor.
You should look up these elements in the documentation (goto to ‘integrations’ search binary sensor)
So one binary sensor one automation will handle both on and off.
Though if you are very new you can construct this using fairly standard components.
(if you want to do it that way I’m afraid I can’t help much (don’t use the gui editors))
From your gui automation above, if you come home at 20:01 the switch won’t be triggered until 21:00
I’d definitely go the route Muttley mentioned above, anything else is likely to have triggers/conditions that might not be met and cause it not to behave as you expect.
Triggers where you are anticipating every possible combination, e.g. some arriving before during and after the condition, as well as leaving during or after are likely to require multiple triggers and multiple conditions to make that work properly. The more you have of both, the more likely there are fringe cases that it misbehaves. Muttley’s suggestion is simple, and will just work when those conditions are met.
The OP wasn’t specific about what the behavior of the off function, but if the light needs to go back off during that time when the person leaves, the one you posted above will not do that. Hence if that is the way the OP expected, it not working ‘exactly as expected’.
What Muttley put above would do that… for example. If the OP wanted the light to stay on when they left during the time, then it wouldnt. What was specified by the OP wasnt technically specific enough.
Your first paragraph presents a theory with no supporting evidence. If you are certain Mutt’s suggestion is “simple”, please compose the template for a binary_sensor that will not have the alleged flaws of “multiple triggers and conditions”.
No, it won’t because the OP has not yet explained when the light should be turned off. When that information becomes available, then it can be addressed.
Thanks for the suggestions guys. The turning off should happen when I’m either not home anymore or when it’s past 23h. The device controlled is a smartplug that is charging an electric toothbrush. Basically I want to charge for a few hours per day but no more than 4h per day and the charging may only happen if I’m at home and not when I’m sleeping.
The easiest way I could think of to solve the max 4h/day + sleeping constraint is to only allow it to be on between 19h and 23h, I never go to bed before 23h anyway. If i’m not home on a particular day between those hours and it misses a charge it’s not a problem anyway because a 4h charge on a previous day should allow for a few days of use.
Okay,
Now both @123 and @callifo have valid points above, and though I don’t agree 100% with either, my opinion is just ‘my opinion’ so doesn’t really count for a lot.
As califo agreed with me I’ll do the counter case for him first : -
Any automation ‘should’ take into account ALL envisaged scenairios regardless of it being encapsulated in a binary sensor or an automation.
Binary sensors are kinda an advanced approach and Taras’s proposal would teach the OP more about how to think about automations, triggers, conditions and the associated actions
Taras’s counter : -
The whole concept of logic, requires breaking things down into smaller, known elements and building it up from there. Taras is doing that but I feel that it’s sometimes easier to adopt a linear approach to such issues and the whole trigger - condition thing gets pretty involved, pretty quickly.
Anything with a time trigger is (‘in my book’) pretty inefficient, as it’s possible to trigger something at 11:14:51 (why you’d need to trigger something at 11 am at 14 minutes and 51 seconds past the hour, is beyond me, but it’s possible) So the watcher for that trigger has to check this trigger every second of every minute of every day. That’s 86,400 evaluations every day. That’s why I use sensor.time templates for my time triggers ( states(‘sensor.time’) == ‘11:15’ ) ( note: - no seconds) - this evaluates only 1440 times a day. Now I ‘could’ put ALL the logic for this in one service template of one automation and call the automation every minute, but I think that’s messy. [Note: these numbers look big and I’m OCD about simplification/efficiency but as you can see (below) such ‘cleansing’ makes sod all difference at the end of the day]
Following on from 2. I have some sensors set up for my speakers (time slots, occupancy, manual control, sleep functions etc.). Doing the same for ALL my regular switches with time/other dependant triggers has halved my CPU usage from 4% and it sometimes even drops to 1% (Pi 4).
So solving this the ‘traditional way’ : -
automation:
- id: somethingotherthanastupidmadeuprandomnumber
alias: toothbrush_charging_slot_start
description: 'Bored with flipping a switch on'
trigger:
- platform: time
at: '19:00:00'
- platform: state
entity_id: device_tracker.moto_g_6
to: 'home'
condition:
- condition: state
entity_id: device_tracker.moto_g_6
state: 'home'
- condition: time
after: '19:00:00'
before: '23:00:00'
action:
- service: switch.turn_on
entity_id: switch.on_off_plug_in_unit_2
- id: imthinkingofwrittingabookontheobservedcolourofnavelfluff
alias: toothbrush_charging_slot_end
description: 'Bored with flipping a switch off'
trigger:
- platform: time
at: '23:00:00'
- platform: state
entity_id: device_tracker.moto_g_6
from: 'home'
condition:
condition: or
conditions:
- condition: state
entity_id: device_tracker.moto_g_6
state: 'not_home'
- condition: time
after: '23:00:00'
action:
- service: switch.turn_off
entity_id: switch.on_off_plug_in_unit_2
And not a template in sight.
This should work (not tested it) - BUT the major reason I dislike this is that the logic for turning on and turning off is closely related but not in one location (hence why sometimes going for the messy solution of putting it all in one service template)
My preferred solution is the binary sensor : -
binary_sensor:
- platform: template
sensors:
## toothbrush
bs_toothbrush_charging_slot:
entity_id: sensor.time, device_tracker.moto_g_6, binary_sensor.bs_toothbrush_charging_slot
value_template: >
{% set start = '19:00' %}
{% set end = '23:00' %}
{% set home = states('device_tracker.moto_g_6') == 'home' %}
{% set tbok = home and start <= states('sensor.time') < end %}
{{ tbok }}
friendly_name: Toothbrush Charging OK
icon_template: "{{ 'mdi:power-plug' if is_state('bs_toothbrush_charging_slot', 'on') else 'mdi:power-plug-off' }}"
automation:
- id: somethingelsereallybanal
alias: toothbrush_charging_slot
description: 'Am I Just Dreaming This ?'
trigger:
- platform: state
entity_id: binary_sensor.bs_toothbrush_charging_slot
action:
- service_template: switch.turn_{{ states('binary_sensor.bs_toothbrush_charging_slot') }}
entity_id: switch.on_off_plug_in_unit_2
Note: you could compress the sensor template a bit more but this is written for easy reading and maintenance. There’s nothing I hate worse than having to comeback to modify something and stand there scratching my head, “What the hell does this do ?”
Note: The reason why the sensor is self referencing is that rather than repeat the whole template in the icon you just reference it’self, so ‘IT’ changes, updates the output, then goes ‘Oh ! I’ve changed too’ and changes the icon.
The sensor updates 1/min but does not class as ‘messy’ because it does more than one thing (yeah. I’m splitting hairs ! )
Oooh ! nearly forgot, you NEED sensor.time to be configured for this to work
Next Thought: the two automations at the top should survive the sequence mangling of the gui editor. The last (binary_sensor version) ‘should’ also survive but the results will be more than fugly !
Edit: Taras has pointed out on another thread how to stop the automations editor mangling your automations (I’ll look for a reference) but another way is to get rid of " - id: " and just use " - alias: " instead. See Below : -
This is the below bit : -
Edit: DON’T do this. See : -
The “advanced” aspect is simply because one must employ templating. It’s a technique I employ frequently in my system.
What I disagree with is callifo’s statement that " anything else is likely to have triggers/conditions that might not be met". It’s equally possible to create a Template Binary Sensor whose template fails to handle all requirements, namely not triggering when it should or overlooking to check a particular condition. After all, the template must achieve the same functionality as explicitly listing triggers and conditions in an automation.
Home Assistant’s ‘clock tick’ is 1 second. That means it has a minimum resolution of 1 second and each time it advances by a second it checks if there’s ‘stuff to do’. So if you use a Time Trigger set for 08:04:30 or 08:00 or a Template Trigger with sensor.time checking for 08:05, the internal clock still checks for ‘stuff to do’ every second.
NOTE
In the example employing explicitly listed triggers and conditions, we both know that the two automations can also employ Template Triggers and Template Conditions. This blurs the line between the two techniques. However, the end-user must know how to create templates (knowledge of Jinja2, Trigger State Object, etc).
Absolutely agree !
You might as well say “do stuff here” garbage is garbage - make it ‘not’ garbage
Yep ! that to is unavoidable AND is actually beneficial for ALL sorts of ‘other’ automations.
My point is : - “lets give HA as little to do at that ‘one second’ point, as is feasibly possible”
Again, I absolutely agree, Templates are like the Superman of HA, they (and the template editor) are your best friends, you can pretty much do anything with a decent template. (Taras is one of those to whom I go, for advice).
The above was not written for Taras’s education: he’s forgotten more than I know about Home Automation. I always try to write my posts to be as informative (and give as little misinformation) as is possible to anyone who comes across the thread. My apologies if I implied anything else.
Similarly Califo has been on the forum a long time and knows this stuff too, I was just showing that there are pro’s and cons to any argument (but ultimately I agreed with his preference )
I agree with the same preference, but not with the premise that it is implicitly superior to “anything else”. It has to achieve the same requirements and simply goes about it another way (via templating).
For example, the template you created can be distilled and used in the first example with Template Triggers and Conditions.
One advantage of using a Template Binary Sensor is that it can be used with a single automation, to turn the switch on/off, whereas in the first technique it’s simpler to use two separate automations (could be bludgeoned into one with some loss of legibility). However, the second technique requires a Template Binary Sensor, an automation, and sensor.time; six of one, half a dozen of the other.
I absolutely agree !
I warned it was messy, it’s difficult to follow the logic and to maintain.
It also floods the ‘network’ with instructions every minute (I could enhance the template further * to stop that) but we are then just adding layers of paint to hide a hideous automation. ( * perhaps with scripts or the soon to be released ‘choose’ but … )
BUT it would work !
You must agree that ‘some’ people try to minimise the ‘number’ of automations on their system, sometimes at the expense of clarity, maintenance and actual efficiency.
@jonas87, please don’t use the last, pretend that you never saw it, but it does illustrate how powerful templates can be AND with a little reading and a few examples there’s not much that you can’t do with them. You don’t need Appdaemon or NodeRed (Taras does use NodeRed though, no idea why as he has the skills to not bother)
Ultimately it depends on what you want out of HA, to some it’s either ‘off the shelf’ or they are not interested.
I’ve experienced this when trying to turn something on and off using a single automation. Often, you can tell by the complexity of the service_template if you’ve been clever and efficient or gone to extraordinary lengths to jam a square peg into a round hole!
Whilst taking into account ‘some’ of Taras’s comments, a possible improvement is : -
automation:
- id: busterbloodvessel
alias: toothbrush_charging_slotification_the_sequel
trigger:
- platform: state
entity_id: device_tracker.moto_g_6
- platform: time
at: '19:00:00'
- platform: time
at: '23:00:00'
action:
- service_template: >
{% set val = states('device_tracker.moto_g_6') == 'home' and '19:00' <= states('sensor.time') < '23:00' %}
switch.turn_{{ 'on' if val else 'off' }}
entity_id: switch.on_off_plug_in_unit_2
This gets rid of the minute by minute checking and the consequent command on the network (there is nothing wrong with turning a switch that is on to on, but it’s just consuming bandwidth)
But ALL the other comments still stand, hard to read, maintain etc.
Note: the amount of time and effort gone into this discussing options and suggestions etc. (by @123 , @callifo and myself) makes this one of the most expensive solutions of any automation I’ve come across. Use it as a lesson, most aren’t worth this !
Um… Going back to the original post… If you need nested conditions you can create them fairly simply with nested scripts. You don’t have to have all your code in one place - it can be broken up into small scripts like subroutines in the bad old days. Particularly useful if different automations perform similar actions.
I like your most recent design iteration best. It incorporates the best of both worlds (and proves “anything else” can indeed be as good or better).
In this situation, if sensor.time isn’t already handy, it can be replaced with now() like this:
- service_template: >
{% set val = states('device_tracker.moto_g_6') == 'home' and
'19:00' <= now().strftime('%H:%M') < '23:00' %}
switch.turn_{{ 'on' if val else 'off' }}
entity_id: switch.on_off_plug_in_unit_2
NOTE
This version of the automation will still call switch.turn_off whenever the device_tracker changes to home but the time is outside of 19:00-23:00. It’s not a showstopper but if there was a desire to eliminate that behavior, all it would take is the inclusion of a condition.