implement changes for dynamic power setting
This commit is contained in:
@@ -96,6 +96,36 @@ QOS_PRESET_MAP = {
|
||||
"Robust": auracast_config.AuracastQosRobust(),
|
||||
}
|
||||
|
||||
# Discrete advertising TX power steps in dBm supported by the Nordic SDC radio
|
||||
# PA. Sent through HCI_LE_Set_Extended_Advertising_Parameters; the controller
|
||||
# clamps to the nearest hardware step.
|
||||
TX_POWER_OPTIONS = [8, 7, 6, 5, 4, 3, 2, 0, -4, -8, -12, -16, -20]
|
||||
TX_POWER_DEFAULT = 8
|
||||
|
||||
|
||||
def _coerce_tx_power(value, default: int = TX_POWER_DEFAULT) -> int:
|
||||
try:
|
||||
v = int(value)
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
if v in TX_POWER_OPTIONS:
|
||||
return v
|
||||
return min(TX_POWER_OPTIONS, key=lambda s: abs(s - v))
|
||||
|
||||
|
||||
def _tx_power_selectbox(label: str, key: str, default: int, disabled: bool, help_text: str | None = None) -> int:
|
||||
snapped = _coerce_tx_power(default)
|
||||
idx = TX_POWER_OPTIONS.index(snapped)
|
||||
return st.selectbox(
|
||||
label,
|
||||
TX_POWER_OPTIONS,
|
||||
index=idx,
|
||||
key=key,
|
||||
format_func=lambda v: f"{v:+d} dBm",
|
||||
disabled=disabled,
|
||||
help=help_text or "Bluetooth advertising TX power for this radio. Higher values increase range; lower values reduce interference and power draw.",
|
||||
)
|
||||
|
||||
# Try loading persisted settings from backend
|
||||
saved_settings = {}
|
||||
try:
|
||||
@@ -394,6 +424,22 @@ if audio_mode == "Demo":
|
||||
disabled=is_streaming,
|
||||
help="Fast: 2 retransmissions, lower latency. Robust: 4 retransmissions, better reliability."
|
||||
)
|
||||
# Per-radio TX power for Demo (independent for R1 and R2)
|
||||
col_tx_r1, col_tx_r2 = st.columns(2, gap="small")
|
||||
with col_tx_r1:
|
||||
tx_power_r1 = _tx_power_selectbox(
|
||||
"TX Power (R1)",
|
||||
key="demo_tx_power_r1",
|
||||
default=saved_settings.get('advertising_tx_power', TX_POWER_DEFAULT),
|
||||
disabled=is_streaming,
|
||||
)
|
||||
with col_tx_r2:
|
||||
tx_power_r2 = _tx_power_selectbox(
|
||||
"TX Power (R2)",
|
||||
key="demo_tx_power_r2",
|
||||
default=saved_settings.get('secondary', {}).get('advertising_tx_power', TX_POWER_DEFAULT),
|
||||
disabled=is_streaming,
|
||||
)
|
||||
#st.info(f"Demo mode selected: {demo_selected} (Streams: {demo_stream_map[demo_selected]['streams']}, Rate: {demo_stream_map[demo_selected]['rate']} Hz)")
|
||||
quality = None # Not used in demo mode
|
||||
else:
|
||||
@@ -490,6 +536,13 @@ else:
|
||||
help="Fast: 2 retransmissions, lower latency. Robust: 4 retransmissions, better reliability."
|
||||
)
|
||||
|
||||
tx_power_r1 = _tx_power_selectbox(
|
||||
"TX Power (R1)",
|
||||
key="analog_tx_power_r1",
|
||||
default=saved_settings.get('advertising_tx_power', TX_POWER_DEFAULT),
|
||||
disabled=is_streaming,
|
||||
)
|
||||
|
||||
col_r1_name, col_r1_lang = st.columns([2, 1])
|
||||
with col_r1_name:
|
||||
stream_name1 = st.text_input(
|
||||
@@ -658,6 +711,13 @@ else:
|
||||
help="Fast: 2 retransmissions, lower latency. Robust: 4 retransmissions, better reliability."
|
||||
)
|
||||
|
||||
tx_power_r2 = _tx_power_selectbox(
|
||||
"TX Power (R2)",
|
||||
key="analog_tx_power_r2",
|
||||
default=saved_settings.get('secondary', {}).get('advertising_tx_power', TX_POWER_DEFAULT),
|
||||
disabled=is_streaming,
|
||||
)
|
||||
|
||||
col_r2_name, col_r2_lang = st.columns([2, 1])
|
||||
with col_r2_name:
|
||||
stream_name2 = st.text_input(
|
||||
@@ -713,6 +773,7 @@ else:
|
||||
'immediate_rendering': immediate_rendering2,
|
||||
'presentation_delay_ms': presentation_delay_ms2,
|
||||
'qos_preset': qos_preset2,
|
||||
'tx_power': tx_power_r2,
|
||||
'analog_gain_db_left': analog_gain_db_left,
|
||||
'analog_gain_db_right': analog_gain_db_right,
|
||||
}
|
||||
@@ -729,6 +790,7 @@ else:
|
||||
'immediate_rendering': immediate_rendering1,
|
||||
'presentation_delay_ms': presentation_delay_ms1,
|
||||
'qos_preset': qos_preset1,
|
||||
'tx_power': tx_power_r1,
|
||||
'stereo_mode': stereo_enabled,
|
||||
'analog_gain_db_left': analog_gain_db_left,
|
||||
'analog_gain_db_right': analog_gain_db_right,
|
||||
@@ -907,7 +969,14 @@ else:
|
||||
disabled=is_streaming,
|
||||
help="Quality of Service preset for Radio 1"
|
||||
)
|
||||
|
||||
|
||||
r1_tx_power = _tx_power_selectbox(
|
||||
"TX Power (R1)",
|
||||
key="dante_tx_power_r1",
|
||||
default=saved_r1_config.get('advertising_tx_power', saved_settings.get('advertising_tx_power', TX_POWER_DEFAULT)),
|
||||
disabled=is_streaming,
|
||||
)
|
||||
|
||||
# Per-stream configuration for Radio 1
|
||||
if dante_stereo_enabled:
|
||||
st.write("**Stereo Stream Configuration (Radio 1)**")
|
||||
@@ -1188,7 +1257,14 @@ else:
|
||||
disabled=is_streaming,
|
||||
help="Quality of Service preset for Radio 2"
|
||||
)
|
||||
|
||||
|
||||
r2_tx_power = _tx_power_selectbox(
|
||||
"TX Power (R2)",
|
||||
key="dante_tx_power_r2",
|
||||
default=saved_r2_config.get('advertising_tx_power', saved_settings.get('secondary', {}).get('advertising_tx_power', TX_POWER_DEFAULT)),
|
||||
disabled=is_streaming,
|
||||
)
|
||||
|
||||
# Per-stream configuration for Radio 2
|
||||
st.write("**Stream Configuration (Radio 2)**")
|
||||
r2_streams = []
|
||||
@@ -1304,6 +1380,7 @@ else:
|
||||
r2_immediate_rendering = False
|
||||
r2_presentation_delay_ms = 40
|
||||
r2_qos_preset = 'Fast'
|
||||
r2_tx_power = TX_POWER_DEFAULT
|
||||
|
||||
# Validate unique input devices for Network - Dante mode
|
||||
if audio_mode == "Network - Dante":
|
||||
@@ -1335,6 +1412,7 @@ else:
|
||||
'immediate_rendering': r1_immediate_rendering,
|
||||
'presentation_delay_ms': r1_presentation_delay_ms,
|
||||
'qos_preset': r1_qos_preset,
|
||||
'tx_power': r1_tx_power,
|
||||
'dante_stereo_mode': dante_stereo_enabled,
|
||||
'dante_stereo_left': dante_left_channel,
|
||||
'dante_stereo_right': dante_right_channel,
|
||||
@@ -1350,6 +1428,7 @@ else:
|
||||
'immediate_rendering': r2_immediate_rendering if radio2_enabled else False,
|
||||
'presentation_delay_ms': r2_presentation_delay_ms if radio2_enabled else 40000,
|
||||
'qos_preset': r2_qos_preset if radio2_enabled else 'Fast',
|
||||
'tx_power': r2_tx_power if radio2_enabled else TX_POWER_DEFAULT,
|
||||
} if radio2_enabled else None
|
||||
|
||||
if audio_mode in ("USB", "Network"):
|
||||
@@ -1406,6 +1485,13 @@ else:
|
||||
help="Fast: 2 retransmissions, lower latency. Robust: 4 retransmissions, better reliability."
|
||||
)
|
||||
|
||||
tx_power = _tx_power_selectbox(
|
||||
"TX Power",
|
||||
key="usb_tx_power",
|
||||
default=saved_settings.get('advertising_tx_power', TX_POWER_DEFAULT),
|
||||
disabled=is_streaming,
|
||||
)
|
||||
|
||||
stream_name = st.text_input(
|
||||
"Channel Name",
|
||||
value=default_name,
|
||||
@@ -1559,6 +1645,7 @@ if start_stream:
|
||||
immediate_rendering=immediate_rendering,
|
||||
presentation_delay_us=int(presentation_delay_ms * 1000),
|
||||
qos_config=QOS_PRESET_MAP[qos_preset],
|
||||
advertising_tx_power=tx_power_r1,
|
||||
bigs=bigs1
|
||||
)
|
||||
config2 = None
|
||||
@@ -1571,6 +1658,7 @@ if start_stream:
|
||||
immediate_rendering=immediate_rendering,
|
||||
presentation_delay_us=int(presentation_delay_ms * 1000),
|
||||
qos_config=QOS_PRESET_MAP[qos_preset],
|
||||
advertising_tx_power=tx_power_r2,
|
||||
bigs=bigs2
|
||||
)
|
||||
|
||||
@@ -1614,6 +1702,7 @@ if start_stream:
|
||||
immediate_rendering=bool(cfg['immediate_rendering']),
|
||||
presentation_delay_us=int(cfg['presentation_delay_ms'] * 1000),
|
||||
qos_config=QOS_PRESET_MAP[cfg['qos_preset']],
|
||||
advertising_tx_power=int(cfg.get('tx_power', TX_POWER_DEFAULT)),
|
||||
analog_gain_db_left=cfg.get('analog_gain_db_left', 0.0),
|
||||
analog_gain_db_right=cfg.get('analog_gain_db_right', 0.0),
|
||||
bigs=[
|
||||
@@ -1701,6 +1790,7 @@ if start_stream:
|
||||
immediate_rendering=bool(radio_cfg['immediate_rendering']),
|
||||
presentation_delay_us=int(radio_cfg['presentation_delay_ms'] * 1000),
|
||||
qos_config=QOS_PRESET_MAP[radio_cfg['qos_preset']],
|
||||
advertising_tx_power=int(radio_cfg.get('tx_power', TX_POWER_DEFAULT)),
|
||||
bigs=bigs
|
||||
)
|
||||
|
||||
@@ -1736,6 +1826,7 @@ if start_stream:
|
||||
immediate_rendering=immediate_rendering,
|
||||
presentation_delay_us=int(presentation_delay_ms * 1000),
|
||||
qos_config=QOS_PRESET_MAP[qos_preset],
|
||||
advertising_tx_power=tx_power,
|
||||
bigs=[
|
||||
auracast_config.AuracastBigConfig(
|
||||
code=(stream_passwort.strip() or None),
|
||||
|
||||
@@ -585,6 +585,7 @@ async def init_radio(transport: str, conf: auracast_config.AuracastConfigGroup,
|
||||
'analog_stereo_mode': getattr(conf.bigs[0], 'analog_stereo_mode', False) if conf.bigs else False,
|
||||
'analog_gain_db_left': getattr(conf, 'analog_gain_db_left', 0.0),
|
||||
'analog_gain_db_right': getattr(conf, 'analog_gain_db_right', 0.0),
|
||||
'advertising_tx_power': getattr(conf, 'advertising_tx_power', 8),
|
||||
'stream_password': (conf.bigs[0].code if conf.bigs and getattr(conf.bigs[0], 'code', None) else None),
|
||||
'big_ids': [getattr(big, 'id', DEFAULT_BIG_ID) for big in conf.bigs],
|
||||
'big_random_addresses': [getattr(big, 'random_address', DEFAULT_RANDOM_ADDRESS) for big in conf.bigs],
|
||||
@@ -755,11 +756,12 @@ async def _autostart_from_settings():
|
||||
big_ids = settings.get('big_ids') or []
|
||||
big_addrs = settings.get('big_random_addresses') or []
|
||||
stream_password = settings.get('stream_password')
|
||||
tx_power = int(settings.get('advertising_tx_power', 8))
|
||||
original_ts = settings.get('timestamp')
|
||||
previously_streaming = bool(settings.get('is_streaming'))
|
||||
|
||||
log.info(
|
||||
"[AUTOSTART][PRIMARY] loaded settings: previously_streaming=%s audio_mode=%s rate=%s octets=%s pres_delay=%s qos_preset=%s immediate_rendering=%s assisted_listening_stream=%s demo_sources=%s",
|
||||
"[AUTOSTART][PRIMARY] loaded settings: previously_streaming=%s audio_mode=%s rate=%s octets=%s pres_delay=%s qos_preset=%s immediate_rendering=%s assisted_listening_stream=%s tx_power=%+d dBm demo_sources=%s",
|
||||
previously_streaming,
|
||||
audio_mode,
|
||||
rate,
|
||||
@@ -768,6 +770,7 @@ async def _autostart_from_settings():
|
||||
saved_qos_preset,
|
||||
immediate_rendering,
|
||||
assisted_listening_stream,
|
||||
tx_power,
|
||||
(settings.get('demo_sources') or []),
|
||||
)
|
||||
|
||||
@@ -817,6 +820,7 @@ async def _autostart_from_settings():
|
||||
immediate_rendering=immediate_rendering,
|
||||
assisted_listening_stream=assisted_listening_stream,
|
||||
presentation_delay_us=pres_delay if pres_delay is not None else 40000,
|
||||
advertising_tx_power=tx_power,
|
||||
bigs=bigs,
|
||||
)
|
||||
# Set num_bis for stereo mode if needed
|
||||
@@ -886,6 +890,7 @@ async def _autostart_from_settings():
|
||||
presentation_delay_us=pres_delay if pres_delay is not None else 40000,
|
||||
analog_gain_db_left=settings.get('analog_gain_db_left', 0.0),
|
||||
analog_gain_db_right=settings.get('analog_gain_db_right', 0.0),
|
||||
advertising_tx_power=tx_power,
|
||||
bigs=bigs,
|
||||
)
|
||||
# Set num_bis for stereo mode if needed
|
||||
@@ -921,10 +926,11 @@ async def _autostart_from_settings():
|
||||
big_ids = settings.get('big_ids') or []
|
||||
big_addrs = settings.get('big_random_addresses') or []
|
||||
stream_password = settings.get('stream_password')
|
||||
tx_power = int(settings.get('advertising_tx_power', 8))
|
||||
original_ts = settings.get('timestamp')
|
||||
previously_streaming = bool(settings.get('is_streaming'))
|
||||
log.info(
|
||||
"[AUTOSTART][SECONDARY] loaded settings: previously_streaming=%s audio_mode=%s rate=%s octets=%s pres_delay=%s qos_preset=%s immediate_rendering=%s assisted_listening_stream=%s demo_sources=%s",
|
||||
"[AUTOSTART][SECONDARY] loaded settings: previously_streaming=%s audio_mode=%s rate=%s octets=%s pres_delay=%s qos_preset=%s immediate_rendering=%s assisted_listening_stream=%s tx_power=%+d dBm demo_sources=%s",
|
||||
previously_streaming,
|
||||
audio_mode,
|
||||
rate,
|
||||
@@ -933,6 +939,7 @@ async def _autostart_from_settings():
|
||||
saved_qos_preset,
|
||||
immediate_rendering,
|
||||
assisted_listening_stream,
|
||||
tx_power,
|
||||
(settings.get('demo_sources') or []),
|
||||
)
|
||||
if not previously_streaming:
|
||||
@@ -972,6 +979,7 @@ async def _autostart_from_settings():
|
||||
immediate_rendering=immediate_rendering,
|
||||
assisted_listening_stream=assisted_listening_stream,
|
||||
presentation_delay_us=pres_delay if pres_delay is not None else 40000,
|
||||
advertising_tx_power=tx_power,
|
||||
bigs=bigs,
|
||||
)
|
||||
conf.qos_config = QOS_PRESET_MAP.get(saved_qos_preset, QOS_PRESET_MAP["Fast"])
|
||||
@@ -1041,6 +1049,7 @@ async def _autostart_from_settings():
|
||||
presentation_delay_us=pres_delay if pres_delay is not None else 40000,
|
||||
analog_gain_db_left=settings.get('analog_gain_db_left', 0.0),
|
||||
analog_gain_db_right=settings.get('analog_gain_db_right', 0.0),
|
||||
advertising_tx_power=tx_power,
|
||||
bigs=bigs,
|
||||
)
|
||||
conf.qos_config = QOS_PRESET_MAP.get(saved_qos_preset, QOS_PRESET_MAP["Fast"])
|
||||
|
||||
Reference in New Issue
Block a user