From 66f5364e7ac32070287e62011dcc667cb2e31a48 Mon Sep 17 00:00:00 2001 From: doudar Date: Wed, 17 Mar 2021 14:49:19 -0500 Subject: [PATCH 01/10] Initial Echelon Incorporation --- include/BLE_Common.h | 9 ++++++ include/sensors/EchelonData.h | 25 +++++++++++++++ include/sensors/SensorDataFactory.h | 1 + src/BLE_Client.cpp | 45 ++++++++++++++++++-------- src/sensors/EchelonData.cpp | 49 +++++++++++++++++++++++++++++ src/sensors/SensorDataFactory.cpp | 5 +++ 6 files changed, 121 insertions(+), 13 deletions(-) create mode 100644 include/sensors/EchelonData.h create mode 100644 src/sensors/EchelonData.cpp diff --git a/include/BLE_Common.h b/include/BLE_Common.h index 061b3bf0..05fc634d 100644 --- a/include/BLE_Common.h +++ b/include/BLE_Common.h @@ -41,6 +41,15 @@ #define FLYWHEEL_UART_RX_UUID BLEUUID((uint16_t)0xCA9E) #define FLYWHEEL_UART_TX_UUID BLEUUID((uint16_t)0xCA9E) +// The Echelon Services +//#define ECHELON_device_UUID BLEUUID("0bf669f0-45f2-11e7-9598-0800200c9a66"); //not used by SS2K currently +#define ECHELON_SERVICE_UUID BLEUUID("0bf669f1-45f2-11e7-9598-0800200c9a66") +#define ECHELON_WRITE_UUID BLEUUID("0bf669f2-45f2-11e7-9598-0800200c9a66") +#define ECHELON_DATA_UUID BLEUUID("0bf669f4-45f2-11e7-9598-0800200c9a66") +//#define ECHELON_SERVICE_UUID BLEUUID((uint16_t)0x69f1) // convert to these once this service works +//#define ECHELON_WRITE_UUID BLEUUID((uint16_t)0x69f2) +//#define ECHELON_DATA_UUID BLEUUID((uint16_t)0x69f4) + // macros to convert different types of bytes into int The naming here sucks and should be fixed. #define bytes_to_s16(MSB, LSB) (((signed int)((signed char)MSB))) << 8 | (((signed char)LSB)) #define bytes_to_u16(MSB, LSB) (((signed int)((signed char)MSB))) << 8 | (((unsigned char)LSB)) diff --git a/include/sensors/EchelonData.h b/include/sensors/EchelonData.h new file mode 100644 index 00000000..173c47d5 --- /dev/null +++ b/include/sensors/EchelonData.h @@ -0,0 +1,25 @@ +#pragma once + +#include "SensorData.h" + +class EchelonData : public SensorData +{ +public: + EchelonData() : SensorData("ECH"){}; + + bool hasHeartRate(); + bool hasCadence(); + bool hasPower(); + bool hasSpeed(); + int getHeartRate(); + float getCadence(); + int getPower(); + float getSpeed(); + void decode(uint8_t *data, size_t length); + +private: + bool hasData = false; + float cadence; + int power; + int resistance; +}; \ No newline at end of file diff --git a/include/sensors/SensorDataFactory.h b/include/sensors/SensorDataFactory.h index 8ae14912..5362de7c 100644 --- a/include/sensors/SensorDataFactory.h +++ b/include/sensors/SensorDataFactory.h @@ -8,6 +8,7 @@ #include "FlywheelData.h" #include "FitnessMachineIndoorBikeData.h" #include "HeartRateData.h" +#include "EchelonData.h" class SensorDataFactory { diff --git a/src/BLE_Client.cpp b/src/BLE_Client.cpp index 2dbeebb7..9884e9fb 100644 --- a/src/BLE_Client.cpp +++ b/src/BLE_Client.cpp @@ -122,6 +122,12 @@ bool SpinBLEClient::connectToServer() charUUID = FITNESSMACHINEINDOORBIKEDATA_UUID; debugDirector("trying to connect to Fitness machine service"); } + else if (myDevice->isAdvertisingService(ECHELON_SERVICE_UUID)) + { + serviceUUID = ECHELON_SERVICE_UUID; + charUUID = ECHELON_DATA_UUID; + debugDirector("trying to connect to Fitness machine service"); + } else if (myDevice->isAdvertisingService(HEARTSERVICE_UUID)) { serviceUUID = HEARTSERVICE_UUID; @@ -200,7 +206,7 @@ bool SpinBLEClient::connectToServer() } if (pRemoteCharacteristic->canNotify()) - { + { debugDirector("Found " + String(pRemoteCharacteristic->getUUID().toString().c_str()) + " on reconnect."); reconnectTries = MAX_RECONNECT_TRIES; //VV Is this really needed? Shouldn't it just carry over from the previous connection? VV @@ -313,7 +319,7 @@ bool SpinBLEClient::connectToServer() void SpinBLEClient::MyClientCallback::onConnect(NimBLEClient *pClient) { - //debugDirector("Connect Called"); This callback happens so early for us it's nearly useless. + //debugDirector("Connect Called"); This callback happens so early for us it's nearly useless. } void SpinBLEClient::MyClientCallback::onDisconnect(NimBLEClient *pclient) @@ -340,7 +346,7 @@ void SpinBLEClient::MyClientCallback::onDisconnect(NimBLEClient *pclient) //spinBLEClient.myBLEDevices[i].connectedClientID = BLE_HS_CONN_HANDLE_NONE; debugDirector("Detected " + String(spinBLEClient.myBLEDevices[i].serviceUUID.toString().c_str()) + " Disconnect"); spinBLEClient.myBLEDevices[i].doConnect = true; - if ((spinBLEClient.myBLEDevices[i].charUUID == CYCLINGPOWERMEASUREMENT_UUID) || (spinBLEClient.myBLEDevices[i].charUUID == FITNESSMACHINEINDOORBIKEDATA_UUID) || (spinBLEClient.myBLEDevices[i].charUUID == FLYWHEEL_UART_RX_UUID)) + 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)) { debugDirector("Deregistered PM on Disconnect"); @@ -394,7 +400,7 @@ void SpinBLEClient::MyAdvertisedDeviceCallback::onResult(BLEAdvertisedDevice *ad { aDevName = ""; } - if ((advertisedDevice->haveServiceUUID()) && (advertisedDevice->isAdvertisingService(CYCLINGPOWERSERVICE_UUID) || advertisedDevice->isAdvertisingService(FLYWHEEL_UART_SERVICE_UUID) || advertisedDevice->isAdvertisingService(FITNESSMACHINESERVICE_UUID) || advertisedDevice->isAdvertisingService(HEARTSERVICE_UUID))) + if ((advertisedDevice->haveServiceUUID()) && (advertisedDevice->isAdvertisingService(CYCLINGPOWERSERVICE_UUID) || advertisedDevice->isAdvertisingService(FLYWHEEL_UART_SERVICE_UUID) || advertisedDevice->isAdvertisingService(FITNESSMACHINESERVICE_UUID) || advertisedDevice->isAdvertisingService(HEARTSERVICE_UUID) || advertisedDevice->isAdvertisingService(ECHELON_SERVICE_UUID))) { //if ((aDevName == c_PM) || (advertisedDevice->getAddress().toString().c_str() == c_PM) || (aDevName == c_HR) || (advertisedDevice->getAddress().toString().c_str() == c_HR) || (String(c_PM) == ("any")) || (String(c_HR) == ("any"))) //{ //notice the subtle difference vv getServiceUUID(int) returns the index of the service in the list or the 0 slot if not specified. @@ -410,7 +416,8 @@ void SpinBLEClient::MyAdvertisedDeviceCallback::onResult(BLEAdvertisedDevice *ad { debugDirector("Skipping non-selected HRM |" + aDevName + "|" + String(userConfig.getconnectedHeartMonitor())); return; - }else if (aDevName == String(userConfig.getconnectedHeartMonitor())) + } + else if (aDevName == String(userConfig.getconnectedHeartMonitor())) { debugDirector("HR String Matched " + aDevName); } @@ -426,7 +433,8 @@ void SpinBLEClient::MyAdvertisedDeviceCallback::onResult(BLEAdvertisedDevice *ad { debugDirector("Skipping non-selected PM |" + aDevName + "|" + String(userConfig.getconnectedPowerMeter())); return; - }else if (aDevName == String(userConfig.getconnectedPowerMeter())) + } + else if (aDevName == String(userConfig.getconnectedPowerMeter())) { debugDirector("PM String Matched " + aDevName); } @@ -468,7 +476,7 @@ void SpinBLEClient::scanProcess() for (int i = 0; i < count; i++) { BLEAdvertisedDevice d = foundDevices.getDevice(i); - if (d.isAdvertisingService(CYCLINGPOWERSERVICE_UUID) || d.isAdvertisingService(HEARTSERVICE_UUID) || d.isAdvertisingService(FLYWHEEL_UART_SERVICE_UUID) || d.isAdvertisingService(FITNESSMACHINESERVICE_UUID)) + if (d.isAdvertisingService(CYCLINGPOWERSERVICE_UUID) || d.isAdvertisingService(HEARTSERVICE_UUID) || d.isAdvertisingService(FLYWHEEL_UART_SERVICE_UUID) || d.isAdvertisingService(FITNESSMACHINESERVICE_UUID) || d.isAdvertisingService(ECHELON_SERVICE_UUID)) { device = "device " + String(i); devices[device]["address"] = d.getAddress().toString(); @@ -566,14 +574,29 @@ void SpinBLEClient::resetDevices() void SpinBLEClient::postConnect(NimBLEClient *pClient) { - for (size_t i = 0; i < NUM_BLE_DEVICES; i++) + for (size_t i = 0; i < NUM_BLE_DEVICES; i++) { if (pClient->getPeerAddress() == this->myBLEDevices[i].peerAddress) { - if ((this->myBLEDevices[i].charUUID == CYCLINGPOWERMEASUREMENT_UUID) || (this->myBLEDevices[i].charUUID == FITNESSMACHINEINDOORBIKEDATA_UUID) || (this->myBLEDevices[i].charUUID == FLYWHEEL_UART_RX_UUID)) + if ((this->myBLEDevices[i].charUUID == CYCLINGPOWERMEASUREMENT_UUID) || (this->myBLEDevices[i].charUUID == FITNESSMACHINEINDOORBIKEDATA_UUID) || (this->myBLEDevices[i].charUUID == FLYWHEEL_UART_RX_UUID)|| (this->myBLEDevices[i].charUUID == ECHELON_DATA_UUID)) { this->connectedPM = true; debugDirector("Registered PM on Connect"); + if (this->myBLEDevices[i].charUUID == ECHELON_DATA_UUID) + { + NimBLERemoteCharacteristic *writeCharacteristic = pClient->getService(ECHELON_SERVICE_UUID)->getCharacteristic(ECHELON_WRITE_UUID); + if (writeCharacteristic == nullptr) + { + debugDirector("Failed to find Echelon write characteristic UUID: ",false); + debugDirector(String(ECHELON_WRITE_UUID.toString().c_str())); + pClient->disconnect(); + return; + } + // Enable device notifications + byte message[] = {0xF0, 0xB0, 0x01, 0x01, 0xA2}; + writeCharacteristic->writeValue(message, 5); + debugDirector("Activated Echelon callbacks."); + } //spinBLEClient.removeDuplicates(pclient); return; } @@ -607,7 +630,3 @@ void SpinBLEAdvertisedDevice::print() strcat(logBufP, "|"); debugDirector(String(logBuf)); } - - - - diff --git a/src/sensors/EchelonData.cpp b/src/sensors/EchelonData.cpp new file mode 100644 index 00000000..a0fd7eda --- /dev/null +++ b/src/sensors/EchelonData.cpp @@ -0,0 +1,49 @@ +#include "BLE_Common.h" +#include "sensors/EchelonData.h" + +bool EchelonData::hasHeartRate() { return false; } + +bool EchelonData::hasCadence() { return this->hasData; } + +bool EchelonData::hasPower() { return this->hasData; } + +bool EchelonData::hasSpeed() { return false; } + +int EchelonData::getHeartRate() { return INT_MIN; } + +float EchelonData::getCadence() { return this->cadence; }; + +int EchelonData::getPower() { return this->power; }; + +float EchelonData::getSpeed() { return NAN; } + +void EchelonData::decode(uint8_t *data, size_t length) +{ + switch (data[1]) + { + // Cadence notification + case 0xD1: + //runtime = int((data[7] << 8) + data[8]); // This runtime has massive drift + cadence = int((data[9] << 8) + data[10]); + hasData = true; + if (cadence == 0 || resistance == 0) + { + power = (pow(1.090112, resistance) * pow(1.015343, cadence) * 7.228958); + break; + } + break; + // Resistance notification + case 0xD2: + resistance = int(data[3]); + hasData = true; + if (cadence == 0 || resistance == 0) + { + power = (pow(1.090112, resistance) * pow(1.015343, cadence) * 7.228958); + break; + } + break; + //Data 1 didn't match + default: + hasData = false; + } +} \ No newline at end of file diff --git a/src/sensors/SensorDataFactory.cpp b/src/sensors/SensorDataFactory.cpp index 68ea30f3..2efebe55 100644 --- a/src/sensors/SensorDataFactory.cpp +++ b/src/sensors/SensorDataFactory.cpp @@ -5,6 +5,7 @@ #include "sensors/FlywheelData.h" #include "sensors/FitnessMachineIndoorBikeData.h" #include "sensors/HeartRateData.h" +#include "sensors/EchelonData.h" std::shared_ptr SensorDataFactory::getSensorData(BLERemoteCharacteristic *characteristic, uint8_t *data, size_t length) { @@ -33,6 +34,10 @@ std::shared_ptr SensorDataFactory::getSensorData(BLERemoteCharacteri else if (uuid == FLYWHEEL_UART_SERVICE_UUID) { sensorData = std::shared_ptr(new FlywheelData()); + } + else if (uuid == ECHELON_SERVICE_UUID) + { + sensorData = std::shared_ptr(new EchelonData()); } else { From 0a01840c5fb1da0c6f20eeafcda3e72e7de01094 Mon Sep 17 00:00:00 2001 From: doudar Date: Wed, 17 Mar 2021 17:58:37 -0500 Subject: [PATCH 02/10] Changed BLE advertising. re-added Double Power --- include/BLE_Common.h | 2 +- src/BLE_Client.cpp | 8 ++++---- src/BLE_Common.cpp | 37 +++++++++++++++++++++---------------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/include/BLE_Common.h b/include/BLE_Common.h index 05fc634d..2b5d1954 100644 --- a/include/BLE_Common.h +++ b/include/BLE_Common.h @@ -42,7 +42,7 @@ #define FLYWHEEL_UART_TX_UUID BLEUUID((uint16_t)0xCA9E) // The Echelon Services -//#define ECHELON_device_UUID BLEUUID("0bf669f0-45f2-11e7-9598-0800200c9a66"); //not used by SS2K currently +#define ECHELON_DEVICE_UUID BLEUUID("0bf669f0-45f2-11e7-9598-0800200c9a66") #define ECHELON_SERVICE_UUID BLEUUID("0bf669f1-45f2-11e7-9598-0800200c9a66") #define ECHELON_WRITE_UUID BLEUUID("0bf669f2-45f2-11e7-9598-0800200c9a66") #define ECHELON_DATA_UUID BLEUUID("0bf669f4-45f2-11e7-9598-0800200c9a66") diff --git a/src/BLE_Client.cpp b/src/BLE_Client.cpp index 9884e9fb..8217c5e7 100644 --- a/src/BLE_Client.cpp +++ b/src/BLE_Client.cpp @@ -122,11 +122,11 @@ bool SpinBLEClient::connectToServer() charUUID = FITNESSMACHINEINDOORBIKEDATA_UUID; debugDirector("trying to connect to Fitness machine service"); } - else if (myDevice->isAdvertisingService(ECHELON_SERVICE_UUID)) + else if (myDevice->isAdvertisingService(ECHELON_DEVICE_UUID)) { serviceUUID = ECHELON_SERVICE_UUID; charUUID = ECHELON_DATA_UUID; - debugDirector("trying to connect to Fitness machine service"); + debugDirector("Trying to connect to Echelon Bike"); } else if (myDevice->isAdvertisingService(HEARTSERVICE_UUID)) { @@ -400,7 +400,7 @@ void SpinBLEClient::MyAdvertisedDeviceCallback::onResult(BLEAdvertisedDevice *ad { aDevName = ""; } - if ((advertisedDevice->haveServiceUUID()) && (advertisedDevice->isAdvertisingService(CYCLINGPOWERSERVICE_UUID) || advertisedDevice->isAdvertisingService(FLYWHEEL_UART_SERVICE_UUID) || advertisedDevice->isAdvertisingService(FITNESSMACHINESERVICE_UUID) || advertisedDevice->isAdvertisingService(HEARTSERVICE_UUID) || advertisedDevice->isAdvertisingService(ECHELON_SERVICE_UUID))) + if ((advertisedDevice->haveServiceUUID()) && (advertisedDevice->isAdvertisingService(CYCLINGPOWERSERVICE_UUID) || advertisedDevice->isAdvertisingService(FLYWHEEL_UART_SERVICE_UUID) || advertisedDevice->isAdvertisingService(FITNESSMACHINESERVICE_UUID) || advertisedDevice->isAdvertisingService(HEARTSERVICE_UUID) || advertisedDevice->isAdvertisingService(ECHELON_DEVICE_UUID))) { //if ((aDevName == c_PM) || (advertisedDevice->getAddress().toString().c_str() == c_PM) || (aDevName == c_HR) || (advertisedDevice->getAddress().toString().c_str() == c_HR) || (String(c_PM) == ("any")) || (String(c_HR) == ("any"))) //{ //notice the subtle difference vv getServiceUUID(int) returns the index of the service in the list or the 0 slot if not specified. @@ -476,7 +476,7 @@ void SpinBLEClient::scanProcess() for (int i = 0; i < count; i++) { BLEAdvertisedDevice d = foundDevices.getDevice(i); - if (d.isAdvertisingService(CYCLINGPOWERSERVICE_UUID) || d.isAdvertisingService(HEARTSERVICE_UUID) || d.isAdvertisingService(FLYWHEEL_UART_SERVICE_UUID) || d.isAdvertisingService(FITNESSMACHINESERVICE_UUID) || d.isAdvertisingService(ECHELON_SERVICE_UUID)) + if (d.isAdvertisingService(CYCLINGPOWERSERVICE_UUID) || d.isAdvertisingService(HEARTSERVICE_UUID) || d.isAdvertisingService(FLYWHEEL_UART_SERVICE_UUID) || d.isAdvertisingService(FITNESSMACHINESERVICE_UUID) || d.isAdvertisingService(ECHELON_DEVICE_UUID)) { device = "device " + String(i); devices[device]["address"] = d.getAddress().toString(); diff --git a/src/BLE_Common.cpp b/src/BLE_Common.cpp index eff898ef..508d7e42 100644 --- a/src/BLE_Common.cpp +++ b/src/BLE_Common.cpp @@ -78,7 +78,14 @@ void BLECommunications(void *pvParameters) if (sensorData->hasPower()) { int power = sensorData->getPower(); - userConfig.setSimulatedWatts(power); + if (userConfig.getDoublePower) + { + userConfig.setSimulatedWatts(power*2); + } + else + { + userConfig.setSimulatedWatts(power); + } spinBLEClient.connectedPM |= true; logBufP += sprintf(logBufP, " PW(%d)", power % 10000); } @@ -93,12 +100,12 @@ void BLECommunications(void *pvParameters) } else if (!pClient->isConnected()) //This shouldn't ever be called really.......... { - if(pClient->disconnect()==0) //0 is a suscessful disconnect :? - { - BLEDevice::deleteClient(pClient); - vTaskDelay(100/portTICK_PERIOD_MS); - debugDirector("Workaround connect"); - myAdvertisedDevice.doConnect = true; + if (pClient->disconnect() == 0) //0 is a suscessful disconnect :? + { + BLEDevice::deleteClient(pClient); + vTaskDelay(100 / portTICK_PERIOD_MS); + debugDirector("Workaround connect"); + myAdvertisedDevice.doConnect = true; } } } @@ -112,9 +119,9 @@ void BLECommunications(void *pvParameters) { calculateInstPwrFromHR(); } - #ifdef DEBUG_HR_TO_PWR - calculateInstPwrFromHR(); - #endif +#ifdef DEBUG_HR_TO_PWR + calculateInstPwrFromHR(); +#endif if (!spinBLEClient.connectedPM && !userPWC.hr2Pwr) { @@ -126,7 +133,7 @@ void BLECommunications(void *pvParameters) userConfig.setSimulatedHr(0); } - if (connectedClientCount()>0) + if (connectedClientCount() > 0) { //update the BLE information on the server computeCSC(); @@ -144,15 +151,14 @@ void BLECommunications(void *pvParameters) } else { - } - if (connectedClientCount()==0) + if (connectedClientCount() == 0) { digitalWrite(LED_PIN, LOW); //blink if no client connected } - if(BLEDevice::getAdvertising()) + if (BLEDevice::getAdvertising()) { - if(!(BLEDevice::getAdvertising()->isAdvertising())&& (BLEDevice::getServer()->getConnectedCount()isAdvertising()) && (BLEDevice::getServer()->getConnectedCount() < CONFIG_BT_NIMBLE_MAX_CONNECTIONS - NUM_BLE_DEVICES)) { debugDirector("Starting Advertising From Communication Loop"); BLEDevice::startAdvertising(); @@ -167,4 +173,3 @@ void BLECommunications(void *pvParameters) #endif } } - From b2b3a7029ff76e9d859b752d96ef4b8f3ca05b98 Mon Sep 17 00:00:00 2001 From: doudar Date: Wed, 17 Mar 2021 18:00:14 -0500 Subject: [PATCH 03/10] Dang Parenthesis --- src/BLE_Common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BLE_Common.cpp b/src/BLE_Common.cpp index 508d7e42..3e51ae6a 100644 --- a/src/BLE_Common.cpp +++ b/src/BLE_Common.cpp @@ -78,7 +78,7 @@ void BLECommunications(void *pvParameters) if (sensorData->hasPower()) { int power = sensorData->getPower(); - if (userConfig.getDoublePower) + if (userConfig.getDoublePower()) { userConfig.setSimulatedWatts(power*2); } From a892a3d95f7d65f2a9075d8e403548353d0d3b22 Mon Sep 17 00:00:00 2001 From: Joel Baranick Date: Wed, 17 Mar 2021 23:37:26 -0700 Subject: [PATCH 04/10] Fix Echelon data parsing Add echelon parsing --- include/sensors/EchelonData.h | 5 ++--- src/sensors/EchelonData.cpp | 35 +++++++++++++++-------------------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/include/sensors/EchelonData.h b/include/sensors/EchelonData.h index 173c47d5..2b5cafbb 100644 --- a/include/sensors/EchelonData.h +++ b/include/sensors/EchelonData.h @@ -5,7 +5,7 @@ class EchelonData : public SensorData { public: - EchelonData() : SensorData("ECH"){}; + EchelonData() : SensorData("ECH"), cadence(NAN), resistance(INT_MIN), power(INT_MIN) {}; bool hasHeartRate(); bool hasCadence(); @@ -18,8 +18,7 @@ class EchelonData : public SensorData void decode(uint8_t *data, size_t length); private: - bool hasData = false; float cadence; - int power; int resistance; + int power; }; \ No newline at end of file diff --git a/src/sensors/EchelonData.cpp b/src/sensors/EchelonData.cpp index a0fd7eda..46900b27 100644 --- a/src/sensors/EchelonData.cpp +++ b/src/sensors/EchelonData.cpp @@ -3,9 +3,9 @@ bool EchelonData::hasHeartRate() { return false; } -bool EchelonData::hasCadence() { return this->hasData; } +bool EchelonData::hasCadence() { return !isnan(this->cadence); } -bool EchelonData::hasPower() { return this->hasData; } +bool EchelonData::hasPower() { return this->cadence >= 0 && this->resistance >= 0; } bool EchelonData::hasSpeed() { return false; } @@ -23,27 +23,22 @@ void EchelonData::decode(uint8_t *data, size_t length) { // Cadence notification case 0xD1: - //runtime = int((data[7] << 8) + data[8]); // This runtime has massive drift - cadence = int((data[9] << 8) + data[10]); - hasData = true; - if (cadence == 0 || resistance == 0) - { - power = (pow(1.090112, resistance) * pow(1.015343, cadence) * 7.228958); - break; - } + this->cadence = int((data[9] << 8) + data[10]); break; // Resistance notification case 0xD2: - resistance = int(data[3]); - hasData = true; - if (cadence == 0 || resistance == 0) - { - power = (pow(1.090112, resistance) * pow(1.015343, cadence) * 7.228958); - break; - } + this->resistance = int(data[3]); break; - //Data 1 didn't match - default: - hasData = false; + } + if (isnan(this->cadence) || this->resistance < 0) { + return; + } + if (this->cadence == 0 || this->resistance == 0) + { + power = 0; + } + else + { + power = pow(1.090112, resistance) * pow(1.015343, cadence) * 7.228958; } } \ No newline at end of file From 7886fbce474e2519b8e6e61306d1637035e393a7 Mon Sep 17 00:00:00 2001 From: doudar Date: Thu, 18 Mar 2021 16:51:11 -0500 Subject: [PATCH 05/10] Fixed UUID --- src/sensors/SensorDataFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sensors/SensorDataFactory.cpp b/src/sensors/SensorDataFactory.cpp index 2efebe55..e33cb91c 100644 --- a/src/sensors/SensorDataFactory.cpp +++ b/src/sensors/SensorDataFactory.cpp @@ -35,7 +35,7 @@ std::shared_ptr SensorDataFactory::getSensorData(BLERemoteCharacteri { sensorData = std::shared_ptr(new FlywheelData()); } - else if (uuid == ECHELON_SERVICE_UUID) + else if (uuid == ECHELON_DATA_UUID) { sensorData = std::shared_ptr(new EchelonData()); } From fb02a35ec9f1c49b9b42581260ca0c41ee8b67d4 Mon Sep 17 00:00:00 2001 From: doudar Date: Thu, 18 Mar 2021 21:27:17 -0500 Subject: [PATCH 06/10] Switched Flywheel UUID's back to long form --- include/BLE_Common.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/include/BLE_Common.h b/include/BLE_Common.h index 2b5d1954..fcce8cff 100644 --- a/include/BLE_Common.h +++ b/include/BLE_Common.h @@ -37,18 +37,16 @@ #define FITNESSMACHINEPOWERRANGE_UUID BLEUUID((uint16_t)0x2AD8) // GATT service/characteristic UUIDs for Flywheel Bike from ptx2/gymnasticon/ -#define FLYWHEEL_UART_SERVICE_UUID BLEUUID((uint16_t)0xCA9E) -#define FLYWHEEL_UART_RX_UUID BLEUUID((uint16_t)0xCA9E) -#define FLYWHEEL_UART_TX_UUID BLEUUID((uint16_t)0xCA9E) +#define FLYWHEEL_UART_SERVICE_UUID BLEUUID("6e400001b5a3f393e0a9e50e24dcca9e") +#define FLYWHEEL_UART_RX_UUID BLEUUID("6e400002b5a3f393e0a9e50e24dcca9e") +#define FLYWHEEL_UART_TX_UUID BLEUUID("6e400003b5a3f393e0a9e50e24dcca9e") // The Echelon Services #define ECHELON_DEVICE_UUID BLEUUID("0bf669f0-45f2-11e7-9598-0800200c9a66") #define ECHELON_SERVICE_UUID BLEUUID("0bf669f1-45f2-11e7-9598-0800200c9a66") #define ECHELON_WRITE_UUID BLEUUID("0bf669f2-45f2-11e7-9598-0800200c9a66") #define ECHELON_DATA_UUID BLEUUID("0bf669f4-45f2-11e7-9598-0800200c9a66") -//#define ECHELON_SERVICE_UUID BLEUUID((uint16_t)0x69f1) // convert to these once this service works -//#define ECHELON_WRITE_UUID BLEUUID((uint16_t)0x69f2) -//#define ECHELON_DATA_UUID BLEUUID((uint16_t)0x69f4) + // macros to convert different types of bytes into int The naming here sucks and should be fixed. #define bytes_to_s16(MSB, LSB) (((signed int)((signed char)MSB))) << 8 | (((signed char)LSB)) From fca05cc193aecb10a3826b699cf816d82870e3d1 Mon Sep 17 00:00:00 2001 From: doudar Date: Thu, 18 Mar 2021 21:45:06 -0500 Subject: [PATCH 07/10] Added licence to the new sensor files --- include/sensors/CyclePowerData.h | 7 +++++++ include/sensors/EchelonData.h | 7 +++++++ include/sensors/FitnessMachineIndoorBikeData.h | 7 +++++++ include/sensors/FlywheelData.h | 7 +++++++ include/sensors/HeartRateData.h | 7 +++++++ include/sensors/SensorData.h | 7 +++++++ include/sensors/SensorDataFactory.h | 7 +++++++ src/sensors/CyclePowerData.cpp | 7 +++++++ src/sensors/EchelonData.cpp | 8 ++++++++ src/sensors/FitnessMachineIndoorBikeData.cpp | 7 +++++++ src/sensors/FlywheelData.cpp | 7 +++++++ src/sensors/HeartRateData.cpp | 7 +++++++ src/sensors/SensorData.cpp | 7 +++++++ src/sensors/SensorDataFactory.cpp | 7 +++++++ 14 files changed, 99 insertions(+) diff --git a/include/sensors/CyclePowerData.h b/include/sensors/CyclePowerData.h index 60734906..bafd3b3e 100644 --- a/include/sensors/CyclePowerData.h +++ b/include/sensors/CyclePowerData.h @@ -1,3 +1,10 @@ +// SmartSpin2K code +// This software registers an ESP32 as a BLE FTMS device which then uses a stepper motor to turn the resistance knob on a regular spin bike. +// BLE code based on examples from https://github.com/nkolban +// Copyright 2020 Anthony Doud & Joel Baranick +// This work is licensed under the GNU General Public License v2 +// Prototype hardware build from plans in the SmartSpin2k repository are licensed under Cern Open Hardware Licence version 2 Permissive + #pragma once #include diff --git a/include/sensors/EchelonData.h b/include/sensors/EchelonData.h index 2b5cafbb..b9880509 100644 --- a/include/sensors/EchelonData.h +++ b/include/sensors/EchelonData.h @@ -1,3 +1,10 @@ +// SmartSpin2K code +// This software registers an ESP32 as a BLE FTMS device which then uses a stepper motor to turn the resistance knob on a regular spin bike. +// BLE code based on examples from https://github.com/nkolban +// Copyright 2020 Anthony Doud & Joel Baranick +// This work is licensed under the GNU General Public License v2 +// Prototype hardware build from plans in the SmartSpin2k repository are licensed under Cern Open Hardware Licence version 2 Permissive + #pragma once #include "SensorData.h" diff --git a/include/sensors/FitnessMachineIndoorBikeData.h b/include/sensors/FitnessMachineIndoorBikeData.h index 97415679..be7e6fc0 100644 --- a/include/sensors/FitnessMachineIndoorBikeData.h +++ b/include/sensors/FitnessMachineIndoorBikeData.h @@ -1,3 +1,10 @@ +// SmartSpin2K code +// This software registers an ESP32 as a BLE FTMS device which then uses a stepper motor to turn the resistance knob on a regular spin bike. +// BLE code based on examples from https://github.com/nkolban +// Copyright 2020 Anthony Doud & Joel Baranick +// This work is licensed under the GNU General Public License v2 +// Prototype hardware build from plans in the SmartSpin2k repository are licensed under Cern Open Hardware Licence version 2 Permissive + #pragma once #include diff --git a/include/sensors/FlywheelData.h b/include/sensors/FlywheelData.h index 3289563b..737ecf94 100644 --- a/include/sensors/FlywheelData.h +++ b/include/sensors/FlywheelData.h @@ -1,3 +1,10 @@ +// SmartSpin2K code +// This software registers an ESP32 as a BLE FTMS device which then uses a stepper motor to turn the resistance knob on a regular spin bike. +// BLE code based on examples from https://github.com/nkolban +// Copyright 2020 Anthony Doud & Joel Baranick +// This work is licensed under the GNU General Public License v2 +// Prototype hardware build from plans in the SmartSpin2k repository are licensed under Cern Open Hardware Licence version 2 Permissive + #pragma once #include "SensorData.h" diff --git a/include/sensors/HeartRateData.h b/include/sensors/HeartRateData.h index ec7c4c91..dca77950 100644 --- a/include/sensors/HeartRateData.h +++ b/include/sensors/HeartRateData.h @@ -1,3 +1,10 @@ +// SmartSpin2K code +// This software registers an ESP32 as a BLE FTMS device which then uses a stepper motor to turn the resistance knob on a regular spin bike. +// BLE code based on examples from https://github.com/nkolban +// Copyright 2020 Anthony Doud & Joel Baranick +// This work is licensed under the GNU General Public License v2 +// Prototype hardware build from plans in the SmartSpin2k repository are licensed under Cern Open Hardware Licence version 2 Permissive + #pragma once #include "SensorData.h" diff --git a/include/sensors/SensorData.h b/include/sensors/SensorData.h index 87492646..4c5349d4 100644 --- a/include/sensors/SensorData.h +++ b/include/sensors/SensorData.h @@ -1,3 +1,10 @@ +// SmartSpin2K code +// This software registers an ESP32 as a BLE FTMS device which then uses a stepper motor to turn the resistance knob on a regular spin bike. +// BLE code based on examples from https://github.com/nkolban +// Copyright 2020 Anthony Doud & Joel Baranick +// This work is licensed under the GNU General Public License v2 +// Prototype hardware build from plans in the SmartSpin2k repository are licensed under Cern Open Hardware Licence version 2 Permissive + #pragma once #include diff --git a/include/sensors/SensorDataFactory.h b/include/sensors/SensorDataFactory.h index 5362de7c..dc8691e7 100644 --- a/include/sensors/SensorDataFactory.h +++ b/include/sensors/SensorDataFactory.h @@ -1,3 +1,10 @@ +// SmartSpin2K code +// This software registers an ESP32 as a BLE FTMS device which then uses a stepper motor to turn the resistance knob on a regular spin bike. +// BLE code based on examples from https://github.com/nkolban +// Copyright 2020 Anthony Doud & Joel Baranick +// This work is licensed under the GNU General Public License v2 +// Prototype hardware build from plans in the SmartSpin2k repository are licensed under Cern Open Hardware Licence version 2 Permissive + #pragma once #include diff --git a/src/sensors/CyclePowerData.cpp b/src/sensors/CyclePowerData.cpp index 8faef074..cb72b40c 100644 --- a/src/sensors/CyclePowerData.cpp +++ b/src/sensors/CyclePowerData.cpp @@ -1,3 +1,10 @@ +// SmartSpin2K code +// This software registers an ESP32 as a BLE FTMS device which then uses a stepper motor to turn the resistance knob on a regular spin bike. +// BLE code based on examples from https://github.com/nkolban +// Copyright 2020 Anthony Doud & Joel Baranick +// This work is licensed under the GNU General Public License v2 +// Prototype hardware build from plans in the SmartSpin2k repository are licensed under Cern Open Hardware Licence version 2 Permissive + #include "BLE_Common.h" #include "sensors/CyclePowerData.h" diff --git a/src/sensors/EchelonData.cpp b/src/sensors/EchelonData.cpp index 46900b27..ddf6acdb 100644 --- a/src/sensors/EchelonData.cpp +++ b/src/sensors/EchelonData.cpp @@ -1,3 +1,11 @@ +// SmartSpin2K code +// This software registers an ESP32 as a BLE FTMS device which then uses a stepper motor to turn the resistance knob on a regular spin bike. +// BLE code based on examples from https://github.com/nkolban +// Copyright 2020 Anthony Doud & Joel Baranick +// This work is licensed under the GNU General Public License v2 +// Prototype hardware build from plans in the SmartSpin2k repository are licensed under Cern Open Hardware Licence version 2 Permissive +// Echelon Decoding model based on https://github.com/snowzach/echbt + #include "BLE_Common.h" #include "sensors/EchelonData.h" diff --git a/src/sensors/FitnessMachineIndoorBikeData.cpp b/src/sensors/FitnessMachineIndoorBikeData.cpp index 2324aac6..d8d414ff 100644 --- a/src/sensors/FitnessMachineIndoorBikeData.cpp +++ b/src/sensors/FitnessMachineIndoorBikeData.cpp @@ -1,3 +1,10 @@ +// SmartSpin2K code +// This software registers an ESP32 as a BLE FTMS device which then uses a stepper motor to turn the resistance knob on a regular spin bike. +// BLE code based on examples from https://github.com/nkolban +// Copyright 2020 Anthony Doud & Joel Baranick +// This work is licensed under the GNU General Public License v2 +// Prototype hardware build from plans in the SmartSpin2k repository are licensed under Cern Open Hardware Licence version 2 Permissive + #include "BLE_Common.h" #include "sensors/FitnessMachineIndoorBikeData.h" diff --git a/src/sensors/FlywheelData.cpp b/src/sensors/FlywheelData.cpp index 79a2f554..b4de4a84 100644 --- a/src/sensors/FlywheelData.cpp +++ b/src/sensors/FlywheelData.cpp @@ -1,3 +1,10 @@ +// SmartSpin2K code +// This software registers an ESP32 as a BLE FTMS device which then uses a stepper motor to turn the resistance knob on a regular spin bike. +// BLE code based on examples from https://github.com/nkolban +// Copyright 2020 Anthony Doud & Joel Baranick +// This work is licensed under the GNU General Public License v2 +// Prototype hardware build from plans in the SmartSpin2k repository are licensed under Cern Open Hardware Licence version 2 Permissive + #include "BLE_Common.h" #include "sensors/FlywheelData.h" diff --git a/src/sensors/HeartRateData.cpp b/src/sensors/HeartRateData.cpp index 604ff6e2..fd861fd4 100644 --- a/src/sensors/HeartRateData.cpp +++ b/src/sensors/HeartRateData.cpp @@ -1,3 +1,10 @@ +// SmartSpin2K code +// This software registers an ESP32 as a BLE FTMS device which then uses a stepper motor to turn the resistance knob on a regular spin bike. +// BLE code based on examples from https://github.com/nkolban +// Copyright 2020 Anthony Doud & Joel Baranick +// This work is licensed under the GNU General Public License v2 +// Prototype hardware build from plans in the SmartSpin2k repository are licensed under Cern Open Hardware Licence version 2 Permissive + #include "sensors/HeartRateData.h" bool HeartRateData::hasHeartRate() { return true; } diff --git a/src/sensors/SensorData.cpp b/src/sensors/SensorData.cpp index 34d51192..f24325f3 100644 --- a/src/sensors/SensorData.cpp +++ b/src/sensors/SensorData.cpp @@ -1,3 +1,10 @@ +// SmartSpin2K code +// This software registers an ESP32 as a BLE FTMS device which then uses a stepper motor to turn the resistance knob on a regular spin bike. +// BLE code based on examples from https://github.com/nkolban +// Copyright 2020 Anthony Doud & Joel Baranick +// This work is licensed under the GNU General Public License v2 +// Prototype hardware build from plans in the SmartSpin2k repository are licensed under Cern Open Hardware Licence version 2 Permissive + #include "sensors/SensorData.h" String SensorData::getId() { return this->id; } \ No newline at end of file diff --git a/src/sensors/SensorDataFactory.cpp b/src/sensors/SensorDataFactory.cpp index e33cb91c..c33d4490 100644 --- a/src/sensors/SensorDataFactory.cpp +++ b/src/sensors/SensorDataFactory.cpp @@ -1,3 +1,10 @@ +// SmartSpin2K code +// This software registers an ESP32 as a BLE FTMS device which then uses a stepper motor to turn the resistance knob on a regular spin bike. +// BLE code based on examples from https://github.com/nkolban +// Copyright 2020 Anthony Doud & Joel Baranick +// This work is licensed under the GNU General Public License v2 +// Prototype hardware build from plans in the SmartSpin2k repository are licensed under Cern Open Hardware Licence version 2 Permissive + #include "BLE_Common.h" #include "sensors/SensorDataFactory.h" #include "sensors/SensorData.h" From 5d5e982110b088e718100f22777f7468a74ff38e Mon Sep 17 00:00:00 2001 From: doudar Date: Thu, 18 Mar 2021 21:55:56 -0500 Subject: [PATCH 08/10] Capped UUID's in logging to max length of 8 --- src/BLE_Common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BLE_Common.cpp b/src/BLE_Common.cpp index 3e51ae6a..a2c506d0 100644 --- a/src/BLE_Common.cpp +++ b/src/BLE_Common.cpp @@ -56,7 +56,7 @@ void BLECommunications(void *pvParameters) { logBufP += sprintf(logBufP, "%02x ", pData[i]); } - logBufP += sprintf(logBufP, "<- %s | %s", myAdvertisedDevice.serviceUUID.toString().c_str(), myAdvertisedDevice.charUUID.toString().c_str()); + logBufP += sprintf(logBufP, "<- %s | %s", myAdvertisedDevice.serviceUUID.toString().substr(0,8).c_str(), myAdvertisedDevice.charUUID.toString().substr(0,8).c_str()); std::shared_ptr sensorData = sensorDataFactory.getSensorData(pRemoteBLECharacteristic, pData, length); From 8b8de57b4516ccded004ab05f30a74c487dce49f Mon Sep 17 00:00:00 2001 From: doudar Date: Fri, 19 Mar 2021 19:34:58 -0500 Subject: [PATCH 09/10] FIxed UUID formating per @kadaan request --- src/BLE_Common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BLE_Common.cpp b/src/BLE_Common.cpp index a2c506d0..09bd27a7 100644 --- a/src/BLE_Common.cpp +++ b/src/BLE_Common.cpp @@ -56,7 +56,7 @@ void BLECommunications(void *pvParameters) { logBufP += sprintf(logBufP, "%02x ", pData[i]); } - logBufP += sprintf(logBufP, "<- %s | %s", myAdvertisedDevice.serviceUUID.toString().substr(0,8).c_str(), myAdvertisedDevice.charUUID.toString().substr(0,8).c_str()); + logBufP += sprintf(logBufP, "<- %.8s | %.8s", myAdvertisedDevice.serviceUUID.toString().c_str(), myAdvertisedDevice.charUUID.toString().c_str()); std::shared_ptr sensorData = sensorDataFactory.getSensorData(pRemoteBLECharacteristic, pData, length); From 7a57884a9a38a6e220905df10f22de41b0aef9cd Mon Sep 17 00:00:00 2001 From: doudar Date: Sat, 20 Mar 2021 09:15:23 -0500 Subject: [PATCH 10/10] Set scan duplicate filter --- src/BLE_Client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BLE_Client.cpp b/src/BLE_Client.cpp index 8217c5e7..f1f9ad88 100644 --- a/src/BLE_Client.cpp +++ b/src/BLE_Client.cpp @@ -248,7 +248,6 @@ bool SpinBLEClient::connectToServer() pClient->connect(myDevice->getAddress()); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private) debugDirector(" - Connected to server", true); debugDirector(" - RSSI " + pClient->getRssi(), true); - // Obtain a reference to the service we are after in the remote BLE server. BLERemoteService *pRemoteService = pClient->getService(serviceUUID); if (pRemoteService == nullptr) @@ -464,6 +463,7 @@ void SpinBLEClient::scanProcess() pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallback()); pBLEScan->setInterval(550); pBLEScan->setWindow(500); + pBLEScan->setDuplicateFilter(true); pBLEScan->setActiveScan(true); BLEScanResults foundDevices = pBLEScan->start(10, false); // Load the scan into a Json String