+++ /dev/null
-#!/bin/sh
-# Checks inverter state as repoted by a meteocontrol weblog
-# device HTML interface, reports issues via Atlassian
-# Opsgenie. Written with the intention to run via cron on
-# a LTE Router with either OpenWRT or Teltonika RutOS.
-# Requires curl other stock sh/cut/cat/test are enough.
-
-### path to the suntime / check for daylight script
-checkdaylight="./suntime.lua"
-
-### opsgenie configuration
-API_HOST="api.eu.opsgenie.com"
-API_KEY=""
-
-# adjust meteocontrol default password and IPs
-# meteocontrol devices must be added to the main loop as well
-mc1="http://admin:ist02@192.168.1.2/html/de/onlineOverWr.html"
-mc2="http://admin:ist02@192.168.1.3/html/de/onlineOverWr.html"
-
-
-### check for daylight, otherwise exit early
-${checkdaylight} || exit 3
-
-
-# createAlert <alias> <message> <description>
-createAlert() {
- local alias="${1}"
- local message="${2}"
- local description="${3}"
-
- if [ -z "${alias}" ]; then
- echo "ERROR: Empty alert alias"
- return
- fi
-
- if [ -z "${message}" ]; then
- echo "ERROR: Empty alert message"
- return
- fi
-
- curl -o /dev/null -s \
- -X POST https://${API_HOST}/v2/alerts \
- -H "Content-Type: application/json" \
- -H "Authorization: GenieKey ${API_KEY}" \
- -d \
- "{
- \"message\":\"${message}\",
- \"alias\":\"${alias}\",
- \"description\":\"${description}\"
- }"
-}
-
-# closeAlert <alias>
-closeAlert() {
- local alias=${1}
-
- if [ -z "${alias}" ]; then
- echo "ERROR: Empty alert alias"
- return
- fi
-
- curl -o /dev/null -s \
- -X POST https://${API_HOST}/v2/alerts/${alias}/close?identifierType=alias \
- -H "Authorization: GenieKey ${API_KEY}" \
- -H "Content-Type: application/json" \
- -d '{}'
-
-}
-
-# parseMcLine <meteocontrol html page output line>
-parseMcLine() {
- local input="${@}"
-
- local wrleistung="$(echo ${input} | cut -d'>' -f 13 | cut -d'<' -f 1)"
- local wradresse="$(echo ${input} | cut -d'>' -f 4 | cut -d'<' -f 1)"
- local wrserial="$(echo ${input} | cut -d'>' -f 7 | cut -d'<' -f 1)"
-
- # known bad case e.g. during the night
- if [ "${wrleistung}" = "---" ]; then
- echo "No Power Value at WR${wradresse} Serial:${wrserial}"
- return 3
- fi
-
- # known good case
- if [ "${wrleistung}" -gt 0 ]; then
- echo "OK"
- return
- fi
-
- echo "ERROR: WR${wradresse} ${wrleistung}W Serial:${wrserial}"
- return 1
-}
-
-# parseMcOutput <meteocontrol status html output page>
-parseMcOutput() {
- local file="${1}"
- local result=""
- if ! [ -f "${file}" ]; then
- echo "ERROR: Supplied input ${file} is not a regular file"
- return
- fi
-
- grep "cLink" "${file}" | while read line; do
- result="$(parseMcLine \"${line}\")"
- # good case
- if [ "${result}" = "OK" ]; then
- continue
- fi
- # return failure data
- echo -n "${result} -- "
- done
-}
-
-# getMCstates <outfile> <status-url>
-getMCstates() {
- local outfile="${1}"
- local url="${2}"
-
- if [ -z "${outfile}" ]; then
- echo "ERROR: no meteocontrol tmp file provided"
- exit 1
- fi
-
- if [ -z "${url}" ]; then
- echo "ERROR: no meteocontrol URL provided"
- exit 1
- fi
-
- # remove eventual remains of prior runs
- rm -f "${outfile}"
-
- # ready to try to download the data from meteocontrol
- if ! curl -s -o "${outfile}" "${url}"; then
- echo "ERROR: could not download ${url} into ${outfile}"
- exit 1
- fi
-
- # verify we have content to parse in our downloaded file
- if ! grep -c -q cLink "${outfile}"; then
- echo "ERROR: no matching cLink lines found in output file ${outfile}"
- exit 1
- fi
-}
-
-# checkAlertState <statefile> <new-status>
-# return 0 on alert state change
-# return 1 if nothing changed
-checkAlertState() {
- local statefile="${1}"
- local newstatus="${2}"
- local oldstatus="null"
-
- test -f "${statefile}" && oldstatus="$(cat ${statefile})"
- if [ "${oldstatus}" = "${newstatus}" ]; then
- return 1
- fi
-
- # update state file on state change
- echo "${newstatus}" > "${statefile}"
- return 0
-}
-
-### main loop
-for dev in mc1 mc2; do
- outfile="/tmp/${dev}.html"
- statefile="/tmp/pvstate-${dev}"
- url=$(eval echo \${$dev})
-
- # download the html overview page from meteocontrol device
- getMCstates "${outfile}" "${url}"
-
- # parse the overview page and collect failures
- failures=$(parseMcOutput "${outfile}")
-
- # handle failures and alerting
- if ! [ -z "${failures}" ]; then
- checkAlertState "${statefile}" "FAILED" && \
- createAlert "${dev}" "PV ${dev}" "${failures}"
- continue
- fi
-
- # update alert state close alert on state change
- checkAlertState "${statefile}" "OK" && \
- closeAlert "${dev}"
-done