mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-10-23 01:51:23 +00:00
fix(picker): recommend unified RAK repeater profiles
This commit is contained in:
1 parent
4bbd613417
commit
c07d16e398
4 files changed
+90
-16
No files matched your search
@@ -482,6 +482,11 @@
|
||||
if (/^RAK_(?:3401|4631)_repeater_unified_lora_ota(?:-(?:full|reduced)(?:-ota)?)?$/i.test(target)) {
|
||||
variant = "default";
|
||||
}
|
||||
if (/^RAK_4631_repeater_ethernet(?:-(?:full|reduced)(?:-ota)?)?$/i.test(target)) {
|
||||
// The RAK13800 Ethernet image is a real hardware choice, separate from
|
||||
// adaptive storage. Label it consistently for both sensor policies.
|
||||
variant = "ethernet";
|
||||
}
|
||||
if (sourceHardware === "Station_G2_logging") {
|
||||
variant = variant === "default"
|
||||
? "rx-boosted"
|
||||
@@ -571,11 +576,13 @@
|
||||
heltec_t096_repeater_bridge_rs232_lora_ota_no_external_sensors:
|
||||
"heltec_t096_repeater_lora_ota_no_external_sensors",
|
||||
rak_4631_repeater_bridge_rs232_serial1_lora_ota_no_external_sensors:
|
||||
"rak_4631_repeater_lora_ota_no_external_sensors",
|
||||
["rak_4631_repeater_unified_lora_ota", "rak_4631_repeater_lora_ota_no_external_sensors"],
|
||||
rak_4631_repeater_bridge_rs232_serial2_lora_ota_no_external_sensors:
|
||||
"rak_4631_repeater_lora_ota_no_external_sensors",
|
||||
rak_4631_repeater_bridge_rs232_serial1: "rak_4631_repeater",
|
||||
rak_4631_repeater_bridge_rs232_serial2: "rak_4631_repeater",
|
||||
["rak_4631_repeater_unified_lora_ota", "rak_4631_repeater_lora_ota_no_external_sensors"],
|
||||
rak_4631_repeater_bridge_rs232_serial1:
|
||||
["rak_4631_repeater_unified_lora_ota", "rak_4631_repeater"],
|
||||
rak_4631_repeater_bridge_rs232_serial2:
|
||||
["rak_4631_repeater_unified_lora_ota", "rak_4631_repeater"],
|
||||
promicro_repeater_bridge_rs232_serial1: "promicro_repeater",
|
||||
heltec_t114_without_display_repeater_bridge_rs232:
|
||||
"heltec_t114_without_display_repeater",
|
||||
@@ -603,11 +610,16 @@
|
||||
combinedUsbBleKeys.has(key);
|
||||
const replacedTerminal = profile.role === "terminal" &&
|
||||
terminalReplacementKeys.has(key);
|
||||
const rs232Replacement = mergedRs232Targets[
|
||||
String(profile.target || "").toLowerCase()
|
||||
];
|
||||
const target = String(profile.target || "").toLowerCase();
|
||||
const sensorSuffix = (target.match(/-(?:full|reduced)$/) || [""])[0];
|
||||
const baseTarget = sensorSuffix ? target.slice(0, -sensorSuffix.length) : target;
|
||||
const rs232Replacement = mergedRs232Targets[baseTarget];
|
||||
// Preserve the exact sensor policy: a Full image does not replace a
|
||||
// missing Reduced image, or an older unsuffixed compatibility image.
|
||||
const replacedRs232 = Boolean(rs232Replacement &&
|
||||
targets.has(rs232Replacement));
|
||||
[].concat(rs232Replacement).some(function (replacement) {
|
||||
return targets.has(replacement + sensorSuffix);
|
||||
}));
|
||||
return !(replacedAttachedTransport && fullKeys.has(key)) &&
|
||||
!replacedByUsbBle && !replacedTerminal && !replacedRs232;
|
||||
});
|
||||
@@ -644,8 +656,8 @@
|
||||
}));
|
||||
return (profiles || []).filter(function (profile) {
|
||||
const target = String(profile && profile.target || "").toLowerCase();
|
||||
const match = /^rak_(3401|4631)_repeater_(?:lora_ota_no_external_sensors|w25q16_lora_ota|rak15001_slot_c_lora_ota|rak13302_w25q16_lora_ota)$/.exec(target);
|
||||
return !match || !targets.has("rak_" + match[1] + "_repeater_unified_lora_ota");
|
||||
const match = /^rak_(3401|4631)_repeater_(?:lora_ota_no_external_sensors|w25q16_lora_ota|rak15001_slot_c_lora_ota|rak13302_w25q16_lora_ota)(-(?:full|reduced))?$/.exec(target);
|
||||
return !match || !targets.has("rak_" + match[1] + "_repeater_unified_lora_ota" + (match[2] || ""));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -668,10 +680,7 @@
|
||||
function applyMergedRak4631RepeaterCapabilities(profiles) {
|
||||
return (profiles || []).map(function (profile) {
|
||||
const target = String(profile && profile.target || "").toLowerCase();
|
||||
if (
|
||||
target !== "rak_4631_repeater" &&
|
||||
target !== "rak_4631_repeater_lora_ota_no_external_sensors"
|
||||
) {
|
||||
if (!/^rak_4631_repeater(?:_lora_ota_no_external_sensors|_unified_lora_ota)?(?:-(?:full|reduced))?$/.test(target)) {
|
||||
return profile;
|
||||
}
|
||||
|
||||
@@ -1667,6 +1676,9 @@
|
||||
if (profile.role === "repeater") toggle("Repeat mesh traffic", "set repeat", "get repeat");
|
||||
if (info.rs232 && infrastructure) {
|
||||
const mode = chosen.mode;
|
||||
const uartNote = /^RAK_4631_repeater_unified_lora_ota-(?:full|reduced)$/i.test(profile.target) && profile.sensorProfile
|
||||
? "Use the UART and pin map for this exact board. Unified RAK4631 supports set bridge.uart 1 or set bridge.uart 2 while the bridge is stopped. UART1 pauses UART GPS while the bridge runs and restores it when stopped."
|
||||
: "Use the UART and pin map for this exact board. Canonical GPS-enabled RAK4631 uses UART2; select it with set bridge.uart 2 while the bridge is stopped. UART1 needs a compatible GPS-free image.";
|
||||
// MQTT images keep the historical bridge.enabled ESP-NOW alias.
|
||||
// Their independently saved UART uses the transport-specific controls.
|
||||
const uartSetting = info.mqtt ? "rs232.enabled" : "bridge.enabled";
|
||||
@@ -1677,7 +1689,7 @@
|
||||
{ label: "Set baud", commands: ["set " + uartSetting + " off", "set bridge.baud 115200", "set " + uartSetting + " on"] },
|
||||
].sort(function (a, b) {
|
||||
return mode === "standard" ? Number(b.label === "Off") - Number(a.label === "Off") : 0;
|
||||
}), "Use the UART and pin map for this exact board. Canonical GPS-enabled RAK4631 uses UART2; select it with set bridge.uart 2 while the bridge is stopped. UART1 needs a compatible GPS-free image.");
|
||||
}), uartNote);
|
||||
}
|
||||
if (info.espnowBridge && infrastructure) {
|
||||
// Combined images need the transport-specific switch: bridge.enabled
|
||||
|
||||
@@ -25,6 +25,13 @@ Chip family and hardware are the only dropdowns. All remaining choices use
|
||||
buttons. **Firmware profile** combines OTA support, Full/standard, and sensor
|
||||
or storage differences when a choice between different images is needed.
|
||||
|
||||
RAK3401 and RAK4631 repeaters use one unified image per sensor policy for
|
||||
supported internal and external OTA storage. **Full** and **Reduced** choose
|
||||
optional sensor drivers; they do not select a storage module. The unified
|
||||
RAK4631 image also includes runtime RS-232 UART selection. Ethernet remains
|
||||
a separate RAK4631 hardware image. LoRa OTA still requires the matching
|
||||
OTAFIX bootloader and a package compatible with the installed target.
|
||||
|
||||
The picker reads public release metadata from GitHub. It does not upload device
|
||||
information. Hardware names, target names, and download links come directly
|
||||
from the published firmware assets.
|
||||
|
||||
+1
-1
@@ -127,7 +127,7 @@ extra_javascript:
|
||||
- _javascript/hosted_doc_links.js?v=20261007-1
|
||||
- _javascript/notification_builder.js?v=20261006-channel9
|
||||
- https://unpkg.com/leaflet@1.9.4/dist/leaflet.js
|
||||
- _javascript/firmware_picker.js?v=20261006-simplify-1
|
||||
- _javascript/firmware_picker.js?v=20261008-rak-combined-1
|
||||
- _javascript/telemetry_decoder.js?v=20261007-hosted-form
|
||||
- _javascript/management_decoder.js
|
||||
- _javascript/filter_tool.js?v=20261002-hashbytes-2plus
|
||||
|
||||
@@ -1014,6 +1014,27 @@ const rakLegacyCatalog = picker.buildCatalog([
|
||||
release(family, "2026-09-25T00:00:00Z", rakStorageAssets.slice(1, 4).concat(rakStorageAssets.slice(5))),
|
||||
]);
|
||||
assert.strictEqual(rakLegacyCatalog.profiles.length, 5);
|
||||
// Sensor-policy suffixes must not resurrect the storage-specific compatibility
|
||||
// images. A Full successor cannot replace a missing Reduced successor.
|
||||
const rakPolicyTargets = rakStorageTargets.flatMap(target =>
|
||||
['full', 'reduced'].map(policy => target + '-' + policy));
|
||||
const rakPolicyAssets = rakPolicyTargets.map(target =>
|
||||
asset(target + '-ota-' + family + '.uf2'));
|
||||
const rakPolicyCatalog = picker.buildCatalog([
|
||||
release(family, '2026-10-08T00:00:00Z', rakPolicyAssets),
|
||||
]);
|
||||
assert.deepStrictEqual(rakPolicyCatalog.profiles.map(item => item.target).sort(),
|
||||
['RAK_3401', 'RAK_4631'].flatMap(board =>
|
||||
['full', 'reduced'].map(policy => board + '_repeater_unified_lora_ota-' + policy)).sort());
|
||||
assert.deepStrictEqual(rakPolicyCatalog.rows.map(item => item.target).sort(), rakPolicyTargets.sort(),
|
||||
'All exact legacy OTA identities must remain in the raw catalog');
|
||||
const rakMissingReducedCatalog = picker.buildCatalog([
|
||||
release(family, '2026-10-08T00:00:00Z', rakPolicyAssets.filter(file =>
|
||||
!file.name.includes('_unified_lora_ota-reduced-'))),
|
||||
]);
|
||||
assert.deepStrictEqual(rakMissingReducedCatalog.profiles.map(item => item.target).sort(),
|
||||
rakPolicyTargets.filter(target => target.endsWith('_unified_lora_ota-full') ||
|
||||
(target.endsWith('-reduced') && !target.includes('_unified_lora_ota-'))).sort());
|
||||
assert.strictEqual(picker.formatBytes(2097152), "2.00 MiB");
|
||||
assert.strictEqual(
|
||||
picker.parseFirmwareAsset(
|
||||
@@ -1155,6 +1176,40 @@ const currentCatalog = picker.buildCatalog([
|
||||
], currentControls);
|
||||
assert.strictEqual(currentCatalog.rows.length, currentAssets.length);
|
||||
assert(currentCatalog.profiles.every(profile => profile.controls && profile.chipFamily !== 'unknown'));
|
||||
for (const [hardware, bases] of [
|
||||
['RAK_4631', ['RAK_4631_repeater_unified_lora_ota', 'RAK_4631_repeater_ethernet']],
|
||||
['RAK_3401', ['RAK_3401_repeater_unified_lora_ota']],
|
||||
]) {
|
||||
const context = {hardware, role: 'repeater'};
|
||||
const expected = bases.flatMap(base => ['full', 'reduced'].map(policy => base + '-' + policy));
|
||||
const visible = currentCatalog.profiles.filter(profile => picker.profileMatchesFacets(profile, context));
|
||||
assert.deepStrictEqual(visible.map(profile => profile.target).sort(), expected.sort(),
|
||||
hardware + ' must recommend only combined storage/bridge images and genuine Ethernet variants');
|
||||
const choices = picker.firmwareProfileChoices(currentCatalog.profiles, context);
|
||||
assert.strictEqual(choices.length, expected.length, hardware + ' must have one choice per real image');
|
||||
assert.strictEqual(new Set(choices.map(choice => choice.label)).size, choices.length,
|
||||
hardware + ' must not show duplicate profile labels');
|
||||
for (const profile of visible.filter(item => item.target.includes('_unified_lora_ota-'))) {
|
||||
assert.deepStrictEqual(picker.profileFieldValues(profile, 'mode'),
|
||||
hardware === 'RAK_4631' ? ['standard', 'rs232'] : ['standard']);
|
||||
if (hardware === 'RAK_4631') {
|
||||
const bridge = picker.runtimeDirections(profile, {mode: 'rs232'})
|
||||
.find(section => section.title.startsWith('RS232 bridge'));
|
||||
assert(bridge && bridge.note.includes('set bridge.uart 1') && bridge.note.includes('pauses UART GPS'),
|
||||
'Both combined sensor policies must explain runtime UART selection and GPS sharing');
|
||||
assert(!bridge.note.includes('GPS-free image'));
|
||||
}
|
||||
}
|
||||
}
|
||||
const rakBridgeBase = 'RAK_4631_repeater_bridge_rs232_serial1_lora_ota_no_external_sensors';
|
||||
const rakPartialAssets = currentAssets.filter(file =>
|
||||
file.name.startsWith('RAK_4631_repeater_unified_lora_ota-full-') ||
|
||||
file.name.startsWith(rakBridgeBase + '-reduced-'));
|
||||
const rakPartialCatalog = picker.buildCatalog([
|
||||
release(currentControls.familyTag, '2026-10-08T00:00:00Z', rakPartialAssets),
|
||||
], currentControls);
|
||||
assert(rakPartialCatalog.profiles.some(profile => profile.target === rakBridgeBase + '-reduced'),
|
||||
'A Full combined image must not hide the only available Reduced bridge image');
|
||||
const expandedEsp32 = currentCatalog.profiles.find(profile =>
|
||||
profile.target === 'Ebyte_EoRa-S3_Repeater-full-usb-wifi');
|
||||
assert(expandedEsp32);
|
||||
|
||||
Reference in new issue
Block a user