Skip to content

Commit

Permalink
Watch OS 10 CSC Bluetooth Data for Bike (Issue #1924)
Browse files Browse the repository at this point in the history
  • Loading branch information
cagnulein committed Dec 29, 2023
1 parent 7f6e6e2 commit 93779d0
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 3 deletions.
49 changes: 48 additions & 1 deletion src/characteristicnotifier2a63.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,57 @@ int CharacteristicNotifier2A63::notify(QByteArray &value) {
normalizeWattage = 0;

if (Bike->deviceType() == bluetoothdevice::BIKE) {
value.append((char)0x20); // crank data present
/*
// set measurement
measurement[2] = power & 0xFF;
measurement[3] = (power >> 8) & 0xFF;
measurement[4] = wheelrev & 0xFF;
measurement[5] = (wheelrev >> 8) & 0xFF;
measurement[6] = (wheelrev >> 16) & 0xFF;
measurement[7] = (wheelrev >> 24) & 0xFF;
measurement[8] = lastwheel & 0xFF;
measurement[9] = (lastwheel >> 8) & 0xFF;
measurement[10] = crankrev & 0xFF;
measurement[11] = (crankrev >> 8) & 0xFF;
measurement[12] = lastcrank & 0xFF;
measurement[13] = (lastcrank >> 8) & 0xFF;
// speed & distance
// NOTE : based on Apple Watch default wheel dimension 700c x 2.5mm
// NOTE : 3 is theoretical crank:wheel gear ratio
// NOTE : 2.13 is circumference of 700c in meters
wheelCount = crankCount * 3;
speed = cadence * 3 * 2.13 * 60 / 1000;
distance = wheelCount * 2.13 / 1000;
#if defined(USEPOWER)
lastWheelK = lastCrankK * 2; // 1/2048 s granularity
#else
lastWheelK = lastCrankK * 1; // 1/1024 s granularity
#endif
*/

uint32_t wheelCount = (uint32_t)Bike->currentCrankRevolutions() * 3;
uint16_t lastWheelK = Bike->lastCrankEventTime() * 2;

value.append((char)0x30); // crank data present and wheel for apple watch
value.append((char)0x00);
value.append((char)(((uint16_t)normalizeWattage) & 0xFF)); // watt
value.append((char)(((uint16_t)normalizeWattage) >> 8) & 0xFF); // watt

value.append((char)(((uint32_t)wheelCount) & 0xFF)); // revs count
value.append((char)(((uint32_t)wheelCount) >> 8) & 0xFF); // revs count
value.append((char)(((uint32_t)wheelCount) >> 16) & 0xFF); // revs count
value.append((char)(((uint32_t)wheelCount) >> 24) & 0xFF); // revs count
value.append((char)(lastWheelK & 0xff)); // eventtime
value.append((char)(lastWheelK >> 8) & 0xFF); // eventtime

value.append((char)(((uint16_t)Bike->currentCrankRevolutions()) & 0xFF)); // revs count
value.append((char)(((uint16_t)Bike->currentCrankRevolutions()) >> 8) & 0xFF); // revs count
value.append((char)(Bike->lastCrankEventTime() & 0xff)); // eventtime
Expand Down
6 changes: 6 additions & 0 deletions src/fakebike.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ void fakebike::update() {
if (requestPower != -1) {
// bepo70: don't know if this conversion is really needed, i would do it anyway.
m_watt = (double)requestPower;
Cadence = requestPower;
emit debug(QStringLiteral("writing power ") + QString::number(requestPower));
requestPower = -1;
// bepo70: Disregard the current inclination for calculating speed. When the video
Expand All @@ -60,6 +61,11 @@ void fakebike::update() {
m_watt.value(), 0, Speed.value(), fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0),
speedLimit());
}

if (Cadence.value() > 0) {
CrankRevs++;
LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0));
}

if (requestInclination != -100) {
Inclination = requestInclination;
Expand Down
47 changes: 45 additions & 2 deletions src/ios/virtualbike_zwift.swift
Original file line number Diff line number Diff line change
Expand Up @@ -372,9 +372,52 @@ class BLEPeripheralManagerZwift: NSObject, CBPeripheralManagerDelegate {
}

func calculatePower() -> Data {
let flags:UInt8 = 0x20
let flags:UInt8 = 0x30

/*
// set measurement
measurement[2] = power & 0xFF;
measurement[3] = (power >> 8) & 0xFF;

measurement[4] = wheelrev & 0xFF;
measurement[5] = (wheelrev >> 8) & 0xFF;
measurement[6] = (wheelrev >> 16) & 0xFF;
measurement[7] = (wheelrev >> 24) & 0xFF;

measurement[8] = lastwheel & 0xFF;
measurement[9] = (lastwheel >> 8) & 0xFF;

measurement[10] = crankrev & 0xFF;
measurement[11] = (crankrev >> 8) & 0xFF;

measurement[12] = lastcrank & 0xFF;
measurement[13] = (lastcrank >> 8) & 0xFF;

// speed & distance
// NOTE : based on Apple Watch default wheel dimension 700c x 2.5mm
// NOTE : 3 is theoretical crank:wheel gear ratio
// NOTE : 2.13 is circumference of 700c in meters

wheelCount = crankCount * 3;
speed = cadence * 3 * 2.13 * 60 / 1000;
distance = wheelCount * 2.13 / 1000;

#if defined(USEPOWER)
lastWheelK = lastCrankK * 2; // 1/2048 s granularity
#else
lastWheelK = lastCrankK * 1; // 1/1024 s granularity
#endif

*/

//self.delegate?.BLEPeripheralManagerCSCDidSendValue(flags, crankRevolutions: self.crankRevolutions, lastCrankEventTime: self.lastCrankEventTime)
var power: [UInt8] = [flags, 0x00, (UInt8)(self.CurrentWatt & 0xFF), (UInt8)((self.CurrentWatt >> 8) & 0xFF), (UInt8)(crankRevolutions & 0xFF), (UInt8)((crankRevolutions >> 8) & 0xFF), (UInt8)(lastCrankEventTime & 0xFF), (UInt8)((lastCrankEventTime >> 8) & 0xFF)]
let wheelrev: UInt32 = ((UInt32)(crankRevolutions)) * 3;
let lastWheel: UInt16 = (UInt16)((((UInt32)(lastCrankEventTime)) * 2) & 0xFFFF);
var power: [UInt8] = [flags, 0x00, (UInt8)(self.CurrentWatt & 0xFF), (UInt8)((self.CurrentWatt >> 8) & 0xFF),
(UInt8)(wheelrev & 0xFF), (UInt8)((wheelrev >> 8) & 0xFF), (UInt8)((wheelrev >> 16) & 0xFF), (UInt8)((wheelrev >> 24) & 0xFF),
(UInt8)(lastWheel & 0xFF), (UInt8)((lastWheel >> 8) & 0xFF),
(UInt8)(crankRevolutions & 0xFF), (UInt8)((crankRevolutions >> 8) & 0xFF),
(UInt8)(lastCrankEventTime & 0xFF), (UInt8)((lastCrankEventTime >> 8) & 0xFF)]
let powerData = Data(bytes: &power, count: MemoryLayout.size(ofValue: power))
return powerData
}
Expand Down

0 comments on commit 93779d0

Please sign in to comment.