Merge pull request #52 from b-watch/FR-DoubleFilter

PR doubleFilter
This commit is contained in:
Bastian Schroll 2020-07-15 10:02:42 +02:00 committed by GitHub
commit e742283216
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 88 additions and 21 deletions

View file

@ -0,0 +1,49 @@
# <center>Double Filter</center>
---
## Beschreibung
Mit diesem Modul ist es möglich, die Pakete auf Duplikate zu Filtern. Je nach Konfiguration werden doppelte Pakete im aktuellen Router weitergeleitet oder verworfen.
## Unterstütze Alarmtypen
- Fms
- Pocsag
- Zvei
## Resource
`filter.doubleFilter`
## Konfiguration
|Feld|Beschreibung|Default|
|----|------------|-------|
|ignoreTime|Zeitfenster für doppelte Pakte in Sekunden|10|
|maxEntry|Maximale Anzahl an Paketen in der Vergleichsliste|20|
|pocsagFields|Liste der Pocsag Felder zum Vergleichen: `ric`, `subric` und/oder `message`|`ric,subric`|
**Beispiel:**
```yaml
- type: module
res: filter.doubleFilter
config:
ignoreTime: 30
maxEntry: 10
pocsagFields:
- ric
- subric
```
---
## Modul Abhängigkeiten
- keine
---
## Externe Abhängigkeiten
- keine
---
## Paket Modifikationen
- keine
---
## Zusätzliche Wildcards
- keine

View file

@ -22,6 +22,7 @@ nav:
- Geocoding: modul/geocoding.md - Geocoding: modul/geocoding.md
- Mode Filter: modul/mode_filter.md - Mode Filter: modul/mode_filter.md
- Regex Filter: modul/regex_filter.md - Regex Filter: modul/regex_filter.md
- Double Filter: modul/double_filter.md
- Plugins: - Plugins:
- Http: plugin/http.md - Http: plugin/http.md
- Telegram: plugin/telegram.md - Telegram: plugin/telegram.md

View file

@ -10,33 +10,45 @@
by Bastian Schroll by Bastian Schroll
@file: doubleFilter.py @file: doubleFilter.py
@date: 15.01.2018 @date: 09.07.2020
@author: Bastian Schroll @author: Bastian Schroll, b-watch
@description: Class to implement a filter for double alarms @description: Filter module for double packages
@todo test, refactor and document / check_msg is not implemented yet
""" """
import logging import logging
from module.moduleBase import ModuleBase
# ###################### #
# Custom plugin includes #
import time import time
# ######################
logging.debug("- %s loaded", __name__) logging.debug("- %s loaded", __name__)
class DoubleFilter: class BoswatchModule(ModuleBase):
"""!Double Filter Class""" """!Description of the Module"""
def __init__(self, config): def __init__(self, config):
"""!init""" """!Do not change anything here!"""
self._config = config super().__init__(__name__, config) # you can access the config class on 'self.config'
self._filterLists = {} self._filterLists = {}
logging.debug("Configured ignoreTime: %d", self.config.get("ignoreTime", default=10))
logging.debug("Configured maxEntry: %d", self.config.get("maxEntry", default=10))
def filter(self, bwPacket): def onLoad(self):
"""!Called by import of the plugin
Remove if not implemented"""
pass
def doWork(self, bwPacket):
"""!start an run of the module.
@param bwPacket: A BOSWatch packet instance"""
if bwPacket.get("mode") == "fms": if bwPacket.get("mode") == "fms":
scanWord = "fms" filterFields = ["fms"]
elif bwPacket.get("mode") == "pocsag": elif bwPacket.get("mode") == "pocsag":
scanWord = "ric" filterFields = self.config.get("pocsagFields", default=["ric", "subric"])
elif bwPacket.get("mode") == "zvei": elif bwPacket.get("mode") == "zvei":
scanWord = "zvei" filterFields = ["tone"]
else: else:
logging.error("No Filter for '%s'", bwPacket) logging.error("No Filter for '%s'", bwPacket)
return False return False
@ -45,31 +57,36 @@ class DoubleFilter:
logging.debug("create new doubleFilter list for '%s'", bwPacket.get("mode")) logging.debug("create new doubleFilter list for '%s'", bwPacket.get("mode"))
self._filterLists[bwPacket.get("mode")] = [] self._filterLists[bwPacket.get("mode")] = []
logging.debug("scanWord for '%s' is '%s'", bwPacket.get("mode"), scanWord) logging.debug("filterFields for '%s' is '%s'", bwPacket.get("mode"), ", ".join(filterFields))
return self._check(bwPacket, scanWord) return self._check(bwPacket, filterFields)
def _check(self, bwPacket, scanWord): def onUnload(self):
"""!Called by destruction of the plugin
Remove if not implemented"""
pass
def _check(self, bwPacket, filterFields):
self._filterLists[bwPacket.get("mode")].insert(0, bwPacket) self._filterLists[bwPacket.get("mode")].insert(0, bwPacket)
# delete entries that are to old # delete entries that are to old
counter = 0 counter = 0
for listPacket in self._filterLists[bwPacket.get("mode")][1:]: # [1:] skip first entry, thats the new one for listPacket in self._filterLists[bwPacket.get("mode")][1:]: # [1:] skip first entry, thats the new one
if listPacket.get("timestamp") < (time.time() - self._config["ignoreTime"]): if float(listPacket.get("timestamp")) < (time.time() - self.config.get("ignoreTime", default=10)):
self._filterLists[bwPacket.get("mode")].remove(listPacket) self._filterLists[bwPacket.get("mode")].remove(listPacket)
counter += 1 counter += 1
if counter: if counter:
logging.debug("%d old entry(s) removed", counter) logging.debug("%d old entry(s) removed", counter)
# delete last entry if list is to big # delete last entry if list is to big
if len(self._filterLists[bwPacket.get("mode")]) > self._config["maxEntry"]: if len(self._filterLists[bwPacket.get("mode")]) > self.config.get("maxEntry", default=20):
logging.debug("MaxEntry reached - delete oldest") logging.debug("MaxEntry reached - delete oldest")
self._filterLists[bwPacket.get("mode")].pop() self._filterLists[bwPacket.get("mode")].pop()
for listPacket in self._filterLists[bwPacket.get("mode")][1:]: # [1:] skip first entry, thats the new one for listPacket in self._filterLists[bwPacket.get("mode")][1:]: # [1:] skip first entry, thats the new one
if listPacket.get(scanWord) is bwPacket.get(scanWord): if all(listPacket.get(x) == bwPacket.get(x) for x in filterFields):
logging.debug("found duplicate: %s", bwPacket.get(scanWord)) logging.debug("found duplicate: %s", bwPacket.get("mode"))
return False return False
logging.debug("doubleFilter ok") logging.debug("doubleFilter ok")
return True return None