feat(bot): Actions commands, multi-trigger, and user GPIO pins

- Auto-Reply Bot gains Actions (!buzz/!gps/!advert) behind a new per-target
  toggle nested under Commands (bot_actions_dm/ch/room); off by default.
- Bot Trigger fields accept comma-separated multiple phrases, matching any
  one fires the reply.
- New user-assignable GPIO feature (Wio Tracker L1): !gpio1..!gpio4 bot
  commands plus a Tools > GPIO screen. Each pin cycles Off/Input/Output;
  GPIO1/GPIO2 (P0.02/P0.29, the nRF52840's AIN0/AIN5) also offer a read-only
  Analog mode via direct SAADC access. GPIO3/GPIO4 (P0.09/P0.10) are the
  chip's NFC1/NFC2 pins, repurposed as plain GPIO via a one-time UICR
  NFCPINS bit-clear in initVariant() (adapted from Adafruit's own
  nfc_to_gpio example) -- confirmed working on real hardware.
- Fix: DM/room reply-prefix ("@[nick] ") stripping happened at the wrong
  layer, hiding the "To:" header on DM replies and leaking the raw prefix
  into room messages' list view; a related mismatch had the history
  scrollbar's sizing pass wrap room messages with the sender name still
  attached, disagreeing with the actual rendered text.

Build-verified: WioTrackerL1_companion_solo_dual and
WioTrackerL1Eink_companion_solo_dual both compile and link clean
(sizeof(NodePrefs) confirmed 2720 via real build, not guessed).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-07-21 20:30:03 +02:00
co-authored by Claude Sonnet 5
parent 7113d34ea1
commit 5bfebc6559
15 changed files with 729 additions and 55 deletions
+16
View File
@@ -54,6 +54,22 @@ public:
// Text reply to an on-device-UI-triggered MyMesh::sendAdminCommand() arrived
// (see AdminScreen). pub_key is the contact's key prefix (>=4 bytes valid).
virtual void onAdminReply(const uint8_t* pub_key, const char* text) { (void)pub_key; (void)text; }
// Bot action commands (!gps/!buzz, see MyMesh::botCommandReply) -- device
// state changes triggered remotely, gated by the bot_actions_* prefs.
// Default no-op so UI variants that don't wire these up just ignore them.
virtual void botSetGPS(bool on) { (void)on; }
virtual void botBuzz(int seconds) { (void)seconds; }
// !gpio1..!gpio4 (idx 1-4). botSetGPIO returns false if the pin isn't
// currently configured as an Output (or the board has none) -- lets the
// bot reply distinguish "set" from "ignored". botGetGPIO returns false if
// the pin is Off/unsupported; on true, fills is_output (current direction)
// and value (live level).
virtual bool botSetGPIO(int idx, bool on) { (void)idx; (void)on; return false; }
virtual bool botGetGPIO(int idx, bool& is_output, bool& value) { (void)idx; (void)is_output; (void)value; return false; }
// Analog read for pins that support it (GPIO1/GPIO2 on Wio Tracker L1 --
// the nRF52840's AIN0/AIN5). Returns false if the pin isn't in Analog mode
// or doesn't support it; on true, fills millivolts with the reading.
virtual bool botGetGPIOAnalog(int idx, int& millivolts) { (void)idx; (void)millivolts; return false; }
// True only when a BLE central is actually bonded/connected. On a dual
// (BLE+USB) interface hasConnection() is always true (USB counts), so use
// this for BLE-specific UI like the pairing-PIN prompt.