diff --git a/config/config.template.ini b/config/config.template.ini index be5484b..d943faf 100644 --- a/config/config.template.ini +++ b/config/config.template.ini @@ -49,7 +49,7 @@ doubleFilter_ignore_time = 5 doubleFilter_check_msg = 0 # writes the multimon-ng raw data stream into a text file named mm_raw.txt -writeMultimonRaw = 1 +writeMultimonRaw = 0 [NMAHandler] # you can use a logging handler for sending logging records to NotifyMyAndroid @@ -169,6 +169,8 @@ tableSIG = bos_signal [httpRequest] # example URL http://example.com/remote.php?DESCR=%DESCR% +# multiple URLs can be separated by comma + # you can use the following wildcards in your URL as GET params: # http://en.wikipedia.org/wiki/Query_string @@ -413,13 +415,46 @@ RICforLocationAPIKey = # Required if you want to create a map based on location information received with the above RIC. GoogleAPIKey = +# %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) +# %DESCR% = Description, if description-module is used +# %DATE% = Date (by script) +# %TIME% = Time (by script) +# %LPAR% = ( +# %RPAR% = ) +FMS_message = %DATE% %TIME%: %FMS% + +# %ZVEI% = ZVEI 5-tone Code +# %DESCR% = Description, if description-module is used +# %DATE% = Date (by script) +# %TIME% = Time (by script) +# %LPAR% = ( +# %RPAR% = ) +ZVEI_message = %DATE% %TIME%: %ZVEI% + +# %RIC% = POCSAG RIC +# %FUNC% = POCSAG function/Subric (1-4) +# %FUNCCHAR% = POCSAG function/Subric als character (a-d) +# %MSG% = Message of the POCSAG telegram +# %BITRATE% = Bitrate of the POCSAG telegram +# %DESCR% = Description, if description-module is used +# %DATE% = Date (by script) +# %TIME% = Time (by script) +# %LPAR% = ( +# %RPAR% = ) +POC_message = %MSG% + + [yowsup] # number or chat-number who whants to become the news -empfaenger = +empfaenger = # WhatsApp-number of that the news comes -sender = +sender = # password from this number -password= +password= # %FMS% = FMS Code # %STATUS% = FMS Status diff --git a/csv/fms.csv b/csv/fms.template.csv similarity index 100% rename from csv/fms.csv rename to csv/fms.template.csv diff --git a/csv/nma.csv b/csv/nma.template.csv similarity index 100% rename from csv/nma.csv rename to csv/nma.template.csv diff --git a/csv/poc.csv b/csv/poc.template.csv similarity index 100% rename from csv/poc.csv rename to csv/poc.template.csv diff --git a/csv/zvei.csv b/csv/zvei.template.csv similarity index 100% rename from csv/zvei.csv rename to csv/zvei.template.csv diff --git a/includes/decoders/poc.py b/includes/decoders/poc.py index 46be042..b0198f0 100644 --- a/includes/decoders/poc.py +++ b/includes/decoders/poc.py @@ -126,7 +126,7 @@ def decode(freq, decoded): # If enabled, look up description if globalVars.config.getint("POC", "idDescribed"): from includes import descriptionList - data["description"] = descriptionList.getDescription("POC", poc_id) + data["description"] = descriptionList.getDescription("POC", poc_id+data["functionChar"]) # processing the alarm try: from includes import alarmHandler diff --git a/includes/descriptionList.py b/includes/descriptionList.py index cca894f..848d39a 100644 --- a/includes/descriptionList.py +++ b/includes/descriptionList.py @@ -11,6 +11,7 @@ Function to expand the dataset with a description. import logging # Global logger import csv # for loading the description files +import re # for matching IDs with a regular expression from includes import globalVars # Global variables from includes.helper import stringConverter @@ -41,10 +42,10 @@ def loadCSV(typ, idField): reader = csv.DictReader(csvfile) for row in reader: logging.debug(row) - # only import rows with an integer as id - if row[idField].isdigit() == True: + # only import rows with an integer as id, allow subrics though + if re.match("^[0-9]+[A-D]?$", row[idField], re.IGNORECASE): try: - resultList[row[idField]] = stringConverter.convertToUTF8(row['description']) + resultList[row[idField].lower()] = stringConverter.convertToUTF8(row['description']) except: # skip entry in case of an exception pass @@ -112,7 +113,8 @@ def getDescription(typ, data): resultStr = zveiDescribtionList[data] elif typ == "POC": global ricDescribtionList - resultStr = ricDescribtionList[data] + resultStr = ricDescribtionList[data[:-1]] # MainRIC + resultStr += " " + ricDescribtionList[data] # SubRIC else: logging.warning("Invalid Typ: %s", typ) diff --git a/includes/globalVars.py b/includes/globalVars.py index 9be0fac..2cdcfa7 100644 --- a/includes/globalVars.py +++ b/includes/globalVars.py @@ -9,7 +9,7 @@ Global variables """ # version info -versionNr = "2.2" +versionNr = "2.2-dev" buildDate = "2017/03/30" # Global variables diff --git a/includes/helper/wildcardHandler.py b/includes/helper/wildcardHandler.py index d67dde2..e85e6f8 100644 --- a/includes/helper/wildcardHandler.py +++ b/includes/helper/wildcardHandler.py @@ -17,7 +17,7 @@ from includes import globalVars from includes.helper import timeHandler -def replaceWildcards(text, data, lineBrakeAllowed=False): +def replaceWildcards(text, data): """ Replace all official Wildcards with the Information from the data[] var @@ -25,8 +25,6 @@ def replaceWildcards(text, data, lineBrakeAllowed=False): @param text: Input text with wildcards @type data: map @param data: map of data (structure see readme.md in plugin folder) - @type lineBrakeAllowed: Boolean - @param lineBrakeAllowed: switch to allow lineBreak (%BR%) as wildcard @return: text with replaced wildcards @exception: Exception if Error at replace @@ -36,8 +34,7 @@ def replaceWildcards(text, data, lineBrakeAllowed=False): text = text.replace("%TIME%", timeHandler.getTime(data["timestamp"])).replace("%DATE%", timeHandler.getDate(data["timestamp"])) # replace some special chars - if lineBrakeAllowed == True: - text = text.replace("%BR%", "\r\n") + text = text.replace("%BR%", "\r\n") text = text.replace("%LPAR%", "(") text = text.replace("%RPAR%", ")") diff --git a/plugins/MySQL/MySQL.py b/plugins/MySQL/MySQL.py index 02be083..5941571 100644 --- a/plugins/MySQL/MySQL.py +++ b/plugins/MySQL/MySQL.py @@ -111,9 +111,9 @@ def run(typ,freq,data): elif typ == "POC": if isSignal(data["ric"]): - cursor.execute("UPDATE "+globalVars.config.get("MySQL","tableSIG")+" SET time = NOW() WHERE ric = "+data["ric"]) + cursor.execute("UPDATE "+globalVars.config.get("MySQL","tableSIG")+" SET time = NOW() WHERE ric = '"+data["ric"]+"';") if cursor.rowcount == 0: - cursor.execute("INSERT INTO "+globalVars.config.get("MySQL","tableSIG")+" (time,ric) VALUES (NOW(),"+data["ric"]+")") + cursor.execute("INSERT INTO "+globalVars.config.get("MySQL","tableSIG")+" (time,ric) VALUES (NOW(), '"+data["ric"]+"');") else: cursor.execute("INSERT INTO "+globalVars.config.get("MySQL","tablePOC")+" (time, ric, function, functionChar, msg, bitrate, description) VALUES (FROM_UNIXTIME(%s),%s,%s,%s,%s,%s,%s)", (data["timestamp"], data["ric"], data["function"], data["functionChar"], data["msg"], data["bitrate"], data["description"])) diff --git a/plugins/MySQL/boswatch.sql b/plugins/MySQL/boswatch.sql index 8a88c68..6f93861 100644 --- a/plugins/MySQL/boswatch.sql +++ b/plugins/MySQL/boswatch.sql @@ -104,44 +104,6 @@ CREATE TABLE IF NOT EXISTS `bos_signal` ( PRIMARY KEY (`ID`) ) ENGINE=MYISAM DEFAULT CHARSET=UTF8 AUTO_INCREMENT=1; --- -------------------------------------------------------- - --- --- Schedule für Tabelle `bos_pocsag` --- -CREATE EVENT IF NOT EXISTS `Delete POCSAG Entries > 3 Months` - ON SCHEDULE EVERY 1 DAY - STARTS '2016-01-01 00:00:00' - ON COMPLETION PRESERVE ENABLE - DO - DELETE FROM bos_pocsag WHERE time < DATE_SUB(NOW(),INTERVAL 3 MONTH); - --- -------------------------------------------------------- - --- --- Schedule für Tabelle `bos_fms` --- - -CREATE EVENT IF NOT EXISTS `Delete FMS Entries > 3 Months` - ON SCHEDULE EVERY 1 DAY - STARTS '2016-01-01 00:00:00' - ON COMPLETION PRESERVE ENABLE - DO - DELETE FROM bos_fms WHERE time < DATE_SUB(NOW(),INTERVAL 3 MONTH); - --- -------------------------------------------------------- - --- --- Schedule für Tabelle `bos_zvei` --- - -CREATE EVENT IF NOT EXISTS `Delete ZVEI Entries > 3 Months` - ON SCHEDULE EVERY 1 DAY - STARTS '2016-01-01 00:00:00' - ON COMPLETION PRESERVE ENABLE - DO - DELETE FROM bos_zvei WHERE time < DATE_SUB(NOW(),INTERVAL 3 MONTH); - /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; diff --git a/plugins/MySQL/boswatch_cleanup.sql b/plugins/MySQL/boswatch_cleanup.sql new file mode 100644 index 0000000..eb3fcb0 --- /dev/null +++ b/plugins/MySQL/boswatch_cleanup.sql @@ -0,0 +1,40 @@ +-- Cleanup-routines for boswatch-tables + +use boswatch; +-- -------------------------------------------------------- + +-- +-- Schedule für Tabelle `bos_pocsag` +-- +CREATE EVENT IF NOT EXISTS `Delete POCSAG Entries > 3 Months` + ON SCHEDULE EVERY 1 DAY + STARTS '2016-01-01 00:00:00' + ON COMPLETION PRESERVE ENABLE + DO + DELETE FROM bos_pocsag WHERE time < DATE_SUB(NOW(),INTERVAL 3 MONTH); + +-- -------------------------------------------------------- + +-- +-- Schedule für Tabelle `bos_fms` +-- + +CREATE EVENT IF NOT EXISTS `Delete FMS Entries > 3 Months` + ON SCHEDULE EVERY 1 DAY + STARTS '2016-01-01 00:00:00' + ON COMPLETION PRESERVE ENABLE + DO + DELETE FROM bos_fms WHERE time < DATE_SUB(NOW(),INTERVAL 3 MONTH); + +-- -------------------------------------------------------- + +-- +-- Schedule für Tabelle `bos_zvei` +-- + +CREATE EVENT IF NOT EXISTS `Delete ZVEI Entries > 3 Months` + ON SCHEDULE EVERY 1 DAY + STARTS '2016-01-01 00:00:00' + ON COMPLETION PRESERVE ENABLE + DO + DELETE FROM bos_zvei WHERE time < DATE_SUB(NOW(),INTERVAL 3 MONTH); diff --git a/plugins/Sms77/Sms77.py b/plugins/Sms77/Sms77.py index 9fb4943..e4353d1 100644 --- a/plugins/Sms77/Sms77.py +++ b/plugins/Sms77/Sms77.py @@ -58,6 +58,20 @@ def run(typ,freq,data): """ try: if configHandler.checkConfig("Sms77"): #read and debug the config + + # create an empty message an fill it with the required information + message = "Alarm" + if typ == "FMS": + logging.debug("FMS detected, building message") + message = data["description"]+"
"+data["status"] + elif typ == "ZVEI": + logging.debug("ZVEI detected, building message") + message = data["zvei"]+" - "+data["description"] + elif typ == "POC": + logging.debug("POC detected, building message") + message = data["description"]+"
"+data["msg"].replace(";", "
") + else: + logging.warning("Invalid typ - use empty message") try: @@ -74,7 +88,7 @@ def run(typ,freq,data): "to": globalVars.config.get("Sms77", "to"), "from": globalVars.config.get("Sms77", "from"), "type": globalVars.config.get("Sms77", "type"), - "text": data["description"]+"
"+data["msg"].replace(";", "
") + "text": message }),{"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}) except: diff --git a/plugins/Telegram/Telegram.py b/plugins/Telegram/Telegram.py index 0d890c8..fc4acc7 100644 --- a/plugins/Telegram/Telegram.py +++ b/plugins/Telegram/Telegram.py @@ -16,8 +16,8 @@ from telegram.error import (TelegramError, Unauthorized, BadRequest, NetworkErro from includes import globalVars # Global variables # Helper function, uncomment to use +from includes.helper import wildcardHandler from includes.helper import configHandler -from includes.helper import timeHandler # local variables BOTTokenAPIKey = None @@ -78,20 +78,21 @@ def run(typ,freq,data): try: ########## User Plugin CODE ########## try: - if typ == "POC": - logging.debug("Compose output from POCSAG-message") + if typ in ("POC", "FMS", "ZVEI"): + logging.debug("Read format and compose output for %s-message" % typ) # compose message content - output = timeHandler.curtime()+"\n"+data["ric"]+"("+data["functionChar"]+")\n"+data["description"]+"\n"+data["msg"] + text = globalVars.config.get("Telegram", "%s_message" % typ) + text = wildcardHandler.replaceWildcards(text, data) # Initiate Telegram Bot logging.debug("Initiate Telegram BOT") bot = telegram.Bot(token='%s' % BOTTokenAPIKey) # Send message to chat via Telegram BOT API logging.debug("Send message to chat via Telegram BOT API") - bot.sendMessage('%s' % BOTChatIDAPIKey, output) + bot.sendMessage('%s' % BOTChatIDAPIKey, text) # Generate location information only for specific RIC - if data["ric"] == RICforLocationAPIKey: + if typ == "POC" and data["ric"] == RICforLocationAPIKey: # Generate map logging.debug("Extract address from POCSAG message") address = "+".join(data["msg"].split(')')[0].split('/',1)[1].replace('(',' ').split()) @@ -113,28 +114,6 @@ def run(typ,freq,data): gcode_result = gcode.geocode(address) logging.debug("Send location via Telegram BOT API") bot.sendLocation('%s' % BOTChatIDAPIKey, gcode_result[0]['geometry']['location']['lat'], gcode_result[0]['geometry']['location']['lng'], disable_notification='true') - elif typ == "FMS": - logging.debug("Compose output from FMS-message") - # compose message content - output = timeHandler.curtime()+"\n"+data["fms"]+"\n"+data["description"]+"\n"+data["status"] - - # Initiate Telegram Bot - logging.debug("Initiate Telegram BOT") - bot = telegram.Bot(token='%s' % BOTTokenAPIKey) - # Send message to chat via Telegram BOT API - logging.debug("Send message to chat via Telegram BOT API") - bot.sendMessage('%s' % BOTChatIDAPIKey, output) - elif typ == "ZVEI": - logging.debug("Compose output from ZVEI-message") - # compose message content - output = timeHandler.curtime()+"\n"+data["zvei"]+"\n"+data["description"] - - # Initiate Telegram Bot - logging.debug("Initiate Telegram BOT") - bot = telegram.Bot(token='%s' % BOTTokenAPIKey) - # Send message to chat via Telegram BOT API - logging.debug("Send message to chat via Telegram BOT API") - bot.sendMessage('%s' % BOTChatIDAPIKey, output) else: logging.warning("Invalid Typ: %s", typ) except Unauthorized: diff --git a/plugins/eMail/eMail.py b/plugins/eMail/eMail.py index d054c85..ec271b2 100644 --- a/plugins/eMail/eMail.py +++ b/plugins/eMail/eMail.py @@ -137,7 +137,7 @@ def run(typ,freq,data): # read mailtext-structure from config.ini mailtext = globalVars.config.get("eMail", "fms_message") # replace wildcards with helper function - mailtext = wildcardHandler.replaceWildcards(mailtext, data, lineBrakeAllowed=True) + mailtext = wildcardHandler.replaceWildcards(mailtext, data) # send eMail doSendmail(server, subject, mailtext) @@ -157,7 +157,7 @@ def run(typ,freq,data): # read mailtext-structure from config.ini mailtext = globalVars.config.get("eMail", "zvei_message") # replace wildcards with helper function - mailtext = wildcardHandler.replaceWildcards(mailtext, data, lineBrakeAllowed=True) + mailtext = wildcardHandler.replaceWildcards(mailtext, data) # send eMail doSendmail(server, subject, mailtext) @@ -177,7 +177,7 @@ def run(typ,freq,data): # read mailtext-structure from config.ini mailtext = globalVars.config.get("eMail", "poc_message") # replace wildcards with helper function - mailtext = wildcardHandler.replaceWildcards(mailtext, data, lineBrakeAllowed=True) + mailtext = wildcardHandler.replaceWildcards(mailtext, data) # send eMail doSendmail(server, subject, mailtext) diff --git a/plugins/httpRequest/httpRequest.py b/plugins/httpRequest/httpRequest.py index 3d8d90e..744f621 100644 --- a/plugins/httpRequest/httpRequest.py +++ b/plugins/httpRequest/httpRequest.py @@ -14,6 +14,7 @@ httpRequest-Plugin to dispatch FMS-, ZVEI- and POCSAG - messages to an URL # # Imports # +import urllib import urllib2 import logging # Global logger from includes import globalVars # Global variables @@ -67,36 +68,41 @@ def run(typ,freq,data): try: # - # Create URL + # Replace special characters in data Strings for URL + # + for key in data: + if isinstance(data[key], basestring): + data[key] = urllib.quote(data[key]) + # + # Get URLs # if typ == "FMS": - url = globalVars.config.get("httpRequest", "fms_url") #Get URL - url = wildcardHandler.replaceWildcards(url, data) # replace wildcards with helper function - url = url.replace(" ","%20") # replace space with %20 to be a vaild http request + urls = globalVars.config.get("httpRequest", "fms_url").split(",") elif typ == "ZVEI": - url = globalVars.config.get("httpRequest", "zvei_url") #Get URL - url = wildcardHandler.replaceWildcards(url, data) # replace wildcards with helper function - url = url.replace(" ","%20") # replace space with %20 to be a vaild http request + urls = globalVars.config.get("httpRequest", "zvei_url").split(",") elif typ == "POC": - url = globalVars.config.get("httpRequest", "poc_url") #Get URL - url = wildcardHandler.replaceWildcards(url, data) # replace wildcards with helper function - url = url.replace(" ","%20") # replace space with %20 to be a vaild http request + urls = globalVars.config.get("httpRequest", "poc_url").split(",") else: logging.warning("Invalid Typ: %s", typ) return # + # replace wildcards + # + for (i, url) in enumerate(urls): + urls[i] = wildcardHandler.replaceWildcards(urls[i].strip(), data) + # # HTTP-Request # - logging.debug("send %s HTTP request", typ) + logging.debug("send %s HTTP requests", typ) - try: - #resp = urllib2.urlopen(url) - urllib2.urlopen(url) - except urllib2.HTTPError as e: - logging.warning("HTTP response: %s", e.code) - except urllib2.URLError as e: - logging.warning("HTTP-specific error: %s", e.args) + for url in urls: + try: + urllib2.urlopen(url) + except urllib2.HTTPError as e: + logging.warning("HTTP response: %s", e.code) + except urllib2.URLError as e: + logging.warning("HTTP-specific error: %s", e.args) except: logging.error("cannot send HTTP request") diff --git a/service/README.md b/service/README.md index 3057ee4..41337a9 100644 --- a/service/README.md +++ b/service/README.md @@ -1,3 +1,20 @@ +### Use BOSWatch as service ### + +Old description below + +We assume that BOSWatch is installed to /opt/boswatch! Otherwise you need to adapt all the pathes in this description and in the service-file itself. + +#### Adapt the script +Enter the frequency and the decoder(s) you want to use in line 7; you can add more specific switches if you need to + +### Install the service +1. Copy the file to /lib/systemd/system: sudo cp /opt/boswatch/service/boswatch.service /lib/systemd/system/ +2. Change the rights: sudo chmod 644 /lib/systemd/system/boswatch.service +3. Enable the service: sudo systemcl enable boswatch.service +4. Start the service: sudo systemcl start boswatch.service + +--- + ### Start BOSWatch as a daemon ##### Changing the init script diff --git a/service/boswatch.service b/service/boswatch.service new file mode 100644 index 0000000..80c440b --- /dev/null +++ b/service/boswatch.service @@ -0,0 +1,11 @@ +[Unit] +Description=BOSWatch +After=multi-user.target + +[Service] +Type=simple +ExecStart=/usr/bin/python /opt/boswatch/boswatch.py -f 123.45M -a POC512 +Restart=on-abort + +[Install] +WantedBy=multi-user.target