I seem to be unable to use AND in service templating in scripts.
livingareaautolight:
alias: Auto Light - Living Area Manage
sequence:
- data: {}
entity_id: light.backdoor
service_template: >
{% if states('sensor.diningroom_brightness') | float > 10 and states('sensor.diningroom_brightness') | float < 12 %}
light.turn_off
{% endif %}
generates the following Error:
Logger: homeassistant.components.script
Source: helpers/service.py:123
Integration: Script (documentation, issues)
First occurred: 1:40:52 PM (1 occurrences)
Last logged: 1:40:52 PM
Auto Light - Living Area Manage: Error executing script. Unexpected error for call_service at pos 2: Template rendered invalid service:
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 115, in async_prepare_call_from_config
domain_service = cv.service(domain_service)
File "/usr/src/homeassistant/homeassistant/helpers/config_validation.py", line 411, in service
raise vol.Invalid(f"Service {value} does not match format <domain>.<name>")
voluptuous.error.Invalid: Service does not match format <domain>.<name>
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 153, in _async_step
self, f"_async_{cv.determine_script_action(self._action)}_step"
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 623, in _async_call_service_step
*self._prep_call_service_step(), blocking=True, context=self._context
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 252, in _prep_call_service_step
return async_prepare_call_from_config(self._hass, self._action, self._variables)
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 123, in async_prepare_call_from_config
) from ex
homeassistant.exceptions.HomeAssistantError: Template rendered invalid service:
But the following:
livingareaautolight:
alias: Auto Light - Living Area Manage
sequence:
- data: {}
entity_id: light.backdoor
service_template: >
{% if states('sensor.diningroom_brightness') | float > 10 %} light.turn_off
{% endif %}
executes without error.
Any Advice would be appreciated.
Thanks
Your template wants the brightness to be between 10 and 12 in order to turn on the light. What if the brightness is NOT in that range? Your template will produce nothing which is an invalid service call.
Create a condition prior to the service call (Template Condition). Then the service call doesnāt need a template because it will be executed only if the condition was satisfied.
EDIT
Hereās an example of what I suggest you do:
livingareaautolight:
alias: Auto Light - Living Area Manage
sequence:
- condition: template
value_template: "{{ 10 < states('sensor.diningroom_brightness') | float < 12 }}"
- service: light.turn_off
entity_id: light.backdoor
If the brightness is within the desired range, the condition is satisfied and execution proceeds to the next step and the backdoor light is turned on.
If the brightness is not within the desired range, execution stops.
This technique avoids the entire question of āWhat should I put in the āelseā when I donāt need/want an āelseā?ā
Your code is wrong. An āifā always needs an āelseā just because it sometimes does not error out does not mean you are okay. Itās simply bad programming practice.
AND following the script/automation erroring out, it crashes, and any subsequent actions following it in the script/automation will not be performed.
You can omit as many elifās as you like but always include an else.
If you donāt need an else just use a condition to block further processing
I disagree that an if always needs an else from a programming point of view (and Iāve been doing this since the 1980s in a variety of languages); and there are examples in the template documentation to back me up on that for Jinja templates in general; although I agree that the template in thicase must provide a valid output for service_template.
I wonder if the problem is one of priority that can be solved with brackets? Going overkill to start with, try this:
{% if ((states('sensor.diningroom_brightness') | float) > 10) and ((states('sensor.diningroom_brightness') | float) < 12) %}
service_templatemust be supplied with a service call. So if the template fails to provide one (i.e. returns an empty string), Home Assistant will throw this error:
Invalid: Service does not match format <domain>.<name>
The way the template was constructed, if the brightness fails to be within the desired range, it produces nothing and thatās not a valid service call. Therefore the usual recourse is add an āelseā to supply something. However, scripting allows you to use conditions which can be used in lieu of if-else statements (see example above).
That example generates a long string of text. The āif without an elseā inside it simply decides whether or not to include something in the middle of the sentence (āit is warmā if it is warm, nothing if it is not). The result of the template in its entirety still generates the required data (location of Paulus, times the sensors were last activated etc).
In the case of a service template you MUST always resolve to an actual service, otherwise you will get an error because you told the system to run a command but didnāt actually give it a command to run.
{% if states('sensor.temperature') | float > 20 %}
It is warm!
{% endif %}
This is the only one I can find, I agree itās misleading AND wrong
If used in a sensor the the sensor says ??? āIt is warm!ā or ā¦
This is a crap sensor.
If itās used in an automation/script then what happens when itās not(if()) ? again crap - the document should be corrected.
Just seen your new templates. They still employ the same error
How about you try what Teras, Marc and I suggested : -
service_template: >
{% set brightness = states('sensor.diningroom_brightness') | float %}
{% if (brightness > 10) and (brightness < 12) %}
light.turn_off
{% else %}
light.turn_on
{% endif %}
@Troon ā¦ I was going to jump on that but Taras beat me to it (out Ninjaād (AGAIN !))
Edit: corrected the on/off (but thereās no reason not to have off and off (just donāt see the point))
If you follow the ārule of thumbā (if thatās what you want to call it) you will never fail. if you donāt ā¦ ???
And the case here is that we are writting code for HA running through a Jinja wrapped version of python (and the sandbox only supports a subset of ALL python commands too). We have to bear that in mind as this is not assembler. fortran, cobol, visual basic etc. etc. etc.
I do not want this script to turn the light on, only switch it off at a certain brightness level.
The problem with a condition in a script, is that it is applied to the script as a whole. This script turns a number of lights off on this brightness setting. Adding a condition to check if a single light is on, it would circumvent switching any other lights off if the condition for one light isnt met.
Templates support āif-elseā statements and there are situations where they are useful. However, thereās a distinction between the purpose of an āif-elseā in a template and using a condition like I did in the example above.
The condition is being used to control the scriptās execution flow (go, no-go). If the condition is satisfied, execution proceeds to the next step. If the condition is not satisfied, execution stops.
An if-else within a template determines the templateās output. The service_template option expects to receive the name of a service call and your templateās job is to provide it with one. Perhaps an āif-elseā could be used to return light.turn_on or light.turn_off. However, in your template, it really only needs to return one service, light.turn_on, and thereās no other service to call. In other words, you were trying to use the template to control the scriptās execution flow. That job is best handled by a condition.
In your example, thatās fine however, as you stated, itās problematic if there are other steps that the script must execute.
In that tricky situation, you would need to use the workaround suggested by Mutt. Your original template would use an else that calls a ādo-nothingā service (because the template is still obliged to provide a service call). Itās not pretty but it gets the job done.
There is no specific ādo-nothingā or ādummyā service but this one serves as a fairly safe substitute in most situations: homeassistant.update_entity
This wonāt work here (please educate me) as he wants to call light.turn off as the other servicesee other posts below
presumably with the entity id just before or after depending on your inclinations or if the UI genertaes it.
BUT
service_template: >
{% set brightness = states('sensor.diningroom_brightness') | float %}
{% if (brightness > 10) and (brightness < 12) %}
script.turn_off_the_dang_light
{% else %}
script.zero_delay_script
{% endif %}