From f1f6503198e27c8fc35ceeccf3c937675ff42298 Mon Sep 17 00:00:00 2001 From: JHCD Date: Fri, 5 Jun 2015 21:49:51 +0200 Subject: [PATCH] new functionality: lookUp description in a given csv-file for FMS, ZVEI and POC you have the possibility to set a discription for every FMS, ZWEI oder RIC address descriptions will be imported via csv-files if enabled BOSWatch will look up the description and could be used in the plugins eMail-plugin extended wildcards to use describtion %DESC% --- boswatch.py | 9 +++- config/config.template.ini | 101 ++++++++++++++++++++--------------- csv/fms.csv | 10 ++++ csv/poc.csv | 10 ++++ csv/zvei.csv | 10 ++++ includes/decoders/fms.py | 7 ++- includes/decoders/poc.py | 7 ++- includes/decoders/zvei.py | 7 ++- includes/descriptionList.py | 102 ++++++++++++++++++++++++++++++++++++ includes/globals.py | 8 ++- plugins/eMail/eMail.py | 6 +++ plugins/interface.txt | 3 ++ 12 files changed, 234 insertions(+), 46 deletions(-) create mode 100644 csv/fms.csv create mode 100644 csv/poc.csv create mode 100644 csv/zvei.csv create mode 100644 includes/descriptionList.py diff --git a/boswatch.py b/boswatch.py index 320a19d..c6e8b2e 100755 --- a/boswatch.py +++ b/boswatch.py @@ -106,7 +106,7 @@ try: myLogger = logging.getLogger() myLogger.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 [%(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) #Starts with log level >= Debug @@ -220,6 +220,13 @@ try: 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 diff --git a/config/config.template.ini b/config/config.template.ini index 0a7ebec..64d2137 100644 --- a/config/config.template.ini +++ b/config/config.template.ini @@ -3,69 +3,86 @@ ######################## [BOSWatch] -#set loglevel for logfile -#10 = debug -#20 = info -#30 = warning -#40 = error -#50 = critical +# set loglevel for logfile +# 10 = debug +# 20 = info +# 30 = warning +# 40 = error +# 50 = critical loglevel = 10 -#BOSWatch use a rotating logfile -#Rotating is at midnight -#You can set the backupCount here -#backupCount = 7 (keeps logfiles for a week) +# BOSWatch use a rotating logfile +# Rotating is at midnight +# You can set the backupCount here +# backupCount = 7 (keeps logfiles for a week) backupCount = 7 -#Using RegEx-Filter (0|1) -#Filter-configuration in section [Filters] +# Using RegEx-Filter (0|1) +# 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 + [FMS] -#time to ignore same alarm in a row (sek) +# 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 + [ZVEI] -#time to ignore same alarm in a row (sek) +# 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) +# 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 +# some very simple filters: +# Allow only this RICs (empty: allow all, separator ",") +# f.e.: allow_ric = 1234566,1234567,1234568 allow_ric = -#Deny this RICs (empty: allow all, separator ",") -#f.e.: deny_ric = 1234566,1234567,1234568 + +# Deny this RICs (empty: allow all, separator ",") +# f.e.: deny_ric = 1234566,1234567,1234568 deny_ric = -#start and end of an allowed filter range +# start and end of an allowed filter range filter_range_start = 0000000 filter_range_end = 9999999 +# look-up-table for adding a description +# turn on functionality (0|1) +idDescribed = 0 + [Filters] -#RegEX Filter Configuration -#http://www.regexr.com/ - RegEX Test Tool an Documentation -#No Filter for a Typ/Plugin Combination = all Data pass -#INDIVIDUAL_NAME = TYP;DATAFIELD;PLUGIN;FREQUENZ;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 +# RegEX Filter Configuration +# http://www.regexr.com/ - RegEX Test Tool an Documentation +# No Filter for a Typ/Plugin Combination = all Data pass +# INDIVIDUAL_NAME = TYP;DATAFIELD;PLUGIN;FREQUENZ;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 +# only ZVEI to all Plugins with 25### at 85.5MHz #testfilter = ZVEI;zvei;*;85500000;25[0-9]{3} -#only POCSAG to MySQL with the text "ALARM:" in the Message +# only POCSAG to MySQL with the text "ALARM:" in the Message #pocTest = POC;msg;MySQL;*;ALARM: [Plugins] -#can take on or off the plugins (0|1) +# can take on or off the plugins (0|1) MySQL = 0 httpRequest = 0 eMail = 0 @@ -77,22 +94,23 @@ template = 0 [MySQL] +# MySQL configuration dbserver = localhost dbuser = root dbpassword = root database = boswatch -#tables in the database +# tables in the database tableFMS = bos_fms tableZVEI = bos_zvei tablePOC = bos_pocsag [httpRequest] -#URL without http:// +# URL without http:// -#you can use the following wildcards in your URL as GET params: -#http://en.wikipedia.org/wiki/Query_string +# you can use the following wildcards in your URL as GET params: +# http://en.wikipedia.org/wiki/Query_string # %FMS% = FMS Code # %STATUS% = FMS Status @@ -158,20 +176,21 @@ poc_message = %TIME%: %MSG% [BosMon] -#Server as IP of DNS-Name (without http://) -#actually no ssl supported +# Server as IP of DNS-Name (without http://) +# actually no ssl supported bosmon_server = 192.168.0.1 bosmon_port = 80 -#channel-name of typ "Web-Telegramm" +# channel-name of typ "Web-Telegramm" bosmon_channel = channel -#Use this, when BosMon has restricted access +# Use this, when BosMon has restricted access bosmon_user = bosmon_password = [firEmergency] +# firEmergency configuration firserver = localhost firport = 9001 diff --git a/csv/fms.csv b/csv/fms.csv new file mode 100644 index 0000000..e52a17e --- /dev/null +++ b/csv/fms.csv @@ -0,0 +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 !!! +# +93377141,"John Q. Publics car" \ No newline at end of file diff --git a/csv/poc.csv b/csv/poc.csv new file mode 100644 index 0000000..3a667fe --- /dev/null +++ b/csv/poc.csv @@ -0,0 +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 !!! +# +1234567,"John Q. Public" \ No newline at end of file diff --git a/csv/zvei.csv b/csv/zvei.csv new file mode 100644 index 0000000..da78fe3 --- /dev/null +++ b/csv/zvei.csv @@ -0,0 +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 !!! +# +25832,"John Q. Public" \ No newline at end of file diff --git a/includes/decoders/fms.py b/includes/decoders/fms.py index 737b158..cc542b9 100644 --- a/includes/decoders/fms.py +++ b/includes/decoders/fms.py @@ -53,7 +53,12 @@ def decode(freq, decoded): globals.fms_time_old = timestamp #in case of double alarm, fms_double_ignore_time set new 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} + 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 from includes import alarmHandler alarmHandler.processAlarm("FMS",freq,data) diff --git a/includes/decoders/poc.py b/includes/decoders/poc.py index 3aab240..f40bc40 100644 --- a/includes/decoders/poc.py +++ b/includes/decoders/poc.py @@ -110,9 +110,14 @@ def decode(freq, decoded): 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} + 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 from includes import alarmHandler alarmHandler.processAlarm("POC",freq,data) diff --git a/includes/decoders/zvei.py b/includes/decoders/zvei.py index 1d87f12..8d24ac0 100644 --- a/includes/decoders/zvei.py +++ b/includes/decoders/zvei.py @@ -44,7 +44,12 @@ def decode(freq, decoded): globals.zvei_time_old = timestamp #in case of double alarm, zvei_double_ignore_time set new else: logging.info("5-Ton: %s", zvei_id) - data = {"zvei":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 from includes import alarmHandler alarmHandler.processAlarm("ZVEI",freq,data) diff --git a/includes/descriptionList.py b/includes/descriptionList.py new file mode 100644 index 0000000..c65c091 --- /dev/null +++ b/includes/descriptionList.py @@ -0,0 +1,102 @@ +#!/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 + +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 + @exception: Exception if loading failed + """ + 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.exception("loading csvList for typ: %s failed", typ) + 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.exception("cannot load description lists") + + +## +# +# 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 + return resultStr \ No newline at end of file diff --git a/includes/globals.py b/includes/globals.py index b96e81b..46aa5fc 100644 --- a/includes/globals.py +++ b/includes/globals.py @@ -26,4 +26,10 @@ poc_time_old = 0 pluginList = {} #filter -filterList = [] \ No newline at end of file +filterList = [] + +#idDescribing +fmsDescribtionList = {} +zveiDescribtionList = {} +ricDescribtionList = {} + diff --git a/plugins/eMail/eMail.py b/plugins/eMail/eMail.py index 842d013..24477a5 100644 --- a/plugins/eMail/eMail.py +++ b/plugins/eMail/eMail.py @@ -125,12 +125,14 @@ def run(typ,freq,data): 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) @@ -143,10 +145,12 @@ def run(typ,freq,data): # 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) @@ -161,12 +165,14 @@ def run(typ,freq,data): 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) diff --git a/plugins/interface.txt b/plugins/interface.txt index 821729d..f2e8c01 100644 --- a/plugins/interface.txt +++ b/plugins/interface.txt @@ -9,6 +9,7 @@ They can be used by their Index Names: data['OPTION'] ZVEI: - zvei +- description FMS: - fms @@ -16,6 +17,7 @@ FMS: - direction - directionText - tsi +- description POCSAG: - ric @@ -23,6 +25,7 @@ POCSAG: - functionChar - msg - bitrate +- description Global Objects: