Compare commits

..

No commits in common. "f55f7a039da74d9a84be76253aecaa0468a5115d" and "1fe1182ba37e55a84169a82931e3387ff1f0f3e6" have entirely different histories.

2 changed files with 41 additions and 65 deletions

View File

@ -7,24 +7,3 @@ Perhaps useful if you have a stationary bike of some kind and want to
put the vital statistics on a big screen instead of on your handlebar.
![screenshot](20221209_22h46m07s_grim.png)
## How to use
First you need to identify bluetooth address of your bike sensor(s).
Spin the wheel to wake it up, then run
```sh
$ bluetoothctl scan on
Discovery started
[CHG] Controller 24:FD:52:00:ED:F1 Discovering: yes
[NEW] Device C2:35:5D:F2:F4:0F Giant Combo
[CHG] Device 98:06:3A:15:B7:BA RSSI: -82
^C
$ bluetoothctl connect C2:35:5D:F2:F4:0F
```
Now you can start the app
```sh
$ python wobble.py C2:35:5D:F2:F4:0F
```

View File

@ -1,12 +1,11 @@
import BLE_GATT
from gi.repository import GLib
import pdb
import struct
import sys
import time
from datetime import datetime, timedelta
from datetime import datetime
import os
import pygame
@ -14,6 +13,8 @@ import pygame.freetype
from pygame.locals import *
class CadenceListener:
csc_feature = '00002a5c-0000-1000-8000-00805F9B34FB'
prevCtime = 0
prevWtime = 0
prevWrevs = 0
@ -21,8 +22,7 @@ class CadenceListener:
wheelSpeed = 0
crankSpeed = 0
crankSpeedMax = 120
elapsedTime = None
firstMessage = True
startTime = None
def getWheelSpeed(self):
return self.wheelSpeed
@ -35,13 +35,13 @@ class CadenceListener:
offset = offset + 6
if flags & 2:
crankRevolutions,crankTime = struct.unpack('<HH', bytes(value)[offset:offset+4])
if(self.firstMessage):
# print(wheelrevs, wheeltime, crankrevs, cranktime)
if(not self.startTime):
self.prevCtime = crankTime
self.prevWtime = wheelTime
self.prevCrevs = crankRevolutions
self.prevWrevs = wheelRevolutions
self.firstMessage = False
self.startTime = datetime.now()
return
# handle wraparound
@ -62,17 +62,16 @@ class CadenceListener:
self.prevCrevs = crankRevolutions
if(wheelTime > self.prevWtime):
millis = float(wheelTime - self.prevWtime)
self.rolling = True
revs = (wheelRevolutions - self.prevWrevs) / millis
revs = ((wheelRevolutions - self.prevWrevs) /
float(wheelTime - self.prevWtime))
self.wheelSpeed = revs * 2205 * 3600 / 1024.0
print("wheel", millis, self.wheelSpeed)
print("wheel",
(float(wheelTime - self.prevWtime)),
self.wheelSpeed)
self.prevWtime = wheelTime
self.prevWrevs = wheelRevolutions
self.elapsedTime = (self.elapsedTime or 0) + (millis / 1024.0)
class Wobble:
class Biscuit:
listener = CadenceListener()
def __init__(self):
@ -96,8 +95,8 @@ class Wobble:
(scale/16,scale + 20),
"{: 5.1f} rpm".format(self.listener.crankSpeed),
(0,255,0))
if self.listener.elapsedTime != None:
runTime = timedelta(seconds=self.listener.elapsedTime)
if self.listener.startTime != None:
runTime = datetime.now() - self.listener.startTime
timelabel = str(runTime)[0:9]
else:
timelabel = datetime.now().strftime("%H:%M:%S")
@ -112,43 +111,41 @@ class Wobble:
pygame.display.flip()
bike = BLE_GATT.Central(sys.argv[1])
bike_address = 'C2:35:5D:F2:F4:0F'
bike = BLE_GATT.Central(bike_address)
bike.connect()
app = Wobble()
app = Biscuit()
csc_measurement = '00002a5b-0000-1000-8000-00805F9B34FB'
bike.on_value_change(csc_measurement, app.listener.process)
running = True
def handle_pygame_event(event):
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYUP and event.key == pygame.K_q:
running = False
if event.type == pygame.KEYUP and event.key == pygame.K_SPACE:
if app.listener.startTime == None:
app.listener.startTime = datetime.now()
else:
app.listener.startTime = None
if event.type == pygame.VIDEORESIZE:
app.width = event.w
app.height = event.h
app.font = None
def on_timer():
handle_pygame_event(pygame.event.poll())
app.on_update()
return True
GLib.timeout_add(100, on_timer)
try:
# Time to go live
print("Listening for events...")
bike.mainloop.run()
context = bike.mainloop.get_context()
print("Listening for events...")
while running:
time.sleep(0.1)
context.iteration(False)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYUP and event.key == pygame.K_q:
running = False
if event.type == pygame.KEYUP and event.key == pygame.K_SPACE:
if app.listener.startTime == None:
app.listener.startTime = datetime.now()
else:
app.listener.startTime = None
if event.type == pygame.VIDEORESIZE:
app.width = event.w
app.height = event.h
app.font = None
app.on_update()
finally:
pygame.quit()