zefie icon

collectd_rtlamr

zefie | PRO | 02/24/19 11:12:11 PM UTC | 0 ⭐ | 839 👁️ | Never ⏰ | []
Bash |

3.9 KB

|

None

|

0 👍

/

0 👎

#!/bin/bash
 
## WIP - Check back to this pastebin often (like once a day or so) for updates while this string is here. ##
 
METER_ID="${1}" # first arg required
RTL_PPM="${2:-0}" # send arg, optional, rtl ppm data
INTERVAL="${3:-${COLLECTD_INTERVAL}}" # third arg, interval. fall back to default collectd value if blank
INTERVAL="${INTERVAL:-60}" # third arg second fallback, set to 60 if all else fails
MAX_WAIT="${3:-10}" # forth arg, optional, how long to run radio waiting for a packet per instance
RTL_WAIT=3 # How long to give rtl_tcp to fire up
 
HOSTNAME="${COLLECTD_HOSTNAME:-`hostname -f`}"
 
function zdbg() { if [ ! -z "${DEBUG_TEST}" ]; then echo "${@}"; fi };
 
if [ $(echo "${INTERVAL}" | grep -c "\.") -gt 0 ]; then
        # don't want your float value, collectd
        INTERVAL=$(printf -v int %.0f "${INTERVAL}")
fi
 
while [ "${METER_ID}" != "" ]; do
        TIME="$(date +%s)"
        METER_READING=""
        while [ "${METER_READING}" == "" ]; do
                # start radio
                zdbg "Starting Radio with ppm offset ${RTL_PPM}"
                rtl_tcp -P ${RTL_PPM} 2>/dev/null >/dev/null &
                RTLERR="$?";
                RTLPID="$!";
                if [ ${RTLERR} -ne 0 ]; then
                        # TODO: human intervention is probably required but try some sys hacks to power cycle dongle
                        # TODO NOTE: this will require the collectd user to have sudo NOPASSWD priv
 
                        # for now, sleep and restart the loop
                        zdbg "rtl_tcp failed to start"
                        sleep ${RTL_WAIT}
                        continue;
                fi
 
                zdbg "rtl_tcp started with PID ${RTLPID}, waiting ${RTL_WAIT} seconds to settle...";
                sleep ${RTL_WAIT} # time for radio to start
 
                zdbg "Attempting Meter ${METER_ID} Read (Max wait time: $((MAX_WAIT - RTL_WAIT))s)..."
                METER_READING=$(stdbuf -i0 -o0 -e0 rtlamr -freqcorrection=${RTL_PPM} -filterid=${METER_ID} -single=true -duration=$((MAX_WAIT - RTL_WAIT))s -format=json 2>/dev/null)
                if [ "${METER_READING}" != "" ]; then
                        zdbg "Read meter... parsing..."
                        METER_READING=$(echo "${METER_READING}" | jq -Mrc .Message.Consumption | tail -n1)
                        zdbg "Result: ${METER_READING}"
                fi
 
                # stop radio .. we do it this way to stop kill from echoing to collectd
                zdbg "Stopping Radio..."
                kill -9 "${RTLPID}"
                wait $! &>/dev/null
 
                if [ "${METER_READING}" == "" ]; then
                        # Meters beacon often, but this code might still get hit if we don't get a beacon within our timeframe
                        # Broken radio will no longer reach here since we handle rtl_tcp ourselves
                        zdbg "Could not read meter. Check meter ID (${METER_ID}) and antenna."
                        sleep ${RTL_WAIT}
                fi
        done
 
        echo "PUTVAL ${HOSTNAME}/rtlamr-${METER_ID}/kwh_usage interval=${INTERVAL} N:${METER_READING}"
        echo "PUTVAL ${HOSTNAME}/rtlamr-${METER_ID}/kwh_reading interval=${INTERVAL} N:${METER_READING}"
        TIMEEND="$(date +%s)"
        TIMERUN=$((TIMEEND - TIME))
        CALC_INTERVAL=$((INTERVAL - TIME_RUN))
        if [ ${CALC_INTERVAL} -gt 0 ]; then
                sleep ${CALC_INTERVAL};
        fi
done
 
 
# types.db addition
#kwh_usage               usage:DERIVE:0:U
#kwh_reading             reading:GAUGE:0:U
 
# collectd.conf.d/rtlamr.conf (replace Exec line as needed)
#<Plugin exec>
#  Exec "user" "path-to-this-script" "your-scm-meter-id" "rtlsdr-ppm-offset" "update-interval"
##  Example: Exec "zefie" "/usr/local/sbin/collectd_rtlamr" "39244000 "22" "60"
#</Plugin>
 
# See also: https://github.com/zefie/CGP (modified with rtlamr plugin)

Comments