|
| 1 | +""" |
| 2 | +Read cycling speed and cadence data from a peripheral using the standard BLE |
| 3 | +Cycling Speed and Cadence (CSC) Service. |
| 4 | +Works with single sensor (e.g., Wahoo Blue SC) or sensor pair, such as Wahoo RPM |
| 5 | +""" |
| 6 | + |
| 7 | +import time |
| 8 | +from adafruit_clue import clue |
| 9 | +import adafruit_ble |
| 10 | +from adafruit_ble.advertising.standard import ProvideServicesAdvertisement |
| 11 | +from adafruit_ble.services.standard.device_info import DeviceInfoService |
| 12 | +from adafruit_ble_cycling_speed_and_cadence import CyclingSpeedAndCadenceService |
| 13 | + |
| 14 | +clue_data = clue.simple_text_display(title="Cycle Revs", title_scale=1, text_scale=3, num_lines=3) |
| 15 | + |
| 16 | +# PyLint can't find BLERadio for some reason so special case it here. |
| 17 | +ble = adafruit_ble.BLERadio() # pylint: disable=no-member |
| 18 | + |
| 19 | + |
| 20 | +while True: |
| 21 | + print("Scanning...") |
| 22 | + # Save advertisements, indexed by address |
| 23 | + advs = {} |
| 24 | + for adv in ble.start_scan(ProvideServicesAdvertisement, timeout=5): |
| 25 | + if CyclingSpeedAndCadenceService in adv.services: |
| 26 | + print("found a CyclingSpeedAndCadenceService advertisement") |
| 27 | + # Save advertisement. Overwrite duplicates from same address (device). |
| 28 | + advs[adv.address] = adv |
| 29 | + |
| 30 | + ble.stop_scan() |
| 31 | + print("Stopped scanning") |
| 32 | + if not advs: |
| 33 | + # Nothing found. Go back and keep looking. |
| 34 | + continue |
| 35 | + |
| 36 | + # Connect to all available CSC sensors. |
| 37 | + cyc_connections = [] |
| 38 | + for adv in advs.values(): |
| 39 | + cyc_connections.append(ble.connect(adv)) |
| 40 | + print("Connected", len(cyc_connections)) |
| 41 | + |
| 42 | + # Print out info about each sensors. |
| 43 | + for conn in cyc_connections: |
| 44 | + if conn.connected: |
| 45 | + if DeviceInfoService in conn: |
| 46 | + dis = conn[DeviceInfoService] |
| 47 | + try: |
| 48 | + manufacturer = dis.manufacturer |
| 49 | + except AttributeError: |
| 50 | + manufacturer = "(Manufacturer Not specified)" |
| 51 | + print("Device:", manufacturer) |
| 52 | + else: |
| 53 | + print("No device information") |
| 54 | + |
| 55 | + print("Waiting for data... (could be 10-20 seconds or more)") |
| 56 | + # Get CSC Service from each sensor. |
| 57 | + cyc_services = [] |
| 58 | + for conn in cyc_connections: |
| 59 | + cyc_services.append(conn[CyclingSpeedAndCadenceService]) |
| 60 | + # Read data from each sensor once a second. |
| 61 | + # Stop if we lose connection to all sensors. |
| 62 | + |
| 63 | + while True: |
| 64 | + still_connected = False |
| 65 | + wheel_revs = None |
| 66 | + crank_revs = None |
| 67 | + for conn, svc in zip(cyc_connections, cyc_services): |
| 68 | + if conn.connected: |
| 69 | + still_connected = True |
| 70 | + values = svc.measurement_values |
| 71 | + if values is not None: # add this |
| 72 | + if values.cumulative_wheel_revolutions: |
| 73 | + wheel_revs = values.cumulative_wheel_revolutions |
| 74 | + if values.cumulative_crank_revolutions: |
| 75 | + crank_revs = values.cumulative_crank_revolutions |
| 76 | + |
| 77 | + if not still_connected: |
| 78 | + break |
| 79 | + if wheel_revs: # might still be None |
| 80 | + print(wheel_revs) |
| 81 | + clue_data[0].text = "Wheel: {0:d}".format(wheel_revs) |
| 82 | + clue_data.show() |
| 83 | + if crank_revs: |
| 84 | + print(crank_revs) |
| 85 | + clue_data[2].text = "Crank: {0:d}".format(crank_revs) |
| 86 | + clue_data.show() |
| 87 | + time.sleep(0.1) |
0 commit comments