From f6e25d77b4e306056ee8d74502019a2d45b9a327 Mon Sep 17 00:00:00 2001 From: JHCD Date: Thu, 25 Jun 2015 21:19:41 +0200 Subject: [PATCH] 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 e52a17e..cdc05fb 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 3a667fe..89fb795 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 da78fe3..25ef0ed 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 347987a..23c0d0f 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 13ce7ab..52ac28f 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 7814e59..4997281 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 02da649..ee0329f 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 ceba913..b0ab005 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 e941e75..ca4dea4 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 ebee2bd..6c94a66 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 2f105c9..dfbcac4 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 50f40ab..ce0ec54 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 7ad599d..82e898a 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