Command_line state incorrect no matter what I do

Hi,

I’ve been futzing about with this for about 6 months now, read what I think is relevant posts:

and the command_line documentation

  • but i still can’t get it to work.

I have verified my code for echo’ing 0 or 1 working fine in a terminal, and even on the openssh terminal in hassio.

all i want is for state to report correctly on and off, no matter what i do it seems to either set the state to on, or off and stay on that state and not reflect what the device actually is.

to be clear, this is a old, abandoned product that i love called the moorescloud holiday, what i’ve done thus far has technically integrated it in homekit due to the bridge, so leaps and bounds, but the state is always weird.
https://twitter.com/posty/status/1469787903840514050?s=20&t=QF6eXKovQgI2dEBqCJOBqQ

the code is pretty simple, it returns a json string, but of rgb values. i’m keeping it simple at this stage and just trying to turn “on” and “off” values.

I actually asked Franck Nijhof if he’d consider developing an integration for me (paid of course!) but he wouldn’t.

So here i am, junior systems admin trying to learn this.

Anyway - here’s the code:

#test config for holiday
switch:
  - platform: command_line
    switches:
      lounge_holiday:
        command_on: "/usr/bin/curl -X PUT -d '{ \"lights\": [ \"#ffcb4d\", \"#ff884d\", \"#ff974d\", \"#ffa64d\", \"#ffb54d\",
\"#ffa64d\", \"#ff974d\", \"#ff884d\", \"#ffcb4d\", \"#ff6c4d\",
\"#ffcb4d\", \"#ff884d\",\"#ff974d\", \"#ffa64d\", \"#ffb54d\",
\"#ffa64d\",\"#ff974d\", \"#ff884d\", \"#ffcb4d\", \"#ff6c4d\",
\"#ffcb4d\", \"#ff884d\",\"#ff974d\", \"#ffa64d\", \"#ffb54d\",
\"#ffa64d\",\"#ff974d\", \"#ff884d\", \"#ffcb4d\", \"#ff6c4d\",
\"#ffcb4d\", \"#ff884d\",\"#ff974d\", \"#ffa64d\", \"#ffb54d\",
\"#ffa64d\",\"#ff974d\", \"#ff884d\", \"#ffcb4d\", \"#ff6c4d\",
\"#ffcb4d\", \"#ff884d\",\"#ff974d\", \"#ffa64d\", \"#ffb54d\",
\"#ffa64d\",\"#ff974d\", \"#ff884d\", \"#ffcb4d\", \"#ff6c4d\" ] }' http://192.168.1.204/iotas/0.1/device/moorescloud.holiday/localhost/setlights"
        command_off: "/usr/bin/curl -X PUT -d '{ \"lights\": [ \"#000000\", \"#000000\", \"#000000\", \"#000000\", \"#000000\", 
\"#000000\", \"#000000\", \"#000000\", \"#000000\", \"#000000\",
\"#000000\", \"#000000\", \"#000000\", \"#000000\", \"#000000\",
\"#000000\", \"#000000\", \"#000000\", \"#000000\", \"#000000\", 
\"#000000\", \"#000000\", \"#000000\", \"#000000\", \"#000000\",
\"#000000\", \"#000000\", \"#000000\", \"#000000\", \"#000000\",
\"#000000\", \"#000000\", \"#000000\", \"#000000\", \"#000000\",
\"#000000\", \"#000000\", \"#000000\", \"#000000\", \"#000000\",
\"#000000\", \"#000000\", \"#000000\", \"#000000\", \"#000000\",
\"#000000\", \"#000000\", \"#000000\", \"#000000\", \"#000000\" ] }' http://192.168.1.204/iotas/0.1/device/moorescloud.holiday/localhost/setlights"
        command_state: hostname="192.168.1.204"; status=$(curl --silent -X GET http://${hostname}/device/light/value); if [[ $status =~ [1-9] ]]; then echo 0; else echo 1; fi
        #value_template: '{{ value == "1" }}'

yes i turned value template off because that appeared to make it worse.

i originally was using ‘exit’ and ‘exit 1’ instead of echo’s because of my interpretation of the phrase ‘return code’ - that still worked by the way, but the other comment seems to go for echo

any help appreciated - i’d love to make a full featured integration for this, but for now on and off will suffice, but correct state is needed.

I looked at the source code,

If you are not using the value template then it is checking the return code. So your script will need to generate an error return code and that becomes the state of the switch. So in this case do not use echo use Exit 1

If you are using a value template then it is checking the output of the script. So in this case use echo “1” or output some json, do not use exit.


def _query_state(self) -> str | int | None:
        """Query for state."""
        if self._command_state:
            if self._value_template:
                return self._query_state_value(self._command_state)
            return self._query_state_code(self._command_state)
        if TYPE_CHECKING:
            return None

So with no value template it calls this method:

    def _query_state_code(self, command: str) -> bool:
        """Execute state command for return code."""
        _LOGGER.info("Running state code command: %s", command)
        return (
            call_shell_with_timeout(command, self._timeout, log_return_code=False) == 0
        )

Which then call this


def call_shell_with_timeout(
    command: str, timeout: int, *, log_return_code: bool = True
) -> int:
    """Run a shell command with a timeout.
    If log_return_code is set to False, it will not print an error if a non-zero
    return code is returned.
    """
    try:
        _LOGGER.debug("Running command: %s", command)
        subprocess.check_output(
            command, shell=True, timeout=timeout  # nosec # shell by design
        )
        return 0
    except subprocess.CalledProcessError as proc_exception:
        if log_return_code:
            _LOGGER.error("Command failed: %s", command)
        return proc_exception.returncode
    except subprocess.TimeoutExpired:
        _LOGGER.error("Timeout for command: %s", command)
        return -1
    except subprocess.SubprocessError:
        _LOGGER.error("Error trying to exec command: %s", command)
        return -1

The exit 1 should cause it to hit the CalledProcessError and return your exit code. Regardless of what you echo, if it’s exits normally it’ll return a 0

1 Like

could you provide an example of what json I should echo? because echo 1 is not doing it. it keeps reverting itself to the ‘on’ state no matter what i do. it does send the commands if i quickly toggle them though.
I’m wondering if its because i’m doing the logic within the yaml itself if its causing me issues, if i shouldn’t just put a shell file somewhere? it shouldn’t be a problem but it appears like it is.
i cycled through all 3 of these again and they still didn’t work.
for now i have just reverted and kept ‘on’ and ‘off’ and am not using states at all and letting home assistant manage it - appears to be ok.
I do have full access to the source code of the holiday (it’s largely just python), so it would be possible to add in a state api, but that’s way beyond me at the moment.

thanks for such a quick response by the way

I believe if you’re not using the value_template it should be like this with exits rather than echos.

command_state: hostname="192.168.1.204"; status=$(curl --silent -X GET http://${hostname}/device/light/value); if [[ $status =~ [1-9] ]]; then exit 0; else exit 1; fi