commit f55f7a039da74d9a84be76253aecaa0468a5115d
parent cd243353a99f49a26797654a2c611e875a9a30b9
Author: Daniel Barlow <dan@telent.net>
Date: Sun, 11 Dec 2022 11:22:33 +0000
rename file to wobble
Diffstat:
| M | README.md | | | 10 | +++++++--- |
| D | csc.py | | | 156 | ------------------------------------------------------------------------------- |
| A | wobble.py | | | 154 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 161 insertions(+), 159 deletions(-)
diff --git a/README.md b/README.md
@@ -20,7 +20,11 @@ Discovery started
[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
+$ bluetoothctl connect C2:35:5D:F2:F4:0F
```
-Now
-\ No newline at end of file
+Now you can start the app
+
+```sh
+$ python wobble.py C2:35:5D:F2:F4:0F
+```
+\ No newline at end of file
diff --git a/csc.py b/csc.py
@@ -1,156 +0,0 @@
-import BLE_GATT
-from gi.repository import GLib
-
-import pdb
-import struct
-
-import sys
-import time
-from datetime import datetime, timedelta
-import os
-
-import pygame
-import pygame.freetype
-from pygame.locals import *
-
-class CadenceListener:
- csc_feature = '00002a5c-0000-1000-8000-00805F9B34FB'
-
- prevCtime = 0
- prevWtime = 0
- prevWrevs = 0
- prevCrevs = 0
- wheelSpeed = 0
- crankSpeed = 0
- crankSpeedMax = 120
- elapsedTime = None
- firstMessage = True
-
- def getWheelSpeed(self):
- return self.wheelSpeed
-
- def process(self, value):
- flags = value[0]
- offset = 1
- if flags & 1:
- wheelRevolutions,wheelTime = struct.unpack('<IH', bytes(value)[offset:offset+6])
- offset = offset + 6
- if flags & 2:
- crankRevolutions,crankTime = struct.unpack('<HH', bytes(value)[offset:offset+4])
-
- if(self.firstMessage):
- self.prevCtime = crankTime
- self.prevWtime = wheelTime
- self.prevCrevs = crankRevolutions
- self.prevWrevs = wheelRevolutions
- self.firstMessage = False
- return
-
- # handle wraparound
- if(crankTime < self.prevCtime):
- self.prevCtime = self.prevCtime - 65536
- if(wheelTime < self.prevWtime):
- self.prevWtime = self.prevWtime - 65536
- if(crankRevolutions < self.prevCrevs):
- self.prevCrevs = self.prevCrevs - 65536
- if(wheelRevolutions < self.prevWrevs):
- self.prevWrevs = self.prevWrevs - 65536 * 65536
-
- if(crankTime > self.prevCtime):
- self.crankSpeed = 60 * 1024 * ((crankRevolutions - self.prevCrevs) /
- float(crankTime - self.prevCtime))
- print("crank", self.crankSpeed)
- self.prevCtime = crankTime
- self.prevCrevs = crankRevolutions
-
- if(wheelTime > self.prevWtime):
- millis = float(wheelTime - self.prevWtime)
- self.rolling = True
- revs = (wheelRevolutions - self.prevWrevs) / millis
-
- self.wheelSpeed = revs * 2205 * 3600 / 1024.0
- print("wheel", millis, self.wheelSpeed)
- self.prevWtime = wheelTime
- self.prevWrevs = wheelRevolutions
- self.elapsedTime = (self.elapsedTime or 0) + (millis / 1024.0)
-
-class Biscuit:
- listener = CadenceListener()
-
- def __init__(self):
- pygame.init()
- self.surface = pygame.display.set_mode((600,300), pygame.RESIZABLE)
- self.width = self.surface.get_width();
- self.height = self.surface.get_height();
- self.font = None
-
- def on_update(self):
- scale = int(min(self.width/7, (self.height-20)/3))
- if(self.font == None):
- self.font = pygame.freetype.Font(os.environ['FONT'], scale)
-
- self.surface.fill((10,20,10))
- self.font.render_to(self.surface,
- (scale/16,10),
- "{: 5.1f} km/h".format(self.listener.wheelSpeed),
- (0,255,0))
- self.font.render_to(self.surface,
- (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)
- timelabel = str(runTime)[0:9]
- else:
- timelabel = datetime.now().strftime("%H:%M:%S")
- self.font.render_to(self.surface,
- (scale, scale * 2 + 30),
- timelabel,
- (0,255,0))
- pix = self.width *((self.listener.crankSpeed-40)/ self.listener.crankSpeedMax)
- pix = max(pix, 0)
- pygame.draw.rect(self.surface, (180,0,0), pygame.Rect(0,self.height/2-60, pix, 50))
- pygame.draw.rect(self.surface, (0,0,180), pygame.Rect(pix,self.height/2-60, 20, 50))
- pygame.display.flip()
-
-
-bike = BLE_GATT.Central(sys.argv[1])
-bike.connect()
-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()
-
-finally:
- pygame.quit()
-
diff --git a/wobble.py b/wobble.py
@@ -0,0 +1,154 @@
+import BLE_GATT
+from gi.repository import GLib
+
+import pdb
+import struct
+
+import sys
+import time
+from datetime import datetime, timedelta
+import os
+
+import pygame
+import pygame.freetype
+from pygame.locals import *
+
+class CadenceListener:
+ prevCtime = 0
+ prevWtime = 0
+ prevWrevs = 0
+ prevCrevs = 0
+ wheelSpeed = 0
+ crankSpeed = 0
+ crankSpeedMax = 120
+ elapsedTime = None
+ firstMessage = True
+
+ def getWheelSpeed(self):
+ return self.wheelSpeed
+
+ def process(self, value):
+ flags = value[0]
+ offset = 1
+ if flags & 1:
+ wheelRevolutions,wheelTime = struct.unpack('<IH', bytes(value)[offset:offset+6])
+ offset = offset + 6
+ if flags & 2:
+ crankRevolutions,crankTime = struct.unpack('<HH', bytes(value)[offset:offset+4])
+
+ if(self.firstMessage):
+ self.prevCtime = crankTime
+ self.prevWtime = wheelTime
+ self.prevCrevs = crankRevolutions
+ self.prevWrevs = wheelRevolutions
+ self.firstMessage = False
+ return
+
+ # handle wraparound
+ if(crankTime < self.prevCtime):
+ self.prevCtime = self.prevCtime - 65536
+ if(wheelTime < self.prevWtime):
+ self.prevWtime = self.prevWtime - 65536
+ if(crankRevolutions < self.prevCrevs):
+ self.prevCrevs = self.prevCrevs - 65536
+ if(wheelRevolutions < self.prevWrevs):
+ self.prevWrevs = self.prevWrevs - 65536 * 65536
+
+ if(crankTime > self.prevCtime):
+ self.crankSpeed = 60 * 1024 * ((crankRevolutions - self.prevCrevs) /
+ float(crankTime - self.prevCtime))
+ print("crank", self.crankSpeed)
+ self.prevCtime = crankTime
+ self.prevCrevs = crankRevolutions
+
+ if(wheelTime > self.prevWtime):
+ millis = float(wheelTime - self.prevWtime)
+ self.rolling = True
+ revs = (wheelRevolutions - self.prevWrevs) / millis
+
+ self.wheelSpeed = revs * 2205 * 3600 / 1024.0
+ print("wheel", millis, self.wheelSpeed)
+ self.prevWtime = wheelTime
+ self.prevWrevs = wheelRevolutions
+ self.elapsedTime = (self.elapsedTime or 0) + (millis / 1024.0)
+
+class Wobble:
+ listener = CadenceListener()
+
+ def __init__(self):
+ pygame.init()
+ self.surface = pygame.display.set_mode((600,300), pygame.RESIZABLE)
+ self.width = self.surface.get_width();
+ self.height = self.surface.get_height();
+ self.font = None
+
+ def on_update(self):
+ scale = int(min(self.width/7, (self.height-20)/3))
+ if(self.font == None):
+ self.font = pygame.freetype.Font(os.environ['FONT'], scale)
+
+ self.surface.fill((10,20,10))
+ self.font.render_to(self.surface,
+ (scale/16,10),
+ "{: 5.1f} km/h".format(self.listener.wheelSpeed),
+ (0,255,0))
+ self.font.render_to(self.surface,
+ (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)
+ timelabel = str(runTime)[0:9]
+ else:
+ timelabel = datetime.now().strftime("%H:%M:%S")
+ self.font.render_to(self.surface,
+ (scale, scale * 2 + 30),
+ timelabel,
+ (0,255,0))
+ pix = self.width *((self.listener.crankSpeed-40)/ self.listener.crankSpeedMax)
+ pix = max(pix, 0)
+ pygame.draw.rect(self.surface, (180,0,0), pygame.Rect(0,self.height/2-60, pix, 50))
+ pygame.draw.rect(self.surface, (0,0,180), pygame.Rect(pix,self.height/2-60, 20, 50))
+ pygame.display.flip()
+
+
+bike = BLE_GATT.Central(sys.argv[1])
+bike.connect()
+app = Wobble()
+
+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()
+
+finally:
+ pygame.quit()
+