From 48b3f4e6bddc9f9e6924b4ac0bc5f10b4d836b23 Mon Sep 17 00:00:00 2001 From: Felix Moessbauer Date: Sat, 16 May 2026 16:03:19 +0200 Subject: [PATCH] feat(darc_mowas_service): Re-transmit bit identical messages For the emergency communication, we need to ensure that all messages are transmitted (and received) correctly. We already check if a repeater acks our message, however a missing ack does not tell us if the message was lost, or the ack. For that, we repeat the message in this case, leading to potentially content-wise duplicated receptions on the network. To let the network depulicate the traffic, the re-transmissions need to be bit identical with the original message. For that, we compute a timestamp on initial send and use the same timestamp on re-transmissions (per message). This further allows clients to chronologically sort the received messages, making the result easier to read. Signed-off-by: Felix Moessbauer --- modules/service_plugins/darc_mowas_service.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/service_plugins/darc_mowas_service.py b/modules/service_plugins/darc_mowas_service.py index 38a7e14..b480ea4 100644 --- a/modules/service_plugins/darc_mowas_service.py +++ b/modules/service_plugins/darc_mowas_service.py @@ -19,7 +19,7 @@ import time import xml.dom.minidom from asyncio import AbstractEventLoop from dataclasses import dataclass -from datetime import datetime +from datetime import datetime, timedelta from typing import Any, cast import aiohttp @@ -176,11 +176,14 @@ class DARC_MoWaS_Service(BaseServicePlugin): Send all chunks, each with async retry if configured. Note, that we cannot guarantee that the messages arrive in-order, but as the chunks have a (x/n) identifier at the end, the user still - should be able to grasp the message correctly. + should be able to grasp the message correctly. We further add + an ascending timestamp to each message (also used on re-transmission) to + let the client restore the order, as well as deduplicate retransmissions. Ideally this chunking should be implemented at protocol level to guarantee the atomicity and order of the full message. """ + ts_now = datetime.now() for i, chunk in enumerate(chunks): asyncio.create_task( self._send_chunk_with_retry( @@ -188,6 +191,7 @@ class DARC_MoWaS_Service(BaseServicePlugin): chunk, i, len(chunks), + ts_now + timedelta(seconds=1) ) ) @@ -197,6 +201,7 @@ class DARC_MoWaS_Service(BaseServicePlugin): chunk: str, index: int, total: int, + timestamp: datetime, ) -> None: """Send a chunk and retry until acked or retries exhausted.""" tracker = getattr(self.bot, "transmission_tracker", None) @@ -210,6 +215,7 @@ class DARC_MoWaS_Service(BaseServicePlugin): chunk, command_id=cmd_id, skip_user_rate_limit=True, + timestamp=timestamp ): self.logger.warning("Send failed for '%s'", channel) return