Skip to content

Commit 5b1723e

Browse files
committed
Update Composer for commands
1 parent 27b7b11 commit 5b1723e

File tree

3 files changed

+168
-9
lines changed

3 files changed

+168
-9
lines changed

composer.html

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,24 @@ <h3 id="import-preview-title">Import preview</h3>
437437
const commandsSection = document.getElementById('commands-section');
438438
commandsSection.innerHTML = '';
439439

440+
function getKnownPortOptions() {
441+
const options = [{ label: 'all ports', value: 0 }];
442+
const ports = settingsData && settingsData.ports ? settingsData.ports : null;
443+
if (ports) {
444+
Object.entries(ports)
445+
.filter(([_, portNum]) => Number.isFinite(portNum))
446+
.map(([portName, portNum]) => ({
447+
label: portName.replace(/^port_/, ''),
448+
value: portNum
449+
}))
450+
.sort((a, b) => a.value - b.value)
451+
.forEach(option => options.push(option));
452+
}
453+
return options
454+
.map(option => `<option value="${option.value}">${option.label} (port ${option.value})</option>`)
455+
.join('');
456+
}
457+
440458
for (const [key, command] of Object.entries(settingsData.commands)) {
441459
if (dangerousCommands.some(rx => rx.test(key))) {
442460
continue;
@@ -468,6 +486,32 @@ <h3 id="import-preview-title">Import preview</h3>
468486
${settingOptions.map(option => `<option value="${option.id}">${option.name} (${option.id})</option>`).join('')}
469487
</select>
470488
`;
489+
} else if (key === 'cmd_flash_get_from_head') {
490+
helperHtml = `
491+
<label class="command-helper-label" for="command-select-${command.id}-port">Port</label>
492+
<select id="command-select-${command.id}-port" class="command-helper-input">
493+
${getKnownPortOptions()}
494+
</select>
495+
<label class="command-helper-label" for="command-input-${command.id}-start">Start</label>
496+
<input id="command-input-${command.id}-start" class="command-helper-input" type="text" placeholder="50" data-format="uint32" />
497+
<label class="command-helper-label" for="command-input-${command.id}-count">How many</label>
498+
<input id="command-input-${command.id}-count" class="command-helper-input" type="text" placeholder="10" data-format="uint32" />
499+
`;
500+
} else if (commandInputMeta && commandInputMeta.options) {
501+
helperHtml = `
502+
<label class="command-helper-label" for="command-select-${command.id}">Value</label>
503+
<select id="command-select-${command.id}" class="command-helper-input">
504+
${commandInputMeta.options.map(option => `<option value="${option.value}">${option.label}</option>`).join('')}
505+
</select>
506+
`;
507+
} else if (commandInputMeta && commandInputMeta.input) {
508+
const placeholder = commandInputMeta.input.placeholder || '';
509+
const labelText = commandInputMeta.input.label || 'Value';
510+
const dataFormat = commandInputMeta.input.format || 'uint8';
511+
helperHtml = `
512+
<label class="command-helper-label" for="command-input-${command.id}">${labelText}</label>
513+
<input id="command-input-${command.id}" class="command-helper-input" type="text" placeholder="${placeholder}" data-format="${dataFormat}" />
514+
`;
471515
}
472516
row.innerHTML = `
473517
<div class="checkbox-container">
@@ -610,13 +654,61 @@ <h3 id="import-preview-title">Import preview</h3>
610654
try {
611655
if (settingObj.type === 'command' && settingObj.length === 1) {
612656
const selectEl = document.getElementById(`command-select-${settingObj.id}`);
657+
const inputEl = document.getElementById(`command-input-${settingObj.id}`);
658+
let value = 0;
613659
if (selectEl) {
614660
const selected = selectEl.value;
615-
const parsed = selected && selected.startsWith('0x') ? parseInt(selected, 16) : parseInt(selected, 10);
616-
valueBytes = settingToBytes(settingKey, settingObj, parsed.toString());
617-
} else {
618-
valueBytes = settingToBytes(settingKey, settingObj, getInputValue(settingObj.id));
661+
value = selected && selected.startsWith('0x') ? parseInt(selected, 16) : parseInt(selected, 10);
662+
} else if (inputEl) {
663+
const rawValue = inputEl.value.trim();
664+
const format = inputEl.getAttribute('data-format') || 'uint8';
665+
if (rawValue.length === 0) {
666+
value = 0;
667+
} else if (format === 'hex8') {
668+
const cleaned = rawValue.replace(/^0x/i, '');
669+
const parsed = parseInt(cleaned, 16);
670+
if (Number.isNaN(parsed)) {
671+
throw new Error('Invalid hex value');
672+
}
673+
value = parsed;
674+
} else {
675+
const parsed = parseInt(rawValue, 10);
676+
if (Number.isNaN(parsed)) {
677+
throw new Error('Invalid numeric value');
678+
}
679+
value = parsed;
680+
}
681+
} else if (settingObj.value !== undefined) {
682+
value = settingObj.value;
619683
}
684+
valueBytes = settingToBytes(settingKey, settingObj, value.toString());
685+
} else if (settingObj.type === 'command' && settingKey === 'cmd_flash_get_from_head') {
686+
const portEl = document.getElementById(`command-select-${settingObj.id}-port`);
687+
const startEl = document.getElementById(`command-input-${settingObj.id}-start`);
688+
const countEl = document.getElementById(`command-input-${settingObj.id}-count`);
689+
const parseUint32 = (el, label) => {
690+
if (!el) {
691+
return 0;
692+
}
693+
const rawValue = el.value.trim();
694+
if (!rawValue) {
695+
return 0;
696+
}
697+
const parsed = rawValue.startsWith('0x') ? parseInt(rawValue, 16) : parseInt(rawValue, 10);
698+
if (!Number.isFinite(parsed) || parsed < 0 || parsed > 0xFFFFFFFF) {
699+
throw new Error(`Invalid ${label} (uint32)`);
700+
}
701+
return parsed >>> 0;
702+
};
703+
const port = parseUint32(portEl, 'port');
704+
const start = parseUint32(startEl, 'start index');
705+
const count = parseUint32(countEl, 'count');
706+
const payload = new Uint8Array(12);
707+
const view = new DataView(payload.buffer);
708+
view.setUint32(0, port, true);
709+
view.setUint32(4, start, true);
710+
view.setUint32(8, count, true);
711+
valueBytes = payload;
620712
} else {
621713
valueBytes = settingToBytes(settingKey, settingObj, getInputValue(settingObj.id));
622714
}

index.html

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1960,8 +1960,28 @@ <h4>${setting.display_name} <small>${key} (${setting.id})</small></h4>
19601960
function displayCommands() {
19611961
const commandsSection = document.getElementById('commands-buttons-section');
19621962
commandsSection.innerHTML = '';
1963+
1964+
function getKnownPortOptions() {
1965+
const options = [{ label: 'all ports', value: 0 }];
1966+
const ports = settingsData && settingsData.ports ? settingsData.ports : null;
1967+
if (ports) {
1968+
Object.entries(ports)
1969+
.filter(([_, portNum]) => Number.isFinite(portNum))
1970+
.map(([portName, portNum]) => ({
1971+
label: portName.replace(/^port_/, ''),
1972+
value: portNum
1973+
}))
1974+
.sort((a, b) => a.value - b.value)
1975+
.forEach(option => options.push(option));
1976+
}
1977+
return options
1978+
.map(option => `<option value="${option.value}">${option.label} (port ${option.value})</option>`)
1979+
.join('');
1980+
}
1981+
19631982
for (const [key, command] of Object.entries(settingsData.commands)) {
1964-
if ((command.length !== 0 && command.length !== 1) || dangerousCommands.some(rx => rx.test(key)) || key in mainCommands) {
1983+
const allowComplex = key === 'cmd_flash_get_from_head';
1984+
if (((command.length !== 0 && command.length !== 1) && !allowComplex) || dangerousCommands.some(rx => rx.test(key)) || key in mainCommands) {
19651985
continue;
19661986
}
19671987

@@ -1988,6 +2008,17 @@ <h4>${setting.display_name} <small>${key} (${setting.id})</small></h4>
19882008
${settingOptions.map(option => `<option value="${option.id}">${option.name} (${option.id})</option>`).join('')}
19892009
</select>
19902010
`;
2011+
} else if (key === 'cmd_flash_get_from_head') {
2012+
helperHtml = `
2013+
<label class="command-helper-label" for="command-select-${command.id}-port">Port</label>
2014+
<select id="command-select-${command.id}-port" class="command-helper-input">
2015+
${getKnownPortOptions()}
2016+
</select>
2017+
<label class="command-helper-label" for="command-input-${command.id}-start">Start</label>
2018+
<input id="command-input-${command.id}-start" class="command-helper-input" type="text" placeholder="50" data-format="uint32" />
2019+
<label class="command-helper-label" for="command-input-${command.id}-count">How many</label>
2020+
<input id="command-input-${command.id}-count" class="command-helper-input" type="text" placeholder="10" data-format="uint32" />
2021+
`;
19912022
} else if (commandInputMeta && commandInputMeta.options) {
19922023
helperHtml = `
19932024
<label class="command-helper-label" for="command-select-${command.id}">Value</label>
@@ -3090,6 +3121,42 @@ <h4>${setting.display_name} <small>${key} (${setting.id})</small></h4>
30903121
ubloxFixPending = true;
30913122
scheduleUbloxFixTimeout();
30923123
}
3124+
if (key === 'cmd_flash_get_from_head') {
3125+
const portEl = document.getElementById(`command-select-${commandMeta.id}-port`);
3126+
const startEl = document.getElementById(`command-input-${commandMeta.id}-start`);
3127+
const countEl = document.getElementById(`command-input-${commandMeta.id}-count`);
3128+
const parseUint32 = (el, label) => {
3129+
if (!el) {
3130+
return 0;
3131+
}
3132+
const rawValue = el.value.trim();
3133+
if (!rawValue) {
3134+
return 0;
3135+
}
3136+
const parsed = rawValue.startsWith('0x') ? parseInt(rawValue, 16) : parseInt(rawValue, 10);
3137+
if (!Number.isFinite(parsed) || parsed < 0 || parsed > 0xFFFFFFFF) {
3138+
throw new Error(`Invalid ${label} (uint32)`);
3139+
}
3140+
return parsed >>> 0;
3141+
};
3142+
let port = 0;
3143+
let start = 0;
3144+
let count = 0;
3145+
try {
3146+
port = parseUint32(portEl, 'port');
3147+
start = parseUint32(startEl, 'start index');
3148+
count = parseUint32(countEl, 'count');
3149+
} catch (error) {
3150+
showToast(error.message);
3151+
return;
3152+
}
3153+
const payload = new Uint8Array(12);
3154+
const view = new DataView(payload.buffer);
3155+
view.setUint32(0, port, true);
3156+
view.setUint32(4, start, true);
3157+
view.setUint32(8, count, true);
3158+
return executeBleCommand([0x20, cmd, payload.length, ...payload]);
3159+
}
30933160
if (key === 'cmd_flash_get_all') {
30943161
const expectedTotal = Number.isFinite(flashLogCountTotal) && flashLogCountTotal >= 0 ? flashLogCountTotal : null;
30953162
startFlashLogCapture({

settings-meta.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,15 +1029,15 @@
10291029
"description": "Get all messages on a port (port=0 for all). Returns messages then msg_cmd_confirm.",
10301030
"display_name": "flash get all",
10311031
"input": {
1032-
"label": "Port (0 = all)",
1032+
"label": "Port",
10331033
"placeholder": "0",
10341034
"format": "uint8"
10351035
}
10361036
},
10371037
"cmd_flash_get_from_head": {
10381038
"category": "commands",
10391039
"label": "flash get from head",
1040-
"description": "Read messages from a port starting at a message index. Returns messages then msg_cmd_confirm.",
1040+
"description": "Read a specific number of messages from a given port, starting at a chosen message.",
10411041
"display_name": "flash get from head"
10421042
},
10431043
"cmd_get_ble_scan": {
@@ -1206,7 +1206,7 @@
12061206
"description": "Get a single setting by id. Format: setting_id setting_length [setting bytes].",
12071207
"display_name": "send single setting",
12081208
"input": {
1209-
"label": "Setting ID (hex)",
1209+
"label": "Setting",
12101210
"placeholder": "0x01",
12111211
"format": "hex8",
12121212
"source": "settings"
@@ -1218,7 +1218,7 @@
12181218
"description": "Get a single value by id. Format: value_id value_length [value bytes].",
12191219
"display_name": "send single val",
12201220
"input": {
1221-
"label": "Value ID (hex)",
1221+
"label": "Value",
12221222
"placeholder": "0xD1",
12231223
"format": "hex8",
12241224
"source": "values"

0 commit comments

Comments
 (0)