]> git.sven.stormbind.net Git - sven/scripts.git/blob - home/pvmon2opsgenie.sh
34a5c5af86cf68749286487894727e28c4ed0978
[sven/scripts.git] / home / pvmon2opsgenie.sh
1 #!/bin/sh
2 # Checks inverter state as repoted by a metecontrol weblog
3 # device HTML interface, reports issues via Atlassian
4 # Opsgenie. Written with the intention to run via cron on
5 # a LTE Router with either OpenWRT or Teltonika RutOS.
6 # Requires curl for the Opsgenie part, otherwise
7 # sh/cut/cat/wget/test are enough.
8
9 # createAlert <alias> <message> <description>
10 createAlert() {
11     local alias="${1}"
12     local message="${2}"
13     local description="${3}"
14
15     if [ -z "${alias}" ]; then
16         echo "ERROR: Empty alert alias"
17         return
18     fi
19
20     if [ -z "${message}" ]; then
21         echo "ERROR: Empty alert message"
22         return
23     fi
24
25     curl -o /dev/null -s \
26         -X POST https://${API_HOST}/v2/alerts \
27         -H "Content-Type: application/json" \
28         -H "Authorization: GenieKey ${API_KEY}" \
29         -d \
30         "{
31             \"message\":\"${message}\",
32             \"alias\":\"${alias}\",
33             \"description\":\"${description}\"
34         }"
35 }
36
37 # closeAlert <alias>
38 closeAlert() {
39     local alias=${1}
40
41     if [ -z "${alias}" ]; then
42         echo "ERROR: Empty alert alias"
43         return
44     fi
45
46     curl -o /dev/null -s \
47         -X POST https://${API_HOST}/v2/alerts/${alias}/close?identifierType=alias \
48         -H "Authorization: GenieKey ${API_KEY}" \
49         -H "Content-Type: application/json" \
50         -d '{}'
51
52 }
53
54 # parseMcLine <meteocontrol html page output line>
55 parseMcLine() {
56     local input="${@}"
57
58     local wrleistung="$(echo ${input} | cut -d'>' -f 13 | cut -d'<' -f 1)"
59     local wradresse="$(echo ${input} | cut -d'>' -f 4 | cut -d'<' -f 1)"
60     local wrserial="$(echo ${input} | cut -d'>' -f 7 | cut -d'<' -f 1)"
61
62     # known bad case e.g. during the night
63     if [ "${wrleistung}" = "---" ]; then
64         echo "No Power Value at WR${wradresse} Serial:${wrserial}"
65         return 3
66     fi
67
68     # known good case
69     if [ "${wrleistung}" -gt 0 ]; then
70         echo "OK"
71         return
72     fi
73     
74     echo "ERROR: WR${wradresse} ${wrleistung}W Serial:${wrserial}"
75     return 1
76 }
77
78 # parseMcOutput <meteocontrol status html output page>
79 parseMcOutput() {
80     local file="${1}"
81     local result=""
82     if ! [ -f "${file}" ]; then
83         echo "ERROR: Supplied input ${file} is not a regular file"
84         return
85     fi
86
87     grep "cLink" "${file}" | while read line; do 
88         result="$(parseMcLine \"${line}\")"
89         # good case
90         if [ "${result}" = "OK" ]; then
91             continue
92         fi
93         # return failure data
94         echo -n "${result} -- "
95     done
96 }
97
98 # getMCstates <outfile> <status-url>
99 getMCstates() {
100     local outfile="${1}"
101     local url="${2}"
102
103     if [ -z "${outfile}" ]; then
104         echo "ERROR: no meteocontrol tmp file provided"
105         exit 1
106     fi
107
108     if [ -z "${url}" ]; then
109         echo "ERROR: no meteocontrol URL provided"
110         exit 1
111     fi
112
113     # remove eventual remains of prior runs
114     rm -f "${outfile}"
115
116     # ready to try to download the data from meteocontrol
117     if ! wget -q -O "${outfile}" "${url}"; then
118         echo "ERROR: could not download ${url} into ${outfile}"
119         exit 1
120     fi
121
122     # verify we have content to parse in our downloaded file
123     if ! grep -c -q cLink "${outfile}"; then
124         echo "ERROR: no matching cLink lines found in output file ${outfile}"
125         exit 1
126     fi
127 }
128
129 # checkAlertState <statefile> <new-status>
130 # return 0 on alert state change
131 # return 1 if nothing changed
132 checkAlertState() {
133     local statefile="${1}"
134     local newstatus="${2}"
135     local oldstatus="null"
136
137     test -f "${statefile}" && oldstatus="$(cat ${statefile})"
138     if [ "${oldstatus}" = "${newstatus}" ]; then
139         return 1
140     fi
141
142     # update state file on state change
143     echo "${newstatus}" > "${statefile}"
144     return 0
145 }
146
147 ### main configuration
148 API_HOST="api.eu.opsgenie.com"
149 API_KEY=""
150
151 # adjust meteocontrol default password and IPs
152 mc1="http://admin:ist02@192.168.1.2:80/html/de/onlineOverWr.html"
153 mc2="http://admin:ist02@192.168.1.3:80/html/de/onlineOverWr.html"
154
155 ### main loop
156 for dev in mc1 mc2; do
157     outfile="/tmp/${dev}.html"
158     statefile="/tmp/pvstate-${dev}"
159     url=$(eval echo \${$dev})
160
161     # download the html overview page from meteocontrol device
162     getMCstates "${outfile}" "${url}"
163
164     # parse the overview page and collect failures
165     failures=$(parseMcOutput "${outfile}")
166
167     # handle failures and alerting
168     if ! [ -z "${failures}" ]; then
169         checkAlertState "${statefile}" "FAILED" && \
170         createAlert "${dev}" "PV ${dev}" "${failures}"
171         continue
172     fi
173     
174     # update alert state close alert on state change
175     checkAlertState "${statefile}" "OK" && \
176     closeAlert "${dev}"
177 done