feat: sync upstream/main + integrate PR #3 + extend HA coherence#4
Merged
Conversation
- 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.
…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.
There was a problem hiding this comment.
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 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"), |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings 33 commits from
renjfk/OpenNeatoupstream 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:/api/analog,/api/warranty,/api/battery/new) + battery settings pageapFallbackOnDisconnectsetting)frontend/src/types.tsnow re-exports from a generatedtypes.generated.tsproduced byopenapi-typescriptagainstfrontend/api/openapi.yaml. Hand-edited spec is the single source of truth.frontend/mock/server.js→shared-api.js+shared-state.js+worker.js)/api/firmware/versionConflicts resolved:
frontend/src/types.ts— took upstream (now generated)frontend/mock/server.js— took upstream, then re-added fork-specificntfyServer/ntfyToken/ntfyOnStartstate inshared-state.jsand the settings key list inshared-api.jsfrontend/api/openapi.yaml— added the same three fork ntfy fields toSettingsData(andrequired:)frontend/package-lock.json— took upstream;npm cire-resolves2. 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/analogfield, and tolerates non-UTF-8 bytes in the/api/versionresponse (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:
notify_on_start— was missing despite firmware + frontend already supporting it (fork PR feat(notifications): cleaning-started ntfy + fix done summary race #2)ap_fallback_on_disconnect— toggles the new captive-portal fallback from PR feat: fallback WiFi access point for browser-based provisioning renjfk/OpenNeato#110ntfy_topic,ntfy_server,ntfy_tokenmanifest.jsonbumped 1.10 → 1.11, CHANGELOG entry, translations instrings.json.gitignore— Python__pycache__//*.pyc4. API surface fix (
9870ca6)Fork's
/api/sensors(DigitalSensorData — bumpers, wheel lift, dustbin, DC jack — used by the HAbinary_sensorplatform) wasn't in the OpenAPI spec. Upstream'scheck_api_pathsscript flags route drift, so this keptnpm run buildfrom passing until added.Deferred (documented in CHANGELOG)
_http._tcp(seewifi_manager.cpp:564). Claiming that would match every HTTP device on the LAN. Needs a dedicated_neato._tcpservice first.name/repositoryUrl/licensefrom/api/firmware/versionnot 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).pycompiles,manifest.json+strings.jsonparse, everytranslation_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 thisTest plan
notify_on_startandap_fallback_on_disconnectswitches → confirm settings persistntfy_topic/ntfy_server/ntfy_token→ confirm HA round-trips through/api/settingsPUT🤖 Generated with Claude Code