mirror of
https://github.com/Colorado-Mesh/meshcore-bot-firmware.git
synced 2026-08-11 16:20:29 +00:00
23 KiB
23 KiB
Stack Research: Firmware-only MeshCore Bot
Checked: 2026-05-14
ITEM-stack-1: Build in upstream MeshCore's Arduino C++/PlatformIO firmware stack
- Recommendation: Build the firmware-only bot in C++ inside the MeshCore companion firmware stack, using Arduino framework and PlatformIO exactly as upstream does. Keep
meshcore-botas behavioral reference only. - Rationale: Current MeshCore describes itself as a compact C++ embedded LoRa/packet-radio library, and current upstream
platformio.iniusesframework = arduinowith architecture bases for ESP32, nRF52, RP2040, and STM32. The Pythonmeshcore-botconnects over serial/BLE/TCP and implements a plugin bot outside the radio; it is useful for command semantics, but not for reducing firmware advert/response behavior on-device. - Confidence: HIGH
- Source: Official docs + local code — https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/README.md; https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/platformio.ini;
/Users/cjvana/Documents/GitHub/meshcore-bot/README.md - Checked: 2026-05-14
- Alternatives rejected: Do not introduce ESP-IDF-only, Zephyr, Rust, embedded Python/JS, Docker, or a VPS-side coordinator as the product stack; they either break MeshCore's cross-device firmware model or preserve the external-bot architecture being replaced.
ITEM-stack-2: Keep MeshCore as an upstream submodule plus Colorado overlay/patch queue
- Recommendation: Structure the Colorado Mesh repo as a wrapper with
upstream/MeshCoreas a pinned git submodule, acolorado/overlay for new source files/config snippets/tests, and a deterministicpatches/orgit-format-patchqueue applied to the submodule during build. Do not keep local edits directly inside the submodule as the only source of truth. - Rationale: The user has selected submodule/patch-base strategy. MeshCore's PlatformIO project expects builds from the MeshCore repo root (
extra_configs = variants/*/platformio.ini, relativebuild_src_filter,build.sh, and variant paths), so the wrapper should stage/apply patches into a worktree and invoke upstreambuild.shfrom there. This preserves an auditable upstream pin while still allowing changes acrossexamples/companion_radio,src/helpers,docs, and selected variant.inifiles. - Confidence: HIGH
- Source: Local code + project decision —
/Users/cjvana/Documents/GitHub/meshcore-bot-fw/.forge/PROJECT.md;/Users/cjvana/Documents/GitHub/MeshCore/platformio.ini;/Users/cjvana/Documents/GitHub/MeshCore/build.sh - Checked: 2026-05-14
- Alternatives rejected: Do not vendor-copy MeshCore into the Colorado repo; upstream is moving. Do not rely on uncommitted submodule edits; they make rebuilds and upstream syncs non-reproducible. Do not place a separate PlatformIO project above MeshCore unless it merely orchestrates the upstream-root build.
ITEM-stack-3: Use current MeshCore main as the baseline, then pin it
- Recommendation: Initialize the submodule from current
meshcore-dev/MeshCoremain, record the exact commit SHA in the Colorado repo, and refresh intentionally. Validate against the local checkout only as read-only reconnaissance. - Rationale: The local MeshCore checkout is usable for inspection, but current upstream has evolved: current upstream
platformio.inihas LoRa defaultsLORA_FREQ=869.618,LORA_BW=62.5,LORA_SF=8, adds-D ESP32_PLATFORM, and nRF52 extra scripts includecreate-uf2.pyandpatch_bluefruit.py, while the local checkout differs. Starting from current upstream reduces protocol/build drift. - Confidence: MEDIUM
- Source: Official source + local git — https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/platformio.ini;
/Users/cjvana/Documents/GitHub/MeshCorecommit6b52fb32 - Checked: 2026-05-14
- Alternatives rejected: Do not base implementation solely on the stale local tree; it may miss current companion protocol and build changes. Do not float the submodule without a pinned commit; firmware builds need reproducibility.
ITEM-stack-4: Preserve upstream dependency/platform pins for the first bot build
- Recommendation: Keep upstream platform and library pins initially:
platformio/espressif32@6.11.0for ESP32 Arduino builds,nordicnrf52withframework-arduinoadafruitnrf52 @ 1.10700.0for nRF52, RadioLib^7.3.0, Crypto^0.4.0, RTClib^2.1.3, Melopero RV3028^1.1.0, CayenneLPP1.6.1, anddensaugeo/base64 @ ~1.4.0in companion targets. - Rationale: The first risk is firmware behavior, not dependency modernization.
platformio/espressif32@6.11.0with Arduino uses Arduino-ESP32 2.0.17, and RadioLib 7.3.0 is a 2025 release although newer RadioLib releases exist. Upgrading radio/platform dependencies while adding bot logic would confound failures across ESP32 and nRF52. - Confidence: HIGH
- Source: Official docs/search + upstream source — https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/platformio.ini; https://github.com/platformio/platform-espressif32/blob/v6.11.0/platform.json; https://github.com/jgromes/RadioLib/releases/tag/7.3.0; https://docs.platformio.org/en/latest/librarymanager/dependencies.html
- Checked: 2026-05-14
- Alternatives rejected: Do not upgrade to Arduino-ESP32 3.x, latest RadioLib, or custom nRF framework packages until baseline bot patches build and run; dependency churn should be a separate phase.
ITEM-stack-5: Add bot logic as small fixed-storage companion helpers
- Recommendation: Implement the bot as small C++ helper classes called by
examples/companion_radio/MyMesh, with fixed-size arrays/ring buffers and compile-time feature flags such asCMESH_BOT_ENABLED,CMESH_BOT_MAX_PENDING, andCMESH_BOT_MAX_KNOWN_BOTS. - Rationale: Companion
MyMeshalready owns the required hooks: private DM receive (onMessageRecv), group channel receive (onChannelMessageRecv), control/raw receive, channel lookup, contact lookup, and group/direct send (sendGroupMessage,sendMessage). Upstream contribution guidance says to keep embedded code concise and avoid dynamic allocation except during setup/begin. A helper object avoids a large framework while keeping Colorado logic reviewable. - Confidence: HIGH
- Source: Local code + upstream README —
/Users/cjvana/Documents/GitHub/MeshCore/examples/companion_radio/MyMesh.h;/Users/cjvana/Documents/GitHub/MeshCore/src/helpers/BaseChatMesh.h; https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/README.md - Checked: 2026-05-14
- Alternatives rejected: Do not port the Python plugin loader, SQLite-backed stats, API clients, or dynamic command registry to firmware. Do not create a general embedded scripting runtime.
ITEM-stack-6: Handle only firmware-feasible bot behavior in phase 1
- Recommendation: Phase 1 should implement deterministic local commands and routing policy:
ping,test, compacthelp,cmd, simpledice/roll, path/channel echo where already available, passive suppression/listen-before-answer, #bot/#testing routing, private DM replies, and #emergency forwarding to Public. Defer weather, AQI, satellite, sports, jokes from web APIs, repeater database management, and web viewer features. - Rationale:
meshcore-botincludes many network/API/database features that assume Python, internet, filesystem logs, and async plugins. Firmware bot value is local decentralized operation and duplicate suppression. Keeping responses short also fits MeshCoreMAX_TEXT_LEN = 10*CIPHER_BLOCK_SIZE = 160bytes and group messages include a sender-name prefix. - Confidence: HIGH
- Source: Local code/docs —
/Users/cjvana/Documents/GitHub/meshcore-bot/README.md;/Users/cjvana/Documents/GitHub/MeshCore/src/helpers/BaseChatMesh.h;/Users/cjvana/Documents/GitHub/MeshCore/docs/payloads.md - Checked: 2026-05-14
- Alternatives rejected: Do not attempt feature parity with host-side
meshcore-bot; API-backed commands are not off-grid and would expand flash/RAM/storage unnecessarily.
ITEM-stack-7: Use MeshCore group/private message APIs for bot traffic, not new transport timing knobs
- Recommendation: Send normal bot replies through existing
sendMessage/sendGroupMessagepaths and implement bot-specific delay/suppression above the radio layer. Use configured channel names/hash lookup to restrict normal traffic to private DMs, #bot, and #testing, and special-case #emergency to publish anEMERGENCY MESSAGE FROM <user>announcement to Public. - Rationale: MeshCore already parses private text and group text into
onMessageRecv/onChannelMessageRecv, and packet docs define group text as encrypted channel payload with<sender name>: <message body>. The project decision explicitly says not to repurpose lower-layer MeshCoretxdelay,direct.txdelay, orrxdelayas bot election controls. - Confidence: HIGH
- Source: Local code/docs + project decision —
/Users/cjvana/Documents/GitHub/meshcore-bot-fw/.forge/PROJECT.md;/Users/cjvana/Documents/GitHub/MeshCore/src/helpers/BaseChatMesh.cpp;/Users/cjvana/Documents/GitHub/MeshCore/docs/payloads.md - Checked: 2026-05-14
- Alternatives rejected: Do not route normal bot chatter on Public. Do not use lower-layer TX/RX timing knobs as the primary coordinator; it risks affecting mesh behavior beyond bot replies.
ITEM-stack-8: Build representative firmware with upstream build.sh before expanding
- Recommendation: Use upstream
build.shfrom inside the patched MeshCore worktree. During development, build onlyHeltec_v3_companion_radio_usb,Heltec_v3_companion_radio_ble,RAK_4631_companion_radio_usb, andRAK_4631_companion_radio_ble; after those pass, runbuild.sh build-companion-firmwaresin CI. - Rationale: Upstream
build.sh build-firmware <env>injects firmware version/build date, runspio run -e, creates merged ESP32.binimages, creates nRF52.uf2, and writes outputs toout/. The representative set covers ESP32-S3 and nRF52840 plus USB/BLE companion variants without paying the cost of every supported board during inner-loop development. - Confidence: HIGH
- Source: Local CI/build scripts —
/Users/cjvana/Documents/GitHub/MeshCore/build.sh;/Users/cjvana/Documents/GitHub/MeshCore/.github/workflows/build-companion-firmwares.yml;/Users/cjvana/Documents/GitHub/MeshCore/.github/actions/setup-build-environment/action.yml - Checked: 2026-05-14
- Alternatives rejected: Do not hand-maintain an independent board matrix first; upstream environment suffixes and artifact logic already encode release behavior. Do not wait for all companion boards before validating the two requested representatives.
ITEM-stack-9: Heltec v3 companion target is comfortably feasible
- Recommendation: Treat Heltec v3 as the easiest first target. Use current upstream
Heltec_v3_companion_radio_usbandHeltec_v3_companion_radio_bleenvs unchanged except for the bot feature flag/overlay patch. - Rationale: Current upstream Heltec v3 extends
Heltec_lora32_v3, uses boardesp32-s3-devkitc-1, ESP32-S3 Arduino, SSD1306 UI,MAX_CONTACTS=350,MAX_GROUP_CHANNELS=40, and BLE addsOFFLINE_QUEUE_SIZE=256. PlatformIO'sesp32-s3-devkitc-1board uses 8 MB flash withdefault_8MB.csv; app0/app1 are 0x330000 each (3,342,336 bytes), SPIFFS is 0x180000 (1,572,864 bytes). Heltec official specs confirm ESP32-S3FN8/ESP32-S3N8 with 8 MB flash and no PSRAM. - Confidence: HIGH
- Source: Official source/docs — https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/variants/heltec_v3/platformio.ini; https://raw.githubusercontent.com/platformio/platform-espressif32/master/boards/esp32-s3-devkitc-1.json; https://raw.githubusercontent.com/espressif/arduino-esp32/master/tools/partitions/default_8MB.csv; https://docs.heltec.cn/en/node/esp32/wifi_lora_32/index.html; https://resource.heltec.cn/download/WiFi_LoRa_32_V3/HTIT-WB32LA_V3.2.pdf
- Checked: 2026-05-14
- Alternatives rejected: Do not optimize for Heltec v3 storage first; its app and filesystem margins are much larger than RAK4631's. Do not depend on PSRAM; Heltec v3 does not provide it.
ITEM-stack-10: RAK4631 is feasible but is the storage/RAM gatekeeper
- Recommendation: Treat RAK4631 BLE companion as the gating target. Keep the firmware bot under roughly 20 KB additional flash and 2 KB additional static RAM until measured builds prove more margin.
- Rationale: Current upstream RAK4631 companion USB/BLE extend
rak4631, useboards/nrf52840_s140_v6_extrafs.ld, and explicitly setboard_upload.maximum_size = 712704. The extra-FS linker gives an app FLASH region of 712,704 bytes and RAM region of 237,568 bytes. RAK's raw nRF52840 has 1 MB flash/256 KB RAM, but SoftDevice, bootloader/settings, and extra filesystem reserve much of that; the companion app region, not raw flash, is the practical limit. - Confidence: HIGH
- Source: Official source/docs — https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/variants/rak4631/platformio.ini; https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/boards/rak4631.json; https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/boards/nrf52840_s140_v6_extrafs.ld; https://docs.rakwireless.com/product-categories/wisblock/rak4631/overview/; https://www.nordicsemi.com/Products/nRF52840
- Checked: 2026-05-14
- Alternatives rejected: Do not assume the full 1 MB nRF52840 flash is available to the app. Do not store large response tables or logs in RAK4631 internal flash without measuring filesystem pressure.
ITEM-stack-11: Firmware bot storage budget is small enough if responses stay static and ephemeral
- Recommendation: Budget the phase-1 firmware bot at approximately 10-25 KB flash, 0.5-2 KB RAM, and 0-4 KB persistent storage. Require CI to report binary size deltas for Heltec v3 and RAK4631 on every PR.
- Rationale: A minimal command parser, static command table, short static response strings, a small known-bot/suppression table, and 4-8 pending response records fit easily: example estimate is 3-8 KB
.text, 2-10 KB.rodatadepending on help text, 512-1536 B.bssfor suppression state, and <512 B stack per invocation if implemented without large local buffers. MeshCore already carries large state for companion mode: approximate struct sizing from source givesContactInfo~184 B,ChannelDetails~56 B, offline frame ~173 B, andPacket~260 B; existingMAX_CONTACTS=350,MAX_GROUP_CHANNELS=40, and BLEOFFLINE_QUEUE_SIZE=256dominate RAM more than the bot should. This estimate could not be verified by compiling becausepiois not installed in the local environment. - Confidence: MEDIUM
- Source: Local source analysis —
/Users/cjvana/Documents/GitHub/MeshCore/src/helpers/ContactInfo.h;/Users/cjvana/Documents/GitHub/MeshCore/src/helpers/ChannelDetails.h;/Users/cjvana/Documents/GitHub/MeshCore/src/Packet.h;/Users/cjvana/Documents/GitHub/MeshCore/examples/companion_radio/MyMesh.h; local command result:pio: command not found - Checked: 2026-05-14
- Alternatives rejected: Do not embed full help prose, translation files, jokes, channel databases, repeater databases, web/API clients, or persistent usage stats in firmware phase 1; those could turn a <25 KB feature into a storage problem.
ITEM-stack-12: Storage feasibility estimate by representative target
- Recommendation: Proceed with firmware-only bot if the first implementation stays within the conservative budget below; block or trim features if measured RAK4631 BLE app flash delta exceeds 25 KB or static RAM delta exceeds 2 KB.
- Rationale: Heltec v3 has about 3.34 MB per OTA app slot and 1.57 MB SPIFFS under the default 8 MB partition table, so a 10-25 KB bot is negligible (<0.8% of one app slot). RAK4631 companion has a 712,704-byte app region and 237,568-byte RAM region; the same bot is ~1.4-3.5% of the app region and ~0.2-0.9% of RAM. Persistent config should be a few hundred bytes; even a 4 KB settings/log reserve is reasonable but should be optional. The unknown is current baseline binary size, not the expected bot delta, because no local PlatformIO build artifacts exist.
- Confidence: MEDIUM
- Source: Official docs + local analysis — https://raw.githubusercontent.com/espressif/arduino-esp32/master/tools/partitions/default_8MB.csv; https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/boards/nrf52840_s140_v6_extrafs.ld; https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/variants/rak4631/platformio.ini;
/Users/cjvana/Documents/GitHub/MeshCore/examples/companion_radio/MyMesh.h - Checked: 2026-05-14
- Alternatives rejected: Do not declare final binary margin until PlatformIO builds run; use this as feasibility guidance, then replace with measured
.text/.data/.bssand firmware size deltas.
ITEM-stack-13: Add a size-reporting CI step before feature growth
- Recommendation: Add a wrapper command such as
scripts/build-representative.shthat applies patches, runs the four representative envs, captures PlatformIO RAM/flash usage output, records artifact byte sizes, and fails on configurable bot-delta thresholds once a baseline is established. - Rationale: The user's explicit question is storage feasibility. PlatformIO normally reports memory usage per environment, but local
piois unavailable and there are no existing.pioartifacts. CI size reports make the feasibility estimate concrete and keep future feature creep visible, especially on RAK4631 BLE. - Confidence: HIGH
- Source: Local build scripts + official PlatformIO behavior —
/Users/cjvana/Documents/GitHub/MeshCore/build.sh; https://docs.platformio.org/en/latest/core/userguide/cmd_run.html - Checked: 2026-05-14
- Alternatives rejected: Do not rely on source-only estimates after code exists. Do not run only Heltec v3; RAK4631 is the constrained representative.
ITEM-stack-14: Use host-side Python only for tests and behavioral fixtures
- Recommendation: Keep Python in the repo only for development tooling: generating patch worktrees, golden command-response fixtures, fake MeshCore frames, and CI parsing of size reports. Firmware behavior should not depend on Python at runtime.
- Rationale:
meshcore-botis rich behavioral prior art: command keywords, rate limits, channel policy, and response wording. But its async plugin loader, HTTP API clients, SQLite/database managers, web viewer, and serial/BLE/TCP connection code cannot run inside companion firmware. Host-side tests can still prevent regressions when translating selected behavior to C++. - Confidence: HIGH
- Source: Local code —
/Users/cjvana/Documents/GitHub/meshcore-bot/modules/commands;/Users/cjvana/Documents/GitHub/meshcore-bot/modules/command_manager.py;/Users/cjvana/Documents/GitHub/meshcore-bot/modules/message_handler.py - Checked: 2026-05-14
- Alternatives rejected: Do not make the firmware call out to a local Python service for normal bot responses; that recreates the coordinator dependency.
Confidence Summary
| Item ID | Level | Source Type | URL/Reference |
|---|---|---|---|
| ITEM-stack-1 | HIGH | Official docs + Local code | https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/README.md; https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/platformio.ini; /Users/cjvana/Documents/GitHub/meshcore-bot/README.md |
| ITEM-stack-2 | HIGH | Local code + Project decision | /Users/cjvana/Documents/GitHub/meshcore-bot-fw/.forge/PROJECT.md; /Users/cjvana/Documents/GitHub/MeshCore/platformio.ini; /Users/cjvana/Documents/GitHub/MeshCore/build.sh |
| ITEM-stack-3 | MEDIUM | Official source + Local git | https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/platformio.ini; /Users/cjvana/Documents/GitHub/MeshCore |
| ITEM-stack-4 | HIGH | Official docs/search + Upstream source | https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/platformio.ini; https://github.com/platformio/platform-espressif32/blob/v6.11.0/platform.json; https://github.com/jgromes/RadioLib/releases/tag/7.3.0; https://docs.platformio.org/en/latest/librarymanager/dependencies.html |
| ITEM-stack-5 | HIGH | Local code + Upstream README | /Users/cjvana/Documents/GitHub/MeshCore/examples/companion_radio/MyMesh.h; /Users/cjvana/Documents/GitHub/MeshCore/src/helpers/BaseChatMesh.h; https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/README.md |
| ITEM-stack-6 | HIGH | Local code/docs | /Users/cjvana/Documents/GitHub/meshcore-bot/README.md; /Users/cjvana/Documents/GitHub/MeshCore/src/helpers/BaseChatMesh.h; /Users/cjvana/Documents/GitHub/MeshCore/docs/payloads.md |
| ITEM-stack-7 | HIGH | Local code/docs + Project decision | /Users/cjvana/Documents/GitHub/meshcore-bot-fw/.forge/PROJECT.md; /Users/cjvana/Documents/GitHub/MeshCore/src/helpers/BaseChatMesh.cpp; /Users/cjvana/Documents/GitHub/MeshCore/docs/payloads.md |
| ITEM-stack-8 | HIGH | Local CI/build scripts | /Users/cjvana/Documents/GitHub/MeshCore/build.sh; /Users/cjvana/Documents/GitHub/MeshCore/.github/workflows/build-companion-firmwares.yml |
| ITEM-stack-9 | HIGH | Official source/docs | https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/variants/heltec_v3/platformio.ini; https://raw.githubusercontent.com/platformio/platform-espressif32/master/boards/esp32-s3-devkitc-1.json; https://raw.githubusercontent.com/espressif/arduino-esp32/master/tools/partitions/default_8MB.csv; https://docs.heltec.cn/en/node/esp32/wifi_lora_32/index.html |
| ITEM-stack-10 | HIGH | Official source/docs | https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/variants/rak4631/platformio.ini; https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/boards/rak4631.json; https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/boards/nrf52840_s140_v6_extrafs.ld; https://docs.rakwireless.com/product-categories/wisblock/rak4631/overview/ |
| ITEM-stack-11 | MEDIUM | Local source analysis | /Users/cjvana/Documents/GitHub/MeshCore/src/helpers/ContactInfo.h; /Users/cjvana/Documents/GitHub/MeshCore/src/Packet.h; local pio availability check |
| ITEM-stack-12 | MEDIUM | Official docs + Local analysis | https://raw.githubusercontent.com/espressif/arduino-esp32/master/tools/partitions/default_8MB.csv; https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/boards/nrf52840_s140_v6_extrafs.ld; https://raw.githubusercontent.com/meshcore-dev/MeshCore/main/variants/rak4631/platformio.ini |
| ITEM-stack-13 | HIGH | Local build scripts + Official docs | /Users/cjvana/Documents/GitHub/MeshCore/build.sh; https://docs.platformio.org/en/latest/core/userguide/cmd_run.html |
| ITEM-stack-14 | HIGH | Local code | /Users/cjvana/Documents/GitHub/meshcore-bot/modules/commands; /Users/cjvana/Documents/GitHub/meshcore-bot/modules/command_manager.py |