mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-10-15 16:49:54 +00:00
peripherals & power: GPS fixes, poweroff/pwrmgt, upstream SensorManager telemetry
- gps: servers honour gps_enabled at boot (was lost on reboot; zc.gps_set upgrades older prefs to on once); sleep lock only while acquiring; gps off works on boards without a power line (UART sleep); UI toggles and fixes handled on the main thread; configure only after a good init; observer parks its GPS; one interval clamp (clampGpsInterval); one nav-mode knob (room servers on Air530Z now stationary); GNSS UARTE from DT - gps: split into ZephyrGPSManager / gps_power / gps_module_cfg (+gps_internal.h); dead driver branches, gps_get_diag, sats_* removed - clock: ZephyrRTCClock writes the hardware RTC itself (clkreboot now resets it); MESH_EVENT_RTC_SAVE gone - power: one power-off path (zephcore_power_off, ZephyrBoard::powerOff), poweroff/shutdown CLI, get pwrmgt.*, crash record kept across reboot, battery reading cached 10 s, fuel gauge on the current API - telemetry: upstream SensorManager + CayenneLPP (rounded to nearest), one builder for all roles; per-sensor channels, MCU temp always, guest gating and inverse mask on servers; sensor list/get/set work; BME280/BMP280 also probed at 0x77 - CLI: gps in upstream's form, get gps detail, gps sync
This commit is contained in:
+19
-5
@@ -77,14 +77,16 @@ zephcore/
|
||||
│ │ ├── NoiseFloorEstimator.h # Noise-floor EMA (host-tested)
|
||||
│ │ └── radio_common.h, radio_tuning.h # Shared constants
|
||||
│ ├── ble/ZephyrBLE.cpp/h # BLE NUS service, pairing, TX congestion
|
||||
│ ├── board/ZephyrBoard.cpp/h # Battery ADC, LEDs, reboot, bootloader
|
||||
│ ├── board/ZephyrBoard.cpp/h # Battery ADC, LEDs, reboot, bootloader, pwrmgt reasons
|
||||
│ ├── board/zephyr_poweroff.c/h # The one power-off path + shutdown-reason marker
|
||||
│ ├── clock/ # Millisecond uptime + software RTC + I2C RTC discovery
|
||||
│ ├── datastore/ZephyrDataStore.cpp/h # LittleFS persistence
|
||||
│ ├── gps/ZephyrGPSManager.cpp/h # GNSS state machine, power mgmt
|
||||
│ ├── gps/ZephyrGPSManager.cpp/h # GNSS state machine, fix validation, public API
|
||||
│ ├── gps/gps_power.cpp, gps_module_cfg.cpp, gps_internal.h # module power; module configuration + diag
|
||||
│ ├── mqtt/ZephyrMQTTPublisher.c/h # MQTT packet publisher (observer / uplink)
|
||||
│ ├── ota/wifi_ota.c/h # WiFi SoftAP + HTTP firmware upload
|
||||
│ ├── rng/ZephyrRNG.cpp/h # Hardware CSPRNG with PRNG fallback
|
||||
│ ├── sensors/ # I2C env sensors + power monitors
|
||||
│ ├── sensors/ # ZephyrSensorManager (upstream SensorManager) over the I2C env sensors + power monitors
|
||||
│ ├── transport/ # TCP companion (native Linux) + serial companion (STM32WL)
|
||||
│ ├── usb/ # USB CDC for companion + repeater
|
||||
│ └── wifi/ZephyrWiFiStation.c/h # WiFi station client (ESP32)
|
||||
@@ -724,8 +726,9 @@ Listen-only node (ESP32 only): receives LoRa packets and publishes them to an MQ
|
||||
|
||||
System: `ver`, `board`, `reboot`, `start dfu`, `start ota`, `erase`
|
||||
Config: `set name/freq/radio/tx/flood.max/password/...`, corresponding getters
|
||||
GPS: `gps on/off/setloc/advert`, `set gps duty <sec>`
|
||||
Sensors: `sensor get/set/list`
|
||||
System (power): `poweroff`/`shutdown`, `get pwrmgt.support/source/bootreason/bootmv`
|
||||
GPS: `gps`, `gps on/off/sync/setloc/advert`, `get gps`, `set gps duty <sec>`
|
||||
Sensors: `sensor get/set/list` (upstream's `SensorManager` settings: `gps`)
|
||||
Stats: `stats-core/stats-radio/stats-packets`, `clear stats`
|
||||
Time: `clock`, `clock sync`, `time <epoch>`, `set meshtimesync on/off`
|
||||
|
||||
@@ -778,6 +781,10 @@ Loading also range-checks `freq`/`sf`/`bw` and falls back to the compile-time de
|
||||
- Multi-constellation: GPS+GLONASS+Galileo+BeiDou with fallback
|
||||
- T1000-E: Complex 6-GPIO power sequencing with VRTC preservation
|
||||
- GPS time blocks phone time sync for 2 hours after last fix
|
||||
- Three files: `ZephyrGPSManager.cpp` (states, fix validation, public API), `gps_power.cpp` (power line / PMU rail / UART sleep commands, UARTE PM), `gps_module_cfg.cpp` (GNSS-API or PMTK/PCAS/UBX configuration, `get gps diag`); `gps_internal.h` carries the feature detection
|
||||
- **Main thread only.** The GNSS callbacks (system work queue) only validate and post: a validated fix is snapshotted and handed to the fix callback by `gps_process_event()` on the main thread, so the callback sets the clock and the node position directly. The UI's GPS toggles post an action too.
|
||||
- The SoC light-sleep lock is held only while ACQUIRING (`gps_hold_sleep_lock()`, tracked 1:1), never through standby
|
||||
- Boot: servers apply `prefs.gps_enabled` like upstream's `applyGpsPrefs()` (`zc.gps_set` in prefs.json marks it a real choice; older files are upgraded to on once, because older firmware ran the GPS regardless). The observer parks its GPS (`gps_park()`)
|
||||
|
||||
**Duty cycle vs always-on**
|
||||
|
||||
@@ -811,6 +818,13 @@ Repeaters and room servers default to `CONFIG_ZEPHCORE_REPEATER_GPS_INTERVAL_SEC
|
||||
- UF2 bootloader entry via GPREGRET magic (0x57 = UF2, 0xA8 = BLE DFU)
|
||||
- TX LED bracketing for LoRa transmissions (gated by the LED master switch below)
|
||||
- Bootloader version detection via flash memory scan
|
||||
- Battery reading cached 10 s for every caller (UI, telemetry, stats, alerts), under a mutex
|
||||
- `powerOff()` (CLI `poweroff`/`shutdown`, UI power-off, low-battery shutdown all end in `zephcore_power_off()`, `board/zephyr_poweroff.c`): UI hook (heartbeat, display), GPS/sensor/buzzer rails off, LoRa held in reset, sw0 SENSE armed (nRF), power latch released, System OFF
|
||||
- Upstream's pwrmgt getters: reset cause from `boot_info`, the last fatal error from `fatal_reboot.c`'s `__noinit` record (reason, pc, lr, thread; resolve pc with `addr2line` on the same build), shutdown reason from the `/lfs/shutdn` marker, battery voltage at boot
|
||||
|
||||
**Telemetry** (`REQ_TYPE_GET_TELEMETRY_DATA`, every role, upstream's shape): battery on channel 1, then `sensors.querySensors()` (`adapters/sensors/ZephyrSensorManager.cpp`): GPS position on channel 1 while the GPS is on and has a fix, each environment sensor and power-monitor channel found at boot on its own channel from 2 up (probe order), board-local analog sensors (T1000-E) on channel 1; then the MCU temperature on channel 1. Servers give guests battery + MCU temperature only and honour the requester's inverse permission mask, as upstream. Encoded by `helpers/compat/CayenneLPP.h`: upstream's library API and wire format, but values round to the nearest step where the library truncates.
|
||||
|
||||
**Clock** (`adapters/clock/ZephyrRTCClock`): `setCurrentTime()` also writes the hardware RTC when the board has one (coalesced on the system work queue), as upstream's `AutoDiscoverRTCClock` writes its chip; `seedCurrentTime()` is the boot restore, not written back.
|
||||
|
||||
**LED master switch** (`helpers/led_gate.{c,h}`, `set leds on|off`, all roles): one process-wide
|
||||
flag every LED driver consults — heartbeat and unread-message LEDs in `helpers/ui/ui_common.c`, the
|
||||
|
||||
@@ -27,10 +27,11 @@ All commands are sent over USB serial (CDC-ACM). Commands sent remotely over the
|
||||
| `ver` | Firmware version and build date |
|
||||
| `board` | Board manufacturer name |
|
||||
| `reboot` | Reboot immediately |
|
||||
| `poweroff` / `shutdown` | Power the node off, as upstream: GPS, sensor and buzzer rails off, LoRa held in reset, then System OFF (the power latch released first on soft-power boards). Wake with the user button (nRF) or a power cycle — a node without a reachable button stays off until someone gets to it, so think twice before sending it over remote admin. The shutdown reason `User Request` is recorded for `get pwrmgt.bootreason`. Replies `OK - powering off`; deferred like `reboot` |
|
||||
| `start dfu` | nRF52: reboot into the UF2 bootloader for drag-and-drop update. ESP32-S3: reboot into the ROM download mode on USB-Serial-JTAG (`303a:1001`), so ordinary `esptool write-flash` and browser flashers can reach the chip. Every other chip replies with an error and does **not** reboot — ESP32-C3/C6 and classic ESP32 never lose the port to USB OTG so esptool resets them itself, and nRF54L15/MG24/STM32WL have no USB device peripheral and are flashed over SWD |
|
||||
| `start ota` | ESP32: start WiFi AP + HTTP OTA server. nRF52: reboot into BLE OTA DFU mode |
|
||||
| `stop ota` | Stop WiFi OTA server (ESP32 only) |
|
||||
| `clkreboot` | Set clock to a fixed reference time (15 May 2024 8:50pm UTC) then reboot |
|
||||
| `clkreboot` | Set clock to a fixed reference time (15 May 2024 8:50pm UTC) then reboot. On a board with a hardware RTC the reference time is written to the chip too, as upstream, so the reset survives the reboot |
|
||||
| `powersaving` | Not implemented |
|
||||
|
||||
---
|
||||
@@ -43,6 +44,8 @@ All commands are sent over USB serial (CDC-ACM). Commands sent remotely over the
|
||||
| `clock sync` | Sync clock from the sender's timestamp (only advances, cannot go backwards). Arms the 7-day mesh-time-sync suppression window. |
|
||||
| `time <unix_timestamp>` | Set RTC to a specific Unix timestamp (cannot go backwards). Arms the 7-day mesh-time-sync suppression window. |
|
||||
|
||||
Every clock set (these commands, GPS, the app, mesh time sync, SNTP) is also written to the board's hardware RTC when it has one, so the time survives a power-off.
|
||||
|
||||
---
|
||||
|
||||
## Advertisement
|
||||
@@ -145,10 +148,12 @@ Regions control which flood packets the repeater forwards. The region tree is hi
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `gps` | Show GPS status (`on` or `off`) |
|
||||
| `gps` | GPS status in upstream's form: `on, active\|standby, fix\|no fix, N sats`, `off`, or `Can't find GPS`. `standby` (upstream: `deactivated`) means on but asleep between duty-cycle fixes |
|
||||
| `get gps` | The detail: `> on state=<off\|standby\|acquiring> sats=N fix=Ns ago lat= lon=`, or `no fix next=Ns` (seconds to the next wake) |
|
||||
| `gps sync` | Take a fresh fix now (wake the GPS or extend its window); the fix sets the clock. `gps is off` / `gps provider not found` otherwise |
|
||||
| `gps on` | Enable GPS module |
|
||||
| `gps off` | Disable GPS module |
|
||||
| `gps setloc` | Update stored latitude/longitude from current GPS fix |
|
||||
| `gps off` | Disable GPS module. Persisted: a repeater or room server with GPS off stays off across reboots. Boards whose GPS has no power line (RAK4631, RAK3401 1W, Station G2) put the module to sleep over UART |
|
||||
| `gps setloc` | Update stored latitude/longitude from the last GPS fix (unchanged if there has been none since boot) |
|
||||
| `gps advert` | Show current location advertising policy |
|
||||
| `gps advert none` | Do not include location in advertisements |
|
||||
| `gps advert share` | Include live GPS location in advertisements |
|
||||
@@ -198,6 +203,8 @@ Caveats: the `sys=` tally needs `CONFIG_ZEPHCORE_GPS_SAT_DIAG` (default on for r
|
||||
| `sensor get <key>` | Get a custom sensor setting value by key |
|
||||
| `sensor set <key> <value>` | Set a custom sensor setting value |
|
||||
|
||||
As upstream, the one setting is `gps` (`0`/`1`), listed only on a board with a GPS; `sensor set gps_interval <sec>` also works and sets the duty interval. Neither is saved — `gps on|off` and `set gps duty` are.
|
||||
|
||||
---
|
||||
|
||||
## Radio (Temporary Override)
|
||||
@@ -305,6 +312,10 @@ Companion builds of boards whose `zephcore.yml` declares `capabilities: wifi: tr
|
||||
| `get extra.sf` | LR2021 side detectors: the extra spreading factors currently received alongside `sf`, comma-separated (bare, no `> ` prefix), or `No extra SF configured`. Reflects the saved prefs, not what the chip accepted — if the set became invalid after an `sf`/`bw` change it is reported here but was refused at boot (a `WRN` line says so). |
|
||||
| `get adc.multiplier` | Battery voltage ADC calibration multiplier |
|
||||
| `get bootloader.ver` | Bootloader version string |
|
||||
| `get pwrmgt.support` | `> supported` on nRF52 (VBUS detection, boot voltage), else `> unsupported` — upstream's reply |
|
||||
| `get pwrmgt.source` | nRF52: `> external` (VBUS present) or `> battery`; elsewhere `ERROR: Power management not supported` |
|
||||
| `get pwrmgt.bootreason` | `> Reset: <cause>; Shutdown: <reason>`. The cause is this boot's hardware reset cause as labels (`PIN`, `SOFTWARE`, `BROWNOUT`, `POR`, `WATCHDOG`, `LOWPOWER` for a wake from System OFF, ...), followed by `(crash <K_ERR> in <thread>, pc 0x...)` when the previous run ended in a fatal error and rebooted — resolve the pc with `addr2line` against the same build. The shutdown reason is `User Request`, `Low Voltage` or `None` |
|
||||
| `get pwrmgt.bootmv` | nRF52: battery voltage sampled at boot, `> <mV> mV` |
|
||||
| `get public.key` | Node's public key as hex. **Not** USB-only — it is answerable over remote admin, matching Arduino MeshCore. A public key is broadcast in every advert, so there is nothing to gate. |
|
||||
| `get prv.key` | *(USB only)* Node's private key as hex — the 128-char expanded form, the same one `set prv.key` takes |
|
||||
|
||||
@@ -416,4 +427,4 @@ four radio parameters together, since they are one interop-critical set.
|
||||
- **USB-only commands** — `get acl`, `get prv.key`, `set freq`, `log` (dump), `stats-packets`, `stats-radio`, `stats-core`, `erase` — are blocked when the command arrives over the mesh (remote admin). These are the only ones gated on `sender_timestamp == 0`; `get public.key` and `set prv.key` are **not** among them.
|
||||
- **Adaptive contention window** — `txdelay`, `rxdelay`, and `direct.txdelay` are accepted and stored for Arduino prefs compatibility but have no effect. Use `get txdelay` to inspect the current adaptive state and `set backoff.multiplier` to tune reactive backoff.
|
||||
- **Region load mode** — after `region load`, every line received is parsed as a region entry until a blank line is sent. The loaded map is only committed to the live region tree at that point; use `region save` to persist it. Region rows must be indented by at least one space, so an **unindented line that starts with a name character aborts the mode and is executed as a normal command** — the escape hatch if a `region load` is started by accident or a client dies mid-transfer. An abort discards the partial map, leaving the live region tree untouched. The exported wildcard header line `*` stays unindented and is ignored as before, so pasting the output of `region` still loads cleanly.
|
||||
- **Reboot delay** — `start dfu`, `start ota` (nRF52 BLE-DFU path only), `reboot`, `clkreboot` and `erase` defer the reset by **2 seconds** so the reply can be transmitted over LoRa first. On a companion the handler then keeps deferring in 20 ms steps until the BLE/USB transport has drained, up to a further 3 s grace. On ESP32 `start ota` starts a WiFi AP + HTTP server and does **not** reboot.
|
||||
- **Reboot delay** — `start dfu`, `start ota` (nRF52 BLE-DFU path only), `reboot`, `poweroff`, `clkreboot` and `erase` defer the reset by **2 seconds** so the reply can be transmitted over LoRa first. On a companion the handler then keeps deferring in 20 ms steps until the BLE/USB transport has drained, up to a further 3 s grace. On ESP32 `start ota` starts a WiFi AP + HTTP server and does **not** reboot.
|
||||
|
||||
Reference in New Issue
Block a user