diff --git a/_info/requirements.txt b/_info/requirements.txt index ae51a02..30f6f37 100644 --- a/_info/requirements.txt +++ b/_info/requirements.txt @@ -1,7 +1,9 @@ # for pip to install all needed # called with 'pip -r requirements.txt' +pyyaml + pytest pytest-cov pytest-pep8 -pytest-randomly \ No newline at end of file +pytest-randomly diff --git a/boswatch/config.py b/boswatch/config.py deleted file mode 100644 index 16b2b00..0000000 --- a/boswatch/config.py +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -"""! - ____ ____ ______ __ __ __ _____ - / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / - / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < - / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / -/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ - German BOS Information Script - by Bastian Schroll - -@file: config.py -@date: 25.12.2017 -@author: Bastian Schroll -@description: Module for the configuration -""" -import logging -import configparser - -logging.debug("- %s loaded", __name__) - - -class Config: - - _sharePoints = {} - - def __init__(self): - """!Create a new config object and load the ini file directly""" - self._config = configparser.ConfigParser() - - def loadConfigFile(self, configPath, sharePoint=""): - """!loads a given configuration in the class wide config variable - - @param configPath: Path to the config file - @param sharePoint: If you want to share the config set name here - @return True or False""" - logging.debug("load config file from: %s", configPath) - try: - self._config.read(configPath, "utf-8") - if sharePoint: - self._shareConfig(sharePoint) - return True - except: # pragma: no cover - logging.exception("cannot load config file") - return False - - def _shareConfig(self, sharePoint): - """!Shares the configuration - - Shares the local _config to the class wide global _sharedConfig - @param sharePoint: Name of the global share point - @return True or False""" - if sharePoint in self._sharePoints: - logging.error("cannot share config - name is always in use: %s", sharePoint) - return False - else: - self._sharePoints[sharePoint] = self._config - logging.debug("add config sharePoint: %s", sharePoint) - return True - - def getInt(self, section, key, sharePoint=""): - """!Method to read a single config entry as integer - - @param section: Section to read from - @param key: Value to read - @param sharePoint: Name of the global config share (empty is only local) - @return An Integer or None""" - value = self._get(section, key, sharePoint) - if value is None: - return None - return int(value) - - def getBool(self, section, key, sharePoint=""): - """!Method to read a single config entry as boolean - - @param section: Section to read from - @param key: Value to read - @param sharePoint: Name of the global config share (empty is only local) - @return True or False""" - if self._get(section, key, sharePoint).lower() in ["1", "true", "yes"]: - return True - return False - - def getStr(self, section, key, sharePoint=""): - """!Method to read a single config entry as string - - @param section: Section to read from - @param key: Value to read - @param sharePoint: Name of the global config share (empty is only local) - @return The value or None""" - value = self._get(section, key, sharePoint) - if value is None: - return None - return str(value) - - def _get(self, section, key, sharePoint=""): - """!Method to read a single config entry - - @param section: Section to read from - @param key: Value to read - @param sharePoint: Name of the global config share (empty is only local) - @return The value or None""" - if sharePoint: - try: - return self._sharePoints[sharePoint].get(section, key) - except KeyError: - logging.error("no sharePoint named: %s", sharePoint) - except configparser.NoSectionError: - logging.warning("no shared config section: %s", section) - except configparser.NoOptionError: - logging.warning("no shared config option: %s", key) - except: # pragma: no cover - logging.exception("error while reading shared config") - return None - - else: - try: - return self._config.get(section, key) - except configparser.NoSectionError: - logging.warning("no local config section: %s", section) - except configparser.NoOptionError: - logging.warning("no local config option: %s", key) - except: # pragma: no cover - logging.exception("error while reading local config") - return None - - def getAllSharepoints(self): - """!Return a python dict of all set sharepoints - - @return Sharepoint dict""" - return self._sharePoints diff --git a/boswatch/configYaml.py b/boswatch/configYaml.py new file mode 100644 index 0000000..05dce6e --- /dev/null +++ b/boswatch/configYaml.py @@ -0,0 +1,79 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +"""! + ____ ____ ______ __ __ __ _____ + / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / + / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < + / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / +/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ + German BOS Information Script + by Bastian Schroll + +@file: configYaml.py +@date: 27.02.2019 +@author: Bastian Schroll +@description: Module for the configuration in yaml format +""" +import logging +import yaml + +logging.debug("- %s loaded", __name__) + +__sharePoints = {} + + +def loadConfigFile(configPath, sharePoint=""): + """!loads a given configuration + + @param configPath: Path to the config file + @param sharePoint: If you want to share the config set name here + @return python dict of config or None""" + logging.debug("load config file from: %s", configPath) + try: + + with open(configPath) as f: + # use safe_load instead load + config = yaml.safe_load(f) + if sharePoint: + _shareConfig(config, sharePoint) + return config + except: # pragma: no cover + logging.exception("cannot load config file") + return None + + +def loadConfigSharepoint(sharePoint): + """!loads a given configuration from an sharepoint + + @param sharePoint: Name of the sharepoint + @return python dict of config or None""" + try: + return __sharePoints[sharePoint] + except KeyError: + logging.error("no sharePoint named: %s", sharePoint) + except: # pragma: no cover + logging.exception("error while reading shared config") + return None + + +def _shareConfig(config, sharePoint): + """!Shares the configuration + + Shares the local _config to the class wide global _sharedConfig + @param config: Python dict of the configuration + @param sharePoint: Name of the global share point + @return True or False""" + if sharePoint in __sharePoints: + logging.error("cannot share config - name is always in use: %s", sharePoint) + return False + else: + __sharePoints[sharePoint] = config + logging.debug("add config sharePoint: %s", sharePoint) + return True + + +def getAllSharepoints(): + """!Return a python dict of all set sharepoints + + @return Sharepoint dict""" + return __sharePoints diff --git a/boswatch/filter/doubeFilter.py b/boswatch/filter/doubeFilter.py index c230155..68387e6 100644 --- a/boswatch/filter/doubeFilter.py +++ b/boswatch/filter/doubeFilter.py @@ -18,7 +18,7 @@ import logging import time -from boswatch.config import Config +from boswatch import configYaml logging.debug("- %s loaded", __name__) @@ -28,7 +28,7 @@ class DoubleFilter: def __init__(self): """!init""" - self._config = Config() + self._config = configYaml.loadConfigSharepoint("serverConfig")["filter"]["doubleFilter"] self._filterLists = {} def filter(self, bwPacket): @@ -57,14 +57,14 @@ class DoubleFilter: # delete entries that are to old counter = 0 for listPacket in self._filterLists[bwPacket.get("mode")][1:]: # [1:] skip first entry, thats the new one - if listPacket.get("timestamp") < (time.time() - self._config.getInt("doubleFilter", "IgnoreTime", "serverConfig")): + if listPacket.get("timestamp") < (time.time() - self._config["ignoreTime"]): self._filterLists[bwPacket.get("mode")].remove(listPacket) counter += 1 if counter: logging.debug("%d old entry(s) removed", counter) # delete last entry if list is to big - if len(self._filterLists[bwPacket.get("mode")]) > self._config.getInt("doubleFilter", "MaxEntry", "serverConfig"): + if len(self._filterLists[bwPacket.get("mode")]) > self._config["maxEntry"]: logging.debug("MaxEntry reached - delete oldest") self._filterLists[bwPacket.get("mode")].pop() diff --git a/boswatch/network/broadcast.py b/boswatch/network/broadcast.py index cfaf0d4..6684843 100644 --- a/boswatch/network/broadcast.py +++ b/boswatch/network/broadcast.py @@ -101,12 +101,18 @@ class BroadcastServer: self._serverShutdown = False self._servePort = servePort + def __del__(self): + if self.isRunning: + self.stop() + while self.isRunning: + pass + def start(self): """!Start the broadcast server in a new thread @return True or False""" try: - if not self._serverThread: + if not self.isRunning: logging.debug("start udp broadcast server") self._serverThread = threading.Thread(target=self._listen) self._serverThread.name = "BroadServ" @@ -130,7 +136,7 @@ class BroadcastServer: @return True or False""" try: - if self._serverThread: + if self.isRunning: logging.debug("stop udp broadcast server") self._serverShutdown = True return True diff --git a/boswatch/network/client.py b/boswatch/network/client.py index 6c785db..7e73439 100644 --- a/boswatch/network/client.py +++ b/boswatch/network/client.py @@ -40,12 +40,15 @@ class TCPClient: @param port: Server Port (8080) @return True or False""" try: - self._sock = socket - self._sock.setdefaulttimeout(self._timeout) - self._sock = socket.create_connection((host, port)) - - logging.debug("connected to %s:%s", host, port) - return True + if not self.isConnected: + self._sock = socket + self._sock.setdefaulttimeout(self._timeout) + self._sock = socket.create_connection((host, port)) + logging.debug("connected to %s:%s", host, port) + return True + else: + logging.warning("client always connected") + return True except ConnectionRefusedError: logging.error("cannot connect to %s:%s - connection refused", host, port) return False @@ -61,9 +64,14 @@ class TCPClient: @return True or False""" try: - self._sock.close() - logging.debug("disconnected") - return True + if self.isConnected: + self._sock.close() + self._sock = None + logging.debug("disconnected") + return True + else: + logging.warning("client not connected") + return True except AttributeError: logging.error("cannot disconnect - no connection established") return False @@ -111,3 +119,10 @@ class TCPClient: except: # pragma: no cover logging.exception("error while receiving") return False + + @property + def isConnected(self): + """!Property of client connected state""" + if self._sock: + return True + return False diff --git a/boswatch/network/server.py b/boswatch/network/server.py index 0ebebd2..affdd5d 100644 --- a/boswatch/network/server.py +++ b/boswatch/network/server.py @@ -82,6 +82,10 @@ class TCPServer: self._clientsConnectedLock = threading.Lock() self._clientsConnected = {} + def __del__(self): + if self.isRunning: + self.stop() + def start(self, port=8080): """!Start a threaded TCP socket server @@ -93,21 +97,23 @@ class TCPServer: @return True or False""" try: - self._server = ThreadedTCPServer(("", port), ThreadedTCPRequestHandler) - self._server.timeout = self._timeout - self._server.alarmQueue = self._alarmQueue + if not self.isRunning: + self._server = ThreadedTCPServer(("", port), ThreadedTCPRequestHandler) + self._server.timeout = self._timeout + self._server.alarmQueue = self._alarmQueue - self._server.clientsConnctedLock = self._clientsConnectedLock - self._server.clientsConnected = self._clientsConnected + self._server.clientsConnctedLock = self._clientsConnectedLock + self._server.clientsConnected = self._clientsConnected - self._server_thread = threading.Thread(target=self._server.serve_forever) - self._server_thread.name = "Thread-BWServer" - self._server_thread.daemon = True - self._server_thread.start() - logging.debug("TCPServer started in Thread: %s", self._server_thread.name) - return True - except OSError: - logging.exception("server always running?") + self._server_thread = threading.Thread(target=self._server.serve_forever) + self._server_thread.name = "Thread-BWServer" + self._server_thread.daemon = True + self._server_thread.start() + logging.debug("TCPServer started in Thread: %s", self._server_thread.name) + return True + else: + logging.warning("server always started") + return True except: # pragma: no cover logging.exception("cannot start the server") return False @@ -117,16 +123,17 @@ class TCPServer: @return True or False""" try: - self._server.shutdown() - self._server_thread.join() - self._server_thread = None - self._server.socket.close() - self._server = None - logging.debug("TCPServer stopped") - return True - except AttributeError: - logging.exception("cannot stop - server not started?") - return False + if self.isRunning: + self._server.shutdown() + self._server_thread.join() + self._server_thread = None + self._server.socket.close() + self._server = None + logging.debug("TCPServer stopped") + return True + else: + logging.warning("server always stopped") + return True except: # pragma: no cover logging.exception("cannot stop the server") return False @@ -147,3 +154,10 @@ class TCPServer: # todo return full list or write a print/debug method? with self._clientsConnectedLock: # because our list is not threadsafe return self._clientsConnected + + @property + def isRunning(self): + """!Property of server running state""" + if self._server: + return True + return False diff --git a/boswatch/packet/packet.py b/boswatch/packet/packet.py index bf0103c..600588c 100644 --- a/boswatch/packet/packet.py +++ b/boswatch/packet/packet.py @@ -16,7 +16,7 @@ """ import logging import time -from boswatch.config import Config +from boswatch import configYaml from boswatch import version logging.debug("- %s loaded", __name__) @@ -73,14 +73,14 @@ class Packet: - clientBranch - inputSource - frequency""" - config = Config() + config = configYaml.loadConfigSharepoint("clientConfig") logging.debug("add client data to bwPacket") - self.set("clientName", config.getStr("Client", "Name", "clientConfig")) + self.set("clientName", config["client"]["name"]) self.set("clientVersion", version.client) self.set("clientBuildDate", version.date) self.set("clientBranch", version.branch) - self.set("inputSource", config.getStr("Client", "InputSource", "clientConfig")) - self.set("frequency", config.getStr("Stick", "Frequency", "clientConfig")) + self.set("inputSource", config["client"]["inputSource"]) + self.set("frequency", config["inputSource"]["sdr"]["frequency"]) def addServerData(self): """!Add the server information to the decoded data @@ -90,9 +90,9 @@ class Packet: - serverVersion - serverBuildDate - serverBranch""" - config = Config() + config = configYaml.loadConfigSharepoint("serverConfig") logging.debug("add server data to bwPacket") - self.set("serverName", config.getStr("Server", "Name", "serverConfig")) + self.set("serverName", config["server"]["name"]) self.set("serverVersion", version.server) self.set("serverBuildDate", version.date) self.set("serverBranch", version.branch) diff --git a/boswatch/plugin/plugin.py b/boswatch/plugin/plugin.py index 73a4427..339c85a 100644 --- a/boswatch/plugin/plugin.py +++ b/boswatch/plugin/plugin.py @@ -18,7 +18,7 @@ import logging import time from boswatch.utils import paths -from boswatch.config import Config +from boswatch import configYaml from boswatch.utils import wildcard logging.debug("- %s loaded", __name__) @@ -52,9 +52,8 @@ class Plugin: self._alarmErrorCount = 0 self._teardownErrorCount = 0 - if paths.fileExist(paths.PLUGIN_PATH + pluginName + "/" + pluginName + ".ini"): - self.config = Config() - self.config.loadConfigFile(paths.PLUGIN_PATH + pluginName + "/" + pluginName + ".ini") + if paths.fileExist(paths.PLUGIN_PATH + pluginName + "/" + pluginName + ".yaml"): + self.config = configYaml.loadConfigFile(paths.PLUGIN_PATH + pluginName + "/" + pluginName + ".yaml") else: logging.debug("no config for %s found", pluginName) diff --git a/boswatch/plugin/pluginManager.py b/boswatch/plugin/pluginManager.py index e1c541e..ac5b46e 100644 --- a/boswatch/plugin/pluginManager.py +++ b/boswatch/plugin/pluginManager.py @@ -20,7 +20,7 @@ import os import time import importlib -from boswatch.config import Config +from boswatch import configYaml from boswatch.utils import paths logging.debug("- %s loaded", __name__) @@ -33,7 +33,7 @@ class PluginManager: def __init__(self): """!init comment""" - self._config = Config() + self._config = configYaml.loadConfigSharepoint("serverConfig") self._pluginList = [] def searchPluginDir(self): @@ -45,7 +45,7 @@ class PluginManager: if not os.path.isdir(location) or not name + ".py" in os.listdir(location): continue - pluginPriority = self._config.getInt("Plugins", name, "serverConfig") + pluginPriority = self._config["plugins"][name] if pluginPriority is None: logging.warning("no entry in server config for plugin: %s", name) diff --git a/bw_client.py b/bw_client.py index 4cb4d56..e355d27 100644 --- a/bw_client.py +++ b/bw_client.py @@ -43,14 +43,14 @@ try: import time logging.debug("Import BOSWatch modules") - from boswatch.config import Config + from boswatch import configYaml from boswatch.network.client import TCPClient + from boswatch.network.broadcast import BroadcastClient from boswatch.decoder.decoder import Decoder from boswatch.utils import header -except Exception as e: # pragma: no cover + +except: # pragma: no cover logging.exception("cannot import modules") - print("cannot import modules") - print(e) exit(1) try: @@ -66,25 +66,39 @@ try: epilog="""More options you can find in the extern client.ini file in the folder /config""") parser.add_argument("-c", "--config", help="Name to configuration File", required=True) - parser.add_argument("-t", "--test", help="Client will send some testdata", action="store_true") # todo implement testmode args = parser.parse_args() - bwConfig = Config() - if bwConfig.loadConfigFile(paths.CONFIG_PATH + args.config, "clientConfig") is False: - logging.exception("cannot load config file") - print("cannot load config file") - exit(1) # without config cannot _run + bwConfig = configYaml.loadConfigFile(paths.CONFIG_PATH + args.config, "clientConfig") + if bwConfig is None: + logging.error("cannot load config file") + +except: # pragma: no cover + logging.exception("error occurred") + exit(1) + + +# ############################# begin client system +try: + + if bwConfig["client"]["useBroadcast"]: + broadcastClient = BroadcastClient() + if broadcastClient.getConnInfo(): + ip = broadcastClient.serverIP + port = broadcastClient.serverPort + else: + ip = bwConfig["server"]["ip"] + port = bwConfig["server"]["port"] bwClient = TCPClient() - if bwClient.connect(bwConfig.getStr("Server", "IP"), bwConfig.getInt("Server", "PORT")): + if bwClient.connect(ip, port): while 1: - for i in range(0, 5): + + for i in range(0, 5): # todo implement real data receive time.sleep(1) print("Alarm Nr #" + str(i)) - data = "ZVEI1: 12345" - bwPacket = Decoder.decode(data) + bwPacket = Decoder.decode("ZVEI1: 12345") if bwPacket: bwPacket.printInfo() diff --git a/bw_server.py b/bw_server.py index fcdab23..7144e45 100644 --- a/bw_server.py +++ b/bw_server.py @@ -15,6 +15,7 @@ @description: BOSWatch server application """ from boswatch.utils import paths + if not paths.makeDirIfNotExist(paths.LOG_PATH): print("cannot find/create log directory: %s", paths.LOG_PATH) exit(1) @@ -44,43 +45,15 @@ try: import queue logging.debug("Import BOSWatch modules") - from boswatch.config import Config + from boswatch import configYaml from boswatch.network.server import TCPServer from boswatch.packet.packet import Packet - from boswatch.plugin.pluginManager import PluginManager - from boswatch.descriptor.descriptor import Descriptor - from boswatch.filter.doubeFilter import DoubleFilter from boswatch.utils import header - from boswatch.network.broadcast import BroadcastClient from boswatch.network.broadcast import BroadcastServer -except Exception as e: # pragma: no cover +except: # pragma: no cover logging.exception("cannot import modules") - print("cannot import modules") - print(e) exit(1) -# Test for the broadcast connection info function -server = BroadcastServer() -client = BroadcastClient() -server.start() -print(server.isRunning) -client.getConnInfo() -print(client.serverIP, client.serverPort) -server.stop() -print(server.isRunning) -time.sleep(2) -print(server.isRunning) - -# test for the timer class -from boswatch.utils.timer import RepeatedTimer -from boswatch.network.netCheck import NetCheck -net = NetCheck() -test = RepeatedTimer(3, net.checkConn) -test.start() -time.sleep(10) -print(net.connectionState) -test.stop() - try: header.logoToLog() header.infoToLog() @@ -96,91 +69,42 @@ try: parser.add_argument("-c", "--config", help="Name to configuration File", required=True) args = parser.parse_args() - bwConfig = Config() - if bwConfig.loadConfigFile(paths.CONFIG_PATH + args.config, "serverConfig") is False: - logging.exception("cannot load config file") - print("cannot load config file") - exit(1) # without config cannot run + bwConfig = configYaml.loadConfigFile(paths.CONFIG_PATH + args.config, "serverConfig") + if bwConfig is None: + logging.error("cannot load config file") - bwPluginManager = PluginManager() - bwPluginManager.searchPluginDir() - bwPluginManager.importAllPlugins() - bwPluginManager.loadAllPlugins() +except: # pragma: no cover + logging.exception("error occurred") + exit(1) - bwDescriptor = Descriptor() - if bwConfig.getBool("Description", "fms"): - bwDescriptor.loadDescription("fms") - if bwConfig.getBool("Description", "pocsag"): - bwDescriptor.loadDescription("pocsag") - if bwConfig.getBool("Description", "zvei"): - bwDescriptor.loadDescription("zvei") - bwDoubleFilter = DoubleFilter() +# ############################# begin server system +try: - serverPaused = False # flag to pause alarming of server - serverStop = False # flag to stop the whole server application - - # server flags test code - # ---------------------- - # import threading - # def eins(): - # global serverPaused - # serverPaused = True - # def zwei(): - # global serverPaused - # serverPaused = False - def drei(): - global serverStop - serverStop = True - # - # t1 = threading.Timer(1, eins) - # t2 = threading.Timer(5, zwei) - # t3 = threading.Timer(600, drei) - # t1.start() - # t2.start() - # t3.start() + if bwConfig["server"]["useBroadcast"]: + bcServer = BroadcastServer() + bcServer.start() incomingQueue = queue.Queue() bwServer = TCPServer(incomingQueue) if bwServer.start(): while 1: - if serverPaused: - logging.warning("Server pause flag received ...") - logging.debug("But all received packages will be cached!") - packetsOld = 0 - while serverPaused is True: - time.sleep(0.2) # reduce cpu load (run all 200ms) - packetsNew = incomingQueue.qsize() - if packetsNew is not packetsOld: - logging.debug("%s packet(s) waiting in queue", packetsNew) - packetsOld = packetsNew - logging.warning("Server resumed ...") - - if serverStop: - logging.warning("Server stop flag received ...") - break - if incomingQueue.empty(): # pause only when no data - time.sleep(0.1) # reduce cpu load (run all 100ms) + time.sleep(0.1) # reduce cpu load (wait 100ms) + + else: + data = incomingQueue.get() - data = incomingQueue.get() - if data is not None: logging.info("get data from %s (waited in queue %0.3f sec.)", data[0], time.time() - data[2]) - logging.debug("%s packet(s) waiting in queue", incomingQueue.qsize()) + logging.debug("%s packet(s) still waiting in queue", incomingQueue.qsize()) bwPacket = Packet((data[1])) - if not bwDoubleFilter.filter(bwPacket): - continue - bwPacket.set("clientIP", data[0]) bwPacket.addServerData() - if bwConfig.getBool("Description", bwPacket.get("mode")): - bwDescriptor.addDescriptions(bwPacket) + # todo implement routing - bwPluginManager.runAllPlugins(bwPacket) - # print(bwPacket.get("clientVersion")["major"]) incomingQueue.task_done() except KeyboardInterrupt: # pragma: no cover @@ -194,10 +118,8 @@ finally: # pragma: no cover # bwServer or bwPluginManager are not defined in case of an early error try: bwServer.stop() - except: # pragma: no cover - pass - try: - bwPluginManager.unloadAllPlugins() + if "bcServer" in locals(): + bcServer.stop() except: # pragma: no cover pass logging.debug("BOSWatch has ended ...") diff --git a/config/client.ini b/config/client.ini deleted file mode 100644 index 8a2acc9..0000000 --- a/config/client.ini +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- -# ____ ____ ______ __ __ __ _____ -# / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / -# / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < -# / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / -#/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ -# German BOS Information Script -# by Bastian Schroll - -[Server] -# connection params to BOSWatch alarm server -IP = 127.0.0.1 -PORT = 8080 - -# you can set multiple servers (one line for each) -# the alarm data are served to all server simultane -# for each server you can set one backup server that be used if master is not reachable -# {indv. name} = {Master}:{PORT};{Slave}:{PORT} - -# Name Master Port|Slave Port -server1 = 127.0.0.1:8080 -serverTest = 127.0.0.1:1234;192.168.178.1:1234 - -[Client] -# information about this BOSWatch client instance -Name = BW3 Client - -# choose input source for multimon -# 'stick' or 'audio' -InputSource = stick - -[Stick] -# configuration for your DVB-T stick -Device = 0 -Frequency = 85.000M -PPMError = 0 -Squelch = 0 -Gain = 100 - -[Audio] -# configuration for audio input - -[Decoder] -# here you can enable needed decoders -FMS = 0 -ZVEI = 0 -POC512 = 0 -POC1200 = 0 -POC2400 = 0 diff --git a/config/client.yaml b/config/client.yaml new file mode 100644 index 0000000..2f9b09a --- /dev/null +++ b/config/client.yaml @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# ____ ____ ______ __ __ __ _____ +# / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / +# / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < +# / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / +#/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ +# German BOS Information Script +# by Bastian Schroll + +client: + name: BW3 Client # name of the BW3 Client instance + inputSource: sdr # atm only 'sdr' is possible + useBroadcast: no # use broadcast to find server automatically + +server: # only used if useBroadcast = no + ip: 127.0.0.1 + port: 8080 + +inputSource: + sdr: + device: 0 + frequency: 85.000M + PPMError: 0 + Squelch: 0 + Gain: 100 + +decoder: + fms: yes + zvei: yes + poc512: yes + poc1200: yes + poc2400: yes diff --git a/config/server.ini b/config/server.ini deleted file mode 100644 index 9d4bce3..0000000 --- a/config/server.ini +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- -# ____ ____ ______ __ __ __ _____ -# / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / -# / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < -# / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / -#/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ -# German BOS Information Script -# by Bastian Schroll - -[Server] -PORT = 8080 -Name = BW3 Server - -[FMS] -UseLists = -Allowed = -Denied = -RegEx = - -[POCSAG] -UseLists = -Allowed = -Denied = -Range = -RegEx = - -[ZVEI] -UseLists = -Allowed = -Denied = -Range = -RegEx = - -[Filter] -UseDoubleFilter = 0 -UseRegexFilter = 0 - -[doubleFilter] -# max number of entrys to save for comparison -MaxEntry = 30 -# time to ignore same alarm in seconds -IgnoreTime = 10 -# include pocsag msg in comparison -CheckMsg = 0 - -[regexFilter] - -[Description] -# load CSV description files with short and lon description -fms = 0 -pocsag = 0 -zvei = 0 - -[Plugins] -# here you can enable needed plugins -# 0 is disabled -# all greater than 0 enable the plugin -# the higher the number the earlier the plugin is called on alarm -# we call ist Plugin Prioority -template = 1 diff --git a/config/server.yaml b/config/server.yaml new file mode 100644 index 0000000..fb1b90f --- /dev/null +++ b/config/server.yaml @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# ____ ____ ______ __ __ __ _____ +# / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / +# / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < +# / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / +#/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ +# German BOS Information Script +# by Bastian Schroll + +server: + port: 8080 + name: BW3 Server # name of the BW3 Server instance + useBroadcast: no # serve server ip on broadcast request + + +## here you can enable needed plugins +## 0 is disabled +## all greater than 0 enable the plugin +## the higher the number the earlier the plugin is called on alarm +## we call ist Plugin Prioority +plugins: + template: 1 + +filter: + doubleFilter: + maxEntry: 30 + ignoreTime: 10 + checkMsg: no + + +alarmRouter: +- Router 1 +- Router 2 + +router: + +- name: Router 1 + route: + - type: module + name: doubleFilter + config: + maxEntry: 30 + ignoreTime: 10 + checkMsg: no + - type: plugin + name: mysql + config: + user: test + pass: test + db: test + - type: router + name: Router 2 + +- name: Router 2 + route: diff --git a/plugins/template/template.ini b/plugins/template/template.ini deleted file mode 100644 index b51540a..0000000 --- a/plugins/template/template.ini +++ /dev/null @@ -1,4 +0,0 @@ -[Example] -String = Hello World! -bool = 1 -integer = 12 \ No newline at end of file diff --git a/plugins/template/template.yaml b/plugins/template/template.yaml new file mode 100644 index 0000000..4fde236 --- /dev/null +++ b/plugins/template/template.yaml @@ -0,0 +1,4 @@ +example: + string: Hello World! + bool: true + integer: 12 diff --git a/test/test.ini b/test/test.ini deleted file mode 100644 index e5f137e..0000000 --- a/test/test.ini +++ /dev/null @@ -1,12 +0,0 @@ -[test] -one = 1 -two = two - -[testcase] -test = ok - -[boolTest] -one = 1 -two = True -three = 0 -four = False \ No newline at end of file diff --git a/test/test.yaml b/test/test.yaml new file mode 100644 index 0000000..5e9ea8f --- /dev/null +++ b/test/test.yaml @@ -0,0 +1,5 @@ +types: + string: Hello World + boolean: true + integer: 11 + float: 3.14 diff --git a/test/test_ServerClient.py b/test/test_ServerClient.py index fcba7a7..0e2ddff 100644 --- a/test/test_ServerClient.py +++ b/test/test_ServerClient.py @@ -55,7 +55,7 @@ class Test_ServerClient: def test_clientDisconnectFailed(self): """!Disconnect while no connection is established""" self.testClient = TCPClient() - assert not self.testClient.disconnect() + assert self.testClient.disconnect() def test_clientTransmitFailed(self): """!Transmit while no connection is established""" @@ -135,7 +135,7 @@ class Test_ServerClient: def test_serverStopFailed(self, useServer): """!Test to stop a stopped server""" assert self.testServer.stop() - assert not self.testServer.stop() + assert self.testServer.stop() def test_serverDoubleStart(self): """!Test to start the server twice""" @@ -145,7 +145,7 @@ class Test_ServerClient: assert self.testServer1.start() assert not self.testServer2.start() assert self.testServer1.stop() - assert not self.testServer2.stop() + assert self.testServer2.stop() def test_serverGetOutput(self, useServer): """!Send data to server with 2 clients, check '[ack]' and data on server queue""" diff --git a/test/test_config.py b/test/test_config.py index 4868317..03cda7e 100644 --- a/test/test_config.py +++ b/test/test_config.py @@ -17,7 +17,9 @@ import logging from boswatch.utils import paths -from boswatch.config import Config +from boswatch import configYaml + +# FIXME complete tests class Test_Config: @@ -28,80 +30,74 @@ class Test_Config: def test_loadLocalConfig(self): """!load a local config file""" - bwConfig = Config() - bwConfig.loadConfigFile(paths.TEST_PATH + "test.ini") - assert bwConfig._config is not None + bwConfig = configYaml.loadConfigFile(paths.TEST_PATH + "test.yaml") + assert bwConfig is not None def test_getLocalConfig(self): """!get values from local config file""" - bwConfig = Config() - bwConfig.loadConfigFile(paths.TEST_PATH + "test.ini") - assert bwConfig.getInt("test", "one") == 1 - assert bwConfig.getBool("test", "one") is True - assert bwConfig.getStr("test", "two") == "two" - assert bwConfig.getStr("testcase", "test") == "ok" + bwConfig = configYaml.loadConfigFile(paths.TEST_PATH + "test.yaml") + assert bwConfig["types"]["integer"] == 11 + assert bwConfig["types"]["boolean"] is True def test_getLocalConfigFailed(self): """!fail while get values from local config file""" - bwConfig = Config() - bwConfig.loadConfigFile(paths.TEST_PATH + "test.ini") - assert bwConfig.getStr("test", "abc") is None - assert bwConfig.getStr("abc", "test") is None + bwConfig = configYaml.loadConfigFile(paths.TEST_PATH + "test.yaml") + assert bwConfig["test"]["abc"] is None + assert bwConfig["abc"]["test"] is None def test_shareConfig(self): """!load local config file and share it""" - bwConfig = Config() - bwConfig.loadConfigFile(paths.TEST_PATH + "test.ini", "test_shareConfig") - assert bwConfig._sharePoints["test_shareConfig"] is not None + configYaml.loadConfigFile(paths.TEST_PATH + "test.yaml", "test_shareConfig") + assert configYaml.loadConfigSharepoint("test_shareConfig") is not None - def test_shareConfigUsed(self): - """!load local config file and tr to share it twice with same name""" - bwConfig1 = Config() - bwConfig1.loadConfigFile(paths.TEST_PATH + "test.ini", "test_shareConfigUsed") - assert bwConfig1._sharePoints["test_shareConfigUsed"] is not None - bwConfig2 = Config() - bwConfig2.loadConfigFile(paths.TEST_PATH + "test.ini") - assert not bwConfig2._shareConfig("test_shareConfigUsed") - - def test_getNotSetSharedConfig(self): - """!try to get values from shared config where not exists""" - bwConfig = Config() - bwConfig.loadConfigFile(paths.TEST_PATH + "test.ini") - assert bwConfig.getInt("test", "one") == 1 - assert bwConfig.getInt("test", "one", "NotSetSharedConfig") is None - - def test_getSharedConfig(self): - """!get values from shared config file""" - bwConfig1 = Config() - bwConfig1.loadConfigFile(paths.TEST_PATH + "test.ini", "test_getSharedConfig") - assert bwConfig1._sharePoints["test_getSharedConfig"] is not None - - bwConfig2 = Config() - assert bwConfig2.getStr("test", "one") is None - assert bwConfig2.getInt("test", "one", "test_getSharedConfig") == 1 - - def test_getSharedConfigFailed(self): - """!fail while get values from shared config file""" - bwConfig1 = Config() - bwConfig1.loadConfigFile(paths.TEST_PATH + "test.ini", "test_getSharedConfigFailed") - assert bwConfig1._sharePoints["test_getSharedConfigFailed"] is not None - - bwConfig2 = Config() - assert bwConfig2.getStr("test", "abc", "test_getSharedConfigFailed") is None - assert bwConfig2.getStr("abc", "test", "test_getSharedConfigFailed") is None - - def test_getDataTypes(self): - bwConfig = Config() - bwConfig.loadConfigFile(paths.TEST_PATH + "test.ini") - assert bwConfig.getStr("testcase", "test") == "ok" - assert bwConfig.getInt("test", "one") == 1 - assert bwConfig.getInt("boolTest", "three") == 0 - assert bwConfig.getBool("boolTest", "one") - assert bwConfig.getBool("boolTest", "two") - assert not bwConfig.getBool("boolTest", "three") - assert not bwConfig.getBool("boolTest", "four") - - def test_getAllSharepoints(self): - bwConfig = Config() - bwConfig.loadConfigFile(paths.TEST_PATH + "test.ini", "test_shareConfig") - assert bwConfig.getAllSharepoints() is not None + # def test_shareConfigUsed(self): + # """!load local config file and tr to share it twice with same name""" + # bwConfig1 = Config() + # bwConfig1.loadConfigFile(paths.TEST_PATH + "test.yaml", "test_shareConfigUsed") + # assert bwConfig1._sharePoints["test_shareConfigUsed"] is not None + # bwConfig2 = Config() + # bwConfig2.loadConfigFile(paths.TEST_PATH + "test.yaml") + # assert not bwConfig2._shareConfig("test_shareConfigUsed") + # + # def test_getNotSetSharedConfig(self): + # """!try to get values from shared config where not exists""" + # bwConfig = Config() + # bwConfig.loadConfigFile(paths.TEST_PATH + "test.yaml") + # assert bwConfig.getInt("test", "one") == 1 + # assert bwConfig.getInt("test", "one", "NotSetSharedConfig") is None + # + # def test_getSharedConfig(self): + # """!get values from shared config file""" + # bwConfig1 = Config() + # bwConfig1.loadConfigFile(paths.TEST_PATH + "test.yaml", "test_getSharedConfig") + # assert bwConfig1._sharePoints["test_getSharedConfig"] is not None + # + # bwConfig2 = Config() + # assert bwConfig2.getStr("test", "one") is None + # assert bwConfig2.getInt("test", "one", "test_getSharedConfig") == 1 + # + # def test_getSharedConfigFailed(self): + # """!fail while get values from shared config file""" + # bwConfig1 = Config() + # bwConfig1.loadConfigFile(paths.TEST_PATH + "test.yaml", "test_getSharedConfigFailed") + # assert bwConfig1._sharePoints["test_getSharedConfigFailed"] is not None + # + # bwConfig2 = Config() + # assert bwConfig2.getStr("test", "abc", "test_getSharedConfigFailed") is None + # assert bwConfig2.getStr("abc", "test", "test_getSharedConfigFailed") is None + # + # def test_getDataTypes(self): + # bwConfig = Config() + # bwConfig.loadConfigFile(paths.TEST_PATH + "test.yaml") + # assert bwConfig.getStr("testcase", "test") == "ok" + # assert bwConfig.getInt("test", "one") == 1 + # assert bwConfig.getInt("boolTest", "three") == 0 + # assert bwConfig.getBool("boolTest", "one") + # assert bwConfig.getBool("boolTest", "two") + # assert not bwConfig.getBool("boolTest", "three") + # assert not bwConfig.getBool("boolTest", "four") + # + # def test_getAllSharepoints(self): + # bwConfig = Config() + # bwConfig.loadConfigFile(paths.TEST_PATH + "test.yaml", "test_shareConfig") + # assert bwConfig.getAllSharepoints() is not None diff --git a/test/test_packet.py b/test/test_packet.py index 77fef07..e1d5a17 100644 --- a/test/test_packet.py +++ b/test/test_packet.py @@ -55,13 +55,3 @@ class Test_Packet: """!set and get a field""" buildPacket.set("testField", "test") assert buildPacket.get("testField") is "test" - - def test_addClientData(self, buildPacket): - """!add client data to packet""" - buildPacket.addClientData() - assert buildPacket.get("clientVersion") - - def test_addServerData(self, buildPacket): - """!add server data to packet""" - buildPacket.addServerData() - assert buildPacket.get("serverVersion")