Skip to content

Commit 2d3b3db

Browse files
author
Markus Schneider
committed
Added FTMS-Log
1 parent 49ba693 commit 2d3b3db

File tree

2 files changed

+84
-75
lines changed

2 files changed

+84
-75
lines changed

include/BLE_Common.h

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@
1414
#include <Arduino.h>
1515
#include <Main.h>
1616

17-
#define BLE_CLIENT_LOG_TAG "BLE_Client"
18-
#define BLE_COMMON_LOG_TAG "BLE_Common"
19-
#define BLE_SERVER_LOG_TAG "BLE_Server"
20-
#define BLE_SETUP_LOG_TAG "BLE_Setup"
17+
#define BLE_CLIENT_LOG_TAG "BLE_Client"
18+
#define BLE_COMMON_LOG_TAG "BLE_Common"
19+
#define BLE_SERVER_LOG_TAG "BLE_Server"
20+
#define BLE_SETUP_LOG_TAG "BLE_Setup"
21+
#define FMTS_SERVER_LOG_TAG "FTMS_SERVER"
2122

2223
// custom characteristic codes
2324
#define BLE_firmwareUpdateURL 0x01
@@ -227,6 +228,40 @@ class SpinBLEClient {
227228

228229
extern SpinBLEClient spinBLEClient;
229230

231+
// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
232+
// Table 4.13: Training Status Field Definition
233+
enum FitnessMachineTrainingStatus : uint {
234+
Other = 0x00,
235+
Idle = 0x01,
236+
WarmingUp = 0x02,
237+
LowIntensityInterval = 0x03,
238+
HighIntensityInterval = 0x04,
239+
RecoveryInterval = 0x05,
240+
Isometric = 0x06,
241+
HeartRateControl = 0x07,
242+
FitnessTest = 0x08,
243+
SpeedOutsideOfControlRegionLow = 0x09,
244+
SpeedOutsideOfControlRegionHigh = 0x0A,
245+
CoolDown = 0x0B,
246+
WattControl = 0x0C,
247+
ManualMode = 0x0D,
248+
PreWorkout = 0x0E,
249+
PostWorkout = 0x0F,
250+
// Reserved for Future Use 0x10-0xFF
251+
};
252+
253+
// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
254+
// Table 4.24: Fitness Machine Control Point characteristic – Result Codes
255+
enum FitnessMachineControlPointResultCode : uint {
256+
ReservedForFutureUse = 0x00,
257+
Success = 0x01,
258+
OpCodeNotSupported = 0x02,
259+
InvalidParameter = 0x03,
260+
OperationFailed = 0x04,
261+
ControlNotPermitted = 0x05,
262+
// Reserved for Future Use = 0x06-0xFF
263+
};
264+
230265
// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
231266
// Table 4.3: Definition of the bits of the Fitness Machine Features field
232267
struct FitnessMachineFeatureFlags {
@@ -275,46 +310,7 @@ struct FitnessMachineTargetFlags {
275310
};
276311
};
277312

278-
// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
279-
// Table 4.13: Training Status Field Definition
280-
struct FitnessMachineTrainingStatusFlag {
281-
enum Types : uint {
282-
Other = 0x00,
283-
Idle = 0x01,
284-
WarmingUp = 0x02,
285-
LowIntensityInterval = 0x03,
286-
HighIntensityInterval = 0x04,
287-
RecoveryInterval = 0x05,
288-
Isometric = 0x06,
289-
HeartRateControl = 0x07,
290-
FitnessTest = 0x08,
291-
SpeedOutsideOfControlRegionLow = 0x09,
292-
SpeedOutsideOfControlRegionHigh = 0x0A,
293-
CoolDown = 0x0B,
294-
WattControl = 0x0C,
295-
ManualMode = 0x0D,
296-
PreWorkout = 0x0E,
297-
PostWorkout = 0x0F,
298-
// Reserved for Future Use 0x10-0xFF
299-
};
300-
};
301-
302-
// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
303-
// Table 4.24: Fitness Machine Control Point characteristic – Result Codes
304-
struct FitnessMachineControlPointResultCodeFlag {
305-
enum Types : uint {
306-
ReservedForFutureUse = 0x00,
307-
Success = 0x01,
308-
OpCodeNotSupported = 0x02,
309-
InvalidParameter = 0x03,
310-
OperationFailed = 0x04,
311-
ControlNotPermitted = 0x05,
312-
// Reserved for Future Use = 0x06-0xFF
313-
};
314-
};
315-
316-
inline FitnessMachineFeatureFlags::Types
317-
operator|(FitnessMachineFeatureFlags::Types a, FitnessMachineFeatureFlags::Types b) {
313+
inline FitnessMachineFeatureFlags::Types operator|(FitnessMachineFeatureFlags::Types a, FitnessMachineFeatureFlags::Types b) {
318314
return static_cast<FitnessMachineFeatureFlags::Types>(static_cast<int>(a) | static_cast<int>(b));
319315
}
320316

src/BLE_Server.cpp

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -329,34 +329,34 @@ void processFTMSWrite() {
329329
int logBufLength = ss2k_log_hex_to_buffer(pData, length, logBuf, 0, kLogBufCapacity);
330330

331331
int port = 0;
332-
uint8_t returnValue[3] = {0x80, (uint8_t)rxValue[0], FitnessMachineControlPointResultCodeFlag::Types::OpCodeNotSupported};
332+
uint8_t returnValue[3] = {0x80, (uint8_t)rxValue[0], FitnessMachineControlPointResultCode::OpCodeNotSupported};
333333

334334
switch ((uint8_t)rxValue[0]) {
335-
case 0x00: // request control
336-
returnValue[2] = FitnessMachineControlPointResultCodeFlag::Types::Success; // 0x01;
335+
case 0x00: // request control
336+
returnValue[2] = FitnessMachineControlPointResultCode::Success; // 0x01;
337337
pCharacteristic->setValue(returnValue, 3);
338338

339339
logBufLength += snprintf(logBuf + logBufLength, kLogBufCapacity - logBufLength, "-> Control Request");
340340
// userConfig.setERGMode(false);
341-
ftmsTrainingStatus[1] = FitnessMachineTrainingStatusFlag::Types::Idle; // 0x01;
341+
ftmsTrainingStatus[1] = FitnessMachineTrainingStatus::Idle; // 0x01;
342342
fitnessMachineTrainingStatus->setValue(ftmsTrainingStatus, 2);
343343
fitnessMachineTrainingStatus->notify(false);
344344
pCharacteristic->setValue(returnValue, 3);
345345
break;
346346

347-
case 0x01: // reset
348-
returnValue[2] = FitnessMachineControlPointResultCodeFlag::Types::Success; // 0x01;
347+
case 0x01: // reset
348+
returnValue[2] = FitnessMachineControlPointResultCode::Success; // 0x01;
349349
pCharacteristic->setValue(returnValue, 3);
350350

351351
logBufLength += snprintf(logBuf + logBufLength, kLogBufCapacity - logBufLength, "-> Reset");
352-
ftmsTrainingStatus[1] = FitnessMachineTrainingStatusFlag::Types::Idle; // 0x01;
352+
ftmsTrainingStatus[1] = FitnessMachineTrainingStatus::Idle; // 0x01;
353353
fitnessMachineTrainingStatus->setValue(ftmsTrainingStatus, 2);
354354
fitnessMachineTrainingStatus->notify(false);
355355
pCharacteristic->setValue(returnValue, 3);
356356
break;
357357

358-
case 0x03: { // inclination level setting - differs from sim mode as no negative numbers
359-
returnValue[2] = FitnessMachineControlPointResultCodeFlag::Types::Success; // 0x01;
358+
case 0x03: { // inclination level setting - differs from sim mode as no negative numbers
359+
returnValue[2] = FitnessMachineControlPointResultCode::Success; // 0x01;
360360
pCharacteristic->setValue(returnValue, 3);
361361

362362
port = (rxValue[2] << 8) + rxValue[1];
@@ -366,13 +366,13 @@ void processFTMSWrite() {
366366
logBufLength += snprintf(logBuf + logBufLength, kLogBufCapacity - logBufLength, "-> Incline Mode: %2f", rtConfig.getTargetIncline() / 100);
367367
uint8_t inclineStatus[3] = {0x06, (uint8_t)rxValue[1], (uint8_t)rxValue[2]};
368368
fitnessMachineStatusCharacteristic->setValue(inclineStatus, 3);
369-
ftmsTrainingStatus[1] = FitnessMachineTrainingStatusFlag::Types::Other; // 0x00;
369+
ftmsTrainingStatus[1] = FitnessMachineTrainingStatus::Other; // 0x00;
370370
fitnessMachineTrainingStatus->setValue(ftmsTrainingStatus, 2);
371371
fitnessMachineTrainingStatus->notify();
372372
} break;
373373

374-
case 0x04: { // Resistance level setting
375-
returnValue[2] = FitnessMachineControlPointResultCodeFlag::Types::Success; // 0x01;
374+
case 0x04: { // Resistance level setting
375+
returnValue[2] = FitnessMachineControlPointResultCode::Success; // 0x01;
376376
pCharacteristic->setValue(returnValue, 3);
377377

378378
int targetResistance = rxValue[1];
@@ -381,7 +381,7 @@ void processFTMSWrite() {
381381
logBufLength += snprintf(logBuf + logBufLength, kLogBufCapacity - logBufLength, "-> Resistance Mode: %d", rtConfig.getShifterPosition());
382382
uint8_t resistanceStatus[2] = {0x07, rxValue[1]};
383383
fitnessMachineStatusCharacteristic->setValue(resistanceStatus, 3);
384-
ftmsTrainingStatus[1] = FitnessMachineTrainingStatusFlag::Types::Other; // 0x00;
384+
ftmsTrainingStatus[1] = FitnessMachineTrainingStatus::Other; // 0x00;
385385
fitnessMachineTrainingStatus->setValue(ftmsTrainingStatus, 2);
386386
fitnessMachineTrainingStatus->notify();
387387
} break;
@@ -395,32 +395,45 @@ void processFTMSWrite() {
395395
// computeERG(targetWatts);
396396
logBufLength += snprintf(logBuf + logBufLength, kLogBufCapacity - logBufLength, "-> ERG Mode Target: %d Current: %d Incline: %2f", targetWatts,
397397
rtConfig.getSimulatedWatts().value, rtConfig.getTargetIncline() / 100);
398-
returnValue[2] = FitnessMachineControlPointResultCodeFlag::Types::Success; // 0x01;
398+
returnValue[2] = FitnessMachineControlPointResultCode::Success; // 0x01;
399399
uint8_t ERGStatus[3] = {0x08, (uint8_t)rxValue[1], 0x01};
400400
fitnessMachineStatusCharacteristic->setValue(ERGStatus, 3);
401-
ftmsTrainingStatus[1] = FitnessMachineTrainingStatusFlag::Types::WattControl; // 0x0C;
401+
ftmsTrainingStatus[1] = FitnessMachineTrainingStatus::WattControl; // 0x0C;
402402
fitnessMachineTrainingStatus->setValue(ftmsTrainingStatus, 2);
403403
fitnessMachineTrainingStatus->notify();
404404
} else {
405-
returnValue[2] = FitnessMachineControlPointResultCodeFlag::Types::OpCodeNotSupported; // 0x02; no power meter connected, so no ERG
405+
returnValue[2] = FitnessMachineControlPointResultCode::OpCodeNotSupported; // 0x02; no power meter connected, so no ERG
406406
logBufLength += snprintf(logBuf + logBufLength, kLogBufCapacity - logBufLength, "-> ERG Mode: No Power Meter Connected");
407407
}
408408
pCharacteristic->setValue(returnValue, 3);
409409
} break;
410410

411-
case 0x07: // Start training
412-
returnValue[2] = FitnessMachineControlPointResultCodeFlag::Types::Success; // 0x01;
411+
case 0x07: // Start training
412+
returnValue[2] = FitnessMachineControlPointResultCode::Success; // 0x01;
413413
pCharacteristic->setValue(returnValue, 3);
414414

415415
logBufLength += snprintf(logBuf + logBufLength, kLogBufCapacity - logBufLength, "-> Start Training");
416-
ftmsTrainingStatus[1] = FitnessMachineTrainingStatusFlag::Types::Other; // 0x00;
416+
ftmsTrainingStatus[1] = FitnessMachineTrainingStatus::Other; // 0x00;
417417
fitnessMachineTrainingStatus->setValue(ftmsTrainingStatus, 2);
418418
fitnessMachineTrainingStatus->notify();
419419

420420
break;
421421

422-
case 0x11: { // sim mode
423-
returnValue[2] = FitnessMachineControlPointResultCodeFlag::Types::Success; // 0x01;
422+
case 0x08: // Stop or Pause
423+
returnValue[2] = FitnessMachineControlPointResultCode::Success; // 0x01;
424+
pCharacteristic->setValue(returnValue, 3);
425+
// rxValue[1] == 1 -> Stop, 2 -> Pause
426+
// TODO: Move stepper to Min Position
427+
428+
logBufLength += snprintf(logBuf + logBufLength, kLogBufCapacity - logBufLength, "-> Stop Training");
429+
ftmsTrainingStatus[1] = FitnessMachineTrainingStatus::Other; // 0x00;
430+
fitnessMachineTrainingStatus->setValue(ftmsTrainingStatus, 2);
431+
fitnessMachineTrainingStatus->notify();
432+
433+
break;
434+
435+
case 0x11: { // sim mode
436+
returnValue[2] = FitnessMachineControlPointResultCode::Success; // 0x01;
424437
pCharacteristic->setValue(returnValue, 3);
425438

426439
signed char buf[2];
@@ -435,7 +448,7 @@ void processFTMSWrite() {
435448
rtConfig.setERGMode(false);
436449
uint8_t simStatus[7] = {0x12, (uint8_t)rxValue[1], (uint8_t)rxValue[2], (uint8_t)rxValue[3], (uint8_t)rxValue[4], (uint8_t)rxValue[5], (uint8_t)rxValue[6]};
437450
fitnessMachineStatusCharacteristic->setValue(simStatus, 7);
438-
ftmsTrainingStatus[1] = FitnessMachineTrainingStatusFlag::Types::Other; // 0x00;
451+
ftmsTrainingStatus[1] = FitnessMachineTrainingStatus::Other; // 0x00;
439452
fitnessMachineTrainingStatus->setValue(ftmsTrainingStatus, 2);
440453
fitnessMachineTrainingStatus->notify();
441454
} break;
@@ -446,13 +459,13 @@ void processFTMSWrite() {
446459
fitnessMachineStatusCharacteristic->setValue(spinStatus, 2);
447460
uint8_t controlPoint[6] = {0x80, 0x01, 0x24, 0x03, 0x96, 0x0e}; // send low and high speed targets
448461
pCharacteristic->setValue(controlPoint, 6);
449-
ftmsTrainingStatus[1] = FitnessMachineTrainingStatusFlag::Types::Other; // 0x00;
462+
ftmsTrainingStatus[1] = FitnessMachineTrainingStatus::Other; // 0x00;
450463
fitnessMachineTrainingStatus->setValue(ftmsTrainingStatus, 2);
451464
fitnessMachineTrainingStatus->notify();
452465
} break;
453466

454-
case 0x15: { // Set Targeted Cadence
455-
returnValue[2] = FitnessMachineControlPointResultCodeFlag::Types::Success; // 0x01;
467+
case 0x15: { // Set Targeted Cadence
468+
returnValue[2] = FitnessMachineControlPointResultCode::Success; // 0x01;
456469
pCharacteristic->setValue(returnValue, 3);
457470

458471
int targetCadence = bytes_to_u16(rxValue[2], rxValue[1]);
@@ -462,7 +475,7 @@ void processFTMSWrite() {
462475
uint8_t ERGStatus[3] = {0x08, (uint8_t)rxValue[1], 0x01};
463476
fitnessMachineStatusCharacteristic->setValue(ERGStatus, 3);
464477

465-
ftmsTrainingStatus[1] = FitnessMachineTrainingStatusFlag::Types::Other; // 0x00;
478+
ftmsTrainingStatus[1] = FitnessMachineTrainingStatus::Other; // 0x00;
466479
fitnessMachineTrainingStatus->setValue(ftmsTrainingStatus, 2);
467480
fitnessMachineTrainingStatus->notify();
468481
} break;
@@ -471,16 +484,16 @@ void processFTMSWrite() {
471484
logBufLength += snprintf(logBuf + logBufLength, kLogBufCapacity - logBufLength, "-> Unsupported FTMS Request");
472485
pCharacteristic->setValue(returnValue, 3);
473486
}
474-
SS2K_LOG(BLE_SERVER_LOG_TAG, "%s", logBuf);
487+
SS2K_LOG(FMTS_SERVER_LOG_TAG, "%s", logBuf);
475488
fitnessMachineStatusCharacteristic->notify();
476489
} else {
477-
SS2K_LOG(BLE_SERVER_LOG_TAG, "App wrote nothing ");
478-
SS2K_LOG(BLE_SERVER_LOG_TAG, "assuming it's a Control request");
490+
SS2K_LOG(FMTS_SERVER_LOG_TAG, "App wrote nothing ");
491+
SS2K_LOG(FMTS_SERVER_LOG_TAG, "assuming it's a Control request");
479492

480-
uint8_t controlPoint[3] = {0x80, 0x00, FitnessMachineControlPointResultCodeFlag::Types::Success};
493+
uint8_t controlPoint[3] = {0x80, 0x00, FitnessMachineControlPointResultCode::Success};
481494
pCharacteristic->setValue(controlPoint, 3);
482495

483-
ftmsTrainingStatus[1] = FitnessMachineTrainingStatusFlag::Types::Other; // 0x00;
496+
ftmsTrainingStatus[1] = FitnessMachineTrainingStatus::Other; // 0x00;
484497
fitnessMachineTrainingStatus->setValue(ftmsTrainingStatus, 2);
485498
fitnessMachineTrainingStatus->notify(false);
486499
}

0 commit comments

Comments
 (0)