Talker Alias: allow multiple text encodings (Motorola + Hytera coexistence)

TALKER_ALIAS_TEXT_FORMAT now accepts a comma-separated list (e.g. "utf8,iso8").
encode_talker_alias_emblc emits the TA blocks in each requested encoding back to
back, and rewrite_embed_lc cycles through them, so radios of different vendors
each pick up the format they support in turn.

Rationale: in field testing, Motorola only displayed format 2 (UTF-8) and Hytera
only format 1 (ISO-8859-1) -- mutually exclusive in a single TA. Sending both
("utf8,iso8") makes the alias show on both at once. Confirmed on real Motorola
and Hytera radios.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pull/38/head
pyopower 2 months ago
parent be20f94bc3
commit 4743d3e803

@ -56,7 +56,9 @@ VALIDATE_SERVER_IDS: True
# TALKER_ALIAS_MODE - passthrough (solo reenvia el TA recibido), inject (genera el TA desde el alias del suscriptor) # TALKER_ALIAS_MODE - passthrough (solo reenvia el TA recibido), inject (genera el TA desde el alias del suscriptor)
# o both (reenvia si llega completo, si no lo genera). Por defecto: both # o both (reenvia si llega completo, si no lo genera). Por defecto: both
# TALKER_ALIAS_FORMAT - plantilla del texto generado en modo inject/both. Campos: {callsign} {fname} {surname} {city} {state} {country} {id} # TALKER_ALIAS_FORMAT - plantilla del texto generado en modo inject/both. Campos: {callsign} {fname} {surname} {city} {state} {country} {id}
# TALKER_ALIAS_TEXT_FORMAT - codificacion del TA: utf8 (defecto), iso8 (ISO-8859-1, recomendado si hay radios Hytera) o 7bit # TALKER_ALIAS_TEXT_FORMAT - codificacion(es) del TA, separadas por coma: utf8 (lo muestra Motorola),
# iso8 (ISO-8859-1, lo muestra Hytera), 7bit. Una lista como 'utf8,iso8' emite el
# TA en ambos formatos seguidos, asi Motorola y Hytera lo ven a la vez. Defecto: utf8
TALKER_ALIAS: False TALKER_ALIAS: False
TALKER_ALIAS_MODE: both TALKER_ALIAS_MODE: both
TALKER_ALIAS_FORMAT: {callsign} {fname} TALKER_ALIAS_FORMAT: {callsign} {fname}

@ -246,13 +246,20 @@ def _encode_emblc(_lc):
return {1: out[0:32], 2: out[32:64], 3: out[64:96], 4: out[96:128]} return {1: out[0:32], 2: out[32:64], 3: out[64:96], 4: out[96:128]}
def encode_talker_alias_emblc(text, text_format='utf8'): def encode_talker_alias_emblc(text, text_formats=('utf8',)):
"""Embedded-LC dicts for TA blocks 0..N-1 plus block count N (1-4).""" """Embedded-LC dicts for the TA blocks. `text_formats` may be a single
encoded = encode_ta_buffer(text, text_format) encoding or several; with several, the TA is emitted in each encoding back to
back (e.g. UTF-8 then ISO-8859-1) so radios of different vendors each pick up
the format they support. Returns (list-of-emblc-dicts, total-count)."""
if isinstance(text_formats, str):
text_formats = [text_formats]
emblcs = []
for tf in (list(text_formats) or ['utf8']):
encoded = encode_ta_buffer(text, tf)
blocks = blocks_from_buffer(encoded) blocks = blocks_from_buffer(encoded)
count = required_ta_block_count(encoded) cnt = required_ta_block_count(encoded)
emblcs = [_encode_emblc(talker_alias_lc_bytes(i, blocks[i])) for i in range(count)] emblcs += [_encode_emblc(talker_alias_lc_bytes(i, blocks[i])) for i in range(cnt)]
return emblcs, count return emblcs, len(emblcs)
def encode_talker_alias_emblc_from_blocks(blocks): def encode_talker_alias_emblc_from_blocks(blocks):
@ -313,10 +320,14 @@ def ta_settings(CONFIG, system_name=None):
tfmt = sys_cfg.get('TALKER_ALIAS_TEXT_FORMAT') tfmt = sys_cfg.get('TALKER_ALIAS_TEXT_FORMAT')
if tfmt is None: if tfmt is None:
tfmt = g.get('TALKER_ALIAS_TEXT_FORMAT', 'utf8') tfmt = g.get('TALKER_ALIAS_TEXT_FORMAT', 'utf8')
tfmt = str(tfmt).lower() # comma-separated list -> emit the TA in each encoding back to back, so radios
if tfmt not in ('utf8', 'iso8', '7bit'): # of different vendors each pick up the format they support (e.g. 'utf8,iso8'
tfmt = 'utf8' # for Motorola + Hytera coexistence).
return {'enabled': bool(enabled), 'mode': mode, 'format': str(fmt), 'text_format': tfmt} formats = [f.strip().lower() for f in str(tfmt).split(',')]
formats = [f for f in formats if f in ('utf8', 'iso8', '7bit')]
if not formats:
formats = ['utf8']
return {'enabled': bool(enabled), 'mode': mode, 'format': str(fmt), 'text_formats': formats}
def ta_enabled(CONFIG, system_name=None): def ta_enabled(CONFIG, system_name=None):
@ -404,13 +415,13 @@ def resolve_ta(CONFIG, system_name, rf_src, blocks):
'text': decode_ta(buffer_from_blocks(blocks))} 'text': decode_ta(buffer_from_blocks(blocks))}
if mode == 'inject': if mode == 'inject':
return {'source': 'inject', 'blocks': None, return {'source': 'inject', 'blocks': None,
'text': format_ta_text(CONFIG, rf_src), 'text_format': settings['text_format']} 'text': format_ta_text(CONFIG, rf_src), 'text_formats': settings['text_formats']}
# both # both
if have_passthrough: if have_passthrough:
return {'source': 'passthrough', 'blocks': dict(blocks), return {'source': 'passthrough', 'blocks': dict(blocks),
'text': decode_ta(buffer_from_blocks(blocks))} 'text': decode_ta(buffer_from_blocks(blocks))}
return {'source': 'inject', 'blocks': None, return {'source': 'inject', 'blocks': None,
'text': format_ta_text(CONFIG, rf_src), 'text_format': settings['text_format']} 'text': format_ta_text(CONFIG, rf_src), 'text_formats': settings['text_formats']}
def ta_dmra_packets(rf_src, resolved): def ta_dmra_packets(rf_src, resolved):
@ -419,7 +430,7 @@ def ta_dmra_packets(rf_src, resolved):
return [] return []
if resolved['source'] == 'passthrough': if resolved['source'] == 'passthrough':
return passthrough_packets_from_blocks(rf_src, resolved['blocks']) return passthrough_packets_from_blocks(rf_src, resolved['blocks'])
return build_dmra_packets(rf_src, resolved['text'], resolved.get('text_format', 'utf8')) return build_dmra_packets(rf_src, resolved['text'], (resolved.get('text_formats') or ['utf8'])[0])
def ta_emblc(resolved): def ta_emblc(resolved):
@ -428,7 +439,7 @@ def ta_emblc(resolved):
return None return None
if resolved['source'] == 'passthrough': if resolved['source'] == 'passthrough':
return encode_talker_alias_emblc_from_blocks(resolved['blocks']) return encode_talker_alias_emblc_from_blocks(resolved['blocks'])
return encode_talker_alias_emblc(resolved['text'], resolved.get('text_format', 'utf8')) return encode_talker_alias_emblc(resolved['text'], resolved.get('text_formats', ['utf8']))
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

Loading…
Cancel
Save

Powered by TurnKey Linux.