Command_line switch not evaluating correct state

Hi all I’ve created a command line sensor and command line switch that operate independently. The sensor pings my docker host to return the names of the containers running. This works. The switch command_on starts all docker containers while command_off will stop all unnecessary containers that I don’t want running all the time. These both work. The issue, the value_template which should render the state of the switch is not working for some reason.

Below I’ve tested this with a binary sensor using the same value template as the command line switch. The binary switch works as expected, rendering true/on when the output of sensor.dockerps has all containers, not just the 4 I want on all the time. When using the same value_template for the command line switch says it is off. Me thinks this is an issue with my command line structure or setup, or maybe I need to go in a different direction but everything I’ve read makes me think it should work. Thanks for the help!

command_line:
  - sensor:
      name: DockerPS
      command: ssh -i /config/.ssh/scale -o StrictHostKeyChecking=no [email protected] "/mnt/zebra/jailmaker/jlmkr.py exec docker docker ps --format '{{ '{{' }} .Names {{ '}}' }}'"
      scan_interval: 10
  - switch:
      name: app group
      unique_id: app_group
      command_on: ssh -i /config/.ssh/scale -o StrictHostKeyChecking=no [email protected] "/mnt/zebra/jailmaker/jlmkr.py exec docker docker compose -f /home/config/docker-compose.yml up -d"
      command_off: ssh -i /config/.ssh/scale -o StrictHostKeyChecking=no [email protected] "/mnt/zebra/jailmaker/jlmkr.py exec docker docker stop appgroup"
      value_template: |
        {{not is_state('sensor.dockerps', 'homeassistant
        gluetun
        plex
        heimdall') }}

binary_sensor:
  - platform: template
    sensors:
      testitall:
        value_template: |
          {{not is_state('sensor.dockerps', 'homeassistant
          gluetun
          plex
          heimdall') }}

What is the state of the sensor supposed to be? Name of containers separated by linebreaks? Don’t think you can quite compare the strings with linebreaks that way due to how whitespace might be condensed.

I would start by substituting the linebreaks in the code for \n, or better yet a list that you join with \n as the separator.

['homeassistant', 'gluetun', 'plex', 'heimdall'].join('\n')

But ideally you probably should not be comparing exact strings, as the containers may appear in a different order?

In my research I looked into https://yaml-multiline.info/ and found that you could use the pipe | to take line breaks and not care about spaces in the yaml file. You bring up a really good point about container order, I’ll have to look into it. The question though does still remain why does the binary sensor report true when the command line switch report false?

That I cannot help with as I’ve not had to use a command_line sensor yet.

As for the issue of container ordering, something like this ought to do it:

{{ [states('sensor.dockerps').split('\n')]
| select('contains', 'homeassistant')
| select('contains', 'gluetun')
| select('contains', 'plex')
| select('contains', 'heimdall')
| list | count > 0 }}
1 Like

Thanks for the solve on removing container order, another problem arose from that which I’ll get into below. The same issue from my original post is occurring with your new format though, if anyone has an idea what I’m doing wrong please let me know.

Your fix to container ordering makes it so that there are false positives meaning when I have just those 4 running, it renders true, but when I have all of the app group running (which include those original 4 containers), it also renders true. To fix this I just search for one container name (not part of the original four) that would show up if I run the full stack. Your solve works wonderfully because where ever the codeserver container gets placed on the list, the template correctly identifies the full stack is running. I tried playing with the bottom list | count > 0 part but I don’t understand the code to know if I should remove it so I kept it. Thanks again for your help, amazing.

If anyone has insight why the binary sensor returns true where the command line switch value template returns off (false), I would really appreciate it!

command_line:
  - sensor:
      name: DockerPS
      command: ssh -i /config/.ssh/scale -o StrictHostKeyChecking=no [email protected] "/mnt/zebra/jailmaker/jlmkr.py exec docker docker ps --format '{{ '{{' }} .Names {{ '}}' }}'"
      scan_interval: 10
  - switch:
      name: app group
      unique_id: app_group
      command_on: ssh -i /config/.ssh/scale -o StrictHostKeyChecking=no [email protected] "/mnt/zebra/jailmaker/jlmkr.py exec docker docker compose -f /home/config/docker-compose.yml up -d"
      command_off: ssh -i /config/.ssh/scale -o StrictHostKeyChecking=no [email protected] "/mnt/zebra/jailmaker/jlmkr.py exec docker docker stop appgroup"
      value_template: |
        {{ [states('sensor.dockerps').split('\n')]
        | select('contains', 'codeserver')
        | list | count > 0 }}

binary_sensor:
  - platform: template
    sensors:
      testitall:
        value_template: |
          {{ [states('sensor.dockerps').split('\n')]
          | select('contains', 'codeserver')
          | list | count > 0 }}

Ahh, yeah. The problem is that contains does not seem to support a list as an argument, or rather if you supply a list it’ll only look for values in the filtered object which is an exact match of the entire list rather than any of the list’s individual contents…

But we should be able to reverse the search and use the in filter. I assume two containers cannot have the exact same name, in which case this would get much trickier.

{{ ['homeassistant', 'gluetun', 'plex', 'heimdall']
| select('in', states('sensor.dockerps').split('\n'))
| list | count == 4 }}

hello, thanks again and just FYI the newest code still reports false positives. So you can see, I have the yaml for two test binary sensors with a screenshot of the sensor states and all containers running currently. binary_sensor.testonly4 should report off.

binary_sensor:
  - platform: template
    sensors:
      testitall:
        value_template: |
          {{ [states('sensor.dockerps').split('\n')]
          | select('contains', 'codeserver')
          | list | count > 0 }}
      testonly4:
        value_template: |
          {{ ['homeassistant', 'gluetun', 'plex', 'heimdall']
          | select('in', states('sensor.dockerps').split('\n'))
          | list | count == 4 }}

states

The change I made included in the testitall sensor above works expectedly so I’ll keep it as is.

I’m going to leave this thread open, hopefully someone can help me with the command line switch value_template.