Complete upstream transport integration and regression coverage

This commit is contained in:
mikecarper committed 2026-09-15 21:08:10 -07:00
1 parent 4d34448602
commit 439dc7da3c
10 files changed
+124 -3

No files matched your search

+1
View File
@@ -82,6 +82,7 @@ jobs:
sudo apt-get install -y libssl-dev
python3 -B test/test_companion_tx_routing.py -v
python3 -B test/test_companion_discovery.py -v
python3 -B test/test_pico_ble_queues.py -v
python3 -B test/test_companion_preferences_transaction.py -v
python3 -B test/test_companion_radio_settings_transaction.py -v
python3 -B test/test_companion_prefs_transactions.py -v
+14
View File
@@ -6841,6 +6841,13 @@ bool MyMesh::applyAndSaveBluetoothMac(const char* value, char* reply,
mode = mesh::companion::BLUETOOTH_MAC_CUSTOM;
}
#if defined(RP2040_PLATFORM)
if (mode != mesh::companion::BLUETOOTH_MAC_DEFAULT) {
snprintf(reply, reply_size, "Error: Bluetooth address overrides are not supported on Pico W");
return false;
}
#endif
if (!saveBluetoothMac(mode, address)) {
snprintf(reply, reply_size, "Error: Bluetooth MAC save failed");
return false;
@@ -6913,6 +6920,13 @@ bool MyMesh::applyAndSaveBluetoothStealth(const char* value, char* reply,
return false;
}
#if defined(RP2040_PLATFORM)
if (strcmp(value, "on") == 0) {
snprintf(reply, reply_size, "Error: Bluetooth stealth is not supported on Pico W");
return false;
}
#endif
const uint8_t previous_mode = _prefs.bluetooth_stealth_mode;
const uint8_t previous_type = _prefs.bluetooth_stealth_peer_type;
uint8_t previous_peer[mesh::companion::BLUETOOTH_MAC_BYTES];
+1 -1
View File
@@ -2799,7 +2799,7 @@ void setup() {
#endif
// Load WiFi credentials without starting the radio.
#ifdef WIFI_SSID
#if defined(ESP32) && defined(WIFI_SSID)
loadCompanionWiFiCredentials();
#endif
+3
View File
@@ -112,6 +112,9 @@ lib_deps = ${arduino_base.lib_deps}
ricmoo/QRCode @ 0.0.1
build_src_filter = ${arduino_base.build_src_filter}
+<helpers/ui/DisplayDriver.cpp>
; Shared WiFi transport moved out of esp32/ upstream. Keep it available to
; this fork's WiFi/MQTT and synthesized Full profiles as well.
+<helpers/wifi/*.cpp>
+<helpers/esp32/WebConfigServer.cpp>
+<helpers/esp32/PortableErrorStrings.cpp>
+<helpers/esp32/WiFiOtaSeeder.cpp>
+11
View File
@@ -172,9 +172,20 @@ bool SerialBLEInterface::isConnected() const {
}
bool SerialBLEInterface::isWriteBusy() const {
BluetoothLock lock;
return send_queue_len >= (FRAME_QUEUE_SIZE * 2 / 3);
}
bool SerialBLEInterface::isReadBusy() const {
BluetoothLock lock;
return recv_queue_len > 0;
}
bool SerialBLEInterface::hasPendingIO() const {
BluetoothLock lock;
return recv_queue_len > 0 || send_queue_len > 0 || _tx_pending;
}
size_t SerialBLEInterface::writeFrame(const uint8_t src[], size_t len) {
if (len == 0 || len > MAX_FRAME_SIZE) {
BLE_DEBUG_PRINTLN("writeFrame(), frame too big, len=%u", (unsigned)len);
+3 -1
View File
@@ -51,7 +51,7 @@ public:
/**
* init the BLE interface.
* @param prefix a prefix for the device name
* @param name IN/OUT - a name for the device (combined with prefix). If "@@MAC", is modified and returned
* @param name a name for the device (combined with prefix), or "@@MAC"
* @param pin_code the BLE security pin
*/
bool begin(const char* prefix, const char* name, uint32_t pin_code,
@@ -70,7 +70,9 @@ public:
void disable() override;
bool isEnabled() const override { return _isEnabled; }
bool isConnected() const override;
bool isReadBusy() const override;
bool isWriteBusy() const override;
bool hasPendingIO() const override;
size_t writeFrame(const uint8_t src[], size_t len) override;
size_t checkRecvFrame(uint8_t dest[]) override;
};
+17
View File
@@ -41,6 +41,23 @@ class BluetoothMacContractTests(unittest.TestCase):
self.nrf_source,
)
def test_pico_rejects_unsupported_identity_policies_before_saving(self):
pico = source("src/helpers/rp2040/SerialBLEInterface.cpp")
self.assertIn(
"if (custom_address || clear_bonds || stealth_pair_once || bonded_only_peer) return false;",
pico,
)
mac = self.mesh[self.mesh.index("bool MyMesh::applyAndSaveBluetoothMac("):
self.mesh.index("void MyMesh::formatBluetoothMacStatus(")]
self.assertLess(mac.index("#if defined(RP2040_PLATFORM)"),
mac.index("saveBluetoothMac(mode, address)"))
self.assertIn("mode != mesh::companion::BLUETOOTH_MAC_DEFAULT", mac)
stealth = self.mesh[self.mesh.index("bool MyMesh::applyAndSaveBluetoothStealth("):
self.mesh.index("void MyMesh::formatBluetoothStealthStatus(")]
self.assertLess(stealth.index("#if defined(RP2040_PLATFORM)"),
stealth.index("setCompanionBluetoothStealth(_prefs,"))
self.assertIn('if (strcmp(value, "on") == 0)', stealth)
def test_esp32_supports_nimble_and_bluedroid(self):
self.assertIn("BLEDevice::setOwnAddr(native_address)", self.esp_source)
self.assertIn("BLEDevice::setOwnAddrType(BLE_OWN_ADDR_RANDOM)", self.esp_source)
+3 -1
View File
@@ -191,7 +191,9 @@ int main() {
enum_start = ui.index(" enum HomePage {")
enum = ui[enum_start : ui.index("\n };", enum_start)]
self.assertIn(
"#if UI_WIFI_SETUP_HOME_PAGE == 1\n WIFI_SETUP,\n#endif\n Count",
"#if UI_WIFI_SETUP_HOME_PAGE == 1\n WIFI_SETUP,\n#endif\n"
"#if !(defined(UI_NO_DISCOVER_SCREEN) && (UI_NO_DISCOVER_SCREEN + 0 != 0))\n"
" DISCOVERY,\n#endif\n Count",
enum,
)
self.assertIn("_page == HomePage::WIFI_SETUP", ui)
@@ -156,6 +156,17 @@ TEST(MQTTPresets, WcmeshIsJwtWithIsrgRootX1) {
EXPECT_FALSE(mqttPresetUsesDevicePubkeyUsername(p));
}
TEST(MQTTPresets, BsmeshIsJwtWithIsrgRootX1) {
const MQTTPresetDef* p = findMQTTPreset("bsmesh");
ASSERT_NE(nullptr, p);
EXPECT_EQ(MQTT_AUTH_JWT, p->auth_type);
EXPECT_EQ(MQTT_TOPIC_MESHCORE, p->topic_style);
EXPECT_STREQ("wss://mqtt.bsmesh.de:8885", p->server_url);
EXPECT_STREQ("mqtt.bsmesh.de", p->jwt_audience);
EXPECT_EQ(ISRG_ROOT_X1, p->ca_cert);
EXPECT_FALSE(mqttPresetNeedsSlotCredentials(p));
}
// ---- slot count constants -------------------------------------------------
TEST(MQTTPresets, SlotCountsAreSane) {
+60
View File
@@ -0,0 +1,60 @@
"""Execute Pico W's production queue predicates used by companion sleep control."""
from pathlib import Path
import subprocess
import tempfile
import unittest
from test_radio_receive_contract import method
ROOT = Path(__file__).resolve().parents[1]
class PicoBleQueueTests(unittest.TestCase):
def test_pending_frames_keep_the_transport_awake_below_high_water(self):
source = (ROOT / 'src/helpers/rp2040/SerialBLEInterface.cpp').read_text()
methods = '\n'.join(method(source, 'bool SerialBLEInterface::' + name + '() const')
for name in ('isReadBusy', 'isWriteBusy', 'hasPendingIO'))
code = r'''
#include <cassert>
#define FRAME_QUEUE_SIZE 8
static int locks = 0;
struct BluetoothLock {
BluetoothLock() { ++locks; }
~BluetoothLock() { --locks; }
};
struct SerialBLEInterface {
unsigned recv_queue_len = 0, send_queue_len = 0;
bool _tx_pending = false;
bool isReadBusy() const;
bool isWriteBusy() const;
bool hasPendingIO() const;
};
@METHODS@
int main() {
SerialBLEInterface transport;
for (unsigned rx = 0; rx <= FRAME_QUEUE_SIZE; ++rx) {
for (unsigned tx = 0; tx <= FRAME_QUEUE_SIZE; ++tx) {
for (unsigned pending = 0; pending <= 1; ++pending) {
transport.recv_queue_len = rx;
transport.send_queue_len = tx;
transport._tx_pending = pending;
assert(transport.isReadBusy() == (rx != 0));
assert(transport.isWriteBusy() == (tx >= 5));
assert(transport.hasPendingIO() == (rx || tx || pending));
assert(locks == 0);
}
}
}
}
'''.replace('@METHODS@', methods)
for name in ('isReadBusy', 'isWriteBusy', 'hasPendingIO'):
self.assertIn('BluetoothLock lock;', method(source, 'bool SerialBLEInterface::' + name))
with tempfile.TemporaryDirectory() as directory:
path = Path(directory)
(path / 'test.cpp').write_text(code)
subprocess.run(['g++', '-std=c++17', '-fsanitize=address,undefined',
'-fno-pie', '-no-pie', str(path / 'test.cpp'), '-o', str(path / 'test')], check=True)
subprocess.run([str(path / 'test')], check=True)
if __name__ == '__main__':
unittest.main()