Here is my script:
#!/bin/bash
# Only edit the following setup lines with correct login information
# Mosquitto Broker Details
mqttuser=*****
mqttpassword=*****
mqttbroker=x.x.x.x
mqttport=1883
# DO NOT ALTER ANYTHING BELOW THIS LINE
speedtest_result=$(sudo speedtest --format=json --accept-license)
echo "**********************************************************************************************"
echo $speedtest_result
download=$(echo "$speedtest_result" | jq '.download."bandwidth"')
upload=$(echo "$speedtest_result" | jq '.upload."bandwidth"')
ping_server=$(echo "$speedtest_result" | jq '.ping."latency"')
url_test=$(echo "$speedtest_result" | jq '.result."url"' | tr -d \")
time_run=$(echo "$speedtest_result" | jq '.timestamp' | tr -d \")
echo $download $upload $ping_server $time_run
echo $url_test
download=$(printf %.2f "$((10**3 * $download*8/10**6))e-3")
upload=$(printf %.2f "$((10**3 * $upload*8/10**6))e-3")
ping_server=$(printf %.3f "$ping_server")
echo $download $upload $ping_server $time_run
echo $url_test
speedteststring='{"state":"'"$url_test"'","attributes":{"time_run":"'"$time_run"'","ping":"'"$ping_server"'","download":"'"$download"'","upload":"'"$upload"'"}}'
echo $speedteststring
echo "**********************************************************************************************"
# Publish to MQTT Broker
mosquitto_pub -h $mqttbroker -p $mqttport -u "$mqttuser" -P "$mqttpassword" -t speedtestresult -m "$speedteststring" -r
Enter your creds at the top for the mqtt addon and ip address.
Make sure the script is executable
You first need to install speedtest.
Use these commands
sudo apt-get install gnupg1 apt-transport-https dirmngr
export INSTALL_KEY=379CE192D401AB61
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys $INSTALL_KEY
echo "deb https://ookla.bintray.com/debian generic main" | sudo tee /etc/apt/sources.list.d/speedtest.list
sudo apt-get update
Straight from Ookla site.
The owner of the script is my local debian user.
I run the script via a crontab:
sudo crontab -e
and add these lines to it:
29 * * * * /home/david/speedtest_result.sh 2>&1 >> /var/log/speedtest.log
58 * * * * /home/david/speedtest_result.sh 2>&1 >> /var/log/speedtest.log
0 0 * * * rm /var/log/speedtest.log 2>&1 > /dev/null
so it runs every 30 mins at 29 and 58 past the hour and writes to /var/log/speedtest.log so you can view the current day… it deletes the log at midnight
Then in HA I add MQTT sensors:
- platform: mqtt
name: "Speedtest Result"
state_topic: "speedtestresult"
value_template: "{{ value_json.state }}"
json_attributes_topic: "speedtestresult"
json_attributes_template: "{{ value_json.attributes | tojson }}"
- platform: average
name: "Speedtest Download Average"
entities:
- sensor.speedtest_download
start: '{{ 0 }}'
end: '{{ now() }}'
- platform: average
name: "Speedtest Upload Average"
entities:
- sensor.speedtest_upload
start: '{{ 0 }}'
end: '{{ now() }}'
# Speedtest and Up Time
- platform: template
sensors:
# Speedtest Results
speedtest_download:
value_template: '{{ states.sensor.speedtest_result.attributes["download"] }}'
unique_id: speeddown
speedtest_upload:
value_template: '{{ states.sensor.speedtest_result.attributes["upload"] }}'
unique_id: speedup
speedtest_ping:
value_template: '{{ states.sensor.speedtest_result.attributes["ping"] }}'
unique_id: speedping
speedtest_lastrun:
value_template: '{{ states.sensor.speedtest_result.attributes["time_run"] }}'
unique_id: speedtimerun
homeassistant:
customize:
package.node_anchors:
common: &common
package: "sysmonitor"
sensor.speedtest_download_average:
icon: mdi:speedometer
<<: *common
sensor.speedtest_upload_average:
icon: mdi:speedometer
<<: *common
sensor.speedtest_download:
friendly_name: Speedtest Download
icon: mdi:speedometer
unit_of_measurement: Mbit/s
<<: *common
sensor.speedtest_upload:
friendly_name: Speedtest Upload
icon: mdi:speedometer
unit_of_measurement: Mbit/s
<<: *common
sensor.speedtest_ping:
friendly_name: Speedtest Ping
icon: mdi:speedometer
unit_of_measurement: ms
<<: *common
sensor.speedtest_result:
friendly_name: Speedtest Result
icon: mdi:speedometer
<<: *common
sensor.speedtest_lastrun:
friendly_name: Speedtest Last Run
icon: mdi:clock
device_class: timestamp
<<: *common
I use a custom average component in HACS to give me the average
Then in Lovelace:
- type: vertical-stack
cards:
- type: entities
title: Internet
show_header_toggle: false
entities:
- entity: sensor.speedtest_download
secondary_info: last-updated
- entity: sensor.speedtest_download_average
secondary_info: last-updated
- entity: sensor.speedtest_upload
secondary_info: last-updated
- entity: sensor.speedtest_upload_average
secondary_info: last-updated
- entity: sensor.speedtest_ping
secondary_info: last-updated
- entity: sensor.speedtest_lastrun
format: relative
- sensor.fritz_netmonitor
- type: horizontal-stack
cards:
- type: gauge
name: Mbit/s Download
unit: ' '
min: 0
max: 50
severity:
red: 0
yellow: 30
green: 40
entity: sensor.speedtest_download
- type: gauge
name: Mbit/s Upload
unit: ' '
min: 0
max: 20
severity:
red: 0
yellow: 11
green: 15
entity: sensor.speedtest_upload
- type: custom:apexcharts-card
graph_span: 24h
header:
show: true
title: Speedtest
apex_config:
responsive:
- breakpoint: 765
options:
chart:
height: 500px
- breakpoint: 1025
options:
chart:
height: 400px
- breakpoint: 10000
options:
chart:
height: auto
stroke:
curve: smooth
chart:
zoom:
enabled: true
toolbar:
show: true
tools:
zoom: true
zoomin: true
zoomout: true
pan: true
reset: true
plotOptions:
bar:
columnWidth: '50%'
legend:
showForSingleSeries: true
series:
- entity: sensor.speedtest_download
show:
extremas: true
stroke_width: 3
fill_raw: last
name: Download
type: line
group_by:
func: raw
duration: 30min
- entity: sensor.speedtest_upload
show:
extremas: true
stroke_width: 3
fill_raw: last
name: Upload
type: line
group_by:
func: raw
duration: 30min
- entity: sensor.speedtest_ping
show:
extremas: true
stroke_width: 3
fill_raw: last
name: Ping
type: column
group_by:
func: raw
duration: 30min
Note the sensors etc are in a package /packages/sysmonitor.yaml
Note also it is possible to directly write the sensor from a bash script but I haven’t tried that and also the mqtt way with a retained message means it is always available on restarts instead of waiting up to 30 mins… I also use mqtt for other things so it was a no brainer to use that.