Command line sensor: please validate template + no update

I want to check an Internet speed on a remote client in my LAN.
The client is a Raspberry Pi.
Here is an output of speedtest-cli:

ssh root@RPI_ADDRESS '/storage/utils/speedtest-cli'
Retrieving speedtest.net configuration...
Testing from Rostelecom (213.24.126.144)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by Rostelecom (Moscow) [0.15 km]: 8.639 ms
Testing download speed...............................................................................
.Download: 93.14 Mbit/s
Testing upload speed................................................................................................
Upload: 93.71 Mbit/s

I am using these sensors:

  - platform: command_line
    name: "Speedtest (remote): download"
    command: "ssh root@RPI_ADDRESS '/storage/utils/speedtest-cli'"
    unit_of_measurement: "Mbit/s"
    value_template: '{{ value.split("Download: ")[1].split(" Mbit")[0]}}'
    scan_interval: 3600

  - platform: command_line
    name: "Speedtest (remote): upload"
    command: "ssh root@RPI_ADDRESS '/storage/utils/speedtest-cli'"
    unit_of_measurement: "Mbit/s"
    value_template: '{{ value.split("Upload: ")[1].split(" Mbit")[0]}}'
    scan_interval: 3600

  - platform: command_line
    name: "Speedtest (remote): ping"
    command: "ssh root@RPI_ADDRESS '/storage/utils/speedtest-cli'"
    unit_of_measurement: "ms"
    value_template: '{{ value.split("]: ")[1].split(" ms")[0]}}'
    scan_interval: 3600

To manually update some sensor I am using a service “homeassistant.update_entity” with “entity_id: sensor.speedtest_remote_download”.
And the sensor is not set (((

Please validate my config.

Update:
Checked in “Developer Tools -> Template”, the values are parsed properly:

{% set value = "Retrieving speedtest.net configuration...
Testing from Rostelecom (213.24.135.44)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by Rostelecom (Moscow) [0.15 km]: 8.558 ms
Testing download speed................................................................................
Download: 90.86 Mbit/s
Testing upload speed................................................................................................
Upload: 93.47 Mbit/s
"
%}
value_template: '{{ (value.split("Download: ")[1].split(" Mbit")[0])|float|round(2) }}'
value_template: '{{ value.split("Upload: ")[1].split(" Mbit")[0]}}'
value_template: '{{ value.split("]: ")[1].split(" ms")[0]}}'
value_template: '90.86'
value_template: '93.47'
value_template: '8.558'

Just added “|float|round(2)” for the 1st sensor.
But still the sensors cannot be updated:

So here 2 questions:

  1. Why the sensors cannot be read/updated?
  2. How to read ALL three values with ONE command call?

Do you have any errors in the log? Do you need to be root in the remote pi to execute the command? Did setup SSH keys and copy the public SSH keys to the remote Pi for passwordless login?

Yes, this command works fine if run on the current RPi (with HA installed) to remote RPi:

ssh root@RPI_ADDRESS '/storage/utils/speedtest-cli'

The command gives the output which was shown above.

There is only one account on the remote RPi, it is “root”.

You are right, there are errors in the log:

Command failed: ssh root@RPI_ADDRESS '/storage/utils/speedtest-cli'
5:39:48 PM – command_line (ERROR) - message first occurred at 4:20:37 PM and shows up 7 times

Seems that something prevents executing the command by HA, but this command can be run from command line…

How are you running Home Assistant? Venv? Core? Supervised? If you run it in any install that uses docker, did you mount the private key to the docker container?

If so, change your command to this and try again:

"ssh -i /root/.ssh/id_rsa -o 'StrictHostKeyChecking=no' root@RPI_ADDRESS '/storage/utils/speedtest-cli'"

where /root/.ssh/id_rsa is the location of the private SSH key INSIDE the docker container.

Mmm, I do not know how to mount it((.
Thank you very much for a hint, gonna read about it.

Update:
Meanwhile I made some changes:

  1. Changed to command line to “run speedtest locally” (for testing purpose).
    Copied speedtest-cli to the HA “config” directory.

  2. Provided gathering the “Download”, “Upload” & “Ping” values within ONE call:
    a) There is the main sensor “sensor.speedtest_remote” containing preformatted text value (originally the command’s output):

Rostelecom (XXX.XXX.XXX.XXX).Rostelecom (Moscow) [0.15 km]: 8.558 ms.Download: 90.86 Mbit/s.Upload: 93.47 Mbit/s 

b) There are 3 sensors which are extracted from the preformatted output.

  - platform: command_line
    name: "Speedtest (remote)"
    command: "/config/speedtest-cli"
    value_template: "{% set value1 = value.replace('\n','').split('Testing from ')[1] -%}
                     {%- set value2 = value1.replace('Retrieving speedtest.net server list...Selecting best server based on ping...Hosted by ','') -%}
                     {%- set value3 = value2.replace('Testing download speed...','').replace('Testing upload speed...','').replace('..','') -%}
                     {{ value3 }}"
    command_timeout: 60
    scan_interval: 3600

  - platform: template
    sensors:
      speedtest_remote_download:
        friendly_name: "Speedtest (remote): download"
        unit_of_measurement: "Mbit/s"
        icon_template: 'mdi:download-network'
        value_template: "{% if states('sensor.speedtest_remote') -%}
                         {{ (states('sensor.speedtest_remote').split('Download: ')[1].split(' Mbit')[0])|float|round(3) }}
                         {%- else -%}
                         {{ 0|float }}
                         {%- endif %}"

      speedtest_remote_upload:
        friendly_name: "Speedtest (remote): upload"
        unit_of_measurement: "Mbit/s"
        icon_template: 'mdi:upload-network'
        value_template: "{% if states('sensor.speedtest_remote') -%}
                         {{ (states('sensor.speedtest_remote').split('Upload: ')[1].split(' Mbit')[0])|float|round(3) }}
                         {%- else -%}
                         {{ 0|float }}
                         {%- endif %}"

      speedtest_remote_ping:
        friendly_name: "Speedtest (remote): ping"
        unit_of_measurement: "ms"
        icon_template: 'mdi:timer'
        value_template: "{% if states('sensor.speedtest_remote') -%}
                         {{ (states('sensor.speedtest_remote').split(']: ')[1].split(' ms')[0])|float|round(3) }}
                         {%- else -%}
                         {{ 0|float }}
                         {%- endif %}"

So far it works.
Next step - change the command to “ssh on remote RPi”.

Mount it as a volume to the home assistant docker container.

Here the example from my config:

volumes:
  - /etc/localtime:/etc/localtime:ro
  - /var/run/docker.sock:/var/run/docker.sock
  - ./home-assistant:/config
  - /home/burningstone/.ssh:/root/.ssh
1 Like

Good day!
I used your good advice to add a volume.

  1. Restarted the docker container:
docker run -d --name="HA" -v /storage/HA:/config -v /etc/localtime:/etc/localtime:ro  -v /storage/.ssh:/root/.ssh --restart unless-stopped --net=host homeassistant/home-assistant:stable
  1. In configuration.yaml:
  - platform: command_line
    name: "Speedtest (remote)"
    command: "ssh root@RPI_ADDRESS '/storage/utils/speedtest-cli'"
    value_template: "{% set value1 = value.replace('\n','').split('Testing from ')[1] -%}
                     {%- set value2 = value1.replace('Retrieving speedtest.net server list...Selecting best server based on ping...Hosted by ','') -%}
                     {%- set value3 = value2.replace('Testing download speed...','').replace('Testing upload speed...','').replace('..','') -%}
                     {{ value3 }}"
    command_timeout: 60
    scan_interval: 3600

It works!
My gratitude to you for help here!

1 Like