mirror of
https://github.com/Schrolli91/BOSWatch.git
synced 2025-12-06 07:42:03 +01:00
commit
2b89d49e7d
27
CHANGELOG.md
27
CHANGELOG.md
|
|
@ -1,7 +1,27 @@
|
|||
# Changelog
|
||||
|
||||
|
||||
### __[v2.3.1]__ - Unreleased
|
||||
### __[v#.#]__ - date
|
||||
##### Added
|
||||
- Telegram-Plugin: In der generierten Übersichtkarte wird eine Anfahrtsroute integriert. Der Abfahrtsort ist konfiguierbar. [#382](https://github.com/Schrolli91/BOSWatch/pull/382)
|
||||
##### Changed
|
||||
- Telegram-Plugin: Aufrufe der Google API erfolgen per SSL und ohne zusätzliche Bibliotheken [#382](https://github.com/Schrolli91/BOSWatch/pull/382)
|
||||
##### Deprecated
|
||||
##### Removed
|
||||
##### Fixed
|
||||
##### Security
|
||||
|
||||
|
||||
### __[v2.4.1]__ - 23.10.2018
|
||||
##### Added
|
||||
- Pushover-Plugin: Priorität für einzelne RIC und ZVEI in config einstellbar [#378](https://github.com/Schrolli91/BOSWatch/pull/378)
|
||||
##### Changed
|
||||
- Kleinere Anpassungen im Telegram Plugin (Karten-Generierung) [#380](https://github.com/Schrolli91/BOSWatch/pull/380)
|
||||
##### Removed
|
||||
- Notify-my-Andoird Plugin und Logging-Handler wegen Einstellung des Service entfernt [#374](https://github.com/Schrolli91/BOSWatch/pull/374)
|
||||
|
||||
|
||||
### __[v2.4]__ - 17.08.2018
|
||||
##### Added
|
||||
- Config Eintrag um Port für MySQL Plugin festzulegen [#345](https://github.com/Schrolli91/BOSWatch/pull/345)
|
||||
- FMS und ZVEI Support für Pushover Plugin [#352](https://github.com/Schrolli91/BOSWatch/pull/352)
|
||||
|
|
@ -9,13 +29,10 @@
|
|||
##### Changed
|
||||
- multicastAlarm Plugin - RICs die von multicastAlarm genutzt werden, müssen nicht mehr in der config bei allow_ric bzw. filter_range_start/filter_range_end berücksichtigt werden. [#357](https://github.com/Schrolli91/BOSWatch/pull/357)
|
||||
- FFAgent Plugin - Debug Logging für die alarmHeaders eingebaut zwecks Troubleshooting [#354](https://github.com/Schrolli91/BOSWatch/pull/354)
|
||||
- multicastAlarm Plugin - Buffer nach jedem Alarm löschen - erlaubt in kombination mit "doubleFilter_check_msg" die Verwendung in Netzen, die zwischen multicastAlarm RICs auch normale Alarme senden. #370(https://github.com/Schrolli91/BOSWatch/pull/370)
|
||||
##### Deprecated
|
||||
##### Removed
|
||||
- multicastAlarm Plugin - Buffer nach jedem Alarm löschen - erlaubt in kombination mit "doubleFilter_check_msg" die Verwendung in Netzen, die zwischen multicastAlarm RICs auch normale Alarme senden. [#370](https://github.com/Schrolli91/BOSWatch/pull/370)
|
||||
##### Fixed
|
||||
- Fehler beim Auslesen der netIdent_RIC im MySQL Plugin [#347](https://github.com/Schrolli91/BOSWatch/pull/347)
|
||||
- FFAgent Plugin - Typo bei alarmHeaders für Live Betrieb gefixt [#354](https://github.com/Schrolli91/BOSWatch/pull/354)
|
||||
##### Security
|
||||
|
||||
|
||||
### __[v2.3]__ - 22.12.2017
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
### Fast support on https://bwcc.boswatch.de (Mattermost-Server)
|
||||
#### Forum: https://boswatch.de
|
||||
|
||||
### Arbeiten an BOSWatch 3 gestartet
|
||||
#### Work on BOSWatch 3 has started
|
||||
## see: https://boswatch.de/index.php?thread/29-boswatch-3/
|
||||
|
|
|
|||
23
boswatch.py
23
boswatch.py
|
|
@ -249,29 +249,6 @@ try:
|
|||
logging.debug("cannot set loglevel of fileHandler", exc_info=True)
|
||||
|
||||
|
||||
#
|
||||
# Add NMA logging handler
|
||||
#
|
||||
try:
|
||||
if configHandler.checkConfig("NMAHandler"):
|
||||
# is NMAHandler enabled?
|
||||
if globalVars.config.getboolean("NMAHandler", "enableHandler") == True:
|
||||
# we only could do something, if an APIKey is given:
|
||||
if len(globalVars.config.get("NMAHandler","APIKey")) > 0:
|
||||
logging.debug("add NMA logging handler")
|
||||
from includes import NMAHandler
|
||||
if globalVars.config.get("NMAHandler","appName") == "":
|
||||
nmaHandler = NMAHandler.NMAHandler(globalVars.config.get("NMAHandler","APIKey"))
|
||||
else:
|
||||
nmaHandler = NMAHandler.NMAHandler(globalVars.config.get("NMAHandler","APIKey"), globalVars.config.get("NMAHandler","appName"))
|
||||
nmaHandler.setLevel(globalVars.config.getint("NMAHandler","loglevel"))
|
||||
myLogger.addHandler(nmaHandler)
|
||||
except:
|
||||
# It's an error, but we could work without that stuff...
|
||||
logging.error("cannot add NMA logging handler")
|
||||
logging.debug("cannot add NMA logging handler", exc_info=True)
|
||||
|
||||
|
||||
# initialization was fine, continue with main program...
|
||||
|
||||
#
|
||||
|
|
|
|||
|
|
@ -64,22 +64,6 @@ doubleFilter_check_msg = 0
|
|||
writeMultimonRaw = 0
|
||||
|
||||
|
||||
[NMAHandler]
|
||||
# you can use a logging handler for sending logging records to NotifyMyAndroid
|
||||
# enableHandler (0|1) will enable the NMA handler
|
||||
enableHandler = 0
|
||||
|
||||
# loglevel for NMAHandler (see BOSWatch loglevel description)
|
||||
loglevel = 50
|
||||
|
||||
# logging record will send to APIKey
|
||||
APIKey =
|
||||
|
||||
# you can change the name of the application (default: BOSWatch)
|
||||
# (f.e. if you use more than one instance of BOSWatch)
|
||||
appName = BOSWatch
|
||||
|
||||
|
||||
[FMS]
|
||||
# look-up-table for adding a description
|
||||
# using description (0 - off | 1 - on)
|
||||
|
|
@ -177,7 +161,6 @@ eMail = 0
|
|||
BosMon = 0
|
||||
firEmergency = 0
|
||||
jsonSocket = 0
|
||||
notifyMyAndroid = 0
|
||||
SMS = 0
|
||||
Sms77 = 0
|
||||
FFAgent = 0
|
||||
|
|
@ -287,23 +270,6 @@ server = 192.168.0.1
|
|||
port = 8888
|
||||
|
||||
|
||||
[notifyMyAndroid]
|
||||
# APIKey given from notifyMyAndroid
|
||||
APIKey =
|
||||
|
||||
# Priority goes from -2 (lowest) to 2 (highest). The default priority is 0 (normal)
|
||||
priority = 0
|
||||
|
||||
# You can change the name of the application (default: BOSWatch)
|
||||
# (f.e. if you use more than one instance of BOSWatch)
|
||||
appName = BOSWatch
|
||||
|
||||
# instead of a given APIKey/priority you could import them by a csv-file (0|1)
|
||||
# APIKey and priority above will be ignored, if you use a csv
|
||||
# configuration loaded from csv/nma.csv
|
||||
usecsv = 0
|
||||
|
||||
|
||||
[SMS]
|
||||
# be aware that you need 'gammu' installed and running
|
||||
# at least you need an UMTS-stick which is supported by 'gammu'
|
||||
|
|
@ -383,11 +349,30 @@ SubA = 1
|
|||
SubB = 1
|
||||
SubC = 2
|
||||
SubD = -2
|
||||
|
||||
# ...or define the priority depending on the RIC
|
||||
# 1. switch it on
|
||||
poc_spec_ric = 0
|
||||
|
||||
# 2. fill the following lists, seperator is ,
|
||||
poc_prio2 =
|
||||
poc_prio1 =
|
||||
poc_prio0 =
|
||||
|
||||
poc_title = Alarm: %RIC%%LPAR%%FUNCCHAR%%RPAR%
|
||||
poc_message = %DATE% %TIME% - %DESCR%: %MSG%
|
||||
|
||||
# Section for ZVEI
|
||||
zvei_prio = 1
|
||||
# default prio for all ZVEI - except you specify it different
|
||||
zvei_std_prio = 1
|
||||
|
||||
# [1 - on, 0 - off] - by switching on you can list certain ZVEI depending on their priority
|
||||
zvei_sep_prio = 0
|
||||
|
||||
# use the following lists, separator is ,
|
||||
zvei_prio2 =
|
||||
zvei_prio1 =
|
||||
zvei_prio0 =
|
||||
zvei_title = Alarm: %ZVEI%
|
||||
zvei_message = %DATE% %TIME%: %ZVEI%
|
||||
|
||||
|
|
@ -418,6 +403,9 @@ RICforLocationAPIKey =
|
|||
# This is your Google API key.
|
||||
# Required if you want to create a map based on location information received with the above RIC.
|
||||
GoogleAPIKey =
|
||||
# Define your start address for the routing
|
||||
# Use the following format: CityOfOrigin+Street+Number
|
||||
RoutingOrigin = MyCity+MyStreet+MyNumber
|
||||
|
||||
#Wildcards can be used, see end of the file!
|
||||
FMS_message = %DATE% %TIME%: %FMS%
|
||||
|
|
|
|||
|
|
@ -1,73 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
"""
|
||||
Logging Handler for NotifyMyAndroid
|
||||
|
||||
@author: Jens Herrmann
|
||||
"""
|
||||
|
||||
import logging
|
||||
from includes.pynma import pynma
|
||||
|
||||
class NMAHandler(logging.Handler): # Inherit from logging.Handler
|
||||
"""
|
||||
Handler instances dispatch logging events to NotifyMyAndroid.
|
||||
"""
|
||||
|
||||
def __init__(self, APIKey, application="BOSWatch", event="Logging-Handler"):
|
||||
"""
|
||||
Initializes the handler with NMA-specific parameters.
|
||||
|
||||
@param APIKey: might be a string containing 1 key or an array of keys
|
||||
@param application: application name [256]
|
||||
@param event: event name [1000]
|
||||
"""
|
||||
# run the regular Handler __init__
|
||||
logging.Handler.__init__(self)
|
||||
# Our custom argument
|
||||
self.APIKey = APIKey
|
||||
self.application = application
|
||||
self.event = event
|
||||
self.nma = pynma.PyNMA(self.APIKey)
|
||||
|
||||
|
||||
def emit(self, record):
|
||||
"""
|
||||
Send logging record via NMA
|
||||
"""
|
||||
# record.message is the log message
|
||||
message = record.message
|
||||
|
||||
# if exist, add details as NMA event:
|
||||
# record.module is the module- or filename
|
||||
if (len(record.module) > 0):
|
||||
event = "Module: " + record.module
|
||||
# record.functionName is the name of the function
|
||||
# will be "<module>" if the message is not in a function
|
||||
if len(record.funcName) > 0:
|
||||
if not record.funcName == "<module>":
|
||||
event += " - " + record.funcName + "()"
|
||||
else:
|
||||
# we have to set an event-text, use self.event now
|
||||
event = self.event
|
||||
|
||||
# record.levelno is the log level
|
||||
# loglevel: 10 = debug => priority: -2
|
||||
# loglevel: 20 = info => priority: -1
|
||||
# loglevel: 30 = warning => priority: 0
|
||||
# loglevel: 40 = error => priority: 1
|
||||
# loglevel: 50 = critical => priority: 2
|
||||
if record.levelno >= 50:
|
||||
priority = 2
|
||||
elif record.levelno >= 40:
|
||||
priority = 1
|
||||
elif record.levelno >= 30:
|
||||
priority = 0
|
||||
elif record.levelno >= 20:
|
||||
priority = -1
|
||||
else:
|
||||
priority = -2
|
||||
|
||||
# pynma.push(self, application="", event="", description="", url="", contenttype=None, priority=0, batch_mode=False, html=False)
|
||||
self.nma.push(application=self.application, event=event, description=message, priority=priority)
|
||||
|
|
@ -9,7 +9,7 @@ Global variables
|
|||
"""
|
||||
|
||||
# version info
|
||||
versionNr = "2.3.1"
|
||||
versionNr = "2.4.1"
|
||||
branch = "dev"
|
||||
buildDate = "unreleased"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,137 +0,0 @@
|
|||
Pynma
|
||||
======
|
||||
|
||||
Pynma is a simple python module for the [NotifyMyAndroid][nma] [API][NMA API].
|
||||
|
||||
[nma]: http://nma.usk.bz/
|
||||
[NMA API]: http://nma.usk.bz/api.php
|
||||
|
||||
Credits to: Damien Degois (github.com/babs)
|
||||
Refactoring: Adriano Maia (adriano@usk.bz)
|
||||
|
||||
[NotifyMyAndroid][nma]
|
||||
---------------
|
||||
NotifyMyAndroid is a Prowl-like application for the Android. Notifications can be sent from your application Android device using push. NMA has an extensive API, which allows your scripts to integrate beautifully. (source: http://nma.usk.bz/)
|
||||
|
||||
### How it works:
|
||||
First, import the module:
|
||||
|
||||
import pynma
|
||||
|
||||
#### Keys management
|
||||
|
||||
Create a PyNMA simple instance:
|
||||
|
||||
p = pynma.PyNMA( "apikey(s)", "developerkey")
|
||||
|
||||
A developerkey is optional. If you'd like to add just one API key, set it as string, if you want more, just provide a list of API key strings.
|
||||
|
||||
p = pynma.PyNMA(['apikey1','apikey2']) # multiple API keys
|
||||
p = pynma.PyNMA("apikey1","providerkey") # 1 API key with a providerkey
|
||||
|
||||
For more flexible usage, you can add and remove keys:
|
||||
|
||||
p.addkey("apikey1")
|
||||
p.addkey(["apikey2","apikey3"])
|
||||
|
||||
Or set or change the providerkey
|
||||
|
||||
p.developerkey("developerkey")
|
||||
|
||||
#### Notification or Push or Add
|
||||
|
||||
p.push(application, event, description, (opt) url, (opt) priority, (opt) batch mode)
|
||||
|
||||
##### Application
|
||||
|
||||
Application is your message generating application name (limited to 256)
|
||||
|
||||
ex: my music player
|
||||
|
||||
##### Event
|
||||
|
||||
Event is the event name (limited to 1000)
|
||||
|
||||
ex: switched to next track
|
||||
|
||||
##### Description
|
||||
|
||||
The description is the payload of your message (limited to 10000 (10k))
|
||||
ex:
|
||||
|
||||
Playing next song, Blah Blah Blah
|
||||
Artist: blah blah
|
||||
Album: blah blah
|
||||
Track: 18/24
|
||||
|
||||
##### Url
|
||||
|
||||
The URL which should be attached to the notification.
|
||||
This will trigger a redirect when on the user's device launched, and is viewable in the notification list.
|
||||
|
||||
##### Priority
|
||||
|
||||
Priority goes from -2 (lowest) to 2 (highest). the default priority is 0 (normal)
|
||||
|
||||
##### Batch mode
|
||||
|
||||
Batch mode is a boolean value to set if you'd like to push the same message to multiple API keys 5 by 5 (as the actual verion of prowl API allows you). This can reduce the number of call you make to the API which are limited.
|
||||
|
||||
#### Return
|
||||
|
||||
The push method returns a dict containing different values depending of the success of you call:
|
||||
|
||||
##### The call succeed
|
||||
|
||||
you'll have in the dict those keys:
|
||||
|
||||
type: success
|
||||
code: the HTTP like code (200 if success)
|
||||
remaining: the number of API call you can to until the reset
|
||||
resetdate: number of remaining minutes till the hourly reset of your API call limit
|
||||
|
||||
##### The call failed
|
||||
|
||||
For wathever reason, you call failed, the dict key "message" will contains the erro message returned by Prowl API. You'll find those keys:
|
||||
|
||||
code: 400, 401, 402 or 500 (depends of the error kind)
|
||||
message: API error message
|
||||
|
||||
For the code description, please refer to [NMA API documentation][NMA API] for more informations
|
||||
|
||||
##### The python module encountered an unhandled problem (mostly during parsing)
|
||||
|
||||
The return keys will be:
|
||||
|
||||
code: 600
|
||||
type: pynmaerror
|
||||
message: the exception message
|
||||
|
||||
Thanks
|
||||
------
|
||||
|
||||
* **Cev** for URL integration and some fixes in docstring
|
||||
* **ChaoticXSinZ** for UTF-8 integration and other typos
|
||||
|
||||
License (MIT)
|
||||
-------------
|
||||
|
||||
Copyright (c) 2010-2011, Damien Degois.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
from .pynma import PyNMA
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
from xml.dom.minidom import parseString
|
||||
|
||||
try:
|
||||
from http.client import HTTPSConnection
|
||||
except ImportError:
|
||||
from httplib import HTTPSConnection
|
||||
|
||||
try:
|
||||
from urllib.parse import urlencode
|
||||
except ImportError:
|
||||
from urllib import urlencode
|
||||
|
||||
__version__ = "1.0"
|
||||
|
||||
API_SERVER = 'www.notifymyandroid.com'
|
||||
ADD_PATH = '/publicapi/notify'
|
||||
|
||||
USER_AGENT="PyNMA/v%s"%__version__
|
||||
|
||||
def uniq_preserve(seq): # Dave Kirby
|
||||
# Order preserving
|
||||
seen = set()
|
||||
return [x for x in seq if x not in seen and not seen.add(x)]
|
||||
|
||||
def uniq(seq):
|
||||
# Not order preserving
|
||||
return list({}.fromkeys(seq).keys())
|
||||
|
||||
class PyNMA(object):
|
||||
"""PyNMA(apikey=[], developerkey=None)
|
||||
takes 2 optional arguments:
|
||||
- (opt) apykey: might me a string containing 1 key or an array of keys
|
||||
- (opt) developerkey: where you can store your developer key
|
||||
"""
|
||||
|
||||
def __init__(self, apikey=[], developerkey=None):
|
||||
self._developerkey = None
|
||||
self.developerkey(developerkey)
|
||||
if apikey:
|
||||
if isinstance(apikey, str):
|
||||
apikey = [apikey]
|
||||
self._apikey = uniq(apikey)
|
||||
|
||||
def addkey(self, key):
|
||||
"Add a key (register ?)"
|
||||
if isinstance(key, str):
|
||||
if not key in self._apikey:
|
||||
self._apikey.append(key)
|
||||
elif isinstance(key, list):
|
||||
for k in key:
|
||||
if not k in self._apikey:
|
||||
self._apikey.append(k)
|
||||
|
||||
def delkey(self, key):
|
||||
"Removes a key (unregister ?)"
|
||||
if isinstance(key, str):
|
||||
if key in self._apikey:
|
||||
self._apikey.remove(key)
|
||||
elif isinstance(key, list):
|
||||
for k in key:
|
||||
if key in self._apikey:
|
||||
self._apikey.remove(k)
|
||||
|
||||
def developerkey(self, developerkey):
|
||||
"Sets the developer key (and check it has the good length)"
|
||||
if isinstance(developerkey, str) and len(developerkey) == 48:
|
||||
self._developerkey = developerkey
|
||||
|
||||
def pushWithAPIKey(self, apikey=[], application="", event="", description="", url="", contenttype=None, priority=0, batch_mode=False, html=False):
|
||||
"""Special Funktion"""
|
||||
if apikey:
|
||||
if isinstance(apikey, str):
|
||||
apikey = [apikey]
|
||||
self._apikey = uniq(apikey)
|
||||
return self.push(application, event, description, url, contenttype, priority, batch_mode, html)
|
||||
|
||||
def push(self, application="", event="", description="", url="", contenttype=None, priority=0, batch_mode=False, html=False):
|
||||
"""Pushes a message on the registered API keys.
|
||||
takes 5 arguments:
|
||||
- (req) application: application name [256]
|
||||
- (req) event: event name [1000]
|
||||
- (req) description: description [10000]
|
||||
- (opt) url: url [512]
|
||||
- (opt) contenttype: Content Type (act: None (plain text) or text/html)
|
||||
- (opt) priority: from -2 (lowest) to 2 (highest) (def:0)
|
||||
- (opt) batch_mode: push to all keys at once (def:False)
|
||||
- (opt) html: shortcut for contenttype=text/html
|
||||
Warning: using batch_mode will return error only if all API keys are bad
|
||||
cf: http://nma.usk.bz/api.php
|
||||
"""
|
||||
datas = {
|
||||
'application': application[:256].encode('utf8'),
|
||||
'event': event[:1024].encode('utf8'),
|
||||
'description': description[:10000].encode('utf8'),
|
||||
'priority': priority
|
||||
}
|
||||
|
||||
if url:
|
||||
datas['url'] = url[:512]
|
||||
|
||||
if contenttype == "text/html" or html == True: # Currently only accepted content type
|
||||
datas['content-type'] = "text/html"
|
||||
|
||||
if self._developerkey:
|
||||
datas['developerkey'] = self._developerkey
|
||||
|
||||
results = {}
|
||||
|
||||
if not batch_mode:
|
||||
for key in self._apikey:
|
||||
datas['apikey'] = key
|
||||
res = self.callapi('POST', ADD_PATH, datas)
|
||||
results[key] = res
|
||||
else:
|
||||
datas['apikey'] = ",".join(self._apikey)
|
||||
res = self.callapi('POST', ADD_PATH, datas)
|
||||
results[datas['apikey']] = res
|
||||
return results
|
||||
|
||||
def callapi(self, method, path, args):
|
||||
headers = { 'User-Agent': USER_AGENT }
|
||||
if method == "POST":
|
||||
headers['Content-type'] = "application/x-www-form-urlencoded"
|
||||
http_handler = HTTPSConnection(API_SERVER)
|
||||
http_handler.request(method, path, urlencode(args), headers)
|
||||
resp = http_handler.getresponse()
|
||||
|
||||
try:
|
||||
res = self._parse_reponse(resp.read())
|
||||
except Exception as e:
|
||||
res = {'type': "pynmaerror",
|
||||
'code': 600,
|
||||
'message': str(e)
|
||||
}
|
||||
|
||||
return res
|
||||
|
||||
def _parse_reponse(self, response):
|
||||
root = parseString(response).firstChild
|
||||
for elem in root.childNodes:
|
||||
if elem.nodeType == elem.TEXT_NODE: continue
|
||||
if elem.tagName == 'success':
|
||||
res = dict(list(elem.attributes.items()))
|
||||
res['message'] = ""
|
||||
res['type'] = elem.tagName
|
||||
return res
|
||||
if elem.tagName == 'error':
|
||||
res = dict(list(elem.attributes.items()))
|
||||
res['message'] = elem.firstChild.nodeValue
|
||||
res['type'] = elem.tagName
|
||||
return res
|
||||
|
|
@ -75,9 +75,20 @@ def run(typ, freq, data):
|
|||
#
|
||||
# building message for ZVEI
|
||||
#
|
||||
if globalVars.config.get("Pushover", "zvei_sep_prio") == '1':
|
||||
if data["zvei"] in globalVars.config.get("Pushover", "zvei_prio2"):
|
||||
priority = '2'
|
||||
elif data["zvei"] in globalVars.config.get("Pushover","zvei_prio1"):
|
||||
priority = '1'
|
||||
elif data["zvei"] in globalVars.config.get("Pushover","zvei_prio0"):
|
||||
priority = '0'
|
||||
else:
|
||||
priority = '-1'
|
||||
else:
|
||||
priority = globalVars.config.get("Pushover","zvei_std_prio")
|
||||
|
||||
message = globalVars.config.get("Pushover", "zvei_message")
|
||||
title = globalVars.config.get("Pushover", "zvei_title")
|
||||
priority = globalVars.config.get("Pushover", "zvei_prio")
|
||||
logging.debug("Sending message: %s", message)
|
||||
|
||||
elif typ == "POC":
|
||||
|
|
@ -86,17 +97,27 @@ def run(typ, freq, data):
|
|||
# Pushover-Request
|
||||
#
|
||||
logging.debug("send Pushover for %s", typ)
|
||||
|
||||
if data["function"] == '1':
|
||||
priority = globalVars.config.get("Pushover", "SubA")
|
||||
elif data["function"] == '2':
|
||||
priority = globalVars.config.get("Pushover", "SubB")
|
||||
elif data["function"] == '3':
|
||||
priority = globalVars.config.get("Pushover", "SubC")
|
||||
elif data["function"] == '4':
|
||||
priority = globalVars.config.get("Pushover", "SubD")
|
||||
if globalVars.config.get("Pushover", "poc_spec_ric") == '0':
|
||||
if data["function"] == '1':
|
||||
priority = globalVars.config.get("Pushover", "SubA")
|
||||
elif data["function"] == '2':
|
||||
priority = globalVars.config.get("Pushover", "SubB")
|
||||
elif data["function"] == '3':
|
||||
priority = globalVars.config.get("Pushover", "SubC")
|
||||
elif data["function"] == '4':
|
||||
priority = globalVars.config.get("Pushover", "SubD")
|
||||
else:
|
||||
priority = 0
|
||||
else:
|
||||
priority = 0
|
||||
if data["ric"] in globalVars.config.get("Pushover", "poc_prio2"):
|
||||
priority = 2
|
||||
elif data["ric"] in globalVars.config.get("Pushover","poc_prio1"):
|
||||
priority = 1
|
||||
elif data["ric"] in globalVars.config.get("Pushover","poc_prio0"):
|
||||
priority = 0
|
||||
else:
|
||||
priority = -1
|
||||
|
||||
message = globalVars.config.get("Pushover", "poc_message")
|
||||
title = globalVars.config.get("Pushover", "poc_title")
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"""
|
||||
Plugin to send FMS-, ZVEI- and POCSAG-messages via Telegram
|
||||
@author: Peter Laemmle
|
||||
@requires: Telegram BOT token, Telegram chat ID, library python-telegram-bot and optional googlemaps
|
||||
@requires: Telegram BOT token, Telegram chat ID, library python-telegram-bot and optional requests and json
|
||||
"""
|
||||
|
||||
#
|
||||
|
|
@ -15,7 +15,7 @@ import telegram
|
|||
from telegram.error import (TelegramError, Unauthorized, BadRequest, NetworkError)
|
||||
from includes import globalVars # Global variables
|
||||
if globalVars.config.get("Telegram","RICforLocationAPIKey"):
|
||||
import urllib, googlemaps
|
||||
import requests, json
|
||||
|
||||
# Helper function, uncomment to use
|
||||
from includes.helper import wildcardHandler
|
||||
|
|
@ -26,6 +26,7 @@ BOTTokenAPIKey = None
|
|||
BOTChatIDAPIKey = None
|
||||
RICforLocationAPIKey = None
|
||||
GoogleAPIKey = None
|
||||
RoutingOrigin = None
|
||||
|
||||
##
|
||||
#
|
||||
|
|
@ -43,12 +44,14 @@ def onLoad():
|
|||
global BOTChatIDAPIKey
|
||||
global RICforLocationAPIKey
|
||||
global GoogleAPIKey
|
||||
global RoutingOrigin
|
||||
|
||||
configHandler.checkConfig("Telegram")
|
||||
BOTTokenAPIKey = globalVars.config.get("Telegram","BOTTokenAPIKey")
|
||||
BOTChatIDAPIKey = globalVars.config.get("Telegram","BOTChatIDAPIKey")
|
||||
RICforLocationAPIKey = globalVars.config.get("Telegram","RICforLocationAPIKey")
|
||||
GoogleAPIKey = globalVars.config.get("Telegram","GoogleAPIKey")
|
||||
RoutingOrigin = globalVars.config.get("Telegram","RoutingOrigin")
|
||||
|
||||
return
|
||||
|
||||
|
|
@ -98,12 +101,20 @@ def run(typ,freq,data):
|
|||
# Generate map
|
||||
logging.debug("Extract address from POCSAG message")
|
||||
address = "+".join(data["msg"].split(')')[0].split('/',1)[1].replace('(',' ').split())
|
||||
|
||||
# Retrieve directions using Google API
|
||||
logging.debug("Retrieve polylines from Directions API")
|
||||
url = "".join(["https://maps.googleapis.com/maps/api/directions/json?origin=",
|
||||
RoutingOrigin, "&destination=", address, "&mode=driving&key=", GoogleAPIKey])
|
||||
response = json.loads(requests.get(url).content.decode('utf-8'))
|
||||
logging.debug("Directions API return status: %s" % response['status'])
|
||||
# Retrieve static maps using Google API
|
||||
logging.debug("Retrieve maps from Google")
|
||||
url = "+".join(["http://maps.googleapis.com/maps/api/staticmap?markers=", address, "&size=480x640&maptype=roadmap&zoom=16&key=", GoogleAPIKey])
|
||||
urllib.urlretrieve(url, "overview_map.png")
|
||||
url = "+".join(["http://maps.googleapis.com/maps/api/staticmap?markers=", address, "&size=240x320&scale=2&maptype=hybrid&zoom=17&key=", GoogleAPIKey])
|
||||
urllib.urlretrieve(url, "detail_map.png")
|
||||
url = "".join(["https://maps.googleapis.com/maps/api/staticmap?&size=480x640&maptype=roadmap&path=enc:",
|
||||
response['routes'][0]['overview_polyline']['points'], "&language=de&key=", GoogleAPIKey])
|
||||
with open("overview_map.png", "wb") as img: img.write(requests.get(url).content)
|
||||
url = "".join(["https://maps.googleapis.com/maps/api/staticmap?markers=",
|
||||
address, "&size=240x320&scale=2&maptype=hybrid&zoom=17&language=de&key=", GoogleAPIKey])
|
||||
with open("detail_map.png", "wb") as img: img.write(requests.get(url).content)
|
||||
|
||||
# Send message and map with Telegram
|
||||
logging.debug("Send message and maps via Telegram BOT")
|
||||
|
|
@ -112,10 +123,15 @@ def run(typ,freq,data):
|
|||
|
||||
# Geocoding of address
|
||||
logging.debug("Geocode address")
|
||||
gcode = googlemaps.Client(key='%s' % GoogleAPIKey)
|
||||
gcode_result = gcode.geocode(address)
|
||||
url = "".join(["https://maps.googleapis.com/maps/api/geocode/json?address=",
|
||||
address, "&language=de&key=", GoogleAPIKey])
|
||||
gcode_result = json.loads(requests.get(url).content)
|
||||
logging.debug("Geocoding API return status: %s" % gcode_result['status'])
|
||||
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')
|
||||
bot.sendLocation('%s' % BOTChatIDAPIKey,
|
||||
gcode_result[results][0]['geometry']['location']['lat'],
|
||||
gcode_result[results][0]['geometry']['location']['lng'],
|
||||
disable_notification='true')
|
||||
else:
|
||||
logging.warning("Invalid Typ: %s", typ)
|
||||
except Unauthorized:
|
||||
|
|
|
|||
|
|
@ -1,301 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
notifyMyAndroid-Plugin to dispatch FMS-, ZVEI- and POCSAG-messages via UDP/TCP
|
||||
|
||||
@author: Jens Herrmann
|
||||
|
||||
@requires: notifyMyAndroid-Configuration has to be set in the config.ini
|
||||
"""
|
||||
|
||||
import logging # Global logger
|
||||
import csv # for loading the APIKeys
|
||||
|
||||
|
||||
from includes import globalVars # Global variables
|
||||
|
||||
from includes.helper import configHandler
|
||||
from includes.helper import timeHandler
|
||||
from includes.helper import stringConverter
|
||||
from includes.pynma import pynma
|
||||
|
||||
|
||||
# local variables
|
||||
application = "BOSWatch"
|
||||
APIKey = None
|
||||
remainingMsgs = None
|
||||
usecsv = False
|
||||
# data structures: xAPIKeyList[id][i] = (APIKey, priority, eventPrefix)
|
||||
fmsAPIKeyList = {}
|
||||
zveiAPIKeyList = {}
|
||||
pocAPIKeyList = {}
|
||||
|
||||
|
||||
def checkResponse(response, APIKey):
|
||||
"""
|
||||
Helper function to check the response of NMA
|
||||
|
||||
@type response: dict
|
||||
@param response: Response of the pyNMA.push() method
|
||||
@type data: string / array
|
||||
@param data: a string containing 1 key or an array of keys
|
||||
|
||||
@return: nothing
|
||||
"""
|
||||
# local variables
|
||||
global remainingMsgs
|
||||
try:
|
||||
#
|
||||
# check HTTP-Response
|
||||
#
|
||||
if str(response[APIKey]['code']) == "200": #Check HTTP Response an print a Log or Error
|
||||
logging.debug("NMA response: %s" , str(response[APIKey]['code']))
|
||||
remainingMsgs = response[APIKey]['remaining']
|
||||
if int(remainingMsgs) == 0:
|
||||
logging.error("NMA remaining msgs: %s" , str(remainingMsgs))
|
||||
if int(response[APIKey]['remaining']) < 20:
|
||||
logging.warning("NMA remaining msgs: %s" , str(remainingMsgs))
|
||||
else:
|
||||
logging.debug("NMA remaining msgs: %s" , str(remainingMsgs))
|
||||
else:
|
||||
logging.warning("NMA response: %s - %s" , str(response[APIKey]['code']), str(response[APIKey]['message']))
|
||||
except:
|
||||
logging.error("cannot read pynma response")
|
||||
logging.debug("cannot read pynma response", exc_info=True)
|
||||
return
|
||||
|
||||
|
||||
##
|
||||
#
|
||||
# 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 is called one time for initialize the plugin
|
||||
|
||||
@requires: nothing
|
||||
|
||||
@return: nothing
|
||||
"""
|
||||
# local variables
|
||||
global application
|
||||
global APIKey
|
||||
global usecsv
|
||||
|
||||
# load config:
|
||||
configHandler.checkConfig("notifyMyAndroid")
|
||||
application = stringConverter.convertToUnicode(globalVars.config.get("notifyMyAndroid","appName"))
|
||||
usecsv = globalVars.config.getboolean("notifyMyAndroid","usecsv")
|
||||
|
||||
# if no csv should use, we take the APIKey directly
|
||||
if usecsv == False:
|
||||
APIKey = globalVars.config.get("notifyMyAndroid","APIKey")
|
||||
else:
|
||||
# import the csv-file
|
||||
try:
|
||||
logging.debug("-- loading nma.csv")
|
||||
with open(globalVars.script_path+'/csv/nma.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 supported types
|
||||
supportedTypes = ["FMS", "ZVEI", "POC"]
|
||||
if row['typ'] in supportedTypes:
|
||||
try:
|
||||
if "FMS" in row['typ']:
|
||||
# if len for id in mainList raise an KeyErrorException, we have to init it...
|
||||
try:
|
||||
if len(fmsAPIKeyList[row['id']]) > 0:
|
||||
pass
|
||||
except KeyError:
|
||||
fmsAPIKeyList[row['id']] = []
|
||||
# data structure: fmsAPIKeyList[fms][i] = (APIKey, priority)
|
||||
fmsAPIKeyList[row['id']].append((row['APIKey'], row['priority'], row['eventPrefix']))
|
||||
|
||||
elif "ZVEI" in row['typ']:
|
||||
# if len for id in mainList raise an KeyErrorException, we have to init it...
|
||||
try:
|
||||
if len(zveiAPIKeyList[row['id']]) > 0:
|
||||
pass
|
||||
except KeyError:
|
||||
zveiAPIKeyList[row['id']] = []
|
||||
# data structure: zveiAPIKeyList[zvei][i] = (APIKey, priority)
|
||||
zveiAPIKeyList[row['id']].append((row['APIKey'], row['priority'], row['eventPrefix']))
|
||||
|
||||
elif "POC" in row['typ']:
|
||||
# if len for id in mainList raise an KeyErrorException, we have to init it...
|
||||
try:
|
||||
if len(pocAPIKeyList[row['id']]) > 0:
|
||||
pass
|
||||
except KeyError:
|
||||
pocAPIKeyList[row['id']] = []
|
||||
# data structure: zveiAPIKeyList[ric][i] = (APIKey, priority)
|
||||
pocAPIKeyList[row['id']].append((row['APIKey'], row['priority'], row['eventPrefix']))
|
||||
|
||||
except:
|
||||
# skip entry in case of an exception
|
||||
logging.debug("error in shifting...", exc_info=True)
|
||||
# if row['typ'] in supportedTypes
|
||||
# for row in reader:
|
||||
logging.debug("-- loading csv finished")
|
||||
except:
|
||||
logging.error("loading csvList for nma failed")
|
||||
logging.debug("loading csvList for nma failed", exc_info=True)
|
||||
raise
|
||||
# and if usecsv == True
|
||||
return
|
||||
|
||||
|
||||
##
|
||||
#
|
||||
# Main function of jsonSocket-plugin
|
||||
# will be called by the alarmHandler
|
||||
#
|
||||
def run(typ,freq,data):
|
||||
"""
|
||||
This function is the implementation of the notifyMyAndroid-Plugin.
|
||||
|
||||
The configuration 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 readme.md in plugin folder)
|
||||
@param data: Contains the parameter for dispatch to UDP.
|
||||
@type freq: string
|
||||
@keyword freq: frequency of the SDR Stick
|
||||
|
||||
@requires: notifyMyAndroid-Configuration has to be set in the config.ini
|
||||
|
||||
@return: nothing
|
||||
"""
|
||||
# local variables
|
||||
|
||||
try:
|
||||
try:
|
||||
#
|
||||
# initialize to pyNMA
|
||||
#
|
||||
nma = pynma.PyNMA()
|
||||
except:
|
||||
logging.error("cannot initialize pyNMA")
|
||||
logging.debug("cannot initialize pyNMA", exc_info=True)
|
||||
# Without class, 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 NMA", typ)
|
||||
try:
|
||||
# build event and msg
|
||||
# pyNMA expect strings are not in UTF-8
|
||||
event = stringConverter.convertToUnicode(data['description'])
|
||||
msg = timeHandler.getDateTime(data['timestamp'])
|
||||
if ("POC" in typ) and (len(data['msg']) > 0):
|
||||
msg += "\n" + data['msg']
|
||||
msg = stringConverter.convertToUnicode(msg)
|
||||
|
||||
# if not using csv-import, all is simple...
|
||||
if usecsv == False:
|
||||
response = nma.pushWithAPIKey(APIKey, application, event, msg, priority=globalVars.config.getint("notifyMyAndroid","priority"))
|
||||
checkResponse(response, APIKey)
|
||||
else:
|
||||
if "FMS" in typ:
|
||||
# lets look for fms in fmsAPIKeyList
|
||||
xID = data['fms']
|
||||
try:
|
||||
# data structure: fmsAPIKeyList[xID][i] = (xAPIKey, xPriority, xEventPrefix)
|
||||
for i in range(len(fmsAPIKeyList[xID])):
|
||||
xEvent = event
|
||||
(xAPIKey, xPriority, xEventPrefix) = fmsAPIKeyList[xID][i]
|
||||
if len(xEventPrefix) > 0:
|
||||
xEvent = xEventPrefix + ": " + xEvent
|
||||
response = nma.pushWithAPIKey(xAPIKey, application, xEvent, msg, priority=xPriority)
|
||||
checkResponse(response, xAPIKey)
|
||||
except KeyError:
|
||||
# nothing found
|
||||
pass
|
||||
|
||||
elif "ZVEI" in typ:
|
||||
# lets look for zvei in zveiAPIKeyList
|
||||
xID = data['zvei']
|
||||
try:
|
||||
# data structure: zveiAPIKeyList[xID][i] = (xAPIKey, xPriority, xEventPrefix)
|
||||
for i in range(len(zveiAPIKeyList[xID])):
|
||||
xEvent = event
|
||||
(xAPIKey, xPriority, xEventPrefix) = zveiAPIKeyList[xID][i]
|
||||
if len(xEventPrefix) > 0:
|
||||
xEvent = xEventPrefix + ": " + xEvent
|
||||
response = nma.pushWithAPIKey(xAPIKey, application, xEvent, msg, priority=xPriority)
|
||||
checkResponse(response, xAPIKey)
|
||||
except KeyError:
|
||||
# nothing found
|
||||
pass
|
||||
|
||||
elif "POC" in typ:
|
||||
xID = ""
|
||||
# 1. lets look for ric+functionChar in pocAPIKeyList
|
||||
try:
|
||||
xID = data['ric'] + data['functionChar']
|
||||
# data structure: pocAPIKeyList[xID][i] = (xAPIKey, xPriority, xEventPrefix)
|
||||
for i in range(len(pocAPIKeyList[xID])):
|
||||
xEvent = event
|
||||
(xAPIKey, xPriority, xEventPrefix) = pocAPIKeyList[xID][i]
|
||||
if len(xEventPrefix) > 0:
|
||||
xEvent = xEventPrefix + ": " + xEvent
|
||||
response = nma.pushWithAPIKey(xAPIKey, application, xEvent, msg, priority=xPriority)
|
||||
checkResponse(response, xAPIKey)
|
||||
except KeyError:
|
||||
# nothing found
|
||||
pass
|
||||
# 2. lets look for ric* in pocAPIKeyList
|
||||
try:
|
||||
xID = data['ric'] + "*"
|
||||
# data structure: pocAPIKeyList[xID][i] = (xAPIKey, xPriority, xEventPrefix)
|
||||
for i in range(len(pocAPIKeyList[xID])):
|
||||
xEvent = event
|
||||
(xAPIKey, xPriority, xEventPrefix) = pocAPIKeyList[xID][i]
|
||||
if len(xEventPrefix) > 0:
|
||||
xEvent = xEventPrefix + ": " + xEvent
|
||||
response = nma.pushWithAPIKey(xAPIKey, application, xEvent, msg, priority=xPriority)
|
||||
checkResponse(response, xAPIKey)
|
||||
except KeyError:
|
||||
# nothing found
|
||||
pass
|
||||
# 3. lets look for ric prefixes in pocAPIKeyList
|
||||
for prefixLength in reversed(range(6)):
|
||||
ricPrefix = data['ric'][:prefixLength]
|
||||
#fill the ric with stars
|
||||
ricPrefix = ricPrefix.ljust(8,'*')
|
||||
try:
|
||||
xID = ricPrefix
|
||||
# data structure: pocAPIKeyList[xID][i] = (xAPIKey, xPriority, xEventPrefix)
|
||||
for i in range(len(pocAPIKeyList[xID])):
|
||||
xEvent = event
|
||||
(xAPIKey, xPriority, xEventPrefix) = pocAPIKeyList[xID][i]
|
||||
if len(xEventPrefix) > 0:
|
||||
xEvent = xEventPrefix + ": " + xEvent
|
||||
response = nma.pushWithAPIKey(xAPIKey, application, xEvent, msg, priority=xPriority)
|
||||
checkResponse(response, xAPIKey)
|
||||
except KeyError:
|
||||
# nothing found
|
||||
pass
|
||||
|
||||
# end if "POC" in typ
|
||||
# end if usecsv == True
|
||||
except:
|
||||
logging.error("%s to NMA failed", typ)
|
||||
logging.debug("%s to NMA failed", typ, exc_info=True)
|
||||
return
|
||||
else:
|
||||
logging.warning("Invalid Typ: %s", typ)
|
||||
|
||||
except:
|
||||
# something very mysterious
|
||||
logging.error("unknown error")
|
||||
logging.debug("unknown error", exc_info=True)
|
||||
|
|
@ -45,6 +45,7 @@ elif [ "$action" == "r" ]; then # we want to remove the service
|
|||
|
||||
# and remove it
|
||||
rm /etc/systemd/system/boswatch.service
|
||||
echo "BosWatch service removed"
|
||||
else # error handling
|
||||
echo "Invalid input - please try again"
|
||||
exit 1
|
||||
|
|
|
|||
Loading…
Reference in a new issue