Files
hblink3/const.py
T
Cort BuffingtonandClaude Opus 4.8 c9f628a9ba HBlink3: emit END on stream supersession + 2s no-audio timeout
Fix the root cause of the dashboard's phantom "active" streams: HBlink3 did not
guarantee a matching END for every START. When a new stream took over a timeslot
whose previous stream never sent a terminator, the slot state was simply
overwritten, and the trimmer only ever emitted an END for whichever stream
currently owned the slot -- superseded streams were dropped silently.

- routerHBP._end_slot_stream(slot): if a slot holds an un-terminated stream,
  declare it ended and emit a matching END (with the correct GROUP/UNIT call
  type, now tracked per slot as RX_CT). Idempotent.
- Call it at the new-stream adoption point in group_received and unit_received,
  so a superseding stream first ends the one it replaces (restores the original
  pre-supersession behavior; the overwrite-only version kept routing correct but
  orphaned the call logs).
- Stream timeout dropped from 5s (polled every 5s) to STREAM_TIMEOUT=2s polled
  every 1s: on RF, ~2s of no audio means sync is lost and any resumption is a new
  stream (late entry), so the stream is over. The trimmer's RX timeout now routes
  through _end_slot_stream too.

Report-only behavior; routing is unchanged (byte baseline still green). The
dashboard's stream reaper stays as a backstop for feed-disconnect gaps HBlink3
can't help with. Suite now 42 tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 20:25:39 -05:00

79 lines
2.3 KiB
Python
Executable File

#!/usr/bin/env python
#
###############################################################################
# Copyright (C) 2016-2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
###############################################################################
'''
These are contants used by HBlink. Rather than stuff them into the main program
file, any new constants should be placed here. It makes them easier to keep track
of and keeps hblink.py shorter.
'''
__author__ = 'Cortney T. Buffington, N0MJS'
__copyright__ = 'Copyright (c) 2016 Cortney T. Buffington, N0MJS and the K0USY Group'
__credits__ = ''
__license__ = 'GNU GPLv3'
__maintainer__ = 'Cort Buffington, N0MJS'
__email__ = 'n0mjs@me.com'
# DMR Related constants
ID_MIN = 1
ID_MAX = 16776415
# Timers
STREAM_TO = .360
# Seconds of no audio after which a stream is declared ended. On RF, a gap this
# long means sync is lost and any resumption is a new stream (late entry), so the
# stream is over -- we time it out and emit an END.
STREAM_TIMEOUT = 2
# Options from the LC - used for late entry
LC_OPT = b'\x00\x00\x20'
# HomeBrew Protocol Frame Types
HBPF_VOICE = 0x0
HBPF_VOICE_SYNC = 0x1
HBPF_DATA_SYNC = 0x2
HBPF_SLT_VHEAD = 0x1
HBPF_SLT_VTERM = 0x2
# HomeBrew Protocol Commands
DMRA = b'DMRA'
DMRC = b'DMRC'
DMRD = b'DMRD'
MSTCL = b'MSTCL'
MSTNAK = b'MSTNAK'
MSTPONG = b'MSTPONG'
MSTN = b'MSTN'
MSTP = b'MSTP'
MSTC = b'MSTC'
RPTL = b'RPTL'
RPTPING = b'RPTPING'
RPTCL = b'RPTCL'
RPTACK = b'RPTACK'
RPTK = b'RPTK'
RPTC = b'RPTC'
RPTP = b'RPTP'
RPTA = b'RPTA'
RPTO = b'RPTO'
# Higheset peer ID permitted by HBP
PEER_MAX = 4294967295