Unify full firmware profiles and add dual USB logging

This commit is contained in:
mikecarper committed 2026-08-23 19:22:45 -07:00
1 parent b699e552ec
commit f2d4ffbb7e
56 files changed
+1652 -361

No files matched your search

+33 -12
View File
@@ -115,6 +115,25 @@ The setup AP is unauthenticated unless the firmware was built with
location. When WebConfig is running on the normal LAN, repeater and room-server
builds require the node's admin password.
On an expanded FULL profile with no saved SSID, this automatic setup AP has an
absolute 30-minute window. Browser activity or a phone left associated with the
AP does not extend it. If no SSID has been saved when the window expires,
WebConfig closes and the ESP32 WiFi radio remains off automatically for the
remainder of that boot. A reboot or power cycle starts a new 30-minute setup
window; the timeout is deliberately not written to preferences. An
administrator can still override the automatic cutoff with an explicit
`start webconfig` command.
Once an SSID is saved, the provisioning cutoff no longer applies. When WiFi is
selected by `logging.output wifi|both`, the station stays enabled and keeps
trying the saved network indefinitely: ESP automatic reconnect remains on and
the explicit fallback advances through 15, 30, 60, 120, then 300-second retry
intervals, remaining at five minutes until it reconnects. MQTT broker retries
use their own backoff; a repeatedly failing broker eventually receives one
probe every 30 minutes. Selecting `logging.output off|usb` keeps the MQTT bridge
off, so saved credentials alone do not force WiFi on unless WebConfig is also
enabled explicitly.
The equivalent MQTT observer CLI setup is:
```text
@@ -318,9 +337,10 @@ In this case WebConfig owns WiFi only while it is needed. Stopping the portal
disconnects WiFi and turns the WiFi radio off. There is no persistent MQTT
connection keeping WiFi active.
FULL MQTT and FULL logging repeater/room-server builds both provide these CLI
controls and status checks. FULL MQTT includes the MQTT bridge; FULL logging
does not:
Unified FULL USB + WiFi and FULL logging-fallback repeater/room-server builds
both provide these CLI controls and status checks. The unified profile includes
the MQTT bridge; the fallback is used only where no matching MQTT environment
exists:
```text
get wifi.ssid
@@ -396,10 +416,10 @@ role.
| Build profile | WiFi/MQTT behavior |
|---|---|
| Standard | Uses the selected target's role. Ordinary legacy-slot ESP32 repeater/room-server artifacts omit WebConfig when needed to fit. ESP32 MQTT observer and ESP-NOW bridge targets are automatically promoted to FULL; WiFi-companion targets keep their companion partition profile. |
| Logging | Enables USB/debug packet logging and disables the MQTT bridge. `get/set usb.logging` can silence or restore the live output until reboot. Logging output is not an MQTT uplink. |
| Logging | Enables USB/debug packet logging and disables the MQTT bridge. CommonCLI roles persist `get/set usb.logging`; logging output itself is not a direct MQTT uplink. |
| MQTT | Builds explicit MQTT observer or WiFi-companion-MQTT targets with USB packet logging off. Non-companion ESP32 MQTT observers always use FULL expanded partitions. |
| FULL ESP32 | Uses the board's MQTT target with logging off, expanded dual-OTA partitions, up to 254 neighbors, LoRa OTA, and full-size ESP32 features such as WebConfig where supported. Classic T-Beam MQTT observers retain their 50-entry table because their persistent discovery state exhausts internal DRAM at 254. |
| FULL ESP32 logging | Uses the board's non-MQTT target with debug and packet logging enabled, session-only `get/set usb.logging` control, expanded dual-OTA partitions, up to 254 neighbors, and LoRa OTA. |
| FULL ESP32 USB + WiFi | Uses the board's MQTT target with USB packet logging and direct WiFi MQTT together, expanded dual-OTA partitions, up to 254 neighbors, LoRa OTA, and full-size ESP32 features such as WebConfig where supported. `get/set logging.output off\|usb\|wifi\|both` persists the active paths. Classic T-Beam MQTT observers retain their 50-entry table because their persistent discovery state exhausts internal DRAM at 254. |
| FULL ESP32 logging fallback | Uses the board's non-MQTT target only when no matching WiFi MQTT environment exists. It keeps debug and packet logging, expanded dual-OTA partitions, up to 254 neighbors, and LoRa OTA. Persistent `usb.logging off` also provides normal output-off operation, so ESP-NOW FULL roles need no second non-logging image. |
| LoRa-OTA no-external-sensors | A lean repeater image with no MQTT; ESP32 builds retain the compact on-demand browser WiFi uploader and 254 neighbors. |
All repeater profiles use the full 254-entry neighbor table, including standard,
@@ -407,12 +427,13 @@ logging, bridge, and LoRa-OTA builds on every supported platform. The classic
T-Beam SX1262 and SX1276 MQTT observer repeaters retain 50 entries because their
persistent MQTT discovery state leaves insufficient internal-DRAM margin at 254.
The interactive Option 1 **FULL everything** choice selects the FULL logging
profile: logging is enabled and MQTT is disabled. The standalone FULL ESP32
profile and Profile 3 of the four-profile matrix use the matching MQTT target
instead. Both FULL profiles include LoRa OTA, WebConfig where supported, up to
254 neighbors, and expanded dual-OTA partitions. Target-specific internal-DRAM
limits still apply.
The interactive Option 1 **FULL everything** choice and the standalone FULL
command select the unified USB + WiFi image when a matching MQTT target exists;
otherwise they select the logging fallback. The build matrix no longer emits a
separate standard logging image or non-MQTT FULL twin for a role covered by the
unified image. All FULL profiles include LoRa OTA, WebConfig where supported,
up to 254 neighbors, and expanded dual-OTA partitions. Target-specific
internal-DRAM limits still apply.
FULL images change the ESP32 partition layout. Flash the matching
`*-merged.bin` once when installing that layout. A partition-layout change can
+125 -21
View File
@@ -37,6 +37,9 @@
none: "None / normal operation",
usb: "USB logging / USB-connected MQTT",
wifi: "Wi-Fi MQTT observer",
both: "USB logging + Wi-Fi MQTT",
runtime: "Runtime selectable: off / USB / Wi-Fi / both",
"usb-runtime": "Runtime selectable: off / USB",
});
const OTA_LABELS = Object.freeze({
@@ -90,9 +93,10 @@
});
const HIDDEN_PROFILE_HARDWARE = Object.freeze([
// This legacy environment only changes ADVERT_NAME. The standard G3
// target provides the same firmware behavior, while all legacy files stay
// available through exact filename search.
// These legacy Station environments select a runtime radio-gain default
// or only change ADVERT_NAME. Their ordinary targets provide the same
// behavior, while all legacy files stay available through exact search.
"Station_G2_logging",
"Station_G3_ESP32_logging",
]);
@@ -102,6 +106,9 @@
// siblings; keep those files searchable without recommending them.
"solarxiao_30S_repeater_lora_ota_no_external_sensors",
"solarxiao_33S_repeater_lora_ota_no_external_sensors",
// Exact aliases of the unsuffixed Heltec V4 USB/BLE recipes.
"heltec_v4_companion_radio_usb_femon",
"heltec_v4_companion_radio_ble_femon",
]);
let pickerInstanceCount = 0;
@@ -287,7 +294,13 @@
/^(?:full|ble|usb|wifi|serial|ethernet)(?=$|[_-])/i,
" "
);
// Power saving and controllable FEM gain are persisted settings. Legacy
// filenames retain these tokens for exact search, but they are not
// distinct recommended firmware variants.
value = value.replace(/(?:^|[_-])ps(?=$|[_-])/gi, " ");
value = value.replace(/(?:^|[_-])fem(?:on|off)(?=$|[_-])/gi, " ");
}
value = value.replace(/-full-usb-wifi/gi, "");
value = value.replace(/-logging/gi, "");
value = value.replace(/(?:^|[_-])full(?=$|[_-])/gi, " ");
value = value.replace(/observer_mqtt/gi, " ");
@@ -307,11 +320,23 @@
const lowerTarget = target.toLowerCase();
const lowerTail = parts.tail.toLowerCase();
const mode = modeForRole(parts.role, parts.tail);
const logging = lowerTarget.includes("observer_mqtt")
? "wifi"
: lowerTarget.includes("-logging")
? "usb"
: "none";
const unifiedLogging = lowerTarget.includes("-full-usb-wifi");
const fullLoggingFallback = parts.role !== "companion" &&
lowerTarget.includes("-full-logging");
const logging = unifiedLogging
? "runtime"
: fullLoggingFallback
? "usb-runtime"
: lowerTarget.includes("observer_mqtt")
? "wifi"
: lowerTarget.includes("-logging")
? "usb"
: "none";
const loggingModes = unifiedLogging
? ["none", "usb", "wifi", "both"]
: fullLoggingFallback
? ["none", "usb"]
: [logging];
const feature = lowerTail.includes("-full") ||
(parts.role === "companion" && mode === "full")
? "full"
@@ -334,6 +359,7 @@
hardware: canonicalHardware(sourceHardware),
role: parts.role,
logging: logging,
loggingModes: loggingModes,
mode: mode,
feature: feature,
variant: variant,
@@ -346,6 +372,47 @@
return HARDWARE_ALIASES[value] || value;
}
function isHiddenLegacyProfile(profile) {
const target = String(profile && profile.target || "");
const lowerTarget = target.toLowerCase();
return HIDDEN_PROFILE_HARDWARE.includes(profile.sourceHardware) ||
HIDDEN_PROFILE_TARGETS.includes(target) ||
(lowerTarget.includes("companion_radio_") &&
/(?:^|[_-])(?:ps|femoff)(?=$|[_-])/.test(lowerTarget));
}
function omitNrf52TransportsReplacedByFull(profiles) {
const fullKeys = new Set((profiles || []).filter(function (profile) {
return profile.role === "companion" && profile.mode === "full" &&
profile.installKinds.includes("zip");
}).map(function (profile) {
return profile.hardware + "\n" + profile.variant;
}));
return (profiles || []).filter(function (profile) {
const key = profile.hardware + "\n" + profile.variant;
const replacedAttachedTransport = profile.role === "companion" &&
(profile.mode === "usb" || profile.mode === "ble");
return !(replacedAttachedTransport && fullKeys.has(key));
});
}
function applyNrf52FullCompanionCapabilities(profiles) {
return (profiles || []).map(function (profile) {
const nativeNrf52Full = profile.role === "companion" &&
profile.mode === "full" && profile.installKinds.includes("zip");
if (!nativeNrf52Full) return profile;
// Current nRF52 Full Companion images expose two CDC ACM interfaces:
// framed Companion traffic on interface 00 and plaintext logging on 02.
// The saved USB logging gate covers only the second interface.
profile.logging = "usb-runtime";
profile.loggingModes = ["none", "usb"];
profile.dedicatedUsbLogging = true;
return profile;
});
}
function hardwareFamilyFor(hardware, hardwareNames) {
const value = String(hardware || "");
const lowerValue = value.toLowerCase();
@@ -432,7 +499,7 @@
profile.otaPackaged = profile.otaPackaged || file.otaPackaged;
});
const profiles = Array.from(grouped.values()).map(function (profile) {
const visibleProfiles = Array.from(grouped.values()).map(function (profile) {
profile.ota = profile.explicitOta ||
(profile.otaPackaged ? "lora-receiver" : "none");
profile.installKinds = INSTALL_ORDER.filter(function (kind) {
@@ -443,9 +510,11 @@
});
return profile;
}).filter(function (profile) {
return !HIDDEN_PROFILE_HARDWARE.includes(profile.sourceHardware) &&
!HIDDEN_PROFILE_TARGETS.includes(profile.target);
}).sort(function (a, b) {
return !isHiddenLegacyProfile(profile);
});
const profiles = omitNrf52TransportsReplacedByFull(
applyNrf52FullCompanionCapabilities(visibleProfiles)
).sort(function (a, b) {
return a.target.localeCompare(b.target, undefined, {
numeric: true,
sensitivity: "base",
@@ -473,10 +542,17 @@
const wantedFields = fields || FILTER_FIELDS;
return wantedFields.every(function (field) {
const value = filters && filters[field];
return !value || profile[field] === value;
return !value || profileFieldValues(profile, field).includes(value);
});
}
function profileFieldValues(profile, field) {
if (field === "logging" && Array.isArray(profile.loggingModes)) {
return profile.loggingModes;
}
return profile[field] ? [profile[field]] : [];
}
function profileMatchesFacets(profile, filters, ignoredField) {
const ignoredFields = new Set(
Array.isArray(ignoredField) ? ignoredField : [ignoredField]
@@ -488,7 +564,7 @@
if (field === "install") {
return profile.installKinds.includes(value);
}
return profile[field] === value;
return profileFieldValues(profile, field).includes(value);
});
}
@@ -501,15 +577,15 @@
? compatible.flatMap(function (profile) {
return profile.installKinds;
})
: compatible.map(function (profile) {
return profile[field];
: compatible.flatMap(function (profile) {
return profileFieldValues(profile, field);
});
return Array.from(new Set(values.filter(Boolean)));
}
function uniqueValues(profiles, field) {
return Array.from(new Set((profiles || []).map(function (profile) {
return profile[field];
return Array.from(new Set((profiles || []).flatMap(function (profile) {
return profileFieldValues(profile, field);
}).filter(Boolean)));
}
@@ -566,7 +642,7 @@
function optionSort(field, a, b) {
const roleOrder = ["companion", "repeater", "room", "sensor", "terminal", "kiss", "other"];
const loggingOrder = ["none", "usb", "wifi"];
const loggingOrder = ["none", "usb", "wifi", "both"];
const otaOrder = ["none", "lora-receiver", "lora-source"];
const featureOrder = ["standard", "full"];
const modeOrder = ["standard", "full", "ble", "usb", "wifi", "serial", "ethernet", "mqtt", "espnow", "rs232"];
@@ -627,6 +703,23 @@
"Full Companion can serve a host-supplied update to another node; it does not self-install that LoRa update."
);
}
if (profile.logging === "runtime") {
extra.push(
"Use get logging.output and set logging.output off|usb|wifi|both to choose the saved output mode. Avoid both when two consumers publish the same packets to one broker."
);
extra.push(
"With no saved SSID, the setup AP stays available for 30 minutes after each boot, then Wi-Fi powers off automatically until reboot or an explicit start webconfig command. A configured Wi-Fi mode keeps reconnecting instead."
);
} else if (profile.logging === "usb-runtime") {
extra.push(
"Use get usb.logging and set usb.logging off|on to choose and save normal output-off or USB packet logging."
);
if (profile.dedicatedUsbLogging) {
extra.push(
"This nRF52 Full Companion exposes two serial ports on one USB cable: interface 00 carries Companion/terminal/mOTA traffic and interface 02 carries plaintext logging. Match services by USB interface number instead of assuming tty or COM numbering."
);
}
}
return common.concat(byKind[kind] || [], extra);
}
@@ -649,7 +742,7 @@
const facts = createElement("dl");
facts.className = "firmware-picker-facts";
replaceFacts(facts, [
const factRows = [
["Target", profile.target],
["Connection / mode", labelFor("mode", profile.mode)],
["Logging", labelFor("logging", profile.logging)],
@@ -660,7 +753,14 @@
["File", asset.name],
["Size", formatBytes(asset.size)],
["Release", asset.releaseName],
]);
];
if (profile.dedicatedUsbLogging) {
factRows.splice(3, 0, [
"USB port split",
"Interface 00 Companion; interface 02 logging",
]);
}
replaceFacts(facts, factRows);
card.appendChild(facts);
const actions = createElement("div");
@@ -986,11 +1086,15 @@
flattenReleaseAssets: flattenReleaseAssets,
parseFirmwareAsset: parseFirmwareAsset,
parseTargetProfile: parseTargetProfile,
applyNrf52FullCompanionCapabilities:
applyNrf52FullCompanionCapabilities,
canonicalHardware: canonicalHardware,
omitNrf52TransportsReplacedByFull: omitNrf52TransportsReplacedByFull,
hardwareFamilyFor: hardwareFamilyFor,
humanizeHardwareVariant: humanizeHardwareVariant,
buildCatalog: buildCatalog,
profileMatches: profileMatches,
profileFieldValues: profileFieldValues,
profileMatchesFacets: profileMatchesFacets,
facetValues: facetValues,
uniqueValues: uniqueValues,
+33 -4
View File
@@ -36,16 +36,45 @@ retain 50 because their MQTT discovery tables are constrained by internal DRAM.
| Build/profile | Command availability |
|---|---|
| Standard non-MQTT repeater or room server | Keeps the normal role CLI. Size-constrained ESP32 artifacts can omit WebConfig and browser WiFi OTA, so their WebConfig/WiFi commands are unavailable. |
| Standard logging | Logging does not remove commands by itself. It has the same CLI as the selected role/profile, adds the compiled logging behavior, and provides session-only `get/set usb.logging` control. |
| Standard logging | Logging does not remove commands by itself. It has the same CLI as the selected role/profile and adds compiled logging behavior. CommonCLI roles persist `get/set usb.logging`. ESP32 roles covered by unified FULL and nRF52 Companions covered by dual-CDC Full Companion are not duplicated here. |
| LoRa-OTA (`-ota-`) | LoRa OTA adds the `ota ...` commands; it does not otherwise reduce the role CLI. ESP32 `no_external_sensors` artifacts retain the compact browser WiFi uploader, the complete CLI, and a 254-entry neighbor table. |
| ESP32 MQTT observer or ESP-NOW bridge | Always uses the expanded FULL partition profile. The build never substitutes a reduced CLI to fit the legacy application slot. |
| FULL ESP32 | Uses the matching MQTT target with logging off and keeps the complete command surface supported by that role and hardware. |
| FULL ESP32 logging | Uses the matching non-MQTT target with debug and packet logging enabled, session-only `get/set usb.logging` control, and the complete command surface supported by that role and hardware. |
| FULL ESP32 USB + WiFi | Uses the matching MQTT target with packet logging on, verbose debug off, and the complete command surface supported by that role and hardware. `get/set logging.output off\|usb\|wifi\|both` selects and persists the active output paths. |
| FULL ESP32 logging fallback | Uses the matching non-MQTT target only when no WiFi MQTT sibling exists, with debug and packet logging enabled and the complete command surface supported by that role and hardware. Its persistent USB gate also covers output-off operation, avoiding a second FULL ESP-NOW image. |
| nRF52 Full Companion | Uses one physical USB connection with interface `00` for framed Companion/terminal/mOTA traffic and interface `02` for plaintext logging. It also provides BLE and source-only LoRa OTA. `get/set usb.logging` persistently gates only the logging interface. |
| `no_external_sensors` | Removes optional external-sensor drivers and their settings; it does not remove core repeater discovery or routing commands. GPS-preserving RAK nRF52 OTA profiles retain their GPS commands and provider. The RAK4631 Serial1 RS232 bridge remains GPS-off because both features require Serial1. |
`logging`, `OTA`, and `FULL` describe independent build features. Do not infer
that a command is missing merely because `logging` appears in the filename.
## Canonical bulk-build policy
Bulk and release-matrix commands omit legacy names whose behavior is already
available from a canonical image:
- Companion `_ps` names are replaced by the ordinary Companion image plus the
persisted `powersaving on|off` setting.
- Companion `_femoff` names are replaced by the matching controllable-FEM
image plus `radio.fem.rxgain on|off`. The old names remain explicit build
targets for compatibility.
- `Station_G2_logging_*` and `Station_G3_ESP32_logging_*` hardware names are
replaced by their ordinary Station target. G2 boosted receive gain is the
persisted `radio.rxgain on|off` setting; the G3 alias changed only the
advertised default name.
- When an nRF52 board has a generated Full Companion, that one artifact
replaces its separate USB, BLE, and USB packet-logging Companion artifacts.
It provides BLE plus two USB CDC interfaces: interface `00` carries framed
Companion/terminal/mOTA traffic and interface `02` carries plaintext logs.
Its LoRa OTA support is source-only: it can serve a host file to another node
but has no staging store and cannot update itself over LoRa.
The old aliases still work with `build-firmware` and
`build-matching-firmwares`. Dedicated repeater LoRa OTA receiver images are not
collapsed; they retain their exact storage, bootloader, role, and target
identity contracts. ESP32 USB, BLE, WiFi, and Full Companion images also remain
separate because Full changes partitions, RAM use, active transports, and power
behavior.
## Complete CLI policy
The compact ESP32 CLI has been removed. MQTT observers and ESP-NOW bridges are
@@ -64,7 +93,7 @@ require MQTT or PSRAM.
`discover.neighbors` sends the zero-hop node-discovery request used to refresh
the repeater neighbor table. It is available in every repeater build profile,
including standard, logging, OTA, FULL, and FULL logging builds.
including standard, logging, OTA, unified FULL, and FULL logging-fallback builds.
The exact command is:
+9 -7
View File
@@ -17,10 +17,12 @@ Build columns mean:
remove commands by itself.
- **LoRa OTA** - the explicit `-ota-` repeater or repeater-bridge artifact. Its
optional external-sensor drivers are removed, but onboard GPS is retained.
- **FULL** - the expanded-partition ESP32 artifact with LoRa OTA and the
complete parser. MQTT observers and ESP-NOW bridges always use this profile.
- **FULL logging** - the expanded-partition ESP32 non-MQTT artifact with
logging, LoRa OTA, and the complete parser.
- **FULL unified** - the expanded-partition ESP32 artifact with LoRa OTA, the
complete parser, USB packet logging, and direct WiFi MQTT. Its saved output
mode can be off, USB, WiFi, or both. MQTT observers use this profile.
- **FULL fallback** - the expanded-partition ESP32 non-MQTT artifact used only
where there is no MQTT sibling. It has the complete parser and a saved
USB-logging on/off gate. ESP-NOW bridges use this profile.
Cell values mean:
@@ -69,7 +71,7 @@ fix, no WiFi connection, an inactive bridge, or an nRF52 bootloader without
| Statistics | [`get telemetry.temp/volt`; optional GPS history; `get/set telemetry.tx`](cli_commands.md#read-repeater-telemetry-history) | Non-STM32 repeater; GPS commands require a GPS provider; remote access requires administrator | Yes | Yes | Yes |
| Logging | [`log start`; `log stop`; `log erase`](cli_commands.md#logging) | Storage-backed roles retain data; other roles can return empty data | Yes | Yes | Yes |
| Logging | [`log`](cli_commands.md#print-the-captured-log-to-the-serial-terminal) | Local serial | Serial | Serial | Serial |
| Logging | [`get/set usb.logging`](cli_commands.md#control-live-usb-logging) | Logging artifacts; session-only live USB output gate | No | Yes | No |
| Logging | [`get/set usb.logging`; unified FULL `get/set logging.output`](cli_commands.md#control-live-usb-logging) | Logging artifacts; CommonCLI USB gate is persistent; unified ESP32 FULL selects off/USB/WiFi/both; nRF52 Full Companion gates its second USB port | No | Yes | No |
| Radio | [`get radio`; `set radio ...`](cli_commands.md#view-or-change-this-nodes-radio-parameters) | All text CLI roles | Yes | Yes | Yes |
| Radio | [`get tx`; `set tx <dbm>`](cli_commands.md#view-or-change-this-nodes-transmit-power) | Board TX-power limits apply | Yes | Yes | Yes |
| Radio | [`tempradio ...`; `normalradio`](cli_commands.md#change-the-radio-parameters-for-a-set-duration) | Full parser | Yes | Yes | Yes |
@@ -201,7 +203,7 @@ fix, no WiFi connection, an inactive bridge, or an nRF52 bootloader without
## ESP32
| Area | Command | Scope | Standard | Logging | LoRa OTA | FULL | FULL logging |
| Area | Command | Scope | Standard | Logging | LoRa OTA | FULL unified | FULL fallback |
|---|---|---|---|---|---|---|---|
| Operational | [`reboot`](cli_commands.md#reboot-the-node) | All text CLI roles | Yes | Yes | Yes | Yes | Yes |
| Operational | [`poweroff`; `shutdown`](cli_commands.md#power-off-the-node) | Board power-off support | Yes | Yes | Yes | Yes | Yes |
@@ -231,7 +233,7 @@ fix, no WiFi connection, an inactive bridge, or an nRF52 bootloader without
| Statistics | [`get telemetry.temp/volt`; optional GPS history; `get/set telemetry.tx`](cli_commands.md#read-repeater-telemetry-history) | Non-STM32 repeater; GPS commands require a GPS provider; remote access requires administrator | Yes | Yes | Yes | Yes | Yes |
| Logging | [`log start`; `log stop`; `log erase`](cli_commands.md#logging) | Storage-backed roles retain data | Yes | Yes | Yes | Yes | Yes |
| Logging | [`log`](cli_commands.md#print-the-captured-log-to-the-serial-terminal) | Local serial | Serial | Serial | Serial | Serial | Serial |
| Logging | [`get/set usb.logging`](cli_commands.md#control-live-usb-logging) | Logging artifacts; session-only live USB output gate | No | Yes | No | No | Yes |
| Logging | [`get/set usb.logging`; unified FULL `get/set logging.output`](cli_commands.md#control-live-usb-logging) | Logging artifacts; CommonCLI USB gate is persistent; unified ESP32 FULL selects off/USB/WiFi/both; nRF52 Full Companion gates its second USB port | No | Yes | No | No | Yes |
| Radio | [`get radio`; `set radio ...`](cli_commands.md#view-or-change-this-nodes-radio-parameters) | All text CLI roles | Yes | Yes | Yes | Yes | Yes |
| Radio | [`get tx`; `set tx <dbm>`](cli_commands.md#view-or-change-this-nodes-transmit-power) | Board TX-power limits apply | Yes | Yes | Yes | Yes | Yes |
| Radio | [`tempradio ...`; `normalradio`](cli_commands.md#change-the-radio-parameters-for-a-set-duration) | Full parser | Yes | Yes | Yes | Yes | Yes |
+37 -12
View File
@@ -201,8 +201,13 @@ WiFi SSID, the command starts the open `MeshCore-Setup-XXXX` captive AP at
MQTT bridge, so run `set bridge.enabled off` first. Use `stop webconfig` to
close either mode for the current boot. (`stop webconfig` does not change a
saved `webui on`.)
LAN mode otherwise remains active until reboot; setup mode stops after 10 minutes
with no connected client.
LAN mode otherwise remains active until reboot. On expanded FULL builds, an
unconfigured automatic setup AP receives one absolute 30-minute window per
boot, then powers WiFi off even if a client remains attached; rebooting starts
a new automatic window. An administrator can explicitly run `start webconfig`
again without rebooting. Once an SSID is saved, the cutoff no longer applies
and the selected WiFi/MQTT mode keeps reconnecting. Other setup sessions retain
their profile's idle timeout.
The saved `wifi.cli` setting defaults to `on`. Use `set wifi.cli off` to disable
the **CLI** tab.
@@ -225,7 +230,8 @@ single-command mode. A command that stops WebConfig, changes its WiFi
connection, disables `wifi.cli`, or reboots the node stops the remaining block
and can close the page before its reply is collected.
On FULL MQTT and FULL logging ESP32 repeater/room-server builds,
On unified FULL USB + WiFi and FULL logging-fallback ESP32
repeater/room-server builds,
`get wifi.ssid` reports the saved standalone WebConfig network and
`get wifi.status` reports whether WiFi is unconfigured, off, connecting,
running the setup AP, failed, or connected. A connected result includes the
@@ -301,7 +307,7 @@ remain available.
- `discover.neighbors`
This command is available in every repeater build profile, including portable
MQTT, standard, logging, OTA, FULL, and FULL logging artifacts. It does not
MQTT, standard, logging, OTA, unified FULL, and FULL logging-fallback artifacts. It does not
require MQTT or PSRAM.
---
@@ -520,9 +526,9 @@ summary.
Ordinary `-logging-` artifacts keep packet logging separate from LoRa OTA.
Use the separately named `-ota-` artifact when LoRa OTA is required. A
`-full-logging-ota-` artifact is intentionally the exception: it combines
logging with LoRa OTA and the expanded FULL feature set, while MQTT remains
disabled.
`-full-usb-wifi-ota-` artifact combines USB packet logging, direct WiFi MQTT,
LoRa OTA, and the expanded FULL feature set. A `-full-logging-ota-` artifact is
emitted only when that hardware/role has no matching WiFi MQTT environment.
### Control live USB logging
@@ -535,11 +541,30 @@ set usb.logging off
```
These commands are compiled into logging artifacts and control their live USB
debug and packet output. The switch is session-only: every reboot starts a
logging artifact with USB logging on. Turning it off does not disable CLI
replies, Companion protocol frames, or essential non-debug serial messages.
It also does not change the node-storage capture controlled by `log start` and
`log stop`.
debug and packet output. CommonCLI roles save the setting in `/com_prefs`, so
it survives reboot; first boot defaults to on. nRF52 Full Companion applies the
gate only to USB interface `02`, its dedicated plaintext logging port. USB
interface `00` continues carrying Companion, terminal, and serial mOTA traffic.
Turning USB logging off does not disable CLI replies or Companion protocol
frames. It also does not change the node-storage capture controlled by `log
start` and `log stop`.
Unified ESP32 FULL builds add one saved selector for both output paths:
```text
get logging.output
set logging.output off
set logging.output usb
set logging.output wifi
set logging.output both
```
`usb` emits `RAW:` packets for a USB-connected service such as
meshcoretomqtt. `wifi` enables the direct MQTT bridge configured by the
`wifi.*` and `mqtt.*` commands. `both` intentionally duplicates the radio
stream to both consumers; do not point both consumers at the same broker unless
the downstream setup deduplicates messages. Fresh unified FULL installs start
in `both` mode.
### Begin capture of rx log to node storage
**Usage:** `log start`
+35 -8
View File
@@ -47,11 +47,15 @@ bash build.sh build-full-companion-firmwares \
--firmware-version v1.17.0
```
Heltec `_femon` Companion firmware can switch the external FEM receive gain at
runtime, so the Companion bulk-build commands omit the redundant legacy
`_femoff` targets. Those targets remain available through an explicit
`build-firmware` command for compatibility. In WebConfig, use the **FEM RX
boost** switch. From the text terminal (USB, or TCP 5002 on ESP32), use:
Canonical Companion bulk builds also omit legacy `_ps` and `_femoff` aliases.
Power saving and controllable FEM receive gain are persisted runtime settings;
the old names remain available through an explicit `build-firmware` command
for compatibility. On nRF52, Full Companion replaces separate USB and BLE
normal release artifacts whenever the exact board has both recipes. It also
replaces the USB-only packet-logging artifact: one physical USB connection
enumerates separate Companion and logging serial ports, so plaintext logs
cannot corrupt binary frames. In WebConfig, use the
**FEM RX boost** switch. From the text terminal (USB, or TCP 5002 on ESP32), use:
```text
get radio.rxgain
@@ -242,9 +246,32 @@ The terminal supports Companion chat commands, including `channels`,
`trace [recipient-name-or-prefix]`, plus local `ota`, `tempradio`, and
`normalradio` controls. ESP32 builds also provide local
WiFi credential, status, WebConfig, CLI-tab, and power-save controls. Logging
artifacts additionally provide session-only
`get/set usb.logging`; turning it off suppresses live USB diagnostics without
disabling Companion frames or terminal replies.
artifacts additionally provide `get/set usb.logging`; turning it off
suppresses live USB diagnostics without disabling Companion frames or terminal
replies. nRF52 Full Companion saves this setting and applies it only to its
dedicated logging port.
### nRF52 dual USB serial ports
Current nRF52 Full Companion firmware exposes two CDC ACM serial interfaces on
one physical USB cable:
- USB interface `00` is the normal Binary Companion, text terminal, and serial
mOTA source port.
- USB interface `02` is a write-only plaintext packet/debug logging port. Host
input on this interface is ignored and cannot invoke firmware commands.
On Linux these normally appear as two `/dev/ttyACM*` devices. Match the stable
`/dev/serial/by-id/*-if00` and `*-if02` links, or use a udev rule matching
`ID_USB_INTERFACE_NUM`, rather than assuming which tty number is assigned. On
Windows they appear as two COM ports; identify them by USB interface instead of
depending on a particular COM number. The bootloader may temporarily expose
only its normal DFU serial interface while an update is active.
Point MeshCore Companion software, `meshcli`, and `motatool` at interface `00`.
Point a plaintext reader or USB-connected MQTT service at interface `02`. Use
`set usb.logging off|on` through the Companion terminal to persist whether the
second port emits output.
ESP32 Full Companion exposes this same text terminal on TCP port 5002. Connect
with `nc DEVICE_IP 5002`; no USB control token is needed. USB terminal mode and
+31 -3
View File
@@ -134,6 +134,7 @@ from the published firmware assets.
| Terminal Chat | Standalone serial-terminal interface |
| USB logging / USB-connected MQTT | Node remains attached to a computer over a data-capable USB cable |
| Wi-Fi MQTT observer | Firmware connects directly to MQTT over Wi-Fi; this is not USB logging |
| USB logging + Wi-Fi MQTT | Unified FULL image sends to both paths; avoid two publishers aimed at the same broker unless messages are deduplicated |
| No logging | Normal standalone operation without the dedicated logging/MQTT profile |
| LoRa OTA enabled / receiver | Install-capable profile that can stage an exact matching update received over LoRa |
| LoRa OTA source only | Full Companion serving a host-supplied update to another node without self-installing it |
@@ -155,6 +156,25 @@ Changing between standard and FULL ESP32 layouts requires the exact-board
merged image over USB. A running application cannot safely move its own active
and inactive partitions.
Current `full-usb-wifi` profiles use one binary for no external output, USB
packet logging/USB-connected MQTT, direct WiFi MQTT, or both. The picker shows
that same exact binary for each compatible logging choice; select the saved
runtime mode with `set logging.output off|usb|wifi|both`. A FULL logging-fallback
profile is listed only when no WiFi MQTT sibling exists; it appears for both
the no-output and USB choices because `set usb.logging off|on` is persistent.
On a fresh unified FULL install with no saved SSID, the setup AP and WiFi radio
remain available for 30 minutes per boot, then turn off automatically until the
next reboot or power cycle. An explicit administrator `start webconfig` remains
available as an override. A saved SSID switches to the normal indefinite
reconnect behavior instead.
Current nRF52 Full Companion profiles also use one binary for normal attached
Companion use and USB packet logging. One USB cable exposes interface `00` for
Binary Companion, terminal, and mOTA source traffic, plus interface `02` for
plaintext logging. The picker therefore omits the older separate nRF52 USB,
BLE, and USB-logging Companion choices when the matching Full artifact exists.
Use `set usb.logging off|on` to persist the second port's output state.
## Installation methods
| File | Use |
@@ -184,6 +204,14 @@ and select the hardware-matched HEX, Serial DFU ZIP, or bootloader-update UF2.
Hardware families with multiple released targets get a second hardware-variant
menu. It separates revisions, display type, expansion kit, radio/PA layout,
pin map, and other physical differences without crowding the first menu. The
firmware-variant menu separately exposes build choices such as FEM on/off,
power saving, serial port, or no-external-sensors. Do not substitute a
similarly named target.
firmware-variant menu separately exposes choices that still require different
code or wiring, such as serial port or no-external-sensors. Companion power
saving, controllable FEM receive gain, and radio-chip receive gain are saved
settings rather than separate recommended firmware files. Do not substitute a
similarly named physical target.
For nRF52 hardware with a Full Companion image, the picker recommends that one
normal image instead of separate USB, BLE, and USB-logging images. Full
Companion provides both attached transports and a dedicated plaintext logging
port without mixing logs into framed Companion traffic. Exact filename search
still finds old aliases from earlier releases.
+4 -2
View File
@@ -56,8 +56,10 @@ The USB ASCII switch (`+++MESHCORE-TERM-START`) is the local control path, not
the mOTA data framing. On an nRF52 full Companion, the script uses that mode
briefly for `ota status` and TempRadio commands. It then closes the CLI and
starts `motatool`, whose existing `ota folder on` preamble switches the same
USB port into exclusive mOTA mode. On an ESP32 Full Companion with serial
folder support, `motatool --companion-terminal` keeps the ASCII session open
USB interface `00` into exclusive mOTA mode. Its separate USB interface `02`
continues to provide plaintext logging and is not a controller or source port.
On an ESP32 Full Companion with serial folder support,
`motatool --companion-terminal` keeps the ASCII session open
while the same link carries framed folder requests. BLE remains available.
## Destination requirements
+10 -8
View File
@@ -88,14 +88,15 @@ speed optimization. This prevents the retained software Ed25519 fallback from ex
in-place workspace; CC310 hardware crypto, hardware RNG mixing, telemetry history, and board-native features
remain enabled.
ESP32 `*-full-ota-*` artifacts retain all compiled features and enable LoRa OTA for every FULL role,
ESP32 `*-full-usb-wifi-ota-*` artifacts retain all compiled features and enable LoRa OTA for every FULL role,
including room servers, sensors, observers, and bridges. A FULL image requires its expanded partition table:
install the matching merged image over USB once before installing later non-merged FULL updates over LoRa.
ESP32 MQTT observers and ESP-NOW bridges are always emitted as FULL artifacts; compact-CLI variants are no
longer built.
The `*-full-ota-*` profile uses MQTT with logging off. Use a `*-full-logging-ota-*` artifact when USB debug
and packet logging are needed instead; that diagnostic profile explicitly disables MQTT and can produce
substantial serial output.
The `*-full-usb-wifi-ota-*` profile compiles USB packet logging and direct WiFi MQTT into one image. Use
`set logging.output off|usb|wifi|both` to persist the desired path. A `*-full-logging-ota-*` artifact is now
only a fallback for a hardware/role combination without a WiFi MQTT target and can produce substantial
serial output.
### Choose the source radio
@@ -107,8 +108,9 @@ serves host images but cannot stage or install one for itself. ESP32 full
combines USB, BLE, and WiFi; nRF52 full combines USB and BLE because nRF52840
has no WiFi.
A small set of high-capacity, non-PSRAM classic ESP32 companions
keep their normal image and provide a separate `-full-ota-` image with 100 contacts, 8 group channels, and
a 16-frame offline queue. Install that variant's merged image over USB once before using it. Connect the
keep their normal image and provide a separate `-full-logging-ota-` fallback with 100 contacts, 8 group
channels, a 16-frame offline queue, and persistent USB output selection. Install that variant's merged
image over USB once before using it. Connect the
source by USB serial or, when supported, by WiFi. For an ordinary raw-text USB
source, confirm that its USB CLI accepts:
@@ -116,8 +118,8 @@ source, confirm that its USB CLI accepts:
ota folder on
```
If an older build reports that `OTA_FOLDER_SERIAL` is not compiled in, install a current `-ota-` or
`-full-ota-` build first. Do **not** use a KISS modem: KISS firmware is a TNC/KISS frame interface
If an older build reports that `OTA_FOLDER_SERIAL` is not compiled in, install a current `-ota-`,
`-full-usb-wifi-ota-`, or applicable `-full-logging-ota-` build first. Do **not** use a KISS modem: KISS firmware is a TNC/KISS frame interface
and does not provide the MeshCore CLI or the OTA-folder transport that `motatool serve` requires.
An nRF52 `companion_radio_full` starts in USB Binary mode. Use
+18 -11
View File
@@ -116,8 +116,9 @@ ESP32 companion firmware is exempt from the portable-slot limit. USB and WiFi co
LoRa OTA and carry `-ota-` in their filenames so they can seed a host folder over serial or TCP; they keep
their target partition table rather than using the FULL profile. A small set of high-capacity, non-PSRAM classic ESP32
companions cannot combine their configured contact, group-channel, and offline-queue capacities with LoRa
OTA in internal DRAM. Their normal artifacts remain unchanged, and option 3 also emits `-full-ota-` and
`-full-logging-ota-` variants with 100 contacts, 8 group channels, and a 16-frame offline queue. MQTT
OTA in internal DRAM. Their normal artifacts remain unchanged, and option 3 emits a
`-full-logging-ota-` fallback with 100 contacts, 8 group channels, a 16-frame offline queue, and a saved
USB-logging on/off gate. MQTT
observers and ESP-NOW bridges always use FULL builds because fitting them into the legacy slot would require
removing CLI and role features. Except for those FULL roles and the ESP32-C6 case below, non-companion ESP32
artifacts, including room, sensor, and repeater roles, must fit the legacy slot from `0x10000` up to
@@ -157,21 +158,27 @@ during a settings save restores the last committed common preference image or pu
image; it does not leave a partially written `/com_prefs` file to fail on the next boot. A truncated legacy
image is rejected before any partial radio or string fields are applied, then rewritten from safe defaults.
Option 3 in `build.sh` emits `*-full-ota-*` and `*-full-logging-ota-*` ESP32 artifacts for
FULL-capable non-companion roles and for the constrained companion fallbacks described above. MQTT observers
and ESP-NOW bridges are emitted only with expanded FULL partitions. Menu option 8, or
`build-full-esp32-firmwares`, builds the logging-off FULL
artifacts from matching MQTT targets. Menu option 9, or `build-full-esp32-logging-firmwares`, builds the
FULL logging artifacts from matching non-MQTT targets.
Option 3 in `build.sh` emits one `*-full-usb-wifi-ota-*` ESP32 artifact for each
FULL-capable non-companion hardware/role that has a matching MQTT environment.
It compiles USB packet logging and direct WiFi MQTT together. A
`*-full-logging-ota-*` fallback is emitted only when there is no MQTT sibling;
the old separate standard-logging and non-MQTT FULL twins are skipped for
covered ESP32 roles. MQTT observers and ESP-NOW bridges are emitted only with
expanded FULL partitions. Menu option 8, or `build-full-esp32-firmwares`,
builds the unified profiles plus necessary fallbacks. Menu option 9, or
`build-full-esp32-logging-firmwares`, builds only those fallbacks.
FULL builds restore WebConfig, display support, optional external sensors, and the full role CLI and feature
set,
full ElegantOTA where that target declares the required library, and LoRa OTA for every included role,
including room servers, sensors, observers, and bridges. They use expanded A/B partition
tables: 1984 KiB application slots on 4 MiB boards and the framework's larger dual-OTA tables on 8 MiB
and 16 MiB boards. Explicit `*_lora_ota_no_external_sensors` targets are not duplicated; their ordinary
repeater build is the FULL, sensor-enabled counterpart. The `*-full-logging-ota-*` profile enables USB
debug and packet logging and explicitly disables MQTT. Install a matching
`*-full-ota-*-merged.bin` or `*-full-logging-ota-*-merged.bin` over USB once to write the expanded partition
repeater build is the FULL, sensor-enabled counterpart. The
`*-full-usb-wifi-ota-*` profile enables USB packet logging and MQTT, with a
persistent `logging.output` selector; its verbose internal debug remains off.
The fallback `*-full-logging-ota-*` profile enables USB debug and packet
logging and has no MQTT target. Install a matching
`*-full-usb-wifi-ota-*-merged.bin` or `*-full-logging-ota-*-merged.bin` over USB once to write the expanded partition
table. After that, its matching non-merged FULL application image can be installed through USB, WiFi OTA,
or LoRa OTA. Do not install a non-merged FULL image onto a node that still has its old partition table.