v3.1.0
Roomba+ v3.1.0 — Self-Calibrating Intelligence
Config entry version: 24 (unchanged — no migration required)
Minimum Home Assistant: 2025.5.0
Breaking changes: none for end users
Overview
v3.1.0 focuses on making Roomba+ smarter about its own robot rather than relying on fixed, one-size-fits-all thresholds. Three new self-calibrating systems learn each robot's individual normal behaviour over time and only raise an alert when something genuinely deviates from it — replacing an earlier approach that would have produced false positives (or, in one case, a literally nonsensical 354-year battery life projection) on perfectly healthy robots.
This release also adds three new dictionary-style sensors for mission and room history, a plain-language layer on top of the existing health-score sensors, and a documentation pass on privacy and robot lifecycle.
What's new
Self-calibrating navigation health (SMART-tier)
sensor.*_relocalisation_rate tracks how often the robot has to relocalise during a mission — a direct signal of Smart Map quality. Rather than using a fixed threshold (which field testing showed doesn't generalise across different homes, floor plans, and WiFi conditions), the sensor learns each robot's own normal relocalisation rate over its first 15 cleaning missions, then compares the recent 10-mission window against that personal baseline. A Repair Issue fires only when the rate climbs to 3× the established baseline, and clears itself automatically once the rate returns to normal — no manual dismissal needed.
Disabled by default (diagnostic-tier); enable it if you want visibility into navigation health, especially after a Smart Map retrain.
Self-calibrating battery health
The existing estimated_battery_eol sensor (days remaining until 65% capacity) has been hardened against measurement noise. Field testing on a long-running i7+ revealed that estCap readings naturally oscillate by ±10–15 mAh between missions on an otherwise healthy battery — and the previous linear extrapolation, taken at face value, projected a 354-year remaining lifespan from that noise alone. Technically correct math, useless as information.
The sensor now learns each robot's own measurement noise floor (using Welford's algorithm for a numerically stable running standard deviation) and only trusts a degradation trend once it clearly exceeds that floor. A conservative fallback threshold means genuinely failing batteries are still detected immediately, without waiting through the full learning period.
Map drift detection — sliding window instead of lifetime total
map_drift_detected previously accumulated drift as a lifetime sum, which meant any EPHEMERAL-tier robot with enough mission history would eventually cross the trigger threshold regardless of whether it was actually drifting right now — a robot that had logged 5820mm of lifetime drift over months of normal use, none of it currently problematic, would still show a permanent false-positive warning.
Drift is now tracked over a 10-mission sliding window. The issue fires only when the recent average exceeds 250mm, and clears automatically (with hysteresis at 150mm to prevent flapping) once drift returns to normal. The lifetime total is retained as a diagnostic value but no longer drives the alert.
New sensors
sensor.*_last_mission_summary— the most recent mission as a single entity, with 14 attributes (duration, area, battery delta, recharges, dirt events, initiator, timestamps) for easy automation triggers and troubleshooting, without digging through mission history.sensor.*_room_cleaning_history— a dictionary sensor mapping each room to its last-cleaned timestamp, built from existing mission records (SMART-tier with cloud access). No new storage schema, no entity-count growth on map retrain.sensor.*_room_areas— a dictionary sensor mapping each room to its floor area in m², calculated from UMF polygon data. The only automatically-measured room area available without a tape measure.
All three use the dictionary-attribute pattern rather than one entity per room — stable entity count regardless of how many rooms your home has, and no orphaned entities after a Smart Map retrain.
Plain-language health status
integration_health and robot_health_score now carry status_text and recommendation attributes in addition to their numeric score — a human-readable summary ("Cloud connection has been stuck for 6h" / "Check your iRobot credentials in the options") instead of requiring you to interpret a raw breakdown dict. Available in all 7 supported languages.
Documentation
- Privacy: the cloud credentials setup step now explicitly states that all commands run locally over MQTT and never touch the cloud — cloud access is read-only, used only for room names, mission history, and favorites.
- Lifecycle: a new "Replacing or selling your robot" section in the README and Troubleshooting guide covers exporting your mission history before removing the integration, and restoring it on a replacement robot.
Field-data acknowledgements
Several fixes and the entire self-calibration approach in this release came directly out of real-world field reports:
- The relocalisation-rate sensor's design — and the discovery that
nMssnincrements automatically without an actual cleaning mission starting — came from detailed MQTT captures and patient back-and-forth troubleshooting on an i7+. - The battery noise-floor fix was driven by a multi-month
estCapreading history on the same robot, which made the false-positive risk concrete rather than theoretical. - A Smart Map corruption report (recurring "New space found" messages, inaccurate room tracking, eventually requiring a full map reset) provided useful context on what genuine navigation degradation looks like, distinct from normal noise.
Thank you to everyone who took the time to capture diagnostics, re-run templates, and report back — this release would have shipped with much weaker thresholds without that data.
Internal changes
RobotProfileStoregained three new self-calibrating subsystems (relocalisation baseline, estCap noise floor, drift sliding window), all following the same running-mean/Welford pattern already established for the existing coverage baseline.estcap_to_mah()extracted toconst.pyas shared logic betweensensor.pyandcallbacks.py(third call site — same reasoning as the existingactive_charge_cycles()extraction).FAN_SPEED_AUTOMATIC/ECO/PERFORMANCEconstants changed from Capital-Case to lowercase slugs to satisfy Home Assistant'stranslation_keyvalidation rules (hassfest). Bothselect.select_optionandvacuum.set_fan_speedaccept the old Capital-Case values too via case-insensitive matching — no automation changes required.- Three mop-related sensors (
mop_clean_mode,mop_tank_status,mop_ars_behavior) had the same Capital-Case state-key issue as the fan speed select above, caught by a second hassfest validation pass. All three now use lowercase underscore slugs (e.g."Dirty Pause + Dry + Wash"→"dirty_pause_dry_wash"). One additional bug found and fixed during this pass:mop_tank_statuswas missing a translation entry for its"unknown"state entirely, in all 7 languages — a pre-existing gap, now closed. New test coverage guards against the underlying class of bug (optionsarray,strings.json, and all 7 translation files silently drifting out of sync with each other). manifest.jsoncleaned up: removed two invalid fields that were never part of the schema, added thehttp(direct) andrecorder(optional) dependencies that were previously undeclared, removed an unrecognisedserviceskey (the services.yaml file is auto-discovered by Home Assistant via directory convention and needs no manifest entry).
Test suite
3027 tests, 0 failures (baseline: 2942 before this release).
Upgrade notes
No config entry migration — this release does not change the persisted schema. All new sensors and Repair Issues activate automatically; self-calibrating sensors will show Unknown/None until they've accumulated enough mission history (10–20 missions depending on the signal) to establish a personal baseline. That's expected — it's exactly the behaviour the self-calibration is designed to provide instead of guessing with insufficient data.