Subject: RAK4631 companion-radio builds (USB/BLE/Ethernet) silently enter CLI Rescue mode on boards with no physical button
Hi,
I ran into a connectivity bug building RAK_4631_companion_radio_ethernet (and confirmed it also affects _usb and _ble) for a WisBlock RAK4631 stack with GPS, LCD, Ethernet (RAK13800), and PoE — no physical pushbutton (only the reset button).
Symptom: The device accepts a connection at the transport level (BLE pairs, USB enumerates, TCP connects and I could even see the raw socket accept the data), but never responds to any companion protocol frame — not even CMD_APP_START. Client apps (I tested with Meshy, and confirmed with a hand-crafted raw frame + raw serial debug log) see a connection that just times out and gets dropped, with no error on the device side under normal builds.
Root cause: variants/rak4631/platformio.ini sets -D PIN_USER_BTN=9 -D PIN_USER_BTN_ANA=31 for all three RAK_4631_companion_radio_* envs. examples/companion_radio/ui-new/UITask.cpp's handleLongPress() treats a long-press on either of those pins within the first 8 seconds of boot as a request to enter CLI Rescue mode (MyMesh::enterCLIRescue()). On hardware with no button physically wired to those pins, they float:
PIN_USER_BTN_ANA (31) is read with a bare analogRead(pin) < 20 threshold and no pull reference at all — a floating ADC input on the nRF52840 drifts easily below that.
PIN_USER_BTN (9) is at least configured INPUT_PULLUP, but still misreads as held on this hardware (possibly not a truly free GPIO on this WisBlock IO-slot pin layout — didn't fully trace the electrical cause).
Once _cli_rescue is set, MyMesh::loop() (examples/companion_radio/MyMesh.cpp, ~line 2232) calls checkCLIRescueCmd() instead of checkSerialInterface() — permanently, for the rest of that boot. Since checkSerialInterface() is the transport-agnostic entry point that drains MultiSerialInterface, this breaks USB, BLE, and Ethernet identically, regardless of which one you're trying to debug. The only visible symptom is a boot-time Serial.println("========= CLI Rescue ========="), which is invisible on the USB build specifically (Serial doubles as the companion channel there) and easy to miss elsewhere since nothing else logs it.
Workaround (confirmed working): removed PIN_USER_BTN/PIN_USER_BTN_ANA from all three RAK_4631_companion_radio_* envs. Confirmed via a manual CMD_APP_START → RESP_CODE_SELF_INFO round trip over raw TCP, and then a full working sync in Meshy over Ethernet, USB, and BLE.
Suggested upstream fixes (any of these would help):
Require a debounced, multi-sample confirmation before honoring a long-press as a rescue trigger, rather than a single analogRead() against a bare threshold with no pull reference.
Document, in the platformio.ini comments or board docs, which physical enclosure/button wiring the RAK_4631_companion_radio_* envs assume — they read as generic "any RAK4631" targets but silently require a specific button.
Log CLI Rescue entry somewhere visible across all transports (not just a Serial.println that's actively dangerous to rely on on the USB build), so this doesn't look like a dead/bricked device.
Consider not wiring PIN_USER_BTN_ANA to a WisBlock IO-slot pin without a way to detect whether anything's actually connected there.
Happy to open this as a GitHub issue/PR with the platformio.ini diff if useful.
Thanks for the project — really appreciate the work that went into it.
Subject: RAK4631 companion-radio builds (USB/BLE/Ethernet) silently enter CLI Rescue mode on boards with no physical button
Hi,
I ran into a connectivity bug building RAK_4631_companion_radio_ethernet (and confirmed it also affects _usb and _ble) for a WisBlock RAK4631 stack with GPS, LCD, Ethernet (RAK13800), and PoE — no physical pushbutton (only the reset button).
Symptom: The device accepts a connection at the transport level (BLE pairs, USB enumerates, TCP connects and I could even see the raw socket accept the data), but never responds to any companion protocol frame — not even CMD_APP_START. Client apps (I tested with Meshy, and confirmed with a hand-crafted raw frame + raw serial debug log) see a connection that just times out and gets dropped, with no error on the device side under normal builds.
Root cause: variants/rak4631/platformio.ini sets -D PIN_USER_BTN=9 -D PIN_USER_BTN_ANA=31 for all three RAK_4631_companion_radio_* envs. examples/companion_radio/ui-new/UITask.cpp's handleLongPress() treats a long-press on either of those pins within the first 8 seconds of boot as a request to enter CLI Rescue mode (MyMesh::enterCLIRescue()). On hardware with no button physically wired to those pins, they float:
PIN_USER_BTN_ANA (31) is read with a bare analogRead(pin) < 20 threshold and no pull reference at all — a floating ADC input on the nRF52840 drifts easily below that.
PIN_USER_BTN (9) is at least configured INPUT_PULLUP, but still misreads as held on this hardware (possibly not a truly free GPIO on this WisBlock IO-slot pin layout — didn't fully trace the electrical cause).
Once _cli_rescue is set, MyMesh::loop() (examples/companion_radio/MyMesh.cpp, ~line 2232) calls checkCLIRescueCmd() instead of checkSerialInterface() — permanently, for the rest of that boot. Since checkSerialInterface() is the transport-agnostic entry point that drains MultiSerialInterface, this breaks USB, BLE, and Ethernet identically, regardless of which one you're trying to debug. The only visible symptom is a boot-time Serial.println("========= CLI Rescue ========="), which is invisible on the USB build specifically (Serial doubles as the companion channel there) and easy to miss elsewhere since nothing else logs it.
Workaround (confirmed working): removed PIN_USER_BTN/PIN_USER_BTN_ANA from all three RAK_4631_companion_radio_* envs. Confirmed via a manual CMD_APP_START → RESP_CODE_SELF_INFO round trip over raw TCP, and then a full working sync in Meshy over Ethernet, USB, and BLE.
Suggested upstream fixes (any of these would help):
Require a debounced, multi-sample confirmation before honoring a long-press as a rescue trigger, rather than a single analogRead() against a bare threshold with no pull reference.
Document, in the platformio.ini comments or board docs, which physical enclosure/button wiring the RAK_4631_companion_radio_* envs assume — they read as generic "any RAK4631" targets but silently require a specific button.
Log CLI Rescue entry somewhere visible across all transports (not just a Serial.println that's actively dangerous to rely on on the USB build), so this doesn't look like a dead/bricked device.
Consider not wiring PIN_USER_BTN_ANA to a WisBlock IO-slot pin without a way to detect whether anything's actually connected there.
Happy to open this as a GitHub issue/PR with the platformio.ini diff if useful.
Thanks for the project — really appreciate the work that went into it.