fix(bridge): OBP routing — TS1 match, DMRE slot, OBP dedupe

- Match BRIDGES source rules with effective TS1 for OpenBridge (has_source).
- Normalize DMRE receive slot to 1 for OPENBRIDGE before STATUS/dmrd_received.
- Dedupe OBP (SYSTEM, TS) per packet like legacy sysIgnore (TG + reflector lists).
pull/4/head
Rodrigo Pérez 6 months ago
parent 9d5e7d00c0
commit d1696d6016

@ -1095,6 +1095,10 @@ class BridgeUseCases:
dst_int = int_id(dst_id)
systems_cfg = self._config.get("SYSTEMS", {})
source_is_obp = systems_cfg.get(system_name, {}).get("MODE") == "OPENBRIDGE"
# Legacy bridge_master to_target: OpenBridge clears TS bit — "all OpenBridge streams are
# effectively on TS1". DMRD v1 rejects slot != 1; DMRE v5 can still set slot 2 from bits.
# BRIDGES entries for OBP use TS:1 (make_single_bridge / make_stat_bridge). Match that.
bridge_match_slot = 1 if source_is_obp else slot
if bridge_key not in bridges:
if dst_int < 5 or dst_int == 9 or dst_int == 4000 or dst_int == 5000:
logger.debug(
@ -1121,7 +1125,7 @@ class BridgeUseCases:
dst_id_b = dst_id if isinstance(dst_id, bytes) and len(dst_id) >= 3 else bytes_3(dst_int)
has_source = any(
entry.get("SYSTEM") == system_name
and entry.get("TS") == slot
and entry.get("TS") == bridge_match_slot
and entry.get("ACTIVE")
and (entry.get("TGID") == dst_id_b or int_id(entry.get("TGID") or b"\x00\x00\x00") == dst_int)
for entry in entries
@ -1132,7 +1136,7 @@ class BridgeUseCases:
entries = list(bridges.get(bridge_key, [])) + list(bridges.get("#" + bridge_key, []))
has_source = any(
entry.get("SYSTEM") == system_name
and entry.get("TS") == slot
and entry.get("TS") == bridge_match_slot
and entry.get("ACTIVE")
and (entry.get("TGID") == dst_id_b or int_id(entry.get("TGID") or b"\x00\x00\x00") == dst_int)
for entry in entries
@ -1140,7 +1144,7 @@ class BridgeUseCases:
if not has_source:
logger.debug(
"(ROUTER) No matching source rule for TG %s from %s slot %s (ACTIVE), not forwarding",
bridge_key, system_name, slot,
bridge_key, system_name, bridge_match_slot,
)
return
pkt_time = time.time()
@ -1272,6 +1276,11 @@ class BridgeUseCases:
source_lc = st.get(slot, {}).get("RX_LC")
if not source_lc or len(source_lc) < 9:
source_lc = b"\x00\x00\x20" + dst_id_b + rf_src
# Legacy bridge_master to_target: _sysIgnore — dedupe OBP (SYSTEM, TS) per packet across
# multiple to_target passes (current TG + reflector + other bridges). We merge those
# lists into one `entries` loop, so the same OpenBridge can appear twice (e.g. TG + #TG)
# and would get duplicate sends → echo/loops without this.
sys_ignore_obp: set[tuple[str, int]] = set()
forwarded = []
for entry in entries:
if entry.get("SYSTEM") == system_name:
@ -1287,6 +1296,13 @@ class BridgeUseCases:
if target_mode == "OPENBRIDGE":
# ── Exact port of legacy bridge.py OBP target (lines 355-401 / 672-718) ──
entry_ts_obp = entry.get("TS")
if entry_ts_obp is None:
entry_ts_obp = 1
_obp_key = (entry["SYSTEM"], int(entry_ts_obp))
if _obp_key in sys_ignore_obp:
continue
sys_ignore_obp.add(_obp_key)
target_tgid = entry.get("TGID")
if isinstance(target_tgid, int):
target_tgid = bytes_3(target_tgid)

@ -1167,6 +1167,10 @@ class HBPProtocol(DatagramProtocol):
_int_dst_id = int_id(_dst_id)
_bits = _data[15]
_slot = 2 if (_bits & 0x80) else 1
if self._config.get("MODE") == "OPENBRIDGE":
# Legacy bridge_master: OpenBridge streams are effectively TS1 (DMRD v1 rejects slot != 1).
# DMRE can still carry TS2 in bits; BRIDGES use TS:1 for OBP — normalize before STATUS/dmrd.
_slot = 1
if _bits & 0x40:
_call_type = "unit"
elif (_bits & 0x23) == 0x23:

Loading…
Cancel
Save

Powered by TurnKey Linux.