Skip to content

feat: sync upstream/main + integrate PR #3 + extend HA coherence#4

Merged
Leicas merged 46 commits into
mainfrom
feat/upstream-sync-2026-05
May 23, 2026
Merged

feat: sync upstream/main + integrate PR #3 + extend HA coherence#4
Leicas merged 46 commits into
mainfrom
feat/upstream-sync-2026-05

Conversation

@Leicas

@Leicas Leicas commented May 23, 2026

Copy link
Copy Markdown
Owner

Summary

Brings 33 commits from renjfk/OpenNeato upstream into the Leicas fork and merges open PR #3 (battery diagnostics for HA), then extends the HA integration so the new firmware capabilities don't sit unused.

What this PR does

1. Upstream sync (merge commit 1846b26)

Full merge of upstream/main. Highlights:

Conflicts resolved:

  • frontend/src/types.ts — took upstream (now generated)
  • frontend/mock/server.js — took upstream, then re-added fork-specific ntfyServer / ntfyToken / ntfyOnStart state in shared-state.js and the settings key list in shared-api.js
  • frontend/api/openapi.yaml — added the same three fork ntfy fields to SettingsData (and required:)
  • frontend/package-lock.json — took upstream; npm ci re-resolves

2. PR #3 merge (ffc1b29)

@druby-luke's feature/firmware013-integration-update — clean merge, no conflicts. Adds 5 battery diagnostic sensors, a "New battery" calibration button, repoints battery-temp to the new /api/analog field, and tolerates non-UTF-8 bytes in the /api/version response (firmware PR renjfk#121 surfaces raw smart-battery bytes).

3. HA coherence pass (2420117)

With firmware shipping new capabilities, the HA integration should expose them:

4. API surface fix (9870ca6)

Fork's /api/sensors (DigitalSensorData — bumpers, wheel lift, dustbin, DC jack — used by the HA binary_sensor platform) wasn't in the OpenAPI spec. Upstream's check_api_paths script flags route drift, so this kept npm run build from passing until added.

Deferred (documented in CHANGELOG)

  • mDNS zeroconf in HA manifest — firmware advertises only generic _http._tcp (see wifi_manager.cpp:564). Claiming that would match every HTTP device on the LAN. Needs a dedicated _neato._tcp service first.
  • About metadata as device attributesname / repositoryUrl / license from /api/firmware/version not surfaced. Threading through nine platform constructors is too invasive vs cosmetic value — better fit for a dedicated diagnostic sensor later.

Verification

  • npm run build (frontend) — biome + jscpd + openapi-typescript + check_api_paths + tsc --noEmit + vite + embed_frontend (35 routes in sync, web_assets.h regenerated)
  • pio run -e c3-debug — succeeds; RAM 17.7%, Flash 87.3% of the C3 OTA slot (heads-up: tight)
  • ✅ HA integration — every .py compiles, manifest.json + strings.json parse, every translation_key= in code has a matching entry in strings.json (no orphans, no unused)
  • ⚠️ python scripts/check_format.py — clang-format not on PATH locally; CI will gate this

Test plan

  • CI green (firmware c3/s3/esp32-debug builds, frontend, flash tool)
  • Install HACS integration from this branch on a real HA instance
  • Toggle notify_on_start and ap_fallback_on_disconnect switches → confirm settings persist
  • Set a value in ntfy_topic / ntfy_server / ntfy_token → confirm HA round-trips through /api/settings PUT
  • Verify battery diagnostic sensors (current, voltage, cycles, cleaning time, temp) populate after coordinator refresh
  • Verify "New battery" button is disabled by default (safety) and works when enabled

🤖 Generated with Claude Code

renjfk and others added 30 commits April 25, 2026 22:24
- Added support for battery diagnostics including voltage, current, and warranty data.
- Implemented a new button to reset battery fuel-gauge calibration after a pack swap.
- Enhanced JSON response handling to tolerate non-UTF-8 bytes, preventing setup crashes.
- Updated changelog and version to 1.10.
renjfk and others added 16 commits May 18, 2026 02:40
…llback AP, OpenAPI-generated types

Resolved conflicts:
- frontend/src/types.ts: take upstream (now generates from openapi.yaml).
- frontend/mock/server.js: take upstream (split into shared-api.js/shared-state.js).
- frontend/api/openapi.yaml: re-added fork-specific ntfyServer/ntfyToken/ntfyOnStart.
- frontend/mock/shared-state.js + shared-api.js: re-added fork ntfy fields.
- frontend/package-lock.json: take upstream; re-resolve via npm install in build step.
Surfaces firmware 0.13 (/api/analog, /api/warranty, /api/battery/new)
endpoints as HA entities and tolerates non-UTF8 bytes in version response.
- New switches:
  * notify_on_start — was missing despite firmware/frontend having it (fork PR #2)
  * ap_fallback_on_disconnect — upstream renjfk#110 captive-portal AP fallback

- New text entities for full ntfy config from HA UI:
  * ntfy_topic, ntfy_server, ntfy_token

- manifest.json: 1.10 -> 1.11
- CHANGELOG: document additions and deferred items (zeroconf disabled because
  firmware only advertises _http._tcp; About metadata not surfaced yet)
- .gitignore: ignore Python __pycache__/*.pyc
This fork's web server registers GET /api/sensors (returning DigitalSensorData
— dustbin, bumpers, wheel lift, DC jack) for the HA integration. Upstream's
check_api_paths script flags route surface drift, so the spec needs the
endpoint + schema to keep `npm run build` green.
Reddit follow-up: u/leicas was asked to surface the HACS integration in the
fork's README. The README was the upstream version verbatim and never
mentioned the integration that's been the fork's value-add since 1.0.0.

New section covers install via HACS, the full entity inventory (vacuum,
2 cameras, sensors, binary_sensors, switches, text, numbers, select,
buttons), coordinator resilience guarantees, ntfy/custom-server tips,
and per-version highlights (links to custom_components/openneato/CHANGELOG.md
for the full log).
Repositions the README so the first thing a Reddit-linked visitor sees is
'this is a fork focused on the HA integration with minor firmware tweaks'.
The previous commit landed the HA section but the title, intro, and upstream
'Motivation'/'Features' headings still read as the upstream project verbatim.

Changes:
- Title -> 'OpenNeato - Home Assistant fork'
- Lead paragraph + IMPORTANT box: when to use this fork vs upstream; firmware
  changes here are minor and only exist to back the integration.
- 'Motivation' -> 'About the underlying project (upstream)' with a skip-ahead
  link to the HA section.
- 'Features' -> 'Upstream web UI features' (sub-heading) so reader knows the
  feature list describes upstream, not the fork's HA-specific surface.
- Bug-report routing: HA issues here, firmware/frontend/flash-tool upstream.
- Badges repointed: CI/release badges no longer pull from upstream.

Also: large insertion/deletion count is the LF normalization pass; the prior
commit landed CRLF on disk on Windows. Forcing LF here so future diffs stay
clean.
CI's clang-format check failed against the fork's firmware sources — these
files had never been clang-formatted (the verification ran on Windows where
clang-format isn't on PATH, so the check_format script silently skipped).
Running 'python scripts/check_format.py --fix' under an ad-hoc clang-format
22 (installed in .venv-cf via uv) brought 4 files into compliance:
neato_serial.cpp, notification_manager.{cpp,h}, web_server.cpp — each just
collapsing a 2-line statement onto one because ColumnLimit=120 allows it.

Most of the diff stat is line-ending normalization: the fork files were
CRLF on disk and clang-format outputs LF (no LineEnding override in the
.clang-format config). 'git diff -w' shows the real code delta is 13 lines
across 4 files; the remaining ~6600 'changes' are pure CRLF -> LF.

Files touched: cleaning_history.{cpp,h}, neato_serial.cpp,
notification_manager.{cpp,h}, system_manager.cpp, web_server.cpp.
Adds the ESP32-C6 target to the CI build matrix so PRs and main pushes
verify it compiles. The [board_c6] / [env:c6-*] platformio.ini entries
already exist (pioarduino 54.03.21-2 platform); they just weren't gated
in CI.

Also uploads the c6-debug build's firmware.bin (+ bootloader / partitions)
as an actions artifact, retention 7 days. Lets you OTA-flash the C6 bridge
without a working local pioarduino install — useful on Windows where the
toolchain dance is finicky. Only c6-debug uploads to keep storage low;
other targets can opt in if needed.
c6-debug overflows the 1.5625 MB OTA slot (~1.7 MB binary — debug strings
push it over). c6-ota disables logging (-DENABLE_LOGGING=0), which fits.
Both targets stay in the matrix so debug-build regressions still show up;
the artifact comes from c6-ota since that's what you actually OTA-flash
to the bridge.
C6 ota build overshoots the 1.5625 MB OTA slot by ~42 KB. Arduino-ESP32's
log_e/log_w/log_i/log_d macros expand based on CORE_DEBUG_LEVEL; defaulting
to 0 strips the format strings and call sites that the framework's WiFi /
BLE / 802.15.4 layers emit. ENABLE_LOGGING=0 only covers our own LOG()
helper, not the framework's. Trying this first before resorting to a C6
partition table change.
Previous commit (ad3e5d8) was supposed to add -DCORE_DEBUG_LEVEL=0 to c6
ota/release flags but my Edit failed silently because pio had rewritten
platformio.ini locally (added 'platform_packages' blocks pinning both
pioarduino and platformio editions of tool-esptoolpy after a local
package-install hiccup). That cruft also slipped into ad3e5d8.

This commit:
- Actually adds -DCORE_DEBUG_LEVEL=0 to c6-ota and c6-release build_flags
- Removes the spurious platform_packages blocks from both envs (CI installs
  tool-esptoolpy via 'pip install platformio intelhex' just fine without
  the override).
The 'platform_packages = pioarduino/tool-esptoolpy@^5.0.2' override broke
the pioarduino 54.03.21 platform's auto-resolution: build script ends up
calling 'python esptool.py' with a relative path that doesn't exist in the
workspace. c6-ota and c6-release didn't have the override and built cleanly
in CI; c6-debug had it and failed at bootloader.bin generation. Removing it.
@Leicas Leicas marked this pull request as ready for review May 23, 2026 18:11
Copilot AI review requested due to automatic review settings May 23, 2026 18:11
@Leicas Leicas merged commit 95b35ec into main May 23, 2026
9 checks passed
@Leicas Leicas deleted the feat/upstream-sync-2026-05 branch May 23, 2026 18:11

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR syncs a large set of upstream changes into the fork, merges HA battery-diagnostics work, and extends firmware/frontend/HA integration to expose newly added capabilities (battery diagnostics, WiFi fallback AP management, ntfy configuration) while tightening API/spec/tooling coherence.

Changes:

  • Adds firmware + frontend support for WiFi management (status/scan/connect/disconnect) and fallback AP behavior, plus related frontend UI.
  • Extends HA custom integration with additional entities (battery diagnostics, “new battery” button, notify-on-start, AP fallback switch, ntfy text config) and version bump.
  • Introduces/extends build tooling: OpenAPI→TS codegen, API route drift checks, demo worker + analytics, and various workflow/release pipeline updates.

Reviewed changes

Copilot reviewed 73 out of 84 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
README.md Documents fork focus and adds HA integration overview/instructions.
platformio.ini Updates PlatformIO configuration/versions and adds env tweaks for additional boards/tools.
frontend/wrangler.toml Adds Cloudflare Worker config for demo deployment.
frontend/vite.config.ts Switches to async config, adds demo build flag + dev mock plugin import.
frontend/src/views/settings/wifi-section.tsx Adds WiFi status/scan/connect/forget UI and AP fallback toggle UI.
frontend/src/views/settings/use-settings-form.ts Adds apFallbackOnDisconnect to settings form state + patching.
frontend/src/views/settings/use-reboot.ts Replaces bespoke polling with shared usePoll hook for reboot detection.
frontend/src/views/settings/settings-category.tsx Adds optional lazy-mounting of category content.
frontend/src/views/settings/constants.ts Adds apFallbackOnDisconnect default setting.
frontend/src/views/settings/battery-diagnostics.tsx Adds battery diagnostics UI + “New Battery” action.
frontend/src/views/settings.tsx Adds WiFi category, diagnostics link to battery page, About section, and shared polling improvements.
frontend/src/views/history/motion-player.tsx Adds rotation support and ability to suspend canvas painting during reveal.
frontend/src/views/history/item.tsx Adds persisted rotation controls and loading-wave reveal integration.
frontend/src/views/history/helpers.ts Refactors map rendering helpers; adds projection/grid helpers and rotation support.
frontend/src/views/history.tsx Adds corrupted-history recovery panel and uses shared polling hook.
frontend/src/views/battery.tsx Adds dedicated Battery view route rendering battery diagnostics.
frontend/src/types.ts Switches API types to re-export generated OpenAPI types and keeps frontend-only map types.
frontend/src/svg.d.ts Adds module declaration for *.css side-effect imports.
frontend/src/main.tsx Adds demo-mode scenario cookie + deferred analytics init.
frontend/src/hooks/use-poll.ts Adds shared non-overlapping, visibility-aware polling hook.
frontend/src/hooks/use-map-gestures.ts Updates gesture math to stay aligned with rotated rendering.
frontend/src/components/confirm-dialog.tsx Extends confirm dialog with destructive/primary styling and optional input prompt.
frontend/src/assets/icons/rotate-right.svg Adds rotate-right icon asset.
frontend/src/assets/icons/rotate-left.svg Adds rotate-left icon asset.
frontend/src/assets/icons/globe.svg Adds globe icon asset.
frontend/src/assets/icons/battery.svg Removes old battery icon asset.
frontend/src/app.tsx Adds /battery route.
frontend/src/api.ts Adds battery/wifi endpoints, JSON parse error signaling, and upload refactor.
frontend/src/analytics.ts Adds demo analytics tracker (beacon/fetch).
frontend/scripts/write_demo_build_info.js Writes demo build/version info for the worker.
frontend/scripts/embed_frontend.js Converts embed script to ESM and fixes __dirname handling.
frontend/scripts/check_api_paths.js Adds build-time firmware↔OpenAPI route surface parity check.
frontend/package.json Adds ESM mode + codegen + route check + demo build scripts and new dev deps.
frontend/mock/worker.js Adds Cloudflare Worker demo API + session/scenario handling + analytics relay.
frontend/mock/shared-version.js Adds shared mock version helpers.
frontend/mock/shared-state.js Adds scenario state/fault injection and WiFi-related scenarios.
frontend/biome.json Updates schema and excludes generated TS types from linting.
frontend/.npmrc Adds legacy peer-deps setting.
frontend/.jscpd.json Adds jscpd duplicate-code configuration.
flash/go.sum Updates Go module sums for flash tool dependencies.
flash/go.mod Updates Go version and dependency versions for flash tool.
firmware/src/wifi_manager.h Adds WiFi API structs and WiFiManager API surface/AP fallback hooks.
firmware/src/wifi_manager.cpp Implements WiFi API endpoints support, fallback AP lifecycle, and mDNS start logic.
firmware/src/web_server.h Wires WiFiManager into WebServer and adds WiFi route registration.
firmware/src/system_manager.cpp Formatting/whitespace normalization (no behavioral change apparent in diff).
firmware/src/settings_manager.h Adds apFallbackOnDisconnect setting and callback hook.
firmware/src/settings_manager.cpp Persists/applies apFallbackOnDisconnect and emits callback on change.
firmware/src/notification_manager.h Formatting/whitespace normalization (no behavioral change apparent in diff).
firmware/src/neato_serial.h Adds analog/warranty fetch APIs and new-battery command hook.
firmware/src/neato_commands.h Adds battery-related command constants and new data structs/parse hooks.
firmware/src/neato_commands.cpp Adds battery analog/warranty parsing + expands version parsing and robustness.
firmware/src/main.cpp Starts web server on STA or fallback AP; ties settings to WiFi fallback policy; safer OTA-valid marking.
firmware/src/firmware_manager.cpp Fixes OTA chip-ID validation by mapping header IDs to esp model enum.
firmware/src/data_logger.cpp Simplifies HTTP method string mapping (behavior unchanged).
firmware/src/config.h Adds NVS key and constants for fallback AP configuration.
firmware/src/cleaning_history.h Formatting/whitespace normalization (no behavioral change apparent in diff).
docs/mock-scenarios.md Documents mock scenarios, including new WiFi and corruption scenarios.
custom_components/openneato/text.py Adds ntfy topic/server/token text entities.
custom_components/openneato/switch.py Adds notify-on-start and AP fallback switches.
custom_components/openneato/strings.json Adds translations for new entities/sensors/button.
custom_components/openneato/sensor.py Adds analog/warranty battery diagnostic sensors and updates battery temperature source.
custom_components/openneato/manifest.json Bumps HA integration version to 1.11.
custom_components/openneato/coordinator.py Adds polling of /api/analog and /api/warranty.
custom_components/openneato/CHANGELOG.md Adds 1.10/1.11 changelog entries for HA integration.
custom_components/openneato/button.py Adds “New battery” button entity (disabled by default).
custom_components/openneato/api.py Adds tolerant JSON decoding and new battery/analog/warranty endpoints.
AGENTS.md Updates contributor/build pipeline documentation (codegen + route checks + dupes).
.goreleaser.yml Stamps release version into OpenAPI spec and includes it in release artifacts; macOS deployment pin.
.gitignore Ignores Python caches and generated frontend artifacts.
.github/workflows/slash-command.yml Adjusts prerelease workflow trigger ref behavior.
.github/workflows/release.yml Minor robustness changes (quoting, loop style, step naming).
.github/workflows/prerelease.yml Improves PR checkout logic and output formatting; loop style updates.
.github/workflows/ci.yml Expands firmware matrix and uploads C6-OTA artifacts; retains frontend/flash checks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +26 to +34
export function computeMapProjection(displayW: number, displayH: number, bounds: MapBounds): MapProjection {
const { minX, maxX, minY, maxY } = bounds;
const worldW = maxX - minX;
const worldH = maxY - minY;
const availW = displayW - MAP_PAD * 2;
const availH = displayH - MAP_PAD * 2;
const scale = Math.min(availW / worldW, availH / worldH);
const offX = MAP_PAD + (availW - worldW * scale) / 2;
const offY = MAP_PAD + (availH - worldH * scale) / 2;
Comment thread frontend/src/api.ts
Comment on lines +171 to +175
getWifiStatus: () => get<WiFiStatus>("/api/wifi/status"),
scanWifi: () => get<WiFiScanResult>("/api/wifi/scan"),
connectWifi: (ssid: string, password: string) =>
post(`/api/wifi/connect?ssid=${encodeURIComponent(ssid)}&password=${encodeURIComponent(password)}`),
disconnectWifi: () => post("/api/wifi/disconnect"),
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.

5 participants