fix(channels): refresh channel secret cache after join/create

After set_channel(), read back the actual secret from the device and
update both _channel_secrets in-memory cache and the DB. This fixes
newly-joined # channels (where firmware auto-generates the key) having
no repeater info, missing Analyzer URLs, and incorrect route data until
container restart.

Also clean up _channel_secrets on channel removal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
MarekWo
2026-03-31 20:48:35 +02:00
parent 5919e43f3a
commit f6c9c65a51
+25
View File
@@ -1955,11 +1955,35 @@ class DeviceManager:
try:
self.execute(self.mc.commands.set_channel(idx, name, secret))
self.db.upsert_channel(idx, name, secret.hex() if secret else None)
# Read back the actual secret from device (firmware may have
# generated it for # channels) and update in-memory cache + DB.
self._refresh_channel_secret(idx, name)
return {'success': True, 'message': f'Channel {idx} set'}
except Exception as e:
logger.error(f"Failed to set channel: {e}")
return {'success': False, 'error': str(e)}
def _refresh_channel_secret(self, idx: int, name: str = ''):
"""Read back a channel's secret from device and update cache + DB."""
try:
event = self.execute(self.mc.commands.get_channel(idx))
if event:
data = getattr(event, 'payload', None) or {}
secret = data.get('channel_secret', data.get('secret', b''))
if isinstance(secret, bytes):
secret = secret.hex()
if secret and len(secret) == 32:
self._channel_secrets[idx] = secret
ch_name = data.get('channel_name', data.get('name', ''))
if isinstance(ch_name, str):
ch_name = ch_name.strip('\x00').strip()
self.db.upsert_channel(idx, ch_name or name, secret)
logger.info(f"Refreshed channel {idx} secret into cache")
except Exception as e:
logger.warning(f"Failed to refresh channel {idx} secret: {e}")
def remove_channel(self, idx: int) -> Dict:
"""Remove a channel from the device."""
if not self.is_connected:
@@ -1969,6 +1993,7 @@ class DeviceManager:
# Set channel with empty name removes it
self.execute(self.mc.commands.set_channel(idx, '', None))
self.db.delete_channel(idx)
self._channel_secrets.pop(idx, None)
return {'success': True, 'message': f'Channel {idx} removed'}
except Exception as e:
logger.error(f"Failed to remove channel: {e}")