diff --git a/boswatch/router/routerManager.py b/boswatch/router/routerManager.py index cf26d5f..86f6326 100644 --- a/boswatch/router/routerManager.py +++ b/boswatch/router/routerManager.py @@ -28,6 +28,7 @@ logging.debug("- %s loaded", __name__) class RouterManager: """!Class to manage all routers""" + def __init__(self): """!Create new router""" self._routerDict = {} @@ -92,9 +93,8 @@ class RouterManager: logging.error("unknown type '%s' in %s", routeType, route) return False - # except ModuleNotFoundError: # only since Py3.6 - except ImportError: - logging.error("%s not found: %s", route.get("type"), route.get("res")) + except ModuleNotFoundError: + logging.exception("%s not found: %s", route.get("type"), route.get("res")) return False logging.debug("finished building routers") diff --git a/docu/docs/plugin/mysql.md b/docu/docs/plugin/mysql.md new file mode 100644 index 0000000..b2cd2d4 --- /dev/null +++ b/docu/docs/plugin/mysql.md @@ -0,0 +1,43 @@ +#
Mysql
+--- + +## Beschreibung +Mit diesem Plugin ist es moeglich, die Alarmierungen in einer Mysql / Mariadb Datenbank zu speichern. +Das Plugin legt die Tabelle "boswatch" selbststaendig an, wenn diese nicht vorhanden ist. + +## Unterstütze Alarmtypen +- Fms +- Pocsag +- Zvei +- Msg + +## Resource +`mysql` + +## Konfiguration +|Feld|Beschreibung|Default| +|----|------------|-------| +|host|IP-Adresse bzw. URL des Hosts|| +|user|Username|| +|password|Passwort|| +|database|Name der Datenbank|| + +**Beispiel:** +```yaml + - type: plugin + name: mysql + res: mysql + config: + host: HOST + user: USERNAME + password: PASSWORD + database: DATABASE +``` + +--- +## Modul Abhängigkeiten +- keine + +--- +## Externe Abhängigkeiten +- mysql-connector-python diff --git a/init_db.sql b/init_db.sql new file mode 100644 index 0000000..b5948bc --- /dev/null +++ b/init_db.sql @@ -0,0 +1,35 @@ +create table boswatch +( + id int auto_increment primary key, + packetTimestamp timestamp default now() not null, + packetMode enum('fms', 'pocsag', 'zvei', 'msg') not null, + pocsag_ric char(7) default null, + pocsag_subric enum('1', '2', '3', '4') default null, + pocsag_subricText enum('a', 'b', 'c', 'd') default null, + pocsag_message text default null, + pocsag_bitrate enum('512', '1200', '2400') default null, + zvei_tone char(5) default null, + fms_fms char(8) default null, + fms_service varchar(255) default null, + fms_country varchar(255) default null, + fms_location varchar(255) default null, + fms_vehicle varchar(255) default null, + fms_status char(1) default null, + fms_direction char(1) default null, + fms_directionText tinytext default null, + fms_tacticalInfo char(3) default null, + serverName varchar(255) not null, + serverVersion varchar(100) not null, + serverBuildDate varchar(255) not null, + serverBranch varchar(255) not null, + clientName varchar(255) not null, + clientIP varchar(255) not null, + clientVersion varchar(100) not null, + clientBuildDate varchar(255) not null, + clientBranch varchar(255) not null, + inputSource varchar(30) not null, + frequency varchar(30) not null +); +create unique index boswatch_id_uindex + on boswatch (id); + diff --git a/plugin/mysql.py b/plugin/mysql.py new file mode 100644 index 0000000..f882703 --- /dev/null +++ b/plugin/mysql.py @@ -0,0 +1,188 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +"""! + ____ ____ ______ __ __ __ _____ + / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / + / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < + / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / +/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ + German BOS Information Script + by Bastian Schroll + +@file: mysql.py +@date: 15.02.2021 +@author: Jan Speller +@description: Mysql Plugin +""" +import logging +from plugin.pluginBase import PluginBase + +# ###################### # +# Custom plugin includes # +import mysql.connector +from datetime import datetime + +# ###################### # + +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 + Remove if not implemented""" + self.sqlInserts = { + "pocsag": "INSERT INTO boswatch (packetTimestamp, packetMode, pocsag_ric, pocsag_subric, pocsag_subricText, pocsag_message, pocsag_bitrate, serverName, serverVersion, serverBuildDate, serverBranch, clientName, clientIP, clientVersion, clientBuildDate, clientBranch, inputSource, frequency) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", + "zvei": "INSERT INTO boswatch (packetTimestamp, packetMode, zvei_tone, serverName, serverVersion, serverBuildDate, serverBranch, clientName, clientIP, clientVersion, clientBuildDate, clientBranch, inputSource, frequency) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", + "fms": "INSERT INTO boswatch (packetTimestamp, packetMode, fms_fms, fms_service, fms_country, fms_location, fms_vehicle, fms_status, fms_direction, fms_directionText, fms_tacticalInfo, serverName, serverVersion, serverBuildDate, serverBranch, clientName, clientIP, clientVersion, clientBuildDate, clientBranch, inputSource, frequency) VALUE (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", + "msg": "INSERT INTO boswatch (packetTimestamp, packetMode, serverName, serverVersion, serverBuildDate, serverBranch, clientName, clientIP, clientVersion, clientBuildDate, clientBranch, inputSource, frequency) VALUE (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" + } + + self.connection = mysql.connector.connect( + host=self.config.get("host"), + user=self.config.get("user"), + password=self.config.get("password"), + database=self.config.get("database"), + ) + + self.cursor = self.connection.cursor() + self.cursor.execute("SHOW TABLES LIKE 'boswatch'") + + if self.cursor.fetchone() is None: + with open('init_db.sql') as f: + for stmnt in f.read().split(';'): + self.cursor.execute(stmnt) + self.connection.commit() + + self.cursor.close() + + def setup(self): + """!Called before alarm + Remove if not implemented""" + try: + self.connection.ping(reconnect=True, attempts=3, delay=2) + except mysql.connector.Error: + logging.warning("Connection was down, trying to reconnect...") + self.onLoad() + + self.cursor = self.connection.cursor() + + def fms(self, bwPacket): + """!Called on FMS alarm + + @param bwPacket: bwPacket instance + Remove if not implemented""" + val = ( + datetime.fromtimestamp(float(bwPacket.get("timestamp"))), + bwPacket.get("mode"), + bwPacket.get("fms"), + bwPacket.get("service"), + bwPacket.get("country"), + bwPacket.get("location"), + bwPacket.get("vehicle"), + bwPacket.get("status"), + bwPacket.get("direction"), + bwPacket.get("directionText"), + bwPacket.get("tacticalInfo"), + bwPacket.get("serverName"), + bwPacket.get("serverVersion"), + bwPacket.get("serverBuildDate"), + bwPacket.get("serverBranch"), + bwPacket.get("clientName"), + bwPacket.get("clientIP"), + bwPacket.get("clientVersion"), + bwPacket.get("clientBuildDate"), + bwPacket.get("clientBranch"), + bwPacket.get("inputSource"), + bwPacket.get("frequency") + ) + self.cursor.execute(self.sqlInserts.get("fms"), val) + + def pocsag(self, bwPacket): + """!Called on POCSAG alarm + + @param bwPacket: bwPacket instance + Remove if not implemented""" + val = ( + datetime.fromtimestamp(float(bwPacket.get("timestamp"))), + bwPacket.get("mode"), + bwPacket.get("ric"), + bwPacket.get("subric"), + bwPacket.get("subricText"), + bwPacket.get("message"), + bwPacket.get("bitrate"), + bwPacket.get("serverName"), + bwPacket.get("serverVersion"), + bwPacket.get("serverBuildDate"), + bwPacket.get("serverBranch"), + bwPacket.get("clientName"), + bwPacket.get("clientIP"), + bwPacket.get("clientVersion"), + bwPacket.get("clientBuildDate"), + bwPacket.get("clientBranch"), + bwPacket.get("inputSource"), + bwPacket.get("frequency") + ) + self.cursor.execute(self.sqlInserts.get("pocsag"), val) + + def zvei(self, bwPacket): + """!Called on ZVEI alarm + + @param bwPacket: bwPacket instance + Remove if not implemented""" + val = ( + datetime.fromtimestamp(float(bwPacket.get("timestamp"))), + bwPacket.get("mode"), + bwPacket.get("tone"), + bwPacket.get("serverName"), + bwPacket.get("serverVersion"), + bwPacket.get("serverBuildDate"), + bwPacket.get("serverBranch"), + bwPacket.get("clientName"), + bwPacket.get("clientIP"), + bwPacket.get("clientVersion"), + bwPacket.get("clientBuildDate"), + bwPacket.get("clientBranch"), + bwPacket.get("inputSource"), + bwPacket.get("frequency") + ) + self.cursor.execute(self.sqlInserts.get("pocsag"), val) + + def msg(self, bwPacket): + """!Called on MSG packet + + @param bwPacket: bwPacket instance + Remove if not implemented""" + val = ( + datetime.fromtimestamp(float(bwPacket.get("timestamp"))), + bwPacket.get("mode"), + bwPacket.get("serverName"), + bwPacket.get("serverVersion"), + bwPacket.get("serverBuildDate"), + bwPacket.get("serverBranch"), + bwPacket.get("clientName"), + bwPacket.get("clientIP"), + bwPacket.get("clientVersion"), + bwPacket.get("clientBuildDate"), + bwPacket.get("clientBranch"), + bwPacket.get("inputSource"), + bwPacket.get("frequency") + ) + self.cursor.execute(self.sqlInserts.get("msg"), val) + + def teardown(self): + """!Called after alarm + Remove if not implemented""" + self.connection.commit() + self.cursor.close() + + def onUnload(self): + """!Called by destruction of the plugin + Remove if not implemented""" + self.connection.close()