Command Line Switch state from command_on return code

In command line switches, is it possible to use the return code from command_on and command_off to feed the state back rather than using a dedicated command_state?

My application is a LAN relay board which struggles with closely-spaced commands, therefore i’d like to avoid polling it with a command_state.

On the other hand, the board gives me a feedback when the on or off commands are successful, making the command_state polling redundant.

I tried as a workaround to push the state of the relay via the REST API as part of the command_on/off script, but it doesn’t seem to work (maybe because it’s executed before the script returns).

"""
Command state
arg 1 relay number
arg 2 relay state (on/off)
"""

import requests
import sys
import socket
import json

RELAY_ADDR = ("192.168.0.57", 2000)
HASS_URL = "http://localhost:8123/api/states/"
HASS_KEY = "XXXX"

relay_number = sys.argv[1]
relay_state = sys.argv[2]

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect(RELAY_ADDR)
    s.sendall(('{"relay' + relay_number + '":"' + relay_state + '"}').encode())

# relay_state = states_dict[f"relay{relay}"]
payload = '{"state":"' + relay_state + '"}'
headers = {
"Authorization": f"Bearer {HASS_KEY}",
"content-type": "application/json",
}
update = requests.post(HASS_URL + f"switch.rly8_01_0{relay_number}_relay", headers=headers, data=payload)
- platform: command_line
  switches:
    rly8_01_01_relay:
      command_on: python3 /config/py-scripts/relay-command.py 1 on
      command_off: python3 /config/py-scripts/relay-command.py 1 off

Another ugly workaround that works is to poll the sensors every N seconds and push the state via the REST API, but the state update can be late by as much as N seconds…

Any ideas?

P.S.
The script above doesn’t really parse the response from the relay YET, but it shouldn’t matter to the point made here.

Yes. If command_state is not defined, then the state of the switch will be updated after command_on or command_off are run based on the return code. I.e., if the command returns zero (i.e., success), then the state will be updated (to on after command_on, or to off after command_off), but if the command returns a non-zero code (i.e., failure), then the state will not be updated.

Thanks Phil,

I’ve tried that, but whenever i trigger a switch this way the attribute assumed_state is set to true, which changes the display mode from the “slider” to the “thunders” as shown in the picture.

image

Yes, that’s the way it works, so that’s to be expected. The state of the switch should still show whether it’s on or off, or at least, what it assumes the state to be based on whether or not the on/off command worked.

You’re back!

1 Like

Thanks Phil,

I will have to try write something up myself then.

In an ideal world I would expect the possibility/option of using the return codes (or stdout) in a meaningful way, so that if the “on” command actually obtains a feedback, that can be taken as true rather than “assumed”.

Also, I find odd that even if I set the assumed_state as false in the configuration, this is overridden by the above. Am i doing something wrong here? Is there a way to force the switch to show the slider at all times? To be honest that’s really the only thing that bothers me

Hi
I used RLY8 switch and use simple configuration like below with “command_state”. This is example for relay number 1. For others you have to change index in value_template.

switch:
  - platform: command_line
    switches:
        rly8_01_01_relay:
            command_on: echo -n '{"relay1":"on"}' | nc 192.168.1.23 2000
            command_off: echo -n '{"relay1":"off"}' | nc 192.168.1.23 2000
            command_state: echo -n '{"get":"relayStatus"}' | nc 192.168.1.23 2000
            value_template: '{{value.split(",")[0].split("\"")[3] == "on" }}'
            friendly_name: 'Gabinet'