Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,12 @@ iPhone-style dark look (status bar, battery glyph, grouped settings cards).
enabling one frees the other.

### 🔭 Later
- **MeshCore companion bridge** — V0 protocol foundation is drafted, and an
initial `companion mc ...` USB serial-console smoke surface can report
snapshots and exercise send boundaries; the formal USB/BLE bridge remains
planned, and it is not official MeshCore app compatible unless the real
MeshCore app protocol is confirmed.
- **MeshCore companion bridge** — V0 USB foundation is in progress:
`companion mc ...` covers console smoke, and `companion mc usb on` enters
formal MC0 mode for identity/status/node/thread snapshots, send boundaries,
revision counters, event controls, and bounded node/message/TX event draining.
BLE transport remains planned, and it is not official MeshCore app compatible
unless the real MeshCore app protocol is confirmed.
- **Roll the iPhone look everywhere** — grouped cards / dividers across Messages, Nodes, Contacts.
- **Local app platform** - scan local app manifests from `/sd/limitlezz/apps`,
`/sd/apps`, `/appfs/apps`, and simulator data dirs, then show accepted apps
Expand Down Expand Up @@ -185,7 +186,7 @@ iPhone-style dark look (status bar, battery glyph, grouped settings cards).
- [`docs/tdeck-firmware-audit.md`](docs/tdeck-firmware-audit.md) - current firmware audit and risk list.
- [`docs/tdeck-feature-inventory.md`](docs/tdeck-feature-inventory.md) - feature-by-feature implementation inventory.
- [`docs/tdeck-firmware-roadmap.md`](docs/tdeck-firmware-roadmap.md) - roadmap to a complete T-Deck firmware.
- [`docs/tdeck-meshcore-companion-protocol.md`](docs/tdeck-meshcore-companion-protocol.md) - draft Phase 5/V0.8 MeshCore companion line protocol.
- [`docs/tdeck-meshcore-companion-protocol.md`](docs/tdeck-meshcore-companion-protocol.md) - Phase 5/V0.8 MeshCore companion V0 protocol.
- [`docs/tdeck-hardware-dogfood-checklist.md`](docs/tdeck-hardware-dogfood-checklist.md) - stock-device hardware proof checklist.
- [`docs/tdeck-release-checklist.md`](docs/tdeck-release-checklist.md) - slow-host Actions artifact and COM8 release evidence checklist.
- [`docs/tdeck-troubleshooting.md`](docs/tdeck-troubleshooting.md) - build, flash, boot, radio, storage, Wi-Fi, and companion troubleshooting.
Expand Down
2 changes: 1 addition & 1 deletion docs/tdeck-feature-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Status labels:
| MeshCore self-advert TX | Partial, needs validation | Ed25519 identity, self-advert builder, serial/UI advert commands | Needs interop proof with real MeshCore nodes. |
| MeshCore public channel / rooms | Planned | README says receive/default Public channel still ahead | V0.6: implement group text decode/send, room model, and split airtime config. |
| MeshCore DMs | Planned | MeshCore contacts are non-messageable while gated | V0.7: implement key/session model, send path, ACKs, and UI routing. |
| MeshCore companion bridge | Planned/In progress | `docs/tdeck-meshcore-companion-protocol.md` drafts the V0 USB serial line protocol; `companion mc ...` provides an initial firmware smoke surface for snapshots, sends, and self-test | V0.8: formalize USB first, mirror to BLE later, and do not claim external MeshCore app compatibility until the real app protocol is confirmed. |
| MeshCore companion bridge | Partial/In progress | `docs/tdeck-meshcore-companion-protocol.md` defines the V0 USB serial line protocol; `companion mc ...` provides console smoke coverage, and `companion mc usb on` enters formal MC0 mode for identity/status/node/thread snapshots, send boundaries, event controls, revision counters, and bounded node/message/TX event drain | V0.8: hardware-validate USB MC0 with TX-event smoke, mirror to BLE later, and do not claim external MeshCore app compatibility until the real app protocol is confirmed. |

## User Interface

Expand Down
20 changes: 13 additions & 7 deletions docs/tdeck-firmware-roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ These maintainer-provided beta labels are the canonical near-term sequence. The
| V0.6 | MeshCore public chat and split airtime config | 🚧 Public chat send/receive hardware-verified; **split airtime may not be working — needs re-verification**; config UI still TODO |
| V0.6 | MeshCore public chat and split airtime config | In progress - public chat send/receive hardware-verified; split-airtime serial dwell/switch smoke passed on COM8; packet-loss, latency, and real dual-network traffic soak still open |
| V0.7 | MeshCore DMs and private chats | ✅ Encrypted DMs (X25519 ECDH + AES) send/receive hardware-verified against a real MeshCore peer |
| V0.8 | MeshCore USB companion and MeshCore BLE companion | 🚧 Protocol foundation drafted; USB/BLE implementation still planned and not external-app compatible yet |
| V0.8 | MeshCore USB companion and MeshCore BLE companion | In progress - USB MC0 mode now covers identity/status/node/thread snapshots, send boundaries, revision counters, event controls, and COM8 smoke hooks; BLE and external-app compatibility are still planned |
| V0.9 | Code review, optimization, and emoji polish | ⬜ Not started |
| V0.95 | Basic app SDK and infrastructure; Home UI supports adding apps and multiple home screens | 🚧 Local manifest scanner, Home paging, and detail shell started; runtime/catalog still TODO |
| V0.96 | Upgraded Wi-Fi password storage | ✅ Implemented on T-Deck hardware: credentials use ESP32 NVS, legacy `wifi.cfg` migrates/removes, and diagnostics do not print passwords |
Expand Down Expand Up @@ -189,17 +189,23 @@ Exit criteria:

Goal: expose MeshCore companion functionality only after native MeshCore messaging is stable.

**Status:** protocol foundation in progress with an initial USB serial-console
smoke surface. `companion mc hello|status|nodes|threads|send|dm|test` now
exercises the firmware-owned MeshCore snapshots and send boundaries for COM8
validation, while the formal `MC0` bridge, BLE transport, events, and real
external MeshCore app compatibility are still planned work.
**Status:** USB-first protocol foundation in progress. `companion mc
hello|status|nodes|threads|send|dm|test` still exercises the firmware-owned
MeshCore snapshots and send boundaries for COM8 validation, and formal
`companion mc usb on` MC0 mode now handles `HELLO`, `IDENTITY`, `STATUS`,
`NODES`, `THREADS`, `SEND_PUBLIC`, `SEND_DM`, `EVENTS`, and `EXIT` with
snapshot revisions plus bounded node/message/TX event draining. BLE transport
and real external MeshCore app compatibility are still planned work.

Deliverables:

- Define the MeshCore companion protocol surface for node DB, public chat, private chats, and send/receive forwarding. Drafted as `docs/tdeck-meshcore-companion-protocol.md`.
- Add a USB serial-console smoke surface that reports MeshCore companion status, nodes, threads, Public send, DM send, and self-test.
- Implement MeshCore USB companion mode.
- Implement MeshCore USB companion mode. In progress: MC0 USB request/response
mode is implemented for identity, status, node/thread snapshots, send
boundaries, exact full-public-key DM routing, event controls, bounded event
draining, and reconnect/resync counters; BLE and external protocol mapping
remain.
- Implement MeshCore BLE companion mode.
- Add UI and serial commands that distinguish Meshtastic companion from MeshCore companion.
- Decide whether one companion session or one network can own the external-app bridge at a time.
Expand Down
100 changes: 59 additions & 41 deletions docs/tdeck-meshcore-companion-protocol.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# T-Deck MeshCore Companion V0 Protocol

Status: Phase 5 / V0.8 protocol foundation plus an initial firmware serial
smoke surface. The current firmware exposes `companion mc hello`, `status`,
`nodes`, `threads`, `send`, `dm`, and `test` for USB console validation; the
formal `MC0` request/response bridge, live events, BLE transport, and external
app compatibility are still planned.
Status: Phase 5 / V0.8 USB-first protocol foundation. The firmware exposes
`companion mc hello`, `status`, `nodes`, `threads`, `send`, `dm`, and `test`
for USB console validation, plus formal `companion mc usb on` MC0 mode for
`HELLO`, `IDENTITY`, `STATUS`, `NODES`, `THREADS`, `SEND_PUBLIC`, `SEND_DM`,
`EVENTS`, and `EXIT`. Snapshot revision counters and a bounded event drain are
implemented; BLE transport and external app compatibility are still planned.

## Goal

Expand Down Expand Up @@ -49,8 +50,12 @@ the normal console prompt. The firmware enters MC0 mode with:
```text
companion mc usb on
MC0 1 HELLO proto=0 app=limitlezz-smoke host=windows want=none
MC0 2 STATUS
MC0 3 NODES since=0 limit=5
MC0 2 IDENTITY
MC0 3 STATUS
MC0 4 NODES since=0 limit=5
MC0 5 THREADS since=0 limit=5
MC0 6 EVENTS mode=on types=nodes,messages,tx,status
MC0 7 EVENTS mode=off
MC0 99 EXIT
```

Expand Down Expand Up @@ -111,7 +116,7 @@ MC0 1 HELLO proto=0 app=limitlezz-test host=windows want=events
Response:

```text
MC0 1 OK proto=0 fw=0.8-draft device=tdeck session=84 caps=identity,nodes,status,send_public,send_dm,events max_line=512 max_text=180 event_seq=120 nodes_rev=42 messages_rev=77
MC0 1 OK proto=0 fw=0.8-draft device=tdeck caps=identity,nodes,status,threads,send_public,send_dm,events,exit max_line=512 max_text=180 event_seq=120 nodes_rev=42 messages_rev=77
```

Required fields:
Expand Down Expand Up @@ -140,14 +145,16 @@ MC0 2 IDENTITY
Response:

```text
MC0 2 OK enabled=1 name=Jess addr=4f8e21a0 role=chat pubkey=6b1d... addr_format=meshcore-hex advert_ready=1
MC0 2 OK enabled=1 name=Jess addr=6b1d000000000000000000000000000000000000000000000000000000000000 short_id=MC-6b1d0000 role=chat pubkey=6b1d000000000000000000000000000000000000000000000000000000000000 addr_format=meshcore-pubkey-hex advert_ready=1
```

Required fields:

- `enabled`: whether MeshCore is currently enabled.
- `name`: percent-encoded local display name.
- `addr`: local MeshCore address, lowercase hex, opaque to the host.
- `addr`: local MeshCore address, lowercase 64-hex MeshCore public key, opaque
to the host except for exact equality.
- `short_id`: optional display-only short identifier. Hosts must not route by it.
- `role`: current local MeshCore role, such as `chat`, `router`, or
`unknown`.
- `addr_format`: the address encoding advertised for this session.
Expand All @@ -169,18 +176,19 @@ MC0 3 STATUS
Response:

```text
MC0 3 OK mc=on bridge=usb mc_companion=idle mt_companion=off tdm=active airtime=balanced queue=0 event_seq=120 nodes_rev=42 messages_rev=77
MC0 3 OK proto=0 mc=on bridge=usb mc_companion=attached mt_companion=off addr=6b1d000000000000000000000000000000000000000000000000000000000000 short_id=MC-6b1d0000 nodes=2 threads=2 unread=1 public=1 dm=1 events=off event_seq=120 nodes_rev=42 messages_rev=77
```

Suggested fields:

- `mc`: `on`, `off`, or `disabled`.
- `bridge`: active transport, usually `usb` for V0.
- `mc_companion`: `idle`, `attached`, or `streaming`.
- `mc_companion`: `attached` or `streaming`.
- `mt_companion`: Meshtastic companion state so clients can detect conflicts.
- `tdm`: `active`, `mc_only`, `mt_only`, or `idle`.
- `airtime`: current split-airtime preset.
- `queue`: queued outbound MeshCore sends owned by the firmware.
- `addr` and `short_id`: local MeshCore identity fields, matching `IDENTITY`.
- `nodes`, `threads`, and `unread`: current snapshot counts.
- `public` and `dm`: whether firmware-backed public and DM sends are available.
- `events`: `on` when typed event streaming is enabled.
- `event_seq`, `nodes_rev`, `messages_rev`: resync counters.

### `NODES`
Expand All @@ -197,25 +205,28 @@ Response:

```text
MC0 4 BEGIN type=nodes rev=42 count=2 more=0 cursor=end
MC0 4 NODE addr=4f8e21a0 name=Limitlezz role=chat seen_ms=12000 snr=-9 rssi=-112 public_key=present dm=ready
MC0 4 NODE addr=12ab9001 name=Hilltop role=router seen_ms=180000 snr=-14 rssi=-118 public_key=missing dm=not_messageable
MC0 4 NODE addr=4f8e21a000000000000000000000000000000000000000000000000000000000 short_id=MC-4f8e21a0 name=Limitlezz role=chat seen_ms=12000 snr=-9 public_key=present dm=ready
MC0 4 NODE addr=- short_id=MC-12ab9001 name=Hilltop role=router seen_ms=180000 snr=-14 public_key=missing dm=not_messageable
MC0 4 END type=nodes rev=42 count=2 more=0 cursor=end
```

Request fields:

- `since`: last `nodes_rev` known by the host, or `0` for a full snapshot.
- `limit`: maximum rows requested. Firmware may cap this below the requested
value.
value; V0 USB mode caps node snapshots at five rows to keep line responses
bounded.
- `cursor`: optional opaque cursor from a previous `NODES` response.

Node fields:

- `addr`: MeshCore address, lowercase hex, opaque to the host.
- `addr`: MeshCore address, lowercase 64-hex public key when known. `-` means
the firmware has no usable key yet, so `SEND_DM to_addr=...` is impossible.
- `short_id`: display-only short identifier for compact UI labels.
- `name`: percent-encoded display name, if known.
- `role`: `chat`, `router`, `repeater`, `sensor`, or `unknown`.
- `seen_ms`: milliseconds since last heard, or `-1` if unknown.
- `snr`, `rssi`: last RF quality values, or omitted when unknown.
- `snr`: last RF quality value, or omitted when unknown.
- `public_key`: `present`, `missing`, or `unknown`.
- `dm`: `ready`, `no_key`, `not_messageable`, or `unknown`.

Expand All @@ -236,14 +247,13 @@ MC0 5 SEND_PUBLIC room=public text=Hello%20mesh client_mid=pc-0001
Immediate response:

```text
MC0 5 OK accepted=1 msg_id=mc-804 queue=1 status=queued
MC0 5 OK accepted=1 kind=public status=queued event_seq=121 client_mid=pc-0001
```

Later events:

```text
MC0 EVT 121 tx_status client_mid=pc-0001 msg_id=mc-804 kind=public status=sent
MC0 EVT 122 tx_status client_mid=pc-0001 msg_id=mc-804 kind=public status=delivered
MC0 EVT 121 tx_status kind=public status=queued room=public client_mid=pc-0001
```

Request fields:
Expand All @@ -263,7 +273,7 @@ name. Address is preferred because display names can collide.
By address:

```text
MC0 6 SEND_DM to_addr=4f8e21a0 text=Meet%20at%20camp client_mid=pc-0002
MC0 6 SEND_DM to_addr=4f8e21a000000000000000000000000000000000000000000000000000000000 text=Meet%20at%20camp client_mid=pc-0002
```

By known name:
Expand All @@ -275,23 +285,25 @@ MC0 7 SEND_DM to_name=Limitlezz text=Copy%20that client_mid=pc-0003
Immediate response:

```text
MC0 6 OK accepted=1 msg_id=mc-805 to_addr=4f8e21a0 status=queued
MC0 6 OK accepted=1 kind=dm to_addr=4f8e21a000000000000000000000000000000000000000000000000000000000 to_name=Limitlezz status=queued event_seq=122 client_mid=pc-0002
```

Later event:

```text
MC0 EVT 123 tx_status client_mid=pc-0002 msg_id=mc-805 kind=dm to_addr=4f8e21a0 status=delivered
MC0 EVT 122 tx_status kind=dm status=queued to_addr=4f8e21a000000000000000000000000000000000000000000000000000000000 client_mid=pc-0002
```

V0 name matching rules:

- Match against the firmware's known MeshCore display name and short name.
- Match against the firmware's known MeshCore display name.
- Case-insensitive exact match only.
- If zero nodes match, return `ERR code=not_found`.
- If more than one node matches, return `ERR code=ambiguous_name`.
- If the matching node lacks a usable session/key, return `ERR code=no_key`.
- If the node role is not messageable, return `ERR code=not_messageable`.
- If both `to_addr` and `to_name` are supplied, they must identify the same
node or firmware returns `ERR code=target_mismatch`.

The host does not manage MeshCore private keys or sessions in V0.

Expand All @@ -309,22 +321,22 @@ MC0 8 EVENTS mode=on types=nodes,messages,tx,status
Response:

```text
MC0 8 OK events=on types=nodes,messages,tx,status event_seq=123
MC0 8 OK events=on types=nodes,messages,tx,status event_seq=123 nodes_rev=42 messages_rev=77
```

Supported event types:

```text
MC0 EVT 124 node_upsert addr=4f8e21a0 nodes_rev=43
MC0 EVT 125 snapshot_dirty type=nodes rev=43 reason=node_upsert
MC0 EVT 126 rx_public msg_id=mc-806 from_addr=4f8e21a0 from_name=Limitlezz room=public text=Copy%20CH0.
MC0 EVT 127 rx_dm msg_id=mc-807 from_addr=4f8e21a0 from_name=Limitlezz text=Direct%20copy.
MC0 EVT 128 tx_status client_mid=pc-0002 msg_id=mc-805 kind=dm status=failed reason=ack_timeout retry=1
MC0 EVT 129 status mc=on tdm=active airtime=balanced queue=0
MC0 EVT 124 node_upsert addr=4f8e21a000000000000000000000000000000000000000000000000000000000 short_id=MC-4f8e21a0 nodes_rev=43 name=Limitlezz role=chat public_key=present dm=ready
MC0 EVT 125 rx_public messages_rev=78 kind=public room=public from_name=Limitlezz text=Copy%20CH0.
MC0 EVT 126 rx_dm messages_rev=79 kind=dm from_addr=4f8e21a000000000000000000000000000000000000000000000000000000000 from_name=Limitlezz text=Direct%20copy.
MC0 EVT 127 tx_status kind=dm status=queued to_addr=4f8e21a000000000000000000000000000000000000000000000000000000000 client_mid=pc-0002
```

Snapshot events are hints. The host should use `STATUS`, `NODES`, or later
message snapshot commands for authoritative state after reconnect.
The current V0 firmware accepts `status` in `types`, but it has no live status
event producer yet; poll `STATUS` for authoritative radio and bridge state.

## Error Semantics

Expand Down Expand Up @@ -373,12 +385,14 @@ Rules:
2. Add an initial USB serial-console smoke surface for `hello`, `status`,
`nodes`, `threads`, Public send, DM send, and self-test.
3. Add a USB-only MeshCore companion mode with `HELLO`, `IDENTITY`, `STATUS`,
and `NODES`.
and `NODES`. Implemented.
4. Add `SEND_PUBLIC` and `SEND_DM` using the existing firmware-owned MeshCore
send paths.
send paths. Implemented.
5. Add event streaming for receive, send-status, node-change, and status
changes.
6. Add snapshot revision counters and reconnect/resync behavior.
changes. In progress: event controls and a bounded event drain are
implemented for node, message, and TX events.
6. Add snapshot revision counters and reconnect/resync behavior. Implemented
for node/thread snapshots and `STATUS`/`HELLO` resync.
7. Mirror the same logical protocol over BLE only after USB behavior is stable.
8. Revisit external-app compatibility only after the real MeshCore app protocol
is confirmed.
Expand All @@ -390,9 +404,13 @@ Rules:
`companion mc test`.
- Formal USB MC0 smoke is opt-in:
`python scripts/mc_companion_usb_smoke.py --mc0-usb` enters the configured
USB mode, sends `HELLO`, `STATUS`, and `NODES`, asserts `MC0 ... OK`,
`BEGIN`, and `END` response markers, then exits through the configured
`MC0 <id> EXIT` line.
USB mode, sends `HELLO`, `IDENTITY`, `STATUS`, `NODES`, `THREADS`, and
`EVENTS` on/off, asserts `MC0 ... OK`, the public-key address format,
revision markers, `BEGIN`, and `END` response markers, then exits through
the configured `MC0 <id> EXIT` line.
- Add `--mc0-tx-smoke` to the formal USB smoke when a hardware run should prove
live event draining. It sends a public `SEND_PUBLIC` with a known
`client_mid` and waits for a matching `MC0 EVT tx_status`.
- If firmware lands different command names, use the smoke helper's
`--mc0-enter-command`, `--mc0-*-template`, `--mc0-*-marker`, and
`--mc0-exit-template` flags instead of editing firmware or weakening the
Expand Down
Loading