--- title: Ampler eBike Bluetooth protocol authors: [michaelh] date: 2024-05-12 --- I have an [Ampler Stout][stout] eBike which exposes metrics as Bluetooth attributes over [GATT]. I'd like to track the battery level and odomoter, so spent some time and decoded some of the attributes. The bike exposes: | Characteristic | Example data | | ------------------------------------ | ------------------------------------------------------------------------------- | | 340d1528-a89e-4d4e-9078-06d21096ea36 | 0x5b 0x00 0x00 0x00 0x11 0x02 0x00 0x00 0x04 0x01 0x00 0x00 0x00 0x00 0x00 0x00 | | 340d1529-a89e-4d4e-9078-06d21096ea36 | 0x00 0x00 0x00 0x00 0xdf 0x14 0x00 0x00 0x9c 0x0a 0x90 0x00 | | 340d1530-a89e-4d4e-9078-06d21096ea36 | 0xa0 0x00 0x90 0x01 0x02 0x00 0x06 0x00 0x64 0x00 0xfa 0x00 | | 340d1536-a89e-4d4e-9078-06d21096ea36 | 0x01 | | 340d1538-a89e-4d4e-9078-06d21096ea36 | 0x00 | | 340d1542-a89e-4d4e-9078-06d21096ea36 | 0x58 0x02 | | 340d1544-a89e-4d4e-9078-06d21096ea36 | 0x00 | | 340d1545-a89e-4d4e-9078-06d21096ea36 | 0x0a 0x18 0xe2 0x64 | | 340d1547-a89e-4d4e-9078-06d21096ea36 | 0xff 0x02 0x11 0x00 0x00 0x00 0x03 0x00 | | 340d1548-a89e-4d4e-9078-06d21096ea36 | 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 | | 340d1549-a89e-4d4e-9078-06d21096ea36 | 0x00 0x00 0x00 0x00 | | 340d1550-a89e-4d4e-9078-06d21096ea36 | 0x33 | The format appears to pack related values into the same characteristic. Values are little endian and either half words or words. The units seem to be metric such as `m` for range and `m/s` for speed with a power of 10 multiplier, such as the voltage being in decivolts: | Characteristic | [Format] | Fields | | ------------------------------------ | -------- | --------------------------------------------- | | 340d1528-a89e-4d4e-9078-06d21096ea36 | HHhH | % charged, voltage (dV), temperature (dºC), ? | | 340d1529-a89e-4d4e-9078-06d21096ea36 | III | ?, speed (mm/s), odometer (dm) | | 340d1536-a89e-4d4e-9078-06d21096ea36 | B | assist level (0, 1, 2) | | 340d1538-a89e-4d4e-9078-06d21096ea36 | ? (bool) | light | | 340d1545-a89e-4d4e-9078-06d21096ea36 | I | ? increases over time 1692538885 | The time value isn't clear but might be a POSIX time, i.e. roughly Sunday, 20 August 2023. Decoding the example above gives: | Characteristic | Fields | | ------------------------------------ | ------------------------------------- | | 340d1528-a89e-4d4e-9078-06d21096ea36 | 91 % charged, 52.9 V, 26.0 ºC, 0 | | 340d1529-a89e-4d4e-9078-06d21096ea36 | 0, 5343 mm/s (19.2 km/h), 943.9900 km | | 340d1536-a89e-4d4e-9078-06d21096ea36 | assist level 1 | | 340d1538-a89e-4d4e-9078-06d21096ea36 | light off | Next step is to implement a decoder, export this to Home Assistant, and collect it via Prometheus. [format]: https://docs.python.org/3/library/struct.html#format-characters [gatt]: https://learn.adafruit.com/introduction-to-bluetooth-low-energy/gatt [stout]: https://amplerbikes.com/en-CH/e-bikes/stout