@ -338,7 +338,7 @@ def peer_owns_multi_dynamic_ua(
* ,
peer_id : bytes | None = None ,
) - > bool :
""" True when SINGLE=0 peer has keyed this non-static dynamic TG on ``slot`` ."""
""" True when SINGLE=0 peer has keyed this non-static dynamic TG (either slot) ."""
if not sys_cfg or peer_single_mode ( peer , sys_cfg ) :
return False
if peer_id is None :
@ -352,8 +352,12 @@ def peer_owns_multi_dynamic_ua(
per_peer = store . get ( pk )
if not isinstance ( per_peer , dict ) :
return False
slot_set = per_peer . get ( int ( slot ) )
return isinstance ( slot_set , set ) and int ( tgid ) in slot_set
tgid_i = int ( tgid )
for voice_slot in ( 1 , 2 ) :
slot_set = per_peer . get ( voice_slot )
if isinstance ( slot_set , set ) and tgid_i in slot_set :
return True
return False
def register_peer_ua_session (
@ -582,17 +586,21 @@ def peer_single_blocks_group_voice(
peer_id : bytes | None = None ,
now : float | None = None ,
) - > bool :
""" True when SINGLE=1 peer must not receive downlink for ``tgid`` on ``slot`` .
""" True when SINGLE=1 peer must not receive downlink for ``tgid`` .
With an active session on TG X , every other TG ( static or dynamic ) is blocked
until the TIMER expires or a new local TX replaces the session .
"""
del slot
if not sys_cfg :
return False
locked = peer_single_exclusive_tgid ( peer , slot , sys_cfg , peer_id = peer_id , now = now )
if locked is None :
return False
return int ( tgid ) != locked
for voice_slot in ( 1 , 2 ) :
locked = peer_single_exclusive_tgid (
peer , voice_slot , sys_cfg , peer_id = peer_id , now = now ,
)
if locked is not None and int ( tgid ) != locked :
return True
return False
def peer_receives_group_tgid ( peer : dict [ str , Any ] , slot : int , tgid : int ) - > bool :
@ -602,7 +610,11 @@ def peer_receives_group_tgid(peer: dict[str, Any], slot: int, tgid: int) -> bool
slot while self - service lists the TG on the other .
"""
del slot
return peer_options_static_tg_slot ( peer , tgid ) is not None
from adn_server . application . report . payloads import parse_peer_options_static
ts1 , ts2 = parse_peer_options_static ( peer . get ( " OPTIONS " ) )
tg = str ( tgid )
return tg in ts1 or tg in ts2
def peer_options_static_tg_slot ( peer : dict [ str , Any ] , tgid : int ) - > int | None :
@ -620,6 +632,56 @@ def peer_options_static_tg_slot(peer: dict[str, Any], tgid: int) -> int | None:
return None
def synthetic_group_dmrd_route_packet ( slot : int , tgid : int ) - > bytes :
""" Minimal DMRD for inject-only downlink fan-out lookup (slot + TG only). """
bits = 0x80 if int ( slot ) == 2 else 0
return b " DMRD " + b " \x00 " * 4 + bytes_3 ( tgid ) + b " \x00 " * 4 + bytes ( [ bits ] ) + b " \x00 " * 38
def repeat_downlink_report_slot (
wire_slot : int ,
tgid : int ,
peers : dict [ Any , Any ] ,
downlink_peer_ids : tuple [ bytes , . . . ] ,
sys_cfg : dict [ str , Any ] | None ,
) - > int :
""" Monitor timeslot for REPEAT downlink START/TX (OBP bridge uses target TS, not wire slot).
When every downlink peer maps the TG to the same OPTIONS or UA slot , use that slot so
CTABLE chips match RF ( cross - slot static / dynamic ) . Otherwise fall back to wire slot .
"""
display_slots : set [ int ] = set ( )
tgid_i = int ( tgid )
for peer_id in downlink_peer_ids :
peer = peers . get ( peer_id )
if not isinstance ( peer , dict ) :
continue
static_slot = peer_options_static_tg_slot ( peer , tgid_i )
if static_slot is not None :
display_slots . add ( static_slot )
continue
if not sys_cfg :
continue
pk = bytes_4 ( int_id ( peer_id ) )
for voice_slot in ( 1 , 2 ) :
locked = peer_single_exclusive_tgid (
peer , voice_slot , sys_cfg , peer_id = peer_id ,
)
if locked is not None and int ( locked ) == tgid_i :
display_slots . add ( voice_slot )
store = sys_cfg . get ( " _PEER_UA_MULTI_TGS " )
if isinstance ( store , dict ) :
per_peer = store . get ( pk )
if isinstance ( per_peer , dict ) :
for voice_slot in ( 1 , 2 ) :
slot_set = per_peer . get ( voice_slot )
if isinstance ( slot_set , set ) and tgid_i in slot_set :
display_slots . add ( voice_slot )
if len ( display_slots ) == 1 :
return display_slots . pop ( )
return int ( wire_slot )
def peer_single_blocks_uplink (
peer : dict [ str , Any ] ,
peer_id : bytes ,
@ -651,8 +713,14 @@ def _peer_owns_dynamic_ua(
return False
if not sys_cfg :
return False
locked = peer_single_exclusive_tgid ( peer , slot , sys_cfg , peer_id = peer_id , now = now )
return locked is not None and int ( tgid ) == locked
tgid_i = int ( tgid )
for voice_slot in ( 1 , 2 ) :
locked = peer_single_exclusive_tgid (
peer , voice_slot , sys_cfg , peer_id = peer_id , now = now ,
)
if locked is not None and tgid_i == locked :
return True
return False
def peer_should_receive_group_voice (