Script help (turning off only devices currently on)

Hello guys!

Can someone help me please? Since updating to version 0.84, this script does not work anymore, could not figure it out:

casa_desligar_tudo:
  alias: "Desligar tudo em casa"
  sequence:
  - service: climate.set_operation_mode
    data_template:
      operation_mode: 'off'
      entity_id: >
        {% for device in states if not device.state == 'off' and (device.entity_id in ['climate.ar_condicionado_da_suite','climate.ar_condicionado_do_quarto','climate.ar_condicionado_da_sala']) -%}
          {%- if loop.first %}{{ device.entity_id }}{% else %}, {{ device.entity_id }}{% endif -%}
        {% endfor %}
  - service_template: light.turn_off
    data_template:
      entity_id: >
        {% for device in states if device.state == 'on' and ( device.entity_id in ['light.area_servico','light.suite_banheiro_principal','light.suite_banheiro_espelho','light.corredor','light.cozinha','light.entrada','light.ledchaocozinha','light.ledcozinhabalcao','light.ledquartotv','light.ledsaladesktop','light.ledsalatv','light.ledsuitecama','light.ledsuitetv','light.mesa_jantar','light.quarto','light.sala_principal','light.banheiro_social_principal','light.banheiro_social_espelho','light.suite_principal'] ) -%}
          {%- if loop.first %}{{ device.entity_id }}{% else %}, {{ device.entity_id }}{% endif -%}
        {%- endfor %}
  - service_template: switch.turn_off
    data_template:
      entity_id: >
        {% for device in states if device.state == 'on' and ( device.entity_id in ['switch.chuveirosuite','switch.toalheiro','switch.tv_lg_sala','switch.tv_lg_suite','switch.chuveirosocial','switch.tv_lg_quarto','switch.cafeteira_casa','switch.chaleira_casa','switch.ventilador_casa','switch.home_theater_sala'] ) -%}
          {%- if loop.first %}{{ device.entity_id }}{% else %}, {{ device.entity_id }}{% endif -%}
        {%- endfor %}
  - service: alarm_control_panel.alarm_disarm
    entity_id: alarm_control_panel.alarme

I use this on my house entrance tablet, so I can turn off everything that is currently on and disarm the alarm.

Now I get this:

Log Details (ERROR)
Fri Dec 14 2018 14:35:47 GMT-0200 (HorĂĄrio de VerĂŁo de BrasĂ­lia)

Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/service.py", line 277, in _handle_service_platform_call
    await getattr(entity, func)(**data)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/switch/template.py", line 158, in async_turn_off
    await self._off_script.async_run(context=self._context)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/script.py", line 130, in async_run
    await self._handle_action(action, variables, context)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/script.py", line 172, in _handle_action
    action, variables, context)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/script.py", line 261, in _async_call_service
    context=context
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/service.py", line 81, in async_call_from_config
    domain, service_name, service_data, blocking=blocking, context=context)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/core.py", line 1121, in async_call
    self._execute_service(handler, service_call))
  File "/usr/local/lib/python3.6/site-packages/homeassistant/core.py", line 1143, in _execute_service
    await handler.func(service_call)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/script.py", line 123, in service_handler
    context=service.context)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/script.py", line 181, in async_turn_on
    kwargs.get(ATTR_VARIABLES), context)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/script.py", line 130, in async_run
    await self._handle_action(action, variables, context)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/script.py", line 172, in _handle_action
    action, variables, context)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/script.py", line 261, in _async_call_service
    context=context
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/service.py", line 81, in async_call_from_config
    domain, service_name, service_data, blocking=blocking, context=context)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/core.py", line 1101, in async_call
    processed_data = handler.schema(service_data)
  File "/usr/local/lib/python3.6/site-packages/voluptuous/schema_builder.py", line 267, in __call__
    return self._compiled([], data)
  File "/usr/local/lib/python3.6/site-packages/voluptuous/schema_builder.py", line 589, in validate_dict
    return base_validate(path, iteritems(data), out)
  File "/usr/local/lib/python3.6/site-packages/voluptuous/schema_builder.py", line 427, in validate_mapping
    raise er.MultipleInvalid(errors)
voluptuous.error.MultipleInvalid: Entity ID "" is an invalid entity id for dictionary value @ data['entity_id']

If someone could make this script better, I really appreciate the help.

Maybe the great @petro could solve this puzzle, again!

Thanks guys!

honestly, I’m surprised that worked in the past because yaml like single argument returns not lists. Anyways, you could try this but you will get errors if all lights are off regardless.

casa_desligar_tudo:
  alias: "Desligar tudo em casa"
  sequence:
  - service: climate.set_operation_mode
    data_template:
      operation_mode: 'off'
      entity_id: >
        {% set entities = ['climate.ar_condicionado_da_suite','climate.ar_condicionado_do_quarto','climate.ar_condicionado_da_sala'] %}
        {{ states.climate | selectattr('entity_id', 'in', entities) | selectattr('state','!=','off') | map(attribute='entity_id') | join(', ') }}
  - service_template: light.turn_off
    data_template:
      entity_id: >
        {% set entities = ['light.area_servico','light.suite_banheiro_principal','light.suite_banheiro_espelho','light.corredor','light.cozinha','light.entrada','light.ledchaocozinha','light.ledcozinhabalcao','light.ledquartotv','light.ledsaladesktop','light.ledsalatv','light.ledsuitecama','light.ledsuitetv','light.mesa_jantar','light.quarto','light.sala_principal','light.banheiro_social_principal','light.banheiro_social_espelho','light.suite_principal'] %}
        {{ states.light | selectattr('entity_id', 'in', entities) | selectattr('state','eq','on') | map(attribute='entity_id') | join(', ') }}
  - service_template: switch.turn_off
    data_template:
      entity_id: >
        {% set entities = ['switch.chuveirosuite','switch.toalheiro','switch.tv_lg_sala','switch.tv_lg_suite','switch.chuveirosocial','switch.tv_lg_quarto','switch.cafeteira_casa','switch.chaleira_casa','switch.ventilador_casa','switch.home_theater_sala'] %}
        {{ states.switch| selectattr('entity_id', 'in', entities) | selectattr('state','eq','on') | map(attribute='entity_id') | join(', ') }}
  - service: alarm_control_panel.alarm_disarm
    entity_id: alarm_control_panel.alarme
1 Like

Hello @petro! Thanks for your reply!

Yes, it worked like a charm before, no idea why hahaha

No problem if there are errors on log, I just want it to finish doing what it was supposed to do. :laughing:

I think my YAML editor did not like your suggestion:

I believe the colors are wrong because there is a syntax error, maybe?

Also, changed the first service call to states.climate (it was states.light):

  - service: climate.set_operation_mode
    data_template:
      operation_mode: 'off'
      entity_id: >
        {% set entities = ['climate.ar_condicionado_da_suite','climate.ar_condicionado_do_quarto','climate.ar_condicionado_da_sala'] %}
        {{ states.climate | selectattr('entity_id', 'in', entities) | selectattr('state','!=','off') | map(attribute='entity_id') | join(', ') }}

Thanks a lot!

1 Like

Hello again @petro! It did not work… There is something with the syntax. Can you please take a look the image above? The next service call does not work, it has the same color as the service before…

It seems there is something with this part:

{{ states.climate | selectattr('entity_id', 'in', entities) | selectattr('state','!=','off') | map(attribute='entity_id') | join(', ') }}

Also, some parts have service_template others just service.

Thanks!

Have you tried it in the template editor? These 2 lines:

{% set entities = ['climate.ar_condicionado_da_suite','climate.ar_condicionado_do_quarto','climate.ar_condicionado_da_sala'] %}
{{ states.climate | selectattr('entity_id', 'in', entities) | selectattr('state','!=','off') | map(attribute='entity_id') | join(', ') }}

Yes, they work but on Visual Studio Code the colors shows that this YAML syntax may have something wrong. You can see that the service call is joined to the previous one.

Even the next script gets confused:

Also, do you think I should use service_template or just service?

Thanks a lot for your time!

service, not service_template. I think the VS colors is just messing up. It appears to not see the end of the selectattr() lines.

I think the problem is here:

After taking out the join command, YAML seems OK.

Not sure what is the problem with join(', ')

Using https://codebeautify.org/yaml-validator, I get this:

Error : Unexpected characters (, entities) | selectattr('state', '!=', 'off') | map(attribute='entity_id') | join(', ') }}). Line : 1 {{ states.climate | selectattr('entity_id', 'in', entities) | selectattr('state', '!=', 'off') | map(attribute='entity_id') | join(', ') }}

join(', ')

should be in that spot.

I also get valid yaml when I copy and paste the post:


FYI For some reason the link doesn’t include the 2 spaces before alias.
1 Like

Hello again my friend!

It was actually a problem with VSC after all haha

I’ve installed a Jinja extension and look how everything is now:

So sorry to bother you with this!

Your suggestions works perfectly, I will now update the other ones I have with this function.

Thanks a lot mate! Have a great weekend!

1 Like

You’re welcome!

Dang! It looks like it does not allow empty templates with version 84 :frowning:

This was changed:

Improved service calling

We have improved how we call services with better validation checks. This means that if you have an automation or a script that sends invalid data, we will now stop the execution and be better able to point out where your incorrect calls are coming from.

Now it just stops and log shows this:

voluptuous.error.MultipleInvalid: Entity ID "" is an invalid entity id for dictionary value @ data['entity_id']

This script does not work anymore. I need something that does not trigger this service call if there is nothing on. Maybe using if and calling a script?

Too bad…

I have a newbie question- Why?
I just turn everything off regardless if it’s on or not. If a light or switch or other device is already off, what’s the harm in turning it off again?

Hello sir!

The main point of doing this is because many devices are condition based or have scripts to turn it off or not and with this latest update, I get most of the time invalid data (empty entity_id for example) so this is a real problem for me now.

Also, a couple of switches are controlled by a broadlink IR and RF commands that are not that smart so, for example, If I turn off all AC (wall split types) I hear all of the devices beeping and IR codes are blasted all over the house.

It is not a huge problem but makes me go crazy that this simple filtering task is so tricky to do…

Thanks.

I envy you. If I have any devices that beep, I can’t hear them.

Too bad mate, sorry to hear that.

It is quite difficult to explain, especially because english is not my mother language :slight_smile:

I can assure you that if you see my setup you will understand my use-case, I really like to dig deep and customize all scripts for the best results.

Have a great day!

Would I interest you with a python script instead?

This is what I used for something similar, call it toggle.py and put it in HA folder/python_scripts.
You can pass state to check in ‘chkstate’ from python_script.toggle service.
if ‘chkstate’ is not specified, script defaults to check ‘off’ state.
Just update the list of lights entity ID to yours.

Basically, it check each ‘hpEntities’ state, if not ‘chkstate’ (off), toggle that entity.

It is now setup for lights, you can adapt it for climate, switch, etc. also.

toggle.py:

chkState = data.get('chkstate','off')
hpEntities = ["light.a_light","light.backporch","light.basement","light.dining","light.dinner_table_light"]
for entity_id in hpEntities:
  state = hass.states.get(entity_id)
  if (not state.state == chkState):
    hass.services.call('light', 'toggle', {'entity_id': entity_id}, False)
1 Like

Newbie question- Where do you put Python scripts and how do you run it?

Hello sir! Thanks for your suggestion!

Not sure if this would be easy to implement since device list changes depending on conditions and script function. Sometimes I need to turn off all lights and sometimes if we have guests in our home, I’ve created a “guest input boolean” that if checked, some lights should be ignored. The same scenario with switches, climates and covers.

Not sure the best approach would be yet, I wish I could just set a list of entities and a macro checks if it is on or not and send the service.

I think this is an area to be improved on HA, these custom service calling scripts.

Thanks a lot!