TL;DR
Some mower commands do not send a notification back. The raw API has no way to say “write this packet and finish.” Setting expect_cmd to null instead means “wait for the first notification of any kind,” so the call either times out or returns an unrelated packet.
Problem
The low-level request method supports write_only=True, but async_send_raw_json() never exposes or enables it.
Relevant code:
The reverse-engineering material records commands, including schedule writes, where no immediate application-level acknowledgement was observed.
Why it happens
Two separate concepts are represented by one nullable field:
- no command filter: accept any response;
- no response expected: finish after the GATT write.
The current implementation uses None only for the first meaning. A user reasonably trying "expect_cmd": null for a no-ACK command gets the opposite behavior: pyGrouw waits for traffic.
Current behavior
For a raw command that sends no notification:
- the GATT write succeeds;
- pyGrouw waits up to the notification timeout;
- the mower may already have applied the command;
- the API raises
GrouwBleTimeout.
If an unrelated notification arrives first, it is returned as the command response because expected_cmd is None accepts any parsed message.
The caller cannot distinguish “write succeeded, no response expected” from “write outcome unknown.”
Expected behavior
The raw schema should represent response policy explicitly, for example:
{
"hex": "...",
"response_mode": "write_only"
}
Supported modes could be:
write_only: return after a successful GATT write;
any: return the first valid parsed notification;
command: wait for a specified response command;
status_follow_up: write the payload, issue a status query, then wait for status.
expect_cmd: null should not ambiguously mean both “anything” and “nothing.”
Impact
Protocol validation becomes misleading: an applied command is reported as failed, encouraging users to resend it. On a mower moving near a Bluetooth range boundary, the timeout also holds the request lock and delays normal commands while waiting for a response that will never exist.
Suggested direction
Expose the existing write_only capability through a validated raw-request model and return structured transport information, such as write_completed=True and response=None.
Keep raw/debug behavior explicit and avoid guessing response policy from protocol prefix alone.
Acceptance criteria
- A raw write-only request completes after the GATT write without waiting for a notification.
any response remains available as a separate explicit mode.
- A write-only failure before completion raises a GATT/connection error.
- A cancelled or disconnected post-write operation reports an indeterminate outcome rather than claiming the command was not sent.
- Tests cover no notification, an unrelated notification, a specified command response, and follow-up status mode.
- Home Assistant's raw service can select the response policy explicitly.
TL;DR
Some mower commands do not send a notification back. The raw API has no way to say “write this packet and finish.” Setting
expect_cmdtonullinstead means “wait for the first notification of any kind,” so the call either times out or returns an unrelated packet.Problem
The low-level request method supports
write_only=True, butasync_send_raw_json()never exposes or enables it.Relevant code:
async_request_daye()supports a realwrite_onlymodewrite_onlyis trueexpected_cmd=Nonemeans accept the first parsed notificationasync_send_raw_json()mapsexpect_cmdbut never passeswrite_onlyThe reverse-engineering material records commands, including schedule writes, where no immediate application-level acknowledgement was observed.
Why it happens
Two separate concepts are represented by one nullable field:
The current implementation uses
Noneonly for the first meaning. A user reasonably trying"expect_cmd": nullfor a no-ACK command gets the opposite behavior: pyGrouw waits for traffic.Current behavior
For a raw command that sends no notification:
GrouwBleTimeout.If an unrelated notification arrives first, it is returned as the command response because
expected_cmd is Noneaccepts any parsed message.The caller cannot distinguish “write succeeded, no response expected” from “write outcome unknown.”
Expected behavior
The raw schema should represent response policy explicitly, for example:
{ "hex": "...", "response_mode": "write_only" }Supported modes could be:
write_only: return after a successful GATT write;any: return the first valid parsed notification;command: wait for a specified response command;status_follow_up: write the payload, issue a status query, then wait for status.expect_cmd: nullshould not ambiguously mean both “anything” and “nothing.”Impact
Protocol validation becomes misleading: an applied command is reported as failed, encouraging users to resend it. On a mower moving near a Bluetooth range boundary, the timeout also holds the request lock and delays normal commands while waiting for a response that will never exist.
Suggested direction
Expose the existing
write_onlycapability through a validated raw-request model and return structured transport information, such aswrite_completed=Trueandresponse=None.Keep raw/debug behavior explicit and avoid guessing response policy from protocol prefix alone.
Acceptance criteria
any responseremains available as a separate explicit mode.