#!/bin/sh : << =cut =head1 NAME tasmota_ - logs voltage, energy usage, power, power factor and current logged from tasmota power switches To install the plugin, copy or move the plugin to /usr/share/munin/plugins/ set the chmod to 755 and create a symbolic link: ln -s /usr/share/munin/plugins/tasmota_ /etc/munin/plugins/tasmota_hostname_voltage ln -s /usr/share/munin/plugins/tasmota_ /etc/munin/plugins/tasmota_hostname_energy ln -s /usr/share/munin/plugins/tasmota_ /etc/munin/plugins/tasmota_hostname_power ln -s /usr/share/munin/plugins/tasmota_ /etc/munin/plugins/tasmota_hostname_powerfactor ln -s /usr/share/munin/plugins/tasmota_ /etc/munin/plugins/tasmota_hostname_current 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: https://github.com/spacelama/ansible-initial-server-setup/tree/master/roles/monitoring/tasks =head1 APPLICABLE SYSTEMS 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. =head1 AUTHOR Tim Connors =head1 LICENSE GPLv2 or later =head1 MAGICK MARKERS #%# family=auto #%# capabilities=autoconf =cut 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() { 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 cached_curl='{}' fi fi res=$( echo "$cached_curl" | jq -c "$2" ) if [ "$res" = null ] ; then res=U fi } DEVICE=$(basename "$0" | cut -d_ -f2) FUNCTION=$(basename "$0" | cut -d_ -f3) if [ "$1" = "autoconf" ]; then if ! which curl > /dev/null 2>&1 ; then echo "no (no curl)" exit 0 fi if ! which jq > /dev/null 2>&1 ; then echo "no (no jq)" exit 0 fi echo yes && exit 0 fi if [ "$1" = "suggest" ]; then nodeattr -n 'tasmota&&powermon' | while read -r device ; do for i in voltage power powerfactor current energy ; do echo "${device}_${i}" done done nodeattr -n 'tasmota&&DS18B20' | while read -r device ; do for i in DS18B20 ; do echo "${device}_${i}" done done nodeattr -n 'tasmota&&SCD40' | while read -r device ; do for i in SCD40 ; do echo "${device}_${i}" done done nodeattr -n 'tasmota&&PMS5003' | while read -r device ; do for i in PMS5003 ; do echo "${device}_${i}" done done exit fi voltage() { 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 else get_value 8 ".StatusSNS.ENERGY.Voltage" echo "Volts.value $res" fi } 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 else get_value 8 ".StatusSNS.ENERGY.Current" echo "Current.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" done else for i in Power ApparentPower ReactivePower ; do get_value 8 ".StatusSNS.ENERGY.$i" echo "$i.value $res" done fi } 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 else get_value 8 ".StatusSNS.ENERGY.Factor" echo "PowerFactor.value $res" fi } 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 else get_value 8 ".StatusSNS.ENERGY.Total" echo "Energy.value $res" fi } DS18B20() { 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 else get_value 10 ".StatusSNS.DS18B20.Temperature" echo "Temperature.value $res" fi } SCD40() { 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 else get_value 8 ".StatusSNS.SCD40.CarbonDioxide" echo "CO2.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 ) lab=$( echo "$v" | cut -d= -f 2 ) echo "${i}.label $lab" echo "${i}.type GAUGE" echo "${i}.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 ) field=$( echo "$v" | cut -d= -f 2 ) get_value 8 ".StatusSNS.PMS5003.$field" echo "$i.value $res" done fi } [ "$1" = "config" ] && echo "graph_category sensors" case "$FUNCTION" in voltage|power|powerfactor|current|energy|DS18B20|SCD40|PMS5003) $FUNCTION "$1" ;; *) echo "Unknown Function" ;; esac