walkingpad-controller 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,51 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ id-token: write
9
+
10
+ jobs:
11
+ build:
12
+ name: Build distribution
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Set up Python
18
+ uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.12"
21
+
22
+ - name: Install build tools
23
+ run: pip install build
24
+
25
+ - name: Build package
26
+ run: python -m build
27
+
28
+ - name: Upload artifacts
29
+ uses: actions/upload-artifact@v4
30
+ with:
31
+ name: dist
32
+ path: dist/
33
+
34
+ publish-pypi:
35
+ name: Publish to PyPI
36
+ needs: build
37
+ runs-on: ubuntu-latest
38
+ environment:
39
+ name: pypi
40
+ url: https://pypi.org/p/walkingpad-controller
41
+ permissions:
42
+ id-token: write
43
+ steps:
44
+ - name: Download artifacts
45
+ uses: actions/download-artifact@v4
46
+ with:
47
+ name: dist
48
+ path: dist/
49
+
50
+ - name: Publish to PyPI
51
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ *.egg
6
+ dist/
7
+ build/
8
+ .eggs/
9
+ *.so
10
+ .venv/
11
+ venv/
12
+ .env
13
+ .tox/
14
+ .mypy_cache/
15
+ .pytest_cache/
16
+ .ruff_cache/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 mcdax
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,184 @@
1
+ Metadata-Version: 2.4
2
+ Name: walkingpad-controller
3
+ Version: 0.1.0
4
+ Summary: Python library for controlling KingSmith WalkingPad treadmills over BLE (FTMS and legacy WiLink protocols)
5
+ Project-URL: Homepage, https://github.com/mcdax/walkingpad-controller
6
+ Project-URL: Repository, https://github.com/mcdax/walkingpad-controller
7
+ Project-URL: Issues, https://github.com/mcdax/walkingpad-controller/issues
8
+ Author: mcdax
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: ble,bluetooth,ftms,kingsmith,treadmill,walkingpad
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Home Automation
20
+ Classifier: Topic :: Software Development :: Libraries
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: bleak>=0.20.0
23
+ Provides-Extra: all
24
+ Requires-Dist: ph4-walkingpad>=1.0.0; extra == 'all'
25
+ Provides-Extra: wilink
26
+ Requires-Dist: ph4-walkingpad>=1.0.0; extra == 'wilink'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # walkingpad-controller
30
+
31
+ Python library for controlling KingSmith WalkingPad treadmills over Bluetooth Low Energy (BLE).
32
+
33
+ Supports both **FTMS** (Fitness Machine Service) and legacy **WiLink** protocols behind a unified API. Protocol is auto-detected based on the BLE device name and advertised services.
34
+
35
+ ## Features
36
+
37
+ - **Unified API** — single `WalkingPadController` class for all device types
38
+ - **Auto protocol detection** — FTMS for newer KS-HD-* devices, WiLink for older models
39
+ - **Real-time status** — speed, distance, duration, calories, steps via BLE notifications
40
+ - **Cold-start handling** — retry logic for KingSmith FTMS devices that need START_OR_RESUME before accepting speed commands
41
+ - **Reconnect recovery** — pending target speed is automatically re-applied after BLE reconnection
42
+ - **KingSmith extensions** — step counter via proprietary FTMS extension (bit 13)
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ pip install walkingpad-controller
48
+ ```
49
+
50
+ For legacy WiLink device support (older WalkingPad models):
51
+
52
+ ```bash
53
+ pip install walkingpad-controller[wilink]
54
+ ```
55
+
56
+ ## Quick Start
57
+
58
+ ```python
59
+ import asyncio
60
+ from bleak import BleakScanner
61
+ from walkingpad_controller import WalkingPadController
62
+
63
+ async def main():
64
+ # Find your treadmill
65
+ device = await BleakScanner.find_device_by_name("KS-HD-Z1D")
66
+
67
+ # Create controller (protocol auto-detected from BLE name)
68
+ controller = WalkingPadController(ble_device=device)
69
+
70
+ # Connect
71
+ await controller.connect()
72
+ print(f"Protocol: {controller.protocol.value}")
73
+ print(f"Speed range: {controller.min_speed}-{controller.max_speed} km/h")
74
+
75
+ # Start at 3.0 km/h
76
+ await controller.start(target_speed=3.0)
77
+
78
+ # Read status
79
+ print(f"Speed: {controller.status.speed} km/h")
80
+ print(f"Steps: {controller.status.steps}")
81
+
82
+ # Stop and disconnect
83
+ await controller.stop()
84
+ await controller.disconnect()
85
+
86
+ asyncio.run(main())
87
+ ```
88
+
89
+ ## Status Callbacks
90
+
91
+ Register callbacks to receive real-time status updates:
92
+
93
+ ```python
94
+ from walkingpad_controller import WalkingPadController, TreadmillStatus
95
+
96
+ def on_status(status: TreadmillStatus):
97
+ print(f"Speed: {status.speed} km/h, Distance: {status.distance}m, "
98
+ f"Duration: {status.duration}s, Calories: {status.calories}, "
99
+ f"Steps: {status.steps}")
100
+
101
+ controller = WalkingPadController(ble_device=device)
102
+ controller.register_status_callback(on_status)
103
+ controller.register_disconnect_callback(lambda: print("Disconnected!"))
104
+ await controller.connect()
105
+ ```
106
+
107
+ ## API Reference
108
+
109
+ ### WalkingPadController
110
+
111
+ The main entry point. Auto-detects protocol and delegates to the appropriate backend.
112
+
113
+ | Property / Method | Description |
114
+ |---|---|
115
+ | `protocol` | Detected protocol (`ProtocolType.FTMS` or `ProtocolType.WILINK`) |
116
+ | `connected` | Whether the device is currently connected |
117
+ | `status` | Current `TreadmillStatus` |
118
+ | `min_speed` / `max_speed` | Speed range in km/h (read from device for FTMS) |
119
+ | `speed_increment` | Speed step size in km/h |
120
+ | `connect()` | Connect and auto-detect protocol |
121
+ | `disconnect()` | Disconnect from the device |
122
+ | `start(target_speed=None)` | Start the belt, optionally at a target speed |
123
+ | `stop()` | Stop the belt |
124
+ | `set_speed(speed_kmh)` | Set speed (starts belt if stopped) |
125
+ | `switch_mode(mode)` | Switch operating mode (WiLink: auto/manual/standby) |
126
+ | `register_status_callback(cb)` | Register a `TreadmillStatus` callback |
127
+ | `register_disconnect_callback(cb)` | Register a disconnect callback |
128
+ | `update_ble_device(device)` | Update BLE device reference after rediscovery |
129
+
130
+ ### TreadmillStatus
131
+
132
+ Dataclass with real-time treadmill data:
133
+
134
+ | Field | Type | Description |
135
+ |---|---|---|
136
+ | `belt_state` | `int` | 0=stopped, 1=active, 5=standby, 9=starting |
137
+ | `speed` | `float` | Current speed in km/h |
138
+ | `mode` | `int` | Operating mode (0=auto, 1=manual, 2=standby) |
139
+ | `distance` | `int` | Total distance in meters |
140
+ | `duration` | `int` | Elapsed time in seconds |
141
+ | `steps` | `int` | Step count (FTMS KingSmith extension) |
142
+ | `calories` | `int` | Total energy in kcal |
143
+ | `calories_per_hour` | `int` | Energy rate |
144
+ | `heart_rate` | `int` | Heart rate in bpm (if available) |
145
+ | `timestamp` | `float` | Unix timestamp of last update |
146
+
147
+ ### Protocol-Specific Controllers
148
+
149
+ For advanced use, you can use the protocol controllers directly:
150
+
151
+ - **`FTMSController`** — FTMS protocol (newer KS-HD-* devices)
152
+ - **`WiLinkController`** — Legacy WiLink protocol (older WalkingPad models, requires `[wilink]` extra)
153
+
154
+ ## Supported Devices
155
+
156
+ ### FTMS Protocol (tested)
157
+ - KingSmith KS-Z1D (BLE name: `KS-HD-Z1D`)
158
+ - Other KingSmith devices with BLE names starting with `KS-HD-`
159
+
160
+ ### WiLink Protocol (via ph4-walkingpad)
161
+ - WalkingPad A1, A1 Pro
162
+ - WalkingPad C1, C2
163
+ - Other models supported by [ph4-walkingpad](https://github.com/niclasku/ph4-walkingpad)
164
+
165
+ ## Known Behavior
166
+
167
+ ### FTMS Cold Start
168
+ KingSmith FTMS devices require a `START_OR_RESUME` command before the belt will accept speed commands. After a cold start, there is a delay of several seconds before `SET_TARGET_SPEED` takes effect. The library handles this automatically with retry logic.
169
+
170
+ ### BLE Connection Drops
171
+ KingSmith FTMS devices may drop the BLE connection shortly after a cold start, especially at weaker signal strength. The library stores the pending target speed and can re-apply it after reconnection via the status callback mechanism.
172
+
173
+ ### Connection Exclusivity
174
+ Only one BLE client can connect to the treadmill at a time. If Home Assistant holds the connection, the KS Fit app cannot connect, and vice versa.
175
+
176
+ ## Requirements
177
+
178
+ - Python 3.10+
179
+ - [bleak](https://github.com/hbldh/bleak) >= 0.20.0
180
+ - [ph4-walkingpad](https://github.com/niclasku/ph4-walkingpad) >= 1.0.0 (optional, for WiLink devices)
181
+
182
+ ## License
183
+
184
+ MIT
@@ -0,0 +1,156 @@
1
+ # walkingpad-controller
2
+
3
+ Python library for controlling KingSmith WalkingPad treadmills over Bluetooth Low Energy (BLE).
4
+
5
+ Supports both **FTMS** (Fitness Machine Service) and legacy **WiLink** protocols behind a unified API. Protocol is auto-detected based on the BLE device name and advertised services.
6
+
7
+ ## Features
8
+
9
+ - **Unified API** — single `WalkingPadController` class for all device types
10
+ - **Auto protocol detection** — FTMS for newer KS-HD-* devices, WiLink for older models
11
+ - **Real-time status** — speed, distance, duration, calories, steps via BLE notifications
12
+ - **Cold-start handling** — retry logic for KingSmith FTMS devices that need START_OR_RESUME before accepting speed commands
13
+ - **Reconnect recovery** — pending target speed is automatically re-applied after BLE reconnection
14
+ - **KingSmith extensions** — step counter via proprietary FTMS extension (bit 13)
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pip install walkingpad-controller
20
+ ```
21
+
22
+ For legacy WiLink device support (older WalkingPad models):
23
+
24
+ ```bash
25
+ pip install walkingpad-controller[wilink]
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```python
31
+ import asyncio
32
+ from bleak import BleakScanner
33
+ from walkingpad_controller import WalkingPadController
34
+
35
+ async def main():
36
+ # Find your treadmill
37
+ device = await BleakScanner.find_device_by_name("KS-HD-Z1D")
38
+
39
+ # Create controller (protocol auto-detected from BLE name)
40
+ controller = WalkingPadController(ble_device=device)
41
+
42
+ # Connect
43
+ await controller.connect()
44
+ print(f"Protocol: {controller.protocol.value}")
45
+ print(f"Speed range: {controller.min_speed}-{controller.max_speed} km/h")
46
+
47
+ # Start at 3.0 km/h
48
+ await controller.start(target_speed=3.0)
49
+
50
+ # Read status
51
+ print(f"Speed: {controller.status.speed} km/h")
52
+ print(f"Steps: {controller.status.steps}")
53
+
54
+ # Stop and disconnect
55
+ await controller.stop()
56
+ await controller.disconnect()
57
+
58
+ asyncio.run(main())
59
+ ```
60
+
61
+ ## Status Callbacks
62
+
63
+ Register callbacks to receive real-time status updates:
64
+
65
+ ```python
66
+ from walkingpad_controller import WalkingPadController, TreadmillStatus
67
+
68
+ def on_status(status: TreadmillStatus):
69
+ print(f"Speed: {status.speed} km/h, Distance: {status.distance}m, "
70
+ f"Duration: {status.duration}s, Calories: {status.calories}, "
71
+ f"Steps: {status.steps}")
72
+
73
+ controller = WalkingPadController(ble_device=device)
74
+ controller.register_status_callback(on_status)
75
+ controller.register_disconnect_callback(lambda: print("Disconnected!"))
76
+ await controller.connect()
77
+ ```
78
+
79
+ ## API Reference
80
+
81
+ ### WalkingPadController
82
+
83
+ The main entry point. Auto-detects protocol and delegates to the appropriate backend.
84
+
85
+ | Property / Method | Description |
86
+ |---|---|
87
+ | `protocol` | Detected protocol (`ProtocolType.FTMS` or `ProtocolType.WILINK`) |
88
+ | `connected` | Whether the device is currently connected |
89
+ | `status` | Current `TreadmillStatus` |
90
+ | `min_speed` / `max_speed` | Speed range in km/h (read from device for FTMS) |
91
+ | `speed_increment` | Speed step size in km/h |
92
+ | `connect()` | Connect and auto-detect protocol |
93
+ | `disconnect()` | Disconnect from the device |
94
+ | `start(target_speed=None)` | Start the belt, optionally at a target speed |
95
+ | `stop()` | Stop the belt |
96
+ | `set_speed(speed_kmh)` | Set speed (starts belt if stopped) |
97
+ | `switch_mode(mode)` | Switch operating mode (WiLink: auto/manual/standby) |
98
+ | `register_status_callback(cb)` | Register a `TreadmillStatus` callback |
99
+ | `register_disconnect_callback(cb)` | Register a disconnect callback |
100
+ | `update_ble_device(device)` | Update BLE device reference after rediscovery |
101
+
102
+ ### TreadmillStatus
103
+
104
+ Dataclass with real-time treadmill data:
105
+
106
+ | Field | Type | Description |
107
+ |---|---|---|
108
+ | `belt_state` | `int` | 0=stopped, 1=active, 5=standby, 9=starting |
109
+ | `speed` | `float` | Current speed in km/h |
110
+ | `mode` | `int` | Operating mode (0=auto, 1=manual, 2=standby) |
111
+ | `distance` | `int` | Total distance in meters |
112
+ | `duration` | `int` | Elapsed time in seconds |
113
+ | `steps` | `int` | Step count (FTMS KingSmith extension) |
114
+ | `calories` | `int` | Total energy in kcal |
115
+ | `calories_per_hour` | `int` | Energy rate |
116
+ | `heart_rate` | `int` | Heart rate in bpm (if available) |
117
+ | `timestamp` | `float` | Unix timestamp of last update |
118
+
119
+ ### Protocol-Specific Controllers
120
+
121
+ For advanced use, you can use the protocol controllers directly:
122
+
123
+ - **`FTMSController`** — FTMS protocol (newer KS-HD-* devices)
124
+ - **`WiLinkController`** — Legacy WiLink protocol (older WalkingPad models, requires `[wilink]` extra)
125
+
126
+ ## Supported Devices
127
+
128
+ ### FTMS Protocol (tested)
129
+ - KingSmith KS-Z1D (BLE name: `KS-HD-Z1D`)
130
+ - Other KingSmith devices with BLE names starting with `KS-HD-`
131
+
132
+ ### WiLink Protocol (via ph4-walkingpad)
133
+ - WalkingPad A1, A1 Pro
134
+ - WalkingPad C1, C2
135
+ - Other models supported by [ph4-walkingpad](https://github.com/niclasku/ph4-walkingpad)
136
+
137
+ ## Known Behavior
138
+
139
+ ### FTMS Cold Start
140
+ KingSmith FTMS devices require a `START_OR_RESUME` command before the belt will accept speed commands. After a cold start, there is a delay of several seconds before `SET_TARGET_SPEED` takes effect. The library handles this automatically with retry logic.
141
+
142
+ ### BLE Connection Drops
143
+ KingSmith FTMS devices may drop the BLE connection shortly after a cold start, especially at weaker signal strength. The library stores the pending target speed and can re-apply it after reconnection via the status callback mechanism.
144
+
145
+ ### Connection Exclusivity
146
+ Only one BLE client can connect to the treadmill at a time. If Home Assistant holds the connection, the KS Fit app cannot connect, and vice versa.
147
+
148
+ ## Requirements
149
+
150
+ - Python 3.10+
151
+ - [bleak](https://github.com/hbldh/bleak) >= 0.20.0
152
+ - [ph4-walkingpad](https://github.com/niclasku/ph4-walkingpad) >= 1.0.0 (optional, for WiLink devices)
153
+
154
+ ## License
155
+
156
+ MIT
@@ -0,0 +1,45 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "walkingpad-controller"
7
+ version = "0.1.0"
8
+ description = "Python library for controlling KingSmith WalkingPad treadmills over BLE (FTMS and legacy WiLink protocols)"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "mcdax" },
14
+ ]
15
+ keywords = ["walkingpad", "kingsmith", "treadmill", "bluetooth", "ble", "ftms"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Topic :: Home Automation",
25
+ "Topic :: Software Development :: Libraries",
26
+ ]
27
+ dependencies = [
28
+ "bleak>=0.20.0",
29
+ ]
30
+
31
+ [project.optional-dependencies]
32
+ wilink = [
33
+ "ph4-walkingpad>=1.0.0",
34
+ ]
35
+ all = [
36
+ "walkingpad-controller[wilink]",
37
+ ]
38
+
39
+ [project.urls]
40
+ Homepage = "https://github.com/mcdax/walkingpad-controller"
41
+ Repository = "https://github.com/mcdax/walkingpad-controller"
42
+ Issues = "https://github.com/mcdax/walkingpad-controller/issues"
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["src/walkingpad_controller"]
@@ -0,0 +1,57 @@
1
+ """walkingpad-controller — Python library for controlling WalkingPad treadmills over BLE.
2
+
3
+ Supports both FTMS (Fitness Machine Service) and legacy WiLink protocols.
4
+ Protocol is auto-detected based on the BLE device name and services.
5
+
6
+ Quick start:
7
+
8
+ from bleak import BleakScanner
9
+ from walkingpad_controller import WalkingPadController
10
+
11
+ device = await BleakScanner.find_device_by_name("KS-HD-Z1D")
12
+ controller = WalkingPadController(ble_device=device)
13
+ await controller.connect()
14
+ await controller.start(target_speed=3.0)
15
+ print(controller.status)
16
+ await controller.stop()
17
+ await controller.disconnect()
18
+ """
19
+
20
+ from .const import (
21
+ FTMS_NAME_PREFIXES,
22
+ FTMS_SERVICE_UUID,
23
+ WILINK_SERVICE_UUID,
24
+ BeltState,
25
+ FTMSOpcode,
26
+ FTMSResultCode,
27
+ OperatingMode,
28
+ ProtocolType,
29
+ )
30
+ from .controller import WalkingPadController
31
+ from .ftms import FTMSController
32
+ from .models import DeviceCapabilities, SpeedRange, TreadmillStatus
33
+ from .wilink import WiLinkController
34
+
35
+ __version__ = "0.1.0"
36
+
37
+ __all__ = [
38
+ # Main controller
39
+ "WalkingPadController",
40
+ # Protocol-specific controllers
41
+ "FTMSController",
42
+ "WiLinkController",
43
+ # Data models
44
+ "TreadmillStatus",
45
+ "SpeedRange",
46
+ "DeviceCapabilities",
47
+ # Enums
48
+ "BeltState",
49
+ "OperatingMode",
50
+ "ProtocolType",
51
+ "FTMSOpcode",
52
+ "FTMSResultCode",
53
+ # Constants
54
+ "FTMS_SERVICE_UUID",
55
+ "WILINK_SERVICE_UUID",
56
+ "FTMS_NAME_PREFIXES",
57
+ ]
@@ -0,0 +1,130 @@
1
+ """Constants, enums, and BLE UUIDs for WalkingPad treadmill control."""
2
+
3
+ from enum import Enum, IntEnum, unique
4
+
5
+
6
+ # --- BLE UUIDs ---
7
+
8
+ # Standard FTMS Service
9
+ FTMS_SERVICE_UUID = "00001826-0000-1000-8000-00805f9b34fb"
10
+
11
+ # FTMS Characteristics
12
+ FTMS_FEATURE_UUID = "00002acc-0000-1000-8000-00805f9b34fb"
13
+ TREADMILL_DATA_UUID = "00002acd-0000-1000-8000-00805f9b34fb"
14
+ TRAINING_STATUS_UUID = "00002ad3-0000-1000-8000-00805f9b34fb"
15
+ SUPPORTED_SPEED_RANGE_UUID = "00002ad4-0000-1000-8000-00805f9b34fb"
16
+ SUPPORTED_INCLINATION_RANGE_UUID = "00002ad5-0000-1000-8000-00805f9b34fb"
17
+ FITNESS_MACHINE_STATUS_UUID = "00002ada-0000-1000-8000-00805f9b34fb"
18
+ FTMS_CONTROL_POINT_UUID = "00002ad9-0000-1000-8000-00805f9b34fb"
19
+
20
+ # Custom KingSmith Supplement Service
21
+ SUPPLEMENT_SERVICE_UUID = "24e2521c-f63b-48ed-85be-c5330a00fdf7"
22
+ SUPPLEMENT_NOTIFY_UUID = "24e2521c-f63b-48ed-85be-c5330b00fdf7"
23
+ SUPPLEMENT_WRITE_UUID = "24e2521c-f63b-48ed-85be-c5330d00fdf7"
24
+
25
+ # Legacy WiLink Service (for older devices)
26
+ WILINK_SERVICE_UUID = "0000fe00-0000-1000-8000-00805f9b34fb"
27
+
28
+
29
+ # --- Enums ---
30
+
31
+
32
+ @unique
33
+ class ProtocolType(Enum):
34
+ """Supported BLE communication protocols."""
35
+
36
+ WILINK = "wilink" # Legacy protocol (service 0xFE00, ph4-walkingpad)
37
+ FTMS = "ftms" # Standard FTMS (service 0x1826)
38
+ UNKNOWN = "unknown"
39
+
40
+
41
+ @unique
42
+ class BeltState(IntEnum):
43
+ """Belt states."""
44
+
45
+ STOPPED = 0
46
+ ACTIVE = 1
47
+ STANDBY = 5
48
+ STARTING = 9
49
+ UNKNOWN = 1000
50
+
51
+
52
+ @unique
53
+ class OperatingMode(Enum):
54
+ """Treadmill operating modes."""
55
+
56
+ AUTO = 0 # Belt starts/stops on foot detection
57
+ MANUAL = 1 # Speed set via commands
58
+ STANDBY = 2 # Belt off
59
+
60
+
61
+ # --- FTMS Protocol Constants ---
62
+
63
+
64
+ @unique
65
+ class FTMSOpcode(IntEnum):
66
+ """FTMS Control Point opcodes (Bluetooth SIG standard)."""
67
+
68
+ REQUEST_CONTROL = 0x00
69
+ RESET = 0x01
70
+ SET_TARGET_SPEED = 0x02 # param: UINT16 in 0.01 km/h
71
+ SET_TARGET_INCLINATION = 0x03 # param: INT16 in 0.1%
72
+ START_OR_RESUME = 0x07
73
+ STOP_OR_PAUSE = 0x08 # param: UINT8 (0x01=Stop, 0x02=Pause)
74
+ RESPONSE_CODE = 0x80
75
+
76
+
77
+ @unique
78
+ class FTMSResultCode(IntEnum):
79
+ """FTMS Control Point result codes."""
80
+
81
+ SUCCESS = 0x01
82
+ OPCODE_NOT_SUPPORTED = 0x02
83
+ INVALID_PARAMETER = 0x03
84
+ OPERATION_FAILED = 0x04
85
+ CONTROL_NOT_PERMITTED = 0x05
86
+
87
+
88
+ @unique
89
+ class FTMSStopPauseParam(IntEnum):
90
+ """Parameter for the Stop or Pause opcode."""
91
+
92
+ STOP = 0x01
93
+ PAUSE = 0x02
94
+
95
+
96
+ class TreadmillDataFlags:
97
+ """Bit flags for the FTMS Treadmill Data characteristic (0x2ACD).
98
+
99
+ Per the Bluetooth FTMS specification, the flags field is a 16-bit value.
100
+ If a bit is SET, the corresponding optional field is PRESENT in the data.
101
+ Instantaneous Speed is always present (mandatory field).
102
+
103
+ Bit 13 (0x2000) is a KingSmith-specific extension that carries 3 extra
104
+ bytes: a uint16 LE step count + 1 zero byte. The step counter is
105
+ pressure-sensor based -- it only increments when someone is walking.
106
+ """
107
+
108
+ MORE_DATA = 0x0001
109
+ AVERAGE_SPEED = 0x0002
110
+ TOTAL_DISTANCE = 0x0004
111
+ INCLINATION = 0x0008
112
+ ELEVATION_GAIN = 0x0010
113
+ INSTANTANEOUS_PACE = 0x0020
114
+ AVERAGE_PACE = 0x0040
115
+ EXPENDED_ENERGY = 0x0080
116
+ HEART_RATE = 0x0100
117
+ METABOLIC_EQUIVALENT = 0x0200
118
+ ELAPSED_TIME = 0x0400
119
+ REMAINING_TIME = 0x0800
120
+ FORCE_ON_BELT = 0x1000
121
+ KINGSMITH_EXTENSION = 0x2000
122
+
123
+
124
+ # BLE name prefixes known to use FTMS protocol.
125
+ # These devices have service 0x1826 but NOT 0xFE00.
126
+ FTMS_NAME_PREFIXES = ("KS-HD-",)
127
+
128
+ # Default connection parameters
129
+ MAX_CONNECT_RETRIES = 3
130
+ RETRY_DELAY_SECONDS = 2.0