diff --git a/docu/docs/modul/geocoding.md b/docu/docs/modul/geocoding.md
new file mode 100644
index 0000000..ca939ea
--- /dev/null
+++ b/docu/docs/modul/geocoding.md
@@ -0,0 +1,53 @@
+#
Geocoding
+---
+
+## Beschreibung
+Mit diesem Modul können einem Paket die Koordinaten eines Ortes oder einer Adresse angefügt werden.
+
+## 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
+
+- geocoder
+- re
+
+---
+## Paket Modifikationen
+
+- Im Paket werden die Felder `lat` und `lng` hinterlegt
+
+---
+## Zusätzliche Wildcards
+
+- keine
\ No newline at end of file
diff --git a/docu/docs/plugin/telegram.md b/docu/docs/plugin/telegram.md
index 1f1b3d4..d6afdfb 100644
--- a/docu/docs/plugin/telegram.md
+++ b/docu/docs/plugin/telegram.md
@@ -2,38 +2,20 @@
---
## Beschreibung
-Mit diesem Plugin ist es moeglich, Telegram-Nachrichten für POCSAG-Alarmierungen zu senden.
-Außerdem unterstützt das Plugin das Versenden von Location über folgende geocoding-Api's:
+Mit diesem Plugin ist es moeglich, Telegram-Nachrichten für POCSAG-Alarmierungen zu senden. Außerdem werden Locations versenden, wenn die Felder `lat` und `lng` im Paket definiert sind.
-- Mapbox
-- Google Maps
+## Unterstütze Alarmtypen
+- Pocsag
## Resource
`telegram`
## Konfiguration
-|Feld|Beschreibung|Default|
-|----|------------|-------|
-|name|Beliebiger Name des Plugins||
-
-#### `config:`
-
|Feld|Beschreibung|Default|
|----|------------|-------|
|botToken|Der Api-Key des Telegram-Bots||
-|chatId|Die Chat-Id des Empfängers / der Emfänger-Gruppe||
-|geocoding|Aktivieren des Geocodings|false|
-|geoRegex|Regex Capture-Group zum Herausfiltern der Adresse||
-|geoApiProvider|Der Provider für das Geocoding||
-|geoApiToken|Der Api-Token fuer die Geocoding-Api||
-
-#### Verfügbare Geocoding Provider
-
-|Name|Einstellungswert|
-|----|------------|
-|Mapbox|mapbox|
-|Google Maps|google|
+|chatIds|Liste mit Chat-Ids der Empfängers / der Emfänger-Gruppen||
**Beispiel:**
```yaml
@@ -41,19 +23,15 @@ Außerdem unterstützt das Plugin das Versenden von Location über folgende geoc
name: Telegram Plugin
res: telegram
config:
- botToken: {{ Telegram Bot Token }}
- chatId: {{ Telegram Chat Id }}
- geocoding: true
- geoRegex: ((?:[^ ]*,)*?)
- geoApiProvider: mapbox
- geoApiToken: {{ Mapbox Api Key }}
+ botToken: "{{ Telegram Bot Token }}"
+ chatIds:
+ - "{{ Telegram Chat Id }}"
```
---
## Abhängigkeiten
- python-telegram-bot
-- geocoder
---
## Paket Modifikationen
diff --git a/docu/mkdocs.yml b/docu/mkdocs.yml
index 846363e..5ba0bc9 100644
--- a/docu/mkdocs.yml
+++ b/docu/mkdocs.yml
@@ -21,6 +21,7 @@ nav:
- Mode Filter: modul/mode_filter.md
- Regex Filter: modul/regex_filter.md
- Descriptor: modul/descriptor.md
+ - Geocoding: modul/geocoding.md
- Plugins:
- Telegram: plugin/telegram.md
- Entwickler:
diff --git a/module/geocoding.py b/module/geocoding.py
new file mode 100644
index 0000000..b2bbb5c
--- /dev/null
+++ b/module/geocoding.py
@@ -0,0 +1,72 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""!
+ ____ ____ ______ __ __ __ _____
+ / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ /
+ / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ <
+ / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ /
+/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/
+ German BOS Information Script
+ by Bastian Schroll
+
+@file: geocoding.py
+@date: 01.03.2019
+@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)
+ pass
+
+ return bwPacket
+
+ def geocode(self, bwPacket):
+ """!find address in message and get latitude and longitude
+
+ @param bwPacket: A BOSWatch packet instance"""
+ try:
+ address = re.search(self.config.get("regex"), bwPacket.get("message"))[1]
+ provider = self.config.get("apiProvider")
+ if "mapbox" == provider:
+ g = geocoder.mapbox(address, key=self.config.get("apiToken"))
+ print(address)
+ elif "google" == provider:
+ g = geocoder.google(address, key=self.config.get("apiToken"))
+ else:
+ return bwPacket
+
+ (lat, lng) = g.latlng
+ bwPacket.set("lat", lat)
+ bwPacket.set("lng", lng)
+ return bwPacket
+ except (IndexError, TypeError, ValueError):
+ logging.warning("Address was not found in current Message, skipping geocoding")
+ except Exception as e:
+ logging.error("Unknown Error while executing geocoding module: " + str(type(e).__name__) + ": " + str(e))
+ return bwPacket
+
+ def onUnload(self):
+ """!Called by destruction of the plugin"""
+ pass
diff --git a/plugin/telegram.py b/plugin/telegram.py
index e97c5bc..f32a0cf 100644
--- a/plugin/telegram.py
+++ b/plugin/telegram.py
@@ -9,22 +9,19 @@
German BOS Information Script
by Bastian Schroll
-@file: template_module.py
-@date: 14.01.2018
-@author: Bastian Schroll
-@description: Template Plugin File
+@file: telegram.py
+@date: 20.02.2020
+@author: Jan Speller
+@description: Telegram Plugin
"""
import logging
-from telegram.error import (TelegramError, Unauthorized, BadRequest, TimedOut, ChatMigrated, NetworkError)
from plugin.pluginBase import PluginBase
-import telegram
-import re
-import geocoder
# ###################### #
# Custom plugin includes #
-
+from telegram.error import (TelegramError, Unauthorized, BadRequest, TimedOut, ChatMigrated, NetworkError)
+import telegram
# ###################### #
logging.debug("- %s loaded", __name__)
@@ -39,75 +36,31 @@ class BoswatchPlugin(PluginBase):
def onLoad(self):
"""!Called by import of the plugin"""
- pass
-
- def setup(self):
- """!Called before alarm"""
self.bot = telegram.Bot(token=self.config.get("botToken", default=""))
pass
- def fms(self, bwPacket):
- """!Called on FMS alarm
-
- @param bwPacket: bwPacket instance"""
- logging.warning("Telegram Plugin does not work for FMS")
- pass
-
def pocsag(self, bwPacket):
"""!Called on POCSAG alarm
@param bwPacket: bwPacket instance"""
+ msg = bwPacket.get("ric") + " (" + bwPacket.get("subric") + ")\n" + bwPacket.get("message")
- try:
- # Send Message via Telegram
- msg = bwPacket.get("ric") + " (" + bwPacket.get("subric") + ")\n" + bwPacket.get("message")
- self.bot.send_message(chat_id=self.config.get("chatId", default=""), text=msg)
-
- # Send Location via Telegram if Geocoding is enabled and Provider and Key are set
- if self.config.get("geocoding", default=False):
- address = re.search(self.config.get("geoRegex"), bwPacket.get("message"))[1]
- provider = self.config.get("geoApiProvider")
-
- if "mapbox" == provider:
- g = geocoder.mapbox(address, key=self.config.get("geoApiToken"))
- elif "google" == provider:
- g = geocoder.google(address, key=self.config.get("geoApiToken"))
- else:
- return
-
- (lat, lng) = g.latlng
- self.bot.sendLocation(chat_id=self.config.get("chatId", default=""), latitude=lat, longitude=lng)
- except (IndexError, TypeError, ValueError):
- logging.warning("Address was not found in current Message, skipping Location")
- except Unauthorized:
- logging.error("Error while sending Telegram Message, please Check your api-key")
- except (TimedOut, NetworkError):
- logging.error("Error while sending Telegram Message, please Check your connectivity")
- except (BadRequest, TelegramError):
- logging.error("Error while sending Telegram Message")
- except Exception as e:
- logging.error("Unknown Error while sending Telegram Message: " + str(type(e).__name__) + ": " + str(e))
+ if bwPacket.get("lat") is not None and bwPacket.get("lng") is not None:
+ (lat, lng) = (bwPacket.get("lat"), bwPacket.get("lng"))
+ for chatId in self.config.get("chatIds", default=[]):
+ try:
+ # Send Message via Telegram
+ self.bot.send_message(chat_id=chatId, default=""), text=msg)
- pass
-
- def zvei(self, bwPacket):
- """!Called on ZVEI alarm
-
- @param bwPacket: bwPacket instance"""
- logging.warning("Telegram Plugin does not work for ZVEI")
- pass
-
- def msg(self, bwPacket):
- """!Called on MSG packet
-
- @param bwPacket: bwPacket instance"""
- logging.warning("Telegram Plugin does not work for MSG")
- pass
-
- def teardown(self):
- """!Called after alarm"""
- pass
-
- def onUnload(self):
- """!Called by destruction of the plugin"""
+ # Send Location via Telegram if lat and lng exist in Package
+ if lat is not None and lng is not None:
+ self.bot.sendLocation(chat_id=chatId, latitude=lat, longitude=lng)
+ except Unauthorized:
+ logging.error("Error while sending Telegram Message, please Check your api-key")
+ except (TimedOut, NetworkError):
+ logging.error("Error while sending Telegram Message, please Check your connectivity")
+ except (BadRequest, TelegramError):
+ logging.error("Error while sending Telegram Message")
+ except Exception as e:
+ logging.error("Unknown Error while sending Telegram Message: " + str(type(e).__name__) + ": " + str(e))
pass
diff --git a/testPackage.py b/testPackage.py
new file mode 100644
index 0000000..a9bfeb7
--- /dev/null
+++ b/testPackage.py
@@ -0,0 +1,134 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import logging
+import socket
+import select
+
+logging.debug("- %s loaded", __name__)
+
+HEADERSIZE = 10
+class TCPClient:
+ """!TCP client class"""
+
+ def __init__(self, timeout=3):
+ """!Create a new instance
+
+ @param timeout: timeout for the client in sec. (3)"""
+ socket.setdefaulttimeout(timeout)
+ self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ def connect(self, host="localhost", port=8080):
+ """!Connect to the server
+
+ @param host: Server IP address ("localhost")
+ @param port: Server Port (8080)
+ @return True or False"""
+ try:
+ if not self.isConnected:
+ self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self._sock.connect((host, port))
+ logging.debug("connected to %s:%s", host, port)
+ return True
+ logging.warning("client always connected")
+ return True
+ except socket.error as e:
+ logging.error(e)
+ return False
+
+ def disconnect(self):
+ """!Disconnect from the server
+
+ @return True or False"""
+ try:
+ if self.isConnected:
+ self._sock.shutdown(socket.SHUT_RDWR)
+ self._sock.close()
+ logging.debug("disconnected")
+ return True
+ logging.warning("client always disconnected")
+ return True
+ except socket.error as e:
+ logging.error(e)
+ return False
+
+ def transmit(self, data):
+ """!Send a data packet to the server
+
+ @param data: data to send to the server
+ @return True or False"""
+ try:
+ logging.debug("transmitting:\n%s", data)
+ data = data.encode("utf-8")
+ header = str(len(data)).ljust(HEADERSIZE).encode("utf-8")
+ self._sock.sendall(header + data)
+ logging.debug("transmitted...")
+ return True
+ except socket.error as e:
+ logging.error(e)
+ return False
+
+ def receive(self, timeout=1):
+ """!Receive data from the server
+
+ @param timeout: to wait for incoming data in seconds
+ @return received data"""
+ try:
+ read, _, _ = select.select([self._sock], [], [], timeout)
+ if not read: # check if there is something to read
+ return False
+
+ header = self._sock.recv(HEADERSIZE).decode("utf-8")
+ if not len(header): # check if there data
+ return False
+
+ length = int(header.strip())
+ received = self._sock.recv(length).decode("utf-8")
+
+ logging.debug("recv header: '%s'", header)
+ logging.debug("received %d bytes: %s", len(received), received)
+ return received
+ except socket.error as e:
+ logging.error(e)
+ return False
+
+ @property
+ def isConnected(self):
+ """!Property of client connected state"""
+ try:
+ if self._sock:
+ _, write, _ = select.select([], [self._sock], [], 0.1)
+ if write:
+ data = "".encode("utf-8")
+ header = str(len(data)).ljust(HEADERSIZE).encode("utf-8")
+ self._sock.sendall(header + data)
+ return True
+ return False
+ except socket.error as e:
+ if e.errno != 32:
+ logging.exception(e)
+ return False
+ except ValueError:
+ return False
+
+client = TCPClient()
+client.connect()
+client.transmit(str({
+ 'serverName': 'TestServer',
+ 'serverVersion': '3.0',
+ 'serverBuildDate': '01.01.2020',
+ 'serverBranch': 'develop',
+ 'clientName': 'TestClient',
+ 'clientIP': '127.0.0.1',
+ 'clientVersion': '3.0',
+ 'clientBuildDate': '01.01.2020',
+ 'clientBranch': 'develop',
+ 'inputSource': 'sdr',
+ 'timestamp': '15:30',
+ 'frequency': '173.240',
+ 'mode': 'pocsag',
+ 'bitrate': '512',
+ 'ric': '1326089',
+ 'subric': '1',
+ 'subricText': 'a',
+ 'message': '17:22 FW 18865 Gebäudebrand_kle Sandkampstr.,15,-,Hopsten,NRW rauchentwicklung'
+}))
\ No newline at end of file