diff --git a/app/routes/api.py b/app/routes/api.py index 0ee177e..8237f0d 100644 --- a/app/routes/api.py +++ b/app/routes/api.py @@ -1170,6 +1170,14 @@ def get_device_config(): if not info: return jsonify({'success': False, 'error': 'No device info available'}), 503 + path_hash_mode = None + try: + phm_result = dm.get_param('path_hash_mode') + if phm_result.get('success'): + path_hash_mode = phm_result.get('data', {}).get('path_hash_mode') + except Exception as e: + logger.warning(f"Could not read path_hash_mode: {e}") + return jsonify({ 'success': True, 'config': { @@ -1177,6 +1185,7 @@ def get_device_config(): 'lat': info.get('adv_lat', 0), 'lon': info.get('adv_lon', 0), 'advert_loc_policy': info.get('adv_loc_policy', 0), + 'path_hash_mode': path_hash_mode, 'radio_freq': info.get('radio_freq', 0), 'radio_bw': info.get('radio_bw', 0), 'radio_sf': info.get('radio_sf', 0), @@ -1224,6 +1233,19 @@ def update_device_config(): if not result.get('success'): errors.append(f"advert_loc_policy: {result.get('error')}") + # Path hash mode (0=1B, 1=2B, 2=3B) + if 'path_hash_mode' in data and data['path_hash_mode'] is not None: + try: + phm = int(data['path_hash_mode']) + if phm not in (0, 1, 2): + errors.append(f"path_hash_mode: must be 0, 1, or 2") + else: + result = dm.set_param('path_hash_mode', str(phm)) + if not result.get('success'): + errors.append(f"path_hash_mode: {result.get('error')}") + except (TypeError, ValueError): + errors.append("path_hash_mode: invalid value") + # Radio params (all 4 together) if 'radio_freq' in data: freq = float(data['radio_freq']) diff --git a/app/static/js/app.js b/app/static/js/app.js index 02bef85..b18bdd9 100644 --- a/app/static/js/app.js +++ b/app/static/js/app.js @@ -1872,6 +1872,13 @@ async function loadDeviceConfig() { document.getElementById('settDeviceLat').value = c.lat || ''; document.getElementById('settDeviceLon').value = c.lon || ''; document.getElementById('settDeviceAdvertLoc').checked = !!c.advert_loc_policy; + const phmSel = document.getElementById('settDevicePathHashMode'); + if (phmSel) { + const phm = (c.path_hash_mode === 0 || c.path_hash_mode === 1 || c.path_hash_mode === 2) + ? String(c.path_hash_mode) : '0'; + phmSel.value = phm; + phmSel.dataset.initial = phm; + } // Radio document.getElementById('settRadioFreq').value = c.radio_freq || ''; @@ -1910,21 +1917,28 @@ async function saveDevicePublicInfo() { const lon = parseFloat(document.getElementById('settDeviceLon').value) || 0; const advertLoc = document.getElementById('settDeviceAdvertLoc').checked; + const phmSel = document.getElementById('settDevicePathHashMode'); + const payload = { + name: name, + lat: lat, + lon: lon, + advert_loc_policy: advertLoc + }; + if (phmSel && phmSel.value !== phmSel.dataset.initial) { + payload.path_hash_mode = parseInt(phmSel.value, 10); + } + try { const resp = await fetch('/api/device/config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - name: name, - lat: lat, - lon: lon, - advert_loc_policy: advertLoc - }) + body: JSON.stringify(payload) }); const data = await resp.json(); if (data.success) { showNotification('Public info saved', 'success'); _selfInfo = null; + if (phmSel) phmSel.dataset.initial = phmSel.value; } else { showNotification(data.error || 'Failed to save', 'danger'); } diff --git a/app/templates/base.html b/app/templates/base.html index ae76df8..08be202 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -440,6 +440,19 @@ + + Path hash mode + + + + + +
@@ -723,6 +736,9 @@
+