From ca82806cf595a34b4f6921b4aa71417f3940df03 Mon Sep 17 00:00:00 2001 From: JHCD Date: Sun, 21 Jun 2015 18:28:05 +0200 Subject: [PATCH 01/98] add an jsonUDP-plugin send data via UDP as a json-string --- config/config.template.ini | 6 +++ plugins/jsonUDP/jsonUDP.py | 107 +++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 plugins/jsonUDP/jsonUDP.py diff --git a/config/config.template.ini b/config/config.template.ini index 64d21372..58b67270 100644 --- a/config/config.template.ini +++ b/config/config.template.ini @@ -88,6 +88,7 @@ httpRequest = 0 eMail = 0 BosMon = 0 firEmergency = 0 +jsonUDP = 0 # for developing template-module template = 0 @@ -194,6 +195,11 @@ bosmon_password = firserver = localhost firport = 9001 +[jsonUDP] +# Server as IP of DNS-Name (without http://) +server = 192.168.0.1 +port = 8888 + ##################### ##### Not ready yet # diff --git a/plugins/jsonUDP/jsonUDP.py b/plugins/jsonUDP/jsonUDP.py new file mode 100644 index 00000000..ed21f8fc --- /dev/null +++ b/plugins/jsonUDP/jsonUDP.py @@ -0,0 +1,107 @@ +#!/usr/bin/python +# -*- coding: cp1252 -*- + +""" +json-Plugin to dispatch FMS-, ZVEI- and POCSAG - messages via UDP + +@author: Jens Herrmann + +@requires: jsonUDP-Configuration has to be set in the config.ini +""" + +import logging # Global logger + +import socket # for udp-connection +import json # for data + +from includes import globals # Global variables + +## +# +# Main function of jsonUDP-plugin +# will be called by the alarmHandler +# +def run(typ,freq,data): + """ + This function is the implementation of the jsonUDP-Plugin. + It will send the data via UDP + + The configuration for the UDP-Connection is set in the config.ini. + + @type typ: string (FMS|ZVEI|POC) + @param typ: Typ of the dataset for sending via UDP + @type data: map of data (structure see interface.txt) + @param data: Contains the parameter for dispatch to UDP. + @type freq: string + @keyword freq: frequency of the SDR Stick + + @requires: jsonUDP-Configuration has to be set in the config.ini + + @return: nothing + @exception: Exception if ConfigParser failed + @exception: Exception if connect to UDP-Server failed + @exception: Exception if sending the UDP-message failed + """ + try: + # + # ConfigParser + # + logging.debug("reading config file") + try: + for key,val in globals.config.items("jsonUDP"): + logging.debug(" - %s = %s", key, val) + + except: + logging.exception("cannot read config file") + + try: + # + # initialize to UDP-Server + # + # SOCK_DGRAM is the socket type to use for UDP sockets + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + except: + logging.exception("cannot initialize UDP-socket") + + else: + + if typ == "FMS": + logging.debug("Start FMS to UDP") + try: + # convert data to json + sendData = json.dumps(data) + # send UDP + sock.sendto(sendData, (globals.config.get("jsonUDP", "server"), globals.config.getint("jsonUDP", "port"))) + except: + logging.exception("FMS to UDP failed") + + elif typ == "ZVEI": + logging.debug("Start ZVEI to UDP") + try: + # convert data to json + sendData = json.dumps(data) + # send UDP + sock.sendto(sendData, (globals.config.get("jsonUDP", "server"), globals.config.getint("jsonUDP", "port"))) + except: + logging.exception("ZVEI to UDP failed") + + elif typ == "POC": + logging.debug("Start POC to UDP") + try: + # convert data to json + sendData = json.dumps(data) + # send UDP + sock.sendto(sendData, (globals.config.get("jsonUDP", "server"), globals.config.getint("jsonUDP", "port"))) + except: + logging.exception("POC to UDP failed") + + else: + logging.warning("Invalid Typ: %s", typ) + + finally: + logging.debug("close UDP-Connection") + sock.close() + + except: + logging.exception("") \ No newline at end of file From f2fcbf4ca51c3de6f808de1152162d0ec15e8f80 Mon Sep 17 00:00:00 2001 From: JHCD Date: Mon, 22 Jun 2015 18:00:39 +0200 Subject: [PATCH 02/98] add TCP-support to jsonSocket-Plugin rename plugin from jsonUDP to jsonSocket --- config/config.template.ini | 6 +- plugins/jsonSocket/jsonSocket.py | 93 +++++++++++++++++++++++++++ plugins/jsonUDP/jsonUDP.py | 107 ------------------------------- 3 files changed, 97 insertions(+), 109 deletions(-) create mode 100644 plugins/jsonSocket/jsonSocket.py delete mode 100644 plugins/jsonUDP/jsonUDP.py diff --git a/config/config.template.ini b/config/config.template.ini index 58b67270..6162d51c 100644 --- a/config/config.template.ini +++ b/config/config.template.ini @@ -88,7 +88,7 @@ httpRequest = 0 eMail = 0 BosMon = 0 firEmergency = 0 -jsonUDP = 0 +jsonSocket = 0 # for developing template-module template = 0 @@ -195,7 +195,9 @@ bosmon_password = firserver = localhost firport = 9001 -[jsonUDP] +[jsonSocket] +# Protocol for socket (TCP|UDP) +protocol = UDP # Server as IP of DNS-Name (without http://) server = 192.168.0.1 port = 8888 diff --git a/plugins/jsonSocket/jsonSocket.py b/plugins/jsonSocket/jsonSocket.py new file mode 100644 index 00000000..f1a95b7f --- /dev/null +++ b/plugins/jsonSocket/jsonSocket.py @@ -0,0 +1,93 @@ +#!/usr/bin/python +# -*- coding: cp1252 -*- + +""" +jsonSocket-Plugin to dispatch FMS-, ZVEI- and POCSAG-messages via UDP/TCP + +@author: Jens Herrmann + +@requires: jsonSocket-Configuration has to be set in the config.ini +""" + +import logging # Global logger + +import socket # for connection +import json # for data-transfer + +from includes import globals # Global variables + +## +# +# Main function of jsonSocket-plugin +# will be called by the alarmHandler +# +def run(typ,freq,data): + """ + This function is the implementation of the jsonSocket-Plugin. + It will send the data via UDP/TCP + + The configuration for the Connection is set in the config.ini. + + @type typ: string (FMS|ZVEI|POC) + @param typ: Typ of the dataset for sending via UDP/TCP + @type data: map of data (structure see interface.txt) + @param data: Contains the parameter for dispatch to UDP. + @type freq: string + @keyword freq: frequency of the SDR Stick + + @requires: jsonSocket-Configuration has to be set in the config.ini + + @return: nothing + @exception: Exception if ConfigParser failed + @exception: Exception if connect to socket-Server failed + @exception: Exception if sending the socket-message failed + """ + try: + # + # ConfigParser + # + logging.debug("reading config file") + try: + for key,val in globals.config.items("jsonSocket"): + logging.debug(" - %s = %s", key, val) + + except: + logging.exception("cannot read config file") + + try: + # + # initialize to socket-Server + # + # SOCK_DGRAM is the socket type to use for UDP sockets + # SOCK_STREAM is the socket type to use for TCP sockets + if globals.config.get("jsonSocket", "protocol") == "TCP": + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((globals.config.get("jsonSocket", "server"), globals.config.getint("jsonSocket", "port"))) + else: + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + except: + logging.exception("cannot initialize %s-socket", globals.config.get("jsonSocket", "protocol")) + + else: + + supportedTypes = ["FMS", "ZVEI", "POC"] + if typ in supportedTypes: + logging.debug("Start %s to %s", typ, globals.config.get("jsonSocket", "protocol")) + try: + # convert data to json + sendData = json.dumps(data) + # send data + sock.sendto(sendData, (globals.config.get("jsonSocket", "server"), globals.config.getint("jsonSocket", "port"))) + except: + logging.exception("%s to %s failed", typ, globals.config.get("jsonSocket", "protocol")) + + else: + logging.warning("Invalid Typ: %s", typ) + + finally: + logging.debug("close %s-Connection", globals.config.get("jsonSocket", "protocol")) + sock.close() + + except: + logging.exception("") \ No newline at end of file diff --git a/plugins/jsonUDP/jsonUDP.py b/plugins/jsonUDP/jsonUDP.py deleted file mode 100644 index ed21f8fc..00000000 --- a/plugins/jsonUDP/jsonUDP.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- - -""" -json-Plugin to dispatch FMS-, ZVEI- and POCSAG - messages via UDP - -@author: Jens Herrmann - -@requires: jsonUDP-Configuration has to be set in the config.ini -""" - -import logging # Global logger - -import socket # for udp-connection -import json # for data - -from includes import globals # Global variables - -## -# -# Main function of jsonUDP-plugin -# will be called by the alarmHandler -# -def run(typ,freq,data): - """ - This function is the implementation of the jsonUDP-Plugin. - It will send the data via UDP - - The configuration for the UDP-Connection is set in the config.ini. - - @type typ: string (FMS|ZVEI|POC) - @param typ: Typ of the dataset for sending via UDP - @type data: map of data (structure see interface.txt) - @param data: Contains the parameter for dispatch to UDP. - @type freq: string - @keyword freq: frequency of the SDR Stick - - @requires: jsonUDP-Configuration has to be set in the config.ini - - @return: nothing - @exception: Exception if ConfigParser failed - @exception: Exception if connect to UDP-Server failed - @exception: Exception if sending the UDP-message failed - """ - try: - # - # ConfigParser - # - logging.debug("reading config file") - try: - for key,val in globals.config.items("jsonUDP"): - logging.debug(" - %s = %s", key, val) - - except: - logging.exception("cannot read config file") - - try: - # - # initialize to UDP-Server - # - # SOCK_DGRAM is the socket type to use for UDP sockets - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - - except: - logging.exception("cannot initialize UDP-socket") - - else: - - if typ == "FMS": - logging.debug("Start FMS to UDP") - try: - # convert data to json - sendData = json.dumps(data) - # send UDP - sock.sendto(sendData, (globals.config.get("jsonUDP", "server"), globals.config.getint("jsonUDP", "port"))) - except: - logging.exception("FMS to UDP failed") - - elif typ == "ZVEI": - logging.debug("Start ZVEI to UDP") - try: - # convert data to json - sendData = json.dumps(data) - # send UDP - sock.sendto(sendData, (globals.config.get("jsonUDP", "server"), globals.config.getint("jsonUDP", "port"))) - except: - logging.exception("ZVEI to UDP failed") - - elif typ == "POC": - logging.debug("Start POC to UDP") - try: - # convert data to json - sendData = json.dumps(data) - # send UDP - sock.sendto(sendData, (globals.config.get("jsonUDP", "server"), globals.config.getint("jsonUDP", "port"))) - except: - logging.exception("POC to UDP failed") - - else: - logging.warning("Invalid Typ: %s", typ) - - finally: - logging.debug("close UDP-Connection") - sock.close() - - except: - logging.exception("") \ No newline at end of file From 74c804f4c3e139bfe0bf7b7998df3cc9662eea7b Mon Sep 17 00:00:00 2001 From: JHCD Date: Tue, 23 Jun 2015 17:59:43 +0200 Subject: [PATCH 03/98] change exception-handling - only error-msg instead of logging.exception - second logging.debug with exec-trace --- plugins/jsonSocket/jsonSocket.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/plugins/jsonSocket/jsonSocket.py b/plugins/jsonSocket/jsonSocket.py index f1a95b7f..4da30121 100644 --- a/plugins/jsonSocket/jsonSocket.py +++ b/plugins/jsonSocket/jsonSocket.py @@ -38,9 +38,6 @@ def run(typ,freq,data): @requires: jsonSocket-Configuration has to be set in the config.ini @return: nothing - @exception: Exception if ConfigParser failed - @exception: Exception if connect to socket-Server failed - @exception: Exception if sending the socket-message failed """ try: # @@ -52,7 +49,8 @@ def run(typ,freq,data): logging.debug(" - %s = %s", key, val) except: - logging.exception("cannot read config file") + logging.error("cannot read config file") + logging.debug("cannot read config file", exc_info=True) try: # @@ -67,20 +65,22 @@ def run(typ,freq,data): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) except: - logging.exception("cannot initialize %s-socket", globals.config.get("jsonSocket", "protocol")) + logging.error("cannot initialize %s-socket", globals.config.get("jsonSocket", "protocol")) + logging.debug("cannot initialize %s-socket", globals.config.get("jsonSocket", "protocol"), exc_info=True) else: - + # toDo is equals for all types, so only check if typ is supported supportedTypes = ["FMS", "ZVEI", "POC"] if typ in supportedTypes: logging.debug("Start %s to %s", typ, globals.config.get("jsonSocket", "protocol")) try: - # convert data to json + # dump data to json-string sendData = json.dumps(data) # send data sock.sendto(sendData, (globals.config.get("jsonSocket", "server"), globals.config.getint("jsonSocket", "port"))) except: - logging.exception("%s to %s failed", typ, globals.config.get("jsonSocket", "protocol")) + logging.error("%s to %s failed", typ, globals.config.get("jsonSocket", "protocol")) + logging.debug("%s to %s failed", typ, globals.config.get("jsonSocket", "protocol"), exc_info=True) else: logging.warning("Invalid Typ: %s", typ) @@ -90,4 +90,6 @@ def run(typ,freq,data): sock.close() except: - logging.exception("") \ No newline at end of file + # something very mysterious + logging.error("unknown error") + logging.debug("unknown error", exc_info=True) \ No newline at end of file From c32beae4bb651af3725f1bbf8df5a1d9e4a4678c Mon Sep 17 00:00:00 2001 From: JHCD Date: Tue, 23 Jun 2015 18:37:32 +0200 Subject: [PATCH 04/98] change exception-handling - only error-msg instead of logging.exception - second logging.debug with exec-trace --- includes/alarmHandler.py | 21 ++++++++++++++----- includes/decoders/poc.py | 2 ++ plugins/BosMon/BosMon.py | 36 +++++++++++++++++++++----------- plugins/jsonSocket/jsonSocket.py | 2 ++ plugins/template/template.py | 36 +++++++++++++++++++++++++++----- 5 files changed, 75 insertions(+), 22 deletions(-) diff --git a/includes/alarmHandler.py b/includes/alarmHandler.py index 4a1b9c54..fa4ab19f 100644 --- a/includes/alarmHandler.py +++ b/includes/alarmHandler.py @@ -43,12 +43,23 @@ def processAlarm(typ,freq,data): from includes import filter if filter.checkFilters(typ,data,pluginName,freq): logging.debug("call Plugin: %s", pluginName) - plugin.run(typ,freq,data) - logging.debug("return from: %s", pluginName) + try: + plugin.run(typ,freq,data) + logging.debug("return from: %s", pluginName) + except: + # call next plugin, if one has thrown an exception + logging.debug("return from: %s", pluginName, exc_info=True) + pass else: # RegEX filter off - call plugin directly logging.debug("call Plugin: %s", pluginName) - plugin.run(typ,freq,data) - logging.debug("return from: %s", pluginName) + try: + plugin.run(typ,freq,data) + logging.debug("return from: %s", pluginName) + except: + # call next plugin, if one has thrown an exception + logging.debug("return from: %s", pluginName, exc_info=True) + pass logging.debug("[END ALARM]") except: - logging.exception("Error in Alarm processing") \ No newline at end of file + logging.error("Error in Alarm processing") + logging.debug("Error in Alarm processing", exc_info=True) \ No newline at end of file diff --git a/includes/decoders/poc.py b/includes/decoders/poc.py index 4f8abc06..ce4d570a 100644 --- a/includes/decoders/poc.py +++ b/includes/decoders/poc.py @@ -105,6 +105,8 @@ def decode(freq, decoded): if re.search("[0-9]{7}", poc_id): #if POC is valid if isAllowed(poc_id): # check for double alarm + logging.debug(" - old id: %s ", globals.poc_id_old) + logging.debug(" - old time: %s ", globals.poc_time_old) if poc_id == globals.poc_id_old and timestamp < globals.poc_time_old + globals.config.getint("POC", "double_ignore_time"): logging.info("POCSAG%s double alarm: %s within %s second(s)", bitrate, globals.poc_id_old, timestamp-globals.poc_time_old) # in case of double alarm, poc_double_ignore_time set new diff --git a/plugins/BosMon/BosMon.py b/plugins/BosMon/BosMon.py index 968c4236..cf5da656 100644 --- a/plugins/BosMon/BosMon.py +++ b/plugins/BosMon/BosMon.py @@ -35,7 +35,6 @@ def bosMonRequest(httprequest, params, headers): @param headers: The headers argument should be a mapping of extra HTTP headers to send with the request. @return: nothing - @exception: Exception if httprequest.request failed """ try: # @@ -43,7 +42,9 @@ def bosMonRequest(httprequest, params, headers): # httprequest.request("POST", "/telegramin/"+globals.config.get("BosMon", "bosmon_channel")+"/input.xml", params, headers) except: - logging.exception("request to BosMon failed") + logging.error("request to BosMon failed") + logging.debug("request to BosMon failed", exc_info=True) + raise Exception("request to BosMon failed") else: # # check HTTP-Response @@ -77,9 +78,6 @@ def run(typ,freq,data): @requires: BosMon-Configuration has to be set in the config.ini @return: nothing - @exception: Exception if ConfigParser failed - @exception: Exception if initialize header and connect to BosMon-Server failed - @exception: Exception if urlencoding the params failed """ try: # @@ -90,7 +88,10 @@ def run(typ,freq,data): for key,val in globals.config.items("BosMon"): logging.debug(" - %s = %s", key, val) except: - logging.exception("cannot read config file") + logging.error("cannot read config file") + logging.debug("cannot read config file", exc_info=True) + # Without config, plugin couldn't work + return try: # @@ -105,11 +106,14 @@ def run(typ,freq,data): headers['Authorization'] = "Basic {0}".format(base64.b64encode("{0}:{1}".format(globals.config.get("BosMon", "bosmon_user"), globals.config.get("BosMon", "bosmon_password")))) logging.debug("connect to BosMon") # open connection to BosMon-Server - httprequest = httplib.HTTPConnection(globals.config.get("BosMon", "bosmon_server"), globals.config.get("BosMon", "bosmon_port")) + httprequest = httplib.HTTPConnection(globals.config.get("BosMon", "bosmon_server"), globals.config.get("BosMon", "bosmon_port"), timeout=5) # debug-level to shell (0=no debug|1) httprequest.set_debuglevel(0) except: - logging.exception("cannot connect to BosMon") + logging.error("cannot connect to BosMon") + logging.debug("cannot connect to BosMon", exc_info=True) + # Without connection, plugin couldn't work + return else: # @@ -141,7 +145,9 @@ def run(typ,freq,data): # dispatch the BosMon-request bosMonRequest(httprequest, params, headers) except: - logging.exception("FMS to BosMon failed") + logging.error("FMS to BosMon failed") + logging.debug("FMS to BosMon failed", exc_info=True) + return elif typ == "ZVEI": logging.debug("Start ZVEI to BosMon") @@ -151,7 +157,9 @@ def run(typ,freq,data): # dispatch the BosMon-request bosMonRequest(httprequest, params, headers) except: - logging.exception("ZVEI to BosMon failed") + logging.error("ZVEI to BosMon failed") + logging.debug("ZVEI to BosMon failed", exc_info=True) + return elif typ == "POC": logging.debug("Start POC to BosMon") @@ -162,7 +170,9 @@ def run(typ,freq,data): # dispatch the BosMon-request bosMonRequest(httprequest, params, headers) except: - logging.exception("POC to BosMon failed") + logging.error("POC to BosMon failed") + logging.debug("POC to BosMon failed", exc_info=True) + return else: logging.warning("Invalid Typ: %s", typ) @@ -172,4 +182,6 @@ def run(typ,freq,data): httprequest.close() except: - logging.exception("") \ No newline at end of file + # something very mysterious + logging.error("unknown error") + logging.debug("unknown error", exc_info=True) \ No newline at end of file diff --git a/plugins/jsonSocket/jsonSocket.py b/plugins/jsonSocket/jsonSocket.py index 4da30121..69766a01 100644 --- a/plugins/jsonSocket/jsonSocket.py +++ b/plugins/jsonSocket/jsonSocket.py @@ -51,6 +51,8 @@ def run(typ,freq,data): except: logging.error("cannot read config file") logging.debug("cannot read config file", exc_info=True) + # Without config, plugin couldn't work + return try: # diff --git a/plugins/template/template.py b/plugins/template/template.py index 5e99e1aa..85a92e9d 100644 --- a/plugins/template/template.py +++ b/plugins/template/template.py @@ -24,17 +24,42 @@ from includes import globals # Global variables - +## +# +# Main function of plugin +# will be called by the alarmHandler +# def run(typ,freq,data): + """ + This function is the implementation of the Plugin. + + If necessary the configuration hast to be set in the config.ini. + + @type typ: string (FMS|ZVEI|POC) + @param typ: Typ of the dataset + @type data: map of data (structure see interface.txt) + @param data: Contains the parameter for dispatch + @type freq: string + @keyword freq: frequency of the SDR Stick + + @requires: If necessary the configuration hast to be set in the config.ini. + + @return: nothing + """ try: - #ConfigParser + # + # ConfigParser + # logging.debug("reading config file") try: for key,val in globals.config.items("template"): logging.debug(" - %s = %s", key, val) except: - logging.exception("cannot read config file") - + logging.error("cannot read config file") + logging.debug("cannot read config file", exc_info=True) + # Without config, plugin couldn't work + return + ########## User Plugin CODE ########## if typ == "FMS": logging.warning("%s not supported", typ) @@ -47,4 +72,5 @@ def run(typ,freq,data): ########## User Plugin CODE ########## except: - logging.exception("unknown error") \ No newline at end of file + logging.error("unknown error") + logging.debug("unknown error", exc_info=True) \ No newline at end of file From d6b917411223d23ee0ae40643ceca4eb4f720b35 Mon Sep 17 00:00:00 2001 From: JHCD Date: Tue, 23 Jun 2015 22:27:48 +0200 Subject: [PATCH 05/98] change exception-handling - only error-msg instead of logging.exception - second logging.debug with exec-trace --- includes/alarmHandler.py | 5 +--- includes/decoders/fms.py | 11 +++++--- includes/decoders/poc.py | 13 ++++++---- includes/decoders/zvei.py | 11 +++++--- plugins/BosMon/BosMon.py | 16 +++++++----- plugins/MySQL/MySQL.py | 32 +++++++++++++++-------- plugins/eMail/eMail.py | 38 ++++++++++++++++++++-------- plugins/firEmergency/firEmergency.py | 34 +++++++++++++++++-------- plugins/httpRequest/httpRequest.py | 25 ++++++++++++------ plugins/jsonSocket/jsonSocket.py | 8 +++++- 10 files changed, 132 insertions(+), 61 deletions(-) diff --git a/includes/alarmHandler.py b/includes/alarmHandler.py index fa4ab19f..adb8e231 100644 --- a/includes/alarmHandler.py +++ b/includes/alarmHandler.py @@ -48,7 +48,6 @@ def processAlarm(typ,freq,data): logging.debug("return from: %s", pluginName) except: # call next plugin, if one has thrown an exception - logging.debug("return from: %s", pluginName, exc_info=True) pass else: # RegEX filter off - call plugin directly logging.debug("call Plugin: %s", pluginName) @@ -57,9 +56,7 @@ def processAlarm(typ,freq,data): logging.debug("return from: %s", pluginName) except: # call next plugin, if one has thrown an exception - logging.debug("return from: %s", pluginName, exc_info=True) pass logging.debug("[END ALARM]") except: - logging.error("Error in Alarm processing") - logging.debug("Error in Alarm processing", exc_info=True) \ No newline at end of file + logging.exception("Error in alarm processing") \ No newline at end of file diff --git a/includes/decoders/fms.py b/includes/decoders/fms.py index 3ef24f22..02da649e 100644 --- a/includes/decoders/fms.py +++ b/includes/decoders/fms.py @@ -62,9 +62,14 @@ def decode(freq, decoded): from includes import descriptionList data["description"] = descriptionList.getDescription("FMS", fms_id[0:8]) # processing the alarm - from includes import alarmHandler - alarmHandler.processAlarm("FMS",freq,data) - + try: + from includes import alarmHandler + alarmHandler.processAlarm("POC",freq,data) + except: + logging.error("processing alarm failed") + logging.debug("processing alarm failed", exc_info=True) + pass + # in every time save old data for double alarm globals.fms_id_old = fms_id #save last id globals.fms_time_old = timestamp #save last time else: diff --git a/includes/decoders/poc.py b/includes/decoders/poc.py index ce4d570a..ceba9134 100644 --- a/includes/decoders/poc.py +++ b/includes/decoders/poc.py @@ -105,8 +105,6 @@ def decode(freq, decoded): if re.search("[0-9]{7}", poc_id): #if POC is valid if isAllowed(poc_id): # check for double alarm - logging.debug(" - old id: %s ", globals.poc_id_old) - logging.debug(" - old time: %s ", globals.poc_time_old) if poc_id == globals.poc_id_old and timestamp < globals.poc_time_old + globals.config.getint("POC", "double_ignore_time"): logging.info("POCSAG%s double alarm: %s within %s second(s)", bitrate, globals.poc_id_old, timestamp-globals.poc_time_old) # in case of double alarm, poc_double_ignore_time set new @@ -121,9 +119,14 @@ def decode(freq, decoded): from includes import descriptionList data["description"] = descriptionList.getDescription("POC", poc_id) # processing the alarm - from includes import alarmHandler - alarmHandler.processAlarm("POC",freq,data) - + try: + from includes import alarmHandler + alarmHandler.processAlarm("POC",freq,data) + except: + logging.error("processing alarm failed") + logging.debug("processing alarm failed", exc_info=True) + pass + # in every time save old data for double alarm globals.poc_id_old = poc_id #save last id globals.poc_time_old = timestamp #save last time else: diff --git a/includes/decoders/zvei.py b/includes/decoders/zvei.py index 789d5da5..e941e75e 100644 --- a/includes/decoders/zvei.py +++ b/includes/decoders/zvei.py @@ -74,9 +74,14 @@ def decode(freq, decoded): from includes import descriptionList data["description"] = descriptionList.getDescription("ZVEI", zvei_id) # processing the alarm - from includes import alarmHandler - alarmHandler.processAlarm("ZVEI",freq,data) - + try: + from includes import alarmHandler + alarmHandler.processAlarm("POC",freq,data) + except: + logging.error("processing alarm failed") + logging.debug("processing alarm failed", exc_info=True) + pass + # in every time save old data for double alarm globals.zvei_id_old = zvei_id # save last id globals.zvei_time_old = timestamp # save last time else: diff --git a/plugins/BosMon/BosMon.py b/plugins/BosMon/BosMon.py index cf5da656..9b9aed68 100644 --- a/plugins/BosMon/BosMon.py +++ b/plugins/BosMon/BosMon.py @@ -35,6 +35,7 @@ def bosMonRequest(httprequest, params, headers): @param headers: The headers argument should be a mapping of extra HTTP headers to send with the request. @return: nothing + @exception: Exception if HTTP-Request failed """ try: # @@ -44,7 +45,7 @@ def bosMonRequest(httprequest, params, headers): except: logging.error("request to BosMon failed") logging.debug("request to BosMon failed", exc_info=True) - raise Exception("request to BosMon failed") + raise else: # # check HTTP-Response @@ -94,7 +95,7 @@ def run(typ,freq,data): return try: - # + # # Initialize header an connect to BosMon-Server # headers = {} @@ -116,7 +117,7 @@ def run(typ,freq,data): return else: - # + # # Format given data-structure to compatible BosMon string # if typ == "FMS": @@ -179,9 +180,12 @@ def run(typ,freq,data): finally: logging.debug("close BosMon-Connection") - httprequest.close() - - except: + try: + httprequest.close() + except: + pass + + except: # something very mysterious logging.error("unknown error") logging.debug("unknown error", exc_info=True) \ No newline at end of file diff --git a/plugins/MySQL/MySQL.py b/plugins/MySQL/MySQL.py index 887d314b..2ef31a6f 100644 --- a/plugins/MySQL/MySQL.py +++ b/plugins/MySQL/MySQL.py @@ -43,19 +43,20 @@ def run(typ,freq,data): @requires: Created Database/Tables, see boswatch.sql @return: nothing - @exception: Exception if ConfigParser failed - @exception: Exception if connect to MySQL failed - @exception: Exception if executing the sql-statement is failed """ - try: + # #ConfigParser + # logging.debug("reading config file") try: for key,val in globals.config.items("MySQL"): logging.debug(" - %s = %s", key, val) except: - logging.exception("cannot read config file") + logging.error("cannot read config file") + logging.debug("cannot read config file", exc_info=True) + # Without config, plugin couldn't work + return try: # @@ -65,7 +66,11 @@ def run(typ,freq,data): connection = mysql.connector.connect(host = globals.config.get("MySQL","dbserver"), user = globals.config.get("MySQL","dbuser"), passwd = globals.config.get("MySQL","dbpassword"), db = globals.config.get("MySQL","database")) cursor = connection.cursor() except: - logging.exception("cannot connect to MySQL") + logging.error("cannot connect to MySQL") + logging.debug("cannot connect to MySQL", exc_info=True) + # Without connection, plugin couldn't work + return + else: try: # @@ -89,11 +94,18 @@ def run(typ,freq,data): else: logging.warning("Invalid Typ: %s", typ) except: - logging.exception("cannot Insert %s", typ) + logging.error("cannot Insert %s", typ) + logging.debug("cannot Insert %s", typ, exc_info=True) + return finally: logging.debug("close MySQL") - cursor.close() - connection.close() #Close connection in every case + try: + cursor.close() + connection.close() #Close connection in every case + except: + pass + except: - logging.exception("unknown error") \ No newline at end of file + logging.error("unknown error") + logging.debug("unknown error", exc_info=True) \ No newline at end of file diff --git a/plugins/eMail/eMail.py b/plugins/eMail/eMail.py index 24477a55..f879431f 100644 --- a/plugins/eMail/eMail.py +++ b/plugins/eMail/eMail.py @@ -54,7 +54,9 @@ def doSendmail(server, subject, mailtext): msg['Priority'] = globals.config.get("eMail", "priority") server.sendmail(globals.config.get("eMail", "from"), globals.config.get("eMail", "to"), msg.as_string()) except: - logging.exception("send eMail failed") + logging.error("send eMail failed") + logging.debug("send eMail failed", exc_info=True) + raise ## @@ -80,9 +82,6 @@ def run(typ,freq,data): @requires: eMail-Configuration has to be set in the config.ini @return: nothing - @exception: Exception if ConfigParser failed - @exception: Exception if connect to SMTP-Server failed - @exception: Exception if sending the eMail failed """ try: # @@ -94,7 +93,10 @@ def run(typ,freq,data): logging.debug(" - %s = %s", key, val) except: - logging.exception("cannot read config file") + logging.error("cannot read config file") + logging.debug("cannot read config file", exc_info=True) + # Without config, plugin couldn't work + return try: # @@ -113,7 +115,10 @@ def run(typ,freq,data): server.login(globals.config.get("eMail", "user"), globals.config.get("eMail", "password")) except: - logging.exception("cannot connect to eMail") + logging.error("cannot connect to eMail") + logging.debug("cannot connect to eMail", exc_info=True) + # Without connection, plugin couldn't work + return else: @@ -137,7 +142,9 @@ def run(typ,freq,data): # send eMail doSendmail(server, subject, mailtext) except: - logging.exception("FMS to eMail failed") + logging.error("%s to eMail failed", typ) + logging.debug("%s to eMail failed", typ, exc_info=True) + return elif typ == "ZVEI": logging.debug("Start ZVEI to eMail") @@ -155,7 +162,9 @@ def run(typ,freq,data): # send eMail doSendmail(server, subject, mailtext) except: - logging.exception("ZVEI to eMail failed") + logging.error("%s to eMail failed", typ) + logging.debug("%s to eMail failed", typ, exc_info=True) + return elif typ == "POC": logging.debug("Start POC to eMail") @@ -177,14 +186,21 @@ def run(typ,freq,data): # send eMail doSendmail(server, subject, mailtext) except: - logging.exception("POC to eMail failed") + logging.error("%s to eMail failed", typ) + logging.debug("%s to eMail failed", typ, exc_info=True) + return else: logging.warning("Invalid Typ: %s", typ) finally: logging.debug("close eMail-Connection") - server.quit() + try: + server.quit() + except: + pass except: - logging.exception("") \ No newline at end of file + # something very mysterious + logging.error("unknown error") + logging.debug("unknown error", exc_info=True) \ No newline at end of file diff --git a/plugins/firEmergency/firEmergency.py b/plugins/firEmergency/firEmergency.py index 3b2a4b20..83cbcb6f 100644 --- a/plugins/firEmergency/firEmergency.py +++ b/plugins/firEmergency/firEmergency.py @@ -36,9 +36,6 @@ def run(typ,freq,data): @requires: firEmergency-Configuration has to be set in the config.ini @return: nothing - @exception: Exception if ConfigParser failed - @exception: Exception ifconnect to firEmergency failed - @exception: Exception if sending the data failed """ try: # @@ -49,7 +46,10 @@ def run(typ,freq,data): for key,val in globals.config.items("firEmergency"): logging.debug(" - %s = %s", key, val) except: - logging.exception("cannot read config file") + logging.error("cannot read config file") + logging.debug("cannot read config file", exc_info=True) + # Without config, plugin couldn't work + return try: # @@ -58,7 +58,11 @@ def run(typ,freq,data): firSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) firSocket.connect((globals.config.get("firEmergency", "firserver"), globals.config.getint("firEmergency", "firport"))) except: - logging.exception("cannot connect to firEmergency") + logging.error("cannot connect to firEmergency") + logging.debug("cannot connect to firEmergency", exc_info=True) + # Without connection, plugin couldn't work + return + else: # # Format given data-structure to xml-string for firEmergency @@ -72,22 +76,32 @@ def run(typ,freq,data): firXML = "\n
"+data["zvei"]+"
\n"+data["zvei"]+" alarmiert.\n
\n" firSocket.send(firXML) except: - logging.exception("ZVEI to firEmergency failed") - + logging.error("%s to firEmergency failed", typ) + logging.debug("%s to firEmergency failed", typ, exc_info=True) + # Without connection, plugin couldn't work + return + elif typ == "POC": logging.debug("POC to firEmergency") try: firXML = "\n
"+data["ric"]+"
\n"+data["msg"]+"\n
\n" firSocket.send(firXML) except: - logging.exception("POC to firEmergency failed") + logging.error("%s to firEmergency failed", typ) + logging.debug("%s to firEmergency failed", typ, exc_info=True) + # Without connection, plugin couldn't work + return else: logging.warning("Invalid Typ: %s", typ) finally: logging.debug("close firEmergency-Connection") - firSocket.close() + try: + firSocket.close() + except: + pass except: - logging.exception("unknown error") \ No newline at end of file + logging.error("unknown error") + logging.debug("unknown error", exc_info=True) \ No newline at end of file diff --git a/plugins/httpRequest/httpRequest.py b/plugins/httpRequest/httpRequest.py index da484508..7c5c761e 100644 --- a/plugins/httpRequest/httpRequest.py +++ b/plugins/httpRequest/httpRequest.py @@ -36,9 +36,6 @@ def run(typ,freq,data): @requires: httpRequest-Configuration has to be set in the config.ini @return: nothing - @exception: Exception if ConfigParser failed - @exception: Exception if http Request failed - @exception: Exception if http Response failed """ try: # @@ -49,7 +46,10 @@ def run(typ,freq,data): for key,val in globals.config.items("httpRequest"): logging.debug(" - %s = %s", key, val) except: - logging.exception("cannot read config file") + logging.error("cannot read config file") + logging.debug("cannot read config file", exc_info=True) + # Without config, plugin couldn't work + return try: # @@ -79,7 +79,10 @@ def run(typ,freq,data): httprequest.request("GET", url[5]) #send URL Querry per GET except: - logging.exception("cannot send HTTP request") + logging.error("cannot send HTTP request") + logging.debug("cannot send HTTP request", exc_info=True) + return + else: try: # @@ -91,11 +94,17 @@ def run(typ,freq,data): else: logging.warning("HTTP response: %s - %s" , str(httpresponse.status), str(httpresponse.reason)) except: #otherwise - logging.exception("cannot get HTTP response") + logging.error("cannot get HTTP response") + logging.debug("cannot get HTTP response", exc_info=True) + return finally: logging.debug("close HTTP-Connection") - httprequest.close() + try: + httprequest.close() + except: + pass except: - logging.exception("unknown error") \ No newline at end of file + logging.error("unknown error") + logging.debug("unknown error", exc_info=True) \ No newline at end of file diff --git a/plugins/jsonSocket/jsonSocket.py b/plugins/jsonSocket/jsonSocket.py index 69766a01..010dad6f 100644 --- a/plugins/jsonSocket/jsonSocket.py +++ b/plugins/jsonSocket/jsonSocket.py @@ -69,6 +69,8 @@ def run(typ,freq,data): except: logging.error("cannot initialize %s-socket", globals.config.get("jsonSocket", "protocol")) logging.debug("cannot initialize %s-socket", globals.config.get("jsonSocket", "protocol"), exc_info=True) + # Without connection, plugin couldn't work + return else: # toDo is equals for all types, so only check if typ is supported @@ -83,13 +85,17 @@ def run(typ,freq,data): except: logging.error("%s to %s failed", typ, globals.config.get("jsonSocket", "protocol")) logging.debug("%s to %s failed", typ, globals.config.get("jsonSocket", "protocol"), exc_info=True) + return else: logging.warning("Invalid Typ: %s", typ) finally: logging.debug("close %s-Connection", globals.config.get("jsonSocket", "protocol")) - sock.close() + try: + sock.close() + except: + pass except: # something very mysterious From 3280c68737b653f87dfa73afe93df65a3d0e9a42 Mon Sep 17 00:00:00 2001 From: JHCD Date: Tue, 23 Jun 2015 22:50:33 +0200 Subject: [PATCH 06/98] change exception-handling - only error-msg instead of logging.exception - second logging.debug with exec-trace --- includes/alarmHandler.py | 2 +- includes/decoder.py | 2 +- includes/descriptionList.py | 17 +++++++++++++---- includes/filter.py | 13 ++++++++----- includes/shellHeader.py | 4 ++-- 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/includes/alarmHandler.py b/includes/alarmHandler.py index adb8e231..8934b817 100644 --- a/includes/alarmHandler.py +++ b/includes/alarmHandler.py @@ -32,7 +32,7 @@ def processAlarm(typ,freq,data): @requires: active plugins in pluginList @return: nothing - @exception: Exception if Alarm processing failed + @exception: Exception if Alarm processing itself failed """ try: logging.debug("[ ALARM ]") diff --git a/includes/decoder.py b/includes/decoder.py index 2161968a..7814e596 100644 --- a/includes/decoder.py +++ b/includes/decoder.py @@ -21,7 +21,7 @@ def decode(freq, decoded): @param decoded: RAW Information from Multimon-NG @return: nothing - @exception: Exception if decoder File call failed + @exception: Exception if decoder file call failed """ try: # FMS Decoder Section diff --git a/includes/descriptionList.py b/includes/descriptionList.py index 6f3e0eaa..ebee2bda 100644 --- a/includes/descriptionList.py +++ b/includes/descriptionList.py @@ -25,7 +25,6 @@ def loadCSV(typ, idField): Structure: [id] = description @return: Python list of descriptions - @exception: Exception if loading failed """ resultList = {} try: @@ -40,9 +39,12 @@ def loadCSV(typ, idField): resultList[row[idField]] = row['description'] logging.debug("-- loading csv finished") except: - logging.exception("loading csvList for typ: %s failed", typ) + logging.error("loading csvList for typ: %s failed", typ) + logging.debug("loading csvList for typ: %s failed", typ, exc_info=True) + raise return resultList; + ## # # call this for loading the description lists @@ -70,7 +72,9 @@ def loadDescriptionLists(): globals.ricDescribtionList = loadCSV("poc", "ric") except: - logging.exception("cannot load description lists") + logging.error("cannot load description lists") + logging.debug("cannot load description lists", exc_info=True) + pass ## @@ -95,10 +99,15 @@ def getDescription(typ, id): resultStr = globals.ricDescribtionList[id] else: logging.warning("Invalid Typ: %s", typ) + except KeyError: # will be thrown when there is no description for the id # -> nothing to do... pass + except: - logging.debug("Error during look up description lists") + logging.debug("Error during look up description lists", exc_info=True) + pass + + logging.debug(" - result for %s: %s", id, resultStr) return resultStr \ No newline at end of file diff --git a/includes/filter.py b/includes/filter.py index 4849d50a..8fb91456 100644 --- a/includes/filter.py +++ b/includes/filter.py @@ -23,7 +23,6 @@ def loadFilters(): @requires: Configuration has to be set in the config.ini @return: nothing - @exception: Exception if filter loading failed """ try: logging.debug("loading filters") @@ -34,8 +33,10 @@ def loadFilters(): # insert splitet data into globals.filterList globals.filterList.append({"name": key, "typ": filter[0], "dataField": filter[1], "plugin": filter[2], "freq": freqToHz(filter[3]), "regex": filter[4]}) except: - logging.exception("cannot read config file") - + logging.error("cannot read config file") + logging.debug("cannot read config file", exc_info=True) + return + def checkFilters(typ,data,plugin,freq): """ @@ -54,7 +55,6 @@ def checkFilters(typ,data,plugin,freq): @requires: all filters in the filterList @return: nothing - @exception: Exception if filter check failed """ try: logging.debug("search Filter for %s to %s at %s Hz", typ, plugin, freq) @@ -81,4 +81,7 @@ def checkFilters(typ,data,plugin,freq): return True except: - logging.exception("Error in Filter checking") \ No newline at end of file + logging.error("Error in filter checking") + logging.debug("Error in filter checking", exc_info=True) + # something goes wrong, data will path + return True \ No newline at end of file diff --git a/includes/shellHeader.py b/includes/shellHeader.py index 8d352eb0..2f105c9b 100644 --- a/includes/shellHeader.py +++ b/includes/shellHeader.py @@ -18,7 +18,6 @@ def printHeader(args): @param args: All given arguments from argsparser @return: nothing - @exception: Exception if display of the shell header failed """ try: print " ____ ____ ______ __ __ __ " @@ -49,4 +48,5 @@ def printHeader(args): print "Verbose Mode!" print "" except: - logging.exception("cannot display shell header") \ No newline at end of file + logging.error("cannot display shell header") + logging.debug("cannot display shell header", exc_info=True) \ No newline at end of file From 259239a90b6fbd58339a1fbb10078f45d80eaaac Mon Sep 17 00:00:00 2001 From: JHCD Date: Wed, 24 Jun 2015 23:26:02 +0200 Subject: [PATCH 07/98] prepare boswatch.py for use as a daemon 1.) We had to change the subprocess calls, don't use shell=True if you want to run as daemon, you will never be able to kill the sub-sub-processes 2.) implement signal-handler for TERM signal of the daemon-control --- boswatch.py | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/boswatch.py b/boswatch.py index c8aa067e..b0507fe6 100755 --- a/boswatch.py +++ b/boswatch.py @@ -21,6 +21,8 @@ import os # for log mkdir import time # for timestamp import subprocess # for starting rtl_fm and multimon-ng +import signal # for use as daemon +import sys # throw SystemExitException when daemon is terminated from includes import globals # Global variables @@ -58,6 +60,20 @@ def freqToHz(freq): except: logging.exception("Error in freqToHz()") + +## +# +# TERM-Handler for use script as a daemon +# In order for the Python program to exit gracefully when the TERM signal is received, +# it must have a function that exits the program when signal.SIGTERM is received. +# +def sigterm_handler(_signo, _stack_frame): + import sys + global logging + logging.warning("TERM signal received") + sys.exit(0) + +signal.signal(signal.SIGTERM, sigterm_handler) # # ArgParser @@ -245,11 +261,12 @@ def freqToHz(freq): # Start rtl_fm # logging.debug("starting rtl_fm") - rtl_fm = subprocess.Popen("rtl_fm -d "+str(args.device)+" -f "+str(freqToHz(args.freq))+" -M fm -s 22050 -p "+str(args.error)+" -E DC -F 0 -l "+str(args.squelch)+" -g 100", + command = "rtl_fm -d "+str(args.device)+" -f "+str(freqToHz(args.freq))+" -M fm -s 22050 -p "+str(args.error)+" -E DC -F 0 -l "+str(args.squelch)+" -g 100" + rtl_fm = subprocess.Popen(command.split(), #stdin=rtl_fm.stdout, stdout=subprocess.PIPE, stderr=open(globals.script_path+"/log/rtl_fm.log","a"), - shell=True) + shell=False) except: logging.exception("cannot start rtl_fm") else: @@ -260,11 +277,12 @@ def freqToHz(freq): # Start multimon # logging.debug("starting multimon-ng") - multimon_ng = subprocess.Popen("multimon-ng "+str(demodulation)+" -f alpha -t raw /dev/stdin - ", + command = "multimon-ng "+str(demodulation)+" -f alpha -t raw /dev/stdin - " + multimon_ng = subprocess.Popen(command.split(), stdin=rtl_fm.stdout, stdout=subprocess.PIPE, stderr=open(globals.script_path+"/log/multimon.log","a"), - shell=True) + shell=False) except: logging.exception("cannot start multimon-ng") else: @@ -298,18 +316,28 @@ def freqToHz(freq): except KeyboardInterrupt: logging.warning("Keyboard Interrupt") +except SystemExit: + # SystemExitException is thrown if daemon was terminated + logging.warning("SystemExit received") + # only exit to call finally-block + exit(0) except: logging.exception("unknown error") finally: try: logging.debug("BOSWatch shuting down") - rtl_fm.terminate() - logging.debug("rtl_fm terminated") + logging.debug("terminate multimon-ng (%s)", multimon_ng.pid) multimon_ng.terminate() + multimon_ng.wait() logging.debug("multimon-ng terminated") + logging.debug("terminate rtl_fm (%s)", rtl_fm.pid) + rtl_fm.terminate() + rtl_fm.wait() + logging.debug("rtl_fm terminated") logging.debug("exiting BOSWatch") except: - logging.warning("failed in clean-up routine") + logging.exception("failed in clean-up routine") + finally: # Close Logging logging.debug("close Logging") @@ -317,4 +345,4 @@ def freqToHz(freq): logging.shutdown() fh.close() ch.close() - exit(0) \ No newline at end of file + exit(0) \ No newline at end of file From f58891a8ec4dd1d74fe9050f4100134b9d6b259e Mon Sep 17 00:00:00 2001 From: JHCD Date: Thu, 25 Jun 2015 16:13:52 +0200 Subject: [PATCH 08/98] extract class and functions from boswatch.py to includes --- boswatch.py | 67 ++++---------------------- includes/MyTimedRotatingFileHandler.py | 18 +++++++ includes/converter.py | 29 +++++++++++ includes/signalHandler.py | 32 ++++++++++++ 4 files changed, 89 insertions(+), 57 deletions(-) create mode 100644 includes/MyTimedRotatingFileHandler.py create mode 100644 includes/converter.py create mode 100644 includes/signalHandler.py diff --git a/boswatch.py b/boswatch.py index b0507fe6..efffbab9 100755 --- a/boswatch.py +++ b/boswatch.py @@ -21,59 +21,12 @@ import os # for log mkdir import time # for timestamp import subprocess # for starting rtl_fm and multimon-ng -import signal # for use as daemon -import sys # throw SystemExitException when daemon is terminated from includes import globals # Global variables - -## -# -# This Class extended the TimedRotatingFileHandler with the possibility to change the backupCount after initialization. -# -## -class MyTimedRotatingFileHandler(logging.handlers.TimedRotatingFileHandler): - """Extended Version of TimedRotatingFileHandler""" - def setBackupCount(self, backupCount): - """Set/Change backupCount""" - self.backupCount = backupCount - - -## -# -# convert frequency to Hz -# -def freqToHz(freq): - """ - gets a frequency and resolve it in Hz - - @type freq: string - @param freq: frequency of the SDR Stick - - @return: frequency in Hz - @exception: Exception if Error by recalc - """ - try: - freq = freq.replace("k","e3").replace("M","e6") - # freq has to be interpreted as float first... - # otherwise you will get the error: an invalid literal for int() with base 10 - return int(float(freq)) - except: - logging.exception("Error in freqToHz()") - +from includes import MyTimedRotatingFileHandler # extension of TimedRotatingFileHandler +from includes import converter # converter functions +from includes import signalHandler # TERM-Handler for use script as a daemon -## -# -# TERM-Handler for use script as a daemon -# In order for the Python program to exit gracefully when the TERM signal is received, -# it must have a function that exits the program when signal.SIGTERM is received. -# -def sigterm_handler(_signo, _stack_frame): - import sys - global logging - logging.warning("TERM signal received") - sys.exit(0) - -signal.signal(signal.SIGTERM, sigterm_handler) # # ArgParser @@ -125,7 +78,7 @@ def sigterm_handler(_signo, _stack_frame): # set log string format formatter = logging.Formatter('%(asctime)s - %(module)-15s [%(levelname)-8s] %(message)s', '%d.%m.%Y %H:%M:%S') # create a file logger - fh = MyTimedRotatingFileHandler(globals.script_path+"/log/boswatch.log", "midnight", interval=1, backupCount=999) + fh = MyTimedRotatingFileHandler.MyTimedRotatingFileHandler(globals.script_path+"/log/boswatch.log", "midnight", interval=1, backupCount=999) # Starts with log level >= Debug # will be changed with config.ini-param later fh.setLevel(logging.DEBUG) @@ -163,7 +116,7 @@ def sigterm_handler(_signo, _stack_frame): # # For debug display/log args # - logging.debug(" - Frequency: %s", freqToHz(args.freq)) + logging.debug(" - Frequency: %s", converter.freqToHz(args.freq)) logging.debug(" - Device: %s", args.device) logging.debug(" - PPM Error: %s", args.error) logging.debug(" - Squelch: %s", args.squelch) @@ -261,7 +214,7 @@ def sigterm_handler(_signo, _stack_frame): # Start rtl_fm # logging.debug("starting rtl_fm") - command = "rtl_fm -d "+str(args.device)+" -f "+str(freqToHz(args.freq))+" -M fm -s 22050 -p "+str(args.error)+" -E DC -F 0 -l "+str(args.squelch)+" -g 100" + command = "rtl_fm -d "+str(args.device)+" -f "+str(converter.freqToHz(args.freq))+" -M fm -s 22050 -p "+str(args.error)+" -E DC -F 0 -l "+str(args.squelch)+" -g 100" rtl_fm = subprocess.Popen(command.split(), #stdin=rtl_fm.stdout, stdout=subprocess.PIPE, @@ -308,11 +261,11 @@ def sigterm_handler(_signo, _stack_frame): #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=II (ohneNA,mit SIGNAL)) CRC correct\n'" #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 1=LST->FZG 2=III(mit NA,ohneSIGNAL)) CRC correct\n'" #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=IV (mit NA,mit SIGNAL)) CRC correct\n'" - #decoded = "POCSAG1200: Address: 1234567 Function: 1 Alpha: Hello World" + #decoded = "POCSAG1200: Address: 1664001 Function: 1 Alpha: Hello World" #time.sleep(1) from includes import decoder - decoder.decode(freqToHz(args.freq), decoded) + decoder.decode(converter.freqToHz(args.freq), decoded) except KeyboardInterrupt: logging.warning("Keyboard Interrupt") @@ -336,7 +289,7 @@ def sigterm_handler(_signo, _stack_frame): logging.debug("rtl_fm terminated") logging.debug("exiting BOSWatch") except: - logging.exception("failed in clean-up routine") + logging.warning("failed in clean-up routine") finally: # Close Logging @@ -345,4 +298,4 @@ def sigterm_handler(_signo, _stack_frame): logging.shutdown() fh.close() ch.close() - exit(0) \ No newline at end of file + exit(0) \ No newline at end of file diff --git a/includes/MyTimedRotatingFileHandler.py b/includes/MyTimedRotatingFileHandler.py new file mode 100644 index 00000000..347987a4 --- /dev/null +++ b/includes/MyTimedRotatingFileHandler.py @@ -0,0 +1,18 @@ +#!/usr/bin/python +# -*- coding: cp1252 -*- +# + +""" +This Class extended the TimedRotatingFileHandler with the possibility +to change the backupCount after initialization. + +@author: Jens Herrmann +""" + +import logging + +class MyTimedRotatingFileHandler(logging.handlers.TimedRotatingFileHandler): + """Extended Version of TimedRotatingFileHandler""" + def setBackupCount(self, backupCount): + """Set/Change backupCount""" + self.backupCount = backupCount \ No newline at end of file diff --git a/includes/converter.py b/includes/converter.py new file mode 100644 index 00000000..13ce7ab9 --- /dev/null +++ b/includes/converter.py @@ -0,0 +1,29 @@ +#!/usr/bin/python +# -*- coding: cp1252 -*- +# + +""" +convert frequency to Hz + +@author: Bastian Schroll +""" + +import logging + +def freqToHz(freq): + """ + gets a frequency and resolve it in Hz + + @type freq: string + @param freq: frequency of the SDR Stick + + @return: frequency in Hz + @exception: Exception if Error by recalc + """ + try: + freq = freq.replace("k","e3").replace("M","e6") + # freq has to be interpreted as float first... + # otherwise you will get the error: an invalid literal for int() with base 10 + return int(float(freq)) + except: + logging.exception("Error in freqToHz()") \ No newline at end of file diff --git a/includes/signalHandler.py b/includes/signalHandler.py new file mode 100644 index 00000000..50f40ab5 --- /dev/null +++ b/includes/signalHandler.py @@ -0,0 +1,32 @@ +#!/usr/bin/python +# -*- coding: cp1252 -*- +# + +""" +TERM-Handler for use script as a daemon +In order for the Python program to exit gracefully when the TERM signal is received, +it must have a function that exits the program when signal.SIGTERM is received. + +@author: Jens Herrmann +""" + +import logging +import signal # for use as daemon +import sys # throw SystemExitException when daemon is terminated + +def sigterm_handler(_signo, _stack_frame): + """ + TERM-Handler for use script as a daemon + + @type _signo: signalnum + @param _signo: signal number + @type _stack_frame: frame object + @param _stack_frame: current stack frame + + @exception: SystemExitException when daemon is terminated + """ + logging.warning("TERM signal received") + sys.exit(0) + +# Set the handler for signal to the function handler. +signal.signal(signal.SIGTERM, sigterm_handler) \ No newline at end of file From 00902784a4e9b5458ba57a462bb73ba872087e0a Mon Sep 17 00:00:00 2001 From: JHCD Date: Thu, 25 Jun 2015 17:10:31 +0200 Subject: [PATCH 09/98] add new argument for logfile-location -u --usevarlog Use '/var/log/boswatch' for logfiles instead of subdir 'log' in BOSWatch directory --- boswatch.py | 30 ++++++++++++++++++++---------- includes/globals.py | 1 + 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/boswatch.py b/boswatch.py index efffbab9..41fbf8be 100755 --- a/boswatch.py +++ b/boswatch.py @@ -43,6 +43,7 @@ parser.add_argument("-e", "--error", help="Frequency-Error of your device in PPM", type=int, default=0) parser.add_argument("-a", "--demod", help="Demodulation functions", choices=['FMS', 'ZVEI', 'POC512', 'POC1200', 'POC2400'], required=True, nargs="+") parser.add_argument("-s", "--squelch", help="Level of squelch", type=int, default=0) + parser.add_argument("-u", "--usevarlog", help="Use '/var/log/boswatch' for logfiles instead of subdir 'log' in BOSWatch directory", action="store_true") parser.add_argument("-v", "--verbose", help="Shows more information", action="store_true") parser.add_argument("-q", "--quiet", help="Shows no information. Only logfiles", action="store_true") args = parser.parse_args() @@ -63,12 +64,20 @@ # Script-pathes # globals.script_path = os.path.dirname(os.path.abspath(__file__)) - + + # + # Set log_path + # + if args.usevarlog: + globals.log_path = "/var/log/BOSWatch/" + else: + globals.log_path = globals.script_path+"/log/" + # # If necessary create log-path # - if not os.path.exists(globals.script_path+"/log/"): - os.mkdir(globals.script_path+"/log/") + if not os.path.exists(globals.log_path): + os.mkdir(globals.log_path) # # Create new myLogger... @@ -78,7 +87,7 @@ # set log string format formatter = logging.Formatter('%(asctime)s - %(module)-15s [%(levelname)-8s] %(message)s', '%d.%m.%Y %H:%M:%S') # create a file logger - fh = MyTimedRotatingFileHandler.MyTimedRotatingFileHandler(globals.script_path+"/log/boswatch.log", "midnight", interval=1, backupCount=999) + fh = MyTimedRotatingFileHandler.MyTimedRotatingFileHandler(globals.log_path+"boswatch.log", "midnight", interval=1, backupCount=999) # Starts with log level >= Debug # will be changed with config.ini-param later fh.setLevel(logging.DEBUG) @@ -101,8 +110,8 @@ # Clear the logfiles # fh.doRollover() - rtl_log = open(globals.script_path+"/log/rtl_fm.log", "w") - mon_log = open(globals.script_path+"/log/multimon.log", "w") + rtl_log = open(globals.log_path+"rtl_fm.log", "w") + mon_log = open(globals.log_path+"multimon.log", "w") rtl_log.write("") mon_log.write("") rtl_log.close() @@ -138,6 +147,7 @@ demodulation += "-a POCSAG2400 " logging.debug(" - Demod: POC2400") + logging.debug(" - Use /var/log: %s", args.usevarlog) logging.debug(" - Verbose Mode: %s", args.verbose) logging.debug(" - Quiet Mode: %s", args.quiet) @@ -182,7 +192,7 @@ # # Set the loglevel and backupCount of the file handler # - logging.debug("set loglevel of fileHandler to: %s",globals.config.getint("BOSWatch","loglevel") ) + logging.debug("set loglevel of fileHandler to: %s",globals.config.getint("BOSWatch","loglevel")) fh.setLevel(globals.config.getint("BOSWatch","loglevel")) logging.debug("set backupCount of fileHandler to: %s", globals.config.getint("BOSWatch","backupCount")) fh.setBackupCount(globals.config.getint("BOSWatch","backupCount")) @@ -218,7 +228,7 @@ rtl_fm = subprocess.Popen(command.split(), #stdin=rtl_fm.stdout, stdout=subprocess.PIPE, - stderr=open(globals.script_path+"/log/rtl_fm.log","a"), + stderr=open(globals.log_path+"rtl_fm.log","a"), shell=False) except: logging.exception("cannot start rtl_fm") @@ -234,7 +244,7 @@ multimon_ng = subprocess.Popen(command.split(), stdin=rtl_fm.stdout, stdout=subprocess.PIPE, - stderr=open(globals.script_path+"/log/multimon.log","a"), + stderr=open(globals.log_path+"multimon.log","a"), shell=False) except: logging.exception("cannot start multimon-ng") @@ -261,7 +271,7 @@ #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=II (ohneNA,mit SIGNAL)) CRC correct\n'" #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 1=LST->FZG 2=III(mit NA,ohneSIGNAL)) CRC correct\n'" #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=IV (mit NA,mit SIGNAL)) CRC correct\n'" - #decoded = "POCSAG1200: Address: 1664001 Function: 1 Alpha: Hello World" + #decoded = "POCSAG1200: Address: 1234567 Function: 1 Alpha: Hello World" #time.sleep(1) from includes import decoder diff --git a/includes/globals.py b/includes/globals.py index f2d4e6d6..1e5750a8 100644 --- a/includes/globals.py +++ b/includes/globals.py @@ -11,6 +11,7 @@ # Global variables config = 0 script_path = "" +log_path = "" # double alarm fms_id_old = 0 From 249b3bbf538ec85bb12e3a150cb988a5ba1833dd Mon Sep 17 00:00:00 2001 From: JHCD Date: Thu, 25 Jun 2015 17:38:43 +0200 Subject: [PATCH 10/98] add init script for useing BOSWatch as a daemon see service/README.md for details --- service/README.md | 28 ++++++++++++++++++++ service/boswatch.sh | 62 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 service/README.md create mode 100755 service/boswatch.sh diff --git a/service/README.md b/service/README.md new file mode 100644 index 00000000..cdcf79b8 --- /dev/null +++ b/service/README.md @@ -0,0 +1,28 @@ +### Start BOSWatch as a daemon + +## Changing the init script + +Lines 14 and 15 define where to find the Python script. +In this case the script expects that there is a folder `/usr/local/bin/BOSWatch` and that the script is inside there. + +Line 23 sets what user to run the script as. Using root is generally not a good idea but might be necessary for BOSWatch. + +Line 19 sets the parameters for BOSWatch, use the same as starting BOSWatch from the shell. +We recommend to use "-u" and "-q" when you want to run BOSWatch as a daemon. +- "-u": You will find the logfiles in `/var/log/BOSWatch` +- "-q": Shows no information. Only logfiles + +## Using the init script + +To actually use this script, put your Python script where you want (recommend `/usr/local/bin/BOSWatch`) +and make sure it is executable (e.g. `sudo chmod 755 boswatch.py`) +Edit the init script accordingly. Copy the init script into /etc/init.d using e.g. `sudo cp boswatch.sh /etc/init.d`. +Make sure the script is executable (chmod again) and make sure that it has UNIX line-endings. + +At this point you should be able to start your Python script using the command `sudo /etc/init.d/boswatch.sh start`, +check its status with the `sudo /etc/init.d/boswatch.sh status` argument and stop it with `sudo /etc/init.d/boswatch.sh stop`. + +To make the Raspberry Pi use your init script at the right time, one more step is required: +Running the command `sudo update-rc.d boswatch.sh defaults`. +This command adds in symbolic links to the `/etc/rc.x` directories so that the init script is run at the default times. +You can see these links if you do ls -l /etc/rc?.d/*myservice.sh \ No newline at end of file diff --git a/service/boswatch.sh b/service/boswatch.sh new file mode 100755 index 00000000..bbfacba1 --- /dev/null +++ b/service/boswatch.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides: BOSWatch +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Python Service to receive and decode German BOS Information with rtl_fm and multimon-NG +# Description: Python Service to receive and decode German BOS Information with rtl_fm and multimon-NG +### END INIT INFO + +# Change the next 3 lines to suit where you install your script and what you want to call it +DIR=/usr/local/bin/BOSWatch +DAEMON=$DIR/boswatch.py +DAEMON_NAME=boswatch + +# Add any command line options for your daemon here +DAEMON_OPTS="-f xxx -a yyy -s zz -u -q" + +# This next line determines what user the script runs as. +# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python. +DAEMON_USER=root + +# The process ID of the script when it runs is stored here: +PIDFILE=/var/run/$DAEMON_NAME.pid + +. /lib/lsb/init-functions + +do_start () { + log_daemon_msg "Starting system $DAEMON_NAME daemon" + start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS + log_end_msg $? +} +do_stop () { + log_daemon_msg "Stopping system $DAEMON_NAME daemon" + start-stop-daemon --stop --pidfile $PIDFILE --retry 10 + log_end_msg $? +} + +case "$1" in + + start|stop) + do_${1} + ;; + + restart|reload|force-reload) + do_stop + do_start + ;; + + status) + status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $? + ;; + + *) + echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}" + exit 1 + ;; + +esac +exit 0 From 72208d80c68fd6b373750624f247c047567ae3f9 Mon Sep 17 00:00:00 2001 From: JHCD Date: Thu, 25 Jun 2015 17:40:09 +0200 Subject: [PATCH 11/98] update readme --- README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index eb2c636e..9a4b50e4 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,10 @@ unless you are developer you can use the develop-Branch - may be unstable! - Filtering data for each typ/plugin combination with RegEX - All configurations in a seperate config file - Data validation (plausibility test) +- Description look-up from csv-files - Logfiles for better troubleshooting - verbose/quiet mode for more/none information +- Ready for use BOSWatch as daemon ##### Features for the future: - more plugins @@ -34,6 +36,7 @@ unless you are developer you can use the develop-Branch - may be unstable! - eMail (send Mails [FMS|ZVEI|POC]) - BosMon (send data to BosMon server [FMS|ZVEI|POC]) - firEmergency (send data to firEmergency server [ZVEI|POC]) +- jsonSocket (send data as jsonString to a socket server [FMS|ZVEI|POC]) - for more Information to the plugins see `config.ini` @@ -90,12 +93,13 @@ usage: boswatch.py [-h] -f FREQ [-d DEVICE] [-e ERROR] -a optional arguments: -h, --help show this help message and exit -f FREQ, --freq FREQ Frequency you want to listen - -d DEVICE, --device DEVICE Device you want to use (Check with rtl_test) + -d DEVICE, --device DEVICE Device you want to use (Check with rtl_test) -e ERROR, --error ERROR Frequency-Error of your device in PPM -a {FMS,ZVEI,POC512,POC1200,POC2400} [{FMS,ZVEI,POC512,POC1200,POC2400} ...], --demod {FMS,ZVEI,POC512,POC1200,POC2400} [{FMS,ZVEI,POC512,POC1200,POC2400} ...] - Demodulation functions - -s SQUELCH, --squelch SQUELCH level of squelch + Demodulation functions + -s SQUELCH, --squelch SQUELCH level of squelch + -u, --usevarlog Use '/var/log/boswatch' for logfiles instead of subdir 'log' in BOSWatch directory -v, --verbose Shows more information -q, --quiet Shows no information. Only logfiles ``` @@ -115,6 +119,10 @@ In case of an error during the installation, check the logfile in `~/boswatch/in Caution, script don't install a webserver with PHP and MySQL. So you have to make up manually if you want to use MySQL support. +If you want to use BOSWatch as a daemon, you have to set your +configuration in `service/boswatch.sh` and copy it to `/etc/init.d`. +Then you can start BOSWatch with `sudo /etc/init.d/boswatch.sh start`. +For configuration-details see `service/README.md`. ### Requirements - RTL_SDR (rtl_fm) From 727379c237c31137c331eca898bbd819d741add0 Mon Sep 17 00:00:00 2001 From: JHCD Date: Thu, 25 Jun 2015 18:56:46 +0200 Subject: [PATCH 12/98] small changes --- service/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/service/README.md b/service/README.md index cdcf79b8..3af43e70 100644 --- a/service/README.md +++ b/service/README.md @@ -1,21 +1,21 @@ ### Start BOSWatch as a daemon -## Changing the init script +##### Changing the init script Lines 14 and 15 define where to find the Python script. In this case the script expects that there is a folder `/usr/local/bin/BOSWatch` and that the script is inside there. -Line 23 sets what user to run the script as. Using root is generally not a good idea but might be necessary for BOSWatch. +Line 23 sets what user to run the script as. Using a root-user is necessary for BOSWatch. Line 19 sets the parameters for BOSWatch, use the same as starting BOSWatch from the shell. We recommend to use "-u" and "-q" when you want to run BOSWatch as a daemon. - "-u": You will find the logfiles in `/var/log/BOSWatch` - "-q": Shows no information. Only logfiles -## Using the init script +##### Using the init script To actually use this script, put your Python script where you want (recommend `/usr/local/bin/BOSWatch`) -and make sure it is executable (e.g. `sudo chmod 755 boswatch.py`) +and make sure it is executable (e.g. `sudo chmod 755 boswatch.py`). Edit the init script accordingly. Copy the init script into /etc/init.d using e.g. `sudo cp boswatch.sh /etc/init.d`. Make sure the script is executable (chmod again) and make sure that it has UNIX line-endings. @@ -25,4 +25,4 @@ check its status with the `sudo /etc/init.d/boswatch.sh status` argument and sto To make the Raspberry Pi use your init script at the right time, one more step is required: Running the command `sudo update-rc.d boswatch.sh defaults`. This command adds in symbolic links to the `/etc/rc.x` directories so that the init script is run at the default times. -You can see these links if you do ls -l /etc/rc?.d/*myservice.sh \ No newline at end of file +You can see these links if you do ls -l /etc/rc?.d/*boswatch.sh \ No newline at end of file From f54debb44eccb732bda6b76e767e3332f8826477 Mon Sep 17 00:00:00 2001 From: JHCD Date: Thu, 25 Jun 2015 19:46:59 +0200 Subject: [PATCH 13/98] solve bug: rtl-fm and multimon-ng not found (daemon) the programs are not in the path when you want to start the daemon on systemstart --- boswatch.py | 4 ++-- service/README.md | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/boswatch.py b/boswatch.py index 41fbf8be..d160c72b 100755 --- a/boswatch.py +++ b/boswatch.py @@ -224,7 +224,7 @@ # Start rtl_fm # logging.debug("starting rtl_fm") - command = "rtl_fm -d "+str(args.device)+" -f "+str(converter.freqToHz(args.freq))+" -M fm -s 22050 -p "+str(args.error)+" -E DC -F 0 -l "+str(args.squelch)+" -g 100" + command = "/usr/local/bin/rtl_fm -d "+str(args.device)+" -f "+str(converter.freqToHz(args.freq))+" -M fm -s 22050 -p "+str(args.error)+" -E DC -F 0 -l "+str(args.squelch)+" -g 100" rtl_fm = subprocess.Popen(command.split(), #stdin=rtl_fm.stdout, stdout=subprocess.PIPE, @@ -240,7 +240,7 @@ # Start multimon # logging.debug("starting multimon-ng") - command = "multimon-ng "+str(demodulation)+" -f alpha -t raw /dev/stdin - " + command = "/usr/local/bin/multimon-ng "+str(demodulation)+" -f alpha -t raw /dev/stdin - " multimon_ng = subprocess.Popen(command.split(), stdin=rtl_fm.stdout, stdout=subprocess.PIPE, diff --git a/service/README.md b/service/README.md index 3af43e70..7ad599de 100644 --- a/service/README.md +++ b/service/README.md @@ -14,15 +14,15 @@ We recommend to use "-u" and "-q" when you want to run BOSWatch as a daemon. ##### Using the init script -To actually use this script, put your Python script where you want (recommend `/usr/local/bin/BOSWatch`) +To actually use this script, put BOSWatch where you want (recommend `/usr/local/bin/BOSWatch`) and make sure it is executable (e.g. `sudo chmod 755 boswatch.py`). -Edit the init script accordingly. Copy the init script into /etc/init.d using e.g. `sudo cp boswatch.sh /etc/init.d`. +Edit the init script accordingly. Copy it into /etc/init.d using e.g. `sudo cp boswatch.sh /etc/init.d`. Make sure the script is executable (chmod again) and make sure that it has UNIX line-endings. -At this point you should be able to start your Python script using the command `sudo /etc/init.d/boswatch.sh start`, +At this point you should be able to start BOSWatchcd ~/srt using the command `sudo /etc/init.d/boswatch.sh start`, check its status with the `sudo /etc/init.d/boswatch.sh status` argument and stop it with `sudo /etc/init.d/boswatch.sh stop`. To make the Raspberry Pi use your init script at the right time, one more step is required: Running the command `sudo update-rc.d boswatch.sh defaults`. -This command adds in symbolic links to the `/etc/rc.x` directories so that the init script is run at the default times. -You can see these links if you do ls -l /etc/rc?.d/*boswatch.sh \ No newline at end of file +This command adds in symbolic links to the /etc/rc.x directories so that the init script is run at the default times. +You can see these links if you do `ls -l /etc/rc?.d/*boswatch.sh` \ No newline at end of file From f6e25d77b4e306056ee8d74502019a2d45b9a327 Mon Sep 17 00:00:00 2001 From: JHCD Date: Thu, 25 Jun 2015 21:19:41 +0200 Subject: [PATCH 14/98] only dos2linux on files --- csv/fms.csv | 18 +- csv/poc.csv | 18 +- csv/zvei.csv | 18 +- includes/MyTimedRotatingFileHandler.py | 34 ++-- includes/converter.py | 56 +++--- includes/decoder.py | 104 +++++----- includes/decoders/fms.py | 154 +++++++------- includes/decoders/poc.py | 268 ++++++++++++------------- includes/decoders/zvei.py | 174 ++++++++-------- includes/descriptionList.py | 224 ++++++++++----------- includes/shellHeader.py | 102 +++++----- includes/signalHandler.py | 62 +++--- service/README.md | 54 ++--- 13 files changed, 643 insertions(+), 643 deletions(-) diff --git a/csv/fms.csv b/csv/fms.csv index e52a17e4..cdc05fbf 100644 --- a/csv/fms.csv +++ b/csv/fms.csv @@ -1,10 +1,10 @@ -fms,description -# -# BOSWatch CSV file for describing FMS-Addresses -# -# For each FMS-Address you could set a description-text -# Use the structure: fms,"Description-Text" -# -# !!! DO NOT delete the first line !!! -# +fms,description +# +# BOSWatch CSV file for describing FMS-Addresses +# +# For each FMS-Address you could set a description-text +# Use the structure: fms,"Description-Text" +# +# !!! DO NOT delete the first line !!! +# 93377141,"John Q. Publics car" \ No newline at end of file diff --git a/csv/poc.csv b/csv/poc.csv index 3a667fed..89fb7952 100644 --- a/csv/poc.csv +++ b/csv/poc.csv @@ -1,10 +1,10 @@ -ric,description -# -# BOSWatch CSV file for describing POCSAG-Addresses -# -# For each RIC-Address you could set a description-text -# Use the structure: ric,"Description-Text" -# -# !!! DO NOT delete the first line !!! -# +ric,description +# +# BOSWatch CSV file for describing POCSAG-Addresses +# +# For each RIC-Address you could set a description-text +# Use the structure: ric,"Description-Text" +# +# !!! DO NOT delete the first line !!! +# 1234567,"John Q. Public" \ No newline at end of file diff --git a/csv/zvei.csv b/csv/zvei.csv index da78fe33..25ef0ed7 100644 --- a/csv/zvei.csv +++ b/csv/zvei.csv @@ -1,10 +1,10 @@ -zvei,description -# -# BOSWatch CSV file for describing ZVEI-Addresses -# -# For each ZVEI-Address you could set a description-text -# Use the structure: zvei,"Description-Text" -# -# !!! DO NOT delete the first line !!! -# +zvei,description +# +# BOSWatch CSV file for describing ZVEI-Addresses +# +# For each ZVEI-Address you could set a description-text +# Use the structure: zvei,"Description-Text" +# +# !!! DO NOT delete the first line !!! +# 25832,"John Q. Public" \ No newline at end of file diff --git a/includes/MyTimedRotatingFileHandler.py b/includes/MyTimedRotatingFileHandler.py index 347987a4..23c0d0f3 100644 --- a/includes/MyTimedRotatingFileHandler.py +++ b/includes/MyTimedRotatingFileHandler.py @@ -1,18 +1,18 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- -# - -""" -This Class extended the TimedRotatingFileHandler with the possibility -to change the backupCount after initialization. - -@author: Jens Herrmann -""" - -import logging - -class MyTimedRotatingFileHandler(logging.handlers.TimedRotatingFileHandler): - """Extended Version of TimedRotatingFileHandler""" - def setBackupCount(self, backupCount): - """Set/Change backupCount""" +#!/usr/bin/python +# -*- coding: cp1252 -*- +# + +""" +This Class extended the TimedRotatingFileHandler with the possibility +to change the backupCount after initialization. + +@author: Jens Herrmann +""" + +import logging + +class MyTimedRotatingFileHandler(logging.handlers.TimedRotatingFileHandler): + """Extended Version of TimedRotatingFileHandler""" + def setBackupCount(self, backupCount): + """Set/Change backupCount""" self.backupCount = backupCount \ No newline at end of file diff --git a/includes/converter.py b/includes/converter.py index 13ce7ab9..52ac28fe 100644 --- a/includes/converter.py +++ b/includes/converter.py @@ -1,29 +1,29 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- -# - -""" -convert frequency to Hz - -@author: Bastian Schroll -""" - -import logging - -def freqToHz(freq): - """ - gets a frequency and resolve it in Hz - - @type freq: string - @param freq: frequency of the SDR Stick - - @return: frequency in Hz - @exception: Exception if Error by recalc - """ - try: - freq = freq.replace("k","e3").replace("M","e6") - # freq has to be interpreted as float first... - # otherwise you will get the error: an invalid literal for int() with base 10 - return int(float(freq)) - except: +#!/usr/bin/python +# -*- coding: cp1252 -*- +# + +""" +convert frequency to Hz + +@author: Bastian Schroll +""" + +import logging + +def freqToHz(freq): + """ + gets a frequency and resolve it in Hz + + @type freq: string + @param freq: frequency of the SDR Stick + + @return: frequency in Hz + @exception: Exception if Error by recalc + """ + try: + freq = freq.replace("k","e3").replace("M","e6") + # freq has to be interpreted as float first... + # otherwise you will get the error: an invalid literal for int() with base 10 + return int(float(freq)) + except: logging.exception("Error in freqToHz()") \ No newline at end of file diff --git a/includes/decoder.py b/includes/decoder.py index 7814e596..49972816 100644 --- a/includes/decoder.py +++ b/includes/decoder.py @@ -1,53 +1,53 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- - -""" -Search for decode string and call the right decoder function - -@author: Jens Herrmann - -@requires: none -""" - -import logging # Global logger - -def decode(freq, decoded): - """ - Search for decode string and call the right decoder function - - @type freq: string - @param freq: frequency of the SDR Stick - @type decoded: string - @param decoded: RAW Information from Multimon-NG - - @return: nothing - @exception: Exception if decoder file call failed - """ - try: - # FMS Decoder Section - # check FMS: -> check CRC -> validate -> check double alarm -> log - if "FMS:" in decoded: - logging.debug("recieved FMS") - from includes.decoders import fms - fms.decode(freq, decoded) - - # ZVEI Decoder Section - # check ZVEI: -> validate -> check double alarm -> log - elif "ZVEI2:" in decoded: - logging.debug("recieved ZVEI") - from includes.decoders import zvei - zvei.decode(freq, decoded) - - # For POCSAG we have to ignore the multimon-ng line "Enabled demodulators:" - elif "Enabled demodulators:" in decoded: - pass - - # POCSAG Decoder Section - # check POCSAG -> validate -> check double alarm -> log - elif "POCSAG" in decoded: - logging.debug("recieved POCSAG") - from includes.decoders import poc - poc.decode(freq, decoded) - - except: +#!/usr/bin/python +# -*- coding: cp1252 -*- + +""" +Search for decode string and call the right decoder function + +@author: Jens Herrmann + +@requires: none +""" + +import logging # Global logger + +def decode(freq, decoded): + """ + Search for decode string and call the right decoder function + + @type freq: string + @param freq: frequency of the SDR Stick + @type decoded: string + @param decoded: RAW Information from Multimon-NG + + @return: nothing + @exception: Exception if decoder file call failed + """ + try: + # FMS Decoder Section + # check FMS: -> check CRC -> validate -> check double alarm -> log + if "FMS:" in decoded: + logging.debug("recieved FMS") + from includes.decoders import fms + fms.decode(freq, decoded) + + # ZVEI Decoder Section + # check ZVEI: -> validate -> check double alarm -> log + elif "ZVEI2:" in decoded: + logging.debug("recieved ZVEI") + from includes.decoders import zvei + zvei.decode(freq, decoded) + + # For POCSAG we have to ignore the multimon-ng line "Enabled demodulators:" + elif "Enabled demodulators:" in decoded: + pass + + # POCSAG Decoder Section + # check POCSAG -> validate -> check double alarm -> log + elif "POCSAG" in decoded: + logging.debug("recieved POCSAG") + from includes.decoders import poc + poc.decode(freq, decoded) + + except: logging.exception("cannot start decoder") \ No newline at end of file diff --git a/includes/decoders/fms.py b/includes/decoders/fms.py index 02da649e..ee0329f4 100644 --- a/includes/decoders/fms.py +++ b/includes/decoders/fms.py @@ -1,78 +1,78 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- - -""" -FMS Decoder - -@author: Bastian Schroll - -@requires: Configuration has to be set in the config.ini -""" - -import logging # Global logger -import time # timestamp for doublealarm -import re # Regex for validation - -from includes import globals # Global variables - -## -# -# FMS decoder function -# validate -> check double alarm -> log -# -def decode(freq, decoded): - """ - Export FMS Information from Multimon-NG RAW String and call alarmHandler.processAlarm() - - @type freq: string - @param freq: frequency of the SDR Stick - @type decoded: string - @param decoded: RAW Information from Multimon-NG - - @requires: Configuration has to be set in the config.ini - - @return: nothing - @exception: Exception if FMS decode failed - """ - timestamp = int(time.time()) # Get Timestamp - - fms_service = decoded[19] # Organisation - fms_country = decoded[36] # Bundesland - fms_location = decoded[65:67] # Ort - fms_vehicle = decoded[72:76] # Fahrzeug - fms_status = decoded[84] # Status - fms_direction = decoded[101] # Richtung - fms_directionText = decoded[103:110] # Richtung (Text) - fms_tsi = decoded[114:117] # Taktische Kruzinformation - - if "CRC correct" in decoded: #check CRC is correct - fms_id = fms_service+fms_country+fms_location+fms_vehicle+fms_status+fms_direction # build FMS id - # if FMS is valid - if re.search("[0-9a-f]{8}[0-9a-f]{1}[01]{1}", fms_id): - # check for double alarm - if fms_id == globals.fms_id_old and timestamp < globals.fms_time_old + globals.config.getint("FMS", "double_ignore_time"): - logging.info("FMS double alarm: %s within %s second(s)", globals.fms_id_old, timestamp-globals.fms_time_old) - # in case of double alarm, fms_double_ignore_time set new - globals.fms_time_old = timestamp - else: - logging.info("FMS:%s Status:%s Richtung:%s TSI:%s", fms_id[0:8], fms_status, fms_direction, fms_tsi) - data = {"fms":fms_id[0:8], "status":fms_status, "direction":fms_direction, "directionText":fms_directionText, "tsi":fms_tsi, "description":fms_id[0:8]} - # If enabled, look up description - if globals.config.getint("FMS", "idDescribed"): - from includes import descriptionList - data["description"] = descriptionList.getDescription("FMS", fms_id[0:8]) - # processing the alarm - try: - from includes import alarmHandler - alarmHandler.processAlarm("POC",freq,data) - except: - logging.error("processing alarm failed") - logging.debug("processing alarm failed", exc_info=True) - pass - # in every time save old data for double alarm - globals.fms_id_old = fms_id #save last id - globals.fms_time_old = timestamp #save last time - else: - logging.warning("No valid FMS: %s", fms_id) - else: +#!/usr/bin/python +# -*- coding: cp1252 -*- + +""" +FMS Decoder + +@author: Bastian Schroll + +@requires: Configuration has to be set in the config.ini +""" + +import logging # Global logger +import time # timestamp for doublealarm +import re # Regex for validation + +from includes import globals # Global variables + +## +# +# FMS decoder function +# validate -> check double alarm -> log +# +def decode(freq, decoded): + """ + Export FMS Information from Multimon-NG RAW String and call alarmHandler.processAlarm() + + @type freq: string + @param freq: frequency of the SDR Stick + @type decoded: string + @param decoded: RAW Information from Multimon-NG + + @requires: Configuration has to be set in the config.ini + + @return: nothing + @exception: Exception if FMS decode failed + """ + timestamp = int(time.time()) # Get Timestamp + + fms_service = decoded[19] # Organisation + fms_country = decoded[36] # Bundesland + fms_location = decoded[65:67] # Ort + fms_vehicle = decoded[72:76] # Fahrzeug + fms_status = decoded[84] # Status + fms_direction = decoded[101] # Richtung + fms_directionText = decoded[103:110] # Richtung (Text) + fms_tsi = decoded[114:117] # Taktische Kruzinformation + + if "CRC correct" in decoded: #check CRC is correct + fms_id = fms_service+fms_country+fms_location+fms_vehicle+fms_status+fms_direction # build FMS id + # if FMS is valid + if re.search("[0-9a-f]{8}[0-9a-f]{1}[01]{1}", fms_id): + # check for double alarm + if fms_id == globals.fms_id_old and timestamp < globals.fms_time_old + globals.config.getint("FMS", "double_ignore_time"): + logging.info("FMS double alarm: %s within %s second(s)", globals.fms_id_old, timestamp-globals.fms_time_old) + # in case of double alarm, fms_double_ignore_time set new + globals.fms_time_old = timestamp + else: + logging.info("FMS:%s Status:%s Richtung:%s TSI:%s", fms_id[0:8], fms_status, fms_direction, fms_tsi) + data = {"fms":fms_id[0:8], "status":fms_status, "direction":fms_direction, "directionText":fms_directionText, "tsi":fms_tsi, "description":fms_id[0:8]} + # If enabled, look up description + if globals.config.getint("FMS", "idDescribed"): + from includes import descriptionList + data["description"] = descriptionList.getDescription("FMS", fms_id[0:8]) + # processing the alarm + try: + from includes import alarmHandler + alarmHandler.processAlarm("POC",freq,data) + except: + logging.error("processing alarm failed") + logging.debug("processing alarm failed", exc_info=True) + pass + # in every time save old data for double alarm + globals.fms_id_old = fms_id #save last id + globals.fms_time_old = timestamp #save last time + else: + logging.warning("No valid FMS: %s", fms_id) + else: logging.warning("FMS CRC incorrect") \ No newline at end of file diff --git a/includes/decoders/poc.py b/includes/decoders/poc.py index ceba9134..b0ab005a 100644 --- a/includes/decoders/poc.py +++ b/includes/decoders/poc.py @@ -1,135 +1,135 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- - -""" -POCSAG Decoder - -@author: Bastian Schroll -@author: Jens Herrmann - -@requires: Configuration has to be set in the config.ini -""" - -import logging # Global logger -import time # timestamp for doublealarm -import re # Regex for validation - -from includes import globals # Global variables - -## -# -# Simple local filter -# -def isAllowed(poc_id): - """ - Simple Filter Functions (Allowed, Denied and Range) - - @type poc_id: string - @param poc_id: POCSAG Ric - - @requires: Configuration has to be set in the config.ini - - @return: True if the Ric is allowed, other False - @exception: none - """ - # 1.) If allowed RICs is set, only they will path, - # If RIC is the right one return True, else False - if globals.config.get("POC", "allow_ric"): - if poc_id in globals.config.get("POC", "allow_ric"): - logging.info("RIC %s is allowed", poc_id) - return True - else: - logging.info("RIC %s is not in the allowed list", poc_id) - return False - # 2.) If denied RIC, return False - elif poc_id in globals.config.get("POC", "deny_ric"): - logging.info("RIC %s is denied by config.ini", poc_id) - return False - # 3.) Check Range, return False if outside def. range - elif int(poc_id) < globals.config.getint("POC", "filter_range_start"): - logging.info("RIC %s out of filter range (start)", poc_id) - return False - elif int(poc_id) > globals.config.getint("POC", "filter_range_end"): - logging.info("RIC %s out of filter range (end)", poc_id) - return False - return True - -## -# -# POCSAG decoder function -# validate -> check double alarm -> log -# -def decode(freq, decoded): - """ - Export POCSAG Information from Multimon-NG RAW String and call alarmHandler.processAlarm() - - @type freq: string - @param freq: frequency of the SDR Stick - @type decoded: string - @param decoded: RAW Information from Multimon-NG - - @requires: Configuration has to be set in the config.ini - - @return: nothing - @exception: Exception if POCSAG decode failed - """ - bitrate = 0 - timestamp = int(time.time())#Get Timestamp - - if "POCSAG512:" in decoded: - bitrate = 512 - poc_id = decoded[20:27].replace(" ", "").zfill(7) - poc_sub = decoded[39].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") - - elif "POCSAG1200:" in decoded: - bitrate = 1200 - poc_id = decoded[21:28].replace(" ", "").zfill(7) - poc_sub = decoded[40].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") - - elif "POCSAG2400:" in decoded: - bitrate = 2400 - poc_id = decoded[21:28].replace(" ", "").zfill(7) - poc_sub = decoded[40].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") - - if bitrate is 0: - logging.warning("POCSAG Bitrate not found") - logging.debug(" - (%s)", decoded) - else: - logging.debug("POCSAG Bitrate: %s", bitrate) - - if "Alpha:" in decoded: #check if there is a text message - poc_text = decoded.split('Alpha: ')[1].strip().rstrip('').strip() - else: - poc_text = "" - - if re.search("[0-9]{7}", poc_id): #if POC is valid - if isAllowed(poc_id): - # check for double alarm - if poc_id == globals.poc_id_old and timestamp < globals.poc_time_old + globals.config.getint("POC", "double_ignore_time"): - logging.info("POCSAG%s double alarm: %s within %s second(s)", bitrate, globals.poc_id_old, timestamp-globals.poc_time_old) - # in case of double alarm, poc_double_ignore_time set new - globals.poc_time_old = timestamp - else: - logging.info("POCSAG%s: %s %s %s ", bitrate, poc_id, poc_sub, poc_text) - data = {"ric":poc_id, "function":poc_sub, "msg":poc_text, "bitrate":bitrate, "description":poc_id} - # Add function as character a-d to dataset - data["functionChar"] = data["function"].replace("1", "a").replace("2", "b").replace("3", "c").replace("4", "d") - # If enabled, look up description - if globals.config.getint("POC", "idDescribed"): - from includes import descriptionList - data["description"] = descriptionList.getDescription("POC", poc_id) - # processing the alarm - try: - from includes import alarmHandler - alarmHandler.processAlarm("POC",freq,data) - except: - logging.error("processing alarm failed") - logging.debug("processing alarm failed", exc_info=True) - pass - # in every time save old data for double alarm - globals.poc_id_old = poc_id #save last id - globals.poc_time_old = timestamp #save last time - else: - logging.debug("POCSAG%s: %s is not allowed", bitrate, poc_id) - else: +#!/usr/bin/python +# -*- coding: cp1252 -*- + +""" +POCSAG Decoder + +@author: Bastian Schroll +@author: Jens Herrmann + +@requires: Configuration has to be set in the config.ini +""" + +import logging # Global logger +import time # timestamp for doublealarm +import re # Regex for validation + +from includes import globals # Global variables + +## +# +# Simple local filter +# +def isAllowed(poc_id): + """ + Simple Filter Functions (Allowed, Denied and Range) + + @type poc_id: string + @param poc_id: POCSAG Ric + + @requires: Configuration has to be set in the config.ini + + @return: True if the Ric is allowed, other False + @exception: none + """ + # 1.) If allowed RICs is set, only they will path, + # If RIC is the right one return True, else False + if globals.config.get("POC", "allow_ric"): + if poc_id in globals.config.get("POC", "allow_ric"): + logging.info("RIC %s is allowed", poc_id) + return True + else: + logging.info("RIC %s is not in the allowed list", poc_id) + return False + # 2.) If denied RIC, return False + elif poc_id in globals.config.get("POC", "deny_ric"): + logging.info("RIC %s is denied by config.ini", poc_id) + return False + # 3.) Check Range, return False if outside def. range + elif int(poc_id) < globals.config.getint("POC", "filter_range_start"): + logging.info("RIC %s out of filter range (start)", poc_id) + return False + elif int(poc_id) > globals.config.getint("POC", "filter_range_end"): + logging.info("RIC %s out of filter range (end)", poc_id) + return False + return True + +## +# +# POCSAG decoder function +# validate -> check double alarm -> log +# +def decode(freq, decoded): + """ + Export POCSAG Information from Multimon-NG RAW String and call alarmHandler.processAlarm() + + @type freq: string + @param freq: frequency of the SDR Stick + @type decoded: string + @param decoded: RAW Information from Multimon-NG + + @requires: Configuration has to be set in the config.ini + + @return: nothing + @exception: Exception if POCSAG decode failed + """ + bitrate = 0 + timestamp = int(time.time())#Get Timestamp + + if "POCSAG512:" in decoded: + bitrate = 512 + poc_id = decoded[20:27].replace(" ", "").zfill(7) + poc_sub = decoded[39].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") + + elif "POCSAG1200:" in decoded: + bitrate = 1200 + poc_id = decoded[21:28].replace(" ", "").zfill(7) + poc_sub = decoded[40].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") + + elif "POCSAG2400:" in decoded: + bitrate = 2400 + poc_id = decoded[21:28].replace(" ", "").zfill(7) + poc_sub = decoded[40].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") + + if bitrate is 0: + logging.warning("POCSAG Bitrate not found") + logging.debug(" - (%s)", decoded) + else: + logging.debug("POCSAG Bitrate: %s", bitrate) + + if "Alpha:" in decoded: #check if there is a text message + poc_text = decoded.split('Alpha: ')[1].strip().rstrip('').strip() + else: + poc_text = "" + + if re.search("[0-9]{7}", poc_id): #if POC is valid + if isAllowed(poc_id): + # check for double alarm + if poc_id == globals.poc_id_old and timestamp < globals.poc_time_old + globals.config.getint("POC", "double_ignore_time"): + logging.info("POCSAG%s double alarm: %s within %s second(s)", bitrate, globals.poc_id_old, timestamp-globals.poc_time_old) + # in case of double alarm, poc_double_ignore_time set new + globals.poc_time_old = timestamp + else: + logging.info("POCSAG%s: %s %s %s ", bitrate, poc_id, poc_sub, poc_text) + data = {"ric":poc_id, "function":poc_sub, "msg":poc_text, "bitrate":bitrate, "description":poc_id} + # Add function as character a-d to dataset + data["functionChar"] = data["function"].replace("1", "a").replace("2", "b").replace("3", "c").replace("4", "d") + # If enabled, look up description + if globals.config.getint("POC", "idDescribed"): + from includes import descriptionList + data["description"] = descriptionList.getDescription("POC", poc_id) + # processing the alarm + try: + from includes import alarmHandler + alarmHandler.processAlarm("POC",freq,data) + except: + logging.error("processing alarm failed") + logging.debug("processing alarm failed", exc_info=True) + pass + # in every time save old data for double alarm + globals.poc_id_old = poc_id #save last id + globals.poc_time_old = timestamp #save last time + else: + logging.debug("POCSAG%s: %s is not allowed", bitrate, poc_id) + else: logging.warning("No valid POCSAG%s RIC: %s", bitrate, poc_id) \ No newline at end of file diff --git a/includes/decoders/zvei.py b/includes/decoders/zvei.py index e941e75e..ca4dea4e 100644 --- a/includes/decoders/zvei.py +++ b/includes/decoders/zvei.py @@ -1,88 +1,88 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- - -""" -ZVEI Decoder - -@author: Bastian Schroll - -@requires: Configuration has to be set in the config.ini -""" - -import logging # Global logger -import time # timestamp for doublealarm -import re # Regex for validation - -from includes import globals # Global variables - -## -# -# Local function to remove the 'F' -# -def removeF(zvei): - """ - Resolve the F from the repeat Tone - - @type zvei: string - @param zvei: ZVEI Information - - @return: ZVEI without F - @exception: none - """ - if "F" in zvei: - zvei_old = zvei - for i in range(1, 5): - if zvei[i] == "F": - zvei = zvei.replace("F",zvei[i-1],1) - logging.debug("resolve F: %s -> %s", zvei_old, zvei) - return zvei - -## -# -# ZVEI decoder function -# validate -> check double alarm -> log -# -def decode(freq, decoded): - """ - Export ZVEI Information from Multimon-NG RAW String and call alarmHandler.processAlarm() - - @type freq: string - @param freq: frequency of the SDR Stick - @type decoded: string - @param decoded: RAW Information from Multimon-NG - - @requires: Configuration has to be set in the config.ini - - @return: nothing - @exception: Exception if ZVEI decode failed - """ - timestamp = int(time.time()) # Get Timestamp - - zvei_id = decoded[7:12] # ZVEI Code - zvei_id = removeF(zvei_id) # resolve F - if re.search("[0-9]{5}", zvei_id): # if ZVEI is valid - # check for double alarm - if zvei_id == globals.zvei_id_old and timestamp < globals.zvei_time_old + globals.config.getint("ZVEI", "double_ignore_time"): - logging.info("ZVEI double alarm: %s within %s second(s)", globals.zvei_id_old, timestamp-globals.zvei_time_old) - # in case of double alarm, zvei_double_ignore_time set new - globals.zvei_time_old = timestamp - else: - logging.info("5-Ton: %s", zvei_id) - data = {"zvei":zvei_id, "description":zvei_id} - # If enabled, look up description - if globals.config.getint("ZVEI", "idDescribed"): - from includes import descriptionList - data["description"] = descriptionList.getDescription("ZVEI", zvei_id) - # processing the alarm - try: - from includes import alarmHandler - alarmHandler.processAlarm("POC",freq,data) - except: - logging.error("processing alarm failed") - logging.debug("processing alarm failed", exc_info=True) - pass - # in every time save old data for double alarm - globals.zvei_id_old = zvei_id # save last id - globals.zvei_time_old = timestamp # save last time - else: +#!/usr/bin/python +# -*- coding: cp1252 -*- + +""" +ZVEI Decoder + +@author: Bastian Schroll + +@requires: Configuration has to be set in the config.ini +""" + +import logging # Global logger +import time # timestamp for doublealarm +import re # Regex for validation + +from includes import globals # Global variables + +## +# +# Local function to remove the 'F' +# +def removeF(zvei): + """ + Resolve the F from the repeat Tone + + @type zvei: string + @param zvei: ZVEI Information + + @return: ZVEI without F + @exception: none + """ + if "F" in zvei: + zvei_old = zvei + for i in range(1, 5): + if zvei[i] == "F": + zvei = zvei.replace("F",zvei[i-1],1) + logging.debug("resolve F: %s -> %s", zvei_old, zvei) + return zvei + +## +# +# ZVEI decoder function +# validate -> check double alarm -> log +# +def decode(freq, decoded): + """ + Export ZVEI Information from Multimon-NG RAW String and call alarmHandler.processAlarm() + + @type freq: string + @param freq: frequency of the SDR Stick + @type decoded: string + @param decoded: RAW Information from Multimon-NG + + @requires: Configuration has to be set in the config.ini + + @return: nothing + @exception: Exception if ZVEI decode failed + """ + timestamp = int(time.time()) # Get Timestamp + + zvei_id = decoded[7:12] # ZVEI Code + zvei_id = removeF(zvei_id) # resolve F + if re.search("[0-9]{5}", zvei_id): # if ZVEI is valid + # check for double alarm + if zvei_id == globals.zvei_id_old and timestamp < globals.zvei_time_old + globals.config.getint("ZVEI", "double_ignore_time"): + logging.info("ZVEI double alarm: %s within %s second(s)", globals.zvei_id_old, timestamp-globals.zvei_time_old) + # in case of double alarm, zvei_double_ignore_time set new + globals.zvei_time_old = timestamp + else: + logging.info("5-Ton: %s", zvei_id) + data = {"zvei":zvei_id, "description":zvei_id} + # If enabled, look up description + if globals.config.getint("ZVEI", "idDescribed"): + from includes import descriptionList + data["description"] = descriptionList.getDescription("ZVEI", zvei_id) + # processing the alarm + try: + from includes import alarmHandler + alarmHandler.processAlarm("POC",freq,data) + except: + logging.error("processing alarm failed") + logging.debug("processing alarm failed", exc_info=True) + pass + # in every time save old data for double alarm + globals.zvei_id_old = zvei_id # save last id + globals.zvei_time_old = timestamp # save last time + else: logging.warning("No valid ZVEI: %s", zvei_id) \ No newline at end of file diff --git a/includes/descriptionList.py b/includes/descriptionList.py index ebee2bda..6c94a666 100644 --- a/includes/descriptionList.py +++ b/includes/descriptionList.py @@ -1,113 +1,113 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- - -""" -Function to expand the dataset with a description. - -@author: Jens Herrmann - -@requires: Configuration has to be set in the config.ini -""" - -import logging # Global logger - -import csv # for loading the description files - -from includes import globals # Global variables - -## -# -# Local function will load the csv-file -# -def loadCSV(typ, idField): - """ - Local function for loading csv-file into python list - Structure: [id] = description - - @return: Python list of descriptions - """ - resultList = {} - try: - logging.debug("-- loading %s.csv", typ) - with open(globals.script_path+'/csv/'+typ+'.csv') as csvfile: - # DictReader expected structure described in first line of csv-file - reader = csv.DictReader(csvfile) - for row in reader: - logging.debug(row) - # only import rows with an integer as id - if row[idField].isdigit() == True: - resultList[row[idField]] = row['description'] - logging.debug("-- loading csv finished") - except: - logging.error("loading csvList for typ: %s failed", typ) - logging.debug("loading csvList for typ: %s failed", typ, exc_info=True) - raise - return resultList; - - -## -# -# call this for loading the description lists -# -def loadDescriptionLists(): - """ - Load data from the csv-files in global description list for FMS, ZVEI and POCSAG - - @return: nothing - @exception: Exception if loading failed - """ - try: - logging.debug("loading description lists") - - if globals.config.getint("FMS", "idDescribed"): - logging.debug("- load FMS description list") - globals.fmsDescribtionList = loadCSV("fms", "fms") - - if globals.config.getint("ZVEI", "idDescribed"): - logging.debug("- load ZVEI description list") - globals.zveiDescribtionList = loadCSV("zvei", "zvei") - - if globals.config.getint("POC", "idDescribed"): - logging.debug("- load pocsag description list") - globals.ricDescribtionList = loadCSV("poc", "ric") - - except: - logging.error("cannot load description lists") - logging.debug("cannot load description lists", exc_info=True) - pass - - -## -# -# public function for getting a description -# -def getDescription(typ, id): - """ - Get description for id. - Will return id if no description will be found. - - @return: description as string - """ - resultStr = id; - logging.debug("look up description lists") - try: - if typ == "FMS": - resultStr = globals.fmsDescribtionList[id] - elif typ == "ZVEI": - resultStr = globals.zveiDescribtionList[id] - elif typ == "POC": - resultStr = globals.ricDescribtionList[id] - else: - logging.warning("Invalid Typ: %s", typ) - - except KeyError: - # will be thrown when there is no description for the id - # -> nothing to do... - pass - - except: - logging.debug("Error during look up description lists", exc_info=True) - pass - - logging.debug(" - result for %s: %s", id, resultStr) +#!/usr/bin/python +# -*- coding: cp1252 -*- + +""" +Function to expand the dataset with a description. + +@author: Jens Herrmann + +@requires: Configuration has to be set in the config.ini +""" + +import logging # Global logger + +import csv # for loading the description files + +from includes import globals # Global variables + +## +# +# Local function will load the csv-file +# +def loadCSV(typ, idField): + """ + Local function for loading csv-file into python list + Structure: [id] = description + + @return: Python list of descriptions + """ + resultList = {} + try: + logging.debug("-- loading %s.csv", typ) + with open(globals.script_path+'/csv/'+typ+'.csv') as csvfile: + # DictReader expected structure described in first line of csv-file + reader = csv.DictReader(csvfile) + for row in reader: + logging.debug(row) + # only import rows with an integer as id + if row[idField].isdigit() == True: + resultList[row[idField]] = row['description'] + logging.debug("-- loading csv finished") + except: + logging.error("loading csvList for typ: %s failed", typ) + logging.debug("loading csvList for typ: %s failed", typ, exc_info=True) + raise + return resultList; + + +## +# +# call this for loading the description lists +# +def loadDescriptionLists(): + """ + Load data from the csv-files in global description list for FMS, ZVEI and POCSAG + + @return: nothing + @exception: Exception if loading failed + """ + try: + logging.debug("loading description lists") + + if globals.config.getint("FMS", "idDescribed"): + logging.debug("- load FMS description list") + globals.fmsDescribtionList = loadCSV("fms", "fms") + + if globals.config.getint("ZVEI", "idDescribed"): + logging.debug("- load ZVEI description list") + globals.zveiDescribtionList = loadCSV("zvei", "zvei") + + if globals.config.getint("POC", "idDescribed"): + logging.debug("- load pocsag description list") + globals.ricDescribtionList = loadCSV("poc", "ric") + + except: + logging.error("cannot load description lists") + logging.debug("cannot load description lists", exc_info=True) + pass + + +## +# +# public function for getting a description +# +def getDescription(typ, id): + """ + Get description for id. + Will return id if no description will be found. + + @return: description as string + """ + resultStr = id; + logging.debug("look up description lists") + try: + if typ == "FMS": + resultStr = globals.fmsDescribtionList[id] + elif typ == "ZVEI": + resultStr = globals.zveiDescribtionList[id] + elif typ == "POC": + resultStr = globals.ricDescribtionList[id] + else: + logging.warning("Invalid Typ: %s", typ) + + except KeyError: + # will be thrown when there is no description for the id + # -> nothing to do... + pass + + except: + logging.debug("Error during look up description lists", exc_info=True) + pass + + logging.debug(" - result for %s: %s", id, resultStr) return resultStr \ No newline at end of file diff --git a/includes/shellHeader.py b/includes/shellHeader.py index 2f105c9b..dfbcac41 100644 --- a/includes/shellHeader.py +++ b/includes/shellHeader.py @@ -1,52 +1,52 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- - -""" -Shows the header in shell if quiet mode is not active - -@author: Bastian Schroll -@author: Jens Herrmann - -@requires: none -""" - -def printHeader(args): - """ - Prints the header to the shell - - @type args: Array - @param args: All given arguments from argsparser - - @return: nothing - """ - try: - print " ____ ____ ______ __ __ __ " - print " / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ b" - print " / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ e" - print " / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / t" - print " /_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ a" - print " German BOS Information Script " - print " by Bastian Schroll " - print "" - - print "Frequency: "+args.freq - print "Device-ID: "+str(args.device) - print "Error in PPM: "+str(args.error) - print "Active Demods: "+str(len(args.demod)) - if "FMS" in args.demod: - print "- FMS" - if "ZVEI" in args.demod: - print "- ZVEI" - if "POC512" in args.demod: - print "- POC512" - if "POC1200" in args.demod: - print "- POC1200" - if "POC2400" in args.demod: - print "- POC2400" - print "Squelch: "+str(args.squelch) - if args.verbose: - print "Verbose Mode!" - print "" - except: - logging.error("cannot display shell header") +#!/usr/bin/python +# -*- coding: cp1252 -*- + +""" +Shows the header in shell if quiet mode is not active + +@author: Bastian Schroll +@author: Jens Herrmann + +@requires: none +""" + +def printHeader(args): + """ + Prints the header to the shell + + @type args: Array + @param args: All given arguments from argsparser + + @return: nothing + """ + try: + print " ____ ____ ______ __ __ __ " + print " / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ b" + print " / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ e" + print " / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / t" + print " /_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ a" + print " German BOS Information Script " + print " by Bastian Schroll " + print "" + + print "Frequency: "+args.freq + print "Device-ID: "+str(args.device) + print "Error in PPM: "+str(args.error) + print "Active Demods: "+str(len(args.demod)) + if "FMS" in args.demod: + print "- FMS" + if "ZVEI" in args.demod: + print "- ZVEI" + if "POC512" in args.demod: + print "- POC512" + if "POC1200" in args.demod: + print "- POC1200" + if "POC2400" in args.demod: + print "- POC2400" + print "Squelch: "+str(args.squelch) + if args.verbose: + print "Verbose Mode!" + print "" + except: + logging.error("cannot display shell header") logging.debug("cannot display shell header", exc_info=True) \ No newline at end of file diff --git a/includes/signalHandler.py b/includes/signalHandler.py index 50f40ab5..ce0ec542 100644 --- a/includes/signalHandler.py +++ b/includes/signalHandler.py @@ -1,32 +1,32 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- -# - -""" -TERM-Handler for use script as a daemon -In order for the Python program to exit gracefully when the TERM signal is received, -it must have a function that exits the program when signal.SIGTERM is received. - -@author: Jens Herrmann -""" - -import logging -import signal # for use as daemon -import sys # throw SystemExitException when daemon is terminated - -def sigterm_handler(_signo, _stack_frame): - """ - TERM-Handler for use script as a daemon - - @type _signo: signalnum - @param _signo: signal number - @type _stack_frame: frame object - @param _stack_frame: current stack frame - - @exception: SystemExitException when daemon is terminated - """ - logging.warning("TERM signal received") - sys.exit(0) - -# Set the handler for signal to the function handler. +#!/usr/bin/python +# -*- coding: cp1252 -*- +# + +""" +TERM-Handler for use script as a daemon +In order for the Python program to exit gracefully when the TERM signal is received, +it must have a function that exits the program when signal.SIGTERM is received. + +@author: Jens Herrmann +""" + +import logging +import signal # for use as daemon +import sys # throw SystemExitException when daemon is terminated + +def sigterm_handler(_signo, _stack_frame): + """ + TERM-Handler for use script as a daemon + + @type _signo: signalnum + @param _signo: signal number + @type _stack_frame: frame object + @param _stack_frame: current stack frame + + @exception: SystemExitException when daemon is terminated + """ + logging.warning("TERM signal received") + sys.exit(0) + +# Set the handler for signal to the function handler. signal.signal(signal.SIGTERM, sigterm_handler) \ No newline at end of file diff --git a/service/README.md b/service/README.md index 7ad599de..82e898a8 100644 --- a/service/README.md +++ b/service/README.md @@ -1,28 +1,28 @@ -### Start BOSWatch as a daemon - -##### Changing the init script - -Lines 14 and 15 define where to find the Python script. -In this case the script expects that there is a folder `/usr/local/bin/BOSWatch` and that the script is inside there. - -Line 23 sets what user to run the script as. Using a root-user is necessary for BOSWatch. - -Line 19 sets the parameters for BOSWatch, use the same as starting BOSWatch from the shell. -We recommend to use "-u" and "-q" when you want to run BOSWatch as a daemon. -- "-u": You will find the logfiles in `/var/log/BOSWatch` -- "-q": Shows no information. Only logfiles - -##### Using the init script - -To actually use this script, put BOSWatch where you want (recommend `/usr/local/bin/BOSWatch`) -and make sure it is executable (e.g. `sudo chmod 755 boswatch.py`). -Edit the init script accordingly. Copy it into /etc/init.d using e.g. `sudo cp boswatch.sh /etc/init.d`. -Make sure the script is executable (chmod again) and make sure that it has UNIX line-endings. - -At this point you should be able to start BOSWatchcd ~/srt using the command `sudo /etc/init.d/boswatch.sh start`, -check its status with the `sudo /etc/init.d/boswatch.sh status` argument and stop it with `sudo /etc/init.d/boswatch.sh stop`. - -To make the Raspberry Pi use your init script at the right time, one more step is required: -Running the command `sudo update-rc.d boswatch.sh defaults`. -This command adds in symbolic links to the /etc/rc.x directories so that the init script is run at the default times. +### Start BOSWatch as a daemon + +##### Changing the init script + +Lines 14 and 15 define where to find the Python script. +In this case the script expects that there is a folder `/usr/local/bin/BOSWatch` and that the script is inside there. + +Line 23 sets what user to run the script as. Using a root-user is necessary for BOSWatch. + +Line 19 sets the parameters for BOSWatch, use the same as starting BOSWatch from the shell. +We recommend to use "-u" and "-q" when you want to run BOSWatch as a daemon. +- "-u": You will find the logfiles in `/var/log/BOSWatch` +- "-q": Shows no information. Only logfiles + +##### Using the init script + +To actually use this script, put BOSWatch where you want (recommend `/usr/local/bin/BOSWatch`) +and make sure it is executable (e.g. `sudo chmod 755 boswatch.py`). +Edit the init script accordingly. Copy it into /etc/init.d using e.g. `sudo cp boswatch.sh /etc/init.d`. +Make sure the script is executable (chmod again) and make sure that it has UNIX line-endings. + +At this point you should be able to start BOSWatchcd ~/srt using the command `sudo /etc/init.d/boswatch.sh start`, +check its status with the `sudo /etc/init.d/boswatch.sh status` argument and stop it with `sudo /etc/init.d/boswatch.sh stop`. + +To make the Raspberry Pi use your init script at the right time, one more step is required: +Running the command `sudo update-rc.d boswatch.sh defaults`. +This command adds in symbolic links to the /etc/rc.x directories so that the init script is run at the default times. You can see these links if you do `ls -l /etc/rc?.d/*boswatch.sh` \ No newline at end of file From 4eaf27c75499bc3f79c261adba531937c57a5d0a Mon Sep 17 00:00:00 2001 From: JHCD Date: Sun, 28 Jun 2015 22:28:21 +0200 Subject: [PATCH 15/98] implemtation of new doubleAlarm-Filter You can set the number of historical entries the filter will check and the time ignoring the id in case of a double alarm --- config/config.template.ini | 15 +-- includes/decoders/fms.py | 147 ++++++++++----------- includes/decoders/poc.py | 262 ++++++++++++++++++------------------- includes/decoders/zvei.py | 167 +++++++++++------------ includes/globals.py | 12 +- 5 files changed, 287 insertions(+), 316 deletions(-) diff --git a/config/config.template.ini b/config/config.template.ini index 6162d51c..7f354fd9 100644 --- a/config/config.template.ini +++ b/config/config.template.ini @@ -25,26 +25,25 @@ useRegExFilter = 0 # You have to be enabled it for every typ in the sections below too useDescription = 0 -[FMS] -# time to ignore same alarm in a row (sek) +# for double check save the last n IDs +# it is used in combination with double_ignore_time +# 1 is required if you want to use the double alarm filter +double_ignore_entries = 10 + +#time to ignore same alarm (only ID is checked) (sek) double_ignore_time = 5 +[FMS] # look-up-table for adding a description # turn on functionality (0|1) idDescribed = 0 [ZVEI] -# time to ignore same alarm in a row (sek) -double_ignore_time = 5 - # look-up-table for adding a description # turn on functionality (0|1) idDescribed = 0 [POC] -# time to ignore same alarm in a row (sek) -double_ignore_time = 5 - # some very simple filters: # Allow only this RICs (empty: allow all, separator ",") # f.e.: allow_ric = 1234566,1234567,1234568 diff --git a/includes/decoders/fms.py b/includes/decoders/fms.py index ee0329f4..17c24532 100644 --- a/includes/decoders/fms.py +++ b/includes/decoders/fms.py @@ -1,78 +1,71 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- - -""" -FMS Decoder - -@author: Bastian Schroll - -@requires: Configuration has to be set in the config.ini -""" - -import logging # Global logger -import time # timestamp for doublealarm -import re # Regex for validation - -from includes import globals # Global variables - -## -# -# FMS decoder function -# validate -> check double alarm -> log -# -def decode(freq, decoded): - """ - Export FMS Information from Multimon-NG RAW String and call alarmHandler.processAlarm() - - @type freq: string - @param freq: frequency of the SDR Stick - @type decoded: string - @param decoded: RAW Information from Multimon-NG - - @requires: Configuration has to be set in the config.ini - - @return: nothing - @exception: Exception if FMS decode failed - """ - timestamp = int(time.time()) # Get Timestamp - - fms_service = decoded[19] # Organisation - fms_country = decoded[36] # Bundesland - fms_location = decoded[65:67] # Ort - fms_vehicle = decoded[72:76] # Fahrzeug - fms_status = decoded[84] # Status - fms_direction = decoded[101] # Richtung - fms_directionText = decoded[103:110] # Richtung (Text) - fms_tsi = decoded[114:117] # Taktische Kruzinformation - - if "CRC correct" in decoded: #check CRC is correct - fms_id = fms_service+fms_country+fms_location+fms_vehicle+fms_status+fms_direction # build FMS id - # if FMS is valid - if re.search("[0-9a-f]{8}[0-9a-f]{1}[01]{1}", fms_id): - # check for double alarm - if fms_id == globals.fms_id_old and timestamp < globals.fms_time_old + globals.config.getint("FMS", "double_ignore_time"): - logging.info("FMS double alarm: %s within %s second(s)", globals.fms_id_old, timestamp-globals.fms_time_old) - # in case of double alarm, fms_double_ignore_time set new - globals.fms_time_old = timestamp - else: - logging.info("FMS:%s Status:%s Richtung:%s TSI:%s", fms_id[0:8], fms_status, fms_direction, fms_tsi) - data = {"fms":fms_id[0:8], "status":fms_status, "direction":fms_direction, "directionText":fms_directionText, "tsi":fms_tsi, "description":fms_id[0:8]} - # If enabled, look up description - if globals.config.getint("FMS", "idDescribed"): - from includes import descriptionList - data["description"] = descriptionList.getDescription("FMS", fms_id[0:8]) - # processing the alarm - try: - from includes import alarmHandler - alarmHandler.processAlarm("POC",freq,data) - except: - logging.error("processing alarm failed") - logging.debug("processing alarm failed", exc_info=True) - pass - # in every time save old data for double alarm - globals.fms_id_old = fms_id #save last id - globals.fms_time_old = timestamp #save last time - else: - logging.warning("No valid FMS: %s", fms_id) - else: +#!/usr/bin/python +# -*- coding: cp1252 -*- + +""" +FMS Decoder + +@author: Bastian Schroll + +@requires: Configuration has to be set in the config.ini +""" + +import logging # Global logger +import re # Regex for validation + +from includes import globals # Global variables +from includes import doubleFilter # double alarm filter + +## +# +# FMS decoder function +# validate -> check double alarm -> log +# +def decode(freq, decoded): + """ + Export FMS Information from Multimon-NG RAW String and call alarmHandler.processAlarm() + + @type freq: string + @param freq: frequency of the SDR Stick + @type decoded: string + @param decoded: RAW Information from Multimon-NG + + @requires: Configuration has to be set in the config.ini + + @return: nothing + @exception: Exception if FMS decode failed + """ + fms_service = decoded[19] # Organisation + fms_country = decoded[36] # Bundesland + fms_location = decoded[65:67] # Ort + fms_vehicle = decoded[72:76] # Fahrzeug + fms_status = decoded[84] # Status + fms_direction = decoded[101] # Richtung + fms_directionText = decoded[103:110] # Richtung (Text) + fms_tsi = decoded[114:117] # Taktische Kruzinformation + + if "CRC correct" in decoded: #check CRC is correct + fms_id = fms_service+fms_country+fms_location+fms_vehicle+fms_status+fms_direction # build FMS id + # if FMS is valid + if re.search("[0-9a-f]{8}[0-9a-f]{1}[01]{1}", fms_id): + # check for double alarm + if doubleFilter.checkID("FMS", fms_id): + logging.info("FMS:%s Status:%s Richtung:%s TSI:%s", fms_id[0:8], fms_status, fms_direction, fms_tsi) + data = {"fms":fms_id[0:8], "status":fms_status, "direction":fms_direction, "directionText":fms_directionText, "tsi":fms_tsi, "description":fms_id[0:8]} + # If enabled, look up description + if globals.config.getint("FMS", "idDescribed"): + from includes import descriptionList + data["description"] = descriptionList.getDescription("FMS", fms_id[0:8]) + # processing the alarm + try: + from includes import alarmHandler + alarmHandler.processAlarm("FMS", freq, data) + except: + logging.error("processing alarm failed") + logging.debug("processing alarm failed", exc_info=True) + pass + # in every time save old data for double alarm + doubleFilter.newEntry(fms_id) + else: + logging.warning("No valid FMS: %s", fms_id) + else: logging.warning("FMS CRC incorrect") \ No newline at end of file diff --git a/includes/decoders/poc.py b/includes/decoders/poc.py index b0ab005a..c8dee0d8 100644 --- a/includes/decoders/poc.py +++ b/includes/decoders/poc.py @@ -1,135 +1,129 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- - -""" -POCSAG Decoder - -@author: Bastian Schroll -@author: Jens Herrmann - -@requires: Configuration has to be set in the config.ini -""" - -import logging # Global logger -import time # timestamp for doublealarm -import re # Regex for validation - -from includes import globals # Global variables - -## -# -# Simple local filter -# -def isAllowed(poc_id): - """ - Simple Filter Functions (Allowed, Denied and Range) - - @type poc_id: string - @param poc_id: POCSAG Ric - - @requires: Configuration has to be set in the config.ini - - @return: True if the Ric is allowed, other False - @exception: none - """ - # 1.) If allowed RICs is set, only they will path, - # If RIC is the right one return True, else False - if globals.config.get("POC", "allow_ric"): - if poc_id in globals.config.get("POC", "allow_ric"): - logging.info("RIC %s is allowed", poc_id) - return True - else: - logging.info("RIC %s is not in the allowed list", poc_id) - return False - # 2.) If denied RIC, return False - elif poc_id in globals.config.get("POC", "deny_ric"): - logging.info("RIC %s is denied by config.ini", poc_id) - return False - # 3.) Check Range, return False if outside def. range - elif int(poc_id) < globals.config.getint("POC", "filter_range_start"): - logging.info("RIC %s out of filter range (start)", poc_id) - return False - elif int(poc_id) > globals.config.getint("POC", "filter_range_end"): - logging.info("RIC %s out of filter range (end)", poc_id) - return False - return True - -## -# -# POCSAG decoder function -# validate -> check double alarm -> log -# -def decode(freq, decoded): - """ - Export POCSAG Information from Multimon-NG RAW String and call alarmHandler.processAlarm() - - @type freq: string - @param freq: frequency of the SDR Stick - @type decoded: string - @param decoded: RAW Information from Multimon-NG - - @requires: Configuration has to be set in the config.ini - - @return: nothing - @exception: Exception if POCSAG decode failed - """ - bitrate = 0 - timestamp = int(time.time())#Get Timestamp - - if "POCSAG512:" in decoded: - bitrate = 512 - poc_id = decoded[20:27].replace(" ", "").zfill(7) - poc_sub = decoded[39].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") - - elif "POCSAG1200:" in decoded: - bitrate = 1200 - poc_id = decoded[21:28].replace(" ", "").zfill(7) - poc_sub = decoded[40].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") - - elif "POCSAG2400:" in decoded: - bitrate = 2400 - poc_id = decoded[21:28].replace(" ", "").zfill(7) - poc_sub = decoded[40].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") - - if bitrate is 0: - logging.warning("POCSAG Bitrate not found") - logging.debug(" - (%s)", decoded) - else: - logging.debug("POCSAG Bitrate: %s", bitrate) - - if "Alpha:" in decoded: #check if there is a text message - poc_text = decoded.split('Alpha: ')[1].strip().rstrip('').strip() - else: - poc_text = "" - - if re.search("[0-9]{7}", poc_id): #if POC is valid - if isAllowed(poc_id): - # check for double alarm - if poc_id == globals.poc_id_old and timestamp < globals.poc_time_old + globals.config.getint("POC", "double_ignore_time"): - logging.info("POCSAG%s double alarm: %s within %s second(s)", bitrate, globals.poc_id_old, timestamp-globals.poc_time_old) - # in case of double alarm, poc_double_ignore_time set new - globals.poc_time_old = timestamp - else: - logging.info("POCSAG%s: %s %s %s ", bitrate, poc_id, poc_sub, poc_text) - data = {"ric":poc_id, "function":poc_sub, "msg":poc_text, "bitrate":bitrate, "description":poc_id} - # Add function as character a-d to dataset - data["functionChar"] = data["function"].replace("1", "a").replace("2", "b").replace("3", "c").replace("4", "d") - # If enabled, look up description - if globals.config.getint("POC", "idDescribed"): - from includes import descriptionList - data["description"] = descriptionList.getDescription("POC", poc_id) - # processing the alarm - try: - from includes import alarmHandler - alarmHandler.processAlarm("POC",freq,data) - except: - logging.error("processing alarm failed") - logging.debug("processing alarm failed", exc_info=True) - pass - # in every time save old data for double alarm - globals.poc_id_old = poc_id #save last id - globals.poc_time_old = timestamp #save last time - else: - logging.debug("POCSAG%s: %s is not allowed", bitrate, poc_id) - else: +#!/usr/bin/python +# -*- coding: cp1252 -*- + +""" +POCSAG Decoder + +@author: Bastian Schroll +@author: Jens Herrmann + +@requires: Configuration has to be set in the config.ini +""" + +import logging # Global logger +import re # Regex for validation + +from includes import globals # Global variables +from includes import doubleFilter # double alarm filter + +## +# +# Simple local filter +# +def isAllowed(poc_id): + """ + Simple Filter Functions (Allowed, Denied and Range) + + @type poc_id: string + @param poc_id: POCSAG Ric + + @requires: Configuration has to be set in the config.ini + + @return: True if the Ric is allowed, other False + @exception: none + """ + # 1.) If allowed RICs is set, only they will path, + # If RIC is the right one return True, else False + if globals.config.get("POC", "allow_ric"): + if poc_id in globals.config.get("POC", "allow_ric"): + logging.info("RIC %s is allowed", poc_id) + return True + else: + logging.info("RIC %s is not in the allowed list", poc_id) + return False + # 2.) If denied RIC, return False + elif poc_id in globals.config.get("POC", "deny_ric"): + logging.info("RIC %s is denied by config.ini", poc_id) + return False + # 3.) Check Range, return False if outside def. range + elif int(poc_id) < globals.config.getint("POC", "filter_range_start"): + logging.info("RIC %s out of filter range (start)", poc_id) + return False + elif int(poc_id) > globals.config.getint("POC", "filter_range_end"): + logging.info("RIC %s out of filter range (end)", poc_id) + return False + return True + +## +# +# POCSAG decoder function +# validate -> check double alarm -> log +# +def decode(freq, decoded): + """ + Export POCSAG Information from Multimon-NG RAW String and call alarmHandler.processAlarm() + + @type freq: string + @param freq: frequency of the SDR Stick + @type decoded: string + @param decoded: RAW Information from Multimon-NG + + @requires: Configuration has to be set in the config.ini + + @return: nothing + @exception: Exception if POCSAG decode failed + """ + bitrate = 0 + + if "POCSAG512:" in decoded: + bitrate = 512 + poc_id = decoded[20:27].replace(" ", "").zfill(7) + poc_sub = decoded[39].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") + + elif "POCSAG1200:" in decoded: + bitrate = 1200 + poc_id = decoded[21:28].replace(" ", "").zfill(7) + poc_sub = decoded[40].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") + + elif "POCSAG2400:" in decoded: + bitrate = 2400 + poc_id = decoded[21:28].replace(" ", "").zfill(7) + poc_sub = decoded[40].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") + + if bitrate is 0: + logging.warning("POCSAG Bitrate not found") + logging.debug(" - (%s)", decoded) + else: + logging.debug("POCSAG Bitrate: %s", bitrate) + + if "Alpha:" in decoded: #check if there is a text message + poc_text = decoded.split('Alpha: ')[1].strip().rstrip('').strip() + else: + poc_text = "" + + if re.search("[0-9]{7}", poc_id): #if POC is valid + if isAllowed(poc_id): + # check for double alarm + if doubleFilter.checkID("POC", poc_id): + logging.info("POCSAG%s: %s %s %s ", bitrate, poc_id, poc_sub, poc_text) + data = {"ric":poc_id, "function":poc_sub, "msg":poc_text, "bitrate":bitrate, "description":poc_id} + # Add function as character a-d to dataset + data["functionChar"] = data["function"].replace("1", "a").replace("2", "b").replace("3", "c").replace("4", "d") + # If enabled, look up description + if globals.config.getint("POC", "idDescribed"): + from includes import descriptionList + data["description"] = descriptionList.getDescription("POC", poc_id) + # processing the alarm + try: + from includes import alarmHandler + alarmHandler.processAlarm("POC", freq, data) + except: + logging.error("processing alarm failed") + logging.debug("processing alarm failed", exc_info=True) + pass + # in every time save old data for double alarm + doubleFilter.newEntry(poc_id) + else: + logging.debug("POCSAG%s: %s is not allowed", bitrate, poc_id) + else: logging.warning("No valid POCSAG%s RIC: %s", bitrate, poc_id) \ No newline at end of file diff --git a/includes/decoders/zvei.py b/includes/decoders/zvei.py index ca4dea4e..39afcbf0 100644 --- a/includes/decoders/zvei.py +++ b/includes/decoders/zvei.py @@ -1,88 +1,81 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- - -""" -ZVEI Decoder - -@author: Bastian Schroll - -@requires: Configuration has to be set in the config.ini -""" - -import logging # Global logger -import time # timestamp for doublealarm -import re # Regex for validation - -from includes import globals # Global variables - -## -# -# Local function to remove the 'F' -# -def removeF(zvei): - """ - Resolve the F from the repeat Tone - - @type zvei: string - @param zvei: ZVEI Information - - @return: ZVEI without F - @exception: none - """ - if "F" in zvei: - zvei_old = zvei - for i in range(1, 5): - if zvei[i] == "F": - zvei = zvei.replace("F",zvei[i-1],1) - logging.debug("resolve F: %s -> %s", zvei_old, zvei) - return zvei - -## -# -# ZVEI decoder function -# validate -> check double alarm -> log -# -def decode(freq, decoded): - """ - Export ZVEI Information from Multimon-NG RAW String and call alarmHandler.processAlarm() - - @type freq: string - @param freq: frequency of the SDR Stick - @type decoded: string - @param decoded: RAW Information from Multimon-NG - - @requires: Configuration has to be set in the config.ini - - @return: nothing - @exception: Exception if ZVEI decode failed - """ - timestamp = int(time.time()) # Get Timestamp - - zvei_id = decoded[7:12] # ZVEI Code - zvei_id = removeF(zvei_id) # resolve F - if re.search("[0-9]{5}", zvei_id): # if ZVEI is valid - # check for double alarm - if zvei_id == globals.zvei_id_old and timestamp < globals.zvei_time_old + globals.config.getint("ZVEI", "double_ignore_time"): - logging.info("ZVEI double alarm: %s within %s second(s)", globals.zvei_id_old, timestamp-globals.zvei_time_old) - # in case of double alarm, zvei_double_ignore_time set new - globals.zvei_time_old = timestamp - else: - logging.info("5-Ton: %s", zvei_id) - data = {"zvei":zvei_id, "description":zvei_id} - # If enabled, look up description - if globals.config.getint("ZVEI", "idDescribed"): - from includes import descriptionList - data["description"] = descriptionList.getDescription("ZVEI", zvei_id) - # processing the alarm - try: - from includes import alarmHandler - alarmHandler.processAlarm("POC",freq,data) - except: - logging.error("processing alarm failed") - logging.debug("processing alarm failed", exc_info=True) - pass - # in every time save old data for double alarm - globals.zvei_id_old = zvei_id # save last id - globals.zvei_time_old = timestamp # save last time - else: +#!/usr/bin/python +# -*- coding: cp1252 -*- + +""" +ZVEI Decoder + +@author: Bastian Schroll + +@requires: Configuration has to be set in the config.ini +""" + +import logging # Global logger +import re # Regex for validation + +from includes import globals # Global variables +from includes import doubleFilter # double alarm filter + +## +# +# Local function to remove the 'F' +# +def removeF(zvei): + """ + Resolve the F from the repeat Tone + + @type zvei: string + @param zvei: ZVEI Information + + @return: ZVEI without F + @exception: none + """ + if "F" in zvei: + zvei_old = zvei + for i in range(1, 5): + if zvei[i] == "F": + zvei = zvei.replace("F",zvei[i-1],1) + logging.debug("resolve F: %s -> %s", zvei_old, zvei) + return zvei + +## +# +# ZVEI decoder function +# validate -> check double alarm -> log +# +def decode(freq, decoded): + """ + Export ZVEI Information from Multimon-NG RAW String and call alarmHandler.processAlarm() + + @type freq: string + @param freq: frequency of the SDR Stick + @type decoded: string + @param decoded: RAW Information from Multimon-NG + + @requires: Configuration has to be set in the config.ini + + @return: nothing + @exception: Exception if ZVEI decode failed + """ + zvei_id = decoded[7:12] # ZVEI Code + zvei_id = removeF(zvei_id) # resolve F + if re.search("[0-9]{5}", zvei_id): # if ZVEI is valid + # check for double alarm + if doubleFilter.checkID("ZVEI", zvei_id): + logging.info("5-Ton: %s", zvei_id) + data = {"zvei":zvei_id, "description":zvei_id} + # If enabled, look up description + if globals.config.getint("ZVEI", "idDescribed"): + from includes import descriptionList + data["description"] = descriptionList.getDescription("ZVEI", zvei_id) + # processing the alarm + try: + from includes import alarmHandler + alarmHandler.processAlarm("ZVEI", freq, data) + except: + logging.error("processing alarm failed") + logging.debug("processing alarm failed", exc_info=True) + pass + # in every time save old data for double alarm + doubleFilter.newEntry(zvei_id) + else: logging.warning("No valid ZVEI: %s", zvei_id) \ No newline at end of file diff --git a/includes/globals.py b/includes/globals.py index 1e5750a8..f4ab2d81 100644 --- a/includes/globals.py +++ b/includes/globals.py @@ -14,14 +14,7 @@ log_path = "" # double alarm -fms_id_old = 0 -fms_time_old = 0 - -zvei_id_old = 0 -zvei_time_old = 0 - -poc_id_old = 0 -poc_time_old = 0 +doubleList = [] # pluginLoader pluginList = {} @@ -32,5 +25,4 @@ # idDescribing fmsDescribtionList = {} zveiDescribtionList = {} -ricDescribtionList = {} - +ricDescribtionList = {} \ No newline at end of file From 098faa02559919c3d08cc2807902f3d67bf1280e Mon Sep 17 00:00:00 2001 From: JHCD Date: Sun, 28 Jun 2015 22:32:17 +0200 Subject: [PATCH 16/98] implemtation of new doubleAlarm-Filter You can set the number of historical entries the filter will check and the time ignoring the id in case of a double alarm --- includes/doubleFilter.py | 56 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 includes/doubleFilter.py diff --git a/includes/doubleFilter.py b/includes/doubleFilter.py new file mode 100644 index 00000000..321dd6fb --- /dev/null +++ b/includes/doubleFilter.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +# -*- coding: cp1252 -*- + +""" +doubleFilter is the central function to filter out double alarms. +You can set the number of historical entries the filter will check +and the time ignoring the id in case of a double alarm + +@author: Jens Herrmann + +@requires: Configuration has to be set in the config.ini +""" + +import logging # Global logger +import time # timestamp for doublealarm + +from includes import globals # Global variables + +# +# ListStructure [0..n] = (ID, TimeStamp) +# + +def checkID(typ, id): + """ + check if id was called in the last x sec and n entries + + @requires: Configuration has to be set in the config.ini + + @return: True if check was OK + @return: False if double was found + """ + timestamp = int(time.time()) # Get Timestamp + + for i in range(len(globals.doubleList)): + (xID, xTimestamp) = globals.doubleList[i] + # given ID found? + # return False if the first entry in double_ignore_time is found, we will not check for younger one... + if id == xID and timestamp < xTimestamp + globals.config.getint("BOSWatch", "double_ignore_time"): + logging.info("%s double alarm: %s within %s second(s)", typ, xID, timestamp-xTimestamp) + return False + return True + + +def newEntry(id): + """ + new entry in double alarm + + @return: nothing + """ + timestamp = int(time.time()) # Get Timestamp + globals.doubleList.append((id, timestamp)) + + # now check if list has more than n entries: + if len(globals.doubleList) > 10: + # we have to kill the oldest one + globals.doubleList.pop(0) \ No newline at end of file From 304b7ddeb068a2e22d4cfca18a342a674e3d4ae5 Mon Sep 17 00:00:00 2001 From: JHCD Date: Sun, 28 Jun 2015 22:37:01 +0200 Subject: [PATCH 17/98] small bug, forgotten to read config-param --- includes/doubleFilter.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/doubleFilter.py b/includes/doubleFilter.py index 321dd6fb..861c1ba2 100644 --- a/includes/doubleFilter.py +++ b/includes/doubleFilter.py @@ -34,7 +34,7 @@ def checkID(typ, id): for i in range(len(globals.doubleList)): (xID, xTimestamp) = globals.doubleList[i] # given ID found? - # return False if the first entry in double_ignore_time is found, we will not check for younger one... + # return False if the first entry in double_ignore_time is found, we will not check for younger ones... if id == xID and timestamp < xTimestamp + globals.config.getint("BOSWatch", "double_ignore_time"): logging.info("%s double alarm: %s within %s second(s)", typ, xID, timestamp-xTimestamp) return False @@ -43,7 +43,7 @@ def checkID(typ, id): def newEntry(id): """ - new entry in double alarm + new entry in double alarm list @return: nothing """ @@ -51,6 +51,6 @@ def newEntry(id): globals.doubleList.append((id, timestamp)) # now check if list has more than n entries: - if len(globals.doubleList) > 10: + if len(globals.doubleList) > globals.config.getint("BOSWatch", "double_ignore_entries"): # we have to kill the oldest one globals.doubleList.pop(0) \ No newline at end of file From 95d2d2f119c735ad8305fd90947effd1160bb4d6 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Mon, 29 Jun 2015 12:19:44 +0200 Subject: [PATCH 18/98] insert onLoad() routine in plugins --- plugins/BosMon/BosMon.py | 23 ++++++++++++++ plugins/MySQL/MySQL.py | 22 +++++++++++++ plugins/eMail/eMail.py | 23 ++++++++++++++ plugins/firEmergency/firEmergency.py | 23 ++++++++++++++ plugins/httpRequest/httpRequest.py | 22 +++++++++++++ plugins/jsonSocket/jsonSocket.py | 23 ++++++++++++++ plugins/template/template.py | 46 ++++++++++++++++++++-------- 7 files changed, 170 insertions(+), 12 deletions(-) diff --git a/plugins/BosMon/BosMon.py b/plugins/BosMon/BosMon.py index 9b9aed68..971fcb30 100644 --- a/plugins/BosMon/BosMon.py +++ b/plugins/BosMon/BosMon.py @@ -19,6 +19,29 @@ from includes import globals # Global variables +## +# +# onLoad function of plugin +# will be called by the pluginLoader +# +def onLoad(): + """ + While loading the plugins by pluginLoader.loadPlugins() + this onLoad() routine are called + + @requires: nothing + + @return: nothing + """ + try: + ########## User onLoad CODE ########## + + ########## User onLoad CODE ########## + + except: + logging.error("unknown error") + logging.debug("unknown error", exc_info=True) + ## # # do BosMon-Request diff --git a/plugins/MySQL/MySQL.py b/plugins/MySQL/MySQL.py index 2ef31a6f..34b95e5b 100644 --- a/plugins/MySQL/MySQL.py +++ b/plugins/MySQL/MySQL.py @@ -18,6 +18,28 @@ from includes import globals # Global variables +## +# +# onLoad function of plugin +# will be called by the pluginLoader +# +def onLoad(): + """ + While loading the plugins by pluginLoader.loadPlugins() + this onLoad() routine are called + + @requires: nothing + + @return: nothing + """ + try: + ########## User onLoad CODE ########## + + ########## User onLoad CODE ########## + + except: + logging.error("unknown error") + logging.debug("unknown error", exc_info=True) ## # diff --git a/plugins/eMail/eMail.py b/plugins/eMail/eMail.py index f879431f..11a38dc6 100644 --- a/plugins/eMail/eMail.py +++ b/plugins/eMail/eMail.py @@ -19,6 +19,29 @@ from includes import globals # Global variables +## +# +# onLoad function of plugin +# will be called by the pluginLoader +# +def onLoad(): + """ + While loading the plugins by pluginLoader.loadPlugins() + this onLoad() routine are called + + @requires: nothing + + @return: nothing + """ + try: + ########## User onLoad CODE ########## + + ########## User onLoad CODE ########## + + except: + logging.error("unknown error") + logging.debug("unknown error", exc_info=True) + ## # # Private helper function for a printable Timestamp diff --git a/plugins/firEmergency/firEmergency.py b/plugins/firEmergency/firEmergency.py index 83cbcb6f..89be104d 100644 --- a/plugins/firEmergency/firEmergency.py +++ b/plugins/firEmergency/firEmergency.py @@ -14,6 +14,29 @@ from includes import globals # Global variables +## +# +# onLoad function of plugin +# will be called by the pluginLoader +# +def onLoad(): + """ + While loading the plugins by pluginLoader.loadPlugins() + this onLoad() routine are called + + @requires: nothing + + @return: nothing + """ + try: + ########## User onLoad CODE ########## + + ########## User onLoad CODE ########## + + except: + logging.error("unknown error") + logging.debug("unknown error", exc_info=True) + ## # # Main function of firEmergency-plugin diff --git a/plugins/httpRequest/httpRequest.py b/plugins/httpRequest/httpRequest.py index 7c5c761e..97444a45 100644 --- a/plugins/httpRequest/httpRequest.py +++ b/plugins/httpRequest/httpRequest.py @@ -15,6 +15,28 @@ from includes import globals # Global variables +## +# +# onLoad function of plugin +# will be called by the pluginLoader +# +def onLoad(): + """ + While loading the plugins by pluginLoader.loadPlugins() + this onLoad() routine are called + + @requires: nothing + + @return: nothing + """ + try: + ########## User onLoad CODE ########## + + ########## User onLoad CODE ########## + + except: + logging.error("unknown error") + logging.debug("unknown error", exc_info=True) ## # diff --git a/plugins/jsonSocket/jsonSocket.py b/plugins/jsonSocket/jsonSocket.py index 010dad6f..60b6f63c 100644 --- a/plugins/jsonSocket/jsonSocket.py +++ b/plugins/jsonSocket/jsonSocket.py @@ -16,6 +16,29 @@ from includes import globals # Global variables +## +# +# onLoad function of plugin +# will be called by the pluginLoader +# +def onLoad(): + """ + While loading the plugins by pluginLoader.loadPlugins() + this onLoad() routine are called + + @requires: nothing + + @return: nothing + """ + try: + ########## User onLoad CODE ########## + + ########## User onLoad CODE ########## + + except: + logging.error("unknown error") + logging.debug("unknown error", exc_info=True) + ## # # Main function of jsonSocket-plugin diff --git a/plugins/template/template.py b/plugins/template/template.py index 85a92e9d..afe0eaf0 100644 --- a/plugins/template/template.py +++ b/plugins/template/template.py @@ -24,6 +24,29 @@ from includes import globals # Global variables +## +# +# onLoad function of plugin +# will be called by the pluginLoader +# +def onLoad(): + """ + While loading the plugins by pluginLoader.loadPlugins() + this onLoad() routine are called + + @requires: nothing + + @return: nothing + """ + try: + ########## User onLoad CODE ########## + + ########## User onLoad CODE ########## + + except: + logging.error("unknown error") + logging.debug("unknown error", exc_info=True) + ## # # Main function of plugin @@ -57,19 +80,18 @@ def run(typ,freq,data): except: logging.error("cannot read config file") logging.debug("cannot read config file", exc_info=True) - # Without config, plugin couldn't work - return + else: # Without config, plugin couldn't work -########## User Plugin CODE ########## - if typ == "FMS": - logging.warning("%s not supported", typ) - elif typ == "ZVEI": - logging.warning("%s not supported", typ) - elif typ == "POC": - logging.warning("%s not supported", typ) - else: - logging.warning("Invalid Typ: %s", typ) -########## User Plugin CODE ########## + ########## User Plugin CODE ########## + if typ == "FMS": + logging.warning("%s not supported", typ) + elif typ == "ZVEI": + logging.warning("%s not supported", typ) + elif typ == "POC": + logging.warning("%s not supported", typ) + else: + logging.warning("Invalid Typ: %s", typ) + ########## User Plugin CODE ########## except: logging.error("unknown error") From 6371d1cf3cb71c6ef3279565151fe72e60c6ca9b Mon Sep 17 00:00:00 2001 From: Schrolli Date: Mon, 29 Jun 2015 12:25:21 +0200 Subject: [PATCH 19/98] replace the return with an else: statement after config reading --- plugins/BosMon/BosMon.py | 181 ++++++++++++------------ plugins/MySQL/MySQL.py | 88 ++++++------ plugins/eMail/eMail.py | 201 +++++++++++++-------------- plugins/firEmergency/firEmergency.py | 97 +++++++------ plugins/httpRequest/httpRequest.py | 99 +++++++------ plugins/jsonSocket/jsonSocket.py | 81 ++++++----- 6 files changed, 369 insertions(+), 378 deletions(-) diff --git a/plugins/BosMon/BosMon.py b/plugins/BosMon/BosMon.py index 971fcb30..0fc49ec2 100644 --- a/plugins/BosMon/BosMon.py +++ b/plugins/BosMon/BosMon.py @@ -114,99 +114,98 @@ def run(typ,freq,data): except: logging.error("cannot read config file") logging.debug("cannot read config file", exc_info=True) - # Without config, plugin couldn't work - return - - try: - # - # Initialize header an connect to BosMon-Server - # - headers = {} - headers['Content-type'] = "application/x-www-form-urlencoded" - headers['Accept'] = "text/plain" - # if an user is set in the config.ini we will use HTTP-Authorization - if globals.config.get("BosMon", "bosmon_user"): - # generate b64encoded autorization-token for HTTP-request - headers['Authorization'] = "Basic {0}".format(base64.b64encode("{0}:{1}".format(globals.config.get("BosMon", "bosmon_user"), globals.config.get("BosMon", "bosmon_password")))) - logging.debug("connect to BosMon") - # open connection to BosMon-Server - httprequest = httplib.HTTPConnection(globals.config.get("BosMon", "bosmon_server"), globals.config.get("BosMon", "bosmon_port"), timeout=5) - # debug-level to shell (0=no debug|1) - httprequest.set_debuglevel(0) - except: - logging.error("cannot connect to BosMon") - logging.debug("cannot connect to BosMon", exc_info=True) - # Without connection, plugin couldn't work - return + else: # Without config, plugin couldn't work + + try: + # + # Initialize header an connect to BosMon-Server + # + headers = {} + headers['Content-type'] = "application/x-www-form-urlencoded" + headers['Accept'] = "text/plain" + # if an user is set in the config.ini we will use HTTP-Authorization + if globals.config.get("BosMon", "bosmon_user"): + # generate b64encoded autorization-token for HTTP-request + headers['Authorization'] = "Basic {0}".format(base64.b64encode("{0}:{1}".format(globals.config.get("BosMon", "bosmon_user"), globals.config.get("BosMon", "bosmon_password")))) + logging.debug("connect to BosMon") + # open connection to BosMon-Server + httprequest = httplib.HTTPConnection(globals.config.get("BosMon", "bosmon_server"), globals.config.get("BosMon", "bosmon_port"), timeout=5) + # debug-level to shell (0=no debug|1) + httprequest.set_debuglevel(0) + except: + logging.error("cannot connect to BosMon") + logging.debug("cannot connect to BosMon", exc_info=True) + # Without connection, plugin couldn't work + return - else: - # - # Format given data-structure to compatible BosMon string - # - if typ == "FMS": - logging.debug("Start FMS to BosMon") - try: - # BosMon-Telegramin expected assembly group, direction and tsi in one field - # structure (binary as hex in base10): - # Byte 1: assembly group; Byte 2: Direction; Byte 3+4: tactic short info - info = 0 - # assembly group: - info = info + 1 # + b0001 (Assumption: is in every time 1 (no output from multimon-ng)) - # direction: - if data["direction"] == "1": - info = info + 2 # + b0010 - # tsi: - if "IV" in data["tsi"]: - info = info + 12 # + b1100 - elif "III" in data["tsi"]: - info = info + 8 # + b1000 - elif "II" in data["tsi"]: - info = info + 4 # + b0100 - # "I" is nothing to do + b0000 - - params = urllib.urlencode({'type':'fms', 'address':data["fms"], 'status':data["status"], 'info':info, 'flags':'0'}) - logging.debug(" - Params: %s", params) - # dispatch the BosMon-request - bosMonRequest(httprequest, params, headers) - except: - logging.error("FMS to BosMon failed") - logging.debug("FMS to BosMon failed", exc_info=True) - return - - elif typ == "ZVEI": - logging.debug("Start ZVEI to BosMon") - try: - params = urllib.urlencode({'type':'zvei', 'address':data["zvei"], 'flags':'0'}) - logging.debug(" - Params: %s", params) - # dispatch the BosMon-request - bosMonRequest(httprequest, params, headers) - except: - logging.error("ZVEI to BosMon failed") - logging.debug("ZVEI to BosMon failed", exc_info=True) - return - - elif typ == "POC": - logging.debug("Start POC to BosMon") - try: - # BosMon-Telegramin expected "a-d" as RIC-sub/function - params = urllib.urlencode({'type':'pocsag', 'address':data["ric"], 'flags':'0', 'function':data["functionChar"], 'message':data["msg"]}) - logging.debug(" - Params: %s", params) - # dispatch the BosMon-request - bosMonRequest(httprequest, params, headers) - except: - logging.error("POC to BosMon failed") - logging.debug("POC to BosMon failed", exc_info=True) - return - else: - logging.warning("Invalid Typ: %s", typ) - - finally: - logging.debug("close BosMon-Connection") - try: - httprequest.close() - except: - pass + # + # Format given data-structure to compatible BosMon string + # + if typ == "FMS": + logging.debug("Start FMS to BosMon") + try: + # BosMon-Telegramin expected assembly group, direction and tsi in one field + # structure (binary as hex in base10): + # Byte 1: assembly group; Byte 2: Direction; Byte 3+4: tactic short info + info = 0 + # assembly group: + info = info + 1 # + b0001 (Assumption: is in every time 1 (no output from multimon-ng)) + # direction: + if data["direction"] == "1": + info = info + 2 # + b0010 + # tsi: + if "IV" in data["tsi"]: + info = info + 12 # + b1100 + elif "III" in data["tsi"]: + info = info + 8 # + b1000 + elif "II" in data["tsi"]: + info = info + 4 # + b0100 + # "I" is nothing to do + b0000 + + params = urllib.urlencode({'type':'fms', 'address':data["fms"], 'status':data["status"], 'info':info, 'flags':'0'}) + logging.debug(" - Params: %s", params) + # dispatch the BosMon-request + bosMonRequest(httprequest, params, headers) + except: + logging.error("FMS to BosMon failed") + logging.debug("FMS to BosMon failed", exc_info=True) + return + + elif typ == "ZVEI": + logging.debug("Start ZVEI to BosMon") + try: + params = urllib.urlencode({'type':'zvei', 'address':data["zvei"], 'flags':'0'}) + logging.debug(" - Params: %s", params) + # dispatch the BosMon-request + bosMonRequest(httprequest, params, headers) + except: + logging.error("ZVEI to BosMon failed") + logging.debug("ZVEI to BosMon failed", exc_info=True) + return + + elif typ == "POC": + logging.debug("Start POC to BosMon") + try: + # BosMon-Telegramin expected "a-d" as RIC-sub/function + params = urllib.urlencode({'type':'pocsag', 'address':data["ric"], 'flags':'0', 'function':data["functionChar"], 'message':data["msg"]}) + logging.debug(" - Params: %s", params) + # dispatch the BosMon-request + bosMonRequest(httprequest, params, headers) + except: + logging.error("POC to BosMon failed") + logging.debug("POC to BosMon failed", exc_info=True) + return + + else: + logging.warning("Invalid Typ: %s", typ) + + finally: + logging.debug("close BosMon-Connection") + try: + httprequest.close() + except: + pass except: # something very mysterious diff --git a/plugins/MySQL/MySQL.py b/plugins/MySQL/MySQL.py index 34b95e5b..226c0713 100644 --- a/plugins/MySQL/MySQL.py +++ b/plugins/MySQL/MySQL.py @@ -77,56 +77,52 @@ def run(typ,freq,data): except: logging.error("cannot read config file") logging.debug("cannot read config file", exc_info=True) - # Without config, plugin couldn't work - return + else: # Without config, plugin couldn't work - try: - # - # Connect to MySQL - # - logging.debug("connect to MySQL") - connection = mysql.connector.connect(host = globals.config.get("MySQL","dbserver"), user = globals.config.get("MySQL","dbuser"), passwd = globals.config.get("MySQL","dbpassword"), db = globals.config.get("MySQL","database")) - cursor = connection.cursor() - except: - logging.error("cannot connect to MySQL") - logging.debug("cannot connect to MySQL", exc_info=True) - # Without connection, plugin couldn't work - return - - else: try: + # + # Connect to MySQL # - # Create and execute SQL-statement - # - logging.debug("Insert %s", typ) - - if typ == "FMS": - #data = {"fms":fms_id[0:8], "status":fms_status, "direction":fms_direction, "tsi":fms_tsi} - cursor.execute("INSERT INTO "+globals.config.get("MySQL","tableFMS")+" (time,fms,status,direction,tsi) VALUES (NOW(),%s,%s,%s,%s)",(data["fms"],data["status"],data["direction"],data["tsi"])) - - elif typ == "ZVEI": - #data = {"zvei":zvei_id} - #Don't use %s here (bug in mysql-lib with one parameter) - cursor.execute("INSERT INTO "+globals.config.get("MySQL","tableZVEI")+" (time,zvei) VALUES (NOW(),"+(data["zvei"])+")") - - elif typ == "POC": - #data = {"ric":poc_id, "function":poc_sub, "msg":poc_text} - cursor.execute("INSERT INTO "+globals.config.get("MySQL","tablePOC")+" (time,ric,funktion,text) VALUES (NOW(),%s,%s,%s)",(data["ric"],data["function"],data["msg"])) - - else: - logging.warning("Invalid Typ: %s", typ) + logging.debug("connect to MySQL") + connection = mysql.connector.connect(host = globals.config.get("MySQL","dbserver"), user = globals.config.get("MySQL","dbuser"), passwd = globals.config.get("MySQL","dbpassword"), db = globals.config.get("MySQL","database")) + cursor = connection.cursor() except: - logging.error("cannot Insert %s", typ) - logging.debug("cannot Insert %s", typ, exc_info=True) - return - - finally: - logging.debug("close MySQL") - try: - cursor.close() - connection.close() #Close connection in every case - except: - pass + logging.error("cannot connect to MySQL") + logging.debug("cannot connect to MySQL", exc_info=True) + else: # Without connection, plugin couldn't work + try: + # + # Create and execute SQL-statement + # + logging.debug("Insert %s", typ) + + if typ == "FMS": + #data = {"fms":fms_id[0:8], "status":fms_status, "direction":fms_direction, "tsi":fms_tsi} + cursor.execute("INSERT INTO "+globals.config.get("MySQL","tableFMS")+" (time,fms,status,direction,tsi) VALUES (NOW(),%s,%s,%s,%s)",(data["fms"],data["status"],data["direction"],data["tsi"])) + + elif typ == "ZVEI": + #data = {"zvei":zvei_id} + #Don't use %s here (bug in mysql-lib with one parameter) + cursor.execute("INSERT INTO "+globals.config.get("MySQL","tableZVEI")+" (time,zvei) VALUES (NOW(),"+(data["zvei"])+")") + + elif typ == "POC": + #data = {"ric":poc_id, "function":poc_sub, "msg":poc_text} + cursor.execute("INSERT INTO "+globals.config.get("MySQL","tablePOC")+" (time,ric,funktion,text) VALUES (NOW(),%s,%s,%s)",(data["ric"],data["function"],data["msg"])) + + else: + logging.warning("Invalid Typ: %s", typ) + except: + logging.error("cannot Insert %s", typ) + logging.debug("cannot Insert %s", typ, exc_info=True) + return + + finally: + logging.debug("close MySQL") + try: + cursor.close() + connection.close() #Close connection in every case + except: + pass except: logging.error("unknown error") diff --git a/plugins/eMail/eMail.py b/plugins/eMail/eMail.py index 11a38dc6..2540ddae 100644 --- a/plugins/eMail/eMail.py +++ b/plugins/eMail/eMail.py @@ -118,110 +118,109 @@ def run(typ,freq,data): except: logging.error("cannot read config file") logging.debug("cannot read config file", exc_info=True) - # Without config, plugin couldn't work - return + else: # Without config, plugin couldn't work + + try: + # + # connect to SMTP-Server + # + server = smtplib.SMTP(globals.config.get("eMail", "smtp_server"), globals.config.get("eMail", "smtp_port")) + # debug-level to shell (0=no debug|1) + server.set_debuglevel(0) + + # if tls is enabled, starttls + if globals.config.get("eMail", "tls"): + server.starttls() + + # if user is given, login + if globals.config.get("eMail", "user"): + server.login(globals.config.get("eMail", "user"), globals.config.get("eMail", "password")) + + except: + logging.error("cannot connect to eMail") + logging.debug("cannot connect to eMail", exc_info=True) + # Without connection, plugin couldn't work + return - try: - # - # connect to SMTP-Server - # - server = smtplib.SMTP(globals.config.get("eMail", "smtp_server"), globals.config.get("eMail", "smtp_port")) - # debug-level to shell (0=no debug|1) - server.set_debuglevel(0) - - # if tls is enabled, starttls - if globals.config.get("eMail", "tls"): - server.starttls() - - # if user is given, login - if globals.config.get("eMail", "user"): - server.login(globals.config.get("eMail", "user"), globals.config.get("eMail", "password")) - - except: - logging.error("cannot connect to eMail") - logging.debug("cannot connect to eMail", exc_info=True) - # Without connection, plugin couldn't work - return - - else: - - if typ == "FMS": - logging.debug("Start FMS to eMail") - try: - # read subject-structure from config.ini - subject = globals.config.get("eMail", "fms_subject") - subject = subject.replace("%FMS%", data["fms"]).replace("%STATUS%", data["status"]) #replace Wildcards - subject = subject.replace("%DIR%", data["direction"]).replace("%DIRT%", data["directionText"]) #replace Wildcards - subject = subject.replace("%TSI%", data["tsi"]) #replace Wildcards - subject = subject.replace("%DESCR%", data["description"]) # replace Wildcards - subject = subject.replace("%TIME%", curtime()) # replace Wildcards - # read mailtext-structure from config.ini - mailtext = globals.config.get("eMail", "fms_message") - mailtext = mailtext.replace("%FMS%", data["fms"]).replace("%STATUS%", data["status"]) #replace Wildcards - mailtext = mailtext.replace("%DIR%", data["direction"]).replace("%DIRT%", data["directionText"]) #replace Wildcards - mailtext = mailtext.replace("%TSI%", data["tsi"]) #replace Wildcards - mailtext = mailtext.replace("%DESCR%", data["description"]) # replace Wildcards - mailtext = mailtext.replace("%TIME%", curtime()) # replace Wildcards - # send eMail - doSendmail(server, subject, mailtext) - except: - logging.error("%s to eMail failed", typ) - logging.debug("%s to eMail failed", typ, exc_info=True) - return - - elif typ == "ZVEI": - logging.debug("Start ZVEI to eMail") - try: - # read subject-structure from config.ini - subject = globals.config.get("eMail", "zvei_subject") - subject = subject.replace("%ZVEI%", data["zvei"]) #replace Wildcards - subject = subject.replace("%DESCR%", data["description"]) # replace Wildcards - subject = subject.replace("%TIME%", curtime()) # replace Wildcards - # read mailtext-structure from config.ini - mailtext = globals.config.get("eMail", "zvei_message") - mailtext = mailtext.replace("%ZVEI%", data["zvei"]) #replace Wildcards - mailtext = mailtext.replace("%DESCR%", data["description"]) # replace Wildcards - mailtext = mailtext.replace("%TIME%", curtime()) # replace Wildcards - # send eMail - doSendmail(server, subject, mailtext) - except: - logging.error("%s to eMail failed", typ) - logging.debug("%s to eMail failed", typ, exc_info=True) - return - - elif typ == "POC": - logging.debug("Start POC to eMail") - try: - # read subject-structure from config.ini - subject = globals.config.get("eMail", "poc_subject") - subject = subject.replace("%RIC%", data["ric"]) #replace Wildcards - subject = subject.replace("%FUNC%", data["function"]).replace("%FUNCCHAR%", data["functionChar"]) #replace Wildcards - subject = subject.replace("%MSG%", data["msg"]).replace("%BITRATE%", str(data["bitrate"])) #replace Wildcards - subject = subject.replace("%DESCR%", data["description"]) # replace Wildcards - subject = subject.replace("%TIME%", curtime()) # replace Wildcards - # read mailtext-structure from config.ini - mailtext = globals.config.get("eMail", "poc_message") - mailtext = mailtext.replace("%RIC%", data["ric"]) #replace Wildcards - mailtext = mailtext.replace("%FUNC%", data["function"]).replace("%FUNCCHAR%", data["functionChar"]) #replace Wildcards - mailtext = mailtext.replace("%MSG%", data["msg"]).replace("%BITRATE%", str(data["bitrate"])) #replace Wildcards - mailtext = mailtext.replace("%DESCR%", data["description"]) # replace Wildcards - mailtext = mailtext.replace("%TIME%", curtime()) # replace Wildcards - # send eMail - doSendmail(server, subject, mailtext) - except: - logging.error("%s to eMail failed", typ) - logging.debug("%s to eMail failed", typ, exc_info=True) - return - else: - logging.warning("Invalid Typ: %s", typ) - finally: - logging.debug("close eMail-Connection") - try: - server.quit() - except: - pass + if typ == "FMS": + logging.debug("Start FMS to eMail") + try: + # read subject-structure from config.ini + subject = globals.config.get("eMail", "fms_subject") + subject = subject.replace("%FMS%", data["fms"]).replace("%STATUS%", data["status"]) #replace Wildcards + subject = subject.replace("%DIR%", data["direction"]).replace("%DIRT%", data["directionText"]) #replace Wildcards + subject = subject.replace("%TSI%", data["tsi"]) #replace Wildcards + subject = subject.replace("%DESCR%", data["description"]) # replace Wildcards + subject = subject.replace("%TIME%", curtime()) # replace Wildcards + # read mailtext-structure from config.ini + mailtext = globals.config.get("eMail", "fms_message") + mailtext = mailtext.replace("%FMS%", data["fms"]).replace("%STATUS%", data["status"]) #replace Wildcards + mailtext = mailtext.replace("%DIR%", data["direction"]).replace("%DIRT%", data["directionText"]) #replace Wildcards + mailtext = mailtext.replace("%TSI%", data["tsi"]) #replace Wildcards + mailtext = mailtext.replace("%DESCR%", data["description"]) # replace Wildcards + mailtext = mailtext.replace("%TIME%", curtime()) # replace Wildcards + # send eMail + doSendmail(server, subject, mailtext) + except: + logging.error("%s to eMail failed", typ) + logging.debug("%s to eMail failed", typ, exc_info=True) + return + + elif typ == "ZVEI": + logging.debug("Start ZVEI to eMail") + try: + # read subject-structure from config.ini + subject = globals.config.get("eMail", "zvei_subject") + subject = subject.replace("%ZVEI%", data["zvei"]) #replace Wildcards + subject = subject.replace("%DESCR%", data["description"]) # replace Wildcards + subject = subject.replace("%TIME%", curtime()) # replace Wildcards + # read mailtext-structure from config.ini + mailtext = globals.config.get("eMail", "zvei_message") + mailtext = mailtext.replace("%ZVEI%", data["zvei"]) #replace Wildcards + mailtext = mailtext.replace("%DESCR%", data["description"]) # replace Wildcards + mailtext = mailtext.replace("%TIME%", curtime()) # replace Wildcards + # send eMail + doSendmail(server, subject, mailtext) + except: + logging.error("%s to eMail failed", typ) + logging.debug("%s to eMail failed", typ, exc_info=True) + return + + elif typ == "POC": + logging.debug("Start POC to eMail") + try: + # read subject-structure from config.ini + subject = globals.config.get("eMail", "poc_subject") + subject = subject.replace("%RIC%", data["ric"]) #replace Wildcards + subject = subject.replace("%FUNC%", data["function"]).replace("%FUNCCHAR%", data["functionChar"]) #replace Wildcards + subject = subject.replace("%MSG%", data["msg"]).replace("%BITRATE%", str(data["bitrate"])) #replace Wildcards + subject = subject.replace("%DESCR%", data["description"]) # replace Wildcards + subject = subject.replace("%TIME%", curtime()) # replace Wildcards + # read mailtext-structure from config.ini + mailtext = globals.config.get("eMail", "poc_message") + mailtext = mailtext.replace("%RIC%", data["ric"]) #replace Wildcards + mailtext = mailtext.replace("%FUNC%", data["function"]).replace("%FUNCCHAR%", data["functionChar"]) #replace Wildcards + mailtext = mailtext.replace("%MSG%", data["msg"]).replace("%BITRATE%", str(data["bitrate"])) #replace Wildcards + mailtext = mailtext.replace("%DESCR%", data["description"]) # replace Wildcards + mailtext = mailtext.replace("%TIME%", curtime()) # replace Wildcards + # send eMail + doSendmail(server, subject, mailtext) + except: + logging.error("%s to eMail failed", typ) + logging.debug("%s to eMail failed", typ, exc_info=True) + return + + else: + logging.warning("Invalid Typ: %s", typ) + + finally: + logging.debug("close eMail-Connection") + try: + server.quit() + except: + pass except: # something very mysterious diff --git a/plugins/firEmergency/firEmergency.py b/plugins/firEmergency/firEmergency.py index 89be104d..6692a7bb 100644 --- a/plugins/firEmergency/firEmergency.py +++ b/plugins/firEmergency/firEmergency.py @@ -71,59 +71,58 @@ def run(typ,freq,data): except: logging.error("cannot read config file") logging.debug("cannot read config file", exc_info=True) - # Without config, plugin couldn't work - return + else: # Without config, plugin couldn't work - try: - # - # connect to firEmergency - # - firSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - firSocket.connect((globals.config.get("firEmergency", "firserver"), globals.config.getint("firEmergency", "firport"))) - except: - logging.error("cannot connect to firEmergency") - logging.debug("cannot connect to firEmergency", exc_info=True) - # Without connection, plugin couldn't work - return - - else: - # - # Format given data-structure to xml-string for firEmergency - # - if typ == "FMS": - logging.debug("FMS not supported by firEmgency") + try: + # + # connect to firEmergency + # + firSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + firSocket.connect((globals.config.get("firEmergency", "firserver"), globals.config.getint("firEmergency", "firport"))) + except: + logging.error("cannot connect to firEmergency") + logging.debug("cannot connect to firEmergency", exc_info=True) + # Without connection, plugin couldn't work + return - elif typ == "ZVEI": - logging.debug("ZVEI to firEmergency") - try: - firXML = "\n
"+data["zvei"]+"
\n"+data["zvei"]+" alarmiert.\n
\n" - firSocket.send(firXML) - except: - logging.error("%s to firEmergency failed", typ) - logging.debug("%s to firEmergency failed", typ, exc_info=True) - # Without connection, plugin couldn't work - return - - elif typ == "POC": - logging.debug("POC to firEmergency") - try: - firXML = "\n
"+data["ric"]+"
\n"+data["msg"]+"\n
\n" - firSocket.send(firXML) - except: - logging.error("%s to firEmergency failed", typ) - logging.debug("%s to firEmergency failed", typ, exc_info=True) - # Without connection, plugin couldn't work - return + else: + # + # Format given data-structure to xml-string for firEmergency + # + if typ == "FMS": + logging.debug("FMS not supported by firEmgency") + + elif typ == "ZVEI": + logging.debug("ZVEI to firEmergency") + try: + firXML = "\n
"+data["zvei"]+"
\n"+data["zvei"]+" alarmiert.\n
\n" + firSocket.send(firXML) + except: + logging.error("%s to firEmergency failed", typ) + logging.debug("%s to firEmergency failed", typ, exc_info=True) + # Without connection, plugin couldn't work + return + + elif typ == "POC": + logging.debug("POC to firEmergency") + try: + firXML = "\n
"+data["ric"]+"
\n"+data["msg"]+"\n
\n" + firSocket.send(firXML) + except: + logging.error("%s to firEmergency failed", typ) + logging.debug("%s to firEmergency failed", typ, exc_info=True) + # Without connection, plugin couldn't work + return - else: - logging.warning("Invalid Typ: %s", typ) + else: + logging.warning("Invalid Typ: %s", typ) - finally: - logging.debug("close firEmergency-Connection") - try: - firSocket.close() - except: - pass + finally: + logging.debug("close firEmergency-Connection") + try: + firSocket.close() + except: + pass except: logging.error("unknown error") diff --git a/plugins/httpRequest/httpRequest.py b/plugins/httpRequest/httpRequest.py index 97444a45..54559839 100644 --- a/plugins/httpRequest/httpRequest.py +++ b/plugins/httpRequest/httpRequest.py @@ -70,62 +70,61 @@ def run(typ,freq,data): except: logging.error("cannot read config file") logging.debug("cannot read config file", exc_info=True) - # Without config, plugin couldn't work - return - - try: - # - # Create URL - # - logging.debug("send %s HTTP request", typ) - - if typ == "FMS": - url = globals.config.get("httpRequest", "fms_url") #Get URL - url = url.replace("%FMS%", data["fms"]).replace("%STATUS%", data["status"]) #replace Wildcards in URL - url = url.replace("%DIR%", data["direction"]).replace("%TSI%", data["tsi"]) #replace Wildcards in URL - elif typ == "ZVEI": - url = globals.config.get("httpRequest", "zvei_url") #Get URL - url = url.replace("%ZVEI%", data["zvei"]) #replace Wildcards in URL - elif typ == "POC": - url = globals.config.get("httpRequest", "poc_url") #Get URL - url = url.replace("%RIC%", data["ric"]).replace("%FUNC%", data["function"]) #replace Wildcards in URL - url = url.replace("%MSG%", data["msg"]).replace("%BITRATE%", data["bitrate"]) #replace Wildcards in URL - else: - logging.warning("Invalid Typ: %s", typ) + else: # Without config, plugin couldn't work - # - # HTTP-Request - # - url = urlparse(url) #split URL into path and querry - httprequest = httplib.HTTPConnection(url[2]) #connect to URL Path - httprequest.request("GET", url[5]) #send URL Querry per GET - - except: - logging.error("cannot send HTTP request") - logging.debug("cannot send HTTP request", exc_info=True) - return - - else: try: - # - # check HTTP-Response # - httpresponse = httprequest.getresponse() - if str(httpresponse.status) == "200": #Check HTTP Response an print a Log or Error - logging.debug("HTTP response: %s - %s" , str(httpresponse.status), str(httpresponse.reason)) + # Create URL + # + logging.debug("send %s HTTP request", typ) + + if typ == "FMS": + url = globals.config.get("httpRequest", "fms_url") #Get URL + url = url.replace("%FMS%", data["fms"]).replace("%STATUS%", data["status"]) #replace Wildcards in URL + url = url.replace("%DIR%", data["direction"]).replace("%TSI%", data["tsi"]) #replace Wildcards in URL + elif typ == "ZVEI": + url = globals.config.get("httpRequest", "zvei_url") #Get URL + url = url.replace("%ZVEI%", data["zvei"]) #replace Wildcards in URL + elif typ == "POC": + url = globals.config.get("httpRequest", "poc_url") #Get URL + url = url.replace("%RIC%", data["ric"]).replace("%FUNC%", data["function"]) #replace Wildcards in URL + url = url.replace("%MSG%", data["msg"]).replace("%BITRATE%", data["bitrate"]) #replace Wildcards in URL else: - logging.warning("HTTP response: %s - %s" , str(httpresponse.status), str(httpresponse.reason)) - except: #otherwise - logging.error("cannot get HTTP response") - logging.debug("cannot get HTTP response", exc_info=True) - return + logging.warning("Invalid Typ: %s", typ) + + # + # HTTP-Request + # + url = urlparse(url) #split URL into path and querry + httprequest = httplib.HTTPConnection(url[2]) #connect to URL Path + httprequest.request("GET", url[5]) #send URL Querry per GET - finally: - logging.debug("close HTTP-Connection") - try: - httprequest.close() except: - pass + logging.error("cannot send HTTP request") + logging.debug("cannot send HTTP request", exc_info=True) + return + + else: + try: + # + # check HTTP-Response + # + httpresponse = httprequest.getresponse() + if str(httpresponse.status) == "200": #Check HTTP Response an print a Log or Error + logging.debug("HTTP response: %s - %s" , str(httpresponse.status), str(httpresponse.reason)) + else: + logging.warning("HTTP response: %s - %s" , str(httpresponse.status), str(httpresponse.reason)) + except: #otherwise + logging.error("cannot get HTTP response") + logging.debug("cannot get HTTP response", exc_info=True) + return + + finally: + logging.debug("close HTTP-Connection") + try: + httprequest.close() + except: + pass except: logging.error("unknown error") diff --git a/plugins/jsonSocket/jsonSocket.py b/plugins/jsonSocket/jsonSocket.py index 60b6f63c..6bc6f42d 100644 --- a/plugins/jsonSocket/jsonSocket.py +++ b/plugins/jsonSocket/jsonSocket.py @@ -74,51 +74,50 @@ def run(typ,freq,data): except: logging.error("cannot read config file") logging.debug("cannot read config file", exc_info=True) - # Without config, plugin couldn't work - return + else: # Without config, plugin couldn't work - try: - # - # initialize to socket-Server - # - # SOCK_DGRAM is the socket type to use for UDP sockets - # SOCK_STREAM is the socket type to use for TCP sockets - if globals.config.get("jsonSocket", "protocol") == "TCP": - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect((globals.config.get("jsonSocket", "server"), globals.config.getint("jsonSocket", "port"))) - else: - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - - except: - logging.error("cannot initialize %s-socket", globals.config.get("jsonSocket", "protocol")) - logging.debug("cannot initialize %s-socket", globals.config.get("jsonSocket", "protocol"), exc_info=True) - # Without connection, plugin couldn't work - return - - else: - # toDo is equals for all types, so only check if typ is supported - supportedTypes = ["FMS", "ZVEI", "POC"] - if typ in supportedTypes: - logging.debug("Start %s to %s", typ, globals.config.get("jsonSocket", "protocol")) - try: - # dump data to json-string - sendData = json.dumps(data) - # send data - sock.sendto(sendData, (globals.config.get("jsonSocket", "server"), globals.config.getint("jsonSocket", "port"))) - except: - logging.error("%s to %s failed", typ, globals.config.get("jsonSocket", "protocol")) - logging.debug("%s to %s failed", typ, globals.config.get("jsonSocket", "protocol"), exc_info=True) - return + try: + # + # initialize to socket-Server + # + # SOCK_DGRAM is the socket type to use for UDP sockets + # SOCK_STREAM is the socket type to use for TCP sockets + if globals.config.get("jsonSocket", "protocol") == "TCP": + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((globals.config.get("jsonSocket", "server"), globals.config.getint("jsonSocket", "port"))) + else: + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + except: + logging.error("cannot initialize %s-socket", globals.config.get("jsonSocket", "protocol")) + logging.debug("cannot initialize %s-socket", globals.config.get("jsonSocket", "protocol"), exc_info=True) + # Without connection, plugin couldn't work + return else: - logging.warning("Invalid Typ: %s", typ) + # toDo is equals for all types, so only check if typ is supported + supportedTypes = ["FMS", "ZVEI", "POC"] + if typ in supportedTypes: + logging.debug("Start %s to %s", typ, globals.config.get("jsonSocket", "protocol")) + try: + # dump data to json-string + sendData = json.dumps(data) + # send data + sock.sendto(sendData, (globals.config.get("jsonSocket", "server"), globals.config.getint("jsonSocket", "port"))) + except: + logging.error("%s to %s failed", typ, globals.config.get("jsonSocket", "protocol")) + logging.debug("%s to %s failed", typ, globals.config.get("jsonSocket", "protocol"), exc_info=True) + return - finally: - logging.debug("close %s-Connection", globals.config.get("jsonSocket", "protocol")) - try: - sock.close() - except: - pass + else: + logging.warning("Invalid Typ: %s", typ) + + finally: + logging.debug("close %s-Connection", globals.config.get("jsonSocket", "protocol")) + try: + sock.close() + except: + pass except: # something very mysterious From 7da58fe5217f6ef0b7bb30ffd61ee5864b015943 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Mon, 29 Jun 2015 12:55:13 +0200 Subject: [PATCH 20/98] call the .onLoad() routine during plugin loading --- includes/pluginLoader.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/includes/pluginLoader.py b/includes/pluginLoader.py index 31bd097a..3b606af7 100644 --- a/includes/pluginLoader.py +++ b/includes/pluginLoader.py @@ -30,7 +30,17 @@ def loadPlugins(): # call for each Plugin the loadPlugin() Methode plugin = loadPlugin(i) # Add it to globals.pluginList - globals.pluginList[i["name"]] = plugin + globals.pluginList[i["name"]] = plugin + + #call the .onLoad() routine for all active plugins + for pluginName, plugin in globals.pluginList.items(): + logging.debug("call %s.onLoad()", pluginName) + try: + plugin.onLoad(typ,freq,data) + except: + # call next plugin, if one has thrown an exception + pass + except: logging.exception("cannot load Plugins") From 407e22e1e4ea97cc0c7eef6c78cbb4e0bdf778f1 Mon Sep 17 00:00:00 2001 From: JHCD Date: Mon, 29 Jun 2015 17:06:11 +0200 Subject: [PATCH 21/98] resolve small bug in onLoad() --- plugins/BosMon/BosMon.py | 6 ++---- plugins/MySQL/MySQL.py | 6 ++---- plugins/eMail/eMail.py | 6 ++---- plugins/firEmergency/firEmergency.py | 6 ++---- plugins/httpRequest/httpRequest.py | 6 ++---- plugins/jsonSocket/jsonSocket.py | 6 ++---- plugins/template/template.py | 3 +-- 7 files changed, 13 insertions(+), 26 deletions(-) diff --git a/plugins/BosMon/BosMon.py b/plugins/BosMon/BosMon.py index 0fc49ec2..760cc446 100644 --- a/plugins/BosMon/BosMon.py +++ b/plugins/BosMon/BosMon.py @@ -34,10 +34,8 @@ def onLoad(): @return: nothing """ try: - ########## User onLoad CODE ########## - - ########## User onLoad CODE ########## - + # we have to do nothing here... + pass except: logging.error("unknown error") logging.debug("unknown error", exc_info=True) diff --git a/plugins/MySQL/MySQL.py b/plugins/MySQL/MySQL.py index 226c0713..ceb377dd 100644 --- a/plugins/MySQL/MySQL.py +++ b/plugins/MySQL/MySQL.py @@ -33,10 +33,8 @@ def onLoad(): @return: nothing """ try: - ########## User onLoad CODE ########## - - ########## User onLoad CODE ########## - + # we have to do nothing here... + pass except: logging.error("unknown error") logging.debug("unknown error", exc_info=True) diff --git a/plugins/eMail/eMail.py b/plugins/eMail/eMail.py index 2540ddae..ec72743e 100644 --- a/plugins/eMail/eMail.py +++ b/plugins/eMail/eMail.py @@ -34,10 +34,8 @@ def onLoad(): @return: nothing """ try: - ########## User onLoad CODE ########## - - ########## User onLoad CODE ########## - + # we have to do nothing here... + pass except: logging.error("unknown error") logging.debug("unknown error", exc_info=True) diff --git a/plugins/firEmergency/firEmergency.py b/plugins/firEmergency/firEmergency.py index 6692a7bb..5ea918b7 100644 --- a/plugins/firEmergency/firEmergency.py +++ b/plugins/firEmergency/firEmergency.py @@ -29,10 +29,8 @@ def onLoad(): @return: nothing """ try: - ########## User onLoad CODE ########## - - ########## User onLoad CODE ########## - + # we have to do nothing here... + pass except: logging.error("unknown error") logging.debug("unknown error", exc_info=True) diff --git a/plugins/httpRequest/httpRequest.py b/plugins/httpRequest/httpRequest.py index 54559839..0f8a22e1 100644 --- a/plugins/httpRequest/httpRequest.py +++ b/plugins/httpRequest/httpRequest.py @@ -30,10 +30,8 @@ def onLoad(): @return: nothing """ try: - ########## User onLoad CODE ########## - - ########## User onLoad CODE ########## - + # we have to do nothing here... + pass except: logging.error("unknown error") logging.debug("unknown error", exc_info=True) diff --git a/plugins/jsonSocket/jsonSocket.py b/plugins/jsonSocket/jsonSocket.py index 6bc6f42d..4dec8a51 100644 --- a/plugins/jsonSocket/jsonSocket.py +++ b/plugins/jsonSocket/jsonSocket.py @@ -31,10 +31,8 @@ def onLoad(): @return: nothing """ try: - ########## User onLoad CODE ########## - - ########## User onLoad CODE ########## - + # we have to do nothing here... + pass except: logging.error("unknown error") logging.debug("unknown error", exc_info=True) diff --git a/plugins/template/template.py b/plugins/template/template.py index afe0eaf0..9d306c08 100644 --- a/plugins/template/template.py +++ b/plugins/template/template.py @@ -40,9 +40,8 @@ def onLoad(): """ try: ########## User onLoad CODE ########## - + pass ########## User onLoad CODE ########## - except: logging.error("unknown error") logging.debug("unknown error", exc_info=True) From eba5b7947a3db9551be173b5f0b0a71e40753aff Mon Sep 17 00:00:00 2001 From: JHCD Date: Mon, 29 Jun 2015 17:15:20 +0200 Subject: [PATCH 22/98] enhancement of doubleFilter - expand id for pocsag: new pocID+function als "id" - if wanted, enable doubleFilter_check_msg in config.ini it will check if the new msg is a substring of the old one if not it will pass --- config/config.template.ini | 13 ++++++++++--- includes/decoders/poc.py | 4 ++-- includes/doubleFilter.py | 25 ++++++++++++++++--------- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/config/config.template.ini b/config/config.template.ini index 7f354fd9..206ede9c 100644 --- a/config/config.template.ini +++ b/config/config.template.ini @@ -28,10 +28,17 @@ useDescription = 0 # for double check save the last n IDs # it is used in combination with double_ignore_time # 1 is required if you want to use the double alarm filter -double_ignore_entries = 10 +doubleFilter_ignore_entries = 10 -#time to ignore same alarm (only ID is checked) (sek) -double_ignore_time = 5 +# time to ignore same alarm (only ID is checked) (sek) +doubleFilter_ignore_time = 5 + +# ignore msg is only usefull for POCSAG (0|1) +# 0: double check ignores the msg-text (only check ID + function) +# 1: if you want to differentiate between with/ without msg +# f.e. if they use quick-alarm (without text, then same ric with msg) +# you will get more then one alarm anyway if the msg is different (receiving-problems) +doubleFilter_check_msg = 0 [FMS] # look-up-table for adding a description diff --git a/includes/decoders/poc.py b/includes/decoders/poc.py index c8dee0d8..ee2e7bef 100644 --- a/includes/decoders/poc.py +++ b/includes/decoders/poc.py @@ -104,7 +104,7 @@ def decode(freq, decoded): if re.search("[0-9]{7}", poc_id): #if POC is valid if isAllowed(poc_id): # check for double alarm - if doubleFilter.checkID("POC", poc_id): + if doubleFilter.checkID("POC", poc_id+poc_sub, poc_text): logging.info("POCSAG%s: %s %s %s ", bitrate, poc_id, poc_sub, poc_text) data = {"ric":poc_id, "function":poc_sub, "msg":poc_text, "bitrate":bitrate, "description":poc_id} # Add function as character a-d to dataset @@ -122,7 +122,7 @@ def decode(freq, decoded): logging.debug("processing alarm failed", exc_info=True) pass # in every time save old data for double alarm - doubleFilter.newEntry(poc_id) + doubleFilter.newEntry(poc_id+poc_sub, poc_text) else: logging.debug("POCSAG%s: %s is not allowed", bitrate, poc_id) else: diff --git a/includes/doubleFilter.py b/includes/doubleFilter.py index 861c1ba2..b1248ac3 100644 --- a/includes/doubleFilter.py +++ b/includes/doubleFilter.py @@ -17,10 +17,10 @@ from includes import globals # Global variables # -# ListStructure [0..n] = (ID, TimeStamp) +# ListStructure [0..n] = (ID, TimeStamp, msg) # -def checkID(typ, id): +def checkID(typ, id, msg=""): """ check if id was called in the last x sec and n entries @@ -32,25 +32,32 @@ def checkID(typ, id): timestamp = int(time.time()) # Get Timestamp for i in range(len(globals.doubleList)): - (xID, xTimestamp) = globals.doubleList[i] + (xID, xTimestamp, xMsg) = globals.doubleList[i] # given ID found? # return False if the first entry in double_ignore_time is found, we will not check for younger ones... - if id == xID and timestamp < xTimestamp + globals.config.getint("BOSWatch", "double_ignore_time"): - logging.info("%s double alarm: %s within %s second(s)", typ, xID, timestamp-xTimestamp) - return False + if id == xID and timestamp < xTimestamp + globals.config.getint("BOSWatch", "doubleFilter_ignore_time"): + # if wanted, we have to check the msg additional + if "POC" in typ and globals.config.getint("BOSWatch", "doubleFilter_check_msg"): + # if msg is a substring of xMsg we found a double + if msg in xMsg: + logging.info("%s double alarm (id+msg): %s within %s second(s)", typ, xID, timestamp-xTimestamp) + return False + else: + logging.info("%s double alarm (id): %s within %s second(s)", typ, xID, timestamp-xTimestamp) + return False return True -def newEntry(id): +def newEntry(id, msg = ""): """ new entry in double alarm list @return: nothing """ timestamp = int(time.time()) # Get Timestamp - globals.doubleList.append((id, timestamp)) + globals.doubleList.append((id, timestamp, msg)) # now check if list has more than n entries: - if len(globals.doubleList) > globals.config.getint("BOSWatch", "double_ignore_entries"): + if len(globals.doubleList) > globals.config.getint("BOSWatch", "doubleFilter_ignore_entries"): # we have to kill the oldest one globals.doubleList.pop(0) \ No newline at end of file From a1d610ee6ac8b0be4d962c21d2f32c642820a8ca Mon Sep 17 00:00:00 2001 From: JHCD Date: Mon, 29 Jun 2015 22:31:34 +0200 Subject: [PATCH 23/98] solve issue #30 and #31; change error-handling; test-mode 1.) move bin-path for rtl_fm and multimon-ng to config.ini 2.) check if rtl_fm and multimon-ng started without errors both programs don't terminate in case of an error, so we have to read the logfile and look into it 3.) now we can't start a instance of BOSWatch without a free SDR-stick added -t --test as new argument to skip instantiate of rtl-fm and multimon-ng 4.) change error-handling --- boswatch.py | 428 +++++++++++++++++++++---------------- config/config.template.ini | 6 + 2 files changed, 249 insertions(+), 185 deletions(-) diff --git a/boswatch.py b/boswatch.py index d160c72b..32967d8a 100755 --- a/boswatch.py +++ b/boswatch.py @@ -46,6 +46,8 @@ parser.add_argument("-u", "--usevarlog", help="Use '/var/log/boswatch' for logfiles instead of subdir 'log' in BOSWatch directory", action="store_true") parser.add_argument("-v", "--verbose", help="Shows more information", action="store_true") parser.add_argument("-q", "--quiet", help="Shows no information. Only logfiles", action="store_true") + # We need this argument for testing (skip instantiate of rtl-fm and multimon-ng): + parser.add_argument("-t", "--test", help=argparse.SUPPRESS, action="store_true") args = parser.parse_args() except SystemExit: # -h or --help called, exit right now @@ -58,7 +60,10 @@ # Main program # try: - # initialization + # initialization: + rtl_fm = None + multimon_ng = None + try: # # Script-pathes @@ -95,211 +100,265 @@ myLogger.addHandler(fh) # create a display logger ch = logging.StreamHandler() - # log level for display >= info - # will be changed later after parsing args - ch.setLevel(logging.INFO) + # log level for display: Default: info + if args.verbose: + ch.setLevel(logging.DEBUG) + elif args.quiet: + ch.setLevel(logging.CRITICAL) + else: + ch.setLevel(logging.INFO) ch.setFormatter(formatter) myLogger.addHandler(ch) + except: - logging.exception("cannot create logger") - else: + # we couldn't work without logging -> exit + logging.critical("cannot create logger") + logging.debug("cannot create logger", exc_info=True) + exit(1) + # initialization of the logging was fine, continue... + try: + # + # Clear the logfiles + # + fh.doRollover() + rtl_log = open(globals.log_path+"rtl_fm.log", "w") + mon_log = open(globals.log_path+"multimon.log", "w") + rtl_log.write("") + mon_log.write("") + rtl_log.close() + mon_log.close() + logging.debug("BOSWatch has started") + logging.debug("Logfiles cleared") + except: + # It's an error, but we could work without that stuff... + logging.error("cannot clear Logfiles") + logging.debug("cannot clear Logfiles", exc_info=True) + pass - try: - # - # Clear the logfiles - # - fh.doRollover() - rtl_log = open(globals.log_path+"rtl_fm.log", "w") - mon_log = open(globals.log_path+"multimon.log", "w") - rtl_log.write("") - mon_log.write("") - rtl_log.close() - mon_log.close() - logging.debug("BOSWatch has started") - logging.debug("Logfiles cleared") - except: - logging.exception("cannot clear Logfiles") - - try: - # - # For debug display/log args - # - logging.debug(" - Frequency: %s", converter.freqToHz(args.freq)) - logging.debug(" - Device: %s", args.device) - logging.debug(" - PPM Error: %s", args.error) - logging.debug(" - Squelch: %s", args.squelch) - - demodulation = "" - if "FMS" in args.demod: - demodulation += "-a FMSFSK " - logging.debug(" - Demod: FMS") - if "ZVEI" in args.demod: - demodulation += "-a ZVEI2 " - logging.debug(" - Demod: ZVEI") - if "POC512" in args.demod: - demodulation += "-a POCSAG512 " - logging.debug(" - Demod: POC512") - if "POC1200" in args.demod: - demodulation += "-a POCSAG1200 " - logging.debug(" - Demod: POC1200") - if "POC2400" in args.demod: - demodulation += "-a POCSAG2400 " - logging.debug(" - Demod: POC2400") + try: + # + # For debug display/log args + # + if args.test: + logging.debug(" - We are in Test-Mode!") - logging.debug(" - Use /var/log: %s", args.usevarlog) - logging.debug(" - Verbose Mode: %s", args.verbose) - logging.debug(" - Quiet Mode: %s", args.quiet) + logging.debug(" - Frequency: %s", converter.freqToHz(args.freq)) + logging.debug(" - Device: %s", args.device) + logging.debug(" - PPM Error: %s", args.error) + logging.debug(" - Squelch: %s", args.squelch) + + demodulation = "" + if "FMS" in args.demod: + demodulation += "-a FMSFSK " + logging.debug(" - Demod: FMS") + if "ZVEI" in args.demod: + demodulation += "-a ZVEI2 " + logging.debug(" - Demod: ZVEI") + if "POC512" in args.demod: + demodulation += "-a POCSAG512 " + logging.debug(" - Demod: POC512") + if "POC1200" in args.demod: + demodulation += "-a POCSAG1200 " + logging.debug(" - Demod: POC1200") + if "POC2400" in args.demod: + demodulation += "-a POCSAG2400 " + logging.debug(" - Demod: POC2400") + + logging.debug(" - Use /var/log: %s", args.usevarlog) + logging.debug(" - Verbose Mode: %s", args.verbose) + logging.debug(" - Quiet Mode: %s", args.quiet) - if args.verbose: - ch.setLevel(logging.DEBUG) - if args.quiet: - ch.setLevel(logging.CRITICAL) - - if not args.quiet: #only if not quiet mode - from includes import shellHeader - shellHeader.printHeader(args) - except: - logging.exception("cannot display/log args") + if not args.quiet: #only if not quiet mode + from includes import shellHeader + shellHeader.printHeader(args) + + if args.test: + logging.warning("!!! We are in Test-Mode !!!") + + except: + # we couldn't work without config -> exit + logging.critical("cannot display/log args") + logging.debug("cannot display/log args", exc_info=True) + exit(1) + + try: + # + # Read config.ini + # + logging.debug("reading config file") + globals.config = ConfigParser.ConfigParser() + globals.config.read(globals.script_path+"/config/config.ini") + # if given loglevel is debug: + if globals.config.getint("BOSWatch","loglevel") == 10: + logging.debug(" - BOSWatch:") + for key,val in globals.config.items("BOSWatch"): + logging.debug(" -- %s = %s", key, val) + logging.debug(" - FMS:") + for key,val in globals.config.items("FMS"): + logging.debug(" -- %s = %s", key, val) + logging.debug(" - ZVEI:") + for key,val in globals.config.items("ZVEI"): + logging.debug(" -- %s = %s", key, val) + logging.debug(" - POC:") + for key,val in globals.config.items("POC"): + logging.debug(" -- %s = %s", key, val) + except: + # we couldn't work without config -> exit + logging.critical("cannot read config file") + logging.debug("cannot read config file", exc_info=True) + exit(1) + + # initialization was fine, continue with main program... + try: + # + # Set the loglevel and backupCount of the file handler + # + logging.debug("set loglevel of fileHandler to: %s",globals.config.getint("BOSWatch","loglevel")) + fh.setLevel(globals.config.getint("BOSWatch","loglevel")) + logging.debug("set backupCount of fileHandler to: %s", globals.config.getint("BOSWatch","backupCount")) + fh.setBackupCount(globals.config.getint("BOSWatch","backupCount")) + except: + # It's an error, but we could work without that stuff... + logging.error("cannot set loglevel of fileHandler") + logging.debug("cannot set loglevel of fileHandler", exc_info=True) + pass + + # + # Load plugins + # + from includes import pluginLoader + pluginLoader.loadPlugins() + + # + # Load filters + # + if globals.config.getboolean("BOSWatch","useRegExFilter"): + from includes import filter + filter.loadFilters() + + # + # Load description lists + # + if globals.config.getboolean("BOSWatch","useDescription"): + from includes import descriptionList + descriptionList.loadDescriptionLists() + + try: + # + # Start rtl_fm + # + if not args.test: + logging.debug("starting rtl_fm") + command = "" + if globals.config.has_option("BOSWatch","rtl_path"): + command = globals.config.get("BOSWatch","rtl_path") + command = command+"rtl_fm -d "+str(args.device)+" -f "+str(converter.freqToHz(args.freq))+" -M fm -s 22050 -p "+str(args.error)+" -E DC -F 0 -l "+str(args.squelch)+" -g 100" + rtl_fm = subprocess.Popen(command.split(), + #stdin=rtl_fm.stdout, + stdout=subprocess.PIPE, + stderr=open(globals.log_path+"rtl_fm.log","a"), + shell=False) + # rtl_fm doesn't self-destruct, when an error occurs + # wait a moment to give the subprocess a chance to write the logfile + time.sleep(3) + rtlLog = open(globals.log_path+"rtl_fm.log","r").read() + if ("Failed" in rtlLog) or ("error" in rtlLog): + logging.debug("\n%s", rtlLog) + raise OSError("starting rtl_fm returns an error") + else: + logging.warning("!!! Test-Mode: rtl_fm not started !!!") + except: + # we couldn't work without rtl_fm -> exit + logging.critical("cannot start rtl_fm") + logging.debug("cannot start rtl_fm", exc_info=True) + exit(1) - try: - # - # Read config.ini - # - logging.debug("reading config file") - globals.config = ConfigParser.ConfigParser() - globals.config.read(globals.script_path+"/config/config.ini") - # if given loglevel is debug: - if globals.config.getint("BOSWatch","loglevel") == 10: - logging.debug(" - BOSWatch:") - for key,val in globals.config.items("BOSWatch"): - logging.debug(" -- %s = %s", key, val) - logging.debug(" - FMS:") - for key,val in globals.config.items("FMS"): - logging.debug(" -- %s = %s", key, val) - logging.debug(" - ZVEI:") - for key,val in globals.config.items("ZVEI"): - logging.debug(" -- %s = %s", key, val) - logging.debug(" - POC:") - for key,val in globals.config.items("POC"): - logging.debug(" -- %s = %s", key, val) - except: - logging.exception("cannot read config file") + # rtl_fm started, continue... + try: + # + # Start multimon + # + if not args.test: + logging.debug("starting multimon-ng") + command = "" + if globals.config.has_option("BOSWatch","multimon_path"): + command = globals.config.get("BOSWatch","multimon_path") + command = command+"multimon-ng "+str(demodulation)+" -f alpha -t raw /dev/stdin - " + multimon_ng = subprocess.Popen(command.split(), + stdin=rtl_fm.stdout, + stdout=subprocess.PIPE, + stderr=open(globals.log_path+"multimon.log","a"), + shell=False) + # multimon-ng doesn't self-destruct, when an error occurs + # wait a moment to give the subprocess a chance to write the logfile + time.sleep(3) + multimonLog = open(globals.log_path+"multimon.log","r").read() + if ("invalid" in multimonLog) or ("error" in multimonLog): + logging.debug("\n%s", multimonLog) + raise OSError("starting multimon-ng returns an error") else: - # initialization was fine, continue with main program... - - try: - # - # Set the loglevel and backupCount of the file handler - # - logging.debug("set loglevel of fileHandler to: %s",globals.config.getint("BOSWatch","loglevel")) - fh.setLevel(globals.config.getint("BOSWatch","loglevel")) - logging.debug("set backupCount of fileHandler to: %s", globals.config.getint("BOSWatch","backupCount")) - fh.setBackupCount(globals.config.getint("BOSWatch","backupCount")) - except: - logging.exception("cannot set loglevel of fileHandler") - - # - # Load plugins - # - from includes import pluginLoader - pluginLoader.loadPlugins() - - # - # Load filters - # - if globals.config.getint("BOSWatch","useRegExFilter"): - from includes import filter - filter.loadFilters() - - # - # Load description lists - # - if globals.config.getint("BOSWatch","useDescription"): - from includes import descriptionList - descriptionList.loadDescriptionLists() - - try: - # - # Start rtl_fm - # - logging.debug("starting rtl_fm") - command = "/usr/local/bin/rtl_fm -d "+str(args.device)+" -f "+str(converter.freqToHz(args.freq))+" -M fm -s 22050 -p "+str(args.error)+" -E DC -F 0 -l "+str(args.squelch)+" -g 100" - rtl_fm = subprocess.Popen(command.split(), - #stdin=rtl_fm.stdout, - stdout=subprocess.PIPE, - stderr=open(globals.log_path+"rtl_fm.log","a"), - shell=False) - except: - logging.exception("cannot start rtl_fm") - else: - # rtl_fm started, continue... - - try: - # - # Start multimon - # - logging.debug("starting multimon-ng") - command = "/usr/local/bin/multimon-ng "+str(demodulation)+" -f alpha -t raw /dev/stdin - " - multimon_ng = subprocess.Popen(command.split(), - stdin=rtl_fm.stdout, - stdout=subprocess.PIPE, - stderr=open(globals.log_path+"multimon.log","a"), - shell=False) - except: - logging.exception("cannot start multimon-ng") - else: - # multimon-ng started, continue... - - logging.debug("start decoding") - - while True: - # - # Get decoded data from multimon-ng and call BOSWatch-decoder - # - - # RAW Data from Multimon-NG - # ZVEI2: 25832 - # FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST2=III(mit NA,ohneSIGNAL)) CRC correct\n' - # POCSAG1200: Address: 1234567 Function: 1 Alpha: Hello World - decoded = str(multimon_ng.stdout.readline()) #Get line data from multimon stdout - - # Test-strings only for develop - #decoded = "ZVEI2: 25832" - #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=I (ohneNA,ohneSIGNAL)) CRC correct\n'" - #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 1=LST->FZG 2=I (ohneNA,ohneSIGNAL)) CRC correct\n'" - #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=II (ohneNA,mit SIGNAL)) CRC correct\n'" - #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 1=LST->FZG 2=III(mit NA,ohneSIGNAL)) CRC correct\n'" - #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=IV (mit NA,mit SIGNAL)) CRC correct\n'" - #decoded = "POCSAG1200: Address: 1234567 Function: 1 Alpha: Hello World" - #time.sleep(1) - - from includes import decoder - decoder.decode(converter.freqToHz(args.freq), decoded) - + logging.warning("!!! Test-Mode: multimon-ng not started !!!") + except: + # we couldn't work without multimon-ng -> exit + logging.critical("cannot start multimon-ng") + logging.debug("cannot start multimon-ng", exc_info=True) + exit(1) + + # multimon-ng started, continue... + logging.debug("start decoding") + while True: + # + # Get decoded data from multimon-ng and call BOSWatch-decoder + # + + # RAW Data from Multimon-NG + # ZVEI2: 25832 + # FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST2=III(mit NA,ohneSIGNAL)) CRC correct\n' + # POCSAG1200: Address: 1234567 Function: 1 Alpha: Hello World + if not args.test: + decoded = str(multimon_ng.stdout.readline()) #Get line data from multimon stdout + + else: + # Test-strings only for develop + #decoded = "ZVEI2: 25832" + #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=I (ohneNA,ohneSIGNAL)) CRC correct\n'" + #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 1=LST->FZG 2=I (ohneNA,ohneSIGNAL)) CRC correct\n'" + #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=II (ohneNA,mit SIGNAL)) CRC correct\n'" + #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 1=LST->FZG 2=III(mit NA,ohneSIGNAL)) CRC correct\n'" + #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=IV (mit NA,mit SIGNAL)) CRC correct\n'" + decoded = "POCSAG1200: Address: 1234567 Function: 1 Alpha: Hello World" + time.sleep(1) + + from includes import decoder + decoder.decode(converter.freqToHz(args.freq), decoded) + except KeyboardInterrupt: logging.warning("Keyboard Interrupt") except SystemExit: # SystemExitException is thrown if daemon was terminated logging.warning("SystemExit received") # only exit to call finally-block - exit(0) + exit() except: logging.exception("unknown error") finally: try: logging.debug("BOSWatch shuting down") - logging.debug("terminate multimon-ng (%s)", multimon_ng.pid) - multimon_ng.terminate() - multimon_ng.wait() - logging.debug("multimon-ng terminated") - logging.debug("terminate rtl_fm (%s)", rtl_fm.pid) - rtl_fm.terminate() - rtl_fm.wait() - logging.debug("rtl_fm terminated") + if multimon_ng and multimon_ng.pid: + logging.debug("terminate multimon-ng (%s)", multimon_ng.pid) + multimon_ng.terminate() + multimon_ng.wait() + logging.debug("multimon-ng terminated") + if rtl_fm and rtl_fm.pid: + logging.debug("terminate rtl_fm (%s)", rtl_fm.pid) + rtl_fm.terminate() + rtl_fm.wait() + logging.debug("rtl_fm terminated") logging.debug("exiting BOSWatch") except: logging.warning("failed in clean-up routine") + logging.debug("failed in clean-up routine", exc_info=True) finally: # Close Logging @@ -307,5 +366,4 @@ logging.info("BOSWatch exit()") logging.shutdown() fh.close() - ch.close() - exit(0) \ No newline at end of file + ch.close() \ No newline at end of file diff --git a/config/config.template.ini b/config/config.template.ini index 206ede9c..59ad1821 100644 --- a/config/config.template.ini +++ b/config/config.template.ini @@ -17,6 +17,12 @@ loglevel = 10 # backupCount = 7 (keeps logfiles for a week) backupCount = 7 +# if you want to start BOSWatch as a daemon with rc2.d, +# you have to set the path to rtl_fm and multimon-ng ! +# the path have to end with an / +#rtl_path = /usr/local/bin/ +#multimon_path = /usr/local/bin/ + # Using RegEx-Filter (0|1) # Filter-configuration in section [Filters] useRegExFilter = 0 From 09b9cc5f7d4438bdf58ee1da7a837afb957248a1 Mon Sep 17 00:00:00 2001 From: JHCD Date: Mon, 29 Jun 2015 23:24:48 +0200 Subject: [PATCH 24/98] change pluginLoader and exception-handling - if the function plugin.onLoad() throws an exception the plugin will skipped - change exception-handling for pluginLoader --- includes/pluginLoader.py | 27 ++++++++++-------- plugins/BosMon/BosMon.py | 14 ++++------ plugins/MySQL/MySQL.py | 15 ++++------ plugins/eMail/eMail.py | 18 ++++++------ plugins/firEmergency/firEmergency.py | 17 +++++------- plugins/httpRequest/httpRequest.py | 15 ++++------ plugins/interface.txt | 41 ++++++++++++++++++++++++++-- plugins/jsonSocket/jsonSocket.py | 15 ++++------ plugins/template/template.py | 10 +++++-- 9 files changed, 100 insertions(+), 72 deletions(-) diff --git a/includes/pluginLoader.py b/includes/pluginLoader.py index 3b606af7..45b811b7 100644 --- a/includes/pluginLoader.py +++ b/includes/pluginLoader.py @@ -29,20 +29,21 @@ def loadPlugins(): for i in getPlugins(): # call for each Plugin the loadPlugin() Methode plugin = loadPlugin(i) - # Add it to globals.pluginList - globals.pluginList[i["name"]] = plugin - - #call the .onLoad() routine for all active plugins - for pluginName, plugin in globals.pluginList.items(): - logging.debug("call %s.onLoad()", pluginName) + # Try to call the .onLoad() routine for all active plugins try: - plugin.onLoad(typ,freq,data) + logging.debug("call %s.onLoad()", i["name"]) + plugin.onLoad() + # Add it to globals.pluginList + globals.pluginList[i["name"]] = plugin except: # call next plugin, if one has thrown an exception + logging.error("error calling %s.onLoad()", i["name"]) + logging.debug("error calling %s.onLoad()", exc_info=True) pass - except: - logging.exception("cannot load Plugins") + logging.error("cannot load Plugins") + logging.debug("cannot load Plugins", exc_info=True) + raise def getPlugins(): @@ -77,7 +78,9 @@ def getPlugins(): logging.warning("Plugin [NO CONF ] %s", i) pass except: - logging.exception("Error during Plugin search") + logging.error("Error during Plugin search") + logging.debug("cannot load Plugins", exc_info=True) + raise return plugins @@ -97,4 +100,6 @@ def loadPlugin(plugin): logging.debug("load Plugin: %s", plugin["name"]) return imp.load_module(plugin["name"], *plugin["info"]) except: - logging.exception("cannot load Plugin: %s", plugin["name"]) \ No newline at end of file + logging.error("cannot load Plugin: %s", plugin["name"]) + logging.debug("cannot load Plugin: %s", plugin["name"], exc_info=True) + raise \ No newline at end of file diff --git a/plugins/BosMon/BosMon.py b/plugins/BosMon/BosMon.py index 760cc446..40b54cbc 100644 --- a/plugins/BosMon/BosMon.py +++ b/plugins/BosMon/BosMon.py @@ -21,24 +21,20 @@ ## # -# onLoad function of plugin -# will be called by the pluginLoader +# onLoad (init) function of plugin +# will be called one time by the pluginLoader on start # def onLoad(): """ While loading the plugins by pluginLoader.loadPlugins() - this onLoad() routine are called + this onLoad() routine is called one time for initialize the plugin @requires: nothing @return: nothing """ - try: - # we have to do nothing here... - pass - except: - logging.error("unknown error") - logging.debug("unknown error", exc_info=True) + # nothing to do for this plugin + return ## # diff --git a/plugins/MySQL/MySQL.py b/plugins/MySQL/MySQL.py index ceb377dd..c321cc1d 100644 --- a/plugins/MySQL/MySQL.py +++ b/plugins/MySQL/MySQL.py @@ -20,24 +20,21 @@ ## # -# onLoad function of plugin -# will be called by the pluginLoader +# onLoad (init) function of plugin +# will be called one time by the pluginLoader on start # def onLoad(): """ While loading the plugins by pluginLoader.loadPlugins() - this onLoad() routine are called + this onLoad() routine is called one time for initialize the plugin @requires: nothing @return: nothing """ - try: - # we have to do nothing here... - pass - except: - logging.error("unknown error") - logging.debug("unknown error", exc_info=True) + # nothing to do for this plugin + return + ## # diff --git a/plugins/eMail/eMail.py b/plugins/eMail/eMail.py index ec72743e..904a62a6 100644 --- a/plugins/eMail/eMail.py +++ b/plugins/eMail/eMail.py @@ -21,25 +21,22 @@ ## # -# onLoad function of plugin -# will be called by the pluginLoader +# onLoad (init) function of plugin +# will be called one time by the pluginLoader on start # def onLoad(): """ While loading the plugins by pluginLoader.loadPlugins() - this onLoad() routine are called + this onLoad() routine is called one time for initialize the plugin @requires: nothing @return: nothing """ - try: - # we have to do nothing here... - pass - except: - logging.error("unknown error") - logging.debug("unknown error", exc_info=True) - + # nothing to do for this plugin + return + + ## # # Private helper function for a printable Timestamp @@ -47,6 +44,7 @@ def onLoad(): def curtime(): return time.strftime("%Y-%m-%d %H:%M:%S") + ## # # do send mail diff --git a/plugins/firEmergency/firEmergency.py b/plugins/firEmergency/firEmergency.py index 5ea918b7..4d40f87c 100644 --- a/plugins/firEmergency/firEmergency.py +++ b/plugins/firEmergency/firEmergency.py @@ -14,26 +14,23 @@ from includes import globals # Global variables -## +### # -# onLoad function of plugin -# will be called by the pluginLoader +# onLoad (init) function of plugin +# will be called one time by the pluginLoader on start # def onLoad(): """ While loading the plugins by pluginLoader.loadPlugins() - this onLoad() routine are called + this onLoad() routine is called one time for initialize the plugin @requires: nothing @return: nothing """ - try: - # we have to do nothing here... - pass - except: - logging.error("unknown error") - logging.debug("unknown error", exc_info=True) + # nothing to do for this plugin + return + ## # diff --git a/plugins/httpRequest/httpRequest.py b/plugins/httpRequest/httpRequest.py index 0f8a22e1..74d6df3e 100644 --- a/plugins/httpRequest/httpRequest.py +++ b/plugins/httpRequest/httpRequest.py @@ -17,24 +17,21 @@ ## # -# onLoad function of plugin -# will be called by the pluginLoader +# onLoad (init) function of plugin +# will be called one time by the pluginLoader on start # def onLoad(): """ While loading the plugins by pluginLoader.loadPlugins() - this onLoad() routine are called + this onLoad() routine is called one time for initialize the plugin @requires: nothing @return: nothing """ - try: - # we have to do nothing here... - pass - except: - logging.error("unknown error") - logging.debug("unknown error", exc_info=True) + # nothing to do for this plugin + return + ## # diff --git a/plugins/interface.txt b/plugins/interface.txt index f2e8c016..d8b7718e 100644 --- a/plugins/interface.txt +++ b/plugins/interface.txt @@ -1,9 +1,9 @@ Handover to Plugin: +------------------- typ = [FMS|ZVEI|POC] freq = [Freq in Hz] data = {"KEY1":"VALUE1","KEY2":"VALUE2"} - The following informations are included in the var "data". They can be used by their Index Names: data['OPTION'] @@ -29,6 +29,7 @@ POCSAG: Global Objects: +--------------- 1.) import logging # Global logger @@ -38,4 +39,40 @@ Loglevel: debug|info|warning|error|exception|critical 2.) import globals # Global variables reads Data from the config.ini -VALUE = globals.config.get("SECTION", "OPTION") \ No newline at end of file +VALUE = globals.config.get("SECTION", "OPTION") + + +General for plugins: +-------------------- +All Plugins have to implement the following functions (see template.py): + +def onLoad(): + """ + While loading the plugins by pluginLoader.loadPlugins() + this onLoad() routine is called one time for initialize the plugin + + @requires: nothing + + @return: nothing + @exception: Exception if init has an fatal error so that the plugin couldn't work + + """ + +def run(typ,freq,data): + """ + This function is the implementation of the Plugin. + + If necessary the configuration hast to be set in the config.ini. + + @type typ: string (FMS|ZVEI|POC) + @param typ: Typ of the dataset + @type data: map of data (structure see interface.txt) + @param data: Contains the parameter for dispatch + @type freq: string + @keyword freq: frequency of the SDR Stick + + @requires: If necessary the configuration hast to be set in the config.ini. + + @return: nothing + @exception: nothing, make sure this function will never thrown an exception + """ \ No newline at end of file diff --git a/plugins/jsonSocket/jsonSocket.py b/plugins/jsonSocket/jsonSocket.py index 4dec8a51..01afeb26 100644 --- a/plugins/jsonSocket/jsonSocket.py +++ b/plugins/jsonSocket/jsonSocket.py @@ -18,24 +18,21 @@ ## # -# onLoad function of plugin -# will be called by the pluginLoader +# onLoad (init) function of plugin +# will be called one time by the pluginLoader on start # def onLoad(): """ While loading the plugins by pluginLoader.loadPlugins() - this onLoad() routine are called + this onLoad() routine is called one time for initialize the plugin @requires: nothing @return: nothing """ - try: - # we have to do nothing here... - pass - except: - logging.error("unknown error") - logging.debug("unknown error", exc_info=True) + # nothing to do for this plugin + return + ## # diff --git a/plugins/template/template.py b/plugins/template/template.py index 9d306c08..b20c3eb7 100644 --- a/plugins/template/template.py +++ b/plugins/template/template.py @@ -26,17 +26,19 @@ ## # -# onLoad function of plugin -# will be called by the pluginLoader +# onLoad (init) function of plugin +# will be called one time by the pluginLoader on start # def onLoad(): """ While loading the plugins by pluginLoader.loadPlugins() - this onLoad() routine are called + this onLoad() routine is called one time for initialize the plugin @requires: nothing @return: nothing + @exception: Exception if init has an fatal error so that the plugin couldn't work + """ try: ########## User onLoad CODE ########## @@ -45,6 +47,7 @@ def onLoad(): except: logging.error("unknown error") logging.debug("unknown error", exc_info=True) + raise ## # @@ -67,6 +70,7 @@ def run(typ,freq,data): @requires: If necessary the configuration hast to be set in the config.ini. @return: nothing + @exception: nothing, make sure this function will never thrown an exception """ try: # From 9b6e5c8da32f889dc1407e232cd404f9e104e68d Mon Sep 17 00:00:00 2001 From: JHCD Date: Mon, 29 Jun 2015 23:32:55 +0200 Subject: [PATCH 25/98] some changes in exception-handling --- boswatch.py | 67 +++++++++++++++++++++++-------------- includes/descriptionList.py | 1 + 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/boswatch.py b/boswatch.py index 32967d8a..250bca02 100755 --- a/boswatch.py +++ b/boswatch.py @@ -136,10 +136,10 @@ logging.debug("cannot clear Logfiles", exc_info=True) pass + # + # For debug display/log args + # try: - # - # For debug display/log args - # if args.test: logging.debug(" - We are in Test-Mode!") @@ -182,10 +182,10 @@ logging.debug("cannot display/log args", exc_info=True) exit(1) + # + # Read config.ini + # try: - # - # Read config.ini - # logging.debug("reading config file") globals.config = ConfigParser.ConfigParser() globals.config.read(globals.script_path+"/config/config.ini") @@ -227,27 +227,45 @@ # # Load plugins # - from includes import pluginLoader - pluginLoader.loadPlugins() + try: + from includes import pluginLoader + pluginLoader.loadPlugins() + except: + # we couldn't work without filters -> exit + logging.critical("cannot load Plugins") + logging.debug("cannot load Plugins", exc_info=True) + exit(1) # # Load filters # - if globals.config.getboolean("BOSWatch","useRegExFilter"): - from includes import filter - filter.loadFilters() + try: + if globals.config.getboolean("BOSWatch","useRegExFilter"): + from includes import filter + filter.loadFilters() + except: + # It's an error, but we could work without that stuff... + logging.error("cannot load filters") + logging.debug("cannot load filters", exc_info=True) + pass # # Load description lists # - if globals.config.getboolean("BOSWatch","useDescription"): - from includes import descriptionList - descriptionList.loadDescriptionLists() + try: + if globals.config.getboolean("BOSWatch","useDescription"): + from includes import descriptionList + descriptionList.loadDescriptionLists() + except: + # It's an error, but we could work without that stuff... + logging.error("cannot load description lists") + logging.debug("cannot load description lists", exc_info=True) + pass + # + # Start rtl_fm + # try: - # - # Start rtl_fm - # if not args.test: logging.debug("starting rtl_fm") command = "" @@ -274,11 +292,10 @@ logging.debug("cannot start rtl_fm", exc_info=True) exit(1) - # rtl_fm started, continue... + # + # Start multimon + # try: - # - # Start multimon - # if not args.test: logging.debug("starting multimon-ng") command = "" @@ -307,11 +324,11 @@ # multimon-ng started, continue... logging.debug("start decoding") + + # + # Get decoded data from multimon-ng and call BOSWatch-decoder + # while True: - # - # Get decoded data from multimon-ng and call BOSWatch-decoder - # - # RAW Data from Multimon-NG # ZVEI2: 25832 # FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST2=III(mit NA,ohneSIGNAL)) CRC correct\n' diff --git a/includes/descriptionList.py b/includes/descriptionList.py index 6c94a666..7f57ad2d 100644 --- a/includes/descriptionList.py +++ b/includes/descriptionList.py @@ -106,6 +106,7 @@ def getDescription(typ, id): pass except: + logging.error("Error during look up description lists") logging.debug("Error during look up description lists", exc_info=True) pass From bcc0fca656b17911e3ed4727d8f0d02efc9b4883 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Tue, 30 Jun 2015 07:59:27 +0200 Subject: [PATCH 26/98] added the name of the talking function to the logging --- .gitignore | 3 ++- README.md | 2 ++ boswatch.py | 6 ++++-- includes/shellHeader.py | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index aad2b93f..7617a015 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.psd *.pyc *.log -config.ini \ No newline at end of file +config.ini +log/ diff --git a/README.md b/README.md index 9a4b50e4..1e69290c 100644 --- a/README.md +++ b/README.md @@ -129,3 +129,5 @@ For configuration-details see `service/README.md`. - Multimon-NG - Python Support - MySQL Connector for Python (for MySQL-plugin) + +Thanks to smith_fms and McBo from Funkmeldesystem.de - Forum for Inspiration and Groundwork! diff --git a/boswatch.py b/boswatch.py index 250bca02..78b15924 100755 --- a/boswatch.py +++ b/boswatch.py @@ -8,7 +8,9 @@ For more information see the README.md @author: Bastian Schroll -@author: Jens Herrmann +@author: Jens Herrmann + +Thanks to smith_fms and McBo from Funkmeldesystem.de - Forum for Inspiration and Groundwork! GitHUB: https://github.com/Schrolli91/BOSWatch """ @@ -90,7 +92,7 @@ myLogger = logging.getLogger() myLogger.setLevel(logging.DEBUG) # set log string format - formatter = logging.Formatter('%(asctime)s - %(module)-15s [%(levelname)-8s] %(message)s', '%d.%m.%Y %H:%M:%S') + formatter = logging.Formatter('%(asctime)s - %(module)-15s %(funcName)-15s [%(levelname)-8s] %-4ds %(message)s', '%d.%m.%Y %H:%M:%S') # create a file logger fh = MyTimedRotatingFileHandler.MyTimedRotatingFileHandler(globals.log_path+"boswatch.log", "midnight", interval=1, backupCount=999) # Starts with log level >= Debug diff --git a/includes/shellHeader.py b/includes/shellHeader.py index dfbcac41..aa7a5d10 100644 --- a/includes/shellHeader.py +++ b/includes/shellHeader.py @@ -26,7 +26,7 @@ def printHeader(args): print " / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / t" print " /_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ a" print " German BOS Information Script " - print " by Bastian Schroll " + print " by Bastian Schroll, Jens Herrmann " print "" print "Frequency: "+args.freq From 34603a1297ee244068cc49905e9bac6e09557a00 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Tue, 30 Jun 2015 08:00:40 +0200 Subject: [PATCH 27/98] little Bug in last commit --- boswatch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boswatch.py b/boswatch.py index 78b15924..051d623a 100755 --- a/boswatch.py +++ b/boswatch.py @@ -92,7 +92,7 @@ myLogger = logging.getLogger() myLogger.setLevel(logging.DEBUG) # set log string format - formatter = logging.Formatter('%(asctime)s - %(module)-15s %(funcName)-15s [%(levelname)-8s] %-4ds %(message)s', '%d.%m.%Y %H:%M:%S') + formatter = logging.Formatter('%(asctime)s - %(module)-15s %(funcName)-15s [%(levelname)-8s] %(message)s', '%d.%m.%Y %H:%M:%S') # create a file logger fh = MyTimedRotatingFileHandler.MyTimedRotatingFileHandler(globals.log_path+"boswatch.log", "midnight", interval=1, backupCount=999) # Starts with log level >= Debug From 8b8cd81abcc986c3334328064ad8489328489915 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Tue, 30 Jun 2015 08:27:50 +0200 Subject: [PATCH 28/98] resolve error in RegEX Filter --- includes/filter.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/includes/filter.py b/includes/filter.py index 8fb91456..4805f5cc 100644 --- a/includes/filter.py +++ b/includes/filter.py @@ -15,6 +15,8 @@ from includes import globals # Global variables +from includes import converter # converter functions + def loadFilters(): """ @@ -30,8 +32,13 @@ def loadFilters(): for key,val in globals.config.items("Filters"): logging.debug(" - %s = %s", key, val) filter = val.split(";") + + # resolve the * for freqToHz() + if not filter[3] == "*": + filter[3] = converter.freqToHz(filter[3]) + # insert splitet data into globals.filterList - globals.filterList.append({"name": key, "typ": filter[0], "dataField": filter[1], "plugin": filter[2], "freq": freqToHz(filter[3]), "regex": filter[4]}) + globals.filterList.append({"name": key, "typ": filter[0], "dataField": filter[1], "plugin": filter[2], "freq": filter[3], "regex": filter[4]}) except: logging.error("cannot read config file") logging.debug("cannot read config file", exc_info=True) From 948aaea0658bb6b4f38a949cceadc67bd7890891 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Tue, 30 Jun 2015 08:55:46 +0200 Subject: [PATCH 29/98] insert a debug log in doubleFilter.newEntry() --- includes/doubleFilter.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/includes/doubleFilter.py b/includes/doubleFilter.py index b1248ac3..bd7186f5 100644 --- a/includes/doubleFilter.py +++ b/includes/doubleFilter.py @@ -57,6 +57,8 @@ def newEntry(id, msg = ""): timestamp = int(time.time()) # Get Timestamp globals.doubleList.append((id, timestamp, msg)) + logging.debug("Added %s to doubleList", id) + # now check if list has more than n entries: if len(globals.doubleList) > globals.config.getint("BOSWatch", "doubleFilter_ignore_entries"): # we have to kill the oldest one From 64768e544e6bf26d0e01a638268f685e97b58c31 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Tue, 30 Jun 2015 12:25:22 +0200 Subject: [PATCH 30/98] move and edit boswatch.sql --- {sql => plugins/MySQL}/boswatch.sql | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) rename {sql => plugins/MySQL}/boswatch.sql (89%) diff --git a/sql/boswatch.sql b/plugins/MySQL/boswatch.sql similarity index 89% rename from sql/boswatch.sql rename to plugins/MySQL/boswatch.sql index 735804bf..0427f8e4 100644 --- a/sql/boswatch.sql +++ b/plugins/MySQL/boswatch.sql @@ -32,7 +32,9 @@ CREATE TABLE IF NOT EXISTS `bos_fms` ( `fms` varchar(8) NOT NULL, `status` varchar(1) NOT NULL, `direction` varchar(1) NOT NULL, + `directionText` text(10) NOT NULL, `tsi` varchar(3) NOT NULL, + `description` text NOT NULL, PRIMARY KEY (`ID`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; @@ -47,7 +49,10 @@ CREATE TABLE IF NOT EXISTS `bos_pocsag` ( `time` datetime NOT NULL, `ric` varchar(7) NOT NULL DEFAULT '0', `funktion` int(1) NOT NULL, - `text` text NOT NULL, + `funktionChar` text(1) NOT NULL, + `msg` text NOT NULL, + `bitrate` int(4) NOT NULL, + `description` text NOT NULL, KEY `ID` (`ID`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; @@ -61,6 +66,7 @@ CREATE TABLE IF NOT EXISTS `bos_zvei` ( `id` int(11) NOT NULL AUTO_INCREMENT, `time` datetime NOT NULL, `zvei` varchar(5) NOT NULL DEFAULT '0', + `description` text NOT NULL, PRIMARY KEY (`ID`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; From d28dfa951bfb113209d616d4be7417b5f3a6bb8c Mon Sep 17 00:00:00 2001 From: Schrolli Date: Tue, 30 Jun 2015 12:26:27 +0200 Subject: [PATCH 31/98] edit MySQL plugin - save all given information from data[ ] into MySQL database --- README.md | 3 ++- plugins/MySQL/MySQL.py | 10 +++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1e69290c..b95340f5 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ unless you are developer you can use the develop-Branch - may be unstable! ##### Implemented features: - FMS, ZVEI and POCSAG512/1200/2400 decoding and displaying - Plugin support for easy functional extension -- Filtering double alarms with adjustable time +- Filtering double alarms with adjustable time and check width - Filtering allowed, denied and range of POCSAG RIC´s - Filtering data for each typ/plugin combination with RegEX - All configurations in a seperate config file @@ -118,6 +118,7 @@ In case of an error during the installation, check the logfile in `~/boswatch/in Caution, script don't install a webserver with PHP and MySQL. So you have to make up manually if you want to use MySQL support. +Database Structure `boswatch.sql` in the MySQL Plugin Folder If you want to use BOSWatch as a daemon, you have to set your configuration in `service/boswatch.sh` and copy it to `/etc/init.d`. diff --git a/plugins/MySQL/MySQL.py b/plugins/MySQL/MySQL.py index c321cc1d..bfaa144e 100644 --- a/plugins/MySQL/MySQL.py +++ b/plugins/MySQL/MySQL.py @@ -92,17 +92,13 @@ def run(typ,freq,data): logging.debug("Insert %s", typ) if typ == "FMS": - #data = {"fms":fms_id[0:8], "status":fms_status, "direction":fms_direction, "tsi":fms_tsi} - cursor.execute("INSERT INTO "+globals.config.get("MySQL","tableFMS")+" (time,fms,status,direction,tsi) VALUES (NOW(),%s,%s,%s,%s)",(data["fms"],data["status"],data["direction"],data["tsi"])) + cursor.execute("INSERT INTO "+globals.config.get("MySQL","tableFMS")+" (time,fms,status,direction,directionText,tsi,description) VALUES (NOW(),%s,%s,%s,%s,%s,%s)",(data["fms"],data["status"],data["direction"],data["directionText"],data["tsi"],data["description"])) elif typ == "ZVEI": - #data = {"zvei":zvei_id} - #Don't use %s here (bug in mysql-lib with one parameter) - cursor.execute("INSERT INTO "+globals.config.get("MySQL","tableZVEI")+" (time,zvei) VALUES (NOW(),"+(data["zvei"])+")") + cursor.execute("INSERT INTO "+globals.config.get("MySQL","tableZVEI")+" (time,zvei,description) VALUES (NOW(),%s,%s)",(data["zvei"],data["description"])) elif typ == "POC": - #data = {"ric":poc_id, "function":poc_sub, "msg":poc_text} - cursor.execute("INSERT INTO "+globals.config.get("MySQL","tablePOC")+" (time,ric,funktion,text) VALUES (NOW(),%s,%s,%s)",(data["ric"],data["function"],data["msg"])) + cursor.execute("INSERT INTO "+globals.config.get("MySQL","tablePOC")+" (time,ric,funktion,funktionChar,msg,bitrate,description) VALUES (NOW(),%s,%s,%s,%s,%s,%s)",(data["ric"],data["function"],data["functionChar"],data["msg"],data["bitrate"],data["description"])) else: logging.warning("Invalid Typ: %s", typ) From 0199151165025eb1eac523ef114c0e25bcaa1065 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Tue, 30 Jun 2015 12:38:52 +0200 Subject: [PATCH 32/98] littles changes at arguments debug --- boswatch.py | 3 ++- includes/shellHeader.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/boswatch.py b/boswatch.py index 051d623a..24727c9d 100755 --- a/boswatch.py +++ b/boswatch.py @@ -142,8 +142,9 @@ # For debug display/log args # try: + logging.debug("BOSWatch given arguments") if args.test: - logging.debug(" - We are in Test-Mode!") + logging.debug(" - Test-Mode!") logging.debug(" - Frequency: %s", converter.freqToHz(args.freq)) logging.debug(" - Device: %s", args.device) diff --git a/includes/shellHeader.py b/includes/shellHeader.py index aa7a5d10..7137c419 100644 --- a/includes/shellHeader.py +++ b/includes/shellHeader.py @@ -46,6 +46,8 @@ def printHeader(args): print "Squelch: "+str(args.squelch) if args.verbose: print "Verbose Mode!" + if args.test: + print "Test Mode!" print "" except: logging.error("cannot display shell header") From 174ad46a8c2589352b0aacd5c628a2f50cb831b9 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Tue, 30 Jun 2015 13:53:06 +0200 Subject: [PATCH 33/98] collect testdata for the testmode --- boswatch.py | 4 ---- testdata/testdata.txt | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 testdata/testdata.txt diff --git a/boswatch.py b/boswatch.py index 24727c9d..a38746e6 100755 --- a/boswatch.py +++ b/boswatch.py @@ -332,10 +332,6 @@ # Get decoded data from multimon-ng and call BOSWatch-decoder # while True: - # RAW Data from Multimon-NG - # ZVEI2: 25832 - # FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST2=III(mit NA,ohneSIGNAL)) CRC correct\n' - # POCSAG1200: Address: 1234567 Function: 1 Alpha: Hello World if not args.test: decoded = str(multimon_ng.stdout.readline()) #Get line data from multimon stdout diff --git a/testdata/testdata.txt b/testdata/testdata.txt new file mode 100644 index 00000000..7349dbeb --- /dev/null +++ b/testdata/testdata.txt @@ -0,0 +1,16 @@ +#Testdata for the BOSWatch Test Mode function +#Data in Multimon-NG Raw Format +#Data is alternately passed to the decoder to simulate an used Radio-Frequency + +#POCSAG + +#FMS + +#ZVEI +#two different ids to check filter function +ZVEI2: 12345 +ZVEI2: 56789 +#in case of incomplete id +ZVEI2: 135 +#in case of a double-tone for siren n-Fs are sended +ZVEI2: FFF \ No newline at end of file From b4708390f9c1177a1990d19fc6889e011400664f Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 1 Jul 2015 07:51:44 +0200 Subject: [PATCH 34/98] rtl_fm error messages from http://git.osmocom.org/rtl-sdr/tree/src/rtl_fm.c --- testdata/rt_fm errors.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 testdata/rt_fm errors.txt diff --git a/testdata/rt_fm errors.txt b/testdata/rt_fm errors.txt new file mode 100644 index 00000000..582a19b2 --- /dev/null +++ b/testdata/rt_fm errors.txt @@ -0,0 +1,7 @@ +Error Messages from RTL_FM + +fprintf(stderr, "Signal caught, exiting!\n"); +fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dongle.dev_index); +fprintf(stderr, "Failed to open %s\n", output.filename); +fprintf(stderr, "\nUser cancel, exiting...\n"); +fprintf(stderr, "\nLibrary error %d, exiting...\n", r); \ No newline at end of file From 8b744c1a4668be62387a969368490e271268b897 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 1 Jul 2015 08:21:08 +0200 Subject: [PATCH 35/98] update testdata --- csv/fms.csv | 2 +- csv/poc.csv | 2 +- csv/zvei.csv | 2 +- testdata/testdata.txt | 10 +++++++--- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/csv/fms.csv b/csv/fms.csv index cdc05fbf..6a9d021b 100644 --- a/csv/fms.csv +++ b/csv/fms.csv @@ -7,4 +7,4 @@ fms,description # # !!! DO NOT delete the first line !!! # -93377141,"John Q. Publics car" \ No newline at end of file +12345678,"FMS testdata" \ No newline at end of file diff --git a/csv/poc.csv b/csv/poc.csv index 89fb7952..4dc46346 100644 --- a/csv/poc.csv +++ b/csv/poc.csv @@ -7,4 +7,4 @@ ric,description # # !!! DO NOT delete the first line !!! # -1234567,"John Q. Public" \ No newline at end of file +1234567,"POCSAG testdata" \ No newline at end of file diff --git a/csv/zvei.csv b/csv/zvei.csv index 25ef0ed7..62f4c565 100644 --- a/csv/zvei.csv +++ b/csv/zvei.csv @@ -7,4 +7,4 @@ zvei,description # # !!! DO NOT delete the first line !!! # -25832,"John Q. Public" \ No newline at end of file +12345,"ZVEI testdata" \ No newline at end of file diff --git a/testdata/testdata.txt b/testdata/testdata.txt index 7349dbeb..438037a6 100644 --- a/testdata/testdata.txt +++ b/testdata/testdata.txt @@ -7,10 +7,14 @@ #FMS #ZVEI -#two different ids to check filter function +#with csv description ZVEI2: 12345 +#without csv description ZVEI2: 56789 +#with repeat Tone +ZVEI2: 1F21F2 #in case of incomplete id ZVEI2: 135 -#in case of a double-tone for siren n-Fs are sended -ZVEI2: FFF \ No newline at end of file +#in case of a double-tone for siren n-'D's are sended +ZVEI2: DDD +ZVEI2: DDDDD \ No newline at end of file From 8c5cb8ec85f0db8d32adca7bbd2c853acc756247 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 1 Jul 2015 09:31:23 +0200 Subject: [PATCH 36/98] update parameters for httpRequest plugin --- config/config.template.ini | 11 ++++++++--- plugins/httpRequest/httpRequest.py | 26 +++++++++++++++++++++----- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/config/config.template.ini b/config/config.template.ini index 59ad1821..3f3659cf 100644 --- a/config/config.template.ini +++ b/config/config.template.ini @@ -127,19 +127,24 @@ tablePOC = bos_pocsag # %FMS% = FMS Code # %STATUS% = FMS Status -# %DIR% = Direction of the telegram -# %TSI% = Tactical Short Information +# %DIR% = Direction of the telegram (0/1) +# %DIRT% = Direction of the telegram (Text-String) +# %TSI% = Tactical Short Information (I-IV) +# %TIME% = Date/Time (by script) #fms_url = www.google.de?code=%FMS%&stat=%STATUS% fms_url = # %ZVEI% = ZVEI 5-tone Code +# %TIME% = Date/Time (by script) #zvei_url = www.google.de?zvei=%ZVEI% zvei_url = # %RIC% = Pocsag RIC -# %FUNC% = Pocsac function/Subric +# %FUNC% = Pocsac function/Subric (1-4) +# %FUNCCHAR% = Pocsac function/Subric als character (a-d) # %MSG% = Message of the Pocsag telegram # %BITRATE% = Bitrate of the Pocsag telegram +# %TIME% = Date/Time (by script) #poc_url = www.google.de?ric=%RIC%&subric=%FUNC%&msg=%MSG% poc_url = diff --git a/plugins/httpRequest/httpRequest.py b/plugins/httpRequest/httpRequest.py index 74d6df3e..0e3a118f 100644 --- a/plugins/httpRequest/httpRequest.py +++ b/plugins/httpRequest/httpRequest.py @@ -9,6 +9,7 @@ @requires: httpRequest-Configuration has to be set in the config.ini """ +import time import logging # Global logger import httplib #for the HTTP request from urlparse import urlparse #for split the URL into url and path @@ -31,6 +32,13 @@ def onLoad(): """ # nothing to do for this plugin return + +## +# +# Private helper function for a printable Timestamp +# +def curtime(): + return time.strftime("%Y-%m-%d %H:%M:%S") ## @@ -75,15 +83,23 @@ def run(typ,freq,data): if typ == "FMS": url = globals.config.get("httpRequest", "fms_url") #Get URL - url = url.replace("%FMS%", data["fms"]).replace("%STATUS%", data["status"]) #replace Wildcards in URL - url = url.replace("%DIR%", data["direction"]).replace("%TSI%", data["tsi"]) #replace Wildcards in URL + url = url.replace("%FMS%", data["fms"]).replace("%STATUS%", data["status"]) #replace Wildcards + url = url.replace("%DIR%", data["direction"]).replace("%DIRT%", data["directionText"]) #replace Wildcards + url = url.replace("%TSI%", data["tsi"]) #replace Wildcards + url = url.replace("%DESCR%", data["description"]) # replace Wildcards + url = url.replace("%TIME%", curtime()) # replace Wildcards elif typ == "ZVEI": url = globals.config.get("httpRequest", "zvei_url") #Get URL - url = url.replace("%ZVEI%", data["zvei"]) #replace Wildcards in URL + url = url.replace("%ZVEI%", data["zvei"]) #replace Wildcards + url = url.replace("%DESCR%", data["description"]) # replace Wildcards + url = url.replace("%TIME%", curtime()) # replace Wildcards elif typ == "POC": url = globals.config.get("httpRequest", "poc_url") #Get URL - url = url.replace("%RIC%", data["ric"]).replace("%FUNC%", data["function"]) #replace Wildcards in URL - url = url.replace("%MSG%", data["msg"]).replace("%BITRATE%", data["bitrate"]) #replace Wildcards in URL + url = url.replace("%RIC%", data["ric"]) #replace Wildcards + url = url.replace("%FUNC%", data["function"]).replace("%FUNCCHAR%", data["functionChar"]) #replace Wildcards + url = url.replace("%MSG%", data["msg"]).replace("%BITRATE%", str(data["bitrate"])) #replace Wildcards + url = url.replace("%DESCR%", data["description"]) # replace Wildcards + url = url.replace("%TIME%", curtime()) # replace Wildcards else: logging.warning("Invalid Typ: %s", typ) From 7322d2b709c46a84449357f0e4abd3e3cea59c88 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 1 Jul 2015 09:35:31 +0200 Subject: [PATCH 37/98] insert "%DESCR%" in config.template.ini for httpRequest and eMail plugin --- config/config.template.ini | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/config/config.template.ini b/config/config.template.ini index 3f3659cf..80475b48 100644 --- a/config/config.template.ini +++ b/config/config.template.ini @@ -130,11 +130,13 @@ tablePOC = bos_pocsag # %DIR% = Direction of the telegram (0/1) # %DIRT% = Direction of the telegram (Text-String) # %TSI% = Tactical Short Information (I-IV) +# %DESCR% = Description from csv-file # %TIME% = Date/Time (by script) #fms_url = www.google.de?code=%FMS%&stat=%STATUS% fms_url = # %ZVEI% = ZVEI 5-tone Code +# %DESCR% = Description from csv-file # %TIME% = Date/Time (by script) #zvei_url = www.google.de?zvei=%ZVEI% zvei_url = @@ -144,6 +146,7 @@ zvei_url = # %FUNCCHAR% = Pocsac function/Subric als character (a-d) # %MSG% = Message of the Pocsag telegram # %BITRATE% = Bitrate of the Pocsag telegram +# %DESCR% = Description from csv-file # %TIME% = Date/Time (by script) #poc_url = www.google.de?ric=%RIC%&subric=%FUNC%&msg=%MSG% poc_url = @@ -174,11 +177,13 @@ priority = urgent # %DIR% = Direction of the telegram (0/1) # %DIRT% = Direction of the telegram (Text-String) # %TSI% = Tactical Short Information (I-IV) +# %DESCR% = Description from csv-file # %TIME% = Date/Time (by script) fms_subject = FMS: %FMS% fms_message = %TIME%: %FMS% - Status: %STATUS% - Direction: %DIRT% - TSI: %TSI% # %ZVEI% = ZVEI 5-tone Code +# %DESCR% = Description from csv-file # %TIME% = Date/Time (by script) zvei_subject = Alarm: %ZVEI% zvei_message = %TIME%: %ZVEI% @@ -188,6 +193,7 @@ zvei_message = %TIME%: %ZVEI% # %FUNCCHAR% = Pocsac function/Subric als character (a-d) # %MSG% = Message of the Pocsag telegram # %BITRATE% = Bitrate of the Pocsag telegram +# %DESCR% = Description from csv-file # %TIME% = Date/Time (by script) poc_subject = Alarm: %RIC%%FUNCCHAR% poc_message = %TIME%: %MSG% From 5b875b4def0ab7cde79de3537adadfe3d81f81cb Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 1 Jul 2015 10:41:23 +0200 Subject: [PATCH 38/98] now you must only activate the description tool in the needed section, not global --- boswatch.py | 4 ++-- config/config.template.ini | 10 +++------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/boswatch.py b/boswatch.py index a38746e6..b0759fa0 100755 --- a/boswatch.py +++ b/boswatch.py @@ -234,7 +234,7 @@ from includes import pluginLoader pluginLoader.loadPlugins() except: - # we couldn't work without filters -> exit + # we couldn't work without plugins -> exit logging.critical("cannot load Plugins") logging.debug("cannot load Plugins", exc_info=True) exit(1) @@ -256,7 +256,7 @@ # Load description lists # try: - if globals.config.getboolean("BOSWatch","useDescription"): + if globals.config.getboolean("FMS","idDescribed") or globals.config.getboolean("ZVEI","idDescribed") or globals.config.getboolean("POC","idDescribed"): from includes import descriptionList descriptionList.loadDescriptionLists() except: diff --git a/config/config.template.ini b/config/config.template.ini index 80475b48..c207de2e 100644 --- a/config/config.template.ini +++ b/config/config.template.ini @@ -27,10 +27,6 @@ backupCount = 7 # Filter-configuration in section [Filters] useRegExFilter = 0 -# Using Description (0|1) -# You have to be enabled it for every typ in the sections below too -useDescription = 0 - # for double check save the last n IDs # it is used in combination with double_ignore_time # 1 is required if you want to use the double alarm filter @@ -48,12 +44,12 @@ doubleFilter_check_msg = 0 [FMS] # look-up-table for adding a description -# turn on functionality (0|1) +# Using Description (0|1) idDescribed = 0 [ZVEI] # look-up-table for adding a description -# turn on functionality (0|1) +# Using Description (0|1) idDescribed = 0 [POC] @@ -71,7 +67,7 @@ filter_range_start = 0000000 filter_range_end = 9999999 # look-up-table for adding a description -# turn on functionality (0|1) +# Using Description (0|1) idDescribed = 0 From b05b155dc121fbe74eb84a0c484b1024340987a1 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 1 Jul 2015 13:28:46 +0200 Subject: [PATCH 39/98] little changes --- plugin_test.py | 2 +- testdata/testdata.txt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plugin_test.py b/plugin_test.py index ce6a67aa..c78bee72 100644 --- a/plugin_test.py +++ b/plugin_test.py @@ -21,7 +21,7 @@ logger.setLevel(logging.DEBUG) #set log string format -formatter = logging.Formatter('%(asctime)s - %(module)-12s [%(levelname)-8s] %(message)s', '%d.%m.%Y %H:%M:%S') +formatter = logging.Formatter('%(asctime)s - %(module)-15s %(funcName)-15s [%(levelname)-8s] %(message)s', '%d.%m.%Y %H:%M:%S') #create a display loger ch = logging.StreamHandler() diff --git a/testdata/testdata.txt b/testdata/testdata.txt index 438037a6..f9c63c71 100644 --- a/testdata/testdata.txt +++ b/testdata/testdata.txt @@ -11,6 +11,8 @@ ZVEI2: 12345 #without csv description ZVEI2: 56789 +#duplicate +ZVEI2: 56789 #with repeat Tone ZVEI2: 1F21F2 #in case of incomplete id From 2778b9e710616550b5365d60d84f68c77640fe2c Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 1 Jul 2015 14:11:11 +0200 Subject: [PATCH 40/98] file for little helper functions - also for use in plugins directly --- includes/helper.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 includes/helper.py diff --git a/includes/helper.py b/includes/helper.py new file mode 100644 index 00000000..6c0cd2b8 --- /dev/null +++ b/includes/helper.py @@ -0,0 +1,30 @@ +#!/usr/bin/python +# -*- coding: cp1252 -*- +# + +""" +little Helper functions + +@author: Bastian Schroll +""" + +import logging +import time + + +def freqToHz(freq): + """ + gets a frequency and resolve it in Hz + + @type format: string + @param format: Python time Format-String + + @return: Formated Time and/or Date + @exception: Exception if Error in format + """ +def curtime(format="%d.%m.%Y %H:%M:%S"): + try: + return time.strftime(format) + except: + logging.warning("error in time-format-string") + logging.debug("error in time-format-string", exc_info=True) \ No newline at end of file From 71070932db65b015b8b60232bcc0dcf6306c4a25 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 1 Jul 2015 14:27:22 +0200 Subject: [PATCH 41/98] use helper function for date and time --- config/config.template.ini | 9 ++++++--- plugins/httpRequest/httpRequest.py | 20 +++++++------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/config/config.template.ini b/config/config.template.ini index c207de2e..bbb4bfbb 100644 --- a/config/config.template.ini +++ b/config/config.template.ini @@ -127,13 +127,15 @@ tablePOC = bos_pocsag # %DIRT% = Direction of the telegram (Text-String) # %TSI% = Tactical Short Information (I-IV) # %DESCR% = Description from csv-file -# %TIME% = Date/Time (by script) +# %TIME% = Time (by script) +# %DATE% = DATE (by script) #fms_url = www.google.de?code=%FMS%&stat=%STATUS% fms_url = # %ZVEI% = ZVEI 5-tone Code # %DESCR% = Description from csv-file -# %TIME% = Date/Time (by script) +# %TIME% = Time (by script) +# %DATE% = DATE (by script) #zvei_url = www.google.de?zvei=%ZVEI% zvei_url = @@ -143,7 +145,8 @@ zvei_url = # %MSG% = Message of the Pocsag telegram # %BITRATE% = Bitrate of the Pocsag telegram # %DESCR% = Description from csv-file -# %TIME% = Date/Time (by script) +# %TIME% = Time (by script) +# %DATE% = DATE (by script) #poc_url = www.google.de?ric=%RIC%&subric=%FUNC%&msg=%MSG% poc_url = diff --git a/plugins/httpRequest/httpRequest.py b/plugins/httpRequest/httpRequest.py index 0e3a118f..f374b308 100644 --- a/plugins/httpRequest/httpRequest.py +++ b/plugins/httpRequest/httpRequest.py @@ -15,6 +15,7 @@ from urlparse import urlparse #for split the URL into url and path from includes import globals # Global variables +from includes import helper #Global helper functions ## # @@ -32,13 +33,6 @@ def onLoad(): """ # nothing to do for this plugin return - -## -# -# Private helper function for a printable Timestamp -# -def curtime(): - return time.strftime("%Y-%m-%d %H:%M:%S") ## @@ -86,22 +80,22 @@ def run(typ,freq,data): url = url.replace("%FMS%", data["fms"]).replace("%STATUS%", data["status"]) #replace Wildcards url = url.replace("%DIR%", data["direction"]).replace("%DIRT%", data["directionText"]) #replace Wildcards url = url.replace("%TSI%", data["tsi"]) #replace Wildcards - url = url.replace("%DESCR%", data["description"]) # replace Wildcards - url = url.replace("%TIME%", curtime()) # replace Wildcards elif typ == "ZVEI": url = globals.config.get("httpRequest", "zvei_url") #Get URL url = url.replace("%ZVEI%", data["zvei"]) #replace Wildcards - url = url.replace("%DESCR%", data["description"]) # replace Wildcards - url = url.replace("%TIME%", curtime()) # replace Wildcards elif typ == "POC": url = globals.config.get("httpRequest", "poc_url") #Get URL url = url.replace("%RIC%", data["ric"]) #replace Wildcards url = url.replace("%FUNC%", data["function"]).replace("%FUNCCHAR%", data["functionChar"]) #replace Wildcards url = url.replace("%MSG%", data["msg"]).replace("%BITRATE%", str(data["bitrate"])) #replace Wildcards - url = url.replace("%DESCR%", data["description"]) # replace Wildcards - url = url.replace("%TIME%", curtime()) # replace Wildcards else: logging.warning("Invalid Typ: %s", typ) + raise + + #same in all types + url = url.replace("%DESCR%", data["description"]) # replace Wildcards + url = url.replace("%TIME%", helper.curtime("%H:%M:%S")) # replace Wildcards + url = url.replace("%DATE%", helper.curtime("%d.%m.%Y")) # replace Wildcards # # HTTP-Request From 3b0a50f8785c2e819391139c020254b82ff858bf Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 1 Jul 2015 14:29:55 +0200 Subject: [PATCH 42/98] no longer needed - boswatch.py has own testmode "-t" --- plugin_test.py | 81 -------------------------------------------------- 1 file changed, 81 deletions(-) delete mode 100644 plugin_test.py diff --git a/plugin_test.py b/plugin_test.py deleted file mode 100644 index c78bee72..00000000 --- a/plugin_test.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- - -########################################################################### -# Use this as a simple Plugin Loading Tool to test your own Coded Plugins # -########################################################################### - -import logging - -import ConfigParser #for parse the config file -import os #for log mkdir -import time #timestamp for doublealarm - -from includes import globals # Global variables -from includes import pluginLoader -from includes import alarmHandler -from includes import filter - -#create new logger -logger = logging.getLogger() -logger.setLevel(logging.DEBUG) - -#set log string format -formatter = logging.Formatter('%(asctime)s - %(module)-15s %(funcName)-15s [%(levelname)-8s] %(message)s', '%d.%m.%Y %H:%M:%S') - -#create a display loger -ch = logging.StreamHandler() -ch.setLevel(logging.DEBUG) #log level >= info -ch.setFormatter(formatter) -logger.addHandler(ch) - -#https://docs.python.org/2/howto/logging.html#logging-basic-tutorial -#log levels -#---------- -#debug - debug messages only for log -#info - information for normal display -#warning -#error - normal error - program goes further -#exception - error with exception message in log -#critical - critical error, program exit - -globals.script_path = os.path.dirname(os.path.abspath(__file__)) - -try: - logging.debug("reading config file") - globals.config = ConfigParser.ConfigParser() - globals.config.read(globals.script_path+"/config/config.ini") - for key,val in globals.config.items("Plugins"): - logging.debug(" - %s = %s", key, val) -except: - logging.exception("cannot read config file") - - -pluginLoader.loadPlugins() - -filter.loadFilters() - - -# ----- Test Data ----- # -#typ = "FMS" -#data = {"fms":"12345678", "status":"2", "direction":"1", "tsi":"III"} - -typ = "ZVEI" -data = {"zvei":"25345"} - -#typ = "POC" -#data = {"ric":"1234567", "function":"1", "msg":"Hello World!, "bitrate":"1200"} - -while True: - try: - time.sleep(1) - - print "" - alarmHandler.processAlarm(typ,"0",data) - - except KeyboardInterrupt: - logging.warning("Keyboard Interrupt") - exit() - except: - logging.exception("unknown error") - exit() From 29873c5ec3c0d886063e4d0e13f5313a90ad02dd Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 1 Jul 2015 14:35:44 +0200 Subject: [PATCH 43/98] use helper function curtime() and split date and time in eMail plugin --- config/config.template.ini | 21 ++++++++++++--------- plugins/eMail/eMail.py | 22 +++++++--------------- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/config/config.template.ini b/config/config.template.ini index bbb4bfbb..57036a3f 100644 --- a/config/config.template.ini +++ b/config/config.template.ini @@ -128,14 +128,14 @@ tablePOC = bos_pocsag # %TSI% = Tactical Short Information (I-IV) # %DESCR% = Description from csv-file # %TIME% = Time (by script) -# %DATE% = DATE (by script) +# %DATE% = Date (by script) #fms_url = www.google.de?code=%FMS%&stat=%STATUS% fms_url = # %ZVEI% = ZVEI 5-tone Code # %DESCR% = Description from csv-file # %TIME% = Time (by script) -# %DATE% = DATE (by script) +# %DATE% = Date (by script) #zvei_url = www.google.de?zvei=%ZVEI% zvei_url = @@ -146,7 +146,7 @@ zvei_url = # %BITRATE% = Bitrate of the Pocsag telegram # %DESCR% = Description from csv-file # %TIME% = Time (by script) -# %DATE% = DATE (by script) +# %DATE% = Date (by script) #poc_url = www.google.de?ric=%RIC%&subric=%FUNC%&msg=%MSG% poc_url = @@ -177,15 +177,17 @@ priority = urgent # %DIRT% = Direction of the telegram (Text-String) # %TSI% = Tactical Short Information (I-IV) # %DESCR% = Description from csv-file -# %TIME% = Date/Time (by script) +# %TIME% = Time (by script) +# %DATE% = Date (by script) fms_subject = FMS: %FMS% -fms_message = %TIME%: %FMS% - Status: %STATUS% - Direction: %DIRT% - TSI: %TSI% +fms_message = %DATE% %TIME%: %FMS% - Status: %STATUS% - Direction: %DIRT% - TSI: %TSI% # %ZVEI% = ZVEI 5-tone Code # %DESCR% = Description from csv-file -# %TIME% = Date/Time (by script) +# %TIME% = Time (by script) +# %DATE% = Date (by script) zvei_subject = Alarm: %ZVEI% -zvei_message = %TIME%: %ZVEI% +zvei_message = %DATE% %TIME%: %ZVEI% # %RIC% = Pocsag RIC # %FUNC% = Pocsac function/Subric (1-4) @@ -193,9 +195,10 @@ zvei_message = %TIME%: %ZVEI% # %MSG% = Message of the Pocsag telegram # %BITRATE% = Bitrate of the Pocsag telegram # %DESCR% = Description from csv-file -# %TIME% = Date/Time (by script) +# %TIME% = Time (by script) +# %DATE% = Date (by script) poc_subject = Alarm: %RIC%%FUNCCHAR% -poc_message = %TIME%: %MSG% +poc_message = %DATE% %TIME%: %MSG% [BosMon] diff --git a/plugins/eMail/eMail.py b/plugins/eMail/eMail.py index 904a62a6..af60e5a2 100644 --- a/plugins/eMail/eMail.py +++ b/plugins/eMail/eMail.py @@ -18,6 +18,7 @@ from email.utils import make_msgid # need for confirm to RFC2822 standard from includes import globals # Global variables +from includes import helper #Global helper functions ## # @@ -35,16 +36,7 @@ def onLoad(): """ # nothing to do for this plugin return - - -## -# -# Private helper function for a printable Timestamp -# -def curtime(): - return time.strftime("%Y-%m-%d %H:%M:%S") - ## # # do send mail @@ -149,14 +141,14 @@ def run(typ,freq,data): subject = subject.replace("%DIR%", data["direction"]).replace("%DIRT%", data["directionText"]) #replace Wildcards subject = subject.replace("%TSI%", data["tsi"]) #replace Wildcards subject = subject.replace("%DESCR%", data["description"]) # replace Wildcards - subject = subject.replace("%TIME%", curtime()) # replace Wildcards + subject = subject.replace("%TIME%", helper.curtime("H:M:S")).replace("%DATE%", helper.curtime("Y-m-d")) # replace Wildcards # read mailtext-structure from config.ini mailtext = globals.config.get("eMail", "fms_message") mailtext = mailtext.replace("%FMS%", data["fms"]).replace("%STATUS%", data["status"]) #replace Wildcards mailtext = mailtext.replace("%DIR%", data["direction"]).replace("%DIRT%", data["directionText"]) #replace Wildcards mailtext = mailtext.replace("%TSI%", data["tsi"]) #replace Wildcards mailtext = mailtext.replace("%DESCR%", data["description"]) # replace Wildcards - mailtext = mailtext.replace("%TIME%", curtime()) # replace Wildcards + mailtext = mailtext.replace("%TIME%", helper.curtime("H:M:S")).replace("%DATE%", helper.curtime("Y-m-d")) # replace Wildcards # send eMail doSendmail(server, subject, mailtext) except: @@ -171,12 +163,12 @@ def run(typ,freq,data): subject = globals.config.get("eMail", "zvei_subject") subject = subject.replace("%ZVEI%", data["zvei"]) #replace Wildcards subject = subject.replace("%DESCR%", data["description"]) # replace Wildcards - subject = subject.replace("%TIME%", curtime()) # replace Wildcards + subject = subject.replace("%TIME%", helper.curtime("H:M:S")).replace("%DATE%", helper.curtime("Y-m-d")) # replace Wildcards # read mailtext-structure from config.ini mailtext = globals.config.get("eMail", "zvei_message") mailtext = mailtext.replace("%ZVEI%", data["zvei"]) #replace Wildcards mailtext = mailtext.replace("%DESCR%", data["description"]) # replace Wildcards - mailtext = mailtext.replace("%TIME%", curtime()) # replace Wildcards + mailtext = mailtext.replace("%TIME%", helper.curtime("H:M:S")).replace("%DATE%", helper.curtime("Y-m-d")) # replace Wildcards # send eMail doSendmail(server, subject, mailtext) except: @@ -193,14 +185,14 @@ def run(typ,freq,data): subject = subject.replace("%FUNC%", data["function"]).replace("%FUNCCHAR%", data["functionChar"]) #replace Wildcards subject = subject.replace("%MSG%", data["msg"]).replace("%BITRATE%", str(data["bitrate"])) #replace Wildcards subject = subject.replace("%DESCR%", data["description"]) # replace Wildcards - subject = subject.replace("%TIME%", curtime()) # replace Wildcards + subject = subject.replace("%TIME%", helper.curtime("H:M:S")).replace("%DATE%", helper.curtime("Y-m-d")) # replace Wildcards # read mailtext-structure from config.ini mailtext = globals.config.get("eMail", "poc_message") mailtext = mailtext.replace("%RIC%", data["ric"]) #replace Wildcards mailtext = mailtext.replace("%FUNC%", data["function"]).replace("%FUNCCHAR%", data["functionChar"]) #replace Wildcards mailtext = mailtext.replace("%MSG%", data["msg"]).replace("%BITRATE%", str(data["bitrate"])) #replace Wildcards mailtext = mailtext.replace("%DESCR%", data["description"]) # replace Wildcards - mailtext = mailtext.replace("%TIME%", curtime()) # replace Wildcards + mailtext = mailtext.replace("%TIME%", helper.curtime("H:M:S")).replace("%DATE%", helper.curtime("Y-m-d")) # replace Wildcards # send eMail doSendmail(server, subject, mailtext) except: From dea33d5b7e63bd36415177ae11db045ce2f067d8 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 1 Jul 2015 14:52:33 +0200 Subject: [PATCH 44/98] little docu mistake in helper.py --- includes/helper.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/includes/helper.py b/includes/helper.py index 6c0cd2b8..d2d6f258 100644 --- a/includes/helper.py +++ b/includes/helper.py @@ -4,6 +4,7 @@ """ little Helper functions +mainly for direct usw in plugins to save code @author: Bastian Schroll """ @@ -12,9 +13,10 @@ import time -def freqToHz(freq): +def curtime(format="%d.%m.%Y %H:%M:%S"): """ - gets a frequency and resolve it in Hz + Returns formated date and/or time + see: https://docs.python.org/2/library/time.html#time.strftime @type format: string @param format: Python time Format-String @@ -22,7 +24,6 @@ def freqToHz(freq): @return: Formated Time and/or Date @exception: Exception if Error in format """ -def curtime(format="%d.%m.%Y %H:%M:%S"): try: return time.strftime(format) except: From 214ce78470745239761b20f26e4f302a497bae11 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 1 Jul 2015 15:02:45 +0200 Subject: [PATCH 45/98] Extend interface.txt --- plugins/interface.txt | 10 +++++++++- plugins/template/template.py | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/plugins/interface.txt b/plugins/interface.txt index d8b7718e..264d4901 100644 --- a/plugins/interface.txt +++ b/plugins/interface.txt @@ -75,4 +75,12 @@ def run(typ,freq,data): @return: nothing @exception: nothing, make sure this function will never thrown an exception - """ \ No newline at end of file + """ + + +Global Functions for plugins: +----------------------------- +from includes import helper #Global helper functions + + +helper.curtime("FORMAT") \ No newline at end of file diff --git a/plugins/template/template.py b/plugins/template/template.py index b20c3eb7..dfe104a5 100644 --- a/plugins/template/template.py +++ b/plugins/template/template.py @@ -23,6 +23,7 @@ import logging # Global logger from includes import globals # Global variables +#from includes import helper #Global helper functions ## # From 5f9bfa7a634c63e20642ad90c45df90623d447ae Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Wed, 1 Jul 2015 19:01:16 +0200 Subject: [PATCH 46/98] edit decoder.py --- includes/decoder.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/includes/decoder.py b/includes/decoder.py index 49972816..8edd422d 100644 --- a/includes/decoder.py +++ b/includes/decoder.py @@ -30,7 +30,7 @@ def decode(freq, decoded): logging.debug("recieved FMS") from includes.decoders import fms fms.decode(freq, decoded) - + # ZVEI Decoder Section # check ZVEI: -> validate -> check double alarm -> log elif "ZVEI2:" in decoded: @@ -38,13 +38,9 @@ def decode(freq, decoded): from includes.decoders import zvei zvei.decode(freq, decoded) - # For POCSAG we have to ignore the multimon-ng line "Enabled demodulators:" - elif "Enabled demodulators:" in decoded: - pass - # POCSAG Decoder Section # check POCSAG -> validate -> check double alarm -> log - elif "POCSAG" in decoded: + elif "POCSAG512:" in decoded or "POCSAG1024:" in decoded or "POCSAG2400:" in decoded: logging.debug("recieved POCSAG") from includes.decoders import poc poc.decode(freq, decoded) From 25daa26c9863f6993449341c356602b27b36a8d2 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Wed, 1 Jul 2015 20:33:43 +0200 Subject: [PATCH 47/98] little error in httpRequest Plugin --- plugins/httpRequest/httpRequest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/httpRequest/httpRequest.py b/plugins/httpRequest/httpRequest.py index f374b308..e2ceabc8 100644 --- a/plugins/httpRequest/httpRequest.py +++ b/plugins/httpRequest/httpRequest.py @@ -90,8 +90,8 @@ def run(typ,freq,data): url = url.replace("%MSG%", data["msg"]).replace("%BITRATE%", str(data["bitrate"])) #replace Wildcards else: logging.warning("Invalid Typ: %s", typ) - raise - + return + #same in all types url = url.replace("%DESCR%", data["description"]) # replace Wildcards url = url.replace("%TIME%", helper.curtime("%H:%M:%S")) # replace Wildcards From 241a31ec01d40494272b9216d9f32503b0132a55 Mon Sep 17 00:00:00 2001 From: JHCD Date: Wed, 1 Jul 2015 21:57:27 +0200 Subject: [PATCH 48/98] solve bug in if-clause --- includes/decoder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/decoder.py b/includes/decoder.py index 8edd422d..addef2ef 100644 --- a/includes/decoder.py +++ b/includes/decoder.py @@ -40,7 +40,7 @@ def decode(freq, decoded): # POCSAG Decoder Section # check POCSAG -> validate -> check double alarm -> log - elif "POCSAG512:" in decoded or "POCSAG1024:" in decoded or "POCSAG2400:" in decoded: + elif "POCSAG512:" in decoded or "POCSAG1200:" in decoded or "POCSAG2400:" in decoded: logging.debug("recieved POCSAG") from includes.decoders import poc poc.decode(freq, decoded) From 01ae87c918254425dbf4d1a00cf3d0327c1eea76 Mon Sep 17 00:00:00 2001 From: JHCD Date: Wed, 1 Jul 2015 22:04:06 +0200 Subject: [PATCH 49/98] solve some bugs - solve issue #35 - some bugs in logging errors - move check subprocesses in include-file --- boswatch.py | 35 ++++++++++++----------- includes/checkSubprocesses.py | 54 +++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 16 deletions(-) create mode 100644 includes/checkSubprocesses.py diff --git a/boswatch.py b/boswatch.py index b0759fa0..13f1f299 100755 --- a/boswatch.py +++ b/boswatch.py @@ -28,6 +28,7 @@ from includes import MyTimedRotatingFileHandler # extension of TimedRotatingFileHandler from includes import converter # converter functions from includes import signalHandler # TERM-Handler for use script as a daemon +from includes import checkSubprocesses # check startup of the subprocesses # @@ -55,7 +56,9 @@ # -h or --help called, exit right now exit(0) except: - print "cannot parsing the arguments" + # we couldn't work without arguments -> exit + print "ERROR: cannot parsing the arguments" + exit(1) # @@ -85,14 +88,20 @@ # if not os.path.exists(globals.log_path): os.mkdir(globals.log_path) - - # - # Create new myLogger... - # + except: + # we couldn't work without logging -> exit + print "ERROR: cannot initialize paths" + exit(1) + + # + # Create new myLogger... + # + try: myLogger = logging.getLogger() myLogger.setLevel(logging.DEBUG) # set log string format - formatter = logging.Formatter('%(asctime)s - %(module)-15s %(funcName)-15s [%(levelname)-8s] %(message)s', '%d.%m.%Y %H:%M:%S') + #formatter = logging.Formatter('%(asctime)s - %(module)-15s %(funcName)-15s [%(levelname)-8s] %(message)s', '%d.%m.%Y %H:%M:%S') + formatter = logging.Formatter('%(asctime)s - %(module)-15s [%(levelname)-8s] %(message)s', '%d.%m.%Y %H:%M:%S') # create a file logger fh = MyTimedRotatingFileHandler.MyTimedRotatingFileHandler(globals.log_path+"boswatch.log", "midnight", interval=1, backupCount=999) # Starts with log level >= Debug @@ -114,8 +123,7 @@ except: # we couldn't work without logging -> exit - logging.critical("cannot create logger") - logging.debug("cannot create logger", exc_info=True) + print "ERROR: cannot create logger" exit(1) # initialization of the logging was fine, continue... @@ -132,6 +140,7 @@ mon_log.close() logging.debug("BOSWatch has started") logging.debug("Logfiles cleared") + except: # It's an error, but we could work without that stuff... logging.error("cannot clear Logfiles") @@ -283,10 +292,7 @@ # rtl_fm doesn't self-destruct, when an error occurs # wait a moment to give the subprocess a chance to write the logfile time.sleep(3) - rtlLog = open(globals.log_path+"rtl_fm.log","r").read() - if ("Failed" in rtlLog) or ("error" in rtlLog): - logging.debug("\n%s", rtlLog) - raise OSError("starting rtl_fm returns an error") + checkSubprocesses.checkRTL() else: logging.warning("!!! Test-Mode: rtl_fm not started !!!") except: @@ -313,10 +319,7 @@ # multimon-ng doesn't self-destruct, when an error occurs # wait a moment to give the subprocess a chance to write the logfile time.sleep(3) - multimonLog = open(globals.log_path+"multimon.log","r").read() - if ("invalid" in multimonLog) or ("error" in multimonLog): - logging.debug("\n%s", multimonLog) - raise OSError("starting multimon-ng returns an error") + checkSubprocesses.checkMultimon() else: logging.warning("!!! Test-Mode: multimon-ng not started !!!") except: diff --git a/includes/checkSubprocesses.py b/includes/checkSubprocesses.py new file mode 100644 index 00000000..120d4f64 --- /dev/null +++ b/includes/checkSubprocesses.py @@ -0,0 +1,54 @@ +#!/usr/bin/python +# -*- coding: cp1252 -*- +# +""" +Functions for checking the subprocesses rtl_fm and multimon-ng +Used in boswatch.py at startup and designated for watching-service + +@author: Jens Herrmann +""" + +import logging + +from includes import globals # Global variables + + +def checkRTL(): + """ + check startup of rtl_fm + + @exception: OSError when rtl_fm returns an error + @exception: Exception when checkRTL throws an unexpected error + """ + try: + rtlLog = open(globals.log_path+"rtl_fm.log","r").read() + if ("exiting" in rtlLog) or ("Failed to open" in rtlLog): + logging.debug("\n%s", rtlLog) + raise OSError("starting rtl_fm returns an error") + except OSError: + raise + except: + # we couldn't work without rtl_fm + logging.critical("cannot check rtl_fm.log") + logging.debug("cannot check rtl_fm.log", exc_info=True) + raise + +def checkMultimon(): + """ + check startup of multimon-ng + + @exception: OSError when multimon-ng returns an error + @exception: Exception when checkMultimon throws an unexpected error + """ + try: + multimonLog = open(globals.log_path+"multimon.log","r").read() + if ("invalid" in multimonLog) or ("error" in multimonLog): + logging.debug("\n%s", multimonLog) + raise OSError("starting multimon-ng returns an error") + except OSError: + raise + except: + # we couldn't work without multimon-ng + logging.critical("cannot check multimon.log") + logging.debug("cannot check multimon.log", exc_info=True) + raise \ No newline at end of file From 4562704b842a2f2794d1720a404b9b1053fb7e32 Mon Sep 17 00:00:00 2001 From: JHCD Date: Wed, 1 Jul 2015 22:31:20 +0200 Subject: [PATCH 50/98] dos2linux-converting --- includes/checkSubprocesses.py | 106 +++++++++++++++++----------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/includes/checkSubprocesses.py b/includes/checkSubprocesses.py index 120d4f64..ba4080bf 100644 --- a/includes/checkSubprocesses.py +++ b/includes/checkSubprocesses.py @@ -1,54 +1,54 @@ -#!/usr/bin/python -# -*- coding: cp1252 -*- -# -""" -Functions for checking the subprocesses rtl_fm and multimon-ng -Used in boswatch.py at startup and designated for watching-service - -@author: Jens Herrmann -""" - -import logging - -from includes import globals # Global variables - - -def checkRTL(): - """ - check startup of rtl_fm - - @exception: OSError when rtl_fm returns an error - @exception: Exception when checkRTL throws an unexpected error - """ - try: - rtlLog = open(globals.log_path+"rtl_fm.log","r").read() - if ("exiting" in rtlLog) or ("Failed to open" in rtlLog): - logging.debug("\n%s", rtlLog) - raise OSError("starting rtl_fm returns an error") - except OSError: - raise - except: - # we couldn't work without rtl_fm - logging.critical("cannot check rtl_fm.log") - logging.debug("cannot check rtl_fm.log", exc_info=True) - raise - -def checkMultimon(): - """ - check startup of multimon-ng - - @exception: OSError when multimon-ng returns an error - @exception: Exception when checkMultimon throws an unexpected error - """ - try: - multimonLog = open(globals.log_path+"multimon.log","r").read() - if ("invalid" in multimonLog) or ("error" in multimonLog): - logging.debug("\n%s", multimonLog) - raise OSError("starting multimon-ng returns an error") - except OSError: - raise - except: - # we couldn't work without multimon-ng - logging.critical("cannot check multimon.log") - logging.debug("cannot check multimon.log", exc_info=True) +#!/usr/bin/python +# -*- coding: cp1252 -*- +# +""" +Functions for checking the subprocesses rtl_fm and multimon-ng +Used in boswatch.py at startup and designated for watching-service + +@author: Jens Herrmann +""" + +import logging + +from includes import globals # Global variables + + +def checkRTL(): + """ + check startup of rtl_fm + + @exception: OSError when rtl_fm returns an error + @exception: Exception when checkRTL throws an unexpected error + """ + try: + rtlLog = open(globals.log_path+"rtl_fm.log","r").read() + if ("exiting" in rtlLog) or ("Failed to open" in rtlLog): + logging.debug("\n%s", rtlLog) + raise OSError("starting rtl_fm returns an error") + except OSError: + raise + except: + # we couldn't work without rtl_fm + logging.critical("cannot check rtl_fm.log") + logging.debug("cannot check rtl_fm.log", exc_info=True) + raise + +def checkMultimon(): + """ + check startup of multimon-ng + + @exception: OSError when multimon-ng returns an error + @exception: Exception when checkMultimon throws an unexpected error + """ + try: + multimonLog = open(globals.log_path+"multimon.log","r").read() + if ("invalid" in multimonLog) or ("error" in multimonLog): + logging.debug("\n%s", multimonLog) + raise OSError("starting multimon-ng returns an error") + except OSError: + raise + except: + # we couldn't work without multimon-ng + logging.critical("cannot check multimon.log") + logging.debug("cannot check multimon.log", exc_info=True) raise \ No newline at end of file From fdc5f6e40c4b88d6eeedee2b35085deda74ab828 Mon Sep 17 00:00:00 2001 From: JHCD Date: Wed, 1 Jul 2015 22:33:32 +0200 Subject: [PATCH 51/98] implementation of an example jsonSocketServer - jsonSocketServer for receive alarm-messages from BOSWatch. - jsonSocketServer controlls an pibrella-bord in case of received POCSAG-RIC --- serverExamples/jsonSocketServer.py | 148 +++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 serverExamples/jsonSocketServer.py diff --git a/serverExamples/jsonSocketServer.py b/serverExamples/jsonSocketServer.py new file mode 100644 index 00000000..6e59bfa1 --- /dev/null +++ b/serverExamples/jsonSocketServer.py @@ -0,0 +1,148 @@ +#!/usr/bin/python +# -*- coding: cp1252 -*- +# + +""" +jsonSocketServer +This is a small example of an jsonSocketServer for receive alarm-messages from BOSWatch. +The jsonSocketServer controlls an pibrella-bord in case of received POCSAG-RIC + +Implemented functions: +- asynchronous service for alarm-sound +- green LED if jsonSocketServer is running +- green LED is blinking if Dau-Test-RIC was received +- yellow LED is blinking if our RICs is reveived with functioncode "a" +- red LED is blinking in case of an alarm (our RICs with functioncode "b") +- siren will run with the pack +- press Pibrella button to stop alarm and reset the LEDs + +@author: Jens Herrmann + +BOSWatch: https://github.com/Schrolli91/BOSWatch +Pibrella: https://github.com/pimoroni/pibrella +""" + +# no IP for server necessary +IP = "" +# listen on port +PORT = 8112 + + +import logging +import logging.handlers + +import socket # for udp-socket +import pibrella # for pi-board +import json # for data + + +# +# Eventhandler for button +# will stop the alarm and reset the LEDs +# +def button_pressed(pin): + global siren_stopped + import pibrella + pibrella.light.off() + pibrella.light.green.on() + siren_stopped = True +# load Eventhandler +pibrella.button.pressed(button_pressed) + +# +# Siren-control +# + +# normally we have no alarm, siren-control-var is True +siren_stopped = True + +# asynchronous siren: +def siren(): + import time + if siren_stopped == True: + pibrella.buzzer.stop() + return True + for x in xrange(-30,30,2): + pibrella.buzzer.note(x) + time.sleep(0.01) + for x in reversed(xrange(-30,30,2)): + pibrella.buzzer.note(x) + time.sleep(0.01) +# start asynchronous siren +pibrella.async_start('siren',siren) + + +# +# Main Program +# +try: + # Logging + myLogger = logging.getLogger() + myLogger.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(asctime)s [%(levelname)-8s] %(message)s', '%d.%m.%Y %H:%M:%S') + ch = logging.StreamHandler() + ch.setLevel(logging.DEBUG) + ch.setFormatter(formatter) + myLogger.addHandler(ch) + + # Start TCP socket: + logging.debug("Start jsonSocketServer") + sock = socket.socket() + sock.bind((IP,PORT)) + sock.listen(2) + logging.info("jsonSocketServer runs") + pibrella.light.green.on() + + # our Alarm-RICs: + ric_alarm = [12345677, 12345676, 12345675] + + while True: + # accept connections from outside + (clientsocket, address) = sock.accept() + logging.debug("connected client: %s", address) + + # receive message as json string + json_string = clientsocket.recv( 4096 ) # buffer size is 4096 bytes + try: + # parse json + parsed_json = json.loads(json_string) + logging.debug("parsed message: %s", parsed_json) + except ValueError: + # parsing error is foolish, but we don't have to exit + logging.warning("No JSON object could be decoded: %s", json_string) + pass + else: + # DAU-Test-RIC received + if parsed_json['ric'] == "1234567": + logging.debug("POCSAG is alive") + pibrella.light.green.blink(1, 1) + + elif int(parsed_json['ric']) in ric_alarm: + logging.debug("We have do to something") + if parsed_json['functionChar'] == "a": + logging.info("-> Probealarm: %", parsed_json['ric']) + pibrella.light.yellow.blink(1, 1) + elif parsed_json['functionChar'] == "b": + logging.info("-> Alarm: %", parsed_json['ric']) + pibrella.light.red.blink(1, 1) + # change variable to False to start the siren + siren_stopped = False + +except KeyboardInterrupt: + logging.warning("Keyboard Interrupt") +except: + logging.exception("unknown error") +finally: + try: + logging.debug("socketServer shuting down") + sock.close() + logging.debug("socket closed") + logging.debug("exiting socketServer") + except: + logging.warning("failed in clean-up routine") + finally: + logging.debug("close Logging") + logging.info("socketServer exit()") + logging.shutdown() + ch.close() + exit(0) \ No newline at end of file From ab4b63daacea943a47c5a02087244e5a12b77353 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 2 Jul 2015 07:33:27 +0200 Subject: [PATCH 52/98] insert version number and build date in the globals --- boswatch.py | 2 ++ includes/globals.py | 10 +++++++++- includes/shellHeader.py | 19 ++++++++++++------- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/boswatch.py b/boswatch.py index 13f1f299..e2071026 100755 --- a/boswatch.py +++ b/boswatch.py @@ -151,6 +151,8 @@ # For debug display/log args # try: + logging.debug("SW Version: %s",globals.getVers("vers")) + logging.debug("Build Date: %s",globals.getVers("date")) logging.debug("BOSWatch given arguments") if args.test: logging.debug(" - Test-Mode!") diff --git a/includes/globals.py b/includes/globals.py index f4ab2d81..269dc6f4 100644 --- a/includes/globals.py +++ b/includes/globals.py @@ -25,4 +25,12 @@ # idDescribing fmsDescribtionList = {} zveiDescribtionList = {} -ricDescribtionList = {} \ No newline at end of file +ricDescribtionList = {} + +# returns the Version number +# function -> read only in script +def getVers(mode="vers"): + if mode == "vers": + return "2.0-RC" + elif mode == "date": + return " 2015/07/02" \ No newline at end of file diff --git a/includes/shellHeader.py b/includes/shellHeader.py index 7137c419..b13d909a 100644 --- a/includes/shellHeader.py +++ b/includes/shellHeader.py @@ -10,6 +10,8 @@ @requires: none """ +from includes import globals + def printHeader(args): """ Prints the header to the shell @@ -20,14 +22,17 @@ def printHeader(args): @return: nothing """ try: - print " ____ ____ ______ __ __ __ " - print " / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ b" - print " / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ e" - print " / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / t" - print " /_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ a" - print " German BOS Information Script " - print " by Bastian Schroll, Jens Herrmann " + print " ____ ____ ______ __ __ __ " + print " / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ " + print " / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ " + print " / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / " + print " /_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ " + print " German BOS Information Script " + print " by Bastian Schroll, Jens Herrmann " print "" + print "SW Version: "+globals.getVers("vers") + print "Build Date: "+globals.getVers("date") + print "" print "Frequency: "+args.freq print "Device-ID: "+str(args.device) From 5e6cf3b7ae250452a01995d220f2fefe071a02cb Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 2 Jul 2015 07:48:17 +0200 Subject: [PATCH 53/98] add pocsag testdata for test-driver --- includes/globals.py | 2 +- testdata/testdata.txt | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/includes/globals.py b/includes/globals.py index 269dc6f4..7eadb146 100644 --- a/includes/globals.py +++ b/includes/globals.py @@ -27,7 +27,7 @@ zveiDescribtionList = {} ricDescribtionList = {} -# returns the Version number +# returns the version or build date # function -> read only in script def getVers(mode="vers"): if mode == "vers": diff --git a/testdata/testdata.txt b/testdata/testdata.txt index f9c63c71..c2ac3756 100644 --- a/testdata/testdata.txt +++ b/testdata/testdata.txt @@ -3,6 +3,24 @@ #Data is alternately passed to the decoder to simulate an used Radio-Frequency #POCSAG +#all bitrates, all functions, with and without text, duplicates same and other msg + +#witch csv +POCSAG512: Address: 1234567 Function: 1 Alpha: Hello World + +#without csv +POCSAG1200: Address: 2345678 Function: 2 Alpha: Hello World +POCSAG2400: Address: 3456789 Function: 3 Alpha: Hello World + +#OHNE TEXT???? +POCSAG1200: Address: 1358246 Function: 4 + +#duplicate with same and other msg +POCSAG1200: Address: 2345678 Function: 1 Alpha: Hello World +POCSAG1200: Address: 2345678 Function: 1 Alpha: Hello Earth + +#invalid +POCSAG1200: Address: 123567 Function: 1 Alpha: Hello World #FMS @@ -14,8 +32,8 @@ ZVEI2: 56789 #duplicate ZVEI2: 56789 #with repeat Tone -ZVEI2: 1F21F2 -#in case of incomplete id +ZVEI2: 1F2F3 +#in case of invalid id ZVEI2: 135 #in case of a double-tone for siren n-'D's are sended ZVEI2: DDD From c2e435564db05e8fa6a5cc73a1772b3703ae4de9 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 2 Jul 2015 08:15:55 +0200 Subject: [PATCH 54/98] edit testdata - See Issue #38 --- testdata/testdata.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testdata/testdata.txt b/testdata/testdata.txt index c2ac3756..543f721e 100644 --- a/testdata/testdata.txt +++ b/testdata/testdata.txt @@ -16,8 +16,8 @@ POCSAG2400: Address: 3456789 Function: 3 Alpha: Hello World POCSAG1200: Address: 1358246 Function: 4 #duplicate with same and other msg -POCSAG1200: Address: 2345678 Function: 1 Alpha: Hello World -POCSAG1200: Address: 2345678 Function: 1 Alpha: Hello Earth +POCSAG1200: Address: 2345678 Function: 2 Alpha: Hello World +POCSAG1200: Address: 2345678 Function: 2 Alpha: Bye Earth #invalid POCSAG1200: Address: 123567 Function: 1 Alpha: Hello World From 15f4f9901298a3239b453f322b8d352489fa1779 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 2 Jul 2015 08:54:42 +0200 Subject: [PATCH 55/98] update readme.md --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index b95340f5..e19f2519 100644 --- a/README.md +++ b/README.md @@ -59,12 +59,12 @@ For the RegEX filter functions see Section `[Filters]` http://www.regexr.com/ - RegEX test tool an documentation No filter for a combination typ/plugin = all data will pass -Syntax: INDIVIDUAL_NAME = TYP;DATAFIELD;PLUGIN;FREQUENZ;REGEX (separator ";") -- TYP = the data typ (FMS|ZVEI|POC) -- DATAFIELD = the field of the data array (See interface.txt) -- PLUGIN = the name of the plugin to call with this filter (* for all) -- FREQUENZ = the frequenz to use the filter (for more SDR sticks (* for all)) -- REGEX = the RegEX +Syntax: `INDIVIDUAL_NAME = TYP;DATAFIELD;PLUGIN;FREQUENZ;REGEX` (separator `;`) +- `TYP` = the data typ (FMS|ZVEI|POC) +- `DATAFIELD` = the field of the data array (See interface.txt) +- `PLUGIN` = the name of the plugin to call with this filter (* for all) +- `FREQUENZ` = the frequenz to use the filter (for more SDR sticks (* for all)) +- `REGEX` = the RegEX only ZVEI to all plugins with 25### at 85.5MHz testfilter = ZVEI;zvei;*;85500000;25[0-9]{3} @@ -120,7 +120,7 @@ Caution, script don't install a webserver with PHP and MySQL. So you have to make up manually if you want to use MySQL support. Database Structure `boswatch.sql` in the MySQL Plugin Folder -If you want to use BOSWatch as a daemon, you have to set your +If you want to use BOSWatch as a daemon, you have to set your configuration in `service/boswatch.sh` and copy it to `/etc/init.d`. Then you can start BOSWatch with `sudo /etc/init.d/boswatch.sh start`. For configuration-details see `service/README.md`. From 48c4d1e35449fc1c16d1705f05ed0d50e30b2351 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 2 Jul 2015 09:02:49 +0200 Subject: [PATCH 56/98] remove trailing whitespace --- LICENSE | 1 - boswatch.py | 106 ++++++++++++------------- config/config.template.ini | 18 ++--- csv/fms.csv | 2 +- csv/poc.csv | 2 +- csv/zvei.csv | 2 +- includes/MyTimedRotatingFileHandler.py | 4 +- includes/alarmHandler.py | 6 +- includes/checkSubprocesses.py | 6 +- includes/converter.py | 6 +- includes/decoder.py | 22 ++--- includes/decoders/fms.py | 14 ++-- includes/decoders/poc.py | 22 ++--- includes/decoders/zvei.py | 10 +-- includes/descriptionList.py | 20 ++--- includes/doubleFilter.py | 20 ++--- includes/filter.py | 22 ++--- includes/globals.py | 2 +- includes/helper.py | 10 +-- includes/pluginLoader.py | 18 ++--- includes/shellHeader.py | 28 +++---- includes/signalHandler.py | 6 +- install.sh | 24 +++--- plugins/BosMon/BosMon.py | 34 ++++---- plugins/MySQL/MySQL.py | 32 ++++---- plugins/eMail/eMail.py | 28 +++---- plugins/firEmergency/firEmergency.py | 22 ++--- plugins/httpRequest/httpRequest.py | 30 +++---- plugins/interface.txt | 10 +-- plugins/jsonSocket/jsonSocket.py | 20 ++--- plugins/template/template.py | 18 ++--- serverExamples/jsonSocketServer.py | 30 +++---- service/README.md | 20 ++--- testdata/rt_fm errors.txt | 2 +- testdata/testdata.txt | 2 +- www/config.php | 2 +- www/index.php | 18 ++--- www/mysql.class.php | 40 +++++----- www/tpl/content.overview.php | 2 +- www/tpl/content.parser.php | 2 +- www/tpl/template.overview.php | 22 ++--- 41 files changed, 352 insertions(+), 353 deletions(-) diff --git a/LICENSE b/LICENSE index 8cdb8451..23cb7903 100644 --- a/LICENSE +++ b/LICENSE @@ -337,4 +337,3 @@ proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. - diff --git a/boswatch.py b/boswatch.py index e2071026..03ce8da9 100755 --- a/boswatch.py +++ b/boswatch.py @@ -8,7 +8,7 @@ For more information see the README.md @author: Bastian Schroll -@author: Jens Herrmann +@author: Jens Herrmann Thanks to smith_fms and McBo from Funkmeldesystem.de - Forum for Inspiration and Groundwork! @@ -25,20 +25,20 @@ import subprocess # for starting rtl_fm and multimon-ng from includes import globals # Global variables -from includes import MyTimedRotatingFileHandler # extension of TimedRotatingFileHandler +from includes import MyTimedRotatingFileHandler # extension of TimedRotatingFileHandler from includes import converter # converter functions from includes import signalHandler # TERM-Handler for use script as a daemon from includes import checkSubprocesses # check startup of the subprocesses - + # # ArgParser # Have to be before main program # -try: +try: # With -h or --help you get the Args help - parser = argparse.ArgumentParser(prog="boswatch.py", - description="BOSWatch is a Python Script to recive and decode german BOS information with rtl_fm and multimon-NG", + parser = argparse.ArgumentParser(prog="boswatch.py", + description="BOSWatch is a Python Script to recive and decode german BOS information with rtl_fm and multimon-NG", epilog="More options you can find in the extern config.ini file in the folder /config") # parser.add_argument("-c", "--channel", help="BOS Channel you want to listen") parser.add_argument("-f", "--freq", help="Frequency you want to listen", required=True) @@ -49,9 +49,9 @@ parser.add_argument("-u", "--usevarlog", help="Use '/var/log/boswatch' for logfiles instead of subdir 'log' in BOSWatch directory", action="store_true") parser.add_argument("-v", "--verbose", help="Shows more information", action="store_true") parser.add_argument("-q", "--quiet", help="Shows no information. Only logfiles", action="store_true") - # We need this argument for testing (skip instantiate of rtl-fm and multimon-ng): + # We need this argument for testing (skip instantiate of rtl-fm and multimon-ng): parser.add_argument("-t", "--test", help=argparse.SUPPRESS, action="store_true") - args = parser.parse_args() + args = parser.parse_args() except SystemExit: # -h or --help called, exit right now exit(0) @@ -60,7 +60,7 @@ print "ERROR: cannot parsing the arguments" exit(1) - + # # Main program # @@ -106,26 +106,26 @@ fh = MyTimedRotatingFileHandler.MyTimedRotatingFileHandler(globals.log_path+"boswatch.log", "midnight", interval=1, backupCount=999) # Starts with log level >= Debug # will be changed with config.ini-param later - fh.setLevel(logging.DEBUG) + fh.setLevel(logging.DEBUG) fh.setFormatter(formatter) myLogger.addHandler(fh) # create a display logger ch = logging.StreamHandler() # log level for display: Default: info if args.verbose: - ch.setLevel(logging.DEBUG) + ch.setLevel(logging.DEBUG) elif args.quiet: ch.setLevel(logging.CRITICAL) else: - ch.setLevel(logging.INFO) + ch.setLevel(logging.INFO) ch.setFormatter(formatter) - myLogger.addHandler(ch) - + myLogger.addHandler(ch) + except: # we couldn't work without logging -> exit print "ERROR: cannot create logger" exit(1) - + # initialization of the logging was fine, continue... try: # @@ -139,29 +139,29 @@ rtl_log.close() mon_log.close() logging.debug("BOSWatch has started") - logging.debug("Logfiles cleared") - + logging.debug("Logfiles cleared") + except: # It's an error, but we could work without that stuff... - logging.error("cannot clear Logfiles") + logging.error("cannot clear Logfiles") logging.debug("cannot clear Logfiles", exc_info=True) pass - + # # For debug display/log args # - try: + try: logging.debug("SW Version: %s",globals.getVers("vers")) logging.debug("Build Date: %s",globals.getVers("date")) logging.debug("BOSWatch given arguments") if args.test: logging.debug(" - Test-Mode!") - + logging.debug(" - Frequency: %s", converter.freqToHz(args.freq)) logging.debug(" - Device: %s", args.device) logging.debug(" - PPM Error: %s", args.error) logging.debug(" - Squelch: %s", args.squelch) - + demodulation = "" if "FMS" in args.demod: demodulation += "-a FMSFSK " @@ -174,18 +174,18 @@ logging.debug(" - Demod: POC512") if "POC1200" in args.demod: demodulation += "-a POCSAG1200 " - logging.debug(" - Demod: POC1200") + logging.debug(" - Demod: POC1200") if "POC2400" in args.demod: demodulation += "-a POCSAG2400 " logging.debug(" - Demod: POC2400") - + logging.debug(" - Use /var/log: %s", args.usevarlog) logging.debug(" - Verbose Mode: %s", args.verbose) logging.debug(" - Quiet Mode: %s", args.quiet) if not args.quiet: #only if not quiet mode from includes import shellHeader - shellHeader.printHeader(args) + shellHeader.printHeader(args) if args.test: logging.warning("!!! We are in Test-Mode !!!") @@ -204,7 +204,7 @@ globals.config = ConfigParser.ConfigParser() globals.config.read(globals.script_path+"/config/config.ini") # if given loglevel is debug: - if globals.config.getint("BOSWatch","loglevel") == 10: + if globals.config.getint("BOSWatch","loglevel") == 10: logging.debug(" - BOSWatch:") for key,val in globals.config.items("BOSWatch"): logging.debug(" -- %s = %s", key, val) @@ -225,8 +225,8 @@ # initialization was fine, continue with main program... try: - # - # Set the loglevel and backupCount of the file handler + # + # Set the loglevel and backupCount of the file handler # logging.debug("set loglevel of fileHandler to: %s",globals.config.getint("BOSWatch","loglevel")) fh.setLevel(globals.config.getint("BOSWatch","loglevel")) @@ -237,11 +237,11 @@ logging.error("cannot set loglevel of fileHandler") logging.debug("cannot set loglevel of fileHandler", exc_info=True) pass - + # # Load plugins # - try: + try: from includes import pluginLoader pluginLoader.loadPlugins() except: @@ -249,11 +249,11 @@ logging.critical("cannot load Plugins") logging.debug("cannot load Plugins", exc_info=True) exit(1) - + # # Load filters # - try: + try: if globals.config.getboolean("BOSWatch","useRegExFilter"): from includes import filter filter.loadFilters() @@ -262,11 +262,11 @@ logging.error("cannot load filters") logging.debug("cannot load filters", exc_info=True) pass - + # # Load description lists # - try: + try: if globals.config.getboolean("FMS","idDescribed") or globals.config.getboolean("ZVEI","idDescribed") or globals.config.getboolean("POC","idDescribed"): from includes import descriptionList descriptionList.loadDescriptionLists() @@ -275,11 +275,11 @@ logging.error("cannot load description lists") logging.debug("cannot load description lists", exc_info=True) pass - + # # Start rtl_fm # - try: + try: if not args.test: logging.debug("starting rtl_fm") command = "" @@ -317,7 +317,7 @@ stdin=rtl_fm.stdout, stdout=subprocess.PIPE, stderr=open(globals.log_path+"multimon.log","a"), - shell=False) + shell=False) # multimon-ng doesn't self-destruct, when an error occurs # wait a moment to give the subprocess a chance to write the logfile time.sleep(3) @@ -331,15 +331,15 @@ exit(1) # multimon-ng started, continue... - logging.debug("start decoding") + logging.debug("start decoding") # # Get decoded data from multimon-ng and call BOSWatch-decoder # - while True: + while True: if not args.test: decoded = str(multimon_ng.stdout.readline()) #Get line data from multimon stdout - + else: # Test-strings only for develop #decoded = "ZVEI2: 25832" @@ -349,13 +349,13 @@ #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 1=LST->FZG 2=III(mit NA,ohneSIGNAL)) CRC correct\n'" #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=IV (mit NA,mit SIGNAL)) CRC correct\n'" decoded = "POCSAG1200: Address: 1234567 Function: 1 Alpha: Hello World" - time.sleep(1) - + time.sleep(1) + from includes import decoder decoder.decode(converter.freqToHz(args.freq), decoded) - + except KeyboardInterrupt: - logging.warning("Keyboard Interrupt") + logging.warning("Keyboard Interrupt") except SystemExit: # SystemExitException is thrown if daemon was terminated logging.warning("SystemExit received") @@ -367,24 +367,24 @@ try: logging.debug("BOSWatch shuting down") if multimon_ng and multimon_ng.pid: - logging.debug("terminate multimon-ng (%s)", multimon_ng.pid) + logging.debug("terminate multimon-ng (%s)", multimon_ng.pid) multimon_ng.terminate() multimon_ng.wait() logging.debug("multimon-ng terminated") if rtl_fm and rtl_fm.pid: - logging.debug("terminate rtl_fm (%s)", rtl_fm.pid) + logging.debug("terminate rtl_fm (%s)", rtl_fm.pid) rtl_fm.terminate() rtl_fm.wait() - logging.debug("rtl_fm terminated") - logging.debug("exiting BOSWatch") + logging.debug("rtl_fm terminated") + logging.debug("exiting BOSWatch") except: - logging.warning("failed in clean-up routine") + logging.warning("failed in clean-up routine") logging.debug("failed in clean-up routine", exc_info=True) - - finally: + + finally: # Close Logging - logging.debug("close Logging") + logging.debug("close Logging") logging.info("BOSWatch exit()") logging.shutdown() fh.close() - ch.close() \ No newline at end of file + ch.close() diff --git a/config/config.template.ini b/config/config.template.ini index 57036a3f..0bfe0196 100644 --- a/config/config.template.ini +++ b/config/config.template.ini @@ -56,11 +56,11 @@ idDescribed = 0 # some very simple filters: # Allow only this RICs (empty: allow all, separator ",") # f.e.: allow_ric = 1234566,1234567,1234568 -allow_ric = +allow_ric = # Deny this RICs (empty: allow all, separator ",") # f.e.: deny_ric = 1234566,1234567,1234568 -deny_ric = +deny_ric = # start and end of an allowed filter range filter_range_start = 0000000 @@ -130,14 +130,14 @@ tablePOC = bos_pocsag # %TIME% = Time (by script) # %DATE% = Date (by script) #fms_url = www.google.de?code=%FMS%&stat=%STATUS% -fms_url = +fms_url = # %ZVEI% = ZVEI 5-tone Code # %DESCR% = Description from csv-file # %TIME% = Time (by script) # %DATE% = Date (by script) #zvei_url = www.google.de?zvei=%ZVEI% -zvei_url = +zvei_url = # %RIC% = Pocsag RIC # %FUNC% = Pocsac function/Subric (1-4) @@ -148,13 +148,13 @@ zvei_url = # %TIME% = Time (by script) # %DATE% = Date (by script) #poc_url = www.google.de?ric=%RIC%&subric=%FUNC%&msg=%MSG% -poc_url = +poc_url = [eMail] # SMTP-Server smtp_server = localhost -# Port of SMTP-Server (default: +# Port of SMTP-Server (default: smtp_port = # use tls for connection (0|1) tls = 0 @@ -211,8 +211,8 @@ bosmon_port = 80 bosmon_channel = channel # Use this, when BosMon has restricted access -bosmon_user = -bosmon_password = +bosmon_user = +bosmon_password = [firEmergency] @@ -234,4 +234,4 @@ port = 8888 [template] test1 = testString -test2 = 123456 \ No newline at end of file +test2 = 123456 diff --git a/csv/fms.csv b/csv/fms.csv index 6a9d021b..a9260fdf 100644 --- a/csv/fms.csv +++ b/csv/fms.csv @@ -7,4 +7,4 @@ fms,description # # !!! DO NOT delete the first line !!! # -12345678,"FMS testdata" \ No newline at end of file +12345678,"FMS testdata" diff --git a/csv/poc.csv b/csv/poc.csv index 4dc46346..44ddacbd 100644 --- a/csv/poc.csv +++ b/csv/poc.csv @@ -7,4 +7,4 @@ ric,description # # !!! DO NOT delete the first line !!! # -1234567,"POCSAG testdata" \ No newline at end of file +1234567,"POCSAG testdata" diff --git a/csv/zvei.csv b/csv/zvei.csv index 62f4c565..ebfc9e03 100644 --- a/csv/zvei.csv +++ b/csv/zvei.csv @@ -7,4 +7,4 @@ zvei,description # # !!! DO NOT delete the first line !!! # -12345,"ZVEI testdata" \ No newline at end of file +12345,"ZVEI testdata" diff --git a/includes/MyTimedRotatingFileHandler.py b/includes/MyTimedRotatingFileHandler.py index 23c0d0f3..bafd4a80 100644 --- a/includes/MyTimedRotatingFileHandler.py +++ b/includes/MyTimedRotatingFileHandler.py @@ -3,7 +3,7 @@ # """ -This Class extended the TimedRotatingFileHandler with the possibility +This Class extended the TimedRotatingFileHandler with the possibility to change the backupCount after initialization. @author: Jens Herrmann @@ -15,4 +15,4 @@ class MyTimedRotatingFileHandler(logging.handlers.TimedRotatingFileHandler): """Extended Version of TimedRotatingFileHandler""" def setBackupCount(self, backupCount): """Set/Change backupCount""" - self.backupCount = backupCount \ No newline at end of file + self.backupCount = backupCount diff --git a/includes/alarmHandler.py b/includes/alarmHandler.py index 8934b817..212593e0 100644 --- a/includes/alarmHandler.py +++ b/includes/alarmHandler.py @@ -30,7 +30,7 @@ def processAlarm(typ,freq,data): @param data: Contains the parameter @requires: active plugins in pluginList - + @return: nothing @exception: Exception if Alarm processing itself failed """ @@ -41,7 +41,7 @@ def processAlarm(typ,freq,data): # if enabled use RegEx-filter if globals.config.getint("BOSWatch","useRegExFilter"): from includes import filter - if filter.checkFilters(typ,data,pluginName,freq): + if filter.checkFilters(typ,data,pluginName,freq): logging.debug("call Plugin: %s", pluginName) try: plugin.run(typ,freq,data) @@ -59,4 +59,4 @@ def processAlarm(typ,freq,data): pass logging.debug("[END ALARM]") except: - logging.exception("Error in alarm processing") \ No newline at end of file + logging.exception("Error in alarm processing") diff --git a/includes/checkSubprocesses.py b/includes/checkSubprocesses.py index ba4080bf..f76e1ebd 100644 --- a/includes/checkSubprocesses.py +++ b/includes/checkSubprocesses.py @@ -5,7 +5,7 @@ Functions for checking the subprocesses rtl_fm and multimon-ng Used in boswatch.py at startup and designated for watching-service -@author: Jens Herrmann +@author: Jens Herrmann """ import logging @@ -32,7 +32,7 @@ def checkRTL(): logging.critical("cannot check rtl_fm.log") logging.debug("cannot check rtl_fm.log", exc_info=True) raise - + def checkMultimon(): """ check startup of multimon-ng @@ -51,4 +51,4 @@ def checkMultimon(): # we couldn't work without multimon-ng logging.critical("cannot check multimon.log") logging.debug("cannot check multimon.log", exc_info=True) - raise \ No newline at end of file + raise diff --git a/includes/converter.py b/includes/converter.py index 52ac28fe..b6625090 100644 --- a/includes/converter.py +++ b/includes/converter.py @@ -13,10 +13,10 @@ def freqToHz(freq): """ gets a frequency and resolve it in Hz - + @type freq: string @param freq: frequency of the SDR Stick - + @return: frequency in Hz @exception: Exception if Error by recalc """ @@ -26,4 +26,4 @@ def freqToHz(freq): # otherwise you will get the error: an invalid literal for int() with base 10 return int(float(freq)) except: - logging.exception("Error in freqToHz()") \ No newline at end of file + logging.exception("Error in freqToHz()") diff --git a/includes/decoder.py b/includes/decoder.py index addef2ef..62243142 100644 --- a/includes/decoder.py +++ b/includes/decoder.py @@ -19,31 +19,31 @@ def decode(freq, decoded): @param freq: frequency of the SDR Stick @type decoded: string @param decoded: RAW Information from Multimon-NG - + @return: nothing @exception: Exception if decoder file call failed """ try: - # FMS Decoder Section + # FMS Decoder Section # check FMS: -> check CRC -> validate -> check double alarm -> log - if "FMS:" in decoded: + if "FMS:" in decoded: logging.debug("recieved FMS") from includes.decoders import fms fms.decode(freq, decoded) - + # ZVEI Decoder Section - # check ZVEI: -> validate -> check double alarm -> log + # check ZVEI: -> validate -> check double alarm -> log elif "ZVEI2:" in decoded: - logging.debug("recieved ZVEI") + logging.debug("recieved ZVEI") from includes.decoders import zvei zvei.decode(freq, decoded) - + # POCSAG Decoder Section - # check POCSAG -> validate -> check double alarm -> log + # check POCSAG -> validate -> check double alarm -> log elif "POCSAG512:" in decoded or "POCSAG1200:" in decoded or "POCSAG2400:" in decoded: - logging.debug("recieved POCSAG") + logging.debug("recieved POCSAG") from includes.decoders import poc poc.decode(freq, decoded) - + except: - logging.exception("cannot start decoder") \ No newline at end of file + logging.exception("cannot start decoder") diff --git a/includes/decoders/fms.py b/includes/decoders/fms.py index 17c24532..e28be3ae 100644 --- a/includes/decoders/fms.py +++ b/includes/decoders/fms.py @@ -18,7 +18,7 @@ ## # # FMS decoder function -# validate -> check double alarm -> log +# validate -> check double alarm -> log # def decode(freq, decoded): """ @@ -30,7 +30,7 @@ def decode(freq, decoded): @param decoded: RAW Information from Multimon-NG @requires: Configuration has to be set in the config.ini - + @return: nothing @exception: Exception if FMS decode failed """ @@ -42,11 +42,11 @@ def decode(freq, decoded): fms_direction = decoded[101] # Richtung fms_directionText = decoded[103:110] # Richtung (Text) fms_tsi = decoded[114:117] # Taktische Kruzinformation - - if "CRC correct" in decoded: #check CRC is correct + + if "CRC correct" in decoded: #check CRC is correct fms_id = fms_service+fms_country+fms_location+fms_vehicle+fms_status+fms_direction # build FMS id # if FMS is valid - if re.search("[0-9a-f]{8}[0-9a-f]{1}[01]{1}", fms_id): + if re.search("[0-9a-f]{8}[0-9a-f]{1}[01]{1}", fms_id): # check for double alarm if doubleFilter.checkID("FMS", fms_id): logging.info("FMS:%s Status:%s Richtung:%s TSI:%s", fms_id[0:8], fms_status, fms_direction, fms_tsi) @@ -66,6 +66,6 @@ def decode(freq, decoded): # in every time save old data for double alarm doubleFilter.newEntry(fms_id) else: - logging.warning("No valid FMS: %s", fms_id) + logging.warning("No valid FMS: %s", fms_id) else: - logging.warning("FMS CRC incorrect") \ No newline at end of file + logging.warning("FMS CRC incorrect") diff --git a/includes/decoders/poc.py b/includes/decoders/poc.py index ee2e7bef..7462af5b 100644 --- a/includes/decoders/poc.py +++ b/includes/decoders/poc.py @@ -28,11 +28,11 @@ def isAllowed(poc_id): @param poc_id: POCSAG Ric @requires: Configuration has to be set in the config.ini - + @return: True if the Ric is allowed, other False @exception: none """ - # 1.) If allowed RICs is set, only they will path, + # 1.) If allowed RICs is set, only they will path, # If RIC is the right one return True, else False if globals.config.get("POC", "allow_ric"): if poc_id in globals.config.get("POC", "allow_ric"): @@ -55,7 +55,7 @@ def isAllowed(poc_id): return True ## -# +# # POCSAG decoder function # validate -> check double alarm -> log # @@ -69,38 +69,38 @@ def decode(freq, decoded): @param decoded: RAW Information from Multimon-NG @requires: Configuration has to be set in the config.ini - + @return: nothing @exception: Exception if POCSAG decode failed """ bitrate = 0 - + if "POCSAG512:" in decoded: bitrate = 512 poc_id = decoded[20:27].replace(" ", "").zfill(7) poc_sub = decoded[39].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") - + elif "POCSAG1200:" in decoded: bitrate = 1200 poc_id = decoded[21:28].replace(" ", "").zfill(7) poc_sub = decoded[40].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") - + elif "POCSAG2400:" in decoded: bitrate = 2400 poc_id = decoded[21:28].replace(" ", "").zfill(7) poc_sub = decoded[40].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") - + if bitrate is 0: logging.warning("POCSAG Bitrate not found") logging.debug(" - (%s)", decoded) else: logging.debug("POCSAG Bitrate: %s", bitrate) - + if "Alpha:" in decoded: #check if there is a text message poc_text = decoded.split('Alpha: ')[1].strip().rstrip('').strip() else: poc_text = "" - + if re.search("[0-9]{7}", poc_id): #if POC is valid if isAllowed(poc_id): # check for double alarm @@ -126,4 +126,4 @@ def decode(freq, decoded): else: logging.debug("POCSAG%s: %s is not allowed", bitrate, poc_id) else: - logging.warning("No valid POCSAG%s RIC: %s", bitrate, poc_id) \ No newline at end of file + logging.warning("No valid POCSAG%s RIC: %s", bitrate, poc_id) diff --git a/includes/decoders/zvei.py b/includes/decoders/zvei.py index 39afcbf0..70d61961 100644 --- a/includes/decoders/zvei.py +++ b/includes/decoders/zvei.py @@ -25,7 +25,7 @@ def removeF(zvei): @type zvei: string @param zvei: ZVEI Information - + @return: ZVEI without F @exception: none """ @@ -40,7 +40,7 @@ def removeF(zvei): ## # # ZVEI decoder function -# validate -> check double alarm -> log +# validate -> check double alarm -> log # def decode(freq, decoded): """ @@ -52,11 +52,11 @@ def decode(freq, decoded): @param decoded: RAW Information from Multimon-NG @requires: Configuration has to be set in the config.ini - + @return: nothing @exception: Exception if ZVEI decode failed """ - zvei_id = decoded[7:12] # ZVEI Code + zvei_id = decoded[7:12] # ZVEI Code zvei_id = removeF(zvei_id) # resolve F if re.search("[0-9]{5}", zvei_id): # if ZVEI is valid # check for double alarm @@ -78,4 +78,4 @@ def decode(freq, decoded): # in every time save old data for double alarm doubleFilter.newEntry(zvei_id) else: - logging.warning("No valid ZVEI: %s", zvei_id) \ No newline at end of file + logging.warning("No valid ZVEI: %s", zvei_id) diff --git a/includes/descriptionList.py b/includes/descriptionList.py index 7f57ad2d..80b7ea70 100644 --- a/includes/descriptionList.py +++ b/includes/descriptionList.py @@ -44,7 +44,7 @@ def loadCSV(typ, idField): raise return resultList; - + ## # # call this for loading the description lists @@ -62,7 +62,7 @@ def loadDescriptionLists(): if globals.config.getint("FMS", "idDescribed"): logging.debug("- load FMS description list") globals.fmsDescribtionList = loadCSV("fms", "fms") - + if globals.config.getint("ZVEI", "idDescribed"): logging.debug("- load ZVEI description list") globals.zveiDescribtionList = loadCSV("zvei", "zvei") @@ -70,17 +70,17 @@ def loadDescriptionLists(): if globals.config.getint("POC", "idDescribed"): logging.debug("- load pocsag description list") globals.ricDescribtionList = loadCSV("poc", "ric") - + except: logging.error("cannot load description lists") logging.debug("cannot load description lists", exc_info=True) pass - + ## # # public function for getting a description -# +# def getDescription(typ, id): """ Get description for id. @@ -98,17 +98,17 @@ def getDescription(typ, id): elif typ == "POC": resultStr = globals.ricDescribtionList[id] else: - logging.warning("Invalid Typ: %s", typ) - + logging.warning("Invalid Typ: %s", typ) + except KeyError: # will be thrown when there is no description for the id # -> nothing to do... pass - + except: logging.error("Error during look up description lists") logging.debug("Error during look up description lists", exc_info=True) pass - + logging.debug(" - result for %s: %s", id, resultStr) - return resultStr \ No newline at end of file + return resultStr diff --git a/includes/doubleFilter.py b/includes/doubleFilter.py index bd7186f5..710a7773 100644 --- a/includes/doubleFilter.py +++ b/includes/doubleFilter.py @@ -23,20 +23,20 @@ def checkID(typ, id, msg=""): """ check if id was called in the last x sec and n entries - + @requires: Configuration has to be set in the config.ini - + @return: True if check was OK @return: False if double was found """ - timestamp = int(time.time()) # Get Timestamp + timestamp = int(time.time()) # Get Timestamp for i in range(len(globals.doubleList)): (xID, xTimestamp, xMsg) = globals.doubleList[i] # given ID found? # return False if the first entry in double_ignore_time is found, we will not check for younger ones... if id == xID and timestamp < xTimestamp + globals.config.getint("BOSWatch", "doubleFilter_ignore_time"): - # if wanted, we have to check the msg additional + # if wanted, we have to check the msg additional if "POC" in typ and globals.config.getint("BOSWatch", "doubleFilter_check_msg"): # if msg is a substring of xMsg we found a double if msg in xMsg: @@ -46,20 +46,20 @@ def checkID(typ, id, msg=""): logging.info("%s double alarm (id): %s within %s second(s)", typ, xID, timestamp-xTimestamp) return False return True - + def newEntry(id, msg = ""): """ new entry in double alarm list - + @return: nothing """ - timestamp = int(time.time()) # Get Timestamp + timestamp = int(time.time()) # Get Timestamp globals.doubleList.append((id, timestamp, msg)) - + logging.debug("Added %s to doubleList", id) - + # now check if list has more than n entries: if len(globals.doubleList) > globals.config.getint("BOSWatch", "doubleFilter_ignore_entries"): # we have to kill the oldest one - globals.doubleList.pop(0) \ No newline at end of file + globals.doubleList.pop(0) diff --git a/includes/filter.py b/includes/filter.py index 4805f5cc..77712a43 100644 --- a/includes/filter.py +++ b/includes/filter.py @@ -23,7 +23,7 @@ def loadFilters(): load all filters from the config.ini into globals.filterList @requires: Configuration has to be set in the config.ini - + @return: nothing """ try: @@ -32,11 +32,11 @@ def loadFilters(): for key,val in globals.config.items("Filters"): logging.debug(" - %s = %s", key, val) filter = val.split(";") - + # resolve the * for freqToHz() if not filter[3] == "*": filter[3] = converter.freqToHz(filter[3]) - + # insert splitet data into globals.filterList globals.filterList.append({"name": key, "typ": filter[0], "dataField": filter[1], "plugin": filter[2], "freq": filter[3], "regex": filter[4]}) except: @@ -44,12 +44,12 @@ def loadFilters(): logging.debug("cannot read config file", exc_info=True) return - + def checkFilters(typ,data,plugin,freq): """ Check the Typ/Plugin combination with the RegEX filter If no filter for the combination is found, function returns True. - + @type typ: string (FMS|ZVEI|POC) @param typ: Typ of the dataset @type data: map of data (structure see interface.txt) @@ -58,14 +58,14 @@ def checkFilters(typ,data,plugin,freq): @param plugin: Name of the plugin to checked @type freq: string @param freq: frequency of the SDR Stick - + @requires: all filters in the filterList - + @return: nothing """ try: logging.debug("search Filter for %s to %s at %s Hz", typ, plugin, freq) - + foundFilter = False # go to all filter in globals.filterList for i in globals.filterList: @@ -79,16 +79,16 @@ def checkFilters(typ,data,plugin,freq): return True else: logging.debug("Filter not passed: %s", i["name"]) - + if foundFilter: logging.debug("no Filter passed") return False else: logging.debug("no Filter found") return True - + except: logging.error("Error in filter checking") logging.debug("Error in filter checking", exc_info=True) # something goes wrong, data will path - return True \ No newline at end of file + return True diff --git a/includes/globals.py b/includes/globals.py index 7eadb146..0774cb43 100644 --- a/includes/globals.py +++ b/includes/globals.py @@ -33,4 +33,4 @@ def getVers(mode="vers"): if mode == "vers": return "2.0-RC" elif mode == "date": - return " 2015/07/02" \ No newline at end of file + return " 2015/07/02" diff --git a/includes/helper.py b/includes/helper.py index d2d6f258..2c9b789e 100644 --- a/includes/helper.py +++ b/includes/helper.py @@ -17,15 +17,15 @@ def curtime(format="%d.%m.%Y %H:%M:%S"): """ Returns formated date and/or time see: https://docs.python.org/2/library/time.html#time.strftime - + @type format: string @param format: Python time Format-String - + @return: Formated Time and/or Date @exception: Exception if Error in format - """ + """ try: - return time.strftime(format) + return time.strftime(format) except: logging.warning("error in time-format-string") - logging.debug("error in time-format-string", exc_info=True) \ No newline at end of file + logging.debug("error in time-format-string", exc_info=True) diff --git a/includes/pluginLoader.py b/includes/pluginLoader.py index 45b811b7..9d40dc8c 100644 --- a/includes/pluginLoader.py +++ b/includes/pluginLoader.py @@ -34,7 +34,7 @@ def loadPlugins(): logging.debug("call %s.onLoad()", i["name"]) plugin.onLoad() # Add it to globals.pluginList - globals.pluginList[i["name"]] = plugin + globals.pluginList[i["name"]] = plugin except: # call next plugin, if one has thrown an exception logging.error("error calling %s.onLoad()", i["name"]) @@ -60,13 +60,13 @@ def getPlugins(): # Go to all Folders in the Plugin-Dir for i in os.listdir(PluginFolder): location = os.path.join(PluginFolder, i) - - # Skip if Path.isdir() or no File DIR_NAME.py is found + + # Skip if Path.isdir() or no File DIR_NAME.py is found if not os.path.isdir(location) or not i + ".py" in os.listdir(location): continue # is the plugin enabled in the config-file? - try: + try: if globals.config.getint("Plugins", i): info = imp.find_module(i, [location]) plugins.append({"name": i, "info": info}) @@ -74,8 +74,8 @@ def getPlugins(): else: logging.debug("Plugin [DISABLED] %s ", i) # no entry for plugin found in config-file - except NoOptionError: - logging.warning("Plugin [NO CONF ] %s", i) + except NoOptionError: + logging.warning("Plugin [NO CONF ] %s", i) pass except: logging.error("Error during Plugin search") @@ -91,8 +91,8 @@ def loadPlugin(plugin): @type plugin: Plugin Data @param plugin: Contains the information to import a Plugin - - + + @return: nothing @exception: Exception if Plugin import failed """ @@ -102,4 +102,4 @@ def loadPlugin(plugin): except: logging.error("cannot load Plugin: %s", plugin["name"]) logging.debug("cannot load Plugin: %s", plugin["name"], exc_info=True) - raise \ No newline at end of file + raise diff --git a/includes/shellHeader.py b/includes/shellHeader.py index b13d909a..6cf4a29d 100644 --- a/includes/shellHeader.py +++ b/includes/shellHeader.py @@ -18,18 +18,18 @@ def printHeader(args): @type args: Array @param args: All given arguments from argsparser - + @return: nothing """ try: - print " ____ ____ ______ __ __ __ " - print " / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ " - print " / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ " - print " / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / " - print " /_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ " - print " German BOS Information Script " - print " by Bastian Schroll, Jens Herrmann " - print "" + print " ____ ____ ______ __ __ __ " + print " / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ " + print " / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ " + print " / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / " + print " /_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ " + print " German BOS Information Script " + print " by Bastian Schroll, Jens Herrmann " + print "" print "SW Version: "+globals.getVers("vers") print "Build Date: "+globals.getVers("date") print "" @@ -41,19 +41,19 @@ def printHeader(args): if "FMS" in args.demod: print "- FMS" if "ZVEI" in args.demod: - print "- ZVEI" + print "- ZVEI" if "POC512" in args.demod: print "- POC512" if "POC1200" in args.demod: print "- POC1200" if "POC2400" in args.demod: - print "- POC2400" + print "- POC2400" print "Squelch: "+str(args.squelch) if args.verbose: - print "Verbose Mode!" + print "Verbose Mode!" if args.test: print "Test Mode!" - print "" + print "" except: logging.error("cannot display shell header") - logging.debug("cannot display shell header", exc_info=True) \ No newline at end of file + logging.debug("cannot display shell header", exc_info=True) diff --git a/includes/signalHandler.py b/includes/signalHandler.py index ce0ec542..7afb9787 100644 --- a/includes/signalHandler.py +++ b/includes/signalHandler.py @@ -4,7 +4,7 @@ """ TERM-Handler for use script as a daemon -In order for the Python program to exit gracefully when the TERM signal is received, +In order for the Python program to exit gracefully when the TERM signal is received, it must have a function that exits the program when signal.SIGTERM is received. @author: Jens Herrmann @@ -19,7 +19,7 @@ def sigterm_handler(_signo, _stack_frame): TERM-Handler for use script as a daemon @type _signo: signalnum - @param _signo: signal number + @param _signo: signal number @type _stack_frame: frame object @param _stack_frame: current stack frame @@ -29,4 +29,4 @@ def sigterm_handler(_signo, _stack_frame): sys.exit(0) # Set the handler for signal to the function handler. -signal.signal(signal.SIGTERM, sigterm_handler) \ No newline at end of file +signal.signal(signal.SIGTERM, sigterm_handler) diff --git a/install.sh b/install.sh index dbcac0b7..9ad0026c 100644 --- a/install.sh +++ b/install.sh @@ -1,20 +1,20 @@ #!/bin/sh tput clear tput civis -echo " ____ ____ ______ __ __ __ " -echo " / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ " -echo " / __ / / / /\__ \| | /| / / __ / __/ ___/ __ \ " -echo " / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / " -echo " /_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ " -echo " German BOS Information Script " -echo " by Bastian Schroll " +echo " ____ ____ ______ __ __ __ " +echo " / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ " +echo " / __ / / / /\__ \| | /| / / __ / __/ ___/ __ \ " +echo " / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / " +echo " /_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ " +echo " German BOS Information Script " +echo " by Bastian Schroll " echo "" echo "This may take a several minutes... Don't panic!" echo "" echo "Caution, script don't install a Webserver with PHP and MySQL" echo "So you have to make up manually if you want to use MySQL support" -mkdir -p ~/boswatch/install +mkdir -p ~/boswatch/install tput cup 13 15 echo "[ 1/10] [#---------]" @@ -32,7 +32,7 @@ tput cup 13 15 echo "[ 3/10] [###-------]" tput cup 15 5 echo "-> download rtl_fm......................" -cd ~/boswatch/install +cd ~/boswatch/install git clone git://git.osmocom.org/rtl-sdr.git >> ~/boswatch/install/setup_log.txt 2>&1 cd rtl-sdr/ @@ -50,7 +50,7 @@ tput cup 13 15 echo "[ 5/10] [#####-----]" tput cup 15 5 echo "-> download multimon-ng................" -cd ~/boswatch/install +cd ~/boswatch/install git clone https://github.com/EliasOenal/multimonNG.git >> ~/boswatch/install/setup_log.txt 2>&1 cd multimonNG/ @@ -68,7 +68,7 @@ tput cup 13 15 echo "[ 7/10] [#######---]" tput cup 15 5 echo "-> download MySQL Connector for Python." -cd ~/boswatch/install +cd ~/boswatch/install wget "http://dev.mysql.com/get/Downloads/Connector-Python/mysql-connector-python-1.0.9.tar.gz/from/http://cdn.mysql.com/" -O mysql-connector.tar >> ~/boswatch/install/setup_log.txt 2>&1 tar xfv mysql-connector.tar >> ~/boswatch/install/setup_log.txt 2>&1 cd mysql-connector-python* @@ -97,4 +97,4 @@ echo "# BOSWatch - blacklist the DVB drivers to avoid conflict with the SDR driv tput cup 17 1 echo "BOSWatch are now installed in ~/boswatch/" -echo "Install ready!" \ No newline at end of file +echo "Install ready!" diff --git a/plugins/BosMon/BosMon.py b/plugins/BosMon/BosMon.py index 40b54cbc..2072e7cd 100644 --- a/plugins/BosMon/BosMon.py +++ b/plugins/BosMon/BosMon.py @@ -30,7 +30,7 @@ def onLoad(): this onLoad() routine is called one time for initialize the plugin @requires: nothing - + @return: nothing """ # nothing to do for this plugin @@ -50,7 +50,7 @@ def bosMonRequest(httprequest, params, headers): @param params: Contains the parameter for transfer to BosMon. @type headers: map @param headers: The headers argument should be a mapping of extra HTTP headers to send with the request. - + @return: nothing @exception: Exception if HTTP-Request failed """ @@ -63,8 +63,8 @@ def bosMonRequest(httprequest, params, headers): logging.error("request to BosMon failed") logging.debug("request to BosMon failed", exc_info=True) raise - else: - # + else: + # # check HTTP-Response # httpresponse = httprequest.getresponse() @@ -82,7 +82,7 @@ def run(typ,freq,data): """ This function is the implementation of the BosMon-Plugin. It will send the data to an BosMon-Instance via http - + The configuration for the BosMon-Connection is set in the config.ini. If an user is set, the HTTP-Request is authenticatet. @@ -94,7 +94,7 @@ def run(typ,freq,data): @keyword freq: frequency is not used in this plugin @requires: BosMon-Configuration has to be set in the config.ini - + @return: nothing """ try: @@ -140,8 +140,8 @@ def run(typ,freq,data): logging.debug("Start FMS to BosMon") try: # BosMon-Telegramin expected assembly group, direction and tsi in one field - # structure (binary as hex in base10): - # Byte 1: assembly group; Byte 2: Direction; Byte 3+4: tactic short info + # structure (binary as hex in base10): + # Byte 1: assembly group; Byte 2: Direction; Byte 3+4: tactic short info info = 0 # assembly group: info = info + 1 # + b0001 (Assumption: is in every time 1 (no output from multimon-ng)) @@ -156,10 +156,10 @@ def run(typ,freq,data): elif "II" in data["tsi"]: info = info + 4 # + b0100 # "I" is nothing to do + b0000 - + params = urllib.urlencode({'type':'fms', 'address':data["fms"], 'status':data["status"], 'info':info, 'flags':'0'}) logging.debug(" - Params: %s", params) - # dispatch the BosMon-request + # dispatch the BosMon-request bosMonRequest(httprequest, params, headers) except: logging.error("FMS to BosMon failed") @@ -171,7 +171,7 @@ def run(typ,freq,data): try: params = urllib.urlencode({'type':'zvei', 'address':data["zvei"], 'flags':'0'}) logging.debug(" - Params: %s", params) - # dispatch the BosMon-request + # dispatch the BosMon-request bosMonRequest(httprequest, params, headers) except: logging.error("ZVEI to BosMon failed") @@ -184,24 +184,24 @@ def run(typ,freq,data): # BosMon-Telegramin expected "a-d" as RIC-sub/function params = urllib.urlencode({'type':'pocsag', 'address':data["ric"], 'flags':'0', 'function':data["functionChar"], 'message':data["msg"]}) logging.debug(" - Params: %s", params) - # dispatch the BosMon-request + # dispatch the BosMon-request bosMonRequest(httprequest, params, headers) except: logging.error("POC to BosMon failed") logging.debug("POC to BosMon failed", exc_info=True) return - + else: - logging.warning("Invalid Typ: %s", typ) + logging.warning("Invalid Typ: %s", typ) finally: logging.debug("close BosMon-Connection") - try: + try: httprequest.close() except: pass - except: + except: # something very mysterious logging.error("unknown error") - logging.debug("unknown error", exc_info=True) \ No newline at end of file + logging.debug("unknown error", exc_info=True) diff --git a/plugins/MySQL/MySQL.py b/plugins/MySQL/MySQL.py index bfaa144e..b545dced 100644 --- a/plugins/MySQL/MySQL.py +++ b/plugins/MySQL/MySQL.py @@ -29,12 +29,12 @@ def onLoad(): this onLoad() routine is called one time for initialize the plugin @requires: nothing - + @return: nothing """ # nothing to do for this plugin return - + ## # @@ -45,7 +45,7 @@ def run(typ,freq,data): """ This function is the implementation of the MySQL-Plugin. It will store the data to an MySQL database - + The configuration for the MySQL-Connection is set in the config.ini. For DB- and tablestructure see boswatch.sql @@ -58,7 +58,7 @@ def run(typ,freq,data): @requires: MySQL-Configuration has to be set in the config.ini @requires: Created Database/Tables, see boswatch.sql - + @return: nothing """ try: @@ -73,7 +73,7 @@ def run(typ,freq,data): logging.error("cannot read config file") logging.debug("cannot read config file", exc_info=True) else: # Without config, plugin couldn't work - + try: # # Connect to MySQL @@ -83,38 +83,38 @@ def run(typ,freq,data): cursor = connection.cursor() except: logging.error("cannot connect to MySQL") - logging.debug("cannot connect to MySQL", exc_info=True) + logging.debug("cannot connect to MySQL", exc_info=True) else: # Without connection, plugin couldn't work try: # # Create and execute SQL-statement # logging.debug("Insert %s", typ) - + if typ == "FMS": cursor.execute("INSERT INTO "+globals.config.get("MySQL","tableFMS")+" (time,fms,status,direction,directionText,tsi,description) VALUES (NOW(),%s,%s,%s,%s,%s,%s)",(data["fms"],data["status"],data["direction"],data["directionText"],data["tsi"],data["description"])) - + elif typ == "ZVEI": cursor.execute("INSERT INTO "+globals.config.get("MySQL","tableZVEI")+" (time,zvei,description) VALUES (NOW(),%s,%s)",(data["zvei"],data["description"])) - + elif typ == "POC": cursor.execute("INSERT INTO "+globals.config.get("MySQL","tablePOC")+" (time,ric,funktion,funktionChar,msg,bitrate,description) VALUES (NOW(),%s,%s,%s,%s,%s,%s)",(data["ric"],data["function"],data["functionChar"],data["msg"],data["bitrate"],data["description"])) - + else: - logging.warning("Invalid Typ: %s", typ) + logging.warning("Invalid Typ: %s", typ) except: logging.error("cannot Insert %s", typ) logging.debug("cannot Insert %s", typ, exc_info=True) return - + finally: logging.debug("close MySQL") - try: + try: cursor.close() - connection.close() #Close connection in every case + connection.close() #Close connection in every case except: pass - + except: logging.error("unknown error") - logging.debug("unknown error", exc_info=True) \ No newline at end of file + logging.debug("unknown error", exc_info=True) diff --git a/plugins/eMail/eMail.py b/plugins/eMail/eMail.py index af60e5a2..5c133697 100644 --- a/plugins/eMail/eMail.py +++ b/plugins/eMail/eMail.py @@ -31,7 +31,7 @@ def onLoad(): this onLoad() routine is called one time for initialize the plugin @requires: nothing - + @return: nothing """ # nothing to do for this plugin @@ -51,11 +51,11 @@ def doSendmail(server, subject, mailtext): @param subject: Subject for the eMail @type mailtext: string @param mailtext: Mailtext for the eMail - + @return: nothing @exception: Exception if smtp.sendmail failed """ - try: + try: msg = MIMEText(mailtext) msg['From'] = globals.config.get("eMail", "from") msg['To'] = globals.config.get("eMail", "to") @@ -79,7 +79,7 @@ def run(typ,freq,data): """ This function is the implementation of the eMail-Plugin. It will send the data via eMail (SMTP) - + The configuration for the eMail-Connection is set in the config.ini. If an user is set, the HTTP-Request is authenticatet. @@ -91,7 +91,7 @@ def run(typ,freq,data): @keyword freq: frequency of the SDR Stick @requires: eMail-Configuration has to be set in the config.ini - + @return: nothing """ try: @@ -102,7 +102,7 @@ def run(typ,freq,data): try: for key,val in globals.config.items("eMail"): logging.debug(" - %s = %s", key, val) - + except: logging.error("cannot read config file") logging.debug("cannot read config file", exc_info=True) @@ -115,15 +115,15 @@ def run(typ,freq,data): server = smtplib.SMTP(globals.config.get("eMail", "smtp_server"), globals.config.get("eMail", "smtp_port")) # debug-level to shell (0=no debug|1) server.set_debuglevel(0) - + # if tls is enabled, starttls if globals.config.get("eMail", "tls"): server.starttls() - + # if user is given, login if globals.config.get("eMail", "user"): server.login(globals.config.get("eMail", "user"), globals.config.get("eMail", "password")) - + except: logging.error("cannot connect to eMail") logging.debug("cannot connect to eMail", exc_info=True) @@ -199,18 +199,18 @@ def run(typ,freq,data): logging.error("%s to eMail failed", typ) logging.debug("%s to eMail failed", typ, exc_info=True) return - + else: - logging.warning("Invalid Typ: %s", typ) + logging.warning("Invalid Typ: %s", typ) finally: logging.debug("close eMail-Connection") - try: + try: server.quit() except: pass - + except: # something very mysterious logging.error("unknown error") - logging.debug("unknown error", exc_info=True) \ No newline at end of file + logging.debug("unknown error", exc_info=True) diff --git a/plugins/firEmergency/firEmergency.py b/plugins/firEmergency/firEmergency.py index 4d40f87c..a70d86e8 100644 --- a/plugins/firEmergency/firEmergency.py +++ b/plugins/firEmergency/firEmergency.py @@ -25,12 +25,12 @@ def onLoad(): this onLoad() routine is called one time for initialize the plugin @requires: nothing - + @return: nothing """ # nothing to do for this plugin return - + ## # @@ -41,7 +41,7 @@ def run(typ,freq,data): """ This function is the implementation of the firEmergency-Plugin. It will send the data to an firEmergency-Instance. - + The configuration for the firEmergency-Connection is set in the config.ini. @type typ: string (ZVEI|POC) @@ -52,7 +52,7 @@ def run(typ,freq,data): @keyword freq: frequency is not used in this plugin @requires: firEmergency-Configuration has to be set in the config.ini - + @return: nothing """ try: @@ -79,14 +79,14 @@ def run(typ,freq,data): logging.debug("cannot connect to firEmergency", exc_info=True) # Without connection, plugin couldn't work return - - else: + + else: # # Format given data-structure to xml-string for firEmergency # if typ == "FMS": logging.debug("FMS not supported by firEmgency") - + elif typ == "ZVEI": logging.debug("ZVEI to firEmergency") try: @@ -97,7 +97,7 @@ def run(typ,freq,data): logging.debug("%s to firEmergency failed", typ, exc_info=True) # Without connection, plugin couldn't work return - + elif typ == "POC": logging.debug("POC to firEmergency") try: @@ -110,15 +110,15 @@ def run(typ,freq,data): return else: - logging.warning("Invalid Typ: %s", typ) + logging.warning("Invalid Typ: %s", typ) finally: logging.debug("close firEmergency-Connection") - try: + try: firSocket.close() except: pass except: logging.error("unknown error") - logging.debug("unknown error", exc_info=True) \ No newline at end of file + logging.debug("unknown error", exc_info=True) diff --git a/plugins/httpRequest/httpRequest.py b/plugins/httpRequest/httpRequest.py index e2ceabc8..d92759c1 100644 --- a/plugins/httpRequest/httpRequest.py +++ b/plugins/httpRequest/httpRequest.py @@ -28,12 +28,12 @@ def onLoad(): this onLoad() routine is called one time for initialize the plugin @requires: nothing - + @return: nothing """ # nothing to do for this plugin return - + ## # @@ -53,7 +53,7 @@ def run(typ,freq,data): @keyword freq: frequency of the SDR Stick @requires: httpRequest-Configuration has to be set in the config.ini - + @return: nothing """ try: @@ -68,13 +68,13 @@ def run(typ,freq,data): logging.error("cannot read config file") logging.debug("cannot read config file", exc_info=True) else: # Without config, plugin couldn't work - + try: # # Create URL # logging.debug("send %s HTTP request", typ) - + if typ == "FMS": url = globals.config.get("httpRequest", "fms_url") #Get URL url = url.replace("%FMS%", data["fms"]).replace("%STATUS%", data["status"]) #replace Wildcards @@ -89,29 +89,29 @@ def run(typ,freq,data): url = url.replace("%FUNC%", data["function"]).replace("%FUNCCHAR%", data["functionChar"]) #replace Wildcards url = url.replace("%MSG%", data["msg"]).replace("%BITRATE%", str(data["bitrate"])) #replace Wildcards else: - logging.warning("Invalid Typ: %s", typ) + logging.warning("Invalid Typ: %s", typ) return - + #same in all types url = url.replace("%DESCR%", data["description"]) # replace Wildcards url = url.replace("%TIME%", helper.curtime("%H:%M:%S")) # replace Wildcards url = url.replace("%DATE%", helper.curtime("%d.%m.%Y")) # replace Wildcards - + # # HTTP-Request # url = urlparse(url) #split URL into path and querry httprequest = httplib.HTTPConnection(url[2]) #connect to URL Path httprequest.request("GET", url[5]) #send URL Querry per GET - + except: logging.error("cannot send HTTP request") logging.debug("cannot send HTTP request", exc_info=True) return - + else: try: - # + # # check HTTP-Response # httpresponse = httprequest.getresponse() @@ -123,14 +123,14 @@ def run(typ,freq,data): logging.error("cannot get HTTP response") logging.debug("cannot get HTTP response", exc_info=True) return - + finally: logging.debug("close HTTP-Connection") - try: + try: httprequest.close() except: pass - + except: logging.error("unknown error") - logging.debug("unknown error", exc_info=True) \ No newline at end of file + logging.debug("unknown error", exc_info=True) diff --git a/plugins/interface.txt b/plugins/interface.txt index 264d4901..d7886283 100644 --- a/plugins/interface.txt +++ b/plugins/interface.txt @@ -52,16 +52,16 @@ def onLoad(): this onLoad() routine is called one time for initialize the plugin @requires: nothing - + @return: nothing @exception: Exception if init has an fatal error so that the plugin couldn't work - + """ def run(typ,freq,data): """ This function is the implementation of the Plugin. - + If necessary the configuration hast to be set in the config.ini. @type typ: string (FMS|ZVEI|POC) @@ -72,7 +72,7 @@ def run(typ,freq,data): @keyword freq: frequency of the SDR Stick @requires: If necessary the configuration hast to be set in the config.ini. - + @return: nothing @exception: nothing, make sure this function will never thrown an exception """ @@ -83,4 +83,4 @@ Global Functions for plugins: from includes import helper #Global helper functions -helper.curtime("FORMAT") \ No newline at end of file +helper.curtime("FORMAT") diff --git a/plugins/jsonSocket/jsonSocket.py b/plugins/jsonSocket/jsonSocket.py index 01afeb26..1445aa9f 100644 --- a/plugins/jsonSocket/jsonSocket.py +++ b/plugins/jsonSocket/jsonSocket.py @@ -27,12 +27,12 @@ def onLoad(): this onLoad() routine is called one time for initialize the plugin @requires: nothing - + @return: nothing """ # nothing to do for this plugin return - + ## # @@ -43,7 +43,7 @@ def run(typ,freq,data): """ This function is the implementation of the jsonSocket-Plugin. It will send the data via UDP/TCP - + The configuration for the Connection is set in the config.ini. @type typ: string (FMS|ZVEI|POC) @@ -54,7 +54,7 @@ def run(typ,freq,data): @keyword freq: frequency of the SDR Stick @requires: jsonSocket-Configuration has to be set in the config.ini - + @return: nothing """ try: @@ -65,7 +65,7 @@ def run(typ,freq,data): try: for key,val in globals.config.items("jsonSocket"): logging.debug(" - %s = %s", key, val) - + except: logging.error("cannot read config file") logging.debug("cannot read config file", exc_info=True) @@ -82,7 +82,7 @@ def run(typ,freq,data): sock.connect((globals.config.get("jsonSocket", "server"), globals.config.getint("jsonSocket", "port"))) else: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - + except: logging.error("cannot initialize %s-socket", globals.config.get("jsonSocket", "protocol")) logging.debug("cannot initialize %s-socket", globals.config.get("jsonSocket", "protocol"), exc_info=True) @@ -105,16 +105,16 @@ def run(typ,freq,data): return else: - logging.warning("Invalid Typ: %s", typ) + logging.warning("Invalid Typ: %s", typ) finally: logging.debug("close %s-Connection", globals.config.get("jsonSocket", "protocol")) - try: + try: sock.close() except: pass - + except: # something very mysterious logging.error("unknown error") - logging.debug("unknown error", exc_info=True) \ No newline at end of file + logging.debug("unknown error", exc_info=True) diff --git a/plugins/template/template.py b/plugins/template/template.py index dfe104a5..68581bcd 100644 --- a/plugins/template/template.py +++ b/plugins/template/template.py @@ -36,10 +36,10 @@ def onLoad(): this onLoad() routine is called one time for initialize the plugin @requires: nothing - + @return: nothing @exception: Exception if init has an fatal error so that the plugin couldn't work - + """ try: ########## User onLoad CODE ########## @@ -58,7 +58,7 @@ def onLoad(): def run(typ,freq,data): """ This function is the implementation of the Plugin. - + If necessary the configuration hast to be set in the config.ini. @type typ: string (FMS|ZVEI|POC) @@ -69,7 +69,7 @@ def run(typ,freq,data): @keyword freq: frequency of the SDR Stick @requires: If necessary the configuration hast to be set in the config.ini. - + @return: nothing @exception: nothing, make sure this function will never thrown an exception """ @@ -85,8 +85,8 @@ def run(typ,freq,data): logging.error("cannot read config file") logging.debug("cannot read config file", exc_info=True) else: # Without config, plugin couldn't work - - ########## User Plugin CODE ########## + + ########## User Plugin CODE ########## if typ == "FMS": logging.warning("%s not supported", typ) elif typ == "ZVEI": @@ -94,9 +94,9 @@ def run(typ,freq,data): elif typ == "POC": logging.warning("%s not supported", typ) else: - logging.warning("Invalid Typ: %s", typ) + logging.warning("Invalid Typ: %s", typ) ########## User Plugin CODE ########## - + except: logging.error("unknown error") - logging.debug("unknown error", exc_info=True) \ No newline at end of file + logging.debug("unknown error", exc_info=True) diff --git a/serverExamples/jsonSocketServer.py b/serverExamples/jsonSocketServer.py index 6e59bfa1..d659dd0d 100644 --- a/serverExamples/jsonSocketServer.py +++ b/serverExamples/jsonSocketServer.py @@ -16,7 +16,7 @@ - siren will run with the pack - press Pibrella button to stop alarm and reset the LEDs -@author: Jens Herrmann +@author: Jens Herrmann BOSWatch: https://github.com/Schrolli91/BOSWatch Pibrella: https://github.com/pimoroni/pibrella @@ -39,7 +39,7 @@ # # Eventhandler for button # will stop the alarm and reset the LEDs -# +# def button_pressed(pin): global siren_stopped import pibrella @@ -75,15 +75,15 @@ def siren(): # # Main Program # -try: +try: # Logging myLogger = logging.getLogger() myLogger.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s [%(levelname)-8s] %(message)s', '%d.%m.%Y %H:%M:%S') ch = logging.StreamHandler() - ch.setLevel(logging.DEBUG) + ch.setLevel(logging.DEBUG) ch.setFormatter(formatter) - myLogger.addHandler(ch) + myLogger.addHandler(ch) # Start TCP socket: logging.debug("Start jsonSocketServer") @@ -91,7 +91,7 @@ def siren(): sock.bind((IP,PORT)) sock.listen(2) logging.info("jsonSocketServer runs") - pibrella.light.green.on() + pibrella.light.green.on() # our Alarm-RICs: ric_alarm = [12345677, 12345676, 12345675] @@ -116,7 +116,7 @@ def siren(): if parsed_json['ric'] == "1234567": logging.debug("POCSAG is alive") pibrella.light.green.blink(1, 1) - + elif int(parsed_json['ric']) in ric_alarm: logging.debug("We have do to something") if parsed_json['functionChar'] == "a": @@ -127,22 +127,22 @@ def siren(): pibrella.light.red.blink(1, 1) # change variable to False to start the siren siren_stopped = False - + except KeyboardInterrupt: - logging.warning("Keyboard Interrupt") + logging.warning("Keyboard Interrupt") except: logging.exception("unknown error") finally: try: logging.debug("socketServer shuting down") sock.close() - logging.debug("socket closed") - logging.debug("exiting socketServer") + logging.debug("socket closed") + logging.debug("exiting socketServer") except: - logging.warning("failed in clean-up routine") - finally: - logging.debug("close Logging") + logging.warning("failed in clean-up routine") + finally: + logging.debug("close Logging") logging.info("socketServer exit()") logging.shutdown() ch.close() - exit(0) \ No newline at end of file + exit(0) diff --git a/service/README.md b/service/README.md index 82e898a8..c5c8cacb 100644 --- a/service/README.md +++ b/service/README.md @@ -2,8 +2,8 @@ ##### Changing the init script -Lines 14 and 15 define where to find the Python script. -In this case the script expects that there is a folder `/usr/local/bin/BOSWatch` and that the script is inside there. +Lines 14 and 15 define where to find the Python script. +In this case the script expects that there is a folder `/usr/local/bin/BOSWatch` and that the script is inside there. Line 23 sets what user to run the script as. Using a root-user is necessary for BOSWatch. @@ -14,15 +14,15 @@ We recommend to use "-u" and "-q" when you want to run BOSWatch as a daemon. ##### Using the init script -To actually use this script, put BOSWatch where you want (recommend `/usr/local/bin/BOSWatch`) +To actually use this script, put BOSWatch where you want (recommend `/usr/local/bin/BOSWatch`) and make sure it is executable (e.g. `sudo chmod 755 boswatch.py`). -Edit the init script accordingly. Copy it into /etc/init.d using e.g. `sudo cp boswatch.sh /etc/init.d`. -Make sure the script is executable (chmod again) and make sure that it has UNIX line-endings. +Edit the init script accordingly. Copy it into /etc/init.d using e.g. `sudo cp boswatch.sh /etc/init.d`. +Make sure the script is executable (chmod again) and make sure that it has UNIX line-endings. -At this point you should be able to start BOSWatchcd ~/srt using the command `sudo /etc/init.d/boswatch.sh start`, +At this point you should be able to start BOSWatchcd ~/srt using the command `sudo /etc/init.d/boswatch.sh start`, check its status with the `sudo /etc/init.d/boswatch.sh status` argument and stop it with `sudo /etc/init.d/boswatch.sh stop`. -To make the Raspberry Pi use your init script at the right time, one more step is required: -Running the command `sudo update-rc.d boswatch.sh defaults`. -This command adds in symbolic links to the /etc/rc.x directories so that the init script is run at the default times. -You can see these links if you do `ls -l /etc/rc?.d/*boswatch.sh` \ No newline at end of file +To make the Raspberry Pi use your init script at the right time, one more step is required: +Running the command `sudo update-rc.d boswatch.sh defaults`. +This command adds in symbolic links to the /etc/rc.x directories so that the init script is run at the default times. +You can see these links if you do `ls -l /etc/rc?.d/*boswatch.sh` diff --git a/testdata/rt_fm errors.txt b/testdata/rt_fm errors.txt index 582a19b2..3b3705e4 100644 --- a/testdata/rt_fm errors.txt +++ b/testdata/rt_fm errors.txt @@ -4,4 +4,4 @@ fprintf(stderr, "Signal caught, exiting!\n"); fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dongle.dev_index); fprintf(stderr, "Failed to open %s\n", output.filename); fprintf(stderr, "\nUser cancel, exiting...\n"); -fprintf(stderr, "\nLibrary error %d, exiting...\n", r); \ No newline at end of file +fprintf(stderr, "\nLibrary error %d, exiting...\n", r); diff --git a/testdata/testdata.txt b/testdata/testdata.txt index 543f721e..b8246147 100644 --- a/testdata/testdata.txt +++ b/testdata/testdata.txt @@ -37,4 +37,4 @@ ZVEI2: 1F2F3 ZVEI2: 135 #in case of a double-tone for siren n-'D's are sended ZVEI2: DDD -ZVEI2: DDDDD \ No newline at end of file +ZVEI2: DDDDD diff --git a/www/config.php b/www/config.php index e78cee22..5136c406 100644 --- a/www/config.php +++ b/www/config.php @@ -9,4 +9,4 @@ $tableZVEI = "bos_zvei"; $tablePOC = "bos_pocsag"; -?> \ No newline at end of file +?> diff --git a/www/index.php b/www/index.php index e7146ecf..aeaa785e 100644 --- a/www/index.php +++ b/www/index.php @@ -17,12 +17,12 @@
- BOSWatch
- [Übersicht] - [Parser] - -

+ BOSWatch
+ [�bersicht] - [Parser] + +

+ + ?>
- + - \ No newline at end of file + diff --git a/www/mysql.class.php b/www/mysql.class.php index 9343fdde..69d5fbdb 100644 --- a/www/mysql.class.php +++ b/www/mysql.class.php @@ -10,9 +10,9 @@ /** * Database::__construct() - * + * * Stellt eine Verbung mit der MySQL Datenbank fest - * + * * @param mixed $host Hostname des Datenbank Server * @param mixed $user Username des Datenbank Nutzers * @param mixed $password Passwort des Datenbank Nutzers @@ -40,10 +40,10 @@ function __construct($host, $user, $password, $database, $show_error = 1) /** * Database::query() - * - * Führt einen MySQL Query aus - * - * @param mixed $query Auszuführender Query + * + * F�hrt einen MySQL Query aus + * + * @param mixed $query Auszuf�hrender Query * @return Result-Handler/FALSE */ function query($query) @@ -59,11 +59,11 @@ function query($query) /** * Database::fetchAssoc() - * - * Liefert alle gefundnen Datensätze als Assoc - * + * + * Liefert alle gefundnen Datens�tze als Assoc + * * @param mixed $result Externer Result-Handler - * @return gefundene Datensätze als Assoc + * @return gefundene Datens�tze als Assoc */ function fetchAssoc($result = null) { @@ -78,11 +78,11 @@ function fetchAssoc($result = null) /** * Database::count() - * - * Zählt alle gefundenen Datensätze - * + * + * Z�hlt alle gefundenen Datens�tze + * * @param mixed $result Externer Result-Handler - * @return Anzahl gefundener Datensätze + * @return Anzahl gefundener Datens�tze */ function count($result = null) { @@ -97,9 +97,9 @@ function count($result = null) /** * Database::closeConnection() - * - * Schließt die bestehende MySQL Verbindung - * + * + * Schlie�t die bestehende MySQL Verbindung + * * @return TRUE/FALSE */ function closeConnection() @@ -114,9 +114,9 @@ function closeConnection() /** * Database::error() - * + * * Gibt eine Interne Fehlermeldung aus - * + * * @param mixed $error_msg Text der Fehlermeldung * @param mixed $sql_err MySQL Fehlermeldung per mysql_error() * @return NULL @@ -131,4 +131,4 @@ private function error($error_msg, $sql_err) } } -} ?> \ No newline at end of file +} ?> diff --git a/www/tpl/content.overview.php b/www/tpl/content.overview.php index 8f4f7f6f..dd094042 100644 --- a/www/tpl/content.overview.php +++ b/www/tpl/content.overview.php @@ -7,7 +7,7 @@ $Rows[] = $daten; } $tpl['fms'] = $Rows; - + //read ZVEI $db->query("SELECT id, time, zvei FROM ".$tableZVEI." ORDER BY id DESC LIMIT 50"); $Rows = array(); diff --git a/www/tpl/content.parser.php b/www/tpl/content.parser.php index 15c5adc7..62a2de0c 100644 --- a/www/tpl/content.parser.php +++ b/www/tpl/content.parser.php @@ -1,3 +1,3 @@ \ No newline at end of file +?> diff --git a/www/tpl/template.overview.php b/www/tpl/template.overview.php index 6fd6e2ae..fa4e3e6b 100644 --- a/www/tpl/template.overview.php +++ b/www/tpl/template.overview.php @@ -1,5 +1,5 @@ Last alarms for FMS and ZVEI (max. 50)

- +
Last FMS alarms @@ -11,13 +11,13 @@ - "; echo ""; echo ""; @@ -39,13 +39,13 @@ - "; echo ""; echo ""; @@ -57,7 +57,7 @@ ?>
Richt. TKI
". $fms['id'] . "". $time . "Funktion Text
". $poc['id'] . "". $time . "
- +
Last ZVEI alarms @@ -66,13 +66,13 @@ - "; echo ""; echo ""; From 4b5bd9073f2fe7cf28011dc7cd54cf19eda58a14 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 2 Jul 2015 10:06:40 +0200 Subject: [PATCH 57/98] edit readme.md and interface.txt --- README.md | 22 +++++++++++++++++----- plugins/interface.txt | 3 ++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e19f2519..53e6d040 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,12 @@ unless you are developer you can use the develop-Branch - may be unstable! ##### Features for the future: - more plugins +- other Ideas per Issues please ###Plugins +If you want to code your own Plugin, see Section `Code your own Plugin` at the end of this readme.MD + ##### Implemented plugins: - MySQL (insert data into MySQL database [FMS|ZVEI|POC]) - httpRequest (send a request with parameter to an URL [FMS|ZVEI|POC]) @@ -57,6 +60,7 @@ For the other functions see "Usage" below. ##### Filtering Functions (RegEX) For the RegEX filter functions see Section `[Filters]` http://www.regexr.com/ - RegEX test tool an documentation + No filter for a combination typ/plugin = all data will pass Syntax: `INDIVIDUAL_NAME = TYP;DATAFIELD;PLUGIN;FREQUENZ;REGEX` (separator `;`) @@ -67,15 +71,17 @@ Syntax: `INDIVIDUAL_NAME = TYP;DATAFIELD;PLUGIN;FREQUENZ;REGEX` (separator `;`) - `REGEX` = the RegEX only ZVEI to all plugins with 25### at 85.5MHz -testfilter = ZVEI;zvei;*;85500000;25[0-9]{3} +`testfilter = ZVEI;zvei;*;85500000;25[0-9]{3}` only POCSAG to MySQL with the text "ALARM:" in the message -pocTest = POC;msg;MySQL;*;ALARM: +`pocTest = POC;msg;MySQL;*;ALARM:` + +##### Web frontend (obsolete) +New version in future - old data in folder `/www/` -##### Web frontend -Put the files in folder /wwww/ into your local webserver folder (f.e. /var/www/). +~~Put the files in folder /wwww/ into your local webserver folder (f.e. /var/www/). Now you must edit the "config.php" with your userdata to your local database. -Take a look into the parser.php for the parsing functions +Take a look into the parser.php for the parsing functions~~ ### Usage @@ -132,3 +138,9 @@ For configuration-details see `service/README.md`. - MySQL Connector for Python (for MySQL-plugin) Thanks to smith_fms and McBo from Funkmeldesystem.de - Forum for Inspiration and Groundwork! + + +### Code your own Plugin +To code your own Plugin look at the litte example `/plugins/template/template.py` + +In the text-file `plugins/interface.txt` are all relevant data, that your plugin can use. diff --git a/plugins/interface.txt b/plugins/interface.txt index d7886283..e6396047 100644 --- a/plugins/interface.txt +++ b/plugins/interface.txt @@ -82,5 +82,6 @@ Global Functions for plugins: ----------------------------- from includes import helper #Global helper functions - +#for format see https://docs.python.org/2/library/time.html#time.strftime +#without format string the function returns with: %d.%m.%Y %H:%M:%S helper.curtime("FORMAT") From 735a20d0704fd966f1ba8dadf3ccc3d6f5687cb1 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 2 Jul 2015 10:23:55 +0200 Subject: [PATCH 58/98] insert table in readme.md at plugin section --- README.md | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 53e6d040..3ef4321a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![# BOSWatch](/www/gfx/logo.png) -Python Script to receive and decode German BOS Information with rtl_fm and multimon-NG +:satellite: Python Script to receive and decode German BOS Information with rtl_fm and multimon-NG :satellite: #### Notice: The intercept of the German BOS radio is **strictly prohibited** and will be prosecuted. the use is **only authorized** personnel permitted. @@ -34,12 +34,15 @@ unless you are developer you can use the develop-Branch - may be unstable! If you want to code your own Plugin, see Section `Code your own Plugin` at the end of this readme.MD ##### Implemented plugins: -- MySQL (insert data into MySQL database [FMS|ZVEI|POC]) -- httpRequest (send a request with parameter to an URL [FMS|ZVEI|POC]) -- eMail (send Mails [FMS|ZVEI|POC]) -- BosMon (send data to BosMon server [FMS|ZVEI|POC]) -- firEmergency (send data to firEmergency server [ZVEI|POC]) -- jsonSocket (send data as jsonString to a socket server [FMS|ZVEI|POC]) + +|Plugin|Function|FMS|ZVEI|POC| +|-----|---------|:-:|:--:|:-:| +|MySQL|insert data into MySQL database|:thumbsup:|:thumbsup:|:thumbsup:| +|httpRequest|send a request with parameter to an URL|:thumbsup:|:thumbsup:|:thumbsup:| +|eMail|send Mails with own text|:thumbsup:|:thumbsup:|:thumbsup:| +|BosMon|send data to BosMon server|:thumbsup:|:thumbsup:|:thumbsup:| +|firEmergency|send data to firEmergency server|:thumbsup:|:x:|:thumbsup:| +|jsonSocket|send data as jsonString to a socket server|:thumbsup:|:thumbsup:|:thumbsup:| - for more Information to the plugins see `config.ini` @@ -64,11 +67,11 @@ http://www.regexr.com/ - RegEX test tool an documentation No filter for a combination typ/plugin = all data will pass Syntax: `INDIVIDUAL_NAME = TYP;DATAFIELD;PLUGIN;FREQUENZ;REGEX` (separator `;`) -- `TYP` = the data typ (FMS|ZVEI|POC) -- `DATAFIELD` = the field of the data array (See interface.txt) -- `PLUGIN` = the name of the plugin to call with this filter (* for all) -- `FREQUENZ` = the frequenz to use the filter (for more SDR sticks (* for all)) -- `REGEX` = the RegEX +- `TYP` = the data typ (FMS|ZVEI|POC) +- `DATAFIELD` = the field of the data array (See interface.txt) +- `PLUGIN` = the name of the plugin to call with this filter (* for all) +- `FREQUENZ` = the frequenz to use the filter (for more SDR sticks (* for all)) +- `REGEX` = the RegEX only ZVEI to all plugins with 25### at 85.5MHz `testfilter = ZVEI;zvei;*;85500000;25[0-9]{3}` From f124c4fca5dc841c1fc90e530de0aac4b0254f21 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 2 Jul 2015 10:27:34 +0200 Subject: [PATCH 59/98] mistake at firEmergency support info --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ef4321a..69ec78dc 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ If you want to code your own Plugin, see Section `Code your own Plugin` at the e |httpRequest|send a request with parameter to an URL|:thumbsup:|:thumbsup:|:thumbsup:| |eMail|send Mails with own text|:thumbsup:|:thumbsup:|:thumbsup:| |BosMon|send data to BosMon server|:thumbsup:|:thumbsup:|:thumbsup:| -|firEmergency|send data to firEmergency server|:thumbsup:|:x:|:thumbsup:| +|firEmergency|send data to firEmergency server|:x:|:thumbsup:|:thumbsup:| |jsonSocket|send data as jsonString to a socket server|:thumbsup:|:thumbsup:|:thumbsup:| - for more Information to the plugins see `config.ini` From c94ddfce3188d3c1f308871656e3098b10937e4e Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 2 Jul 2015 11:51:28 +0200 Subject: [PATCH 60/98] add helper.replaceWildcards() to helper.py --- README.md | 12 ++++++------ includes/helper.py | 46 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 69ec78dc..1e8bd6ac 100644 --- a/README.md +++ b/README.md @@ -37,12 +37,12 @@ If you want to code your own Plugin, see Section `Code your own Plugin` at the e |Plugin|Function|FMS|ZVEI|POC| |-----|---------|:-:|:--:|:-:| -|MySQL|insert data into MySQL database|:thumbsup:|:thumbsup:|:thumbsup:| -|httpRequest|send a request with parameter to an URL|:thumbsup:|:thumbsup:|:thumbsup:| -|eMail|send Mails with own text|:thumbsup:|:thumbsup:|:thumbsup:| -|BosMon|send data to BosMon server|:thumbsup:|:thumbsup:|:thumbsup:| -|firEmergency|send data to firEmergency server|:x:|:thumbsup:|:thumbsup:| -|jsonSocket|send data as jsonString to a socket server|:thumbsup:|:thumbsup:|:thumbsup:| +|MySQL|insert data into MySQL database|:white_check_mark:|:white_check_mark:|:white_check_mark:| +|httpRequest|send a request with parameter to an URL|:white_check_mark:|:white_check_mark:|:white_check_mark:| +|eMail|send Mails with own text|:white_check_mark:|:white_check_mark:|:white_check_mark:| +|BosMon|send data to BosMon server|:white_check_mark:|:white_check_mark:|:white_check_mark:| +|firEmergency|send data to firEmergency server|:x:|:white_check_mark:|:white_check_mark:| +|jsonSocket|send data as jsonString to a socket server|:white_check_mark:|:white_check_mark:|:white_check_mark:| - for more Information to the plugins see `config.ini` diff --git a/includes/helper.py b/includes/helper.py index 2c9b789e..2b549e2e 100644 --- a/includes/helper.py +++ b/includes/helper.py @@ -4,12 +4,13 @@ """ little Helper functions -mainly for direct usw in plugins to save code +mainly for direct use in plugins to save code @author: Bastian Schroll """ import logging + import time @@ -29,3 +30,46 @@ def curtime(format="%d.%m.%Y %H:%M:%S"): except: logging.warning("error in time-format-string") logging.debug("error in time-format-string", exc_info=True) + + +def replaceWildcards(text,data): + """ + Replace all official Wildcards with the Information from the data[] var + + @type text: string + @param text: Input text with wildcards + @type data: map + @param data: map of data (structure see interface.txt) + + @return: text with replaced wildcards + @exception: Exception if Error at replace + """ + try: + # replace date and time wildcards + text = text.replace("%TIME%", curtime("%H:%M:%S")).replace("%DATE%", curtime("%d.%m.%Y")) + + # replace FMS data + if "fms" in data: text = text.replace("%FMS%", data["fms"]) + if "status" in data: text = text.replace("%STATUS%", data["status"]) + if "direction" in data: text = text.replace("%DIR%", data["direction"]) + if "directionText" in data: text = text.replace("%DIRT%", data["directionText"]) + if "tsi" in data: text = text.replace("%TSI%", data["tsi"]) + + # replace ZVEI data + if "zvei" in data: text = text.replace("%ZVEI%", data["zvei"]) + + # replace POC data + if "ric" in data: text = text.replace("%RIC%", data["ric"]) + if "function" in data: text = text.replace("%FUNC%", data["function"]) + if "functionChar" in data: text = text.replace("%FUNCCHAR%", data["functionChar"]) + if "msg" in data: text = text.replace("%MSG%", data["msg"]) + if "bitrate" in data: text = text.replace("%BITRATE%", str(data["bitrate"])) + + # replace description (exists by all) + if "description" in data: text = text.replace("%DESCR%", data["description"]) + + return text + + except: + logging.warning("error wildcard replacement") + logging.debug("error wildcard replacement", exc_info=True) From f02d306082b2b625fbc08346bfd055a9aa02ee05 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 2 Jul 2015 12:56:16 +0200 Subject: [PATCH 61/98] insert a plugin-coding-readme Issue #40 --- plugins/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 plugins/README.md diff --git a/plugins/README.md b/plugins/README.md new file mode 100644 index 00000000..71818be7 --- /dev/null +++ b/plugins/README.md @@ -0,0 +1,8 @@ +### How to Code your own plugin: + +More information and a little Tutorial coming soon! + +##### Code your own Plugin +To code your own Plugin look at the litte example `/plugins/template/template.py` + +In the text-file `plugins/interface.txt` are all relevant data, that your plugin can use. From 3b66a1d9525aa08a81cd2e5046c781dd431bd83d Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 2 Jul 2015 13:00:38 +0200 Subject: [PATCH 62/98] edit Interface.txt --- plugins/interface.txt | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/plugins/interface.txt b/plugins/interface.txt index e6396047..c1e95498 100644 --- a/plugins/interface.txt +++ b/plugins/interface.txt @@ -82,6 +82,31 @@ Global Functions for plugins: ----------------------------- from includes import helper #Global helper functions -#for format see https://docs.python.org/2/library/time.html#time.strftime -#without format string the function returns with: %d.%m.%Y %H:%M:%S + +# for format see https://docs.python.org/2/library/time.html#time.strftime +# without format string the function returns with: %d.%m.%Y %H:%M:%S +# helper.curtime("FORMAT") + + +# replace all the standard wildcards in the given text +# the function needs the data[] var +# %TIME% = Time (by script) +# %DATE% = Date (by script) +# +# %FMS% = FMS Code +# %STATUS% = FMS Status +# %DIR% = Direction of the telegram (0/1) +# %DIRT% = Direction of the telegram (Text-String) +# %TSI% = Tactical Short Information (I-IV) +# +# %ZVEI% = ZVEI 5-tone Code +# +# %RIC% = Pocsag RIC +# %FUNC% = Pocsac function/Subric (1-4) +# %FUNCCHAR% = Pocsac function/Subric als character (a-d) +# %MSG% = Message of the Pocsag telegram +# %BITRATE% = Bitrate of the Pocsag telegram +# %DESCR% = Description from csv-file +# +helper.replaceWildcards("TEXT",data[]) From 68fb88cc63a278fac68d2ac7928e424c3d8f69e8 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 2 Jul 2015 15:16:24 +0200 Subject: [PATCH 63/98] move helper functions in seperate folder and split to logical files --- includes/helper/__init__.py | 0 includes/helper/timeHandler.py | 49 +++++++++++++++++++ .../{helper.py => helper/wildcardHandler.py} | 28 ++--------- plugins/MySQL/boswatch.sql | 3 ++ 4 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 includes/helper/__init__.py create mode 100644 includes/helper/timeHandler.py rename includes/{helper.py => helper/wildcardHandler.py} (70%) diff --git a/includes/helper/__init__.py b/includes/helper/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/includes/helper/timeHandler.py b/includes/helper/timeHandler.py new file mode 100644 index 00000000..7c45fb4b --- /dev/null +++ b/includes/helper/timeHandler.py @@ -0,0 +1,49 @@ +#!/usr/bin/python +# -*- coding: cp1252 -*- +# + +""" +little Helper to get easy the curent date or time +for direct use in plugins to save code + +@author: Bastian Schroll +""" + +import logging + +import time + + +def curtime(format="%d.%m.%Y %H:%M:%S"): + """ + Returns formated date and/or time + see: https://docs.python.org/2/library/time.html#time.strftime + + @type format: string + @param format: Python time Format-String + + @return: Formated Time and/or Date + @exception: Exception if Error in format + """ + try: + return time.strftime(format) + except: + logging.warning("error in time-format-string") + logging.debug("error in time-format-string", exc_info=True) + + +def getDate(): + """ + Returns the date + + @return: Formated date + """ + return curtime("%d.%m.%Y") + +def getTime(): + """ + Returns the time + + @return: Formated time + """ + return curtime("%H:%M:%S") diff --git a/includes/helper.py b/includes/helper/wildcardHandler.py similarity index 70% rename from includes/helper.py rename to includes/helper/wildcardHandler.py index 2b549e2e..be7f9848 100644 --- a/includes/helper.py +++ b/includes/helper/wildcardHandler.py @@ -3,33 +3,15 @@ # """ -little Helper functions -mainly for direct use in plugins to save code +little Helper to replace fast and easy the standard wildcards +for direct use in plugins to save code -@author: Bastian Schroll +@author: Bastian Schroll """ import logging -import time - - -def curtime(format="%d.%m.%Y %H:%M:%S"): - """ - Returns formated date and/or time - see: https://docs.python.org/2/library/time.html#time.strftime - - @type format: string - @param format: Python time Format-String - - @return: Formated Time and/or Date - @exception: Exception if Error in format - """ - try: - return time.strftime(format) - except: - logging.warning("error in time-format-string") - logging.debug("error in time-format-string", exc_info=True) +from includes.helper import timeHandler def replaceWildcards(text,data): @@ -46,7 +28,7 @@ def replaceWildcards(text,data): """ try: # replace date and time wildcards - text = text.replace("%TIME%", curtime("%H:%M:%S")).replace("%DATE%", curtime("%d.%m.%Y")) + text = text.replace("%TIME%", timeHandler.getTime()).replace("%DATE%", timeHandler.getDate()) # replace FMS data if "fms" in data: text = text.replace("%FMS%", data["fms"]) diff --git a/plugins/MySQL/boswatch.sql b/plugins/MySQL/boswatch.sql index 0427f8e4..cf91616f 100644 --- a/plugins/MySQL/boswatch.sql +++ b/plugins/MySQL/boswatch.sql @@ -1,3 +1,6 @@ +-- MySQL Database Structure for the BOSWatch MySQL Plugin +-- @author: Bastian Schroll + -- phpMyAdmin SQL Dump -- version 3.4.11.1deb2+deb7u1 -- http://www.phpmyadmin.net From 4a995683c08b76dab960902cf4679e43b31eaf60 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 2 Jul 2015 15:19:46 +0200 Subject: [PATCH 64/98] update interface.txt to new helper structure --- plugins/interface.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/interface.txt b/plugins/interface.txt index c1e95498..ee2860b3 100644 --- a/plugins/interface.txt +++ b/plugins/interface.txt @@ -80,13 +80,13 @@ def run(typ,freq,data): Global Functions for plugins: ----------------------------- -from includes import helper #Global helper functions - # for format see https://docs.python.org/2/library/time.html#time.strftime -# without format string the function returns with: %d.%m.%Y %H:%M:%S # -helper.curtime("FORMAT") +from includes.helper import timeHandler +timeHandler.curtime("FORMAT") # without format string the function returns with "%d.%m.%Y %H:%M:%S" +timeHandler.getDate() # Gets the date in "%d.%m.%Y" +timeHandler.getTime() # Gets the time in %H:%M:%S # replace all the standard wildcards in the given text @@ -109,4 +109,5 @@ helper.curtime("FORMAT") # %BITRATE% = Bitrate of the Pocsag telegram # %DESCR% = Description from csv-file # -helper.replaceWildcards("TEXT",data[]) +from includes.helper import wildcardHandler +wildcardHandler.replaceWildcards("TEXT",data[]) From ac8a02e3ca2fe5943ea743d2772696708479272e Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Thu, 2 Jul 2015 21:39:43 +0200 Subject: [PATCH 65/98] insert helper function timeHandler.getTimestamp() --- boswatch.py | 2 +- includes/helper/timeHandler.py | 8 ++++++++ plugins/interface.txt | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/boswatch.py b/boswatch.py index 03ce8da9..b0b423ac 100755 --- a/boswatch.py +++ b/boswatch.py @@ -21,7 +21,7 @@ import argparse # for parse the args import ConfigParser # for parse the config file import os # for log mkdir -import time # for timestamp +import time # for time.sleep() import subprocess # for starting rtl_fm and multimon-ng from includes import globals # Global variables diff --git a/includes/helper/timeHandler.py b/includes/helper/timeHandler.py index 7c45fb4b..d6b2ad96 100644 --- a/includes/helper/timeHandler.py +++ b/includes/helper/timeHandler.py @@ -47,3 +47,11 @@ def getTime(): @return: Formated time """ return curtime("%H:%M:%S") + +def getTimestamp(): + """ + Returns a integer timestamp + + @return: integer timestamp + """ + return int(time.time() diff --git a/plugins/interface.txt b/plugins/interface.txt index ee2860b3..73ecbec5 100644 --- a/plugins/interface.txt +++ b/plugins/interface.txt @@ -87,6 +87,7 @@ from includes.helper import timeHandler timeHandler.curtime("FORMAT") # without format string the function returns with "%d.%m.%Y %H:%M:%S" timeHandler.getDate() # Gets the date in "%d.%m.%Y" timeHandler.getTime() # Gets the time in %H:%M:%S +timeHandler.getTimestamp() # Gets a integer timestamp # replace all the standard wildcards in the given text From aaa6a96a47108d1f818ff5837808c242d83d7451 Mon Sep 17 00:00:00 2001 From: JHCD Date: Fri, 3 Jul 2015 23:16:11 +0200 Subject: [PATCH 66/98] add testdata driver for testing all the different stuff see issue #38 add much more testdate --- boswatch.py | 35 +++++++------- testdata/testdata.txt | 109 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 106 insertions(+), 38 deletions(-) diff --git a/boswatch.py b/boswatch.py index b0b423ac..be531a69 100755 --- a/boswatch.py +++ b/boswatch.py @@ -330,29 +330,26 @@ logging.debug("cannot start multimon-ng", exc_info=True) exit(1) - # multimon-ng started, continue... - logging.debug("start decoding") - # # Get decoded data from multimon-ng and call BOSWatch-decoder # - while True: - if not args.test: + if not args.test: + logging.debug("start decoding") + while True: decoded = str(multimon_ng.stdout.readline()) #Get line data from multimon stdout - - else: - # Test-strings only for develop - #decoded = "ZVEI2: 25832" - #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=I (ohneNA,ohneSIGNAL)) CRC correct\n'" - #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 1=LST->FZG 2=I (ohneNA,ohneSIGNAL)) CRC correct\n'" - #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=II (ohneNA,mit SIGNAL)) CRC correct\n'" - #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 1=LST->FZG 2=III(mit NA,ohneSIGNAL)) CRC correct\n'" - #decoded = "FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=IV (mit NA,mit SIGNAL)) CRC correct\n'" - decoded = "POCSAG1200: Address: 1234567 Function: 1 Alpha: Hello World" - time.sleep(1) - - from includes import decoder - decoder.decode(converter.freqToHz(args.freq), decoded) + from includes import decoder + decoder.decode(converter.freqToHz(args.freq), decoded) + + else: + logging.debug("start testing") + testFile = open(globals.script_path+"/testdata/testdata.txt","r") + for testData in testFile: + if (len(testData) > 1) and ("#" not in testData[0]): + logging.info("Testdata: %s", testData.rstrip(' \t\n\r')) + from includes import decoder + decoder.decode(converter.freqToHz(args.freq), testData) + time.sleep(1) + logging.debug("test finished") except KeyboardInterrupt: logging.warning("Keyboard Interrupt") diff --git a/testdata/testdata.txt b/testdata/testdata.txt index b8246147..ada96303 100644 --- a/testdata/testdata.txt +++ b/testdata/testdata.txt @@ -1,30 +1,101 @@ -#Testdata for the BOSWatch Test Mode function -#Data in Multimon-NG Raw Format -#Data is alternately passed to the decoder to simulate an used Radio-Frequency +# Testdata for the BOSWatch Test Mode function +# Data in Multimon-NG Raw Format +# Data is alternately passed to the decoder to simulate an used Radio-Frequency -#POCSAG -#all bitrates, all functions, with and without text, duplicates same and other msg +# +# POCSAG +# ------ +# -#witch csv -POCSAG512: Address: 1234567 Function: 1 Alpha: Hello World +# +# The following settings in config.ini are expected for pocsag +# +# [BOSWatch] +# useDescription = 1 +# doubleFilter_ignore_entries = 10 +# doubleFilter_check_msg = 1 +# +# [POC] +# deny_ric = 7777777 +# filter_range_start = 1000000 +# filter_range_end = 8999999 +# idDescribed = 1 +# -#without csv -POCSAG1200: Address: 2345678 Function: 2 Alpha: Hello World -POCSAG2400: Address: 3456789 Function: 3 Alpha: Hello World +# bitrate +POCSAG512: Address: 1000512 Function: 1 Alpha: BOSWatch-Test: okay +POCSAG1200: Address: 1001200 Function: 1 Alpha: BOSWatch-Test: okay +POCSAG2400: Address: 1002400 Function: 1 Alpha: BOSWatch-Test: okay -#OHNE TEXT???? -POCSAG1200: Address: 1358246 Function: 4 +# function-code +POCSAG512: Address: 1000000 Function: 0 Alpha: BOSWatch-Test: okay +POCSAG512: Address: 1000001 Function: 1 Alpha: BOSWatch-Test: okay +POCSAG512: Address: 1000002 Function: 2 Alpha: BOSWatch-Test: okay +POCSAG512: Address: 1000003 Function: 3 Alpha: BOSWatch-Test: okay -#duplicate with same and other msg -POCSAG1200: Address: 2345678 Function: 2 Alpha: Hello World -POCSAG1200: Address: 2345678 Function: 2 Alpha: Bye Earth +# witch csv +POCSAG512: Address: 1234567 Function: 1 Alpha: BOSWatch-Test: with csv -#invalid -POCSAG1200: Address: 123567 Function: 1 Alpha: Hello World +# without csv +POCSAG1200: Address: 2345678 Function: 2 Alpha: BOSWatch-Test: without csv +POCSAG2400: Address: 3456789 Function: 3 Alpha: BOSWatch-Test: without csv -#FMS +# OHNE TEXT???? +POCSAG1200: Address: 1100000 Function: 1 +POCSAG1200: Address: 1100000 Function: 2 +POCSAG1200: Address: 1100000 Function: 3 +POCSAG1200: Address: 1100000 Function: 4 + +# duplicate with same and other msg +POCSAG1200: Address: 2000001 Function: 2 Alpha: BOSWatch-Test: second is a duplicate +POCSAG1200: Address: 2000001 Function: 2 Alpha: BOSWatch-Test: second is a duplicate +POCSAG1200: Address: 2000001 Function: 2 Alpha: BOSWatch-Testing: okay + +# duplicate in different order +POCSAG1200: Address: 2100000 Function: 2 Alpha: +POCSAG1200: Address: 2100001 Function: 2 Alpha: +POCSAG1200: Address: 2100002 Function: 2 Alpha: +POCSAG1200: Address: 2100000 Function: 2 Alpha: +POCSAG1200: Address: 2100001 Function: 2 Alpha: +POCSAG1200: Address: 2100002 Function: 2 Alpha: +POCSAG1200: Address: 2100000 Function: 2 Alpha: BOSWatch-Test: second is a duplicate +POCSAG1200: Address: 2100001 Function: 2 Alpha: BOSWatch-Test: second is a duplicate +POCSAG1200: Address: 2100002 Function: 2 Alpha: BOSWatch-Test: second is a duplicate +POCSAG1200: Address: 2100000 Function: 2 Alpha: BOSWatch-Test: second is a duplicate +POCSAG1200: Address: 2100001 Function: 2 Alpha: BOSWatch-Test: second is a duplicate +POCSAG1200: Address: 2100002 Function: 2 Alpha: BOSWatch-Test: second is a duplicate + +# invalid +POCSAG512: Address: 123456 Function: 0 Alpha: BOSWatch-Test: invalid +POCSAG1200: Address: 123456 Function: 1 Alpha: BOSWatch-Test: invalid +POCSAG2400: Address: 1234567 Function: 4 Alpha: BOSWatch-Test: invalid + +# denied +POCSAG1200: Address: 7777777 Function: 1 Alpha: BOSWatch-Test: denied + +# out of filter Range +POCSAG1200: Address: 0999999 Function: 1 Alpha: BOSWatch-Test: out of filter start +POCSAG1200: Address: 9000000 Function: 1 Alpha: BOSWatch-Test: out of filter end + +# regEx-Filter? + + +# +# FMS +# --- +# +FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=I (ohneNA,ohneSIGNAL)) CRC correct +FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 1=LST->FZG 2=I (ohneNA,ohneSIGNAL)) CRC correct +FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=II (ohneNA,mit SIGNAL)) CRC correct +FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 1=LST->FZG 2=III(mit NA,ohneSIGNAL)) CRC correct +FMS: 43f314170000 (9=Rotkreuz 3=Bayern 1 Ort 0x25=037FZG 7141Status 3=Einsatz Ab 0=FZG->LST 2=IV (mit NA,mit SIGNAL)) CRC correct + + +# +# ZVEI +# ---- +# -#ZVEI #with csv description ZVEI2: 12345 #without csv description From 664cceff18fb735f6ec5f5710f2cfc5654d39e5a Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Fri, 3 Jul 2015 23:25:54 +0200 Subject: [PATCH 67/98] error in timeHandler --- includes/helper/timeHandler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/helper/timeHandler.py b/includes/helper/timeHandler.py index d6b2ad96..246a5ee4 100644 --- a/includes/helper/timeHandler.py +++ b/includes/helper/timeHandler.py @@ -54,4 +54,4 @@ def getTimestamp(): @return: integer timestamp """ - return int(time.time() + return int(time.time()) From dfc982a7e408528875815ec8dc93ef93a660a1d8 Mon Sep 17 00:00:00 2001 From: JHCD Date: Fri, 3 Jul 2015 23:36:50 +0200 Subject: [PATCH 68/98] solve bug in exception-handling we don't want to break down BOSWatch, if an plugin doesn't work --- includes/pluginLoader.py | 45 +++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/includes/pluginLoader.py b/includes/pluginLoader.py index 9d40dc8c..7fbb1920 100644 --- a/includes/pluginLoader.py +++ b/includes/pluginLoader.py @@ -18,7 +18,7 @@ def loadPlugins(): """ - Load all Plugins into globals.pluginList + Load all plugins into globals.pluginList @return: nothing @exception: Exception if insert into globals.pluginList failed @@ -27,10 +27,17 @@ def loadPlugins(): logging.debug("loading plugins") # go to all Plugins from getPlugins() for i in getPlugins(): - # call for each Plugin the loadPlugin() Methode - plugin = loadPlugin(i) - # Try to call the .onLoad() routine for all active plugins try: + # call for each Plugin the loadPlugin() Methode + plugin = loadPlugin(i) + except: + # call next plugin, if one has thrown an exception + logging.error("error loading plugin: %s", i["name"]) + logging.debug("error loading plugin: %s", i["name"], exc_info=True) + pass + + try: + # Try to call the .onLoad() routine for all active plugins logging.debug("call %s.onLoad()", i["name"]) plugin.onLoad() # Add it to globals.pluginList @@ -41,20 +48,20 @@ def loadPlugins(): logging.debug("error calling %s.onLoad()", exc_info=True) pass except: - logging.error("cannot load Plugins") - logging.debug("cannot load Plugins", exc_info=True) + logging.error("cannot load plugins") + logging.debug("cannot load plugins", exc_info=True) raise def getPlugins(): """ - get a Python Dict of all activeated Plugins + get a Python Dict of all activeated plugins - @return: Plugins as Python Dict - @exception: Exception if Plugin search failed + @return: plugins as Python Dict + @exception: Exception if plugin search failed """ try: - logging.debug("Search in Plugin Folder") + logging.debug("Search in plugin folder") PluginFolder = globals.script_path+"/plugins" plugins = [] # Go to all Folders in the Plugin-Dir @@ -78,8 +85,8 @@ def getPlugins(): logging.warning("Plugin [NO CONF ] %s", i) pass except: - logging.error("Error during Plugin search") - logging.debug("cannot load Plugins", exc_info=True) + logging.error("Error during plugin search") + logging.debug("cannot load plugins", exc_info=True) raise return plugins @@ -87,19 +94,19 @@ def getPlugins(): def loadPlugin(plugin): """ - Imports a single Plugin + Imports a single plugin - @type plugin: Plugin Data - @param plugin: Contains the information to import a Plugin + @type plugin: plugin Data + @param plugin: Contains the information to import a plugin @return: nothing - @exception: Exception if Plugin import failed + @exception: Exception if plugin import failed """ try: - logging.debug("load Plugin: %s", plugin["name"]) + logging.debug("load plugin: %s", plugin["name"]) return imp.load_module(plugin["name"], *plugin["info"]) except: - logging.error("cannot load Plugin: %s", plugin["name"]) - logging.debug("cannot load Plugin: %s", plugin["name"], exc_info=True) + logging.error("cannot load plugin: %s", plugin["name"]) + logging.debug("cannot load plugin: %s", plugin["name"], exc_info=True) raise From 6a1c77b9167345a8905e1614846e11984d0e00e8 Mon Sep 17 00:00:00 2001 From: JHCD Date: Fri, 3 Jul 2015 23:43:22 +0200 Subject: [PATCH 69/98] solve issue #41: support more than one recipient --- plugins/eMail/eMail.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/eMail/eMail.py b/plugins/eMail/eMail.py index 5c133697..586696ab 100644 --- a/plugins/eMail/eMail.py +++ b/plugins/eMail/eMail.py @@ -18,7 +18,7 @@ from email.utils import make_msgid # need for confirm to RFC2822 standard from includes import globals # Global variables -from includes import helper #Global helper functions +from includes.helper import timeHandler # helper function ## # @@ -63,7 +63,7 @@ def doSendmail(server, subject, mailtext): msg['Date'] = formatdate() msg['Message-Id'] = make_msgid() msg['Priority'] = globals.config.get("eMail", "priority") - server.sendmail(globals.config.get("eMail", "from"), globals.config.get("eMail", "to"), msg.as_string()) + server.sendmail(globals.config.get("eMail", "from"), globals.config.get("eMail", "to").split(), msg.as_string()) except: logging.error("send eMail failed") logging.debug("send eMail failed", exc_info=True) @@ -141,14 +141,14 @@ def run(typ,freq,data): subject = subject.replace("%DIR%", data["direction"]).replace("%DIRT%", data["directionText"]) #replace Wildcards subject = subject.replace("%TSI%", data["tsi"]) #replace Wildcards subject = subject.replace("%DESCR%", data["description"]) # replace Wildcards - subject = subject.replace("%TIME%", helper.curtime("H:M:S")).replace("%DATE%", helper.curtime("Y-m-d")) # replace Wildcards + subject = subject.replace("%TIME%", timeHandler.curtime("H:M:S")).replace("%DATE%", timeHandler.curtime("Y-m-d")) # replace Wildcards # read mailtext-structure from config.ini mailtext = globals.config.get("eMail", "fms_message") mailtext = mailtext.replace("%FMS%", data["fms"]).replace("%STATUS%", data["status"]) #replace Wildcards mailtext = mailtext.replace("%DIR%", data["direction"]).replace("%DIRT%", data["directionText"]) #replace Wildcards mailtext = mailtext.replace("%TSI%", data["tsi"]) #replace Wildcards mailtext = mailtext.replace("%DESCR%", data["description"]) # replace Wildcards - mailtext = mailtext.replace("%TIME%", helper.curtime("H:M:S")).replace("%DATE%", helper.curtime("Y-m-d")) # replace Wildcards + mailtext = mailtext.replace("%TIME%", timeHandler.curtime("H:M:S")).replace("%DATE%", timeHandler.curtime("Y-m-d")) # replace Wildcards # send eMail doSendmail(server, subject, mailtext) except: @@ -163,12 +163,12 @@ def run(typ,freq,data): subject = globals.config.get("eMail", "zvei_subject") subject = subject.replace("%ZVEI%", data["zvei"]) #replace Wildcards subject = subject.replace("%DESCR%", data["description"]) # replace Wildcards - subject = subject.replace("%TIME%", helper.curtime("H:M:S")).replace("%DATE%", helper.curtime("Y-m-d")) # replace Wildcards + subject = subject.replace("%TIME%", timeHandler.curtime("H:M:S")).replace("%DATE%", timeHandler.curtime("Y-m-d")) # replace Wildcards # read mailtext-structure from config.ini mailtext = globals.config.get("eMail", "zvei_message") mailtext = mailtext.replace("%ZVEI%", data["zvei"]) #replace Wildcards mailtext = mailtext.replace("%DESCR%", data["description"]) # replace Wildcards - mailtext = mailtext.replace("%TIME%", helper.curtime("H:M:S")).replace("%DATE%", helper.curtime("Y-m-d")) # replace Wildcards + mailtext = mailtext.replace("%TIME%", timeHandler.curtime("H:M:S")).replace("%DATE%", timeHandler.curtime("Y-m-d")) # replace Wildcards # send eMail doSendmail(server, subject, mailtext) except: @@ -185,14 +185,14 @@ def run(typ,freq,data): subject = subject.replace("%FUNC%", data["function"]).replace("%FUNCCHAR%", data["functionChar"]) #replace Wildcards subject = subject.replace("%MSG%", data["msg"]).replace("%BITRATE%", str(data["bitrate"])) #replace Wildcards subject = subject.replace("%DESCR%", data["description"]) # replace Wildcards - subject = subject.replace("%TIME%", helper.curtime("H:M:S")).replace("%DATE%", helper.curtime("Y-m-d")) # replace Wildcards + subject = subject.replace("%TIME%", timeHandler.curtime("H:M:S")).replace("%DATE%", timeHandler.curtime("Y-m-d")) # replace Wildcards # read mailtext-structure from config.ini mailtext = globals.config.get("eMail", "poc_message") mailtext = mailtext.replace("%RIC%", data["ric"]) #replace Wildcards mailtext = mailtext.replace("%FUNC%", data["function"]).replace("%FUNCCHAR%", data["functionChar"]) #replace Wildcards mailtext = mailtext.replace("%MSG%", data["msg"]).replace("%BITRATE%", str(data["bitrate"])) #replace Wildcards mailtext = mailtext.replace("%DESCR%", data["description"]) # replace Wildcards - mailtext = mailtext.replace("%TIME%", helper.curtime("H:M:S")).replace("%DATE%", helper.curtime("Y-m-d")) # replace Wildcards + mailtext = mailtext.replace("%TIME%", timeHandler.curtime("H:M:S")).replace("%DATE%", timeHandler.curtime("Y-m-d")) # replace Wildcards # send eMail doSendmail(server, subject, mailtext) except: From 80f955beca8fcd09f736208a21f5f8592b3ebad0 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Fri, 3 Jul 2015 23:52:31 +0200 Subject: [PATCH 70/98] solve error by helper import in http plugin --- plugins/httpRequest/httpRequest.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/httpRequest/httpRequest.py b/plugins/httpRequest/httpRequest.py index d92759c1..8d904eaa 100644 --- a/plugins/httpRequest/httpRequest.py +++ b/plugins/httpRequest/httpRequest.py @@ -15,7 +15,7 @@ from urlparse import urlparse #for split the URL into url and path from includes import globals # Global variables -from includes import helper #Global helper functions +from includes.helper import timeHandler ## # @@ -94,8 +94,8 @@ def run(typ,freq,data): #same in all types url = url.replace("%DESCR%", data["description"]) # replace Wildcards - url = url.replace("%TIME%", helper.curtime("%H:%M:%S")) # replace Wildcards - url = url.replace("%DATE%", helper.curtime("%d.%m.%Y")) # replace Wildcards + url = url.replace("%TIME%", timeHandler.getTime()) # replace Wildcards + url = url.replace("%DATE%", timeHandler.getDate()) # replace Wildcards # # HTTP-Request From 474679f78a89285aa393988a0d54389a85afaffd Mon Sep 17 00:00:00 2001 From: JHCD Date: Fri, 3 Jul 2015 23:58:41 +0200 Subject: [PATCH 71/98] new testdata #38 --- testdata/testdata.txt | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/testdata/testdata.txt b/testdata/testdata.txt index ada96303..1dd907f9 100644 --- a/testdata/testdata.txt +++ b/testdata/testdata.txt @@ -6,9 +6,7 @@ # POCSAG # ------ # - -# -# The following settings in config.ini are expected for pocsag +# The following settings in config.ini are expected for POCSAG # # [BOSWatch] # useDescription = 1 @@ -17,7 +15,7 @@ # # [POC] # deny_ric = 7777777 -# filter_range_start = 1000000 +# filter_range_start = 0000005 # filter_range_end = 8999999 # idDescribed = 1 # @@ -52,12 +50,12 @@ POCSAG1200: Address: 2000001 Function: 2 Alpha: BOSWatch-Test: second is a d POCSAG1200: Address: 2000001 Function: 2 Alpha: BOSWatch-Testing: okay # duplicate in different order -POCSAG1200: Address: 2100000 Function: 2 Alpha: -POCSAG1200: Address: 2100001 Function: 2 Alpha: -POCSAG1200: Address: 2100002 Function: 2 Alpha: -POCSAG1200: Address: 2100000 Function: 2 Alpha: -POCSAG1200: Address: 2100001 Function: 2 Alpha: -POCSAG1200: Address: 2100002 Function: 2 Alpha: +POCSAG1200: Address: 2100000 Function: 2 +POCSAG1200: Address: 2100001 Function: 2 +POCSAG1200: Address: 2100002 Function: 2 +POCSAG1200: Address: 2100000 Function: 2 +POCSAG1200: Address: 2100001 Function: 2 +POCSAG1200: Address: 2100002 Function: 2 POCSAG1200: Address: 2100000 Function: 2 Alpha: BOSWatch-Test: second is a duplicate POCSAG1200: Address: 2100001 Function: 2 Alpha: BOSWatch-Test: second is a duplicate POCSAG1200: Address: 2100002 Function: 2 Alpha: BOSWatch-Test: second is a duplicate @@ -66,15 +64,22 @@ POCSAG1200: Address: 2100001 Function: 2 Alpha: BOSWatch-Test: second is a d POCSAG1200: Address: 2100002 Function: 2 Alpha: BOSWatch-Test: second is a duplicate # invalid -POCSAG512: Address: 123456 Function: 0 Alpha: BOSWatch-Test: invalid -POCSAG1200: Address: 123456 Function: 1 Alpha: BOSWatch-Test: invalid -POCSAG2400: Address: 1234567 Function: 4 Alpha: BOSWatch-Test: invalid +POCSAG512: Address: 3 Function: 0 Alpha: BOSWatch-Test: okay +POCSAG512: Address: 33 Function: 0 Alpha: BOSWatch-Test: okay +POCSAG512: Address: 333 Function: 0 Alpha: BOSWatch-Test: okay +POCSAG512: Address: 3333 Function: 0 Alpha: BOSWatch-Test: okay +POCSAG512: Address: 33333 Function: 0 Alpha: BOSWatch-Test: okay +POCSAG512: Address: 333333 Function: 0 Alpha: BOSWatch-Test: okay +POCSAG512: Address: 3333333 Function: 0 Alpha: BOSWatch-Test: okay +POCSAG512: Address: 333333F Function: 0 Alpha: BOSWatch-Test: invalid +POCSAG512: Address: 333333F Function: 1 Alpha: BOSWatch-Test: invalid +POCSAG512: Address: 3333333 Function: 4 Alpha: BOSWatch-Test: invalid # denied POCSAG1200: Address: 7777777 Function: 1 Alpha: BOSWatch-Test: denied # out of filter Range -POCSAG1200: Address: 0999999 Function: 1 Alpha: BOSWatch-Test: out of filter start +POCSAG1200: Address: 0000004 Function: 1 Alpha: BOSWatch-Test: out of filter start POCSAG1200: Address: 9000000 Function: 1 Alpha: BOSWatch-Test: out of filter end # regEx-Filter? From b494c8281b09e0d1e9de45e2c3234d1f86013f77 Mon Sep 17 00:00:00 2001 From: JHCD Date: Sat, 4 Jul 2015 00:03:02 +0200 Subject: [PATCH 72/98] extend testdata (issue #38) --- testdata/testdata.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testdata/testdata.txt b/testdata/testdata.txt index 1dd907f9..6f9d6d16 100644 --- a/testdata/testdata.txt +++ b/testdata/testdata.txt @@ -73,7 +73,7 @@ POCSAG512: Address: 333333 Function: 0 Alpha: BOSWatch-Test: okay POCSAG512: Address: 3333333 Function: 0 Alpha: BOSWatch-Test: okay POCSAG512: Address: 333333F Function: 0 Alpha: BOSWatch-Test: invalid POCSAG512: Address: 333333F Function: 1 Alpha: BOSWatch-Test: invalid -POCSAG512: Address: 3333333 Function: 4 Alpha: BOSWatch-Test: invalid +POCSAG512: Address: 3333333 Function: 4 Alpha: BOSWatch-Test: invalid (issue #) # denied POCSAG1200: Address: 7777777 Function: 1 Alpha: BOSWatch-Test: denied From 89796881a1147b4b6e9c0be16344f6d80b9c2818 Mon Sep 17 00:00:00 2001 From: JHCD Date: Sat, 4 Jul 2015 00:03:02 +0200 Subject: [PATCH 73/98] extend testdata (issue #38) --- testdata/testdata.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testdata/testdata.txt b/testdata/testdata.txt index 1dd907f9..0c9f1a88 100644 --- a/testdata/testdata.txt +++ b/testdata/testdata.txt @@ -39,10 +39,10 @@ POCSAG1200: Address: 2345678 Function: 2 Alpha: BOSWatch-Test: without csv POCSAG2400: Address: 3456789 Function: 3 Alpha: BOSWatch-Test: without csv # OHNE TEXT???? +POCSAG1200: Address: 1100000 Function: 0 POCSAG1200: Address: 1100000 Function: 1 POCSAG1200: Address: 1100000 Function: 2 POCSAG1200: Address: 1100000 Function: 3 -POCSAG1200: Address: 1100000 Function: 4 # duplicate with same and other msg POCSAG1200: Address: 2000001 Function: 2 Alpha: BOSWatch-Test: second is a duplicate @@ -73,7 +73,7 @@ POCSAG512: Address: 333333 Function: 0 Alpha: BOSWatch-Test: okay POCSAG512: Address: 3333333 Function: 0 Alpha: BOSWatch-Test: okay POCSAG512: Address: 333333F Function: 0 Alpha: BOSWatch-Test: invalid POCSAG512: Address: 333333F Function: 1 Alpha: BOSWatch-Test: invalid -POCSAG512: Address: 3333333 Function: 4 Alpha: BOSWatch-Test: invalid +POCSAG512: Address: 3333333 Function: 4 Alpha: BOSWatch-Test: invalid (issue #38) # denied POCSAG1200: Address: 7777777 Function: 1 Alpha: BOSWatch-Test: denied From 02b53930cfeb9f144ee7a0a31b4de943b810237a Mon Sep 17 00:00:00 2001 From: JHCD Date: Sat, 4 Jul 2015 00:18:24 +0200 Subject: [PATCH 74/98] resolve issue #43 --- plugins/firEmergency/firEmergency.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/firEmergency/firEmergency.py b/plugins/firEmergency/firEmergency.py index a70d86e8..ef469384 100644 --- a/plugins/firEmergency/firEmergency.py +++ b/plugins/firEmergency/firEmergency.py @@ -91,7 +91,7 @@ def run(typ,freq,data): logging.debug("ZVEI to firEmergency") try: firXML = "\n
"+data["zvei"]+"
\n"+data["zvei"]+" alarmiert.\n
\n" - firSocket.send(firXML) + firSocket.send(firXML.encode('utf-8')) except: logging.error("%s to firEmergency failed", typ) logging.debug("%s to firEmergency failed", typ, exc_info=True) @@ -102,7 +102,7 @@ def run(typ,freq,data): logging.debug("POC to firEmergency") try: firXML = "\n
"+data["ric"]+"
\n"+data["msg"]+"\n
\n" - firSocket.send(firXML) + firSocket.send(firXML.encode('utf-8')) except: logging.error("%s to firEmergency failed", typ) logging.debug("%s to firEmergency failed", typ, exc_info=True) From e31ab6591197d75b6bfbda00e20cbcf3401675a9 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Sat, 4 Jul 2015 00:39:34 +0200 Subject: [PATCH 75/98] Issue #44 --- includes/decoders/poc.py | 4 ++-- testdata/testdata.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/decoders/poc.py b/includes/decoders/poc.py index 7462af5b..add42a1e 100644 --- a/includes/decoders/poc.py +++ b/includes/decoders/poc.py @@ -101,7 +101,7 @@ def decode(freq, decoded): else: poc_text = "" - if re.search("[0-9]{7}", poc_id): #if POC is valid + if re.search("[0-9]{7}", poc_id) and re.search("[0-3]{1}", poc_sub): #if POC is valid if isAllowed(poc_id): # check for double alarm if doubleFilter.checkID("POC", poc_id+poc_sub, poc_text): @@ -126,4 +126,4 @@ def decode(freq, decoded): else: logging.debug("POCSAG%s: %s is not allowed", bitrate, poc_id) else: - logging.warning("No valid POCSAG%s RIC: %s", bitrate, poc_id) + logging.warning("No valid POCSAG%s RIC: %s SUB: %s", bitrate, poc_id, poc_sub) diff --git a/testdata/testdata.txt b/testdata/testdata.txt index 0c9f1a88..acd6c88d 100644 --- a/testdata/testdata.txt +++ b/testdata/testdata.txt @@ -73,7 +73,7 @@ POCSAG512: Address: 333333 Function: 0 Alpha: BOSWatch-Test: okay POCSAG512: Address: 3333333 Function: 0 Alpha: BOSWatch-Test: okay POCSAG512: Address: 333333F Function: 0 Alpha: BOSWatch-Test: invalid POCSAG512: Address: 333333F Function: 1 Alpha: BOSWatch-Test: invalid -POCSAG512: Address: 3333333 Function: 4 Alpha: BOSWatch-Test: invalid (issue #38) +POCSAG512: Address: 3333333 Function: 4 Alpha: BOSWatch-Test: invalid # denied POCSAG1200: Address: 7777777 Function: 1 Alpha: BOSWatch-Test: denied From 624addad4367dcb6469e4fbe5da9994882a80b34 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Sat, 4 Jul 2015 00:53:29 +0200 Subject: [PATCH 76/98] Issue #44 --- includes/decoders/poc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/decoders/poc.py b/includes/decoders/poc.py index add42a1e..f47a9792 100644 --- a/includes/decoders/poc.py +++ b/includes/decoders/poc.py @@ -101,7 +101,7 @@ def decode(freq, decoded): else: poc_text = "" - if re.search("[0-9]{7}", poc_id) and re.search("[0-3]{1}", poc_sub): #if POC is valid + if re.search("[0-9]{7}", poc_id) and re.search("[1-4]{1}", poc_sub): #if POC is valid if isAllowed(poc_id): # check for double alarm if doubleFilter.checkID("POC", poc_id+poc_sub, poc_text): From dc3cf610c157dad50510b28e023b59ecd6fa8c52 Mon Sep 17 00:00:00 2001 From: JHCD Date: Sat, 4 Jul 2015 01:23:34 +0200 Subject: [PATCH 77/98] change testdata to utf8 (issue #43) --- testdata/testdata.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testdata/testdata.txt b/testdata/testdata.txt index acd6c88d..c22f4604 100644 --- a/testdata/testdata.txt +++ b/testdata/testdata.txt @@ -1,4 +1,4 @@ -# Testdata for the BOSWatch Test Mode function +# Testdata for the BOSWatch Test Mode function # Data in Multimon-NG Raw Format # Data is alternately passed to the decoder to simulate an used Radio-Frequency From 4a5798b127f9d2d42bc6e74833058ad64a1ba62f Mon Sep 17 00:00:00 2001 From: JHCD Date: Sat, 4 Jul 2015 01:25:21 +0200 Subject: [PATCH 78/98] undo commit 02b5393 (see issue #43) --- plugins/firEmergency/firEmergency.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/firEmergency/firEmergency.py b/plugins/firEmergency/firEmergency.py index ef469384..a70d86e8 100644 --- a/plugins/firEmergency/firEmergency.py +++ b/plugins/firEmergency/firEmergency.py @@ -91,7 +91,7 @@ def run(typ,freq,data): logging.debug("ZVEI to firEmergency") try: firXML = "\n
"+data["zvei"]+"
\n"+data["zvei"]+" alarmiert.\n
\n" - firSocket.send(firXML.encode('utf-8')) + firSocket.send(firXML) except: logging.error("%s to firEmergency failed", typ) logging.debug("%s to firEmergency failed", typ, exc_info=True) @@ -102,7 +102,7 @@ def run(typ,freq,data): logging.debug("POC to firEmergency") try: firXML = "\n
"+data["ric"]+"
\n"+data["msg"]+"\n
\n" - firSocket.send(firXML.encode('utf-8')) + firSocket.send(firXML) except: logging.error("%s to firEmergency failed", typ) logging.debug("%s to firEmergency failed", typ, exc_info=True) From 3150aed20600ddb59b45da36112631b9baed1b61 Mon Sep 17 00:00:00 2001 From: JHCD Date: Sat, 4 Jul 2015 01:33:47 +0200 Subject: [PATCH 79/98] add testdata for german special signs (issue #43 and #38) --- testdata/testdata.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/testdata/testdata.txt b/testdata/testdata.txt index c22f4604..6f121c7e 100644 --- a/testdata/testdata.txt +++ b/testdata/testdata.txt @@ -21,7 +21,7 @@ # # bitrate -POCSAG512: Address: 1000512 Function: 1 Alpha: BOSWatch-Test: okay +POCSAG512: Address: 1000512 Function: 1 Alpha: BOSWatch-Test ÖÄÜß: okay POCSAG1200: Address: 1001200 Function: 1 Alpha: BOSWatch-Test: okay POCSAG2400: Address: 1002400 Function: 1 Alpha: BOSWatch-Test: okay @@ -31,6 +31,10 @@ POCSAG512: Address: 1000001 Function: 1 Alpha: BOSWatch-Test: okay POCSAG512: Address: 1000002 Function: 2 Alpha: BOSWatch-Test: okay POCSAG512: Address: 1000003 Function: 3 Alpha: BOSWatch-Test: okay +# german special sign +POCSAG512: Address: 1200001 Function: 1 Alpha: BOSWatch-Test ÖÄÜß: okay +POCSAG512: Address: 1200001 Function: 1 Alpha: BOSWatch-Test öäü: okay + # witch csv POCSAG512: Address: 1234567 Function: 1 Alpha: BOSWatch-Test: with csv From c4c5b796262da9a98829561abb096da417f19125 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Sat, 4 Jul 2015 08:14:33 +0200 Subject: [PATCH 80/98] Issue #44 --- includes/decoders/poc.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/decoders/poc.py b/includes/decoders/poc.py index f47a9792..279c9221 100644 --- a/includes/decoders/poc.py +++ b/includes/decoders/poc.py @@ -78,17 +78,17 @@ def decode(freq, decoded): if "POCSAG512:" in decoded: bitrate = 512 poc_id = decoded[20:27].replace(" ", "").zfill(7) - poc_sub = decoded[39].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") + poc_sub = str(int(decoded[39])+1) elif "POCSAG1200:" in decoded: bitrate = 1200 poc_id = decoded[21:28].replace(" ", "").zfill(7) - poc_sub = decoded[40].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") + poc_sub = str(int(decoded[40])+1) elif "POCSAG2400:" in decoded: bitrate = 2400 poc_id = decoded[21:28].replace(" ", "").zfill(7) - poc_sub = decoded[40].replace("3", "4").replace("2", "3").replace("1", "2").replace("0", "1") + poc_sub = str(int(decoded[40])+1) if bitrate is 0: logging.warning("POCSAG Bitrate not found") From 9f99d0e705f6b70e595584436b5448bd6cc4c870 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Sat, 4 Jul 2015 08:34:50 +0200 Subject: [PATCH 81/98] edit pluginLoader debug msg --- includes/pluginLoader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/pluginLoader.py b/includes/pluginLoader.py index 7fbb1920..1adc4bd9 100644 --- a/includes/pluginLoader.py +++ b/includes/pluginLoader.py @@ -86,7 +86,7 @@ def getPlugins(): pass except: logging.error("Error during plugin search") - logging.debug("cannot load plugins", exc_info=True) + logging.debug("Error during plugin search", exc_info=True) raise return plugins From e8e1b5940cf7f8f3f47ab6d0b3d65006123ca8c8 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Sat, 4 Jul 2015 08:46:05 +0200 Subject: [PATCH 82/98] added .rstrip(' \t\n\r') to len(testdata) check now no clear lines are interpretet --- boswatch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boswatch.py b/boswatch.py index be531a69..9e63beb9 100755 --- a/boswatch.py +++ b/boswatch.py @@ -344,7 +344,7 @@ logging.debug("start testing") testFile = open(globals.script_path+"/testdata/testdata.txt","r") for testData in testFile: - if (len(testData) > 1) and ("#" not in testData[0]): + if (len(testData.rstrip(' \t\n\r')) > 1) and ("#" not in testData[0]): logging.info("Testdata: %s", testData.rstrip(' \t\n\r')) from includes import decoder decoder.decode(converter.freqToHz(args.freq), testData) From 649b00bf8a2b432f2ff99ef551b42401610563d4 Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Sat, 4 Jul 2015 14:37:35 +0200 Subject: [PATCH 83/98] insert a try:exception: for the three decode() methods Issue #44 --- includes/decoders/fms.py | 70 ++++++++++++------------ includes/decoders/poc.py | 108 ++++++++++++++++++++------------------ includes/decoders/zvei.py | 50 ++++++++++-------- 3 files changed, 120 insertions(+), 108 deletions(-) diff --git a/includes/decoders/fms.py b/includes/decoders/fms.py index e28be3ae..08c06f8b 100644 --- a/includes/decoders/fms.py +++ b/includes/decoders/fms.py @@ -34,38 +34,42 @@ def decode(freq, decoded): @return: nothing @exception: Exception if FMS decode failed """ - fms_service = decoded[19] # Organisation - fms_country = decoded[36] # Bundesland - fms_location = decoded[65:67] # Ort - fms_vehicle = decoded[72:76] # Fahrzeug - fms_status = decoded[84] # Status - fms_direction = decoded[101] # Richtung - fms_directionText = decoded[103:110] # Richtung (Text) - fms_tsi = decoded[114:117] # Taktische Kruzinformation + try: + fms_service = decoded[19] # Organisation + fms_country = decoded[36] # Bundesland + fms_location = decoded[65:67] # Ort + fms_vehicle = decoded[72:76] # Fahrzeug + fms_status = decoded[84] # Status + fms_direction = decoded[101] # Richtung + fms_directionText = decoded[103:110] # Richtung (Text) + fms_tsi = decoded[114:117] # Taktische Kruzinformation - if "CRC correct" in decoded: #check CRC is correct - fms_id = fms_service+fms_country+fms_location+fms_vehicle+fms_status+fms_direction # build FMS id - # if FMS is valid - if re.search("[0-9a-f]{8}[0-9a-f]{1}[01]{1}", fms_id): - # check for double alarm - if doubleFilter.checkID("FMS", fms_id): - logging.info("FMS:%s Status:%s Richtung:%s TSI:%s", fms_id[0:8], fms_status, fms_direction, fms_tsi) - data = {"fms":fms_id[0:8], "status":fms_status, "direction":fms_direction, "directionText":fms_directionText, "tsi":fms_tsi, "description":fms_id[0:8]} - # If enabled, look up description - if globals.config.getint("FMS", "idDescribed"): - from includes import descriptionList - data["description"] = descriptionList.getDescription("FMS", fms_id[0:8]) - # processing the alarm - try: - from includes import alarmHandler - alarmHandler.processAlarm("FMS", freq, data) - except: - logging.error("processing alarm failed") - logging.debug("processing alarm failed", exc_info=True) - pass - # in every time save old data for double alarm - doubleFilter.newEntry(fms_id) + if "CRC correct" in decoded: #check CRC is correct + fms_id = fms_service+fms_country+fms_location+fms_vehicle+fms_status+fms_direction # build FMS id + # if FMS is valid + if re.search("[0-9a-f]{8}[0-9a-f]{1}[01]{1}", fms_id): + # check for double alarm + if doubleFilter.checkID("FMS", fms_id): + logging.info("FMS:%s Status:%s Richtung:%s TSI:%s", fms_id[0:8], fms_status, fms_direction, fms_tsi) + data = {"fms":fms_id[0:8], "status":fms_status, "direction":fms_direction, "directionText":fms_directionText, "tsi":fms_tsi, "description":fms_id[0:8]} + # If enabled, look up description + if globals.config.getint("FMS", "idDescribed"): + from includes import descriptionList + data["description"] = descriptionList.getDescription("FMS", fms_id[0:8]) + # processing the alarm + try: + from includes import alarmHandler + alarmHandler.processAlarm("FMS", freq, data) + except: + logging.error("processing alarm failed") + logging.debug("processing alarm failed", exc_info=True) + pass + # in every time save old data for double alarm + doubleFilter.newEntry(fms_id) + else: + logging.warning("No valid FMS: %s", fms_id) else: - logging.warning("No valid FMS: %s", fms_id) - else: - logging.warning("FMS CRC incorrect") + logging.warning("FMS CRC incorrect") + except: + logging.error("error while decoding") + logging.debug("error while decoding", exc_info=True) diff --git a/includes/decoders/poc.py b/includes/decoders/poc.py index 279c9221..b40dafee 100644 --- a/includes/decoders/poc.py +++ b/includes/decoders/poc.py @@ -73,57 +73,61 @@ def decode(freq, decoded): @return: nothing @exception: Exception if POCSAG decode failed """ - bitrate = 0 - - if "POCSAG512:" in decoded: - bitrate = 512 - poc_id = decoded[20:27].replace(" ", "").zfill(7) - poc_sub = str(int(decoded[39])+1) - - elif "POCSAG1200:" in decoded: - bitrate = 1200 - poc_id = decoded[21:28].replace(" ", "").zfill(7) - poc_sub = str(int(decoded[40])+1) - - elif "POCSAG2400:" in decoded: - bitrate = 2400 - poc_id = decoded[21:28].replace(" ", "").zfill(7) - poc_sub = str(int(decoded[40])+1) - - if bitrate is 0: - logging.warning("POCSAG Bitrate not found") - logging.debug(" - (%s)", decoded) - else: - logging.debug("POCSAG Bitrate: %s", bitrate) - - if "Alpha:" in decoded: #check if there is a text message - poc_text = decoded.split('Alpha: ')[1].strip().rstrip('').strip() + try: + bitrate = 0 + + if "POCSAG512:" in decoded: + bitrate = 512 + poc_id = decoded[20:27].replace(" ", "").zfill(7) + poc_sub = str(int(decoded[39])+1) + + elif "POCSAG1200:" in decoded: + bitrate = 1200 + poc_id = decoded[21:28].replace(" ", "").zfill(7) + poc_sub = str(int(decoded[40])+1) + + elif "POCSAG2400:" in decoded: + bitrate = 2400 + poc_id = decoded[21:28].replace(" ", "").zfill(7) + poc_sub = str(int(decoded[40])+1) + + if bitrate is 0: + logging.warning("POCSAG Bitrate not found") + logging.debug(" - (%s)", decoded) else: - poc_text = "" - - if re.search("[0-9]{7}", poc_id) and re.search("[1-4]{1}", poc_sub): #if POC is valid - if isAllowed(poc_id): - # check for double alarm - if doubleFilter.checkID("POC", poc_id+poc_sub, poc_text): - logging.info("POCSAG%s: %s %s %s ", bitrate, poc_id, poc_sub, poc_text) - data = {"ric":poc_id, "function":poc_sub, "msg":poc_text, "bitrate":bitrate, "description":poc_id} - # Add function as character a-d to dataset - data["functionChar"] = data["function"].replace("1", "a").replace("2", "b").replace("3", "c").replace("4", "d") - # If enabled, look up description - if globals.config.getint("POC", "idDescribed"): - from includes import descriptionList - data["description"] = descriptionList.getDescription("POC", poc_id) - # processing the alarm - try: - from includes import alarmHandler - alarmHandler.processAlarm("POC", freq, data) - except: - logging.error("processing alarm failed") - logging.debug("processing alarm failed", exc_info=True) - pass - # in every time save old data for double alarm - doubleFilter.newEntry(poc_id+poc_sub, poc_text) + logging.debug("POCSAG Bitrate: %s", bitrate) + + if "Alpha:" in decoded: #check if there is a text message + poc_text = decoded.split('Alpha: ')[1].strip().rstrip('').strip() else: - logging.debug("POCSAG%s: %s is not allowed", bitrate, poc_id) - else: - logging.warning("No valid POCSAG%s RIC: %s SUB: %s", bitrate, poc_id, poc_sub) + poc_text = "" + + if re.search("[0-9]{7}", poc_id) and re.search("[1-4]{1}", poc_sub): #if POC is valid + if isAllowed(poc_id): + # check for double alarm + if doubleFilter.checkID("POC", poc_id+poc_sub, poc_text): + logging.info("POCSAG%s: %s %s %s ", bitrate, poc_id, poc_sub, poc_text) + data = {"ric":poc_id, "function":poc_sub, "msg":poc_text, "bitrate":bitrate, "description":poc_id} + # Add function as character a-d to dataset + data["functionChar"] = data["function"].replace("1", "a").replace("2", "b").replace("3", "c").replace("4", "d") + # If enabled, look up description + if globals.config.getint("POC", "idDescribed"): + from includes import descriptionList + data["description"] = descriptionList.getDescription("POC", poc_id) + # processing the alarm + try: + from includes import alarmHandler + alarmHandler.processAlarm("POC", freq, data) + except: + logging.error("processing alarm failed") + logging.debug("processing alarm failed", exc_info=True) + pass + # in every time save old data for double alarm + doubleFilter.newEntry(poc_id+poc_sub, poc_text) + else: + logging.debug("POCSAG%s: %s is not allowed", bitrate, poc_id) + else: + logging.warning("No valid POCSAG%s RIC: %s SUB: %s", bitrate, poc_id, poc_sub) + except: + logging.error("error while decoding") + logging.debug("error while decoding", exc_info=True) diff --git a/includes/decoders/zvei.py b/includes/decoders/zvei.py index 70d61961..ce6e9e2c 100644 --- a/includes/decoders/zvei.py +++ b/includes/decoders/zvei.py @@ -56,26 +56,30 @@ def decode(freq, decoded): @return: nothing @exception: Exception if ZVEI decode failed """ - zvei_id = decoded[7:12] # ZVEI Code - zvei_id = removeF(zvei_id) # resolve F - if re.search("[0-9]{5}", zvei_id): # if ZVEI is valid - # check for double alarm - if doubleFilter.checkID("ZVEI", zvei_id): - logging.info("5-Ton: %s", zvei_id) - data = {"zvei":zvei_id, "description":zvei_id} - # If enabled, look up description - if globals.config.getint("ZVEI", "idDescribed"): - from includes import descriptionList - data["description"] = descriptionList.getDescription("ZVEI", zvei_id) - # processing the alarm - try: - from includes import alarmHandler - alarmHandler.processAlarm("ZVEI", freq, data) - except: - logging.error("processing alarm failed") - logging.debug("processing alarm failed", exc_info=True) - pass - # in every time save old data for double alarm - doubleFilter.newEntry(zvei_id) - else: - logging.warning("No valid ZVEI: %s", zvei_id) + try: + zvei_id = decoded[7:12] # ZVEI Code + zvei_id = removeF(zvei_id) # resolve F + if re.search("[0-9]{5}", zvei_id): # if ZVEI is valid + # check for double alarm + if doubleFilter.checkID("ZVEI", zvei_id): + logging.info("5-Ton: %s", zvei_id) + data = {"zvei":zvei_id, "description":zvei_id} + # If enabled, look up description + if globals.config.getint("ZVEI", "idDescribed"): + from includes import descriptionList + data["description"] = descriptionList.getDescription("ZVEI", zvei_id) + # processing the alarm + try: + from includes import alarmHandler + alarmHandler.processAlarm("ZVEI", freq, data) + except: + logging.error("processing alarm failed") + logging.debug("processing alarm failed", exc_info=True) + pass + # in every time save old data for double alarm + doubleFilter.newEntry(zvei_id) + else: + logging.warning("No valid ZVEI: %s", zvei_id) + except: + logging.error("error while decoding") + logging.debug("error while decoding", exc_info=True) From 1945acb7d4c3e9ad881d3032256138dd085c4427 Mon Sep 17 00:00:00 2001 From: kevinkleist Date: Sat, 4 Jul 2015 22:22:29 +0200 Subject: [PATCH 84/98] Update firEmergency.py Add Subric in Numeric (POCSAG) Add Description in ZVEI + POCSAG !!! Subric is Subric+"XX" because of an Issuse in firEmergency --- plugins/firEmergency/firEmergency.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/firEmergency/firEmergency.py b/plugins/firEmergency/firEmergency.py index a70d86e8..981b9410 100644 --- a/plugins/firEmergency/firEmergency.py +++ b/plugins/firEmergency/firEmergency.py @@ -90,7 +90,7 @@ def run(typ,freq,data): elif typ == "ZVEI": logging.debug("ZVEI to firEmergency") try: - firXML = "\n
"+data["zvei"]+"
\n"+data["zvei"]+" alarmiert.\n
\n" + firXML = "\n
"+data["zvei"]+"
\n"+data["description"]+"\n"+data["zvei"]+" alarmiert.\n
\n" firSocket.send(firXML) except: logging.error("%s to firEmergency failed", typ) @@ -101,7 +101,7 @@ def run(typ,freq,data): elif typ == "POC": logging.debug("POC to firEmergency") try: - firXML = "\n
"+data["ric"]+"
\n"+data["msg"]+"\n
\n" + firXML = "\n
"+data["ric"]+"
\n"+data["function"]+"XX\n"+data["description"]+"\n"+data["msg"]+"\n
\n" firSocket.send(firXML) except: logging.error("%s to firEmergency failed", typ) From 79b71b99e8cd44ec0de242947b05b61be2ccb22b Mon Sep 17 00:00:00 2001 From: Bastian Schroll Date: Sun, 5 Jul 2015 09:02:21 +0200 Subject: [PATCH 85/98] insert little docu into firEmergency Plugin Pull Request #47 --- plugins/firEmergency/firEmergency.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/firEmergency/firEmergency.py b/plugins/firEmergency/firEmergency.py index 981b9410..d62dcb4c 100644 --- a/plugins/firEmergency/firEmergency.py +++ b/plugins/firEmergency/firEmergency.py @@ -4,6 +4,9 @@ """ firEmergency-Plugin to dispatch ZVEI- and POCSAG - messages to firEmergency +firEmergency configuration: +- set input to "FMS32" at Port 5555 + @autor: Smith-fms @requires: firEmergency-Configuration has to be set in the config.ini @@ -101,6 +104,7 @@ def run(typ,freq,data): elif typ == "POC": logging.debug("POC to firEmergency") try: + # !!! Subric+"XX" because of an Issuse in firEmergency !!! firXML = "\n
"+data["ric"]+"
\n"+data["function"]+"XX\n"+data["description"]+"\n"+data["msg"]+"\n
\n" firSocket.send(firXML) except: From 444b6a7ba620364b3afbd99b8e0a57b805a72dc4 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Mon, 6 Jul 2015 10:36:35 +0200 Subject: [PATCH 86/98] edit build date --- includes/globals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/globals.py b/includes/globals.py index 0774cb43..4d26d44a 100644 --- a/includes/globals.py +++ b/includes/globals.py @@ -33,4 +33,4 @@ def getVers(mode="vers"): if mode == "vers": return "2.0-RC" elif mode == "date": - return " 2015/07/02" + return " 2015/07/06" From 4ad5766f982aff4e487bc90454f997e31806a298 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Tue, 7 Jul 2015 13:17:18 +0200 Subject: [PATCH 87/98] insert wildcardHandler.replaceWildcards() in httpReq Plugin --- includes/helper/wildcardHandler.py | 2 ++ plugins/httpRequest/httpRequest.py | 19 ++++++------------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/includes/helper/wildcardHandler.py b/includes/helper/wildcardHandler.py index be7f9848..a7895b93 100644 --- a/includes/helper/wildcardHandler.py +++ b/includes/helper/wildcardHandler.py @@ -50,6 +50,8 @@ def replaceWildcards(text,data): # replace description (exists by all) if "description" in data: text = text.replace("%DESCR%", data["description"]) + logging.debug("wildcards been replaced") + return text except: diff --git a/plugins/httpRequest/httpRequest.py b/plugins/httpRequest/httpRequest.py index 8d904eaa..df165434 100644 --- a/plugins/httpRequest/httpRequest.py +++ b/plugins/httpRequest/httpRequest.py @@ -16,6 +16,7 @@ from includes import globals # Global variables from includes.helper import timeHandler +from includes.helper import wildcardHandler ## # @@ -73,33 +74,25 @@ def run(typ,freq,data): # # Create URL # - logging.debug("send %s HTTP request", typ) - if typ == "FMS": url = globals.config.get("httpRequest", "fms_url") #Get URL - url = url.replace("%FMS%", data["fms"]).replace("%STATUS%", data["status"]) #replace Wildcards - url = url.replace("%DIR%", data["direction"]).replace("%DIRT%", data["directionText"]) #replace Wildcards - url = url.replace("%TSI%", data["tsi"]) #replace Wildcards + url = wildcardHandler.replaceWildcards(url, data) # replace wildcards with helper function elif typ == "ZVEI": url = globals.config.get("httpRequest", "zvei_url") #Get URL - url = url.replace("%ZVEI%", data["zvei"]) #replace Wildcards + url = wildcardHandler.replaceWildcards(url, data) # replace wildcards with helper function elif typ == "POC": url = globals.config.get("httpRequest", "poc_url") #Get URL - url = url.replace("%RIC%", data["ric"]) #replace Wildcards - url = url.replace("%FUNC%", data["function"]).replace("%FUNCCHAR%", data["functionChar"]) #replace Wildcards - url = url.replace("%MSG%", data["msg"]).replace("%BITRATE%", str(data["bitrate"])) #replace Wildcards + url = wildcardHandler.replaceWildcards(url, data) # replace wildcards with helper function + else: logging.warning("Invalid Typ: %s", typ) return - #same in all types - url = url.replace("%DESCR%", data["description"]) # replace Wildcards - url = url.replace("%TIME%", timeHandler.getTime()) # replace Wildcards - url = url.replace("%DATE%", timeHandler.getDate()) # replace Wildcards # # HTTP-Request # + logging.debug("send %s HTTP request", typ) url = urlparse(url) #split URL into path and querry httprequest = httplib.HTTPConnection(url[2]) #connect to URL Path httprequest.request("GET", url[5]) #send URL Querry per GET From 1d65f9fb97ca5586e5b2589365851391313e6f22 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Tue, 7 Jul 2015 14:08:46 +0200 Subject: [PATCH 88/98] edit plugin readme Issue #40 --- README.md | 6 ++-- plugins/README.md | 57 ++++++++++++++++++++++++++++++++++-- plugins/template/template.py | 33 +++++++++------------ 3 files changed, 72 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 1e8bd6ac..3c2ed6a2 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,8 @@ Thanks to smith_fms and McBo from Funkmeldesystem.de - Forum for Inspiration and ### Code your own Plugin -To code your own Plugin look at the litte example `/plugins/template/template.py` +See `plugins/README.md` -In the text-file `plugins/interface.txt` are all relevant data, that your plugin can use. +~~To code your own Plugin look at the litte example `/plugins/template/template.py`~~ + +~~In the text-file `plugins/interface.txt` are all relevant data, that your plugin can use.~~ diff --git a/plugins/README.md b/plugins/README.md index 71818be7..98b2edb0 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -2,7 +2,58 @@ More information and a little Tutorial coming soon! -##### Code your own Plugin -To code your own Plugin look at the litte example `/plugins/template/template.py` +### Plugin template +##### General +You can find a little template plugin file in `plugins/template/template.py` +##### .onLoad() +This onLoad() routine is called one time for initialize the plugin +##### .run() +This onLoad() routine is called every time an alarm comes in -In the text-file `plugins/interface.txt` are all relevant data, that your plugin can use. +### Use Global Logging +##### Init and Use +##### Choose right Loglevel + +### Use config file +##### Own configuration in config.ini +First you must set a new Section in `config.ini` +A section is between brackets. Its recommended to give the section the same name as the plugin. `[SECTION_NAME]` + +Now you can an set a unlimited number of options with its own value in these format: `OPTION = VALUE`. + +Here is the sample from the template plugin: +```python +[template] +test1 = testString +test2 = 123456 +``` + +##### Read data from config.ini +To read yout configuration data you must import the `globals.py` where the global config-object is located: +```python +from includes import globals # Global variables +``` + +Now you can get your configration data with: +```python +VALUE = globals.config.get("SECTION", "OPTION") #Gets any value +``` +or better, use this: +```python +VALUE = globals.config.getint("SECTION", "OPTION") #Value must be an Integer +VALUE = globals.config.getfloat("SECTION", "OPTION") #Value must be an Float +VALUE = globals.config.getboolean("SECTION", "OPTION") #Value must be an Boolean +``` + + +### Global helper functions +##### timeHandler.py +##### wildcardHandler.py + +### Process the data from BOSWatch +Three parameters are passed during the alarm to the .run() method +##### typ +Thats the function of the alarm. Possible values are **FMS**, **ZVEI** or **POC** +##### freq +The reception frequency of the tuner in Hz +##### data[ ] diff --git a/plugins/template/template.py b/plugins/template/template.py index 68581bcd..7218ced5 100644 --- a/plugins/template/template.py +++ b/plugins/template/template.py @@ -1,29 +1,24 @@ #!/usr/bin/python # -*- coding: cp1252 -*- -######### -# USAGE -# -# Config -# ====== -# to read a option from config File -# VALUE = globals.config.get("SECTION", "OPTION") +""" +template plugin to show the function and usage of plugins + +@author: Jens Herrmann +@author: Bastian Schroll + +@requires: none +""" + # -# Data from boswatch.py -# ===================== -# use data["KEY"] for Alarm Data from boswatch.py -# for usable KEYs in different Functions (FMS|ZVEI|POC) see interface.txt +# Imports # -# LOG Messages -# ============ -# send Log Messages with logging.LOGLEVEL("MESSAGE") -# usable Loglevels debug|info|warning|error|exception|critical -# if you use .exception in Try:Exception: Construct, it logs the Python EX.message too - import logging # Global logger - from includes import globals # Global variables -#from includes import helper #Global helper functions + +# Helper function, uncomment to use +#from includes.helper import timeHandler +#from includes.helper import wildcardHandler ## # From 3880227fc2f36a42a0bc491fd97cdb9c1bb13d1e Mon Sep 17 00:00:00 2001 From: Schrolli Date: Tue, 7 Jul 2015 14:24:41 +0200 Subject: [PATCH 89/98] edit plugin readme Issue #40 --- plugins/README.md | 75 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 19 deletions(-) diff --git a/plugins/README.md b/plugins/README.md index 98b2edb0..73101bd0 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -2,20 +2,53 @@ More information and a little Tutorial coming soon! -### Plugin template -##### General +### 1. Plugin template +##### 1.1 General You can find a little template plugin file in `plugins/template/template.py` -##### .onLoad() -This onLoad() routine is called one time for initialize the plugin -##### .run() -This onLoad() routine is called every time an alarm comes in -### Use Global Logging -##### Init and Use -##### Choose right Loglevel +##### 1.2 Plugin Init `.onLoad()` +This `.onLoad()` routine is called one time for initialize the plugin -### Use config file -##### Own configuration in config.ini +##### 1.3 Plugin call `.run()` +This `.run()` routine is called every time an alarm comes in + + +### 2. Use Global Logging +##### 2.1 Init and Use +First you must import the logging module +```python +import logging # Global logger +``` +Now you can send log messages with: + +```python +logging.LOGLEVEL("MESSAGE") +``` +You must replace the word `LOGLEVEL` with one if the following `debug`, `info`, `warning`, `error`, `exception` or `critical` + +To use the right loglevel see next section `2.2 Choose right Loglevel` + +##### 2.2 Choose right Loglevel +`debug` +all messages to find errors and for the internal program flow + +`info` +messages that serve only to inform the user + +`warning` + + +`error` +error does not lead to the end of boswatch + +`Exception` + +`critical` +errors leading to the end of boswatch immediate - in plugins not allowed + + +### 3. Use config file +##### 3.1 Own configuration in config.ini First you must set a new Section in `config.ini` A section is between brackets. Its recommended to give the section the same name as the plugin. `[SECTION_NAME]` @@ -28,7 +61,7 @@ test1 = testString test2 = 123456 ``` -##### Read data from config.ini +##### 3.2 Read data from config.ini To read yout configuration data you must import the `globals.py` where the global config-object is located: ```python from includes import globals # Global variables @@ -46,14 +79,18 @@ VALUE = globals.config.getboolean("SECTION", "OPTION") #Value must be an Boolean ``` -### Global helper functions -##### timeHandler.py -##### wildcardHandler.py +### 4. Global helper functions +##### 4.1 timeHandler.py +##### 4.2 wildcardHandler.py + -### Process the data from BOSWatch +### 5. Process the data from BOSWatch Three parameters are passed during the alarm to the .run() method -##### typ + +##### 5.1 typ Thats the function of the alarm. Possible values are **FMS**, **ZVEI** or **POC** -##### freq + +##### 5.2 freq The reception frequency of the tuner in Hz -##### data[ ] + +##### 5.3 data[ ] From 88bdaa2c29b5609ad1a75ad9c25c9fcf53c1b3cb Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 8 Jul 2015 07:30:09 +0200 Subject: [PATCH 90/98] edit plugin readme Issue #40 --- plugins/README.md | 118 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 20 deletions(-) diff --git a/plugins/README.md b/plugins/README.md index 73101bd0..2beb777c 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -1,20 +1,20 @@ -### How to Code your own plugin: +## How to Code your own plugin: More information and a little Tutorial coming soon! -### 1. Plugin template -##### 1.1 General +## 1. Plugin template +#### 1.1 General You can find a little template plugin file in `plugins/template/template.py` -##### 1.2 Plugin Init `.onLoad()` +#### 1.2 Plugin Init `.onLoad()` This `.onLoad()` routine is called one time for initialize the plugin -##### 1.3 Plugin call `.run()` +#### 1.3 Plugin call `.run()` This `.run()` routine is called every time an alarm comes in -### 2. Use Global Logging -##### 2.1 Init and Use +## 2. Use Global Logging +#### 2.1 Init and Use First you must import the logging module ```python import logging # Global logger @@ -28,7 +28,7 @@ You must replace the word `LOGLEVEL` with one if the following `debug`, `info`, To use the right loglevel see next section `2.2 Choose right Loglevel` -##### 2.2 Choose right Loglevel +#### 2.2 Choose right Loglevel `debug` all messages to find errors and for the internal program flow @@ -47,8 +47,8 @@ error does not lead to the end of boswatch errors leading to the end of boswatch immediate - in plugins not allowed -### 3. Use config file -##### 3.1 Own configuration in config.ini +## 3. Use config file +#### 3.1 Own configuration in config.ini First you must set a new Section in `config.ini` A section is between brackets. Its recommended to give the section the same name as the plugin. `[SECTION_NAME]` @@ -61,13 +61,13 @@ test1 = testString test2 = 123456 ``` -##### 3.2 Read data from config.ini +#### 3.2 Read data from config.ini To read yout configuration data you must import the `globals.py` where the global config-object is located: ```python from includes import globals # Global variables ``` -Now you can get your configration data with: +Now you can get your configuration data with: ```python VALUE = globals.config.get("SECTION", "OPTION") #Gets any value ``` @@ -79,18 +79,96 @@ VALUE = globals.config.getboolean("SECTION", "OPTION") #Value must be an Boolean ``` -### 4. Global helper functions -##### 4.1 timeHandler.py -##### 4.2 wildcardHandler.py +## 4. Global helper functions +#### 4.1 timeHandler.py +First you must include the helper file +```python +from includes.helper import timeHandler +``` +##### 4.1.1 `.curtime(format)` +```python +timeHandler.curtime() # returns a formated datetime string +``` +you can give the function an format string. See https://docs.python.org/2/library/time.html#time.strftime +default (without format parameter) the function returns a date time with this format `%d.%m.%Y %H:%M:%S` +##### 4.1.2 `.getDate()` +```python +timeHandler.getDate() # returns the current date in format `%d.%m.%Y` +``` +##### 4.1.3 `.getTime()` +```python +timeHandler.getTime() # returns the current time in format `%H:%M:%S` +``` +##### 4.1.4 `.getTimestamp()` +```python +timeHandler.getTimestamp() # returns the current linux timestamp +``` -### 5. Process the data from BOSWatch +#### 4.2 wildcardHandler.py +First you must include the helper file +```python +from includes.helper import wildcardHandler +``` +##### 4.2.1 'replaceWildcards(text,data)' +```python +wildcardHandler.replaceWildcards(text,data) # replace all standard wildcards +``` +replace all the standard wildcards in the given text +the function needs the data[ ] var + +defined wildcards: + +**General:** +- `%TIME%` = Time (by script) +- `%DATE%` = Date (by script) +- `%DESCR%` = Description from csv-file + +**FMS:** +- `%FMS%` = FMS Code +- `%STATUS%` = FMS Status +- `%DIR%` = Direction of the telegram (0/1) +- `%DIRT%` = Direction of the telegram (Text-String) +- `%TSI%` = Tactical Short Information (I-IV) + +**ZVEI:** +- `%ZVEI%` = ZVEI 5-tone Code + +**POCSAG:** +- `%RIC%` = Pocsag RIC +- `%FUNC%` = Pocsac function/Subric (1-4) +- `%FUNCCHAR%` = Pocsac function/Subric als character (a-d) +- `%MSG%` = Message of the Pocsag telegram +- `%BITRATE%` = Bitrate of the Pocsag telegram + +## 5. Process the data from BOSWatch Three parameters are passed during the alarm to the .run() method -##### 5.1 typ -Thats the function of the alarm. Possible values are **FMS**, **ZVEI** or **POC** +#### 5.1 typ +Thats the function of the alarm. Possible values are `FMS`, `ZVEI` or `POC` -##### 5.2 freq +#### 5.2 freq The reception frequency of the tuner in Hz -##### 5.3 data[ ] +#### 5.3 data[ ] +In the data map are the folowing informations: + +**ZVEI:** +- zvei +- description + +**FMS:** +- fms +- status +- direction +- directionText +- tsi +- description + +**POCSAG:** +- ric +- function +- functionChar +- msg +- bitrate +- description From 1ab3b61ef41b8ed7ff13b0febdc55ab4158aab93 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 8 Jul 2015 09:42:52 +0200 Subject: [PATCH 91/98] insert helper configHandler.py little edit in wildcardHandler.py error message --- includes/helper/configHandler.py | 37 ++++++++++++++++++++++++++++++ includes/helper/wildcardHandler.py | 4 ++-- 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 includes/helper/configHandler.py diff --git a/includes/helper/configHandler.py b/includes/helper/configHandler.py new file mode 100644 index 00000000..8dfe90ee --- /dev/null +++ b/includes/helper/configHandler.py @@ -0,0 +1,37 @@ +#!/usr/bin/python +# -*- coding: cp1252 -*- +# + +""" +little Helper to handle config data +for direct use in plugins to save code + +@author: Bastian Schroll +""" + +import logging +from includes import globals + + +def checkConfig(section=""): + """ + Reads the config option from an section and prints it to debug log + + @type section: string + @param section: Section name from config.ini + + @return: true (false if reading failed) + @exception: Exception if Error at read an debug + """ + try: + if section is not "": # read only data if section is given + logging.debug("read [%s] from config file", section) + + for key,val in globals.config.items(section): + logging.debug(" - %s = %s", key, val) + + return True + except: + logging.warning("error in config read/debug") + logging.debug("error in config read/debug", exc_info=True) + return False diff --git a/includes/helper/wildcardHandler.py b/includes/helper/wildcardHandler.py index a7895b93..1b85b969 100644 --- a/includes/helper/wildcardHandler.py +++ b/includes/helper/wildcardHandler.py @@ -55,5 +55,5 @@ def replaceWildcards(text,data): return text except: - logging.warning("error wildcard replacement") - logging.debug("error wildcard replacement", exc_info=True) + logging.warning("error in wildcard replacement") + logging.debug("error in wildcard replacement", exc_info=True) From 07872ac81776f05d9bf55e195f47303344ece906 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 8 Jul 2015 09:44:13 +0200 Subject: [PATCH 92/98] edit plugin readme Issue #40 remove interface.txt - all infos now in the plugins/readme.md --- plugins/README.md | 36 +++++++++---- plugins/interface.txt | 114 ------------------------------------------ 2 files changed, 27 insertions(+), 123 deletions(-) delete mode 100644 plugins/interface.txt diff --git a/plugins/README.md b/plugins/README.md index 2beb777c..7cc12fe6 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -4,7 +4,9 @@ More information and a little Tutorial coming soon! ## 1. Plugin template #### 1.1 General -You can find a little template plugin file in `plugins/template/template.py` +You can find a little template plugin file in `plugins/template/template.py` But you can also take a look in all other plugins. + +A plugin must be in an seperate folder with the same name of the .py file #### 1.2 Plugin Init `.onLoad()` This `.onLoad()` routine is called one time for initialize the plugin @@ -12,6 +14,8 @@ This `.onLoad()` routine is called one time for initialize the plugin #### 1.3 Plugin call `.run()` This `.run()` routine is called every time an alarm comes in +Here are the information from BOSWatch available. See section `5. Process the data from BOSWatch` + ## 2. Use Global Logging #### 2.1 Init and Use @@ -30,7 +34,7 @@ To use the right loglevel see next section `2.2 Choose right Loglevel` #### 2.2 Choose right Loglevel `debug` -all messages to find errors and for the internal program flow +all messages to find errors and for the internal program flow `info` messages that serve only to inform the user @@ -80,37 +84,51 @@ VALUE = globals.config.getboolean("SECTION", "OPTION") #Value must be an Boolean ## 4. Global helper functions -#### 4.1 timeHandler.py +#### 4.1 configHandler.py +First you must include the helper file +```python +from includes.helper import configHandler +``` +##### 4.1.1 `.checkConfig(section)` +This function read all options from a config section and prints it to the debug log. The return value is `true`, also the section var is empty. In case of error a `false` is returned and error printed to log. +```python +if configHandler.checkConfig("template"): #check config file + ########## User Plugin CODE ########## + pass +``` + + +#### 4.2 timeHandler.py First you must include the helper file ```python from includes.helper import timeHandler ``` -##### 4.1.1 `.curtime(format)` +##### 4.2.1 `.curtime(format)` ```python timeHandler.curtime() # returns a formated datetime string ``` you can give the function an format string. See https://docs.python.org/2/library/time.html#time.strftime default (without format parameter) the function returns a date time with this format `%d.%m.%Y %H:%M:%S` -##### 4.1.2 `.getDate()` +##### 4.2.2 `.getDate()` ```python timeHandler.getDate() # returns the current date in format `%d.%m.%Y` ``` -##### 4.1.3 `.getTime()` +##### 4.2.3 `.getTime()` ```python timeHandler.getTime() # returns the current time in format `%H:%M:%S` ``` -##### 4.1.4 `.getTimestamp()` +##### 4.2.4 `.getTimestamp()` ```python timeHandler.getTimestamp() # returns the current linux timestamp ``` -#### 4.2 wildcardHandler.py +#### 4.3 wildcardHandler.py First you must include the helper file ```python from includes.helper import wildcardHandler ``` -##### 4.2.1 'replaceWildcards(text,data)' +##### 4.3.1 `.replaceWildcards(text,data)` ```python wildcardHandler.replaceWildcards(text,data) # replace all standard wildcards ``` diff --git a/plugins/interface.txt b/plugins/interface.txt deleted file mode 100644 index 73ecbec5..00000000 --- a/plugins/interface.txt +++ /dev/null @@ -1,114 +0,0 @@ -Handover to Plugin: -------------------- -typ = [FMS|ZVEI|POC] -freq = [Freq in Hz] -data = {"KEY1":"VALUE1","KEY2":"VALUE2"} - -The following informations are included in the var "data". -They can be used by their Index Names: data['OPTION'] - -ZVEI: -- zvei -- description - -FMS: -- fms -- status -- direction -- directionText -- tsi -- description - -POCSAG: -- ric -- function -- functionChar -- msg -- bitrate -- description - - -Global Objects: ---------------- - -1.) -import logging # Global logger -Message into Log: logging.LOGLEVEL("MESSAGE") -Loglevel: debug|info|warning|error|exception|critical - -2.) -import globals # Global variables -reads Data from the config.ini -VALUE = globals.config.get("SECTION", "OPTION") - - -General for plugins: --------------------- -All Plugins have to implement the following functions (see template.py): - -def onLoad(): - """ - While loading the plugins by pluginLoader.loadPlugins() - this onLoad() routine is called one time for initialize the plugin - - @requires: nothing - - @return: nothing - @exception: Exception if init has an fatal error so that the plugin couldn't work - - """ - -def run(typ,freq,data): - """ - This function is the implementation of the Plugin. - - If necessary the configuration hast to be set in the config.ini. - - @type typ: string (FMS|ZVEI|POC) - @param typ: Typ of the dataset - @type data: map of data (structure see interface.txt) - @param data: Contains the parameter for dispatch - @type freq: string - @keyword freq: frequency of the SDR Stick - - @requires: If necessary the configuration hast to be set in the config.ini. - - @return: nothing - @exception: nothing, make sure this function will never thrown an exception - """ - - -Global Functions for plugins: ------------------------------ - -# for format see https://docs.python.org/2/library/time.html#time.strftime -# -from includes.helper import timeHandler -timeHandler.curtime("FORMAT") # without format string the function returns with "%d.%m.%Y %H:%M:%S" -timeHandler.getDate() # Gets the date in "%d.%m.%Y" -timeHandler.getTime() # Gets the time in %H:%M:%S -timeHandler.getTimestamp() # Gets a integer timestamp - - -# replace all the standard wildcards in the given text -# the function needs the data[] var -# %TIME% = Time (by script) -# %DATE% = Date (by script) -# -# %FMS% = FMS Code -# %STATUS% = FMS Status -# %DIR% = Direction of the telegram (0/1) -# %DIRT% = Direction of the telegram (Text-String) -# %TSI% = Tactical Short Information (I-IV) -# -# %ZVEI% = ZVEI 5-tone Code -# -# %RIC% = Pocsag RIC -# %FUNC% = Pocsac function/Subric (1-4) -# %FUNCCHAR% = Pocsac function/Subric als character (a-d) -# %MSG% = Message of the Pocsag telegram -# %BITRATE% = Bitrate of the Pocsag telegram -# %DESCR% = Description from csv-file -# -from includes.helper import wildcardHandler -wildcardHandler.replaceWildcards("TEXT",data[]) From 49b93daa959bd6cd5188cebc6e7695f7f343d64e Mon Sep 17 00:00:00 2001 From: Schrolli Date: Wed, 8 Jul 2015 09:45:36 +0200 Subject: [PATCH 93/98] use configHandler.checkConfig() helper in template plugin for demonstration --- plugins/template/template.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/plugins/template/template.py b/plugins/template/template.py index 7218ced5..33401c26 100644 --- a/plugins/template/template.py +++ b/plugins/template/template.py @@ -3,6 +3,9 @@ """ template plugin to show the function and usage of plugins +feel free to edit to yout own plugin +please edit theese desciption, the @author-Tag and the @requires-Tag +For more information take a look into the other plugins @author: Jens Herrmann @author: Bastian Schroll @@ -19,6 +22,7 @@ # Helper function, uncomment to use #from includes.helper import timeHandler #from includes.helper import wildcardHandler +from includes.helper import configHandler ## # @@ -72,14 +76,7 @@ def run(typ,freq,data): # # ConfigParser # - logging.debug("reading config file") - try: - for key,val in globals.config.items("template"): - logging.debug(" - %s = %s", key, val) - except: - logging.error("cannot read config file") - logging.debug("cannot read config file", exc_info=True) - else: # Without config, plugin couldn't work + if configHandler.checkConfig("template"): #read and debug the config (let empty if no config used) ########## User Plugin CODE ########## if typ == "FMS": From cbb9481c5ccbfdfd9de9e3fb592d2df52de05791 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 9 Jul 2015 07:09:32 +0200 Subject: [PATCH 94/98] edit plugin readme Issue #40 --- plugins/README.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/plugins/README.md b/plugins/README.md index 7cc12fe6..f14a3b9a 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -28,27 +28,25 @@ Now you can send log messages with: ```python logging.LOGLEVEL("MESSAGE") ``` -You must replace the word `LOGLEVEL` with one if the following `debug`, `info`, `warning`, `error`, `exception` or `critical` +You must replace the word `LOGLEVEL` with one if the following `debug`, `info`, `warning` or `error` To use the right loglevel see next section `2.2 Choose right Loglevel` #### 2.2 Choose right Loglevel `debug` -all messages to find errors and for the internal program flow +all messages to find errors and for the internal program flow. `info` -messages that serve only to inform the user +messages that serve only to inform the user. `warning` - +Warnings are notes and technical errors. Never leads to terminate BOSWatch. `error` -error does not lead to the end of boswatch - -`Exception` +An error that does not necessarily lead to end of BOSWatch, but an administrator intervention required. `critical` -errors leading to the end of boswatch immediate - in plugins not allowed +errors leading to the end of boswatch immediate - **in plugins not allowed** (Plugin cannot crash the entire program) ## 3. Use config file From 76686e016c62c308b6b258d53239086bcd2b48bb Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 9 Jul 2015 07:52:21 +0200 Subject: [PATCH 95/98] insert configHandler.checkConfig() helper in all plugins so save always same code --- plugins/BosMon/BosMon.py | 14 +++----------- plugins/MySQL/MySQL.py | 14 +++----------- plugins/eMail/eMail.py | 15 +++------------ plugins/firEmergency/firEmergency.py | 14 +++----------- plugins/httpRequest/httpRequest.py | 14 +++----------- plugins/jsonSocket/jsonSocket.py | 15 +++------------ plugins/template/template.py | 3 --- 7 files changed, 18 insertions(+), 71 deletions(-) diff --git a/plugins/BosMon/BosMon.py b/plugins/BosMon/BosMon.py index 2072e7cd..8ccb7b00 100644 --- a/plugins/BosMon/BosMon.py +++ b/plugins/BosMon/BosMon.py @@ -19,6 +19,8 @@ from includes import globals # Global variables +from includes.helper import configHandler + ## # # onLoad (init) function of plugin @@ -98,17 +100,7 @@ def run(typ,freq,data): @return: nothing """ try: - # - # ConfigParser - # - logging.debug("reading config file") - try: - for key,val in globals.config.items("BosMon"): - logging.debug(" - %s = %s", key, val) - except: - logging.error("cannot read config file") - logging.debug("cannot read config file", exc_info=True) - else: # Without config, plugin couldn't work + if configHandler.checkConfig("BosMon"): #read and debug the config try: # diff --git a/plugins/MySQL/MySQL.py b/plugins/MySQL/MySQL.py index b545dced..39cab728 100644 --- a/plugins/MySQL/MySQL.py +++ b/plugins/MySQL/MySQL.py @@ -18,6 +18,8 @@ from includes import globals # Global variables +from includes.helper import configHandler + ## # # onLoad (init) function of plugin @@ -62,17 +64,7 @@ def run(typ,freq,data): @return: nothing """ try: - # - #ConfigParser - # - logging.debug("reading config file") - try: - for key,val in globals.config.items("MySQL"): - logging.debug(" - %s = %s", key, val) - except: - logging.error("cannot read config file") - logging.debug("cannot read config file", exc_info=True) - else: # Without config, plugin couldn't work + if configHandler.checkConfig("MySQL"): #read and debug the config try: # diff --git a/plugins/eMail/eMail.py b/plugins/eMail/eMail.py index 586696ab..f7c74480 100644 --- a/plugins/eMail/eMail.py +++ b/plugins/eMail/eMail.py @@ -18,7 +18,9 @@ from email.utils import make_msgid # need for confirm to RFC2822 standard from includes import globals # Global variables + from includes.helper import timeHandler # helper function +from includes.helper import configHandler ## # @@ -95,18 +97,7 @@ def run(typ,freq,data): @return: nothing """ try: - # - # ConfigParser - # - logging.debug("reading config file") - try: - for key,val in globals.config.items("eMail"): - logging.debug(" - %s = %s", key, val) - - except: - logging.error("cannot read config file") - logging.debug("cannot read config file", exc_info=True) - else: # Without config, plugin couldn't work + if configHandler.checkConfig("eMail"): #read and debug the config try: # diff --git a/plugins/firEmergency/firEmergency.py b/plugins/firEmergency/firEmergency.py index d62dcb4c..84fefa3f 100644 --- a/plugins/firEmergency/firEmergency.py +++ b/plugins/firEmergency/firEmergency.py @@ -17,6 +17,8 @@ from includes import globals # Global variables +from includes.helper import configHandler + ### # # onLoad (init) function of plugin @@ -59,17 +61,7 @@ def run(typ,freq,data): @return: nothing """ try: - # - #ConfigParser - # - logging.debug("reading config file") - try: - for key,val in globals.config.items("firEmergency"): - logging.debug(" - %s = %s", key, val) - except: - logging.error("cannot read config file") - logging.debug("cannot read config file", exc_info=True) - else: # Without config, plugin couldn't work + if configHandler.checkConfig("firEmergency"): #read and debug the config try: # diff --git a/plugins/httpRequest/httpRequest.py b/plugins/httpRequest/httpRequest.py index df165434..fd6815bc 100644 --- a/plugins/httpRequest/httpRequest.py +++ b/plugins/httpRequest/httpRequest.py @@ -15,8 +15,10 @@ from urlparse import urlparse #for split the URL into url and path from includes import globals # Global variables + from includes.helper import timeHandler from includes.helper import wildcardHandler +from includes.helper import configHandler ## # @@ -58,17 +60,7 @@ def run(typ,freq,data): @return: nothing """ try: - # - # ConfigParser - # - logging.debug("reading config file") - try: - for key,val in globals.config.items("httpRequest"): - logging.debug(" - %s = %s", key, val) - except: - logging.error("cannot read config file") - logging.debug("cannot read config file", exc_info=True) - else: # Without config, plugin couldn't work + if configHandler.checkConfig("httpRequest"): #read and debug the config try: # diff --git a/plugins/jsonSocket/jsonSocket.py b/plugins/jsonSocket/jsonSocket.py index 1445aa9f..4bb7162b 100644 --- a/plugins/jsonSocket/jsonSocket.py +++ b/plugins/jsonSocket/jsonSocket.py @@ -16,6 +16,8 @@ from includes import globals # Global variables +from includes.helper import configHandler + ## # # onLoad (init) function of plugin @@ -58,18 +60,7 @@ def run(typ,freq,data): @return: nothing """ try: - # - # ConfigParser - # - logging.debug("reading config file") - try: - for key,val in globals.config.items("jsonSocket"): - logging.debug(" - %s = %s", key, val) - - except: - logging.error("cannot read config file") - logging.debug("cannot read config file", exc_info=True) - else: # Without config, plugin couldn't work + if configHandler.checkConfig("jsonSocket"): #read and debug the config try: # diff --git a/plugins/template/template.py b/plugins/template/template.py index 33401c26..148fb44c 100644 --- a/plugins/template/template.py +++ b/plugins/template/template.py @@ -73,9 +73,6 @@ def run(typ,freq,data): @exception: nothing, make sure this function will never thrown an exception """ try: - # - # ConfigParser - # if configHandler.checkConfig("template"): #read and debug the config (let empty if no config used) ########## User Plugin CODE ########## From bd6432b1e58beaa375af7a52ddee017727f97bd0 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 9 Jul 2015 08:04:55 +0200 Subject: [PATCH 96/98] Fix error in pluginLoader.py see Issue #52 --- includes/pluginLoader.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/includes/pluginLoader.py b/includes/pluginLoader.py index 1adc4bd9..a79a7791 100644 --- a/includes/pluginLoader.py +++ b/includes/pluginLoader.py @@ -35,18 +35,19 @@ def loadPlugins(): logging.error("error loading plugin: %s", i["name"]) logging.debug("error loading plugin: %s", i["name"], exc_info=True) pass - - try: - # Try to call the .onLoad() routine for all active plugins - logging.debug("call %s.onLoad()", i["name"]) - plugin.onLoad() - # Add it to globals.pluginList - globals.pluginList[i["name"]] = plugin - except: - # call next plugin, if one has thrown an exception - logging.error("error calling %s.onLoad()", i["name"]) - logging.debug("error calling %s.onLoad()", exc_info=True) - pass + else: # only call onLoad() and insert into pluginList[] if import is succesfull + + try: + # Try to call the .onLoad() routine for all active plugins + logging.debug("call %s.onLoad()", i["name"]) + plugin.onLoad() + # Add it to globals.pluginList + globals.pluginList[i["name"]] = plugin + except: + # call next plugin, if one has thrown an exception + logging.error("error calling %s.onLoad()", i["name"]) + logging.debug("error calling %s.onLoad()", exc_info=True) + pass except: logging.error("cannot load plugins") logging.debug("cannot load plugins", exc_info=True) From 0eebab4564659438772bcee5d45b13eb54a28cb6 Mon Sep 17 00:00:00 2001 From: Schrolli Date: Thu, 9 Jul 2015 08:29:01 +0200 Subject: [PATCH 97/98] remove trailing whitespaces in testdata.txt --- testdata/testdata.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/testdata/testdata.txt b/testdata/testdata.txt index 6f121c7e..58e5a5e6 100644 --- a/testdata/testdata.txt +++ b/testdata/testdata.txt @@ -1,4 +1,4 @@ -# Testdata for the BOSWatch Test Mode function +# Testdata for the BOSWatch Test Mode function # Data in Multimon-NG Raw Format # Data is alternately passed to the decoder to simulate an used Radio-Frequency @@ -7,7 +7,7 @@ # ------ # # The following settings in config.ini are expected for POCSAG -# +# # [BOSWatch] # useDescription = 1 # doubleFilter_ignore_entries = 10 @@ -54,12 +54,12 @@ POCSAG1200: Address: 2000001 Function: 2 Alpha: BOSWatch-Test: second is a d POCSAG1200: Address: 2000001 Function: 2 Alpha: BOSWatch-Testing: okay # duplicate in different order -POCSAG1200: Address: 2100000 Function: 2 -POCSAG1200: Address: 2100001 Function: 2 -POCSAG1200: Address: 2100002 Function: 2 -POCSAG1200: Address: 2100000 Function: 2 -POCSAG1200: Address: 2100001 Function: 2 -POCSAG1200: Address: 2100002 Function: 2 +POCSAG1200: Address: 2100000 Function: 2 +POCSAG1200: Address: 2100001 Function: 2 +POCSAG1200: Address: 2100002 Function: 2 +POCSAG1200: Address: 2100000 Function: 2 +POCSAG1200: Address: 2100001 Function: 2 +POCSAG1200: Address: 2100002 Function: 2 POCSAG1200: Address: 2100000 Function: 2 Alpha: BOSWatch-Test: second is a duplicate POCSAG1200: Address: 2100001 Function: 2 Alpha: BOSWatch-Test: second is a duplicate POCSAG1200: Address: 2100002 Function: 2 Alpha: BOSWatch-Test: second is a duplicate From 1ea5cce24ea993dc04f29ae02210b854b1714b0f Mon Sep 17 00:00:00 2001 From: Schrolli Date: Mon, 13 Jul 2015 09:42:54 +0200 Subject: [PATCH 98/98] edit build date --- includes/globals.py | 4 ++-- plugins/README.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/includes/globals.py b/includes/globals.py index 4d26d44a..0cc0c5e6 100644 --- a/includes/globals.py +++ b/includes/globals.py @@ -31,6 +31,6 @@ # function -> read only in script def getVers(mode="vers"): if mode == "vers": - return "2.0-RC" + return "2.0" elif mode == "date": - return " 2015/07/06" + return " 2015/07/13" diff --git a/plugins/README.md b/plugins/README.md index f14a3b9a..260d0282 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -167,6 +167,7 @@ Thats the function of the alarm. Possible values are `FMS`, `ZVEI` or `POC` The reception frequency of the tuner in Hz #### 5.3 data[ ] +You can get an information with `data["INFO"]` In the data map are the folowing informations: **ZVEI:**
Datum - Zeit Schleife
". $zvei['id'] . "". $time . "