Skip to content

Mower-settings writes silently clear an unknown hardware setting when callers omit it #24

Description

@Bjorkan

TL;DR

Changing a known option such as rain mowing can also switch off another mower setting whose meaning is still unknown. This happens because the library defaults the unknown byte to false instead of preserving the value already stored in the mower.

Problem

The DYM mower-settings packet is a full replacement payload. Byte 6 is parsed as unknown_setting, but its exact meaning is not confirmed. The high-level write API nevertheless gives this field a default value of False and always writes it.

Relevant code:

Why it happens

The API presents the settings write like a partial update of known options, but the mower protocol requires a complete settings structure. A Python default is therefore not neutral: omitting the argument actively writes zero to byte 6.

The repository notes that this byte may represent ultrasound or another app-hidden setting. Until its meaning is known, forcing it off is unsafe.

Current behavior

A caller can run:

await client.async_set_mower_settings(
    mow_in_rain=True,
    boundary_cut=True,
    helix=False,
    rain_delay_hours=1,
    rain_delay_minutes=0,
)

Even though unknown_setting was not mentioned, the generated packet writes it as 0x00. If the mower previously returned 0x01, the operation silently changes that setting while the user intended to change only known fields.

Expected behavior

An unknown or omitted field must be preserved, not guessed.

Safe options include:

  1. require unknown_setting explicitly for the low-level complete-write API;
  2. provide a high-level read-modify-write method that first reads 0x89 and copies the existing byte;
  3. accept None to mean “preserve current value,” requiring a fresh settings read before writing;
  4. hide the field entirely from normal users until its meaning is confirmed.

If the read needed for preservation fails, the write should abort rather than default to zero.

Impact

A user changing rain delay, boundary cutting, or helix mode can unknowingly disable an unrelated mower feature. The effect may be difficult to reverse because the integration does not know what the byte controls.

This is especially risky when a weak Bluetooth link causes settings reads to fail but writes are retried later through another receiver.

Suggested direction

Split the APIs into explicit operations:

async_set_mower_settings_complete(..., unknown_setting: bool)
async_update_mower_settings(..., unknown_setting: bool | None = None)

The update form should read and preserve all unmodified confirmed and reserved fields before issuing the full replacement write.

Acceptance criteria

  • Omitting the unknown field never changes its current mower value.
  • A complete low-level write requires every transmitted field explicitly.
  • A partial high-level update performs a validated read-modify-write.
  • Failure to read the current unknown value prevents the write.
  • Tests start with unknown_setting=True, update only a known field, and verify that byte 6 remains 0x01.
  • The Home Assistant service no longer supplies False as a silent default.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions