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