Unify full firmware profiles and add dual USB logging
This commit is contained in:
1 parent
b699e552ec
commit
f2d4ffbb7e
56 files changed
+1652
-361
No files matched your search
@@ -80,6 +80,22 @@ TEST(CompanionNodePrefs, WiFiStateIsIndependentFromPowerSaving) {
|
||||
EXPECT_EQ(1, prefs.powersaving_enabled);
|
||||
}
|
||||
|
||||
TEST(CompanionNodePrefs, UsbLoggingStateIsIndependentFromTransports) {
|
||||
CompanionNodePrefs prefs = {};
|
||||
prefs.usb_logging_enabled = 1;
|
||||
prefs.wifi_enabled = 0;
|
||||
prefs.powersaving_enabled = 1;
|
||||
|
||||
EXPECT_EQ(1, prefs.usb_logging_enabled);
|
||||
EXPECT_EQ(0, prefs.wifi_enabled);
|
||||
EXPECT_EQ(1, prefs.powersaving_enabled);
|
||||
|
||||
prefs.usb_logging_enabled = 0;
|
||||
EXPECT_EQ(0, prefs.usb_logging_enabled);
|
||||
EXPECT_EQ(0, prefs.wifi_enabled);
|
||||
EXPECT_EQ(1, prefs.powersaving_enabled);
|
||||
}
|
||||
|
||||
TEST(CompanionNodePrefs, MigratesRegressedPowerSavingDefaultOnce) {
|
||||
CompanionNodePrefs prefs = {};
|
||||
prefs.powersaving_enabled = 0;
|
||||
|
||||
@@ -196,6 +196,7 @@ TEST(NodePrefs, FemGainSettingsRoundTrip) {
|
||||
NodePrefs saved;
|
||||
saved.radio_fem_rxgain = 0;
|
||||
saved.radio_fem_txgain = 1;
|
||||
saved.usb_logging_enabled = 0;
|
||||
|
||||
MockPrintStream output;
|
||||
ASSERT_TRUE(saved.saveSerial(output));
|
||||
@@ -203,15 +204,18 @@ TEST(NodePrefs, FemGainSettingsRoundTrip) {
|
||||
std::string serialised(reinterpret_cast<const char*>(output.getBytes()), output.getLength());
|
||||
EXPECT_NE(std::string::npos, serialised.find("fem_rxgain:0"));
|
||||
EXPECT_NE(std::string::npos, serialised.find("fem_txgain:1"));
|
||||
EXPECT_NE(std::string::npos, serialised.find("usb_log:0"));
|
||||
|
||||
MockInputStream input(serialised.c_str());
|
||||
NodePrefs loaded;
|
||||
loaded.radio_fem_rxgain = 1;
|
||||
loaded.radio_fem_txgain = 0;
|
||||
loaded.usb_logging_enabled = 1;
|
||||
|
||||
ASSERT_TRUE(loaded.loadSerial(input));
|
||||
EXPECT_EQ(0, loaded.radio_fem_rxgain);
|
||||
EXPECT_EQ(1, loaded.radio_fem_txgain);
|
||||
EXPECT_EQ(0, loaded.usb_logging_enabled);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+102
-23
@@ -38,6 +38,10 @@ const releases = [
|
||||
asset("Station_G3_ESP32_logging_repeater-" + family + ".bin"),
|
||||
asset("Heltec_t096_companion_radio_ble_ps_femon-" + family + ".uf2"),
|
||||
asset("Heltec_t096_companion_radio_ble_ps_femon-" + family + ".zip"),
|
||||
asset("RAK_4631_companion_radio_full-" + family + ".uf2"),
|
||||
asset("RAK_4631_companion_radio_full-" + family + ".zip"),
|
||||
asset("RAK_4631_companion_radio_usb-logging-" + family + ".uf2"),
|
||||
asset("RAK_4631_companion_radio_usb-logging-" + family + ".zip"),
|
||||
]),
|
||||
release("repeater-room-" + family, "2026-08-23T12:00:05Z", [
|
||||
asset("Station_G2_repeater-" + family + "-deadbee-merged.bin"),
|
||||
@@ -76,15 +80,15 @@ const releases = [
|
||||
]),
|
||||
release("full-profiles-" + family, "2026-08-23T12:00:01Z", [
|
||||
asset(
|
||||
"Station_G2_repeater-full-logging-ota-" + family + "-merged.bin"
|
||||
"Generic_ESPNOW_repeatr-full-logging-ota-" + family + "-merged.bin"
|
||||
),
|
||||
asset("Station_G2_repeater-full-logging-ota-" + family + ".bin"),
|
||||
asset("Generic_ESPNOW_repeatr-full-logging-ota-" + family + ".bin"),
|
||||
asset(
|
||||
"Station_G2_repeater_observer_mqtt-full-ota-" +
|
||||
"Station_G2_repeater_observer_mqtt-full-usb-wifi-ota-" +
|
||||
family + "-merged.bin"
|
||||
),
|
||||
asset(
|
||||
"Station_G2_repeater_observer_mqtt-full-ota-" + family + ".bin"
|
||||
"Station_G2_repeater_observer_mqtt-full-usb-wifi-ota-" + family + ".bin"
|
||||
),
|
||||
]),
|
||||
release(
|
||||
@@ -106,8 +110,8 @@ assert(!releaseSet.releases.some(function (item) {
|
||||
|
||||
const catalog = picker.buildCatalog(releases);
|
||||
assert.strictEqual(catalog.releaseSet.familyTag, family);
|
||||
assert.strictEqual(catalog.profiles.length, 12);
|
||||
assert.strictEqual(catalog.rows.length, 29);
|
||||
assert.strictEqual(catalog.profiles.length, 11);
|
||||
assert.strictEqual(catalog.rows.length, 33);
|
||||
|
||||
function profile(target) {
|
||||
const found = catalog.profiles.find(function (item) {
|
||||
@@ -126,14 +130,29 @@ assert.strictEqual(companionFull.ota, "lora-source");
|
||||
assert.strictEqual(companionFull.feature, "full");
|
||||
assert.strictEqual(companionFull.variant, "default");
|
||||
|
||||
const companionBle = profile("Heltec_t096_companion_radio_ble_ps_femon");
|
||||
const rakFull = profile("RAK_4631_companion_radio_full");
|
||||
assert.strictEqual(rakFull.logging, "usb-runtime");
|
||||
assert.deepStrictEqual(rakFull.loggingModes, ["none", "usb"]);
|
||||
assert.strictEqual(rakFull.dedicatedUsbLogging, true);
|
||||
assert(!catalog.profiles.some(function (item) {
|
||||
return item.target === "RAK_4631_companion_radio_usb-logging";
|
||||
}));
|
||||
assert(catalog.rows.some(function (item) {
|
||||
return item.target === "RAK_4631_companion_radio_usb-logging";
|
||||
}));
|
||||
|
||||
const companionBle = picker.parseTargetProfile(
|
||||
"Heltec_t096_companion_radio_ble_ps_femon"
|
||||
);
|
||||
assert.strictEqual(companionBle.hardware, "Heltec_t096");
|
||||
assert.strictEqual(companionBle.mode, "ble");
|
||||
assert.strictEqual(companionBle.variant, "ps-femon");
|
||||
assert.strictEqual(
|
||||
picker.humanizeVariant(companionBle.variant),
|
||||
"Power save FEM on"
|
||||
);
|
||||
assert.strictEqual(companionBle.variant, "default");
|
||||
assert(!catalog.profiles.some(function (item) {
|
||||
return item.target === "Heltec_t096_companion_radio_ble_ps_femon";
|
||||
}));
|
||||
assert(catalog.rows.some(function (item) {
|
||||
return item.target === "Heltec_t096_companion_radio_ble_ps_femon";
|
||||
}));
|
||||
|
||||
const fullWifiLogging = picker.parseTargetProfile(
|
||||
"Heltec_v2_companion_radio_wifi-full-logging"
|
||||
@@ -156,7 +175,7 @@ assert.strictEqual(heltecV4Full.target,
|
||||
"heltec_v4_2_v4_3_companion_radio_full_femon");
|
||||
assert.strictEqual(heltecV4Full.hardware, "heltec_v4");
|
||||
assert.strictEqual(heltecV4Full.mode, "full");
|
||||
assert.strictEqual(heltecV4Full.variant, "femon");
|
||||
assert.strictEqual(heltecV4Full.variant, "default");
|
||||
assert.strictEqual(
|
||||
picker.canonicalHardware("heltec_v4_2_v4_3"),
|
||||
"heltec_v4"
|
||||
@@ -174,15 +193,17 @@ const heltecV4FemOff = picker.parseTargetProfile(
|
||||
"heltec_v4_3_companion_radio_ble_femoff"
|
||||
);
|
||||
assert.strictEqual(heltecV4FemOff.hardware, "heltec_v4_3");
|
||||
assert.strictEqual(heltecV4FemOff.variant, "femoff");
|
||||
assert.strictEqual(heltecV4FemOff.variant, "default");
|
||||
|
||||
const heltecV4TftFemOff = picker.parseTargetProfile(
|
||||
"heltec_v4_3_tft_companion_radio_wifi_femoff"
|
||||
);
|
||||
assert.strictEqual(heltecV4TftFemOff.hardware, "heltec_v4_3_tft");
|
||||
assert.strictEqual(heltecV4TftFemOff.variant, "femoff");
|
||||
assert.strictEqual(heltecV4TftFemOff.variant, "default");
|
||||
|
||||
const g2RxBoosted = profile("Station_G2_logging_repeater");
|
||||
const g2RxBoosted = picker.parseTargetProfile(
|
||||
"Station_G2_logging_repeater"
|
||||
);
|
||||
assert.strictEqual(g2RxBoosted.sourceHardware, "Station_G2_logging");
|
||||
assert.strictEqual(g2RxBoosted.hardware, "Station_G2");
|
||||
assert.strictEqual(g2RxBoosted.variant, "rx-boosted");
|
||||
@@ -190,6 +211,12 @@ assert.strictEqual(
|
||||
picker.humanizeVariant(g2RxBoosted.variant),
|
||||
"RX Boosted"
|
||||
);
|
||||
assert(!catalog.profiles.some(function (item) {
|
||||
return item.target === "Station_G2_logging_repeater";
|
||||
}));
|
||||
assert(catalog.rows.some(function (item) {
|
||||
return item.target === "Station_G2_logging_repeater";
|
||||
}));
|
||||
|
||||
const g3Standard = profile("Station_G3_ESP32_repeater");
|
||||
assert.strictEqual(g3Standard.hardware, "Station_G3_ESP32");
|
||||
@@ -200,6 +227,48 @@ assert(catalog.rows.some(function (item) {
|
||||
return item.target === "Station_G3_ESP32_logging_repeater";
|
||||
}));
|
||||
|
||||
assert.deepStrictEqual(
|
||||
picker.omitNrf52TransportsReplacedByFull([
|
||||
{
|
||||
target: "RAK_4631_companion_radio_full",
|
||||
hardware: "RAK_4631",
|
||||
variant: "default",
|
||||
role: "companion",
|
||||
mode: "full",
|
||||
logging: "none",
|
||||
installKinds: ["zip", "uf2"],
|
||||
},
|
||||
{
|
||||
target: "RAK_4631_companion_radio_usb",
|
||||
hardware: "RAK_4631",
|
||||
variant: "default",
|
||||
role: "companion",
|
||||
mode: "usb",
|
||||
logging: "none",
|
||||
installKinds: ["zip", "uf2"],
|
||||
},
|
||||
{
|
||||
target: "RAK_4631_companion_radio_ble",
|
||||
hardware: "RAK_4631",
|
||||
variant: "default",
|
||||
role: "companion",
|
||||
mode: "ble",
|
||||
logging: "none",
|
||||
installKinds: ["zip", "uf2"],
|
||||
},
|
||||
{
|
||||
target: "RAK_4631_companion_radio_usb-logging",
|
||||
hardware: "RAK_4631",
|
||||
variant: "default",
|
||||
role: "companion",
|
||||
mode: "usb",
|
||||
logging: "usb",
|
||||
installKinds: ["zip", "uf2"],
|
||||
},
|
||||
]).map(function (item) { return item.target; }),
|
||||
["RAK_4631_companion_radio_full"]
|
||||
);
|
||||
|
||||
const standardRepeater = profile("Station_G2_repeater");
|
||||
assert.strictEqual(standardRepeater.hardwareFamily, "Station_G2");
|
||||
assert.strictEqual(standardRepeater.role, "repeater");
|
||||
@@ -212,16 +281,19 @@ assert.strictEqual(
|
||||
"Station_G2_repeater-" + family + "-merged.bin"
|
||||
);
|
||||
|
||||
const fullLogging = profile("Station_G2_repeater-full-logging");
|
||||
assert.strictEqual(fullLogging.logging, "usb");
|
||||
const fullLogging = profile("Generic_ESPNOW_repeatr-full-logging");
|
||||
assert.strictEqual(fullLogging.logging, "usb-runtime");
|
||||
assert.deepStrictEqual(fullLogging.loggingModes, ["none", "usb"]);
|
||||
assert.strictEqual(fullLogging.ota, "lora-receiver");
|
||||
assert.strictEqual(fullLogging.feature, "full");
|
||||
assert.strictEqual(fullLogging.variant, "default");
|
||||
|
||||
const mqtt = profile("Station_G2_repeater_observer_mqtt-full");
|
||||
assert.strictEqual(mqtt.logging, "wifi");
|
||||
const mqtt = profile("Station_G2_repeater_observer_mqtt-full-usb-wifi");
|
||||
assert.strictEqual(mqtt.logging, "runtime");
|
||||
assert.deepStrictEqual(mqtt.loggingModes, ["none", "usb", "wifi", "both"]);
|
||||
assert.strictEqual(mqtt.mode, "mqtt");
|
||||
assert.strictEqual(mqtt.ota, "lora-receiver");
|
||||
assert.strictEqual(mqtt.variant, "default");
|
||||
|
||||
const lora = profile(
|
||||
"Station_G2_repeater_lora_ota_no_external_sensors"
|
||||
@@ -275,7 +347,10 @@ const matches = catalog.profiles.filter(function (item) {
|
||||
});
|
||||
});
|
||||
assert.strictEqual(matches.length, 1);
|
||||
assert.strictEqual(matches[0].target, "Station_G2_repeater-full-logging");
|
||||
assert.strictEqual(
|
||||
matches[0].target,
|
||||
"Station_G2_repeater_observer_mqtt-full-usb-wifi"
|
||||
);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
picker.FACET_FIELDS,
|
||||
@@ -371,6 +446,10 @@ assert.deepStrictEqual(
|
||||
picker.facetValues(catalog.profiles, { logging: "wifi" }, "hardware"),
|
||||
["Station_G2"]
|
||||
);
|
||||
assert.deepStrictEqual(
|
||||
picker.facetValues(catalog.profiles, { logging: "both" }, "hardware"),
|
||||
["Station_G2"]
|
||||
);
|
||||
assert.deepStrictEqual(
|
||||
picker.facetValues(
|
||||
catalog.profiles,
|
||||
@@ -382,13 +461,13 @@ assert.deepStrictEqual(
|
||||
},
|
||||
"hardware"
|
||||
),
|
||||
["Station_G2"]
|
||||
["Generic_ESPNOW", "Station_G2"]
|
||||
);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
picker.uniqueValues(catalog.profiles, "hardware").sort(),
|
||||
[
|
||||
"Heltec_t096",
|
||||
"Generic_ESPNOW",
|
||||
"ProMicro",
|
||||
"RAK_4631",
|
||||
"Station_G2",
|
||||
|
||||
@@ -129,6 +129,38 @@ TEST(WebConfigBatch, SetupWiFiHandoffUsesBoundedConnectAndBriefFlushDelays) {
|
||||
EXPECT_EQ(1000U, Batch::kSetupHandoffRebootConfirmMs);
|
||||
}
|
||||
|
||||
TEST(WebConfigBatch, FullUnconfiguredSetupWindowIsAnAbsoluteThirtyMinutes) {
|
||||
const uint32_t started = 1000;
|
||||
EXPECT_EQ(30UL * 60UL * 1000UL, Batch::kFullSetupApWindowMs);
|
||||
EXPECT_FALSE(Batch::unconfiguredSetupWindowExpired(
|
||||
true, false, started + Batch::kFullSetupApWindowMs - 1, started,
|
||||
Batch::kFullSetupApWindowMs));
|
||||
EXPECT_TRUE(Batch::unconfiguredSetupWindowExpired(
|
||||
true, false, started + Batch::kFullSetupApWindowMs, started,
|
||||
Batch::kFullSetupApWindowMs));
|
||||
|
||||
// Saving any SSID converts the node to deployed behavior, which continues
|
||||
// reconnecting and is not subject to the provisioning cutoff.
|
||||
EXPECT_FALSE(Batch::unconfiguredSetupWindowExpired(
|
||||
true, true, started + Batch::kFullSetupApWindowMs, started,
|
||||
Batch::kFullSetupApWindowMs));
|
||||
EXPECT_FALSE(Batch::unconfiguredSetupWindowExpired(
|
||||
false, false, started + Batch::kFullSetupApWindowMs, started,
|
||||
Batch::kFullSetupApWindowMs));
|
||||
EXPECT_FALSE(Batch::unconfiguredSetupWindowExpired(
|
||||
true, false, started + Batch::kFullSetupApWindowMs, started, 0));
|
||||
}
|
||||
|
||||
TEST(WebConfigBatch, FullUnconfiguredSetupWindowSurvivesMillisRollover) {
|
||||
const uint32_t started = std::numeric_limits<uint32_t>::max() - 1000;
|
||||
EXPECT_FALSE(Batch::unconfiguredSetupWindowExpired(
|
||||
true, false, started + Batch::kFullSetupApWindowMs - 1, started,
|
||||
Batch::kFullSetupApWindowMs));
|
||||
EXPECT_TRUE(Batch::unconfiguredSetupWindowExpired(
|
||||
true, false, started + Batch::kFullSetupApWindowMs, started,
|
||||
Batch::kFullSetupApWindowMs));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Result read
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
Reference in new issue
Block a user