[feat/multicast]: add multi-instance multicast module with active trigger system

Introduce a robust multicast processing module for POCSAG that correlates
empty tone-RICs (recipients) with subsequent text-RICs (content).

Key Features:
- Four Output Modes: Internally supports 'complete', 'incomplete', 'single',
  and 'control'. Functional alarms are delivered as the first three, while
  technical 'control' packets (Delimiters/NetIdent) are filtered by default.
- Active Trigger System: Implements a loss-free deferred delivery mechanism
  using a loopback socket (TCP) to re-inject wakeup packets, flushing the
  internal queue during auto-clear timeouts.
- Shared State & Multi-Instance: State is shared across instances but
  separated by frequency to prevent crosstalk in multi-frequency setups.
- Data Aggregation: Automatically generates '{FIELD}_list' wildcards (e.g.,
  RIC_LIST, DESCRIPTION_LIST) for all collected recipients, enabling
  consolidated notifications in downstream plugins.
- Dynamic Filtering: Automatically blocks Delimiter and NetIdent RICs from
  reaching subsequent plugins if they are defined in the configuration.

Infrastructural Changes:
- ModuleBase: Expanded return semantics to support:
  * False: Explicitly blocks/drops a packet.
  * List: Allows a module to expand one input into multiple output packets.
- PluginBase: Updated to handle lists of packets, ensuring a full
  setup->alarm->teardown lifecycle for every individual element.
This commit is contained in:
KoenigMjr 2025-11-25 16:25:28 +01:00
parent 7d4cb57a6e
commit 0b9387af08
5 changed files with 1069 additions and 1 deletions

View file

@ -65,6 +65,15 @@ class PluginBase(ABC):
The alarm() method serves the BOSWatch packet to the plugin.
@param bwPacket: A BOSWatch packet instance"""
# --- FIX: Multicast list support ---
if isinstance(bwPacket, list):
# if we got a list of packets, we have to run each packet through the complete alarm process (Setup -> Alarm -> Teardown)
for single_packet in bwPacket:
self._run(single_packet)
return None
# ---------------------------------------------------------------------
self._runCount += 1
logging.debug("[%s] run #%d", self._pluginName, self._runCount)