mirror of
https://github.com/MarekWo/mc-webui.git
synced 2026-08-10 02:32:56 +02:00
feat: path_hash_mode selector in Settings + global Close button
Adds a Path hash mode dropdown (1B/2B/3B) to Settings → Device → Public Info, so the mode can be switched from the UI instead of the meshcli console. The Settings modal now has a persistent Close button in the footer, visible on every tab. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -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'])
|
||||
|
||||
+20
-6
@@ -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');
|
||||
}
|
||||
|
||||
@@ -440,6 +440,19 @@
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="ps-0">Path hash mode
|
||||
<span class="badge rounded-pill text-muted" data-bs-toggle="tooltip"
|
||||
title="Bytes per hop in routing paths. 1B = shortest path, more collisions; 3B = longest, fewest collisions."><i class="bi bi-info-circle"></i></span>
|
||||
</td>
|
||||
<td class="pe-0">
|
||||
<select class="form-select form-select-sm" id="settDevicePathHashMode">
|
||||
<option value="0">1 byte (default)</option>
|
||||
<option value="1">2 bytes</option>
|
||||
<option value="2">3 bytes</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="d-flex gap-2">
|
||||
@@ -723,6 +736,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer py-2">
|
||||
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user