Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ C/Users/
dependencies.lock
.vscode/settings.json
*.map
graphify-out/
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,8 @@
"idf.pythonInstallPath": "C:\\Users\\anthony\\.espressif\\tools\\idf-python\\3.11.2\\python.exe",
"idf.flashType": "UART",
"liveServer.settings.port": 5501,
"clangd.arguments": [
"--compile-commands-dir=d:/git/SmartSpin2k/.cache/clangd",
"--query-driver=C:/Users/emadm/.platformio/packages/toolchain-*/bin/*,C:/Users/emadm/.platformio/packages/tool-*/bin/*"
],
}
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Hardware


## [26.5.27]

### Added

### Changed

### Hardware


## [26.5.4]

### Added
Expand Down
2 changes: 1 addition & 1 deletion dependencies.lock
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,6 @@ direct_dependencies:
- espressif/network_provisioning
- idf
- joltwallet/littlefs
manifest_hash: df9baa925ebc2a028ee0e349be53f2169bb7ac38b2cb9c63b3ebf69123c43ef8
manifest_hash: e7ce7a886dfdb3cc5cd59acbdb4ff333c0a91c6e4de55b9fd6323d866c7cc691
target: esp32
version: 2.0.0
1 change: 1 addition & 0 deletions include/BLE_Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const std::vector<BLEServiceInfo> SUPPORTED_SERVICES = {{CYCLINGPOWERSERVICE_UUI
{HEARTSERVICE_UUID, HEARTCHARACTERISTIC_UUID, "Heart Rate Service"},
{ECHELON_DEVICE_UUID, ECHELON_SERVICE_UUID, "Echelon Device"}, // Two lines for Echelon
{ECHELON_SERVICE_UUID, ECHELON_DATA_UUID, "Echelon Service"}, // Because one is for search, the other for data
{CHRONO_SERVICE_UUID, CHRONO_DATA_UUID, "Spinner Chrono"},
{FITNESSMACHINESERVICE_UUID, FITNESSMACHINEINDOORBIKEDATA_UUID, "Fitness Machine Service"},
{HID_SERVICE_UUID, HID_REPORT_DATA_UUID, "HID Service"},
{FLYWHEEL_UART_SERVICE_UUID, FLYWHEEL_UART_TX_UUID, "Flywheel UART Service"}};
Expand Down
5 changes: 5 additions & 0 deletions lib/SS2K/include/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@
#define ECHELON_WRITE_UUID NimBLEUUID("0bf669f2-45f2-11e7-9598-0800200c9a66")
#define ECHELON_DATA_UUID NimBLEUUID("0bf669f4-45f2-11e7-9598-0800200c9a66")

// Spinning / Precor Spinner Chrono Power (proprietary, no standard CPS/CSC)
#define CHRONO_SERVICE_UUID NimBLEUUID("a026ee07-0a7d-4ab3-97fa-f1500f9feb8b")
#define CHRONO_DATA_UUID NimBLEUUID("a026e01d-0a7d-4ab3-97fa-f1500f9feb8b")
#define CHRONO_BLE_NAME "CHRONO" // device advertises "CHRONO <n>"

// Dummy UUID for Peloton Serial Data Interface
#define PELOTON_DATA_UUID NimBLEUUID("00000000-0000-0000-0000-000000000321")
#define PELOTON_ADDRESS NimBLEAddress("00:00:00:00:00:00", 0)
Expand Down
32 changes: 32 additions & 0 deletions lib/SS2K/include/sensors/ChronoData.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2020 Anthony Doud & Joel Baranick
* All rights reserved
*
* SPDX-License-Identifier: GPL-2.0-only
*/

#pragma once

#include "SensorData.h"

class ChronoData : public SensorData {
public:
ChronoData() : SensorData("CHRO") {}

bool hasHeartRate();
bool hasCadence();
bool hasPower();
bool hasSpeed();
bool hasResistance();
int getHeartRate();
float getCadence();
int getPower();
float getSpeed();
int getResistance();
void decode(uint8_t *data, size_t length);

private:
bool hasData = false;
float cadence = nanf("");
int power = INT_MIN;
};
42 changes: 42 additions & 0 deletions lib/SS2K/src/sensors/ChronoData.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2020 Anthony Doud & Joel Baranick
* All rights reserved
*
* SPDX-License-Identifier: GPL-2.0-only
*/

#include "endian.h"
#include "sensors/ChronoData.h"

bool ChronoData::hasHeartRate() { return false; }

bool ChronoData::hasCadence() { return this->hasData; }

bool ChronoData::hasPower() { return this->hasData; }

bool ChronoData::hasSpeed() { return false; }

bool ChronoData::hasResistance() { return false; }

int ChronoData::getHeartRate() { return INT_MIN; }

float ChronoData::getCadence() { return this->cadence; }

int ChronoData::getPower() { return this->power; }

float ChronoData::getSpeed() { return nanf(""); }

int ChronoData::getResistance() { return INT_MIN; }

void ChronoData::decode(uint8_t *data, size_t length) {
// Validate the fixed 19-byte telemetry packet with its magic header 0x53 0x59 0x16.
if (length < 19 || data[0] != 0x53 || data[1] != 0x59 || data[2] != 0x16) {
hasData = false;
cadence = nanf("");
power = INT_MIN;
return;
}
cadence = get_le16(&data[8]) / 10.0f; // bytes 8-9, uint16 little-endian, ÷10 RPM
power = get_le16(&data[17]); // bytes 17-18, uint16 little-endian, watts
hasData = true;
}
3 changes: 3 additions & 0 deletions lib/SS2K/src/sensors/SensorDataFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "sensors/EchelonData.h"
#include "sensors/PelotonData.h"
#include "sensors/CscSensorData.h"
#include "sensors/ChronoData.h"

std::shared_ptr<SensorData> SensorDataFactory::getSensorData(const NimBLEUUID characteristicUUID, std::string& uniqueName, uint8_t *data, size_t length) {
for (auto &it : SensorDataFactory::knownDevices) {
Expand All @@ -34,6 +35,8 @@ std::shared_ptr<SensorData> SensorDataFactory::getSensorData(const NimBLEUUID ch
sensorData = std::shared_ptr<SensorData>(new FlywheelData());
} else if (characteristicUUID == ECHELON_DATA_UUID) {
sensorData = std::shared_ptr<SensorData>(new EchelonData());
} else if (characteristicUUID == CHRONO_DATA_UUID) {
sensorData = std::shared_ptr<SensorData>(new ChronoData());
} else if (characteristicUUID == PELOTON_DATA_UUID) {
sensorData = std::shared_ptr<SensorData>(new PelotonData());
} else if (characteristicUUID == CSCMEASUREMENT_UUID) {
Expand Down
5 changes: 3 additions & 2 deletions src/BLE_Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,8 @@ void MyClientCallback::onDisconnect(NimBLEClient* pClient, int reason) {
SS2K_LOG(BLE_CLIENT_LOG_TAG, "Detected %s Disconnect", spinBLEClient.myBLEDevices[i].serviceUUID.toString().c_str());
if ((spinBLEClient.myBLEDevices[i].charUUID == CYCLINGPOWERMEASUREMENT_UUID) || (spinBLEClient.myBLEDevices[i].charUUID == FITNESSMACHINEINDOORBIKEDATA_UUID) ||
(spinBLEClient.myBLEDevices[i].charUUID == FLYWHEEL_UART_RX_UUID) || (spinBLEClient.myBLEDevices[i].charUUID == ECHELON_SERVICE_UUID) ||
(spinBLEClient.myBLEDevices[i].charUUID == CYCLINGPOWERSERVICE_UUID) || (spinBLEClient.myBLEDevices[i].charUUID == CSCSERVICE_UUID)) {
(spinBLEClient.myBLEDevices[i].charUUID == CHRONO_DATA_UUID) || (spinBLEClient.myBLEDevices[i].charUUID == CYCLINGPOWERSERVICE_UUID) ||
(spinBLEClient.myBLEDevices[i].charUUID == CSCSERVICE_UUID)) {
SS2K_LOG(BLE_CLIENT_LOG_TAG, "Deregistered PM on Disconnect");
}
if ((spinBLEClient.myBLEDevices[i].charUUID == HEARTCHARACTERISTIC_UUID)) {
Expand Down Expand Up @@ -1094,7 +1095,7 @@ void SpinBLEAdvertisedDevice::set(const NimBLEAdvertisedDevice* device, int id,
SS2K_LOG(BLE_CLIENT_LOG_TAG, "Registered CSC on Connect");
} else if (serviceUUID == CYCLINGPOWERSERVICE_UUID || serviceUUID == FITNESSMACHINESERVICE_UUID ||
(serviceUUID == FLYWHEEL_UART_SERVICE_UUID && this->uniqueName.find("Flywheel") != std::string::npos) || serviceUUID == ECHELON_DEVICE_UUID ||
serviceUUID == PELOTON_DATA_UUID) {
serviceUUID == CHRONO_SERVICE_UUID || serviceUUID == PELOTON_DATA_UUID) {
this->isPM = true;
spinBLEClient.connectedPM = true;
SS2K_LOG(BLE_CLIENT_LOG_TAG, "Registered PM on Connect");
Expand Down
Loading