Deutscher Wetterdienst notifications in openHAB and Telegram
Posted by
ads' corner
on
Sunday, 2020-06-28 Posted in [Ansible][Linux][Openhab]
The “Deutscher Wetterdienst” DWD (German Weather Service) provices a service which sends out alarms for upcoming events, like heavy rain, storm, blizzard, strong winds ect. This service is only available for Germany. And it has a binding for openHAB. Time to integrate this, activate a number of regions I’m interested in, and send notifications to our mobile phones.
At this point I’m really happy that I deploy my openHAB with Ansible, I can use the Template module and loop over the Items, Things and Rules.
The Binding can “track” multiple regions, so called Cell IDs. I’m interested in 4 different Cells (the list is available here), your mileage might vary. For each reagion there can be multiple messages - and although every single example I found only assumes there is only one message (warningCount=1), I already had a situation where a Cell had two warnings. That information likely goes missing if you set warningCount to 1. Given how much configuration overhead it is when you add more channels, I can understand why most examples stay at 1 for warningCount. Doubling the number doubles the number of Items (12 -> 24). However since I deploy everything in a template, that’s not a problem here.
I started this with a generous warningCount=5 - and in my templates I just loop from 1 to 5, and over every Cell, and generate all the necessary Things and Rules for every channel.
Ok, the details:
Binding
First I need to install the Binding. That’s easy by using the API, and Ansible. You can also do that using the Paper UI.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
- name:Get list of available and installed extensionsuri:url:"http://{{ ansible_host }}:8080/rest/extensions"register:oh2_extensionschanged_when:false- name:Install extensionsuri:url:"http://{{ ansible_host }}:8080/rest/extensions/{{ item }}/install"method:POSTwhen:"not (oh2_extensions.json|byattr('id', item))[0].installed"loop:- binding-dwdunwetterregister:oh2_install_extensions
The two Tasks above will first fetch a list of all available and installed extensions from the openHAB host in $ansible_host. Then the binding-dwdunwetter extension is installed, if it is not yet installed. The list of extensions is longer in my case, but I broke down the list to just show this example.
Things
Next up: the Things definition. As mentioned before, I’m interested in multiple Cell IDs. Therefore in my dwd.things file I have an Ansible list with the entries, and loop over them when creating the Things definitions. When the file is deployed, Ansible will create the final version using the data in the list.
The deployed version of the file, from /etc/openhab2/things/dwd.things:
1
2
3
4
dwdunwetter:dwdwarnings:ort1 "Warnings Ort 1"[ cellId="111000001", refresh=30, warningCount=5 ]dwdunwetter:dwdwarnings:ort2 "Warnings Ort 2"[ cellId="111000002", refresh=30, warningCount=5 ]dwdunwetter:dwdwarnings:Ort3 "Warnings Ort 3"[ cellId="111000003", refresh=30, warningCount=5 ]dwdunwetter:dwdwarnings:ort4 "Warnings Ort 4"[ cellId="111000004", refresh=30, warningCount=5 ]
Items
Now that I have 4 different Things for the 4 locations, I need to create the Items for all of them. Each Thing provides 12 channels - per message. I have 5 of the messages. That makes 4 * 12 * 5 = 240 Items to declare. But in reality it’s just two loops and 12 Item lines, everything else is done by Ansible when the Template is deployed:
The $dwd loop runs over the 4 entries in $dwds, which defines the Cells. The $chan loop runs over the channels 1-5 (the range() function will not reach the final 6). The deployed file in /etc/openhab2/items/dwd.items:
These two, and 18 more, for every Cell and channel. And if a Cell changes, or I add a new one, or if we move to another location, or I decide to have more messages: I only need to change one setting, and re-deploy everything. This kind of native functionality I’m really missing in openHAB.
Rules
Everything is online, what about the alarms when a notification arrives. The Binding provides a Switch named warning, which goes ON when there is a warning. However this switch stays ON when one warning is replaced with another one - which is not uncommon when a warning is updated. Not useful for notifications. The Binding also provides a trigger channel Update, which is fired every time there is an update. The rule for a Trigger:
1
2
3
4
5
6
rule "New DWD Warnung"
when
Channel 'dwdunwetter:dwdwarnings:<Cell ID>:updated<Channel Number>' triggered NEW
then
// New Warning send a push notification to everyone
end
Except I need 20 of these rules. There might be a way to handle this using Groups and just one Rule in openHAB, but since I already use Ansible Templates to create the Things and Items, I just created Rules the same way:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
rule "New DWD Warnung ({{ dwd[0] }} - {{ chan }})"
when
Channel 'dwdunwetter:dwdwarnings:{{ dwd[1]}}:updated{{ chan }}' triggered NEW
then
// New Warning send a push notification to everyone
var String meldung_ausgabedatum =""+ Warning{{ dwd[1]}}Ausgabedatum{{ chan }}.state.format("%1$td.%1$tm.%1$tY %1$tH:%1$tM")
var String meldung_gueltigab =""+ Warning{{ dwd[1]}}GueltigAb{{ chan }}.state.format("%1$td.%1$tm.%1$tY %1$tH:%1$tM")
var String meldung_gueltigbis =""+ Warning{{ dwd[1]}}GueltigBis{{ chan }}.state.format("%1$td.%1$tm.%1$tY %1$tH:%1$tM")
var meldung ="Warnung für {{ dwd[0] }}\n\n"
meldung = meldung +"Ausgegeben:\n`"+ meldung_ausgabedatum +"`\n"
meldung = meldung +"Ab: `"+ meldung_gueltigab +"`\n"
meldung = meldung +"Bis: `"+ meldung_gueltigbis +"`\n"
meldung = meldung +"\n"+ Warning{{ dwd[1]}}Titel{{ chan }}.state.toString+"\n\n"
meldung = meldung + Warning{{ dwd[1]}}Instruction{{ chan }}.state.toString
logInfo("DWD", meldung)
val telegramAction = getActions("telegram","telegram:telegramBot:HA_Bot")
telegramAction.sendTelegram(Long::parseLong(TELEGRAM_CHANNEL_HA),"%s", meldung)
end
This creates a Rule for every Cell and Channel, and deploys everything into /etc/openhab2/rules/dwd.rules. Excerpt from the final version of the file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
rule "New DWD Warnung (Ort 1 - 1)"
when
Channel 'dwdunwetter:dwdwarnings:ort1:updated1' triggered NEW
then
// New Warning send a push notification to everyone
var String meldung_ausgabedatum =""+ Warningort1Ausgabedatum1.state.format("%1$td.%1$tm.%1$tY %1$tH:%1$tM")
var String meldung_gueltigab =""+ Warningort1GueltigAb1.state.format("%1$td.%1$tm.%1$tY %1$tH:%1$tM")
var String meldung_gueltigbis =""+ Warningort1GueltigBis1.state.format("%1$td.%1$tm.%1$tY %1$tH:%1$tM")
var meldung ="Warnung für Ort 1\n\n"
meldung = meldung +"Ausgegeben:\n`"+ meldung_ausgabedatum +"`\n"
meldung = meldung +"Ab: `"+ meldung_gueltigab +"`\n"
meldung = meldung +"Bis: `"+ meldung_gueltigbis +"`\n"
meldung = meldung +"\n"+ Warningort1Titel1.state.toString+"\n\n"
meldung = meldung + Warningort1Instruction1.state.toStringlogInfo("DWD", meldung)
val telegramAction = getActions("telegram","telegram:telegramBot:HA_Bot")
telegramAction.sendTelegram(Long::parseLong(TELEGRAM_CHANNEL_HA),"%s", meldung)
end
This creates a nicely formatted message for Telegram (instructions for a Telegram bot are here), and sends it out to our group (stored in TELEGRAM_CHANNEL_HA) where we get the notification.