Change Switch state without performing action

Thanks. Python script works very well. But what is the right place to call it from? In fronted i can asign only one tap_action and this can be call-service or toogle…

type: entity-button
entity: switch.livolo_all_off
tap_action:
  action: toggle
  action: call-service
  service: python_script.state_change
  service_data:
    entity_id: switch.light_1
    state: 'off'
hold_action:
  action: more-info
show_icon: true
show_name: true

you can use it everywhere? its a service like another service?

I think you have an error in the command above. You are missing }} at the end of the json string.

After I fixed the json error I tried that method and the result is exactly as it is using the dev-tools state page. It sets the state to the opposite state but then it switches the state back to the correct true state after a few seconds.

then I tried the python script and appears to do exactly the same thing.

At least it does for entities that have a real world feedback mechanism.

It probably (maybe…) works for a stateless device but it doesn’t work for devices that have a state feedback.

Yeah, it’s possible that I copy pasted wrong, I had some variables in that string that I removed, I am using it for my 40 lights, don’t want to have 40 shell commands :wink:

Yes, it’s only for changing states, so if you actually press a button or or if you have state feedback later, it will override off course…

So my code doesn’t help?

But in your first reply, you asked for a service to just change a state for a switch, without actually doing anything like on/off, that’s what this code do?
Or do your switches have a value_template configured?
Because I have configured my lights and switches with an assumed state, you see that in the curl…

So I can turn on a light even its on…

I have finally done this. Thanks again, Fabio.

…may be useful to someone

Fronted:

cards:
  - cards:
      - entity: switch.livolo_all
        icon: 'mdi:lightbulb'
        show_name: false
        tap_action:
          action: call-service
          service: script.lights_turn_state
          service_data:
            state_copy: 'on'
        type: entity-button
      - entity: switch.livolo_all
        icon: 'mdi:lightbulb-outline'
        show_name: false
        tap_action:
          action: call-service
          service: script.lights_turn_state
          service_data:
            state_copy: 'off'
        type: entity-button
    type: horizontal-stack
  - entities:
      - entity: switch.livolo_1
      - entity: switch.livolo_2
      - entity: switch.livolo_3
      - entity: switch.livolo_4
      - entity: switch.livolo_5
      - entity: switch.livolo_6
      - entity: switch.livolo_7
    show_header_toggle: true
    title: Lights
    type: entities
type: vertical-stack

Script:
for performing all_on/all_off actions and copying states to 1-7

lights_turn_state:
  alias: On/Off all lights
  fields:
    state_copy:
      description: 'Set state for other switches'
      example: 'on'
  sequence:
  - service: python_script.state_change
    data_template:
      entity_id: 'switch.livolo_1'
      state: '{{ state_copy }}'
  - service: python_script.state_change
    data_template:
      entity_id: 'switch.livolo_2'
      state: '{{ state_copy }}'
  - service: python_script.state_change
    data_template:
      entity_id: 'switch.livolo_3'
      state: '{{ state_copy }}'
  - service: python_script.state_change
    data_template:
      entity_id: 'switch.livolo_4'
      state: '{{ state_copy }}'
  - service: python_script.state_change
    data_template:
      entity_id: 'switch.livolo_5'
      state: '{{ state_copy }}'
  - service: python_script.state_change
    data_template:
      entity_id: 'switch.livolo_6'
      state: '{{ state_copy }}'
  - service: python_script.state_change
    data_template:
      entity_id: 'switch.livolo_7'
      state: '{{ state_copy }}'
  - service_template: switch.turn_{{ state_copy }}
    entity_id: switch.livolo_all

Automation:
for copying states from 1-7 to all_on/all_off

- id: synchronize.state_switchlight
  alias: Synchronize switches
  trigger:
  - platform: state
    entity_id:
      - switch.livolo_1
      - switch.livolo_2
      - switch.livolo_3
      - switch.livolo_4
      - switch.livolo_5
      - switch.livolo_6
      - switch.livolo_7
  condition:
    condition: or
    conditions:
      - condition: template
        value_template: >
          {{ is_state(trigger.entity_id, 'on') }}
      - condition: and
        conditions:
          - condition: template
            value_template:  >
              {{ is_state(trigger.entity_id, 'off') }}
          - condition: template
            value_template:  >
              {{ is_state('switch.livolo_1', 'off') }}
          - condition: template
            value_template:  >
              {{ is_state('switch.livolo_2', 'off') }}
          - condition: template
            value_template:  >
              {{ is_state('switch.livolo_3', 'off') }}
          - condition: template
            value_template:  >
              {{ is_state('switch.livolo_4', 'off') }}
          - condition: template
            value_template:  >
              {{ is_state('switch.livolo_5', 'off') }}
          - condition: template
            value_template:  >
              {{ is_state('switch.livolo_6', 'off') }}
          - condition: template
            value_template:  >
              {{ is_state('switch.livolo_7', 'off') }}    
  action:
  - service: python_script.state_change
    data_template:
      entity_id: 'switch.livolo_all'
      state: >
        {{ states(trigger.entity_id) }}

No problel :wink:

Is there way to call service for some entities when using data_template? Something like:

- service: python_script.state_change 
  data_template: 
    entity_id:
      - 'switch.livolo_2'
      - ... 
    state: 
      - '{{ state_copy }}'
      - ...

Hmm, no idea, not using it for a data template… I just use this code , I not created it myself, just found it in the community here…

I updated the python state_change script to be able to pass several entitys at once.

now:

  - service: python_script.state_change
    data_template:
      entity_id:
        - person.one
        - person.two
      state: 'not_home'

before:

  - service: python_script.state_change
    data_template:
      entity_id: 'person.one'
      state: 'not_home'
  - service: python_script.state_change
    data_template:
      entity_id: 'person.two'
      state: 'not_home'

SCRIPT:

# EXEMPLE 1
#   - service: python_script.state_change
#     data_template:
#       entity_id: person.one, person.two
#       state: 'not_home'

# EXEMPLE 2
#   - service: python_script.state_change
#     data_template:
#       entity_id:
#         - person.one
#         - person.two
#       state: 'not_home'

# EXEMPLE 3
#   - service: python_script.state_change
#     data_template:
#       entity_id: >
#         {% set entities = state_attr('group.family_persons', 'entity_id') %}
#         {{ states.person | selectattr('entity_id', 'in', entities)
#                          | selectattr('state', 'eq', 'home')  
#                          | map(attribute='entity_id')
#                          | join(', ') }}
#       state: 'not_home'

if isinstance(data.get('entity_id'), str):
    EntityList = data.get('entity_id').split(', ')
else:
    EntityList = data.get('entity_id')
for item in EntityList:
    inputEntity = item
    if inputEntity is None:
        logger.warning("===== entity_id is required if you want to set something.")
    else:    
        inputStateObject = hass.states.get(inputEntity)
        inputState = inputStateObject.state
        inputAttributesObject = inputStateObject.attributes.copy()
    
        for item in data:
            newAttribute = data.get(item)
            logger.debug("===== item = {0}; value = {1}".format(item,newAttribute))
            if item == 'entity_id':
                continue            # already handled
            elif item == 'state':
                inputState = newAttribute
                logger.info(inputEntity + ': ' 'state' + '> ' + inputState)
            else:
                inputAttributesObject[item] = newAttribute
        hass.states.set(inputEntity, inputState, inputAttributesObject)
4 Likes

Cool, gonna copy paste for later :wink:

Hi,
I have a problem with my SwitchBot controlling my air conditioner. If somebody manually turns on the air conditioner I get out of sync since HA does not know it is operational. I would like to manually change the state of the SwitchBot entry and this script seemed to do it.

My issue is when I sense that the air conditioner is not operational and change the state of the switch in HA, it changes this state back on almost immediately.

Here is my automation:-

- alias: Set airconditioner operational off
  initial_state: true
  trigger:
  - entity_id: sensor.possible_airconditioner_operation
    from: 'True'
    platform: state
    to: 'False'
    for:
      minutes: 45
  condition:
  - condition: state
    entity_id: switch.air_conditioner
    state: 'on'
  action:
    - data:
        message: AUTOMATED CORRECTION Seems like the air conditioner is not operational HA thinks it is!
      service: notify.ios_tincan
    - service: python_script.set_statev2
      data:
        entity_id: switch.air_conditioner
        state: 'off'

As you can see here in my logs:-

configure this in your switch :

value_template: "false"

Thanks for the reply, how do I do this with a switchbot. I can’t see this as an allowable parameter and Check Configuration confirms that. - https://www.home-assistant.io/integrations/switchbot

  - platform: switchbot
    mac: 'FF:FF:FF:FF:FF:FF'
    name: 'Air Conditioner'

no idea :frowning: maybe you can create an extra template switch that controls your switch

I was miffed that the basic switch didn’t work like mqtt version which has separate mqtt command/set and state. It seems most basic “action/input” entities should support this as HA might be may be just a UI for an otherwise independent process controlled in various ways and by other UI’s. Since my code listens (via websocket api) for changes to this switch setting the switch was causing havoc looping. This script fixed all that and works great calling from via websocket api. I now have a new method for my api for changing just state just like with mqtt version. Thx!!

Well, after more investigation this script didn’t work. Changing the state (no matter in this script or not) triggers an event on the event bus which is picked up in my socket listener for that entity and causes a “double fire”. One wonders if you can disable the event bus temporarily during a state update? I saw some other posts where automations were turning off “homeassistant” then doing the switch state change then turning it back on. Only changing state of switch, no action I guess I’ll try that next.

for those who code in nodes and are interested here is my websocket api repo. It’s still a work in
progress and has no docs. https://git.kebler.net/UCOMmandIt/uci-ha.git

Gosh, I have exactly the same problem with my airco - what happens when someone triggers it manually. I’m trying to do this with an input boolean and automation in between

I think you need 3 things
Have your switchbot.airconditionner be used only for toggle. Not on/off
Create an input_boolean.airconditonner with on / off
Create another input_boolean.resetairconditonner

Then use automations 3 (!) to:

trigger: input_boolean.airconditonner change from off to on
condition “input_boolean.resetairconditonner” = off
action toggle switchbot.airconditionner

Then identical as above for " change from on to off" on the trigger

Finally automation to reset:
trigger “input_boolean.resetairconditonner” = on
no conditions
action: input_boolean.turn_off for airconditonner
delay 10 seconds
action: input_boolean.turn_off for resetairconditonner

I should have written that in code, but I am useless at writing it - it would take me half a day… :frowning:

In this case the trigger fires all the same

I have a Button Card to turn on a light (switch) via IR with a Broadlink Mini.

What I have so far is this:

  • tap: light turns on and off
  • hold: state sets to “on” without sending an IR signal
entity: switch.light_bedroom
show_icon: true
show_name: true
show_state: false
tap_action:
  action: toggle
hold_action:
  action: call-service
  service: python_script.set_statev2
  service_data:
    entity_id: switch.light_bedroom
    state: 'on'
type: button

The hold action calls the python_script.set_statev2 with the state of “on”
This works perfectly to update the state to on without sending that IR for when the physical light is on but home assistant it showing it as off.

What I’d like now it to send service_data conditionally based on the current state, something like :

...
  service_data:
    entity_id: switch.light_bedroom
    state: {{ 'off' if is_state('switch.light_bedroom','on') else 'off' }}
...

is this possible?

For anybody “newbie as I am” - here’s a write up on how to do this from scratch

In configuration.yaml add only this line

python_script:

Create a folder under “config” called “python_scripts”
It should end up like this: /config/python_scripts

Copy the script of Oligarch (on the right of the gray box, there is a copy symbol. Use that to make sure you all have the good identation, etc. You want to copy the box with “SCRIPT” in the top…

Open notepad, paste that text, and save it as “state_change.py” (and on a windows system, put the quotes around the filename otherwise you’ll end up with a .txt at the end and you don’t want that)

Restart Hassio / Home Assistant

Now you should be good to go to use it. It has created a new service you can call in automations, etc. The best place to test it out is
Developer tools > Services (tab at the top)

In there, the simple two lines of config seen below does the magic of changing the state of my switch called “switch.warmeroffice” to “off” without triggering the automation linked to that.

entity_id: switch.warmeroffice
state: 'off'

2 Likes