mirror of
https://github.com/Schrolli91/BOSWatch.git
synced 2025-12-06 07:42:03 +01:00
Merge branch 'develop' into pyinotify
This commit is contained in:
commit
7b34fc6f7e
8
.gitignore
vendored
8
.gitignore
vendored
|
|
@ -3,3 +3,11 @@
|
||||||
*.log
|
*.log
|
||||||
config.ini
|
config.ini
|
||||||
log/
|
log/
|
||||||
|
|
||||||
|
\.project
|
||||||
|
|
||||||
|
\.pydevproject
|
||||||
|
|
||||||
|
\.settings/
|
||||||
|
|
||||||
|
\.idea/
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ sudo: required
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
- beta
|
|
||||||
- develop
|
- develop
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
|
|
|
||||||
44
CHANGELOG.md
44
CHANGELOG.md
|
|
@ -1,17 +1,53 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
### __[v2.3]__ - unreleased
|
|
||||||
|
### __[v2.#]__ - Unreleased
|
||||||
|
##### Added
|
||||||
|
##### Changed
|
||||||
|
##### Deprecated
|
||||||
|
##### Removed
|
||||||
|
- Notify-my-Andoird Plugin und Logging-Handler wegen Einstellung des Service entfernt [#374](https://github.com/Schrolli91/BOSWatch/pull/374)
|
||||||
|
##### Fixed
|
||||||
|
##### Security
|
||||||
|
|
||||||
|
|
||||||
|
### __[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)
|
||||||
|
- Benutzerdefinierte Nachrichten für Pushover Plugin in config [#352](https://github.com/Schrolli91/BOSWatch/pull/352)
|
||||||
|
##### 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)
|
||||||
|
##### 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)
|
||||||
|
|
||||||
|
|
||||||
|
### __[v2.3]__ - 22.12.2017
|
||||||
|
##### Added
|
||||||
|
- zuschaltbare POCSAG Multicast-Alarm Funktionalität [#307](https://github.com/Schrolli91/BOSWatch/pull/307)
|
||||||
|
- Flag in Config um nur letzte Net Ident oder gesamte Historie zu speichern [#317](https://github.com/Schrolli91/BOSWatch/pull/317)
|
||||||
|
##### Removed
|
||||||
|
- Beta Branch aus Readme, Installer und Travis-CI entfernt [#324](https://github.com/Schrolli91/BOSWatch/pull/324)
|
||||||
|
##### Fixed
|
||||||
|
- Bug in httpRequest Plugin (data Field wurde überschrieben) [#337](https://github.com/Schrolli91/BOSWatch/pull/337)
|
||||||
|
- Kommentar für FirEmergency Einstellung angepasst [#338](https://github.com/Schrolli91/BOSWatch/pull/338)
|
||||||
|
|
||||||
|
|
||||||
|
### __[v2.2.2]__ - 21.10.2017
|
||||||
##### Added
|
##### Added
|
||||||
- Installations Script für Services [#316](https://github.com/Schrolli91/BOSWatch/pull/316)
|
- Installations Script für Services [#316](https://github.com/Schrolli91/BOSWatch/pull/316)
|
||||||
##### Changed
|
##### Changed
|
||||||
- Telegram Plugin importiert Google Maps Funktionen nur noch wenn API Key eingetragen ist [#315](https://github.com/Schrolli91/BOSWatch/pull/315)
|
- Telegram Plugin importiert Google Maps Funktionen nur noch wenn API Key eingetragen ist [#315](https://github.com/Schrolli91/BOSWatch/pull/315)
|
||||||
- Versions Nummer und Branch Name getrennt [3fed1ac](https://github.com/Schrolli91/BOSWatch/commit/3fed1ac12af8690213766e0e81d71c237530ed2c)
|
- Versions Nummer und Branch Name getrennt [3fed1ac](https://github.com/Schrolli91/BOSWatch/commit/3fed1ac12af8690213766e0e81d71c237530ed2c)
|
||||||
##### Deprecated
|
##### Deprecated
|
||||||
##### Removed
|
- Beta Branch wird mit nächstem Update entfernt [Forum](http://boswatch.de/index.php?thread/16-beta-branch-abschaffen/&postID=113#post113)
|
||||||
##### Fixed
|
##### Fixed
|
||||||
|
- Schreibfehler der Pfadangabe im Installer [#317](https://github.com/Schrolli91/BOSWatch/pull/317)
|
||||||
- Schreibfehler in Service Readme [#313](https://github.com/Schrolli91/BOSWatch/issues/313)
|
- Schreibfehler in Service Readme [#313](https://github.com/Schrolli91/BOSWatch/issues/313)
|
||||||
- Einige Code-Style Verbesserungen [#310](https://github.com/Schrolli91/BOSWatch/pull/310)
|
- Einige Code-Style Verbesserungen [#310](https://github.com/Schrolli91/BOSWatch/pull/310)
|
||||||
##### Security
|
|
||||||
|
|
||||||
|
|
||||||
### __[v2.2.1]__ - 19.09.2017
|
### __[v2.2.1]__ - 19.09.2017
|
||||||
|
|
@ -36,7 +72,7 @@
|
||||||
Zum schreiben des Changelog's siehe:
|
Zum schreiben des Changelog's siehe:
|
||||||
http://keepachangelog.com/de/1.0.0/
|
http://keepachangelog.com/de/1.0.0/
|
||||||
|
|
||||||
### __[version]__ - date
|
### __[v#.#]__ - date
|
||||||
##### Added
|
##### Added
|
||||||
##### Changed
|
##### Changed
|
||||||
##### Deprecated
|
##### Deprecated
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
============
|
============
|
||||||
|
|
||||||
|
|
||||||
|
Python 3
|
||||||
Verpacken der Funktionalitäten in Klassen um OOP-Grundsätze zu erreichen.
|
Verpacken der Funktionalitäten in Klassen um OOP-Grundsätze zu erreichen.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -12,11 +13,13 @@ Verpacken der Funktionalitäten in Klassen um OOP-Grundsätze zu erreichen.
|
||||||
- reine Dekodierung mittels rtl-fm und multimon
|
- reine Dekodierung mittels rtl-fm und multimon
|
||||||
- Keine Filter usw. nur die Dekoder, Daten verpacken, verschicken
|
- Keine Filter usw. nur die Dekoder, Daten verpacken, verschicken
|
||||||
- per TCP Socket an den Server
|
- per TCP Socket an den Server
|
||||||
|
- versch Eingabequellen (DVB-T Stick, Audio Eingang)
|
||||||
|
|
||||||
### Server:
|
### Server:
|
||||||
- Empfängt die TCP Socket Pakete der einzelnen Clients
|
- Empfängt die TCP Socket Pakete der einzelnen Clients
|
||||||
- Durch doubleFiltering fallen doppelt eingehende Alarme der Clienten sowieso raus
|
- Durch doubleFiltering fallen doppelt eingehende Alarme der Clienten sowieso raus
|
||||||
- Danach Filterung usw. dann call an die plugins
|
- Danach Filterung nach neuen Filterkonzept
|
||||||
|
- dann call an die plugins
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
|
### Arbeiten an BOSWatch 3 gestartet
|
||||||
|
#### Work on BOSWatch 3 has started
|
||||||
|
## see: https://boswatch.de/index.php?thread/29-boswatch-3/
|
||||||
|
|
||||||
|
|
||||||
|Branch|Code Qualität|CI-Build|
|
|Branch|Code Qualität|CI-Build|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|master|[](https://www.codacy.com/app/Schrolli91/BOSWatch/dashboard?bid=3763821)|[](https://travis-ci.org/Schrolli91/BOSWatch)|
|
|master|[](https://www.codacy.com/app/Schrolli91/BOSWatch/dashboard?bid=3763821)|[](https://travis-ci.org/Schrolli91/BOSWatch)|
|
||||||
|beta|[](https://www.codacy.com/app/Schrolli91/BOSWatch/dashboard?bid=4213030)|[](https://travis-ci.org/Schrolli91/BOSWatch)|
|
|
||||||
|develop|[](https://www.codacy.com/app/Schrolli91/BOSWatch/dashboard?bid=3763820)|[](https://travis-ci.org/Schrolli91/BOSWatch)|
|
|develop|[](https://www.codacy.com/app/Schrolli91/BOSWatch/dashboard?bid=3763820)|[](https://travis-ci.org/Schrolli91/BOSWatch)|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -47,6 +51,7 @@ unless you are developer you can use the develop-Branch - may be unstable!
|
||||||
- Ready for use BOSWatch as daemon
|
- Ready for use BOSWatch as daemon
|
||||||
- possibility to start plugins asynchron
|
- possibility to start plugins asynchron
|
||||||
- NMA Error Handler
|
- NMA Error Handler
|
||||||
|
- multicastAlarm for transmission optimized networks
|
||||||
|
|
||||||
|
|
||||||
### Plugins
|
### Plugins
|
||||||
|
|
|
||||||
25
boswatch.py
25
boswatch.py
|
|
@ -268,6 +268,8 @@ try:
|
||||||
# if given loglevel is debug:
|
# if given loglevel is debug:
|
||||||
if globalVars.config.getint("BOSWatch","loglevel") == 10:
|
if globalVars.config.getint("BOSWatch","loglevel") == 10:
|
||||||
configHandler.checkConfig("BOSWatch")
|
configHandler.checkConfig("BOSWatch")
|
||||||
|
configHandler.checkConfig("multicastAlarm")
|
||||||
|
configHandler.checkConfig("Filters")
|
||||||
configHandler.checkConfig("FMS")
|
configHandler.checkConfig("FMS")
|
||||||
configHandler.checkConfig("ZVEI")
|
configHandler.checkConfig("ZVEI")
|
||||||
configHandler.checkConfig("POC")
|
configHandler.checkConfig("POC")
|
||||||
|
|
@ -291,29 +293,6 @@ try:
|
||||||
logging.error("cannot set loglevel of fileHandler")
|
logging.error("cannot set loglevel of fileHandler")
|
||||||
logging.debug("cannot set loglevel of fileHandler", exc_info=True)
|
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...
|
# initialization was fine, continue with main program...
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,26 @@ ricd = Unwetter
|
||||||
# Usually sent periodically, separated by comma
|
# Usually sent periodically, separated by comma
|
||||||
netIdent_ric = 0174760, 1398098
|
netIdent_ric = 0174760, 1398098
|
||||||
|
|
||||||
|
|
||||||
|
[multicastAlarm]
|
||||||
|
# Configure multicastAlarm if your POCSAG network uses an optimized transmission scheme for alarms with more than one RIC (often found in Swissphone networks).
|
||||||
|
# In this optimized transmission scheme, a POCSAG telegram with each RIC that needs to be alarmed will be send in a sequence. These telegrams are send without a text message. This sequence is directly followed by a telegram with a specific RIC and the text message that belongs to the sequnece send right before.
|
||||||
|
# A POCSAG pager (DME) can be configured to start an acoustic alarm if a specific RIC without text has been received. If afterwards the specific RIC with the text message will be received, the pager will show the message in it's display.
|
||||||
|
# multicastAlarm enables BOSwatch to process the all received RICs joined with the text message.
|
||||||
|
#
|
||||||
|
# enable multicastAlarm (0 - off | 1 - on)
|
||||||
|
multicastAlarm = 0
|
||||||
|
|
||||||
|
# time limit for alarms that do not belong to the multicastAlarm sequence in seconds
|
||||||
|
multicastAlarm_ignore_time = 15
|
||||||
|
|
||||||
|
# multicastAlarm delimiter RIC (usually used as a starting point for a alarm sequence) (can be empty)
|
||||||
|
multicastAlarm_delimiter_ric =
|
||||||
|
|
||||||
|
# multicastAlarm RIC that is used to send the text message
|
||||||
|
multicastAlarm_ric =
|
||||||
|
|
||||||
|
|
||||||
[Filters]
|
[Filters]
|
||||||
# RegEX Filter Configuration
|
# RegEX Filter Configuration
|
||||||
# http://www.regexr.com/ - RegEX Test Tool an Documentation
|
# http://www.regexr.com/ - RegEX Test Tool an Documentation
|
||||||
|
|
@ -154,8 +174,10 @@ template = 0
|
||||||
|
|
||||||
[MySQL]
|
[MySQL]
|
||||||
# MySQL configuration
|
# MySQL configuration
|
||||||
|
#default port: 3306
|
||||||
dbserver = localhost
|
dbserver = localhost
|
||||||
dbuser = root
|
dbport = 3306
|
||||||
|
dbuser = boswatch
|
||||||
dbpassword = root
|
dbpassword = root
|
||||||
database = boswatch
|
database = boswatch
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,26 @@ ricd = Unwetter
|
||||||
# Usually sent periodically, separated by comma
|
# Usually sent periodically, separated by comma
|
||||||
netIdent_ric = 0174760, 1398098
|
netIdent_ric = 0174760, 1398098
|
||||||
|
|
||||||
|
|
||||||
|
[multicastAlarm]
|
||||||
|
# Configure multicastAlarm if your POCSAG network uses an optimized transmission scheme for alarms with more than one RIC (often found in Swissphone networks).
|
||||||
|
# In this optimized transmission scheme, a POCSAG telegram with each RIC that needs to be alarmed will be send in a sequence. These telegrams are send without a text message. This sequence is directly followed by a telegram with a specific RIC and the text message that belongs to the sequnece send right before.
|
||||||
|
# A POCSAG pager (DME) can be configured to start an acoustic alarm if a specific RIC without text has been received. If afterwards the specific RIC with the text message will be received, the pager will show the message in it's display.
|
||||||
|
# multicastAlarm enables BOSwatch to process the all received RICs joined with the text message.
|
||||||
|
#
|
||||||
|
# enable multicastAlarm (0 - off | 1 - on)
|
||||||
|
multicastAlarm = 0
|
||||||
|
|
||||||
|
# time limit for alarms that do not belong to the multicastAlarm sequence in seconds
|
||||||
|
multicastAlarm_ignore_time = 15
|
||||||
|
|
||||||
|
# multicastAlarm delimiter RIC (usually used as a starting point for a alarm sequence) (can be empty)
|
||||||
|
multicastAlarm_delimiter_ric =
|
||||||
|
|
||||||
|
# multicastAlarm RIC that is used to send the text message
|
||||||
|
multicastAlarm_ric =
|
||||||
|
|
||||||
|
|
||||||
[Filters]
|
[Filters]
|
||||||
# RegEX Filter Configuration
|
# RegEX Filter Configuration
|
||||||
# http://www.regexr.com/ - RegEX Test Tool an Documentation
|
# http://www.regexr.com/ - RegEX Test Tool an Documentation
|
||||||
|
|
@ -154,7 +174,9 @@ template = 0
|
||||||
|
|
||||||
[MySQL]
|
[MySQL]
|
||||||
# MySQL configuration
|
# MySQL configuration
|
||||||
|
#default port: 3306
|
||||||
dbserver = localhost
|
dbserver = localhost
|
||||||
|
dbport = 3306
|
||||||
dbuser = boswatch
|
dbuser = boswatch
|
||||||
dbpassword = root
|
dbpassword = root
|
||||||
database = boswatch
|
database = boswatch
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ POCSAG512: Address: 1000003 Function: 3 Alpha: BOSWatch-Test: okay
|
||||||
POCSAG512: Address: 1200001 Function: 1 Alpha: BOSWatch-Test ÖÄÜß: okay
|
POCSAG512: Address: 1200001 Function: 1 Alpha: BOSWatch-Test ÖÄÜß: okay
|
||||||
POCSAG512: Address: 1200001 Function: 1 Alpha: BOSWatch-Test öäü: okay
|
POCSAG512: Address: 1200001 Function: 1 Alpha: BOSWatch-Test öäü: okay
|
||||||
|
|
||||||
# witch csv
|
# with csv
|
||||||
POCSAG512: Address: 1234567 Function: 1 Alpha: BOSWatch-Test: with csv
|
POCSAG512: Address: 1234567 Function: 1 Alpha: BOSWatch-Test: with csv
|
||||||
|
|
||||||
# without csv
|
# without csv
|
||||||
|
|
@ -86,6 +86,22 @@ POCSAG1200: Address: 7777777 Function: 1 Alpha: BOSWatch-Test: denied
|
||||||
POCSAG1200: Address: 0000004 Function: 1 Alpha: BOSWatch-Test: out of filter start
|
POCSAG1200: Address: 0000004 Function: 1 Alpha: BOSWatch-Test: out of filter start
|
||||||
POCSAG1200: Address: 9000000 Function: 1 Alpha: BOSWatch-Test: out of filter end
|
POCSAG1200: Address: 9000000 Function: 1 Alpha: BOSWatch-Test: out of filter end
|
||||||
|
|
||||||
|
#Probealram
|
||||||
|
POCSAG1200: Address: 0871004 Function: 1 Alpha: Dies ist ein Probealarm!
|
||||||
|
## Multicast Alarm
|
||||||
|
POCSAG1200: Address: 0871002 Function: 0 Alpha: <EOT><FF>
|
||||||
|
POCSAG1200: Address: 0860001 Function: 0
|
||||||
|
POCSAG1200: Address: 0860002 Function: 0
|
||||||
|
POCSAG1200: Address: 0860003 Function: 0
|
||||||
|
POCSAG1200: Address: 0860004 Function: 0
|
||||||
|
POCSAG1200: Address: 0860005 Function: 0
|
||||||
|
POCSAG1200: Address: 0860006 Function: 0
|
||||||
|
POCSAG1200: Address: 0860007 Function: 0
|
||||||
|
POCSAG1200: Address: 0860008 Function: 0
|
||||||
|
POCSAG1200: Address: 0860009 Function: 0
|
||||||
|
POCSAG1200: Address: 0860010 Function: 0
|
||||||
|
POCSAG1200: Address: 0871003 Function: 0 Alpha: B2 Feuer Gebäude Pers in Gefahr. bla bla bla<NUL>
|
||||||
|
|
||||||
# regEx-Filter?
|
# regEx-Filter?
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,22 +64,6 @@ doubleFilter_check_msg = 0
|
||||||
writeMultimonRaw = 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]
|
[FMS]
|
||||||
# look-up-table for adding a description
|
# look-up-table for adding a description
|
||||||
# using description (0 - off | 1 - on)
|
# using description (0 - off | 1 - on)
|
||||||
|
|
@ -128,6 +112,27 @@ ricd = Unwetter
|
||||||
# RIC for net identification
|
# RIC for net identification
|
||||||
# Usually sent periodically, separated by comma
|
# Usually sent periodically, separated by comma
|
||||||
netIdent_ric = 0174760, 1398098
|
netIdent_ric = 0174760, 1398098
|
||||||
|
# you can hold one entry per netIdent_ric [0] or the whole history [1]
|
||||||
|
netIdent_history = 0
|
||||||
|
|
||||||
|
|
||||||
|
[multicastAlarm]
|
||||||
|
# Configure multicastAlarm if your POCSAG network uses an optimized transmission scheme for alarms with more than one RIC (often found in Swissphone networks).
|
||||||
|
# In this optimized transmission scheme, a POCSAG telegram with each RIC that needs to be alarmed will be send in a sequence. These telegrams are send without a text message. This sequence is directly followed by a telegram with a specific RIC and the text message that belongs to the sequnece send right before.
|
||||||
|
# A POCSAG pager (DME) can be configured to start an acoustic alarm if a specific RIC without text has been received. If afterwards the specific RIC with the text message will be received, the pager will show the message in it's display.
|
||||||
|
# multicastAlarm enables BOSwatch to process the all received RICs joined with the text message.
|
||||||
|
#
|
||||||
|
# enable multicastAlarm (0 - off | 1 - on)
|
||||||
|
multicastAlarm = 0
|
||||||
|
|
||||||
|
# time limit for alarms that do not belong to the multicastAlarm sequence in seconds
|
||||||
|
multicastAlarm_ignore_time = 15
|
||||||
|
|
||||||
|
# multicastAlarm delimiter RIC (usually used as a starting point for a alarm sequence). Needs to be empty if multicastAlarms are interrupted by normal alarms.
|
||||||
|
multicastAlarm_delimiter_ric =
|
||||||
|
|
||||||
|
# multicastAlarm RIC that is used to send the text message
|
||||||
|
multicastAlarm_ric =
|
||||||
|
|
||||||
|
|
||||||
[Filters]
|
[Filters]
|
||||||
|
|
@ -156,7 +161,6 @@ eMail = 0
|
||||||
BosMon = 0
|
BosMon = 0
|
||||||
firEmergency = 0
|
firEmergency = 0
|
||||||
jsonSocket = 0
|
jsonSocket = 0
|
||||||
notifyMyAndroid = 0
|
|
||||||
SMS = 0
|
SMS = 0
|
||||||
Sms77 = 0
|
Sms77 = 0
|
||||||
FFAgent = 0
|
FFAgent = 0
|
||||||
|
|
@ -170,7 +174,9 @@ template = 0
|
||||||
|
|
||||||
[MySQL]
|
[MySQL]
|
||||||
# MySQL configuration
|
# MySQL configuration
|
||||||
|
#default port: 3306
|
||||||
dbserver = localhost
|
dbserver = localhost
|
||||||
|
dbport = 3306
|
||||||
dbuser = boswatch
|
dbuser = boswatch
|
||||||
dbpassword = root
|
dbpassword = root
|
||||||
database = boswatch
|
database = boswatch
|
||||||
|
|
@ -264,23 +270,6 @@ server = 192.168.0.1
|
||||||
port = 8888
|
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]
|
[SMS]
|
||||||
# be aware that you need 'gammu' installed and running
|
# be aware that you need 'gammu' installed and running
|
||||||
# at least you need an UMTS-stick which is supported by 'gammu'
|
# at least you need an UMTS-stick which is supported by 'gammu'
|
||||||
|
|
@ -354,14 +343,24 @@ api_key =
|
||||||
# Pushover Userkey or Groupkey to receive message
|
# Pushover Userkey or Groupkey to receive message
|
||||||
user_key =
|
user_key =
|
||||||
|
|
||||||
# Title of the message
|
# Section for POCSAG
|
||||||
title = BOSWatch Message
|
|
||||||
|
|
||||||
# Adapt Pocsag Subric (a,b,c,d) to Pushover Priorities (see https://pushover.net/api#priority)
|
# Adapt Pocsag Subric (a,b,c,d) to Pushover Priorities (see https://pushover.net/api#priority)
|
||||||
SubA = 0
|
SubA = 1
|
||||||
SubB = 2
|
SubB = 1
|
||||||
SubC = 1
|
SubC = 2
|
||||||
SubD = 0
|
SubD = -2
|
||||||
|
poc_title = Alarm: %RIC%%LPAR%%FUNCCHAR%%RPAR%
|
||||||
|
poc_message = %DATE% %TIME% - %DESCR%: %MSG%
|
||||||
|
|
||||||
|
# Section for ZVEI
|
||||||
|
zvei_prio = 1
|
||||||
|
zvei_title = Alarm: %ZVEI%
|
||||||
|
zvei_message = %DATE% %TIME%: %ZVEI%
|
||||||
|
|
||||||
|
# Section for FMS
|
||||||
|
fms_prio = 1
|
||||||
|
fms_title = FMS: %FMS%
|
||||||
|
fms_message = %DATE% %TIME%: %FMS%%BR%Status: %STATUS% - Direction: %DIRT% - TSI: %TSI% %LPAR%%DESCR%%RPAR%
|
||||||
|
|
||||||
# how often should Pushover re-alert in seconds (emergency-messages)
|
# how often should Pushover re-alert in seconds (emergency-messages)
|
||||||
retry = 30
|
retry = 30
|
||||||
|
|
@ -453,6 +452,7 @@ test2 = 123456
|
||||||
# %RIC% = POCSAG RIC
|
# %RIC% = POCSAG RIC
|
||||||
# %FUNC% = POCSAG function/Subric (1-4)
|
# %FUNC% = POCSAG function/Subric (1-4)
|
||||||
# %FUNCCHAR% = POCSAG function/Subric als character (a-d)
|
# %FUNCCHAR% = POCSAG function/Subric als character (a-d)
|
||||||
|
# %FUNCTEXT% = POCSAG static Subric message (see [POC])
|
||||||
# %MSG% = Message of the POCSAG telegram
|
# %MSG% = Message of the POCSAG telegram
|
||||||
# %BITRATE% = Bitrate of the POCSAG telegram
|
# %BITRATE% = Bitrate of the POCSAG telegram
|
||||||
# %DESCR% = Description, if description-module is used
|
# %DESCR% = Description, if description-module is used
|
||||||
|
|
|
||||||
|
|
@ -23,16 +23,16 @@ Simple Database Class (C) by Bastian Schroll
|
||||||
function __construct($host, $user, $password, $database, $show_error = 1)
|
function __construct($host, $user, $password, $database, $show_error = 1)
|
||||||
{
|
{
|
||||||
$this->show_error = $show_error;
|
$this->show_error = $show_error;
|
||||||
@$this->conn = mysql_connect($host, $user, $password);
|
@$this->conn = mysqli_connect($host, $user, $password);
|
||||||
if ($this->conn == false)
|
if ($this->conn == false)
|
||||||
{
|
{
|
||||||
$this->error("Keine Verbindung zum Datenbank Server!", mysql_error());
|
$this->error("Keine Verbindung zum Datenbank Server!", mysqli_error($this->conn));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!@mysql_select_db($database, $this->conn))
|
if (!@mysqli_select_db($this->conn, $database))
|
||||||
{
|
{
|
||||||
$this->error("Datenbank nicht gefunden!", mysql_error());
|
$this->error("Datenbank nicht gefunden!", mysqli_error($this->conn));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -41,17 +41,17 @@ Simple Database Class (C) by Bastian Schroll
|
||||||
/**
|
/**
|
||||||
* Database::query()
|
* Database::query()
|
||||||
*
|
*
|
||||||
* F<EFBFBD>hrt einen MySQL Query aus
|
* Fuehrt einen MySQL Query aus
|
||||||
*
|
*
|
||||||
* @param mixed $query Auszuf<EFBFBD>hrender Query
|
* @param mixed $query Auszufuehrender Query
|
||||||
* @return Result-Handler/FALSE
|
* @return Result-Handler/FALSE
|
||||||
*/
|
*/
|
||||||
function query($query)
|
function query($query)
|
||||||
{
|
{
|
||||||
$this->result = @mysql_query($query, $this->conn);
|
$this->result = @mysqli_query($this->conn, $query);
|
||||||
if ($this->result == false)
|
if ($this->result == false)
|
||||||
{
|
{
|
||||||
$this->error("Fehlerhafte Datenbank Anfrage!", mysql_error());
|
$this->error("Fehlerhafte Datenbank Anfrage!", mysqli_error($this->conn));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return $this->result;
|
return $this->result;
|
||||||
|
|
@ -60,51 +60,51 @@ Simple Database Class (C) by Bastian Schroll
|
||||||
/**
|
/**
|
||||||
* Database::fetchAssoc()
|
* Database::fetchAssoc()
|
||||||
*
|
*
|
||||||
* Liefert alle gefundnen Datens<EFBFBD>tze als Assoc
|
* Liefert alle gefundnen Datensaetze als Assoc
|
||||||
*
|
*
|
||||||
* @param mixed $result Externer Result-Handler
|
* @param mixed $result Externer Result-Handler
|
||||||
* @return gefundene Datens<EFBFBD>tze als Assoc
|
* @return gefundene Datensaetze als Assoc
|
||||||
*/
|
*/
|
||||||
function fetchAssoc($result = null)
|
function fetchAssoc($result = null)
|
||||||
{
|
{
|
||||||
if ($result != null)
|
if ($result != null)
|
||||||
{
|
{
|
||||||
return @mysql_fetch_assoc($result);
|
return @mysqli_fetch_assoc($result);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
return @mysql_fetch_assoc($this->result);
|
return @mysqli_fetch_assoc($this->result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database::count()
|
* Database::count()
|
||||||
*
|
*
|
||||||
* Z<EFBFBD>hlt alle gefundenen Datens<EFBFBD>tze
|
* Zaehlt alle gefundenen Datensaetze
|
||||||
*
|
*
|
||||||
* @param mixed $result Externer Result-Handler
|
* @param mixed $result Externer Result-Handler
|
||||||
* @return Anzahl gefundener Datens<EFBFBD>tze
|
* @return Anzahl gefundener Datensaetze
|
||||||
*/
|
*/
|
||||||
function count($result = null)
|
function count($result = null)
|
||||||
{
|
{
|
||||||
if ($result != null)
|
if ($result != null)
|
||||||
{
|
{
|
||||||
return @mysql_num_rows($result);
|
return @mysqli_num_rows($result);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
return @mysql_num_rows($this->result);
|
return @mysqli_num_rows($this->result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database::closeConnection()
|
* Database::closeConnection()
|
||||||
*
|
*
|
||||||
* Schlie<EFBFBD>t die bestehende MySQL Verbindung
|
* Schliesst die bestehende MySQL Verbindung
|
||||||
*
|
*
|
||||||
* @return TRUE/FALSE
|
* @return TRUE/FALSE
|
||||||
*/
|
*/
|
||||||
function closeConnection()
|
function closeConnection()
|
||||||
{
|
{
|
||||||
if (!@mysql_close($this->conn))
|
if (!@mysqli_close($this->conn))
|
||||||
{
|
{
|
||||||
$this->error("Verbindung zur Datenbank konnte nicht getrennt werden!", mysql_error());
|
$this->error("Verbindung zur Datenbank konnte nicht getrennt werden!", mysql_error());
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -62,11 +62,23 @@ def isAllowed(poc_id):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
allowed = 0
|
allowed = 0
|
||||||
|
# 5.) Implementation for multicastAlarm
|
||||||
|
if globalVars.config.get("multicastAlarm", "multicastAlarm_delimiter_ric"):
|
||||||
|
if poc_id in globalVars.config.get("multicastAlarm", "multicastAlarm_delimiter_ric"):
|
||||||
|
logging.info("RIC %s as multicastAlarm delimiter", poc_id)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
allowed = 0
|
||||||
|
if globalVars.config.get("multicastAlarm", "multicastAlarm_ric"):
|
||||||
|
if poc_id in globalVars.config.get("multicastAlarm", "multicastAlarm_ric"):
|
||||||
|
logging.info("RIC %s as multicastAlarm message", poc_id)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
allowed = 0
|
||||||
|
|
||||||
if allowed == 0:
|
if allowed == 0:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
# POCSAG decoder function
|
# POCSAG decoder function
|
||||||
|
|
@ -117,16 +129,33 @@ def decode(freq, decoded):
|
||||||
|
|
||||||
if re.search("[0-9]{7}", poc_id) and re.search("[1-4]{1}", poc_sub): #if POC is valid
|
if re.search("[0-9]{7}", poc_id) and re.search("[1-4]{1}", poc_sub): #if POC is valid
|
||||||
if isAllowed(poc_id):
|
if isAllowed(poc_id):
|
||||||
|
|
||||||
# check for double alarm
|
# check for double alarm
|
||||||
if doubleFilter.checkID("POC", poc_id+poc_sub, poc_text):
|
if doubleFilter.checkID("POC", poc_id+poc_sub, poc_text):
|
||||||
logging.info("POCSAG%s: %s %s %s ", bitrate, poc_id, poc_sub, poc_text)
|
|
||||||
data = {"ric":poc_id, "function":poc_sub, "msg":poc_text, "bitrate":bitrate, "description":poc_id}
|
data = {"ric":poc_id, "function":poc_sub, "msg":poc_text, "bitrate":bitrate, "description":poc_id}
|
||||||
# Add function as character a-d to dataset
|
# Add function as character a-d to dataset
|
||||||
data["functionChar"] = data["function"].replace("1", "a").replace("2", "b").replace("3", "c").replace("4", "d")
|
data["functionChar"] = data["function"].replace("1", "a").replace("2", "b").replace("3", "c").replace("4", "d")
|
||||||
|
|
||||||
|
logging.info("POCSAG%s: %s %s %s ", data["bitrate"], data["ric"], data["function"], data["msg"])
|
||||||
|
|
||||||
# If enabled, look up description
|
# If enabled, look up description
|
||||||
if globalVars.config.getint("POC", "idDescribed"):
|
if globalVars.config.getint("POC", "idDescribed"):
|
||||||
from includes import descriptionList
|
from includes import descriptionList
|
||||||
data["description"] = descriptionList.getDescription("POC", poc_id+data["functionChar"])
|
data["description"] = descriptionList.getDescription("POC", data["ric"]+data["functionChar"])
|
||||||
|
|
||||||
|
# multicastAlarm processing if enabled and a message without text or delimiter RIC or netIdent_ric received
|
||||||
|
if globalVars.config.getint("multicastAlarm", "multicastAlarm") and data["ric"] != globalVars.config.get("POC", "netIdent_ric") and (data["msg"] == "" or data["ric"] in globalVars.config.get("multicastAlarm", "multicastAlarm_delimiter_ric")):
|
||||||
|
logging.debug(" - multicastAlarm without msg")
|
||||||
|
from includes import multicastAlarm
|
||||||
|
multicastAlarm.newEntrymultiList(data)
|
||||||
|
|
||||||
|
# multicastAlarm processing if enabled and alarm message has been received
|
||||||
|
elif globalVars.config.getint("multicastAlarm", "multicastAlarm") and data["msg"] != "" and data["ric"] in globalVars.config.get("multicastAlarm", "multicastAlarm_ric"):
|
||||||
|
logging.debug(" - multicastAlarm with message")
|
||||||
|
from includes import multicastAlarm
|
||||||
|
multicastAlarm.multicastAlarmExec(freq, data)
|
||||||
|
|
||||||
|
else:
|
||||||
# processing the alarm
|
# processing the alarm
|
||||||
try:
|
try:
|
||||||
from includes import alarmHandler
|
from includes import alarmHandler
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ Global variables
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# version info
|
# version info
|
||||||
versionNr = "2.2.2"
|
versionNr = "2.4"
|
||||||
branch = "dev"
|
branch = "dev"
|
||||||
buildDate = "unreleased"
|
buildDate = "unreleased"
|
||||||
|
|
||||||
|
|
|
||||||
65
includes/multicastAlarm.py
Normal file
65
includes/multicastAlarm.py
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
multicastAlarm is the function to enable BOSwatch to work in networks that optimise the transmission of POCSAG telegrams
|
||||||
|
|
||||||
|
@author: Fabian Kessler
|
||||||
|
|
||||||
|
@requires: Configuration has to be set in the config.ini
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging # Global logger
|
||||||
|
import time # timestamp for multicastAlarm
|
||||||
|
|
||||||
|
from includes import globalVars # Global variables
|
||||||
|
|
||||||
|
#
|
||||||
|
# ListStructure [0..n] = (Data, TimeStamp)
|
||||||
|
#
|
||||||
|
multiList = []
|
||||||
|
|
||||||
|
def newEntrymultiList(data):
|
||||||
|
"""
|
||||||
|
add entry to multi alarm list and remove old entries
|
||||||
|
|
||||||
|
@return: nothing
|
||||||
|
"""
|
||||||
|
global multiList
|
||||||
|
timestamp = int(time.time())
|
||||||
|
# multicastAlarm processing if enabled and delimiter RIC has been received
|
||||||
|
if data['ric'] == globalVars.config.get("multicastAlarm", "multicastAlarm_delimiter_ric"):
|
||||||
|
del multiList[:]
|
||||||
|
logging.debug("delimiter RIC received - buffer cleared")
|
||||||
|
else:
|
||||||
|
multiList.append([data, timestamp])
|
||||||
|
logging.debug("Added %s to multiList", data['ric'])
|
||||||
|
# check for old entries in multiList
|
||||||
|
for (xData, xTimestamp) in multiList[:]:
|
||||||
|
if xTimestamp < timestamp-globalVars.config.getint("multicastAlarm", "multicastAlarm_ignore_time"):
|
||||||
|
multiList.remove([xData, xTimestamp])
|
||||||
|
logging.debug("RIC %s removed - %s sec. older than current timestamp", xData['ric'], xTimestamp-timestamp)
|
||||||
|
|
||||||
|
|
||||||
|
def multicastAlarmExec(freq, data):
|
||||||
|
"""
|
||||||
|
call alarmHandler for every entry in multiList
|
||||||
|
|
||||||
|
@return: nothing
|
||||||
|
"""
|
||||||
|
logging.debug("data before update from multiList: %s", data)
|
||||||
|
for (xData, _) in multiList:
|
||||||
|
#update data with values multiList
|
||||||
|
data['ric'] = xData['ric']
|
||||||
|
data['function'] = xData['function']
|
||||||
|
data['functionChar'] = xData['functionChar']
|
||||||
|
data['description'] = xData['description']
|
||||||
|
logging.debug("data after update from multiList: %s", data)
|
||||||
|
try:
|
||||||
|
from includes import alarmHandler
|
||||||
|
alarmHandler.processAlarmHandler("POC", freq, data)
|
||||||
|
except:
|
||||||
|
logging.error("processing alarm failed")
|
||||||
|
logging.debug("processing alarm failed", exc_info=True)
|
||||||
|
del multiList[:]
|
||||||
|
logging.debug("multicastAlarm finished - buffer cleared")
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -78,7 +78,6 @@ for (( i=1; i<=$#; i=$i+2 )); do
|
||||||
-b|--branch)
|
-b|--branch)
|
||||||
case $arg2 in
|
case $arg2 in
|
||||||
dev|develop) echo " !!! WARNING: you are using the DEV BRANCH !!! "; branch=dev ;;
|
dev|develop) echo " !!! WARNING: you are using the DEV BRANCH !!! "; branch=dev ;;
|
||||||
beta) echo " !!! WARNING: you are using the BETA BRANCH !!! "; branch=beta ;;
|
|
||||||
*) branch=master ;;
|
*) branch=master ;;
|
||||||
esac ;;
|
esac ;;
|
||||||
|
|
||||||
|
|
@ -213,7 +212,7 @@ echo "Installation ready!"
|
||||||
tput cup 19 3
|
tput cup 19 3
|
||||||
echo "Watch out: to run BOSWatch you have to modify the config.ini!"
|
echo "Watch out: to run BOSWatch you have to modify the config.ini!"
|
||||||
echo "Do the following step to do so:"
|
echo "Do the following step to do so:"
|
||||||
echo "sudo nano $boswatchpath/BOSWatch/config/config.ini"
|
echo "sudo nano $boswatchpath/config/config.ini"
|
||||||
echo "and modify the config as you need. This step is optional if you are upgrading an old version of BOSWatch. "
|
echo "and modify the config as you need. This step is optional if you are upgrading an old version of BOSWatch. "
|
||||||
|
|
||||||
tput cnorm
|
tput cnorm
|
||||||
|
|
|
||||||
|
|
@ -132,9 +132,10 @@ def run(typ,freq,data):
|
||||||
"selectiveCallCode": selectiveCallCode,
|
"selectiveCallCode": selectiveCallCode,
|
||||||
"hmac": hmac.new(webApiKey, webApiToken + selectiveCallCode + accessToken + alarmData, digestmod=hashlib.sha256).hexdigest()
|
"hmac": hmac.new(webApiKey, webApiToken + selectiveCallCode + accessToken + alarmData, digestmod=hashlib.sha256).hexdigest()
|
||||||
}
|
}
|
||||||
|
logging.debug(alarmHeaders)
|
||||||
|
|
||||||
if globalVars.config.get("FFAgent", "live") == "1":
|
if globalVars.config.get("FFAgent", "live") == "1":
|
||||||
r = requests.post(url, data=alarmData, headers=headers, verify=serverCertFile, cert=(clientCertFile, clientCertPass))
|
r = requests.post(url, data=alarmData, headers=alarmHeaders, verify=serverCertFile, cert=(clientCertFile, clientCertPass))
|
||||||
else:
|
else:
|
||||||
r = requests.post(url, data=alarmData, headers=alarmHeaders, verify=serverCertFile)
|
r = requests.post(url, data=alarmData, headers=alarmHeaders, verify=serverCertFile)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ def run(typ,freq,data):
|
||||||
# Connect to MySQL
|
# Connect to MySQL
|
||||||
#
|
#
|
||||||
logging.debug("connect to MySQL")
|
logging.debug("connect to MySQL")
|
||||||
connection = mysql.connector.connect(host = globalVars.config.get("MySQL","dbserver"), user = globalVars.config.get("MySQL","dbuser"), passwd = globalVars.config.get("MySQL","dbpassword"), db = globalVars.config.get("MySQL","database"), charset='utf8')
|
connection = mysql.connector.connect(host = globalVars.config.get("MySQL","dbserver"), port = globalVars.config.get("MySQL","dbport"), user = globalVars.config.get("MySQL","dbuser"), passwd = globalVars.config.get("MySQL","dbpassword"), db = globalVars.config.get("MySQL","database"), charset='utf8')
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
except:
|
except:
|
||||||
logging.error("cannot connect to MySQL")
|
logging.error("cannot connect to MySQL")
|
||||||
|
|
@ -111,6 +111,9 @@ def run(typ,freq,data):
|
||||||
|
|
||||||
elif typ == "POC":
|
elif typ == "POC":
|
||||||
if isSignal(data["ric"]):
|
if isSignal(data["ric"]):
|
||||||
|
if globalVars.config.getint("POC","netIdent_history"):
|
||||||
|
cursor.execute("INSERT INTO "+globalVars.config.get("MySQL","tableSIG")+" (time,ric) VALUES (NOW(), '"+data["ric"]+"');")
|
||||||
|
else:
|
||||||
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:
|
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"]+"');")
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,14 @@ Pushover-Plugin to send FMS-, ZVEI- and POCSAG - messages to Pushover Clients
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging # Global logger
|
import logging # Global logger
|
||||||
import httplib #for the HTTP request
|
import httplib # for the HTTP request
|
||||||
import urllib
|
import urllib
|
||||||
from includes import globalVars # Global variables
|
from includes import globalVars # Global variables
|
||||||
|
|
||||||
#from includes.helper import timeHandler
|
# from includes.helper import timeHandler
|
||||||
from includes.helper import configHandler
|
from includes.helper import configHandler
|
||||||
|
from includes.helper import wildcardHandler
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
|
|
@ -40,7 +42,7 @@ def onLoad():
|
||||||
# Main function of Pushover-plugin
|
# Main function of Pushover-plugin
|
||||||
# will be called by the alarmHandler
|
# will be called by the alarmHandler
|
||||||
#
|
#
|
||||||
def run(typ,freq,data):
|
def run(typ, freq, data):
|
||||||
"""
|
"""
|
||||||
This function is the implementation of the Pushover-Plugin.
|
This function is the implementation of the Pushover-Plugin.
|
||||||
It will send the data to Pushover API
|
It will send the data to Pushover API
|
||||||
|
|
@ -57,13 +59,33 @@ def run(typ,freq,data):
|
||||||
@return: nothing
|
@return: nothing
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if configHandler.checkConfig("Pushover"): #read and debug the config
|
if configHandler.checkConfig("Pushover"): # read and debug the config
|
||||||
|
|
||||||
|
if typ == "FMS":
|
||||||
|
#
|
||||||
|
# building message for FMS
|
||||||
|
#
|
||||||
|
|
||||||
|
message = globalVars.config.get("Pushover", "fms_message")
|
||||||
|
title = globalVars.config.get("Pushover", "fms_title")
|
||||||
|
priority = globalVars.config.get("Pushover", "fms_prio")
|
||||||
|
logging.debug("Sending message: %s", message)
|
||||||
|
|
||||||
|
elif typ == "ZVEI":
|
||||||
|
#
|
||||||
|
# building message for ZVEI
|
||||||
|
#
|
||||||
|
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":
|
||||||
|
|
||||||
try:
|
|
||||||
#
|
#
|
||||||
# Pushover-Request
|
# Pushover-Request
|
||||||
#
|
#
|
||||||
logging.debug("send Pushover %s", typ)
|
logging.debug("send Pushover for %s", typ)
|
||||||
|
|
||||||
if data["function"] == '1':
|
if data["function"] == '1':
|
||||||
priority = globalVars.config.get("Pushover", "SubA")
|
priority = globalVars.config.get("Pushover", "SubA")
|
||||||
|
|
@ -75,36 +97,46 @@ def run(typ,freq,data):
|
||||||
priority = globalVars.config.get("Pushover", "SubD")
|
priority = globalVars.config.get("Pushover", "SubD")
|
||||||
else:
|
else:
|
||||||
priority = 0
|
priority = 0
|
||||||
|
message = globalVars.config.get("Pushover", "poc_message")
|
||||||
|
title = globalVars.config.get("Pushover", "poc_title")
|
||||||
|
|
||||||
|
else:
|
||||||
|
logging.warning("Invalid type: %s", typ)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# replace the wildcards
|
||||||
|
message = wildcardHandler.replaceWildcards(message, data)
|
||||||
|
title = wildcardHandler.replaceWildcards(title, data)
|
||||||
|
|
||||||
|
# start the connection
|
||||||
conn = httplib.HTTPSConnection("api.pushover.net:443")
|
conn = httplib.HTTPSConnection("api.pushover.net:443")
|
||||||
conn.request("POST", "/1/messages.json",
|
conn.request("POST", "/1/messages.json",
|
||||||
urllib.urlencode({
|
urllib.urlencode({
|
||||||
"token": globalVars.config.get("Pushover", "api_key"),
|
"token": globalVars.config.get("Pushover", "api_key"),
|
||||||
"user": globalVars.config.get("Pushover", "user_key"),
|
"user": globalVars.config.get("Pushover", "user_key"),
|
||||||
"message": "<b>"+data["description"]+"</b><br>"+data["msg"].replace(";", "<br>"),
|
"message": message,
|
||||||
"html": globalVars.config.get("Pushover", "html"),
|
"html": globalVars.config.get("Pushover", "html"),
|
||||||
"title": globalVars.config.get("Pushover", "title"),
|
"title": title,
|
||||||
"priority": priority,
|
"priority": priority,
|
||||||
"retry": globalVars.config.get("Pushover", "retry"),
|
"retry": globalVars.config.get("Pushover", "retry"),
|
||||||
"expire": globalVars.config.get("Pushover", "expire")
|
"expire": globalVars.config.get("Pushover", "expire")
|
||||||
}),{"Content-type": "application/x-www-form-urlencoded"})
|
}), {"Content-type": "application/x-www-form-urlencoded"})
|
||||||
|
|
||||||
except:
|
except:
|
||||||
logging.error("cannot send Pushover request")
|
logging.error("cannot send Pushover request")
|
||||||
logging.debug("cannot send Pushover request", exc_info=True)
|
logging.debug("cannot send Pushover request", exc_info=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
else:
|
|
||||||
try:
|
try:
|
||||||
#
|
#
|
||||||
# check Pushover-Response
|
# check Pushover-Response
|
||||||
#
|
#
|
||||||
response = conn.getresponse()
|
response = conn.getresponse()
|
||||||
if str(response.status) == "200": #Check Pushover Response and print a Log or Error
|
if str(response.status) == "200": # Check Pushover Response and print a Log or Error
|
||||||
logging.debug("Pushover response: %s - %s" , str(response.status), str(response.reason))
|
logging.debug("Pushover response: %s - %s", str(response.status), str(response.reason))
|
||||||
else:
|
else:
|
||||||
logging.warning("Pushover response: %s - %s" , str(response.status), str(response.reason))
|
logging.warning("Pushover response: %s - %s", str(response.status), str(response.reason))
|
||||||
except: #otherwise
|
except: # otherwise
|
||||||
logging.error("cannot get Pushover response")
|
logging.error("cannot get Pushover response")
|
||||||
logging.debug("cannot get Pushover response", exc_info=True)
|
logging.debug("cannot get Pushover response", exc_info=True)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
firEmergency-Plugin to dispatch ZVEI- and POCSAG - messages to firEmergency
|
firEmergency-Plugin to dispatch ZVEI- and POCSAG - messages to firEmergency
|
||||||
|
|
||||||
firEmergency configuration:
|
firEmergency configuration:
|
||||||
- set input to "FMS32" at Port 5555
|
- set input to "Standartschnittstelle" at Port 5555
|
||||||
|
|
||||||
@autor: Smith-fms
|
@autor: Smith-fms
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,11 +68,13 @@ def run(typ,freq,data):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
#
|
#
|
||||||
# Replace special characters in data Strings for URL
|
# Make a copy of the data field to not overwrite the data in it
|
||||||
|
# Replace special characters in dataCopy Strings for URL
|
||||||
#
|
#
|
||||||
for key in data:
|
dataCopy = dict(data)
|
||||||
if isinstance(data[key], basestring):
|
for key in dataCopy:
|
||||||
data[key] = urllib.quote(data[key])
|
if isinstance(dataCopy[key], basestring):
|
||||||
|
dataCopy[key] = urllib.quote(dataCopy[key])
|
||||||
#
|
#
|
||||||
# Get URLs
|
# Get URLs
|
||||||
#
|
#
|
||||||
|
|
@ -90,7 +92,7 @@ def run(typ,freq,data):
|
||||||
# replace wildcards
|
# replace wildcards
|
||||||
#
|
#
|
||||||
for (i, url) in enumerate(urls):
|
for (i, url) in enumerate(urls):
|
||||||
urls[i] = wildcardHandler.replaceWildcards(urls[i].strip(), data)
|
urls[i] = wildcardHandler.replaceWildcards(urls[i].strip(), dataCopy)
|
||||||
#
|
#
|
||||||
# HTTP-Request
|
# HTTP-Request
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
Loading…
Reference in a new issue