How can I change the state of a template sensor via the UI (not de DevTools!)

Hi all,

I’m not a HA guru, or even a YAML or Python one, but I do know how to troubleshoot. Sometimes they call me a pitbull because I cannot let go easily if I encounter a problem with something which seem to be trivial. So, here we go:

I have a parcel box. You can put in a parcel through the drop box, and you can take it out again through a door (which is locked with a key). I added sensors (switch1 and switch2 connected to an ESP01 running Tasmota) for both the drop box and the door and created a template sensor which turns ‘on’ when the drop box is used, and is turned ‘off’ when the door is opened.

This works fine, I added my configuration below. Note that I split up my yaml files over multiple files/folders, so in my configuration.yaml I have:

# Secret trick: load integration multiple times! the word 'split' is free to choose as long as it is unique
automation split: !include_dir_merge_list automations/
binary_sensor: !include_dir_merge_list binary_sensors/
light: !include_dir_merge_list lights/
mqtt: !include_dir_merge_named mqtt/
notify: !include_dir_merge_list notifiers/
rest_command: !include_dir_merge_named rest_commands/
sensor: !include_dir_merge_list sensors/
shell_command: !include_dir_merge_named shell_commands/
switch: !include_dir_merge_list switches/
template: !include_dir_merge_list templates/
tts: !include_dir_merge_list tts/
utility_meter: !include_dir_merge_named utility_meters/

Don’t forget to restart HA to make changes effective!

My sensor is in config/templates/parcelbox.yaml:

- binary_sensor:
    - unique_id: parcelbox_status
      state: >
        {%- set box = states('binary_sensor.template_parcelbox_status') -%}
        {%- if is_state('binary_sensor.esp01_03_switch1', 'off') -%}
        {%- set box = "on" -%}
        {%- endif -%}
        {%- if is_state('binary_sensor.esp01_03_switch2', 'off') -%}
        {%- set box = "off" -%}
        {%- endif -%}
        {{- box -}}
  trigger:
    - platform: state
      entity_id: binary_sensor.esp01_03_switch1
    - platform: state
      entity_id: binary_sensor.esp01_03_switch2

So far, so good (my switches are ‘off’ when the drop box or door are opened).

However, When someone opens the drop box the template-sensor gets ‘on’. There are then two ways to get it ‘off’ again:

  1. Open the door
  2. In DevTools → States, change the state of this sensor to ‘off’

I would like a third option: Press a button in the UI to switch it ‘off’ (or toggle it)

There are some services like switch.toggle, light.toggle and even a generic homeassistant.toggle, but they cannot toggle a template sensor. I also tried the ‘turn off’ versions I could find, but none of them work for a template sensor neither.

I also investigated the possibilities of events, but as they seem capable of setting the state, I cannot get it to work from the action within a button card

I do have a solution which feels like a U-turn: You can change a state through the API!

My solution is as follows (I tried to make it as generic as possible, so I can re-use it in other places):

First I need an API key, which can be generated from your personal settings page. I stored that in secrets.yaml. BEWARE: You need the keyword 'Bearer ’ in front of it!

My secrets.yaml line looks like (redacted):

local-apikey: Bearer eyJhbGciOiJIUzI1NiIsIawew6nR5cCI6Ikp....

Next I created a ‘my_set_state.yaml’ in the ‘rest_commands/’ folder (remember I split up my config files):

my_set_state:
  url: "http://localhost:8123/api/states/{{ entity_id }}"
  method: POST
  headers:
    authorization: !secret local-apikey
    accept: "application/json, text/html"
    user-agent: "Mozilla/5.0"
  content_type: "application/json; charset=utf-8"
  payload: "{{ payload | tojson }}"

The ‘tojson’ filter is crucial, otherwise this will generate strings with ‘single quotes’, which are not accepted by json (only “double quotes” are valid).

If you want it to be even more universal, you can put more variables here (e.g. {{ url }} )

WARNING: There are NO safety checks here! Use at your own risk!

The final step is to call this command from a button. In this example I use a HACS custom-button-card, because this allows me to implement a toggle functionality. If you just hardcode ‘state: off’ at the end of the configuration, then a standard button card will work as well.

My button card looks like:

type: custom:button-card
entity: binary_sensor.template_parcelbox_status
icon: mdi:package
state:
  - value: 'off'
    color: rgb(0,0,160)
  - value: 'on'
    color: rgb(0,160,0)
show_name: false
show_label: true
label: Parcel box
tap_action:
  action: call-service
  service: rest_command.my_set_state
  service_data:
    entity_id: '[[[ return entity.entity_id ]]]'
    payload:
      state: |
        [[[
             if (entity.state == 'on') return 'off';
             if (entity.state == 'off') return 'on';
             else return 'unknown';
        ]]]

One last note: In the payload the entity_id to be changed is returned. I use a local variable to obtain the id of the entity monitored in this button (in the “entity:” field, in this case ‘binary_sensor.template_parcelbox_status’), but you can put any valid entity_id here.

I used the DevTools to test the various possibilities, and even configured a local Apache server with ‘dumpio’ to send the API calls to, just to see what was sent and what needed to be sent. It took me quite some hours to figure this out, so I hope someone else can save some time to achieve a similar goal.

But I truly believe there is another, cleaner way of doing this (without this U-turn), as it is also possible through the DevTools. How does that work, anyway?

Any thoughts?

Regards,

Marcel

I would probably just make a binary helper for the parcel box and then set up automations to set the helper to on or off and make a button that does the same.

1 Like

The limitation is the button action… they can’t raise events themselves but they can call scripts. For things like this I set up a script that raises custom events. Then you can have the events consumed as a trigger for your sensor.

alias: Manual Events
fields:
 type:
   name: Type
   description: The targetted sub-event
   required: true
   example: dashboard_button_reset_mail
sequence:
 - event: manual_events
   event_data:
     type: "{{type}}"    
mode: single
- binary_sensor:
    - unique_id: parcelbox_status
      state: >
        {%- set box = states('binary_sensor.template_parcelbox_status') -%}
        {% if trigger.platform == 'event' or ( trigger.id = 'switch_2' and 
        is_state('binary_sensor.esp01_03_switch2', 'off')) %}
          {%- set box = "off" -%}
        {%- elif is_state('binary_sensor.esp01_03_switch1', 'off') -%}
          {%- set box = "on" -%}
        {%- endif -%}
        {{- box -}}
  trigger:
    - platform: state
      entity_id: binary_sensor.esp01_03_switch1
    - platform: state
      entity_id: binary_sensor.esp01_03_switch2
      id: switch_2
    - platform: event
      event_type: manual_events
      event_data:
        type: dashboard_button_reset_mail
tap_action:
  action: call-service
  service: script.manual_events
  service_data:
    type: dashboard_button_reset_mail

Thanks, this was what I was looking for.

I changed the template a bit to obtain a toggle function, but that was not part of the question.

Also a big thank you for giving me a better understanding of events in HA

Regards,

Marcel

1 Like