diff --git a/munin/munin-collector.sh b/munin/munin-collector.sh index 428cbb8..a4257b8 100755 --- a/munin/munin-collector.sh +++ b/munin/munin-collector.sh @@ -2,8 +2,8 @@ TARGETS="192.168.0.51" #PLUGINS="load memory pisense_temp 1wire ina219 hue_temp_10 hue_temp_14 433mhz" PLUGINS="load memory pisense_temp 1wire ina219 433mhz" -PASSWORD="SET_ME" -source ~/.munin-collector.conf +# Sets DATABASE, USER, PASSWORD +source ~/.mysql_grafana.conf while true; do @@ -41,7 +41,7 @@ while true; do SQL=$(echo $LINE | sed -E "s/(.*)\.(.*) (.*)/INSERT INTO ${TABLE_NAME} (source, metric, value) VALUES (\"${SOURCE}\",\"\1\", \"\3\");/") # fi #echo $SQL - echo $SQL | mysql --host="192.168.0.12" --database="grafanaData" --user="grafanaWriter" --password="${PASSWORD}" + echo $SQL | mysql --host="192.168.0.12" --database="${DATABASE}" --user="${USER}" --password="${PASSWORD}" done # LINE done # PLUGINS done # TARGETS diff --git a/scripts/conf.d/1wire b/scripts/conf.d/1wire new file mode 100644 index 0000000..2a9861b --- /dev/null +++ b/scripts/conf.d/1wire @@ -0,0 +1,12 @@ +[1wire] +env.alias_001415daa6ff Vorlauf +env.alias_000802775a88 Ext_1 +env.alias_0008027777d5 Ext_2 +env.alias_00000614a13f Schlafen_1 +env.alias_00000614a9dd Schlafen_2 +env.alias_00042c37a7ff Wohnen_1 +env.alias_000802774f41 Wohnen_2 +env.alias_00042e0076ff Kind +env.alias_000006140045 Bad +env.alias_0000061451b3 Kueche +env.alias_0008027774a6 Esstisch diff --git a/scripts/conf.d/433mhz b/scripts/conf.d/433mhz new file mode 100644 index 0000000..0c1f2aa --- /dev/null +++ b/scripts/conf.d/433mhz @@ -0,0 +1,22 @@ +[433mhz] +user root + +#env.ignore_ttl true + +# global types +env.type_1 Temperatur +env.type_2 Luftfeuchte +env.type_3 Spannung + +# node names +env.node_0 Wohnzimmer +env.node_1 Schlafzimmer +env.node_2 Arbeitszimmer +env.node_3 Esszimmer +env.node_4 Küche +env.node_5 Bad +env.node_6 Abstellkammer +env.node_7 Balkon + +# single sensor type overrides +#env.sensor_0_0 Special diff --git a/scripts/monitor.sh b/scripts/monitor.sh new file mode 100755 index 0000000..468ca59 --- /dev/null +++ b/scripts/monitor.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# https://stackoverflow.com/a/1482133 +SCRIPT_PATH=$(dirname -- "$( readlink -f -- "$0"; )";) + +while true; do + ${SCRIPT_PATH}/run.sh + + sleep 300 + +done # FOREVER-LOOP diff --git a/scripts/plugins/1wire b/scripts/plugins/1wire new file mode 100755 index 0000000..8a99f74 --- /dev/null +++ b/scripts/plugins/1wire @@ -0,0 +1,75 @@ +#!/bin/bash +# -*- sh -*- + +: << =cut + +=head1 NAME + +433mhz - Plugin to capture readings from wireless sensors via serial + +=head1 NOTES + +=head1 AUTHOR + +Contributed by Florian Klemenz + +=head1 LICENSE + +GPLv2 + +=head1 MAGIC MARKERS + + #%# family=auto + #%# capabilities=autoconf + +=cut + +. $MUNIN_LIBDIR/plugins/plugin.sh + +if [ "$1" = "autoconf" ]; then + echo yes + exit 0 +fi + +if [ "$1" = "config" ]; then + + echo 'graph_title Wireless temperature sensor readings' + echo 'graph_args --base 1 -l 0 ' + echo 'graph_scale no' + echo 'graph_vlabel °C' + echo 'graph_category temperature' + echo 'temp.label Vorratskammer' + echo 'temp.draw LINE' + print_warning temp + print_critical temp + exit 0 +fi + + +CMD="for f in $(find -L /sys/bus/w1/devices/ -maxdepth 2 -name temperature); do s=${f%/*}; s=${s##*-}; v=$(cat $f); echo "${s} ${v}"; done" + +IFS=$'\n' +SENSORS=( $(eval $CMD) ) + +echo $SENSORS + +IFS=' ' +for ROW in "${SENSORS[@]}"; do + ENTRY=( $ROW ) + SENSOR=${ENTRY[0]} + VALUE=${ENTRY[1]} + + # Overrides SENSOR - Example: env.sensor_0_0 Batterie + ENV_SENSOR_VAR_NAME="alias_${SENSOR}" + ENV_SENSOR_NAME=${!ENV_SENSOR_VAR_NAME} + + if [ -n "${ENV_SENSOR_NAME}" ]; then + echo "${ENV_SENSOR_NAME}.value ${VALUE}" + else + echo "${SENSOR}.value ${VALUE}" + fi +done + + +#echo "Vorratskammer.value $TEMP" + diff --git a/scripts/plugins/433mhz b/scripts/plugins/433mhz new file mode 100755 index 0000000..be2f1d8 --- /dev/null +++ b/scripts/plugins/433mhz @@ -0,0 +1,99 @@ +#!/bin/bash +# -*- sh -*- + +: << =cut + +=head1 NAME + +433mhz - Plugin to capture readings from wireless sensors via serial + +=head1 NOTES + +=head1 AUTHOR + +Contributed by Florian Klemenz + +=head1 LICENSE + +GPLv2 + +=head1 MAGIC MARKERS + + #%# family=auto + #%# capabilities=autoconf + +=cut + +. $MUNIN_LIBDIR/plugins/plugin.sh + +if [ "$1" = "autoconf" ]; then + echo yes + exit 0 +fi + +if [ "$1" = "config" ]; then + + echo 'graph_title Wireless temperature sensor readings' + echo 'graph_args --base 1 -l 0 ' + echo 'graph_scale no' + echo 'graph_vlabel °C' + echo 'graph_category temperature' + echo 'temp.label Vorratskammer' + echo 'temp.draw LINE' + print_warning temp + print_critical temp + exit 0 +fi + +# DATA TYPE IDs +#define TYPE_TEMPERATURE 1 +#define TYPE_HUMIDITY 2 +#define TYPE_VOLTAGE 3 +TYPES=( none tmp hmd vlt ) + +CMD="arduino | tail -n +2" + +IFS=$'\n' +SENSORS=( $(eval $CMD) ) +#declare -p SENSORS + +IFS=' ' +for ROW in "${SENSORS[@]}"; do + ENTRY=( $ROW ) + NODE=${ENTRY[0]} + SENSOR=${ENTRY[1]} + VALUE=${ENTRY[2]} + TYPE=${ENTRY[3]} + TTL=$(echo "${ENTRY[4]}" | tr -d '[:space:]') + + if [ "$TTL" != "0" ] || [ ${ignore_ttl} ]; then + # Overrides NODE - Example: env.node_0 Wohnzimmer + ENV_NODE_VAR_NAME="node_${NODE}" + ENV_NODE_NAME=${!ENV_NODE_VAR_NAME} + + # Overrides SENSOR - Example: env.sensor_0_0 Batterie + ENV_SENSOR_VAR_NAME="sensor_${NODE}_${SENSOR}" + ENV_SENSOR_NAME=${!ENV_SENSOR_VAR_NAME} + + if [ -n "${ENV_SENSOR_NAME}" ]; then + echo "${ENV_NODE_NAME:-$NODE}_${SENSOR}_${ENV_SENSOR_NAME}.value ${VALUE}" + else + # Overrides TYPE - Example: env.type_1 Batterie + ENV_TYPE_VAR_NAME="type_${TYPE}" + ENV_TYPE_NAME=${!ENV_TYPE_VAR_NAME} + + if [ -n "${ENV_TYPE_NAME}" ]; then + echo "${ENV_NODE_NAME:-$NODE}_${SENSOR}_${ENV_TYPE_NAME}.value ${VALUE}" + else + echo "${ENV_NODE_NAME:-$NODE}_${SENSOR}_${TYPES[$TYPE]}.value ${VALUE}" + fi + + fi + + #echo "${ENV_NODE_NAME:-$NODE}_${ENV_SENSOR_NAME:-$SENSOR}_${TYPES[$TYPE]}.value ${VALUE}" + fi +done + + +#echo "Vorratskammer.value $TEMP" + diff --git a/scripts/plugins/ina219 b/scripts/plugins/ina219 new file mode 100755 index 0000000..ccb1f9d --- /dev/null +++ b/scripts/plugins/ina219 @@ -0,0 +1,70 @@ +#!/bin/sh +# -*- sh -*- + +: << =cut + +=head1 NAME + +ina219 - Plugin to measure power consumption. + +=head1 NOTES + +=head1 AUTHOR + +Contributed by Florian Klemenz + +=head1 LICENSE + +GPLv2 + +=head1 MAGIC MARKERS + + #%# family=auto + #%# capabilities=autoconf + +=cut + +. $MUNIN_LIBDIR/plugins/plugin.sh + +if [ "$1" = "autoconf" ]; then + echo yes + exit 0 +fi + +if [ "$1" = "config" ]; then + + echo 'graph_title Power' + echo 'graph_args --base 1 -l 0 ' + echo 'graph_scale no' + echo 'graph_vlabel mW' + echo 'graph_category power' + echo 'power.label power' + echo 'power.draw LINE' + print_warning power + print_critical power + exit 0 +fi + +ROUNDS=5 + +VOLTAGE=0 +CURRENT=0 +POWER=0 + +for i in $(seq ${ROUNDS}); do + RESULT=$(/usr/bin/ina219) + + VOLTAGE_RAW=$(echo $RESULT | /bin/sed 's/\([0-9]\+\)mV \+\([0-9\.]\+\)mA/\1/') + VOLTAGE=$(echo "scale=3; $VOLTAGE+$VOLTAGE_RAW" | /usr/bin/bc) + + CURRENT_RAW=$(echo $RESULT | /bin/sed 's/\([0-9]\+\)mV \+\([0-9\.]\+\)mA/\2/') + CURRENT=$(echo "scale=3; $CURRENT+$CURRENT_RAW" | /usr/bin/bc) + +done + +VOLTAGE=$(echo "scale=3; $VOLTAGE/$ROUNDS" | /usr/bin/bc) +CURRENT=$(echo "scale=3; $CURRENT/$ROUNDS" | /usr/bin/bc) +POWER=$(echo "scale=3; $VOLTAGE*$CURRENT/1000000" | /usr/bin/bc) + + +echo "power.value $POWER" diff --git a/scripts/plugins/plugin.sh b/scripts/plugins/plugin.sh new file mode 100644 index 0000000..2c9c231 --- /dev/null +++ b/scripts/plugins/plugin.sh @@ -0,0 +1,203 @@ +# -*- sh -*- +# Support functions for shell munin plugins +# + +clean_fieldname () { + # Clean up field name so it complies with munin requirements. + # Even though most versions of munin sanitises field names + # this at least avoids getting .s in field names which will + # very much still break munin. + # + # usage: name="$(clean_fieldname "$item")" + + # "root" is *not* allowed due to a 2.0 bug + echo "$@" | sed -e 's/^[^A-Za-z_]/_/' -e 's/[^A-Za-z0-9_]/_/g' -e 's/^root$/__root/' +} + + +# Look up warning environment variables. Takes these two options: +# $1 = field name +# $2 = optional override of environment variable name +# +# Checks for "$2" in the environment, then "$1_warning", then "warning" + +get_warning () { + # Skip $2 if it isn't defined + if [ -n "$2" ]; then + local warntmp=$(eval "echo \$$2") + if [ -n "$warntmp" ]; then + echo "${warntmp}" + return + fi + fi + local warntmp=$(eval "echo \$${1}_warning") + if [ -n "$warntmp" ]; then + echo "${warntmp}" + return + fi + local warntmp=$warning + if [ -n "$warntmp" ]; then + echo "${warntmp}" + return + fi +} + + +# Usage: +# warning=${warning:-92} +# print_warning "$name" + +print_warning () { + warnout=$(get_warning $1 $2) + if [ -n "${warnout}" ]; then + echo "${1}.warning ${warnout}" + fi +} + +# Ditto for critical values + +get_critical () { + # Skip $2 if it isn't defined + if [ -n "$2" ]; then + local crittmp=$(eval "echo \$$2") + if [ -n "$crittmp" ]; then + echo "${crittmp}" + return + fi + fi + local crittmp=$(eval "echo \$${1}_critical") + if [ -n "$crittmp" ]; then + echo "${crittmp}" + return + fi + local crittmp=$critical + if [ -n "$crittmp" ]; then + echo "${crittmp}" + return + fi +} + +print_critical () { + critout=$(get_critical $1 $2) + if [ -n "${critout}" ]; then + echo "${1}.critical ${critout}" + fi +} + +# adjust_threshold() takes a threshold string and a base value in, and returns +# the threshold string adjusted for percentages if percent sizes are present. +# If not, the threshold is left unchanged. +# Usage: +# adjust_threshold "50%:50%" 200 +# Returns: +# 100:100 +# +adjust_threshold () { + + if [ -n "$1" -a -n "$2" ]; then + echo "$1" | awk "BEGIN { FS=\":\"; OFS=\":\" } + \$1 ~ /.*%/ {\$1 = $2 * substr(\$1, 0, length(\$1) - 1) / 100} + \$2 ~ /.*%/ {\$2 = $2 * substr(\$2, 0, length(\$2) - 1) / 100} + + { print }" + fi + +} + +# print_thresholds() takes three arguments. The first is the field name, the +# second is the default environment variable for warnings (see the second +# argument to get_warning), and the third is the default environment variable +# for criticals (see the second argument to get_critical). +# +# This is a convenience function for plugins that don't need to do anything +# special for warnings vs criticals. +# +# Usage: +# warning='20' critical='40' print_thresholds user +# Returns: +# user.warning 20 +# user.critical 40 + +print_thresholds() { + print_warning $1 $2 + print_critical $1 $3 +} + +# print_adjusted_thresholds() takes four arguments. The first is the field +# name, the second is the base value (see the second argument to +# adjust_threshold), the third is the default environment variable for +# warnings (see the second argument to get_warning), and the fourth is the +# default environment variable for criticals (see the second argument to +# get_critical). +# +# Usage: +# warning=20% critical=40% print_adjusted_thresholds "user" 800 +# Returns: +# user.warning 160 +# user.critical 320 +# +print_adjusted_thresholds () { + tempthresh=$(get_warning $1 $3) + if [ -n "$tempthresh" ]; then + echo "$1.warning $(adjust_threshold "$tempthresh" "$2")" + fi + tempthresh=$(get_critical $1 $4) + if [ -n "$tempthresh" ]; then + echo "$1.critical $(adjust_threshold "$tempthresh" "$2")" + fi + unset tempthresh +} + + + +is_multigraph () { + # Multigraph feature is available in Munin 1.4.0 and later. + # But it also needs support on the node to stay perfectly + # compatible with old munin-masters. + # + # Using this procedure at the start of a multigraph plugin makes + # sure it does not interact with old node installations at all + # and thus does not break anything. + # + case $MUNIN_CAP_MULTIGRAPH:$1 in + 1:*) return;; # Yes! Rock and roll! + *:autoconf) + echo 'no (no multigraph support)' + exit 0 + ;; + + *:config) + echo 'graph_title This plugin needs multigraph support' + echo 'multigraph.label No multigraph here' + echo 'multigraph.info This plugin has been installed in a munin-node that is too old to know about multigraph plugins. Even if your munin master understands multigraph plugins this is not enough, the node too needs to be new enough. Version 1.4.0 or later should work.' + exit 0 + ;; + + *: ) echo 'multigraph.value 0' + exit 0 + ;; + esac +} + + +is_dirtyconfig () { + # Detect if node/server supports dirty config (feature not yet supported) + case $MUNIN_CAP_DIRTYCONFIG in + 1) exit 1;; + *) exit 0;; + esac +} + + + +# janl_: can I in a shell script save STDOUT so I can restore it after +# a "exec >>somefile"? +# james: exec 2>&4 etc. +# janl_: this saves handle 2 in handle 4? +# james: yes, that's basically the same as dup +# james: dup2, even +# janl_: so... ... "exec 4>&2" to restore? +# james: Actually you can do: exec 4>&2- ... which closes 4 afterwards ... +# I think that's historical behaviour and not a newish extension + +# vim: ft=sh sw=4 ts=4 et diff --git a/scripts/run.sh b/scripts/run.sh new file mode 100755 index 0000000..5e86a41 --- /dev/null +++ b/scripts/run.sh @@ -0,0 +1,52 @@ +#!/bin/bash +source ~/.mysql-grafana.conf + + +PLUGINS="1wire 433mhz" +#PLUGINS="433mhz ina219" + +# https://stackoverflow.com/a/1482133 +SCRIPT_PATH=$(dirname -- "$( readlink -f -- "$0"; )";) + + +SOURCE=$(hostname -s) +for PLUGIN in ${PLUGINS}; do + echo "Processing ${PLUGIN}..." + + PLUGIN_ENV="MUNIN_LIBDIR="${SCRIPT_PATH}"" + PLUGIN_CONF="${SCRIPT_PATH}/conf.d/${PLUGIN}" + if [ -f ${PLUGIN_CONF} ]; then + while IFS="" read -r p || [ -n "$p" ] + do + #printf '%s\n' "$p" + if [[ $p == env.* ]]; then + PARAM=${p##env.} # Match longest pattern from front -> everthing after the starting 'env.' + PARAM=${PARAM%% *} # Match longest pattern from back -> everything before the first ' ' + VALUE=${p#* } # Match shortest pattern from front -> everything after the first ' ' + PLUGIN_ENV+=" ${PARAM}=${VALUE}" + fi + done < ${PLUGIN_CONF} + echo "${PLUGIN_ENV}" + fi + + DATA=$(env -i ${PLUGIN_ENV} plugins/${PLUGIN} | tail -n +2 | head -n -1) + + echo "-----------------" + echo "$DATA" + echo "-----------------" + + TABLE_NAME="home_${PLUGIN}" # default + + + + IFS=$'\n'; for LINE in ${DATA}; do + # parse data and insert to database + #echo $LINE + + SQL=$(echo $LINE | sed -E "s/(.*)\.(.*) (.*)/INSERT INTO ${TABLE_NAME} (source, metric, value) VALUES (\"${SOURCE}\",\"\1\", \"\3\");/") + echo $SQL + #echo $SQL | mysql --host="192.168.0.12" --database="${DATABASE}" --user="${USER}" --password="${PASSWORD}" + done # LINE + +done # PLUGINS +