Skip to content

fix: keep active vacuum status from working_status telemetry - #63

Merged
sjmotew merged 1 commit into
sjmotew:masterfrom
Sean-StarLabs:sean/narwal-flow2-status
Aug 8, 2026
Merged

fix: keep active vacuum status from working_status telemetry#63
sjmotew merged 1 commit into
sjmotew:masterfrom
Sean-StarLabs:sean/narwal-flow2-status

Conversation

@Sean-StarLabs

@Sean-StarLabs Sean-StarLabs commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

What

Rebuilds the old Flow 2 status work as a focused fix for #73. Fresh status/working_status task metrics now keep the vacuum entity in an active state briefly, while unconfirmed stale robot_base_status dock/idle overlays only refresh battery/consumables instead of clobbering activity. Confirmed dock indicators still end the active state.

Also maps working_status=3 as an active cleaning state observed on newer Flow 2 firmware.

Why

#73 reports the vacuum entity freezing on its last base-status state, usually docked, while the robot is actually cleaning and other sensors continue updating. The activity path was effectively trusting robot_base_status over the live task metrics topic.

Validation

No live robot validation yet. Non-hardware checks only:

  • python -m compileall -q custom_components/narwal narwal_client tests
  • git diff --check
  • direct Python smoke assertions for model/client/coordinator stale-status handling

pytest is not installed in this checkout, so the focused unit files were added but not run here.

@greptile-apps greptile-apps Bot 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.

Your trial has ended. Reactivate Greptile to resume code reviews.

@Sean-StarLabs
Sean-StarLabs force-pushed the sean/narwal-flow2-status branch from d5b9730 to 3e551d4 Compare August 4, 2026 20:16

@greptile-apps greptile-apps Bot 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.

Your trial has ended. Reactivate Greptile to resume code reviews.

@Sean-StarLabs Sean-StarLabs changed the title narwal: Keep Flow 2 status fresh fix: keep active vacuum status from working_status telemetry Aug 4, 2026
sjmotew added a commit that referenced this pull request Aug 8, 2026
…ate (#73)

Refines the #63 fix. update_from_working_status treated the mere presence of
field 3 as proof of an active clean, so a working_status frame reporting
timeConsuming=0 would set working_status=CLEANING, clear the dock indicators
and show a parked robot as running for the 15s freshness window — the mirror
image of the bug #63 set out to fix.

Activity now requires a positive value: timeConsuming > 0 or coveredArea > 0.
Station-only frames and zeroed session counters no longer override base_status.

Also flags WorkingStatus.CLEANING_V2 (3) as UNCONFIRMED: it arrived with #63 on
"observed on newer Flow 2 firmware" with no capture, and PROTOCOL.md has no
entry for 3. Kept as active because #73's failure mode is showing docked during
a clean, but the uncertainty is now recorded at the definition.
@sjmotew
sjmotew merged commit fa2c649 into sjmotew:master Aug 8, 2026
@sjmotew

sjmotew commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Merged as fa2c649 — thank you. This is the right diagnosis for #73, and the two-topic split was exactly the thing to attack. Two maintainer-side changes you should know about.

1. Conflicts resolved here rather than sent back

#50, #62, #61 and #24 all landed ahead of this today, so client.py, const.py, coordinator.py and vacuum.py had all moved under you. Your structure was kept intact; the only real merge decision was preserving master's room-enumerating start() (from the #69 fix) alongside your client changes.

2. Activity now requires a positive counter (5a9e627)

As written, update_from_working_status set active_payload on the mere presence of field 3:

if "3" in decoded:
    try:
        self.cleaning_time = int(decoded["3"])
        active_payload = True   # also fires when cleaning_time == 0

So a working_status frame carrying timeConsuming=0 would set working_status=CLEANING, clear the dock indicators, and show a docked robot as cleaning for the full 15 s window — the mirror image of the bug this fixes. Your test_working_status_station_timers_do_not_mark_cleaning covers the field-13-only case but not a zeroed field 3.

It now requires timeConsuming > 0 or coveredArea > 0, with a test. Everything else about the approach is unchanged.

One open ask: CLEANING_V2 = 3

I kept it, but marked it UNCONFIRMED at the definition — there's no capture attached and docs/PROTOCOL.md has no entry for 3. If you have the log or capture where you observed it, I'll record it in PROTOCOL.md and drop the caveat.

Not scepticism about your work specifically: this repo has been burned by exactly this before. #48's room-type ordering was merged, reverted, and only relanded once @jgus supplied a blutter object-pool dump. There's also a long-standing unmapped "self test paused" status in the notes, which is the kind of thing 3 could turn out to be.

Validation

#73 stays open until a reporter confirms on affected hardware — I listened to my own Flow (AX12, v01.08.03.07) for 150 s docked and robot_base_status arrived every ~1.5 s the whole time, so the freeze doesn't reproduce here. Asked @Duqino and @romedtino on #73.

sjmotew added a commit that referenced this pull request Aug 8, 2026
)

Root cause of the frozen vacuum state, found on hardware during a live room
clean rather than inferred.

The robot only broadcasts status/working_status and display_map while an
active_robot_publish subscription is live, and that subscription lasts 600 s.
It was sent once at setup and never renewed. Once it expired the robot went
quiet on both topics while continuing to flood status/robot_base_status, so
the vacuum entity kept deriving its state from base_status alone, sat at
"docked" while the robot was audibly cleaning, and the live map stopped
moving. cleaning_area and cleaning_time never populated at all.

Measured on a Flow (AX12, v01.08.03.07) mid-clean. Subscription expired:
423 base_status / 1 working_status / 1 display_map. Immediately after
re-subscribing: 211 / 30 / 30, and the entity went to cleaning, room=Pantry,
area=2.58 m2, elapsed=312 s within seconds.

It was also a deadlock. The only renewal path was _resub_topics, reached from
the display_map dropout recovery, which is gated on is_cleaning — and
is_cleaning cannot become true without working_status. So the one thing that
could have recovered the subscription required the subscription.

The poll loop now renews unconditionally after TOPIC_RESUBSCRIBE_AFTER (240 s,
well inside the 600 s TTL), independent of believed cleaning state.

This supersedes the mechanism assumed by #63: that fix reads fresh
working_status telemetry to override a stale docked base_status, but on this
firmware there was no working_status telemetry to read. Both changes are
complementary — this one keeps the telemetry flowing, #63 interprets it.
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.

2 participants