Skip to content
Open
Show file tree
Hide file tree
Changes from all 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