From f2080448e1b606d6bd41a9ed1fb8996a29a13e2b Mon Sep 17 00:00:00 2001 From: Tim Connors <1707595+spacelama@users.noreply.github.com> Date: Thu, 16 Nov 2023 05:02:19 +1100 Subject: [PATCH] Tasmota voltmeter (#1397) * added millivolts to tasmota_ to get ANALOG/Range value * allow to print_thresholds in tasmota plugin * Experimented with different graph settings to obtain best axis labels If voltage limits were eg 11 and 14 volts, the labels and limits default terribly to 10 to 20, and if you fix limits, then labels read "11, 11, 11, 12, 12, 12, 13, ...". alt-y-grid and alt-autoscale seem to improve this a lot * get_value -> get_status to better reflect what it's doing * millivolts() forgot to account for invalid value "U" --------- Co-authored-by: Tim Connors --- plugins/power/tasmota_ | 155 ++++++++++++++++++++++++----------------- 1 file changed, 91 insertions(+), 64 deletions(-) diff --git a/plugins/power/tasmota_ b/plugins/power/tasmota_ index e6f7420e..2dc058be 100755 --- a/plugins/power/tasmota_ +++ b/plugins/power/tasmota_ @@ -16,9 +16,9 @@ ln -s /usr/share/munin/plugins/tasmota_ /etc/munin/plugins/tasmota_hostname_curr Plugin also implements suggests, so if you have nodeattr installed and /etc/genders populated with "tasmota" as well as "powermon", -"DS18B20","SCD40" or "PMS5003" flags for those tasmota devices that -implement energy or temperature monitoring, you can run an ansible -play like this to set up your links: +"DS18B20","SCD40", "PMS5003" or "millivolts" flags for those tasmota +devices that implement energy or temperature monitoring, you can run +an ansible play like this to set up your links: https://github.com/spacelama/ansible-initial-server-setup/tree/master/roles/monitoring/tasks =head1 APPLICABLE SYSTEMS @@ -26,7 +26,7 @@ https://github.com/spacelama/ansible-initial-server-setup/tree/master/roles/moni Any host that can access tasmota systems and has "jq" installed. Can auto suggest values if nodeattr genders (debian: apt install genders) installed and configured with tasmota, powermon, DS18B20, SCD40, -PMS5003 flags. +PMS5003, millivolts flags. =head1 AUTHOR @@ -47,7 +47,7 @@ cached_curl=none # runs curl on "Status $1", and parses through jq -c "$2", setting the value in "$res" # Caches the curl results for when we're plotting multiple (power) values # -- don't forget to make sure we're not being called in a subshell! -get_value() { +get_status() { if [ "$cached_curl" = none ] ; then # run curl, cache the result, and if there was an error, set value to "U" if ! cached_curl=$( curl --max-time 5 -fsS --data-urlencode "cmnd=Status $1" "http://$DEVICE/cm" ) ; then @@ -63,6 +63,8 @@ get_value() { DEVICE=$(basename "$0" | cut -d_ -f2) FUNCTION=$(basename "$0" | cut -d_ -f3) +. "$MUNIN_LIBDIR/plugins/plugin.sh" + if [ "$1" = "autoconf" ]; then if ! which curl > /dev/null 2>&1 ; then echo "no (no curl)" @@ -97,161 +99,186 @@ if [ "$1" = "suggest" ]; then echo "${device}_${i}" done done + nodeattr -n 'tasmota&&millivolts' | while read -r device ; do + for i in millivolts ; do + echo "${device}_${i}" + done + done exit fi voltage() { + axis=Volts if [ "$1" = "config" ]; then - echo "graph_title Tasmota Voltage: $DEVICE" echo "graph_vlabel Volts" echo "graph_args --base 1000 -l 0" - echo "Volts.label Voltage" - exit 0 + echo "$axis.label Voltage" else - get_value 8 ".StatusSNS.ENERGY.Voltage" - echo "Volts.value $res" + get_status 8 ".StatusSNS.ENERGY.Voltage" + echo "$axis.value $res" fi } current() { + axis=Current if [ "$1" = "config" ]; then - echo "graph_title Tasmota Current: $DEVICE" echo "graph_vlabel Amps" echo "graph_args --base 1000 -l 0" - echo "Current.label Current" - exit 0 + echo "$axis.label Current" else - get_value 8 ".StatusSNS.ENERGY.Current" - echo "Current.value $res" + get_status 8 ".StatusSNS.ENERGY.Current" + echo "$axis.value $res" fi } power() { if [ "$1" = "config" ]; then - echo "graph_title Tasmota Power: $DEVICE" echo "graph_vlabel Watts" echo "graph_args --base 1000 -l 0" - for i in Power ApparentPower ReactivePower ; do - echo "${i}.label $i" - echo "${i}.type GAUGE" - echo "${i}.min 0" + for axis in ApparentPower ReactivePower Power ; do + echo "$axis.label $axis" + echo "$axis.type GAUGE" + echo "$axis.min 0" + + print_thresholds "$axis" done else - for i in Power ApparentPower ReactivePower ; do - get_value 8 ".StatusSNS.ENERGY.$i" - echo "$i.value $res" + for axis in ApparentPower ReactivePower Power ; do + get_status 8 ".StatusSNS.ENERGY.$axis" + echo "$axis.value $res" done fi } powerfactor() { + axis=PowerFactor if [ "$1" = "config" ]; then - echo "graph_title Tasmota Power factor: $DEVICE" echo "graph_vlabel Power Factor" echo "graph_args --base 1000 -l 0" - echo "PowerFactor.min 0" - echo "PowerFactor.max 1" - echo "PowerFactor.label Power Factor" - exit 0 + echo "$axis.min 0" + echo "$axis.max 1" + echo "$axis.label Power Factor" else - get_value 8 ".StatusSNS.ENERGY.Factor" - echo "PowerFactor.value $res" + get_status 8 ".StatusSNS.ENERGY.Factor" + echo "$axis.value $res" fi } energy() { + axis=Energy if [ "$1" = "config" ]; then - echo "graph_title Tasmota Energy: $DEVICE" echo "graph_args --base 1000" echo "graph_vlabel kWh" - echo "Energy.label Energy" - echo "Energy.draw AREA" - - exit 0 + echo "$axis.label Energy" + echo "$axis.draw AREA" else - get_value 8 ".StatusSNS.ENERGY.Total" - echo "Energy.value $res" + get_status 8 ".StatusSNS.ENERGY.Total" + echo "$axis.value $res" fi } DS18B20() { + axis=Temperature if [ "$1" = "config" ]; then - echo "graph_title Tasmota Temperature: $DEVICE" echo "graph_args --base 1000" echo "graph_vlabel °C" - echo "Temperature.label Temperature" - echo "Temperature.type GAUGE" - #echo "Temperature.min 0" - - exit 0 + echo "$axis.label Temperature" + echo "$axis.type GAUGE" + #echo "$axis.min 0" else - get_value 10 ".StatusSNS.DS18B20.Temperature" - echo "Temperature.value $res" + get_status 10 ".StatusSNS.DS18B20.Temperature" + echo "$axis.value $res" fi } SCD40() { + axis=CO2 if [ "$1" = "config" ]; then - echo "graph_title Tasmota Carbon Dioxide: $DEVICE" echo "graph_args --base 1000" echo "graph_vlabel PPM" - echo "CO2.label Carbon Dioxide" - echo "CO2.type GAUGE" - - exit 0 + echo "$axis.label Carbon Dioxide" + echo "$axis.type GAUGE" else - get_value 8 ".StatusSNS.SCD40.CarbonDioxide" - echo "CO2.value $res" + get_status 8 ".StatusSNS.SCD40.CarbonDioxide" + echo "$axis.value $res" fi } PMS5003() { if [ "$1" = "config" ]; then - echo "graph_title Tasmota Particulate Pollution: $DEVICE" echo "graph_args --base 1000" for v in 'PB1=<1μm PPD' 'PB2_5=<2.5μm PPD' 'PB10=<10μm PPD' ; do - i=$( echo "$v" | cut -d= -f 1 ) + axis=$( echo "$v" | cut -d= -f 1 ) lab=$( echo "$v" | cut -d= -f 2 ) - echo "${i}.label $lab" - echo "${i}.type GAUGE" - echo "${i}.min 0" + echo "$axis.label $lab" + echo "$axis.type GAUGE" + echo "$axis.min 0" done - - exit 0 else for v in 'PB1="PB1"' 'PB2_5="PB2.5"' 'PB10="PB10"' ; do - i=$( echo "$v" | cut -d= -f 1 ) + axis=$( echo "$v" | cut -d= -f 1 ) field=$( echo "$v" | cut -d= -f 2 ) - get_value 8 ".StatusSNS.PMS5003.$field" - echo "$i.value $res" + get_status 8 ".StatusSNS.PMS5003.$field" + echo "$axis.value $res" done fi } -[ "$1" = "config" ] && echo "graph_category sensors" +millivolts() { + axis=Volts + if [ "$1" = "config" ]; then + limits= +# # man rrdgraph for relevant --limit args +# if [ -n "$lower" ] ; then +# limits="$limits --lower-limit $lower --rigid --allow-shrink" +# limits="$limits --lower-limit $lower --rigid --alt-autoscale" +# fi +# if [ -n "$upper" ] ; then +# limits="$limits --upper-limit $upper --rigid" +# fi + echo "graph_title Tasmota Volts: $DEVICE" +# echo "graph_args --base 1000$limits" + echo "graph_args --base 1000 --alt-autoscale --alt-y-grid" + + echo "graph_vlabel Volts" + echo "$axis.label V" + echo "$axis.type GAUGE" + else + get_status 8 ".StatusSNS.ANALOG.Range" + if [ "$res" != U ] ; then + res=$( echo "$res" | awk '{printf "%0.3f", $1/1000}' ) + fi + echo "$axis.value $res" + fi +} case "$FUNCTION" in - voltage|power|powerfactor|current|energy|DS18B20|SCD40|PMS5003) + voltage|power|powerfactor|current|energy|DS18B20|SCD40|PMS5003|millivolts) $FUNCTION "$1" ;; *) echo "Unknown Function" ;; esac + +if [ "$1" = "config" ] ; then + echo "graph_category sensors" + print_thresholds "$axis" +fi