Merge branch 'new_docs' into wio-unified
@@ -24,11 +24,22 @@ jobs:
|
||||
- name: Setup Build Environment
|
||||
uses: ./.github/actions/setup-build-environment
|
||||
|
||||
- name: Resolve build version
|
||||
run: |
|
||||
if [ "$GITHUB_REF_TYPE" = "tag" ]; then
|
||||
echo "BUILD_VERSION=${GITHUB_REF_NAME}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "BUILD_VERSION=dev-$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Build Dual OLED Firmware
|
||||
env:
|
||||
FIRMWARE_VERSION: ${{ env.GIT_TAG_VERSION }}
|
||||
FIRMWARE_VERSION: ${{ env.BUILD_VERSION }}
|
||||
run: /usr/bin/env bash build.sh build-firmware WioTrackerL1_companion_dual
|
||||
|
||||
- name: Rename OLED firmware
|
||||
run: mv out/*.uf2 "out/solo-${{ env.BUILD_VERSION }}-oled.uf2" 2>/dev/null || true
|
||||
|
||||
- name: Upload OLED Firmware
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -45,11 +56,22 @@ jobs:
|
||||
- name: Setup Build Environment
|
||||
uses: ./.github/actions/setup-build-environment
|
||||
|
||||
- name: Resolve build version
|
||||
run: |
|
||||
if [ "$GITHUB_REF_TYPE" = "tag" ]; then
|
||||
echo "BUILD_VERSION=${GITHUB_REF_NAME}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "BUILD_VERSION=dev-$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Build Dual E-ink Firmware
|
||||
env:
|
||||
FIRMWARE_VERSION: ${{ env.GIT_TAG_VERSION }}
|
||||
FIRMWARE_VERSION: ${{ env.BUILD_VERSION }}
|
||||
run: /usr/bin/env bash build.sh build-firmware WioTrackerL1Eink_companion_dual
|
||||
|
||||
- name: Rename E-ink firmware
|
||||
run: mv out/*.uf2 "out/solo-${{ env.BUILD_VERSION }}-eink.uf2" 2>/dev/null || true
|
||||
|
||||
- name: Upload E-ink Firmware
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -80,7 +102,7 @@ jobs:
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: Wio Tracker L1 Firmware ${{ env.GIT_TAG_VERSION }}
|
||||
name: Solo ${{ env.GIT_TAG_VERSION }}
|
||||
body: ""
|
||||
draft: true
|
||||
files: out/*.uf2
|
||||
|
||||
382
README.md
@@ -1,24 +1,35 @@
|
||||
# Wio Tracker L1 — Extended Companion Radio Firmware
|
||||
# Seeed Wio Tracker L1 - MeshCore "Solo" companion firmware
|
||||
|
||||
This branch extends the official MeshCore companion radio firmware for the **Seeed Wio Tracker L1**.
|
||||
This branch extends the official MeshCore companion radio firmware for the **Seeed Wio Tracker L1**. Provides support for both the original OLED and the e-ink variant, with additional features and UI enhancements.
|
||||
|
||||
Join the discussion on offical MeshCore discord: https://discord.gg/sdhYArU2jr
|
||||
Join the discussion on the official MeshCore Discord: https://discord.gg/sdhYArU2jr
|
||||
|
||||
<img src="./img/radios.jpeg">
|
||||
|
||||
[E-ink case](https://www.printables.com/model/1420534-seeed-wio-tracker-l1-e-ink-enclosure)
|
||||
[Oled case](https://www.printables.com/model/1380791-meshpack-seeed-l1-oled)
|
||||
**Enclosures**
|
||||
|
||||
## Firmware Variants
|
||||
- [E-ink case](https://www.printables.com/model/1420534-seeed-wio-tracker-l1-e-ink-enclosure)
|
||||
- [Oled case](https://www.printables.com/model/1380791-meshpack-seeed-l1-oled)
|
||||
|
||||
Two firmware builds are published with each release:
|
||||
---
|
||||
|
||||
| Variant | Display | File |
|
||||
|---------|---------|------|
|
||||
| **OLED** | SSD1306 / SH1106 128 × 64 | `WioTrackerL1_companion_dual_*.uf2` |
|
||||
| **E-ink** | GxEPD2 250 × 122 | `WioTrackerL1Eink_companion_dual_*.uf2` |
|
||||
## Feature highlights
|
||||
|
||||
Both variants are built from a single codebase and share the same feature set. The `dual` in the filename means a single binary supports both BLE and USB serial — there are no separate BLE/USB builds.
|
||||
- Extended language support with native Unicode rendering and input [Lemon font](https://github.com/cmvnd/fonts) alongside the original ASCII mode (Default font with transliteration)
|
||||
|
||||
- Enabled sensor screens with support for all onboard sensors (temperature, humidity, pressure, luminosity, CO₂) and GPS data
|
||||
|
||||
- [Messages Screen](./docs/solo_features/message_screen/message_screen.md) — view and send messages, open message details, reply with quick messages or custom text, per-channel notification and melody overrides
|
||||
|
||||
- [Favourites Dial](./docs/solo_features/favourites_dial/favourites_dial.md) — pin up to six contacts for quick access from the home screen
|
||||
|
||||
- [Settings Screen](./docs/solo_features/settings_screen/settings_screen.md) — configure display, sound, home page order, radio and system settings
|
||||
|
||||
- [Clock Screen](./docs/solo_features/clock_screen/clock_screen.md) — view time and date plus up to three configurable data fields
|
||||
|
||||
- [Screen Lock](./docs/solo_features/screen_lock/screen_lock.md) — lock the device to prevent accidental keypresses, with a lock screen showing time and sensor data
|
||||
|
||||
- [Tools Screen](./docs/solo_features/tools_screen/tools_screen.md) — GPS trail recording and export, nearby nodes, ringtone editor, auto-reply bot, auto-advert
|
||||
|
||||
### E-ink Display
|
||||
|
||||
@@ -26,251 +37,102 @@ The e-ink variant targets the Wio Tracker L1 fitted with a 2.13″ GxEPD2 panel
|
||||
|
||||
- **Adaptive layout** — every screen reflows correctly in both landscape (250 × 122) and portrait (122 × 250) orientations
|
||||
- **Display rotation** — configurable in Settings › Display; applied immediately and persisted across reboots
|
||||
- **Scaled navigation dots** — dot indicators on the home screen scale with line height so they remain visible at all orientations
|
||||
- **Joystick rotation** — independent of display rotation; useful for custom enclosures
|
||||
- **Full refresh interval** — configurable in Settings › Display; reduces ghosting on long sessions
|
||||
- **Clock seconds suppressed by default** — seconds are hidden to reduce per-second panel refreshes and extend display lifetime; re-enable in Settings › Display
|
||||
|
||||
---
|
||||
## Firmware Variants
|
||||
|
||||
## New Features
|
||||
Two firmware builds are published with each release:
|
||||
|
||||
### Messages Screen
|
||||
| Variant | Display | File |
|
||||
| --------- | ------------------------- | ------------------------- |
|
||||
| **OLED** | SSD1306 / SH1106 128 × 64 | `solo-<version>-oled.uf2` |
|
||||
| **E-ink** | GxEPD2 250 × 122 | `solo-<version>-eink.uf2` |
|
||||
|
||||
View and send messages using the on-screen keyboard or predefined quick replies. The keyboard supports placeholders that insert live sensor data — `{time}` and `{loc}` are always available; additional placeholders (`{temp}`, `{hum}`, `{pres}`, `{batt}`, `{alt}`, `{lux}`, `{co2}`) appear automatically for sensors that are connected and returning data.
|
||||
Both variants are built from a single codebase and share the same feature set. The firmware supports both BLE and USB serial in a single binary — there are no separate BLE/USB builds.
|
||||
|
||||
Each message in the history list shows the sender name and a compact age indicator (`3m`, `2h`, `>1d`) in the top-right corner of the entry.
|
||||
> [!IMPORTANT]
|
||||
> BLE connection has priority over USB serial. When a BLE connection is active, the USB protocol is suspended. When connecting to the companion app via USB, ensure to disconnect from BLE first or disable BLE directly from the device to avoid confusion.
|
||||
|
||||
```
|
||||
╔══════════════════════════════╗
|
||||
║ #general ║
|
||||
╠══════════════════════════════╣
|
||||
║▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ║ ← selected
|
||||
║ Alice 3m ║
|
||||
║ Hey, let's meet tomorrow ║
|
||||
║┌───────────────────────────┐ ║
|
||||
║│▓▓▓▓▓▓▓▓▓ Bob 1h ▓▓▓▓ │ ║
|
||||
║│ Sure, what time works? │ ║
|
||||
║└───────────────────────────┘ ║
|
||||
║[+ send] ║
|
||||
╚══════════════════════════════╝
|
||||
```
|
||||
### Flashing
|
||||
|
||||
Press Enter on a message to open it in fullscreen. Navigate between messages with left (newer) and right (older). If the message is a reply addressed to someone (`@[nick]`), a **To: nick** bar is shown below the sender name and the body is displayed without the address prefix.
|
||||
1. Download the appropriate `.uf2` file for your display variant from the [releases page](https://github.com/MarekZegare4/MeshCore/releases)
|
||||
2. Press reset twice quickly to enter bootloader mode (solid amber LED) - the device should appear as a mass storage drive on your computer
|
||||
3. Copy the `.uf2` file to the drive to flash the firmware
|
||||
|
||||
```
|
||||
╔══════════════════════════════╗
|
||||
║▓▓ Alice ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ║ ← sender
|
||||
║▓▓ To: Bob ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ║ ← recipient
|
||||
╠══════════════════════════════╣
|
||||
║ Hey Bob, let's meet up ║
|
||||
║ tomorrow at 6pm downtown. ║
|
||||
║ Will you make it? ║
|
||||
║ ║
|
||||
║< newer older >║
|
||||
╚══════════════════════════════╝
|
||||
```
|
||||
Updating to newer firmware versions usually does not require erasing flash unless the release notes explicitly state otherwise. To retain your settings and data, avoid performing a factory reset after flashing unless you need to start fresh or encounter problems.
|
||||
|
||||
Hold Enter on a message to open a context menu. From the list or fullscreen view, select **Reply** to pre-fill the keyboard or a quick message with `@[nick]` so the recipient is clearly addressed. The reply picker title shows the recipient's name.
|
||||
|
||||
```
|
||||
╔══════════════════════════════╗
|
||||
║ RE:Alice ║
|
||||
╠══════════════════════════════╣
|
||||
║> Custom message... ║
|
||||
║ OK, I understand ║
|
||||
║ On my way ║
|
||||
║ Be right there ║
|
||||
╚══════════════════════════════╝
|
||||
```
|
||||
|
||||
On channel or contact list entries, the context menu also lets you change per-channel notification settings (mute, follow global, or force-on), per-channel melody override (follow global, Melody 1, or Melody 2), or mark messages as read.
|
||||
|
||||
**Mark all read** — Hold Enter on the DM / Channels / Rooms mode-select screen to clear all unread counters for the highlighted category at once.
|
||||
|
||||
### Favourites Dial
|
||||
|
||||
A dedicated home page showing a 2×3 grid of pinned contacts. Navigate tiles with the joystick; press Enter on a filled tile to open that contact's DM directly.
|
||||
|
||||
```
|
||||
╔══════════════════════════════╗
|
||||
║ Favourites ║
|
||||
╠══════════════════════════════╣
|
||||
║ ┌──────┐ ┌──────┐ ┌──────┐ ║
|
||||
║ │Alice │ │Bob 3│ │ + │ ║
|
||||
║ └──────┘ └──────┘ └──────┘ ║
|
||||
║ ┌──────┐ ┌──────┐ ┌──────┐ ║
|
||||
║ │Carol │ │ + │ │ + │ ║
|
||||
║ └──────┘ └──────┘ └──────┘ ║
|
||||
╚══════════════════════════════╝
|
||||
```
|
||||
|
||||
- Unread badge shown on filled tiles
|
||||
- Enter on an empty tile (`+`) opens a contact picker (upstream-favourited contacts first, then recent DMs)
|
||||
- **Pin / unpin** — open a DM, then Hold Enter › options menu › "Pin to dial" to choose a slot; selecting a contact already pinned elsewhere moves it to the new slot
|
||||
- LEFT/RIGHT in the Home Pages settings reorders the Favourites page in the navigation sequence
|
||||
|
||||
### Settings Screen
|
||||
|
||||
All settings are saved to flash and restored on next boot. Settings are organised into collapsible sections — press Enter on a section header to expand or collapse it. All sections start collapsed for faster navigation.
|
||||
|
||||
- **Display**
|
||||
- Brightness
|
||||
- Auto-off timeout
|
||||
- Battery display mode (icon, %, V)
|
||||
- Clock seconds (show/hide — hiding reduces display refresh from 1 s to 60 s)
|
||||
- Clock format (12 h / 24 h)
|
||||
- Font — **Default** (5×7 Adafruit, ASCII + transliteration) or **Lemon** (native Unicode, pixel-accurate wrap)
|
||||
- Display rotation *(e-ink only)* — 0 ° / 90 ° / 180 ° / 270 °; applied immediately
|
||||
- Joystick rotation *(e-ink only)* — rotates the joystick input mapping independently of the display rotation; useful when mounting the device in a custom enclosure
|
||||
- Full refresh interval *(e-ink only)* — how many partial refreshes before a cleansing full refresh (off / 5 / 10 / 20 / 30); reduces ghosting on long sessions
|
||||
- **Sound**
|
||||
- Buzzer: On / Off / **Auto** — Auto mode silences the device while connected via Bluetooth, and re-enables sound when the connection drops
|
||||
- Volume (1–5; preview tone plays on each change)
|
||||
- DM Melody — notification sound for incoming private messages: built-in, Melody 1, or Melody 2
|
||||
- Channel Melody — notification sound for incoming channel messages: built-in, Melody 1, or Melody 2
|
||||
- **Home Pages** — toggle visibility and reorder individual home screen pages; press LEFT / RIGHT on any entry to move it earlier or later in the navigation sequence; press ENTER to toggle ON / OFF (Settings and Messages are always visible and cannot be disabled)
|
||||
- **Radio**
|
||||
- TX power
|
||||
- **System**
|
||||
- Timezone (UTC offset in hours)
|
||||
- Low battery shutdown threshold
|
||||
- Auto-lock — automatically locks the device when the display turns off
|
||||
- **Contacts**
|
||||
- Show all DMs or favourites only
|
||||
- Show all room servers or favourites only
|
||||
- **Messages**
|
||||
- Edit up to 10 quick reply templates (Q1–Q10)
|
||||
|
||||
### Clock Screen
|
||||
|
||||
A dedicated clock page on the home screen shows the current time and date, synchronized from GPS or via Bluetooth. Timezone offset is applied from Settings.
|
||||
|
||||
Up to three configurable data fields are displayed below the clock. Available fields: battery voltage, temperature, humidity, pressure, GPS coordinates, altitude, luminosity, CO₂, contact count, and total unread message count.
|
||||
|
||||
### Screen Lock
|
||||
|
||||
Hold **Back** and press **Enter** three times to lock or unlock the device. While locked:
|
||||
|
||||
- The display turns off and ignores incoming keypresses
|
||||
- A brief button press shows the lock screen: current time, date, and up to two sensor values (reuses the Dashboard Config fields)
|
||||
- A hint popup guides through the unlock sequence
|
||||
- **Auto-lock** (configurable in Settings → System) locks automatically when the display turns off
|
||||
|
||||
### Nearby Nodes
|
||||
|
||||
Browse nodes that have recently advertised on the mesh. Filter by category (Favourites, All, Companion, Repeater, Room, Sensor). Select a node to see its coordinates, distance, bearing with cardinal direction, type, and last-heard time.
|
||||
|
||||
```
|
||||
╔══════════════════════════════╗
|
||||
║▓▓▓▓▓ WioTracker-Alice ▓▓▓▓▓▓ ║ ← node name
|
||||
╠══════════════════════════════╣
|
||||
║ Lat: 50.06190 ║
|
||||
║ Lon: 19.94090 ║
|
||||
║ Dist: 2.3km ║
|
||||
║ Az: 145d (SE) ║
|
||||
║ Type: Companion ║
|
||||
║ Seen: 5m ago ║
|
||||
╚══════════════════════════════╝
|
||||
```
|
||||
|
||||
Use **Send my advert** (hold Enter → context menu) to broadcast your position and prompt nearby nodes to respond with theirs.
|
||||
|
||||
#### Active Discovery
|
||||
|
||||
Press **Enter** from the Nearby screen to send a live `NODE_DISCOVER_REQ` ping. All reachable repeaters, sensors and room servers within zero-hop range respond immediately with their name, type and signal data. Results appear as 2-line boxed cards with RSSI, SNR and the remote SNR (signal quality at the responder's end).
|
||||
|
||||
```
|
||||
╔═══════════════════════════════╗
|
||||
║▓▓▓▓▓▓▓ DISCOVER (2 found) ▓▓ ║
|
||||
╠═══════════════════════════════╣
|
||||
║▓▓▓▓▓▓▓▓▓▓▓▓▓ Rptr-A Rpt ▓▓▓▓║ ← selected
|
||||
║▓▓▓▓▓▓▓▓ RSSI:-79 SNR:9 ▓▓▓▓▓▓▓║
|
||||
║┌────────────────────────────┐ ║
|
||||
║│▓▓▓▓▓▓▓▓▓▓▓▓ Sensor-B Snsr │ ║
|
||||
║│ RSSI:-94 SNR:3 │ ║
|
||||
║└────────────────────────────┘ ║
|
||||
╚═══════════════════════════════╝
|
||||
```
|
||||
|
||||
Navigate with **UP/DOWN**. Press **Enter** on a node to open a full-screen detail view showing the public key, RSSI, SNR, remote SNR and whether the node is already in your contacts.
|
||||
|
||||
Hold **Enter** from the discovery list to rescan. Press **Cancel** or **Back** to return.
|
||||
|
||||
### Tools Screen
|
||||
|
||||
#### GPS Trail
|
||||
|
||||
Records your route in a RAM ring buffer (up to 512 points). Sampling runs in the background whenever tracking is active — a blinking **G** indicator appears in the status bar. The trail survives display auto-off but is lost on reboot unless saved to flash first.
|
||||
|
||||
Three views cycle with **LEFT / RIGHT**:
|
||||
|
||||
| View | Content |
|
||||
|------|---------|
|
||||
| **Summary** | Total distance, elapsed time, avg speed or pace, point count, tracking status |
|
||||
| **Map** | Auto-fit dot-and-line plot with cos(lat) aspect correction; segment breaks marked with open/filled dots; north arrow; scale grid (toggle with Enter) |
|
||||
| **List** | Per-point rows showing local time (HH:MM) and delta distance from the previous point; segment-start rows show `start` |
|
||||
|
||||
**Hold Enter** opens the action menu:
|
||||
|
||||
| Item | Action |
|
||||
|------|--------|
|
||||
| Min dist | Cycle min-distance gate: 5 m / 10 m / 25 m / 100 m (LEFT/RIGHT while focused) |
|
||||
| Units | Cycle speed/pace units: km/h / mph / min/km / min/mi (LEFT/RIGHT while focused) |
|
||||
| Start / Stop tracking | Begin or end a recording session |
|
||||
| Save trail | Write the current RAM ring to flash (`/trail`) |
|
||||
| Load trail | Restore the saved flash trail into RAM |
|
||||
| Export GPX | Stream the live RAM trail as GPX 1.1 over USB Serial |
|
||||
| Export saved | Stream the saved flash trail as GPX 1.1 over USB Serial without loading it into RAM |
|
||||
| Reset trail | Clear the RAM ring and elapsed time |
|
||||
|
||||
#### Downloading GPX to your computer
|
||||
|
||||
1. Connect the device to your computer with a USB cable.
|
||||
2. Open a serial terminal at **115200 baud** on the device's serial port:
|
||||
- **macOS / Linux** — `screen /dev/tty.usbmodem* 115200` or `cat /dev/tty.usbmodem*` (replace with your port, e.g. `/dev/ttyACM0` on Linux); to save directly to a file use `cat /dev/tty.usbmodem* > track.gpx` and stop with Ctrl-C after the dump completes
|
||||
- **Windows** — open PuTTY (Connection type: Serial, Speed: 115200), or use Arduino IDE › Tools › Serial Monitor (set line ending to "No line ending")
|
||||
3. On the device, navigate to **Tools › Trail**, then **Hold Enter** and select **Export GPX** (live ring) or **Export saved** (flash slot).
|
||||
4. The device streams a GPX 1.1 XML document to the serial port. Copy the output starting from `<?xml` to `</gpx>` and save it as a `.gpx` file.
|
||||
5. Import the file into any GPX-compatible application — OsmAnd, Garmin BaseCamp, GPX Studio, Google Earth, etc.
|
||||
|
||||
> **Note:** If the companion app is connected over **BLE**, the export is safe — the app ignores USB input while BLE is active and the device alert will read *"GPX N B (USB)"*. If you are using the app over **USB**, disconnect from the app first before exporting; the raw XML stream will otherwise disrupt the app's serial framing. The alert *"GPX N B - disc. app"* indicates no BLE link was detected and serves as a reminder to reconnect the app afterwards.
|
||||
|
||||
#### Auto-Advert
|
||||
|
||||
Periodically broadcasts a 0-hop advert with your GPS position so nearby nodes can track your location automatically. Configurable interval: off / 30 s / 1 min / 2 min / 5 min / 10 min / 30 min / 1 h.
|
||||
|
||||
A blinking **A** indicator appears in the status bar while Auto-Advert is active.
|
||||
|
||||
#### Ringtone Editor
|
||||
|
||||
A step sequencer for composing custom notification melodies stored on the device. Two independent melody slots are available — **Melody 1** and **Melody 2** — switchable from within the editor. Each melody supports up to 32 notes with adjustable pitch (C–B + pause), octave (4–7), duration (1/4 / 1/8 / 1/16 / 1/32), and BPM (60 / 90 / 120 / 150 / 180). Playback preview is available directly from the editor.
|
||||
|
||||
Melodies can be assigned as notification sounds per message type (DM / channel) in Settings, and individually overridden per channel or per contact from the message screen context menu.
|
||||
|
||||
#### Auto-Reply Bot
|
||||
|
||||
Automatically replies to incoming messages that contain a configured trigger word (case-insensitive).
|
||||
|
||||
- **DM mode** — when enabled, the bot listens to all incoming private messages and replies with the DM reply text.
|
||||
- **Channel mode** — optionally, select a channel for the bot to monitor. When a trigger is matched, it replies with a separate channel reply text.
|
||||
- Both modes can be active simultaneously and share the same trigger word but use independent reply texts.
|
||||
- Replies support placeholders (`{time}`, `{loc}`).
|
||||
- A 10-second cooldown prevents repeated replies in quick succession.
|
||||
> [!WARNING]
|
||||
> When migrating from official/custom firmware, backup your data and **perform factory reset** to prevent conflicts with existing settings and data:
|
||||
>
|
||||
> 1. Open device settings in the companion app and download data backup
|
||||
> 2. Go to [MeshCore Flasher](https://meshcore.io/flasher) website
|
||||
> 3. Select "Wio Tracker L1 Pro"
|
||||
> 4. Choose any of the firmware variant
|
||||
> 5. Perform "Erase flash"
|
||||
|
||||
---
|
||||
|
||||
## Font Switcher
|
||||
## Documentation
|
||||
|
||||
Both the default font and the [Lemon bitmap font](https://github.com/cmvnd/fonts) are built into every firmware variant. Switch between them at runtime in **Settings → Display → Font** — no reflashing required. The selected font is saved to flash and takes effect immediately.
|
||||
### This fork
|
||||
|
||||
The Lemon font offers:
|
||||
| Document | Description |
|
||||
| -------------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
||||
| [Messages Screen](./docs/solo_features/message_screen/message_screen.md) | Sending messages, context menus, reply, Notif/Melody overrides |
|
||||
| [Favourites Dial](./docs/solo_features/favourites_dial/favourites_dial.md) | Pinned contacts grid, unread badges, pin/unpin |
|
||||
| [Clock Screen](./docs/solo_features/clock_screen/clock_screen.md) | Clock page, date, configurable data fields |
|
||||
| [Settings Screen](./docs/solo_features/settings_screen/settings_screen.md) | All settings sections with values and interactions |
|
||||
| [Screen Lock](./docs/solo_features/screen_lock/screen_lock.md) | Lock/unlock sequence, lock screen, auto-lock |
|
||||
| [Tools Screen](./docs/solo_features/tools_screen/tools_screen.md) | GPS trail, nearby nodes, ringtone editor, auto-reply bot, auto-advert |
|
||||
|
||||
- **Native Unicode rendering** — Latin Extended, Greek, and Cyrillic characters (U+0020–U+04FF) are displayed directly without transliteration, covering Polish, Czech, Slovak, German, French, Scandinavian, Hungarian, Romanian, Croatian, Turkish, Baltic, Russian, and Greek scripts.
|
||||
- **Pixel-accurate word wrap** — text wraps based on actual glyph widths rather than a fixed character count.
|
||||
- **Slightly taller glyphs** — the font uses a 9 px line height on OLED and 10 px on e-ink, compared to 8 px for the default font on both displays.
|
||||
### Upstream MeshCore
|
||||
|
||||
| Document | Description |
|
||||
| -------------------------------------------------- | ------------------------------------------------ |
|
||||
| [FAQ](./docs/faq.md) | Frequently asked questions |
|
||||
| [CLI Commands](./docs/cli_commands.md) | Commands for repeaters, room servers and sensors |
|
||||
| [Terminal Chat CLI](./docs/terminal_chat_cli.md) | Commands for the terminal chat client |
|
||||
| [Companion Protocol](./docs/companion_protocol.md) | Serial/BLE frame protocol between device and app |
|
||||
| [Packet Format](./docs/packet_format.md) | LoRa packet structure |
|
||||
| [QR Codes](./docs/qr_codes.md) | Channel and contact QR code formats |
|
||||
|
||||
---
|
||||
|
||||
Feel free to explore, share feedback and feature requests!
|
||||
## Screenshot Tool
|
||||
|
||||
The firmware can capture the current display contents and send them over USB serial as a PNG — useful for debugging and documentation. Works with both OLED and e-ink variants.
|
||||
|
||||
> [!NOTE]
|
||||
> Requires firmware built with `-D ENABLE_SCREENSHOT`. Use the `_dev` environment or add the flag manually.
|
||||
|
||||
**1. Build and flash with screenshot support**
|
||||
|
||||
```sh
|
||||
# OLED
|
||||
PLATFORMIO_BUILD_FLAGS="-D ENABLE_SCREENSHOT" pio run -e WioTrackerL1_companion_dual -t upload
|
||||
|
||||
# E-ink
|
||||
pio run -e WioTrackerL1Eink_companion_dual_dev -t upload
|
||||
```
|
||||
|
||||
**2. Disconnect from the companion app** — USB serial is not available while BLE/app is connected
|
||||
|
||||
**3. Run the tool** — [uv](https://docs.astral.sh/uv/) is recommended for managing Python dependencies:
|
||||
|
||||
```sh
|
||||
uv run tools/screenshot.py
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
- `--port PORT` — serial port (default: auto-detect)
|
||||
- `--scale SCALE` — upscale factor for output image (default: 1)
|
||||
|
||||
**4.** Press **S** in the interactive menu to capture. Screenshots are saved to `tools/pngs/` with a timestamp filename.
|
||||
|
||||
---
|
||||
|
||||
## Development
|
||||
|
||||
@@ -279,47 +141,7 @@ This fork tracks the upstream [MeshCore](https://github.com/ripplebiz/MeshCore)
|
||||
```sh
|
||||
git config merge.ours.driver true
|
||||
```
|
||||
---
|
||||
|
||||
#### Display Screenshot Tool
|
||||
### Contributing
|
||||
|
||||
> **⚠️ Note:** The screenshot feature requires the `ENABLE_SCREENSHOT` build flag to be enabled. Add `-D ENABLE_SCREENSHOT` to your PlatformIO build flags, then recompile and flash the firmware.
|
||||
|
||||
The firmware supports capturing the current display contents and transmitting
|
||||
it over USB serial. This is useful for debugging, remote monitoring, or
|
||||
creating documentation.
|
||||
|
||||
**Important:** When the device is connected to the companion app, the USB
|
||||
serial port is not available for communication. To use the screenshot tool,
|
||||
ensure the device is not connected to the companion app.
|
||||
|
||||
**Usage:**
|
||||
|
||||
1. Build and flash firmware with `-D ENABLE_SCREENSHOT` build flag enabled
|
||||
|
||||
Example for the OLED dual firmware:
|
||||
|
||||
```
|
||||
PLATFORMIO_BUILD_FLAGS="-D ENABLE_SCREENSHOT" pio run -e WioTrackerL1_companion_dual -t upload
|
||||
```
|
||||
|
||||
2. Connect the device to your computer via USB (ensure no companion app connection)
|
||||
3. Install dependencies and run the screenshot tool. To manage python and python dependencies, use uv: https://docs.astral.sh/uv/
|
||||
|
||||
```sh
|
||||
cd tools
|
||||
uv run tools/screenshot.py
|
||||
```
|
||||
|
||||
Options:
|
||||
- `--port PORT` — Serial port to use (default: auto-detect)
|
||||
- `--scale SCALE` — Upscale factor for the output image (1=no upscale, 2=2x, 3=3x, 4=4x, etc.; default: 1)
|
||||
|
||||
4. In the tool's interactive menu, press **S** to capture a screenshot
|
||||
5. The tool will save the screenshot as a PNG file in `tools/pngs/` with a timestamp-based filename
|
||||
|
||||
**How it works:**
|
||||
- The tool sends the `CMD_GET_SCREENSHOT` command (66) to the device
|
||||
- The device responds with `RESP_CODE_SCREENSHOT` (29) containing the framebuffer data
|
||||
- The framebuffer is transmitted in chunks (128×64 display = 1024 bytes, split across multiple frames)
|
||||
- The tool reassembles the chunks and converts them to a PNG image
|
||||
Contributions are welcome. Fork the repository, make your changes, and open a pull request. Please follow the existing code style and keep changes focused.
|
||||
|
||||
BIN
docs/solo_features/clock_screen/clk_scr_1_eink.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
docs/solo_features/clock_screen/clk_scr_1_oled.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
docs/solo_features/clock_screen/clk_scr_2_eink.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
docs/solo_features/clock_screen/clk_scr_2_oled.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
55
docs/solo_features/clock_screen/clock_screen.md
Normal file
@@ -0,0 +1,55 @@
|
||||
## Clock Screen
|
||||
|
||||
[Go back](../../../README.md)
|
||||
|
||||
### Overview
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
A full-screen clock page on the home screen. Shows the current time and date, with up to three configurable data fields below.
|
||||
|
||||
Time is synchronized from GPS or via the companion app. Timezone offset is applied from **Settings › System**.
|
||||
|
||||
If no time source is available, the screen shows _"! No time sync"_ with a hint to enable GPS or connect the app.
|
||||
|
||||
---
|
||||
|
||||
### Time display
|
||||
|
||||
- **Format** — 24 h or 12 h with AM/PM; configurable in **Settings › Display**
|
||||
- **Seconds** — shown by default on OLED; hidden on e-ink (always) and optionally on OLED via **Settings › Display › Clock seconds**; hiding reduces the refresh rate from 1 s to 60 s
|
||||
|
||||
---
|
||||
|
||||
### Data fields
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Up to three data fields are shown below the date separator. Each field displays a label and a value on the same line.
|
||||
|
||||
| Field | Label | Value |
|
||||
| ----------- | ----- | ------------------------------------------------------------------------- |
|
||||
| None | — | — |
|
||||
| Batt V | Batt | Battery voltage (e.g. `3.92V`) |
|
||||
| Batt % | Batt | Battery percentage using LiPo curve anchored at the low-battery threshold |
|
||||
| Temperature | Temp | °C from onboard sensor |
|
||||
| Humidity | Hum | % from onboard sensor |
|
||||
| Pressure | Pres | hPa from onboard sensor |
|
||||
| GPS | GPS | `lat lon` decimal degrees, or `no fix` |
|
||||
| Altitude | Alt | metres from onboard sensor (GPS or barometric) |
|
||||
| Luminosity | Lux | lux from onboard sensor |
|
||||
| CO₂ | CO2 | ppm from onboard sensor |
|
||||
| Contacts | Nodes | Total contacts in the mesh |
|
||||
| Messages | Msgs | Total unread message count |
|
||||
|
||||
Sensor fields show `--` when the sensor is not connected or has no data.
|
||||
|
||||
---
|
||||
|
||||
### Configuring fields
|
||||
|
||||
**Hold Enter** (or press the **Context menu** key) on the Clock page to open the Dashboard Config screen, where each of the three field slots can be cycled with **LEFT/RIGHT**.
|
||||
BIN
docs/solo_features/favourites_dial/fav_dial_1_eink.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
docs/solo_features/favourites_dial/fav_dial_1_oled.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
60
docs/solo_features/favourites_dial/favourites_dial.md
Normal file
@@ -0,0 +1,60 @@
|
||||
## Favourites Dial
|
||||
|
||||
[Go back](../../../README.md)
|
||||
|
||||
### Overview
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :------------------------: | :------------------------: |
|
||||
|  |  |
|
||||
|
||||
A dedicated home page showing a grid of up to 6 pinned contacts for quick access. The layout adapts to the display orientation:
|
||||
|
||||
- **Portrait** (OLED, e-ink portrait) — 2 columns × 3 rows
|
||||
- **Landscape** (e-ink landscape) — 3 columns × 2 rows
|
||||
|
||||
---
|
||||
|
||||
### Navigation
|
||||
|
||||
Navigate tiles with **UP / DOWN / LEFT / RIGHT**. Pressing a directional key at the edge of the grid switches to the adjacent home page instead of wrapping.
|
||||
|
||||
**Enter on a filled tile** — opens that contact's DM directly.
|
||||
|
||||
**Enter on an empty tile (`+`)** — opens a contact picker to fill the slot.
|
||||
|
||||
---
|
||||
|
||||
### Unread badge
|
||||
|
||||
Filled tiles show an unread message count in the top-right corner when there are unread DMs from that contact. The contact name is ellipsized to make room for the badge.
|
||||
|
||||
If a pinned contact has been removed from the contacts list, the tile shows `(gone)` until the slot is reassigned.
|
||||
|
||||
---
|
||||
|
||||
### Pinning a contact
|
||||
|
||||
**From the Favourites Dial** — press **Enter** on an empty tile (`+`). A picker opens showing:
|
||||
|
||||
1. Contacts marked as favourites in the upstream app (starred contacts) — listed first
|
||||
2. Recent DM contacts — listed after
|
||||
3. All remaining chat contacts — fallback when the first two tiers are empty (e.g. fresh install before any DMs)
|
||||
|
||||
Select a contact to pin it to that slot.
|
||||
|
||||
**From a DM conversation** — **Hold Enter** › context menu › **Pin to dial**, then choose a slot from the slot picker (Slot 1–6, showing the current occupant name or "empty").
|
||||
|
||||
If the selected contact is already pinned in another slot, it is moved to the new slot automatically.
|
||||
|
||||
---
|
||||
|
||||
### Unpinning a contact
|
||||
|
||||
Open the contact's DM, **Hold Enter** › context menu › **Unpin (slot N)**.
|
||||
|
||||
---
|
||||
|
||||
### Reordering the Favourites page
|
||||
|
||||
The position of the Favourites Dial in the home page navigation sequence can be changed in **Settings › Home Pages** — press **LEFT / RIGHT** on the Favourites entry to move it earlier or later.
|
||||
BIN
docs/solo_features/message_screen/mes_scr_1_eink.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
docs/solo_features/message_screen/mes_scr_1_oled.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
docs/solo_features/message_screen/mes_scr_2_eink.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
docs/solo_features/message_screen/mes_scr_2_oled.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
docs/solo_features/message_screen/mes_scr_3_eink.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
docs/solo_features/message_screen/mes_scr_3_oled.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
docs/solo_features/message_screen/mes_scr_4_eink.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
docs/solo_features/message_screen/mes_scr_4_oled.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
docs/solo_features/message_screen/mes_scr_5_eink.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
docs/solo_features/message_screen/mes_scr_5_oled.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
docs/solo_features/message_screen/mes_scr_6_eink.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
docs/solo_features/message_screen/mes_scr_6_oled.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
docs/solo_features/message_screen/mes_scr_7_eink.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
docs/solo_features/message_screen/mes_scr_7_oled.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
111
docs/solo_features/message_screen/message_screen.md
Normal file
@@ -0,0 +1,111 @@
|
||||
## Messages Screen
|
||||
|
||||
[Go back](../../../README.md)
|
||||
|
||||
### Overview
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
The Messages screen is split into three modes — **DMs**, **Channels**, and **Rooms** — selectable with UP/DOWN on the mode-select screen. Each mode shows the corresponding list of conversations with unread counters.
|
||||
|
||||
---
|
||||
|
||||
### Sending messages
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Press **Enter** on a contact or channel to open its history, then press **Enter** again (or select an empty send row) to compose a message. Choose between:
|
||||
|
||||
- **Custom message** — opens the on-screen keyboard
|
||||
- **Q1–Q10** — quick reply templates editable in Settings › Messages
|
||||
|
||||
The keyboard supports placeholders that insert live data at send time:
|
||||
|
||||
| Placeholder | Value | Availability |
|
||||
| ----------- | -------------------- | --------------------------- |
|
||||
| `{time}` | current time (HH:MM) | always |
|
||||
| `{loc}` | GPS coordinates | always ("no GPS" if no fix) |
|
||||
| `{temp}` | temperature | sensor connected |
|
||||
| `{hum}` | humidity | sensor connected |
|
||||
| `{pres}` | barometric pressure | sensor connected |
|
||||
| `{alt}` | altitude | sensor connected |
|
||||
| `{lux}` | luminosity | sensor connected |
|
||||
| `{co2}` | CO₂ concentration | sensor connected |
|
||||
|
||||
Sensor placeholders appear automatically in the placeholder picker when the corresponding sensor is active. `{time}` and `{loc}` are always shown.
|
||||
|
||||
---
|
||||
|
||||
### Message history
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Each entry in the history list shows the sender name and a compact age indicator (`3m`, `2h`, `>1d`) in the top-right corner.
|
||||
|
||||
**Short Enter** on a message opens it in fullscreen. **Hold Enter** opens the context menu (Reply option).
|
||||
|
||||
---
|
||||
|
||||
### Fullscreen message view
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Navigate between messages with **LEFT** (newer) and **RIGHT** (older). Long messages scroll with **UP/DOWN**.
|
||||
|
||||
If the message is a reply addressed to someone (`@[nick]`), a **To: nick** bar is shown below the sender name and the body is displayed without the address prefix.
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
**Hold Enter** in fullscreen opens the Reply option.
|
||||
|
||||
---
|
||||
|
||||
### Context menu — contact list
|
||||
|
||||
**Hold Enter** on a contact entry opens a context menu:
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
| Item | Action |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------ |
|
||||
| Mark as read | Clears unread counter for this contact |
|
||||
| Notif: default / OFF / ON | Per-contact notification override — **LEFT/RIGHT** to cycle |
|
||||
| Melody: global / M1 / M2 | Per-contact melody override — **LEFT/RIGHT** to cycle |
|
||||
| Pin to dial / Unpin (slot N) | Pin this contact to a Favourites Dial slot; if already pinned shows which slot |
|
||||
|
||||
When **Pin to dial** is selected, a slot picker opens (Slot 1–6 showing current occupant name or "empty"). Choosing a slot that already holds another contact moves the new contact there.
|
||||
|
||||
---
|
||||
|
||||
### Context menu — channel list
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
**Hold Enter** on a channel entry opens a context menu:
|
||||
|
||||
| Item | Action |
|
||||
| ------------------------- | --------------------------------------------------------------------- |
|
||||
| Mark all read | Clears all unread for this channel |
|
||||
| Notif: default / OFF / ON | Per-channel notification override — **LEFT/RIGHT** to cycle |
|
||||
| Melody: global / M1 / M2 | Per-channel melody override — **LEFT/RIGHT** to cycle |
|
||||
| Fav: yes / no | Add or remove this channel from favourites — **LEFT/RIGHT** to toggle |
|
||||
|
||||
---
|
||||
|
||||
### Mark all read
|
||||
|
||||
**Hold Enter** on the DM / Channels / Rooms mode-select screen to clear all unread counters for the highlighted category at once.
|
||||
BIN
docs/solo_features/screen_lock/lck_scr_1_eink.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
docs/solo_features/screen_lock/lck_scr_1_oled.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
docs/solo_features/screen_lock/lck_scr_2_eink.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
docs/solo_features/screen_lock/lck_scr_2_oled.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
51
docs/solo_features/screen_lock/screen_lock.md
Normal file
@@ -0,0 +1,51 @@
|
||||
## Screen Lock
|
||||
|
||||
[Go back](../../../README.md)
|
||||
|
||||
### Overview
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Screen lock prevents accidental keypresses. While locked the display turns off and all input is ignored.
|
||||
|
||||
---
|
||||
|
||||
### Locking and unlocking
|
||||
|
||||
**Hold Back** and press **Enter** three times within 3 seconds. The sequence works in both directions — the same combination locks and unlocks.
|
||||
|
||||
If the display is off when the sequence begins, it turns on automatically so the hint is visible. Each press in the sequence extends the display-on timer by 5 seconds.
|
||||
|
||||
The hint popup at the bottom of the lock screen guides through the sequence:
|
||||
|
||||
| Step | Hint |
|
||||
| -------------- | --------------------- |
|
||||
| Not started | _Hold Back + 3×Enter_ |
|
||||
| 1 press done | _Enter ×2 more…_ |
|
||||
| 2 presses done | _Enter ×1 more…_ |
|
||||
|
||||
If no press is made for 3 seconds, the counter resets.
|
||||
|
||||
---
|
||||
|
||||
### Lock screen
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
A brief press of any button wakes the display and shows the lock screen. It displays:
|
||||
|
||||
- **Time** — large, same format as the Clock page (24 h / 12 h from Settings)
|
||||
- **Date** — day-of-week, day, month
|
||||
- **Two sensor values** — the first two Dashboard Config fields (same values configured for the Clock page); shown side by side if both are set
|
||||
|
||||
The display turns off again automatically after 5 seconds of inactivity (or 2 seconds immediately after locking).
|
||||
|
||||
---
|
||||
|
||||
### Auto-lock
|
||||
|
||||
Enable **Auto-lock** in **Settings › Display** to lock the device automatically whenever the display turns off due to auto-off timeout. With auto-lock on, the device is always locked after the screen goes dark — no manual lock needed.
|
||||
BIN
docs/solo_features/settings_screen/set_scr_1_eink.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
docs/solo_features/settings_screen/set_scr_1_oled.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
docs/solo_features/settings_screen/set_scr_2_eink.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
docs/solo_features/settings_screen/set_scr_2_oled.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
91
docs/solo_features/settings_screen/settings_screen.md
Normal file
@@ -0,0 +1,91 @@
|
||||
## Settings Screen
|
||||
|
||||
[Go back](../../../README.md)
|
||||
|
||||
### Overview
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
All settings are saved to flash and restored on next boot. Settings are organised into collapsible sections. Press **Enter** on a section header to expand or collapse it — all sections start collapsed for faster navigation. Press **LEFT/RIGHT** to change a value, or **Enter** for toggle items.
|
||||
|
||||
Press **Cancel/Back** to save and return to the home screen.
|
||||
|
||||
---
|
||||
|
||||
### Display
|
||||
|
||||
| Setting | Options | Notes |
|
||||
| ------------------------------------ | -------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| Brightness | 1–5 | LEFT/RIGHT; preview applies immediately |
|
||||
| Auto-off | 5 s / 15 s / 30 s / 60 s / never | LEFT/RIGHT |
|
||||
| Auto-lock | on / off | Locks device when display turns off |
|
||||
| Battery | icon / % / V | Display mode for the top-bar battery indicator |
|
||||
| Clock seconds | show / hide | Hiding reduces OLED refresh from 1 s to 60 s |
|
||||
| Clock format | 24 h / 12 h | 12 h appends AM/PM |
|
||||
| Font | Default / Lemon | Default: 5×7 Adafruit with ASCII transliteration; Lemon: native Unicode with pixel-accurate line wrap |
|
||||
| Display rotation _(e-ink only)_ | 0° / 90° / 180° / 270° | Applied immediately |
|
||||
| Joystick rotation _(e-ink only)_ | 0° / 90° / 180° / 270° | Rotates input mapping independently of display rotation; useful for custom enclosures |
|
||||
| Full refresh interval _(e-ink only)_ | off / 5 / 10 / 20 / 30 | Partial refreshes between full clears; reduces ghosting on long sessions |
|
||||
|
||||
---
|
||||
|
||||
### Sound
|
||||
|
||||
| Setting | Options | Notes |
|
||||
| -------------- | ------------------------------ | ------------------------------------------------------------ |
|
||||
| Buzzer | On / Off / Auto | Auto: silences while BLE connected, re-enables on disconnect |
|
||||
| Volume | 1–5 | LEFT/RIGHT; preview tone plays on each change |
|
||||
| DM Melody | built-in / Melody 1 / Melody 2 | Notification sound for incoming private messages |
|
||||
| Channel Melody | built-in / Melody 1 / Melody 2 | Notification sound for incoming channel messages |
|
||||
|
||||
Melody 1 and Melody 2 are custom sequences editable in **Tools › Ringtone Editor**.
|
||||
|
||||
---
|
||||
|
||||
### Home Pages
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Lists all available home screen pages. For each entry:
|
||||
|
||||
- **LEFT / RIGHT** — move the page earlier or later in the navigation sequence
|
||||
- **Enter** — toggle the page ON / OFF
|
||||
|
||||
**Settings** and **Messages** are always visible and cannot be disabled.
|
||||
|
||||
---
|
||||
|
||||
### Radio
|
||||
|
||||
| Setting | Options | Notes |
|
||||
| -------- | -------- | ---------- |
|
||||
| TX power | 2–22 dBm | LEFT/RIGHT |
|
||||
|
||||
---
|
||||
|
||||
### System
|
||||
|
||||
| Setting | Options | Notes |
|
||||
| ----------- | --------------------------------------------------- | -------------------------------------------------------------------------------------- |
|
||||
| Timezone | −12 h … +14 h | UTC offset in whole hours |
|
||||
| Low battery | off / 3.0 V / 3.1 V / 3.2 V / 3.3 V / 3.4 V / 3.5 V | Auto-shutdown threshold; also sets the 0 % anchor for the battery percentage indicator |
|
||||
|
||||
---
|
||||
|
||||
### Contacts
|
||||
|
||||
| Setting | Options | Notes |
|
||||
| -------- | ---------------- | ---------------------------------------------------- |
|
||||
| DMs | all / favourites | Show all chat contacts or only upstream-starred ones |
|
||||
| Channels | all / favourites | Show all channels or only favourited ones |
|
||||
| Rooms | all / favourites | Show all room servers or only favourited ones |
|
||||
|
||||
---
|
||||
|
||||
### Messages
|
||||
|
||||
Up to 10 quick reply templates (Q1–Q10). Press **Enter** on a slot to open the keyboard editor. Supports the same placeholders as the main keyboard (`{time}`, `{loc}`, and sensor placeholders when connected).
|
||||
BIN
docs/solo_features/tools_screen/tls_scr_1_eink.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
docs/solo_features/tools_screen/tls_scr_1_oled.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
docs/solo_features/tools_screen/tls_scr_2_eink.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
docs/solo_features/tools_screen/tls_scr_2_oled.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
docs/solo_features/tools_screen/tls_scr_3_eink.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
docs/solo_features/tools_screen/tls_scr_3_oled.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
docs/solo_features/tools_screen/tls_scr_4_eink.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
docs/solo_features/tools_screen/tls_scr_4_oled.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
docs/solo_features/tools_screen/tls_scr_5_eink.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
docs/solo_features/tools_screen/tls_scr_5_oled.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
docs/solo_features/tools_screen/tls_scr_6_eink.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
docs/solo_features/tools_screen/tls_scr_6_oled.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
docs/solo_features/tools_screen/tls_scr_7_eink.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
docs/solo_features/tools_screen/tls_scr_7_oled.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
173
docs/solo_features/tools_screen/tools_screen.md
Normal file
@@ -0,0 +1,173 @@
|
||||
## Tools Screen
|
||||
|
||||
[Go back](../../../README.md)
|
||||
|
||||
### Overview
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
The Tools screen is a hub for GPS trail recording, nearby node browsing, ringtone editing, auto-reply bot, and auto-advert. Navigate the tool list with **UP/DOWN** and press **Enter** to open a tool.
|
||||
|
||||
---
|
||||
|
||||
## Nearby Nodes
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Browse nodes that have recently advertised on the mesh. Filter by category with **LEFT/RIGHT**:
|
||||
|
||||
| Filter | Shows |
|
||||
| ------ | ------------------------------ |
|
||||
| Fav | Upstream-starred contacts only |
|
||||
| ALL | All known nodes |
|
||||
| Comp | Companion (chat) nodes |
|
||||
| Rpt | Repeaters |
|
||||
| Room | Room servers |
|
||||
| Snsr | Sensors |
|
||||
|
||||
Select a node to see its coordinates, distance, bearing with cardinal direction, type, and last-heard time.
|
||||
|
||||
**Hold Enter** → context menu → **Discover nearby** to send a live `NODE_DISCOVER_REQ` ping.
|
||||
|
||||
> [!TIP]
|
||||
> Combined with **Auto-Advert** on the other device, Nearby Nodes becomes a passive location tracker — as long as the tracked device periodically broadcasts its GPS position, you can see its current distance and bearing without any manual interaction on either end.
|
||||
|
||||
---
|
||||
|
||||
### Active Discovery
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Sends a `NODE_DISCOVER_REQ` ping. Repeaters, sensors and room servers within zero-hop range respond immediately with name, type and signal data.
|
||||
|
||||
Results show as 2-line cards: node name + type, then RSSI / SNR / remote SNR.
|
||||
|
||||
- **UP/DOWN** — navigate results
|
||||
- **Enter** — open full-screen detail (public key, signal data, contact status)
|
||||
- **Hold Enter** — rescan
|
||||
- **Cancel / Back** — return to nearby list
|
||||
|
||||
---
|
||||
|
||||
## GPS Trail
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Records your route in a RAM ring buffer (up to 512 points, sampled every 1 s). Tracking runs in the background — a blinking **G** appears in the status bar. The trail survives display auto-off but is lost on reboot unless saved to flash first.
|
||||
|
||||
Cycle views with **LEFT / RIGHT**:
|
||||
|
||||
| View | Content |
|
||||
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Summary** | Distance, elapsed time, avg speed or pace, point count, tracking status |
|
||||
| **Map** | Auto-fit dot-and-line plot with cos(lat) aspect correction; segment breaks marked; north arrow; scale grid (toggle with **LEFT/RIGHT** on the Grid row in the menu) |
|
||||
| **List** | Per-point rows showing local time (HH:MM) and delta distance from the previous point; segment-start rows show `start`; scroll with **UP/DOWN** |
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
**Hold Enter** opens the action menu:
|
||||
|
||||
| Item | Interaction | Action |
|
||||
| --------------------- | ------------------- | --------------------------------------------------- |
|
||||
| Min dist | LEFT/RIGHT | Filter gate: 5 m / 10 m / 25 m / 100 m |
|
||||
| Units | LEFT/RIGHT | Speed/pace: km/h / mph / min/km / min/mi |
|
||||
| Grid | LEFT/RIGHT or Enter | Toggle scale grid on the map |
|
||||
| Start / Stop tracking | Enter | Begin or end a recording session |
|
||||
| Save trail | Enter | Write RAM ring to flash (`/trail`) |
|
||||
| Load trail | Enter | Restore flash trail into RAM |
|
||||
| Export (live) | Enter | Stream live RAM trail as GPX 1.1 over USB Serial |
|
||||
| Export (saved) | Enter | Stream saved flash trail as GPX 1.1 over USB Serial |
|
||||
| Reset trail | Enter | Clear RAM ring and elapsed time |
|
||||
|
||||
### Downloading GPX
|
||||
|
||||
1. Connect the device via USB cable
|
||||
2. Open a serial terminal at **115200 baud**:
|
||||
- **macOS/Linux** — `cat /dev/tty.usbmodem* > track.gpx` (stop with Ctrl-C after dump completes)
|
||||
- **Windows** — PuTTY (Serial, 115200) or Arduino IDE Serial Monitor (no line ending)
|
||||
3. On the device: **Tools › Trail** → **Hold Enter** → **Export (live)** or **Export (saved)**
|
||||
4. The device streams a GPX 1.1 XML document. Save the output from `<?xml` to `</gpx>` as a `.gpx` file
|
||||
5. Import into OsmAnd, Garmin BaseCamp, GPX Studio, Google Earth, etc.
|
||||
|
||||
> [!NOTE]
|
||||
> If the companion app is connected via **BLE**, the export is safe — BLE and USB operate independently. If connected via **USB**, disconnect the app before exporting.
|
||||
|
||||
---
|
||||
|
||||
## Auto-Advert
|
||||
|
||||
Periodically broadcasts a 0-hop advert with your GPS position. Configurable interval: off / 30 s / 1 min / 2 min / 5 min / 10 min / 30 min / 1 h. A blinking **A** appears in the status bar while active.
|
||||
|
||||
---
|
||||
|
||||
## Ringtone Editor
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
A step sequencer for composing custom notification melodies. Two slots — **Melody 1** and **Melody 2** — switchable from within the editor.
|
||||
|
||||
Each melody supports up to 32 notes:
|
||||
|
||||
| Parameter | Options |
|
||||
| --------- | --------------------------------- |
|
||||
| Pitch | C / D / E / F / G / A / B / pause |
|
||||
| Octave | 4 – 7 |
|
||||
| Duration | 1/4 / 1/8 / 1/16 / 1/32 |
|
||||
| BPM | 60 / 90 / 120 / 150 / 180 |
|
||||
|
||||
**Navigation in the editor:**
|
||||
|
||||
- **LEFT/RIGHT** — move between notes
|
||||
- **UP/DOWN** — change pitch of selected note
|
||||
- **Enter** — cycle octave of selected note
|
||||
- **Hold Enter** (or context menu) — open options menu
|
||||
|
||||
**Options menu:**
|
||||
|
||||
| Item | Interaction | Action |
|
||||
| ------------ | ----------- | -------------------------------------- |
|
||||
| Play / Stop | Enter | Preview the melody |
|
||||
| Melody 1 / 2 | Enter | Switch to the other slot |
|
||||
| Duration | LEFT/RIGHT | Cycle duration for selected note |
|
||||
| BPM | LEFT/RIGHT | Cycle tempo |
|
||||
| Insert | Enter | Insert a new note after the cursor |
|
||||
| Delete | Enter | Delete the note at cursor |
|
||||
| Save & Exit | Enter | Persist the melody and return to Tools |
|
||||
| Discard | Enter | Return to Tools without saving |
|
||||
|
||||
Melodies can be assigned in **Settings › Sound** (global default) or overridden per contact or channel from the Messages screen context menu.
|
||||
|
||||
---
|
||||
|
||||
## Auto-Reply Bot
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Automatically replies to incoming messages that contain a configured trigger word (case-insensitive, contains match).
|
||||
|
||||
When the bot is enabled it listens to DMs by default. Channel monitoring is an optional addition — select a channel separately to activate it alongside DM mode.
|
||||
|
||||
| Setting | Description |
|
||||
| ------------- | -------------------------------------------------------------------------------- |
|
||||
| Bot | ON / OFF — enables DM listening |
|
||||
| Channel mode | ON / OFF — additionally monitors a selected channel |
|
||||
| Channel | Which channel to monitor (only relevant when channel mode is ON) |
|
||||
| Trigger | Word or phrase that activates the reply (shared by both modes, case-insensitive) |
|
||||
| DM reply | Reply text for DMs; supports `{time}` and `{loc}` placeholders |
|
||||
| Channel reply | Reply text for channel messages; supports `{time}` and `{loc}` placeholders |
|
||||
|
||||
A 10-second cooldown prevents repeated replies in quick succession.
|
||||
@@ -15,9 +15,9 @@ class UITask;
|
||||
#define FIRMWARE_BUILD_DATE "12 May 2026"
|
||||
#endif
|
||||
|
||||
// Versioning: vX.Y = upstream base, plus.N = fork revision
|
||||
// Versioning: vX.Y = upstream base, solo.N = fork revision
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "v1.15-plus.1"
|
||||
#define FIRMWARE_VERSION "v1.15-solo.1"
|
||||
#endif
|
||||
|
||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||
|
||||
@@ -37,7 +37,7 @@ class SplashScreen : public UIScreen {
|
||||
UITask* _task;
|
||||
unsigned long dismiss_after;
|
||||
char _version_info[12];
|
||||
char _plus_ver[12];
|
||||
char _solo_ver[12];
|
||||
|
||||
public:
|
||||
SplashScreen(UITask* task) : _task(task) {
|
||||
@@ -45,13 +45,13 @@ public:
|
||||
strncpy(_version_info, MESHCORE_VERSION, sizeof(_version_info) - 1);
|
||||
_version_info[sizeof(_version_info) - 1] = '\0';
|
||||
|
||||
// Plus firmware version: strip commit hash suffix (v1.11-abcdef -> v1.11)
|
||||
// Solo firmware version: strip commit hash suffix (v1.15-solo.1-abcdef -> v1.15)
|
||||
const char *ver = FIRMWARE_VERSION;
|
||||
const char *dash = strchr(ver, '-');
|
||||
int plen = dash ? (int)(dash - ver) : (int)strlen(ver);
|
||||
if (plen >= (int)sizeof(_plus_ver)) plen = sizeof(_plus_ver) - 1;
|
||||
memcpy(_plus_ver, ver, plen);
|
||||
_plus_ver[plen] = '\0';
|
||||
if (plen >= (int)sizeof(_solo_ver)) plen = sizeof(_solo_ver) - 1;
|
||||
memcpy(_solo_ver, ver, plen);
|
||||
_solo_ver[plen] = '\0';
|
||||
|
||||
dismiss_after = millis() + BOOT_SCREEN_MILLIS;
|
||||
}
|
||||
@@ -78,16 +78,16 @@ public:
|
||||
display.setTextSize(1);
|
||||
display.drawTextCentered(display.width()/2, date_y, FIRMWARE_BUILD_DATE);
|
||||
|
||||
#ifdef FIRMWARE_PLUS_BUILD
|
||||
int plus_y = date_y + step;
|
||||
display.fillRect(0, plus_y - 1, display.width(), lh + 2);
|
||||
#ifdef FIRMWARE_SOLO_BUILD
|
||||
int solo_y = date_y + step;
|
||||
display.fillRect(0, solo_y - 1, display.width(), lh + 2);
|
||||
display.setColor(DisplayDriver::DARK);
|
||||
char plus_label[24];
|
||||
if (_plus_ver[0])
|
||||
snprintf(plus_label, sizeof(plus_label), "Plus %s for Wio", _plus_ver);
|
||||
char solo_label[24];
|
||||
if (_solo_ver[0])
|
||||
snprintf(solo_label, sizeof(solo_label), "Solo %s for Wio", _solo_ver);
|
||||
else
|
||||
snprintf(plus_label, sizeof(plus_label), "Plus for Wio");
|
||||
display.drawTextCentered(display.width()/2, plus_y, plus_label);
|
||||
snprintf(solo_label, sizeof(solo_label), "Solo for Wio");
|
||||
display.drawTextCentered(display.width()/2, solo_y, solo_label);
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
#endif
|
||||
|
||||
@@ -216,8 +216,23 @@ class HomeScreen : public UIScreen {
|
||||
}
|
||||
}
|
||||
}
|
||||
// 3) Fallback: all remaining chat contacts not already in the list.
|
||||
if (_pin_count == 0) {
|
||||
_task->showAlert("No fav contacts", 1000);
|
||||
for (int idx = 0; _pin_count < PIN_PICKER_MAX; idx++) {
|
||||
ContactInfo c;
|
||||
if (!the_mesh.getContactByIdx(idx, c)) break;
|
||||
if (c.type != ADV_TYPE_CHAT) continue;
|
||||
bool dup = false;
|
||||
for (int j = 0; j < _pin_count; j++)
|
||||
if (memcmp(_pin_keys[j], c.id.pub_key, NodePrefs::FAVOURITE_PREFIX_LEN) == 0) { dup = true; break; }
|
||||
if (dup) continue;
|
||||
memcpy(_pin_keys[_pin_count], c.id.pub_key, NodePrefs::FAVOURITE_PREFIX_LEN);
|
||||
DisplayDriver::translateUTF8Static(_pin_labels[_pin_count], c.name, sizeof(_pin_labels[_pin_count]));
|
||||
_pin_count++;
|
||||
}
|
||||
}
|
||||
if (_pin_count == 0) {
|
||||
_task->showAlert("No contacts", 1000);
|
||||
_pin_target_slot = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ build_flags = ${nrf52_base.build_flags}
|
||||
-D UI_HAS_JOYSTICK_UPDOWN=1
|
||||
-D PIN_BUZZER=12
|
||||
-D QSPIFLASH=1
|
||||
-D FIRMWARE_PLUS_BUILD=1
|
||||
-D FIRMWARE_SOLO_BUILD=1
|
||||
-D MESHCORE_VERSION='"1.15"'
|
||||
-D UI_SENSORS_PAGE=1
|
||||
-D BLE_PIN_CODE=123456
|
||||
|
||||
@@ -69,7 +69,7 @@ build_flags = ${WioTrackerL1.build_flags}
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D PIN_BUZZER=12
|
||||
-D QSPIFLASH=1
|
||||
-D FIRMWARE_PLUS_BUILD=1
|
||||
-D FIRMWARE_SOLO_BUILD=1
|
||||
-D MESHCORE_VERSION='"1.15"'
|
||||
-D UI_SENSORS_PAGE=1
|
||||
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
|
||||
@@ -111,7 +111,7 @@ build_flags = ${WioTrackerL1.build_flags}
|
||||
-D PIN_BUZZER=12
|
||||
-D QSPIFLASH=1
|
||||
-D ADVERT_NAME='"@@MAC"'
|
||||
-D FIRMWARE_PLUS_BUILD=1
|
||||
-D FIRMWARE_SOLO_BUILD=1
|
||||
-D MESHCORE_VERSION='"1.15"'
|
||||
-D UI_SENSORS_PAGE=1
|
||||
-D ENV_PIN_SDA=PIN_WIRE1_SDA
|
||||
|
||||