fix(regions): rename tab to Regions and soften v1.14 firmware error

Two small follow-ups after initial deployment.

- Rename the Settings tab 'Channels' -> 'Regions' (id now tabSettingsRegions).
  The tab manages the region registry, not channels; the old label was
  confusing. The per-channel picker still lives under Manage Channels as
  before.
- Graceful handling of firmware rejection: CMD_SET_DEFAULT_FLOOD_SCOPE
  (63) and CMD_GET_DEFAULT_FLOOD_SCOPE (64) were introduced in firmware
  v1.15.0; on v1.14.x the device replies with a generic ERR frame and
  our toast showed the unhelpful 'Firmware error: unknown'. Now the
  device_manager translates the empty/timeout reason into a concrete
  message naming the v1.15 requirement, and the api handler appends
  'Your choice is saved locally' so the user knows the local state
  still persists. Same treatment for the delete-default-region clear
  path.
This commit is contained in:
MarekWo
2026-04-24 11:54:01 +02:00
parent 226bd2abac
commit e293de2a76
4 changed files with 19 additions and 11 deletions

View File

@@ -3005,8 +3005,15 @@ class DeviceManager:
timeout=5,
)
if event and getattr(event, 'type', None) == EventType.ERROR:
reason = (getattr(event, 'payload', {}) or {}).get('reason', 'unknown')
return {'success': False, 'error': f'Firmware error: {reason}'}
reason = (getattr(event, 'payload', {}) or {}).get('reason', '')
# CMD_SET_DEFAULT_FLOOD_SCOPE (63) was introduced in firmware v1.15.0.
# Older firmware replies with a generic ERR frame (no specific reason)
# or times out — both funnel into this branch.
if not reason or reason in ('timeout', 'no_event_received'):
friendly = "Device did not accept the default scope — this requires firmware v1.15 or newer."
else:
friendly = f"Device rejected the default scope (reason: {reason})."
return {'success': False, 'error': friendly}
return {'success': True, 'message': f'Default scope set to: {name or "(cleared)"}'}
except Exception as e:
logger.error(f"set_default_flood_scope failed: {e}")

View File

@@ -4003,9 +4003,9 @@ def delete_region_api(region_id):
try:
res = dm.set_default_flood_scope('', '')
if not res.get('success'):
warning = f"Firmware default not cleared: {res.get('error')}"
warning = f"{res.get('error')} Firmware default left as-is."
except Exception as e:
warning = f"Firmware default not cleared: {e}"
warning = f"Could not clear firmware default: {e}"
out = {'success': True}
if warning:
@@ -4094,11 +4094,12 @@ def set_default_region_api(region_id):
try:
res = dm.set_default_flood_scope(region['name'], region['key_hex'])
if not res.get('success'):
warning = f"Firmware push failed: {res.get('error')}"
# device_manager already returns a user-friendly message here.
warning = f"{res.get('error')} Your choice is saved locally."
except Exception as e:
warning = f"Firmware push failed: {e}"
warning = f"Could not push to firmware: {e}. Your choice is saved locally."
else:
warning = 'Device disconnected; firmware default not updated'
warning = 'Device disconnected — choice saved locally; firmware default not updated.'
out = {'success': True, 'region': db.get_region(region_id)}
if warning:

View File

@@ -2439,7 +2439,7 @@ document.addEventListener('DOMContentLoaded', () => {
// Initial load so suppress flag is available before user opens Settings
loadContactsSettings();
// Channels tab: region registry
// Regions tab: region registry
const addRegionForm = document.getElementById('addRegionForm');
if (addRegionForm) {
addRegionForm.addEventListener('submit', (e) => {
@@ -2998,7 +2998,7 @@ function renderRegionPickerList() {
// Activate the Channels tab after the modal is shown.
settingsModal.addEventListener('shown.bs.modal', function onceShown() {
settingsModal.removeEventListener('shown.bs.modal', onceShown);
const btn = document.querySelector('[data-bs-target="#tabSettingsChannels"]');
const btn = document.querySelector('[data-bs-target="#tabSettingsRegions"]');
if (btn) bootstrap.Tab.getOrCreateInstance(btn).show();
});
});

View File

@@ -420,7 +420,7 @@
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tabSettingsContacts" type="button">Contacts</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tabSettingsChannels" type="button">Channels</button>
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tabSettingsRegions" type="button">Regions</button>
</li>
</ul>
<div class="tab-content">
@@ -768,7 +768,7 @@
</tbody>
</table>
</div>
<div class="tab-pane fade" id="tabSettingsChannels">
<div class="tab-pane fade" id="tabSettingsRegions">
<div class="alert alert-info py-2 small mb-3 mt-2">
<i class="bi bi-info-circle"></i> Only repeaters allowing a region will forward messages tagged with it.
Find standardised region names at