v0.4.1 — MeshCore 1.16, full companion command set, message-sync fixes
MeshCore 1.16 upgrade, the full companion command set (status/trace, anon-req, explicit-unscoped), and companion message-sync fixes. Update over WiFi (Admin → WiFi → Check for updates) or via the web flasher.
Added
-
Manage rooms and channels from the companion app. The companion protocol gained the standard write/action
commands the official MeshCore app uses, so things that previously failed against MCLite now work:- Room login (
CMD_SEND_LOGIN): log into a configured room or repeater from the app. A blank password field
uses the password already in the device config, and a wrong password instantly retries with the stored one.
Thanks to the reporters (#32). - Add / remove channels (
CMD_SET_CHANNEL): join a Public, hashtag, or private channel — or remove one —
from the app. Adding applies instantly with no reboot — the channel is usable right away and its share QR
shows the real key, not zeros, with the session staying connected. Removing a channel still reboots to
apply (a known limitation — MeshCore offers no way to remove a channel from the running radio, so the device
rebuilds its channel table from config at boot; the app reconnects on its own). Gated by the
permissions.conversation_managementsetting, so a locked-down device still refuses it (#31). - Add / edit / remove contacts (
CMD_ADD_UPDATE_CONTACT,CMD_REMOVE_CONTACT): add a contact, rename one,
or delete one (and its chat history) straight from the app. Adding and renaming apply instantly (the app
stays connected); removing reboots to apply (the app reconnects) — see the consistent add/remove model
below. Editing maps to the contact's display name; per-contact permission flags stay device-owner settings
(the config tool / on-device Admin), and the app's own contact flags remain app-local. Gated by
permissions.conversation_management(#33). - Share a contact (
CMD_SHARE_CONTACT) re-broadcasts a contact's advert so a nearby device can add them,
and reboot (CMD_REBOOT) is now honoured from the app's button. - The app's Local vs Flood advert buttons were already handled; confirmed during this work.
With this, the companion can fully manage rooms, channels, and contacts (#31, #32, #33 all closed). A consistent
rule across both contacts and channels: adding and editing apply instantly; removing reboots to apply (the
app reconnects on its own). The reboot on removal is required for channels — MeshCore has no way to drop a
channel from the running radio — and kept for contacts so the behaviour is uniform and predictable. Live changes
are reflected on the device's own UI too — a contact/channel added or renamed from the app shows up in the
on-device conversation list and Admin screens right away, no reboot. In-place editing of a contact's permission
flags / a channel's settings still arrives alongside on-device editing.
- Room login (
-
Change device settings from the companion app. With
permissions.settingsset tofull, a connected app
can now set the device name, radio parameters (frequency / spreading factor / bandwidth / coding rate),
TX power, the BLE pairing PIN, and the path-hash mode (1/2/3 bytes per hop). Values are range-checked;
the device name applies instantly to mesh adverts (the Bluetooth scan name refreshes on the next reboot), while
radio / TX / PIN / path-hash save and apply on a quick reboot (the app reconnects). Path-hash mode is
especially useful on large meshes — it lets app users match a 3-byte network
without hand-editingconfig.json(see #36). A device left atrestrictedornonerefuses these. Identity
keys, advert location (MCLite advertises GPS at the configured precision), and auto-add stay device-managed by
design and are rejected. -
Set the region/scope from the companion app. The companion now honours
CMD_SET_DEFAULT_FLOOD_SCOPE(set the
persistent region),CMD_GET_DEFAULT_FLOOD_SCOPE(read it), andCMD_SET_FLOOD_SCOPE_KEY(a temporary session
override), gated bypermissions.settings = full. Together with the existing path-hash command, the radio's
region and path-hash size are now both configurable from the app — the two settings a large 3-byte mesh needs.
A public#regionround-trips exactly (MCLite derives the same transport key MeshCore does); a custom/private key
that isn't derivable from the name is refused. -
On-device contact/channel/room actions. Tapping a contact in Admin now offers Reset path (force flood
rediscovery of the route) beside Delete; tapping a channel or room offers Set scope (edit that entry's own
region override, blank = inherit the global one) beside Delete. A configured override is shown as[scope:…]on
the row in both the manage and read-only views. -
Edit region and path-hash size on the device. Admin → Radio now lets you change the region/scope and the
path-hash size (1/2/3 bytes per hop) directly on-device (a roller for the size, a text editor for the region),
gated bypermissions.settings = full. Both apply on a quick reboot. Handy for matching a large 3-byte mesh
without the config tool. A blank region means none (*); a bare name likeregionis treated as#region. The
other radio params (frequency / SF / BW / CR / TX) stay on the existing region-preset picker + TX slider. -
More companion commands: reset a contact's path (
CMD_RESET_PATH— forces flood rediscovery of the
route), export a contact (CMD_EXPORT_CONTACT— your own or a known contact's signed advert, as a portable
blob), and import a contact (CMD_IMPORT_CONTACT— the imported advert appears in Heard Adverts to review
and save, keeping the contact list curated). Import is gated bypermissions.conversation_management. -
Explicit un-scoped flood scope from the app. The companion app can now force flood sends out un-scoped,
independent of the configured region (CMD_SET_FLOOD_SCOPE_KEYexplicit-unscoped variant). Session-only —
reverts to the configured scope on reboot. Gated bypermissions.settings == "full". -
Send a request to a node that isn't a contact (
CMD_SEND_ANON_REQ). The companion app can query a node
addressed only by its public key — without adding it as a contact first — and the reply is forwarded back to
the app. The temporary node is never saved to the contact list. Gated bypermissions.settings == "full".
With this, MCLite now advertises companion firmware-version 13 so apps surface both this and the
un-scoped-scope option above. -
Node status and path-trace from the app. Two more standard companion commands: status request
(CMD_SEND_STATUS_REQ— ask a repeater/node for its status, e.g. uptime and counters) and trace path
(CMD_SEND_TRACE_PATH— trace the route to a node and report per-hop signal). This completes the companion
command set MCLite supports.
Changed
- Updated the MeshCore library 1.15 → 1.16. Brings RadioLib 7.6, an SF-dependent preamble (32 symbols for
SF ≤ 8, matching the rest of the network for better low-SF link reliability), and upstream fixes (EU
client-repeat frequency, WiFi reconnect, repeater neighbor-discovery when path-hash mode ≠ 0). Confirmed
interoperable with 1.16 nodes — including message ACKs — at SF8.
Fixed
- Companion message sync no longer drops messages on connect. Two issues fixed: the on-connect history
replay was capped (about two dozen messages) and walked oldest-first, so an active chat could lose its newest
messages and other chats could sync nothing; and over WiFi a full transport send-queue could silently drop a
message frame. Sync now streams the full stored history with no cap (newest included, all chats) and only
removes a message once the transport confirms it was sent — so reconnecting shows everything you received.
Works the same over WiFi and Bluetooth. (Note: messages you type on the device still don't appear in the
app — the MeshCore companion protocol has no outgoing-message frame; see the README.) - Region scope without a leading
#now matches MeshCore. A region/flood-scope written as a bare name (e.g.
regioninstead of#region) was hashed literally, producing a different transport key than the rest of the
network. MCLite now prepends#to a bare name before deriving the key — mirroring MeshCore's implicit-hashtag
behavior — soregionand#regionare the same region and interoperate. (#/$prefixes pass through
unchanged; explicit#regionconfigs are unaffected.) - Custom canned-message list (global) was lost on save. A
canned_messagesarray configured at the messaging
level was serialized back as a baretrue, so the custom list vanished on the next boot — and with the new
companion config writes, almost any settings change triggered it. Serialization now writes the array faithfully
(and honors the on/off toggle, so a disabled state also persists). Per-conversation canned lists
(per contact/channel/room) were always stored separately and were never affected. Thanks @jason-s13r (#34). - Non-English devices ignored a configured global canned list in the chat quick-reply picker. The picker only
honored a customcanned_messagesarray when the UI language was English; on other languages it always showed
the translated defaults. A configured custom array is an explicit, language-independent choice and now wins
regardless of language (translated defaults still apply when no custom array is set). Thanks @jason-s13r (#34).
Full changelog: https://github.com/laserir/MCLite/blob/v0.4.1/CHANGELOG.md