Merge branch 'develop' into feature/tg_message_queuing

This commit is contained in:
Bastian Schroll 2020-07-10 07:14:51 +02:00 committed by GitHub
commit 954cf0fa26
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 441 additions and 22 deletions

39
.github/workflows/build_docs.yml vendored Normal file
View file

@ -0,0 +1,39 @@
name: build_docs
on:
push:
branches:
- master
jobs:
build_docs:
name: Build documentation
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Build doxygen
uses: mattnotmitt/doxygen-action@v1
with:
working-directory: './'
doxyfile-path: 'docu/doxygen.ini'
- name: Build mkdocs
run: |
python -m pip install --upgrade pip
pip install mkdocs
python -m mkdocs build -f docu/mkdocs.yml
- name: Upload to docs-server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SCP_HOST }}
port: ${{ secrets.SCP_PORT }}
username: ${{ secrets.SCP_USERNAME }}
password: ${{ secrets.SCP_PASSWORD }}
source: "docu/site/**"
target: ${{ secrets.SCP_TARGET_PATH }}
strip_components: 2

View file

@ -6,25 +6,29 @@ jobs:
build: build:
strategy: strategy:
max-parallel: 3
matrix: matrix:
os: [ubuntu-latest] os: [ubuntu-latest]
python-version: [3.5, 3.6, 3.7] python-version: [3.5, 3.6, 3.7, 3.8]
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: Set up Python ${{matrix.python-version}} at ${{matrix.os}} - name: Set up Python ${{matrix.python-version}} at ${{matrix.os}}
uses: actions/setup-python@v1 uses: actions/setup-python@v1
with: with:
python-version: ${{matrix.python-version}} python-version: ${{matrix.python-version}}
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install -r requirements.txt pip install -r requirements.txt
mkdir log/ mkdir log/
- name: Test with pytest - name: Test with pytest
run: | run: |
pytest -c 'test/pytest.ini' pytest -c 'test/pytest.ini'
- name: Save artifacts - name: Save artifacts
uses: actions/upload-artifact@master uses: actions/upload-artifact@master
with: with:

View file

@ -0,0 +1,78 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""!
____ ____ ______ __ __ __ _____
/ __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ /
/ __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ <
/ /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ /
/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/
German BOS Information Script
by Bastian Schroll
@file: lienInInput.py
@date: 18.04.2020
@author: Philipp von Kirschbaum
@description: Input source for line-in with alsa
"""
import logging
from boswatch.utils import paths
from boswatch.processManager import ProcessManager
from boswatch.inputSource.inputBase import InputBase
logging.debug("- %s loaded", __name__)
class LineInInput(InputBase):
"""!Class for the line-in input source"""
def _runThread(self, dataQueue, lineInConfig, decoderConfig):
lineInProc = None
mmProc = None
try:
lineInProc = ProcessManager("arecord")
lineInProc.addArgument("-q ") # supress any other outputs
lineInProc.addArgument("-f S16_LE") # set output format (16bit)
lineInProc.addArgument("-r 22050") # set output sampling rate (22050Hz)
lineInProc.addArgument("-D plughw:" +
str(lineInConfig.get("card", default="1")) +
"," +
str(lineInConfig.get("device", default="0"))) # device id
lineInProc.setStderr(open(paths.LOG_PATH + "asla.log", "a"))
lineInProc.start()
mmProc = ProcessManager(str(lineInConfig.get("mmPath", default="multimon-ng")), textMode=True)
if decoderConfig.get("fms", default=0):
mmProc.addArgument("-a FMSFSK")
if decoderConfig.get("zvei", default=0):
mmProc.addArgument("-a ZVEI1")
if decoderConfig.get("poc512", default=0):
mmProc.addArgument("-a POCSAG512")
if decoderConfig.get("poc1200", default=0):
mmProc.addArgument("-a POCSAG1200")
if decoderConfig.get("poc2400", default=0):
mmProc.addArgument("-a POCSAG2400")
if lineInConfig.get("mmChar"):
mmProc.addArgument("-C " + str(lineInConfig.get("mmChar")))
mmProc.addArgument("-f alpha")
mmProc.addArgument("-t raw -")
mmProc.setStdin(lineInProc.stdout)
mmProc.setStderr(open(paths.LOG_PATH + "multimon-ng.log", "a"))
mmProc.start()
logging.info("start decoding")
while self._isRunning:
if not lineInProc.isRunning:
logging.warning("asla was down - try to restart")
lineInProc.start()
elif not mmProc.isRunning:
logging.warning("multimon was down - try to restart")
mmProc.start()
elif lineInProc.isRunning and mmProc.isRunning:
line = mmProc.readline()
if line:
self.addToQueue(line)
except:
logging.exception("error in lineIn input routine")
finally:
mmProc.stop()
lineInProc.stop()

View file

@ -0,0 +1,77 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""!
____ ____ ______ __ __ __ _____
/ __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ /
/ __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ <
/ /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ /
/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/
German BOS Information Script
by Bastian Schroll
@file: pulseaudioInput.py
@date: 18.04.2020, 29.06.2020
@author: Philipp von Kirschbaum, b-watch
@description: Input source for PulseAudio
"""
import logging
from boswatch.utils import paths
from boswatch.processManager import ProcessManager
from boswatch.inputSource.inputBase import InputBase
logging.debug("- %s loaded", __name__)
class PulseAudioInput(InputBase):
"""!Class for the PulseAudio input source"""
def _runThread(self, dataQueue, PulseAudioConfig, decoderConfig):
PulseAudioProc = None
mmProc = None
try:
PulseAudioProc = ProcessManager("parec")
PulseAudioProc.addArgument("--channels=1") # supress any other outputs
PulseAudioProc.addArgument("--format=s16le") # set output format (16bit)
PulseAudioProc.addArgument("--rate=22050") # set output sampling rate (22050Hz)
PulseAudioProc.addArgument("--device=" +
str(PulseAudioConfig.get("device", default="boswatch")) +
".monitor") # sink name
PulseAudioProc.setStderr(open(paths.LOG_PATH + "pulseaudio.log", "a"))
PulseAudioProc.start()
mmProc = ProcessManager(str(PulseAudioConfig.get("mmPath", default="multimon-ng")), textMode=True)
if decoderConfig.get("fms", default=0):
mmProc.addArgument("-a FMSFSK")
if decoderConfig.get("zvei", default=0):
mmProc.addArgument("-a ZVEI1")
if decoderConfig.get("poc512", default=0):
mmProc.addArgument("-a POCSAG512")
if decoderConfig.get("poc1200", default=0):
mmProc.addArgument("-a POCSAG1200")
if decoderConfig.get("poc2400", default=0):
mmProc.addArgument("-a POCSAG2400")
if PulseAudioConfig.get("mmChar"):
mmProc.addArgument("-C " + str(PulseAudioConfig.get("mmChar")))
mmProc.addArgument("-f alpha")
mmProc.addArgument("-t raw -")
mmProc.setStdin(PulseAudioProc.stdout)
mmProc.setStderr(open(paths.LOG_PATH + "multimon-ng.log", "a"))
mmProc.start()
logging.info("start decoding")
while self._isRunning:
if not PulseAudioProc.isRunning:
logging.warning("PulseAudio was down - try to restart")
PulseAudioProc.start()
elif not mmProc.isRunning:
logging.warning("multimon was down - try to restart")
mmProc.start()
elif PulseAudioProc.isRunning and mmProc.isRunning:
line = mmProc.readline()
if line:
self.addToQueue(line)
except:
logging.exception("error in PulseAudio input routine")
finally:
mmProc.stop()
PulseAudioProc.stop()

View file

@ -52,6 +52,8 @@ class SdrInput(InputBase):
mmProc.addArgument("-a POCSAG1200") mmProc.addArgument("-a POCSAG1200")
if decoderConfig.get("poc2400", default=0): if decoderConfig.get("poc2400", default=0):
mmProc.addArgument("-a POCSAG2400") mmProc.addArgument("-a POCSAG2400")
if sdrConfig.get("mmChar"):
mmProc.addArgument("-C " + str(sdrConfig.get("mmChar")))
mmProc.addArgument("-f alpha") mmProc.addArgument("-f alpha")
mmProc.addArgument("-t raw -") mmProc.addArgument("-t raw -")
mmProc.setStdin(sdrProc.stdout) mmProc.setStdin(sdrProc.stdout)

View file

@ -50,6 +50,8 @@ from boswatch.decoder.decoder import Decoder
from boswatch.utils import header from boswatch.utils import header
from boswatch.utils import misc from boswatch.utils import misc
from boswatch.inputSource.sdrInput import SdrInput from boswatch.inputSource.sdrInput import SdrInput
from boswatch.inputSource.lineInInput import LineInInput
from boswatch.inputSource.pulseaudioInput import PulseAudioInput
header.logoToLog() header.logoToLog()
header.infoToLog() header.infoToLog()
@ -88,6 +90,10 @@ try:
logging.debug("loading input source: %s", bwConfig.get("client", "inputSource")) logging.debug("loading input source: %s", bwConfig.get("client", "inputSource"))
if bwConfig.get("client", "inputSource") == "sdr": if bwConfig.get("client", "inputSource") == "sdr":
inputSource = SdrInput(inputQueue, bwConfig.get("inputSource", "sdr"), bwConfig.get("decoder")) inputSource = SdrInput(inputQueue, bwConfig.get("inputSource", "sdr"), bwConfig.get("decoder"))
elif bwConfig.get("client", "inputSource") == "lineIn":
inputSource = LineInInput(inputQueue, bwConfig.get("inputSource", "lineIn"), bwConfig.get("decoder"))
elif bwConfig.get("client", "inputSource") == "PulseAudio":
inputSource = PulseAudioInput(inputQueue, bwConfig.get("inputSource", "PulseAudio"), bwConfig.get("decoder"))
else: else:
logging.fatal("Invalid input source: %s", bwConfig.get("client", "inputSource")) logging.fatal("Invalid input source: %s", bwConfig.get("client", "inputSource"))
exit(1) exit(1)

View file

@ -86,7 +86,7 @@ try:
incomingQueue = queue.Queue() incomingQueue = queue.Queue()
bwServer = TCPServer(incomingQueue) bwServer = TCPServer(incomingQueue)
if bwServer.start(): if bwServer.start(port=bwConfig.get('server', 'port', default=8080)):
while 1: while 1:
if incomingQueue.empty(): # pause only when no data if incomingQueue.empty(): # pause only when no data

View file

@ -9,7 +9,7 @@
client: client:
name: BW3 Client # name of the BW3 Client instance name: BW3 Client # name of the BW3 Client instance
inputSource: sdr # atm only 'sdr' is possible inputSource: sdr # name of the input source('sdr' or 'lineIn')
useBroadcast: no # use broadcast to find server automatically useBroadcast: no # use broadcast to find server automatically
reconnectDelay: 3 # time in seconds to delay reconnect try reconnectDelay: 3 # time in seconds to delay reconnect try
sendTries: 3 # how often should tried to send a packet sendTries: 3 # how often should tried to send a packet
@ -28,6 +28,12 @@ inputSource:
gain: 100 gain: 100
rtlPath: /usr/bin/rtl_fm rtlPath: /usr/bin/rtl_fm
mmPath: /opt/multimon/multimon-ng mmPath: /opt/multimon/multimon-ng
mmChar: DE
lineIn:
card: 1
device: 0
mmPath: /opt/multimon/multimon-ng
mmChar: DE
decoder: decoder:
fms: yes fms: yes

View file

@ -11,7 +11,7 @@ zwingend in die Konfiguration eingetragen werden.
|Feld|Beschreibung|Default| |Feld|Beschreibung|Default|
|----|------------|-------| |----|------------|-------|
|name|Name zur Identifizierung der Client Instanz|| |name|Name zur Identifizierung der Client Instanz||
|inputSource|Art der zu nutzenden Input Quelle (aktuell nur `sdr`)|sdr| |inputSource|Art der zu nutzenden Input Quelle (`sdr`, `lineIn` oder `PulseAudio`)||
|useBroadcast|Verbindungsdaten per [Broadcast](information/broadcast.md) beziehen|no| |useBroadcast|Verbindungsdaten per [Broadcast](information/broadcast.md) beziehen|no|
|reconnectDelay|Verzögerung für erneuten Verbindungsversuch zum Server|3| |reconnectDelay|Verzögerung für erneuten Verbindungsversuch zum Server|3|
|sendTries|Anzahl der Sendeversuche eines Pakets|3| |sendTries|Anzahl der Sendeversuche eines Pakets|3|
@ -36,7 +36,10 @@ server:
--- ---
### `inputSource:` ### `inputSource:`
Aktuell gibt es nur `sdr:` als Input Quelle Es gibt die Auswahl zwischen `sdr`, `lineIn` oder `PulseAudio` als Input Quelle.
Mit `sdr` wird direkt per **rtl_sdr** die zu empfangende Frequenz an Multimon-NG weitergereicht.
Mit `lineIn` wird eine Quelle die (per **ALSA**) direkt an die Soundkarte angeschlossen ist an Multimon-NG weitergereicht.
Mit `PulseAudio` wird ein PulseAudio-Sink an Multimon-NG weitergereicht, z.B. in Kombination mit [RTLSDR-Airband](https://github.com/szpajder/RTLSDR-Airband) und/oder Docker.
#### `sdr:` #### `sdr:`
|Feld|Beschreibung|Default| |Feld|Beschreibung|Default|
@ -48,6 +51,7 @@ Aktuell gibt es nur `sdr:` als Input Quelle
|gain|Verstärkung des Eingangssignals|100| |gain|Verstärkung des Eingangssignals|100|
|rtlPath|Pfad zur rtl_fm Binary|rtl_fm| |rtlPath|Pfad zur rtl_fm Binary|rtl_fm|
|mmPath|Pfad zur multimon-ng Binary|multimon-ng| |mmPath|Pfad zur multimon-ng Binary|multimon-ng|
|mmChar|multimon-ng Char-Set|not set|
**Beispiel:** **Beispiel:**
```yaml ```yaml
@ -60,8 +64,85 @@ inputSource:
gain: 100 gain: 100
rtlPath: /usr/bin/rtl-fm rtlPath: /usr/bin/rtl-fm
mmPath: /opt/multimon/multimon-ng mmPath: /opt/multimon/multimon-ng
mmChar: DE
``` ```
#### `lineIn:`
|Feld|Beschreibung|Default|
|----|------------|-------|
|device|die device Id der Soundkarte|1|
|mmPath|Pfad zur multimon-ng Binary|multimon-ng|
|mmChar|multimon-ng Char-Set|not set|
**Device herausfinden**
Durch eingabe des Befehls `aplay -l` werden alle Soundkarten ausgegeben. Das schaut ungefähr so aus:
```console
**** List of PLAYBACK Hardware Devices ****
card 0: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA]
Subdevices: 7/7
Subdevice #0: subdevice #0
Subdevice #1: subdevice #1
Subdevice #2: subdevice #2
Subdevice #3: subdevice #3
Subdevice #4: subdevice #4
Subdevice #5: subdevice #5
Subdevice #6: subdevice #6
card 0: ALSA [bcm2835 ALSA], device 1: bcm2835 IEC958/HDMI [bcm2835 IEC958/HDMI]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: ALSA [bcm2835 ALSA], device 2: bcm2835 IEC958/HDMI1 [bcm2835 IEC958/HDMI1]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: Device [C-Media USB Audio Device], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
```
Wir betrachten das letzte Gerät: `card 1: Device [C-Media USB Audio Device], device 0: USB Audio [USB Audio]`
In dem Fall ist das letzte Gerät - `card 1` - unsere USB-Audio Schnittstelle die wir verwenden wollen.
In der Konfiguration wird das Feld `card` nun auf den Wert 1 gesetzt.
Nach dem Typ der Soundkarte steht das device, in diesem Fall `device 0`.
In der Konfiguration wird das Feld `device` nun auf den Wert 0 gesetzt.
**Beispiel:**
```yaml
inputSource:
...
lineIn:
card: 1
device: 0
mmPath: /opt/multimon/multimon-ng
mmChar: DE
```
#### `PulseAudio:`
|Feld|Beschreibung|Default|
|----|------------|-------|
|device|Der Sinks-Name der Quelle|boswatch|
|mmPath|Pfad zur multimon-ng Binary|multimon-ng|
|mmChar|multimon-ng Char-Set|not set|
**Device herausfinden**
Durch eingabe des Befehls `pacmd list-sinks | grep name:` werden alle Sinks ausgegeben. Beispiel:
```console
bash-5.0# pacmd list-sinks | grep name:
name: <boswatch>
```
In der Konfiguration wird das Feld `device` nun auf den den Namen des gewünschten Sinks gesetzt (ohne spitze Klammern, <>).
**Beispiel:**
```yaml
inputSource:
...
PulseAudio:
device: boswatch
mmPath: /opt/multimon/multimon-ng
mmChar: DE
```
--- ---
### `decoder:` ### `decoder:`
|Feld|Beschreibung|Default| |Feld|Beschreibung|Default|

View file

@ -34,7 +34,7 @@ Informationen zum Aufbau eines [BOSWatch Pakets](../develop/packet.md)
- type: module - type: module
res: descriptor res: descriptor
config: config:
- scanField: zvei - scanField: tone
descrField: description descrField: description
wildcard: "{DESCR}" wildcard: "{DESCR}"
descriptions: descriptions:

View file

@ -43,7 +43,7 @@ Vereinfacht kann man sagen, dass einzelnen Router ODER-verknüpft und die jeweil
config: config:
- name: "Zvei filter" - name: "Zvei filter"
checks: checks:
- field: zvei - field: tone
regex: "65[0-9]{3}" # all zvei with starting 65 regex: "65[0-9]{3}" # all zvei with starting 65
- name: "FMS Stat 3" - name: "FMS Stat 3"
checks: checks:

View file

@ -6,7 +6,10 @@ Mit diesem Plugin ist es moeglich, Telegram-Nachrichten für POCSAG-Alarmierunge
Außerdem werden Locations versendet, wenn die Felder `lat` und `lon` im Paket definiert sind. (beispielsweise durch das [Geocoding](../modul/geocoding.md) Modul) Außerdem werden Locations versendet, wenn die Felder `lat` und `lon` im Paket definiert sind. (beispielsweise durch das [Geocoding](../modul/geocoding.md) Modul)
## Unterstütze Alarmtypen ## Unterstütze Alarmtypen
- Fms
- Pocsag - Pocsag
- Zvei
- Msg
## Resource ## Resource
`telegram` `telegram`
@ -15,9 +18,12 @@ Außerdem werden Locations versendet, wenn die Felder `lat` und `lon` im Paket d
|Feld|Beschreibung|Default| |Feld|Beschreibung|Default|
|----|------------|-------| |----|------------|-------|
|message|Format der Nachricht||
|botToken|Der Api-Key des Telegram-Bots|| |botToken|Der Api-Key des Telegram-Bots||
|chatIds|Liste mit Chat-Ids der Empfängers / der Emfänger-Gruppen|| |chatIds|Liste mit Chat-Ids der Empfängers / der Emfänger-Gruppen||
|message_fms|Format der Nachricht für FMS|`{FMS}`|
|message_pocsag|Format der Nachricht für Pocsag|`{RIC}({SRIC})\n{MSG}`|
|message_zvei|Format der Nachricht für ZVEI|`{TONE}`|
|message_msg|Format der Nachricht für MSG||
**Beispiel:** **Beispiel:**
```yaml ```yaml
@ -25,7 +31,7 @@ Außerdem werden Locations versendet, wenn die Felder `lat` und `lon` im Paket d
name: Telegram Plugin name: Telegram Plugin
res: telegram res: telegram
config: config:
message: "{RIC}({SRIC})\n{MSG}" message_pocsag: "{RIC}({SRIC})\n{MSG}"
botToken: "BOT_TOKEN" botToken: "BOT_TOKEN"
chatIds: chatIds:
- "CHAT_ID" - "CHAT_ID"
@ -33,7 +39,7 @@ Außerdem werden Locations versendet, wenn die Felder `lat` und `lon` im Paket d
--- ---
## Modul Abhängigkeiten ## Modul Abhängigkeiten
Aus dem Modul [Geocoding](../modul/geocoding.md) (optional): Aus dem Modul [Geocoding](../modul/geocoding.md) (optional/nur POCSAG):
- `lat` - `lat`
- `lon` - `lon`

View file

@ -42,10 +42,10 @@ class BoswatchModule(ModuleBase):
@param bwPacket: A BOSWatch packet instance""" @param bwPacket: A BOSWatch packet instance"""
for descriptor in self.config: for descriptor in self.config:
for description in descriptor.get("descriptions"):
if not bwPacket.get(descriptor.get("scanField")): if not bwPacket.get(descriptor.get("scanField")):
break # scanField is not available in this packet break # scanField is not available in this packet
bwPacket.set(descriptor.get("descrField"), description.get("for")) bwPacket.set(descriptor.get("descrField"), bwPacket.get(descriptor.get("scanField")))
for description in descriptor.get("descriptions"):
if str(description.get("for")) == bwPacket.get(descriptor.get("scanField")): if str(description.get("for")) == bwPacket.get(descriptor.get("scanField")):
logging.debug("Description '%s' added in packet field '%s'", logging.debug("Description '%s' added in packet field '%s'",
description.get("add"), descriptor.get("descrField")) description.get("add"), descriptor.get("descrField"))

View file

@ -25,7 +25,7 @@ from module.moduleBase import ModuleBase
logging.debug("- %s loaded", __name__) logging.debug("- %s loaded", __name__)
class BoswatchModul(ModuleBase): class BoswatchModule(ModuleBase):
"""!Description of the Module""" """!Description of the Module"""
def __init__(self, config): def __init__(self, config):
"""!Do not change anything here!""" """!Do not change anything here!"""

View file

@ -63,25 +63,64 @@ class BoswatchPlugin(PluginBase):
request = Request(con_pool_size=8) request = Request(con_pool_size=8)
self.bot = MQBot(token=self.config.get("botToken", default=""), request=request, mqueue=q) self.bot = MQBot(token=self.config.get("botToken", default=""), request=request, mqueue=q)
def fms(self, bwPacket):
"""!Called on FMS alarm
@param bwPacket: bwPacket instance"""
msg = self.parseWildcards(self.config.get("message_fms", default="{FMS}"))
self._sendMessage(msg)
def pocsag(self, bwPacket): def pocsag(self, bwPacket):
"""!Called on POCSAG alarm """!Called on POCSAG alarm
@param bwPacket: bwPacket instance""" @param bwPacket: bwPacket instance"""
msg = self.parseWildcards(self.config.get("message")) msg = self.parseWildcards(self.config.get("message_pocsag", default="{RIC}({SRIC})\n{MSG}"))
self._sendMessage(msg)
if bwPacket.get("lat") is not None and bwPacket.get("lon") is not None: if bwPacket.get("lat") is not None and bwPacket.get("lon") is not None:
logging.debug("Found coordinates in packet") logging.debug("Found coordinates in packet")
(lat, lon) = (bwPacket.get("lat"), bwPacket.get("lon")) (lat, lon) = (bwPacket.get("lat"), bwPacket.get("lon"))
self._sendMessage(lat, lon)
def zvei(self, bwPacket):
"""!Called on ZVEI alarm
@param bwPacket: bwPacket instance"""
msg = self.parseWildcards(self.config.get("message_zvei", default="{TONE}"))
self._sendMessage(msg)
def msg(self, bwPacket):
"""!Called on MSG packet
@param bwPacket: bwPacket instance"""
msg = self.parseWildcards(self.config.get("message_msg"))
self._sendMessage(msg)
def _sendMessage(self, message):
for chatId in self.config.get("chatIds", default=[]): for chatId in self.config.get("chatIds", default=[]):
try: try:
# Send Message via Telegram # Send Message via Telegram
logging.info("Sending message to " + chatId) logging.info("Sending message to " + chatId)
self.bot.send_message(chat_id=chatId, text=msg) self.bot.send_message(chat_id=chatId, text=message)
except Unauthorized:
logging.exception("Error while sending Telegram Message, please Check your api-key")
except (TimedOut, NetworkError):
logging.exception("Error while sending Telegram Message, please Check your connectivity")
except (BadRequest, TelegramError):
logging.exception("Error while sending Telegram Message")
except Exception as e:
logging.exception("Unknown Error while sending Telegram Message: " + str(type(e).__name__) + ": " + str(e))
def _sendLocation(self, lat, lon):
for chatId in self.config.get("chatIds", default=[]):
try:
# Send Location via Telegram
if lat is not None and lon is not None:
logging.info("Sending location to " + chatId)
self.bot.sendLocation(chat_id=chatId, latitude=lat, longitude=lon)
# Send Location via Telegram if lat and lon are defined
if lat is not None and lon is not None:
logging.info("Sending location to " + chatId)
self.bot.sendLocation(chat_id=chatId, latitude=lat, longitude=lon)
except Unauthorized: except Unauthorized:
logging.exception("Error while sending Telegram Message, please Check your api-key") logging.exception("Error while sending Telegram Message, please Check your api-key")
except (TimedOut, NetworkError): except (TimedOut, NetworkError):

View file

@ -0,0 +1,72 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""!
____ ____ ______ __ __ __ _____
/ __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ /
/ __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ <
/ /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ /
/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/
German BOS Information Script
by Bastian Schroll
@file: test_descriptor.py
@date: 14.04.2020
@author: Bastian Schroll
@description: Unittests for BOSWatch. File have to run as "pytest" unittest
"""
# problem of the pytest fixtures
# pylint: disable=redefined-outer-name
import logging
import pytest
from boswatch.utils import paths
from boswatch.configYaml import ConfigYAML
from boswatch.packet import Packet
from module.descriptor import BoswatchModule as Descriptor
def setup_method(method):
logging.debug("[TEST] %s.%s", method.__module__, method.__name__)
@pytest.fixture
def makeDescriptor():
"""!Build a descriptor object with loaded configuration"""
config = ConfigYAML()
assert config.loadConfigFile(paths.TEST_PATH + "test_config.yaml") is True
descriptor = Descriptor(config.get("descriptor_test"))
return descriptor
@pytest.fixture
def makePacket():
"""!Build a BW Packet object"""
packet = Packet()
return packet
def test_descriptorFoundFirst(makeDescriptor, makePacket):
"""!Run descriptor on the first entry in list"""
makePacket.set("tone", "12345")
makePacket = makeDescriptor.doWork(makePacket)
assert makePacket.get("description") == "Test 12345"
def test_descriptorFoundSecond(makeDescriptor, makePacket):
"""!Run descriptor on the second entry in list"""
makePacket.set("tone", "23456")
makePacket = makeDescriptor.doWork(makePacket)
assert makePacket.get("description") == "Test 23456"
def test_descriptorNotFound(makeDescriptor, makePacket):
"""!Run descriptor no matching data found"""
makePacket.set("tone", "99999")
makePacket = makeDescriptor.doWork(makePacket)
assert makePacket.get("description") == "99999"
def test_descriptorScanFieldNotAvailable(makeDescriptor, makePacket):
"""!Run descriptor on a non existent scanField"""
makePacket = makeDescriptor.doWork(makePacket)
assert makePacket.get("description") is None

View file

@ -8,7 +8,7 @@
# by Bastian Schroll # by Bastian Schroll
[pytest] [pytest]
addopts = -v --pep8 --flakes --cov=boswatch/ --cov-report=term-missing --log-level=CRITICAL addopts = -v --pep8 --flakes --cov=boswatch/ --cov=module/ --cov plugin/ --cov-report=term-missing --log-level=CRITICAL
# classic or progress # classic or progress
console_output_style = progress console_output_style = progress

View file

@ -30,3 +30,12 @@ list1:
- two - two
- three - three
- string1 - string1
descriptor_test:
- scanField: tone
descrField: description
descriptions:
- for: 12345
add: Test 12345
- for: 23456
add: Test 23456