docs: stage I3 -- documentation rewritten under docs/solo
Short pages by feature (getting started, messages, contacts, navigation,
tools, settings, lock, hardware) instead of one page per OLED screen, with
Wio Tracker L2 differences as notes; facts checked against the code
(keyboard scripts vs. hold-for-accents, {batt}/{dist}, L2 limits and
settings layout). Developer guides and build flags under docs/solo/developer.
Old docs/solo_features and its ~50 screenshots removed; a hero banner and
three simulator screenshots added; links updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@@ -1,3 +1,5 @@
|
||||
<p align="center"><img src="./docs/solo/img/hero.png" alt="MeshCore Solo" width="640"></p>
|
||||
|
||||
# MeshCore Solo Companion Firmware
|
||||
|
||||
A fork of the official [MeshCore](https://github.com/meshcore-dev/MeshCore) companion radio firmware with a full standalone on-device UI — messages, contacts, GPS navigation and tools without a phone.
|
||||
@@ -27,7 +29,7 @@ Discussion: [MeshCore Discord](https://discord.gg/sdhYArU2jr) — [Solo firmware
|
||||
|
||||
Firmware files are on the [releases page](https://github.com/MarekZegare4/MeshCore-Solo/releases). Every binary serves the companion app over both BLE and USB serial.
|
||||
|
||||
Heltec V3/V4 need [a keyboard or joystick wired up](./docs/solo_features/external_keyboard.md#wiring-heltec-v3--v4); ProMicro needs a CardKB; the T-Echo Lite needs the KeyShield. The rest work out of the box.
|
||||
Heltec V3/V4 need [a keyboard or joystick wired up](./docs/solo/hardware.md#wiring-on-the-heltec-v3--v4); ProMicro needs a CardKB; the T-Echo Lite needs the KeyShield. The rest work out of the box.
|
||||
|
||||
---
|
||||
|
||||
@@ -47,7 +49,7 @@ Heltec V3/V4 need [a keyboard or joystick wired up](./docs/solo_features/externa
|
||||
|
||||
## Documentation
|
||||
|
||||
[docs/solo_features](./docs/solo_features/README.md) — features, screens, external keyboards, build flags and developer guides.
|
||||
[Documentation](./docs/solo/README.md) — getting started, messages, navigation, tools, settings, hardware and developer guides.
|
||||
|
||||
**Solo Tools** — [a web app](https://marekzegare4.github.io/Solo-tools/) (Chromium, Web Serial) that takes screenshots and exports the GPS trail as GPX over USB; the same as local scripts in [tools/](./tools/README.md).
|
||||
|
||||
@@ -60,7 +62,7 @@ pio run -e <env> -t upload # build and flash ov
|
||||
FIRMWARE_VERSION=v1.0.0 bash build.sh build-firmware <env> # release artifacts into out/
|
||||
```
|
||||
|
||||
Environments are the `*_solo_dual` (OLED / e-ink) and `*_solo_lvgl` (touch) entries in `solo/<board>/platformio.ini`. Optional hardware (CardKB, joystick, GPIO, buzzer…) is enabled with [build flags](./docs/solo_features/build_flags.md). Releasing: [RELEASE.md](./RELEASE.md).
|
||||
Environments are the `*_solo_dual` (OLED / e-ink) and `*_solo_lvgl` (touch) entries in `solo/<board>/platformio.ini`. Optional hardware (CardKB, joystick, GPIO, buzzer…) is enabled with [build flags](./docs/solo/developer/build-flags.md). Releasing: [RELEASE.md](./RELEASE.md).
|
||||
|
||||
This README is protected from upstream merges via `.gitattributes`; after cloning run once `git config merge.ours.driver true`.
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<p align="center"><img src="./img/hero.png" alt="MeshCore Solo" width="640"></p>
|
||||
|
||||
# MeshCore Solo
|
||||
|
||||
Solo is a MeshCore companion firmware that works on its own: messages, contacts,
|
||||
GPS navigation and tools right on the device, no phone needed. The phone app
|
||||
still connects as with the stock firmware, over Bluetooth or USB.
|
||||
|
||||
**Try it in your browser: [solo.marekzegarek.com](https://solo.marekzegarek.com)**
|
||||
|
||||
## What it does
|
||||
|
||||
- **Messages without a phone**: channels, direct messages and rooms, with
|
||||
quick replies, live placeholders (`{loc}`, `{time}`, sensor readings) and
|
||||
keyboards for Latin, Cyrillic, Greek and European diacritics.
|
||||
- **GPS navigation**: trail recording with GPX export, waypoints, a compass,
|
||||
navigate to any node, waypoint or shared location, live location sharing
|
||||
and a geofence alert (Locator).
|
||||
- **Nearby nodes**: who's around, signal and distance, ping, and remote
|
||||
admin of your repeaters and rooms.
|
||||
- **Tools**: clock with alarm, timer and stopwatch, a remote bot that answers
|
||||
commands over the mesh, repeater mode, a ringtone editor, diagnostics.
|
||||
- **Screen lock** with an optional PIN.
|
||||
- **On the Wio Tracker L2**: an offline map, message history on the SD card,
|
||||
the SD card as a USB drive, updates over WiFi.
|
||||
|
||||
## Devices
|
||||
|
||||
The firmware is the same everywhere; how you drive it depends on the device.
|
||||
These docs mark the differences with notes like this:
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** what's different on the touch screen.
|
||||
|
||||
| Group | Devices | Controls |
|
||||
| ----- | ------- | -------- |
|
||||
| **Joystick** | Wio Tracker L1 (OLED / e-ink), GAT562 30S, GAT562 Watch13, Heltec V3/V4 with a joystick | Four directions, Enter, Back |
|
||||
| **Keyboard** | M5Stack Cardputer ADV, T-Echo Lite + KeyShield, any board with a CardKB | Keys; arrows or their Fn combinations for the directions |
|
||||
| **Touch** | Wio Tracker L2 | Taps, swipes and holds; two side buttons |
|
||||
|
||||
| OLED / e-ink | | Wio Tracker L2 |
|
||||
| :---: | :---: | :---: |
|
||||
|  |  |  |
|
||||
|
||||
The joystick and keyboard devices share one interface, sized for small OLED
|
||||
and e-ink screens. The Wio Tracker L2 has its own, built for a 320 × 240
|
||||
colour touch screen, with extras its hardware allows: an offline map, message
|
||||
history on the SD card and updates over WiFi.
|
||||
|
||||
## Pages
|
||||
|
||||
- [Getting started](./getting-started.md): controls, the home screen, the phone app, updates
|
||||
- [Messages](./messages.md): channels, direct messages, rooms, typing
|
||||
- [Contacts](./contacts.md): nearby nodes, favourites, remote admin
|
||||
- [Navigation](./navigation.md): GPS, trail, waypoints, compass, sharing your location, the map
|
||||
- [Tools](./tools.md): clock tools, bot, repeater, ringtones, diagnostics
|
||||
- [Settings](./settings.md): what is where
|
||||
- [Screen lock](./lock.md): locking, auto-lock, PIN
|
||||
- [Hardware](./hardware.md): external keyboards and joysticks, e-ink, SD card, WiFi
|
||||
|
||||
For developers: [UI Core](./developer/ui-core.md), [UI framework](./developer/ui-framework.md), [build flags](./developer/build-flags.md).
|
||||
|
||||
## Contributors
|
||||
|
||||
Big thanks to the people who contributed to Solo:
|
||||
[vanous](https://github.com/vanous), [marczykm](https://github.com/marczykm),
|
||||
[tchellow](https://github.com/tchellow) and [3urobeat](https://github.com/3urobeat).
|
||||
|
||||
Built on [MeshCore](https://github.com/meshcore-dev/MeshCore) and the work of
|
||||
its [community](https://github.com/meshcore-dev/MeshCore/graphs/contributors).
|
||||
@@ -0,0 +1,69 @@
|
||||
# Contacts
|
||||
|
||||
## Nearby nodes
|
||||
|
||||
**Tools › Nodes** lists the nodes the device has heard: their type, how long
|
||||
ago, and, when they have a position, distance and bearing. **Left / Right**
|
||||
filters by type (All, Fav, Companions, Repeaters, Rooms, Sensors); the sort,
|
||||
by distance or by last heard, is in the options. A ★ marks a favourite, a ♦
|
||||
someone sharing their position live.
|
||||
|
||||
**Enter** shows a node's details. **Hold Enter**, in the list or the details,
|
||||
for what you can do with it:
|
||||
|
||||
| Option | Does |
|
||||
| ------ | ---- |
|
||||
| Navigate | Distance and bearing to the node; follows it if it shares its position live |
|
||||
| Ping | Sends a ping and shows the round trip time and SNR |
|
||||
| Save waypoint, Set as target | Its position as a waypoint, or as the [Locator](./navigation.md#locator) target |
|
||||
| Fav, Pin to dial | Favourite, or a place on the Favourites page |
|
||||
| Admin | Remote admin, for a repeater or room (below) |
|
||||
| Discover scan | Asks the repeaters, rooms and sensors in direct range to answer, with their signal |
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** the **Nodes** app. Filter chips at the top, the sort in
|
||||
> the header, and a map button that shows every node with a position. A
|
||||
> node's card has buttons for the same actions, plus **Add** for a node that
|
||||
> isn't a contact yet and **Delete**.
|
||||
|
||||
## Favourites
|
||||
|
||||
The **Favourites** home page holds six slots for the conversations you open
|
||||
most: a contact, a room or a channel, each with its unread count. **Enter** on
|
||||
an empty slot picks one from Messages; **hold Enter** on a filled slot to
|
||||
replace or remove it. **Pin to dial** in any contact, channel or node menu
|
||||
does the same.
|
||||
|
||||
A pinned slot is not the same as a favourite. **Fav** is the star shared with
|
||||
the phone app: it sorts contacts to the top and drives the "favourites only"
|
||||
filters in Settings › Contacts.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** the first home page. Tap a slot to open it, hold it to
|
||||
> change it.
|
||||
|
||||
## Cleaning up
|
||||
|
||||
Settings › Contacts › **Expire** (7, 30 or 90 days) sets when a contact you
|
||||
haven't heard from counts as inactive, and **Prune now** removes those after
|
||||
showing how many it will delete. Favourites are always kept, and nothing is
|
||||
removed without **Prune now**.
|
||||
|
||||
## Remote admin
|
||||
|
||||
**Tools › Admin** manages a repeater or room server you are an admin on, the
|
||||
same way the phone app does. Pick the node, type its admin password (saved for
|
||||
next time), then choose a field:
|
||||
|
||||
- **System**: name, owner info, admin password.
|
||||
- **Radio**: frequency, bandwidth, spreading factor, coding rate, TX power.
|
||||
- **Routing**: repeat on/off, advert intervals, max hops.
|
||||
- **Actions**: send an advert, sync its clock, reboot, start OTA, or any
|
||||
[CLI command](../cli_commands.md).
|
||||
|
||||
Name and owner info are read from the node first, so you edit the current
|
||||
value. Reboot and OTA ask before sending.
|
||||
|
||||
> [!WARNING]
|
||||
> Admin commands change the remote node. Check the node and the value before
|
||||
> sending.
|
||||
@@ -1,6 +1,6 @@
|
||||
## Build Flags
|
||||
|
||||
[Go back](../../README.md)
|
||||
[Go back](../README.md)
|
||||
|
||||
Reference for the `-D` build flags a Solo build understands beyond the
|
||||
per-board defaults already set in `solo/<board>/platformio.ini`. Add any of
|
||||
@@ -11,7 +11,7 @@ isn't there costs nothing and can't brick a build; the exceptions (pin
|
||||
conflicts, wrong polarity) are called out per flag.
|
||||
|
||||
None of this needs touching to get a board running — see the
|
||||
[environment table](../../README.md#building-from-source) for the flag-free
|
||||
[environment list](../../../README.md#building) for the flag-free
|
||||
default build for each supported board.
|
||||
|
||||
---
|
||||
@@ -48,11 +48,11 @@ existing `solo/<board>/platformio.ini` for what's already claimed).
|
||||
|
||||
| Flag | Adds |
|
||||
| --- | --- |
|
||||
| `ENV_PIN_SDA` / `ENV_PIN_SCL` | CardKB (M5Stack I2C keyboard, addr `0x5F`) on a second I2C bus (resolves to `Wire1`). Probed at boot — harmless with nothing plugged in. See [External Keyboard & Joystick](./external_keyboard.md). |
|
||||
| `ENV_PIN_SDA` / `ENV_PIN_SCL` | CardKB (M5Stack I2C keyboard, addr `0x5F`) on a second I2C bus (resolves to `Wire1`). Probed at boot — harmless with nothing plugged in. See [External Keyboard & Joystick](../hardware.md#external-keyboard-and-joystick). |
|
||||
| `CARDKB_I2C=<Wire\|Wire1>` | Same CardKB support, naming the bus directly — for a board with no free pins for a second bus, set `CARDKB_I2C=Wire` to share the primary bus (already used by the display/RTC) instead of defining `ENV_PIN_SDA`/`ENV_PIN_SCL`. Takes precedence if both are somehow set. |
|
||||
| `UI_HAS_JOYSTICK=1` + `UI_HAS_JOYSTICK_UPDOWN=1` (optional) + `JOYSTICK_UP` / `JOYSTICK_DOWN` / `JOYSTICK_LEFT` / `JOYSTICK_RIGHT` + `PIN_USER_BTN` + `PIN_BACK_BTN` | A wired joystick (four direction contacts + a press contact for Enter). Replaces single-button navigation entirely once enabled. See [External Keyboard & Joystick](./external_keyboard.md). |
|
||||
| `PIN_GPIO1` .. `PIN_GPIO4` | Up to four general-purpose pins, each independently switchable between Off / Input / Output (GPIO1/GPIO2 also get an Analog step, if wired to an ADC-capable pin) from Tools › GPIO, and via the `!gpio1`..`!gpio4` bot commands. Not restricted to any particular board — works anywhere the pins are actually free. See [Tools Screen › GPIO](./tools_screen/tools_screen.md#gpio). |
|
||||
| `PIN_HALL_SENSOR` + `HALL_ACTIVE_HIGH=1` (optional) | A Hall-effect or reed sensor for a magnetic flip cover: closing locks and blanks the screen instantly, opening unlocks and wakes it, no combo either way. `HALL_ACTIVE_HIGH` is only for a module wired to pull the pin high (rather than low) when the magnet is near. See [Screen Lock › Magnetic cover](./screen_lock/screen_lock.md#magnetic-cover-hall-sensor). |
|
||||
| `UI_HAS_JOYSTICK=1` + `UI_HAS_JOYSTICK_UPDOWN=1` (optional) + `JOYSTICK_UP` / `JOYSTICK_DOWN` / `JOYSTICK_LEFT` / `JOYSTICK_RIGHT` + `PIN_USER_BTN` + `PIN_BACK_BTN` | A wired joystick (four direction contacts + a press contact for Enter). Replaces single-button navigation entirely once enabled. See [External Keyboard & Joystick](../hardware.md#external-keyboard-and-joystick). |
|
||||
| `PIN_GPIO1` .. `PIN_GPIO4` | Up to four general-purpose pins, each independently switchable between Off / Input / Output (GPIO1/GPIO2 also get an Analog step, if wired to an ADC-capable pin) from Tools › GPIO, and via the `!gpio1`..`!gpio4` bot commands. Not restricted to any particular board — works anywhere the pins are actually free. See [Tools › GPIO](../tools.md#gpio). |
|
||||
| `PIN_HALL_SENSOR` + `HALL_ACTIVE_HIGH=1` (optional) | A Hall-effect or reed sensor for a magnetic flip cover: closing locks and blanks the screen instantly, opening unlocks and wakes it, no combo either way. `HALL_ACTIVE_HIGH` is only for a module wired to pull the pin high (rather than low) when the magnet is near. See [Screen lock › Magnetic cover](../lock.md#magnetic-cover). |
|
||||
| `PIN_GPS_SWITCH` | A physical on/off switch for GPS power, read alongside the software GPS toggle — the Tools screen shows `gps off(hw)` / `gps off(sw)` when the two disagree, instead of silently trusting one over the other. |
|
||||
|
||||
---
|
||||
@@ -1,10 +1,10 @@
|
||||
# Solo UI framework — a guide for adding features
|
||||
|
||||
[Go back](../../README.md)
|
||||
[Go back](../README.md)
|
||||
|
||||
This is a developer guide to the reusable building blocks behind the
|
||||
`companion_radio` **solo** firmware UI (the `ui-new` screens). It is not a
|
||||
user manual — for what each screen *does*, see [solo_features](../solo_features/).
|
||||
user manual — for what each screen *does*, see the [documentation](../README.md).
|
||||
The goal here is so that adding a new screen or feature means *wiring together
|
||||
existing helpers*, not reinventing list scrolling, text wrapping, or persistence.
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
# Getting started
|
||||
|
||||
## Controls
|
||||
|
||||
On joystick devices:
|
||||
|
||||
| Input | Does |
|
||||
| ----- | ---- |
|
||||
| **Up / Down** | Move through a list |
|
||||
| **Left / Right** | Switch home pages; change the value of a setting |
|
||||
| **Enter** | Open, select, confirm |
|
||||
| **Hold Enter** | Options for the selected item (a message, contact, channel…) |
|
||||
| **Back** | One step back; from a screen, back to the home screen |
|
||||
|
||||
Lists wrap around at both ends. Any key wakes a dark screen without acting on it.
|
||||
|
||||
Keyboard devices use the same controls, from the arrow keys (or their Fn
|
||||
combinations), Enter and Esc. [Hardware](./hardware.md) has the key maps.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** tap to open, hold for options, swipe sideways between
|
||||
> pages. The top button turns the screen off and on. The side button goes
|
||||
> back to the home screen; hold it and let go to mute or unmute the sound.
|
||||
> Holding the side button while pressing the top one takes a screenshot.
|
||||
|
||||
## Home screen
|
||||
|
||||
The home screen is a row of pages. On joystick devices, **Left / Right** steps
|
||||
through them and **Enter** opens the one shown:
|
||||
|
||||
Clock, Recent, Radio, Bluetooth, Advert, GPS, Sensors, Tools, Shutdown,
|
||||
Settings, Messages, Favourites, Map.
|
||||
|
||||
Settings › Home Pages sets their order and hides the ones you don't use;
|
||||
Settings and Messages are always shown.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** pages you swipe between: favourite chats, the clock
|
||||
> (where it starts), a minimap, then the apps, six to a page. Hold an app to
|
||||
> arrange or hide them.
|
||||
|
||||
## Connecting the phone app
|
||||
|
||||
Every build serves the MeshCore app over **Bluetooth and USB**, one at a time:
|
||||
while Bluetooth is connected, USB is ignored. To use USB, disconnect Bluetooth
|
||||
first or turn it off on the device.
|
||||
|
||||
The Bluetooth pairing PIN is shown on the Bluetooth home page until the phone
|
||||
is paired.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** the PIN is under Settings › Bluetooth.
|
||||
|
||||
Everything you do on the device and in the app stays in sync: contacts,
|
||||
channels and messages are the same data.
|
||||
|
||||
## Updating
|
||||
|
||||
Download the new file from the [releases page](https://github.com/MarekZegare4/MeshCore-Solo/releases)
|
||||
and flash it the way you did the first time (see the [main README](../../README.md#flashing)).
|
||||
Settings, contacts and messages are kept.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** Settings › Firmware update checks GitHub for a newer
|
||||
> release and installs it over WiFi. Set up a network under Settings › WiFi
|
||||
> first.
|
||||
@@ -0,0 +1,99 @@
|
||||
# Hardware
|
||||
|
||||
## External keyboard and joystick
|
||||
|
||||
Two optional add-ons, detected at boot; a build with them enabled works the
|
||||
same with nothing plugged in.
|
||||
|
||||
| Device | CardKB | Wired joystick |
|
||||
| ------ | :----: | :------------: |
|
||||
| Wio Tracker L1 (OLED / e-ink) | Grove connector | built in |
|
||||
| GAT562 30S Mesh Kit | — | built in |
|
||||
| Heltec V3 / V4 | soldered (below) | soldered (below) |
|
||||
| ProMicro | on the main I2C bus (required: it has no buttons) | — |
|
||||
| Cardputer ADV, T-Echo Lite + KeyShield | built-in keyboard instead | — |
|
||||
|
||||
### CardKB
|
||||
|
||||
An M5Stack CardKB types straight into any text field. It sends plain
|
||||
characters, so the keyboard alphabet settings don't apply to it.
|
||||
|
||||
| Key | Does |
|
||||
| --- | ---- |
|
||||
| Arrows, Enter, Esc | Same as the joystick, Enter and Back |
|
||||
| Backspace | Deletes before the cursor |
|
||||
| **Fn+Enter** | Submits the field |
|
||||
| **Fn+letter** | Accents for that letter (Fn+A → á à ä…) |
|
||||
| **Tab** | Hold Enter (options menus) |
|
||||
| **Fn+Esc** | Locks / unlocks the screen |
|
||||
|
||||
Settings › Keyboard › **Ext. KB**: **Full** keeps the on-screen grid, so the
|
||||
CardKB and the joystick can be mixed; **Compact** hides it, the arrows move the
|
||||
text cursor and Enter submits. Compact needs no joystick at all.
|
||||
|
||||
### Wired joystick
|
||||
|
||||
Four direction contacts and a press contact (Enter), each shorted to ground
|
||||
when pressed; the firmware enables the pull-ups, so no resistors are needed.
|
||||
The board's own button becomes Back. Settings › Display › **Joystick
|
||||
rotation** turns the directions for a stick mounted sideways.
|
||||
|
||||
### Wiring on the Heltec V3 / V4
|
||||
|
||||
Neither board has a joystick or a keyboard connector, so both are soldered to
|
||||
free pins. V3 and V4 use the same pins (confirmed on a V4).
|
||||
|
||||
| Function | GPIO |
|
||||
| -------- | :--: |
|
||||
| CardKB SDA / SCL | 3 / 4 (second I2C bus, not the display's) |
|
||||
| Joystick up / down / left / right | 23 / 6 / 47 / 48 |
|
||||
| Joystick press (Enter) | 33 |
|
||||
| Back | 0 (the PRG button, nothing to wire) |
|
||||
|
||||
The pins are set in [`solo/heltec_v3/platformio.ini`](../../solo/heltec_v3/platformio.ini)
|
||||
and [`solo/heltec_v4/platformio.ini`](../../solo/heltec_v4/platformio.ini).
|
||||
For a CardKB-only build, comment out the joystick block there and use
|
||||
Ext. KB = Compact.
|
||||
|
||||
### Built-in keyboards
|
||||
|
||||
The Cardputer ADV has a QWERTY keyboard, the T-Echo Lite a T9 keypad on its
|
||||
KeyShield add-on (without it the board has no usable input). Their keymaps
|
||||
are in each board's driver under `variants/`; they don't follow the CardKB's
|
||||
Fn shortcuts.
|
||||
|
||||
## E-ink
|
||||
|
||||
The e-ink Wio Tracker L1 (250 × 122) has a few settings of its own in
|
||||
Settings › Display:
|
||||
|
||||
- **Rotation**: landscape or portrait, applied at once; every screen reflows.
|
||||
- **Joystick rotation**, independent of the display's.
|
||||
- **Full refresh**: how many partial updates between full ones, against
|
||||
ghosting.
|
||||
|
||||
Clock seconds are hidden by default, and live timers refresh coarsely, to
|
||||
spare the panel.
|
||||
|
||||
## Wio Tracker L2
|
||||
|
||||
- **Buttons**: the top one turns the screen off and on; the side one goes
|
||||
home, and held and let go mutes the sound. Side + top takes a screenshot.
|
||||
Holding the side button in the first seconds after power-on starts the CLI
|
||||
rescue on USB serial.
|
||||
- **SD card**: holds the message history, maps, GPX trails and live map tiles.
|
||||
Settings › Storage shows what takes the space, how many messages each
|
||||
conversation keeps, and deletes the history.
|
||||
- **USB drive**: plugged into a computer, the device asks whether to only
|
||||
charge or to lend the computer the SD card. While lent, the device can't use
|
||||
the card; eject it on the computer and the device restarts. With a screen
|
||||
PIN set, it doesn't ask until the screen is unlocked.
|
||||
- **WiFi**: used only for map downloads, live tiles and updates, and off the
|
||||
rest of the time. Settings › WiFi saves several networks and joins the
|
||||
strongest; the WiFi switch in Settings forbids it entirely.
|
||||
|
||||
## Build flags
|
||||
|
||||
Extra hardware (a buzzer, a vibration motor, a Hall sensor for a magnetic
|
||||
cover, GPIO, an external PA) is enabled with build flags in your own
|
||||
`solo/<board>/platformio.ini`; see [Build flags](./developer/build-flags.md).
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,45 @@
|
||||
# Screen lock
|
||||
|
||||
The lock keeps pocket presses from doing anything. It locks the screen only:
|
||||
messages still arrive, alarms still ring and the phone app still connects.
|
||||
|
||||
## Locking and unlocking
|
||||
|
||||
**Hold Back and press Enter three times** within 3 seconds; the same locks
|
||||
and unlocks. A hint on the lock screen counts the presses. With a CardKB,
|
||||
**Fn+Esc** does it in one press.
|
||||
|
||||
**Settings › Display › Lock screen** locks the device whenever the screen
|
||||
turns off by itself.
|
||||
|
||||
The lock screen shows the time, the date and the first two of the Clock
|
||||
page's fields, but not the device's name.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** with **Lock screen** on (Settings › Display), waking
|
||||
> the screen shows a clock card with **slide to unlock**. Settings › Display
|
||||
> › **Tap to wake** decides whether a tap wakes it or only the top button.
|
||||
|
||||
## PIN
|
||||
|
||||
**Settings › Display › Lock PIN** adds a PIN to unlocking, asked also right
|
||||
after power-up.
|
||||
|
||||
- Enter on the row opens a number pad. Type the PIN (at least 4 characters),
|
||||
confirm, then type it again. The pad's keyboard key switches to letters.
|
||||
- A wrong PIN shows how many tries are left; after 5 in a row, entry pauses
|
||||
for 30 seconds.
|
||||
- Enter on the row again removes the PIN.
|
||||
|
||||
The PIN is stored as a salted hash, never as the PIN itself.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** **Settings › Display › Screen PIN**, digits only. With a PIN, the lock card comes up every time the screen wakes, and
|
||||
> the SD card isn't offered as a USB drive until it's unlocked.
|
||||
|
||||
## Magnetic cover
|
||||
|
||||
A Hall or reed sensor wired to a free pin (`PIN_HALL_SENSOR`, see
|
||||
[Build flags](./developer/build-flags.md)) locks and blanks the screen when a
|
||||
magnetic cover closes and unlocks it when it opens (asking for the PIN, if
|
||||
one is set).
|
||||
@@ -0,0 +1,117 @@
|
||||
# Messages
|
||||
|
||||
Messages holds three lists: **Channels**, **Direct** messages and **Rooms**.
|
||||
Unread counts show on each conversation, on the list and on the home screen.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** one screen with all three as sections; tap a section
|
||||
> title to fold it. **New** in the header starts a conversation with any
|
||||
> contact.
|
||||
|
||||
## Reading
|
||||
|
||||
Open a conversation to see its history as chat bubbles: yours on the right,
|
||||
received ones on the left, newest at the bottom. Each bubble shows the sender,
|
||||
its age and a small hop count: on a received message, how many repeaters it
|
||||
came through; on your own, how many repeaters were heard passing it on.
|
||||
|
||||
**Enter** on a message opens it full screen; **Left / Right** there pages to the
|
||||
older and newer one.
|
||||
|
||||
**Hold Enter** on a message for its options:
|
||||
|
||||
- **Reply**: starts a message addressed to the sender (`@[name]`).
|
||||
- **Navigate**, **Save waypoint**, **Set as target**: when the message
|
||||
contains a location (see [Navigation](./navigation.md)).
|
||||
- **Path** on a received message: the repeaters it came through.
|
||||
**Relayed by** on your own channel post: the repeaters heard repeating it.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** hold a bubble. The card shows when it was sent, the hop
|
||||
> count, the path as a diagram, and **Reply** / **Set target**.
|
||||
|
||||
### How much is kept
|
||||
|
||||
The device keeps the newest 48 channel messages and 32 direct messages, all
|
||||
conversations together. When a busy conversation pushes out messages you
|
||||
haven't read, its unread count gets a **+** (for example `48+`).
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** 256 channel and 128 direct messages in memory, and with
|
||||
> an SD card every conversation is also saved to the card (100 to 2000
|
||||
> messages each, Settings › Storage). The history survives a reboot and
|
||||
> scrolls back through everything on the card.
|
||||
|
||||
## Writing
|
||||
|
||||
Open a conversation and choose **[+ send]** (or Enter at the bottom of the
|
||||
history). Pick a quick message or **Custom message** for the keyboard.
|
||||
|
||||
- **Quick messages**: ten of your own, edited in Settings › Messages.
|
||||
- **Placeholders** fill in live data when the message is sent:
|
||||
`{loc}` (your GPS position), `{time}`, `{batt}`, and the readings of any
|
||||
sensor the device has: `{temp}`, `{hum}`, `{pres}`, `{alt}`, `{lux}`,
|
||||
`{dist}`, `{co2}`.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** the compose bar sits under the conversation; its **+**
|
||||
> opens quick messages and placeholders. Quick messages are edited in
|
||||
> Settings › Messages & contacts.
|
||||
|
||||
### The keyboard
|
||||
|
||||
The on-screen keyboard is a letter grid (or a phone-style T9 keypad, Settings ›
|
||||
Keyboard › Layout). Up from the top row moves the cursor through the text.
|
||||
|
||||
Accented letters don't need a language setting: **hold Enter** on the base
|
||||
letter and pick from its variants, for example `a` → `á à â ä å ą…`, `z` →
|
||||
`ź ż ž`. This covers Polish, Czech, German, French, Spanish, Nordic and the
|
||||
other European languages written in Latin.
|
||||
|
||||
Settings › Keyboard picks two scripts, **Main** and **Additional**, from Latin,
|
||||
Cyrillic and Greek; the keyboard's **#@/abc** key cycles between them and
|
||||
symbols. Cyrillic includes the Ukrainian, Belarusian and Serbian letters
|
||||
(under the key they sit on). Received messages in any of these scripts display
|
||||
correctly whatever the keyboard is set to.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** a phone-style keyboard. Hold a key for its accents; the
|
||||
> globe key switches between the two alphabets.
|
||||
|
||||
## Channels
|
||||
|
||||
**Hold Enter** on a channel for its options:
|
||||
|
||||
| Option | Does |
|
||||
| ------ | ---- |
|
||||
| Mark all read | Clears its unread count |
|
||||
| Notif, Melody | Its own notification and sound, instead of the global ones |
|
||||
| Fav | Marks it as a favourite (shared with the app) |
|
||||
| Scope | The region its messages are tagged with (`*` = none); the list is in Settings › Radio › Scope |
|
||||
| Pin to dial | Puts it on the Favourites page |
|
||||
| Edit, Delete | Renames it or changes its secret; removes it |
|
||||
|
||||
**+ Add channel** at the end of the list adds:
|
||||
|
||||
- **Public**: the default public channel, if you deleted it.
|
||||
- **Hashtag**: a topic such as `#hiking`. Anyone who types the same topic
|
||||
joins the same channel.
|
||||
- **Private**: a name and a secret, typed as a passphrase or as the 32-digit
|
||||
hex key (the format of channel QR codes).
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** hold a channel, or tap ⚙ in an open channel, for its
|
||||
> options.
|
||||
|
||||
## Direct messages
|
||||
|
||||
**Hold Enter** on a contact: Mark as read, Notif, Melody, Fav, Pin to dial.
|
||||
**Fav** is the star shared with the app and sorts favourites to the top;
|
||||
**Pin to dial** only puts the contact on the Favourites page.
|
||||
|
||||
## Rooms
|
||||
|
||||
Opening a room logs in first. You type the password once (empty if the room
|
||||
has none); it's saved on the device, including passwords set from the app,
|
||||
so the next time it logs in without asking. A wrong password is forgotten and
|
||||
you're asked again. **Hold Enter** on a room offers **Login…** and **Logout**.
|
||||
@@ -0,0 +1,125 @@
|
||||
# Navigation
|
||||
|
||||
Everything here works from the device's own GPS; no magnetometer or extra
|
||||
hardware is needed. Distances and speeds follow Settings › System › Units
|
||||
(metric or imperial).
|
||||
|
||||
## Trail
|
||||
|
||||
**Tools › Trail** records your route in the background while you use the rest
|
||||
of the device (a blinking **G** in the status bar). Straight stretches are
|
||||
stored as their two ends, so the 512 points cover a long route. **Left / Right**
|
||||
switches between the **Summary** (distance, time, speed or pace), the **Map**
|
||||
(your route, waypoints, people sharing their position, the target) and the
|
||||
point **List**.
|
||||
|
||||
**Hold Enter** for the trail menu: start / stop, mark a waypoint, the waypoint
|
||||
list, **Track back** (retrace the route to where it started), share your
|
||||
position, the trail file, and the trail settings:
|
||||
|
||||
- **Min dist**: how far apart points are recorded.
|
||||
- **Auto-pause**: pauses the trail after you stop for 1–5 minutes and resumes
|
||||
when you move, so breaks don't count.
|
||||
- **Mark avg**: averages the GPS for 5–30 seconds when marking a waypoint.
|
||||
- **Auto-save**: saves the trail when the device powers off, including a
|
||||
low-battery shutdown.
|
||||
|
||||
The trail lives in memory: save it (Trail file › Save) or turn on Auto-save
|
||||
to keep it through a reboot.
|
||||
|
||||
### GPX export
|
||||
|
||||
Connect USB, open [Solo Tools](https://marekzegare4.github.io/Solo-tools/) in
|
||||
Chrome or Edge and click **Connect device**, then on the device choose
|
||||
**Trail file › Export**. The GPX includes your waypoints. Without a browser,
|
||||
`uv run tools/trail_export.py` does the same. Disconnect the phone app first if
|
||||
it's connected over USB.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** the trail holds 4096 points and is drawn on the map.
|
||||
> Its controls (start / stop, save, load, track back, reset) are in the map's
|
||||
> **Map tools**, the settings in Settings › Map. **GPX** writes the trail to
|
||||
> the SD card; take it off with the card as a USB drive
|
||||
> ([Hardware](./hardware.md)).
|
||||
|
||||
## Waypoints
|
||||
|
||||
A waypoint is a saved spot (the car, a camp, water) with a short label, up to
|
||||
16 of them, kept through reboots. Add one with **Mark here** at your position,
|
||||
or **+ Add by coords** to type coordinates. The list starts with **Trail
|
||||
start**, so you can always go back to where the trail began.
|
||||
|
||||
**Hold Enter** on a waypoint: Rename, Delete, **Send** (as a message to a
|
||||
contact or channel) and **Set as target**.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** up to 64 waypoints. The pin button on the map opens the
|
||||
> list; hold a spot on the map to make it a waypoint or the target.
|
||||
|
||||
## Navigating to something
|
||||
|
||||
**Navigate** on a waypoint, a node in Nearby or a location in a message opens
|
||||
the navigation view: the distance, the bearing **To** the target and your own
|
||||
heading (**Hdg**), with the time to arrival once you're getting closer. Turn
|
||||
until the two bearings match. The heading comes from your movement, so it
|
||||
shows `--` while you stand still.
|
||||
|
||||
**Tools › Compass** shows the same heading as a scrolling tape with the
|
||||
degrees and direction.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** the target is drawn on the map with a line to it, and a
|
||||
> bar with distance, bearing, heading and time to arrival. The Compass app is
|
||||
> a turning dial.
|
||||
|
||||
## Sharing locations
|
||||
|
||||
- **Once**: **Share my pos** in the trail menu sends your position to a
|
||||
contact or channel you pick.
|
||||
- **A waypoint**: **Send** in the waypoint menu.
|
||||
- **Live**: **Tools › Live Share** sends your position while you move, to one
|
||||
contact or channel, for 1 to 12 hours. It only sends after you've moved
|
||||
(50–500 m) and never more often than you set; an optional heartbeat repeats
|
||||
it while you stand still.
|
||||
|
||||
With **Track loc** on in Live Share, other people's shares show on the map
|
||||
and in Nearby, with live distance and bearing.
|
||||
|
||||
Locations travel as ordinary text (`[LOC]lat,lon`, or `[WAY]lat,lon label`
|
||||
for a waypoint), readable in the phone app and on other firmware. On the
|
||||
receiving side, **hold Enter** on the message to navigate to it, save it or
|
||||
set it as the target.
|
||||
|
||||
## Locator
|
||||
|
||||
**Tools › Locator** alerts you when you cross a circle around a target:
|
||||
arriving at a waypoint, leaving it, or a person coming near or moving away.
|
||||
|
||||
- **Target**: a waypoint (a fixed place) or a contact (follows their live
|
||||
share, else their last known position).
|
||||
- **Radius**: 50 m to 1 km.
|
||||
- **Mode**: alert on arriving, leaving, or both.
|
||||
- **Beeper**: ticks faster as you get closer, even when the sound is muted.
|
||||
|
||||
**Set as target** in Nearby, the waypoint list or a message sets the target
|
||||
in one step. The target shows as a flag on the map.
|
||||
|
||||
## Map
|
||||
|
||||
The **Map** home page shows your position, the trail, waypoints, people
|
||||
sharing their position and the target. **Enter** opens the trail map;
|
||||
**hold Enter** shares your position.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** a real map with offline tiles on the SD card. Drag to
|
||||
> pan, +/− to zoom, the crosshair follows your GPS again.
|
||||
>
|
||||
> - **Download**: frame an area on the map and download its tiles over WiFi.
|
||||
> Downloaded areas can be renamed, refreshed or deleted.
|
||||
> - **Live tiles**: with WiFi on, tiles for where you look are fetched and
|
||||
> cached, up to the size set in Settings › Storage.
|
||||
> - **Vector regions**: whole regions as packs made with
|
||||
> `tools/maps/osm_vector.py`, copied to the card.
|
||||
>
|
||||
> The minimap on the home screen shows your surroundings at a glance; tap it
|
||||
> for the full map. The **Nodes** map shows every node with a position.
|
||||
@@ -0,0 +1,40 @@
|
||||
# Settings
|
||||
|
||||
Settings are saved as you change them and kept through reboots and updates.
|
||||
On joystick devices they're folding sections: **Enter** on a section opens
|
||||
it, **Left / Right** changes a value, **Back** leaves. Only the rows your
|
||||
board supports are shown.
|
||||
|
||||
| Section | What's there |
|
||||
| ------- | ------------ |
|
||||
| **Display** | Brightness, auto-off, lock screen and [PIN](./lock.md), battery as icon / % / volts, clock format and seconds, wake on message; on e-ink also rotation and full refresh |
|
||||
| **Sound** | Buzzer on / off / auto (quiet while the app is connected), volume, quiet hours, the melody for messages, channels and adverts |
|
||||
| **Home Pages** | Order of the home pages, and which are shown |
|
||||
| **Radio** | TX power, preset, frequency, SF / BW / CR, saved presets, Auto pwr, the scope list |
|
||||
| **System** | Device name, time zone, low-battery shutdown, GPS power saving, units, reboot |
|
||||
| **Keyboard** | ABC or T9 layout, the two scripts, CardKB mode |
|
||||
| **Contacts** | Show all or favourites only (DMs, channels, rooms), favourites on top, contact expiry and prune |
|
||||
| **Messages** | Automatic resend of direct messages, the ten quick messages |
|
||||
|
||||
A few notes:
|
||||
|
||||
- **Auto pwr** lowers the TX power on strong links and raises it back on weak
|
||||
ones; the power set above is the ceiling.
|
||||
- **Scope** is a list of named regions (plus `*`, no region). Messages are
|
||||
tagged with a scope so repeaters can tell communities on the same frequency
|
||||
apart. The default one is used for direct messages and repeating, and each
|
||||
channel picks its own (see [Messages](./messages.md#channels)). Anyone who
|
||||
types the same name gets the same scope; it isn't encryption.
|
||||
- **Low battery** shuts the device down at the voltage you choose, which is
|
||||
also 0 % on the battery indicator.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** one list of pages:
|
||||
>
|
||||
> - **Device**: Display (including the lock and **Tap to wake**), Home apps,
|
||||
> Power (battery, GPS), Sound (with the melody editor), Keyboard, Messages
|
||||
> & contacts.
|
||||
> - **Connections**: Radio, Bluetooth, WiFi, GPS.
|
||||
> - **Map & data**: Map (trail, live sharing and arrival alert options),
|
||||
> Storage.
|
||||
> - **System**: Name, Time, Firmware update, About; Reboot and Power off.
|
||||
@@ -0,0 +1,114 @@
|
||||
# Tools
|
||||
|
||||
On joystick devices, the tools are in **Tools**, grouped into Location, Comms
|
||||
and System. The navigation tools are on the [Navigation](./navigation.md)
|
||||
page, Nodes and Admin on [Contacts](./contacts.md).
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** the tools are apps on the home screen: Messages, Nodes,
|
||||
> Settings, Compass, Clock, GPS, Bot, Repeater, Admin, Diagnostics. The trail,
|
||||
> live sharing and the locator are on the map (its tools button) and in
|
||||
> Settings › Map.
|
||||
|
||||
## Clock
|
||||
|
||||
The **Clock** home page shows the time, the date and up to three fields you
|
||||
choose (hold Enter): battery, temperature, humidity, pressure, altitude
|
||||
(barometric or GPS), light, CO₂, GPS position, satellites, contacts, unread
|
||||
messages. The time comes from GPS or the phone app; the time zone is in
|
||||
Settings.
|
||||
|
||||
**Enter** on the clock opens the clock tools:
|
||||
|
||||
- **Alarm**: a time, repeating daily, on weekdays, at weekends or once. It
|
||||
rings with the screen off or locked, but not after a shutdown.
|
||||
- **Timer**: a countdown that rings when it reaches zero, whatever screen
|
||||
you're on.
|
||||
- **Stopwatch**.
|
||||
|
||||
Any key silences the ringing; it stops by itself after a minute.
|
||||
|
||||
## Remote bot
|
||||
|
||||
**Tools › Bot** answers messages for you. It watches your direct messages, one
|
||||
channel and one room, each switched on separately:
|
||||
|
||||
- **Trigger and reply**: when a message contains the trigger (several can be
|
||||
separated by commas, `*` matches any message), the bot sends the reply. The
|
||||
reply can use placeholders, plus `{name}` (the sender) and `{hops}`.
|
||||
- **Commands**: messages starting with `!` get live data back:
|
||||
|
||||
| Command | Reply |
|
||||
| ------- | ----- |
|
||||
| `!ping` | `pong` |
|
||||
| `!batt`, `!temp`, `!time`, `!loc` | battery, temperature, time, position |
|
||||
| `!hops` | how many hops the command took |
|
||||
| `!status` | battery, position and time |
|
||||
| `!help` | the list of commands |
|
||||
|
||||
Several in one message get one reply: `!batt !time` → `4.10V | 14:30`.
|
||||
- **Actions** (off by default) let the command change the device: `!buzz`
|
||||
(sounds the buzzer to find it), `!gps on` / `!gps off`, `!gps fix` (turns
|
||||
the GPS on, waits for a good fix and sends it), `!advert`.
|
||||
|
||||
**DM allow = Fav** limits the DM bot to your favourites, and **quiet hours**
|
||||
stop trigger replies at night (commands still answer). Replies are rate
|
||||
limited so two bots can't answer each other forever. The room bot uses the
|
||||
room's saved login.
|
||||
|
||||
## Auto-advert
|
||||
|
||||
**Tools › Auto-advert** sends an advert with your position every 30 seconds
|
||||
to 1 hour, so others see you in their Nearby list. With it on at both ends
|
||||
and Settings › Sound › **AD sound** set, each device beeps when it hears the
|
||||
other: a hands-free "still in range".
|
||||
|
||||
## Repeater
|
||||
|
||||
**Tools › Repeater** makes the device relay other people's packets while it
|
||||
keeps working as a companion. By default it relays on a separate repeater
|
||||
profile (the community's repeater frequency) and switches back when you turn
|
||||
it off; **Network = Current** relays on your own frequency instead.
|
||||
|
||||
Optional filters keep a mobile repeater from adding noise: skip adverts, a
|
||||
maximum hop count, **Yield** (let fixed repeaters go first), a minimum SNR,
|
||||
drop duplicates already relayed by someone else, and relay only your
|
||||
**scopes**. Diagnostics shows how much it forwards.
|
||||
|
||||
## Ringtones
|
||||
|
||||
**Tools › Ringtone** composes two melodies of up to 32 notes (pitch, octave,
|
||||
length, tempo). Use them for notifications in Settings › Sound, or for a
|
||||
single contact or channel from its options.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** the melody editor is under Settings › Sound.
|
||||
|
||||
## Diagnostics
|
||||
|
||||
**Tools › Diagnostics** shows live counters (packets received and sent by
|
||||
type, forwarded, errors), memory, the radio's noise floor and the last
|
||||
packet's signal; a **System** tab with the firmware and radio settings; and a
|
||||
**Font** tab with a sample of every script the font covers. Hold Enter on the
|
||||
live tab to reset the counters.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** the Diagnostics app, with a **Noise** tab that
|
||||
> measures the noise floor over time.
|
||||
|
||||
## GPIO
|
||||
|
||||
*Wio Tracker L1 only.* **Tools › GPIO** sets four spare pins as input,
|
||||
output or (GPIO1–2) analog input, shows their level and switches outputs. The
|
||||
bot's `!gpio1`…`!gpio4` commands read and set the same pins.
|
||||
|
||||
## GPS and sensors
|
||||
|
||||
The **GPS** home page shows the fix and satellites; **Sensors** shows the
|
||||
readings of the sensors the board has. **GPS pwr** in Settings › System turns
|
||||
the GPS off between fixes to save battery; anything that needs your position
|
||||
(the trail, live share, the locator) keeps it on.
|
||||
|
||||
> [!NOTE]
|
||||
> **Wio Tracker L2:** the **GPS** app draws a sky plot of the satellites and
|
||||
> each one's signal strength.
|
||||
@@ -1,70 +0,0 @@
|
||||
# MeshCore Solo — documentation
|
||||
|
||||
## Documents
|
||||
|
||||
| Document | Description |
|
||||
| -------------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
||||
| [Messages Screen](./message_screen/message_screen.md) | Sending messages, context menus, reply, navigate to / save shared locations, Notif/Melody overrides |
|
||||
| [Favourites Dial](./favourites_dial/favourites_dial.md) | Pinned contacts grid, unread badges, pin/unpin |
|
||||
| [Clock Screen](./clock_screen/clock_screen.md) | Clock page, date, configurable data fields, alarm / timer / stopwatch |
|
||||
| [Settings Screen](./settings_screen/settings_screen.md) | All settings sections with values and interactions |
|
||||
| [Screen Lock](./screen_lock/screen_lock.md) | Lock/unlock sequence, lock screen, auto-lock |
|
||||
| [Tools Screen](./tools_screen/tools_screen.md) | GPS trail & waypoints, compass, navigation, nearby nodes, ringtone editor, remote bot, auto-advert, live location sharing, locator, diagnostics, repeater, remote admin |
|
||||
| [External Keyboard & Joystick](./external_keyboard.md) | CardKB shortcuts, Full vs Compact mode, wired joystick, Heltec V3/V4 wiring |
|
||||
| [Build Flags](./build_flags.md) | Every optional `-D` build flag a solo build understands — GPIO, Hall sensor, buzzer/vibration, GPS switch, display/battery tuning |
|
||||
| [Solo UI framework](../developer/ui-framework.md) | **Developer guide** — the reusable building blocks (screens, lists, popups, mini-icons, geo/persistence helpers) and how to add a new feature |
|
||||
| [UI Core](../developer/ui-core.md) | **Developer guide** — the frontend-independent layer (models, settings schema, events) shared by the OLED/e-ink UI and the LVGL touch UI |
|
||||
|
||||
## Upstream MeshCore
|
||||
|
||||
| Document | Description |
|
||||
| -------------------------------------------------- | ------------------------------------------------ |
|
||||
| [FAQ](../faq.md) | Frequently asked questions |
|
||||
| [CLI Commands](../cli_commands.md) | Commands for repeaters, room servers and sensors |
|
||||
| [Terminal Chat CLI](../terminal_chat_cli.md) | Commands for the terminal chat client |
|
||||
| [Companion Protocol](../companion_protocol.md) | Serial/BLE frame protocol between device and app |
|
||||
| [Packet Format](../packet_format.md) | LoRa packet structure |
|
||||
| [QR Codes](../qr_codes.md) | Channel and contact QR code formats |
|
||||
|
||||
## Features
|
||||
|
||||
- Extended language support — one unified 6×9 font (Latin, Greek, Cyrillic) plus on-screen keyboard alphabets for Cyrillic, Greek, Polish, Czech, Slovak, German, French, Spanish, Portuguese and Nordic. Pick two in Settings › Keyboard (**Main**/**Additional**) and switch between them while typing
|
||||
|
||||
- Enabled sensor screens with support for onboard sensors (temperature, humidity, pressure, luminosity, CO₂) and GPS data
|
||||
|
||||
- **GPS navigation** — a full navigation suite that needs no extra hardware (details in the [Tools Screen](./tools_screen/tools_screen.md) docs):
|
||||
|
||||
- **Waypoints** — mark a spot (car, camp, water…) with a short label, see it on the trail map, and get live bearing + distance back to it; the list always offers a one-tap backtrack to where your trail started
|
||||
- **GPS compass** — heading derived from course-over-ground (no magnetometer needed), shown as a clear scrolling heading tape with a large degrees + cardinal readout
|
||||
- **Navigate to anything** — a saved waypoint, a node straight from Nearby Nodes, or a location someone shares with you in a message
|
||||
- **Share & save locations** — send a waypoint to a contact or channel; on the other end, navigate to or save any shared location with one menu
|
||||
- **Live location sharing** — broadcast your position over the mesh as you move (movement-gated, to a channel or contact) and see others who share theirs as pins on the map and live distance/bearing in Nearby
|
||||
- **Locator** — arm a geofence around a waypoint or a person, get alerted on arrive/leave or near/far, with an optional homing beeper that speeds up as you close in. Set from the Locator screen, Nearby Nodes, or Waypoints; target shown as a flag on the map
|
||||
- **GPS trail** — background route recording with an auto-fit map (waypoints + live position), summary stats, auto-pause on stops, and [GPX export](../../README.md#documentation)
|
||||
- **Metric or imperial** — one global Units setting drives every distance and speed across the UI
|
||||
|
||||
- [Messages Screen](./message_screen/message_screen.md) — view and send messages, open message details, reply with quick messages or custom text, navigate to / save locations shared in a message, per-channel notification and melody overrides, add/edit/delete channels on-device
|
||||
|
||||
- [Favourites Dial](./favourites_dial/favourites_dial.md) — pin up to six contacts for quick access from the home screen
|
||||
|
||||
- [Settings Screen](./settings_screen/settings_screen.md) — configure display, sound, home page order, radio and system settings
|
||||
|
||||
- [Clock Screen](./clock_screen/clock_screen.md) — view time and date plus up to three configurable data fields, with built-in clock tools (one-shot alarm, countdown timer, stopwatch)
|
||||
|
||||
- [Screen Lock](./screen_lock/screen_lock.md) — lock the device to prevent accidental keypresses, with a lock screen showing time and sensor data
|
||||
|
||||
- [Tools Screen](./tools_screen/tools_screen.md) — GPS trail & waypoints, compass, nearby nodes (with ping & navigate), ringtone editor, remote bot, auto-advert, live location sharing, locator, diagnostics, repeater, remote admin
|
||||
|
||||
- [External Keyboard & Joystick](./external_keyboard.md) — optional, auto-detected: **CardKB** for typing without the on-screen grid (Fn+Enter submits, Fn+letter picks an accent, Tab is Hold-Enter, Fn+Esc locks), plus a **wired joystick** for boards without one. Compact mode makes CardKB-only operation practical
|
||||
|
||||
- **Auto pwr** (Settings › Radio) — Adaptive Power Control: trims actual TX power on strong links (from ACK SNR) and ramps back up to the configured ceiling on weak/lost links; the home screen shows the live power
|
||||
|
||||
## E-ink Display (Wio Tracker L1)
|
||||
|
||||
The e-ink variant targets the Wio Tracker L1 fitted with a 2.13″ GxEPD2 panel (250 × 122 px). Every screen is adapted for it:
|
||||
|
||||
- **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
|
||||
- **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
|
||||
@@ -1,93 +0,0 @@
|
||||
## 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 (Baro) | Alt | metres/feet (per Settings › System › Units) from onboard barometric sensor (`--` without one) |
|
||||
| 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. A trailing **+** (e.g. `48+`) means at least one channel or DM has filled its on-device history ring while unread — the real total is higher than shown, but that's everything still recoverable; the rest was evicted before ever being seen. |
|
||||
| Satellites | Sats | GPS satellite count (or `--` without GPS) |
|
||||
| Altitude (GPS) | AltG | metres/feet (per Settings › System › Units) from the GPS fix (or `no fix`) |
|
||||
|
||||
Sensor fields show `--` when the sensor is not connected or has no data.
|
||||
|
||||
---
|
||||
|
||||
### Configuring fields
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
<!-- screenshot pending: Dashboard Config — three field slots cycled with LEFT/RIGHT -->
|
||||
|
||||
**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**.
|
||||
|
||||
---
|
||||
|
||||
### Clock tools — Alarm, Timer, Stopwatch
|
||||
|
||||
**Press Enter** (short press) on the Clock page to open **Clock Tools**, a small menu with three time utilities. **Cancel** backs out one level (tool → menu → home). The same menu also has an entry under **Tools › System**, so it's reachable without the Clock page.
|
||||
|
||||
#### Alarm
|
||||
|
||||
A wake alarm with an optional repeat. Rows: **Hour**, **Minute**, **Repeat** and **Armed**. **Enter** on Hour or Minute opens the digit editor (LEFT/RIGHT moves between the tens/units, UP/DOWN changes the digit); **Enter** on Repeat cycles **OFF → Daily → Weekdays → Weekends → OFF**; **Enter** on Armed toggles ON/OFF. The configured time is shown next to the **Alarm** menu row when armed, and the setting persists across reboots.
|
||||
|
||||
While armed, a bell icon shows in the Clock page's top-left corner and in the status bar on other home pages (hidden on the Clock page itself, hence its own indicator). Icon-only — the exact time is on the **Alarm** row in Clock Tools.
|
||||
|
||||
The alarm fires at an absolute instant, so it survives clock re-syncs (mesh packets, companion app, GPS and the CLI can all jump the device clock). A jump past the alarm time still fires it, just late. With **Repeat** OFF (default) it disarms after firing once; with a pattern set, it re-arms for the next matching day.
|
||||
|
||||
The alarm only fires while the device is **awake** (it keeps running with the display off or locked). It cannot wake the device from a full **Shutdown** (the CPU and RAM are powered down), and needs a valid time source — it stays pending until the clock is synced.
|
||||
|
||||
#### Timer (countdown)
|
||||
|
||||
A large **HH:MM:SS** readout with one digit underlined. **LEFT/RIGHT** moves the cursor one digit at a time, **Up/Down** changes the digit under it (minute/second tens cap at 5, hours at 23), and **Enter** starts the countdown. While running it shows **H:MM:SS** — **Enter** stops it, **Cancel** returns to the menu and leaves it counting. When it reaches zero the device rings, even if you have navigated to another screen.
|
||||
|
||||
#### Stopwatch
|
||||
|
||||
**Enter** starts/stops; **Up/Down** resets when stopped; **Cancel** returns to the menu and leaves it running.
|
||||
|
||||
#### Ringing
|
||||
|
||||
When the alarm or timer fires the device plays a melody (overriding mute) and shows an alert. **Any key** silences it; otherwise it stops on its own after a minute.
|
||||
|
||||
> **E-ink note:** the live timer/stopwatch readouts would thrash a slow e-paper panel if redrawn every second, so on e-ink they refresh only coarsely (and immediately on any key press). The underlying timing is exact regardless, and the countdown's buzzer always fires on time.
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
@@ -1,144 +0,0 @@
|
||||
## External Keyboard & Joystick
|
||||
|
||||
[Go back](../../README.md)
|
||||
|
||||
Two optional, auto-detected hardware add-ons — a build with them enabled runs
|
||||
the same with nothing plugged in. Two of the newer boards also ship with
|
||||
their own **built-in** keypad instead —
|
||||
see [Built-in keyboards](#built-in-keyboards-cardputer-adv-t-echo-lite--keyshield).
|
||||
|
||||
- **CardKB** — an M5Stack I2C QWERTY keyboard (address `0x5F`), for typing
|
||||
messages, names and labels without walking the on-screen letter grid.
|
||||
- **Wired joystick** — four direction contacts plus a Back button, replacing the
|
||||
single-button navigation on boards that have no joystick of their own.
|
||||
|
||||
### Support by device
|
||||
|
||||
| Device | CardKB | Wired joystick |
|
||||
| ------ | :----: | :------------: |
|
||||
| Seeed Wio Tracker L1 (OLED) | ✅ Grove connector | onboard |
|
||||
| Seeed Wio Tracker L1 (E-ink) | ✅ Grove connector | onboard |
|
||||
| GAT562 30S Mesh Kit | — | onboard |
|
||||
| Heltec V3 *(experimental)* | ✅ solder to free GPIOs | ✅ solder to free GPIOs |
|
||||
| Heltec V4 *(experimental)* | ✅ solder to free GPIOs | ✅ solder to free GPIOs |
|
||||
| M5Stack Cardputer ADV *(experimental)* | — | built-in keyboard instead, see below |
|
||||
| LilyGO T-Echo Lite + KeyShield *(experimental)* | — | built-in keypad instead, see below |
|
||||
| ProMicro (nRF52840) *(experimental)* | ✅ shares the primary I2C bus (D8/D7) — no free pins for a second bus | — |
|
||||
|
||||
---
|
||||
|
||||
## CardKB
|
||||
|
||||
Plug it into the second I2C bus (the Grove connector on the Wio Tracker L1;
|
||||
see [Wiring](#wiring-heltec-v3--v4) for the Heltec boards). The firmware probes
|
||||
for it once at boot — nothing to enable in Settings.
|
||||
|
||||
The same bus is scanned for environment sensors, so a CardKB and a sensor can
|
||||
share it.
|
||||
|
||||
On a board with no free pins for a second bus (ProMicro), CardKB instead
|
||||
shares the primary bus already used by the display/RTC — set `CARDKB_I2C=Wire`
|
||||
as a build flag rather than `ENV_PIN_SDA`/`ENV_PIN_SCL`. See
|
||||
[Build Flags](./build_flags.md) for both forms.
|
||||
|
||||
### Typing
|
||||
|
||||
Printable characters insert straight at the cursor, bypassing the on-screen grid
|
||||
completely. The alphabet and T9/ABC settings do not apply — a real keyboard sends
|
||||
the right character already, so typing is always plain Latin ASCII regardless of
|
||||
what Settings › Keyboard is set to.
|
||||
|
||||
| Key | Action |
|
||||
| --- | ------ |
|
||||
| letters / digits / symbols / space | insert at the cursor |
|
||||
| Backspace | delete the character before the cursor |
|
||||
| Esc | cancel / back |
|
||||
| Arrows | same as the joystick |
|
||||
| Enter | same as the centre button |
|
||||
| **Fn+Enter** | **submit the field** — no need to find the DONE cell |
|
||||
| **Fn+letter** | open the accent popup for that letter (e.g. Fn+A → á à ä ã…) |
|
||||
| **Tab** | the Hold-Enter equivalent, everywhere — context menus, shift-lock, clear-all |
|
||||
| **Fn+Esc** | lock / unlock the device (single press, works in both directions) |
|
||||
|
||||
Fn+Esc rather than the adjacent Fn+Backspace on purpose: Fn and Backspace sit
|
||||
next to each other on CardKB's layout and would be far too easy to hit by
|
||||
accident. See [Screen Lock](./screen_lock/screen_lock.md) for the physical
|
||||
button equivalent.
|
||||
|
||||
### Ext. KB — Full vs Compact
|
||||
|
||||
**Settings › Keyboard › Ext. KB** picks how the on-screen keyboard behaves while
|
||||
a CardKB is doing the typing.
|
||||
|
||||
| Mode | Behaviour |
|
||||
| ---- | --------- |
|
||||
| **Full** (default) | The letter grid stays on screen. Arrows and Enter drive the grid exactly as physical buttons do, so CardKB and the joystick can be used interchangeably. |
|
||||
| **Compact** | The grid, the special-row icons and the status line are all hidden — only the text being typed and two shortcut hints remain. Arrows move the **text cursor** directly, and plain Enter submits the field (same as Fn+Enter). |
|
||||
|
||||
**Compact is designed to need no joystick at all** — the right choice when
|
||||
CardKB is the only input device, e.g. a Heltec V3/V4 with no joystick
|
||||
soldered on.
|
||||
|
||||
Cursor mode and the accent / placeholder popups draw their own visible feedback,
|
||||
so they behave identically in both modes.
|
||||
|
||||
---
|
||||
|
||||
## Wired joystick
|
||||
|
||||
Four direction contacts plus a fifth "press" contact. Each contact simply
|
||||
shorts its pin to ground — the firmware enables the internal pull-ups, so no
|
||||
external resistors are needed.
|
||||
|
||||
- The stick's own press contact drives the centre / Enter press — your thumb
|
||||
is already on the stick, so pressing it in is the natural "confirm" action.
|
||||
- The board's existing user button (PRG on the Heltec boards) becomes Back
|
||||
instead. Back is **not** optional: the UI uses it unconditionally once the
|
||||
joystick is enabled. Triple-clicking Back toggles the buzzer.
|
||||
- **Settings › Display › Joystick rotation** rotates the direction mapping at
|
||||
runtime (0–3), for a stick mounted sideways in a custom enclosure. It is
|
||||
independent of display rotation.
|
||||
|
||||
---
|
||||
|
||||
## Wiring (Heltec V3 / V4)
|
||||
|
||||
Neither board ships with a joystick or a keyboard header, so both are soldered to
|
||||
free GPIOs. V3 and V4 are pin-compatible per Heltec's documentation and the solo
|
||||
builds use the same assignment for both — **confirmed working on real V4
|
||||
hardware**; still worth checking against your own V3 module before soldering.
|
||||
|
||||
| Function | GPIO | Notes |
|
||||
| -------- | ---- | ----- |
|
||||
| CardKB SDA | 3 | second I2C bus (`Wire1`) — *not* the OLED's 17/18 |
|
||||
| CardKB SCL | 4 | |
|
||||
| Joystick UP | 23 | |
|
||||
| Joystick DOWN | 6 | |
|
||||
| Joystick LEFT | 47 | |
|
||||
| Joystick RIGHT | 48 | |
|
||||
| Joystick press — Enter | 33 | the stick's own fifth contact; required when the joystick is enabled |
|
||||
| Back | 0 | the onboard PRG button — nothing to wire |
|
||||
|
||||
Everything above lives in the `[env:Heltec_v3_companion_solo_dual]` /
|
||||
`[env:heltec_v4_companion_solo_dual]` blocks in
|
||||
[`solo/heltec_v3/platformio.ini`](../../solo/heltec_v3/platformio.ini)
|
||||
and [`solo/heltec_v4/platformio.ini`](../../solo/heltec_v4/platformio.ini),
|
||||
with comments explaining which pins are safe to reuse. To build a CardKB-only
|
||||
device, comment out the joystick block and set Ext. KB to Compact.
|
||||
|
||||
---
|
||||
|
||||
## Built-in keyboards (Cardputer ADV, T-Echo Lite + KeyShield)
|
||||
|
||||
*Experimental* — newly-added board support, not the CardKB/joystick add-ons
|
||||
above. Both keypads are TCA8418-based and share one polling path, entirely
|
||||
independent of the CardKB code — a board can have either, or neither.
|
||||
|
||||
- **M5Stack Cardputer ADV** — built-in QWERTY, no CardKB or joystick needed.
|
||||
- **LilyGO T-Echo Lite + KeyShield** — the KeyShield add-on gives the T-Echo
|
||||
Lite a T9 keypad; without it the board has no usable input for the solo UI.
|
||||
|
||||
Neither keypad follows CardKB's exact Fn-shortcut table (Fn+Enter,
|
||||
Fn+letter accent popups, Tab, Fn+Esc lock) — see each board's own
|
||||
keyboard driver under `variants/` and its solo `platformio.ini` under `solo/`
|
||||
for its current keymap.
|
||||
@@ -1,74 +0,0 @@
|
||||
## Favourites Dial
|
||||
|
||||
[Go back](../../../README.md)
|
||||
|
||||
### Overview
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :------------------------: | :------------------------: |
|
||||
|  |  |
|
||||
|
||||
A dedicated home page showing a grid of up to 6 pinned conversations — chat contacts, room servers or channels — 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 conversation directly: a contact's DM, a channel's history, or a room server (running the room's login handshake first if it isn't logged in yet).
|
||||
|
||||
**Enter on an empty tile (`+`)** — starts the picker to fill the slot.
|
||||
|
||||
**Hold Enter on a filled tile** — opens **Unpin** / **Replace** for that slot.
|
||||
|
||||
Channel tiles show their name with a leading `#`, so they read apart from contacts and rooms sharing the same grid.
|
||||
|
||||
---
|
||||
|
||||
### Unread badge
|
||||
|
||||
Filled tiles show an unread message count in the top-right corner — unread DMs for a contact or room, unread posts for a channel. The name is ellipsized to make room for the badge.
|
||||
|
||||
If a pinned target disappears — a contact removed explicitly or auto-evicted to make room when the table is full, or a deleted channel — its slot is freed automatically and goes back to an empty `+` tile.
|
||||
|
||||
---
|
||||
|
||||
### Pinning
|
||||
|
||||
**From the Favourites Dial** — press **Enter** on an empty tile (`+`), or **Hold Enter** on a filled one and choose **Replace**. This opens the **Messages** screen in its normal Direct / Channels / Rooms browse; pick an entry and you land back on the dial with that slot filled. It's the same list you already use to open a conversation, rather than a second browser of its own.
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :------------------------: | :------------------------: |
|
||||
|  |  |
|
||||
|
||||
<!-- screenshot pending: Messages browse entered from an empty dial tile -->
|
||||
|
||||
**From the Messages lists** — **Hold Enter** on a contact, room or channel entry › **Pin to dial**, then choose a slot from the slot picker (Slot 1–6, showing the current occupant or "empty").
|
||||
|
||||
**From Tools › Nodes** — **Hold Enter** on a node › **Pin to dial**. This one doesn't ask which slot; it takes the first free one (and says which), since that menu is already long.
|
||||
|
||||
If the target is already pinned in another slot, it is moved to the new slot automatically.
|
||||
|
||||
---
|
||||
|
||||
### Unpinning
|
||||
|
||||
**From the Favourites Dial** — **Hold Enter** on the tile › **Unpin**.
|
||||
|
||||
**From the Messages lists or Tools › Nodes** — **Hold Enter** › context menu › **Unpin (slot N)**.
|
||||
|
||||
---
|
||||
|
||||
### Pinning is not the same as favouriting
|
||||
|
||||
A pinned tile and a **Fav: ON** entry are two independent things. Pinning puts something on this page. Favouriting marks it with a ★ and sorts it to the top of every list it appears in, and is what the **Settings › Contacts** list filters read. Either can be used without the other.
|
||||
|
||||
---
|
||||
|
||||
### 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.
|
||||
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
@@ -1,184 +0,0 @@
|
||||
## 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.
|
||||
|
||||
DM and channel history are each kept in a fixed-size on-device ring (32 DM / 48 channel entries). A busy conversation that outpaces reading can fill its ring — new messages keep arriving, evicting the oldest ones, including unread ones that were never opened. When that's happened, the unread badge for that conversation (and the DM/Channels row on the mode-select screen, and the clock/lock screen's Msgs field) gets a trailing **+** — e.g. `48+` — meaning the count is honest for what's still on the device but understates how many actually came in; the rest are gone for good. Rooms aren't ring-limited the same way, so they never show a **+**.
|
||||
|
||||
---
|
||||
|
||||
### Sending messages
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Press **Enter** on a contact or channel to open its history, then press **Enter** again (or select the **[+ send]** button, anchored at the right edge of the history) to compose a message. Choose between:
|
||||
|
||||
- **Custom message** — opens the on-screen keyboard
|
||||
- **Q1–Q10** — quick reply templates editable in Settings › Messages
|
||||
|
||||
While typing, **UP** from the top letter row enters cursor mode — LEFT/RIGHT move the insertion point, UP/DOWN jump to start/end (then to the grid on a second press), Enter/Cancel exit from anywhere — so you can edit mid-text, not just at the end. **Hold Enter** on a letter with accented variants (a, e, c, n, o, s, z…) opens a one-row accent popup instead — LEFT/RIGHT picks, Enter inserts, Cancel dismisses. Full key set (Shift, T9, Cyrillic/Greek) in the [UI framework guide](../../developer/ui-framework.md).
|
||||
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
### Rooms — logging in
|
||||
|
||||
Posting to a **room server** needs a login handshake — the device does this on its own, no phone app needed. First **Enter** on a room opens a password prompt automatically; type it and press **✓** (empty for no-password rooms). On success the chat opens automatically, no second Enter needed.
|
||||
|
||||
- **Passwords are remembered across reboots.** After a successful login it's saved on the device, so picking that room again — even after a power cycle — logs back in silently.
|
||||
- **A wrong or changed password self-heals.** A failed login forgets the saved password, so the next **Enter** prompts for a new one.
|
||||
- **Re-login any time** with **Hold Enter** on the room → **Login…** — useful to switch passwords without waiting for a failure.
|
||||
- **Log out** with **Hold Enter** → **Logout** (only offered once logged in). Forgets the saved password, so the next open prompts for one again.
|
||||
- Passwords set from the **phone app** are saved on the device too, so it can post to that room standalone after a reboot.
|
||||
|
||||
> The on-screen keyboard's default (Latin) page is ASCII only. Typing accented or non-Latin characters — Polish, Czech, Slovak, German, French, Spanish, Portuguese or Nordic diacritics, Cyrillic, or Greek — needs Settings › Keyboard › Alphabet set to the matching language first; the keyboard's **#@/abc** key then cycles Latin → that alphabet → Symbols → Latin. A password containing characters outside whatever's currently enabled can still be set from the phone app — the device stores and replays it byte-for-byte.
|
||||
|
||||
---
|
||||
|
||||
### Message history
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Messages appear as chat bubbles sized to their content — **right**-anchored for outgoing, **left** for incoming — with sender name and a compact age indicator (`3m`, `2h`, `>1d`) in the top-right corner. List runs **newest at the bottom**; opening a history starts at the latest message, scrolling up goes further back. The list wraps at both ends like every other list: **UP** at the oldest message jumps to the newest, and **DOWN** past the newest lands on the compose row and then wraps to the oldest.
|
||||
|
||||
A tiny digit icon on a bubble is its hop count: on your own messages, how many repeaters echoed them back; on a **received** DM or channel post, how many hops it took to reach you. A received message always shows a time — if its timestamp is unknown or reads slightly ahead of this device's clock (sender/receiver clock skew, or the clock isn't synced yet), the receipt time is shown instead. In a channel history the title carries the channel's scope in brackets (`name [scope]`) whenever it is set to anything but `*`.
|
||||
|
||||
**Short Enter** on a message opens it in fullscreen. **Hold Enter** — on a history row or in fullscreen — opens the same options menu: Reply, plus **Navigate** / **Save waypoint** / **Set as target** when the message contains a location, and **Path** / **Relayed by** when hop data is available (see Fullscreen message view). You don't need to open the message first.
|
||||
|
||||
---
|
||||
|
||||
### Fullscreen message view
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Navigate between messages like pages in a book — **LEFT** goes back to the older message, **RIGHT** forward to the newer one. The `<` / `>` markers along the bottom edge show which directions still have a message. 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 options menu. It always offers **Reply** for an incoming message, and when the message contains a **location** it adds three more:
|
||||
|
||||
- **Navigate** — opens the bearing/distance view to those coordinates (the same two-bearing screen as Waypoints and Nearby; **Back** returns to the message).
|
||||
- **Save waypoint** — stores the location as a waypoint (visible on the trail map and in the Waypoints list).
|
||||
- **Set as target** — pins those coordinates as the active **Locator/Nav target** in one step, the same row Nodes and Waypoints offer (see Tools › Locator).
|
||||
|
||||
A location is any `lat,lon` pair in the text — exactly what the `{loc}` placeholder inserts — so you can navigate to anything a contact shares. A `[WAY]lat,lon label` share also carries a name, used as the waypoint label. This works on DMs and channel messages, incoming or outgoing.
|
||||
|
||||
When the entry has hop data recorded, the menu also adds one more row:
|
||||
|
||||
- **Path (N hops)** — on a received message (DM or channel), lists every repeater the message actually travelled through to reach you, oldest hop first.
|
||||
- **Relayed by (N)** — on your own channel post instead, lists every distinct repeater heard rebroadcasting it back into the mesh (order isn't meaningful here — each one heard it independently, not as a chain).
|
||||
|
||||
Selecting the row opens a read-only list of the resolved hops — each shown as the matching contact's name where one is known, or a short `?AABB`-style hex tag for an unrecognised repeater. Only repeaters within range of the message's actual travel — or, for **Relayed by**, within your own device's radio range — can ever be identified this way; a message with no recorded path (e.g. a zero-hop send, or one sent before any repeater relayed or echoed it) doesn't show this row at all.
|
||||
|
||||
---
|
||||
|
||||
### Context menu — contact list
|
||||
|
||||
**Hold Enter** on a contact entry opens a context menu:
|
||||
|
||||
> Rows that show a value (`Notif:`, `Melody:`, `Fav:`) are changed in place — **LEFT/RIGHT** steps the value and **Enter** advances it, with the menu staying open. Only **Back** closes the menu. The same rule holds in every context menu on the device.
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
| Item | Action |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------ |
|
||||
| Mark as read | Clears unread counter for this contact |
|
||||
| Notif: Default / OFF / ON | Per-contact notification override — **LEFT/RIGHT** or **Enter** to cycle |
|
||||
| Melody: Global / M1 / M2 | Per-contact melody override — **LEFT/RIGHT** or **Enter** to cycle |
|
||||
| Fav: ON / OFF | Mark this contact as a favourite — **LEFT/RIGHT** or **Enter** to toggle |
|
||||
| Pin to dial / Unpin (slot N) | Pin this contact to a Favourites Dial slot; if already pinned shows which slot |
|
||||
|
||||
**Fav** and **Pin to dial** are separate. **Fav** is the starred flag shared with the companion app: it marks the row with a ★, sorts it above the rest of the list (unless **Settings › Contacts › Favs top** is off), and drives the `DMs = Fav` list filter. **Pin to dial** puts the contact on the [Favourites Dial](../favourites_dial/favourites_dial.md) page and changes nothing about the list.
|
||||
|
||||
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.
|
||||
|
||||
In the **Rooms** list the context menu instead offers:
|
||||
|
||||
| Item | Action |
|
||||
| ------------- | ---------------------------------------------------------------------------- |
|
||||
| Login… | Opens the password prompt to (re-)log in to this room (see Rooms — logging in) |
|
||||
| Logout | Only shown once logged in. Forgets the saved password so the next open prompts for one again |
|
||||
| Fav: ON / OFF | Mark this room as a favourite — **LEFT/RIGHT** or **Enter** to toggle; drives the **Rooms = Fav** list filter |
|
||||
| Pin to dial / Unpin (slot N) | Pin this room to a [Favourites Dial](../favourites_dial/favourites_dial.md) slot |
|
||||
|
||||
---
|
||||
|
||||
### 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** or **Enter** to cycle |
|
||||
| Melody: Global / M1 / M2 | Per-channel melody override — **LEFT/RIGHT** or **Enter** to cycle |
|
||||
| Fav: ON / OFF | Add or remove this channel from favourites — **LEFT/RIGHT** or **Enter** to toggle |
|
||||
| Scope: <name> | **Enter** opens a picker over the shared scope list (Settings › Radio › Scope) — `*` sends this channel unscoped, any named scope tags its flood traffic with that region. Each channel keeps its own pick, matching the phone app's per-channel region picker. |
|
||||
| Pin to dial / Unpin (slot N) | Pin this channel to a [Favourites Dial](../favourites_dial/favourites_dial.md) slot |
|
||||
| Edit | Opens the Add/Edit form below, pre-filled with the channel's name |
|
||||
| Delete | Removes the channel — confirms first (defaults to Cancel) |
|
||||
|
||||
---
|
||||
|
||||
### Adding / editing a channel
|
||||
|
||||
Joining or creating a community channel no longer needs the phone app. The **Channels** list ends with **"+ Add channel"** — **Enter** picks a channel type; **Edit** from the context menu changes an existing channel's name/secret directly, skipping the type picker.
|
||||
|
||||
**+ Add channel** first asks which type to create — the same three the phone app offers:
|
||||
|
||||
- **Public** — instantly re-adds the well-known default public channel, no fields needed. Useful if it was deleted and you don't remember its key.
|
||||
- **Hashtag** — type a topic (e.g. `test`); name (`#test`) and secret (first 16 bytes of `sha256("#test")`) are both derived from it. A topic-based public chat — anyone typing the same topic elsewhere lands on the same channel, separate from the default Public one.
|
||||
- **Private** — the manual Name + Secret form:
|
||||
|
||||
| Field | Notes |
|
||||
| ------ | ---------------------------------------------------------------------------------------------- |
|
||||
| Name | Up to 31 characters |
|
||||
| Secret | **LEFT/RIGHT** toggles between two entry modes; **Enter** opens the keyboard for whichever is selected |
|
||||
|
||||
- **Passphrase** (default) — type any text; the device hashes it to the channel's 16-byte secret. Easiest to agree on verbally — same idea as a room password.
|
||||
- **Hex key** — the exact 32-hex-character secret (channel QR code format, see [QR Codes](../../qr_codes.md)), for joining with a secret you were given rather than a new passphrase. An all-zero secret (`00…0`) is rejected — reserved internally for an empty slot.
|
||||
|
||||
Select **[Save]** to commit. The secret can't be redisplayed once saved (only the derived key is kept) — editing later means typing a new one, same as re-logging into a room.
|
||||
|
||||
---
|
||||
|
||||
### Mark all read
|
||||
|
||||
**Hold Enter** on the DM / Channels / Rooms mode-select screen to clear all unread counters for the highlighted category at once.
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
@@ -1,85 +0,0 @@
|
||||
## 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.
|
||||
|
||||
On boards with a CardKB attached, **Fn+Esc** does the same thing in one press. Esc rather than the adjacent Backspace — those two keys sit next to each other on CardKB's layout and would be too easy to hit by accident.
|
||||
|
||||
If the display is off when the sequence begins, it turns on automatically so the hint is visible. Each press in the physical sequence extends the display-on timer by 5 seconds.
|
||||
|
||||
The hint popup at the bottom of the lock screen guides through the physical sequence:
|
||||
|
||||
| Step | Hint |
|
||||
| -------------- | ------------------------------------------------------------ |
|
||||
| Not started | _Hold Back + 3×Enter_ (_Back+3xEnter/Fn+Esc_ with CardKB attached) |
|
||||
| 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:
|
||||
|
||||
- **Title bar** — battery and status icons, same as every other home page — but never the device name, so a locked device doesn't announce whose it is at a glance
|
||||
- **Time** — same format as the Clock page (24 h / 12 h from Settings), left-aligned
|
||||
- **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.
|
||||
|
||||
---
|
||||
|
||||
### Magnetic cover (Hall sensor)
|
||||
|
||||
Optional, user-supplied hardware — no board in this repo has one built in. Wire a Hall-effect or reed sensor to any free GPIO, then set `PIN_HALL_SENSOR` (and `HALL_ACTIVE_HIGH=1`, if your module pulls the pin high rather than low when the magnet is present) as `build_flags` in your own env. No-op entirely unless `PIN_HALL_SENSOR` is defined.
|
||||
|
||||
Fully autonomous, independent of Auto-lock and of any key combo:
|
||||
|
||||
- **Magnet near (cover closed)** — locks and blanks the display immediately, no wake grace.
|
||||
- **Magnet away (cover opened)** — unlocks and wakes the display right away.
|
||||
|
||||
---
|
||||
|
||||
### Lock PIN
|
||||
|
||||
**Settings › Display › Lock PIN** asks for a PIN before the screen unlocks,
|
||||
also right after power-up, and when the magnet cover opens.
|
||||
|
||||
- Enter on the row opens a number pad: type the PIN (at least 4 characters),
|
||||
confirm with ✓, then type it again. The pad's keyboard key switches to the
|
||||
normal keyboard for a PIN with letters.
|
||||
- Unlocking (Back + Enter three times, or opening the cover) shows the pad
|
||||
with the input masked. A wrong PIN says how many tries are left; after 5 in
|
||||
a row, entry pauses for 30 seconds.
|
||||
- Enter on the row again removes the PIN.
|
||||
|
||||
The PIN is kept as a salted SHA-256 hash, never as the PIN itself. It locks
|
||||
the screen only: messages still arrive and the phone app still connects.
|
||||
On the Wio Tracker L2 it's **Settings › Display & power › Screen PIN**
|
||||
(digits only).
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,142 +0,0 @@
|
||||
## 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. **Enter** advances any row whose options wrap around — toggles, melodies, and option lists like Auto-off. Rows that ramp between fixed ends (Brightness, Volume, TX Pwr, Timezone, SF / BW / CR) are LEFT/RIGHT only, since there is nothing to wrap to.
|
||||
|
||||
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, or **Enter** to advance |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| Msg wake | ON / OFF | Whether an incoming message turns the display back on when it was off and no phone/app is connected (default ON — today's behaviour either way). |
|
||||
|
||||
---
|
||||
|
||||
### 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 / None | Notification sound for incoming private messages. `None` disables the sound for this event. |
|
||||
| Channel Melody | built-in / Melody 1 / Melody 2 / None | Notification sound for incoming channel messages. `None` disables the sound for this event. |
|
||||
| AD sound | built-in / Melody 1 / Melody 2 / None | Sound played whenever an **advert** is received from *any* node — pairs with Auto-Advert as an audible "in range" heartbeat (see Tools › Auto-Advert). `None` disables the sound for this event. |
|
||||
| AD scope | All / Zero-hop | Filters the AD sound so it plays for every advert or only for local zero-hop adverts. |
|
||||
|
||||
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 Pwr | 2–22 dBm | LEFT/RIGHT. With **Auto pwr** on this is the *ceiling* — the radio may transmit lower. On the **GAT562 30S** (external 30 dBm PA) the requested power maps through the PA's measured gain curve, so the stored value matches what is radiated; this row stays capped at 22, while the phone app / CLI can request up to 30 dBm — see [Build Flags › External PA](../build_flags.md#external-pa--tx-power-curve). |
|
||||
| Preset | named presets | LEFT/RIGHT cycles community RF presets (region frequency + bandwidth/SF/CR). **Enter** opens a popup to pick one, save the current settings as a named preset, or delete a saved one — deleting confirms first (defaults to Cancel). Applies frequency, bandwidth, SF and CR together. |
|
||||
| Freq | chip range | **Enter** opens a digit-by-digit editor: LEFT/RIGHT moves between decimal places, UP/DOWN steps that digit. Bounds come from the radio chip's own validated range, so a value the radio would reject can't be entered. |
|
||||
| SF | 5–12 | LEFT/RIGHT. Spreading factor. |
|
||||
| BW | 7.8–500 kHz | LEFT/RIGHT cycles the standard LoRa bandwidths. |
|
||||
| CR | 5–8 | LEFT/RIGHT. Coding rate (4/5–4/8). |
|
||||
| Auto pwr | ON / OFF | **Adaptive Power Control.** Lowers TX power on strong links, ramps back to the **TX Pwr** ceiling on weak/lost ones. Link quality from DM ACK SNR, or — for channels (no ACK) — a repeater's rebroadcast. Live power shown on the radio page/name bar. Default OFF. **Suppressed (`--`) while the repeater is on** — restored once it's switched off. |
|
||||
|
||||
There is no "Pwr save" row: hardware RX duty-cycle receive was tried and disabled (`FEAT_RX_POWERSAVE 0` in `examples/companion_radio/Features.h`) — the SX126x's duty-cycle preamble detection needs the sender's actual preamble to exactly match what we configure, which a mixed-firmware mesh can't guarantee (silently drops every packet from a mismatched sender, no matter the signal strength).
|
||||
| Scope | list | Shows the list's **default** scope. **Enter** opens the **SCOPE** list: `*` (wildcard = unscoped, always first, can't be renamed or deleted) plus up to 8 named scopes of your own (e.g. `pl`). Typing a name derives a shared key the same way on every device, so any device that types the same name lands on the same scope automatically, no key exchange needed. **Enter** on a row opens **Set as default** / **Rename** / **Delete** (delete confirms first); **+ Add scope** at the bottom opens the keyboard. The **default** scope (marked `[default]`) governs **DMs** and the **repeater's own relay slot**; each **channel** carries its own pick — set from the channel's context menu (see [Message Screen](../message_screen/message_screen.md)) — and a channel left on `*` sends unscoped. Scopes tag flood traffic so repeaters can tell your community's messages apart from others sharing the same frequency; paired with **Tools › Repeater › Scope only** it's also what this device relays for in repeater mode. The default also syncs both ways with the phone app's default-scope setting. Not encryption — message content is unaffected either way. Upgrading from a build with the old single Scope field carries it over as the default entry and seeds every existing channel with it, so nothing changes on the air. |
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
<!-- screenshot pending: Radio — preset popup (pick/save/delete) and/or the digit-by-digit frequency editor -->
|
||||
|
||||
The **repeater** mode and its flood filters live on their own screen — see **Tools › Repeater**, including how it uses **Scope** above.
|
||||
|
||||
---
|
||||
|
||||
### System
|
||||
|
||||
| Setting | Options | Notes |
|
||||
| ----------- | --------------------------------------------------- | -------------------------------------------------------------------------------------- |
|
||||
| Name | keyboard entry (up to 31 chars) | This device's node name, shown to others and in every advert. **Enter** opens the keyboard pre-filled with the current name; applied and saved on submit |
|
||||
| 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 |
|
||||
| GPS pwr _(if GPS detected)_ | OFF / 1 min / 5 min / 15 min / 30 min / 1 h | **Battery saver.** Cycles GPS off between fixes; each wake waits up to 60 s for a fix before sleeping again. Stays continuously on whenever something needs a live position — Trail recording, Live share, an armed Locator, Compass/Nearby, or an in-flight `!gps fix`. `OFF` (default) = always-on, as before. Status icon blinks while napping. |
|
||||
| Units | Metric / Imperial | Global unit system for every distance/speed shown in Tools (Nearby Nodes, Trail, navigate-to-point). Metric: m / km, km/h, min/km. Imperial: ft / mi, mph, min/mi |
|
||||
| Reboot | action (**Enter**) | Restarts this device. Pending setting changes are saved first. Last row, so it isn't the default-selected one |
|
||||
|
||||
---
|
||||
|
||||
### Keyboard
|
||||
|
||||
| Setting | Options | Notes |
|
||||
| -------- | ---------- | -------------------------------------------------------------------------------------------------- |
|
||||
| Layout | ABC / T9 | On-screen keyboard style. **ABC**: a-b-c…z grid, one key per letter. **T9**: phone-keypad multi-tap — each key labelled digit+letters (e.g. `2abc`); repeated **Enter** cycles the letters then the digit. Applies to whichever script page is active, not just Latin. |
|
||||
| Main | Latin / Cyrillic / Greek | Which script the keyboard opens on by default. **Latin** is the default; picking **Cyrillic** or **Greek** makes that the one you land on, with Latin moving to the Additional cycle instead. |
|
||||
| Additional | Latin / Cyrillic / Greek | The second script in the **#@/abc** key's cycle (Main → Additional → Symbols → Main). Setting it to the same script as Main drops the cycle to just that script plus Symbols. **Greek** covers the 24-letter alphabet plus final sigma (`ς`), not the tonos stress accents. Every script renders natively via one shared Unicode font — no separate toggle needed. |
|
||||
| Ext. KB | Full / Compact | Only shown on a build with CardKB support (`CARDKB_I2C` or `ENV_PIN_SDA`/`ENV_PIN_SCL` set). Picks how the on-screen keyboard behaves while a CardKB is doing the typing — see [External Keyboard & Joystick](../external_keyboard.md#ext-kb--full-vs-compact). |
|
||||
|
||||
Applies to every on-screen text field (messages, waypoint labels, room passwords, preset names).
|
||||
|
||||
European Latin-diacritic letters (Polish, Czech, Slovak, German, French, Spanish, Portuguese, Nordic, etc.) aren't separate alphabet pages — instead, **Hold Enter** on a plain Latin letter that has accented variants (`a c d e i l n o r s t u y z`) opens a one-row popup of its accents (e.g. holding `a` offers `á à â ã ä å ą`); **LEFT/RIGHT** picks, **Enter** inserts it, **Cancel** dismisses with no change. Holding a letter with no accented variants (e.g. `b`) does nothing. Works on whichever page is currently showing Latin, whether that's Main or Additional.
|
||||
|
||||
---
|
||||
|
||||
### Contacts
|
||||
|
||||
| Setting | Options | Notes |
|
||||
| -------- | --------- | ------------------------------------------- |
|
||||
| DMs | All / Fav | Show all chat contacts or only favourited ones |
|
||||
| Channels | All / Fav | Show all channels or only favourited ones |
|
||||
| Rooms | All / Fav | Show all room servers or only favourited ones |
|
||||
| Favs top | ON / OFF | Sort favourites to the top of every list (default ON) |
|
||||
| Expire | Off / 7d / 30d / 90d | Age after which a contact with no advert/update counts as inactive (default Off). Only used by **Prune now** — nothing is ever deleted automatically. |
|
||||
| Prune now | action (**Enter**) | Counts the contacts older than **Expire**, then asks `Remove N contacts?` (defaults to Cancel) before deleting anything. Shows `Expire is Off` / `No inactive contacts` instead when there is nothing to do. |
|
||||
|
||||
Favourites are set per item in its context menu (**Hold Enter** › **Fav: ON / OFF**) — see [Message Screen](../message_screen/message_screen.md), and the same row exists in Tools › Nodes. A contact's or room's favourite flag is the same one the companion app shows as a starred contact, so it syncs both ways; a channel's is device-only.
|
||||
|
||||
A favourite is marked with a ★ on its row wherever it is listed, and — unless **Favs top** is off — sorted above everything else. The three filters above are independent of that: they control what's *listed at all*, the sort only controls the order.
|
||||
|
||||
**Pruning.** A contact is inactive when its last advert/update is older than **Expire**. **Favourites are never pruned**, and neither is a contact with no timestamp or one that reads ahead of the device's own clock (e.g. the clock isn't set yet) — the rule only ever errs on the side of keeping data.
|
||||
|
||||
---
|
||||
|
||||
### Messages
|
||||
|
||||
| Setting | Options | Notes |
|
||||
| ------- | -------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| Resend | OFF / 1×–5× | Auto-resend an on-device direct message this many times when no delivery ACK is received (default 2×) |
|
||||
|
||||
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).
|
||||
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,593 +0,0 @@
|
||||
## 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, the remote bot, auto-advert, live location sharing, locator, compass, clock tools (alarm / timer / stopwatch), device diagnostics, repeater mode, and remote admin. Tools are grouped into collapsible **Location** / **Comms** / **System** sections — the same fold-in-place model as Settings; Tools always opens folded back to the section list. Navigate with **UP/DOWN**, press **Enter** on a section header to expand or collapse it, or on a tool to open it.
|
||||
|
||||
---
|
||||
|
||||
## Nearby Nodes
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Browse nodes that have recently advertised on the mesh. **Filter** (which nodes) and **sort** (in what order) are independent axes and combine freely.
|
||||
|
||||
Filter by category with **LEFT/RIGHT**:
|
||||
|
||||
| Filter | Shows |
|
||||
| ------ | ------------------------------ |
|
||||
| All | All known nodes |
|
||||
| Fav | Favourites only (★) |
|
||||
| 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. A node that is **broadcasting its position** via Live Share is marked with a **♦ diamond** beside its name in the list (the same marker the map uses), and its detail shows `Sharing pos:` with the share age and whether it's DM-verified or channel-only. A **★ star** marks a favourite, which is also sorted to the top of the list unless **Settings › Contacts › Favs top** is off.
|
||||
|
||||
**Hold Enter** opens the same **Options** menu everywhere (list and detail), in a fixed order — only the actions that apply appear:
|
||||
|
||||
| Action | Available when |
|
||||
| ---------------------- | -------------------------------------------------------------------------------------- |
|
||||
| Navigate | selected node has GPS — for a node sharing live position, the view follows it as it moves and adds an ETA line |
|
||||
| Ping | a public key is known for the node |
|
||||
| Save waypoint | selected node has GPS |
|
||||
| Set as target | selected node has a position — pins it as the active **Locator/Nav target** right away (see **Locator**). A node with a known public key (a contact, a scan result, or someone sharing over DM) becomes a **person** target that keeps following them; a name-only row — someone sharing their position on a channel who isn't your contact — becomes a **place** target pinned where they were, since there's no identity to re-resolve |
|
||||
| Fav: ON / OFF | selected node is a saved contact — **LEFT/RIGHT** or **Enter** toggles it in place, as in the Messages menus; the same starred flag those lists use, shared with the companion app |
|
||||
| Pin to dial / Unpin (slot N) | selected node is a saved contact — puts it on the [Favourites Dial](../favourites_dial/favourites_dial.md), taking the first free slot |
|
||||
| Admin | selected node is a saved **repeater or room server** contact — opens **Tools › Admin** for it directly (see **Admin**) |
|
||||
| Sort: Dist/Recent | browsing stored nodes — **LEFT/RIGHT** or **Enter** flips distance ↔ last-heard in place |
|
||||
| Discover scan / Rescan | always (live `NODE_DISCOVER_REQ` scan) |
|
||||
|
||||
Filtering stays on the list itself (**LEFT/RIGHT** cycles the type), so there is no separate Filter action in the menu. **Sort** is adjusted in place: highlight the **Sort** row and tap **LEFT/RIGHT** to flip the list (and its right-hand column) between **distance** and **last-heard** without closing the menu. The row appears only while browsing stored nodes (live-scan rows carry signal, not distance). Filter and sort are independent and **persist** across re-entry to the screen.
|
||||
|
||||
Selecting **Ping** opens the Ping popup:
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :----------------------------: | :----------------------------: |
|
||||
|  |  |
|
||||
|
||||
Use **Enter** on the popup’s `Ping` row to send a direct mesh ping to that node. The popup then shows the RTT and SNR values on the next lines, and can be used again immediately for another 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 (live scan)
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
**Options → Discover scan** sends a `NODE_DISCOVER_REQ`. Repeaters, sensors and room servers within zero-hop range respond immediately with name, type and signal data. This is not a separate screen — it is the **same list switched to a live-scan source**: the right-hand column shows **RSSI** instead of distance, and node detail shows the public key, signal data and contact status.
|
||||
|
||||
Because it is the same list, all the same keys apply — **UP/DOWN** to navigate, **Enter** for detail, **Hold Enter** for the Options menu (where **Rescan** repeats the scan and **Ping** works exactly as on stored nodes).
|
||||
|
||||
- **Cancel / Back** — return to the stored-nodes list
|
||||
|
||||
---
|
||||
|
||||
## GPS Trail
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
Records your route in a RAM ring buffer (up to 512 points, sampled every 1 s). The track is **simplified as it's recorded** — a long straight stretch is kept as just its two endpoints while curves keep their detail (bounded to within the **Min dist** tolerance of the real path), so the buffer covers a far longer route than a flat point budget would suggest. 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.
|
||||
|
||||
> [!TIP]
|
||||
> The **Map** view is also reachable directly from the home carousel — the **Map** page shows a live mini-preview (your position, trail, and tracked contacts) with a **north marker** and a bottom-left **scale tick**. The status line below reads `Track:N` (tracked-node count) and, when you have a fix and at least one tracked contact, an **arrow + distance** to the **nearest** one (e.g. `Track:3 →120m`). If a **Locator/Nav target** is set it's drawn as a **flag marker** (see **Locator**). Press **Enter** to open the full Trail Map; **Hold Enter** shares your position (see **Live Share**); **Back** returns home.
|
||||
|
||||
A GPS fix indicator also sits in the top status bar, alongside the trail/auto-advert/repeater icons — boxed (lit) once the receiver has a valid fix, a plain glyph while still searching. It only appears on boards with GPS hardware and while **GPS** is turned on in Settings; it's hidden the rest of the time rather than sitting there empty.
|
||||
|
||||
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; square scale grid fitted to the map frame (toggle under **Hold Enter → Settings → Grid**, Map view only). Your **current GPS position**, all **waypoints**, and any **live-tracked contacts** (positions shared via Live Share) are always drawn — even with no trail recording — so the map is useful standalone. The active **Locator/Nav target**, if set, is drawn as a **flag** on top (folded into the frame so it's never off-screen). Point labels are auto-placed to avoid overlapping (a crowded cluster drops some labels rather than smearing them) |
|
||||
| **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**. It is two-level — a short main menu, plus **Trail file…** and **Settings…** submenus. **Cancel/Back** in a submenu returns to the main menu.
|
||||
|
||||
**Main menu:**
|
||||
|
||||
| Item | Action |
|
||||
| --------------------- | --------------------------------------------------- |
|
||||
| Start / Stop tracking | Begin or end a recording session. If **GPS is off**, choosing Start asks **"GPS is off — Enable GPS & start"** so a session can't silently run with nothing to record |
|
||||
| Mark here | Drop a waypoint at the current GPS fix (see below) |
|
||||
| Waypoints… | Open the waypoint list / navigation / add-by-coords |
|
||||
| Track back | Retrace the recorded route back to its start (needs ≥2 points; see below) |
|
||||
| Share my pos | Send your current position as a one-shot `[LOC]` message — pick a contact or channel (see **Live Share**) |
|
||||
| Trail file… | Open the file submenu (below) |
|
||||
| Settings… | Open the settings submenu (below) |
|
||||
|
||||
**Trail file…** (only the operations that apply right now appear):
|
||||
|
||||
| Item | Action |
|
||||
| -------------- | ----------------------------------------------- |
|
||||
| Save trail | Write RAM ring to flash (`/trail`) |
|
||||
| Load trail | Restore flash trail into RAM |
|
||||
| Export (live) | Stream live RAM trail as GPX 1.1 over USB Serial |
|
||||
| Export (saved) | Stream saved flash trail as GPX 1.1 over USB Serial |
|
||||
| Reset trail | Clear RAM ring and elapsed time — confirms first (defaults to Cancel) since there's no way back short of a prior **Save trail** |
|
||||
|
||||
**Settings…** (values cycle with **LEFT/RIGHT** or **Enter**; shown only where they apply):
|
||||
|
||||
| Item | Available | Action |
|
||||
| ---------- | --------- | ------------------------------------------------------- |
|
||||
| Min dist | always | Sample gate, 4 levels — metric: 5/10/25/100 m, imperial: 15/30/75/300 ft |
|
||||
| Auto-pause | always | OFF / 1 / 2 / 5 min — auto-freeze the trail after a stop, resume on movement (see below) |
|
||||
| Mark avg | always | OFF / 5 / 10 / 30 s — GPS averaging for **Mark here** (see Waypoints below) |
|
||||
| Auto-save | always | OFF / ON — auto-write the live trail to flash on shutdown, so a **low-battery auto-shutdown** doesn't lose the route (see below) |
|
||||
| Readout | Summary view | Summary shows Speed or Pace (in the global unit system) |
|
||||
| Grid | Map view | Toggle scale grid on the map |
|
||||
|
||||
(Trail file… appears only when a live or saved trail exists. Mark here needs a GPS fix; Waypoints is always available.)
|
||||
|
||||
**Auto-pause** — when set, a recording trail automatically **pauses** after the device has stayed within ~15 m of one spot for the chosen delay: the elapsed timer and point sampling both freeze, and the map line breaks across the idle gap. It **resumes on its own** as soon as you move again. This keeps a stop (a break, a meal, parking) out of your distance and average-speed stats without you having to remember to stop and restart tracking. A paused trail is still "on" (the **G** marker keeps blinking) — the Summary **Status** row shows `paused`. The stop is detected with its own coarse movement gate, independent of **Min dist**, so GPS jitter while you're parked doesn't keep it awake.
|
||||
|
||||
**Auto-save** — with this on (default off), the live trail is written to flash automatically when the device powers off, so a **low-battery auto-shutdown** no longer discards the whole route. It saves to the same `/trail` file as the manual **Trail file… → Save**, and only writes when the trail actually has points — an empty trail can't overwrite a previously saved one.
|
||||
|
||||
### Track back
|
||||
|
||||
**Hold Enter → Track back** retraces your recorded trail back to the start — useful in poor visibility or unfamiliar ground. It reuses the navigation view (distance + two absolute bearings; see *Waypoints › Navigating*), but walks the recorded breadcrumbs in reverse: snaps to the **nearest recorded point**, guides you to it, then advances to the next earlier point as you reach each one (within ~20 m). The header shows points remaining (`Back: 12 pt`), reading `Trail start` on the final leg; arriving shows `Back at start` and exits. **Cancel** leaves track-back at any time. Needs a trail with at least two points and a GPS fix; tracking doesn't need to still be running.
|
||||
|
||||
### Waypoints
|
||||
|
||||
A waypoint is a saved spot — your car, camp, a water source — that you can navigate back to later. Waypoints are **independent of the trail**: they live in their own flash file (`/waypoints`), survive a reboot, and are **not** cleared by *Reset trail*. Up to 16 can be stored — the Waypoints list header shows how many are in use (e.g. `WAYPOINTS 3/16`).
|
||||
|
||||
**Dropping a waypoint** — **Hold Enter → Mark here**. This captures the current GPS fix and opens the on-screen keyboard for a short label (up to 11 characters — e.g. `CAR`, `CAMP`, `H2O`). Leaving it blank auto-names it `WP1`, `WP2`, … Marking works whether or not the trail is being recorded; it needs a GPS fix (otherwise it reports *No GPS fix*).
|
||||
|
||||
**GPS averaging** — with **Settings → Mark avg** set (5 / 10 / 30 s), *Mark here* doesn't snapshot a single fix; it samples the GPS once a second for that window and stores the **mean** position, for a steadier mark than one instantaneous reading (handy for a precise spot — a cache, a car, a trailhead). A short screen shows the time left and the sample count while it runs; **Cancel** aborts. When the window closes it opens the label keyboard as usual. With **Mark avg = OFF** (the default) marking is instant.
|
||||
|
||||
**Adding by coordinates** — open **Hold Enter → Waypoints** and select the **+ Add by coords** row (always the last entry in the list). This creates a waypoint without being there — no GPS fix required (handy for a meeting point or a spot read off a map). It opens a small form with three editable rows plus **Save**:
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :------------------------: | :------------------------: |
|
||||
|  |  |
|
||||
|
||||
<!-- screenshot pending: Add-by-coords form — Lat/Lon scroll editor, hemisphere toggle, Label, Save -->
|
||||
|
||||
|
||||
- **Lat** / **Lon** — **Enter** opens the digit-by-digit scroll editor (the same widget as the radio frequency field): **LEFT/RIGHT** move the cursor between decimal places, **UP/DOWN** change the digit under it, **Enter** confirms. With the editor closed, **LEFT/RIGHT** on the row toggles the hemisphere — N/S for latitude, E/W for longitude.
|
||||
- **Label** — **Enter** to type a name (blank → auto `WP<n>`).
|
||||
- **Save** — validates the range and stores the waypoint. Missing or out-of-range values report a brief error.
|
||||
|
||||
**On the map** — saved waypoints show as a hollow diamond with the label's first two characters beside it. Waypoints and your GPS position are drawn continuously, even with no trail recording, so the Map view doubles as a live "you + your marks" view. With **no trail**, it auto-fits to waypoints and position; **with a trail**, it frames the route instead, clamping any out-of-frame waypoint to the nearest edge so a distant mark can't blow up the scale.
|
||||
|
||||
**Navigating** — **Hold Enter → Waypoints** opens the list (each row shows the label and live distance). The list always begins with a synthetic **Trail start** row whenever a trail exists, so you can backtrack to where you began without having marked it. Select a row and press **Enter** to open the navigation view:
|
||||
|
||||
```
|
||||
CAMP ← target label
|
||||
1.4 km ← distance to target
|
||||
To: 145° SE ← absolute bearing to the target
|
||||
Hdg: 090° E ← your current course over ground (-- when stationary)
|
||||
```
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :------------------------: | :------------------------: |
|
||||
|  |  |
|
||||
|
||||
<!-- screenshot pending: Waypoints navigation view — target label, distance, To/Hdg bearings (shared with Nearby/message Navigate) -->
|
||||
|
||||
There is no magnetometer, so the screen shows two *absolute* bearings and you compare them: target at 145°, travelling at 90° → bear right. The **Hdg** line is derived from GPS movement (see Compass) and reads `--` until you move. A fourth line shows closing speed and **ETA** once you're actually approaching. **Back** leaves the view — it's the only key that does, on every navigate view.
|
||||
|
||||
**Managing** — **Hold Enter** on a waypoint row offers **Rename** / **Delete** / **Send** / **Set as target** (the *Trail start* row is navigate-only). **Set as target** pins the waypoint as the active **Locator/Nav target** in one step (see **Locator**). Delete removes one at a time; there is no bulk clear.
|
||||
|
||||
**Sharing** — **Send** hands the waypoint to the Messages screen: pick a contact or channel, and the message is pre-filled as `[WAY]<lat>,<lon> <label>` (e.g. `[WAY]37.42123,-122.08456 CAR`) for you to confirm or edit before sending. On the receiving device, opening that message and **Hold Enter → Navigate / Save waypoint / Set as target** turns it back into a navigable point (see *Messages › Fullscreen message view*). The format is plain text, so it stays readable on other firmware and the phone app.
|
||||
|
||||
### Downloading GPX
|
||||
|
||||
**Easiest — [Solo GPX Downloader](https://marekzegare4.github.io/solo-tools/)** (browser-based, no install):
|
||||
|
||||
1. Open the link in **Chrome** or **Edge** (Web Serial API required).
|
||||
2. Click **Connect device** and select the USB serial port.
|
||||
3. On the device: **Tools › Trail** → **Hold Enter** → **Export (live)** or **Export (saved)**.
|
||||
4. The browser captures the stream automatically — set a filename and click **Download**.
|
||||
|
||||
**Script — `tools/trail_export.py`** (auto-detects the port, captures from `<?xml` to `</gpx>`, writes a timestamped file under `tools/gpx/`):
|
||||
|
||||
```sh
|
||||
uv run tools/trail_export.py
|
||||
```
|
||||
|
||||
Then on the device: **Tools › Trail** → **Hold Enter** → **Export (live)** or **Export (saved)**.
|
||||
|
||||
**Manual fallback** — open a serial terminal at **115200 baud** and capture the stream by hand:
|
||||
|
||||
- **macOS/Linux** — `cat /dev/tty.usbmodem* > track.gpx` (stop with Ctrl-C after the dump finishes)
|
||||
- **Windows** — PuTTY (Serial, 115200) or Arduino IDE Serial Monitor with no line ending; copy the text from `<?xml` to `</gpx>` into a `.gpx` file
|
||||
|
||||
Saved **waypoints are included** in the export as GPX `<wpt>` elements (with their label as `<name>`), alongside the track — so they show as pins in 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.
|
||||
|
||||
> [!TIP]
|
||||
> **Audible connection heartbeat** — the device chirps on every *received* advert (sound in **Settings › Sound › AD sound**). With Auto-Advert on both ends (e.g. two hikers), each hears the other's periodic advert as a hands-free "in range" beep. It fires on **every** received advert, so a busy mesh gets chatty — set `None` in **AD sound** to silence just this, or **Advert scope** to `Zero-hop` to limit it to local adverts. **Settings › Sound › Buzzer** = *OFF* (or *Auto*, mutes while a companion app is connected) silences all buzzer output.
|
||||
|
||||
---
|
||||
|
||||
## Live Share
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :------------------------: | :------------------------: |
|
||||
|  |  |
|
||||
|
||||
<!-- screenshot pending: Live Share screen — Track loc / Auto share / Stop after / To / Scope / Move / Min gap / Heartbeat rows -->
|
||||
|
||||
Share your live position over the mesh **as ordinary chat messages**, and put other people who do the same on your map. A position is sent as a `[LOC]<lat>,<lon>` message — the same coordinate format waypoints use, so it stays readable on other firmware and the phone app (it just looks like a coordinate to anything that doesn't know the tag).
|
||||
|
||||
This is **independent of Auto-Advert** and runs alongside it: Auto-Advert announces your *presence* as a 0-hop beacon for Nearby Nodes, while Live Share sends your *position* to a specific channel or contact you choose.
|
||||
|
||||
The tool holds both directions of sharing in one flat list. Navigate with **UP/DOWN**, change a value with **LEFT/RIGHT** (or **Enter**); **Cancel/Back** saves and returns to Tools.
|
||||
|
||||
| Setting | Options | Notes |
|
||||
| ---------- | --------------------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| Track loc | ON / OFF | Receive incoming `[LOC]` shares (DM, monitored channels, and room-server posts) and pin those senders on the map / in Nearby. Off by default. |
|
||||
| Auto share | ON / OFF | Periodically broadcast **your own** position to the target below while you move, for the length of **Stop after**. |
|
||||
| Stop after | 1 / 2 / 4 / 8 / 12 h | **Length of one auto-share session** (default 1 h). When it runs out, Auto share switches itself off and shows `Live share ended` — sharing can never run indefinitely. The clock starts when you turn **Auto share** on (or change this value) and restarts if the device reboots while sharing is on. |
|
||||
| To | channel or contact | **Enter** opens the Messages recipient chooser to pick the target channel or DM contact. |
|
||||
| Scope | Target / `*` / a named scope | Region for these `[LOC]` posts **only**, independent of your chat. **Target** (default) follows the target as before — a channel's own scope pick, or the list default for a DM. Any other value (from the shared list in Settings › Radio › Scope; `*` = unscoped) overrides it for Live Share and never changes how your normal messages are sent. A DM that already has a known route goes direct, where a scope has no effect. |
|
||||
| Move | 50 / 100 / 250 / 500 m | Movement gate — only send after you've moved at least this far since the last share. |
|
||||
| Min gap | 30 s / 1 / 2 / 5 min | Minimum time between sends, so fast movement can't flood the channel. |
|
||||
| Heartbeat | OFF / 5 / 15 min | Optional keep-alive: re-send even while stationary, so the other end knows you're still there. |
|
||||
|
||||
**How auto-share decides to send.** The device checks a few times a minute and transmits once you've moved at least **Move** metres *and* **Min gap** has passed since the last send — a stationary device stays silent unless **Heartbeat** is set. It also sends once immediately on enabling sharing (or changing the target).
|
||||
|
||||
**Receiving.** With **Track loc** on, incoming `[LOC]` messages update a small live table (up to 16 nodes, entries expire ~20 min after the last update). DM shares are keyed by the sender's public key (reliable); channel and room-server shares are keyed by name (best-effort, since channel names are unsigned and a room post only carries a short sender prefix). Tracked nodes appear on the **Trail Map** as a filled diamond with the first two characters of their name, and in **Nearby Nodes** with their live distance/bearing.
|
||||
|
||||
**One-shot share.** To send your position once without enabling auto-share, use **Tools › Trail → Hold Enter → Share my pos** — it builds a `[LOC]` message and hands it to the Messages screen to pick a recipient. There's also a shortcut from the home **Map** page: **Hold Enter** sends an immediate position update to your Live Share target while auto-sharing is on (toast `Position shared`), or opens the recipient picker if it isn't — so you never broadcast to a default channel by accident.
|
||||
|
||||
---
|
||||
|
||||
## Locator
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
<!-- screenshot pending: Locator screen with a target set (e.g. "@Bob (5m)"), radius/mode/beeper rows -->
|
||||
|
||||
A single **geofence** that beeps and alerts when you cross **into** or **out of** a radius. The target is either a **saved waypoint** (a fixed place — "tell me when I'm back at camp") or a **live contact** ("alert me when my friend gets near / falls behind"). A waypoint target is a **snapshot** — it keeps working even if you edit that waypoint later; a contact target follows their latest shared position. If the target waypoint or contact is deleted, the Locator target clears back to `none`.
|
||||
|
||||
Navigate with **UP/DOWN**, change a value with **LEFT/RIGHT** (or **Enter**); **Cancel/Back** saves and returns to Tools.
|
||||
|
||||
| Setting | Options | Notes |
|
||||
| ------- | -------------------------------- | -------------------------------------------------------------------------------------- |
|
||||
| Alert | ON / OFF | Master switch. Enabling without a target prompts you to pick one. |
|
||||
| Target | none / person / waypoint | **Enter** opens a picker — **None** first (clears the target), then your **favourites** (offered even with no known position yet, so you can arm ahead of time), then any other contact with a currently-resolvable position (live-sharing *or* just last-advertised, e.g. a repeater), then waypoints; **UP/DOWN** + **Enter** to choose. **LEFT/RIGHT** quick-cycles the same set in place, including back to **None**. A person is shown with an `@` prefix, a ★ when they're a favourite, plus a compact **age tag** (e.g. `@Bob (5m)`) when the position is last-advertised rather than a live share. Shows `none` until set. |
|
||||
| Radius | 50 / 100 / 250 / 500 m / 1 km | Geofence size. |
|
||||
| Mode | Arrive / Leave / Both | Which crossing fires the alert — entering the radius, leaving it, or both. |
|
||||
| Beeper | ON / OFF | Optional homing tone — shown only in **Arrive** / **Both** modes (see below). |
|
||||
|
||||
**Crossing alert.** When armed with a target, the device watches its own GPS fix and fires the alert (a short melody plus an on-screen message) the moment you cross the radius, according to **Mode**. The wording adapts to the target — `Arrived` / `Left` for a waypoint, `Near` / `Away` for a person. The edge has a little hysteresis so a fix hovering right on the boundary doesn't chatter, and the first reading after arming only seeds the in/out state — it won't fire spuriously just because you armed it while already inside.
|
||||
|
||||
**Following a person.** Pick a **favourite** (or any contact with a known position) as the target and the geofence tracks the distance *between you and them*, working while both of you move. Position resolves with a fixed precedence: an active live `[LOC]` share wins, falling back to the contact's last-advertised position otherwise — so a stationary node (a repeater, or a one-time fix) still works. You can arm ahead of time — a favourite locks onto their pubkey, and the alert starts once a position is known. Live following needs a **DM** share (a channel share has no stable identity); the last-advertised fallback works for any contact.
|
||||
|
||||
**Proximity beeper.** With **Beeper** on, the device ticks while inside the radius, shortening the gap as you get closer — slow near the edge, rapid near the centre — like a homing beeper. Silent outside the radius. As an opt-in toggle, it **overrides the global buzzer mute** — an explicit "I want to hear this." It only appears in **Arrive**/**Both** mode (hidden and silent in **Leave**-only). Independent of the crossing alert, which does follow the mute — use either or both.
|
||||
|
||||
**Setting the target from anywhere.** Besides this screen's picker, the *same* active target can be set in one step with **Set as target** from the **Hold Enter** menu of **Nearby Nodes**, **Waypoints**, or a message carrying a location — handy so you don't need a detour through Tools. Picking from this screen's picker saves on exit (so **LEFT/RIGHT** cycling stays cheap); the per-item shortcuts save immediately and confirm with a `Target set` toast.
|
||||
|
||||
**On the map.** Whatever the active target is — person or waypoint — it's drawn as a **flag marker** on both the home **Map** preview and the full **Trail Map**, on top of any waypoint/contact it overlaps and folded into the frame so it never sits off-screen. This shows even when the **Alert** master switch is off, so a target you set purely to navigate to still appears.
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------------: | :-----------------------------: |
|
||||
|  |  |
|
||||
|
||||
<!-- screenshot pending: PICK TARGET picker — None, favourites, a last-advertised contact with age tag (e.g. "@Bob (5m)"), and waypoints -->
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------------: | :-----------------------------: |
|
||||
|  |  |
|
||||
|
||||
<!-- screenshot pending: Trail Map (or home Map preview) with the active-target flag marker visible -->
|
||||
|
||||
> [!TIP]
|
||||
> Mark the spot first with **Tools › Trail → Hold Enter → Mark here** (or **+ Add by coords**), then set it as the Locator target.
|
||||
|
||||
---
|
||||
|
||||
## Compass
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :------------------------: | :------------------------: |
|
||||
|  |  |
|
||||
|
||||
<!-- screenshot pending: Compass — scrolling heading tape with centre pointer + large degrees/cardinal readout -->
|
||||
|
||||
A heads-up GPS compass. No magnetometer, so heading is **course over ground** — derived from how your GPS position moved over the last few seconds. Display is a horizontal **heading tape**: a fixed pointer at centre, N..E..S..W scrolling underneath as you turn, so whatever's under the pointer is your course. A large numeric readout below shows it in degrees and cardinal (e.g. `145° SE`).
|
||||
|
||||
Since heading comes from movement, it only updates while moving — standing still shows *move to set heading* (navigation's **Hdg** reads `--`). Gross GPS jumps are rejected so one bad fix can't swing it. Runs on any GPS fix; recording a trail is **not** required.
|
||||
|
||||
---
|
||||
|
||||
## 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 or Enter | Cycle duration for selected note |
|
||||
| BPM | LEFT/RIGHT or Enter | Step tempo (stops at each end) |
|
||||
| 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.
|
||||
|
||||
---
|
||||
|
||||
## Remote Bot
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :-----------------------: | :-----------------------: |
|
||||
|  |  |
|
||||
|
||||
<!-- screenshots pending: these predate the tab-carousel layout below (still show the old flat grouped list) -->
|
||||
|
||||
Automatically replies to incoming messages containing a configured trigger word (case-insensitive, contains match). Pack multiple phrases into one Trigger field, comma-separated (`hi,hello there,yo`) — any one matches; spaces around each phrase are trimmed. Three independent targets — **DM**, a monitored **Channel**, and a monitored **Room** — each with its own trigger/reply pair.
|
||||
|
||||
The screen is a **circular tab carousel** (same style as Nearby Nodes' filter tabs): **LEFT/RIGHT** switches between **Channel** / **Room** / **Direct** / **Other** (opens on Channel), **UP/DOWN** moves within the active tab, **Enter** acts on the selected row (LEFT/RIGHT is reserved for tab-switching — every value changes via Enter, not in-place cycling).
|
||||
|
||||
Each target has its own **Enable** toggle on its own tab, and they're fully independent — you can run only a channel bot, only a room bot, only DM, or any combination, with no need to also switch on the others.
|
||||
|
||||
Each target also has its own **Commands** toggle (see below) — DM, channel and room can each independently answer `!` queries or stay quiet, same as Enable.
|
||||
|
||||
#### Channel tab
|
||||
|
||||
| Setting | Description |
|
||||
| ------- | --------------------------------------------------------------------------------- |
|
||||
| Enable | ON / OFF — **Enter** toggles. Independent of which channel is picked below, so switching it off and back on remembers the last channel. |
|
||||
| Channel | Which channel the bot monitors — always shows the last-picked channel (or `(none)` if none exist yet), regardless of Enable. **Enter** opens the full channel picker (the same one Live Share's **To** row uses). |
|
||||
| Commands | ON / OFF — **Enter** toggles. Answer `!` query commands on the monitored channel, independent of the other two tabs' Commands settings. |
|
||||
| Trigger | Independent trigger for the monitored channel. `*` means **reply to every channel message** — bounded by the per-channel cooldown, but use sparingly on a busy channel. |
|
||||
| Reply | Reply text for channel messages; supports the same placeholders as Direct's Reply. |
|
||||
|
||||
#### Room tab
|
||||
|
||||
| Setting | Description |
|
||||
| ------- | --------------------------------------------------------------------------------- |
|
||||
| Enable | ON / OFF — **Enter** toggles. Independent of which room is picked below. |
|
||||
| Room | Which room server the bot posts to — always shows the last-picked room (or `(none)` if you have none yet), regardless of Enable. **Enter** opens the full room picker. Picking a room you've never logged into prompts for its password right there — the bot can't post to a room it has no working login for, so this is the moment to set one up. |
|
||||
| Commands | ON / OFF — **Enter** toggles. Answer `!` query commands on the monitored room, independent of the other two tabs' Commands settings. |
|
||||
| Trigger | Independent trigger for the monitored room. `*` means **reply to every post in the room**. |
|
||||
| Reply | Reply text for room posts; supports the same placeholders as Direct's Reply. |
|
||||
|
||||
#### Direct tab
|
||||
|
||||
| Setting | Description |
|
||||
| ---------- | -------------------------------------------------------------------------------- |
|
||||
| Enable | ON / OFF — **Enter** toggles. Enables DM listening. |
|
||||
| DM allow | **All** / **Fav** — **Enter** toggles. Who the DM bot (trigger-reply and commands) responds to. All (default): any DM sender. Fav: only contacts you've starred (the same star Settings › Contacts filters on) — use this to keep a public bot from being spammed by strangers while it still answers people you trust. |
|
||||
| Commands | ON / OFF — **Enter** toggles. Answer `!` query commands (see below) in DMs. |
|
||||
| Trigger | Word or phrase that activates the DM reply (case-insensitive). A lone `*` means **reply to every DM** (away mode) and is shown as `(any msg)`. **Enter** opens the keyboard. |
|
||||
| Reply | Reply text for DMs; supports `{time}`, `{loc}`, `{name}`, `{hops}` and sensor placeholders. **Enter** opens the keyboard. |
|
||||
|
||||
#### Other tab
|
||||
|
||||
| Setting | Description |
|
||||
| ------------- | --------------------------------------------------------------------------------- |
|
||||
| Quiet from | **Enter** opens a stepper (value shown bracketed, e.g. `[14:00]`) — **UP/DOWN** steps the hour, **Enter**/**Cancel** confirms. Local-time window start; set from = to (`OFF`) to disable quiet hours entirely. Applies to all three targets' trigger-replies. |
|
||||
| Quiet to | Same stepper; window end. |
|
||||
|
||||
The DM, channel and room triggers are independent, so you can run e.g. an away-message (`*`) in DMs while the channel or room reacts only to a specific keyword (or vice-versa).
|
||||
|
||||
`{name}` (the triggering sender's name) and `{hops}` (`direct` or `N hops`) are only meaningful when replying to an actual incoming message, so — unlike `{time}`/`{loc}`/the sensor placeholders — they're offered only while editing a **Reply** field here, not on the general message-compose keyboard.
|
||||
|
||||
The header shows a running count of auto-replies sent since boot, alongside the tab bar.
|
||||
|
||||
**Room posting requires a login.** The room bot reuses whatever session the device already has with that server (Messages › Rooms › **Login…**, or a password saved earlier / from the phone app) — it can't prompt for one itself in the background. If the saved password stops working, it silently stops posting there; log back in from Messages to fix it.
|
||||
|
||||
**Throttle.** DM auto-replies are rate-limited **per contact** (10 s), so a second sender is never starved while one contact is on cooldown. The channel and room bots each keep their own single 10 s cooldown and won't echo a message identical to their own reply (so two bots running the same reply text on one channel/room can't ping-pong); the cooldown caps any residual back-and-forth.
|
||||
|
||||
**Quiet hours** suppress the push (trigger) replies between the configured local hours; a window where *from* is later than *to* wraps past midnight. Commands are a pull (explicitly requested), so they answer even during quiet hours.
|
||||
|
||||
### Commands
|
||||
|
||||
With a tab's **Commands** ON, a message beginning with `!` on that target is answered with live node data, independent of the trigger:
|
||||
|
||||
| Command | Reply |
|
||||
| --------- | --------------------------------------- |
|
||||
| `!ping` | `pong` |
|
||||
| `!batt` | battery voltage |
|
||||
| `!loc` | GPS coordinates (or `no GPS`) |
|
||||
| `!time` | local time `HH:MM` |
|
||||
| `!temp` | temperature (or `n/a` if no sensor) |
|
||||
| `!hops` | how many hops the command message took to reach the node (`direct` if heard directly) |
|
||||
| `!status` | combined battery / location / time |
|
||||
| `!help` | list of available commands |
|
||||
|
||||
Several commands can be combined in one message — `!batt !time !hops` is answered with a single `4.10V | 14:30 | 3 hops` reply (one transmission). A message with no recognised command falls through to the trigger bot.
|
||||
|
||||
Each target's Commands toggle is independent — e.g. answer `!ping` in DMs but stay quiet on a busy public channel. Channel and room replies are broadcast/posted to everyone there, so unlike DM commands they respect quiet hours and use their own shared cooldown. DM commands use the per-contact throttle and the **DM allow** scope above.
|
||||
|
||||
### Actions
|
||||
|
||||
A separate **Actions** toggle, nested under Commands (Commands must be ON for Actions to do anything) — these commands change the device's own behaviour, not just report on it, so they default OFF and are kept independent of the read-only Commands toggle:
|
||||
|
||||
| Command | Effect |
|
||||
| ----------------- | -------------------------------------------------------------------- |
|
||||
| `!buzz [seconds]` | Sounds the buzzer as a find-me signal — default 5s, capped at 30s. Sounds even if the buzzer is muted in Settings (that's the point of a find-me signal). |
|
||||
| `!gps on` / `!gps off` | Enables/disables GPS, same effect as the Home page's GPS toggle. |
|
||||
| `!gps fix [seconds]` | Single-shot location: turns GPS on if needed, waits for a stabilised fix (HDOP ≤ 2.0, or ≥8 satellites without HDOP, averaged over 10s), sends the position, then restores GPS's prior state. Two-part reply — immediate `GPS: acquiring fix...` ack, then the position (or `GPS: no fix (timeout)` / partial fix) up to `seconds` later (default 90s, 15–300s range — raise it under poor sky view). Only one in flight at a time; a second gets `GPS: fix already pending`. |
|
||||
| `!advert` | Sends an advert immediately, same as the Home page's manual advert action. |
|
||||
|
||||
Actions combine with Commands and each other in one message the same way — `!batt !gps on` answers with `4.10V | GPS: on` in a single reply. With Actions OFF for a target, `!buzz`/`!gps`/`!gps fix`/`!advert` are silently ignored (no reply, no effect) exactly like any other unrecognised command, and `!help`'s reply doesn't mention them.
|
||||
|
||||
On boards with user GPIO (see **GPIO** under System tools below), the same Actions gate also covers `!gpio1`..`!gpio4`.
|
||||
|
||||
---
|
||||
|
||||
## Diagnostics
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :------------------------: | :------------------------: |
|
||||
|  |  |
|
||||
|
||||
<!-- screenshot pending: Diagnostics — live device/mesh stats rows (uptime, rx/tx counters, heap, RSSI/SNR, queue, errors) -->
|
||||
|
||||
A circular tab carousel of live device and mesh stats, refreshed once a second (same tab idiom as Remote Bot / Nodes). **LEFT/RIGHT** switches tab; **UP/DOWN** scrolls within it on a small OLED — on a larger e-ink display a tab's rows all fit at once.
|
||||
|
||||
| Tab | Shows |
|
||||
| --- | ----- |
|
||||
| **Live** | Live counters — see table below. |
|
||||
| **System** | Static device identity: firmware version + build date, device model, node name, and the active radio parameters. |
|
||||
| **Font** | A rendering test card — one sample line per script the on-device font claims to cover (Latin, diacritics, Greek, Cyrillic, digits, symbols), so its coverage can be eyeballed directly. |
|
||||
|
||||
**Live** tab rows:
|
||||
|
||||
| Row | Shows |
|
||||
| ------------ | -------------------------------------------------------------------------------------------------- |
|
||||
| Uptime | Time since boot (`d hh:mm:ss`) |
|
||||
| Total rx/tx | All received / transmitted packets, summed across the categories below |
|
||||
| Msg | Text and group-text packets, `rx/tx` |
|
||||
| Advert | Advert packets, `rx/tx` |
|
||||
| Ack/Path | Ack, path-return and trace packets, `rx/tx` |
|
||||
| Other | Everything else (requests, responses, control, raw, …), `rx/tx` |
|
||||
| Forwarded | Packets this node actually re-transmitted as a repeater (reflects overhear suppression, if on) |
|
||||
| Heap free | Free / total heap |
|
||||
| Stack free | Current task's minimum-ever stack headroom |
|
||||
| Noise floor | Live radio noise floor (dBm) |
|
||||
| RSSI/SNR | Signal strength / signal-to-noise of the last received packet |
|
||||
| Pool free | Free entries in the packet pool |
|
||||
| Queue | Packets waiting in the outbound queue |
|
||||
| Errors | Radio error flags since boot/reset — `OK`, or tokens `F` (queue full), `C` (CAD timeout), `R` (RX-start timeout) |
|
||||
|
||||
The packet counters, **Forwarded** and **Errors**, are cumulative since boot. On the **Live** tab, **Hold Enter** opens a *Reset counters?* confirm (defaults to Cancel); the live readings (noise, RSSI/SNR, pool, queue, uptime) are not affected. **Cancel/Back** returns to the Tools list.
|
||||
|
||||
There is no "RXPS wd s/h" row: it belongs to hardware RX duty-cycle receive, which is currently disabled (see the Settings screen doc) — nothing to watchdog.
|
||||
|
||||
The counters make the repeater behaviour observable: **Forwarded** confirms the node is actually relaying (not just configured to), and **Pool free** / **Queue** show whether forwarding is exhausting the packet pool. See **Tools › Repeater** for the relaying options.
|
||||
|
||||
---
|
||||
|
||||
## GPIO
|
||||
|
||||
*Board-specific — currently Wio Tracker L1 only.* Four otherwise-unused pins (GPIO1-GPIO4) are exposed for general-purpose use. Each pin gets its own row showing its current mode; **Enter** (or LEFT/RIGHT) cycles it through **OFF → Input → Output** and back to OFF — GPIO1 and GPIO2 additionally step through **Analog** between Output and OFF (GPIO3/GPIO4 have no ADC channel, so their cycle skips it). Switching a pin's mode shows a brief confirmation (`GPIO1: Input`, `GPIO1: Output`, …).
|
||||
|
||||
Once a pin is set to **Output**, a second **State** row appears right underneath it — **Enter** toggles it **ON**/**OFF**, with its own confirmation. The direction (Mode row) and the on/off state (State row) are deliberately separate: changing one never surprises you by also changing the other.
|
||||
|
||||
- **Input** shows its live level inline on the Mode row: `Input (High)` / `Input (Low)`, refreshed continuously.
|
||||
- **Analog** (GPIO1/GPIO2 only) shows a live millivolt reading inline instead: e.g. `1650mV`. Has no State row — it's read-only.
|
||||
- **Output** shows just `Output` on the Mode row; the actual ON/OFF value lives on the State row below it.
|
||||
|
||||
The same 4 pins are reachable remotely via the Remote Bot's `!gpio1`..`!gpio4` commands (see **Actions** under Remote Bot below) — both paths read/write the same underlying state, so the Tools screen and the bot never disagree. A bare `!gpio1` reports the pin's current mode and reading (`gpio1: out on`, `gpio1: in on`, or `gpio1: 1650mV` in Analog mode); `!gpio1 on`/`!gpio1 off` only takes effect if that pin is currently set to Output here (otherwise the bot replies "not output", including when the pin is in Analog mode).
|
||||
|
||||
---
|
||||
|
||||
## Repeater
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :------------------------: | :------------------------: |
|
||||
|  |  |
|
||||
|
||||
<!-- screenshot pending: Repeater — toggle + Network/profile + flood-filter rows -->
|
||||
|
||||
Turns the companion into a packet **repeater** while it keeps working as a normal companion — no separate firmware. By default, enabling it switches the radio to a dedicated repeater profile rather than relaying on your chat network (see **Network** below), matching the MeshCore community norm of repeaters sitting on a standard channel. Loop-detection and an advert flood-depth cap always apply. Live forwarding stats are on **Tools › Diagnostics**.
|
||||
|
||||
Navigate with **UP/DOWN**; change a value with **LEFT/RIGHT** (or **Enter** for toggles). **Cancel/Back** saves and returns to Tools.
|
||||
|
||||
| Setting | Options | Notes |
|
||||
| -------------- | --------------- | -------------------------------------------------------------------------------------------------------------- |
|
||||
| Repeater | ON / OFF | Master switch. The options below are always visible, so the profile and filters can be set up before switching it on. |
|
||||
| Network | Current / Custom | **Custom** _(default)_: enabling the repeater switches to a dedicated profile (below), disabling restores the companion's settings. A never-configured device seeds Custom from your own network's band (433/868/915 MHz region), not a flat default, so it can't land outside what's legal for your region. **Current**: relay on the companion's own frequency — opt-in, not the community norm. |
|
||||
| Preset | named presets | _(Custom only)_ **Enter** picks a community/saved preset for the repeater profile. |
|
||||
| Freq | chip range | _(Custom only)_ **Enter** opens the digit-by-digit editor (chip-validated bounds). |
|
||||
| SF / BW / CR | 5–12 / 7.8–500 kHz / 5–8 | _(Custom only)_ **LEFT/RIGHT** to adjust the profile's spreading factor, bandwidth, coding rate. |
|
||||
| Skip advert | ON / OFF | Don't re-flood **advert** packets (the highest-volume flood traffic); messages and acks still relay. |
|
||||
| Max hops | OFF / 1–8 | Drop a flood packet once it has already travelled this many hops. |
|
||||
| Yield | OFF / x2–x9 | Scales the retransmit delay for **forwarded** floods only (your own sends are unaffected), so a mobile companion defers to better-sited fixed repeaters. Widens the window for **Suppress dup**. |
|
||||
| Min SNR | OFF / −20…10 dB | Drop a flood copy received below this signal-to-noise threshold, so marginal fringe traffic isn't re-flooded. |
|
||||
| Suppress dup | ON / OFF | If the same flood packet is overheard from another node while still queued to retransmit, cancel our copy — a peer already relayed it. Cuts redundant airtime in dense meshes; pairs with **Yield**. |
|
||||
| Scope only | ON / OFF | Only forward flood traffic matching this device's own default **Scope** (Settings › Radio) or one of the **Extra scopes** below — drops unscoped floods and floods tagged for a different community. No-op while neither is set, so switching this on with no scope configured can't silently stop all relaying. |
|
||||
| Extra scopes | pick list | Extra scopes this repeater also relays for, on top of its own Settings › Radio default **Scope** — relay-only, never changes what scope this device's own messages send under. Shows `N picked`. **Enter** opens a checklist of the Settings › Radio scope list (**Enter** toggles a row, **Back** closes); at most 4 are active. Shows `No scopes defined` until at least one named scope exists. |
|
||||
|
||||
The flood filters (**Skip advert** through **Scope only**) are **opt-in** (default OFF, so a plain repeater is unaffected) and act on **flood** traffic only — on a direct route this node is the named next hop, so it never drops those.
|
||||
|
||||
**Same network vs. separate network.** With **Network = Current** (or a Custom profile matching your companion settings) the repeater stays on your own network — you keep messaging while relaying. A *different* Custom profile moves the device entirely onto that network while relaying (one radio can't be on two at once), returning to your own network when switched off. The profile re-applies after a reboot if the repeater was left on.
|
||||
|
||||
While on, a **»** indicator appears in the status bar (same blink convention as auto-advert/trail markers). **Auto pwr** is overridden off and restored afterwards (full TX power for relay reach) — shows `--` in Settings while active. (Pwr save, hardware RX duty-cycle, is currently disabled outright — see above — so there's nothing left for repeater mode to override there.)
|
||||
|
||||
Live forwarding stats — **Forwarded**, **Pool free**, **Queue** — are shown on **Tools › Diagnostics** (this screen is config-only).
|
||||
|
||||
---
|
||||
|
||||
## Admin
|
||||
|
||||
<!-- screenshot pending: Admin — target picker, command entry, reply view -->
|
||||
|
||||
Send commands to a **repeater/room server you have admin permission on** — the on-device equivalent of the companion app's repeater-admin feature. See [CLI Commands](../../cli_commands.md) for the full command grammar. (Admin only manages *remote* nodes; this device's own name, radio, TX power and reboot live in **Settings** — see below.)
|
||||
|
||||
1. **Select a node** — **Tools › Admin** opens straight into **Tools › Nodes** (same screen, filters, sort, live scan), so picking a node for Admin looks like using Nodes normally; **Enter** on a repeater/room row hands it to Admin, **Cancel** returns to Tools. Also reachable from a node's own **Hold Enter** menu in Nodes.
|
||||
2. **Log in** — type the node's **admin password** (same handshake Messages uses for rooms; set on a repeater with the `password` CLI command). A saved password from an earlier login retries silently. Only **admin**-level permission unlocks the next step — anything less shows "Not admin on this node".
|
||||
3. **Pick a category and a field** — a tab carousel (**LEFT/RIGHT** to switch category, **UP/DOWN** to move within it, same as Remote Bot's tabs), so common settings don't need the CLI grammar memorised:
|
||||
|
||||
| Tab | Rows |
|
||||
| --- | ---- |
|
||||
| **System** | Name, Owner info, Admin password |
|
||||
| **Radio** | Frequency, Bandwidth, Spreading factor, Coding rate, TX power |
|
||||
| **Routing** | Repeat, Advert interval, Flood advert interval, Max hops |
|
||||
| **Actions** | Send advert, Send zero-hop advert, Sync clock, Reboot, Start OTA, **Custom command...** |
|
||||
|
||||
**Enter** on a row does one of four things, depending on the field:
|
||||
- **Name / Owner info** first **fetch** the node's current value, then open the keyboard **pre-filled** with it to edit — submitting sends the change. If the fetch fails or times out, the keyboard still opens (blank), so the value can be set blind.
|
||||
- **Radio and Routing rows** are typed, not free text: **Repeat** is an ON/OFF toggle; **Advert interval / Flood advert interval / Max hops / TX power** are number steppers (**LEFT/RIGHT** to adjust, within that field's valid range); **Frequency** uses the same digit-by-digit cursor editor as Settings' own Radio screen (**LEFT/RIGHT** moves between digits, **UP/DOWN** changes the selected one); **Bandwidth / Spreading factor / Coding rate** step through their valid discrete LoRa values with **LEFT/RIGHT**. All four Radio-tuple fields (Frequency/Bandwidth/SF/Coding rate) fetch and re-send the same underlying `radio` value together — editing any one of them still only overwrites that one, the other three round-trip unchanged. **Enter** sends the change; **Cancel** discards it and returns to the row list without sending anything.
|
||||
- **Admin password** has no fetch (there's no way to read a password back) — it opens straight to a blank keyboard.
|
||||
- **Actions** (Send advert, Sync clock, …) send immediately, no editing step — except **Reboot** and **Start OTA**, which both ask first (defaulting to Cancel): they take the remote out of action for a while with no way to intervene on an unattended node if something goes wrong.
|
||||
- **Custom command...** (last row of Actions) opens the same free-text entry for anything not covered above — up to 160 characters, see the linked reference for the full grammar. The keyboard's **{}** key doubles as command completion here: it lists commands matching whatever's typed since the last space (narrowing as you type), and picking one completes that word instead of just inserting after it.
|
||||
4. **Read the reply** — the text reply opens in a scrollable view (**UP/DOWN** to scroll, **Cancel/Enter** to go back to the category tabs).
|
||||
|
||||
> [!WARNING]
|
||||
> This screen can run **destructive** commands on the *remote* node — `reboot`, `erase`, a new admin password, and others. That's the same capability the phone app's repeater-admin feature already exposes, not a new risk, but double-check the value and the target before sending.
|
||||
|
||||
**Passwords are remembered across reboots**, same self-healing behaviour as room logins in Messages: a successful login is saved, so picking that node again — even after a power cycle — logs back in silently. A password that stops working is forgotten on failure, prompting fresh next time. A correct password that just lacks admin permission is left alone. Commands marked **Serial Only** in the CLI reference reject a remote request and only work over that node's own USB serial.
|
||||
|
||||
### This device
|
||||
|
||||
Admin doesn't manage the companion itself — its own settings live in **Settings**: **Radio** (preset / freq / SF / BW / CR) and **TX power** in the Radio section, and **Name** and **Reboot** in the System section. **Send advert** is the home **ADVERT** page.
|
||||
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
@@ -4,7 +4,7 @@
|
||||
// and always read back clamped to what the ring still holds for that contact --
|
||||
// the same self-healing shape as MessageHistory::chUnread() for channels.
|
||||
//
|
||||
// Header-only UI Core model (see docs/developer/ui-core.md); no drawing, no
|
||||
// Header-only UI Core model (see docs/solo/developer/ui-core.md); no drawing, no
|
||||
// screen state.
|
||||
|
||||
class DmUnreadTable {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
// Declarative settings (docs/developer/ui-core.md, step 4): one table of
|
||||
// Declarative settings (docs/solo/developer/ui-core.md, step 4): one table of
|
||||
// NodePrefs options with their labels, value lists and side effects, so every
|
||||
// frontend renders the same settings without its own per-item code. ui-lvgl
|
||||
// draws it as switches and dropdowns, one page per Page below; ui-new still has
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
// UI Core: hardware-independent UI state and logic shared by every frontend
|
||||
// (ui-new today, ui-lvgl later). See docs/developer/ui-core.md.
|
||||
// (ui-new today, ui-lvgl later). See docs/solo/developer/ui-core.md.
|
||||
//
|
||||
// The Core is MyMesh's Listener: it files incoming/outgoing messages into the
|
||||
// history, keeps the unread counters, runs the engines, and tells the frontend
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// does, and reports to the frontend through UiEventQueue. This interface is the
|
||||
// remainder -- calls that must stay synchronous with mesh processing, or whose
|
||||
// logic still lives in the frontend until its extraction step
|
||||
// (docs/developer/ui-core.md). None of these may draw or block.
|
||||
// (docs/solo/developer/ui-core.md). None of these may draw or block.
|
||||
|
||||
class UiCoreHost {
|
||||
public:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Core → frontend events. Engines never call into the frontend (no drawing, no
|
||||
// sound, no display power); they push a tagged event here and the frontend
|
||||
// drains the queue from its own loop() and reacts in its own way (ui-new:
|
||||
// alert overlay + buzzer; ui-lvgl: a dialog). See docs/developer/ui-core.md.
|
||||
// alert overlay + buzzer; ui-lvgl: a dialog). See docs/solo/developer/ui-core.md.
|
||||
//
|
||||
// Fixed-size ring, no heap. When full the oldest event is dropped -- events are
|
||||
// hints for the view; the authoritative state stays queryable on the engines.
|
||||
|
||||
@@ -95,7 +95,7 @@ static const char* waypointsFull() {
|
||||
return t;
|
||||
}
|
||||
|
||||
// ui-lvgl skeleton (docs/developer/ui-core.md, step 5): status bar, home,
|
||||
// ui-lvgl skeleton (docs/solo/developer/ui-core.md, step 5): status bar, home,
|
||||
// conversation list, contact picker, conversation view with compose. Every
|
||||
// piece of state it shows comes from the UI Core; this file only draws it.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
// ui-lvgl: the rich (colour + touch) frontend of the UI Core. Wio Tracker L2
|
||||
// first. All application state lives in the Core (../ui-core); this class owns
|
||||
// only LVGL screens, display power and input. See docs/developer/ui-core.md.
|
||||
// only LVGL screens, display power and input. See docs/solo/developer/ui-core.md.
|
||||
|
||||
#include <MeshCore.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
@@ -73,9 +73,9 @@
|
||||
### What's new
|
||||
|
||||
- **On-device community scope, and repeater-side scope filtering.** Settings › Radio gets a **Scope** field — type a region/community name (e.g. `pl`) and every device typing the same name derives the same shared tag, no key exchange needed; it's what your own DM/channel sends carry, previously only settable from a connected app. Tools › Repeater gains **Scope only** (only relay flood traffic matching your own scope, or one of the new **Extra scopes** below — a no-op until a scope is actually set, so it can't silently blackhole all forwarding) and **Extra scopes** (comma-separated additional regions to relay for, without changing what scope this device's own messages send under).
|
||||
- **Optional magnetic "flip cover" screen lock**, for anyone who wants to wire a Hall-effect or reed sensor to a free GPIO — no board ships one built in. Set `PIN_HALL_SENSOR` as a build flag on your own env and closing the cover locks and blanks the screen instantly, opening it unlocks and wakes it — no combo, independent of Auto-lock. See [Screen Lock](docs/solo_features/screen_lock/screen_lock.md#magnetic-cover-hall-sensor).
|
||||
- **Optional magnetic "flip cover" screen lock**, for anyone who wants to wire a Hall-effect or reed sensor to a free GPIO — no board ships one built in. Set `PIN_HALL_SENSOR` as a build flag on your own env and closing the cover locks and blanks the screen instantly, opening it unlocks and wakes it — no combo, independent of Auto-lock. See [Screen Lock](docs/solo/lock.md#magnetic-cover).
|
||||
- **Experimental: solo build for ProMicro (nRF52840)**, with CardKB support sharing the board's primary I2C bus (no free pins for a second one on this board). Contributed by @tchellow — thanks!
|
||||
- **New [Build Flags](docs/solo_features/build_flags.md) reference** — every optional `-D` flag a solo build understands (GPIO, CardKB/joystick, Hall-sensor cover lock, buzzer/vibration, GPS switch, display/battery tuning) in one place.
|
||||
- **New [Build Flags](docs/solo/developer/build-flags.md) reference** — every optional `-D` flag a solo build understands (GPIO, CardKB/joystick, Hall-sensor cover lock, buzzer/vibration, GPS switch, display/battery tuning) in one place.
|
||||
- **Tools › Admin gains a "Start OTA" action** for a repeater/room server you're logged into — sends the same `start ota` CLI command the Custom-command row already reached, now with its own menu row and a confirm ("Start" defaulting to "Cancel" first) since it puts the remote into BLE DFU mode for the duration of the update.
|
||||
|
||||
### Fixes
|
||||
|
||||
@@ -37,7 +37,7 @@ lib_deps =
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
; ui-lvgl: the real L2 interface -- LVGL 9 frontend over the shared UI Core
|
||||
; (docs/developer/ui-core.md, step 5), on Arduino-ESP32 3.3.12 / ESP-IDF 5.5
|
||||
; (docs/solo/developer/ui-core.md, step 5), on Arduino-ESP32 3.3.12 / ESP-IDF 5.5
|
||||
; (pioarduino). *_solo_lvgl envs are published by build-solo-firmwares.yml
|
||||
; (merged image + the -ota.bin that Settings > Firmware update installs).
|
||||
[env:Wio_Tracker_L2_companion_solo_lvgl]
|
||||
|
||||