Jinja template script not working, all lights off if nobody is home

Hi there,

I have a script working well

 all_lights_off:
   alias: 'Nobody home all off'
   sequence:
     - service: light.turn_off
       data_template:
       # Turns off all lights, except of ...
         entity_id: >
           {% set exclude_light = [
             'light.shelly_kitchen',
             'light.shelly_floor'
           ] %}
           {%- for device in states.light|rejectattr('entity_id','in',exclude_light)|rejectattr('state','in','off')|rejectattr('state','in','unavailable') %}{%- if loop.first %}{%- else %}, {% endif %}{{device.entity_id }}{%- if loop.last %}{% endif %}{%- endfor  %}

This script works, but throws an error if no light is on. As soon as one light is on (but not light.shelly_kitchen and not light.shelly_floor) there are no errors anymore.
The problem is the ‘for loop’ if its result ist empty. What can I do to prevent that?

Errors:

 Error executing script. Invalid data for call_service at pos 1: not a valid value for dictionary value @ data['entity_id']
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/core.py", line 1276, in catch_exceptions
    await coro_or_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1295, in _execute_service
    await handler.func(service_call)
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 204, in service_handler
    await script.async_turn_on(variables=service.data, context=service.context)
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 280, in async_turn_on
    await self.script.async_run(kwargs.get(ATTR_VARIABLES), context)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 831, in async_run
    await run.async_run()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 555, in async_run
    await self._async_run()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 572, in _async_run
    await self._async_step(log_exceptions=not propagate_exceptions)
  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 656, in _async_call_service_step
    *self._prep_call_service_step(), blocking=True, context=self._context
  File "/usr/src/homeassistant/homeassistant/core.py", line 1222, in async_call
    processed_data = handler.schema(service_data)
  File "/usr/local/lib/python3.7/site-packages/voluptuous/validators.py", line 208, in __call__
    return self._exec((Schema(val) for val in self.validators), v)
  File "/usr/local/lib/python3.7/site-packages/voluptuous/validators.py", line 287, in _exec
    raise e if self.msg is None else AllInvalid(self.msg, path=path)
  File "/usr/local/lib/python3.7/site-packages/voluptuous/validators.py", line 283, in _exec
    v = func(v)
  File "/usr/local/lib/python3.7/site-packages/voluptuous/schema_builder.py", line 272, in __call__
    return self._compiled([], data)
  File "/usr/local/lib/python3.7/site-packages/voluptuous/schema_builder.py", line 817, in validate_callable
    return schema(data)
  File "/usr/local/lib/python3.7/site-packages/voluptuous/schema_builder.py", line 272, in __call__
    return self._compiled([], data)
  File "/usr/local/lib/python3.7/site-packages/voluptuous/schema_builder.py", line 594, in validate_dict
    return base_validate(path, iteritems(data), out)
  File "/usr/local/lib/python3.7/site-packages/voluptuous/schema_builder.py", line 432, in validate_mapping
    raise er.MultipleInvalid(errors)
voluptuous.error.MultipleInvalid: not a valid value for dictionary value @ data['entity_id']

Both errors pop up at the same time.

I appreciate any help

Try this:

 all_lights_off:
   alias: 'Nobody home all off'
   sequence:
     - service: light.turn_off
       data_template:
         entity_id: >
           {% set exclude_light =
             [ 'light.shelly_kitchen',
               'light.shelly_floor' ] %}
           {% set lights = states.light
             | rejectattr('entity_id', 'in', exclude_light)
             | rejectattr('state', 'in', ['unavailable', 'off'])
             | map(attribute='entity_id')
             | list | join(', ') %}
           {{ lights if lights | length > 0 else 'none' }}

The template gets all lights, rejects the ones found in exclude_light, rejects any whose state is unavailable or off, extracts just the entity_id, converts the result to a list, then converts that to comma-separated string.

If the length of the resulting string is greater than zero it reports the string otherwise it reports none which is a valid way of indicating “no entities”.

1 Like

Thanks, that works.