From b1a3a68e35b5e35e62f9c19ee2365bd0b2365f2b Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Tue, 26 Feb 2019 15:16:52 +0100 Subject: [PATCH 01/11] first yaml test --- config/client.yaml | 49 ++++++++++++++++++++++++++++++++++++++++++++++ yaml_test.py | 28 ++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 config/client.yaml create mode 100644 yaml_test.py diff --git a/config/client.yaml b/config/client.yaml new file mode 100644 index 0000000..5358312 --- /dev/null +++ b/config/client.yaml @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# ____ ____ ______ __ __ __ _____ +# / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / +# / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < +# / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / +#/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ +# German BOS Information Script +# by Bastian Schroll + +client: + name: "BW3 Client" + inputSource: "stick" + +server: + - name: "Server one" + ip: "127.0.0.1" + port: 8080 + + - name: "Server two" + ip: "11.12.13.14" + port: 5000 + +# stick or audio +inputSource: + stick: + device: 0 + frequency: "85.000M" + PPMError: 0 + Squelch: 0 + Gain: 100 + audio: + +decoder: + fms: yes + zvei: yes + poc512: yes + poc1200: yes + poc2400: yes + +doubleFilter: + - name: "Filter one" + MaxEntry: 30 + IgnoreTime: 10 + CheckMsg: no + - name: "Filter two" + MaxEntry: 30 + IgnoreTime: 10 + CheckMsg: no + diff --git a/yaml_test.py b/yaml_test.py new file mode 100644 index 0000000..175d63d --- /dev/null +++ b/yaml_test.py @@ -0,0 +1,28 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +"""! + ____ ____ ______ __ __ __ _____ + / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / + / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < + / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / +/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ + German BOS Information Script + by Bastian Schroll +""" + +import yaml +import pprint +pp = pprint.PrettyPrinter(indent=4) + +with open('config/client.yaml') as f: + # use safe_load instead load + dataMap = yaml.safe_load(f) + +pp.pprint(dataMap) + + +#print(dataMap["decoder"]["fms"]) + +for server in dataMap["server"]: + print(server["ip"]) + From 90ccbf9d0d5819fc240b6a0a627a5cfdd2e657a1 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Wed, 27 Feb 2019 08:02:40 +0100 Subject: [PATCH 02/11] use new yaml config loader in client --- boswatch/config_yaml.py | 79 +++++++++++++++++++++++++++++++++++++++++ bw_client.py | 8 ++--- config/client.yaml | 31 ++++++---------- yaml_test.py | 28 --------------- 4 files changed, 93 insertions(+), 53 deletions(-) create mode 100644 boswatch/config_yaml.py delete mode 100644 yaml_test.py diff --git a/boswatch/config_yaml.py b/boswatch/config_yaml.py new file mode 100644 index 0000000..be40fac --- /dev/null +++ b/boswatch/config_yaml.py @@ -0,0 +1,79 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +"""! + ____ ____ ______ __ __ __ _____ + / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / + / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < + / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / +/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ + German BOS Information Script + by Bastian Schroll + +@file: config_yaml.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/bw_client.py b/bw_client.py index 4cb4d56..1ad813a 100644 --- a/bw_client.py +++ b/bw_client.py @@ -43,7 +43,7 @@ try: import time logging.debug("Import BOSWatch modules") - from boswatch.config import Config + from boswatch import config_yaml from boswatch.network.client import TCPClient from boswatch.decoder.decoder import Decoder from boswatch.utils import header @@ -69,14 +69,14 @@ try: 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: + bwConfig = config_yaml.loadConfigFile(paths.CONFIG_PATH + args.config, "clientConfig") + if bwConfig is None: logging.exception("cannot load config file") print("cannot load config file") exit(1) # without config cannot _run bwClient = TCPClient() - if bwClient.connect(bwConfig.getStr("Server", "IP"), bwConfig.getInt("Server", "PORT")): + if bwClient.connect(bwConfig["servers"][0]["ip"], bwConfig["servers"][0]["port"]): while 1: for i in range(0, 5): diff --git a/config/client.yaml b/config/client.yaml index 5358312..022313b 100644 --- a/config/client.yaml +++ b/config/client.yaml @@ -8,27 +8,27 @@ # by Bastian Schroll client: - name: "BW3 Client" - inputSource: "stick" + name: BW3 Client # name of the BW3 Client instance + inputSource: stick # possible is 'stick' or 'audio' + useBroadcast: yes # use broadcast function to find server -server: - - name: "Server one" - ip: "127.0.0.1" +servers: # only used if useBroadcast = no + - name: Server one + ip: 127.0.0.1 port: 8080 - - name: "Server two" - ip: "11.12.13.14" + - name: Server two + ip: 11.12.13.14 port: 5000 -# stick or audio inputSource: stick: device: 0 - frequency: "85.000M" + frequency: 85.000M PPMError: 0 Squelch: 0 Gain: 100 - audio: + audio: # not implemented yet decoder: fms: yes @@ -36,14 +36,3 @@ decoder: poc512: yes poc1200: yes poc2400: yes - -doubleFilter: - - name: "Filter one" - MaxEntry: 30 - IgnoreTime: 10 - CheckMsg: no - - name: "Filter two" - MaxEntry: 30 - IgnoreTime: 10 - CheckMsg: no - diff --git a/yaml_test.py b/yaml_test.py deleted file mode 100644 index 175d63d..0000000 --- a/yaml_test.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -"""! - ____ ____ ______ __ __ __ _____ - / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / - / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < - / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / -/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ - German BOS Information Script - by Bastian Schroll -""" - -import yaml -import pprint -pp = pprint.PrettyPrinter(indent=4) - -with open('config/client.yaml') as f: - # use safe_load instead load - dataMap = yaml.safe_load(f) - -pp.pprint(dataMap) - - -#print(dataMap["decoder"]["fms"]) - -for server in dataMap["server"]: - print(server["ip"]) - From 60912ce7054363a188360ea8e41729ff3b107183 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Wed, 27 Feb 2019 08:39:54 +0100 Subject: [PATCH 03/11] first tests with yaml config --- boswatch/{config_yaml.py => configYaml.py} | 2 +- boswatch/filter/doubeFilter.py | 8 +-- boswatch/packet/packet.py | 14 ++--- bw_client.py | 8 +-- bw_server.py | 17 +----- config/client.ini | 49 ---------------- config/client.yaml | 17 +++--- config/server.yaml | 68 ++++++++++++++++++++++ 8 files changed, 94 insertions(+), 89 deletions(-) rename boswatch/{config_yaml.py => configYaml.py} (98%) delete mode 100644 config/client.ini create mode 100644 config/server.yaml diff --git a/boswatch/config_yaml.py b/boswatch/configYaml.py similarity index 98% rename from boswatch/config_yaml.py rename to boswatch/configYaml.py index be40fac..05dce6e 100644 --- a/boswatch/config_yaml.py +++ b/boswatch/configYaml.py @@ -9,7 +9,7 @@ German BOS Information Script by Bastian Schroll -@file: config_yaml.py +@file: configYaml.py @date: 27.02.2019 @author: Bastian Schroll @description: Module for the configuration in yaml format 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/packet/packet.py b/boswatch/packet/packet.py index bf0103c..87510ec 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"]["stick"]["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/bw_client.py b/bw_client.py index 1ad813a..20b6c01 100644 --- a/bw_client.py +++ b/bw_client.py @@ -43,7 +43,7 @@ try: import time logging.debug("Import BOSWatch modules") - from boswatch import config_yaml + from boswatch import configYaml from boswatch.network.client import TCPClient from boswatch.decoder.decoder import Decoder from boswatch.utils import header @@ -69,14 +69,14 @@ try: parser.add_argument("-t", "--test", help="Client will send some testdata", action="store_true") # todo implement testmode args = parser.parse_args() - bwConfig = config_yaml.loadConfigFile(paths.CONFIG_PATH + args.config, "clientConfig") + bwConfig = configYaml.loadConfigFile(paths.CONFIG_PATH + args.config, "clientConfig") if bwConfig is None: logging.exception("cannot load config file") print("cannot load config file") - exit(1) # without config cannot _run + exit(1) # without config cannot run bwClient = TCPClient() - if bwClient.connect(bwConfig["servers"][0]["ip"], bwConfig["servers"][0]["port"]): + if bwClient.connect(bwConfig["server"]["ip"], bwConfig["server"]["port"]): while 1: for i in range(0, 5): diff --git a/bw_server.py b/bw_server.py index fcdab23..7c8982a 100644 --- a/bw_server.py +++ b/bw_server.py @@ -44,7 +44,7 @@ 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 @@ -96,8 +96,8 @@ 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: + bwConfig = configYaml.loadConfigFile(paths.CONFIG_PATH + args.config, "serverConfig") + if bwConfig is None: logging.exception("cannot load config file") print("cannot load config file") exit(1) # without config cannot run @@ -107,14 +107,6 @@ try: bwPluginManager.importAllPlugins() bwPluginManager.loadAllPlugins() - 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() serverPaused = False # flag to pause alarming of server @@ -176,9 +168,6 @@ try: bwPacket.set("clientIP", data[0]) bwPacket.addServerData() - if bwConfig.getBool("Description", bwPacket.get("mode")): - bwDescriptor.addDescriptions(bwPacket) - bwPluginManager.runAllPlugins(bwPacket) # print(bwPacket.get("clientVersion")["major"]) incomingQueue.task_done() 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 index 022313b..a099a95 100644 --- a/config/client.yaml +++ b/config/client.yaml @@ -10,16 +10,13 @@ client: name: BW3 Client # name of the BW3 Client instance inputSource: stick # possible is 'stick' or 'audio' - useBroadcast: yes # use broadcast function to find server +# useBroadcast: yes # use broadcast function to find server -servers: # only used if useBroadcast = no - - name: Server one - ip: 127.0.0.1 - port: 8080 - - - name: Server two - ip: 11.12.13.14 - port: 5000 +# atm only one server possible +server: # only used if useBroadcast = no + name: Server one + ip: 127.0.0.1 + port: 8080 inputSource: stick: @@ -30,7 +27,7 @@ inputSource: Gain: 100 audio: # not implemented yet -decoder: +decoder: # not implemented yet fms: yes zvei: yes poc512: yes diff --git a/config/server.yaml b/config/server.yaml new file mode 100644 index 0000000..d321a82 --- /dev/null +++ b/config/server.yaml @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# ____ ____ ______ __ __ __ _____ +# / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / +# / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < +# / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / +#/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ +# German BOS Information Script +# by Bastian Schroll + +server: + name: BW3 Server # name of the BW3 Server instance + +filter: + doubleFilter: + maxEntry: 30 + ignoreTime: 10 + checkMsg: no +#[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 From 5f38de181298e17b100ffc06e3d16bcb91d42827 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Wed, 27 Feb 2019 08:43:45 +0100 Subject: [PATCH 04/11] add requirement --- _info/requirements.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 From 54b4c1439adcf95fe005bb618674770ddd154559 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Wed, 27 Feb 2019 09:21:25 +0100 Subject: [PATCH 05/11] remove two not possible tests --- test/test_packet.py | 10 ---------- 1 file changed, 10 deletions(-) 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") From e2ca436e5dcab6bd5eeb269537f51ce4ca0a638d Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Wed, 27 Feb 2019 12:08:55 +0100 Subject: [PATCH 06/11] make client ready for broadcast function --- boswatch/network/broadcast.py | 6 ++++++ boswatch/packet/packet.py | 2 +- bw_client.py | 24 ++++++++++++++++++++---- bw_server.py | 9 +-------- config/client.yaml | 13 +++++-------- 5 files changed, 33 insertions(+), 21 deletions(-) diff --git a/boswatch/network/broadcast.py b/boswatch/network/broadcast.py index cfaf0d4..7f9da4b 100644 --- a/boswatch/network/broadcast.py +++ b/boswatch/network/broadcast.py @@ -101,6 +101,12 @@ 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 diff --git a/boswatch/packet/packet.py b/boswatch/packet/packet.py index 87510ec..600588c 100644 --- a/boswatch/packet/packet.py +++ b/boswatch/packet/packet.py @@ -80,7 +80,7 @@ class Packet: self.set("clientBuildDate", version.date) self.set("clientBranch", version.branch) self.set("inputSource", config["client"]["inputSource"]) - self.set("frequency", config["inputSource"]["stick"]["frequency"]) + self.set("frequency", config["inputSource"]["sdr"]["frequency"]) def addServerData(self): """!Add the server information to the decoded data diff --git a/bw_client.py b/bw_client.py index 20b6c01..67ff76b 100644 --- a/bw_client.py +++ b/bw_client.py @@ -45,6 +45,7 @@ try: logging.debug("Import BOSWatch modules") 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 @@ -71,12 +72,27 @@ try: bwConfig = configYaml.loadConfigFile(paths.CONFIG_PATH + args.config, "clientConfig") if bwConfig is None: - logging.exception("cannot load config file") - print("cannot load config file") - exit(1) # without config cannot run + logging.error("cannot load config file") + +except Exception as e: # 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["server"]["ip"], bwConfig["server"]["port"]): + if bwClient.connect(ip, port): while 1: for i in range(0, 5): diff --git a/bw_server.py b/bw_server.py index 7c8982a..c695d16 100644 --- a/bw_server.py +++ b/bw_server.py @@ -61,15 +61,8 @@ except Exception as e: # pragma: no cover # 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 diff --git a/config/client.yaml b/config/client.yaml index a099a95..2f9b09a 100644 --- a/config/client.yaml +++ b/config/client.yaml @@ -9,25 +9,22 @@ client: name: BW3 Client # name of the BW3 Client instance - inputSource: stick # possible is 'stick' or 'audio' -# useBroadcast: yes # use broadcast function to find server + inputSource: sdr # atm only 'sdr' is possible + useBroadcast: no # use broadcast to find server automatically -# atm only one server possible -server: # only used if useBroadcast = no - name: Server one +server: # only used if useBroadcast = no ip: 127.0.0.1 port: 8080 inputSource: - stick: + sdr: device: 0 frequency: 85.000M PPMError: 0 Squelch: 0 Gain: 100 - audio: # not implemented yet -decoder: # not implemented yet +decoder: fms: yes zvei: yes poc512: yes From a879f274073c23b62c756a8d4464e994c3476012 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Wed, 27 Feb 2019 12:41:29 +0100 Subject: [PATCH 07/11] remove old config class --- boswatch/config.py | 131 ------------------------------- boswatch/plugin/plugin.py | 7 +- boswatch/plugin/pluginManager.py | 6 +- config/server.ini | 60 -------------- config/server.yaml | 6 ++ plugins/template/template.ini | 4 - plugins/template/template.yaml | 4 + 7 files changed, 16 insertions(+), 202 deletions(-) delete mode 100644 boswatch/config.py delete mode 100644 config/server.ini delete mode 100644 plugins/template/template.ini create mode 100644 plugins/template/template.yaml 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/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/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 index d321a82..4a24d79 100644 --- a/config/server.yaml +++ b/config/server.yaml @@ -10,11 +10,16 @@ server: name: BW3 Server # name of the BW3 Server instance +plugins: + template: 1 + filter: doubleFilter: maxEntry: 30 ignoreTime: 10 checkMsg: no + + #[Server] #PORT = 8080 #Name = BW3 Server @@ -66,3 +71,4 @@ filter: ## the higher the number the earlier the plugin is called on alarm ## we call ist Plugin Prioority #template = 1 + 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 From a8a4116464a998d9be0e06ad335174dcc7269762 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Wed, 27 Feb 2019 13:06:41 +0100 Subject: [PATCH 08/11] edit config_tests --- test/test.ini | 12 ---- test/test.yaml | 5 ++ test/test_config.py | 132 +++++++++++++++++++++----------------------- 3 files changed, 69 insertions(+), 80 deletions(-) delete mode 100644 test/test.ini create mode 100644 test/test.yaml 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_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 From 031f19063bb47209eedd6f5e68e389be63d12615 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Wed, 27 Feb 2019 14:29:17 +0100 Subject: [PATCH 09/11] add simple router config --- config/server.yaml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/config/server.yaml b/config/server.yaml index 4a24d79..85ef068 100644 --- a/config/server.yaml +++ b/config/server.yaml @@ -20,6 +20,32 @@ filter: 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: + #[Server] #PORT = 8080 #Name = BW3 Server From cc680b578f5d0a830dd8f0c0578d957542806f3f Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Wed, 27 Feb 2019 22:05:59 +0100 Subject: [PATCH 10/11] simplify server and and client --- bw_client.py | 14 +++---- bw_server.py | 96 ++++++++++------------------------------------ config/server.yaml | 61 ++++------------------------- 3 files changed, 34 insertions(+), 137 deletions(-) diff --git a/bw_client.py b/bw_client.py index 67ff76b..e355d27 100644 --- a/bw_client.py +++ b/bw_client.py @@ -48,10 +48,9 @@ try: 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: @@ -67,14 +66,13 @@ 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 = configYaml.loadConfigFile(paths.CONFIG_PATH + args.config, "clientConfig") if bwConfig is None: logging.error("cannot load config file") -except Exception as e: # pragma: no cover +except: # pragma: no cover logging.exception("error occurred") exit(1) @@ -95,12 +93,12 @@ try: 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 c695d16..8838cbb 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) @@ -53,27 +54,10 @@ try: 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() -server.start() - - -# 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() @@ -91,78 +75,40 @@ try: bwConfig = configYaml.loadConfigFile(paths.CONFIG_PATH + args.config, "serverConfig") if bwConfig is None: - logging.exception("cannot load config file") - print("cannot load config file") - exit(1) # without config cannot run + logging.error("cannot load config file") - bwPluginManager = PluginManager() - bwPluginManager.searchPluginDir() - bwPluginManager.importAllPlugins() - bwPluginManager.loadAllPlugins() +except: # pragma: no cover + logging.exception("error occurred") + exit(1) - bwDoubleFilter = DoubleFilter() - serverPaused = False # flag to pause alarming of server - serverStop = False # flag to stop the whole server application +# ############################# begin server system +try: - # 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() - bwPluginManager.runAllPlugins(bwPacket) - # print(bwPacket.get("clientVersion")["major"]) + # todo implement routing + incomingQueue.task_done() except KeyboardInterrupt: # pragma: no cover @@ -176,10 +122,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/server.yaml b/config/server.yaml index 85ef068..fb1b90f 100644 --- a/config/server.yaml +++ b/config/server.yaml @@ -8,8 +8,16 @@ # 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 @@ -45,56 +53,3 @@ router: - name: Router 2 route: - -#[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 - From 9371b71ee035c0457a16734eb1b36008f62c9a93 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Thu, 28 Feb 2019 08:57:41 +0100 Subject: [PATCH 11/11] add isRunning/isConnected Props to server and client --- boswatch/network/broadcast.py | 4 +-- boswatch/network/client.py | 33 +++++++++++++------ boswatch/network/server.py | 60 +++++++++++++++++++++-------------- bw_server.py | 4 --- test/test_ServerClient.py | 6 ++-- 5 files changed, 66 insertions(+), 41 deletions(-) diff --git a/boswatch/network/broadcast.py b/boswatch/network/broadcast.py index 7f9da4b..6684843 100644 --- a/boswatch/network/broadcast.py +++ b/boswatch/network/broadcast.py @@ -112,7 +112,7 @@ class BroadcastServer: @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" @@ -136,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/bw_server.py b/bw_server.py index 8838cbb..7144e45 100644 --- a/bw_server.py +++ b/bw_server.py @@ -48,11 +48,7 @@ try: 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: # pragma: no cover logging.exception("cannot import modules") 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"""