Skip to content

MCOtxt codec to companion firmware - #3670

Open
HDDen wants to merge 8 commits into
meshcore-dev:devfrom
HDDen:feature/MCOtxt
Open

HDDen wants to merge 8 commits into
meshcore-dev:devfrom
HDDen:feature/MCOtxt

Conversation

@HDDen

@HDDen HDDen commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

Add MCOtxt decoding to companion firmware

MCOtxt (MeshCore Open Text codec) is a lightweight text-compression codec designed for MeshCore messages. It was specifically developed to keep code size, language tables, and RAM requirements small enough to fit on nRF microcontrollers, including nRF52840-based nodes, alongside the existing firmware.

It uses small, fixed language-specific prediction tables and variable-length character codes. Tables are available for English, Russian, French, German, Italian, Ukrainian, and Belarusian, including mixed-language messages. Characters absent from the tables are preserved through raw UTF-8 escape sequences, allowing emoji, other scripts, and arbitrary Unicode text to remain representable.

Representative text averages approximately 5.6 bits per character in the codec stream. Compared with plain UTF-8, this corresponds to roughly:

  • 30% smaller text for single-byte Latin characters: 5.6 versus 8 bits.
  • 65% smaller text for two-byte Cyrillic characters: 5.6 versus 16 bits.

These estimates exclude container headers, reply metadata, and Base91 overhead. Actual savings depend on message content and transport. Smaller payloads allow more text per radio packet and can reduce LoRa airtime.

The format also supports:

  • Codec and model versioning for identifying supported formats.
  • Optional sender and timestamp metadata.
  • Structured reply references: the quoted message is identified by its author's name and original timestamp. Compatible clients can resolve the referenced message without relying on matching quoted text.
  • Two transports: binary GROUP_DATA envelopes (0x0120, subtype/version 0x31) and Base91 text prefixed with mct:.

Message encoding is currently available only in the MeshCore Open Advanced (MCOa) companion app, a fork of MeshCore Open. MCOa builds are available from its releases page.

Other applications can add MCOtxt encoding and decoding by porting the reference Dart implementation. The MCOtxt v1 protocol reference documents the wire format and links to the relevant implementation files.

Encoder interoperability: for binary GROUP_DATA messages, new encoders should reuse the existing application namespace data_type = 0x0120 and MCOtxt subtype/version byte 0x31 — subtype 0x03, wire version 0x01. Using these identifiers with the documented envelope format maintains compatibility with the current MCOa application.

This PR adds decoding to the companion firmware so existing companion apps and local displays can read compressed chat messages.

The implementation:

  • Recognizes binary and Base91 containers, including containers embedded in ordinary text.
  • Keeps original companion frames in the offline queue and generates decoded parts during delivery.
  • Checks the optional comma-separated cap= list in CMD_APP_START. Apps declaring mctxt receive the original frames, preserving structured metadata.
  • Provides decoded text to other apps: Base91 text is replaced, while binary messages are delivered raw first, followed by decoded text.
  • Splits long text within existing frame limits, preserving UTF-8 boundaries, sender prefixes, continuation markers, and part numbers.
  • Represents reply metadata as an @[author] mention at the beginning of the first decoded part for apps receiving plain text.
  • Shows decoded messages through existing local display previews.
  • Uses bounded buffers and fixed language tables without heap allocation.

Implementation details and test instructions are included in docs/mcotxt.md.

Validation: 72 native tests and 7 queue lifecycle tests pass under AddressSanitizer. Queue tests are also connected to CI.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants