Repository navigation
SharkIQ MQTT: maps, room and spot cleaning, settings, live faults and model capabilities - #34
Open
andrew-from-toronto wants to merge 32 commits into
Conversation
added 23 commits
September 19, 2026 22:15
Live frames carry the occupancy grid, cleaned path and pose log; the persisted frame published on docking adds rooms, wall/door vectors, dock pose, job stats and the robot's event log. VacuumStatus gains job_active, deep_clean, recharge_resume and evac_resume. Captured RV2610BFCA frames are included as fixtures.
…pping start_cleaning and stop/go_home now send the bare job command; the previous payloads also set suction (normal on start, eco on dock). Mode 4 maps to idle.
The persisted map only arrives when the robot docks, but room and spot cleaning need its room definition at any time; storing it lets a caller clean rooms after a restart.
A distinct version lets Home Assistant tell this build from the PyPI 0.2.0 it may already have installed.
Creating an SSL context reads the certificate store, which Home Assistant reports as a blocking call when it happens on the first request inside the event loop. Built in the constructor, it runs wherever the caller constructs the client, which Home Assistant does in an executor.
Cell value 0x00 is floor covered by the job, not void: every point of the cleaned path lands on one in every captured frame. The persisted frame's field 11 counters (.3, .6) were read as duration and cleaned cells from a single capture, but a second job showed them almost unchanged (335 -> 306, 3947 -> 3978) while the robot's own log reported 101 s and 70 s of cleaning. VacuumMap.cleaned_area now counts cleaned cells and the new clean_time sums the log's DT_*_CLEAN_TIME entries; job_duration and cleaned_cells are removed.
After a Spot Clean the robot keeps the PinDrop square in its saved map, marked as the room the job cleaned (measured 2026-09-26). VacuumMap.spot returns it and named_rooms leaves it out; room and spot cleaning re-upload only the named rooms, so a stale zone is neither selectable nor sent back. spot_polygon(x, y) exposes the square a spot clean sends.
…state table - sharklocal.codes: the SysStateT, ErrorCodeT, WarningCodeT and dock-event names from the SharkClean app's protobuf schema - the same names the event log writes as strings. - VacuumStatus.errors / warnings: status fields 5 and 6, the codes active now (repeated, packed or not). - The sharkiq_v1 mode table now follows SysStateT: 13 is charging on the dock (docked, was docking - a robot back on its dock read as still docking until the battery was full), 4 is paused (was idle), and the error, waiting, spot, zone, redock and explore states are mapped. VacuumMode gains PAUSED and ERROR.
…nd settings - Status: charging now follows the system state (13 charging); field 9.1 is the Wi-Fi state, which reads 3 while the robot cleans and made charging read true mid-job. Device info (temperature, Wi-Fi state/link/signal, water and dust level, IP), live suction/brushroll/side-brush speeds, CleanEdge and carpet-detect status and the relocation state are decoded. Checked against the captured frames: the end-of-job frame's live warning (WARN_MM_LOWLIGHT) matches its own event log. - Commands from the app's schema: pause (USR_CTR_PAUSE; start resumes), edge clean (USR_CTR_ALONG_WALL) and explore over MQTT. - set_config writes one field of the settings block; set_toggle names the on/off settings (DnD, child lock, silent mode, CleanEdge, carpet boost, button sounds, underglow lights, continuous crosshatch, room by room), and reproduces the app's captured Recharge & Resume / Evac & Resume commands byte for byte. set_carpet_detect and set_volume write theirs. - codes gains the Wi-Fi, carpet-detect and relocation state names.
A port of the app's capability logic and its 611-model table (SharkClean 6.27.0): model string -> family -> classification, the prefix-letter and hex-bitmask hardware rules, and the exact RV3000 / OPP / spot-lidar / 360EZ / ODM / MPP lists. Features are three-valued, None when the model is missing from the table, because the robot does not report its cloud model locally and retail SKUs are not cloud model strings.
Every model in the app's table falls into one of seven types (lidar, lidar_carpet, rv3000, spot_lidar, map, air, basic); Capabilities(type, self_empty_dock, clean_edge) answers the gated features as booleans, and a test checks that for all 611 models the type plus its two extras matches the per-model rules exactly - so a user can configure a robot without knowing its cloud model string.
Status frames can carry the robot's event log mid-job (field 34, repeated PbDiagnoseInfo, JSON in its field 5), not only at the end with the persisted map. VacuumStatus.log_entries holds them; vacuum_map.parse_log_json is the shared parser. Fixture: a real frame from a spot clean.
Charging comes from the system state (the old footnote read the Wi-Fi state), state 13 is charging on the dock and 4 is paused, and the report now covers what was verified since: warnings, temperature, motor speeds, firmware versions, mid-job log entries, room/Matrix/spot cleaning runs and the saved PinDrop zone. Commands sent but not yet run on the robot are marked as untested.
Author
|
I have some forked changes for the sharkiq_local_unofficial repo that I will open a PR for once this hopefully merges. Here's an example of what this PR enables!
|
added 4 commits
September 27, 2026 10:41
Only a refused connection became ConnectError, so a robot that dropped packets instead (aiohttp ConnectionTimeoutError, seen at the nightly network restart) escaped raw: the MQTT fallback never ran and Home Assistant failed the config entry for good instead of retrying it. Every aiohttp connection error and a bare timeout now count as unreachable.
PbInput field 39 = 1 (FloorControlT FL_CTR_LOAD_ALL) makes a docked robot publish its persisted map within a second: floor type 4, carrying the last job's path and summary but not the event log or the top-level report flag. That recovers a job whose end-of-job frame was missed, e.g. while Home Assistant was restarting. VacuumMap.persisted now also covers floor type 4, VacuumMap.report marks the end-of-job frame, job_minutes comes from the summary (PbMapSummary.currentCleanTime) and backs clean_time when there is no log, and a requested map never replaces the report of the same job. Fixture: the real reply after a whole-home job. SIG_EXT_REQ_ALL_MAP (field 29 = 33) was tried too and draws no reply.
andrew-from-toronto
force-pushed
the
feature/map-rooms-and-settings
branch
from
September 27, 2026 15:17
2b9f5e2 to
b14e4b7
Compare
added 4 commits
September 27, 2026 11:47
The four call sites imported aiomqtt on first use, and inside Home Assistant that first use is the monitor starting in the event loop, which HA flags as a blocking call (the import reads the package from disk). It is imported once when the module loads, still optional: without it the MQTT calls raise the same ConnectError. Also asyncio.iscoroutinefunction -> inspect.iscoroutinefunction, deprecated for removal in Python 3.16.
Each job opens with a 78-byte live frame whose grid has no resolution, size or cells (captured on a Matrix clean, 2026-09-27). It decoded as a 0x0 map at resolution 0, and Home Assistant's renderer divided by it: every picture request failed with a 500 until the next real frame. has_map and decode_map now need a grid with cells, size and resolution. Fixture: that frame.
This branch has not been deployed
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.

Disclosure: This is tool assisted with Claude. Fully tested against my personal Shark RV2610BFCA
Summary
Brings the library's
sharkiq_v1MQTT support much closer to what the SharkClean app can do, entirely over the local network. Everything here was captured from and checked on an RV2610BFCA (Matrix Plus, firmware V6.6.10-P7.N3308.17.0), including real cleaning runs.What the library can do now
Maps
Cleaning
Settings
Status
Model capabilities
Improvements and fixes
Notes
Tests
Captured frames are included as fixtures.
pytest --cov=sharklocal: 1056 passed, 99% coverage.