Skip to content

v1.2.0 - #24

Merged
tuzzmaniandevil merged 10 commits into
mainfrom
dev
Sep 30, 2026
Merged

tuzzmaniandevil merged 10 commits into
mainfrom
dev

Conversation

@tuzzmaniandevil

Copy link
Copy Markdown
Contributor

Release v1.2.0: openHop modems and SPI radio hats alongside KISS, firmware-named MQTT status fields, automatic radio reconnect, and meshcore-go v1.6.0. Full notes are in CHANGELOG.md under ## v1.2.0 - 2026-09-30.

Merge #23 first so the changelog heading is renamed, then merge this one with a merge commit. The annotated v1.2.0 tag goes on that merge commit.

tuzzmaniandevil and others added 10 commits August 25, 2026 16:14
- meshcore-go v1.1.0: real-dB SNR + HasSignalInfo, modem handler
  workers/watchdog, salted ACK dedup, unique retry packets, 0-hop direct
  neighbour routing
- MQTT moves under a bot: optional [bot.mqtt] on at most one bot;
  legacy root [[observer]] blocks auto-migrate on first load with a
  timestamped backup of the original config
- port OwlShack MQTT fixes: per-broker publish workers off the RX path,
  panic-safe shutdown (radio detach, stop-channel drain), UTC zone-aware
  timestamps, bounded broker connect handshake (10s)
- bug fixes: unnamed-advert crash, companion channel key normalization
  mismatch, bot self-trigger loop via repeater echo, brokers slice data
  races, atomic identity-key write, id.Sign for auth tokens
- remove companion modem support entirely; KISS firmware nodes only
…lience

- radios: openhop:// (serial, or TCP with modemToken) and spi:// with
  spiBoard (15 SX1262 presets, byte-identical to OwlShack's, plus a
  boards.json override); the connection scheme picks the radio and
  nodeType is ignored so old configs still load
- meshcore-go v1.6.0, plus hardware/sx12xx, hardware/openhop and periph.io;
  every release target still builds with CGO off
- stats: LinkStats replaces the KISS-only ModemStats, nil meaning the
  transport cannot measure a counter
- MQTT status uses the firmware's names and meanings: recv_errors is the
  radio's count (polled from KISS firmware) and packet_parse_errors is new;
  battery_mv replaces the fabricated battery_percent and is omitted when
  unmeasurable or stale; noise_floor moves into stats; recv/packets_recv;
  SNR/RSSI omitted when missing; crc_errors, driver_errors, recv_recoveries
  omitted on KISS
- MQTT adds TX rows, score/duration/path on RX rows, and fault counters
- brokers: retried when down at startup, startup no longer waits on them,
  shutdown bounded at 5s, token refresh recovers and no longer flaps
- dutyCycle setting, TX airtime estimator, 500ms RX handler watchdog
- openHop ignores baudRate: its firmware fixes 921600, and migrated
  configs carry 115200
- config errors (bad scheme, spi:// without spiBoard) caught at load, so a
  bad SIGHUP keeps the running config
- .gitignore: un-ignore the embedded modem_boards.json, which *.json hid
- CHANGELOG.md in OwlShack's format; release.yml extracts the tag's section
  as the release notes
Both rx_meta counters count a packet whose signal report never paired
with it, published without SNR/RSSI. rx_meta_misattributed is the same
loss caught sooner: the next packet arrived first, or a report arrived
with no packet. The library refuses the pairing rather than make it, so
no published SNR/RSSI is ever wrong because of it. The old comments said
the opposite.

Checked on hardware by dropping every second RX_META frame from a real
KISS modem: 23 of 23 rows correct, and the two counters summed to the 11
drops (10 misattributed, 1 timeout, since floods arrive in bursts).
feat: openHop and SPI radios, firmware-named MQTT status, broker resilience
- ci.yml: run on pull requests into dev as well as main, so a feature
  PR is built and tested before it merges rather than at the release PR
- release.yml: a tag containing '-' (v1.3.0-rc.1) is published as a
  GitHub pre-release and no longer moves the :latest image tag; the
  same expressions OwlShack's release workflow uses
- README: maxRetries counts total sends, first included, so the default
  3 is one send and up to two resends; it was described as retries
A radio that is unplugged, whose link drops, or that stops answering is
now torn down and reconnected, and the bots and MQTT observer restarted
with it. Before, the bot kept running but heard and sent nothing until
restarted.

- modem_watch.go: per-modem watchers on Dead() (KISS read loop exited,
  SPI chip no longer re-arming receive) and a liveness probe for the
  case Dead() cannot see: a serial port that stays open while the board
  goes silent. The probe is OwlShack's: every 30s, reconnect after 3
  unanswered polls, and skip a modem that has never answered.
- Watchers report the modem itself; the main loop ignores a report about
  a modem it has already replaced. Close stops watchers before closing
  the modem, and a watcher checks for that first, so a deliberate close
  is never reported (a race the test caught 3 times in 20 runs).
- Main loop retries from a timer arm, 1s doubling to 30s, so a SIGHUP
  with the operator's fix is applied at once rather than queued behind
  the retries. A reload whose new radio will not come up now retries
  instead of exiting. Startup still exits if the radio never comes up.
- KISS Stats is serialised: the probe and the MQTT status both poll, and
  two polls at once would reopen the query-ordering trap.
chore: CI on PRs into dev, rc tags as pre-releases, maxRetries wording
feat: reconnect a radio that is lost
@tuzzmaniandevil
tuzzmaniandevil merged commit 5322fab into main Sep 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant