wobble

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit f55f7a039da74d9a84be76253aecaa0468a5115d
parent cd243353a99f49a26797654a2c611e875a9a30b9
Author: Daniel Barlow <dan@telent.net>
Date:   Sun, 11 Dec 2022 11:22:33 +0000

rename file to wobble

Diffstat:
MREADME.md | 10+++++++---
Dcsc.py | 156-------------------------------------------------------------------------------
Awobble.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() +