Skip to content

Use Write Without Response on the control point when Write is not permitted - #72

Open
tun0 wants to merge 1 commit into
dudanov:mainfrom
tun0:control-point-write-without-response
Open

tun0 wants to merge 1 commit into
dudanov:mainfrom
tun0:control-point-write-without-response

Conversation

@tun0

@tun0 tun0 commented Sep 29, 2026

Copy link
Copy Markdown

MachineController.write_command() always writes the Fitness Machine Control Point with response=True. Some machines only permit Write Without Response on that characteristic. On those, every command fails, starting with the automatic Request Control:

bleak.exc.BleakError: Bluetooth GATT Error address=B8:E0:0C:64:60:E8 handle=39 error=3 description=Write not permitted

So on those machines you can read data but not change any setting (speed, inclination, start/stop).

Seen on a Moov Walk Plus treadmill. Its Fitness Machine Control Point:

handle=38  00002ad9-0000-1000-8000-00805f9b34fb  Fitness Machine Control Point  props=['write-without-response', 'indicate']

Writing Request Control (00) directly with bleak:

write 0x00 (response=True):  FAILED: GATT Protocol Error: Write Not Permitted
write 0x00 (response=False): accepted
indication: 80 00 01

The FTMS spec requires Write on the control point, so this treadmill is non-compliant. It still replies to every command with an indication, and write_command() already waits for that indication and checks its result code, so no confirmation is lost.

Change

Choose the write type from the characteristic's properties. Use Write when the control point has write (unchanged for compliant machines), otherwise use Write Without Response. I check the properties explicitly instead of passing response=None, because None only auto-selects from bleak 0.22 and pyproject.toml still allows bleak >= 0.21.

Testing

  • Existing tests pass (pytest: 19 passed).
  • Tested with the equivalent change on a Moov Walk Plus through Home Assistant (hassio-ftms, ESPHome Bluetooth proxy). Before, every speed/inclination change failed with the error above. After, Set Target Speed is acknowledged with SUCCESS (SetupEvent(... {'target_speed': 5.0}, event_source='callback')).

This branch has not been deployed

No deployments
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.

1 participant