diff --git a/boswatch/wildcard.py b/boswatch/wildcard.py index 91f2fea..3519502 100644 --- a/boswatch/wildcard.py +++ b/boswatch/wildcard.py @@ -65,8 +65,8 @@ def replaceWildcards(message, bwPacket): "{CBRCH}": bwPacket.get("clientBranch"), # boswatch wildcards - "{INSRC}": bwPacket.get("mode"), - "{TIMES}": bwPacket.get("mode"), + "{INSRC}": bwPacket.get("inputSource"), + "{TIMES}": bwPacket.get("timestamp"), "{FREQ}": bwPacket.get("frequency"), "{MODE}": bwPacket.get("mode"), @@ -78,7 +78,7 @@ def replaceWildcards(message, bwPacket): "{VEHC}": bwPacket.get("vehicle"), "{STAT}": bwPacket.get("status"), "{DIR}": bwPacket.get("direction"), - "{DIRT}": bwPacket.get("dirextionText"), + "{DIRT}": bwPacket.get("directionText"), "{TACI}": bwPacket.get("tacticalInfo"), # pocsag wildcards @@ -99,6 +99,6 @@ def replaceWildcards(message, bwPacket): for wildcard, field in _additionalWildcards.items(): if field is not None: - message = message.replace(wildcard, bwPacket.getField(field)) + message = message.replace(wildcard, bwPacket.get(field)) return message diff --git a/docu/docs/develop/packet.md b/docu/docs/develop/packet.md index 14d2e88..e67de83 100644 --- a/docu/docs/develop/packet.md +++ b/docu/docs/develop/packet.md @@ -47,5 +47,5 @@ Ein BOSWatch Datenpaket wird in einem Python Dict abgebildet. In der nachfolgend |vehicle|X||||`{VEC}`|| |status|X||||`{STAT}`|| |direction|X||||`{DIR}`|| -|dirextionText|X||||`{DIRT}`|(Fhz->Lst, Lst->Fhz)| +|directionText|X||||`{DIRT}`|(Fhz->Lst, Lst->Fhz)| |tacticalInfo|X||||`{TACI}`|(I, II, III, IV)| diff --git a/docu/docs/modul/geocoding.md b/docu/docs/modul/geocoding.md new file mode 100644 index 0000000..0acf43e --- /dev/null +++ b/docu/docs/modul/geocoding.md @@ -0,0 +1,59 @@ +#
Geocoding
+--- + +## Beschreibung +Mit diesem Modul können einem Paket die Koordinaten eines Ortes oder einer Adresse angefügt werden. + +## Externe Abhängigkeiten +- geocoder + +## Unterstützte Alarmtypen +- Pocsag + +## Resource +`geocoding` + +## Konfiguration + +|Feld|Beschreibung|Default| +|----|------------|-------| +apiProvider|Der Provider für das Geocoding| +apiToken|Der Api-Token fuer die Geocoding-Api| +geoRegex|Regex Capture-Group zum Herausfiltern der Adresse| + +#### Verfügbare Geocoding Provider + +|Name|Einstellungswert| +|----|------------| +|Mapbox|mapbox| +|Google Maps|google| + +**Beispiel:** +```yaml + - type: module + name: Geocoding Module + res: geocoding + config: + apiProvider: "{{ Provider für Geocoding }}" + apiToken: "{{ API-Key für Provider }}" + regex: "((?:[^ ]*,)*?)" +``` + +--- +## Abhängigkeiten + +- keine + +--- +## Paket Modifikationen + +- `address`: gefundene Adresse +- `lat`: Latitude der Adresse +- `lon`: Longitude der Adresse + +--- +## Zusätzliche Wildcards + +- `{ADDRESS}`: gefundene Adresse +- `{LAT}`: Latitude der Adresse +- `{LON}`: Longitude der Adresse \ No newline at end of file diff --git a/docu/docs/plugin/telegram.md b/docu/docs/plugin/telegram.md new file mode 100644 index 0000000..3003bbe --- /dev/null +++ b/docu/docs/plugin/telegram.md @@ -0,0 +1,42 @@ +#
Telegram
+--- + +## Beschreibung +Mit diesem Plugin ist es moeglich, Telegram-Nachrichten für POCSAG-Alarmierungen zu senden. +Außerdem werden Locations versenden, wenn die Felder `lat` und `lon` im Paket definiert sind. (beispielsweise durch das Geocoding-Modul) + +## Externe Abhängigkeiten +- python-telegram-bot + +## Unterstütze Alarmtypen +- Pocsag + +## Resource +`telegram` + +## Konfiguration + +|Feld|Beschreibung|Default| +|----|------------|-------| +|message|Format der Nachricht|| +|botToken|Der Api-Key des Telegram-Bots|| +|chatIds|Liste mit Chat-Ids der Empfängers / der Emfänger-Gruppen|| + +**Beispiel:** +```yaml + - type: plugin + name: Telegram Plugin + res: telegram + config: + message: "{RIC}({SRIC})\n{MSG}" + botToken: "{{ Telegram Bot Token }}" + chatIds: + - "{{ Telegram Chat Id }}" +``` + +--- +## Abhängigkeiten + +- Modul geocoding (Falls in Paket vorhanden): + - `lat` + - `lon` diff --git a/docu/mkdocs.yml b/docu/mkdocs.yml index 611cbfe..2a9d54b 100644 --- a/docu/mkdocs.yml +++ b/docu/mkdocs.yml @@ -18,11 +18,13 @@ nav: - Routing Mechanismus: information/router.md - Changelog: changelog.md - Module: + - Descriptor: modul/descriptor.md + - Geocoding: modul/geocoding.md - Mode Filter: modul/mode_filter.md - Regex Filter: modul/regex_filter.md - - Descriptor: modul/descriptor.md - Plugins: - Http: plugin/http.md + - Telegram: plugin/telegram.md - Entwickler: - Eigenes Modul/Plugin schreiben: develop/ModulPlugin.md - BOSWatch Alarmpaket Format: develop/packet.md diff --git a/module/geocoding.py b/module/geocoding.py new file mode 100644 index 0000000..572bc0d --- /dev/null +++ b/module/geocoding.py @@ -0,0 +1,80 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +"""! + ____ ____ ______ __ __ __ _____ + / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / + / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < + / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / +/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ + German BOS Information Script + by Bastian Schroll + +@file: geocoding.py +@date: 22.02.2020 +@author: Jan Speller +@description: Geocoding Module +""" +import logging +from module.moduleBase import ModuleBase + +# ###################### # +# Custom plugin includes # +import geocoder +import re +# ###################### # + +logging.debug("- %s loaded", __name__) + + +class BoswatchModule(ModuleBase): + """!Description of the Module""" + def __init__(self, config): + """!Do not change anything here!""" + super().__init__(__name__, config) # you can access the config class on 'self.config' + + def doWork(self, bwPacket): + """!start an run of the module. + + @param bwPacket: A BOSWatch packet instance""" + if bwPacket.get("mode") == "pocsag": + self.geocode(bwPacket) + + return bwPacket + + def geocode(self, bwPacket): + """!find address in message and get latitude and longitude + + @param bwPacket: A BOSWatch packet instance""" + try: + addressArray = re.search(self.config.get("regex"), bwPacket.get("message")) + provider = self.config.get("apiProvider") + + if addressArray[1] is None: + logging.info("No address found, skipping geocoding") + return bwPacket + + address = addressArray[1] + bwPacket.set("address", address) + self.registerWildcard("{ADDRESS}", "address") + logging.info("Found address: '" + address + "' in packet") + + if "mapbox" == provider: + logging.info("Using Mapbox as provider") + g = geocoder.mapbox(address, key=self.config.get("apiToken")) + elif "google" == provider: + logging.info("Using Google as provider") + g = geocoder.google(address, key=self.config.get("apiToken")) + else: + return bwPacket + + (lat, lon) = g.latlng + logging.info("Found following coordinates for address: [lat=" + str(lat) + ", lon=" + str(lon) + "]") + bwPacket.set("lat", lat) + bwPacket.set("lon", lon) + self.registerWildcard("{LAT}", "lat") + self.registerWildcard("{LON}", "lon") + + return bwPacket + except Exception as e: + logging.exception("Unknown Error while executing geocoding module: " + str(type(e).__name__) + ": " + str(e)) + return bwPacket diff --git a/plugin/telegram.py b/plugin/telegram.py new file mode 100644 index 0000000..80ff9e7 --- /dev/null +++ b/plugin/telegram.py @@ -0,0 +1,66 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +"""! + ____ ____ ______ __ __ __ _____ + / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / + / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < + / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / +/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ + German BOS Information Script + by Bastian Schroll + +@file: telegram.py +@date: 20.02.2020 +@author: Jan Speller +@description: Telegram Plugin +""" +import logging +from plugin.pluginBase import PluginBase + +# ###################### # +# Custom plugin includes # +from telegram.error import (TelegramError, Unauthorized, BadRequest, TimedOut, NetworkError) +import telegram +# ###################### # + +logging.debug("- %s loaded", __name__) + + +class BoswatchPlugin(PluginBase): + """!Description of the Plugin""" + + def __init__(self, config): + """!Do not change anything here!""" + super().__init__(__name__, config) # you can access the config class on 'self.config' + + def onLoad(self): + """!Called by import of the plugin""" + self.bot = telegram.Bot(token=self.config.get("botToken", default="")) + + def pocsag(self, bwPacket): + """!Called on POCSAG alarm + + @param bwPacket: bwPacket instance""" + msg = self.parseWildcards(self.config.get("message")) + if bwPacket.get("lat") is not None and bwPacket.get("lon") is not None: + logging.debug("Found coordinates in packet") + (lat, lon) = (bwPacket.get("lat"), bwPacket.get("lon")) + + for chatId in self.config.get("chatIds", default=[]): + try: + # Send Message via Telegram + logging.info("Sending message to " + chatId) + self.bot.send_message(chat_id=chatId, text=msg) + + # Send Location via Telegram if lat and lon are defined + if lat is not None and lon is not None: + logging.info("Sending location to " + chatId) + self.bot.sendLocation(chat_id=chatId, latitude=lat, longitude=lon) + except Unauthorized: + logging.exception("Error while sending Telegram Message, please Check your api-key") + except (TimedOut, NetworkError): + logging.exception("Error while sending Telegram Message, please Check your connectivity") + except (BadRequest, TelegramError): + logging.exception("Error while sending Telegram Message") + except Exception as e: + logging.exception("Unknown Error while sending Telegram Message: " + str(type(e).__name__) + ": " + str(e))