Commit Graph
1680 Commits
Author SHA1 Message Date
mikecarper 2ce59b58ed Harden nRF52 contact and settings persistence 2026-09-02 17:32:43 -07:00
mikecarper 249c3680b3 Fix auto nRF52 Companion OTA builds 2026-09-02 12:02:41 -07:00
mikecarper cb27fa8539 Fix nRF52 contact persistence and ExtraFS recovery 2026-09-02 11:41:38 -07:00
mikecarper 4d89de8544 Improve companion setup and USB session recovery 2026-09-02 03:44:28 -07:00
agessaman 366b086713 feat: add automatic network failover 2026-09-01 21:18:22 -07:00
mikecarper 9816e21834 Harden nRF52 OTA, USB sessions, and T096 controls
Bind Companion replies to request transports, make dual-CDC USB sessions nonblocking and reconnect-safe, and harden nRF52 watchdog/OTA storage paths. Fix T096 button debounce, display wake, sleep races, and the compact message layout; add exact WisBlock OTA profiles plus expanded native/static/HIL documentation.
2026-09-01 20:51:43 -07:00
agessaman 03c0ad81fe feat: abstract MQTT network transport 2026-09-01 16:31:28 -07:00
mikecarper 5de1820765 Unify companion BLE and WiFi setup flows 2026-09-01 01:25:00 -07:00
mikecarper 1264f62e9d Add WiFi setup QR to ESP32 displays 2026-08-31 21:49:12 -07:00
mikecarper a5f3a5c5da Make Indicator WiFi setup state actionable 2026-08-31 20:54:56 -07:00
mikecarper 6df9a9f686 Keep Indicator RGB scanout alive during expander recovery 2026-08-31 19:10:54 -07:00
mikecarper 260b07999e Recover Indicator display after warm reset 2026-08-31 19:06:07 -07:00
mikecarper bf2d4e4b93 Make Indicator WiFi display authoritative 2026-08-31 18:45:44 -07:00
mikecarper b562af845a Refresh Indicator WiFi connection state 2026-08-31 18:36:44 -07:00
mikecarper ec94ac44ae Add Indicator WiFi setup as eighth home page 2026-08-31 17:31:48 -07:00
mikecarper 0496affcf8 Keep Indicator setup text large on fallback canvas 2026-08-31 16:36:46 -07:00
mikecarper 4bbdf4b071 Enlarge Indicator native setup screen 2026-08-31 16:10:03 -07:00
mikecarper 164a6e8227 Fix Indicator transport taps and fresh LoRa defaults 2026-08-31 15:56:54 -07:00
mikecarper 2e026caf4a Improve Indicator transport touch UI 2026-08-31 15:11:11 -07:00
mikecarper 5af7b73ff9 Add safe ESP32 transports and Indicator UI
Reserve board-specific GPIOs, make ESP-NOW channel/format handling configurable, and coordinate WiFi, BLE, NTP, MQTT, and host actions safely.

Add the Indicator message page, exclusive transport selector, dynamic 480/320 rendering, larger transport typography, pairing cleanup, and corresponding tests and documentation.
2026-08-31 14:29:42 -07:00
Aleksei Mamlin 1d9a62ca4a companion: get/set timezone offset for clock
* Add tz_offset companion prefs and get/set commands for companion cli
* Use tz_offset for clock on display

Signed-off-by: Aleksei Mamlin <mamlinav@gmail.com>
2026-08-31 09:08:22 +03:00
mikecarper 8920c35da5 Harden marathon-tested OTA and hardware paths
Add durable TempRadio, ACL, clock, bridge, GPS/I2C, USB logging, and Indicator recovery safeguards together with expanded automation, build/profile contracts, release metadata, and the hardware validation ledger.
2026-08-30 19:26:15 -07:00
mikecarper fdf528bb27 Fix Full Companion terminal diagnostics 2026-08-29 16:57:44 -07:00
mikecarper 19c9faab9c Clarify Companion WiFi CLI availability 2026-08-29 16:21:49 -07:00
mikecarper e7962f9598 Fix release matrix gaps and add background builds 2026-08-29 14:55:07 -07:00
mikecarper 83266757ca Avoid USB logging enum macro collision 2026-08-29 09:47:24 -07:00
fdlamotte adbdcf00bb Merge branch 'dev' into node_discover_ui 2026-08-29 11:02:58 -04:00
Adam Gessaman da6bab3e83 Merge upstream/dev into observer-firmware-dev 2026-08-28 19:45:59 -07:00
mikecarper da61c48e7b feat: integrate R8 observer and companion updates 2026-08-28 18:39:26 -07:00
mikecarper 89c12d416e refactor: use companion CLI for hardware settings 2026-08-28 17:37:39 -07:00
mikecarper c24bc82814 Merge upstream dev companion CLI updates 2026-08-28 17:31:28 -07:00
mikecarper 70a129a5bd fix: reserve controls and expose ESP-NOW channel 2026-08-28 16:55:40 -07:00
mikecarper 2b3b93ab2f fix: harden ESP-NOW and full companion networking
Add selectable shared ESP-NOW channels, raw/wrapped bridge compatibility, and bounded fragmentation for maximum-size packets.\n\nGive ESP32 Full profiles WiFi coexistence, stabilize WebConfig and USB terminal lifecycles, and keep disabled bridges stopped during observer updates.\n\nUpdate generated UI, firmware selection, documentation, and regression coverage.
2026-08-28 16:36:34 -07:00
agessaman efde02162b chore(display): log the persisted display.flip state at boot
display.flip lives in /mqtt.json, so it survives a reflash and is invisible
while someone is chasing a wrong orientation - a node still carrying flip=1
from testing looks exactly like a firmware that was never fixed. Boot now
reports "Display: flip off" or "flip on (rotated 180)".
2026-08-28 15:54:16 -07:00
agessaman 5da46cc518 fix(display): make the USER button click immediate, 3 s hold to power off
Power-off now needs a 3 second hold; any shorter press toggles the display.
MomentaryButton reports a CLICK for any release short of its threshold, so
that single value defines both.

The button also felt unreliable - "a brief press doesn't wake it, more often
than not". MomentaryButton's multi-click detection withholds a CLICK for
MULTI_CLICK_WINDOW_MS (280 ms) after release, and folds a second press
arriving inside that window into a DOUBLE_CLICK. Since the handler only acts
on CLICK, an impatient second press produced nothing at all: press, see
nothing, press again, still nothing. Multi-click is now off for these targets,
so CLICK fires on release.

Both settings are build flags defaulted in variants/heltec_v4_r8/target.cpp
and overridden only on the two TFT observer bases, because the companion
builds share this user_btn and do use double/triple click.

DISPLAY_TOUCH_DEBUG additionally logs which input caused a toggle
("Display: button -> on"), so any remaining flake can be attributed to the
button or to a spurious touch read rather than guessed at.
2026-08-28 15:37:09 -07:00
agessaman ca17c2980c feat(display): add runtime display.flip for panel orientation
`set display.flip 0|1` (also off/on) turns the panel 180 degrees from its
compiled DISPLAY_ROTATION, persisted in MQTTPrefs alongside display.timeout
and applied live without a reboot.

Adding 2 to the compiled rotation rather than setting an absolute value keeps
portrait portrait and landscape landscape, so the DisplayViewport geometry
never changes with it and the setting cannot produce a nonsensical mix.
DisplayDriver gains a defaulted no-op setFlipped(), so no other display
driver is affected.

The compiled rotation was verified identical across `pio run` and `build.sh`
on two machines (movi a11, 2 at the setRotation call site), yet the panel read
upside down for one tester and upright for another - which is what a board
mounted either way up looks like. No single compiled constant satisfies both,
so orientation becomes a setting rather than another rebuild.

Runtime-only, like display_timeout_secs: LegacyV1MQTTPrefs and the frozen
binary payload sizes are untouched, and the JSON group is an append that older
firmware skips.
2026-08-28 14:37:03 -07:00
agessaman 11d7551ccd fix(display): correct R8 touch decode, display wake and power-off
Four defects found by hardware testing of the Expansion Kit V2.

Touch never registered. The panel's controller does not use the point-count
encoding the reference CHSC6X drivers document: byte 0 reads 0x00 idle and
0x1F while a finger is down, so testing for a count of 1 never fired. A
partly-failed read leaves 0xFF, which must not count as a press either, so
the test is now != 0x00 && != 0xFF.

Touch polling could stall the UI loop for ~1 s at a time. The controller
NACKs its address whenever it has nothing to report, and calling requestFrom()
unconditionally logged a bus error on every 50 ms poll and, once the bus
wedged, burned a full ESP_ERR_TIMEOUT inside loop(). Probe the address first,
which reports the same NACK quietly, and bound the read with setTimeOut().

The display could not be woken once it blanked; only RST brought it back.
turnOn() re-ran the whole display.init(), which re-enters SPI setup, spends
~500 ms in Adafruit's reset delays and pulses GPIO 21 - the line shared with
TP_RST, so it reset the touch controller on every wake. Since turnOff() no
longer parks that line low, the panel stays configured while dark and waking
is just the backlight. Toggling also clears the refresh deadline so the
current frame is drawn immediately instead of the stale one.

Power-off rebooted instead of staying off. powerOff() went through
enterDeepSleep(), which always arms an ext1 wake on P_LORA_DIO_1; a deep-sleep
wake is a full reboot, so a node in live traffic restarted within seconds of
showing "Turning OFF". It now disables every wake source, so the node stays
down until RST or a power cycle.

Note that the display off/on cycle had never been exercised on this board
before: observer builds pinned AUTO_OFF_MILLIS=0, so the panel never blanked
until display.timeout made it a runtime setting.
2026-08-28 14:26:52 -07:00
agessaman 5d56267176 feat(display): add R8 observer TFT dashboard, touch toggle and display.timeout
Replace the sparse Heltec V4 R8 observer home screen with a padded dark
analytics dashboard, add manual display control, and make blanking a runtime
setting.

Dashboard (DISPLAY_ACTIVITY_DASHBOARD, the four R8 TFT observer envs):

- RadioActivityWindow: 20 one-minute buckets of valid RX packets, no heap.
  The caller's 32-bit millis() is extended to a monotonic 64-bit clock, so
  nothing downstream has a rollover case; an always-on node passes 2^32 ms
  after ~49.7 days, which would otherwise re-enter warm-up and divide 20
  minutes of traffic by seconds. Rates use 19 whole minutes plus the elapsed
  part of the current one rather than a fixed 1200 s.
- ObserverDashboard: header, radio strip, headline totals, a 20-bar
  packets-per-minute graph and RF/status footers, with separate portrait and
  landscape layouts. A text row is a fixed 16 px, which is 3.2 logical units
  in portrait but 4.27 in landscape, so one shared grid would overlap.
  Text is trimmed by character budget, not measured width: getTextWidth()
  reports an over-long string at the portrait driver's fallback scale, so
  DisplayDriver::drawTextEllipsized() under-trims and the row renders at half
  height.
- Six per-row signatures computed from what is actually drawn, so only the
  rows whose pixels changed repaint. No startFrame(), no whole-screen clear.
  Link state moved out of the full-frame signature, so a DHCP renewal or WiFi
  flap repaints one footer row instead of the panel.
- Dark theme by retuning the UIColor statics at runtime, which needs no
  display-driver edit and carries boot, setup, reboot and power-off with it.

Touch and button (DISPLAY_TOUCH_TOGGLE):

- CHSC6X at I2C 0x2E, polled; TP_INT is unusable (optional R13, and GPIO 43
  is U0TXD). The point-count byte is tested against a valid count, never
  against non-zero: an idle read returns 0xFF, which reads as a finger held
  down forever and latches the tap detector after one event.
- turnOff() no longer parks PIN_TFT_RST low on this board. GPIO 21 is a
  shared LCD_RST/TP_RST net, so doing that held the touch controller in
  reset for as long as the display was off. Verified against Heltec's
  expansion-board and mainboard schematics and the V4-R8 datasheet pinout,
  which also correct the pin comment in HeltecV4R8Board.cpp.
- The USER button click now toggles the display too; it previously did
  nothing whenever the display was already on.

display.timeout:

- `set display.timeout <secs>` / `get display.timeout`, 0 = stay on, 60 s
  default, 3600 max. Read live, so a change applies without a reboot and
  restarts the countdown rather than firing on the old deadline.
- Stored in MQTTPrefs (/mqtt.json), keeping NodePrefs aligned with upstream.
  Runtime-only: LegacyV1MQTTPrefs and the four frozen binary payload sizes
  are unchanged. No JSON format-version bump - the loader skips keys no
  def() claims, so older firmware reads newer files and this firmware reads
  older ones with the default applied. Both directions are covered by tests.
- Joins the observer atomic-setter contract, so a failed save rolls the live
  value back instead of only claiming to.

New periodic work uses a wrap-safe deadline check; `millis() >= deadline`
fires every loop for a whole interval before each rollover.

Adds test_radio_activity_window, test_observer_dashboard (driving the real
renderer against a recording DisplayDriver in both orientation profiles) and
test_touch_tap_detector. 440 native cases pass.
2026-08-28 13:39:16 -07:00
agessaman 0d2c926a07 feat(display): add R8 portrait observer layouts 2026-08-28 09:21:38 -07:00
mikecarper c6476b8ba8 feat: consolidate full companion runtime profiles 2026-08-28 08:47:26 -07:00
mikecarper d17c250137 fix: port T-Beam 1W hardware corrections
Adapt the validated fan thermostat, battery ADC calibration, GPS baud, SX1262 register patch, and 1700us PA ramp behavior from mintylinux/Meshcore-T-beam-1W-Firmware to the current board architecture. Also make Arduino 3 full-build dependency switching reliable after standard ESP32 builds and guard the release hardware contract with regression coverage.
2026-08-27 18:58:37 -07:00
mikecarper a0165cb38b fix: harden CLI and GPS handling 2026-08-27 17:59:44 -07:00
mikecarper 5a26d4ddd1 fix: stabilize Heltec RC32 startup 2026-08-27 17:06:20 -07:00
mikecarper 7676e4b1c2 feat: unify companion builds and USB runtime modes 2026-08-27 15:06:26 -07:00
mikecarper e5fd77e53f feat: add Bluetooth-controlled LoRa OTA
Add the framed BLE mOTA transport and companion control path, complete the full-profile build and runtime fixes, and document and test the OTA workflow.
2026-08-27 01:22:18 -07:00
liamcottle e3d0f9fcaa fix cad cli command on companion 2026-08-27 19:05:18 +12:00
Liam Cottle 1c3248902a Merge pull request #3298 from meshcore-dev/companion-cli
Companion CLI
2026-08-27 18:17:10 +12:00
mikecarper 91870e4bb0 fix: harden firmware builds and runtime reliability 2026-08-26 15:42:12 -07:00
mikecarper 83e402bd4d fix: preserve complete companion build profiles 2026-08-25 23:47:40 -07:00
mikecarper 9bc95a60fe fix: default advert location to stored preferences 2026-08-25 23:47:40 -07:00