Merge branch 'develop' into process_manager

This commit is contained in:
Bastian Schroll 2019-03-08 07:54:49 +01:00
commit fc6e0111af
7 changed files with 282 additions and 64 deletions

View file

@ -0,0 +1,2 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

38
boswatch/router/route.py Normal file
View file

@ -0,0 +1,38 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""!
____ ____ ______ __ __ __ _____
/ __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ /
/ __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ <
/ /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ /
/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/
German BOS Information Script
by Bastian Schroll
@file: route.py
@date: 04.03.2019
@author: Bastian Schroll
@description: Class for a single BOSWatch packet router route point
"""
class Route:
"""!Class for single routing points"""
def __init__(self, name, callback):
"""!Create a instance of an route point
@param name: name of the route point
@param callback: instance of the callback function
"""
self._name = name
self._callback = callback
@property
def name(self):
"""!Property to get the route point name"""
return self._name
@property
def callback(self):
"""!Porperty to get the callback function instance"""
return self._callback

72
boswatch/router/router.py Normal file
View file

@ -0,0 +1,72 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""!
____ ____ ______ __ __ __ _____
/ __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ /
/ __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ <
/ /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ /
/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/
German BOS Information Script
by Bastian Schroll
@file: router.py
@date: 01.03.2019
@author: Bastian Schroll
@description: Class for the BOSWatch packet router
"""
import logging
import copy
logging.debug("- %s loaded", __name__)
class Router:
"""!Class for the Router"""
def __init__(self, name):
"""!Create a new router
@param name: name of the router"""
self._name = name
self._routeList = []
logging.debug("[%s] new router", self._name)
def addRoute(self, route):
"""!Adds a route point to the router
@param route: instance of the Route class
"""
logging.debug("[%s] add route: %s", self._name, route.name)
self._routeList.append(route)
def runRouter(self, bwPacket):
"""!Run the router
@param bwPacket: instance of Packet class
@return a instance of Packet class
"""
logging.debug("[%s] started", self._name)
for routeObject in self._routeList:
logging.debug("[%s] -> run route: %s", self._name, routeObject)
bwPacket_tmp = routeObject.callback(copy.deepcopy(bwPacket)) # copy bwPacket to prevent edit the original
if bwPacket_tmp is None: # returning None doesnt change the bwPacket
continue
if bwPacket_tmp is False: # returning False stops the router immediately
logging.debug("[%s] stopped", self._name)
break
bwPacket = bwPacket_tmp
logging.debug("[%s] <- bwPacket returned: %s", self._name, bwPacket)
logging.debug("[%s] ended", self._name)
return bwPacket
@property
def name(self):
"""!Property to get the name of the router"""
return self._name
@property
def routeList(self):
"""!Property to get a list of all route points of this router"""
return self._routeList

View file

@ -9,81 +9,41 @@
German BOS Information Script
by Bastian Schroll
@file: router.py
@date: 01.03.2019
@file: routerManager.py
@date: 04.03.2019
@author: Bastian Schroll
@description: Class for the BOSWatch packet router
@description: Class for the BOSWatch packet router manager class
"""
# todo think about implement threading for routers and the plugin calls (THREAD SAFETY!!!)
import logging
import copy
import importlib
from boswatch.configYaml import ConfigYAML
from boswatch.router.router import Router
from boswatch.router.route import Route
logging.debug("- %s loaded", __name__)
class _Route:
def __init__(self, name, callback):
self._name = name
self._callback = callback
@property
def name(self):
return self._name
@property
def callback(self):
return self._callback
class _Router:
def __init__(self, name):
self._name = name
self._routeList = []
logging.debug("[%s] new router", self._name)
def addRoute(self, route):
logging.debug("[%s] add route: %s", self._name, route.name)
self._routeList.append(route)
def runRouter(self, bwPacket):
logging.debug("[%s] started", self._name)
for routeObject in self._routeList:
logging.debug("[%s] -> run route: %s", self._name, routeObject)
bwPacket_tmp = routeObject.callback(copy.deepcopy(bwPacket)) # copy bwPacket to prevent edit the original
if bwPacket_tmp is None: # returning None doesnt change the bwPacket
continue
if bwPacket_tmp is False: # returning False stops the router immediately
logging.debug("[%s] stopped", self._name)
break
bwPacket = bwPacket_tmp
logging.debug("[%s] <- bwPacket returned: %s", self._name, bwPacket)
logging.debug("[%s] ended", self._name)
return bwPacket
@property
def name(self):
return self._name
@property
def routeList(self):
return self._routeList
class RouterManager:
"""!Class to manage all routers"""
def __init__(self):
"""!Create new router"""
self._routerDict = {}
def __del__(self):
"""!Destroy the internal routerDict
All routers and route point instances will be destroyed too
Also destroys all instances from modules or plugins"""
# destroy all routers (also destroys all instances of modules/plugins)
del self._routerDict
# if there is an error, router list would be empty (see tmp variable)
def buildRouter(self, config):
"""!Initialize Routers from given config file
@param config: instance of ConfigYaml class
@return True or False"""
self._routerDict = {} # all routers and instances of modules/plugins would be destroyed
routerDict_tmp = {}
logging.debug("build routers")
@ -97,7 +57,7 @@ class RouterManager:
if router.get("name") in self._routerDict:
logging.error("duplicated router name: %s", router.get("name"))
return False
routerDict_tmp[router.get("name")] = _Router(router.get("name"))
routerDict_tmp[router.get("name")] = Router(router.get("name"))
for router in config.get("router"):
routerName = router.get("name")
@ -115,15 +75,15 @@ class RouterManager:
if routeType == "plugin":
importedFile = importlib.import_module(routeType + "." + routeName)
loadedClass = importedFile.BoswatchPlugin(routeConfig)
routerDict_tmp[routerName].addRoute(_Route(routeName, loadedClass._run))
routerDict_tmp[routerName].addRoute(Route(routeName, loadedClass._run))
elif routeType == "module":
importedFile = importlib.import_module(routeType + "." + routeName)
loadedClass = importedFile.BoswatchModule(routeConfig)
routerDict_tmp[routerName].addRoute(_Route(routeName, loadedClass._run))
routerDict_tmp[routerName].addRoute(Route(routeName, loadedClass._run))
elif routeType == "router":
routerDict_tmp[routerName].addRoute(_Route(routeName, routerDict_tmp[routeName].runRouter))
routerDict_tmp[routerName].addRoute(Route(routeName, routerDict_tmp[routeName].runRouter))
else:
logging.error("unknown type '%s' in %s", routeType, route)
@ -139,6 +99,10 @@ class RouterManager:
return True
def runRouter(self, routerRunList, bwPacket):
"""!Run given Routers
@param routerRunList: string or list of router names in string form
@param bwPacket: instance of Packet class"""
if type(routerRunList) is str: # convert single string name to list
routerRunList = [routerRunList]
@ -147,6 +111,7 @@ class RouterManager:
self._routerDict[routerName].runRouter(bwPacket)
def _showRouterRoute(self):
"""!Show the routes of all routers"""
for name, routerObject in self._routerDict.items():
logging.debug("Route for %s", name)
counter = 0

View file

@ -97,13 +97,17 @@ try:
bwClient = TCPClient()
if bwClient.connect(ip, port):
testFile = open(paths.TEST_PATH + "testdata.list", "r")
while 1:
for i in range(0, 5): # todo implement real data receive
time.sleep(1)
print("Alarm Nr #" + str(i))
for testData in testFile:
bwPacket = Decoder.decode("ZVEI1: 12345")
if (len(testData.rstrip(' \t\n\r')) == 0) or ("#" in testData[0]):
continue
logging.debug("Test: %s", testData)
bwPacket = Decoder.decode(testData)
if bwPacket:
bwPacket.printInfo()

View file

@ -43,7 +43,7 @@ from boswatch.network.server import TCPServer
from boswatch.packet import Packet
from boswatch.utils import header
from boswatch.network.broadcast import BroadcastServer
from boswatch.router import RouterManager
from boswatch.router.routerManager import RouterManager
header.logoToLog()
@ -82,6 +82,7 @@ try:
while 1:
if incomingQueue.empty(): # pause only when no data
time.sleep(0.1) # reduce cpu load (wait 100ms)
# in worst case a packet have to wait 100ms until it will be processed
else:
data = incomingQueue.get()

136
test/testdata.list Normal file
View file

@ -0,0 +1,136 @@
# Testdata for the BOSWatch Test Mode function
# Data in Multimon-NG Raw Format
# Data is alternately passed to the decoder to simulate an used Radio-Frequency
#
# POCSAG
# ------
#
# The following settings in config.ini are expected for POCSAG
#
# [BOSWatch]
# useDescription = 1
# doubleFilter_ignore_entries = 10
# doubleFilter_check_msg = 1
#
# [POC]
# deny_ric = 7777777
# filter_range_start = 0000005
# filter_range_end = 8999999
# idDescribed = 1
#
# bitrate
POCSAG512: Address: 1000512 Function: 1 Alpha: BOSWatch-Test ÖÄÜß: okay
POCSAG1200: Address: 1001200 Function: 1 Alpha: BOSWatch-Test: okay
POCSAG2400: Address: 1002400 Function: 1 Alpha: BOSWatch-Test: okay
# function-code
POCSAG512: Address: 1000000 Function: 0 Alpha: BOSWatch-Test: okay
POCSAG512: Address: 1000001 Function: 1 Alpha: BOSWatch-Test: okay
POCSAG512: Address: 1000002 Function: 2 Alpha: BOSWatch-Test: okay
POCSAG512: Address: 1000003 Function: 3 Alpha: BOSWatch-Test: okay
# german special sign
POCSAG512: Address: 1200001 Function: 1 Alpha: BOSWatch-Test ÖÄÜß: okay
POCSAG512: Address: 1200001 Function: 1 Alpha: BOSWatch-Test öäü: okay
# with csv
POCSAG512: Address: 1234567 Function: 1 Alpha: BOSWatch-Test: with csv
# without csv
POCSAG1200: Address: 2345678 Function: 2 Alpha: BOSWatch-Test: without csv
POCSAG2400: Address: 3456789 Function: 3 Alpha: BOSWatch-Test: without csv
# OHNE TEXT????
POCSAG1200: Address: 1100000 Function: 0
POCSAG1200: Address: 1100000 Function: 1
POCSAG1200: Address: 1100000 Function: 2
POCSAG1200: Address: 1100000 Function: 3
# duplicate with same and other msg
POCSAG1200: Address: 2000001 Function: 2 Alpha: BOSWatch-Test: second is a duplicate
POCSAG1200: Address: 2000001 Function: 2 Alpha: BOSWatch-Test: second is a duplicate
POCSAG1200: Address: 2000001 Function: 2 Alpha: BOSWatch-Testing: okay
# duplicate in different order
POCSAG1200: Address: 2100000 Function: 2
POCSAG1200: Address: 2100001 Function: 2
POCSAG1200: Address: 2100002 Function: 2
POCSAG1200: Address: 2100000 Function: 2
POCSAG1200: Address: 2100001 Function: 2
POCSAG1200: Address: 2100002 Function: 2
POCSAG1200: Address: 2100000 Function: 2 Alpha: BOSWatch-Test: second is a duplicate
POCSAG1200: Address: 2100001 Function: 2 Alpha: BOSWatch-Test: second is a duplicate
POCSAG1200: Address: 2100002 Function: 2 Alpha: BOSWatch-Test: second is a duplicate
POCSAG1200: Address: 2100000 Function: 2 Alpha: BOSWatch-Test: second is a duplicate
POCSAG1200: Address: 2100001 Function: 2 Alpha: BOSWatch-Test: second is a duplicate
POCSAG1200: Address: 2100002 Function: 2 Alpha: BOSWatch-Test: second is a duplicate
# invalid
POCSAG512: Address: 3 Function: 0 Alpha: BOSWatch-Test: okay
POCSAG512: Address: 33 Function: 0 Alpha: BOSWatch-Test: okay
POCSAG512: Address: 333 Function: 0 Alpha: BOSWatch-Test: okay
POCSAG512: Address: 3333 Function: 0 Alpha: BOSWatch-Test: okay
POCSAG512: Address: 33333 Function: 0 Alpha: BOSWatch-Test: okay
POCSAG512: Address: 333333 Function: 0 Alpha: BOSWatch-Test: okay
POCSAG512: Address: 3333333 Function: 0 Alpha: BOSWatch-Test: okay
POCSAG512: Address: 333333F Function: 0 Alpha: BOSWatch-Test: invalid
POCSAG512: Address: 333333F Function: 1 Alpha: BOSWatch-Test: invalid
POCSAG512: Address: 3333333 Function: 4 Alpha: BOSWatch-Test: invalid
# denied
POCSAG1200: Address: 7777777 Function: 1 Alpha: BOSWatch-Test: denied
# out of filter Range
POCSAG1200: Address: 0000004 Function: 1 Alpha: BOSWatch-Test: out of filter start
POCSAG1200: Address: 9000000 Function: 1 Alpha: BOSWatch-Test: out of filter end
#Probealram
POCSAG1200: Address: 0871004 Function: 1 Alpha: Dies ist ein Probealarm!
## Multicast Alarm
POCSAG1200: Address: 0871002 Function: 0 Alpha: <EOT><FF>
POCSAG1200: Address: 0860001 Function: 0
POCSAG1200: Address: 0860002 Function: 0
POCSAG1200: Address: 0860003 Function: 0
POCSAG1200: Address: 0860004 Function: 0
POCSAG1200: Address: 0860005 Function: 0
POCSAG1200: Address: 0860006 Function: 0
POCSAG1200: Address: 0860007 Function: 0
POCSAG1200: Address: 0860008 Function: 0
POCSAG1200: Address: 0860009 Function: 0
POCSAG1200: Address: 0860010 Function: 0
POCSAG1200: Address: 0871003 Function: 0 Alpha: B2 Feuer Gebäude Pers in Gefahr. bla bla bla<NUL>
# regEx-Filter?
#
# FMS
# ---
#
FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=I (ohneNA,ohneSIGNAL)) CRC correct
FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 1=LST->FZG 2=I (ohneNA,ohneSIGNAL)) CRC correct
FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=II (ohneNA,mit SIGNAL)) CRC correct
FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 1=LST->FZG 2=III(mit NA,ohneSIGNAL)) CRC correct
FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=IV (mit NA,mit SIGNAL)) CRC correct
#
# ZVEI
# ----
#
#with csv description
ZVEI1: 12345
#without csv description
ZVEI1: 56789
#duplicate
ZVEI1: 56789
#with repeat Tone
ZVEI1: 1F2E3
#in case of invalid id
ZVEI1: 135
#in case of a double-tone for siren n-'D's are sended
# ZVEI1: DDD
# ZVEI1: DDDDD