Make "scripts" as toggle "switch"

Feature

  • I have 2 script session for “Theater mode on” and “off”. In the script is many steps.
  • If I add this 2 scripts in homekit or front-end, it shows 2 buttons.
    If you had “delay” in you script, the UI will show a toggle button instead of “execute”. In homekit, it alsways display as switch.
  • When you press it, the toggle will shows “on” during the script runs, but when the script finish, the button state turns “off”. The status can not keep.
  • My target is make the “Theater Mode” as single toggle button.
  • I’ve tried some other method, but a bit hard to understand. I found a method that easy understanding.
  • The main part of the method is create a fake switch as a listener, then when you toggle it, run a automation contain you script.
    In front-end, just need to display the fake switch button, and it can keep status.
  • Hope it to be helpful.

Script

  • In script, you need do nothing special, just add you functions as normal.
theater_mode_on:
  alias: 'ON'
  sequence:
    # 放下幕布
    - service: switch.turn_on
      data:
        entity_id: switch.screen
    - delay: 00:10:00
    # 打开投影仪
    - service: switch.turn_on
      data:
        entity_id: switch.projector_power
    - delay: 00:00:10
    # 关灯
    - service: switch.turn_off
      data:
        entity_id: group.light

theater_mode_off:
  alias: 'OFF'
  sequence:
    # 收起幕布
    - service: switch.turn_off
      data:
        entity_id: switch.screen
    - delay: 00:00:01
    # 关闭投影仪
    - service: switch.turn_off
      data:
        entity_id: switch.projector_power
    - delay: 00:00:03
    - service: switch.turn_off
      data:
        entity_id: switch.projector_power
    # 开灯
    - service: switch.turn_on
      data:
        entity_id: switch.light_2
    - delay: 00:00:01

Create fake switch

  • Create a fake switch as listener.
- platform: command_line
  switches:
    # theater mode ==============================
    theater_mode:
      friendly_name: Theater
      command_on: ''
      command_off: ''

Automations

  • Use automation to hook the switch status, and run scripts.
- id: 'theater_mode_on'
  alias: Theater mode ON
  description: 剧院模式开启
  trigger:
  - entity_id: switch.theater_mode
    platform: state
    from: 'off'
    to: 'on'
  condition: []
  action:
  - service: script.theater_mode_on
- id: 'theater_mode_off'
  alias: Theater mode OFF
  description: 剧院模式关闭
  trigger:
  - entity_id: switch.theater_mode
    platform: state
    from: 'on'
    to: 'off'
  condition: []
  action:
  - service: script.theater_mode_off

Finally, add to homekit.

filter:
  include_entities:
    # - script.theater_mode_on
    # - script.theater_mode_off
    - switch.theater_mode

  • This method is easier to understand for me.
  • But it’s not perfect, because there would be more code in automations. In other method, maybe template switch is enough, but I do not really understand it. (I’m not familiar with hass)
  • There are also some interesting useage, such as you can create a button called open aircon, then write some automation with conditions like temperature range, then control the temperature of aircon.
  • I’m new here, so I do not know how to write a “if…elif…” or “while…case…” in hass. Maybe my method looks fool, please tell me some better, I will be happy to learn.
  • PS: automation is still not good enough for me. For example, I back home, I wish some switch turn on, and in conditional by sun to toggle lights. I have to split the code in 2 automation, because the conditions work on all actions, it looks duplicate in most part. Is that some elegant way? Please tell me.
1 Like

Your first example should be in a separate automation.

As far as your second question, it can be consolidated using the trigger state for a service template.

- id: 'theater_mode'
  alias: Theater mode
  trigger:
  - entity_id: switch.theater_mode
    platform: state
  condition: []
  action:
  - service_template: >
      script.theater_mode_o{% if trigger.to_state == 'on' %}n{% else %}ff{% endif %}

More info:

1 Like

Isn’t this a better case for a template switch?

1 Like

Very thanks for your sample, I understood the “template” part now.
I do not understood where the “trigger” came and how the “{%%}” works before, but your sample is very clear.

And back to the conditions part, if there is a numeric_state, or some complicate case, like:

# python
# case 1: multi case
if sensor.weather_temperature < 15:
    action(service=switch.turn_on, entity_id=switch.aircon_heating_30)
elif sensor.weather_temperature > 30:
    action(service=switch.turn_on, entity_id=switch.aircon_cooling_25)
else:
    action(service=switch.turn_on, entity_id=switch.aircon_fan)

# case 2: some func out of condition
# when I back home
action(service=script.open_amplifier_and_play_music)
if sun.sun == 'below_horizon':
    action(service=switch.turn_on, entity_id=switch.lights_all)

Can you show me some sample please?

And outside of my codes, there is a on/off trigger, this time, conditions is not only tigger.
When turn on, get the temperate as param and returns aircon status, heating or cooling.
And when trun off, make the aircon off.
If write all the codes in one automation, will it looks mess? Is that anyway to make it readable?

To simplify and show what @anon43302295 is suggesting. You can use an input_boolean and use that on the frontend to trigger the template switch. Assuming that an input boolean named theater_mode is defined:

# Example configuration.yaml entry

input_boolean:
  theater_mode:

switch:
  - platform: template
    switches:
      theater_mode:
        value_template: "{{ is_state('input_boolean.theater_mode', 'on') }}"
        turn_on:
          service: script.theater_mode_on
        turn_off:
          service: script.theater_mode_off

Info:

1 Like

Simpler is always better.

OK, is it means use a “input_boolean” instead of my “fack_switch” to record the status, then switch template works. And finally, put the template switch to front page.
There is many new thing to me, I need some time to try it. And a lot of thanks.

Haven’t used the template switch, but I would think the input_boolean would be on the frontend to be controlled and leave the switch in the background.

I’ve tried your code, there’s some problem.

I added both of switch and input boolean to front.
If I toggle input_boolean, the switch states will change, but do not run the service.
And if I toggle switch, the service works, but after script running, the states of switch will back to the input_boolean’s.

I think that means the switch need to add some command to change the state of input_boolean.

Found another example, and you’re right.

switch:
  - platform: template
    switches:
      theater_mode:
        value_template: "{{ is_state('input_boolean.theater_mode', 'on') }}"
        turn_on:
          - service: input_boolean.turn_on
            entity_id: input_boolean.theater_mode
          - service: script.theater_mode_on
        turn_off:
          - service: input_boolean.turn_off
            entity_id: input_boolean.theater_mode
          - service: script.theater_mode_off

I don’t know where the idea of an input boolean came from, just use the state of the screen to define whether theater mode is on.

switch:
  - platform: template
    switches:
      theater_mode:
        friendly_name: Theater mode 
        value_template: "{{ is_state('switch.screen', 'on') }}"
        turn_on:
          service: script.theater_mode_on
        turn_off:
          service: script.theater_mode_off
2 Likes

I’ve tried your code, and hide others.
Changed a part of switch.screen to switch.theater_mode, as it self.

But after script runs, the status of switch will back to “OFF”.
I don’t know what cause it, maybe the run time of value_template.

If I check the status of “screen”(I do really have a screen), it maybe works.
In that situation, I think maybe the screen play the role of “status recoder”, as input boolean.

I’ve tried, “screen” works.

In this case “screen” is a good “status recoder”, but other people maybe confuse what is the “screen”.
It’s looks simple and clear in “theater mode”, what script contains toggle “screen”.

Add a input_boolean as “status recoder” maybe suitable for more case.
Although it will be a bit more code.

I’ve mark your answer in #11 as solution, and can you please edit and add

# Example configuration.yaml entry
input_boolean:
  theater_mode:

as you write in previous answer, to make the answer completely.
It will be more helpful for the rookies like me.

Sorry, I didn’t read your comments carefully, and just pay attention on the codes. Because of my native language is not English. And I hurry to explain what I realized, that’s my mistake.

I’ve read your comment again, you have pointed out the reason, and absolutely you are right. Very thanks for your answer, and ignore my rude please.

1 Like