Closed Berg0162 closed 1 year ago
Dear Joel, Please lets have this thread separated from Elite Direto thread!
Are you 100% sure that the Zwift Hub is not connected to another client application (i.c. Zwift)? It looks like your Zwift Hub is advertising FTMS but is NOT exposing the FTMS Service when it is connected. That means it is controlled by another Client, since you do not have (a) BLE(dongle) that must be over ANT+. Or do you have an other setup?
--> Shut down your PC, remove the ANT+ dongle and restart the PC. --> Please set the Debug level in the Arduoino IDE to RELEASE (level 0)!! Like the instructions say:
Good luck! Jörgen.
Dear Joel, Please have a look at this tool for your smartphone to help you inspecting and testing BLE devices: nRF Connect by Nordic You can perfectly inspect the Zwift Hub trainer and check for the presence of BLE services like CPS, CSC, FTMS and others. You can easily connect to the trainer and test all those different Characteristics.... and their behaviour. It should be part of your toolbox I.C.E.
I have uploaded a new version for the Client (v023) that is more robust when error states occur. It will not result in an other outcome of your previous test! Regards, Jörgen.
Hello Jorghen,
I redid the test with Ant+ disconnected and Bluethoot gsm switched off.
Here is the result with FTMSClient v022:
Now I think it's good !
Joel
PS : I'm waiting for the dongle, maybe tomorrow
Found it! -> Client Reads CP Location Sensor: Loc#: 0 Other Discovering Cycling Speed and Cadence (CSC) Service ... [DISC ] [SVC] Handle start = 1 bool BLEDiscovery::_discoverService(uint16_t, BLEClientService&, uint16_t): 79: verify failed, error = NRF_ERROR_BUSY Not Found and disconnecting! CSC Service is mandatory! [BLE ] BLE_GATTC_EVT_READ_RSP : Conn Handle = 0 [BLE ] BLE_GAP_EVT_DISCONNECTED : Conn Handle = 0 [GAP ] Disconnect Reason: LOCAL_HOST_TERMINATED_CONNECTION Client Disconnected, reason = 0x16
Restart the Feather nRF52 Client for a new run! <<< Couldn't enable notify for Client CP Measurement Characteristic. Couldn't enable indicate for Client CP Control Point Characteristic. Couldn't enable notify for Client CSC Measurement Characteristic. Couldn't enable notify for Client FTM Training Status Characteristic. FTMS (trainer) is controlled by another Client (Training App)! Client (Central) is Up and Running!
BSP Library : 1.3.0 Bootloader : s140 6.1.1 Serial No : C2BA380FAD3CBBC2
--------- SoftDevice Config --------- Max UUID128 : 10 ATTR Table Size : 4096 Service Changed : 1 Central Connect Setting
--------- BLE Settings --------- Name : ItsyBitsy nRF52840 Express Max Connections : Peripheral = 0, Central = 1 Address : E2:AA:F7:E9:06:E0 (Static) TX Power : 0 dBm Conn Intervals : min = 20.00 ms, max = 30.00 ms Conn Timeout : 2000 ms Central Paired Devices:
Test with FTMS_Client_v023 :
Found it! -> Client Reads CP Location Sensor: Loc#: 0 Other Discovering Cycling Speed and Cadence (CSC) Service ... [DISC ] [SVC] Handle start = 1 bool BLEDiscovery::_discoverService(uint16_t, BLEClientService&, uint16_t): 79: verify failed, error = NRF_ERROR_BUSY Not Found and disconnecting! CSC Service is mandatory! [BLE ] BLE_GATTC_EVT_READ_RSP : Conn Handle = 0 [BLE ] BLE_GAP_EVT_DISCONNECTED : Conn Handle = 0 [GAP ] Disconnect Reason: LOCAL_HOST_TERMINATED_CONNECTION Client Disconnected, reason = 0x16
Restart the Feather nRF52 Client for a new run! <<< Stopped! BSP Library : 1.3.0 Bootloader : s140 6.1.1 Serial No : C2BA380FAD3CBBC2
--------- SoftDevice Config --------- Max UUID128 : 10 ATTR Table Size : 4096 Service Changed : 1 Central Connect Setting
--------- BLE Settings --------- Name : ItsyBitsy nRF52840 Express Max Connections : Peripheral = 0, Central = 1 Address : E2:AA:F7:E9:06:E0 (Static) TX Power : 0 dBm Conn Intervals : min = 20.00 ms, max = 30.00 ms Conn Timeout : 2000 ms Central Paired Devices:
Dear Joel, 1) I have asked you before --> Please set the Debug level in the Arduino IDE to RELEASE (level 0) !! You did NOT do this...for a particular reason? Please realize that more elaborate debug levels cost processor capacity and might lead to BLE timing errors.... See above: Discovering the CSC service an error occurs: error = NRF_ERROR_BUSY ---> Busy? Doing what? Does this error also occur when you set Release level to zero at compile time ? 2) --------- BLE Settings --------- Name : ItsyBitsy nRF52840 Express Did you have a particular reason why you bought this board and not the Feather nRF52840 Express that the Simcline projects use? I have no experience with the ItsyBitsy at all and nobody I know ever used it in this project....so I simply do not know if there are critical differences, that lead to unexpected results during operation and/or debugging in this stage or later. 3) The results are not very different from previous runs, the client detects a trainer [Zwift Hub] that advertises with CPS, CSC and FTMS... However when connected the discover actions (in the latest runs) for a mandatory service or characteristic fail at CSC. That is different from the first runs! The first runs failed when FTM was NOT detected! Does your Zwift hub not expose CSC? Is that typical for this type? Are there different types of Zwift Hubs with different specs.? 4) Please use nRF Connect to scan your Zwift hub when it is powered --> advertising -> connect -> detail the different services and characteristics that the hub is exposing... In previous issues (see Elite Direto) you can see how people made screen shots of screens of the nRF Connect tool and how instructive these images are! 5) What other devices (Treadmill(s), trainers, smartphone(s) et cetera) with BLE and/or ANT+ are present in the room that can disturb a smooth connection process. Best wishes, Jörgen.
Dear Joel, After a night sleep.... I have made some changes in the Client software and uploaded version v024. 1) No longer is CSC a MANDATORY service, it is very well possible that Zwift Hub does not has it implemented... sofar we do not know! May be "nRF Connect" is giving soon better insight in what services are exposed exactly! 2) I have changed the order of the connect sequence (discover a service or characteristic). The sequence now starts with more general services that all BLE devices (must) have, only thereafter we check for FTMS... That is mandatory so if it fails -> end of exercise! If all goes well CPS (Mandatory) and CSC (Not Mandatory) are checked... I hope this will give more decisive information! Good luck, Jörgen.
Dear Jörghen,
I ordered today Adafruit Feather nRF52840 Express but there are many sites out of stock! that's why I ordered the ItsyBitsy nRF52840 Express
Here is the first result with version V024. At first I turn on the trainer and watch the results. Here they are :
FTMS and Chars 'initialized' CPS and Chars 'initialized' CSCS and Chars 'initialized' GA and Chars 'initialized' DIS and Chars 'initialized' Start Scanning for CPS, CSC and FTMS! Found advertising Peripheral with FTMS service!, see the Raw Data packet: Timestamp MAC Address Rssi Data 000016166 F8:9C:FC:53:5E:49 -64 09-02-16-18-26-18-18-18-0A-18 Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 Now checking all Client Services and Characteristics! If Mandatory Services Fail --> the Client will disconnect! First checking Generic Access and Device Information Services and Characteristics! Found Client Generic Access -> Client Reads Device Name: [Zwift Hub] -> Client Reads Appearance: [0] Discovering Mandatory Client Fitness Machine (FTM) Service ... Not Found! Disconnecting since Client FTM Service is mandatory! Client Disconnected, reason = 0x16
Restart the Feather nRF52 Client for a new run! <<< Stopped!
And here is the second if just after turning on I pedal to wake up the services.
This is the second result if i'm turn
Feather nRF52 Client/Central: CPS, CSC and FTMS ----------------- Version 02.4 ------------------ Initialise the Bluefruit nRF52 module: Client (Central) FTMS and Chars 'initialized' CPS and Chars 'initialized' CSCS and Chars 'initialized' GA and Chars 'initialized' DIS and Chars 'initialized' Start Scanning for CPS, CSC and FTMS! Found advertising Peripheral with FTMS service!, see the Raw Data packet: Timestamp MAC Address Rssi Data 000001764 F8:9C:FC:53:5E:49 -70 09-02-16-18-26-18-18-18-0A-18 Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 Now checking all Client Services and Characteristics! If Mandatory Services Fail --> the Client will disconnect! First checking Generic Access and Device Information Services and Characteristics! Found Client Generic Access -> Client Reads Device Name: [Zwift Hub] -> Client Reads Appearance: [1152] Found Client Device Information -> Client Reads Manufacturer: [Zwift] -> Client Reads Model Number: [06] -> Client Reads Serial Number: [06-F89CFC535E49] Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 Discovering Client FTM Feature Characteristic ... Found it! -> Client Reads Raw FTM Feature bytes: [8] [ 87 44 00 00 0C E0 00 00 ] Discovering Client FTM Training Status Characteristic ... Not Found! Disconnecting since Client FTM Characteristic is mandatory! Client Disconnected, reason = 0x16
Restart the Feather nRF52 Client for a new run! <<< Stopped!
Here with the V23:
Feather nRF52 Client/Central: CPS, CSC and FTMS ----------------- Version 02.3 ------------------ Initialise the Bluefruit nRF52 module: Client (Central) FTMS and Chars 'initialized' CPS and Chars 'initialized' CSCS and Chars 'initialized' GA and Chars 'initialized' DIS and Chars 'initialized' Start Scanning for CPS, CSC and FTMS! Found advertising Peripheral with FTMS service!, see the Raw Data packet: Timestamp MAC Address Rssi Data 000001160 F8:9C:FC:53:5E:49 -69 09-02-16-18-26-18-18-18-0A-18 Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 Now checking mandatory Client Services and Characteristics! Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 Discovering Client CP Measurement characteristic ... Found it! Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! Discovering Client CP Feature characteristic ... Found it! -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] Wheel revolution data supported Crank revolution data supported Discovering Client CP Sensor Location characteristic ... Found it! -> Client Reads CP Location Sensor: Loc#: 0 Other Discovering Cycling Speed and Cadence (CSC) Service ... Not Found and disconnecting! CSC Service is mandatory! Client Disconnected, reason = 0x16
Restart the Feather nRF52 Client for a new run! <<< Stopped!
Here are the screenshots with nrf connect:
Sincerely,
Joel
I don't know if this can't help you? : Conect nrf debug mode log
nRF Connect, 2022-12-10 Zwift Hub (F8:9C:FC:53:5E:49) V 16:01:11.439 Connecting to F8:9C:FC:53:5E:49... D 16:01:11.439 gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferred PHY = LE 1M) D 16:01:11.697 [Callback] Connection state changed with status: 0 and new state: CONNECTED (2) I 16:01:11.697 Connected to F8:9C:FC:53:5E:49 V 16:01:11.702 Discovering services... D 16:01:11.702 gatt.discoverServices() D 16:01:11.728 [Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED I 16:01:12.541 Connection parameters updated (interval: 7.5ms, latency: 0, timeout: 5000ms) D 16:01:15.576 [Callback] Services discovered with status: 0 I 16:01:15.577 Services discovered V 16:01:15.615 Generic Access (0x1800)
I found this program: https://github.com/arduino-libraries/ArduinoBLE/blob/master/examples/Central/PeripheralExplorer/PeripheralExplorer.ino
for ESP32 BLE of which I did the test and here is the result of the services :
ets Jun 8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0030,len:1344 load:0x40078000,len:13864 load:0x40080400,len:3608 entry 0x400805f0 Bluetooth�� Low Energy Central - Peripheral Explorer Found 64:6c:58:a5:76:71 '' fe9f Found 60:1e:b5:71:b8:93 '' fe9f Found f8:9c:fc:53:5e:49 'Zwift Hub' 1816 Connecting ... Connected Discovering attributes ... Attributes discovered
Device name: Zwift Hub Appearance: 0x0
Service 1800 Characteristic 2a00, properties 0xA, value 0x5A7769667420487562 Descriptor 2803, value 0x020500012A Descriptor 2a01, value 0x8004 Characteristic 2a01, properties 0x2, value 0x8004 Descriptor 2803, value 0x020700042A Descriptor 2a04, value 0x4800780000009001 Characteristic 2a04, properties 0x2, value 0x4800780000009001 Descriptor 2803, value 0x020900A62A Descriptor 2aa6, value 0x01 Characteristic 2aa6, properties 0x2, value 0x01 Service 1801 Characteristic 2a05, properties 0x20 Descriptor 2902, value 0x0000 Service 1826 Characteristic 2ad2, properties 0x10 Descriptor 2902, value 0x0000 Descriptor 2803, value 0x021300CC2A Descriptor 2acc, value 0x874400000CE00000 Characteristic 2acc, properties 0x2, value 0x874400000CE00000 Descriptor 2803, value 0x021500D62A Descriptor 2ad6, value 0x000064000100 Characteristic 2ad6, properties 0x2, value 0x000064000100 Descriptor 2803, value 0x021700D82A Descriptor 2ad8, value 0x0000E8030100 Characteristic 2ad8, properties 0x2, value 0x0000E8030100 Descriptor 2803, value 0x101900DA2A Descriptor 2ada, value 0x Characteristic 2ada, properties 0x10 Descriptor 2902, value 0x0000 Descriptor 2803, value 0x281C00D92A Descriptor 2ad9, value 0x Characteristic 2ad9, properties 0x28 Descriptor 2902, value 0x0000 Service 1816 Characteristic 2a5b, properties 0x10 Descriptor 2902, value 0x0000 Descriptor 2803, value 0x0223005C2A Descriptor 2a5c, value 0x0300 Characteristic 2a5c, properties 0x2, value 0x0300 Descriptor 2803, value 0x0225005D2A Descriptor 2a5d, value 0x0C Characteristic 2a5d, properties 0x2, value 0x0C Descriptor 2803, value 0x282700552A Descriptor 2a55, value 0x Characteristic 2a55, properties 0x28 Descriptor 2902, value 0x0000 Service 1818 Characteristic 2a63, properties 0x10 Descriptor 2902, value 0x0000 Descriptor 2803, value 0x022E00652A Descriptor 2a65, value 0x0C000000 Characteristic 2a65, properties 0x2, value 0x0C000000 Descriptor 2803, value 0x0230005D2A Descriptor 2a5d, value 0x0C Characteristic 2a5d, properties 0x2, value 0x0C Service fe59 Characteristic 8ec90003-f315-4f60-9fb8-838830daea50, properties 0x28 Descriptor 2902, value 0x0000 Service 180d Characteristic 2a37, properties 0x10 Descriptor 2902, value 0x0000 Descriptor 2803, value 0x023A00382A Descriptor 2a38, value 0x01 Characteristic 2a38, properties 0x2, value 0x01 Service c4630001-003f-4cec-8994-e489b04d857f Characteristic c4632b03-003f-4cec-8994-e489b04d857f, properties 0x2, value 0xFF0F0000 Descriptor 2803, value 0x123F007F854DB089E49489EC4C3F00052B63C4 Descriptor 857f, value 0x0000000000000000000000000000000000000000 Descriptor 4cec, value 0x Descriptor 470a, value 0x Characteristic c4632b05-003f-4cec-8994-e489b04d857f, properties 0x12, value 0x0000000000000000000000000000000000000000 Descriptor 2902, value 0x0000 Descriptor 2901, value 0x537461747573 Descriptor 2803, value 0x2843007F854DB089E49489EC4C3F00042B63C4 Descriptor 857f, value 0x Descriptor 4cec, value 0x Descriptor 470a, value 0x Characteristic c4632b04-003f-4cec-8994-e489b04d857f, properties 0x28 Descriptor 2902, value 0x0000 Service 180a Characteristic 2a29, properties 0x2, value 0x5A77696674 Descriptor 2803, value 0x024900242A Descriptor 2a24, value 0x3036 Characteristic 2a24, properties 0x2, value 0x3036 Descriptor 2803, value 0x024B00252A Descriptor 2a25, value 0x30362D463839434643353335453439 Characteristic 2a25, properties 0x2, value 0x30362D463839434643353335453439 Descriptor 2803, value 0x024D00272A Descriptor 2a27, value 0x31 Characteristic 2a27, properties 0x2, value 0x31 Descriptor 2803, value 0x024F00262A Descriptor 2a26, value 0x332E39 Characteristic 2a26, properties 0x2, value 0x332E39
Disconnecting ... Disconnected
Dear Joel, Only this Sunday morning I had time to look into your post..... Wow! Super! That is a wealth of information! This is more than one could have asked for, what a pity we did not start this way.... I have to study it all carefully and that will take some time!
One thing is immediately striking at my first scan:
And here is the second if just after turning on I pedal to wake up the services.
I have only met trainers that are awake all the time, may be after 20 minutes go to sleep, but never within seconds/minutes... CPS (1818), CSC (1816) and FTMS (1826) are all present, NO DOUBT! I have to check if all the Chars are exposed and if there is a discrepancy in what the Client is instructed to be Mandatory and what the Zwift Hub is programmed with !!! This explains definitely the behavior in all of the runs. I will be back soon! Thanks again, this will bring the solution! Regards, Jörgen.
Let's give Client_FTMS version v025 a try! I have changed several Service Characteristics to NOT Mandatory, hopefully this is now fully in accordance with the Zwift Hub settings....! (This is quite different from FTMS trainers I have met so far, but no reason for worries!) Procedure is changed: run Feather code first and then start and wake up your trainer (we know now this is critical!)
Fingers crossed!
Dear jörghen,
Here are the results, You should know that the first attempt was a failure. The Zwift Hub is very temperamental to wake up. On the second I had to hurry to wake him up or else I don't know what happened. But he woke up at just the right time!
Unfortunately I didn't copy everything because the serial monitor had already been closed!!!!
I'm trying to reproduce but I can't!!!
Feather nRF52 Client/Central: CPS, CSC and FTMS ----------------- Version 02.5 ------------------ Initialise the Bluefruit nRF52 module: Client (Central) FTMS and Chars 'initialized' CPS and Chars 'initialized' CSCS and Chars 'initialized' GA and Chars 'initialized' DIS and Chars 'initialized' Start Scanning for CPS, CSC and FTMS! Found advertising Peripheral with FTMS service!, see the Raw Data packet: Timestamp MAC Address Rssi Data 000021991 F8:9C:FC:53:5E:49 -69 09-02-16-18-26-18-18-18-0A-18 Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 Now checking all Client Services and Characteristics! If Mandatory Services Fail --> the Client will disconnect! First checking Generic Access and Device Information Services and Characteristics! Found Client Generic Access -> Client Reads Device Name: [Zwift Hub] -> Client Reads Appearance: [0] Discovering Mandatory Client Fitness Machine (FTM) Service ... Not Found! Disconnecting since Client FTM Service is mandatory! Client Disconnected, reason = 0x16
Restart the Feather nRF52 Client for a new run! <<< Stopped!
15:54:24.551 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 15:54:26.523 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 F5 FF 28 33 00 ] 15:54:26.643 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:26.643 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 F5 FF 28 33 ] 15:54:28.645 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 E4 FF 28 33 00 ] 15:54:28.694 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:28.694 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 E4 FF 28 33 ] 15:54:30.682 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 CF FF 28 33 00 ] 15:54:30.915 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:30.915 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 CF FF 28 33 ] 15:54:32.764 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A8 FF 28 33 00 ] 15:54:32.888 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:32.888 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A8 FF 28 33 ] 15:54:34.867 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 84 FF 28 33 00 ] 15:54:35.131 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:35.131 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 84 FF 28 33 ] 15:54:36.980 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 FF 28 33 00 ] 15:54:37.072 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:37.072 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 FF 28 33 ] 15:54:39.043 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5D FF 28 33 00 ] 15:54:39.168 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:39.168 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5D FF 28 33 ] 15:54:41.168 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5E FF 28 33 00 ] 15:54:41.261 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:41.261 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5E FF 28 33 ] 15:54:43.265 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 6F FF 28 33 00 ] 15:54:43.310 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:43.310 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 6F FF 28 33 ] 15:54:45.302 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 8A FF 28 33 00 ] 15:54:45.361 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:45.382 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8A FF 28 33 ] 15:54:47.333 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 B8 FF 28 33 00 ] 15:54:47.519 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:47.519 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 B8 FF 28 33 ] 15:54:49.443 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 15:54:49.506 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:49.552 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 15:54:51.551 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A2 00 28 33 00 ] 15:54:51.627 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:51.627 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A2 00 28 33 ] 15:54:53.625 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 01 28 33 00 ] 15:54:53.658 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:53.658 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 01 28 33 ] 15:54:55.690 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 4F 01 28 33 00 ] 15:54:55.768 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:55.768 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 4F 01 28 33 ] 15:54:57.765 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 01 28 33 00 ] 15:54:58.198 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:58.198 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 01 28 33 ] 15:54:59.858 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 57 FF 28 33 00 ] 15:54:59.915 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:54:59.915 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 57 FF 28 33 ] 15:55:01.902 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 08 00 00 00 00 00 00 00 ] 15:55:02.041 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 08 03 ] 15:55:04.002 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 01 00 00 00 00 00 00 00 ] 15:55:04.081 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 01 01 ] 15:55:04.129 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 01 ] 15:55:06.110 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 15:55:06.186 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 15:55:08.190 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 15:55:08.236 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 15:55:10.225 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 15:55:10.537 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 15:55:10.537 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 15:55:12.340 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 15:55:12.466 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 15:55:12.511 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ]
Now I managed to get the full serial but I don't know how I woke up the Zwift hub.
I can't reproduce every time!!!!
16:35:25.068 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 16:35:25.068 -> ----------------- Version 02.5 ------------------ 16:35:25.068 -> Initialise the Bluefruit nRF52 module: Client (Central) 16:35:25.071 -> FTMS and Chars 'initialized' 16:35:25.071 -> CPS and Chars 'initialized' 16:35:25.071 -> CSCS and Chars 'initialized' 16:35:25.071 -> GA and Chars 'initialized' 16:35:25.071 -> DIS and Chars 'initialized' 16:35:25.071 -> Start Scanning for CPS, CSC and FTMS! 16:35:25.071 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 16:35:25.071 -> Timestamp MAC Address Rssi Data 16:35:25.071 -> 000000717 F8:9C:FC:53:5E:49 -64 09-02-16-18-26-18-18-18-0A-18 16:35:25.071 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 16:35:25.071 -> Now checking all Client Services and Characteristics! 16:35:25.071 -> If Mandatory Services Fail --> the Client will disconnect! 16:35:25.071 -> First checking Generic Access and Device Information Services and Characteristics! 16:35:25.229 -> Found Client Generic Access 16:35:25.229 -> -> Client Reads Device Name: [Zwift Hub] 16:35:25.231 -> -> Client Reads Appearance: [1152] 16:35:25.231 -> Found Client Device Information 16:35:25.242 -> -> Client Reads Manufacturer: [Zwift] 16:35:25.242 -> -> Client Reads Model Number: [06] 16:35:25.378 -> -> Client Reads Serial Number: [06-F89CFC535E49] 16:35:25.378 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 16:35:25.425 -> Discovering Client FTM Feature Characteristic ... Found it! 16:35:25.832 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 16:35:25.832 -> Discovering Client FTM Control Point Characteristic ... Found it! 16:35:26.374 -> Discovering Client FTM Status Characteristic ... Found it! 16:35:26.374 -> Discovering Client FTM Training Status Characteristic ... Ready to receive Client FTM Control Point Response Messages 16:35:26.409 -> Ready to receive Client FTM Status values 16:35:26.409 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 16:35:26.409 -> >>> Couldn't enable notify for Client FTM Indoor Bike Data Characteristic. 16:35:26.409 -> >>> Couldn't enable notify for Client CP Measurement Characteristic. 16:35:26.409 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 16:35:26.409 -> >>> Couldn't enable notify for Client CSC Measurement Characteristic. 16:35:26.409 -> Client (Central) is Up and Running! 16:35:26.595 -> Not Found! Not Mandatory 16:35:26.595 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 16:35:26.750 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 16:35:26.750 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 16:35:27.058 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 16:35:27.058 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 16:35:27.291 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 16:35:27.383 -> Discovering Client CP Measurement characteristic ... Found it! 16:35:27.554 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 16:35:27.816 -> Discovering Client CP Feature characteristic ... Found it! 16:35:27.987 -> -> Client Reads Raw CP Feature bytes: [4] [ 00 00 00 00 ] 16:35:27.987 -> Discovering Client CP Sensor Location characteristic ... NOT Found! NOT Mandatory! 16:35:27.987 -> Discovering Cycling Speed and Cadence (CSC) Service ... Not Found! CSC Service is Not Mandatory! 16:35:28.391 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 16:35:28.513 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 16:35:30.519 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 16:35:30.597 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 16:35:32.596 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 16:35:32.673 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 16:35:32.673 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 16:35:34.658 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 16:35:34.734 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:34.769 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 16:35:36.711 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 00 28 33 00 ] 16:35:36.789 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:36.789 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 16:35:38.772 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 16:35:39.099 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:39.099 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 16:35:40.880 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 14 00 28 33 00 ] 16:35:40.958 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:40.958 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 00 28 33 ] 16:35:42.973 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 00 28 33 00 ] 16:35:43.066 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:43.066 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 00 28 33 ] 16:35:45.077 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 25 00 28 33 00 ] 16:35:45.154 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:45.154 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 25 00 28 33 ] 16:35:47.144 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 23 00 28 33 00 ] 16:35:47.470 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:47.470 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 00 28 33 ] 16:35:49.244 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 1C 00 28 33 00 ] 16:35:49.415 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:49.415 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 00 28 33 ] 16:35:51.357 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 0F 00 28 33 00 ] 16:35:51.481 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:51.481 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 0F 00 28 33 ] 16:35:53.451 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 16:35:53.523 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:53.523 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 16:35:55.537 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 F5 FF 28 33 00 ] 16:35:55.583 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:55.583 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 F5 FF 28 33 ] 16:35:57.562 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 E4 FF 28 33 00 ] 16:35:57.700 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:57.700 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 E4 FF 28 33 ] 16:35:59.685 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 CF FF 28 33 00 ] 16:35:59.809 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:59.809 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 CF FF 28 33 ] 16:36:01.790 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A8 FF 28 33 00 ] 16:36:01.931 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:36:01.931 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A8 FF 28 33 ] 16:36:03.871 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 84 FF 28 33 00 ] 16:36:03.948 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:36:03.949 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 84 FF 28 33 ]
Did you feel resistance change when moving the pedals?
Op zo 11 dec. 2022 16:41 schreef le-joebar @.***>:
Now is OK !
16:35:25.068 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 16:35:25.068 -> ----------------- Version 02.5 ------------------ 16:35:25.068 -> Initialise the Bluefruit nRF52 module: Client (Central) 16:35:25.071 -> FTMS and Chars 'initialized' 16:35:25.071 -> CPS and Chars 'initialized' 16:35:25.071 -> CSCS and Chars 'initialized' 16:35:25.071 -> GA and Chars 'initialized' 16:35:25.071 -> DIS and Chars 'initialized' 16:35:25.071 -> Start Scanning for CPS, CSC and FTMS! 16:35:25.071 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 16:35:25.071 -> Timestamp MAC Address Rssi Data 16:35:25.071 -> 000000717 F8:9C:FC:53:5E:49 -64 09-02-16-18-26-18-18-18-0A-18 16:35:25.071 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 16:35:25.071 -> Now checking all Client Services and Characteristics! 16:35:25.071 -> If Mandatory Services Fail --> the Client will disconnect! 16:35:25.071 -> First checking Generic Access and Device Information Services and Characteristics! 16:35:25.229 -> Found Client Generic Access 16:35:25.229 -> -> Client Reads Device Name: [Zwift Hub] 16:35:25.231 -> -> Client Reads Appearance: [1152] 16:35:25.231 -> Found Client Device Information 16:35:25.242 -> -> Client Reads Manufacturer: [Zwift] 16:35:25.242 -> -> Client Reads Model Number: [06] 16:35:25.378 -> -> Client Reads Serial Number: [06-F89CFC535E49] 16:35:25.378 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 16:35:25.425 -> Discovering Client FTM Feature Characteristic ... Found it! 16:35:25.832 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 16:35:25.832 -> Discovering Client FTM Control Point Characteristic ... Found it! 16:35:26.374 -> Discovering Client FTM Status Characteristic ... Found it! 16:35:26.374 -> Discovering Client FTM Training Status Characteristic ... Ready to receive Client FTM Control Point Response Messages 16:35:26.409 -> Ready to receive Client FTM Status values 16:35:26.409 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 16:35:26.409 -> >>> Couldn't enable notify for Client FTM Indoor Bike Data Characteristic. 16:35:26.409 -> >>> Couldn't enable notify for Client CP Measurement Characteristic. 16:35:26.409 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 16:35:26.409 -> >>> Couldn't enable notify for Client CSC Measurement Characteristic. 16:35:26.409 -> Client (Central) is Up and Running! 16:35:26.595 -> Not Found! Not Mandatory 16:35:26.595 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 16:35:26.750 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 16:35:26.750 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 16:35:27.058 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 16:35:27.058 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 16:35:27.291 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 16:35:27.383 -> Discovering Client CP Measurement characteristic ... Found it! 16:35:27.554 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 16:35:27.816 -> Discovering Client CP Feature characteristic ... Found it! 16:35:27.987 -> -> Client Reads Raw CP Feature bytes: [4] [ 00 00 00 00 ] 16:35:27.987 -> Discovering Client CP Sensor Location characteristic ... NOT Found! NOT Mandatory! 16:35:27.987 -> Discovering Cycling Speed and Cadence (CSC) Service ... Not Found! CSC Service is Not Mandatory! 16:35:28.391 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 16:35:28.513 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 16:35:30.519 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 16:35:30.597 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 16:35:32.596 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 16:35:32.673 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 16:35:32.673 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 16:35:34.658 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 16:35:34.734 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:34.769 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 16:35:36.711 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 00 28 33 00 ] 16:35:36.789 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:36.789 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 16:35:38.772 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 16:35:39.099 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:39.099 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 16:35:40.880 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 14 00 28 33 00 ] 16:35:40.958 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:40.958 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 00 28 33 ] 16:35:42.973 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 00 28 33 00 ] 16:35:43.066 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:43.066 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 00 28 33 ] 16:35:45.077 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 25 00 28 33 00 ] 16:35:45.154 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:45.154 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 25 00 28 33 ] 16:35:47.144 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 23 00 28 33 00 ] 16:35:47.470 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:47.470 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 00 28 33 ] 16:35:49.244 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 1C 00 28 33 00 ] 16:35:49.415 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:49.415 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 00 28 33 ] 16:35:51.357 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 0F 00 28 33 00 ] 16:35:51.481 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:51.481 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 0F 00 28 33 ] 16:35:53.451 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 16:35:53.523 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:53.523 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 16:35:55.537 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 F5 FF 28 33 00 ] 16:35:55.583 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:55.583 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 F5 FF 28 33 ] 16:35:57.562 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 E4 FF 28 33 00 ] 16:35:57.700 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:57.700 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 E4 FF 28 33 ] 16:35:59.685 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 CF FF 28 33 00 ] 16:35:59.809 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:35:59.809 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 CF FF 28 33 ] 16:36:01.790 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A8 FF 28 33 00 ] 16:36:01.931 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:36:01.931 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A8 FF 28 33 ] 16:36:03.871 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 84 FF 28 33 00 ] 16:36:03.948 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 16:36:03.949 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 84 FF 28 33 ]
— Reply to this email directly, view it on GitHub https://github.com/Berg0162/simcline/issues/7#issuecomment-1345586549, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANS5LSUED4ZI4LVDL3XRNZLWMXY23ANCNFSM6AAAAAASZDERFE . You are receiving this because you authored the thread.Message ID: @.***>
At the first test I turned the pedals with my hand and I would say yes, I think it was decreasing! On the second test I did not pay attention!
Dear Joel, It looks like a successful run now! Feather and Trainer are connected, services/characteristics were detected or not. Focus was until now on establishing the connection, but what I am still missing is the response of the trainer to the resistance simulation parameters that the client is regularly sending...and how these data are decoded by the Feather..... This is critical information!
6) Move the trainer pedals and notice/feel changes in resistance... The Client sends Resistance Parameters to the Trainer that coincide with the first 5 minutes of the Zwift Volcano Circuit! 7) Inspect the info presented by Serial Monitor.....
This is what I miss in the output: -> Client Rec'd Raw FTM Indoor Bike Data: [##] [#####################] Have a careful look at the complete debug output file that I have uploaded and notice the comment (physical experience) at the start of the tester's output file! If you want to be sure communication is working flawless you have to do the pedaling on the bike, Zwift Hub is clearly not doing it by itself! Or it is simply NOT working.... How do we know? See Output Good luck! Jörgen.
Hello Jorghen,
Here are the results after several connection attempts I tried several ways to connect and wake up the services.
I have never managed to do it again 2 times in a row!!!
So I don't know how to make a successful connection!!!
But we have successful results!! And I really felt the different resistances.
20:01:34.256 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 20:01:34.256 -> ----------------- Version 02.5 ------------------ 20:01:34.256 -> Initialise the Bluefruit nRF52 module: Client (Central) 20:01:34.348 -> FTMS and Chars 'initialized' 20:01:34.348 -> CPS and Chars 'initialized' 20:01:34.348 -> CSCS and Chars 'initialized' 20:01:34.348 -> GA and Chars 'initialized' 20:01:34.348 -> DIS and Chars 'initialized' 20:01:34.348 -> Start Scanning for CPS, CSC and FTMS! 20:01:35.186 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 20:01:35.186 -> Timestamp MAC Address Rssi Data 20:01:35.186 -> 000002583 F8:9C:FC:53:5E:49 -69 09-02-16-18-26-18-18-18-0A-18 20:01:35.277 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 20:01:35.277 -> Now checking all Client Services and Characteristics! 20:01:35.277 -> If Mandatory Services Fail --> the Client will disconnect! 20:01:35.277 -> First checking Generic Access and Device Information Services and Characteristics! 20:01:35.494 -> Found Client Generic Access 20:01:35.494 -> -> Client Reads Device Name: [Zwift Hub] 20:01:35.815 -> -> Client Reads Appearance: [1152] 20:01:35.815 -> Found Client Device Information 20:01:36.219 -> -> Client Reads Manufacturer: [Zwift] 20:01:36.219 -> -> Client Reads Model Number: [06] 20:01:36.389 -> -> Client Reads Serial Number: [06-F89CFC535E49] 20:01:36.389 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 20:01:36.467 -> Discovering Client FTM Feature Characteristic ... Found it! 20:01:36.653 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 20:01:36.653 -> Discovering Client FTM Control Point Characteristic ... Not Found! 20:01:36.653 -> Disconnecting since Client FTM Control Point Characteristic is mandatory! 20:01:36.699 -> Client Disconnected, reason = 0x16 20:01:36.699 -> >>> Restart the Feather nRF52 Client for a new run! <<< 20:01:37.689 -> Stopped!
20:02:38.186 -> FTMS and Chars 'initialized' 20:02:38.186 -> CPS and Chars 'initialized' 20:02:38.186 -> CSCS and Chars 'initialized' 20:02:38.186 -> GA and Chars 'initialized' 20:02:38.186 -> DIS and Chars 'initialized' 20:02:38.186 -> Start Scanning for CPS, CSC and FTMS! 20:02:38.186 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 20:02:38.186 -> Timestamp MAC Address Rssi Data 20:02:38.186 -> 000001612 F8:9C:FC:53:5E:49 -67 09-02-16-18-26-18-18-18-0A-18 20:02:38.418 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [] MAC Address: F8:9C:FC:53:5E:49 20:02:38.418 -> Now checking all Client Services and Characteristics! 20:02:38.418 -> If Mandatory Services Fail --> the Client will disconnect! 20:02:38.418 -> First checking Generic Access and Device Information Services and Characteristics! 20:02:38.418 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Not Found! 20:02:38.418 -> Disconnecting since Client FTM Service is mandatory! 20:02:38.418 -> Client Disconnected, reason = 0x3E 20:02:38.418 -> >>> Restart the Feather nRF52 Client for a new run! <<< 20:02:39.988 -> Stopped!
20:03:28.928 -> FTMS and Chars 'initialized' 20:03:28.928 -> CPS and Chars 'initialized' 20:03:28.928 -> CSCS and Chars 'initialized' 20:03:28.928 -> GA and Chars 'initialized' 20:03:28.928 -> DIS and Chars 'initialized' 20:03:28.928 -> Start Scanning for CPS, CSC and FTMS! 20:03:28.928 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 20:03:28.928 -> Timestamp MAC Address Rssi Data 20:03:28.928 -> 000001315 F8:9C:FC:53:5E:49 -67 09-02-16-18-26-18-18-18-0A-18 20:03:28.943 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [] MAC Address: F8:9C:FC:53:5E:49 20:03:28.943 -> Now checking all Client Services and Characteristics! 20:03:28.943 -> If Mandatory Services Fail --> the Client will disconnect! 20:03:28.943 -> First checking Generic Access and Device Information Services and Characteristics! 20:03:28.943 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Not Found! 20:03:28.943 -> Disconnecting since Client FTM Service is mandatory! 20:03:28.943 -> Client Disconnected, reason = 0x3E 20:03:28.943 -> >>> Restart the Feather nRF52 Client for a new run! <<< 20:03:30.705 -> Stopped!
20:15:52.131 -> ----------------- Version 02.5 ------------------ 20:15:52.131 -> Initialise the Bluefruit nRF52 module: Client (Central) 20:15:52.135 -> FTMS and Chars 'initialized' 20:15:52.135 -> CPS and Chars 'initialized' 20:15:52.135 -> CSCS and Chars 'initialized' 20:15:52.135 -> GA and Chars 'initialized' 20:15:52.135 -> DIS and Chars 'initialized' 20:15:52.135 -> Start Scanning for CPS, CSC and FTMS! 20:16:41.655 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 20:16:41.655 -> Timestamp MAC Address Rssi Data 20:16:41.655 -> 000052631 F8:9C:FC:53:5E:49 -63 09-02-16-18-26-18-18-18-0A-18 20:16:41.870 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 20:16:41.870 -> Now checking all Client Services and Characteristics! 20:16:41.870 -> If Mandatory Services Fail --> the Client will disconnect! 20:16:41.870 -> First checking Generic Access and Device Information Services and Characteristics! 20:16:42.087 -> Found Client Generic Access 20:16:42.087 -> -> Client Reads Device Name: [Zwift Hub] 20:16:42.351 -> -> Client Reads Appearance: [1152] 20:16:42.351 -> Found Client Device Information 20:16:42.816 -> -> Client Reads Manufacturer: [Zwift] 20:16:42.816 -> -> Client Reads Model Number: [06] 20:16:42.986 -> -> Client Reads Serial Number: [06-F89CFC535E49] 20:16:42.987 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 20:16:43.112 -> Discovering Client FTM Feature Characteristic ... Found it! 20:16:43.249 -> -> Client Reads Raw FTM Feature bytes: [8] [ 87 44 00 00 0C E0 00 00 ] 20:16:43.249 -> Discovering Client FTM Control Point Characteristic ... Found it! 20:16:43.974 -> Discovering Client FTM Status Characteristic ... Found it! 20:16:43.974 -> Discovering Client FTM Training Status Characteristic ... Ready to receive Client FTM Control Point Response Messages 20:16:44.310 -> Ready to receive Client FTM Status values 20:16:44.310 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 20:16:44.310 -> >>> Couldn't enable notify for Client FTM Indoor Bike Data Characteristic. 20:16:44.310 -> >>> Couldn't enable notify for Client CP Measurement Characteristic. 20:16:44.310 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 20:16:44.310 -> >>> Couldn't enable notify for Client CSC Measurement Characteristic. 20:16:44.310 -> Client (Central) is Up and Running! 20:16:44.346 -> Not Found! Not Mandatory 20:16:44.346 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 20:16:44.516 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 20:16:44.516 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 20:16:44.870 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 20:16:44.870 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 20:16:45.056 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 20:16:45.149 -> Discovering Client CP Measurement characteristic ... Found it! 20:16:45.334 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 20:16:45.569 -> Discovering Client CP Feature characteristic ... Found it! 20:16:45.752 -> -> Client Reads Raw CP Feature bytes: [4] [ 00 00 00 00 ] 20:16:45.752 -> Discovering Client CP Sensor Location characteristic ... NOT Found! NOT Mandatory! 20:16:45.752 -> Discovering Cycling Speed and Cadence (CSC) Service ... Not Found! CSC Service is Not Mandatory! 20:16:46.309 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 20:16:46.401 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 20:16:48.356 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 20:16:48.450 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 20:16:50.443 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 20:16:50.475 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 20:16:50.475 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 20:16:52.514 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 20:16:52.546 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:16:52.546 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 20:16:54.573 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 00 28 33 00 ] 20:16:54.757 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:16:54.803 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 20:16:56.652 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 20:16:56.839 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:16:56.839 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 20:16:58.772 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 14 00 28 33 00 ] 20:16:58.943 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:16:58.943 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 00 28 33 ] 20:17:00.869 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 00 28 33 00 ] 20:17:00.961 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:00.961 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 00 28 33 ] 20:17:02.957 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 25 00 28 33 00 ] 20:17:03.052 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:03.052 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 25 00 28 33 ] 20:17:05.040 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 23 00 28 33 00 ] 20:17:05.072 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:05.072 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 00 28 33 ] 20:17:07.112 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 1C 00 28 33 00 ] 20:17:07.342 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:07.342 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 00 28 33 ] 20:17:09.211 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 0F 00 28 33 00 ] 20:17:09.289 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:09.289 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 0F 00 28 33 ] 20:17:11.266 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 20:17:11.360 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:11.360 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 20:17:13.362 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 F5 FF 28 33 00 ] 20:17:13.473 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:13.473 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 F5 FF 28 33 ] 20:17:15.452 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 E4 FF 28 33 00 ] 20:17:15.545 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:15.545 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 E4 FF 28 33 ] 20:17:17.539 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 CF FF 28 33 00 ] 20:17:17.571 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:17.571 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 CF FF 28 33 ] 20:17:19.604 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A8 FF 28 33 00 ] 20:17:19.715 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:19.715 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A8 FF 28 33 ] 20:17:21.694 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 84 FF 28 33 00 ] 20:17:21.834 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:21.834 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 84 FF 28 33 ] 20:17:23.799 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 FF 28 33 00 ] 20:17:24.109 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:24.109 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 FF 28 33 ] 20:17:25.913 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5D FF 28 33 00 ] 20:17:26.007 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:26.007 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5D FF 28 33 ] 20:17:28.006 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5E FF 28 33 00 ] 20:17:28.053 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:28.053 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5E FF 28 33 ] 20:17:30.047 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 6F FF 28 33 00 ] 20:17:30.111 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:30.111 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 6F FF 28 33 ] 20:17:32.153 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 8A FF 28 33 00 ] 20:17:32.230 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:32.230 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8A FF 28 33 ] 20:17:34.207 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 B8 FF 28 33 00 ] 20:17:34.377 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:34.377 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 B8 FF 28 33 ] 20:17:36.308 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 20:17:36.433 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:36.433 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 20:17:38.431 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A2 00 28 33 00 ] 20:17:38.510 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:38.510 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A2 00 28 33 ] 20:17:40.534 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 01 28 33 00 ] 20:17:40.643 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:40.643 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 01 28 33 ] 20:17:42.606 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 4F 01 28 33 00 ] 20:17:42.682 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:42.682 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 4F 01 28 33 ] 20:17:44.682 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 01 28 33 00 ] 20:17:44.852 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:44.852 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 01 28 33 ] 20:17:46.768 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 57 FF 28 33 00 ] 20:17:46.845 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:46.845 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 57 FF 28 33 ] 20:17:48.847 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 08 00 00 00 00 00 00 00 ] 20:17:49.112 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 08 03 ] 20:17:50.939 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 01 00 00 00 00 00 00 00 ] 20:17:51.063 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 01 01 ] 20:17:51.063 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 01 ] 20:17:53.041 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 20:17:53.088 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 20:17:55.102 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 20:17:55.195 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 20:17:57.185 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 20:17:57.510 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 20:17:57.510 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 20:17:59.284 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 20:17:59.331 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:17:59.331 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 20:18:01.351 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 00 28 33 00 ] 20:18:01.567 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:01.567 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 20:18:03.450 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 20:18:03.528 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:03.528 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 20:18:05.512 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 14 00 28 33 00 ] 20:18:05.590 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:05.590 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 00 28 33 ] 20:18:07.627 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 00 28 33 00 ] 20:18:07.673 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:07.673 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 00 28 33 ] 20:18:09.683 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 25 00 28 33 00 ] 20:18:09.730 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:09.730 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 25 00 28 33 ] 20:18:11.708 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 23 00 28 33 00 ] 20:18:11.802 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:11.802 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 00 28 33 ] 20:18:13.746 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 1C 00 28 33 00 ] 20:18:14.072 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:14.072 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 00 28 33 ] 20:18:15.867 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 0F 00 28 33 00 ] 20:18:15.945 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:15.945 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 0F 00 28 33 ] 20:18:17.918 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 20:18:18.089 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:18.089 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 20:18:20.050 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 F5 FF 28 33 00 ] 20:18:20.096 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:20.096 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 F5 FF 28 33 ] 20:18:22.115 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 E4 FF 28 33 00 ] 20:18:22.207 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:22.207 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 E4 FF 28 33 ] 20:18:24.202 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 CF FF 28 33 00 ] 20:18:24.249 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:24.249 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 CF FF 28 33 ] 20:18:26.259 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A8 FF 28 33 00 ] 20:18:26.508 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:26.508 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A8 FF 28 33 ] 20:18:28.349 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 84 FF 28 33 00 ] 20:18:28.551 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:28.551 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 84 FF 28 33 ] 20:18:30.463 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 FF 28 33 00 ] 20:18:30.604 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:30.604 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 FF 28 33 ] 20:18:32.565 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5D FF 28 33 00 ] 20:18:32.643 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:32.643 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5D FF 28 33 ] 20:18:34.646 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5E FF 28 33 00 ] 20:18:34.678 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:34.678 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5E FF 28 33 ] 20:18:36.693 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 6F FF 28 33 00 ] 20:18:36.769 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:36.769 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 6F FF 28 33 ] 20:18:38.750 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 8A FF 28 33 00 ] 20:18:39.060 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:39.060 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8A FF 28 33 ] 20:18:40.868 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 B8 FF 28 33 00 ] 20:18:41.054 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:41.054 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 B8 FF 28 33 ] 20:18:42.968 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 20:18:43.187 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:43.187 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 20:18:45.072 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A2 00 28 33 00 ] 20:18:45.149 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:45.149 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A2 00 28 33 ] 20:18:47.124 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 01 28 33 00 ] 20:18:47.248 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:47.248 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 01 28 33 ] 20:18:49.238 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 4F 01 28 33 00 ] 20:18:49.332 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:49.332 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 4F 01 28 33 ] 20:18:51.311 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 01 28 33 00 ] 20:18:51.452 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:51.452 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 01 28 33 ] 20:18:53.427 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 57 FF 28 33 00 ] 20:18:53.613 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:18:53.613 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 57 FF 28 33 ] 20:18:55.519 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 08 00 00 00 00 00 00 00 ] 20:18:55.550 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 08 03 ] 20:18:57.571 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 01 00 00 00 00 00 00 00 ] 20:18:57.681 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 01 01 ] 20:18:57.681 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 01 ] 20:18:59.669 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 20:18:59.747 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 20:19:01.734 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 20:19:01.827 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 20:19:03.840 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 20:19:04.105 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 20:19:04.105 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 20:19:05.947 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 20:19:06.116 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:06.116 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 20:19:08.042 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 00 28 33 00 ] 20:19:08.165 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:08.165 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 20:19:10.145 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 20:19:10.208 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:10.253 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 20:19:12.243 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 14 00 28 33 00 ] 20:19:12.321 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:12.321 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 00 28 33 ] 20:19:14.328 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 00 28 33 00 ] 20:19:14.406 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:14.406 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 00 28 33 ] 20:19:16.397 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 25 00 28 33 00 ] 20:19:16.429 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:16.429 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 25 00 28 33 ] 20:19:18.464 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 23 00 28 33 00 ] 20:19:18.541 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:18.541 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 00 28 33 ] 20:19:20.534 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 1C 00 28 33 00 ] 20:19:20.783 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:20.783 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 00 28 33 ] 20:19:22.653 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 0F 00 28 33 00 ] 20:19:22.775 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:22.775 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 0F 00 28 33 ] 20:19:24.753 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 20:19:24.831 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:24.831 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 20:19:26.832 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 F5 FF 28 33 00 ] 20:19:26.971 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:26.971 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 F5 FF 28 33 ] 20:19:28.926 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 E4 FF 28 33 00 ] 20:19:29.097 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:29.097 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 E4 FF 28 33 ] 20:19:31.013 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 CF FF 28 33 00 ] 20:19:31.106 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:31.106 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 CF FF 28 33 ] 20:19:33.127 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A8 FF 28 33 00 ] 20:19:33.329 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:33.329 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A8 FF 28 33 ] 20:19:35.219 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 84 FF 28 33 00 ] 20:19:35.265 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:35.265 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 84 FF 28 33 ] 20:19:37.278 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 FF 28 33 00 ] 20:19:37.356 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:37.356 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 FF 28 33 ] 20:19:39.354 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5D FF 28 33 00 ] 20:19:39.433 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:39.433 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5D FF 28 33 ] 20:19:41.425 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5E FF 28 33 00 ] 20:19:41.457 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:41.457 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5E FF 28 33 ] 20:19:43.492 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 6F FF 28 33 00 ] 20:19:43.723 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:43.723 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 6F FF 28 33 ] 20:19:45.581 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 8A FF 28 33 00 ] 20:19:45.750 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:45.750 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8A FF 28 33 ] 20:19:47.678 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 B8 FF 28 33 00 ] 20:19:47.818 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:47.818 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 B8 FF 28 33 ] 20:19:49.788 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 20:19:49.865 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:49.865 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 20:19:51.859 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A2 00 28 33 00 ] 20:19:51.950 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:51.950 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A2 00 28 33 ] 20:19:53.940 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 01 28 33 00 ] 20:19:54.033 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:54.033 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 01 28 33 ] 20:19:56.027 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 4F 01 28 33 00 ] 20:19:56.462 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:56.462 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 4F 01 28 33 ] 20:19:58.105 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 01 28 33 00 ] 20:19:58.275 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:19:58.322 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 01 28 33 ] 20:20:00.213 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 57 FF 28 33 00 ] 20:20:00.290 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:00.337 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 57 FF 28 33 ] 20:20:02.267 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 08 00 00 00 00 00 00 00 ] 20:20:02.360 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 08 03 ] 20:20:04.371 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 01 00 00 00 00 00 00 00 ] 20:20:04.417 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 01 01 ] 20:20:04.417 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 01 ] 20:20:06.425 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 20:20:06.457 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 20:20:08.481 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 20:20:08.527 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 20:20:10.546 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 20:20:10.624 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 20:20:10.624 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 20:20:12.620 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 20:20:12.698 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:12.698 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 20:20:14.712 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 00 28 33 00 ] 20:20:14.806 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:14.806 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 20:20:16.785 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 20:20:16.862 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:16.862 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 20:20:18.871 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 14 00 28 33 00 ] 20:20:18.980 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:18.980 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 00 28 33 ] 20:20:20.978 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 00 28 33 00 ] 20:20:21.070 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:21.070 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 00 28 33 ] 20:20:23.027 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 25 00 28 33 00 ] 20:20:23.396 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:23.396 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 25 00 28 33 ] 20:20:25.145 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 23 00 28 33 00 ] 20:20:25.223 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:25.223 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 00 28 33 ] 20:20:27.225 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 1C 00 28 33 00 ] 20:20:27.365 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:27.365 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 00 28 33 ] 20:20:29.329 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 0F 00 28 33 00 ] 20:20:29.376 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:29.376 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 0F 00 28 33 ] 20:20:31.379 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 20:20:31.469 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:31.469 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 20:20:33.446 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 F5 FF 28 33 00 ] 20:20:33.569 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:33.569 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 F5 FF 28 33 ] 20:20:35.559 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 E4 FF 28 33 00 ] 20:20:35.591 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:35.591 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 E4 FF 28 33 ] 20:20:37.619 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 CF FF 28 33 00 ] 20:20:37.852 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:37.852 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 CF FF 28 33 ] 20:20:39.714 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A8 FF 28 33 00 ] 20:20:39.977 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:39.977 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A8 FF 28 33 ] 20:20:41.827 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 84 FF 28 33 00 ] 20:20:41.966 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:41.966 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 84 FF 28 33 ] 20:20:43.925 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 FF 28 33 00 ] 20:20:43.973 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:43.973 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 FF 28 33 ] 20:20:45.950 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5D FF 28 33 00 ] 20:20:46.091 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:46.091 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5D FF 28 33 ] 20:20:48.091 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5E FF 28 33 00 ] 20:20:48.138 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:48.138 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5E FF 28 33 ] 20:20:50.141 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 6F FF 28 33 00 ] 20:20:50.188 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:50.188 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 6F FF 28 33 ] 20:20:52.205 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 8A FF 28 33 00 ] 20:20:52.513 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 20:20:52.513 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8A FF 28 33 ]
Thanks,
Joel
Dear Joel, This is different from how the Elite Direto is responding, but that seems not to be a problem since you experience changing resistance. I have uploaded a new version that hopefully accounts for the slightly different timing of the itsybitsy.. (???) and should avoid message cluttering during connection phase. Furthermore I have introduced a Request for Machine Control in an early stage of the connection procedure, may be this helps waking up your trainer.... Best wishes, Jörgen.
Hello Jorghen,
I ordered the Feather but it hasn't arrived yet.
I had also started modifying the FTMS_Client_V25 to wait for feedback from everyone's services.
So I'm going to stop and try V.26 tonight. I'll get back to you with the results.
I received the Bluethoot BLE dongle and tested the FTMS_Server_V.22. It works so my key is good for the future.
Friendship Joel,
I looked at your version V.26 I saw you change the time from 2.5 seconds to 5. Personally I was looking at a different solution which consisted of: Example: if ( client_FitnessMachine_Service.discover(conn_handle) ) If false to restart the complete request and this for all the services which must answer! I don't know if this is the right solution but its a lot of work. if ( client_FitnessMachine_Service.discover(conn_handle) ) If False to restart the complete request and this for all the services that must respond! I don't know if this is the right solution but its a lot of work.
Hello Jörghen,
Here are the results: Unfortunately V0.26 does not work better than the others. Here is the result of V0.25 modified by me.
And the code below
18:07:13.207 -> GA and Chars 'initialized' 18:07:13.207 -> DIS and Chars 'initialized' 18:07:13.207 -> Start Scanning for CPS, CSC and FTMS! 18:07:13.207 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 18:07:13.207 -> Timestamp MAC Address Rssi Data 18:07:13.207 -> 000001374 F8:9C:FC:53:5E:49 -62 09-02-16-18-26-18-18-18-0A-18 18:07:13.207 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 18:07:13.207 -> Now checking all Client Services and Characteristics! 18:07:13.207 -> If Mandatory Services Fail --> the Client will disconnect! 18:07:13.207 -> First checking Generic Access and Device Information Services and Characteristics! 18:07:13.461 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 18:07:13.461 -> Discovering Client FTM Feature Characteristic ... Discovering Client FTM Control Point Characteristic ... Found it! 18:07:14.047 -> Discovering Client FTM Status Characteristic ... Found it! 18:07:14.601 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 18:07:14.864 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 18:07:15.220 -> Ready to receive Client FTM Control Point Response Messages 18:07:15.267 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 18:07:15.267 -> Discovering Client FTM Supported Power Range Characteristic ... Ready to receive Client FTM Status values 18:07:15.267 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 18:07:15.267 -> >>> Couldn't enable notify for Client FTM Indoor Bike Data Characteristic. 18:07:15.267 -> >>> Couldn't enable notify for Client CP Measurement Characteristic. 18:07:15.267 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 18:07:15.267 -> >>> Couldn't enable notify for Client CSC Measurement Characteristic. 18:07:15.267 -> Client (Central) is Up and Running! 18:07:15.392 -> Found it! 18:07:15.484 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 00 00 00 00 ] 18:07:15.484 -> Discovering Client FTM Indoor Bike Data Characteristic ... Not Found! Not Mandatory 18:07:15.484 -> Discovering Client Cycling Power (CP) Service ... Not Found! 18:07:15.484 -> Disconnecting since Client Cyling Power Service is mandatory! 18:07:15.531 -> Client Disconnected, reason = 0x16 18:07:15.531 -> >>> Restart the Feather nRF52 Client for a new run! <<< 18:07:26.723 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 18:07:26.723 -> ----------------- Version 02.5 ------------------ 18:07:26.723 -> Initialise the Bluefruit nRF52 module: Client (Central) 18:07:26.724 -> FTMS and Chars 'initialized' 18:07:26.724 -> CPS and Chars 'initialized' 18:07:26.724 -> CSCS and Chars 'initialized' 18:07:26.724 -> GA and Chars 'initialized' 18:07:26.724 -> DIS and Chars 'initialized' 18:07:26.724 -> Start Scanning for CPS, CSC and FTMS! 18:07:26.724 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 18:07:26.724 -> Timestamp MAC Address Rssi Data 18:07:26.724 -> 000001192 F8:9C:FC:53:5E:49 -62 09-02-16-18-26-18-18-18-0A-18 18:07:26.743 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 18:07:26.743 -> Now checking all Client Services and Characteristics! 18:07:26.743 -> If Mandatory Services Fail --> the Client will disconnect! 18:07:26.743 -> First checking Generic Access and Device Information Services and Characteristics! 18:07:26.747 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 18:07:26.747 -> Discovering Client FTM Feature Characteristic ... Discovering Client FTM Control Point Characteristic ... Found it! 18:07:27.137 -> Discovering Client FTM Status Characteristic ... Found it! 18:07:27.555 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 18:07:27.912 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 18:07:28.129 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 18:07:28.129 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 18:07:28.346 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 18:07:28.346 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 18:07:28.639 -> Discovering Client Cycling Power (CP) Service ... Ready to receive Client FTM Control Point Response Messages 18:07:28.731 -> Found it! CPS Max Payload: 20 Data Length: 27 18:07:28.731 -> Discovering Client CP Measurement characteristic ... Ready to receive Client FTM Status values 18:07:28.731 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 18:07:28.809 -> Ready to receive Client FTM Indoor Bike Data values 18:07:28.809 -> Found it! 18:07:28.809 -> Discovering Client CP Control Point characteristic ... Ready to receive Client CP Measurement values 18:07:28.809 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 18:07:28.809 -> >>> Couldn't enable notify for Client CSC Measurement Characteristic. 18:07:28.809 -> Client (Central) is Up and Running! 18:07:28.932 -> Not Found! NOT Mandatory! 18:07:28.932 -> Discovering Client CP Feature characteristic ... Found it! 18:07:29.446 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 18:07:29.446 -> Wheel revolution data supported 18:07:29.446 -> Crank revolution data supported 18:07:29.446 -> Discovering Client CP Sensor Location characteristic ... Found it! 18:07:29.646 -> -> Client Reads CP Location Sensor: Loc#: 0 Other 18:07:29.646 -> Discovering Cycling Speed and Cadence (CSC) Service ... Not Found! CSC Service is Not Mandatory! 18:07:29.646 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 18:07:29.646 -> Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 18:07:30.031 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 18:07:30.031 -> Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 18:07:30.819 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 18:07:30.864 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 18:07:31.036 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 18:07:31.036 -> Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 18:07:32.006 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 18:07:32.006 -> Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 18:07:32.870 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 18:07:32.916 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 18:07:33.195 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 18:07:33.195 -> Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 18:07:34.074 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 18:07:34.074 -> Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 18:07:34.925 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 18:07:35.266 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 18:07:35.266 -> Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 18:07:35.313 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 18:07:35.313 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 18:07:36.008 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 ] 18:07:36.008 -> Speed: 0 KPH Instantaneous Cadence: 0 RPM Average Cadence: 0 RPM Total Distance: 0 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:07:37.011 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 ] 18:07:37.011 -> Speed: 0 KPH Instantaneous Cadence: 0 RPM Average Cadence: 0 RPM Total Distance: 0 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:07:37.011 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 18:07:37.213 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:07:37.213 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 18:07:37.972 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 ] 18:07:38.018 -> Speed: 0 KPH Instantaneous Cadence: 0 RPM Average Cadence: 0 RPM Total Distance: 0 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:07:38.984 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 ] 18:07:38.984 -> Speed: 0 KPH Instantaneous Cadence: 0 RPM Average Cadence: 0 RPM Total Distance: 0 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:07:39.110 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 00 28 33 00 ] 18:07:39.188 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:07:39.188 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 18:07:39.989 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 ] 18:07:39.989 -> Speed: 0 KPH Instantaneous Cadence: 0 RPM Average Cadence: 0 RPM Total Distance: 0 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:07:41.147 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 ] 18:07:41.147 -> Speed: 0 KPH Instantaneous Cadence: 0 RPM Average Cadence: 0 RPM Total Distance: 0 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:07:41.193 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 18:07:41.286 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:07:41.286 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 18:07:41.978 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 ] 18:07:41.978 -> Speed: 0 KPH Instantaneous Cadence: 0 RPM Average Cadence: 0 RPM Total Distance: 0 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:07:43.072 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 09 05 88 00 00 00 00 00 03 00 00 14 00 78 00 0F 00 00 ] 18:07:43.072 -> Speed: 12 KPH Instantaneous Cadence: 68 RPM Average Cadence: 0 RPM Total Distance: 196608 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 120 Watt Heart Rate: 15 HBM 18:07:43.289 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 14 00 28 33 00 ] 18:07:43.321 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:07:43.321 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 00 28 33 ] 18:07:44.015 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A3 06 1A 01 00 00 00 00 07 00 00 14 00 D5 00 25 00 00 ] 18:07:44.015 -> Speed: 16 KPH Instantaneous Cadence: 141 RPM Average Cadence: 0 RPM Total Distance: 458752 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 213 Watt Heart Rate: 37 HBM 18:07:45.252 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 B5 06 8F 01 00 00 00 00 0B 00 00 14 00 91 00 2F 00 00 ] 18:07:45.252 -> Speed: 17 KPH Instantaneous Cadence: 199 RPM Average Cadence: 0 RPM Total Distance: 720896 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 145 Watt Heart Rate: 47 HBM 18:07:45.344 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 00 28 33 00 ] 18:07:45.390 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:07:45.390 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 00 28 33 ] 18:07:46.008 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 15 07 EF 01 36 00 04 00 0F 00 00 14 00 BE 00 3C 00 00 ] 18:07:46.008 -> Speed: 18 KPH Instantaneous Cadence: 247 RPM Average Cadence: 27 RPM Total Distance: 983044 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 190 Watt Heart Rate: 60 HBM 18:07:46.999 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 B4 07 5D 02 56 00 0B 00 14 00 00 14 00 C5 00 48 00 00 ] 18:07:46.999 -> Speed: 19 KPH Instantaneous Cadence: 302 RPM Average Cadence: 43 RPM Total Distance: 1310731 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 197 Watt Heart Rate: 72 HBM 18:07:47.416 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 25 00 28 33 00 ] 18:07:47.667 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:07:47.667 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 25 00 28 33 ] 18:07:48.011 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 15 08 BA 02 66 00 12 00 19 00 00 14 00 A4 00 4F 00 00 ] 18:07:48.011 -> Speed: 20 KPH Instantaneous Cadence: 349 RPM Average Cadence: 51 RPM Total Distance: 1638418 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 164 Watt Heart Rate: 79 HBM 18:07:49.075 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 6C 08 09 03 70 00 19 00 1E 00 00 14 00 9D 00 54 00 00 ] 18:07:49.075 -> Speed: 21 KPH Instantaneous Cadence: 388 RPM Average Cadence: 56 RPM Total Distance: 1966105 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 157 Watt Heart Rate: 84 HBM 18:07:49.490 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 23 00 28 33 00 ] 18:07:49.568 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:07:49.568 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 00 28 33 ] 18:07:50.015 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 C7 08 67 03 76 00 1F 00 24 00 00 14 00 99 00 59 00 00 ] 18:07:50.015 -> Speed: 22 KPH Instantaneous Cadence: 435 RPM Average Cadence: 59 RPM Total Distance: 2359327 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 153 Watt Heart Rate: 89 HBM 18:07:51.031 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 4D 09 B8 03 7A 00 25 00 2A 00 00 14 00 8E 00 5C 00 00 ] 18:07:51.031 -> Speed: 23 KPH Instantaneous Cadence: 476 RPM Average Cadence: 61 RPM Total Distance: 2752549 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 142 Watt Heart Rate: 92 HBM 18:07:51.570 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 1C 00 28 33 00 ] 18:07:51.849 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:07:51.849 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 00 28 33 ] 18:07:51.973 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 70 09 00 04 80 00 2A 00 30 00 00 14 00 89 00 5F 00 00 ] 18:07:51.973 -> Speed: 24 KPH Instantaneous Cadence: 512 RPM Average Cadence: 64 RPM Total Distance: 3145770 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 137 Watt Heart Rate: 95 HBM 18:07:52.992 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 5E 09 40 04 86 00 2F 00 36 00 00 14 00 85 00 61 00 00 ] 18:07:52.992 -> Speed: 23 KPH Instantaneous Cadence: 544 RPM Average Cadence: 67 RPM Total Distance: 3538991 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 133 Watt Heart Rate: 97 HBM 18:07:53.670 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 0F 00 28 33 00 ] 18:07:53.748 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:07:53.748 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 0F 00 28 33 ] 18:07:53.978 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 65 09 7A 04 88 00 34 00 3C 00 00 14 00 78 00 62 00 00 ] 18:07:53.978 -> Speed: 24 KPH Instantaneous Cadence: 573 RPM Average Cadence: 68 RPM Total Distance: 3932212 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 120 Watt Heart Rate: 98 HBM 18:07:54.980 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 87 09 AD 04 8A 00 38 00 42 00 00 14 00 70 00 63 00 00 ] 18:07:54.980 -> Speed: 24 KPH Instantaneous Cadence: 598 RPM Average Cadence: 69 RPM Total Distance: 4325432 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 112 Watt Heart Rate: 99 HBM 18:07:55.749 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 18:07:55.886 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:07:55.886 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 18:07:56.009 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 5E 09 DC 04 8A 00 3C 00 48 00 00 14 00 5D 00 62 00 00 ] 18:07:56.009 -> Speed: 23 KPH Instantaneous Cadence: 622 RPM Average Cadence: 69 RPM Total Distance: 4718652 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 93 Watt Heart Rate: 98 HBM 18:07:57.015 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A8 09 06 05 8C 00 40 00 4E 00 00 14 00 70 00 63 00 00 ] 18:07:57.015 -> Speed: 24 KPH Instantaneous Cadence: 643 RPM Average Cadence: 70 RPM Total Distance: 5111872 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 112 Watt Heart Rate: 99 HBM 18:07:57.849 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 F5 FF 28 33 00 ] 18:07:57.927 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:07:57.927 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 F5 FF 28 33 ] 18:07:57.974 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 0A 3D 05 8C 00 43 00 55 00 00 14 00 74 00 64 00 00 ] 18:07:57.974 -> Speed: 25 KPH Instantaneous Cadence: 670 RPM Average Cadence: 70 RPM Total Distance: 5570627 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 116 Watt Heart Rate: 100 HBM 18:07:59.038 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 D4 09 60 05 90 00 46 00 5B 00 00 14 00 7D 00 65 00 00 ] 18:07:59.038 -> Speed: 25 KPH Instantaneous Cadence: 688 RPM Average Cadence: 72 RPM Total Distance: 5963846 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 125 Watt Heart Rate: 101 HBM 18:07:59.950 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 E4 FF 28 33 00 ] 18:07:59.997 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:07:59.997 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 E4 FF 28 33 ] 18:07:59.997 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 23 0A 8E 05 92 00 49 00 62 00 00 14 00 75 00 65 00 00 ] 18:07:59.997 -> Speed: 25 KPH Instantaneous Cadence: 711 RPM Average Cadence: 73 RPM Total Distance: 6422601 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 117 Watt Heart Rate: 101 HBM 18:08:01.066 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 0D 0A B9 05 92 00 4C 00 69 00 00 14 00 6B 00 66 00 00 ] 18:08:01.066 -> Speed: 25 KPH Instantaneous Cadence: 732 RPM Average Cadence: 73 RPM Total Distance: 6881356 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 107 Watt Heart Rate: 102 HBM 18:08:01.990 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 4F 0A E1 05 94 00 4E 00 70 00 00 14 00 6C 00 66 00 00 ] 18:08:01.990 -> Speed: 26 KPH Instantaneous Cadence: 752 RPM Average Cadence: 74 RPM Total Distance: 7340110 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 108 Watt Heart Rate: 102 HBM 18:08:01.990 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 CF FF 28 33 00 ] 18:08:02.113 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:02.113 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 CF FF 28 33 ] 18:08:02.993 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 28 0A 06 06 94 00 51 00 77 00 00 14 00 63 00 66 00 00 ] 18:08:02.993 -> Speed: 26 KPH Instantaneous Cadence: 771 RPM Average Cadence: 74 RPM Total Distance: 7798865 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 99 Watt Heart Rate: 102 HBM 18:08:04.087 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A8 FF 28 33 00 ] 18:08:04.211 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 62 0A 28 06 98 00 53 00 7E 00 00 14 00 5A 00 65 00 00 ] 18:08:04.211 -> Speed: 26 KPH Instantaneous Cadence: 788 RPM Average Cadence: 76 RPM Total Distance: 8257619 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 90 Watt Heart Rate: 101 HBM 18:08:04.303 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:04.303 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A8 FF 28 33 ] 18:08:04.996 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 2E 0A 48 06 96 00 56 00 85 00 00 14 00 51 00 65 00 00 ] 18:08:04.996 -> Speed: 26 KPH Instantaneous Cadence: 804 RPM Average Cadence: 75 RPM Total Distance: 8716374 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 81 Watt Heart Rate: 101 HBM 18:08:06.088 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 AF 0A 66 06 96 00 58 00 8C 00 00 14 00 52 00 64 00 00 ] 18:08:06.088 -> Speed: 27 KPH Instantaneous Cadence: 819 RPM Average Cadence: 75 RPM Total Distance: 9175128 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 82 Watt Heart Rate: 100 HBM 18:08:06.181 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 84 FF 28 33 00 ] 18:08:06.303 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:06.303 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 84 FF 28 33 ] 18:08:06.995 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 9B 0A 83 06 A0 00 5A 00 93 00 00 14 00 64 00 64 00 00 ] 18:08:06.995 -> Speed: 27 KPH Instantaneous Cadence: 833 RPM Average Cadence: 80 RPM Total Distance: 9633882 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 100 Watt Heart Rate: 100 HBM 18:08:08.181 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 CA 0A 9D 06 A6 00 5C 00 9A 00 00 14 00 61 00 64 00 00 ] 18:08:08.182 -> Speed: 27 KPH Instantaneous Cadence: 846 RPM Average Cadence: 83 RPM Total Distance: 10092636 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 97 Watt Heart Rate: 100 HBM 18:08:08.274 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 FF 28 33 00 ] 18:08:08.412 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:08.412 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 FF 28 33 ] 18:08:08.999 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 0D 0B B6 06 A6 00 5E 00 A1 00 00 14 00 5E 00 64 00 00 ] 18:08:08.999 -> Speed: 28 KPH Instantaneous Cadence: 859 RPM Average Cadence: 83 RPM Total Distance: 10551390 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 94 Watt Heart Rate: 100 HBM 18:08:10.090 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 0E 0B CD 06 A2 00 60 00 A8 00 00 14 00 51 00 63 00 00 ] 18:08:10.138 -> Speed: 28 KPH Instantaneous Cadence: 870 RPM Average Cadence: 81 RPM Total Distance: 11010144 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 81 Watt Heart Rate: 99 HBM 18:08:10.373 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5D FF 28 33 00 ] 18:08:10.451 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:10.451 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5D FF 28 33 ] 18:08:11.013 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 39 0B E4 06 A6 00 62 00 AF 00 00 14 00 58 00 63 00 00 ] 18:08:11.013 -> Speed: 28 KPH Instantaneous Cadence: 882 RPM Average Cadence: 83 RPM Total Distance: 11468898 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 88 Watt Heart Rate: 99 HBM 18:08:11.978 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 6C 0B 02 07 A6 00 64 00 B7 00 00 14 00 50 00 62 00 00 ] 18:08:11.978 -> Speed: 29 KPH Instantaneous Cadence: 897 RPM Average Cadence: 83 RPM Total Distance: 11993188 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 80 Watt Heart Rate: 98 HBM 18:08:12.432 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5E FF 28 33 00 ] 18:08:12.668 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:12.668 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5E FF 28 33 ] 18:08:12.992 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 70 0B 20 07 AA 00 66 00 BF 00 00 14 00 4D 00 62 00 00 ] 18:08:12.993 -> Speed: 29 KPH Instantaneous Cadence: 912 RPM Average Cadence: 85 RPM Total Distance: 12517478 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 77 Watt Heart Rate: 98 HBM 18:08:13.995 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 B7 0B 3B 07 AE 00 68 00 C7 00 00 14 00 50 00 61 00 00 ] 18:08:13.995 -> Speed: 29 KPH Instantaneous Cadence: 925 RPM Average Cadence: 87 RPM Total Distance: 13041768 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 80 Watt Heart Rate: 97 HBM 18:08:14.550 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 6F FF 28 33 00 ] 18:08:14.768 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:14.768 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 6F FF 28 33 ] 18:08:14.984 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A3 0B 56 07 B2 00 6A 00 CF 00 00 14 00 4C 00 61 00 00 ] 18:08:14.984 -> Speed: 29 KPH Instantaneous Cadence: 939 RPM Average Cadence: 89 RPM Total Distance: 13566058 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 76 Watt Heart Rate: 97 HBM 18:08:16.182 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 81 0B 6F 07 BA 00 6B 00 D7 00 00 14 00 39 00 60 00 00 ] 18:08:16.182 -> Speed: 29 KPH Instantaneous Cadence: 951 RPM Average Cadence: 93 RPM Total Distance: 14090347 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 57 Watt Heart Rate: 96 HBM 18:08:16.631 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 8A FF 28 33 00 ] 18:08:16.709 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:16.709 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8A FF 28 33 ] 18:08:17.003 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 9F 0B 86 07 BC 00 6D 00 DF 00 00 14 00 42 00 5F 00 00 ] 18:08:17.003 -> Speed: 29 KPH Instantaneous Cadence: 963 RPM Average Cadence: 94 RPM Total Distance: 14614637 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 66 Watt Heart Rate: 95 HBM 18:08:18.191 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A0 0B 9D 07 BE 00 6F 00 E7 00 00 14 00 41 00 5E 00 00 ] 18:08:18.191 -> Speed: 29 KPH Instantaneous Cadence: 974 RPM Average Cadence: 95 RPM Total Distance: 15138927 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 65 Watt Heart Rate: 94 HBM 18:08:18.671 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 B8 FF 28 33 00 ] 18:08:18.794 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:18.794 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 B8 FF 28 33 ] 18:08:18.980 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 C3 0B B3 07 B6 00 71 00 EF 00 00 14 00 4E 00 5E 00 00 ] 18:08:18.980 -> Speed: 30 KPH Instantaneous Cadence: 985 RPM Average Cadence: 91 RPM Total Distance: 15663217 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 78 Watt Heart Rate: 94 HBM 18:08:20.077 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 99 0B C7 07 B2 00 72 00 F7 00 00 14 00 46 00 5D 00 00 ] 18:08:20.077 -> Speed: 29 KPH Instantaneous Cadence: 995 RPM Average Cadence: 89 RPM Total Distance: 16187506 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 70 Watt Heart Rate: 93 HBM 18:08:20.803 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 18:08:20.835 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:20.835 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 18:08:20.973 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 89 0B DB 07 B2 00 74 00 FF 00 00 14 00 47 00 5D 00 00 ] 18:08:20.973 -> Speed: 29 KPH Instantaneous Cadence: 1005 RPM Average Cadence: 89 RPM Total Distance: 16711796 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 71 Watt Heart Rate: 93 HBM 18:08:22.098 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 48 0B E6 07 AE 00 75 00 06 01 00 14 00 47 00 5C 00 00 ] 18:08:22.098 -> Speed: 28 KPH Instantaneous Cadence: 1011 RPM Average Cadence: 87 RPM Total Distance: 393333 m Resistance Level: 1 Instantaneous Power: 20 Watt Average Power: 71 Watt Heart Rate: 92 HBM 18:08:22.867 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A2 00 28 33 00 ] 18:08:22.913 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:22.913 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A2 00 28 33 ] 18:08:23.039 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 42 0B F1 07 B0 00 76 00 0D 01 00 14 00 59 00 5C 00 00 ] 18:08:23.039 -> Speed: 28 KPH Instantaneous Cadence: 1016 RPM Average Cadence: 88 RPM Total Distance: 852086 m Resistance Level: 1 Instantaneous Power: 20 Watt Average Power: 89 Watt Heart Rate: 92 HBM 18:08:24.006 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 0E 0B FC 07 AA 00 77 00 14 01 00 14 00 5F 00 5C 00 00 ] 18:08:24.006 -> Speed: 28 KPH Instantaneous Cadence: 1022 RPM Average Cadence: 85 RPM Total Distance: 1310839 m Resistance Level: 1 Instantaneous Power: 20 Watt Average Power: 95 Watt Heart Rate: 92 HBM 18:08:24.918 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 01 28 33 00 ] 18:08:25.012 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:25.012 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 01 28 33 ] 18:08:25.012 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 C9 0A 05 08 96 00 78 00 1B 01 00 14 00 70 00 5D 00 00 ] 18:08:25.012 -> Speed: 27 KPH Instantaneous Cadence: 1026 RPM Average Cadence: 75 RPM Total Distance: 1769592 m Resistance Level: 1 Instantaneous Power: 20 Watt Average Power: 112 Watt Heart Rate: 93 HBM 18:08:26.030 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 62 0A 0F 08 9C 00 78 00 22 01 00 14 00 95 00 5E 00 00 ] 18:08:26.030 -> Speed: 26 KPH Instantaneous Cadence: 1031 RPM Average Cadence: 78 RPM Total Distance: 2228344 m Resistance Level: 1 Instantaneous Power: 20 Watt Average Power: 149 Watt Heart Rate: 94 HBM 18:08:27.014 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 9F 0A 18 08 A0 00 79 00 29 01 00 14 00 A9 00 5F 00 00 ] 18:08:27.014 -> Speed: 27 KPH Instantaneous Cadence: 1036 RPM Average Cadence: 80 RPM Total Distance: 2687097 m Resistance Level: 1 Instantaneous Power: 20 Watt Average Power: 169 Watt Heart Rate: 95 HBM 18:08:27.014 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 4F 01 28 33 00 ] 18:08:27.107 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:27.107 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 4F 01 28 33 ] 18:08:27.989 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 FE 09 21 08 9C 00 7A 00 30 01 00 14 00 C0 00 61 00 00 ] 18:08:27.989 -> Speed: 25 KPH Instantaneous Cadence: 1040 RPM Average Cadence: 78 RPM Total Distance: 3145850 m Resistance Level: 1 Instantaneous Power: 20 Watt Average Power: 192 Watt Heart Rate: 97 HBM 18:08:28.992 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 02 0A 2A 08 98 00 7A 00 37 01 00 14 00 C9 00 63 00 00 ] 18:08:28.992 -> Speed: 25 KPH Instantaneous Cadence: 1045 RPM Average Cadence: 76 RPM Total Distance: 3604602 m Resistance Level: 1 Instantaneous Power: 20 Watt Average Power: 201 Watt Heart Rate: 99 HBM 18:08:29.114 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 01 28 33 00 ] 18:08:29.346 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:29.346 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 01 28 33 ] 18:08:29.995 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A3 09 2B 08 94 00 7B 00 3D 01 00 14 00 CD 00 65 00 00 ] 18:08:29.995 -> Speed: 24 KPH Instantaneous Cadence: 1045 RPM Average Cadence: 74 RPM Total Distance: 3997819 m Resistance Level: 1 Instantaneous Power: 20 Watt Average Power: 205 Watt Heart Rate: 101 HBM 18:08:30.983 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 6B 09 2D 08 92 00 7B 00 43 01 00 14 00 D0 00 67 00 00 ] 18:08:30.983 -> Speed: 24 KPH Instantaneous Cadence: 1046 RPM Average Cadence: 73 RPM Total Distance: 4391035 m Resistance Level: 1 Instantaneous Power: 20 Watt Average Power: 208 Watt Heart Rate: 103 HBM 18:08:31.216 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 57 FF 28 33 00 ] 18:08:31.309 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:31.309 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 57 FF 28 33 ] 18:08:32.004 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 FE 09 34 08 8E 00 7C 00 4A 01 00 14 00 C7 00 68 00 00 ] 18:08:32.004 -> Speed: 25 KPH Instantaneous Cadence: 1050 RPM Average Cadence: 71 RPM Total Distance: 4849788 m Resistance Level: 1 Instantaneous Power: 20 Watt Average Power: 199 Watt Heart Rate: 104 HBM 18:08:33.234 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 3C 0A 3C 08 8E 00 7C 00 51 01 00 14 00 D2 00 6A 00 00 ] 18:08:33.234 -> Speed: 26 KPH Instantaneous Cadence: 1054 RPM Average Cadence: 71 RPM Total Distance: 5308540 m Resistance Level: 1 Instantaneous Power: 20 Watt Average Power: 210 Watt Heart Rate: 106 HBM 18:08:33.310 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 08 00 00 00 00 00 00 00 ] 18:08:33.388 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 08 03 ] 18:08:33.974 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A0 0A 43 08 92 00 7C 00 58 01 00 14 00 B2 00 6B 00 00 ] 18:08:33.974 -> Speed: 27 KPH Instantaneous Cadence: 1057 RPM Average Cadence: 73 RPM Total Distance: 5767292 m Resistance Level: 1 Instantaneous Power: 20 Watt Average Power: 178 Watt Heart Rate: 107 HBM 18:08:34.984 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 EE 0A 4A 08 96 00 7D 00 5F 01 00 14 00 6F 00 6C 00 00 ] 18:08:34.984 -> Speed: 27 KPH Instantaneous Cadence: 1061 RPM Average Cadence: 75 RPM Total Distance: 6226045 m Resistance Level: 1 Instantaneous Power: 20 Watt Average Power: 111 Watt Heart Rate: 108 HBM 18:08:35.386 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 01 00 00 00 00 00 00 00 ] 18:08:35.479 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 01 01 ] 18:08:35.479 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 01 ] 18:08:35.989 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 44 0A 9C 00 14 00 3A 00 00 ] 18:08:35.989 -> Speed: 26 KPH Instantaneous Cadence: 78 RPM Resistance Level: 20 Instantaneous Power: 58 Watt Heart Rate: 0 HBM 18:08:36.992 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 AC 09 00 00 14 00 00 00 00 ] 18:08:36.992 -> Speed: 24 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 18:08:37.486 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 18:08:37.579 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 18:08:37.997 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 18 09 00 00 14 00 00 00 00 ] 18:08:37.997 -> Speed: 23 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 18:08:39.290 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 8A 08 00 00 14 00 00 00 00 ] 18:08:39.290 -> Speed: 21 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 18:08:39.584 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 18:08:39.833 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 18:08:39.956 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 FC 07 00 00 14 00 00 00 00 ] 18:08:39.956 -> Speed: 20 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 18:08:40.991 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 74 07 00 00 14 00 00 00 00 ] 18:08:40.991 -> Speed: 19 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 18:08:41.684 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 18:08:41.793 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 18:08:41.793 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 18:08:42.024 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 ED 06 AC 05 00 00 00 00 04 00 00 14 00 00 00 00 00 00 ] 18:08:42.024 -> Speed: 17 KPH Instantaneous Cadence: 726 RPM Average Cadence: 0 RPM Total Distance: 262144 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:43.125 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 6A 06 AB 05 00 00 00 00 08 00 00 14 00 00 00 00 00 00 ] 18:08:43.125 -> Speed: 16 KPH Instantaneous Cadence: 725 RPM Average Cadence: 0 RPM Total Distance: 524288 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:43.770 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 18:08:43.863 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:43.863 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 18:08:43.987 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E9 05 AB 05 00 00 00 00 0C 00 00 14 00 00 00 00 00 00 ] 18:08:43.987 -> Speed: 15 KPH Instantaneous Cadence: 725 RPM Average Cadence: 0 RPM Total Distance: 786432 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:44.988 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 6C 05 51 05 00 00 00 00 0F 00 00 14 00 00 00 00 00 00 ] 18:08:44.988 -> Speed: 13 KPH Instantaneous Cadence: 680 RPM Average Cadence: 0 RPM Total Distance: 983040 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:45.858 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 00 28 33 00 ] 18:08:45.936 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:45.936 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 18:08:45.982 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 F0 04 1A 05 00 00 00 00 12 00 00 14 00 00 00 00 00 00 ] 18:08:45.982 -> Speed: 12 KPH Instantaneous Cadence: 653 RPM Average Cadence: 0 RPM Total Distance: 1179648 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:47.261 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 7B 04 F6 04 00 00 00 00 15 00 00 14 00 00 00 00 00 00 ] 18:08:47.261 -> Speed: 11 KPH Instantaneous Cadence: 635 RPM Average Cadence: 0 RPM Total Distance: 1376256 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:47.940 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 18:08:47.972 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 07 04 A8 04 00 00 00 00 17 00 00 14 00 00 00 00 00 00 ] 18:08:47.972 -> Speed: 10 KPH Instantaneous Cadence: 596 RPM Average Cadence: 0 RPM Total Distance: 1507328 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:48.003 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:48.003 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 18:08:49.051 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 98 03 6E 04 00 00 00 00 19 00 00 14 00 00 00 00 00 00 ] 18:08:49.096 -> Speed: 9 KPH Instantaneous Cadence: 567 RPM Average Cadence: 0 RPM Total Distance: 1638400 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:50.008 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 2B 03 40 04 00 00 00 00 1B 00 00 14 00 00 00 00 00 00 ] 18:08:50.008 -> Speed: 8 KPH Instantaneous Cadence: 544 RPM Average Cadence: 0 RPM Total Distance: 1769472 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:50.008 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 14 00 28 33 00 ] 18:08:50.132 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:50.132 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 00 28 33 ] 18:08:51.171 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 C2 02 F8 03 00 00 00 00 1C 00 00 14 00 00 00 00 00 00 ] 18:08:51.171 -> Speed: 7 KPH Instantaneous Cadence: 508 RPM Average Cadence: 0 RPM Total Distance: 1835008 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:52.014 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 5C 02 BC 03 00 00 00 00 1D 00 00 14 00 00 00 00 00 00 ] 18:08:52.014 -> Speed: 6 KPH Instantaneous Cadence: 478 RPM Average Cadence: 0 RPM Total Distance: 1900544 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:52.133 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 00 28 33 00 ] 18:08:52.169 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:52.169 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 00 28 33 ] 18:08:52.969 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 FC 01 8B 03 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:08:52.969 -> Speed: 5 KPH Instantaneous Cadence: 453 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:54.032 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 45 03 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:08:54.032 -> Speed: 0 KPH Instantaneous Cadence: 418 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:54.172 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 25 00 28 33 00 ] 18:08:54.375 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:54.375 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 25 00 28 33 ] 18:08:55.011 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 09 03 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:08:55.056 -> Speed: 0 KPH Instantaneous Cadence: 388 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:55.994 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 D6 02 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:08:55.994 -> Speed: 0 KPH Instantaneous Cadence: 363 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:56.274 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 23 00 28 33 00 ] 18:08:56.366 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:56.366 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 00 28 33 ] 18:08:57.103 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 A8 02 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:08:57.103 -> Speed: 0 KPH Instantaneous Cadence: 340 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:58.006 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 80 02 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:08:58.006 -> Speed: 0 KPH Instantaneous Cadence: 320 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:58.393 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 1C 00 28 33 00 ] 18:08:58.486 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:08:58.486 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 00 28 33 ] 18:08:59.043 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 5D 02 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:08:59.043 -> Speed: 0 KPH Instantaneous Cadence: 302 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:08:59.970 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 3D 02 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:08:59.970 -> Speed: 0 KPH Instantaneous Cadence: 286 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:00.484 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 0F 00 28 33 00 ] 18:09:00.562 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:09:00.562 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 0F 00 28 33 ] 18:09:00.982 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 20 02 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:00.982 -> Speed: 0 KPH Instantaneous Cadence: 272 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:02.154 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 06 02 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:02.154 -> Speed: 0 KPH Instantaneous Cadence: 259 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:02.545 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 18:09:02.671 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:09:02.671 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 18:09:03.077 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 EF 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:03.077 -> Speed: 0 KPH Instantaneous Cadence: 247 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:04.037 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 D9 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:04.037 -> Speed: 0 KPH Instantaneous Cadence: 236 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:04.670 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 F5 FF 28 33 00 ] 18:09:04.993 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 C5 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:04.993 -> Speed: 0 KPH Instantaneous Cadence: 226 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:05.039 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:09:05.039 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 F5 FF 28 33 ] 18:09:05.976 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 B3 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:05.976 -> Speed: 0 KPH Instantaneous Cadence: 217 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:06.769 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 E4 FF 28 33 00 ] 18:09:06.848 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:09:06.848 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 E4 FF 28 33 ] 18:09:06.988 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 A3 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:06.988 -> Speed: 0 KPH Instantaneous Cadence: 209 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:07.992 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 93 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:07.992 -> Speed: 0 KPH Instantaneous Cadence: 201 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:08.857 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 CF FF 28 33 00 ] 18:09:08.980 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 85 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:08.980 -> Speed: 0 KPH Instantaneous Cadence: 194 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:09.026 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:09:09.026 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 CF FF 28 33 ] 18:09:10.279 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 77 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:10.279 -> Speed: 0 KPH Instantaneous Cadence: 187 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:10.944 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A8 FF 28 33 00 ] 18:09:10.990 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 6B 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:10.990 -> Speed: 0 KPH Instantaneous Cadence: 181 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:11.037 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:09:11.037 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A8 FF 28 33 ] 18:09:12.001 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 5F 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:12.001 -> Speed: 0 KPH Instantaneous Cadence: 175 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:12.989 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 54 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:12.989 -> Speed: 0 KPH Instantaneous Cadence: 170 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:13.025 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 84 FF 28 33 00 ] 18:09:13.104 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:09:13.104 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 84 FF 28 33 ] 18:09:13.972 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 4A 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:13.972 -> Speed: 0 KPH Instantaneous Cadence: 165 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:14.978 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 40 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:14.978 -> Speed: 0 KPH Instantaneous Cadence: 160 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:15.116 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 FF 28 33 00 ] 18:09:15.194 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:09:15.194 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 FF 28 33 ] 18:09:16.125 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 37 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:16.125 -> Speed: 0 KPH Instantaneous Cadence: 155 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:17.013 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 2E 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:17.013 -> Speed: 0 KPH Instantaneous Cadence: 151 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:17.184 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5D FF 28 33 00 ] 18:09:17.263 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:09:17.263 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5D FF 28 33 ] 18:09:18.010 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 26 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:18.010 -> Speed: 0 KPH Instantaneous Cadence: 147 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:19.015 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 1E 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ] 18:09:19.015 -> Speed: 0 KPH Instantaneous Cadence: 143 RPM Average Cadence: 0 RPM Total Distance: 1966080 m Resistance Level: 0 Instantaneous Power: 20 Watt Average Power: 0 Watt Heart Rate: 0 HBM 18:09:19.248 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5E FF 28 33 00 ] 18:09:19.372 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:09:19.372 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5E FF 28 33 ] 18:09:20.050 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 00 00 17 01 00 00 00 00 1E 00 00 14 00 00 00 00 00 00 ]
// If FTM Feature is not found, disconnect, resume scanning, and return while (!( client_FTM_Feature_Chr.discover() )) { if ( client_FTM_Feature_Chr.discover() ) {
Serial.println("Found it!");
// Read FTM Feature Data
client_FTM_Feature_Chr.read(client_FTM_Feature_Data, 8);
Serial.print(" -> Client Reads Raw FTM Feature bytes: [8] [ ");
for (int i = 0; i < sizeof(client_FTM_Feature_Data); i++) {
Serial.printf("%02X ", client_FTM_Feature_Data[i], HEX);
} // for
Serial.println("] ");
} else {
Serial.println("Disconnecting since Client FTM Feature Characteristic is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
Bluefruit.Connection(conn_handle);
Serial.print("Discovering Client FTM Feature not decouvert ... ");
// return; } }
As you can see in the second test it does not find the speed and cadence values.
Probably I should put more "While".
What is weird is the value of the heart rate because the sensor is not connected (battery removed)
18:26:23.470 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 18:26:23.470 -> ----------------- Version 02.5 ------------------ 18:26:23.470 -> Initialise the Bluefruit nRF52 module: Client (Central) 18:26:23.718 -> FTMS and Chars 'initialized' 18:26:23.718 -> CPS and Chars 'initialized' 18:26:23.718 -> CSCS and Chars 'initialized' 18:26:23.718 -> GA and Chars 'initialized' 18:26:23.718 -> DIS and Chars 'initialized' 18:26:23.718 -> Start Scanning for CPS, CSC and FTMS! 18:26:23.720 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 18:26:23.720 -> Timestamp MAC Address Rssi Data 18:26:23.720 -> 000001552 F8:9C:FC:53:5E:49 -61 09-02-16-18-26-18-18-18-0A-18 18:26:23.720 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 18:26:23.720 -> Now checking all Client Services and Characteristics! 18:26:23.720 -> If Mandatory Services Fail --> the Client will disconnect! 18:26:23.720 -> First checking Generic Access and Device Information Services and Characteristics! 18:26:24.243 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 18:26:24.243 -> Discovering Client FTM Feature Characteristic ... Discovering Client FTM Control Point Characteristic ... Found it! 18:26:24.252 -> Discovering Client FTM Status Characteristic ... Found it! 18:26:24.544 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 18:26:24.823 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 18:26:25.225 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 18:26:25.225 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 18:26:25.457 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 18:26:25.457 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 18:26:25.781 -> Discovering Client Cycling Power (CP) Service ... Ready to receive Client FTM Control Point Response Messages 18:26:25.827 -> Found it! CPS Max Payload: 20 Data Length: 27 18:26:25.827 -> Discovering Client CP Measurement characteristic ... Ready to receive Client FTM Status values 18:26:25.827 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 18:26:25.906 -> >>> Couldn't enable notify for Client FTM Indoor Bike Data Characteristic. 18:26:25.906 -> >>> Couldn't enable notify for Client CP Measurement Characteristic. 18:26:25.906 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 18:26:25.906 -> >>> Couldn't enable notify for Client CSC Measurement Characteristic. 18:26:25.906 -> Client (Central) is Up and Running! 18:26:26.045 -> Found it! 18:26:26.045 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 18:26:26.541 -> Discovering Client CP Feature characteristic ... Found it! 18:26:26.726 -> -> Client Reads Raw CP Feature bytes: [4] [ 00 00 00 00 ] 18:26:26.726 -> Discovering Client CP Sensor Location characteristic ... NOT Found! NOT Mandatory! 18:26:26.726 -> Discovering Cycling Speed and Cadence (CSC) Service ... Not Found! CSC Service is Not Mandatory! 18:26:27.906 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 18:26:27.970 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 18:26:29.983 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 18:26:30.029 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 18:26:32.045 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 18:26:32.122 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 18:26:32.122 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 18:26:34.127 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 18:26:34.174 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:26:34.174 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 18:26:36.191 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 00 28 33 00 ] 18:26:36.237 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:26:36.237 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 18:26:38.240 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 18:26:38.317 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:26:38.317 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 18:26:40.324 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 14 00 28 33 00 ] 18:26:40.402 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:26:40.402 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 00 28 33 ] 18:26:42.383 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 00 28 33 00 ] 18:26:42.508 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 18:26:42.508 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 00 28 33 ] 18:26:44.510 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 25 00 28 33 00 ] 18:26:44.588 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ]
Dear Joel, I am puzzled about how and what you have changed in the code version 025. I see a while loop that waits for ever until the FTM_Feature_Char is discovered: while (!( client_FTM_Feature_Chr.discover() )) { et cetera } FTM_Feature was never a problem....??? Did you put while loops in all discover calls...? For what purpose? Whatever you did: one of the runs now shows -> Client Rec'd Raw FTM Indoor Bike Data: et cetera That never ever happened before ...... ???? So please detail more and better what you have changed otherwise I am only guessing and that does not help progress... Greetings, Jörgen.
Dear Joel, Still I would like to know more precisely what you have altered in the code of 025... that issue is still open! Your code snippet is only relevant when you think a timing problem prevents the discovery of the relevant Char's..... (?) Meanwhile I guessed that (along the same line of reasoning) enabling of the Char's with Notify or Indicate (at the Zwift Hub) might go wrong due to a timing problem...(ItsyBitsy? or Hub?). So I have inserted a timed check for notify/indicate result that gives the polling process two (2) seconds for response.... I wonder if this version 027 will bring us closer to a solution... (You still need to wake up your trainer and ride the trainer!!)
Do not take the IBD decoded data too serious, decoding the IBD data is very complicated and I would not be surprised that I understood it in a wrong way.... although it works fine with Elite Direto specifications! This is not critical for the final result, after all the MITM does not have to understand/decode everything, only what it is interested in...
By the way the FTMS_Zwift_Bridge code v023 can be tested with your setup.... (Notice that you have to pedal as well! Read the instructions)
Best wishes, Jörgen.
Hello Jorghen,
To answer the question should I always wake him up?
No with the modification I made I just have to turn on the trainer. No need to pedal. So the problem was not a problem of waking up but probably of receiving "char"!
Here is the V.025 that I had to modify. There are 3 "While" that I had added.
I will test your V0.27.
Sincerely, Joel
/***** This is programming code for the nRF52 based Bluefruit BLE boards
The code uses heavily the Adafruit supplied Bluefruit BLE libraries !! Adafruit invests time and resources providing open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
MIT license, check LICENSE for more information All text must be included in any redistribution *****/
/*
*/
// ------------------------------------------------------------------------------------------- // COMPILER DIRECTIVE to allow/suppress SERIAL.PRINT messages that help debugging... // Uncomment to activate
//#define DEBUG_CP_MEASUREMENT //#define DEBUG_CSC_MEASUREMENT // --------------------------------------------------------------------------------------------
const uint8_t MAX_PAYLOAD = 20; // Max 20 byte data size for single packet BLE transfer uint16_t client_Connection_Handle = BLE_CONN_HANDLE_INVALID;
/* Generic Access
*/ BLEClientService client_GenericAccess_Service(UUID16_SVC_GENERIC_ACCESS); BLEClientCharacteristic client_GA_Appearance_Chr(UUID16_CHR_APPEARANCE); // Read uint16_t client_GA_Appearance_Value = 0; BLEClientCharacteristic client_GA_DeviceName_Chr(UUID16_CHR_DEVICE_NAME);// Read, Write unsigned char client_GA_DeviceName_Data[MAX_PAYLOAD] = {};
/* Cycling Power Service
const char* client_CP_Feature_Str[] = { "Pedal power balance supported", "Accumulated torque supported", "Wheel revolution data supported", "Crank revolution data supported", "Extreme magnitudes supported", "Extreme angles supported", "Top/bottom dead angle supported", "Accumulated energy supported", "Offset compensation indicator supported", "Offset compensation supported", "Cycling power measurement characteristic content masking supported", "Multiple sensor locations supported", "Crank length adj. supported", "Chain length adj. supported", "Chain weight adj. supported", "Span length adj. supported", "Sensor measurement context", "Instantaineous measurement direction supported", "Factory calibrated date supported", "Enhanced offset compensation supported" };
const char* client_Sensor_Location_Str[] = { "Other", "Top of shoe", "In shoe", "Hip", "Front wheel", "Left crank", "Right crank", "Left pedal", "Right pedal", "Front hub", "Rear dropout", "Chainstay", "Rear wheel", "Rear hub", "Chest", "Spider", "Chain ring"};
/*
// CSC Control Point response values
*/
/CSC Measurement flags/
/ CSC Feature flags /
const char* client_CSC_Feature_Str[] = {"Wheel rev supported", "Crank rev supported", "Multiple locations supported"};
BLEClientService client_CyclingSpeedCadence_Service(UUID16_SVC_CYCLING_SPEED_AND_CADENCE); BLEClientCharacteristic client_CSC_Measurement_Chr(UUID16_CHR_CSC_MEASUREMENT); // Notify, Read BLEClientCharacteristic client_CSC_Feature_Chr(UUID16_CHR_CSC_FEATURE); // Read const uint8_t CSC_FEATURE_FIXED_DATALEN = 2; // UINT16 uint16_t client_CSC_Feature_Flags = 0; BLEClientCharacteristic client_CSC_Location_Chr(UUID16_CHR_SENSOR_LOCATION); // Read uint8_t client_CSC_Location_Value = 0;
/* Client Service Device Information
*/ BLEClientService client_DIS_Service(UUID16_SVC_DEVICE_INFORMATION); BLEClientCharacteristic client_DIS_ManufacturerName_Chr(UUID16_CHR_MANUFACTURER_NAME_STRING); // Read char client_DIS_Manufacturer_Str[MAX_PAYLOAD] = {}; BLEClientCharacteristic client_DIS_ModelNumber_Chr(UUID16_CHR_MODEL_NUMBER_STRING); // Read char client_DIS_ModelNumber_Str[MAX_PAYLOAD] = {}; BLEClientCharacteristic client_DIS_SerialNumber_Chr(UUID16_CHR_SERIAL_NUMBER_STRING); // Read char client_DIS_SerialNumber_Str[MAX_PAYLOAD] = {};
/*
*/ BLEClientService client_FitnessMachine_Service(UUID16_SVC_FITNESS_MACHINE); // FTM Service // Service characteristics exposed by FTM Service BLEClientCharacteristic client_FTM_Feature_Chr(UUID16_CHR_FITNESS_MACHINE_FEATURE); // Fitness Machine Feature, mandatory, read const uint8_t FTM_FEATURE_FIXED_DATALEN = 8; uint8_t client_FTM_Feature_Data[FTM_FEATURE_FIXED_DATALEN]; BLEClientCharacteristic client_FTM_IndoorBikeData_Chr(UUID16_CHR_INDOOR_BIKE_DATA); // Indoor Bike Data, optional, notify BLEClientCharacteristic client_FTM_TrainingStatus_Chr(UUID16_CHR_TRAINING_STATUS); // Training Status, optional, read & notify BLEClientCharacteristic client_FTM_SupportedResistanceLevelRange_Chr(UUID16_CHR_SUPPORTED_RESISTANCE_LEVEL_RANGE); // Supported Resistance Level, read, optional const uint8_t FTM_SRLR_FIXED_DATALEN = 6; uint8_t client_FTM_SupportedResistanceLevelRange_Data[FTM_SRLR_FIXED_DATALEN]; BLEClientCharacteristic client_FTM_SupportedPowerRange_Chr(UUID16_CHR_SUPPORTED_POWER_RANGE); // Supported Power Levels, read, optional const uint8_t FTM_SPR_FIXED_DATALEN = 6; uint8_t client_FTM_SupportedPowerRange_Data[FTM_SPR_FIXED_DATALEN]; BLEClientCharacteristic client_FTM_ControlPoint_Chr(UUID16_CHR_FITNESS_MACHINE_CONTROL_POINT); // Fitness Machine Control Point, optional, write & indicate BLEClientCharacteristic client_FTM_Status_Chr(UUID16_CHR_FITNESS_MACHINE_STATUS); // Fitness Machine Status, mandatory, notify
unsigned long TimeInterval = 0;
// TEST DATA set ----------------------------------------------------- // Test set (Zwift Volcano Circuit) with Control and 2D Resistance data to be sent to Control Point uint8_t ControlPointMessageCount = 0; const uint8_t ControlPointData[32][8] = { {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // Request Control {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // Request Control {0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // Start or Resume {0x11,0x00,0x00,0x22,0x01,0x28,0x33,0x00}, // Set Indoor Bike Simulation Parameters.. {0x11,0x00,0x00,0x09,0x00,0x28,0x33,0x00}, {0x11,0x00,0x00,0x00,0x00,0x28,0x33,0x00}, {0x11,0x00,0x00,0x14,0x00,0x28,0x33,0x00}, {0x11,0x00,0x00,0x22,0x00,0x28,0x33,0x00}, {0x11,0x00,0x00,0x25,0x00,0x28,0x33,0x00}, {0x11,0x00,0x00,0x23,0x00,0x28,0x33,0x00}, {0x11,0x00,0x00,0x1C,0x00,0x28,0x33,0x00}, {0x11,0x00,0x00,0x0F,0x00,0x28,0x33,0x00}, {0x11,0x00,0x00,0x00,0x00,0x28,0x33,0x00}, {0x11,0x00,0x00,0xF5,0xFF,0x28,0x33,0x00}, {0x11,0x00,0x00,0xE4,0xFF,0x28,0x33,0x00}, {0x11,0x00,0x00,0xCF,0xFF,0x28,0x33,0x00}, {0x11,0x00,0x00,0xA8,0xFF,0x28,0x33,0x00}, {0x11,0x00,0x00,0x84,0xFF,0x28,0x33,0x00}, {0x11,0x00,0x00,0x67,0xFF,0x28,0x33,0x00}, {0x11,0x00,0x00,0x5D,0xFF,0x28,0x33,0x00}, {0x11,0x00,0x00,0x5E,0xFF,0x28,0x33,0x00}, {0x11,0x00,0x00,0x6F,0xFF,0x28,0x33,0x00}, {0x11,0x00,0x00,0x8A,0xFF,0x28,0x33,0x00}, {0x11,0x00,0x00,0xB8,0xFF,0x28,0x33,0x00}, {0x11,0x00,0x00,0x00,0x00,0x28,0x33,0x00}, {0x11,0x00,0x00,0xA2,0x00,0x28,0x33,0x00}, {0x11,0x00,0x00,0x09,0x01,0x28,0x33,0x00}, {0x11,0x00,0x00,0x4F,0x01,0x28,0x33,0x00}, {0x11,0x00,0x00,0x67,0x01,0x28,0x33,0x00}, {0x11,0x00,0x00,0x57,0xFF,0x28,0x33,0x00}, {0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // Stop or Pause {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00}};// Reset // TEST DATA set ---------------------------------------------------
void setup() {
Serial.begin(115200); while ( !Serial ) delay(10); // for nrf52840 with native usb
Serial.println(" Feather nRF52 Client/Central: CPS, CSC and FTMS"); Serial.println("----------------- Version 02.5 ------------------"); Serial.println("Initialise the Bluefruit nRF52 module: Client (Central)");
// Initialize Bluefruit module // begin (Peripheral = 0, Central = 1) Bluefruit.begin(0, 1);
Setup_Client_FTMS(); Setup_Client_CPS(); Setup_Client_CSC(); Setup_Client_DIS(); Client_Start_Scanning();
while (Bluefruit.Scanner.isRunning()) { // do nothing else but scanning.... } TimeInterval = millis() + TIME_SPAN; // ADD just enough delay // wait enough time or go on when Client/Central is connected and all set! while( TimeInterval > millis() ) { } // Scanning is finished! Are we connected? // If NO connection is established -> Stop! if( !(Bluefruit.connected()) ) {
Serial.println("Stopped!");
return;
} // Try to enable Client (Trainer) CPS, CSC and FTMS data streams... Client_Enable_Notify_Indicate(); if( !(Bluefruit.connected()) ) { // Are we meanwhile disconnected?
Serial.println("Stopped!");
return;
} // After successful enable notify/indicate of all mandatory Char's continue!
Serial.println("Client (Central) is Up and Running!");
// Set first timing for sending first set of Control Point Data TimeInterval = millis() + CONTROL_POINT_TIME_SPAN; }
void Setup_Client_FTMS(void)
{
// Initialize client FTM Service
client_FitnessMachine_Service.begin();
while( !(client_FitnessMachine_Service.begin()) ) {
Serial.println("Wait for FitnessMachine_Service.begin ");
}
// Initialize client FTM Feature characteristic
client_FTM_Feature_Chr.begin();
// Initialize client FTM Training Status characteristic client_FTM_TrainingStatus_Chr.setNotifyCallback(client_FTM_TrainingStatus_Notify_callback);
client_FTM_TrainingStatus_Chr.begin();
// Initialize client FTM Supported Power Range characteristic client_FTM_SupportedPowerRange_Chr.begin();
// Initialize client FTM Supported Resistance Level Range characteristic client_FTM_SupportedResistanceLevelRange_Chr.begin();
// Initialize client FTM Indoor Bike Data characteristic client_FTM_IndoorBikeData_Chr.setNotifyCallback(client_FTM_IndoorBikeData_Notify_callback); client_FTM_IndoorBikeData_Chr.begin();
// Initialize client FTM Control Point characteristic // For receiving Control Point Responses client_FTM_ControlPoint_Chr.setIndicateCallback(client_FTM_ControlPoint_Indicate_callback); client_FTM_ControlPoint_Chr.begin();
// Initialize client FTM Status characteristic client_FTM_Status_Chr.setNotifyCallback(client_FTM_Status_Notify_callback); client_FTM_Status_Chr.begin();
Serial.println("FTMS and Chars 'initialized'");
}
void Setup_Client_CPS(void)
{
// Initialize CPS client
client_CyclingPower_Service.begin();
// Initialize CP Feature characteristics of client_CyclingPower_Service. client_CP_Feature_Chr.begin();
// Initialize CP sensor location characteristics of client_CyclingPower_Service. client_CP_Location_Chr.begin();
// set up callback for receiving measurement client_CP_Measurement_Chr.setNotifyCallback(client_CP_Measurement_Chr_notify_callback); client_CP_Measurement_Chr.begin();
// Initialize Control Point and set up Indicate callback for receiving responses (indicate!) client_CP_ControlPoint_Chr.setIndicateCallback(client_CP_ControlPoint_Chr_indicate_callback); client_CP_ControlPoint_Chr.begin();
Serial.println("CPS and Chars 'initialized'");
}
void Setup_Client_CSC(void) { // Initialize CSC client client_CyclingSpeedCadence_Service.begin();
// Initialize client characteristics of CSC. client_CSC_Location_Chr.begin();
// Initialize CSC Feature characteristics of client_CSC. client_CSC_Feature_Chr.begin();
// set up callback for receiving measurement client_CSC_Measurement_Chr.setNotifyCallback(client_CSC_Measurement_Chr_notify_callback); client_CSC_Measurement_Chr.begin();
Serial.println("CSCS and Chars 'initialized'");
}
void Setup_Client_DIS(void) { // Initialize client Generic Access Service client_GenericAccess_Service.begin(); // Initialize some characteristics of the Generic Access Service. client_GA_DeviceName_Chr.begin(); client_GA_Appearance_Chr.begin();
Serial.println("GA and Chars 'initialized'");
// Initialize client Device Information Service client_DIS_Service.begin(); // Initialize some characteristics of the Device Information Service. client_DIS_ManufacturerName_Chr.begin(); client_DIS_ModelNumber_Chr.begin(); client_DIS_SerialNumber_Chr.begin();
Serial.println("DIS and Chars 'initialized'");
}
void loop() {
if ( Bluefruit.connected() ) { // If time is there, send test values of Indoor Bike Simulation Parameters to // the Trainer's FTM Control Point to drive the FTM... if(millis() > TimeInterval) { if(ControlPointMessageCount > 31) { ControlPointMessageCount = 0; } // start all over again! uint8_t CPData[8] = {};
Serial.print("Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ ");
// Transfer multidimensional test data to CPData buffer
for (int i = 0; i < sizeof(CPData); i++) {
CPData[i] = ControlPointData[ControlPointMessageCount][i];
Serial.printf("%02X ", CPData[i], HEX);
}
Serial.println("] ");
// client_FTM_ControlPoint_Chr.write(CPData, 8); client_FTM_ControlPoint_Chr.write_resp(CPData, 8); TimeInterval = millis() + CONTROL_POINT_TIME_SPAN; ControlPointMessageCount++; } // TimeInterval } // Bluefruit connected } // end loop
void Client_Start_Scanning(void) { /* Start Central Scanning
// Client/Central Callbacks defined Bluefruit.Central.setDisconnectCallback(client_disconnect_callback); Bluefruit.Central.setConnectCallback(client_connect_callback);
Bluefruit.Scanner.setRxCallback(client_scan_callback); Bluefruit.Scanner.restartOnDisconnect(false); // default -> true !!! in test stage we do not want to RESTART -> false Bluefruit.Scanner.filterRssi(-70); // original value of -80 , we want to scan only nearby peripherals, so get close to your device !! Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms // only invoke callback if one of these services are advertised --> check for FTMS only later Bluefruit.Scanner.filterUuid(UUID16_SVC_CYCLING_POWER, UUID16_SVC_CYCLING_SPEED_AND_CADENCE, UUID16_SVC_FITNESS_MACHINE); Bluefruit.Scanner.useActiveScan(true); Bluefruit.Scanner.start(0); // 0 = Don't stop scanning or n = after n/100 seconds
Serial.println("Start Scanning for CPS, CSC and FTMS!"); delay(100); // To show print message !
}
void Client_Enable_Notify_Indicate(void)
{
// Reaching here means we are ready to go, let's enable Chars with Indicate/Notify
// ------------------------- Enable FTMS Notify and Indicate ---------------------------------------
if ( client_FTM_ControlPoint_Chr.enableIndicate() ) { // MANDATORY
Serial.println("Ready to receive Client FTM Control Point Response Messages");
} else {
Serial.println(">>> Couldn't enable indicate for Client FTM Control Point Characteristic.");
Serial.println("FTMS (trainer) is controlled by another Client (Training App)!");
Bluefruit.disconnect(client_Connection_Handle);
return;
}
if ( client_FTM_Status_Chr.enableNotify() ) { // MANDATORY
Serial.println("Ready to receive Client FTM Status values");
} else {
Serial.println(">>> Couldn't enable notify for Client FTM Status Characteristic.");
Serial.println("FTMS (trainer) is controlled by another Client (Training App)!");
Bluefruit.disconnect(client_Connection_Handle);
return;
}
if ( client_FTM_TrainingStatus_Chr.enableNotify() ) { // NOT MANDATORY
Serial.println("Ready to receive Client FTM Training Status values");
} else {
Serial.println(">>> Couldn't enable notify for Client FTM Training Status Characteristic.");
}
if ( client_FTM_IndoorBikeData_Chr.enableNotify() ) { // NOT MANDATORY
Serial.println("Ready to receive Client FTM Indoor Bike Data values");
} else {
Serial.println(">>> Couldn't enable notify for Client FTM Indoor Bike Data Characteristic.");
}
// ------------------------- Enable FTMS Notify and Indicate ---------------------------------------
// --------------------- Enable CP and CSC Notify and Indicate ------------------------------------
if ( client_CP_Measurement_Chr.enableNotify() ) { // NOT MANDATORY
Serial.println("Ready to receive Client CP Measurement values");
} else {
Serial.println(">>> Couldn't enable notify for Client CP Measurement Characteristic.");
}
if ( client_CP_ControlPoint_Chr.enableIndicate() ) { // NOT MANDATORY
Serial.println("Ready to receive Client CP Control Point Responses");
} else {
Serial.println(">>> Couldn't enable indicate for Client CP Control Point Characteristic.");
}
if ( client_CSC_Measurement_Chr.enableNotify() ) { // NOT MANDATORY
Serial.println("Ready to receive Client CSC Measurement values");
} else {
Serial.println(">>> Couldn't enable notify for Client CSC Measurement Characteristic.");
} // ------------------------- Enable CP and CSC Notify and Indicate -------------------------------- }
/**
uint8_t SDataLen = (uint8_t)len; uint8_t SDataBuf[SDataLen] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw FTM Training Status Data: [%d] [ ", len); for (int i = 0; i < sizeof(SDataBuf); i++) { SDataBuf[i] = *data++; Serial.printf("%02X ", SDataBuf[i], HEX); } Serial.println("] ");
}
/**
// testing ParseIndoorBikeData(data, len);
}
void ParseIndoorBikeData(uint8_t data, uint16_t len) { // ---> IBD Buffer Data Length depends on data flagged to be present !!!! uint8_t IBDDataLen = (uint8_t)len; uint8_t IBDDataBuf[IBDDataLen] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw FTM Indoor Bike Data: [%d] [ ", len); for (int i = 0; i < sizeof(IBDDataBuf); i++) { IBDDataBuf[i] = data++; Serial.printf("%02X ", IBDDataBuf[i], HEX); } Serial.println("]"); uint8_t offset = 0; uint16_t flags = 0; memcpy(&flags, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable offset += 2; // UINT16 if ((flags & 1) != 0) { // More Data Serial.print("More Data!"); } // if ((flags & 2) != 0) { // (flags & 2) --> true or false Average Speed is always(?) there (tested with Elite Direto XR) // Average Speed 0.01 uint16_t sim_Speed = 0; memcpy(&sim_Speed, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Speed: %d KPH", (sim_Speed/100)); offset += 2; // UINT16 // } if ((flags & 4) != 0) { // Instantaneous Cadence 0.5 uint16_t inst_Cadence = 0; memcpy(&inst_Cadence, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Instantaneous Cadence: %d RPM", (inst_Cadence/2)); offset += 2; // UINT16 } if ((flags & 8) != 0) { // Average Cadence 0.5 uint16_t av_Cadence = 0; memcpy(&av_Cadence, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Average Cadence: %d RPM", (av_Cadence/2)); offset += 2; // UINT16 } if ((flags & 16) != 0) { // Total Distance 1 // Little endian format, transfer 24 bit to 32 bit variable uint32_t tot_Distance = 0; memcpy(&tot_Distance, &IBDDataBuf[offset], 3); // Transfer buffer fields to variable Serial.printf(" Total Distance: %d m", tot_Distance); offset += 3; // UINT24 16 + 8 } if ((flags & 32) != 0) { // Resistance Level 1 uint16_t res_Level = 0; memcpy(&res_Level, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Resistance Level: %d ", res_Level); offset += 2; // UINT16 } if ((flags & 64) != 0) { // Instantaneous Power 1 uint16_t inst_Power = 0; memcpy(&inst_Power, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Instantaneous Power: %d Watt", inst_Power); offset += 2; // UINT16 } if ((flags & 128) != 0) { // Average Power 1 uint16_t av_Power = 0; memcpy(&av_Power, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Average Power: %d Watt", av_Power); offset += 2; // UINT16 } if ((flags & 256) != 0) { // Expended Energy -> UINT16 UINT16 UINT8 // Total Energy UINT16 1 uint16_t tot_Energy = 0; memcpy(&tot_Energy, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Tot. Energy: %d kCal", tot_Energy); offset += 2; // UINT16 // Energy per hour UINT16 1 uint16_t Energy_hr = 0; memcpy(&Energy_hr, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Energy/hr: %d kCal/hr", Energy_hr); offset += 2; // UINT16 // Energy per minute UINT8 1 uint8_t Energy_pm = 0; memcpy(&Energy_pm, &IBDDataBuf[offset], 1); // Transfer buffer fields to variable Serial.printf(" Energy/m: %d kCal/m", Energy_pm); offset += 1; // UINT8 } if ((flags & 512) != 0) { // Heart Rate 1 uint8_t Heart_Rate = 0; memcpy(&Heart_Rate, &IBDDataBuf[offset], 1); // Transfer buffer fields to variable Serial.printf(" Heart Rate: %d HBM", Heart_Rate); offset += 1; // UINT8 } if ((flags & 1024) != 0) { // Metabolic Equivalent 0.1 uint8_t Mets = 0; memcpy(&Mets, &IBDDataBuf[offset], 1); // Transfer buffer fields to variable Serial.printf(" Metabolic Equivalent: %d ", Mets/10); offset += 1; // UINT8 } if ((flags & 2048) != 0) { // Elapsed Time 1 uint16_t elap_time = 0; memcpy(&elap_time, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Elapsed time: %d s", elap_time); offset += 2; // UINT16 } if ((flags & 4096) != 0) { // Remaining Time 1 uint16_t rem_time = 0; memcpy(&rem_time, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Remaining time: %d s", rem_time); offset += 2; // UINT16 } Serial.println(); }
/**
uint8_t RespBufferLen = (uint8_t)len; uint8_t RespBuffer[RespBufferLen] = {}; // It is max 6 bytes long // Transfer first the contents of data to buffer (array of chars) Serial.print(" -> Client Rec'd Raw FTM Control Point Response Data: [ "); for (int i = 0; i < sizeof(RespBuffer); i++) { RespBuffer[i] = *data++; Serial.printf("%02X ", RespBuffer[i], HEX); } Serial.println("]");
}
/**
@param len Length of received data / void client_FTM_Status_Notify_callback(BLEClientCharacteristic chr, uint8_t* data, uint16_t len) {
uint8_t SDataLen = (uint8_t)len; uint8_t SDataBuf[SDataLen] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw FTM Machine Status Data: [%d] [ ", len); for (int i = 0; i < sizeof(SDataBuf); i++) { SDataBuf[i] = *data++; Serial.printf("%02X ", SDataBuf[i], HEX); } Serial.println("] ");
}
// Byte swap unsigned short uint16_t swap_uint16( uint16_t val ) { return (val << 8) | (val >> 8 ); }
// Find certain uuid in the data of the received advertising packet bool checkForUuidPresent(const uint16_t uuid, const uint8_t* reportData, uint8_t reportDataLen) { // Enter uuid in printed format like 0x1826 for UUID16_SVC_FITNESS_MACHINE // uuid is internally stored in Little Endian for (int i = 0; i < (reportDataLen); i++) { // step 1: never miss out a position! if( memcmp(&uuid, (reportData+i), 2) == 0) { return true; } } return false; }
/**
Serial.println("Found advertising Peripheral with FTMS service!, see the Raw Data packet:"); Serial.println(F("Timestamp MAC Address Rssi Data")); Serial.printf("%09d ", millis()); // MAC is in little endian --> print reverse Serial.printBufferReverse(report->peer_addr.addr, 6, ':'); Serial.print(F(" ")); Serial.print(report->rssi); Serial.print(F(" ")); Serial.printBuffer(report->data.p_data, report->data.len, '-'); Serial.println();
Bluefruit.Central.connect(report); }
void PrintPeerAddress(uint8_t addr[6]) { for (int i = 1; i < 6; i++) { // Display byte by byte in HEX reverse: little Endian Serial.printf("%02X:",addr[(6-i)], HEX); } Serial.printf("%02X ",addr[0], HEX); }
/**
Serial.printf("Feather nRF52 (Central) connected to Trainer (Peripheral) device: [%s] MAC Address: ", peripheral_name); PrintPeerAddress(peripheral_addr); Serial.println();
client_Connection_Handle = conn_handle;
Serial.println("Now checking all Client Services and Characteristics!"); Serial.println("If Mandatory Services Fail --> the Client will disconnect!");
// ---------------------------- GA and DIS SERVICE ------------------------------------------
Serial.println("First checking Generic Access and Device Information Services and Characteristics!");
// If Generic Access is not found then go on.... NOT FATAL !
while (!(client_GenericAccess_Service.discover(conn_handle))) { if ( client_GenericAccess_Service.discover(conn_handle) ) {
Serial.print(F("Found Client Generic Access\n"));
if ( client_GA_DeviceName_Chr.discover() ) {
client_GA_DeviceName_Chr.read(client_GA_DeviceName_Data, sizeof(client_GA_DeviceName_Data));
Serial.printf(" -> Client Reads Device Name: [%s]\n", client_GA_DeviceName_Data);
}
if ( client_GA_Appearance_Chr.discover() ) {
client_GA_Appearance_Value = client_GA_Appearance_Chr.read16();
Serial.printf(" -> Client Reads Appearance: [%d]\n", client_GA_Appearance_Value);
}
} // GA
}
while (!( client_DIS_Service.discover(conn_handle) )){
// If DIS is not found then go on.... NOT FATAL !
if ( client_DIS_Service.discover(conn_handle) ) {
Serial.print(F("Found Client Device Information\n"));
// 1
if ( client_DIS_ManufacturerName_Chr.discover() ) {
// read and print out Manufacturer
if ( client_DIS_ManufacturerName_Chr.read(client_DIS_Manufacturer_Str, sizeof(client_DIS_Manufacturer_Str)) ) {
Serial.printf(" -> Client Reads Manufacturer: [%s]\n", client_DIS_Manufacturer_Str);
}
} // 1
// 2
if ( client_DIS_ModelNumber_Chr.discover() ) {
// read and print out Model Number
if ( client_DIS_ModelNumber_Chr.read(client_DIS_ModelNumber_Str, sizeof(client_DIS_ModelNumber_Str)) ) {
Serial.printf(" -> Client Reads Model Number: [%s]\n", client_DIS_ModelNumber_Str);
}
} // 2
// 3
if ( client_DIS_SerialNumber_Chr.discover() ) {
// read and print out Serial Number
if ( client_DIS_SerialNumber_Chr.read(client_DIS_SerialNumber_Str, sizeof(client_DIS_SerialNumber_Str)) ) {
Serial.printf(" -> Client Reads Serial Number: [%s]\n", client_DIS_SerialNumber_Str);
}
} // 3
} // DIS }
// ---------------------------- END GA and DIS SERVICE ------------------------------------------------
// -----------------------------FTM SERVICE ------------------------------------------------------------
Serial.print("Discovering Mandatory Client Fitness Machine (FTM) Service ... ");
// If FTM is not found, disconnect, resume scanning, and return if ( client_FitnessMachine_Service.discover(conn_handle) ) {
BLEConnection* conn = Bluefruit.Connection(conn_handle);
uint16_t max_payload = conn->getMtu()-3;
uint16_t data_length = conn->getDataLength();
Serial.print("Found it! ");
Serial.printf("FTMS Max Payload: %d Data Length: %d\n", max_payload, data_length);
} else {
Serial.println("Not Found!");
Serial.println("Disconnecting since Client FTM Service is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
return;
}
Serial.print("Discovering Client FTM Feature Characteristic ... ");
// If FTM Feature is not found, disconnect, resume scanning, and return while (!( client_FTM_Feature_Chr.discover() )) { if ( client_FTM_Feature_Chr.discover() ) {
Serial.println("Found it!");
// Read FTM Feature Data
client_FTM_Feature_Chr.read(client_FTM_Feature_Data, 8);
Serial.print(" -> Client Reads Raw FTM Feature bytes: [8] [ ");
for (int i = 0; i < sizeof(client_FTM_Feature_Data); i++) {
Serial.printf("%02X ", client_FTM_Feature_Data[i], HEX);
} // for
Serial.println("] ");
} else {
Serial.println("Disconnecting since Client FTM Feature Characteristic is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
Bluefruit.Connection(conn_handle);
Serial.print("Discovering Client FTM Feature not decouvert ... ");
// return; } }
Serial.print("Discovering Client FTM Control Point Characteristic ... ");
// If FTM Control Point is not found, disconnect, resume scanning, and return if ( client_FTM_ControlPoint_Chr.discover() ) {
Serial.println("Found it!");
} else {
Serial.println("Not Found!");
Serial.println("Disconnecting since Client FTM Control Point Characteristic is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
return;
}
Serial.print("Discovering Client FTM Status Characteristic ... ");
// If FTM Status is not found, disconnect, resume scanning, and return if ( client_FTM_Status_Chr.discover() ) {
Serial.println("Found it!");
} else {
Serial.println("Not Found!");
Serial.println("Disconnecting since Client FTM Status Characteristic is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
return;
}
Serial.print("Discovering Client FTM Training Status Characteristic ... ");
// FTM Training Status is NOT MANDATORY if ( client_FTM_TrainingStatus_Chr.discover() ) {
Serial.println("Found it!");
} else {
Serial.println("Not Found! Not Mandatory");
} /*
Serial.println("Not Found!");
Serial.println("Disconnecting since Client FTM Characteristic is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
return;
*/
Serial.print("Discovering Client FTM Supported Resistance Level Range Characteristic ... ");
// FTM SupportedResistanceLevelRange is not mandatory! if ( client_FTM_SupportedResistanceLevelRange_Chr.discover() ) {
Serial.println("Found it!");
// Read Supported Resistance Level Range Data
client_FTM_SupportedResistanceLevelRange_Chr.read(client_FTM_SupportedResistanceLevelRange_Data, 6);
Serial.print(" -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ ");
for (int i = 0; i < sizeof(client_FTM_SupportedResistanceLevelRange_Data); i++) {
Serial.printf("%02X ", client_FTM_SupportedResistanceLevelRange_Data[i], HEX);
} // for
Serial.println("] ");
} else {
Serial.println("Not Found! NOT mandatory!");
} / Serial.println("Disconnecting since Client FTM Supported Resistance Level Range Characteristic is mandatory!"); // MANDATORY so disconnect since we couldn't find the service Bluefruit.disconnect(conn_handle); return; /
Serial.print("Discovering Client FTM Supported Power Range Characteristic ... ");
// FTM SupportedPowerRange is not mandatory! if ( client_FTM_SupportedPowerRange_Chr.discover() ) {
Serial.println("Found it!");
// Read Supported Resistance Level Range values
client_FTM_SupportedPowerRange_Chr.read(client_FTM_SupportedPowerRange_Data, 6);
Serial.print(" -> Client Reads Raw FTM Supported Power Range bytes: [6] [ ");
for (int i = 0; i < sizeof(client_FTM_SupportedPowerRange_Data); i++) {
Serial.printf("%02X ", client_FTM_SupportedPowerRange_Data[i], HEX);
} // for
Serial.println("] ");
} else {
Serial.println("Not Found! NOT mandatory!");
} /*
Serial.println("Disconnecting since Client FTM Supported Power Range Characteristic is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
return;
*/
Serial.print("Discovering Client FTM Indoor Bike Data Characteristic ... ");
// FTM Indoor Bike Data is not mandatory if ( client_FTM_IndoorBikeData_Chr.discover() ) {
Serial.println("Found it!");
} else {
Serial.println("Not Found! Not Mandatory");
} /*
Serial.println("Not Found!");
Serial.println("Disconnecting since Client FTM Indoor Bike Data Characteristic is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
return;
*/ // ---------------------------- End FTM SERVICE --------------------------------------------- // ---------------------------- CP SERVICE --------------------------------------------------
Serial.print("Discovering Client Cycling Power (CP) Service ... ");
// If CPS is not found, disconnect, resume scanning, and return if ( client_CyclingPower_Service.discover(conn_handle) ) {
BLEConnection* conn = Bluefruit.Connection(conn_handle);
uint16_t max_payload = conn->getMtu()-3;
uint16_t data_length = conn->getDataLength();
Serial.print("Found it! ");
Serial.printf("CPS Max Payload: %d Data Length: %d\n", max_payload, data_length);
} else {
Serial.println("Not Found!");
Serial.println("Disconnecting since Client Cyling Power Service is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
return;
}
Serial.print("Discovering Client CP Measurement characteristic ... ");
if ( !client_CP_Measurement_Chr.discover() ) { // Measurement chr is mandatory, if it is not found (valid), then disconnect
Serial.println("Not Found!");
Serial.println("Disconnecting since Client CP Measurement Characteristic is mandatory!");
Bluefruit.disconnect(conn_handle);
return;
} else {
Serial.println("Found it!");
}
Serial.print("Discovering Client CP Control Point characteristic ... ");
if ( client_CP_ControlPoint_Chr.discover() ) { // CP Control Point chr is not mandatory
Serial.println("Found it!");
} else {
Serial.println("Not Found! NOT Mandatory!");
}
Serial.print("Discovering Client CP Feature characteristic ... ");
if ( client_CP_Feature_Chr.discover() ) {
Serial.println("Found it!");
// Configure the Cycle Power Feature characteristic // Properties = Read // Min Len = 1 // Max Len = 32 // B0:3 = UINT8 - Cycling Power Feature (MANDATORY) // b0 = Pedal power balance supported; 0 = false, 1 = true // b1 = Accumulated torque supported; 0 = false, 1 = true // b2 = Wheel revolution data supported; 0 = false, 1 = true // b3 = Crank revolution data supported; 0 = false, 1 = true // b4 = Extreme magnatudes supported; 0 = false, 1 = true // b5 = Extreme angles supported; 0 = false, 1 = true // b6 = Top/bottom dead angle supported; 0 = false, 1 = true // b7 = Accumulated energy supported; 0 = false, 1 = true // b8 = Offset compensation indicator supported; 0 = false, 1 = true // b9 = Offset compensation supported; 0 = false, 1 = true // b10 = Cycling power measurement characteristic content masking supported; 0 = false, 1 = true // b11 = Multiple sensor locations supported; 0 = false, 1 = true // b12 = Crank length adj. supported; 0 = false, 1 = true // b13 = Chain length adj. supported; 0 = false, 1 = true // b14 = Chain weight adj. supported; 0 = false, 1 = true // b15 = Span length adj. supported; 0 = false, 1 = true // b16 = Sensor measurement context; 0 = force, 1 = torque // b17 = Instantaineous measurement direction supported; 0 = false, 1 = true // b18 = Factory calibrated date supported; 0 = false, 1 = true // b19 = Enhanced offset compensation supported; 0 = false, 1 = true // b20:21 = Distribtue system support; 0 = legacy, 1 = not supported, 2 = supported, 3 = RFU // b22:32 = Reserved
// Read 32-bit client_CP_Feature_Chr value client_CP_Feature_Flags = client_CP_Feature_Chr.read32();
const uint8_t CPFC_FIXED_DATALEN = 4; uint8_t cpfcData[CPFC_FIXED_DATALEN] = {(uint8_t)(client_CP_Feature_Flags & 0xff), (uint8_t)(client_CP_Feature_Flags >> 8), (uint8_t)(client_CP_Feature_Flags >> 16), (uint8_t)(client_CP_Feature_Flags >> 24)}; Serial.print(" -> Client Reads Raw CP Feature bytes: [4] [ "); for (int i = 0; i < CPFC_FIXED_DATALEN; i++) { if ( i <= sizeof(cpfcData)) { Serial.printf("%02X ", cpfcData[i], HEX); } } Serial.println("] "); for (int i = 0; i < sizeof(client_CP_Feature_Str); i++) { if ( client_CP_Feature_Flags & (1 << i) ) { Serial.println(client_CP_Feature_Str[i]); } }
} else {
Serial.println("NOT Found! NOT Mandatory!");
}
Serial.print("Discovering Client CP Sensor Location characteristic ... ");
if ( client_CP_Location_Chr.discover() ) {
Serial.println("Found it!");
// The Sensor Location characteristic // Properties = Read // Min Len = 1 // Max Len = 1 // B0:1 = UINT8 - Sensor Location
// Read 8-bit client CP sensor location value
client_CP_Location_Value = client_CP_Location_Chr.read8();
Serial.print(" -> Client Reads CP Location Sensor: ");
Serial.printf("Loc#: %d %s\n", client_CP_Location_Value, client_Sensor_Location_Str[client_CP_Location_Value]);
} else {
Serial.println("NOT Found! NOT Mandatory!");
} // ---------------------------- END CP SERVICE ------------------------------------------------ // ---------------------------- CSC SERVICE --------------------------------------------------
Serial.print("Discovering Cycling Speed and Cadence (CSC) Service ... ");
if ( client_CyclingSpeedCadence_Service.discover(conn_handle) ) // UUID16_SVC_CYCLING_SPEED_AND_CADENCE {
BLEConnection* conn = Bluefruit.Connection(conn_handle);
uint16_t max_payload = conn->getMtu()-3;
uint16_t data_length = conn->getDataLength();
Serial.print("Found it! ");
Serial.printf("CSCS Max Payload: %d Data Length: %d\n", max_payload, data_length);
} else {
Serial.println("Not Found! CSC Service is Not Mandatory!");
return; // NO CSC -> end of client_connect_callback !!
} /* // Is Mandatory
Serial.println("Not Found and disconnecting!");
Serial.println("CSC Service is mandatory!");
Bluefruit.disconnect(conn_handle);
return;
*/
// Test for client CSC Characteristics when the client CSC Service is existing
Serial.print("Discovering Client CSC Measurement CHR ... ");
if ( client_CSC_Measurement_Chr.discover() ) // UUID16_CHR_CSC_MEASUREMENT {
Serial.println("Found it! ");
} else {
Serial.println("Not Found! Not Mandatory!");
} /* // Is Mandatory
Serial.println("Not Found!");
Serial.println("Disconnecting since Client CSC Measurement CHR is mandatory!");
Bluefruit.disconnect(conn_handle);
return;
*/
Serial.print("Discovering Client CSC Location CHR ... ");
if ( client_CSC_Location_Chr.discover() ) // UUID16_CHR_SENSOR_LOCATION {
Serial.println("Found it!");
// Read 16-bit client CSC sensor location value
client_CSC_Location_Value = client_CSC_Location_Chr.read8();
Serial.print(" -> Client Reads CSC Location Sensor: ");
Serial.printf("Loc#: %d %s\n", client_CSC_Location_Value, client_Sensor_Location_Str[client_CSC_Location_Value]);
} else {
Serial.println("Not Found! NOT Mandatory!");
}
Serial.print("Discovering Client CSC Feature CHR ... ");
if ( client_CSC_Feature_Chr.discover() ) // UUID16_CHR_CSC_FEATURE {
Serial.println("Found it!");
// Read sensor CSC Feature value in 16 bit
client_CSC_Feature_Flags = client_CSC_Feature_Chr.read16();
uint8_t cscfcData[CSC_FEATURE_FIXED_DATALEN] = { (uint8_t)(client_CSC_Feature_Flags & 0xff), (uint8_t)(client_CSC_Feature_Flags >> 8) }; // Little Endian Representation
Serial.printf(" -> Client Reads Raw CSC Feature bytes: [2] [ ");
for (int i = 0; i < sizeof(cscfcData); i++) {
Serial.printf("%02X ", cscfcData[i], HEX);
}
Serial.println("] ");
for (int i = 0; i < sizeof(client_CSC_Feature_Str); i++) {
if ( (client_CSC_Feature_Flags & (1 << i)) != 0 )
{
Serial.println(client_CSC_Feature_Str[i]);
}
}
} else {
Serial.println("Not Found! NOT Mandatory!");
} // ---------------------------- END CSC SERVICE --------------------------------------------- } // End client_connect_callback
/**
Serial.print("Client Disconnected, reason = 0x"); Serial.println(reason, HEX); Serial.println(">>> Restart the Feather nRF52 Client for a new run! <<<");
}
/**
@param len Length of received data / void client_CP_Measurement_Chr_notify_callback(BLEClientCharacteristic chr, uint8_t* data, uint16_t len) {
uint8_t buffer[len]= {}; /{ (uint8_t)(cpmcDef & 0xff), (uint8_t)(cpmcDef >> 8), // flags (uint8_t)(powerOut & 0xff), (uint8_t)(powerOut >> 8), // inst. power 0, // bal 0, 0, // torque 0, 0, 0, 0, // cum. rev 0, 0, // wheel time 0, 0, // cum. crank 0, 0, // crank time 0, 0, // max force 0, 0, // min force 0, 0, // max tor 0, 0, // min tor 0, 0, // max ang 0, 0, // min ang 0, 0, // tdc 0, 0, // bdc 0, 0 }; // total energy / // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw CP Data: [%d] [ ", len); for (int i = 0; i < sizeof(buffer); i++) { if ( i <= sizeof(buffer)) { buffer[i] = *data++; Serial.printf("%02X ", buffer[i], HEX); } } Serial.print("] ");
uint8_t offset = 0; // Get flags field uint16_t flags = 0; memcpy(&flags, &buffer[offset], 2); // Transfer buffer fields to variable offset += 2; // UINT16 // Get Instantaneous Power values UINT16 uint16_t PowerValue = 0; memcpy(&PowerValue, &buffer[offset], 2); // Transfer buffer fields to variable offset += 2; // UINT16 Serial.printf("Instantaneous Power: %4d\n", PowerValue); // Get the other CP measurement values if ((flags & 1) != 0) { // Power Balance Present Serial.print(" --> Pedal Power Balance!"); } if ((flags & 2) != 0) { // Accumulated Torque Serial.println(" --> Accumulated Torque!"); } // etcetera...
} // End cpmc_notify_callback
/**
// Handle the response message
uint8_t cpcpDataLen = (uint8_t)len; uint8_t cpcpData[cpcpDataLen]= {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw CP Control Point Data: [%d] [ ", len); for (int i = 0; i < sizeof(cpcpData); i++) { cpcpData[i] = *data++; Serial.printf("%02X ", cpcpData[i], HEX); } Serial.print("] ");
}
/**
uint8_t buffer[len]= {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw CSC Data: [%d] [ ", len); for (int i = 0; i < len; i++) { if ( i <= sizeof(buffer)) { buffer[i] = data++; Serial.printf("%02X ", buffer[i], HEX); } } Serial.print("] "); uint8_t offset = 0; // we define the offset that is to be used when reading the next field // Size of variables (e.g. 2 (16) or 4 bytes (32)) are constants in BluetoothGattCharacteristic // these represent the values you can find in the "Value Fields" table in the "Format" column // Read the Flags field at buffer[0] uint8_t flags = buffer[offset]; offset += 1; // UINT8 // we have to check the flags' nth bit to see if C1 field exists if ((flags & 1) != 0) { uint32_t cum_wheel_rev = 0; memcpy(&cum_wheel_rev, &buffer[offset], 4); offset += 4; // UINT32 uint16_t last_wheel_event = 0; memcpy(&last_wheel_event, &buffer[offset], 2); offset += 2; // UINT16 Serial.printf(" Cum. wheel rev.: %d Last wheel event: %d ", cum_wheel_rev, last_wheel_event); / Calculation of speed at the Collector can be derived from the wheel circumference and
}
Dear Jörghen,
Here is the disappointing result.
The problem is still the same no feedback with V0.27
Let's not lose heart!
123456789101112131415161718192021 /***** This is programming code for the nRF52 based Bluefruit BLE boards
The code uses heavily the Adafruit supplied Bluefruit BLE libraries !! Adafruit invests time and resources providing open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
MIT license, check LICENSE for more information All text must be included in any redistribution
Message (Enter to send message to 'Adafruit ItsyBitsy nRF52840 Express' on 'COM11') New Line 115200 baud 16:59:01.080 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 16:59:01.080 -> ----------------- Version 02.7 ------------------ 16:59:01.080 -> Initialise the Bluefruit nRF52 module: Client (Central) 16:59:01.205 -> FTMS and Chars 'initialized' 16:59:01.205 -> CPS and Chars 'initialized' 16:59:01.205 -> CSCS and Chars 'initialized' 16:59:01.205 -> GA and Chars 'initialized' 16:59:01.205 -> DIS and Chars 'initialized' 16:59:01.205 -> Start Scanning for CPS, CSC and FTMS! 16:59:01.434 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 16:59:01.434 -> Timestamp MAC Address Rssi Data 16:59:01.434 -> 000091471 F8:9C:FC:53:5E:49 -59 09-02-16-18-26-18-18-18-0A-18 16:59:01.575 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 16:59:01.575 -> Now checking all Client Services and Characteristics! 16:59:01.575 -> If Mandatory Services Fail --> the Client will disconnect! 16:59:01.575 -> First checking Generic Access and Device Information Services and Characteristics! 16:59:01.668 -> Found Client Generic Access 16:59:01.808 -> -> Client Reads Device Name: [Zwift Hub] 16:59:02.042 -> -> Client Reads Appearance: [0] 16:59:02.042 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Not Found! 16:59:02.042 -> Disconnecting since Client FTM Service is mandatory! 16:59:02.121 -> Client Disconnected, reason = 0x16 16:59:02.121 -> >>> Restart the Feather nRF52 Client for a new run! <<< 16:59:12.257 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 16:59:12.257 -> ----------------- Version 02.7 ------------------ 16:59:12.257 -> Initialise the Bluefruit nRF52 module: Client (Central) 16:59:12.257 -> FTMS and Chars 'initialized' 16:59:12.257 -> CPS and Chars 'initialized' 16:59:12.257 -> CSCS and Chars 'initialized' 16:59:12.257 -> GA and Chars 'initialized' 16:59:12.257 -> DIS and Chars 'initialized' 16:59:12.257 -> Start Scanning for CPS, CSC and FTMS! 16:59:12.258 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 16:59:12.258 -> Timestamp MAC Address Rssi Data 16:59:12.258 -> 000001100 F8:9C:FC:53:5E:49 -55 09-02-16-18-26-18-18-18-0A-18 16:59:12.258 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 16:59:12.258 -> Now checking all Client Services and Characteristics! 16:59:12.258 -> If Mandatory Services Fail --> the Client will disconnect! 16:59:12.258 -> First checking Generic Access and Device Information Services and Characteristics! 16:59:12.266 -> Found Client Generic Access 16:59:12.266 -> -> Client Reads Device Name: [Zwift Hub] 16:59:12.266 -> -> Client Reads Appearance: [1152] 16:59:12.266 -> Found Client Device Information 16:59:12.266 -> -> Client Reads Manufacturer: [Zwift]
Here is the result of FTMS_Zwift_Bridge_v023:
17:15:10.800 -> Feather nRF52840 MITM supporting: CPS, CSC and FTMS 17:15:10.800 -> ------------------ Version 02.3 --------------------- 17:15:10.804 -> FTM Service and Chars are 'initialized' 17:15:10.804 -> CP Service and Chars are 'initialized' 17:15:10.804 -> CSC Service and Chars are 'initialized' 17:15:10.804 -> Generic Access Service and Chars are 'initialized' 17:15:10.804 -> Device Information Service and Chars are 'initialized' 17:15:10.804 -> Start Client-side Scanning for CPS, CSC and FTMS! 17:15:10.805 -> Found advertising Peripheral with FTMS enabled! See Raw data packet: 17:15:10.805 -> Timestamp Addr Rssi Data 17:15:10.805 -> 000001606 F8:9C:FC:53:5E:49 -55 09-02-16-18-26-18-18-18-0A-18 17:15:10.805 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:15:10.805 -> Now checking all mandatory Client Services and Characteristics! 17:15:10.805 -> If Mandatory Services Fail --> the Client will disconnect! 17:15:10.805 -> First checking Generic Access and Device Information Services and Characteristics! 17:15:10.828 -> Found Client Generic Access 17:15:10.828 -> -> Client Reads Device Name: [Zwift Hub] 17:15:10.828 -> -> Client Reads Appearance: [1152] 17:15:10.828 -> Found Client Device Information 17:15:10.828 -> -> Client Reads Manufacturer: [Zwift] 17:15:10.829 -> -> Client Reads Model Number: [06] 17:15:10.920 -> -> Client Reads Serial Number: [06-F89CFC535E49] 17:15:10.920 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 17:15:11.008 -> Discovering Client FTM Feature Characteristic ... Found it! 17:15:11.124 -> -> Client Reads Raw FTM Feature bytes: [8] [ 87 44 00 00 0C E0 00 00 ] 17:15:11.124 -> Discovering Client FTM Control Point Characteristic ... Found it! 17:15:11.703 -> Discovering Client FTM Status Characteristic ... Found it! 17:15:11.984 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 17:15:12.285 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 17:15:12.402 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 17:15:12.402 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 17:15:12.742 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 00 00 00 00 ] 17:15:12.742 -> Discovering Client FTM Indoor Bike Data Characteristic ... Not Found! Not Mandatory 17:15:12.742 -> Discovering Client Cycling Power (CP) Service ... Not Found! 17:15:12.742 -> Disconnecting since Client Cyling Power Service is mandatory! 17:15:12.834 -> Client disconnected from Peripheral Device: [Zwift Hub], reason: [16] 17:15:27.560 -> Feather nRF52840 MITM supporting: CPS, CSC and FTMS 17:15:27.560 -> ------------------ Version 02.3 --------------------- 17:15:27.822 -> FTM Service and Chars are 'initialized' 17:15:27.822 -> CP Service and Chars are 'initialized' 17:15:27.822 -> CSC Service and Chars are 'initialized' 17:15:27.822 -> Generic Access Service and Chars are 'initialized' 17:15:27.822 -> Device Information Service and Chars are 'initialized' 17:15:27.822 -> Start Client-side Scanning for CPS, CSC and FTMS! 17:15:27.836 -> Found advertising Peripheral with FTMS enabled! See Raw data packet: 17:15:27.836 -> Timestamp Addr Rssi Data 17:15:27.836 -> 000001270 F8:9C:FC:53:5E:49 -60 09-02-16-18-26-18-18-18-0A-18 17:15:27.836 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:15:27.836 -> Now checking all mandatory Client Services and Characteristics! 17:15:27.836 -> If Mandatory Services Fail --> the Client will disconnect! 17:15:27.836 -> First checking Generic Access and Device Information Services and Characteristics!
I'll see if with the "While" in the "Bridge V23" version if it's better
The cadence is OK but I don't have the Watts!?
Here is the modified code and the results :
/***** This is programming code for the nRF52 based Bluefruit BLE boards
The code uses heavily the Adafruit supplied Bluefruit BLE libraries !! Adafruit invests time and resources providing open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
MIT license, check LICENSE for more information
All text must be included in any redistribution
*****/
The code links a BLE Server (a peripheral to Zwift) and a BLE Client (a central to the Trainer) with a bridge
in between, the Feather nRF52 being man-in-the-middle (MITM).
The nRF52-bridge can control, filter and alter the bi-directional interchanged data!
The client-side (central) scans and connects with the trainer relevant services: FTMS, CPS and CSC. It collects
all cyling data of the services and passes these on to the server-side....
The client-side supplies the indoor trainer with target and resistance control data.
The server-side (peripheral) advertises and enables connection with cycling apps like Zwift and collects the app's
control commands, target and resistance data. It passes these on to the client-side....
The server-side supplies the app with the generated cycling data in return.
The client plus server (MITM) are transparent to the indoor trainer as well as to the training app Zwift or alike!
Requirements: Zwift app or alike, Feather nRF52 board and a FTMS/CPS/CSC supporting indoor trainer
1) Upload and Run this code on the Feather nRF52
2) Start the Serial Monitor to catch debugging info
3) Start/Power On the indoor trainer
4) Feather nRF52 and trainer (with <name>) will pair as reported in the output
5) Start Zwift on your computer or tablet and wait....
6) Search on the Zwift pairing screens for the Feather nRF52 a.k.a. "Sim <name>"
7) Pair: Power, Cadence and Controllable one after another with "Sim <name>"
8) Optionally one can pair as well devices for heartrate and/or steering (Sterzo)
9) Start the default Zwift ride or any ride you wish
10) Make Serial Monitor output window visible on top of the Zwift window 11) Hop on the bike: do the work and feel resistance change with the road 12) Inspect the info presented by Serial Monitor.....
Your trainer's device <name> is modified by the bridge to "Sim <name>", to allow for a clear distinction
between the bridge (simulating your trainer) and your original trainer, when advertising the trainer's services!
You will notice this only when connecting to Zwift on the pairing screens! Notice: Zwift extends device names with
additional numbers for identification!
*/
// ------------------------------------------------------------------------------------------- // COMPILER DIRECTIVE to allow/suppress SERIAL.PRINT messages that help debugging... // Uncomment to activate
// Restrict activating one or more of the following DEBUG directives --> process intensive // Have caused spurious side effects like a loss of quality of service handling!! //#define DEBUG_CP_MEASUREMENT //#define DEBUG_CSC_MEASUREMENT //#define DEBUG_FTM_INDOORBIKEDATA // --------------------------------------------------------------------------------------------
const uint8_t MAX_PAYLOAD = 20; // Max 20 byte data size for single packet BLE transfer
// Struct containing Device info to administer dis/connected devices typedef struct { uint8_t PeerAddress[6]; char PeerName[MAX_PAYLOAD]; uint16_t conn_handle; bool IsConnected; } Device_info_t; // ----------------------------------------------------------------- // Your hardware MAC/DEVICE ADDRESSES // Laptop/Desktop Device Address that runs Zwift, in printed format: [00:01:02:03:04:05] // Little Endian: in reversed order !!!!
// Trainer FTMS enabled Device Address, in printed format: [00:01:02:03:04:05] // Little Endian: in reversed order !!!!
// ----------------------------------------------------------------- // Initialize connectable device registration Device_info_t Trainer = {TRAINERADDRESS, {0x00}, BLE_CONN_HANDLE_INVALID, false}; Device_info_t Laptop = { LAPTOPADDRESS, {0x00}, BLE_CONN_HANDLE_INVALID, false}; Device_info_t Smartphone = { {0x00}, {0x00}, BLE_CONN_HANDLE_INVALID, false}; // ----------------------------------------------------------------------------------
/* Generic Access
*/ BLEClientService client_GenericAccess_Service(UUID16_SVC_GENERIC_ACCESS); // Optional BLEClientCharacteristic client_GA_Appearance_Chr(UUID16_CHR_APPEARANCE); // Read uint16_t client_GA_Appearance_Value = 0; BLEClientCharacteristic client_GA_DeviceName_Chr(UUID16_CHR_DEVICE_NAME); // Read, Write unsigned char client_GA_DeviceName_Data[MAX_PAYLOAD] = {};
/ Cycling Power Service CP Service: 0x1818 CP Characteristic: 0x2A63 (Measurement) CP Characteristic: 0x2A65 (Feature) CP Characteristic: 0x2A5D (Location) CP Characteristic: 0x2A66 (Control Point) / BLEClientService client_CyclingPower_Service(UUID16_SVC_CYCLING_POWER); // Mandatory BLEClientCharacteristic client_CP_Measurement_Chr(UUID16_CHR_CYCLING_POWER_MEASUREMENT); // Notify, Read, Mandatory BLEClientCharacteristic client_CP_Feature_Chr(UUID16_CHR_CYCLING_POWER_FEATURE); // Read, optional uint32_t client_CP_Feature_Flags = 0; const uint8_t CP_FEATURE_DATALEN = 4; // Set MaxLen to 4 const char client_CP_Feature_Str[] = { "Pedal power balance supported", "Accumulated torque supported", "Wheel revolution data supported", "Crank revolution data supported", \ "Extreme magnitudes supported", "Extreme angles supported", "Top/bottom dead angle supported", "Accumulated energy supported", \ "Offset compensation indicator supported", "Offset compensation supported", "Cycling power measurement characteristic content masking supported", \ "Multiple sensor locations supported", "Crank length adj. supported", "Chain length adj. supported", "Chain weight adj. supported", \ "Span length adj. supported", "Sensor measurement context", "Instantaineous measurement direction supported", "Factory calibrated date supported", \ "Enhanced offset compensation supported" }; BLEClientCharacteristic client_CP_Location_Chr(UUID16_CHR_SENSOR_LOCATION); // Read, optional uint8_t client_CP_Location_Value = 0; // UINT8 const char client_Sensor_Location_Str[] = { "Other", "Top of shoe", "In shoe", "Hip", "Front wheel", "Left crank", "Right crank", "Left pedal", \ "Right pedal", "Front hub", "Rear dropout", "Chainstay", "Rear wheel", "Rear hub", "Chest", "Spider", "Chain ring" }; BLEClientCharacteristic client_CP_ControlPoint_Chr(UUID16_CHR_CYCLING_POWER_CONTROL_POINT); // Indicate, Write, optional const uint16_t CP_CONTROL_POINT_DATALEN = 5;
/ Cycling Speed and Cadence Service CSC Service: 0x1816 CSC Measurement Characteristic: 0x2A5B CSC Feature Characteristic: 0x2A5C CSC Location Characteristic: 0x2A5D CSC Control Point Characteristic:0x2A55 ---> not implemented / BLEClientService client_CyclingSpeedCadence_Service(UUID16_SVC_CYCLING_SPEED_AND_CADENCE); // Mandatory BLEClientCharacteristic client_CSC_Measurement_Chr(UUID16_CHR_CSC_MEASUREMENT); // Notify, Read, Mandatory BLEClientCharacteristic client_CSC_Feature_Chr(UUID16_CHR_CSC_FEATURE); // Read, optional const uint8_t CSC_FEATURE_FIXED_DATALEN = 2; // UINT16 uint16_t client_CSC_Feature_Flags = 0; const char* client_CSC_Feature_Str[] = {"Wheel rev supported", "Crank rev supported", "Multiple locations supported"}; BLEClientCharacteristic client_CSC_Location_Chr(UUID16_CHR_SENSOR_LOCATION); // Read, optional uint8_t client_CSC_Location_Value = 0; // Shared with CPS --> client_Sensor_Location_Str[]
/* Service Device Information
*/ BLEClientService client_DIS_Service(UUID16_SVC_DEVICE_INFORMATION); // Optional BLEClientCharacteristic client_DIS_ManufacturerName_Chr(UUID16_CHR_MANUFACTURER_NAME_STRING); // Read char client_DIS_Manufacturer_Str[MAX_PAYLOAD] = {}; BLEClientCharacteristic client_DIS_ModelNumber_Chr(UUID16_CHR_MODEL_NUMBER_STRING); // Read char client_DIS_ModelNumber_Str[MAX_PAYLOAD] = {}; BLEClientCharacteristic client_DIS_SerialNumber_Chr(UUID16_CHR_SERIAL_NUMBER_STRING); // Read char client_DIS_SerialNumber_Str[MAX_PAYLOAD] = {};
/* Fitness Machine Service
*/ BLEClientService client_FitnessMachine_Service(UUID16_SVC_FITNESS_MACHINE); // Mandatory // Service characteristics exposed by FTM Service BLEClientCharacteristic client_FTM_Feature_Chr(UUID16_CHR_FITNESS_MACHINE_FEATURE); // Mandatory, Read const uint8_t FTM_FEATURE_FIXED_DATALEN = 8; uint8_t client_FTM_Feature_Data[FTM_FEATURE_FIXED_DATALEN]; BLEClientCharacteristic client_FTM_IndoorBikeData_Chr(UUID16_CHR_INDOOR_BIKE_DATA); // Optional, Notify BLEClientCharacteristic client_FTM_TrainingStatus_Chr(UUID16_CHR_TRAINING_STATUS); // Optional, Read & Notify BLEClientCharacteristic client_FTM_SupportedResistanceLevelRange_Chr(UUID16_CHR_SUPPORTED_RESISTANCE_LEVEL_RANGE); // Mandatory, Read const uint8_t FTM_SRLR_FIXED_DATALEN = 6; uint8_t client_FTM_SupportedResistanceLevelRange_Data[FTM_SRLR_FIXED_DATALEN]; BLEClientCharacteristic client_FTM_SupportedPowerRange_Chr(UUID16_CHR_SUPPORTED_POWER_RANGE); // Mandatory, Read const uint8_t FTM_SPR_FIXED_DATALEN = 6; uint8_t client_FTM_SupportedPowerRange_Data[FTM_SPR_FIXED_DATALEN]; BLEClientCharacteristic client_FTM_ControlPoint_Chr(UUID16_CHR_FITNESS_MACHINE_CONTROL_POINT); // Mandatory, Write & Indicate BLEClientCharacteristic client_FTM_Status_Chr(UUID16_CHR_FITNESS_MACHINE_STATUS); // Mandatory, Notify
// ------------------------------------ START of SERVER DEFINITIONS ----------------------------------------------------- / Cycling Speed and Cadence Service / BLEService server_CyclingSpeedCadence_Service = BLEService(UUID16_SVC_CYCLING_SPEED_AND_CADENCE); BLECharacteristic server_CSC_Measurement_Chr = BLECharacteristic(UUID16_CHR_CSC_MEASUREMENT); // Notify, Read BLECharacteristic server_CSC_Feature_Chr = BLECharacteristic(UUID16_CHR_CSC_FEATURE); // Read BLECharacteristic server_CSC_Location_Chr = BLECharacteristic(UUID16_CHR_SENSOR_LOCATION); // Read
/ Cycling Power Service / BLEService server_CylingPower_Service = BLEService(UUID16_SVC_CYCLING_POWER); BLECharacteristic server_CP_Measurement_Chr = BLECharacteristic(UUID16_CHR_CYCLING_POWER_MEASUREMENT); // Notify, Read BLECharacteristic server_CP_Feature_Chr = BLECharacteristic(UUID16_CHR_CYCLING_POWER_FEATURE); // Read BLECharacteristic server_CP_Location_Chr = BLECharacteristic(UUID16_CHR_SENSOR_LOCATION); // Read BLECharacteristic server_CP_ControlPoint_Chr = BLECharacteristic(UUID16_CHR_CYCLING_POWER_CONTROL_POINT); // Indicate, Write
/ Fitness Machine Service / BLEService server_FitnessMachine_Service = BLEService(UUID16_SVC_FITNESS_MACHINE); BLECharacteristic server_FTM_Feature_Chr = BLECharacteristic(UUID16_CHR_FITNESS_MACHINE_FEATURE); // Read BLECharacteristic server_FTM_IndoorBikeData_Chr = BLECharacteristic(UUID16_CHR_INDOOR_BIKE_DATA); // Notify BLECharacteristic server_FTM_TrainingStatus_Chr = BLECharacteristic(UUID16_CHR_TRAINING_STATUS); // Notify, Read const uint8_t FTM_TRAINING_STATUS_FIXED_DATALEN = 2; // Fixed len BLECharacteristic server_FTM_SupportedResistanceLevelRange_Chr = BLECharacteristic(UUID16_CHR_SUPPORTED_RESISTANCE_LEVEL_RANGE); // Read BLECharacteristic server_FTM_SupportedPowerRange_Chr = BLECharacteristic(UUID16_CHR_SUPPORTED_POWER_RANGE); // Read BLECharacteristic server_FTM_ControlPoint_Chr = BLECharacteristic(UUID16_CHR_FITNESS_MACHINE_CONTROL_POINT); // Write & Indicate BLECharacteristic server_FTM_Status_Chr = BLECharacteristic(UUID16_CHR_FITNESS_MACHINE_STATUS); // Notify const uint8_t FTM_STATUS_DATALEN = 7; // Max Len was: [3] --> Notice that with de Elite Direto the size is: [7] !!
/ Device Information Service helper class instance / BLEDis server_bledis; // Read unsigned char FirmwareRevStr[] = "0.0.0"; unsigned char HardwareRevStr[] = "0.0.0"; unsigned char SoftwareRevStr[] = "0.0.0";
/ NORDIC UART SERVICE a.k.a. NUS NUS Service: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E NUS RXD : 6E400002-B5A3-F393-E0A9-E50E24DCCA9E NUS TXD : 6E400003-B5A3-F393-E0A9-E50E24DCCA9E / const uint8_t UUID_NUS_SERVICE[] = {0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x01, 0x00, 0x40, 0x6E}; const uint8_t UUID_NUS_CHR_RXD[] = {0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x02, 0x00, 0x40, 0x6E}; const uint8_t UUID_NUS_CHR_TXD[] = {0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x03, 0x00, 0x40, 0x6E}; BLEService server_NordicUart_Service = BLEService(UUID_NUS_SERVICE); BLECharacteristic server_NUS_RXD_Chr = BLECharacteristic(UUID_NUS_CHR_RXD); // Read (Receiving Data) BLECharacteristic server_NUS_TXD_Chr = BLECharacteristic(UUID_NUS_CHR_TXD); // Notify (Sending Data)
// ----------------------------- The Fitness Machine Control Point data type structure -------------------------------- // ---------------------------- Decoding is done in: server_FTM_ControlPoint_Chr_callback ------------------------------ const uint8_t ftmcpRequestControl = 0x00; const uint8_t ftmcpReset = 0x01; const uint8_t ftmcpSetTargetSpeed = 0x02; const uint8_t ftmcpSetTargetInclination = 0x03; const uint8_t ftmcpSetTargetResistanceLevel = 0x04; const uint8_t ftmcpSetTargetPower = 0x05; const uint8_t ftmcpSetTargetHeartRate = 0x06; const uint8_t ftmcpStartOrResume = 0x07; const uint8_t ftmcpStopOrPause = 0x08; const uint8_t ftmcpSetTargetedExpendedEngery = 0x09; const uint8_t ftmcpSetTargetedNumberOfSteps = 0x0A; const uint8_t ftmcpSetTargetedNumberOfStrided = 0x0B; const uint8_t ftmcpSetTargetedDistance = 0x0C; const uint8_t ftmcpSetTargetedTrainingTime = 0x0D; const uint8_t ftmcpSetTargetedTimeInTwoHeartRateZones = 0x0E; const uint8_t ftmcpSetTargetedTimeInThreeHeartRateZones = 0x0F; const uint8_t ftmcpSetTargetedTimeInFiveHeartRateZones = 0x10; const uint8_t ftmcpSetIndoorBikeSimulationParameters = 0x11; const uint8_t ftmcpSetWheelCircumference = 0x12; const uint8_t ftmcpSetSpinDownControl = 0x13; const uint8_t ftmcpSetTargetedCadence = 0x14;
const uint8_t FTM_CONTROL_POINT_DATALEN = 19; // Control point consists of 1 opcode (byte) and maximum 18 bytes as parameters // This ftmcp_data_t structure represents the control point data. The first octet represents the opcode of the request // followed by a parameter array of maximum 18 octects typedef struct attribute( ( packed ) ) { uint8_t OPCODE; uint8_t OCTETS[(FTM_CONTROL_POINT_DATALEN - 1)]; } ftmcp_data_t; typedef union // The union type automatically maps the bytes member array to the ftmcp_data_t structure member values { ftmcp_data_t values; uint8_t bytes[FTM_CONTROL_POINT_DATALEN]; } ftmcp_data_ut; // Fitness Machine Control Point Data variable ftmcp_data_ut server_FTM_Control_Point_Data; // ----------------------- end of server_FTM_ControlPoint_Chr_callback definitions ----------------------------
// -------------------------------------- END OF SERVER DEFINITIONS -------------------------------------------
// -------------------------------------------------------------------------------- // Global Server variables for decoding of INDOOR BIKE RESISTANCE PARAMETERS // -------------------------------------------------------------------------------- float wind_speed = 0; // meters per second, resolution 0.001 float grade = 0; // percentage, resolution 0.01 float crr = 0; // Coefficient of rolling resistance, resolution 0.0001 float cw = 0; // Wind resistance Kg/m, resolution 0.01; // --------------------------------------------------------------------------------
unsigned long TimeInterval = 0;
void setup() {
Serial.begin(115200); while ( !Serial ) delay(10); // for nrf52840 with native usb Serial.println("Feather nRF52840 MITM supporting: CPS, CSC and FTMS"); Serial.println("------------------ Version 02.3 ---------------------");
// Initialize Bluefruit with maximum connections as Peripheral = 1, Central = 1 Bluefruit.begin(1, 1); Setup_Client_FTMS(); Setup_Client_CPS(); Setup_Client_CSC(); Setup_Client_DIS(); Client_Start_Scanning();
while (Bluefruit.Scanner.isRunning()) { // do nothing else but scanning.... yield(); } // wait enough time or go on when Client/Central is connected and all set! TimeInterval = millis() + TIME_SPAN; // ADD just enough delay while ( (millis() < TimeInterval) || (!Trainer.IsConnected) ) { yield(); }
// Configure and Start the Device Information Service
Serial.println("Configuring the Server Device Information Service");
server_setupDIS(); // Setup the Cycle Power Service, Speed & Cadence Service and FTMS
Serial.println("Configuring the Server Cycle Power Service");
server_setupCPS();
Serial.println("Configuring the Server Cadence and Speed Service");
server_setupCSC();
Serial.println("Configuring the Server Fitness Machine Service");
server_setupFTMS();
Serial.println("Configuring the Server NUS Service");
server_setupNUS(); // Setup and start advertising
Serial.println("Setting up the Server-side advertising payload(s)");
server_startADV();
Serial.println("Server-side is CPS, CSC and FTMS advertising!");
while (Bluefruit.Advertising.isRunning()) { // ONLY advertise! yield(); } TimeInterval = millis() + TIME_SPAN; // ADD just enough DELAY // wait enough time or go on when Server/Peripheral is connected and set! while ( (millis() < TimeInterval) || (!Laptop.IsConnected) ) { yield(); }
Serial.println("Client- and Server-side are Up and Running!");
}
// ---------------------- CLIENT SIDE FUNCTIONS ------------------------- void Setup_Client_FTMS(void) { // Initialize client FTM Service client_FitnessMachine_Service.begin();
// Initialize client FTM Feature characteristic client_FTM_Feature_Chr.begin();
// Initialize client FTM Training Status characteristic client_FTM_TrainingStatus_Chr.setNotifyCallback(client_FTM_TrainingStatus_Notify_callback); client_FTM_TrainingStatus_Chr.begin();
// Initialize client FTM Supported Power Range characteristic client_FTM_SupportedPowerRange_Chr.begin();
// Initialize client FTM Supported Resistance Level Range characteristic client_FTM_SupportedResistanceLevelRange_Chr.begin();
// Initialize client FTM Indoor Bike Data characteristic client_FTM_IndoorBikeData_Chr.setNotifyCallback(client_FTM_IndoorBikeData_Notify_callback); client_FTM_IndoorBikeData_Chr.begin();
// Initialize client FTM Control Point characteristic // For receiving Control Point Responses client_FTM_ControlPoint_Chr.setIndicateCallback(client_FTM_ControlPoint_Indicate_callback); client_FTM_ControlPoint_Chr.begin();
// Initialize client FTM Status characteristic client_FTM_Status_Chr.setNotifyCallback(client_FTM_Status_Notify_callback); client_FTM_Status_Chr.begin();
Serial.println("FTM Service and Chars are 'initialized'");
}
void Setup_Client_CPS(void) { // Initialize CPS client client_CyclingPower_Service.begin();
// Initialize CP Feature characteristics of client_CyclingPower_Service. client_CP_Feature_Chr.begin();
// Initialize CP sensor location characteristics of client_CyclingPower_Service. client_CP_Location_Chr.begin();
// set up callback for receiving measurement client_CP_Measurement_Chr.setNotifyCallback(client_CP_Measurement_Chr_notify_callback); client_CP_Measurement_Chr.begin();
// Initialize Control Point and set up Indicate callback for receiving responses (indicate!) client_CP_ControlPoint_Chr.setIndicateCallback(client_CP_ControlPoint_Chr_indicate_callback); client_CP_ControlPoint_Chr.begin();
Serial.println("CP Service and Chars are 'initialized'");
}
void Setup_Client_CSC(void) { // Initialize CSC client client_CyclingSpeedCadence_Service.begin();
// Initialize client characteristics of CSC. client_CSC_Location_Chr.begin();
// Initialize CSC Feature characteristics of client_CSC. client_CSC_Feature_Chr.begin();
// set up callback for receiving measurement client_CSC_Measurement_Chr.setNotifyCallback(client_CSC_Measurement_Chr_notify_callback); client_CSC_Measurement_Chr.begin();
Serial.println("CSC Service and Chars are 'initialized'");
}
void Setup_Client_DIS(void) { // Initialize client Generic Access Service client_GenericAccess_Service.begin(); // Initialize some characteristics of the Generic Access Service. client_GA_DeviceName_Chr.begin(); client_GA_Appearance_Chr.begin();
Serial.println("Generic Access Service and Chars are 'initialized'");
// Initialize client Device Information Service client_DIS_Service.begin(); // Initialize some characteristics of the Device Information Service. client_DIS_ManufacturerName_Chr.begin(); client_DIS_ModelNumber_Chr.begin(); client_DIS_SerialNumber_Chr.begin();
Serial.println("Device Information Service and Chars are 'initialized'");
}
void loop() { } // end loop
void Client_Start_Scanning(void) { /* Start Central Scanning
Serial.println("Start Client-side Scanning for CPS, CSC and FTMS!"); delay(100); // To show print message !
}
void Client_Enable_Notify_Indicate(void)
{
// --------------------- Enable CP and CSC Notify and Indicate ------------------------------------
// Reaching here means we are ready to go, let's enable notification on measurement chr
// ------------------------- Enable FTMS Notify and Indicate ---------------------------------------
if ( client_FTM_ControlPoint_Chr.enableIndicate() ) { // MANDATORY
Serial.println("Ready to receive Client FTM Control Point Response Messages");
} else {
Serial.println(">>> Couldn't enable indicate for Client FTM Control Point Characteristic.");
Serial.println("FTMS (trainer) is controlled by another Client (Training App)!");
Bluefruit.disconnect(Trainer.conn_handle);
return;
}
if ( client_FTM_Status_Chr.enableNotify() ) { // MANDATORY
Serial.println("Ready to receive Client FTM Status values");
} else {
Serial.println(">>> Couldn't enable notify for Client FTM Status Characteristic.");
Serial.println("FTMS (trainer) is controlled by another Client (Training App)!");
Bluefruit.disconnect(Trainer.conn_handle);
return;
}
if ( client_FTM_TrainingStatus_Chr.enableNotify() ) { // NOT MANDATORY
Serial.println("Ready to receive Client FTM Training Status values");
} else {
Serial.println(">>> Couldn't enable notify for Client FTM Training Status Characteristic.");
}
if ( client_FTM_IndoorBikeData_Chr.enableNotify() ) { // NOT MANDATORY
Serial.println("Ready to receive Client FTM Indoor Bike Data values");
} else {
Serial.println(">>> Couldn't enable notify for Client FTM Indoor Bike Data Characteristic.");
}
// ------------------------- Enable FTMS Notify and Indicate ---------------------------------------
// --------------------- Enable CP and CSC Notify and Indicate ------------------------------------
if ( client_CP_Measurement_Chr.enableNotify() ) { // NOT MANDATORY
Serial.println("Ready to receive Client CP Measurement values");
} else {
Serial.println(">>> Couldn't enable notify for Client CP Measurement Characteristic.");
}
if ( client_CP_ControlPoint_Chr.enableIndicate() ) { // NOT MANDATORY
Serial.println("Ready to receive Client CP Control Point Responses");
} else {
Serial.println(">>> Couldn't enable indicate for Client CP Control Point Characteristic.");
}
if ( client_CSC_Measurement_Chr.enableNotify() ) { // NOT MANDATORY
Serial.println("Ready to receive Client CSC Measurement values");
} else {
Serial.println(">>> Couldn't enable notify for Client CSC Measurement Characteristic.");
} // ------------------------- Enable CP and CSC Notify and Indicate --------------------------------
} // ------------------------- Enable FTMS Notify and Indicate ---------------------------------------
/* Hooked callback that triggered when a status value is sent @param chr Pointer client characteristic @param data Pointer to received data @param len Length of received data / void client_FTM_TrainingStatus_Notify_callback(BLEClientCharacteristic chr, uint8_t data, uint16_t len) { // Client Training Status data is tranferred to the Server // NO TREATMENT OF COMMAND !!! server_FTM_TrainingStatus_Chr.notify(data, len); // Just pass on and process later!
uint8_t SDataLen = (uint8_t)len; uint8_t SDataBuf[SDataLen] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw FTM Training Status Data: [%d] [ ", len); for (int i = 0; i < sizeof(SDataBuf); i++) { SDataBuf[i] = *data++; Serial.printf("%02X ", SDataBuf[i], HEX); } Serial.println("] ");
}
/* Hooked callback that is triggered when an IBD value is sent @param chr Pointer client characteristic @param data Pointer to received data @param len Length of received data / void client_FTM_IndoorBikeData_Notify_callback(BLEClientCharacteristic chr, uint8_t data, uint16_t len) { // Client IBD data is tranferred to the Server // NO TREATMENT OF COMMAND !!! if (server_FTM_IndoorBikeData_Chr.notifyEnabled(Laptop.conn_handle)) { server_FTM_IndoorBikeData_Chr.notify(data, len); // Just pass on and process later! }
// Only when DEBUG_FTM_INDOORBIKEDATA is defined IDBData will be parsed and printed! ParseIndoorBikeData(data, len);
}
void ParseIndoorBikeData(uint8_t data, uint16_t len) { // ---> IBD Buffer Data Length depends on data flagged to be present !!!! uint8_t IBDDataLen = (uint8_t)len; uint8_t IBDDataBuf[IBDDataLen] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw FTM IBD Data: [%d] [ ", len); for (int i = 0; i < sizeof(IBDDataBuf); i++) { IBDDataBuf[i] = data++; Serial.printf("%02X ", IBDDataBuf[i], HEX); } Serial.print("] ");
uint8_t offset = 0; uint16_t flags = 0; memcpy(&flags, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable offset += 2; // UINT16 if ((flags & 1) != 0) { // More Data Serial.print(" More Data!"); } // if ((flags & 2) != 0) { // (flags & 2) --> true or false Average Speed is always(?) there (tested with Elite Direto XR) // Average Speed 0.01 uint16_t sim_Speed = 0; memcpy(&sim_Speed, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Speed: %d KPH", (sim_Speed / 100)); offset += 2; // UINT16 // } if ((flags & 4) != 0) { // Instantaneous Cadence 0.5 uint16_t inst_Cadence = 0; memcpy(&inst_Cadence, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Instantaneous Cadence: %d RPM", (inst_Cadence / 2)); offset += 2; // UINT16 } if ((flags & 8) != 0) { // Average Cadence 0.5 uint16_t av_Cadence = 0; memcpy(&av_Cadence, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Average Cadence: %d RPM", (av_Cadence / 2)); offset += 2; // UINT16 } if ((flags & 16) != 0) { // Total Distance 1 uint32_t tot_Distance = 0; memcpy(&tot_Distance, &IBDDataBuf[offset], 3); // Transfer buffer fields to variable Serial.printf(" Total Distance: %d m", tot_Distance); offset += 3; // UINT24 } if ((flags & 32) != 0) { // Resistance Level 1 uint16_t res_Level = 0; memcpy(&res_Level, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Resistance Level: %d ", res_Level); offset += 2; // UINT16 } if ((flags & 64) != 0) { // Instantaneous Power 1 uint16_t inst_Power = 0; memcpy(&inst_Power, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Instantaneous Power: %d Watt", inst_Power); offset += 2; // UINT16 } if ((flags & 128) != 0) { // Average Power 1 uint16_t av_Power = 0; memcpy(&av_Power, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Average Power: %d Watt", av_Power); offset += 2; // UINT16 } if ((flags & 256) != 0) { // Expended Energy -> UINT16 UINT16 UINT8 // Total Energy UINT16 1 uint16_t tot_Energy = 0; memcpy(&tot_Energy, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Tot. Energy: %d kCal", tot_Energy); offset += 2; // UINT16 // Energy per hour UINT16 1 uint16_t Energy_hr = 0; memcpy(&Energy_hr, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Energy/hr: %d kCal/hr", Energy_hr); offset += 2; // UINT16 // Energy per minute UINT8 1 uint8_t Energy_pm = 0; memcpy(&Energy_pm, &IBDDataBuf[offset], 1); // Transfer buffer fields to variable Serial.printf(" Energy/m: %d kCal/m", Energy_pm); offset += 1; // UINT8 } if ((flags & 512) != 0) { // Heart Rate 1 uint8_t Heart_Rate = 0; memcpy(&Heart_Rate, &IBDDataBuf[offset], 1); // Transfer buffer fields to variable Serial.printf(" Heart Rate: %d HBM", Heart_Rate); offset += 1; // UINT8 } if ((flags & 1024) != 0) { // Metabolic Equivalent 0.1 uint8_t Mets = 0; memcpy(&Mets, &IBDDataBuf[offset], 1); // Transfer buffer fields to variable Serial.printf(" Metabolic Equivalent: %d ", Mets / 10); offset += 1; // UINT8 } if ((flags & 2048) != 0) { // Elapsed Time 1 uint16_t elap_time = 0; memcpy(&elap_time, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Elapsed time: %d s", elap_time); offset += 2; // UINT16 } if ((flags & 4096) != 0) { // Remaining Time 1 uint16_t rem_time = 0; memcpy(&rem_time, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Remaining time: %d s", rem_time); offset += 2; // UINT16 } Serial.println(); }
/* Hooked callback that triggered when a value is sent @param chr Pointer client characteristic @param data Pointer to received data @param len Length of received data / void client_FTM_ControlPoint_Indicate_callback(BLEClientCharacteristic chr, uint8_t data, uint16_t len) { // The receipt of Control Point settings is acknowledged by the trainer: handle it // Send Client's Response message to the Server // NO TREATMENT OF COMMAND !!! server_FTM_ControlPoint_Chr.indicate(data, len); // Just pass on and process later!
uint8_t RespBufferLen = (uint8_t)len; uint8_t RespBuffer[RespBufferLen] = {}; // It is max 6 bytes long // Transfer first the contents of data to buffer (array of chars) Serial.print(" -> Client Rec'd Control Point Response: [ "); for (int i = 0; i < sizeof(RespBuffer); i++) { RespBuffer[i] = *data++; Serial.printf("%02X ", RespBuffer[i], HEX); } Serial.println("] ");
}
/* Hooked callback that triggered when a value is sent @param chr Pointer client characteristic @param data Pointer to received data @param len Length of received data / void client_FTM_Status_Notify_callback(BLEClientCharacteristic chr, uint8_t data, uint16_t len) { // Client's Machine Status data is tranferred to the Server // NO TREATMENT OF COMMAND !!! server_FTM_Status_Chr.notify(data, len); // Just pass on and process later!
uint8_t SDataLen = (uint8_t)len; uint8_t SDataBuf[SDataLen] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw FTM Machine Status Data: [%d] [ ", len); for (int i = 0; i < sizeof(SDataBuf); i++) { SDataBuf[i] = *data++; Serial.printf("%02X ", SDataBuf[i], HEX); } Serial.println("] ");
}
// Byte swap unsigned short uint16_t swap_uint16( uint16_t val ) { return (val << 8) | (val >> 8 ); }
// Find certain uuid in the data of the received advertising packet bool checkForUuidPresent(const uint16_t uuid, const uint8_t* reportData, uint8_t reportDataLen) { // Enter uuid in printed format like 0x1826 for UUID16_SVC_FITNESS_MACHINE // uuid is internally stored in Little Endian for (int i = 0; i < (reportDataLen); i++) { // step 1: never miss out a position! if ( memcmp(&uuid, (reportData + i), 2) == 0) { return true; } } return false; }
/* Callback invoked when scanner pick up an advertising data @param report Structural advertising data / void client_scan_callback(ble_gap_evt_adv_report_t* report) { // Since we configure the scanner with filterUuid(CPS, CSC, FTMS) // scan_callback is invoked for devices with usually CPS service advertised. // However, we only do business with FTMS enabled Trainer types so check // for UUID16_SVC_FITNESS_MACHINE to be present, if not --> keep scanning! uint8_t Device_Addr[6] = {0}; if (!checkForUuidPresent(UUID16_SVC_FITNESS_MACHINE, report->data.p_data, report->data.len)) { return; // Keep scanning for FTMS trainer !! } memcpy(Device_Addr, report->peer_addr.addr, 6); if ( !(memcmp(Device_Addr, Trainer.PeerAddress, 6) == 0) ) { return; // Keep scanning for the required trainer !! } // Connect to device only with required services AND device address if (Bluefruit.Scanner.isRunning()) { Bluefruit.Scanner.stop(); }
Serial.println("Found advertising Peripheral with FTMS enabled! See Raw data packet:"); Serial.println(F("Timestamp Addr Rssi Data")); Serial.printf("%09d ", millis()); // MAC is in little endian --> print reverse Serial.printBufferReverse(report->peer_addr.addr, 6, ':'); Serial.print(F(" ")); Serial.print(report->rssi); Serial.print(F(" ")); Serial.printBuffer(report->data.p_data, report->data.len, '-'); Serial.println();
Bluefruit.Central.connect(report); }
void PrintPeerAddress(uint8_t addr[6]) { for (int i = 1; i < 6; i++) { // Display byte by byte in HEX reverse: little Endian Serial.printf("%02X:", addr[(6 - i)], HEX); } Serial.printf("%02X ", addr[0], HEX); }
/* Callback invoked when a connection is established @param conn_handle / void client_connect_callback(uint16_t conn_handle) { Trainer.conn_handle = conn_handle; // Get the reference to current connection BLEConnection* connection = Bluefruit.Connection(conn_handle); connection->getPeerName(Trainer.PeerName, sizeof(Trainer.PeerName)); ble_gap_addr_t PeerAddr = connection->getPeerAddr(); // Fill BLE Gap struct memcpy(Trainer.PeerAddress, PeerAddr.addr, 6); // Copy Peer Address from ble_gap_addr_t struct
Serial.printf("Feather nRF52 (Central) connected to Trainer (Peripheral) device: [%s] MAC Address: ", Trainer.PeerName); PrintPeerAddress(Trainer.PeerAddress); Serial.println(); Serial.println("Now checking all mandatory Client Services and Characteristics!"); Serial.println("If Mandatory Services Fail --> the Client will disconnect!");
// ---------------------------- GA and DIS SERVICE ------------------------------------------
Serial.println("First checking Generic Access and Device Information Services and Characteristics!");
// If Generic Access is not found then go on.... NOT FATAL ! while (!(client_GenericAccess_Service.discover(conn_handle))) { if ( client_GenericAccess_Service.discover(conn_handle) ) {
Serial.print(F("Found Client Generic Access\n"));
if ( client_GA_DeviceName_Chr.discover() ) {
client_GA_DeviceName_Chr.read(client_GA_DeviceName_Data, sizeof(client_GA_DeviceName_Data));
Serial.printf(" -> Client Reads Device Name: [%s]\n", client_GA_DeviceName_Data);
}
if ( client_GA_Appearance_Chr.discover() ) {
client_GA_Appearance_Value = client_GA_Appearance_Chr.read16();
Serial.printf(" -> Client Reads Appearance: [%d]\n", client_GA_Appearance_Value);
}
} // GA
}
// If DIS is not found then go on.... NOT FATAL !
while (!( client_DIS_Service.discover(conn_handle) )){ if ( client_DIS_Service.discover(conn_handle) ) {
Serial.print(F("Found Client Device Information\n"));
// 1
if ( client_DIS_ManufacturerName_Chr.discover() ) {
// read and print out Manufacturer
if ( client_DIS_ManufacturerName_Chr.read(client_DIS_Manufacturer_Str, sizeof(client_DIS_Manufacturer_Str)) ) {
Serial.printf(" -> Client Reads Manufacturer: [%s]\n", client_DIS_Manufacturer_Str);
}
} // 1
// 2
if ( client_DIS_ModelNumber_Chr.discover() ) {
// read and print out Model Number
if ( client_DIS_ModelNumber_Chr.read(client_DIS_ModelNumber_Str, sizeof(client_DIS_ModelNumber_Str)) ) {
Serial.printf(" -> Client Reads Model Number: [%s]\n", client_DIS_ModelNumber_Str);
}
} // 2
// 3
if ( client_DIS_SerialNumber_Chr.discover() ) {
// read and print out Serial Number
if ( client_DIS_SerialNumber_Chr.read(client_DIS_SerialNumber_Str, sizeof(client_DIS_SerialNumber_Str)) ) {
Serial.printf(" -> Client Reads Serial Number: [%s]\n", client_DIS_SerialNumber_Str);
}
} // 3
} } // DIS // ---------------------------- END GA and DIS SERVICE ------------------------------------------------
// -----------------------------FTM SERVICE ------------------------------------------------------------
Serial.print("Discovering Mandatory Client Fitness Machine (FTM) Service ... ");
// If FTM is not found, disconnect, resume scanning, and return if ( client_FitnessMachine_Service.discover(conn_handle) ) {
BLEConnection* conn = Bluefruit.Connection(conn_handle);
uint16_t max_payload = conn->getMtu()-3;
uint16_t data_length = conn->getDataLength();
Serial.print("Found it! ");
Serial.printf("FTMS Max Payload: %d Data Length: %d\n", max_payload, data_length);
} else {
Serial.println("Not Found!");
Serial.println("Disconnecting since Client FTM Service is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
return;
}
Serial.print("Discovering Client FTM Feature Characteristic ... ");
// If FTM Feature is not found, disconnect, resume scanning, and return while (!( client_FTM_Feature_Chr.discover() )) { if ( client_FTM_Feature_Chr.discover() ) {
Serial.println("Found it!");
// Read FTM Feature Data
client_FTM_Feature_Chr.read(client_FTM_Feature_Data, 8);
Serial.print(" -> Client Reads Raw FTM Feature bytes: [8] [ ");
for (int i = 0; i < sizeof(client_FTM_Feature_Data); i++) {
Serial.printf("%02X ", client_FTM_Feature_Data[i], HEX);
} // for
Serial.println("] ");
} else {
Serial.println("Disconnecting since Client FTM Feature Characteristic is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
Bluefruit.Connection(conn_handle);
Serial.print("Discovering Client FTM Feature not decouvert ... ");
// return; } }
Serial.print("Discovering Client FTM Control Point Characteristic ... ");
// If FTM Control Point is not found, disconnect, resume scanning, and return if ( client_FTM_ControlPoint_Chr.discover() ) {
Serial.println("Found it!");
// Send a Request Control of Machine, OpCode == 0, no values!
const uint8_t RCM[1] = {0};
client_FTM_ControlPoint_Chr.write_resp(RCM, 1);
} else {
Serial.println("Not Found!");
Serial.println("Disconnecting since Client FTM Control Point Characteristic is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
Bluefruit.Connection(conn_handle);
Serial.print("Discovering Client FTM Feature not decouvert ... ");
return;
}
Serial.print("Discovering Client FTM Status Characteristic ... ");
// If FTM Status is not found, disconnect, resume scanning, and return if ( client_FTM_Status_Chr.discover() ) {
Serial.println("Found it!");
} else {
Serial.println("Not Found!");
Serial.println("Disconnecting since Client FTM Status Characteristic is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
return;
}
Serial.print("Discovering Client FTM Training Status Characteristic ... ");
// FTM Training Status is NOT MANDATORY if ( client_FTM_TrainingStatus_Chr.discover() ) {
Serial.println("Found it!");
} else {
Serial.println("Not Found! Not Mandatory");
} /*
Serial.println("Not Found!");
Serial.println("Disconnecting since Client FTM Characteristic is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
return;
*/
Serial.print("Discovering Client FTM Supported Resistance Level Range Characteristic ... ");
// FTM SupportedResistanceLevelRange is not mandatory! if ( client_FTM_SupportedResistanceLevelRange_Chr.discover() ) {
Serial.println("Found it!");
// Read Supported Resistance Level Range Data
client_FTM_SupportedResistanceLevelRange_Chr.read(client_FTM_SupportedResistanceLevelRange_Data, 6);
Serial.print(" -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ ");
for (int i = 0; i < sizeof(client_FTM_SupportedResistanceLevelRange_Data); i++) {
Serial.printf("%02X ", client_FTM_SupportedResistanceLevelRange_Data[i], HEX);
} // for
Serial.println("] ");
} else {
Serial.println("Not Found! NOT mandatory!");
} / Serial.println("Disconnecting since Client FTM Supported Resistance Level Range Characteristic is mandatory!"); // MANDATORY so disconnect since we couldn't find the service Bluefruit.disconnect(conn_handle); return; /
Serial.print("Discovering Client FTM Supported Power Range Characteristic ... ");
// FTM SupportedPowerRange is not mandatory! if ( client_FTM_SupportedPowerRange_Chr.discover() ) {
Serial.println("Found it!");
// Read Supported Resistance Level Range values
client_FTM_SupportedPowerRange_Chr.read(client_FTM_SupportedPowerRange_Data, 6);
Serial.print(" -> Client Reads Raw FTM Supported Power Range bytes: [6] [ ");
for (int i = 0; i < sizeof(client_FTM_SupportedPowerRange_Data); i++) {
Serial.printf("%02X ", client_FTM_SupportedPowerRange_Data[i], HEX);
} // for
Serial.println("] ");
} else {
Serial.println("Not Found! NOT mandatory!");
} /*
Serial.println("Disconnecting since Client FTM Supported Power Range Characteristic is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
return;
*/
Serial.print("Discovering Client FTM Indoor Bike Data Characteristic ... ");
// FTM Indoor Bike Data is not mandatory if ( client_FTM_IndoorBikeData_Chr.discover() ) {
Serial.println("Found it!");
} else {
Serial.println("Not Found! Not Mandatory");
} /*
Serial.println("Not Found!");
Serial.println("Disconnecting since Client FTM Indoor Bike Data Characteristic is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
return;
*/ // ---------------------------- End FTM SERVICE --------------------------------------------- // ---------------------------- CP SERVICE --------------------------------------------------
Serial.print("Discovering Client Cycling Power (CP) Service ... ");
// If CPS is not found, disconnect, resume scanning, and return
while (!( client_CyclingPower_Service.discover(conn_handle) ))
{
if ( client_CyclingPower_Service.discover(conn_handle) )
{
BLEConnection* conn = Bluefruit.Connection(conn_handle);
uint16_t max_payload = conn->getMtu()-3;
uint16_t data_length = conn->getDataLength();
Serial.print("Found it! ");
Serial.printf("CPS Max Payload: %d Data Length: %d\n", max_payload, data_length);
} else {
Serial.println("Not Found!");
Serial.println("Disconnecting since Client Cyling Power Service is mandatory!");
// MANDATORY so disconnect since we couldn't find the service
Bluefruit.disconnect(conn_handle);
Bluefruit.Connection(conn_handle);
Serial.print("Discovering Cycling Power (CP) Service not decouvert ... "); return; } }
Serial.print("Discovering Client CP Measurement characteristic ... ");
if ( !client_CP_Measurement_Chr.discover() ) { // Measurement chr is mandatory, if it is not found (valid), then disconnect
Serial.println("Not Found!");
Serial.println("Disconnecting since Client CP Measurement Characteristic is mandatory!");
Bluefruit.disconnect(conn_handle);
return;
} else {
Serial.println("Found it!");
}
Serial.print("Discovering Client CP Control Point characteristic ... ");
if ( client_CP_ControlPoint_Chr.discover() ) { // CP Control Point chr is not mandatory
Serial.println("Found it!");
} else {
Serial.println("Not Found! NOT Mandatory!");
}
Serial.print("Discovering Client CP Feature characteristic ... ");
if ( client_CP_Feature_Chr.discover() ) {
Serial.println("Found it!");
// Configure the Cycle Power Feature characteristic // Properties = Read // Min Len = 1 // Max Len = 32 // B0:3 = UINT8 - Cycling Power Feature (MANDATORY) // b0 = Pedal power balance supported; 0 = false, 1 = true // b1 = Accumulated torque supported; 0 = false, 1 = true // b2 = Wheel revolution data supported; 0 = false, 1 = true // b3 = Crank revolution data supported; 0 = false, 1 = true // b4 = Extreme magnatudes supported; 0 = false, 1 = true // b5 = Extreme angles supported; 0 = false, 1 = true // b6 = Top/bottom dead angle supported; 0 = false, 1 = true // b7 = Accumulated energy supported; 0 = false, 1 = true // b8 = Offset compensation indicator supported; 0 = false, 1 = true // b9 = Offset compensation supported; 0 = false, 1 = true // b10 = Cycling power measurement characteristic content masking supported; 0 = false, 1 = true // b11 = Multiple sensor locations supported; 0 = false, 1 = true // b12 = Crank length adj. supported; 0 = false, 1 = true // b13 = Chain length adj. supported; 0 = false, 1 = true // b14 = Chain weight adj. supported; 0 = false, 1 = true // b15 = Span length adj. supported; 0 = false, 1 = true // b16 = Sensor measurement context; 0 = force, 1 = torque // b17 = Instantaineous measurement direction supported; 0 = false, 1 = true // b18 = Factory calibrated date supported; 0 = false, 1 = true // b19 = Enhanced offset compensation supported; 0 = false, 1 = true // b20:21 = Distribtue system support; 0 = legacy, 1 = not supported, 2 = supported, 3 = RFU // b22:32 = Reserved
// Read 32-bit client_CP_Feature_Chr value client_CP_Feature_Flags = client_CP_Feature_Chr.read32();
const uint8_t CPFC_FIXED_DATALEN = 4; uint8_t cpfcData[CPFC_FIXED_DATALEN] = {(uint8_t)(client_CP_Feature_Flags & 0xff), (uint8_t)(client_CP_Feature_Flags >> 8), (uint8_t)(client_CP_Feature_Flags >> 16), (uint8_t)(client_CP_Feature_Flags >> 24)}; Serial.print(" -> Client Reads Raw CP Feature bytes: [4] [ "); for (int i = 0; i < CPFC_FIXED_DATALEN; i++) { if ( i <= sizeof(cpfcData)) { Serial.printf("%02X ", cpfcData[i], HEX); } } Serial.println("] "); for (int i = 0; i < sizeof(client_CP_Feature_Str); i++) { if ( client_CP_Feature_Flags & (1 << i) ) { Serial.println(client_CP_Feature_Str[i]); } }
} else {
Serial.println("NOT Found! NOT Mandatory!");
}
Serial.print("Discovering Client CP Sensor Location characteristic ... ");
if ( client_CP_Location_Chr.discover() ) {
Serial.println("Found it!");
// The Sensor Location characteristic // Properties = Read // Min Len = 1 // Max Len = 1 // B0:1 = UINT8 - Sensor Location
// Read 8-bit client CP sensor location value
client_CP_Location_Value = client_CP_Location_Chr.read8();
Serial.print(" -> Client Reads CP Location Sensor: ");
Serial.printf("Loc#: %d %s\n", client_CP_Location_Value, client_Sensor_Location_Str[client_CP_Location_Value]);
} else {
Serial.println("NOT Found! NOT Mandatory!");
} // ---------------------------- END CP SERVICE ------------------------------------------------ // ---------------------------- CSC SERVICE --------------------------------------------------
Serial.print("Discovering Cycling Speed and Cadence (CSC) Service ... ");
if ( client_CyclingSpeedCadence_Service.discover(conn_handle) ) // UUID16_SVC_CYCLING_SPEED_AND_CADENCE {
BLEConnection* conn = Bluefruit.Connection(conn_handle);
uint16_t max_payload = conn->getMtu()-3;
uint16_t data_length = conn->getDataLength();
Serial.print("Found it! ");
Serial.printf("CSCS Max Payload: %d Data Length: %d\n", max_payload, data_length);
} else {
Serial.println("Not Found! CSC Service is Not Mandatory!");
return; // NO CSC -> end of client_connect_callback !!
} /* // Is Mandatory
Serial.println("Not Found and disconnecting!");
Serial.println("CSC Service is mandatory!");
Bluefruit.disconnect(conn_handle);
return;
*/
// Test for client CSC Characteristics when the client CSC Service is existing
Serial.print("Discovering Client CSC Measurement CHR ... ");
if ( client_CSC_Measurement_Chr.discover() ) // UUID16_CHR_CSC_MEASUREMENT {
Serial.println("Found it! ");
} else {
Serial.println("Not Found! Not Mandatory!");
} /* // Is Mandatory
Serial.println("Not Found!");
Serial.println("Disconnecting since Client CSC Measurement CHR is mandatory!");
Bluefruit.disconnect(conn_handle);
return;
*/
Serial.print("Discovering Client CSC Location CHR ... ");
if ( client_CSC_Location_Chr.discover() ) // UUID16_CHR_SENSOR_LOCATION {
Serial.println("Found it!");
// Read 16-bit client CSC sensor location value
client_CSC_Location_Value = client_CSC_Location_Chr.read8();
Serial.print(" -> Client Reads CSC Location Sensor: ");
Serial.printf("Loc#: %d %s\n", client_CSC_Location_Value, client_Sensor_Location_Str[client_CSC_Location_Value]);
} else {
Serial.println("Not Found! NOT Mandatory!");
}
Serial.print("Discovering Client CSC Feature CHR ... ");
if ( client_CSC_Feature_Chr.discover() ) // UUID16_CHR_CSC_FEATURE {
Serial.println("Found it!");
// Read sensor CSC Feature value in 16 bit
client_CSC_Feature_Flags = client_CSC_Feature_Chr.read16();
uint8_t cscfcData[CSC_FEATURE_FIXED_DATALEN] = { (uint8_t)(client_CSC_Feature_Flags & 0xff), (uint8_t)(client_CSC_Feature_Flags >> 8) }; // Little Endian Representation
Serial.printf(" -> Client Reads Raw CSC Feature bytes: [2] [ ");
for (int i = 0; i < sizeof(cscfcData); i++) {
Serial.printf("%02X ", cscfcData[i], HEX);
}
Serial.println("] ");
for (int i = 0; i < sizeof(client_CSC_Feature_Str); i++) {
if ( (client_CSC_Feature_Flags & (1 << i)) != 0 )
{
Serial.println(client_CSC_Feature_Str[i]);
}
}
} else {
Serial.println("Not Found! NOT Mandatory!");
} // ---------------------------- END CSC SERVICE --------------------------------------------- // Only now set true after ALL Mandatory Services and Char's have been discovered !!! Trainer.IsConnected = true; } // End client_connect_callback
/* Callback invoked when a connection is dropped @param conn_handle @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h / void client_disconnect_callback(uint16_t conn_handle, uint8_t reason) {
Serial.printf("Client disconnected from Peripheral Device: [%s], reason: [%02X]\n", Trainer.PeerName, reason, HEX);
Trainer.conn_handle = BLE_CONN_HANDLE_INVALID; Trainer.IsConnected = false; // Force server to disconnect! if (Laptop.conn_handle != BLE_CONN_HANDLE_INVALID) { Bluefruit.disconnect(Laptop.conn_handle); } }
/* Hooked callback that triggered when a measurement value is sent from peripheral @param chr Pointer client characteristic in this example it should be cpmc @param data Pointer to received data @param len Length of received data / void client_CP_Measurement_Chr_notify_callback(BLEClientCharacteristic chr, uint8_t data, uint16_t len) { // Client CP Measurement data is tranferred to the Server (Zwift) // NO TREATMENT OF RESPONSE !!!!! if (server_CP_Measurement_Chr.notifyEnabled(Laptop.conn_handle)) { server_CP_Measurement_Chr.notify(data, len); // Just pass on and process later! }
uint8_t buffer[len] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw CP Data: [%d] [ ", len); for (int i = 0; i < sizeof(buffer); i++) { if ( i <= sizeof(buffer)) { buffer[i] = *data++; Serial.printf("%02X ", buffer[i], HEX); } } Serial.print("] "); uint8_t offset = 0; // Get flags field uint16_t flags = 0; memcpy(&flags, &buffer[offset], 2); // Transfer buffer fields to variable offset += 2; // UINT16 // Get Instantaneous Power values UINT16 uint16_t PowerValue = 0; memcpy(&PowerValue, &buffer[offset], 2); // Transfer buffer fields to variable offset += 2; // UINT16 Serial.printf("Instantaneous Power: %4d\n", PowerValue); // Get the other CP measurement values if ((flags & 1) != 0) { // Power Balance Present Serial.print(" --> Pedal Power Balance!"); } if ((flags & 2) != 0) { // Accumulated Torque Serial.println(" --> Accumulated Torque!"); } // etcetera...
} // End cpmc_notify_callback
/* Hooked callback that triggered when a response value is sent from peripheral @param chr Pointer client characteristic @param data Pointer to received data @param len Length of received data / void client_CP_ControlPoint_Chr_indicate_callback(BLEClientCharacteristic chr, uint8_t data, uint16_t len) { // Send Client's response message to the Server (Zwift) // NO TREATMENT OF RESPONSE !!!!! server_CP_ControlPoint_Chr.indicate(data, len); // Just pass on and process later!
uint8_t cpcpDataLen = (uint8_t)len; uint8_t cpcpData[cpcpDataLen] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw CP Control Point Data: [%d] [ ", len); for (int i = 0; i < sizeof(cpcpData); i++) { cpcpData[i] = *data++; Serial.printf("%02X ", cpcpData[i], HEX); } Serial.print("] ");
}
/* Hooked callback that triggered when a measurement value is sent from peripheral @param chr Pointer client characteristic @param data Pointer to received data @param len Length of received data / void client_CSC_Measurement_Chr_notify_callback(BLEClientCharacteristic chr, uint8_t data, uint16_t len) { // Client CSC Measurement data is transferred to the Server (Zwift) // NO TREATMENT OF RESPONSE !!!!! if (server_CSC_Measurement_Chr.notifyEnabled(Laptop.conn_handle)) { server_CSC_Measurement_Chr.notify(data, len); // Just pass on and process later! }
uint8_t buffer[len] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw CSC Data: [%d] [ ", len); for (int i = 0; i < sizeof(buffer); i++) { if ( i <= sizeof(buffer)) { buffer[i] = *data++; Serial.printf("%02X ", buffer[i], HEX); } } Serial.print("] "); uint8_t offset = 0; // we define the offset that is to be used when reading the next field // Size of variables (e.g. 2 (16) or 4 bytes (32)) are constants in BluetoothGattCharacteristic // these represent the values you can find in the "Value Fields" table in the "Format" column // Read the Flags field at buffer[0] uint8_t flags = buffer[offset]; offset += 1; // UINT8 // we have to check the flags' nth bit to see if C1 field exists if ((flags & 1) != 0) { uint32_t cum_wheel_rev = 0; memcpy(&cum_wheel_rev, &buffer[offset], 4); offset += 4; // UINT32 uint16_t last_wheel_event = 0; memcpy(&last_wheel_event, &buffer[offset], 2); offset += 2; // UINT16 Serial.printf(" Cum. wheel rev.: %d Last wheel event: %d ", cum_wheel_rev, last_wheel_event); } // we have to check the flags' nth bit to see if C2 field exists if ((flags & 2) != 0) { uint16_t cum_cranks = 0; memcpy(&cum_cranks, &buffer[offset], 2); offset += 2; // UINT16 uint16_t last_crank_event = 0; memcpy(&last_crank_event, &buffer[offset], 2); offset += 2; // UINT16 Serial.printf(" Cum cranks: %d Last crank event: %d", cum_cranks, last_crank_event); } Serial.println();
} // ---------------------- END of CLIENT SIDE FUNCTIONS ------------------------- // ---------------------- START of SERVER SIDE FUNCTIONS -------------------------
void server_setupNUS(void) { server_NordicUart_Service.begin(); // Add NUS TXD Characteristic server_NUS_TXD_Chr.setProperties(CHR_PROPS_NOTIFY); // Type "notify" server_NUS_TXD_Chr.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // readAccess, NO writeAccess server_NUS_TXD_Chr.setMaxLen(MAX_PAYLOAD); // To be on the safe side! server_NUS_TXD_Chr.setCccdWriteCallback(server_cccd_callback); // Optionally capture CCCD updates server_NUS_TXD_Chr.begin();
// Add NUS RXD Characteristic server_NUS_RXD_Chr.setProperties(CHR_PROPS_WRITE | CHR_PROPS_WRITE_WO_RESP); // Write with No response !! server_NUS_RXD_Chr.setPermission(SECMODE_NO_ACCESS, SECMODE_OPEN); server_NUS_RXD_Chr.setMaxLen(MAX_PAYLOAD); // Maxlen server_NUS_RXD_Chr.setWriteCallback(server_NUS_RXD_Chr_callback); server_NUS_RXD_Chr.begin(); }
void server_NUS_RXD_Chr_callback(uint16_t conn_hdl, BLECharacteristic chr, uint8_t data, uint16_t len) { // Read data received over NUS RXD from Mobile Phone
uint8_t NusRxdDataLen = (uint8_t)len; // Get the actual length of data bytes and type cast to (uint8_t) char NusRxdData[MAX_PAYLOAD + 1]; // Data is all ASCII ! memset(NusRxdData, 0, MAX_PAYLOAD); // set to zero if (NusRxdDataLen > MAX_PAYLOAD) { NusRxdDataLen = MAX_PAYLOAD; // Check for limit } memcpy(NusRxdData, data, NusRxdDataLen); // Transfer data to char array // Display the raw packet data in actual length Serial.printf(" -> Server NUS RXD Data [%d][%s]\n", NusRxdDataLen, NusRxdData);
}
void Construct_Dev_Name(void) { const char prefix[] = {'S', 'i', 'm', ' '}; // #4 Chars size_t len = strlen((const char)client_GA_DeviceName_Data); // Len of null terminated char array int MaxLen = (MAX_PAYLOAD - sizeof(prefix) - 1); // 1 less for null terminating char if (len > MaxLen) { len = MaxLen; } int pos = MaxLen; if (len > 0) { // pfound points to the first occurence of " " (blank space char) char pfound = strstr((const char)client_GA_DeviceName_Data, " "); if (pfound != NULL) { pos = int(pfound - (char)client_GA_DeviceName_Data); // Convert to position in DevName } } if ( pos > MaxLen ) { pos = MaxLen; // Stay within char array allocated memory! } memmove(&client_GA_DeviceName_Data[sizeof(prefix)], &client_GA_DeviceName_Data, pos); // Make space: shift to the right memcpy(&client_GA_DeviceName_Data, &prefix, sizeof(prefix)); // Insert prefix at begin of DevName client_GA_DeviceName_Data[(pos + sizeof(prefix))] = 0; // Make null terminated char array at new position, skip rest! }
void server_startADV(void) { // Setup and start advertising // Supported tx_power values depending on mcu: // - nRF52832: -40dBm, -20dBm, -16dBm, -12dBm, -8dBm, -4dBm, 0dBm, +3dBm and +4dBm. // - nRF52840: -40dBm, -20dBm, -16dBm, -12dBm, -8dBm, -4dBm, 0dBm, +2dBm, +3dBm, +4dBm, +5dBm, +6dBm, +7dBm and +8dBm. Bluefruit.setTxPower(4); // See above for supported values: +4dBm // Set blink rate in advertising mode Bluefruit.setConnLedInterval(250);
Construct_Dev_Name();
Serial.printf("Setting Server Device Name to: [%s]\n", client_GA_DeviceName_Data);
Bluefruit.setName((const char*)client_GA_DeviceName_Data); if (Bluefruit.setAppearance(client_GA_Appearance_Value)) {
Serial.printf("Setting Server Appearance to: [%d]\n", client_GA_Appearance_Value);
} // Set the connect/disconnect callback handlers Bluefruit.Periph.setConnectCallback(server_connect_callback); Bluefruit.Periph.setDisconnectCallback(server_disconnect_callback);
// Advertising packet Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); Bluefruit.Advertising.addTxPower();
// Test include only FTMS Service as defined above Bluefruit.Advertising.addService(server_CylingPower_Service); Bluefruit.Advertising.addService(server_CyclingSpeedCadence_Service); Bluefruit.Advertising.addService(server_FitnessMachine_Service); // No need to advertise NUS, Companion App detects it anyway!
// Include Bluefruit.Advertising.addName and 128-bit uuid(s) result in a packet space problem!!! // Use secondary Scan Response packet (optional) // if there is no room for 'Name' in Advertising packet Bluefruit.ScanResponse.addName();
/* Start Advertising
void server_setupDIS(void) { // Configure and Start the Device Information Service server_bledis.setManufacturer((const char)client_DIS_Manufacturer_Str); server_bledis.setModel((const char)client_DIS_ModelNumber_Str); // Notice that the Firmware Revision string is default set to // the value of the Feather-nRF52 Board being used! server_bledis.setFirmwareRev((const char)FirmwareRevStr); server_bledis.setSerialNum((const char)client_DIS_SerialNumber_Str); server_bledis.setHardwareRev((const char)HardwareRevStr); server_bledis.setSoftwareRev((const char)SoftwareRevStr); server_bledis.begin(); }
void server_setupFTMS(void) { server_FitnessMachine_Service.begin(); //
// Fitness Machine Feature, mandatory, read server_FTM_Feature_Chr.setProperties(CHR_PROPS_READ); server_FTM_Feature_Chr.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); server_FTM_Feature_Chr.setFixedLen(FTM_FEATURE_FIXED_DATALEN); server_FTM_Feature_Chr.begin(); server_FTM_Feature_Chr.write(client_FTM_Feature_Data, FTM_FEATURE_FIXED_DATALEN);
// Indoor Bike Data, optional, notify server_FTM_IndoorBikeData_Chr.setProperties(CHR_PROPS_NOTIFY); // because type "notify" server_FTM_IndoorBikeData_Chr.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // readAccess, writeAccess server_FTM_IndoorBikeData_Chr.setMaxLen(MAX_PAYLOAD); // To be on the safe side, when many features are set! server_FTM_IndoorBikeData_Chr.setCccdWriteCallback(server_cccd_callback); // Optionally capture CCCD updates server_FTM_IndoorBikeData_Chr.begin();
// Training Status, optional, read & notify server_FTM_TrainingStatus_Chr.setProperties(CHR_PROPS_NOTIFY); // because type is "notify" server_FTM_TrainingStatus_Chr.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // readAccess, writeAccess server_FTM_TrainingStatus_Chr.setFixedLen(FTM_TRAINING_STATUS_FIXED_DATALEN); server_FTM_TrainingStatus_Chr.setCccdWriteCallback(server_cccd_callback); // Optionally capture CCCD updates server_FTM_TrainingStatus_Chr.begin();
// Supported Resistance Level Range, read, optional server_FTM_SupportedResistanceLevelRange_Chr.setProperties(CHR_PROPS_READ); server_FTM_SupportedResistanceLevelRange_Chr.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); server_FTM_SupportedResistanceLevelRange_Chr.setFixedLen(FTM_SRLR_FIXED_DATALEN); server_FTM_SupportedResistanceLevelRange_Chr.begin(); server_FTM_SupportedResistanceLevelRange_Chr.write(client_FTM_SupportedResistanceLevelRange_Data, FTM_SRLR_FIXED_DATALEN);
// Supported Power Range, read, optional server_FTM_SupportedPowerRange_Chr.setProperties(CHR_PROPS_READ); server_FTM_SupportedPowerRange_Chr.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); server_FTM_SupportedPowerRange_Chr.setFixedLen(FTM_SPR_FIXED_DATALEN); server_FTM_SupportedPowerRange_Chr.begin(); server_FTM_SupportedPowerRange_Chr.write(client_FTM_SupportedPowerRange_Data, FTM_SPR_FIXED_DATALEN);
// Fitness Machine Control Point, optional, write server_FTM_ControlPoint_Chr.setProperties(CHR_PROPS_INDICATE | CHR_PROPS_WRITE); // CHR_PROPS_READ // | CHR_PROPS_WRITE_WO_RESP); // Write with No response !! server_FTM_ControlPoint_Chr.setPermission(SECMODE_OPEN, SECMODE_OPEN); // readAccess, writeAccess DO NOT SET: SECMODE_NO_ACCESS ! server_FTM_ControlPoint_Chr.setMaxLen(FTM_CONTROL_POINT_DATALEN); // Maxlen of Client written data: (1) OpCode and (FTM_CONTROL_POINT_DATALEN-1) OCTETS server_FTM_ControlPoint_Chr.setWriteCallback(server_FTM_ControlPoint_Chr_callback); server_FTM_ControlPoint_Chr.begin();
// Fitness Machine Status, mandatory, notify BLENotify, server_FTM_Status_Chr.setProperties(CHR_PROPS_NOTIFY); // because type is "notify" server_FTM_Status_Chr.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // readAccess, writeAccess server_FTM_Status_Chr.setMaxLen(FTM_STATUS_DATALEN); server_FTM_Status_Chr.setCccdWriteCallback(server_cccd_callback); // Optionally capture CCCD updates server_FTM_Status_Chr.begin(); }
void server_FTM_ControlPoint_Chr_callback(uint16_t conn_hdl, BLECharacteristic chr, uint8_t data, uint16_t len) { // Server FTM Control Point data is tranferred to the Client // NO TREATMENT OF COMMAND !!! client_FTM_ControlPoint_Chr.write_resp(data, len); // Just pass on and process later! // Seems to cause hickups in response stream // client_FTM_ControlPoint_Chr.write(data, len); // Just pass on and process later!
uint8_t ftmcpDataLen = (uint8_t)len; memset(server_FTM_Control_Point_Data.bytes, 0, sizeof(server_FTM_Control_Point_Data.bytes)); // Transfer the contents of data to server_FTM_Control_Point_Data.bytes for (int i = 0; i < ftmcpDataLen; i++) { server_FTM_Control_Point_Data.bytes[i] = data++; } / Decodes an incoming Fitness Machine Control Point request */
Serial.printf(" -> Server Rec'd Raw FTM Control Point Data [len: %d] ", ftmcpDataLen); Serial.printf("[OpCode: %02X] [Values: ", server_FTM_Control_Point_Data.values.OPCODE, HEX); for (int i = 0; i < ftmcpDataLen; i++) { Serial.printf("%02X ", server_FTM_Control_Point_Data.values.OCTETS[i], HEX); } Serial.println("]");
switch (server_FTM_Control_Point_Data.values.OPCODE) { case ftmcpRequestControl: {
Serial.println("Request Control of Machine!");
break;
}
case ftmcpStartOrResume: {
Serial.println("Start or Resume Machine!");
break;
}
case ftmcpStopOrPause: {
Serial.println("Stop or Pause Machine, Parameter: Stop!");
break;
}
case ftmcpSetIndoorBikeSimulationParameters: {
// Short is 16 bit signed, so the windspeed is converted from two bytes to signed value. Highest bit is sign bit
short ws = (server_FTM_Control_Point_Data.values.OCTETS[0] << 8) + server_FTM_Control_Point_Data.values.OCTETS[1];
wind_speed = ws / 1000.0;
// Short is 16 bit signed, so a negative grade is correctly converted from two bytes to signed value. Highest bit is sign bit
short gr = (server_FTM_Control_Point_Data.values.OCTETS[3] << 8) + server_FTM_Control_Point_Data.values.OCTETS[2];
grade = gr / 100.0;
crr = server_FTM_Control_Point_Data.values.OCTETS[4] / 10000.0;
cw = server_FTM_Control_Point_Data.values.OCTETS[5] / 100.0;
Serial.print("Set Indoor Bike Simulation Parameters --> ");
Serial.print("Wind speed (1000): "); Serial.print(wind_speed);
Serial.print(" | Grade (100): "); Serial.print(grade);
Serial.print(" | Crr (10000): "); Serial.print(crr);
Serial.print(" | Cw (100): "); Serial.println(cw);
break;
}
case ftmcpReset: {
Serial.println("Reset Machine!");
break;
}
case ftmcpSetTargetResistanceLevel:
case ftmcpSetTargetSpeed:
case ftmcpSetTargetInclination:
case ftmcpSetTargetPower:
case ftmcpSetTargetHeartRate:
case ftmcpSetTargetedExpendedEngery:
case ftmcpSetTargetedNumberOfSteps:
case ftmcpSetTargetedNumberOfStrided:
case ftmcpSetTargetedDistance:
case ftmcpSetTargetedTrainingTime:
case ftmcpSetTargetedTimeInTwoHeartRateZones:
case ftmcpSetTargetedTimeInThreeHeartRateZones:
case ftmcpSetTargetedTimeInFiveHeartRateZones:
case ftmcpSetWheelCircumference:
case ftmcpSetSpinDownControl:
case ftmcpSetTargetedCadence:
{
Serial.println("Unresolved OpCode!");
break;
}
} // switch }
void server_setupCPS(void) { // Configure the Cycling Power service server_CylingPower_Service.begin();
server_CP_Measurement_Chr.setProperties(CHR_PROPS_NOTIFY); // type is "notify" server_CP_Measurement_Chr.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // readAccess, writeAccess server_CP_Measurement_Chr.setMaxLen(MAX_PAYLOAD); // Will work in most cases! server_CP_Measurement_Chr.setCccdWriteCallback(server_cccd_callback); // Optionally capture CCCD updates server_CP_Measurement_Chr.begin();
server_CP_ControlPoint_Chr.setProperties(CHR_PROPS_INDICATE | CHR_PROPS_WRITE); // Indicate and Write !! server_CP_ControlPoint_Chr.setPermission(SECMODE_OPEN, SECMODE_OPEN); // readAccess, writeAccess DO NOT SET: SECMODE_NO_ACCESS ! server_CP_ControlPoint_Chr.setMaxLen(CP_CONTROL_POINT_DATALEN); // The charactersitic's data set varies in length server_CP_ControlPoint_Chr.setCccdWriteCallback(server_cccd_callback); // Optionally capture CCCD updates server_CP_ControlPoint_Chr.begin(); server_CP_ControlPoint_Chr.setWriteCallback(server_CP_ControlPoint_Chr_callback); // Respond to events with "Write with Response" !!
server_CP_Feature_Chr.setProperties(CHR_PROPS_READ); server_CP_Feature_Chr.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); server_CP_Feature_Chr.setMaxLen(CP_FEATURE_DATALEN); server_CP_Feature_Chr.begin(); server_CP_Feature_Chr.write32(client_CP_Feature_Flags);
server_CP_Location_Chr.setProperties(CHR_PROPS_READ); server_CP_Location_Chr.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); server_CP_Location_Chr.setFixedLen(1); // UINT8 server_CP_Location_Chr.begin(); server_CP_Location_Chr.write8(client_CP_Location_Value); // Set the characteristic }
void server_setupCSC() { // Configure the Cadence and Speed service server_CyclingSpeedCadence_Service.begin();
server_CSC_Measurement_Chr.setProperties(CHR_PROPS_NOTIFY); // because type "notify" server_CSC_Measurement_Chr.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // readAccess, writeAccess server_CSC_Measurement_Chr.setMaxLen(MAX_PAYLOAD); server_CSC_Measurement_Chr.setCccdWriteCallback(server_cccd_callback); // Optionally capture CCCD updates server_CSC_Measurement_Chr.begin();
// Set the CSC Feature characteristic server_CSC_Feature_Chr.setProperties(CHR_PROPS_READ); server_CSC_Feature_Chr.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); server_CSC_Feature_Chr.setFixedLen(CSC_FEATURE_FIXED_DATALEN); server_CSC_Feature_Chr.begin(); server_CSC_Feature_Chr.write16(client_CSC_Feature_Flags);
// Configure the Sensor Location characteristic server_CSC_Location_Chr.setProperties(CHR_PROPS_READ); server_CSC_Location_Chr.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); server_CSC_Location_Chr.setFixedLen(1); server_CSC_Location_Chr.begin(); server_CSC_Location_Chr.write8(client_CSC_Location_Value); // Set the characteristic }
void server_CP_ControlPoint_Chr_callback(uint16_t conn_hdl, BLECharacteristic chr, uint8_t data, uint16_t len) { // Server CP Control Point data from Zwift is transferred to the Trainer // NO TREATMENT OF COMMAND !!! client_CP_ControlPoint_Chr.write_resp(data, len); // Just pass on and process later! // Not sure this is the right choice! // client_CP_ControlPoint_Chr.write(data, len); // Just pass on and process later!
uint8_t cpcpDataLen = (uint8_t)len; // Get the actual length of data bytes and type cast to (uint8_t) uint8_t cpcpData[cpcpDataLen]; memset(cpcpData, 0, cpcpDataLen); // set to zero // Display the raw request packet actual length Serial.printf(" -> Server CP Control Point Data [%d] [ ", cpcpDataLen); // Transfer the contents of data to cpcpData for (int i = 0; i < cpcpDataLen; i++) { if ( i <= sizeof(cpcpData)) { cpcpData[i] = *data++; // Display the raw request packet byte by byte in HEX Serial.printf("%02X ", cpcpData[i], HEX); } } Serial.println(" ] ");
}
void server_connect_callback(uint16_t conn_handle) { char Peer_Name[MAX_PAYLOAD] = {0}; uint8_t Peer_Addr[6] = {0}; // Get the reference to current connection BLEConnection* connection = Bluefruit.Connection(conn_handle); connection->getPeerName(Peer_Name, sizeof(Peer_Name)); ble_gap_addr_t peer_address = connection->getPeerAddr(); memcpy(Peer_Addr, peer_address.addr, 6);
Serial.printf("Feather nRF52 (Peripheral) connected to Central device: [%s] MAC Address: ", Peer_Name); PrintPeerAddress(Peer_Addr); Serial.println();
// Who has been exactly connected? // [1] Laptop is connecting if (memcmp(Peer_Addr, Laptop.PeerAddress, 6) == 0 ) { // Check Laptop MAC address // Laptop/PC is connecting ! memcpy(Laptop.PeerName, Peer_Name, sizeof(Peer_Name)); Laptop.conn_handle = conn_handle; Laptop.IsConnected = true; // MITM Server is connected with Central (Laptop/Smartphone) and ONLY // now enable the peripheral (trainer) to stream CPS, CSC and FTMS data... if(Trainer.IsConnected) { Client_Enable_Notify_Indicate(); }
Serial.println("Waiting for Central (Zwift) to set CCCD Notify/Indicate (enable) and start....");
return; // We are done here!
} // [2] Smartphone is connecting memcpy(Smartphone.PeerName, Peer_Name, sizeof(Peer_Name)); Smartphone.conn_handle = conn_handle; Smartphone.IsConnected = true; memcpy(Smartphone.PeerAddress, Peer_Addr, 6);
Serial.println("Waiting for Central (Phone) to set NUS Txd 'Notify' and start....");
}
/ Callback invoked when a connection is dropped @param conn_handle connection where this event happens @param reason is a BLE_HCI_STATUS_CODE / void server_disconnect_callback(uint16_t conn_handle, uint8_t reason) { if (Laptop.conn_handle == conn_handle ) { // Laptop/Desktop is disconnected Laptop.conn_handle = BLE_CONN_HANDLE_INVALID; Laptop.IsConnected = false;
Serial.printf("Server disconnected from Central (Laptop): [%s], reason: [%02X]\n", Laptop.PeerName, reason, HEX);
} if (Smartphone.conn_handle == conn_handle ) { // Smartphone is disconnected Smartphone.conn_handle = BLE_CONN_HANDLE_INVALID; Smartphone.IsConnected = false;
Serial.printf("Server disconnected from Central (Phone): [%s], reason: [%02X]\n", Smartphone.PeerName, reason, HEX);
} Bluefruit.Advertising.start(0); }
void server_cccd_callback(uint16_t conn_handle, BLECharacteristic* chr, uint16_t cccd_value) { // When changed, display the Notify/Indicate Status for all characteristics
Serial.printf("Central Device Updated CCCD to: [%d] --> ", cccd_value);
// Check the characteristic UUID this CCCD callback is associated with, // in case this handler is used for multiple CCCD records. if (chr->uuid == server_CP_Measurement_Chr.uuid) { if (chr->notifyEnabled(conn_handle)) {
Serial.print("Server CP: Measurement 'Notify' enabled");
} else {
Serial.print("Server CP: Measurement 'Notify' disabled");
}
}
if (chr->uuid == server_CP_ControlPoint_Chr.uuid) { if (chr->indicateEnabled(conn_handle)) {
Serial.print("Server CP: ControlPoint 'Indicate' enabled");
} else {
Serial.print("Server CP: ControlPoint 'Indicate' disabled");
}
}
if (chr->uuid == server_CSC_Measurement_Chr.uuid) { if (chr->notifyEnabled(conn_handle)) {
Serial.print("Server CSC: Measurement 'Notify' enabled");
} else {
Serial.print("Server CSC: Measurement 'Notify' disabled");
}
}
if (chr->uuid == server_FTM_IndoorBikeData_Chr.uuid) { if (chr->notifyEnabled(conn_handle)) {
Serial.print("Server FTM: IndoorBikeData 'Notify' enabled");
} else {
Serial.print("Server FTM: IndoorBikeData 'Notify' disabled");
}
}
if (chr->uuid == server_FTM_TrainingStatus_Chr.uuid) { // Zwift is NOT interested at all !!! if (chr->notifyEnabled(conn_handle)) {
Serial.print("Server FTM: TrainingStatus 'Notify' enabled");
} else {
Serial.print("Server FTM: TrainingStatus 'Notify' disabled");
}
}
if (chr->uuid == server_FTM_Status_Chr.uuid) { if (chr->notifyEnabled(conn_handle)) {
Serial.print("Server FTM: Status 'Notify' enabled");
} else {
Serial.print("Server FTM: Status 'Notify' disabled");
}
}
if (chr->uuid == server_FTM_ControlPoint_Chr.uuid) { if (chr->indicateEnabled(conn_handle)) {
Serial.print("Server FTM: ControlPoint 'Indicate' enabled");
} else {
Serial.print("Server FTM: ControlPoint 'Indicate' disabled");
}
}
if (chr->uuid == server_NUS_TXD_Chr.uuid) { if (chr->notifyEnabled(conn_handle)) {
Serial.print("Server NUS: TXD 'Notify' enabled");
} else {
Serial.print("Server NUS: TXD 'Notify' disabled");
}
}
Serial.println();
} // end Server CCCD callback // ---------------------- END of SERVER SIDE FUNCTIONS -------------------------
Result :
18:15:39.969 -> Feather nRF52840 MITM supporting: CPS, CSC and FTMS 18:15:39.969 -> ------------------ Version 02.3 --------------------- 18:15:39.969 -> FTM Service and Chars are 'initialized' 18:15:39.969 -> CP Service and Chars are 'initialized' 18:15:39.969 -> CSC Service and Chars are 'initialized' 18:15:39.969 -> Generic Access Service and Chars are 'initialized' 18:15:39.969 -> Device Information Service and Chars are 'initialized' 18:15:39.969 -> Start Client-side Scanning for CPS, CSC and FTMS! 18:15:39.969 -> Found advertising Peripheral with FTMS enabled! See Raw data packet: 18:15:39.969 -> Timestamp Addr Rssi Data 18:15:39.969 -> 000001090 F8:9C:FC:53:5E:49 -60 09-02-16-18-26-18-18-18-0A-18 18:15:39.969 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 18:15:39.969 -> Now checking all mandatory Client Services and Characteristics! 18:15:39.969 -> If Mandatory Services Fail --> the Client will disconnect! 18:15:39.969 -> First checking Generic Access and Device Information Services and Characteristics! 18:15:39.969 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 18:15:39.969 -> Discovering Client FTM Feature Characteristic ... Discovering Client FTM Control Point Characteristic ... Found it! 18:15:40.064 -> Discovering Client FTM Status Characteristic ... Found it! 18:15:40.391 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 18:15:40.672 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 18:15:40.827 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 18:15:40.827 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 18:15:41.088 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 18:15:41.088 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 18:15:41.368 -> Discovering Client Cycling Power (CP) Service ... Discovering Client CP Measurement characteristic ... Found it! 18:15:41.724 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 18:15:42.005 -> Discovering Client CP Feature characteristic ... Found it! 18:15:42.175 -> -> Client Reads Raw CP Feature bytes: [4] [ 00 00 00 00 ] 18:15:42.175 -> Discovering Client CP Sensor Location characteristic ... NOT Found! NOT Mandatory! 18:15:42.175 -> Discovering Cycling Speed and Cadence (CSC) Service ... Found it! CSCS Max Payload: 20 Data Length: 27 18:15:42.346 -> Discovering Client CSC Measurement CHR ... Found it! 18:15:42.532 -> Discovering Client CSC Location CHR ... Found it! 18:15:42.718 -> -> Client Reads CSC Location Sensor: Loc#: 0 Other 18:15:42.718 -> Discovering Client CSC Feature CHR ... Not Found! NOT Mandatory! 18:15:44.315 -> Configuring the Server Device Information Service 18:15:44.315 -> Configuring the Server Cycle Power Service 18:15:44.315 -> Configuring the Server Cadence and Speed Service 18:15:44.315 -> Configuring the Server Fitness Machine Service 18:15:44.315 -> Configuring the Server NUS Service 18:15:44.315 -> Setting up the Server-side advertising payload(s) 18:15:44.315 -> Setting Server Device Name to: [Sim ] 18:15:44.315 -> Setting Server Appearance to: [0] 18:15:44.315 -> Server-side is CPS, CSC and FTMS advertising! 18:17:45.853 -> Feather nRF52 (Peripheral) connected to Central device: [DESKTOP-1CC9OQN] MAC Address: 58:11:22:53:52:18 18:17:45.853 -> Ready to receive Client FTM Control Point Response Messages 18:17:45.900 -> Ready to receive Client FTM Status values 18:17:45.900 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 18:17:46.024 -> >>> Couldn't enable notify for Client FTM Indoor Bike Data Characteristic. 18:17:46.024 -> Ready to receive Client CP Measurement values 18:17:46.024 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 18:17:46.057 -> Ready to receive Client CSC Measurement values 18:17:46.057 -> Waiting for Central (Zwift) to set CCCD Notify/Indicate (enable) and start.... 18:17:50.388 -> Client- and Server-side are Up and Running! 18:17:51.217 -> Central Device Updated CCCD to: [1] --> Server CP: Measurement 'Notify' enabled 18:17:51.639 -> Central Device Updated CCCD to: [1] --> Server CSC: Measurement 'Notify' enabled 18:17:52.343 -> Central Device Updated CCCD to: [1] --> Server FTM: IndoorBikeData 'Notify' enabled 18:17:53.126 -> Central Device Updated CCCD to: [1] --> Server FTM: Status 'Notify' enabled 18:19:20.062 -> -> Server Rec'd Raw FTM Control Point Data [len: 1] [OpCode: 00] [Values: 00 ] 18:19:20.062 -> Request Control of Machine! 18:19:20.235 -> -> Client Rec'd Control Point Response: [ 80 00 01 ] 18:19:20.360 -> -> Server Rec'd Raw FTM Control Point Data [len: 1] [OpCode: 01] [Values: 00 ] 18:19:20.360 -> Reset Machine! 18:19:20.360 -> -> Server Rec'd Raw FTM Control Point Data [len: 1] [OpCode: 00] [Values: 00 ] 18:19:20.360 -> Request Control of Machine! 18:19:20.626 -> -> Client Rec'd Control Point Response: [ 80 01 01 ] 18:19:20.626 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 01 ] 18:19:25.543 -> -> Server Rec'd Raw FTM Control Point Data [len: 1] [OpCode: 00] [Values: 00 ] 18:19:25.543 -> Request Control of Machine! 18:19:25.589 -> -> Client Rec'd Control Point Response: [ 80 00 01 ] 18:19:25.730 -> -> Server Rec'd Raw FTM Control Point Data [len: 1] [OpCode: 07] [Values: 00 ] 18:19:25.730 -> Start or Resume Machine! 18:19:25.869 -> -> Client Rec'd Control Point Response: [ 80 07 01 ] 18:19:25.869 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 18:19:26.804 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 CC 00 28 33 00 ] 18:19:26.804 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.04 | Crr (10000): 0.00 | Cw (100): 0.51 18:19:26.945 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:19:26.945 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 CC 00 28 33 ] 18:19:55.908 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 84 00 28 33 00 ] 18:19:55.908 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.32 | Crr (10000): 0.00 | Cw (100): 0.51 18:19:56.293 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:19:56.293 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 84 00 28 33 ] 18:19:57.253 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 04 00 28 33 00 ] 18:19:57.253 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.04 | Crr (10000): 0.00 | Cw (100): 0.51 18:19:57.458 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:19:57.458 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 04 00 28 33 ] 18:19:58.366 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 2D 01 28 33 00 ] 18:19:58.366 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 3.01 | Crr (10000): 0.00 | Cw (100): 0.51 18:19:58.538 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:19:58.538 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 2D 01 28 33 ] 18:19:59.475 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 2C 01 28 33 00 ] 18:19:59.475 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 3.00 | Crr (10000): 0.00 | Cw (100): 0.51 18:19:59.616 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:19:59.616 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 2C 01 28 33 ] 18:20:01.176 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 2B 01 28 33 00 ] 18:20:01.176 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.99 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:01.362 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:01.362 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 2B 01 28 33 ] 18:20:04.460 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 2A 01 28 33 00 ] 18:20:04.460 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.98 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:04.664 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:04.664 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 2A 01 28 33 ] 18:20:06.262 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 29 01 28 33 00 ] 18:20:06.262 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.97 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:06.434 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:06.434 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 29 01 28 33 ] 18:20:08.944 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 28 01 28 33 00 ] 18:20:08.944 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.96 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:09.069 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:09.069 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 28 01 28 33 ] 18:20:11.448 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 27 01 28 33 00 ] 18:20:11.448 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.95 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:11.494 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:11.494 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 27 01 28 33 ] 18:20:13.321 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 26 01 28 33 00 ] 18:20:13.321 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.94 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:13.477 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:13.477 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 26 01 28 33 ] 18:20:15.857 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 25 01 28 33 00 ] 18:20:15.857 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.93 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:16.183 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:16.183 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 25 01 28 33 ] 18:20:17.808 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 24 01 28 33 00 ] 18:20:17.808 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.92 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:18.059 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:18.059 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 24 01 28 33 ] 18:20:18.953 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 23 01 28 33 00 ] 18:20:18.953 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.91 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:19.139 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:19.139 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 01 28 33 ] 18:20:21.451 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 22 01 28 33 00 ] 18:20:21.451 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.90 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:21.670 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:21.670 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 18:20:22.628 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 21 01 28 33 00 ] 18:20:22.628 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.89 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:22.722 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:22.722 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 21 01 28 33 ] 18:20:24.290 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 20 01 28 33 00 ] 18:20:24.290 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.88 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:24.370 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:24.370 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 20 01 28 33 ] 18:20:25.946 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 1F 01 28 33 00 ] 18:20:25.946 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.87 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:26.165 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:26.165 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1F 01 28 33 ] 18:20:26.994 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 1E 01 28 33 00 ] 18:20:26.994 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.86 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:27.150 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:27.150 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1E 01 28 33 ] 18:20:28.998 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 1D 01 28 33 00 ] 18:20:28.998 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.85 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:29.170 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:29.170 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1D 01 28 33 ] 18:20:29.985 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 1C 01 28 33 00 ] 18:20:29.985 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.84 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:30.311 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:30.311 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 01 28 33 ] 18:20:31.250 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 1B 01 28 33 00 ] 18:20:31.250 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.83 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:31.328 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 8:20:31.328 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1B 01 28 33 ] 18:20:32.141 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 1A 01 28 33 00 ] 18:20:32.141 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.82 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:32.234 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:32.234 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1A 01 28 33 ] 18:20:33.843 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 19 01 28 33 00 ] 18:20:33.843 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.81 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:33.984 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:33.984 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 19 01 28 33 ] 18:20:34.948 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 18 01 28 33 00 ] 18:20:34.948 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.80 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:35.200 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:35.200 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 18 01 28 33 ] 18:20:36.098 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 17 01 28 33 00 ] 18:20:36.098 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.79 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:36.331 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:36.331 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 17 01 28 33 ] 18:20:37.287 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 16 01 28 33 00 ] 18:20:37.287 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.78 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:37.507 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:37.507 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 16 01 28 33 ] 18:20:38.335 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 14 01 28 33 00 ] 18:20:38.335 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.76 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:38.569 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 18:20:38.569 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 01 28 33 ] 18:20:39.430 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 13 01 28 33 00 ] 18:20:39.430 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.75 | Crr (10000): 0.00 | Cw (100): 0.51 18:20:39.525 -> -> Client Rec'd Control Point Response: [ 80 11 01 ]
I have to look info this... How was your experience on the bike? Did you feel the resistance, grade is about 3%... ?
Op do 15 dec. 2022 19:09 schreef le-joebar @.***>:
I'll see if with the "While" in the "Bridge V23" version if it's better
The cadence is OK but I don't have the Watts!?
[image: 20221215_181851] https://user-images.githubusercontent.com/61932881/207935585-0f4be135-2c92-4284-819a-80c9edc65b79.jpg
Here is the modified code and the results :
/***** This is programming code for the nRF52 based Bluefruit BLE boards
The code uses heavily the Adafruit supplied Bluefruit BLE libraries !! Adafruit invests time and resources providing open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
MIT license, check LICENSE for more information All text must be included in any redistribution
*****/ /*
This code should work with all indoor cycling trainers that fully support, Fitness Machine Service, Cycling Power Service and Cycling Speed & Cadence Service
The code links a BLE Server (a peripheral to Zwift) and a BLE Client (a central to the Trainer) with a bridge in between, the Feather nRF52 being man-in-the-middle (MITM). The nRF52-bridge can control, filter and alter the bi-directional interchanged data! The client-side (central) scans and connects with the trainer relevant services: FTMS, CPS and CSC. It collects all cyling data of the services and passes these on to the server-side.... The client-side supplies the indoor trainer with target and resistance control data. The server-side (peripheral) advertises and enables connection with cycling apps like Zwift and collects the app's control commands, target and resistance data. It passes these on to the client-side.... The server-side supplies the app with the generated cycling data in return.
The client plus server (MITM) are transparent to the indoor trainer as well as to the training app Zwift or alike!
Requirements: Zwift app or alike, Feather nRF52 board and a FTMS/CPS/CSC supporting indoor trainer 1) Upload and Run this code on the Feather nRF52 2) Start the Serial Monitor to catch debugging info 3) Start/Power On the indoor trainer 4) Feather nRF52 and trainer (with
) will pair as reported in the output 5) Start Zwift on your computer or tablet and wait.... 6) Search on the Zwift pairing screens for the Feather nRF52 a.k.a. "Sim " 7) Pair: Power, Cadence and Controllable one after another with "Sim " 8) Optionally one can pair as well devices for heartrate and/or steering (Sterzo) 9) Start the default Zwift ride or any ride you wish
- Make Serial Monitor output window visible on top of the Zwift window
- Hop on the bike: do the work and feel resistance change with the road
- Inspect the info presented by Serial Monitor.....
Your trainer's device
is modified by the bridge to "Sim ", to allow for a clear distinction between the bridge (simulating your trainer) and your original trainer, when advertising the trainer's services! You will notice this only when connecting to Zwift on the pairing screens! Notice: Zwift extends device names with additional numbers for identification! */
//
// COMPILER DIRECTIVE to allow/suppress SERIAL.PRINT messages that help debugging... // Uncomment to activate
define DEBUG
// Restrict activating one or more of the following DEBUG directives --> process intensive // Have caused spurious side effects like a loss of quality of service handling!! //#define DEBUG_CP_MEASUREMENT //#define DEBUG_CSC_MEASUREMENT //#define DEBUG_FTM_INDOORBIKEDATA //
include
const uint8_t MAX_PAYLOAD = 20; // Max 20 byte data size for single packet BLE transfer
// Struct containing Device info to administer dis/connected devices typedef struct { uint8_t PeerAddress[6]; char PeerName[MAX_PAYLOAD]; uint16_t conn_handle; bool IsConnected; } Device_info_t; // ----------------------------------------------------------------- // Your hardware MAC/DEVICE ADDRESSES // Laptop/Desktop Device Address that runs Zwift, in printed format: [00:01:02:03:04:05] // Little Endian: in reversed order !!!!
define LAPTOPADDRESS {0x18,0x52,0x53,0x22,0x11,0x58}
// Trainer FTMS enabled Device Address, in printed format: [00:01:02:03:04:05] // Little Endian: in reversed order !!!!
define TRAINERADDRESS {0x49,0x5E,0x53,0xFC,0x9C,0xF8}
// ----------------------------------------------------------------- // Initialize connectable device registration Device_info_t Trainer = {TRAINERADDRESS, {0x00}, BLE_CONN_HANDLE_INVALID, false}; Device_info_t Laptop = { LAPTOPADDRESS, {0x00}, BLE_CONN_HANDLE_INVALID, false}; Device_info_t Smartphone = { {0x00}, {0x00}, BLE_CONN_HANDLE_INVALID, false}; //
/* Generic Access
define UUID16_SVC_GENERIC_ACCESS 0x1800
define UUID16_CHR_DEVICE_NAME 0x2A00
define UUID16_CHR_APPEARANCE 0x2A01
define UUID16_CHR_PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS 0x2A04 --->
not implemented
define UUID16_CHR_CENTRAL_ADDRESS_RESOLUTION 0x2AA6 ---> not implemented
*/ BLEClientService client_GenericAccess_Service(UUID16_SVC_GENERIC_ACCESS); // Optional BLEClientCharacteristic client_GA_Appearance_Chr(UUID16_CHR_APPEARANCE); // Read uint16_t client_GA_Appearance_Value = 0; BLEClientCharacteristic client_GA_DeviceName_Chr(UUID16_CHR_DEVICE_NAME); // Read, Write unsigned char client_GA_DeviceName_Data[MAX_PAYLOAD] = {};
/* Cycling Power Service CP Service: 0x1818 CP Characteristic: 0x2A63 (Measurement) CP Characteristic: 0x2A65 (Feature) CP Characteristic: 0x2A5D (Location) CP Characteristic: 0x2A66 (Control Point)
/ BLEClientService client_CyclingPower_Service(UUID16_SVC_CYCLING_POWER); // Mandatory BLEClientCharacteristic client_CP_Measurement_Chr(UUID16_CHR_CYCLING_POWER_MEASUREMENT); // Notify, Read, Mandatory BLEClientCharacteristic client_CP_Feature_Chr(UUID16_CHR_CYCLING_POWER_FEATURE); // Read, optional uint32_t client_CP_Feature_Flags = 0; const uint8_t CP_FEATURE_DATALEN = 4; // Set MaxLen to 4 const char client_CP_Feature_Str[] = { "Pedal power balance supported", "Accumulated torque supported", "Wheel revolution data supported", "Crank revolution data supported", "Extreme magnitudes supported", "Extreme angles supported", "Top/bottom dead angle supported", "Accumulated energy supported", "Offset compensation indicator supported", "Offset compensation supported", "Cycling power measurement characteristic content masking supported", "Multiple sensor locations supported", "Crank length adj. supported", "Chain length adj. supported", "Chain weight adj. supported", "Span length adj. supported", "Sensor measurement context", "Instantaineous measurement direction supported", "Factory calibrated date supported", "Enhanced offset compensation supported" }; BLEClientCharacteristic client_CP_Location_Chr(UUID16_CHR_SENSOR_LOCATION); // Read, optional uint8_t client_CP_Location_Value = 0; // UINT8 const char* client_Sensor_Location_Str[] = { "Other", "Top of shoe", "In shoe", "Hip", "Front wheel", "Left crank", "Right crank", "Left pedal", "Right pedal", "Front hub", "Rear dropout", "Chainstay", "Rear wheel", "Rear hub", "Chest", "Spider", "Chain ring" }; BLEClientCharacteristic client_CP_ControlPoint_Chr(UUID16_CHR_CYCLING_POWER_CONTROL_POINT); // Indicate, Write, optional const uint16_t CP_CONTROL_POINT_DATALEN = 5;
/* Cycling Speed and Cadence Service CSC Service: 0x1816 CSC Measurement Characteristic: 0x2A5B CSC Feature Characteristic: 0x2A5C CSC Location Characteristic: 0x2A5D CSC Control Point Characteristic:0x2A55 ---> not implemented
/ BLEClientService client_CyclingSpeedCadence_Service(UUID16_SVC_CYCLING_SPEED_AND_CADENCE); // Mandatory BLEClientCharacteristic client_CSC_Measurement_Chr(UUID16_CHR_CSC_MEASUREMENT); // Notify, Read, Mandatory BLEClientCharacteristic client_CSC_Feature_Chr(UUID16_CHR_CSC_FEATURE); // Read, optional const uint8_t CSC_FEATURE_FIXED_DATALEN = 2; // UINT16 uint16_t client_CSC_Feature_Flags = 0; const char client_CSC_Feature_Str[] = {"Wheel rev supported", "Crank rev supported", "Multiple locations supported"}; BLEClientCharacteristic client_CSC_Location_Chr(UUID16_CHR_SENSOR_LOCATION); // Read, optional uint8_t client_CSC_Location_Value = 0; // Shared with CPS --> client_Sensor_Location_Str[]
/* Service Device Information
define UUID16_SVC_DEVICE_INFORMATION 0x180A
define UUID16_CHR_MODEL_NUMBER_STRING 0x2A24
define UUID16_CHR_SERIAL_NUMBER_STRING 0x2A25
define UUID16_CHR_FIRMWARE_REVISION_STRING 0x2A26 ---> not implemented
define UUID16_CHR_HARDWARE_REVISION_STRING 0x2A27 ---> not implemented
define UUID16_CHR_SOFTWARE_REVISION_STRING 0x2A28 ---> not implemented
define UUID16_CHR_MANUFACTURER_NAME_STRING 0x2A29
*/ BLEClientService client_DIS_Service(UUID16_SVC_DEVICE_INFORMATION); // Optional BLEClientCharacteristic client_DIS_ManufacturerName_Chr(UUID16_CHR_MANUFACTURER_NAME_STRING); // Read char client_DIS_Manufacturer_Str[MAX_PAYLOAD] = {}; BLEClientCharacteristic client_DIS_ModelNumber_Chr(UUID16_CHR_MODEL_NUMBER_STRING); // Read char client_DIS_ModelNumber_Str[MAX_PAYLOAD] = {}; BLEClientCharacteristic client_DIS_SerialNumber_Chr(UUID16_CHR_SERIAL_NUMBER_STRING); // Read char client_DIS_SerialNumber_Str[MAX_PAYLOAD] = {};
/* Fitness Machine Service
define UUID16_SVC_FITNESS_MACHINE 0x1826
define UUID16_CHR_FITNESS_MACHINE_FEATURE 0x2ACC
define UUID16_CHR_INDOOR_BIKE_DATA 0x2AD2
define UUID16_CHR_TRAINING_STATUS 0x2AD3
define UUID16_CHR_SUPPORTED_SPEED_RANGE 0x2AD4 ---> not implemented
define UUID16_CHR_SUPPORTED_INCLINATION_RANGE 0x2AD5 ---> not implemented
define UUID16_CHR_SUPPORTED_RESISTANCE_LEVEL_RANGE 0x2AD6
define UUID16_CHR_SUPPORTED_HEART_RATE_RANGE 0x2AD7 ---> not implemented
define UUID16_CHR_SUPPORTED_POWER_RANGE 0x2AD8
define UUID16_CHR_FITNESS_MACHINE_CONTROL_POINT 0x2AD9
define UUID16_CHR_FITNESS_MACHINE_STATUS 0x2ADA
*/ BLEClientService client_FitnessMachine_Service(UUID16_SVC_FITNESS_MACHINE); // Mandatory // Service characteristics exposed by FTM Service BLEClientCharacteristic client_FTM_Feature_Chr(UUID16_CHR_FITNESS_MACHINE_FEATURE); // Mandatory, Read const uint8_t FTM_FEATURE_FIXED_DATALEN = 8; uint8_t client_FTM_Feature_Data[FTM_FEATURE_FIXED_DATALEN]; BLEClientCharacteristic client_FTM_IndoorBikeData_Chr(UUID16_CHR_INDOOR_BIKE_DATA); // Optional, Notify BLEClientCharacteristic client_FTM_TrainingStatus_Chr(UUID16_CHR_TRAINING_STATUS); // Optional, Read & Notify BLEClientCharacteristic client_FTM_SupportedResistanceLevelRange_Chr(UUID16_CHR_SUPPORTED_RESISTANCE_LEVEL_RANGE); // Mandatory, Read const uint8_t FTM_SRLR_FIXED_DATALEN = 6; uint8_t client_FTM_SupportedResistanceLevelRange_Data[FTM_SRLR_FIXED_DATALEN]; BLEClientCharacteristic client_FTM_SupportedPowerRange_Chr(UUID16_CHR_SUPPORTED_POWER_RANGE); // Mandatory, Read const uint8_t FTM_SPR_FIXED_DATALEN = 6; uint8_t client_FTM_SupportedPowerRange_Data[FTM_SPR_FIXED_DATALEN]; BLEClientCharacteristic client_FTM_ControlPoint_Chr(UUID16_CHR_FITNESS_MACHINE_CONTROL_POINT); // Mandatory, Write & Indicate BLEClientCharacteristic client_FTM_Status_Chr(UUID16_CHR_FITNESS_MACHINE_STATUS); // Mandatory, Notify
// ------------------------------------ START of SERVER DEFINITIONS
/ Cycling Speed and Cadence Service / BLEService server_CyclingSpeedCadence_Service = BLEService(UUID16_SVC_CYCLING_SPEED_AND_CADENCE); BLECharacteristic server_CSC_Measurement_Chr = BLECharacteristic(UUID16_CHR_CSC_MEASUREMENT); // Notify, Read BLECharacteristic server_CSC_Feature_Chr = BLECharacteristic(UUID16_CHR_CSC_FEATURE); // Read BLECharacteristic server_CSC_Location_Chr = BLECharacteristic(UUID16_CHR_SENSOR_LOCATION); // Read
/ Cycling Power Service / BLEService server_CylingPower_Service = BLEService(UUID16_SVC_CYCLING_POWER); BLECharacteristic server_CP_Measurement_Chr = BLECharacteristic(UUID16_CHR_CYCLING_POWER_MEASUREMENT); // Notify, Read BLECharacteristic server_CP_Feature_Chr = BLECharacteristic(UUID16_CHR_CYCLING_POWER_FEATURE); // Read BLECharacteristic server_CP_Location_Chr = BLECharacteristic(UUID16_CHR_SENSOR_LOCATION); // Read BLECharacteristic server_CP_ControlPoint_Chr = BLECharacteristic(UUID16_CHR_CYCLING_POWER_CONTROL_POINT); // Indicate, Write
/ Fitness Machine Service / BLEService server_FitnessMachine_Service = BLEService(UUID16_SVC_FITNESS_MACHINE); BLECharacteristic server_FTM_Feature_Chr = BLECharacteristic(UUID16_CHR_FITNESS_MACHINE_FEATURE); // Read BLECharacteristic server_FTM_IndoorBikeData_Chr = BLECharacteristic(UUID16_CHR_INDOOR_BIKE_DATA); // Notify BLECharacteristic server_FTM_TrainingStatus_Chr = BLECharacteristic(UUID16_CHR_TRAINING_STATUS); // Notify, Read const uint8_t FTM_TRAINING_STATUS_FIXED_DATALEN = 2; // Fixed len BLECharacteristic server_FTM_SupportedResistanceLevelRange_Chr = BLECharacteristic(UUID16_CHR_SUPPORTED_RESISTANCE_LEVEL_RANGE); // Read BLECharacteristic server_FTM_SupportedPowerRange_Chr = BLECharacteristic(UUID16_CHR_SUPPORTED_POWER_RANGE); // Read BLECharacteristic server_FTM_ControlPoint_Chr = BLECharacteristic(UUID16_CHR_FITNESS_MACHINE_CONTROL_POINT); // Write & Indicate BLECharacteristic server_FTM_Status_Chr = BLECharacteristic(UUID16_CHR_FITNESS_MACHINE_STATUS); // Notify const uint8_t FTM_STATUS_DATALEN = 7; // Max Len was: [3] --> Notice that with de Elite Direto the size is: [7] !!
/ Device Information Service helper class instance / BLEDis server_bledis; // Read unsigned char FirmwareRevStr[] = "0.0.0"; unsigned char HardwareRevStr[] = "0.0.0"; unsigned char SoftwareRevStr[] = "0.0.0";
/ NORDIC UART SERVICE a.k.a. NUS NUS Service: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E NUS RXD : 6E400002-B5A3-F393-E0A9-E50E24DCCA9E NUS TXD : 6E400003-B5A3-F393-E0A9-E50E24DCCA9E / const uint8_t UUID_NUS_SERVICE[] = {0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x01, 0x00, 0x40, 0x6E}; const uint8_t UUID_NUS_CHR_RXD[] = {0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x02, 0x00, 0x40, 0x6E}; const uint8_t UUID_NUS_CHR_TXD[] = {0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x03, 0x00, 0x40, 0x6E}; BLEService server_NordicUart_Service = BLEService(UUID_NUS_SERVICE); BLECharacteristic server_NUS_RXD_Chr = BLECharacteristic(UUID_NUS_CHR_RXD); // Read (Receiving Data) BLECharacteristic server_NUS_TXD_Chr = BLECharacteristic(UUID_NUS_CHR_TXD); // Notify (Sending Data)
// ----------------------------- The Fitness Machine Control Point data type structure -------------------------------- // ---------------------------- Decoding is done in: server_FTM_ControlPoint_Chr_callback ------------------------------ const uint8_t ftmcpRequestControl = 0x00; const uint8_t ftmcpReset = 0x01; const uint8_t ftmcpSetTargetSpeed = 0x02; const uint8_t ftmcpSetTargetInclination = 0x03; const uint8_t ftmcpSetTargetResistanceLevel = 0x04; const uint8_t ftmcpSetTargetPower = 0x05; const uint8_t ftmcpSetTargetHeartRate = 0x06; const uint8_t ftmcpStartOrResume = 0x07; const uint8_t ftmcpStopOrPause = 0x08; const uint8_t ftmcpSetTargetedExpendedEngery = 0x09; const uint8_t ftmcpSetTargetedNumberOfSteps = 0x0A; const uint8_t ftmcpSetTargetedNumberOfStrided = 0x0B; const uint8_t ftmcpSetTargetedDistance = 0x0C; const uint8_t ftmcpSetTargetedTrainingTime = 0x0D; const uint8_t ftmcpSetTargetedTimeInTwoHeartRateZones = 0x0E; const uint8_t ftmcpSetTargetedTimeInThreeHeartRateZones = 0x0F; const uint8_t ftmcpSetTargetedTimeInFiveHeartRateZones = 0x10; const uint8_t ftmcpSetIndoorBikeSimulationParameters = 0x11; const uint8_t ftmcpSetWheelCircumference = 0x12; const uint8_t ftmcpSetSpinDownControl = 0x13; const uint8_t ftmcpSetTargetedCadence = 0x14;
const uint8_t FTM_CONTROL_POINT_DATALEN = 19; // Control point consists of 1 opcode (byte) and maximum 18 bytes as parameters // This ftmcp_data_t structure represents the control point data. The first octet represents the opcode of the request // followed by a parameter array of maximum 18 octects typedef struct attribute( ( packed ) ) { uint8_t OPCODE; uint8_t OCTETS[(FTM_CONTROL_POINT_DATALEN - 1)]; } ftmcp_data_t; typedef union // The union type automatically maps the bytes member array to the ftmcp_data_t structure member values { ftmcp_data_t values; uint8_t bytes[FTM_CONTROL_POINT_DATALEN]; } ftmcp_data_ut; // Fitness Machine Control Point Data variable ftmcp_data_ut server_FTM_Control_Point_Data; // ----------------------- end of server_FTM_ControlPoint_Chr_callback definitions ----------------------------
// -------------------------------------- END OF SERVER DEFINITIONS
//
// Global Server variables for decoding of INDOOR BIKE RESISTANCE PARAMETERS //
float wind_speed = 0; // meters per second, resolution 0.001 float grade = 0; // percentage, resolution 0.01 float crr = 0; // Coefficient of rolling resistance, resolution 0.0001 float cw = 0; // Wind resistance Kg/m, resolution 0.01; //
define TIME_SPAN 5000 // Time span in millis 1000 = 1 second
unsigned long TimeInterval = 0;
void setup() {
ifdef DEBUG
Serial.begin(115200); while ( !Serial ) delay(10); // for nrf52840 with native usb Serial.println("Feather nRF52840 MITM supporting: CPS, CSC and FTMS"); Serial.println("------------------ Version 02.3 ---------------------");
endif
// Initialize Bluefruit with maximum connections as Peripheral = 1, Central = 1 Bluefruit.begin(1, 1); Setup_Client_FTMS(); Setup_Client_CPS(); Setup_Client_CSC(); Setup_Client_DIS(); Client_Start_Scanning();
while (Bluefruit.Scanner.isRunning()) { // do nothing else but scanning.... yield(); } // wait enough time or go on when Client/Central is connected and all set! TimeInterval = millis() + TIME_SPAN; // ADD just enough delay while ( (millis() < TimeInterval) || (!Trainer.IsConnected) ) { yield(); }
// Configure and Start the Device Information Service
ifdef DEBUG
Serial.println("Configuring the Server Device Information Service");
endif
server_setupDIS(); // Setup the Cycle Power Service, Speed & Cadence Service and FTMS
ifdef DEBUG
Serial.println("Configuring the Server Cycle Power Service");
endif
server_setupCPS();
ifdef DEBUG
Serial.println("Configuring the Server Cadence and Speed Service");
endif
server_setupCSC();
ifdef DEBUG
Serial.println("Configuring the Server Fitness Machine Service");
endif
server_setupFTMS();
ifdef DEBUG
Serial.println("Configuring the Server NUS Service");
endif
server_setupNUS(); // Setup and start advertising
ifdef DEBUG
Serial.println("Setting up the Server-side advertising payload(s)");
endif
server_startADV();
ifdef DEBUG
Serial.println("Server-side is CPS, CSC and FTMS advertising!");
endif
while (Bluefruit.Advertising.isRunning()) { // ONLY advertise! yield(); } TimeInterval = millis() + TIME_SPAN; // ADD just enough DELAY // wait enough time or go on when Server/Peripheral is connected and set! while ( (millis() < TimeInterval) || (!Laptop.IsConnected) ) { yield(); }
ifdef DEBUG
Serial.println("Client- and Server-side are Up and Running!");
endif
}
// ---------------------- CLIENT SIDE FUNCTIONS ------------------------- void Setup_Client_FTMS(void) { // Initialize client FTM Service client_FitnessMachine_Service.begin();
// Initialize client FTM Feature characteristic client_FTM_Feature_Chr.begin();
// Initialize client FTM Training Status characteristic
client_FTM_TrainingStatus_Chr.setNotifyCallback(client_FTM_TrainingStatus_Notify_callback); client_FTM_TrainingStatus_Chr.begin();
// Initialize client FTM Supported Power Range characteristic client_FTM_SupportedPowerRange_Chr.begin();
// Initialize client FTM Supported Resistance Level Range characteristic client_FTM_SupportedResistanceLevelRange_Chr.begin();
// Initialize client FTM Indoor Bike Data characteristic
client_FTM_IndoorBikeData_Chr.setNotifyCallback(client_FTM_IndoorBikeData_Notify_callback); client_FTM_IndoorBikeData_Chr.begin();
// Initialize client FTM Control Point characteristic // For receiving Control Point Responses
client_FTM_ControlPoint_Chr.setIndicateCallback(client_FTM_ControlPoint_Indicate_callback); client_FTM_ControlPoint_Chr.begin();
// Initialize client FTM Status characteristic client_FTM_Status_Chr.setNotifyCallback(client_FTM_Status_Notify_callback); client_FTM_Status_Chr.begin();
ifdef DEBUG
Serial.println("FTM Service and Chars are 'initialized'");
endif
}
void Setup_Client_CPS(void) { // Initialize CPS client client_CyclingPower_Service.begin();
// Initialize CP Feature characteristics of client_CyclingPower_Service. client_CP_Feature_Chr.begin();
// Initialize CP sensor location characteristics of client_CyclingPower_Service. client_CP_Location_Chr.begin();
// set up callback for receiving measurement
client_CP_Measurement_Chr.setNotifyCallback(client_CP_Measurement_Chr_notify_callback); client_CP_Measurement_Chr.begin();
// Initialize Control Point and set up Indicate callback for receiving responses (indicate!)
client_CP_ControlPoint_Chr.setIndicateCallback(client_CP_ControlPoint_Chr_indicate_callback); client_CP_ControlPoint_Chr.begin();
ifdef DEBUG
Serial.println("CP Service and Chars are 'initialized'");
endif
}
void Setup_Client_CSC(void) { // Initialize CSC client client_CyclingSpeedCadence_Service.begin();
// Initialize client characteristics of CSC. client_CSC_Location_Chr.begin();
// Initialize CSC Feature characteristics of client_CSC. client_CSC_Feature_Chr.begin();
// set up callback for receiving measurement
client_CSC_Measurement_Chr.setNotifyCallback(client_CSC_Measurement_Chr_notify_callback); client_CSC_Measurement_Chr.begin();
ifdef DEBUG
Serial.println("CSC Service and Chars are 'initialized'");
endif
}
void Setup_Client_DIS(void) { // Initialize client Generic Access Service client_GenericAccess_Service.begin(); // Initialize some characteristics of the Generic Access Service. client_GA_DeviceName_Chr.begin(); client_GA_Appearance_Chr.begin();
ifdef DEBUG
Serial.println("Generic Access Service and Chars are 'initialized'");
endif
// Initialize client Device Information Service client_DIS_Service.begin(); // Initialize some characteristics of the Device Information Service. client_DIS_ManufacturerName_Chr.begin(); client_DIS_ModelNumber_Chr.begin(); client_DIS_SerialNumber_Chr.begin();
ifdef DEBUG
Serial.println("Device Information Service and Chars are 'initialized'");
endif
}
void loop() { } // end loop
void Client_Start_Scanning(void) { /* Start Central Scanning
- Enable auto scan if disconnected
- Interval = 100 ms, window = 80 ms
- Don't use active scan
- Filter only accept CP service
- Start(timeout) with timeout = 0 will scan forever (until connected) */ // Client/Central Callbacks defined Bluefruit.Central.setDisconnectCallback(client_disconnect_callback); Bluefruit.Central.setConnectCallback(client_connect_callback); Bluefruit.Scanner.setRxCallback(client_scan_callback); Bluefruit.Scanner.restartOnDisconnect(false); // default is true !!! this stage we do not want to RESTART Bluefruit.Scanner.filterRssi(-70); // original value of -80 , we want to scan only nearby peripherals, so get close to your device !! Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms // Invoke callback if CPS or CSC or FTMS is advertised Bluefruit.Scanner.filterUuid(UUID16_SVC_CYCLING_POWER, UUID16_SVC_CYCLING_SPEED_AND_CADENCE, UUID16_SVC_FITNESS_MACHINE); Bluefruit.Scanner.useActiveScan(true); Bluefruit.Scanner.start(0); // 500 // 0 = Don't stop scanning or n = after n/100 seconds
ifdef DEBUG
Serial.println("Start Client-side Scanning for CPS, CSC and FTMS!"); delay(100); // To show print message !
endif
}
void Client_Enable_Notify_Indicate(void) { // --------------------- Enable CP and CSC Notify and Indicate
// Reaching here means we are ready to go, let's enable notification on measurement chr // ------------------------- Enable FTMS Notify and Indicate
if ( client_FTM_ControlPoint_Chr.enableIndicate() ) { // MANDATORY
ifdef DEBUG
Serial.println("Ready to receive Client FTM Control Point Response Messages");
endif
} else {
ifdef DEBUG
Serial.println(">>> Couldn't enable indicate for Client FTM Control Point Characteristic."); Serial.println("FTMS (trainer) is controlled by another Client (Training App)!");
endif
Bluefruit.disconnect(Trainer.conn_handle); return; }
if ( client_FTM_Status_Chr.enableNotify() ) { // MANDATORY
ifdef DEBUG
Serial.println("Ready to receive Client FTM Status values");
endif
} else {
ifdef DEBUG
Serial.println(">>> Couldn't enable notify for Client FTM Status Characteristic."); Serial.println("FTMS (trainer) is controlled by another Client (Training App)!");
endif
Bluefruit.disconnect(Trainer.conn_handle); return; }
if ( client_FTM_TrainingStatus_Chr.enableNotify() ) { // NOT MANDATORY
ifdef DEBUG
Serial.println("Ready to receive Client FTM Training Status values");
endif
} else {
ifdef DEBUG
Serial.println(">>> Couldn't enable notify for Client FTM Training Status Characteristic.");
endif
}
if ( client_FTM_IndoorBikeData_Chr.enableNotify() ) { // NOT MANDATORY
ifdef DEBUG
Serial.println("Ready to receive Client FTM Indoor Bike Data values");
endif
} else {
ifdef DEBUG
Serial.println(">>> Couldn't enable notify for Client FTM Indoor Bike Data Characteristic.");
endif
} // ------------------------- Enable FTMS Notify and Indicate
// --------------------- Enable CP and CSC Notify and Indicate
if ( client_CP_Measurement_Chr.enableNotify() ) { // NOT MANDATORY
ifdef DEBUG
Serial.println("Ready to receive Client CP Measurement values");
endif
} else {
ifdef DEBUG
Serial.println(">>> Couldn't enable notify for Client CP Measurement Characteristic.");
endif
}
if ( client_CP_ControlPoint_Chr.enableIndicate() ) { // NOT MANDATORY
ifdef DEBUG
Serial.println("Ready to receive Client CP Control Point Responses");
endif
} else {
ifdef DEBUG
Serial.println(">>> Couldn't enable indicate for Client CP Control Point Characteristic.");
endif
}
if ( client_CSC_Measurement_Chr.enableNotify() ) { // NOT MANDATORY
ifdef DEBUG
Serial.println("Ready to receive Client CSC Measurement values");
endif
} else {
ifdef DEBUG
Serial.println(">>> Couldn't enable notify for Client CSC Measurement Characteristic.");
endif
} // ------------------------- Enable CP and CSC Notify and Indicate
} // ------------------------- Enable FTMS Notify and Indicate
/** Hooked callback that triggered when a status value is sent @param https://github.com/param chr Pointer client characteristic @param https://github.com/param data Pointer to received data @param https://github.com/param len Length of received data
/ void client_FTM_TrainingStatus_Notify_callback(BLEClientCharacteristic chr, uint8_t* data, uint16_t len) { // Client Training Status data is tranferred to the Server // NO TREATMENT OF COMMAND !!! server_FTM_TrainingStatus_Chr.notify(data, len); // Just pass on and process later!
ifdef DEBUG
uint8_t SDataLen = (uint8_t)len; uint8_t SDataBuf[SDataLen] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw FTM Training Status Data: [%d] [ ", len); for (int i = 0; i < sizeof(SDataBuf); i++) { SDataBuf[i] = *data++; Serial.printf("%02X ", SDataBuf[i], HEX); } Serial.println("] ");
endif
}
/** Hooked callback that is triggered when an IBD value is sent @param https://github.com/param chr Pointer client characteristic @param https://github.com/param data Pointer to received data @param https://github.com/param len Length of received data
/ void client_FTM_IndoorBikeData_Notify_callback(BLEClientCharacteristic chr, uint8_t* data, uint16_t len) { // Client IBD data is tranferred to the Server // NO TREATMENT OF COMMAND !!! if (server_FTM_IndoorBikeData_Chr.notifyEnabled(Laptop.conn_handle)) { server_FTM_IndoorBikeData_Chr.notify(data, len); // Just pass on and process later! }
ifdef DEBUG_FTM_INDOORBIKEDATA
// Only when DEBUG_FTM_INDOORBIKEDATA is defined IDBData will be parsed and printed! ParseIndoorBikeData(data, len);
endif
}
ifdef DEBUG_FTM_INDOORBIKEDATA
void ParseIndoorBikeData(uint8_t data, uint16_t len) { // ---> IBD Buffer Data Length depends on data flagged to be present !!!! uint8_t IBDDataLen = (uint8_t)len; uint8_t IBDDataBuf[IBDDataLen] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw FTM IBD Data: [%d] [ ", len); for (int i = 0; i < sizeof(IBDDataBuf); i++) { IBDDataBuf[i] = data++; Serial.printf("%02X ", IBDDataBuf[i], HEX); } Serial.print("] ");
uint8_t offset = 0; uint16_t flags = 0; memcpy(&flags, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable offset += 2; // UINT16 if ((flags & 1) != 0) { // More Data Serial.print(" More Data!"); } // if ((flags & 2) != 0) { // (flags & 2) --> true or false Average Speed is always(?) there (tested with Elite Direto XR) // Average Speed 0.01 uint16_t sim_Speed = 0; memcpy(&sim_Speed, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Speed: %d KPH", (sim_Speed / 100)); offset += 2; // UINT16 // } if ((flags & 4) != 0) { // Instantaneous Cadence 0.5 uint16_t inst_Cadence = 0; memcpy(&inst_Cadence, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Instantaneous Cadence: %d RPM", (inst_Cadence / 2)); offset += 2; // UINT16 } if ((flags & 8) != 0) { // Average Cadence 0.5 uint16_t av_Cadence = 0; memcpy(&av_Cadence, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Average Cadence: %d RPM", (av_Cadence / 2)); offset += 2; // UINT16 } if ((flags & 16) != 0) { // Total Distance 1 uint32_t tot_Distance = 0; memcpy(&tot_Distance, &IBDDataBuf[offset], 3); // Transfer buffer fields to variable Serial.printf(" Total Distance: %d m", tot_Distance); offset += 3; // UINT24 } if ((flags & 32) != 0) { // Resistance Level 1 uint16_t res_Level = 0; memcpy(&res_Level, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Resistance Level: %d ", res_Level); offset += 2; // UINT16 } if ((flags & 64) != 0) { // Instantaneous Power 1 uint16_t inst_Power = 0; memcpy(&inst_Power, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Instantaneous Power: %d Watt", inst_Power); offset += 2; // UINT16 } if ((flags & 128) != 0) { // Average Power 1 uint16_t av_Power = 0; memcpy(&av_Power, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Average Power: %d Watt", av_Power); offset += 2; // UINT16 } if ((flags & 256) != 0) { // Expended Energy -> UINT16 UINT16 UINT8 // Total Energy UINT16 1 uint16_t tot_Energy = 0; memcpy(&tot_Energy, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Tot. Energy: %d kCal", tot_Energy); offset += 2; // UINT16 // Energy per hour UINT16 1 uint16_t Energy_hr = 0; memcpy(&Energy_hr, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Energy/hr: %d kCal/hr", Energy_hr); offset += 2; // UINT16 // Energy per minute UINT8 1 uint8_t Energy_pm = 0; memcpy(&Energy_pm, &IBDDataBuf[offset], 1); // Transfer buffer fields to variable Serial.printf(" Energy/m: %d kCal/m", Energy_pm); offset += 1; // UINT8 } if ((flags & 512) != 0) { // Heart Rate 1 uint8_t Heart_Rate = 0; memcpy(&Heart_Rate, &IBDDataBuf[offset], 1); // Transfer buffer fields to variable Serial.printf(" Heart Rate: %d HBM", Heart_Rate); offset += 1; // UINT8 } if ((flags & 1024) != 0) { // Metabolic Equivalent 0.1 uint8_t Mets = 0; memcpy(&Mets, &IBDDataBuf[offset], 1); // Transfer buffer fields to variable Serial.printf(" Metabolic Equivalent: %d ", Mets / 10); offset += 1; // UINT8 } if ((flags & 2048) != 0) { // Elapsed Time 1 uint16_t elap_time = 0; memcpy(&elap_time, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Elapsed time: %d s", elap_time); offset += 2; // UINT16 } if ((flags & 4096) != 0) { // Remaining Time 1 uint16_t rem_time = 0; memcpy(&rem_time, &IBDDataBuf[offset], 2); // Transfer buffer fields to variable Serial.printf(" Remaining time: %d s", rem_time); offset += 2; // UINT16 } Serial.println(); }
endif
/** Hooked callback that triggered when a value is sent @param https://github.com/param chr Pointer client characteristic @param https://github.com/param data Pointer to received data @param https://github.com/param len Length of received data
/ void client_FTM_ControlPoint_Indicate_callback(BLEClientCharacteristic chr, uint8_t* data, uint16_t len) { // The receipt of Control Point settings is acknowledged by the trainer: handle it // Send Client's Response message to the Server // NO TREATMENT OF COMMAND !!! server_FTM_ControlPoint_Chr.indicate(data, len); // Just pass on and process later!
ifdef DEBUG
uint8_t RespBufferLen = (uint8_t)len; uint8_t RespBuffer[RespBufferLen] = {}; // It is max 6 bytes long // Transfer first the contents of data to buffer (array of chars) Serial.print(" -> Client Rec'd Control Point Response: [ "); for (int i = 0; i < sizeof(RespBuffer); i++) { RespBuffer[i] = *data++; Serial.printf("%02X ", RespBuffer[i], HEX); } Serial.println("] ");
endif
}
/** Hooked callback that triggered when a value is sent @param https://github.com/param chr Pointer client characteristic @param https://github.com/param data Pointer to received data @param https://github.com/param len Length of received data
/ void client_FTM_Status_Notify_callback(BLEClientCharacteristic chr, uint8_t* data, uint16_t len) { // Client's Machine Status data is tranferred to the Server // NO TREATMENT OF COMMAND !!! server_FTM_Status_Chr.notify(data, len); // Just pass on and process later!
ifdef DEBUG
uint8_t SDataLen = (uint8_t)len; uint8_t SDataBuf[SDataLen] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw FTM Machine Status Data: [%d] [ ", len); for (int i = 0; i < sizeof(SDataBuf); i++) { SDataBuf[i] = *data++; Serial.printf("%02X ", SDataBuf[i], HEX); } Serial.println("] ");
endif
}
// Byte swap unsigned short uint16_t swap_uint16( uint16_t val ) { return (val << 8) | (val >> 8 ); }
// Find certain uuid in the data of the received advertising packet bool checkForUuidPresent(const uint16_t uuid, const uint8_t* reportData, uint8_t reportDataLen) { // Enter uuid in printed format like 0x1826 for UUID16_SVC_FITNESS_MACHINE // uuid is internally stored in Little Endian for (int i = 0; i < (reportDataLen); i++) { // step 1: never miss out a position! if ( memcmp(&uuid, (reportData + i), 2) == 0) { return true; } } return false; }
/** Callback invoked when scanner pick up an advertising data @param https://github.com/param report Structural advertising data
/ void client_scan_callback(ble_gap_evt_adv_report_t report) { // Since we configure the scanner with filterUuid(CPS, CSC, FTMS) // scan_callback is invoked for devices with usually CPS service advertised. // However, we only do business with FTMS enabled Trainer types so check // for UUID16_SVC_FITNESS_MACHINE to be present, if not --> keep scanning! uint8_t Device_Addr[6] = {0}; if (!checkForUuidPresent(UUID16_SVC_FITNESS_MACHINE, report->data.p_data, report->data.len)) { return; // Keep scanning for FTMS trainer !! } memcpy(Device_Addr, report->peer_addr.addr, 6); if ( !(memcmp(Device_Addr, Trainer.PeerAddress, 6) == 0) ) { return; // Keep scanning for the required trainer !! } // Connect to device only with required services AND device address if (Bluefruit.Scanner.isRunning()) { Bluefruit.Scanner.stop(); }
ifdef DEBUG
Serial.println("Found advertising Peripheral with FTMS enabled! See Raw data packet:"); Serial.println(F("Timestamp Addr Rssi Data")); Serial.printf("%09d ", millis()); // MAC is in little endian --> print reverse Serial.printBufferReverse(report->peer_addr.addr, 6, ':'); Serial.print(F(" ")); Serial.print(report->rssi); Serial.print(F(" ")); Serial.printBuffer(report->data.p_data, report->data.len, '-'); Serial.println();
endif
Bluefruit.Central.connect(report); }
ifdef DEBUG
void PrintPeerAddress(uint8_t addr[6]) { for (int i = 1; i < 6; i++) { // Display byte by byte in HEX reverse: little Endian Serial.printf("%02X:", addr[(6 - i)], HEX); } Serial.printf("%02X ", addr[0], HEX); }
endif
/** Callback invoked when a connection is established @param https://github.com/param conn_handle
/ void client_connect_callback(uint16_t conn_handle) { Trainer.conn_handle = conn_handle; // Get the reference to current connection BLEConnection connection = Bluefruit.Connection(conn_handle); connection->getPeerName(Trainer.PeerName, sizeof(Trainer.PeerName)); ble_gap_addr_t PeerAddr = connection->getPeerAddr(); // Fill BLE Gap struct memcpy(Trainer.PeerAddress, PeerAddr.addr, 6); // Copy Peer Address from ble_gap_addr_t struct
ifdef DEBUG
Serial.printf("Feather nRF52 (Central) connected to Trainer (Peripheral) device: [%s] MAC Address: ", Trainer.PeerName); PrintPeerAddress(Trainer.PeerAddress); Serial.println(); Serial.println("Now checking all mandatory Client Services and Characteristics!"); Serial.println("If Mandatory Services Fail --> the Client will disconnect!");
endif
// ---------------------------- GA and DIS SERVICE
ifdef DEBUG
Serial.println("First checking Generic Access and Device Information Services and Characteristics!");
endif
// If Generic Access is not found then go on.... NOT FATAL ! while (!(client_GenericAccess_Service.discover(conn_handle))) { if ( client_GenericAccess_Service.discover(conn_handle) ) {
ifdef DEBUG
Serial.print(F("Found Client Generic Access\n"));
endif
if ( client_GA_DeviceName_Chr.discover() ) { client_GA_DeviceName_Chr.read(client_GA_DeviceName_Data, sizeof(client_GA_DeviceName_Data));
ifdef DEBUG
Serial.printf(" -> Client Reads Device Name: [%s]\n", client_GA_DeviceName_Data);
endif
} if ( client_GA_Appearance_Chr.discover() ) { client_GA_Appearance_Value = client_GA_Appearance_Chr.read16();
ifdef DEBUG
Serial.printf(" -> Client Reads Appearance: [%d]\n", client_GA_Appearance_Value);
endif
} } // GA } // If DIS is not found then go on.... NOT FATAL !
while (!( client_DIS_Service.discover(conn_handle) )){ if ( client_DIS_Service.discover(conn_handle) ) {
ifdef DEBUG
Serial.print(F("Found Client Device Information\n"));
endif
// 1 if ( client_DIS_ManufacturerName_Chr.discover() ) { // read and print out Manufacturer if ( client_DIS_ManufacturerName_Chr.read(client_DIS_Manufacturer_Str, sizeof(client_DIS_Manufacturer_Str)) ) {
ifdef DEBUG
Serial.printf(" -> Client Reads Manufacturer: [%s]\n", client_DIS_Manufacturer_Str);
endif
} } // 1 // 2 if ( client_DIS_ModelNumber_Chr.discover() ) { // read and print out Model Number if ( client_DIS_ModelNumber_Chr.read(client_DIS_ModelNumber_Str, sizeof(client_DIS_ModelNumber_Str)) ) {
ifdef DEBUG
Serial.printf(" -> Client Reads Model Number: [%s]\n", client_DIS_ModelNumber_Str);
endif
} } // 2 // 3 if ( client_DIS_SerialNumber_Chr.discover() ) { // read and print out Serial Number if ( client_DIS_SerialNumber_Chr.read(client_DIS_SerialNumber_Str, sizeof(client_DIS_SerialNumber_Str)) ) {
ifdef DEBUG
Serial.printf(" -> Client Reads Serial Number: [%s]\n", client_DIS_SerialNumber_Str);
endif
} } // 3 } } // DIS // ---------------------------- END GA and DIS SERVICE
// -----------------------------FTM SERVICE
ifdef DEBUG
Serial.print("Discovering Mandatory Client Fitness Machine (FTM) Service ... ");
endif
// If FTM is not found, disconnect, resume scanning, and return if ( client_FitnessMachine_Service.discover(conn_handle) ) {
ifdef DEBUG
BLEConnection* conn = Bluefruit.Connection(conn_handle); uint16_t max_payload = conn->getMtu()-3; uint16_t data_length = conn->getDataLength(); Serial.print("Found it! "); Serial.printf("FTMS Max Payload: %d Data Length: %d\n", max_payload, data_length);
endif
} else {
ifdef DEBUG
Serial.println("Not Found!"); Serial.println("Disconnecting since Client FTM Service is mandatory!");
endif
// MANDATORY so disconnect since we couldn't find the service Bluefruit.disconnect(conn_handle); return; }
ifdef DEBUG
Serial.print("Discovering Client FTM Feature Characteristic ... ");
endif
// If FTM Feature is not found, disconnect, resume scanning, and return while (!( client_FTM_Feature_Chr.discover() )) { if ( client_FTM_Feature_Chr.discover() ) {
ifdef DEBUG
Serial.println("Found it!");
endif
// Read FTM Feature Data client_FTM_Feature_Chr.read(client_FTM_Feature_Data, 8);
ifdef DEBUG
Serial.print(" -> Client Reads Raw FTM Feature bytes: [8] [ "); for (int i = 0; i < sizeof(client_FTM_Feature_Data); i++) { Serial.printf("%02X ", client_FTM_Feature_Data[i], HEX); } // for Serial.println("] ");
endif
} else {
ifdef DEBUG
Serial.println("Disconnecting since Client FTM Feature Characteristic is mandatory!");
endif
// MANDATORY so disconnect since we couldn't find the service Bluefruit.disconnect(conn_handle); Bluefruit.Connection(conn_handle); Serial.print("Discovering Client FTM Feature not decouvert ... "); // return; } }
ifdef DEBUG
Serial.print("Discovering Client FTM Control Point Characteristic ... ");
endif
// If FTM Control Point is not found, disconnect, resume scanning, and return if ( client_FTM_ControlPoint_Chr.discover() ) {
ifdef DEBUG
Serial.println("Found it!");
endif
// Send a Request Control of Machine, OpCode == 0, no values! const uint8_t RCM[1] = {0}; client_FTM_ControlPoint_Chr.write_resp(RCM, 1); } else {
ifdef DEBUG
Serial.println("Not Found!"); Serial.println("Disconnecting since Client FTM Control Point Characteristic is mandatory!");
endif
// MANDATORY so disconnect since we couldn't find the service Bluefruit.disconnect(conn_handle); Bluefruit.Connection(conn_handle); Serial.print("Discovering Client FTM Feature not decouvert ... "); return; }
ifdef DEBUG
Serial.print("Discovering Client FTM Status Characteristic ... ");
endif
// If FTM Status is not found, disconnect, resume scanning, and return if ( client_FTM_Status_Chr.discover() ) {
ifdef DEBUG
Serial.println("Found it!");
endif
} else {
ifdef DEBUG
Serial.println("Not Found!"); Serial.println("Disconnecting since Client FTM Status Characteristic is mandatory!");
endif
// MANDATORY so disconnect since we couldn't find the service Bluefruit.disconnect(conn_handle); return; }
ifdef DEBUG
Serial.print("Discovering Client FTM Training Status Characteristic ... ");
endif
// FTM Training Status is NOT MANDATORY if ( client_FTM_TrainingStatus_Chr.discover() ) {
ifdef DEBUG
Serial.println("Found it!");
endif
} else {
ifdef DEBUG
Serial.println("Not Found! Not Mandatory");
endif
} /*
ifdef DEBUG
Serial.println("Not Found!"); Serial.println("Disconnecting since Client FTM Characteristic is mandatory!");
endif
// MANDATORY so disconnect since we couldn't find the service Bluefruit.disconnect(conn_handle); return; */
ifdef DEBUG
Serial.print("Discovering Client FTM Supported Resistance Level Range Characteristic ... ");
endif
// FTM SupportedResistanceLevelRange is not mandatory! if ( client_FTM_SupportedResistanceLevelRange_Chr.discover() ) {
ifdef DEBUG
Serial.println("Found it!");
endif
// Read Supported Resistance Level Range Data client_FTM_SupportedResistanceLevelRange_Chr.read(client_FTM_SupportedResistanceLevelRange_Data, 6);
ifdef DEBUG
Serial.print(" -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ "); for (int i = 0; i < sizeof(client_FTM_SupportedResistanceLevelRange_Data); i++) { Serial.printf("%02X ", client_FTM_SupportedResistanceLevelRange_Data[i], HEX); } // for Serial.println("] ");
endif
} else {
ifdef DEBUG
Serial.println("Not Found! NOT mandatory!");
endif
} / Serial.println("Disconnecting since Client FTM Supported Resistance Level Range Characteristic is mandatory!"); // MANDATORY so disconnect since we couldn't find the service Bluefruit.disconnect(conn_handle); return; /
ifdef DEBUG
Serial.print("Discovering Client FTM Supported Power Range Characteristic ... ");
endif
// FTM SupportedPowerRange is not mandatory! if ( client_FTM_SupportedPowerRange_Chr.discover() ) {
ifdef DEBUG
Serial.println("Found it!");
endif
// Read Supported Resistance Level Range values client_FTM_SupportedPowerRange_Chr.read(client_FTM_SupportedPowerRange_Data, 6);
ifdef DEBUG
Serial.print(" -> Client Reads Raw FTM Supported Power Range bytes: [6] [ "); for (int i = 0; i < sizeof(client_FTM_SupportedPowerRange_Data); i++) { Serial.printf("%02X ", client_FTM_SupportedPowerRange_Data[i], HEX); } // for Serial.println("] ");
endif
} else {
ifdef DEBUG
Serial.println("Not Found! NOT mandatory!");
endif
} /*
ifdef DEBUG
Serial.println("Disconnecting since Client FTM Supported Power Range Characteristic is mandatory!");
endif
// MANDATORY so disconnect since we couldn't find the service Bluefruit.disconnect(conn_handle); return; */
ifdef DEBUG
Serial.print("Discovering Client FTM Indoor Bike Data Characteristic ... ");
endif
// FTM Indoor Bike Data is not mandatory if ( client_FTM_IndoorBikeData_Chr.discover() ) {
ifdef DEBUG
Serial.println("Found it!");
endif
} else {
ifdef DEBUG
Serial.println("Not Found! Not Mandatory");
endif
} /*
ifdef DEBUG
Serial.println("Not Found!"); Serial.println("Disconnecting since Client FTM Indoor Bike Data Characteristic is mandatory!");
endif
// MANDATORY so disconnect since we couldn't find the service Bluefruit.disconnect(conn_handle); return;
/ // ---------------------------- End FTM SERVICE --------------------------------------------- // ---------------------------- CP SERVICE -------------------------------------------------- #ifdef DEBUG Serial.print("Discovering Client Cycling Power (CP) Service ... "); #endif // If CPS is not found, disconnect, resume scanning, and return while (!( client_CyclingPower_Service.discover(conn_handle) )) { if ( client_CyclingPower_Service.discover(conn_handle) ) { #ifdef DEBUG BLEConnection conn = Bluefruit.Connection(conn_handle); uint16_t max_payload = conn->getMtu()-3; uint16_t data_length = conn->getDataLength(); Serial.print("Found it! "); Serial.printf("CPS Max Payload: %d Data Length: %d\n", max_payload, data_length);
endif
} else {
ifdef DEBUG
Serial.println("Not Found!"); Serial.println("Disconnecting since Client Cyling Power Service is mandatory!");
endif
// MANDATORY so disconnect since we couldn't find the service Bluefruit.disconnect(conn_handle); Bluefruit.Connection(conn_handle); Serial.print("Discovering Cycling Power (CP) Service not decouvert ... "); return; } }
ifdef DEBUG
Serial.print("Discovering Client CP Measurement characteristic ... ");
endif
if ( !client_CP_Measurement_Chr.discover() ) { // Measurement chr is mandatory, if it is not found (valid), then disconnect
ifdef DEBUG
Serial.println("Not Found!"); Serial.println("Disconnecting since Client CP Measurement Characteristic is mandatory!");
endif
Bluefruit.disconnect(conn_handle); return; } else {
ifdef DEBUG
Serial.println("Found it!");
endif
}
ifdef DEBUG
Serial.print("Discovering Client CP Control Point characteristic ... ");
endif
if ( client_CP_ControlPoint_Chr.discover() ) { // CP Control Point chr is not mandatory
ifdef DEBUG
Serial.println("Found it!");
endif
} else {
ifdef DEBUG
Serial.println("Not Found! NOT Mandatory!");
endif
}
ifdef DEBUG
Serial.print("Discovering Client CP Feature characteristic ... ");
endif
if ( client_CP_Feature_Chr.discover() ) {
ifdef DEBUG
Serial.println("Found it!");
endif
// Configure the Cycle Power Feature characteristic // Properties = Read // Min Len = 1 // Max Len = 32 // B0:3 = UINT8 - Cycling Power Feature (MANDATORY) // b0 = Pedal power balance supported; 0 = false, 1 = true // b1 = Accumulated torque supported; 0 = false, 1 = true // b2 = Wheel revolution data supported; 0 = false, 1 = true // b3 = Crank revolution data supported; 0 = false, 1 = true // b4 = Extreme magnatudes supported; 0 = false, 1 = true // b5 = Extreme angles supported; 0 = false, 1 = true // b6 = Top/bottom dead angle supported; 0 = false, 1 = true // b7 = Accumulated energy supported; 0 = false, 1 = true // b8 = Offset compensation indicator supported; 0 = false, 1 = true // b9 = Offset compensation supported; 0 = false, 1 = true // b10 = Cycling power measurement characteristic content masking supported; 0 = false, 1 = true // b11 = Multiple sensor locations supported; 0 = false, 1 = true // b12 = Crank length adj. supported; 0 = false, 1 = true // b13 = Chain length adj. supported; 0 = false, 1 = true // b14 = Chain weight adj. supported; 0 = false, 1 = true // b15 = Span length adj. supported; 0 = false, 1 = true // b16 = Sensor measurement context; 0 = force, 1 = torque // b17 = Instantaineous measurement direction supported; 0 = false, 1 = true // b18 = Factory calibrated date supported; 0 = false, 1 = true // b19 = Enhanced offset compensation supported; 0 = false, 1 = true // b20:21 = Distribtue system support; 0 = legacy, 1 = not supported, 2 = supported, 3 = RFU // b22:32 = Reserved
// Read 32-bit client_CP_Feature_Chr value client_CP_Feature_Flags = client_CP_Feature_Chr.read32();
ifdef DEBUG
const uint8_t CPFC_FIXED_DATALEN = 4; uint8_t cpfcData[CPFC_FIXED_DATALEN] = {(uint8_t)(client_CP_Feature_Flags & 0xff), (uint8_t)(client_CP_Feature_Flags >> 8), (uint8_t)(client_CP_Feature_Flags >> 16), (uint8_t)(client_CP_Feature_Flags >> 24)}; Serial.print(" -> Client Reads Raw CP Feature bytes: [4] [ "); for (int i = 0; i < CPFC_FIXED_DATALEN; i++) { if ( i <= sizeof(cpfcData)) { Serial.printf("%02X ", cpfcData[i], HEX); } } Serial.println("] "); for (int i = 0; i < sizeof(client_CP_Feature_Str); i++) { if ( client_CP_Feature_Flags & (1 << i) ) { Serial.println(client_CP_Feature_Str[i]); } }
endif
} else {
ifdef DEBUG
Serial.println("NOT Found! NOT Mandatory!");
endif
}
ifdef DEBUG
Serial.print("Discovering Client CP Sensor Location characteristic ... ");
endif
if ( client_CP_Location_Chr.discover() ) {
ifdef DEBUG
Serial.println("Found it!");
endif
// The Sensor Location characteristic // Properties = Read // Min Len = 1 // Max Len = 1 // B0:1 = UINT8 - Sensor Location
// Read 8-bit client CP sensor location value client_CP_Location_Value = client_CP_Location_Chr.read8();
ifdef DEBUG
Serial.print(" -> Client Reads CP Location Sensor: "); Serial.printf("Loc#: %d %s\n", client_CP_Location_Value, client_Sensor_Location_Str[client_CP_Location_Value]);
endif
} else {
ifdef DEBUG
Serial.println("NOT Found! NOT Mandatory!");
endif
} // ---------------------------- END CP SERVICE
// ---------------------------- CSC SERVICE
ifdef DEBUG
Serial.print("Discovering Cycling Speed and Cadence (CSC) Service ... ");
endif
if ( client_CyclingSpeedCadence_Service.discover(conn_handle) ) // UUID16_SVC_CYCLING_SPEED_AND_CADENCE {
ifdef DEBUG
BLEConnection* conn = Bluefruit.Connection(conn_handle); uint16_t max_payload = conn->getMtu()-3; uint16_t data_length = conn->getDataLength(); Serial.print("Found it! "); Serial.printf("CSCS Max Payload: %d Data Length: %d\n", max_payload, data_length);
endif
} else {
ifdef DEBUG
Serial.println("Not Found! CSC Service is Not Mandatory!");
endif
return; // NO CSC -> end of client_connect_callback !! } /* // Is Mandatory
ifdef DEBUG
Serial.println("Not Found and disconnecting!"); Serial.println("CSC Service is mandatory!");
endif
Bluefruit.disconnect(conn_handle); return; */
// Test for client CSC Characteristics when the client CSC Service is existing
ifdef DEBUG
Serial.print("Discovering Client CSC Measurement CHR ... ");
endif
if ( client_CSC_Measurement_Chr.discover() ) // UUID16_CHR_CSC_MEASUREMENT {
ifdef DEBUG
Serial.println("Found it! ");
endif
} else {
ifdef DEBUG
Serial.println("Not Found! Not Mandatory!");
endif
} /* // Is Mandatory
ifdef DEBUG
Serial.println("Not Found!"); Serial.println("Disconnecting since Client CSC Measurement CHR is mandatory!");
endif
Bluefruit.disconnect(conn_handle); return; */
ifdef DEBUG
Serial.print("Discovering Client CSC Location CHR ... ");
endif
if ( client_CSC_Location_Chr.discover() ) // UUID16_CHR_SENSOR_LOCATION {
ifdef DEBUG
Serial.println("Found it!");
endif
// Read 16-bit client CSC sensor location value client_CSC_Location_Value = client_CSC_Location_Chr.read8();
ifdef DEBUG
Serial.print(" -> Client Reads CSC Location Sensor: "); Serial.printf("Loc#: %d %s\n", client_CSC_Location_Value, client_Sensor_Location_Str[client_CSC_Location_Value]);
endif
} else {
ifdef DEBUG
Serial.println("Not Found! NOT Mandatory!");
endif
}
ifdef DEBUG
Serial.print("Discovering Client CSC Feature CHR ... ");
endif
if ( client_CSC_Feature_Chr.discover() ) // UUID16_CHR_CSC_FEATURE {
ifdef DEBUG
Serial.println("Found it!");
endif
// Read sensor CSC Feature value in 16 bit client_CSC_Feature_Flags = client_CSC_Feature_Chr.read16();
ifdef DEBUG
uint8_t cscfcData[CSC_FEATURE_FIXED_DATALEN] = { (uint8_t)(client_CSC_Feature_Flags & 0xff), (uint8_t)(client_CSC_Feature_Flags >> 8) }; // Little Endian Representation Serial.printf(" -> Client Reads Raw CSC Feature bytes: [2] [ "); for (int i = 0; i < sizeof(cscfcData); i++) { Serial.printf("%02X ", cscfcData[i], HEX); } Serial.println("] "); for (int i = 0; i < sizeof(client_CSC_Feature_Str); i++) { if ( (client_CSC_Feature_Flags & (1 << i)) != 0 ) { Serial.println(client_CSC_Feature_Str[i]); } }
endif
} else {
ifdef DEBUG
Serial.println("Not Found! NOT Mandatory!");
endif
} // ---------------------------- END CSC SERVICE
// Only now set true after ALL Mandatory Services and Char's have been discovered !!! Trainer.IsConnected = true; } // End client_connect_callback
/* Callback invoked when a connection is dropped @param https://github.com/param conn_handle @param https://github.com/param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h / void client_disconnect_callback(uint16_t conn_handle, uint8_t reason) {
ifdef DEBUG
Serial.printf("Client disconnected from Peripheral Device: [%s], reason: [%02X]\n", Trainer.PeerName, reason, HEX);
endif
Trainer.conn_handle = BLE_CONN_HANDLE_INVALID; Trainer.IsConnected = false; // Force server to disconnect! if (Laptop.conn_handle != BLE_CONN_HANDLE_INVALID) { Bluefruit.disconnect(Laptop.conn_handle); } }
/** Hooked callback that triggered when a measurement value is sent from peripheral @param https://github.com/param chr Pointer client characteristic in this example it should be cpmc @param https://github.com/param data Pointer to received data @param https://github.com/param len Length of received data
/ void client_CP_Measurement_Chr_notify_callback(BLEClientCharacteristic chr, uint8_t* data, uint16_t len) { // Client CP Measurement data is tranferred to the Server (Zwift) // NO TREATMENT OF RESPONSE !!!!! if (server_CP_Measurement_Chr.notifyEnabled(Laptop.conn_handle)) { server_CP_Measurement_Chr.notify(data, len); // Just pass on and process later! }
ifdef DEBUG_CP_MEASUREMENT
uint8_t buffer[len] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw CP Data: [%d] [ ", len); for (int i = 0; i < sizeof(buffer); i++) { if ( i <= sizeof(buffer)) { buffer[i] = *data++; Serial.printf("%02X ", buffer[i], HEX); } } Serial.print("] "); uint8_t offset = 0; // Get flags field uint16_t flags = 0; memcpy(&flags, &buffer[offset], 2); // Transfer buffer fields to variable offset += 2; // UINT16 // Get Instantaneous Power values UINT16 uint16_t PowerValue = 0; memcpy(&PowerValue, &buffer[offset], 2); // Transfer buffer fields to variable offset += 2; // UINT16 Serial.printf("Instantaneous Power: %4d\n", PowerValue); // Get the other CP measurement values if ((flags & 1) != 0) { // Power Balance Present Serial.print(" --> Pedal Power Balance!"); } if ((flags & 2) != 0) { // Accumulated Torque Serial.println(" --> Accumulated Torque!"); } // etcetera...
endif
} // End cpmc_notify_callback
/** Hooked callback that triggered when a response value is sent from peripheral @param https://github.com/param chr Pointer client characteristic @param https://github.com/param data Pointer to received data @param https://github.com/param len Length of received data
/ void client_CP_ControlPoint_Chr_indicate_callback(BLEClientCharacteristic chr, uint8_t* data, uint16_t len) { // Send Client's response message to the Server (Zwift) // NO TREATMENT OF RESPONSE !!!!! server_CP_ControlPoint_Chr.indicate(data, len); // Just pass on and process later!
ifdef DEBUG
uint8_t cpcpDataLen = (uint8_t)len; uint8_t cpcpData[cpcpDataLen] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw CP Control Point Data: [%d] [ ", len); for (int i = 0; i < sizeof(cpcpData); i++) { cpcpData[i] = *data++; Serial.printf("%02X ", cpcpData[i], HEX); } Serial.print("] ");
endif
}
/** Hooked callback that triggered when a measurement value is sent from peripheral @param https://github.com/param chr Pointer client characteristic @param https://github.com/param data Pointer to received data @param https://github.com/param len Length of received data
/ void client_CSC_Measurement_Chr_notify_callback(BLEClientCharacteristic chr, uint8_t* data, uint16_t len) { // Client CSC Measurement data is transferred to the Server (Zwift) // NO TREATMENT OF RESPONSE !!!!! if (server_CSC_Measurement_Chr.notifyEnabled(Laptop.conn_handle)) { server_CSC_Measurement_Chr.notify(data, len); // Just pass on and process later! }
ifdef DEBUG_CSC_MEASUREMENT
uint8_t buffer[len] = {}; // Transfer first the contents of data to buffer (array of chars) Serial.printf(" -> Client Rec'd Raw CSC Data: [%d] [ ", len); for (int i = 0; i < sizeof(buffer); i++) { if ( i <= sizeof(buffer)) { buffer[i] = *data++; Serial.printf("%02X ", buffer[i], HEX); } } Serial.print("] "); uint8_t offset = 0; // we define the offset that is to be used when reading the next field // Size of variables (e.g. 2 (16) or 4 bytes (32)) are constants in BluetoothGattCharacteristic // these represent the values you can find in the "Value Fields" table in the "Format" column // Read the Flags field at buffer[0] uint8_t flags = buffer[offset]; offset += 1; // UINT8 // we have to check the flags' nth bit to see if C1 field exists if ((flags & 1) != 0) { uint32_t cum_wheel_rev = 0; memcpy(&cum_wheel_rev, &buffer[offset], 4); offset += 4; // UINT32 uint16_t last_wheel_event = 0; memcpy(&last_wheel_event, &buffer[offset], 2); offset += 2; // UINT16 Serial.printf(" Cum. wheel rev.: %d Last wheel event: %d ", cum_wheel_rev, last_wheel_event); } // we have to check the flags' nth bit to see if C2 field exists if ((flags & 2) != 0) { uint16_t cum_cranks = 0; memcpy(&cum_cranks, &buffer[offset], 2); offset += 2; // UINT16 uint16_t last_crank_event = 0; memcpy(&last_crank_event, &buffer[offset], 2); offset += 2; // UINT16 Serial.printf(" Cum cranks: %d Last crank event: %d", cum_cranks, last_crank_event); } Serial.println();
endif
} // ---------------------- END of CLIENT SIDE FUNCTIONS
// ---------------------- START of SERVER SIDE FUNCTIONS
void server_setupNUS(void) { server_NordicUart_Service.begin(); // Add NUS TXD Characteristic server_NUS_TXD_Chr.setProperties(CHR_PROPS_NOTIFY); // Type "notify" server_NUS_TXD_Chr.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // readAccess, NO writeAccess server_NUS_TXD_Chr.setMaxLen(MAX_PAYLOAD); // To be on the safe side! server_NUS_TXD_Chr.setCccdWriteCallback(server_cccd_callback); // Optionally capture CCCD updates server_NUS_TXD_Chr.begin();
// Add NUS RXD Characteristic server_NUS_RXD_Chr.setProperties(CHR_PROPS_WRITE | CHR_PROPS_WRITE_WO_RESP); // Write with No response !! server_NUS_RXD_Chr.setPermission(SECMODE_NO_ACCESS, SECMODE_OPEN); server_NUS_RXD_Chr.setMaxLen(MAX_PAYLOAD); // Maxlen server_NUS_RXD_Chr.setWriteCallback(server_NUS_RXD_Chr_callback); server_NUS_RXD_Chr.begin(); }
void server_NUS_RXD_Chr_callback(uint16_t conn_hdl, BLECharacteristic chr, uint8_t data, uint16_t len) { // Read data received over NUS RXD from Mobile Phone
ifdef DEBUG
uint8_t NusRxdDataLen = (uint8_t)len; // Get the actual length of data bytes and type cast to (uint8_t) char NusRxdData[MAX_PAYLOAD + 1]; // Data is all ASCII ! memset(NusRxdData, 0, MAX_PAYLOAD); // set to zero if (NusRxdDataLen > MAX_PAYLOAD) { NusRxdDataLen = MAX_PAYLOAD; // Check for limit } memcpy(NusRxdData, data, NusRxdDataLen); // Transfer data to char array // Display the raw packet data in actual length Serial.printf(" -> Server NUS RXD Data [%d][%s]\n", NusRxdDataLen, NusRxdData);
endif
}
void Construct_Dev_Name(void) { const char prefix[] = {'S', 'i'
Dear Joel, With respect to FTMS_Zwift_Bridge: You inserted several While loops (in client_connect_callback): No doubt that you also have seen that these have negative (side-)effects, GA- and DIS readings are missed -> No manufacturer name, model number, et cetera. --> consequence later: empty variables:
18:15:44.315 -> Setting Server Device Name to: [Sim ] 18:15:44.315 -> Setting Server Appearance to: [0]
I do not see for example the trainer send IndoorBikeData to Zwift as a response to the resistance parameter settings..... nor a different output as we have seen before... My conclusion is: I am sorry but I do not see any improvement in the output/behavior, with some While loops, on the contrary. Next time just run the original uploaded FTMS Zwift Bridge version 023.
I am still missing the test of the latest uploaded FTMS_Client v027 (please without you inserting extra while loops).
Keep faith, somehow we will tackle the Hub connection problem! Beste wishes, Jörgen.
Dear Jörghen,
Here is the disappointing result.
The problem is still the same no feedback with V0.27
Let's not lose heart!
123456789101112131415161718192021 /***** This is programming code for the nRF52 based Bluefruit BLE boards
The code uses heavily the Adafruit supplied Bluefruit BLE libraries !! Adafruit invests time and resources providing open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
MIT license, check LICENSE for more information All text must be included in any redistribution
Message (Enter to send message to 'Adafruit ItsyBitsy nRF52840 Express' on 'COM11') New Line 115200 baud 16:59:01.080 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 16:59:01.080 -> ----------------- Version 02.7 ------------------ 16:59:01.080 -> Initialise the Bluefruit nRF52 module: Client (Central) 16:59:01.205 -> FTMS and Chars 'initialized' 16:59:01.205 -> CPS and Chars 'initialized' 16:59:01.205 -> CSCS and Chars 'initialized' 16:59:01.205 -> GA and Chars 'initialized' 16:59:01.205 -> DIS and Chars 'initialized' 16:59:01.205 -> Start Scanning for CPS, CSC and FTMS! 16:59:01.434 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 16:59:01.434 -> Timestamp MAC Address Rssi Data 16:59:01.434 -> 000091471 F8:9C:FC:53:5E:49 -59 09-02-16-18-26-18-18-18-0A-18 16:59:01.575 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 16:59:01.575 -> Now checking all Client Services and Characteristics! 16:59:01.575 -> If Mandatory Services Fail --> the Client will disconnect! 16:59:01.575 -> First checking Generic Access and Device Information Services and Characteristics! 16:59:01.668 -> Found Client Generic Access 16:59:01.808 -> -> Client Reads Device Name: [Zwift Hub] 16:59:02.042 -> -> Client Reads Appearance: [0] 16:59:02.042 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Not Found! 16:59:02.042 -> Disconnecting since Client FTM Service is mandatory! 16:59:02.121 -> Client Disconnected, reason = 0x16 16:59:02.121 -> >>> Restart the Feather nRF52 Client for a new run! <<< 16:59:12.257 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 16:59:12.257 -> ----------------- Version 02.7 ------------------ 16:59:12.257 -> Initialise the Bluefruit nRF52 module: Client (Central) 16:59:12.257 -> FTMS and Chars 'initialized' 16:59:12.257 -> CPS and Chars 'initialized' 16:59:12.257 -> CSCS and Chars 'initialized' 16:59:12.257 -> GA and Chars 'initialized' 16:59:12.257 -> DIS and Chars 'initialized' 16:59:12.257 -> Start Scanning for CPS, CSC and FTMS! 16:59:12.258 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 16:59:12.258 -> Timestamp MAC Address Rssi Data 16:59:12.258 -> 000001100 F8:9C:FC:53:5E:49 -55 09-02-16-18-26-18-18-18-0A-18 16:59:12.258 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 16:59:12.258 -> Now checking all Client Services and Characteristics! 16:59:12.258 -> If Mandatory Services Fail --> the Client will disconnect! 16:59:12.258 -> First checking Generic Access and Device Information Services and Characteristics! 16:59:12.266 -> Found Client Generic Access 16:59:12.266 -> -> Client Reads Device Name: [Zwift Hub] 16:59:12.266 -> -> Client Reads Appearance: [1152] 16:59:12.266 -> Found Client Device Information 16:59:12.266 -> -> Client Reads Manufacturer: [Zwift]
Here is the result of FTMS_Zwift_Bridge_v023:
17:15:10.800 -> Feather nRF52840 MITM supporting: CPS, CSC and FTMS 17:15:10.800 -> ------------------ Version 02.3 --------------------- 17:15:10.804 -> FTM Service and Chars are 'initialized' 17:15:10.804 -> CP Service and Chars are 'initialized' 17:15:10.804 -> CSC Service and Chars are 'initialized' 17:15:10.804 -> Generic Access Service and Chars are 'initialized' 17:15:10.804 -> Device Information Service and Chars are 'initialized' 17:15:10.804 -> Start Client-side Scanning for CPS, CSC and FTMS! 17:15:10.805 -> Found advertising Peripheral with FTMS enabled! See Raw data packet: 17:15:10.805 -> Timestamp Addr Rssi Data 17:15:10.805 -> 000001606 F8:9C:FC:53:5E:49 -55 09-02-16-18-26-18-18-18-0A-18 17:15:10.805 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:15:10.805 -> Now checking all mandatory Client Services and Characteristics! 17:15:10.805 -> If Mandatory Services Fail --> the Client will disconnect! 17:15:10.805 -> First checking Generic Access and Device Information Services and Characteristics! 17:15:10.828 -> Found Client Generic Access 17:15:10.828 -> -> Client Reads Device Name: [Zwift Hub] 17:15:10.828 -> -> Client Reads Appearance: [1152] 17:15:10.828 -> Found Client Device Information 17:15:10.828 -> -> Client Reads Manufacturer: [Zwift] 17:15:10.829 -> -> Client Reads Model Number: [06] 17:15:10.920 -> -> Client Reads Serial Number: [06-F89CFC535E49] 17:15:10.920 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 17:15:11.008 -> Discovering Client FTM Feature Characteristic ... Found it! 17:15:11.124 -> -> Client Reads Raw FTM Feature bytes: [8] [ 87 44 00 00 0C E0 00 00 ] 17:15:11.124 -> Discovering Client FTM Control Point Characteristic ... Found it! 17:15:11.703 -> Discovering Client FTM Status Characteristic ... Found it! 17:15:11.984 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 17:15:12.285 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 17:15:12.402 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 17:15:12.402 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 17:15:12.742 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 00 00 00 00 ] 17:15:12.742 -> Discovering Client FTM Indoor Bike Data Characteristic ... Not Found! Not Mandatory 17:15:12.742 -> Discovering Client Cycling Power (CP) Service ... Not Found! 17:15:12.742 -> Disconnecting since Client Cyling Power Service is mandatory! 17:15:12.834 -> Client disconnected from Peripheral Device: [Zwift Hub], reason: [16] 17:15:27.560 -> Feather nRF52840 MITM supporting: CPS, CSC and FTMS 17:15:27.560 -> ------------------ Version 02.3 --------------------- 17:15:27.822 -> FTM Service and Chars are 'initialized' 17:15:27.822 -> CP Service and Chars are 'initialized' 17:15:27.822 -> CSC Service and Chars are 'initialized' 17:15:27.822 -> Generic Access Service and Chars are 'initialized' 17:15:27.822 -> Device Information Service and Chars are 'initialized' 17:15:27.822 -> Start Client-side Scanning for CPS, CSC and FTMS! 17:15:27.836 -> Found advertising Peripheral with FTMS enabled! See Raw data packet: 17:15:27.836 -> Timestamp Addr Rssi Data 17:15:27.836 -> 000001270 F8:9C:FC:53:5E:49 -60 09-02-16-18-26-18-18-18-0A-18 17:15:27.836 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:15:27.836 -> Now checking all mandatory Client Services and Characteristics! 17:15:27.836 -> If Mandatory Services Fail --> the Client will disconnect! 17:15:27.836 -> First checking Generic Access and Device Information Services and Characteristics!
Dear Joel, I think we should first exclude an unexpected behavior/contribution/interference of ItsyBitsy before we undertake new test actions. A failing ItsyBitsy would be the simple explanation but I do not expect it to be that easy!
I find the results very unpredictable and that bothers me most! So I have to ask the question: are the circumstances/procedures every test exactly the same? Could you give me a complete summary of what your procedure is step by step? Please also include when devices are switched on and or reset and what apps are active (like nRF Connect, Zwift, Rouvy, ESP32 boards...) that have access to BLE and might (in theory) connect over BLE..., when in time do you wake up the trainer and when are you moving the pedals on the trainer... The last run shows FTMS to be discovered and Cycling Power of the same device is not..? Can there be a device (smartphone) that auto connects to CP in the meantime, it is very unlikely that only FTMS is exposed and CP NOT? Unless the connection process is completely disturbed by an (un)known agent or CP is simply occupied by another device I find the results unimaginably. I have made so many BLE applications (with so many different devices) and I never came across such erratic behavior. Never a Char-discovery ever failed unless it was simply NOT implemented on the other side (device)...? No way that one had to pull it in a While loop... call it and you get the answer: yes the Char/SVC is there or not!
By the way what is this:
Message (Enter to send message to 'Adafruit ItsyBitsy nRF52840 Express' on 'COM11')
Where does it come from? Do you use some special application on the PC other than Arduino IDE and the regular Serial Monitor on com# to fill the screen? Regards, Jörgen.
Hello Jorghen,
This comes from the Arduino IDE 2.0, no doubt that I copied it with the rest before pasting it.
I received the Feather just now I resume all the tests with and more detail !!
Daar Joël, Fingers crossed.... I have found my decoding misunderstanding in the IBData... so when we will be able to convince Zwift Hub to send those data, at least it is decoded correctly and your HBM will be zero!😉 Good luck! Jörgen
Op vr 16 dec. 2022 16:06 schreef le-joebar @.***>:
Hello Jorghen,
This comes from the Arduino IDE 2.0, no doubt that I copied it with the rest before pasting it.
I received the Feather just now I resume all the tests with and more detail !!
— Reply to this email directly, view it on GitHub https://github.com/Berg0162/simcline/issues/7#issuecomment-1355027051, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANS5LSVSCA5ZCIPA53RQJHDWNSAQVANCNFSM6AAAAAASZDERFE . You are receiving this because you authored the thread.Message ID: @.***>
Dear Jörgen,
I redid all the tests with the feather nRF52840. from V22 to 27.
There is no Bluetooth (Watch, Gsm, Google nest) active nearby. The only thing I hadn't thought of before was my desktop's USB dongle for my mouse. So I removed it and started all over again without it!
I did a Scan with nRFConnect There is no device found, no server and then I turned off my mobile
All tests were done twice with the same version.
-1 turn on the trainer and then turn on the FTMS. -2 Switch on the FTMS and then train it.
I do not pedal to wake up because on Zwift with the Bluethoot USB dongle it is not necessary for him to discover the services. Likewise on an ESP program that I showed you; the services are present just when the trainer is switched on.
17:13:06.265 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 17:13:06.265 -> ----------------- Version 02.2 ------------------ 17:13:06.265 -> Initialise the Bluefruit nRF52 module: Client (Central) 17:13:06.265 -> FTMS and Chars 'initialized' 17:13:06.265 -> CPS and Chars 'initialized' 17:13:06.265 -> CSCS and Chars 'initialized' 17:13:06.265 -> GA and Chars 'initialized' 17:13:06.265 -> DIS and Chars 'initialized' 17:13:06.265 -> Start Scanning for CPS, CSC and FTMS! 17:13:06.266 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 17:13:06.266 -> Timestamp MAC Address Rssi Data 17:13:06.266 -> 000001249 F8:9C:FC:53:5E:49 -54 09-02-16-18-26-18-18-18-0A-18 17:13:07.123 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:13:07.123 -> Now checking mandatory Client Services and Characteristics! 17:13:07.123 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 17:13:07.124 -> Discovering Client CP Measurement characteristic ... Found it! 17:13:07.124 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 17:13:07.133 -> Discovering Client CP Feature characteristic ... Found it! 17:13:07.285 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 17:13:07.285 -> Wheel revolution data supported 17:13:07.285 -> Crank revolution data supported 17:13:07.285 -> Discovering Client CP Sensor Location characteristic ... Found it! 17:13:07.469 -> -> Client Reads CP Location Sensor: Loc#: 12 Rear wheel 17:13:07.469 -> Discovering Cycling Speed and Cadence (CSC) Service ... Found it! CSCS Max Payload: 20 Data Length: 27 17:13:07.533 -> Discovering Client CSC Measurement CHR ... Found it! 17:13:07.905 -> Discovering Client CSC Location CHR ... Found it! 17:13:07.905 -> -> Client Reads CSC Location Sensor: Loc#: 0 Other 17:13:07.905 -> Discovering Client CSC Feature CHR ... Not Found! NOT Mandatory! 17:13:07.905 -> Discovering Client Fitness Machine (FTM) Service ... Not Found! 17:13:07.905 -> Disconnecting since Client FTM Service is mandatory! 17:13:08.074 -> Client Disconnected, reason = 0x16 17:13:08.074 -> >>> Restart the Feather nRF52 Client for a new run! <<< 17:13:08.818 -> >>> Couldn't enable notify for Client CP Measurement Characteristic. 17:13:08.818 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 17:13:08.818 -> >>> Couldn't enable notify for Client CSC Measurement Characteristic. 17:13:08.818 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 17:13:08.818 -> FTMS (trainer) is controlled by another Client (Training App)! 17:13:08.818 -> Client (Central) is Up and Running!
17:13:52.954 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 17:13:52.954 -> ----------------- Version 02.2 ------------------ 17:13:52.954 -> Initialise the Bluefruit nRF52 module: Client (Central) 17:13:52.954 -> FTMS and Chars 'initialized' 17:13:52.954 -> CPS and Chars 'initialized' 17:13:52.954 -> CSCS and Chars 'initialized' 17:13:52.954 -> GA and Chars 'initialized' 17:13:52.954 -> DIS and Chars 'initialized' 17:13:52.954 -> Start Scanning for CPS, CSC and FTMS! 17:14:04.080 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 17:14:04.080 -> Timestamp MAC Address Rssi Data 17:14:04.080 -> 000012677 F8:9C:FC:53:5E:49 -51 09-02-16-18-26-18-18-18-0A-18 17:14:04.205 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:14:04.205 -> Now checking mandatory Client Services and Characteristics! 17:14:04.205 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 17:14:04.330 -> Discovering Client CP Measurement characteristic ... Found it! 17:14:04.794 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 17:14:04.963 -> Discovering Client CP Feature characteristic ... Found it! 17:14:05.147 -> -> Client Reads Raw CP Feature bytes: [4] [ 00 00 00 00 ] 17:14:05.147 -> Discovering Client CP Sensor Location characteristic ... NOT Found! NOT Mandatory! 17:14:05.147 -> Discovering Cycling Speed and Cadence (CSC) Service ... Not Found and disconnecting! 17:14:05.147 -> CSC Service is mandatory! 17:14:05.239 -> Client Disconnected, reason = 0x16 17:14:05.239 -> >>> Restart the Feather nRF52 Client for a new run! <<< 17:14:06.639 -> >>> Couldn't enable notify for Client CP Measurement Characteristic. 17:14:06.639 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 17:14:06.639 -> >>> Couldn't enable notify for Client CSC Measurement Characteristic. 17:14:06.639 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 17:14:06.639 -> FTMS (trainer) is controlled by another Client (Training App)! 17:14:06.639 -> Client (Central) is Up and Running!
17:18:37.912 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 17:18:37.912 -> ----------------- Version 02.3 ------------------ 17:18:37.912 -> Initialise the Bluefruit nRF52 module: Client (Central) 17:18:37.913 -> FTMS and Chars 'initialized' 17:18:37.913 -> CPS and Chars 'initialized' 17:18:37.913 -> CSCS and Chars 'initialized' 17:18:37.913 -> GA and Chars 'initialized' 17:18:37.913 -> DIS and Chars 'initialized' 17:18:37.913 -> Start Scanning for CPS, CSC and FTMS! 17:18:37.937 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 17:18:37.937 -> Timestamp MAC Address Rssi Data 17:18:37.937 -> 000001832 F8:9C:FC:53:5E:49 -51 09-02-16-18-26-18-18-18-0A-18 17:18:37.939 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:18:37.939 -> Now checking mandatory Client Services and Characteristics! 17:18:37.939 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 17:18:38.075 -> Discovering Client CP Measurement characteristic ... Found it! 17:18:38.376 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 17:18:38.547 -> Discovering Client CP Feature characteristic ... Found it! 17:18:38.702 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 17:18:38.702 -> Wheel revolution data supported 17:18:38.702 -> Crank revolution data supported 17:18:38.702 -> Discovering Client CP Sensor Location characteristic ... Found it! 17:18:38.872 -> -> Client Reads CP Location Sensor: Loc#: 0 Other 17:18:38.872 -> Discovering Cycling Speed and Cadence (CSC) Service ... Not Found and disconnecting! 17:18:38.872 -> CSC Service is mandatory! 17:18:39.057 -> Client Disconnected, reason = 0x16 17:18:39.057 -> >>> Restart the Feather nRF52 Client for a new run! <<< 17:18:40.313 -> Stopped!
17:20:02.831 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 17:20:02.831 -> ----------------- Version 02.3 ------------------ 17:20:02.831 -> Initialise the Bluefruit nRF52 module: Client (Central) 17:20:02.831 -> FTMS and Chars 'initialized' 17:20:02.831 -> CPS and Chars 'initialized' 17:20:02.831 -> CSCS and Chars 'initialized' 17:20:02.831 -> GA and Chars 'initialized' 17:20:02.831 -> DIS and Chars 'initialized' 17:20:02.831 -> Start Scanning for CPS, CSC and FTMS! 17:20:09.489 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 17:20:09.489 -> Timestamp MAC Address Rssi Data 17:20:09.489 -> 000008794 F8:9C:FC:53:5E:49 -60 09-02-16-18-26-18-18-18-0A-18 17:20:09.722 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:20:09.722 -> Now checking mandatory Client Services and Characteristics! 17:20:09.722 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 17:20:09.956 -> Discovering Client CP Measurement characteristic ... Found it! 17:20:10.142 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 17:20:10.331 -> Discovering Client CP Feature characteristic ... Found it! 17:20:10.502 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 17:20:10.502 -> Wheel revolution data supported 17:20:10.502 -> Crank revolution data supported 17:20:10.502 -> Discovering Client CP Sensor Location characteristic ... Found it! 17:20:10.721 -> -> Client Reads CP Location Sensor: Loc#: 12 Rear wheel 17:20:10.721 -> Discovering Cycling Speed and Cadence (CSC) Service ... Found it! CSCS Max Payload: 20 Data Length: 27 17:20:10.935 -> Discovering Client CSC Measurement CHR ... Found it! 17:20:11.265 -> Discovering Client CSC Location CHR ... Found it! 17:20:11.265 -> -> Client Reads CSC Location Sensor: Loc#: 12 Rear wheel 17:20:11.265 -> Discovering Client CSC Feature CHR ... Found it! 17:20:11.452 -> -> Client Reads Raw CSC Feature bytes: [2] [ 00 00 ] 17:20:11.452 -> Discovering Client Fitness Machine (FTM) Service ... Not Found! 17:20:11.452 -> Disconnecting since Client FTM Service is mandatory! 17:20:11.547 -> Client Disconnected, reason = 0x16 17:20:11.547 -> >>> Restart the Feather nRF52 Client for a new run! <<< 17:20:12.140 -> Stopped!
17:21:55.142 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 17:21:55.142 -> ----------------- Version 02.4 ------------------ 17:21:55.142 -> Initialise the Bluefruit nRF52 module: Client (Central) 17:21:55.142 -> FTMS and Chars 'initialized' 17:21:55.142 -> CPS and Chars 'initialized' 17:21:55.142 -> CSCS and Chars 'initialized' 17:21:55.142 -> GA and Chars 'initialized' 17:21:55.142 -> DIS and Chars 'initialized' 17:21:55.142 -> Start Scanning for CPS, CSC and FTMS! 17:21:55.142 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 17:21:55.142 -> Timestamp MAC Address Rssi Data 17:21:55.142 -> 000001279 F8:9C:FC:53:5E:49 -54 09-02-16-18-26-18-18-18-0A-18 17:21:55.142 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:21:55.142 -> Now checking all Client Services and Characteristics! 17:21:55.142 -> If Mandatory Services Fail --> the Client will disconnect! 17:21:55.142 -> First checking Generic Access and Device Information Services and Characteristics! 17:21:55.143 -> Found Client Generic Access 17:21:55.143 -> -> Client Reads Device Name: [Zwift Hub] 17:21:55.174 -> -> Client Reads Appearance: [1152] 17:21:55.174 -> Found Client Device Information 17:21:55.753 -> -> Client Reads Manufacturer: [Zwift] 17:21:55.753 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Not Found! 17:21:55.753 -> Disconnecting since Client FTM Service is mandatory! 17:21:55.800 -> Client Disconnected, reason = 0x16 17:21:55.801 -> >>> Restart the Feather nRF52 Client for a new run! <<< 17:21:56.993 -> Stopped!
17:22:57.468 -> ----------------- Version 02.4 ------------------ 17:22:57.468 -> Initialise the Bluefruit nRF52 module: Client (Central) 17:22:58.154 -> FTMS and Chars 'initialized' 17:22:58.154 -> CPS and Chars 'initialized' 17:22:58.154 -> CSCS and Chars 'initialized' 17:22:58.154 -> GA and Chars 'initialized' 17:22:58.154 -> DIS and Chars 'initialized' 17:22:58.154 -> Start Scanning for CPS, CSC and FTMS! 17:23:04.954 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 17:23:04.954 -> Timestamp MAC Address Rssi Data 17:23:04.954 -> 000008494 F8:9C:FC:53:5E:49 -52 09-02-16-18-26-18-18-18-0A-18 17:23:05.310 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:23:05.310 -> Now checking all Client Services and Characteristics! 17:23:05.310 -> If Mandatory Services Fail --> the Client will disconnect! 17:23:05.310 -> First checking Generic Access and Device Information Services and Characteristics! 17:23:05.495 -> Found Client Generic Access 17:23:05.495 -> -> Client Reads Device Name: [Zwift Hub] 17:23:05.713 -> -> Client Reads Appearance: [1152] 17:23:05.713 -> Found Client Device Information 17:23:06.067 -> -> Client Reads Manufacturer: [Zwift] 17:23:06.067 -> -> Client Reads Model Number: [06] 17:23:06.207 -> -> Client Reads Serial Number: [06-F89CFC535E49] 17:23:06.207 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 17:23:06.468 -> Discovering Client FTM Feature Characteristic ... Found it! 17:23:06.653 -> -> Client Reads Raw FTM Feature bytes: [8] [ 87 44 00 00 0C E0 00 00 ] 17:23:06.653 -> Discovering Client FTM Training Status Characteristic ... Not Found! 17:23:07.030 -> Disconnecting since Client FTM Characteristic is mandatory! 17:23:07.062 -> Client Disconnected, reason = 0x16 17:23:07.062 -> >>> Restart the Feather nRF52 Client for a new run! <<< 17:23:07.695 -> Stopped!
17:25:53.099 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 17:25:53.099 -> ----------------- Version 02.5 ------------------ 17:25:53.099 -> Initialise the Bluefruit nRF52 module: Client (Central) 17:25:53.099 -> FTMS and Chars 'initialized' 17:25:53.099 -> CPS and Chars 'initialized' 17:25:53.099 -> CSCS and Chars 'initialized' 17:25:53.099 -> GA and Chars 'initialized' 17:25:53.099 -> DIS and Chars 'initialized' 17:25:53.099 -> Start Scanning for CPS, CSC and FTMS! 17:25:53.099 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 17:25:53.099 -> Timestamp MAC Address Rssi Data 17:25:53.099 -> 000001091 F8:9C:FC:53:5E:49 -56 09-02-16-18-26-18-18-18-0A-18 17:25:53.099 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:25:53.099 -> Now checking all Client Services and Characteristics! 17:25:53.099 -> If Mandatory Services Fail --> the Client will disconnect! 17:25:53.099 -> First checking Generic Access and Device Information Services and Characteristics! 17:25:53.325 -> Found Client Generic Access 17:25:53.325 -> -> Client Reads Device Name: [Zwift Hub] 17:25:53.666 -> -> Client Reads Appearance: [1152] 17:25:53.666 -> Found Client Device Information 17:25:54.036 -> -> Client Reads Manufacturer: [Zwift] 17:25:54.036 -> -> Client Reads Model Number: [06] 17:25:54.345 -> -> Client Reads Serial Number: [06-F89CFC535E49] 17:25:54.345 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 17:25:54.484 -> Discovering Client FTM Feature Characteristic ... Found it! 17:25:54.623 -> -> Client Reads Raw FTM Feature bytes: [8] [ 87 44 00 00 0C E0 00 00 ] 17:25:54.623 -> Discovering Client FTM Control Point Characteristic ... Found it! 17:25:54.982 -> Discovering Client FTM Status Characteristic ... Ready to receive Client FTM Control Point Response Messages 17:25:54.982 -> >>> Couldn't enable notify for Client FTM Status Characteristic. 17:25:54.982 -> FTMS (trainer) is controlled by another Client (Training App)! 17:25:54.982 -> Client (Central) is Up and Running! 17:25:55.058 -> Found it! 17:25:55.058 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 17:25:55.058 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Not Found! NOT mandatory! 17:25:55.058 -> Discovering Client FTM Supported Power Range Characteristic ... Not Found! NOT mandatory! 17:25:55.058 -> Discovering Client FTM Indoor Bike Data Characteristic ... Not Found! Not Mandatory 17:25:55.058 -> Discovering Client Cycling Power (CP) Service ... Not Found! 17:25:55.058 -> Disconnecting since Client Cyling Power Service is mandatory! 17:25:55.058 -> Client Disconnected, reason = 0x16 17:25:55.058 -> >>> Restart the Feather nRF52 Client for a new run! <<<
17:26:41.726 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 17:26:41.726 -> ----------------- Version 02.5 ------------------ 17:26:41.726 -> Initialise the Bluefruit nRF52 module: Client (Central) 17:26:41.726 -> FTMS and Chars 'initialized' 17:26:41.726 -> CPS and Chars 'initialized' 17:26:41.726 -> CSCS and Chars 'initialized' 17:26:41.726 -> GA and Chars 'initialized' 17:26:41.726 -> DIS and Chars 'initialized' 17:26:41.726 -> Start Scanning for CPS, CSC and FTMS! 17:26:48.666 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 17:26:48.666 -> Timestamp MAC Address Rssi Data 17:26:48.666 -> 000008960 F8:9C:FC:53:5E:49 -57 09-02-16-18-26-18-18-18-0A-18 17:26:49.019 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:26:49.019 -> Now checking all Client Services and Characteristics! 17:26:49.019 -> If Mandatory Services Fail --> the Client will disconnect! 17:26:49.019 -> First checking Generic Access and Device Information Services and Characteristics! 17:26:49.376 -> Found Client Generic Access 17:26:49.376 -> -> Client Reads Device Name: [Zwift Hub] 17:26:49.732 -> -> Client Reads Appearance: [1152] 17:26:49.732 -> Found Client Device Information 17:26:50.007 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Not Found! 17:26:50.007 -> Disconnecting since Client FTM Service is mandatory! 17:26:50.101 -> Client Disconnected, reason = 0x16 17:26:50.101 -> >>> Restart the Feather nRF52 Client for a new run! <<< 17:26:51.400 -> Stopped!
17:29:23.561 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 17:29:23.561 -> ----------------- Version 02.6 ------------------ 17:29:23.561 -> Initialise the Bluefruit nRF52 module: Client (Central) 17:29:24.053 -> FTMS and Chars 'initialized' 17:29:24.053 -> CPS and Chars 'initialized' 17:29:24.053 -> CSCS and Chars 'initialized' 17:29:24.053 -> GA and Chars 'initialized' 17:29:24.053 -> DIS and Chars 'initialized' 17:29:24.053 -> Start Scanning for CPS, CSC and FTMS! 17:29:24.053 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 17:29:24.053 -> Timestamp MAC Address Rssi Data 17:29:24.053 -> 000000990 F8:9C:FC:53:5E:49 -58 09-02-16-18-26-18-18-18-0A-18 17:29:24.058 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:29:24.058 -> Now checking all Client Services and Characteristics! 17:29:24.058 -> If Mandatory Services Fail --> the Client will disconnect! 17:29:24.058 -> First checking Generic Access and Device Information Services and Characteristics! 17:29:24.058 -> Found Client Generic Access 17:29:24.284 -> -> Client Reads Device Name: [Zwift Hub] 17:29:24.469 -> -> Client Reads Appearance: [1152] 17:29:24.516 -> Found Client Device Information 17:29:24.736 -> -> Client Reads Manufacturer: [Zwift] 17:29:24.968 -> -> Client Reads Model Number: [06] 17:29:25.139 -> -> Client Reads Serial Number: [06-F89CFC535E49] 17:29:25.139 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 17:29:25.264 -> Discovering Client FTM Feature Characteristic ... Found it! 17:29:25.576 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 17:29:25.576 -> Discovering Client FTM Control Point Characteristic ... Not Found! 17:29:25.576 -> Disconnecting since Client FTM Control Point Characteristic is mandatory! 17:29:25.623 -> Client Disconnected, reason = 0x16 17:29:25.623 -> >>> Restart the Feather nRF52 Client for a new run! <<<
17:30:45.419 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 17:30:45.419 -> ----------------- Version 02.6 ------------------ 17:30:45.419 -> Initialise the Bluefruit nRF52 module: Client (Central) 17:30:45.420 -> FTMS and Chars 'initialized' 17:30:45.420 -> CPS and Chars 'initialized' 17:30:45.420 -> CSCS and Chars 'initialized' 17:30:45.420 -> GA and Chars 'initialized' 17:30:45.420 -> DIS and Chars 'initialized' 17:30:45.420 -> Start Scanning for CPS, CSC and FTMS! 17:31:20.566 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 17:31:20.566 -> Timestamp MAC Address Rssi Data 17:31:20.566 -> 000037231 F8:9C:FC:53:5E:49 -58 09-02-16-18-26-18-18-18-0A-18 17:31:20.876 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:31:20.876 -> Now checking all Client Services and Characteristics! 17:31:20.876 -> If Mandatory Services Fail --> the Client will disconnect! 17:31:20.876 -> First checking Generic Access and Device Information Services and Characteristics! 17:31:21.015 -> Found Client Generic Access 17:31:21.384 -> -> Client Reads Device Name: [] 17:31:21.384 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Not Found! 17:31:21.384 -> Disconnecting since Client FTM Service is mandatory! 17:31:21.476 -> Client Disconnected, reason = 0x16 17:31:21.476 -> >>> Restart the Feather nRF52 Client for a new run! <<<
17:35:49.982 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 17:35:49.982 -> ----------------- Version 02.7 ------------------ 17:35:49.982 -> Initialise the Bluefruit nRF52 module: Client (Central) 17:35:50.410 -> FTMS and Chars 'initialized' 17:35:50.410 -> CPS and Chars 'initialized' 17:35:50.410 -> CSCS and Chars 'initialized' 17:35:50.410 -> GA and Chars 'initialized' 17:35:50.410 -> DIS and Chars 'initialized' 17:35:50.410 -> Start Scanning for CPS, CSC and FTMS! 17:36:08.272 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 17:36:08.272 -> Timestamp MAC Address Rssi Data 17:36:08.272 -> 000019071 F8:9C:FC:53:5E:49 -54 09-02-16-18-26-18-18-18-0A-18 17:36:08.460 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:36:08.460 -> Now checking all Client Services and Characteristics! 17:36:08.460 -> If Mandatory Services Fail --> the Client will disconnect! 17:36:08.460 -> First checking Generic Access and Device Information Services and Characteristics! 17:36:08.585 -> Found Client Generic Access 17:36:08.864 -> -> Client Reads Device Name: [] 17:36:08.864 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Not Found! 17:36:08.864 -> Disconnecting since Client FTM Service is mandatory! 17:36:08.864 -> Client Disconnected, reason = 0x16 17:36:08.864 -> >>> Restart the Feather nRF52 Client for a new run! <<< 17:36:13.400 -> Stopped!
17:36:53.019 -> FTMS and Chars 'initialized' 17:36:53.019 -> CPS and Chars 'initialized' 17:36:53.019 -> CSCS and Chars 'initialized' 17:36:53.019 -> GA and Chars 'initialized' 17:36:53.019 -> DIS and Chars 'initialized' 17:36:53.019 -> Start Scanning for CPS, CSC and FTMS! 17:36:53.020 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 17:36:53.020 -> Timestamp MAC Address Rssi Data 17:36:53.020 -> 000001308 F8:9C:FC:53:5E:49 -60 09-02-16-18-26-18-18-18-0A-18 17:36:53.020 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:36:53.020 -> Now checking all Client Services and Characteristics! 17:36:53.020 -> If Mandatory Services Fail --> the Client will disconnect! 17:36:53.020 -> First checking Generic Access and Device Information Services and Characteristics! 17:36:53.021 -> Found Client Generic Access 17:36:53.021 -> -> Client Reads Device Name: [Zwift Hub] 17:36:53.152 -> -> Client Reads Appearance: [1152] 17:36:53.154 -> Found Client Device Information 17:36:53.309 -> -> Client Reads Manufacturer: [Zwift] 17:36:53.712 -> -> Client Reads Model Number: [06] 17:36:53.881 -> -> Client Reads Serial Number: [06-F89CFC535E49] 17:36:53.881 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 17:36:53.928 -> Discovering Client FTM Feature Characteristic ... Found it! 17:36:54.098 -> -> Client Reads Raw FTM Feature bytes: [8] [ 87 44 00 00 0C E0 00 00 ] 17:36:54.098 -> Discovering Client FTM Control Point Characteristic ... Found it! 17:36:54.653 -> Discovering Client FTM Status Characteristic ... Not Found! 17:36:54.653 -> Disconnecting since Client FTM Status Characteristic is mandatory! 17:36:54.888 -> Client Disconnected, reason = 0x16 17:36:54.888 -> >>> Restart the Feather nRF52 Client for a new run! <<< 17:36:57.446 -> Stopped!
Dear Joel, I have uploaded a new FTMS_Client version 028!
1) Upload and Run this code on the Feather-nRF52 2) Start the Serial Monitor to catch verbose debugging and data info 3) Power ON/Wake UP trainer -> do NOT connect with other devices
I think we have stumbled on a timing problem, now and then a run is more or less succesfull, never it stops at exactly the same point! Only once sofar the code execution really reached the end...... So it is possible!
I have inserted calls to delay(SOME_TIME) in the Client_Connect_Callback function to handle possible time-outs that may occur during discover SVC or Char's... The delay time is now set to 100 ms! Just a guess! Depending on what the result is, you can increase or decrease the value and see how the result is influenced positively or negatively.... Give it a try and fingers crossed, Jörgen
Dear Jörghen,
I had to increase the delay to 200 The system starts in any direction 9/10 times
I have given you several examples of start-ups because I believe that certain services are there at certain start-ups and not at others!
The resistance is well felt during the test :)
JACKPOT !!!!!!! Congratulation !!! 👍
11:40:31.097 -> -> Client Reads Appearance: [1152] 11:40:31.210 -> Found Client Device Information 11:40:31.489 -> -> Client Reads Manufacturer: [Zwift] 11:40:31.944 -> -> Client Reads Model Number: [06] 11:40:32.161 -> -> Client Reads Serial Number: [06-F89CFC535E49] 11:40:32.302 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 11:40:32.537 -> Discovering Client FTM Feature Characteristic ... Found it! 11:40:32.742 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 11:40:32.835 -> Discovering Client FTM Control Point Characteristic ... Found it! 11:40:33.212 -> Discovering Client FTM Status Characteristic ... Found it! 11:40:33.620 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 11:40:34.229 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 11:40:34.403 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 11:40:34.497 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 11:40:34.747 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 00 00 00 00 ] 11:40:34.839 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 11:40:35.057 -> Enable Notify/Indicate of relevant Peripheral (Trainer) Characteristics 11:40:35.134 -> Discovering Client Cycling Power (CP) Service ... Ready to receive Client FTM Control Point Response Messages 11:40:35.181 -> Found it! CPS Max Payload: 20 Data Length: 27 11:40:35.273 -> Ready to receive Client FTM Status values 11:40:35.273 -> Discovering Client CP Measurement characteristic ... Found it! 11:40:35.756 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 11:40:36.023 -> Discovering Client CP Feature characteristic ... Found it! 11:40:36.023 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 11:40:36.023 -> Wheel revolution data supported 11:40:36.023 -> Crank revolution data supported 11:40:36.162 -> Discovering Client CP Sensor Location characteristic ... Found it! 11:40:36.255 -> -> Client Reads CP Location Sensor: Loc#: 0 Other 11:40:36.379 -> Discovering Cycling Speed and Cadence (CSC) Service ... Not Found! CSC Service is Not Mandatory! 11:40:37.221 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 11:40:37.300 -> Ready to receive Client FTM Indoor Bike Data values 11:40:37.300 -> Ready to receive Client CP Measurement values 11:40:38.365 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 11:40:38.365 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 11:40:39.220 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 0B 02 00 00 14 00 00 00 00 ] 11:40:39.220 -> Instant. Speed: 5 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 11:40:39.314 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 11:40:40.385 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 07 03 00 00 14 00 11 00 00 ] 11:40:40.385 -> Instant. Speed: 7 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 17 Watt Heart Rate: 0 HBM 11:40:41.272 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 58 04 00 00 14 00 40 00 00 ] 11:40:41.272 -> Instant. Speed: 11 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 64 Watt Heart Rate: 0 HBM 11:40:41.320 -> >>> Couldn't enable notify for Client CSC Measurement Characteristic. 11:40:41.320 -> Client (Central) is Up and Running! 11:40:42.206 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 78 05 00 00 14 00 90 00 00 ] 11:40:42.206 -> Instant. Speed: 14 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 144 Watt Heart Rate: 0 HBM 11:40:43.237 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 CF 05 20 00 14 00 71 00 00 ] 11:40:43.237 -> Instant. Speed: 14 KPH Instantaneous Cadence: 16 RPM Resistance Level: 20 Instantaneous Power: 113 Watt Heart Rate: 0 HBM 11:40:43.315 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 11:40:43.581 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 11:40:44.313 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 25 06 46 00 14 00 71 00 00 ] 11:40:44.313 -> Instant. Speed: 15 KPH Instantaneous Cadence: 35 RPM Resistance Level: 20 Instantaneous Power: 113 Watt Heart Rate: 0 HBM 11:40:45.311 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 96 06 5A 00 14 00 94 00 00 ] 11:40:45.311 -> Instant. Speed: 16 KPH Instantaneous Cadence: 45 RPM Resistance Level: 20 Instantaneous Power: 148 Watt Heart Rate: 0 HBM 11:40:45.405 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 11:40:45.763 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 11:40:46.212 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 D5 06 68 00 14 00 7E 00 00 ] 11:40:46.212 -> Instant. Speed: 17 KPH Instantaneous Cadence: 52 RPM Resistance Level: 20 Instantaneous Power: 126 Watt Heart Rate: 0 HBM 11:40:47.194 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 16 07 72 00 14 00 6D 00 00 ] 11:40:47.194 -> Instant. Speed: 18 KPH Instantaneous Cadence: 57 RPM Resistance Level: 20 Instantaneous Power: 109 Watt Heart Rate: 0 HBM 11:40:47.506 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 11:40:47.646 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 11:40:47.646 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 11:40:48.206 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 71 07 17 07 7A 00 7A 00 05 00 00 14 00 61 00 61 00 00 ] 11:40:48.206 -> Instant. Speed: 19 KPH Average Speed: 18 KPH Instantaneous Cadence: 61 RPM Average Cadence: 61 RPM Total Distance: 5 m Resistance Level: 20 Instantaneous Power: 97 Watt Average Power: 97 Watt Heart Rate: 0 HBM 11:40:49.611 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 11:40:49.690 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 EC 07 17 07 80 00 7D 00 0A 00 00 14 00 62 00 61 00 00 ] 11:40:49.737 -> Instant. Speed: 20 KPH Average Speed: 18 KPH Instantaneous Cadence: 64 RPM Average Cadence: 62 RPM Total Distance: 10 m Resistance Level: 20 Instantaneous Power: 98 Watt Average Power: 97 Watt Heart Rate: 0 HBM 11:40:49.814 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:40:49.814 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 11:40:50.545 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 1E 08 17 07 82 00 7E 00 0F 00 00 14 00 63 00 62 00 00 ] 11:40:50.545 -> Instant. Speed: 20 KPH Average Speed: 18 KPH Instantaneous Cadence: 65 RPM Average Cadence: 63 RPM Total Distance: 15 m Resistance Level: 20 Instantaneous Power: 99 Watt Average Power: 98 Watt Heart Rate: 0 HBM 11:40:51.247 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 D3 07 17 07 86 00 80 00 14 00 00 14 00 5F 00 61 00 00 ] 11:40:51.247 -> Instant. Speed: 20 KPH Average Speed: 18 KPH Instantaneous Cadence: 67 RPM Average Cadence: 64 RPM Total Distance: 20 m Resistance Level: 20 Instantaneous Power: 95 Watt Average Power: 97 Watt Heart Rate: 0 HBM 11:40:51.715 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 00 28 33 00 ] 11:40:51.887 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:40:51.887 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 11:40:52.338 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A2 07 17 07 88 00 82 00 19 00 00 14 00 6A 00 63 00 00 ] 11:40:52.338 -> Instant. Speed: 19 KPH Average Speed: 18 KPH Instantaneous Cadence: 68 RPM Average Cadence: 65 RPM Total Distance: 25 m Resistance Level: 20 Instantaneous Power: 106 Watt Average Power: 99 Watt Heart Rate: 0 HBM 11:40:53.228 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 19 08 17 07 88 00 83 00 1E 00 00 14 00 85 00 68 00 00 ] 11:40:53.228 -> Instant. Speed: 20 KPH Average Speed: 18 KPH Instantaneous Cadence: 68 RPM Average Cadence: 65 RPM Total Distance: 30 m Resistance Level: 20 Instantaneous Power: 133 Watt Average Power: 104 Watt Heart Rate: 0 HBM 11:40:53.821 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 11:40:54.224 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:40:54.224 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 11:40:54.224 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 38 08 17 07 88 00 83 00 23 00 00 14 00 74 00 6A 00 00 ] 11:40:54.224 -> Instant. Speed: 21 KPH Average Speed: 18 KPH Instantaneous Cadence: 68 RPM Average Cadence: 65 RPM Total Distance: 35 m Resistance Level: 20 Instantaneous Power: 116 Watt Average Power: 106 Watt Heart Rate: 0 HBM 11:40:55.302 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 4E 08 17 07 8A 00 84 00 28 00 00 14 00 67 00 69 00 00 ] 11:40:55.302 -> Instant. Speed: 21 KPH Average Speed: 18 KPH Instantaneous Cadence: 69 RPM Average Cadence: 66 RPM Total Distance: 40 m Resistance Level: 20 Instantaneous Power: 103 Watt Average Power: 105 Watt Heart Rate: 0 HBM 11:40:55.908 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 14 00 28 33 00 ] 11:40:56.034 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:40:56.034 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 00 28 33 ] 11:40:56.206 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 D1 08 3F 07 8C 00 85 00 2E 00 00 14 00 57 00 67 00 00 ] 11:40:56.206 -> Instant. Speed: 22 KPH Average Speed: 18 KPH Instantaneous Cadence: 70 RPM Average Cadence: 66 RPM Total Distance: 46 m Resistance Level: 20 Instantaneous Power: 87 Watt Average Power: 103 Watt Heart Rate: 0 HBM 11:40:57.159 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 7F 08 3B 07 94 00 86 00 33 00 00 14 00 5A 00 66 00 00 ] 11:40:57.205 -> Instant. Speed: 21 KPH Average Speed: 18 KPH Instantaneous Cadence: 74 RPM Average Cadence: 67 RPM Total Distance: 51 m Resistance Level: 20 Instantaneous Power: 90 Watt Average Power: 102 Watt Heart Rate: 0 HBM 11:40:57.986 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 00 28 33 00 ] 11:40:58.159 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:40:58.159 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 00 28 33 ] 11:40:58.284 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 AC 08 58 07 96 00 88 00 39 00 00 14 00 47 00 63 00 00 ] 11:40:58.284 -> Instant. Speed: 22 KPH Average Speed: 18 KPH Instantaneous Cadence: 75 RPM Average Cadence: 68 RPM Total Distance: 57 m Resistance Level: 20 Instantaneous Power: 71 Watt Average Power: 99 Watt Heart Rate: 0 HBM 11:40:59.254 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 84 08 71 07 96 00 89 00 3F 00 00 14 00 58 00 62 00 00 ] 11:40:59.254 -> Instant. Speed: 21 KPH Average Speed: 19 KPH Instantaneous Cadence: 75 RPM Average Cadence: 68 RPM Total Distance: 63 m Resistance Level: 20 Instantaneous Power: 88 Watt Average Power: 98 Watt Heart Rate: 0 HBM 11:41:00.125 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 25 00 28 33 00 ] 11:41:00.344 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E7 08 86 07 20 00 81 00 45 00 00 14 00 5F 00 62 00 00 ] 11:41:00.344 -> Instant. Speed: 22 KPH Average Speed: 19 KPH Instantaneous Cadence: 16 RPM Average Cadence: 64 RPM Total Distance: 69 m Resistance Level: 20 Instantaneous Power: 95 Watt Average Power: 98 Watt Heart Rate: 0 HBM 11:41:00.344 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:00.344 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 25 00 28 33 ] 11:41:01.324 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 C5 08 98 07 6E 00 7F 00 4B 00 00 14 00 57 00 61 00 00 ] 11:41:01.324 -> Instant. Speed: 22 KPH Average Speed: 19 KPH Instantaneous Cadence: 55 RPM Average Cadence: 63 RPM Total Distance: 75 m Resistance Level: 20 Instantaneous Power: 87 Watt Average Power: 97 Watt Heart Rate: 0 HBM 11:41:02.199 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 23 00 28 33 00 ] 11:41:02.245 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 B2 08 A8 07 8C 00 80 00 51 00 00 14 00 5C 00 61 00 00 ] 11:41:02.245 -> Instant. Speed: 22 KPH Average Speed: 19 KPH Instantaneous Cadence: 70 RPM Average Cadence: 64 RPM Total Distance: 81 m Resistance Level: 20 Instantaneous Power: 92 Watt Average Power: 97 Watt Heart Rate: 0 HBM 11:41:02.245 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:02.245 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 00 28 33 ] 11:41:03.228 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 BB 08 B5 07 94 00 81 00 57 00 00 14 00 5D 00 60 00 00 ] 11:41:03.228 -> Instant. Speed: 22 KPH Average Speed: 19 KPH Instantaneous Cadence: 74 RPM Average Cadence: 64 RPM Total Distance: 87 m Resistance Level: 20 Instantaneous Power: 93 Watt Average Power: 96 Watt Heart Rate: 0 HBM 11:41:04.228 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 1C 00 28 33 00 ] 11:41:04.306 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 07 09 C1 07 94 00 82 00 5D 00 00 14 00 55 00 60 00 00 ] 11:41:04.306 -> Instant. Speed: 23 KPH Average Speed: 19 KPH Instantaneous Cadence: 74 RPM Average Cadence: 65 RPM Total Distance: 93 m Resistance Level: 20 Instantaneous Power: 85 Watt Average Power: 96 Watt Heart Rate: 0 HBM 11:41:04.400 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:04.400 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 00 28 33 ] 11:41:05.210 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 D4 08 CC 07 98 00 84 00 63 00 00 14 00 5B 00 5F 00 00 ] 11:41:05.210 -> Instant. Speed: 22 KPH Average Speed: 19 KPH Instantaneous Cadence: 76 RPM Average Cadence: 66 RPM Total Distance: 99 m Resistance Level: 20 Instantaneous Power: 91 Watt Average Power: 95 Watt Heart Rate: 0 HBM 11:41:06.189 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E1 08 D5 07 9C 00 85 00 69 00 00 14 00 5E 00 5F 00 00 ] 11:41:06.190 -> Instant. Speed: 22 KPH Average Speed: 20 KPH Instantaneous Cadence: 78 RPM Average Cadence: 66 RPM Total Distance: 105 m Resistance Level: 20 Instantaneous Power: 94 Watt Average Power: 95 Watt Heart Rate: 0 HBM 11:41:06.329 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 0F 00 28 33 00 ] 11:41:06.829 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:06.829 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 0F 00 28 33 ] 11:41:07.264 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 BD 08 DE 07 9C 00 86 00 6F 00 00 14 00 61 00 5F 00 00 ] 11:41:07.264 -> Instant. Speed: 22 KPH Average Speed: 20 KPH Instantaneous Cadence: 78 RPM Average Cadence: 67 RPM Total Distance: 111 m Resistance Level: 20 Instantaneous Power: 97 Watt Average Power: 95 Watt Heart Rate: 0 HBM 11:41:08.339 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 1F 09 E6 07 98 00 87 00 75 00 00 14 00 58 00 5F 00 00 ] 11:41:08.339 -> Instant. Speed: 23 KPH Average Speed: 20 KPH Instantaneous Cadence: 76 RPM Average Cadence: 67 RPM Total Distance: 117 m Resistance Level: 20 Instantaneous Power: 88 Watt Average Power: 95 Watt Heart Rate: 0 HBM 11:41:08.431 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 11:41:08.618 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:08.618 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 11:41:09.414 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 D6 08 ED 07 9E 00 88 00 7B 00 00 14 00 54 00 5E 00 00 ] 11:41:09.414 -> Instant. Speed: 22 KPH Average Speed: 20 KPH Instantaneous Cadence: 79 RPM Average Cadence: 68 RPM Total Distance: 123 m Resistance Level: 20 Instantaneous Power: 84 Watt Average Power: 94 Watt Heart Rate: 0 HBM 11:41:10.240 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E6 08 F3 07 A2 00 89 00 81 00 00 14 00 53 00 5E 00 00 ] 11:41:10.240 -> Instant. Speed: 22 KPH Average Speed: 20 KPH Instantaneous Cadence: 81 RPM Average Cadence: 68 RPM Total Distance: 129 m Resistance Level: 20 Instantaneous Power: 83 Watt Average Power: 94 Watt Heart Rate: 0 HBM 11:41:10.550 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 F5 FF 28 33 00 ] 11:41:10.691 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:10.691 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 F5 FF 28 33 ] 11:41:11.235 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 C4 08 F9 07 9C 00 8A 00 87 00 00 14 00 44 00 5D 00 00 ] 11:41:11.235 -> Instant. Speed: 22 KPH Average Speed: 20 KPH Instantaneous Cadence: 78 RPM Average Cadence: 69 RPM Total Distance: 135 m Resistance Level: 20 Instantaneous Power: 68 Watt Average Power: 93 Watt Heart Rate: 0 HBM 11:41:12.235 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 04 09 FF 07 9C 00 8A 00 8D 00 00 14 00 43 00 5C 00 00 ] 11:41:12.235 -> Instant. Speed: 23 KPH Average Speed: 20 KPH Instantaneous Cadence: 78 RPM Average Cadence: 69 RPM Total Distance: 141 m Resistance Level: 20 Instantaneous Power: 67 Watt Average Power: 92 Watt Heart Rate: 0 HBM 11:41:12.639 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 E4 FF 28 33 00 ] 11:41:12.857 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:12.857 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 E4 FF 28 33 ] 11:41:13.217 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 09 09 04 08 A0 00 8B 00 93 00 00 14 00 4C 00 5B 00 00 ] 11:41:13.217 -> Instant. Speed: 23 KPH Average Speed: 20 KPH Instantaneous Cadence: 80 RPM Average Cadence: 69 RPM Total Distance: 147 m Resistance Level: 20 Instantaneous Power: 76 Watt Average Power: 91 Watt Heart Rate: 0 HBM 11:41:14.169 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E7 08 08 08 9E 00 8C 00 99 00 00 14 00 4A 00 5B 00 00 ] 11:41:14.216 -> Instant. Speed: 22 KPH Average Speed: 20 KPH Instantaneous Cadence: 79 RPM Average Cadence: 70 RPM Total Distance: 153 m Resistance Level: 20 Instantaneous Power: 74 Watt Average Power: 91 Watt Heart Rate: 0 HBM 11:41:14.745 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 CF FF 28 33 00 ] 11:41:14.902 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:14.902 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 CF FF 28 33 ] 11:41:15.183 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 1D 09 0D 08 9E 00 8D 00 9F 00 00 14 00 48 00 5A 00 00 ] 11:41:15.183 -> Instant. Speed: 23 KPH Average Speed: 20 KPH Instantaneous Cadence: 79 RPM Average Cadence: 70 RPM Total Distance: 159 m Resistance Level: 20 Instantaneous Power: 72 Watt Average Power: 90 Watt Heart Rate: 0 HBM 11:41:16.368 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 1E 09 11 08 A0 00 8D 00 A5 00 00 14 00 49 00 59 00 00 ] 11:41:16.368 -> Instant. Speed: 23 KPH Average Speed: 20 KPH Instantaneous Cadence: 80 RPM Average Cadence: 70 RPM Total Distance: 165 m Resistance Level: 20 Instantaneous Power: 73 Watt Average Power: 89 Watt Heart Rate: 0 HBM 11:41:16.853 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A8 FF 28 33 00 ] 11:41:16.992 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:16.992 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A8 FF 28 33 ] 11:41:17.366 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 17 09 14 08 9E 00 8E 00 AB 00 00 14 00 3F 00 58 00 00 ] 11:41:17.366 -> Instant. Speed: 23 KPH Average Speed: 20 KPH Instantaneous Cadence: 79 RPM Average Cadence: 71 RPM Total Distance: 171 m Resistance Level: 20 Instantaneous Power: 63 Watt Average Power: 88 Watt Heart Rate: 0 HBM 11:41:18.255 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 6F 09 18 08 A2 00 8E 00 B1 00 00 14 00 44 00 58 00 00 ] 11:41:18.255 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 81 RPM Average Cadence: 71 RPM Total Distance: 177 m Resistance Level: 20 Instantaneous Power: 68 Watt Average Power: 88 Watt Heart Rate: 0 HBM 11:41:18.941 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 84 FF 28 33 00 ] 11:41:19.158 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:19.158 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 84 FF 28 33 ] 11:41:19.252 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 65 09 1B 08 9E 00 8F 00 B7 00 00 14 00 4E 00 57 00 00 ] 11:41:19.252 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 79 RPM Average Cadence: 71 RPM Total Distance: 183 m Resistance Level: 20 Instantaneous Power: 78 Watt Average Power: 87 Watt Heart Rate: 0 HBM 11:41:20.216 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 5B 09 1E 08 A6 00 90 00 BD 00 00 14 00 39 00 56 00 00 ] 11:41:20.216 -> Instant. Speed: 23 KPH Average Speed: 20 KPH Instantaneous Cadence: 83 RPM Average Cadence: 72 RPM Total Distance: 189 m Resistance Level: 20 Instantaneous Power: 57 Watt Average Power: 86 Watt Heart Rate: 0 HBM 11:41:21.042 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 FF 28 33 00 ] 11:41:21.215 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 9C 09 21 08 B0 00 91 00 C3 00 00 14 00 32 00 55 00 00 ] 11:41:21.215 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 88 RPM Average Cadence: 72 RPM Total Distance: 195 m Resistance Level: 20 Instantaneous Power: 50 Watt Average Power: 85 Watt Heart Rate: 0 HBM 11:41:21.215 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:21.215 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 FF 28 33 ] 11:41:22.182 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A5 09 24 08 B0 00 91 00 C9 00 00 14 00 3A 00 55 00 00 ] 11:41:22.182 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 88 RPM Average Cadence: 72 RPM Total Distance: 201 m Resistance Level: 20 Instantaneous Power: 58 Watt Average Power: 85 Watt Heart Rate: 0 HBM 11:41:23.149 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5D FF 28 33 00 ] 11:41:23.196 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 8D 09 27 08 A2 00 92 00 CF 00 00 14 00 26 00 53 00 00 ] 11:41:23.196 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 81 RPM Average Cadence: 73 RPM Total Distance: 207 m Resistance Level: 20 Instantaneous Power: 38 Watt Average Power: 83 Watt Heart Rate: 0 HBM 11:41:23.196 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:23.196 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5D FF 28 33 ] 11:41:24.179 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 AC 09 29 08 8A 00 92 00 D5 00 00 14 00 26 00 52 00 00 ] 11:41:24.179 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 69 RPM Average Cadence: 73 RPM Total Distance: 213 m Resistance Level: 20 Instantaneous Power: 38 Watt Average Power: 82 Watt Heart Rate: 0 HBM 11:41:25.221 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5E FF 28 33 00 ] 11:41:25.441 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 7D 09 2B 08 66 00 90 00 DB 00 00 14 00 29 00 51 00 00 ] 11:41:25.441 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 51 RPM Average Cadence: 72 RPM Total Distance: 219 m Resistance Level: 20 Instantaneous Power: 41 Watt Average Power: 81 Watt Heart Rate: 0 HBM 11:41:25.549 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:25.549 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5E FF 28 33 ] 11:41:26.249 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 8C 09 2E 08 5A 00 8F 00 E1 00 00 14 00 29 00 50 00 00 ] 11:41:26.249 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 45 RPM Average Cadence: 71 RPM Total Distance: 225 m Resistance Level: 20 Instantaneous Power: 41 Watt Average Power: 80 Watt Heart Rate: 0 HBM 11:41:27.260 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 9A 09 30 08 5E 00 8E 00 E7 00 00 14 00 26 00 4F 00 00 ] 11:41:27.260 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 47 RPM Average Cadence: 71 RPM Total Distance: 231 m Resistance Level: 20 Instantaneous Power: 38 Watt Average Power: 79 Watt Heart Rate: 0 HBM 11:41:27.307 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 6F FF 28 33 00 ] 11:41:27.447 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:27.447 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 6F FF 28 33 ] 11:41:28.242 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 87 09 32 08 66 00 8D 00 ED 00 00 14 00 22 00 4E 00 00 ] 11:41:28.242 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 51 RPM Average Cadence: 70 RPM Total Distance: 237 m Resistance Level: 20 Instantaneous Power: 34 Watt Average Power: 78 Watt Heart Rate: 0 HBM 11:41:29.224 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 5C 09 34 08 66 00 8C 00 F3 00 00 14 00 2E 00 4D 00 00 ] 11:41:29.224 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 51 RPM Average Cadence: 70 RPM Total Distance: 243 m Resistance Level: 20 Instantaneous Power: 46 Watt Average Power: 77 Watt Heart Rate: 0 HBM 11:41:29.410 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 8A FF 28 33 00 ] 11:41:29.782 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:29.782 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8A FF 28 33 ] 11:41:30.296 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 EB 08 35 08 00 00 89 00 F9 00 00 14 00 00 00 4B 00 00 ] 11:41:30.296 -> Instant. Speed: 22 KPH Average Speed: 21 KPH Instantaneous Cadence: 0 RPM Average Cadence: 68 RPM Total Distance: 249 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 75 Watt Heart Rate: 0 HBM 11:41:31.196 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 AA 09 37 08 00 00 86 00 FF 00 00 14 00 00 00 49 00 00 ] 11:41:31.196 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 0 RPM Average Cadence: 67 RPM Total Distance: 255 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 73 Watt Heart Rate: 0 HBM 11:41:31.523 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 B8 FF 28 33 00 ] 11:41:31.757 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:31.757 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 B8 FF 28 33 ] 11:41:32.458 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 CB 09 39 08 50 00 84 00 05 01 00 14 00 35 00 49 00 00 ] 11:41:32.458 -> Instant. Speed: 25 KPH Average Speed: 21 KPH Instantaneous Cadence: 40 RPM Average Cadence: 66 RPM Total Distance: 261 m Resistance Level: 20 Instantaneous Power: 53 Watt Average Power: 73 Watt Heart Rate: 0 HBM 11:41:33.472 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E4 09 3A 08 56 00 83 00 0B 01 00 14 00 33 00 48 00 00 ] 11:41:33.472 -> Instant. Speed: 25 KPH Average Speed: 21 KPH Instantaneous Cadence: 43 RPM Average Cadence: 65 RPM Total Distance: 267 m Resistance Level: 20 Instantaneous Power: 51 Watt Average Power: 72 Watt Heart Rate: 0 HBM 11:41:33.612 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 11:41:33.830 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:33.830 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 11:41:34.376 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 25 0A 44 08 56 00 82 00 12 01 00 14 00 33 00 48 00 00 ] 11:41:34.376 -> Instant. Speed: 25 KPH Average Speed: 21 KPH Instantaneous Cadence: 43 RPM Average Cadence: 65 RPM Total Distance: 274 m Resistance Level: 20 Instantaneous Power: 51 Watt Average Power: 72 Watt Heart Rate: 0 HBM 11:41:35.450 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 1B 0A 4C 08 54 00 81 00 19 01 00 14 00 2E 00 47 00 00 ] 11:41:35.450 -> Instant. Speed: 25 KPH Average Speed: 21 KPH Instantaneous Cadence: 42 RPM Average Cadence: 64 RPM Total Distance: 281 m Resistance Level: 20 Instantaneous Power: 46 Watt Average Power: 71 Watt Heart Rate: 0 HBM 11:41:35.712 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A2 00 28 33 00 ] 11:41:35.993 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:35.993 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A2 00 28 33 ] 11:41:36.259 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 1F 0A 55 08 5E 00 81 00 20 01 00 14 00 27 00 47 00 00 ] 11:41:36.259 -> Instant. Speed: 25 KPH Average Speed: 21 KPH Instantaneous Cadence: 47 RPM Average Cadence: 64 RPM Total Distance: 288 m Resistance Level: 20 Instantaneous Power: 39 Watt Average Power: 71 Watt Heart Rate: 0 HBM 11:41:37.320 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 AE 09 56 08 64 00 80 00 26 01 00 14 00 27 00 46 00 00 ] 11:41:37.320 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 50 RPM Average Cadence: 64 RPM Total Distance: 294 m Resistance Level: 20 Instantaneous Power: 39 Watt Average Power: 70 Watt Heart Rate: 0 HBM 11:41:37.818 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 01 28 33 00 ] 11:41:38.148 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:38.148 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 01 28 33 ] 11:41:38.241 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 65 09 57 08 5C 00 7F 00 2C 01 00 14 00 1F 00 45 00 00 ] 11:41:38.241 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 46 RPM Average Cadence: 63 RPM Total Distance: 300 m Resistance Level: 20 Instantaneous Power: 31 Watt Average Power: 69 Watt Heart Rate: 0 HBM 11:41:39.209 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 0B 09 57 08 54 00 7E 00 32 01 00 14 00 1F 00 45 00 00 ] 11:41:39.209 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 42 RPM Average Cadence: 63 RPM Total Distance: 306 m Resistance Level: 20 Instantaneous Power: 31 Watt Average Power: 69 Watt Heart Rate: 0 HBM 11:41:39.909 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 4F 01 28 33 00 ] 11:41:40.021 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:40.021 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 4F 01 28 33 ] 11:41:40.301 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 19 09 58 08 50 00 7E 00 38 01 00 14 00 4C 00 45 00 00 ] 11:41:40.301 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 40 RPM Average Cadence: 63 RPM Total Distance: 312 m Resistance Level: 20 Instantaneous Power: 76 Watt Average Power: 69 Watt Heart Rate: 0 HBM 11:41:41.281 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 8B 08 59 08 50 00 7D 00 3E 01 00 14 00 7A 00 46 00 00 ] 11:41:41.281 -> Instant. Speed: 21 KPH Average Speed: 21 KPH Instantaneous Cadence: 40 RPM Average Cadence: 62 RPM Total Distance: 318 m Resistance Level: 20 Instantaneous Power: 122 Watt Average Power: 70 Watt Heart Rate: 0 HBM 11:41:41.999 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 01 28 33 00 ] 11:41:42.203 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:42.203 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 01 28 33 ] 11:41:42.203 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E7 08 5A 08 30 00 7B 00 44 01 00 14 00 7A 00 47 00 00 ] 11:41:42.203 -> Instant. Speed: 22 KPH Average Speed: 21 KPH Instantaneous Cadence: 24 RPM Average Cadence: 61 RPM Total Distance: 324 m Resistance Level: 20 Instantaneous Power: 122 Watt Average Power: 71 Watt Heart Rate: 0 HBM 11:41:43.463 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 27 08 54 08 70 00 7B 00 49 01 00 14 00 62 00 47 00 00 ] 11:41:43.463 -> Instant. Speed: 20 KPH Average Speed: 21 KPH Instantaneous Cadence: 56 RPM Average Cadence: 61 RPM Total Distance: 329 m Resistance Level: 20 Instantaneous Power: 98 Watt Average Power: 71 Watt Heart Rate: 0 HBM 11:41:44.118 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 57 FF 28 33 00 ] 11:41:44.258 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 85 08 55 08 86 00 7B 00 4F 01 00 14 00 C1 00 49 00 00 ] 11:41:44.258 -> Instant. Speed: 21 KPH Average Speed: 21 KPH Instantaneous Cadence: 67 RPM Average Cadence: 61 RPM Total Distance: 335 m Resistance Level: 20 Instantaneous Power: 193 Watt Average Power: 73 Watt Heart Rate: 0 HBM 11:41:44.337 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:44.337 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 57 FF 28 33 ] 11:41:45.414 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E0 08 55 08 8C 00 7C 00 55 01 00 14 00 B9 00 4B 00 00 ] 11:41:45.414 -> Instant. Speed: 22 KPH Average Speed: 21 KPH Instantaneous Cadence: 70 RPM Average Cadence: 62 RPM Total Distance: 341 m Resistance Level: 20 Instantaneous Power: 185 Watt Average Power: 75 Watt Heart Rate: 0 HBM 11:41:46.191 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 08 00 00 00 00 00 00 00 ] 11:41:46.238 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 28 09 56 08 8E 00 7C 00 5B 01 00 14 00 C6 00 4D 00 00 ] 11:41:46.238 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 71 RPM Average Cadence: 62 RPM Total Distance: 347 m Resistance Level: 20 Instantaneous Power: 198 Watt Average Power: 77 Watt Heart Rate: 0 HBM 11:41:46.238 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 08 03 ] 11:41:47.396 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 38 09 57 08 98 00 7C 00 61 01 00 14 00 71 00 4E 00 00 ] 11:41:47.396 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 76 RPM Average Cadence: 62 RPM Total Distance: 353 m Resistance Level: 20 Instantaneous Power: 113 Watt Average Power: 78 Watt Heart Rate: 0 HBM 11:41:48.212 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 81 09 58 08 9E 00 7D 00 67 01 00 14 00 3F 00 4E 00 00 ] 11:41:48.212 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 79 RPM Average Cadence: 62 RPM Total Distance: 359 m Resistance Level: 20 Instantaneous Power: 63 Watt Average Power: 78 Watt Heart Rate: 0 HBM 11:41:48.253 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 01 00 00 00 00 00 00 00 ] 11:41:48.394 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 01 01 ] 11:41:48.394 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 01 ] 11:41:49.269 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 C7 09 A6 00 14 00 31 00 00 ] 11:41:49.315 -> Instant. Speed: 25 KPH Instantaneous Cadence: 83 RPM Resistance Level: 20 Instantaneous Power: 49 Watt Heart Rate: 0 HBM 11:41:50.351 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 11:41:50.477 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 AB 09 AC 00 14 00 38 00 00 ] 11:41:50.477 -> Instant. Speed: 24 KPH Instantaneous Cadence: 86 RPM Resistance Level: 20 Instantaneous Power: 56 Watt Heart Rate: 0 HBM 11:41:50.570 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 11:41:51.365 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 B0 09 9E 00 14 00 3C 00 00 ] 11:41:51.365 -> Instant. Speed: 24 KPH Instantaneous Cadence: 79 RPM Resistance Level: 20 Instantaneous Power: 60 Watt Heart Rate: 0 HBM 11:41:52.239 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 E7 09 84 00 14 00 4C 00 00 ] 11:41:52.285 -> Instant. Speed: 25 KPH Instantaneous Cadence: 66 RPM Resistance Level: 20 Instantaneous Power: 76 Watt Heart Rate: 0 HBM 11:41:52.457 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 11:41:52.535 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 11:41:53.362 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 F0 09 7A 00 14 00 4C 00 00 ] 11:41:53.362 -> Instant. Speed: 25 KPH Instantaneous Cadence: 61 RPM Resistance Level: 20 Instantaneous Power: 76 Watt Heart Rate: 0 HBM 11:41:54.534 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 11:41:54.613 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 0A 90 00 14 00 58 00 00 ] 11:41:54.613 -> Instant. Speed: 25 KPH Instantaneous Cadence: 72 RPM Resistance Level: 20 Instantaneous Power: 88 Watt Heart Rate: 0 HBM 11:41:54.798 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 11:41:54.798 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 11:41:55.252 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A4 09 81 08 A2 00 A2 00 06 00 00 14 00 59 00 59 00 00 ] 11:41:55.252 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 81 RPM Average Cadence: 81 RPM Total Distance: 6 m Resistance Level: 20 Instantaneous Power: 89 Watt Average Power: 89 Watt Heart Rate: 0 HBM 11:41:56.231 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A7 09 81 08 AA 00 A6 00 0C 00 00 14 00 5A 00 59 00 00 ] 11:41:56.231 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 85 RPM Average Cadence: 83 RPM Total Distance: 12 m Resistance Level: 20 Instantaneous Power: 90 Watt Average Power: 89 Watt Heart Rate: 0 HBM 11:41:56.655 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 11:41:56.874 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:56.874 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 11:41:57.190 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 9E 09 81 08 A8 00 A6 00 12 00 00 14 00 53 00 57 00 00 ] 11:41:57.190 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 84 RPM Average Cadence: 83 RPM Total Distance: 18 m Resistance Level: 20 Instantaneous Power: 83 Watt Average Power: 87 Watt Heart Rate: 0 HBM 11:41:58.221 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 45 09 81 08 A8 00 A7 00 18 00 00 14 00 50 00 55 00 00 ] 11:41:58.221 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 84 RPM Average Cadence: 83 RPM Total Distance: 24 m Resistance Level: 20 Instantaneous Power: 80 Watt Average Power: 85 Watt Heart Rate: 0 HBM 11:41:58.736 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 00 28 33 00 ] 11:41:59.018 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:59.018 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 11:41:59.203 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 35 09 81 08 A6 00 A6 00 1E 00 00 14 00 73 00 5B 00 00 ] 11:41:59.203 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 83 RPM Average Cadence: 83 RPM Total Distance: 30 m Resistance Level: 20 Instantaneous Power: 115 Watt Average Power: 91 Watt Heart Rate: 0 HBM 11:42:00.276 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 60 09 81 08 A2 00 A6 00 24 00 00 14 00 B0 00 69 00 00 ] 11:42:00.276 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 81 RPM Average Cadence: 83 RPM Total Distance: 36 m Resistance Level: 20 Instantaneous Power: 176 Watt Average Power: 105 Watt Heart Rate: 0 HBM 11:42:00.833 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 11:42:01.239 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:42:01.285 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 11:42:01.285 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 8D 09 81 08 A4 00 A5 00 2A 00 00 14 00 9C 00 70 00 00 ] 11:42:01.285 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 82 RPM Average Cadence: 82 RPM Total Distance: 42 m Resistance Level: 20 Instantaneous Power: 156 Watt Average Power: 112 Watt Heart Rate: 0 HBM 11:42:02.267 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 71 09 81 08 A0 00 A5 00 30 00 00 14 00 61 00 6E 00 00 ] 11:42:02.267 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 80 RPM Average Cadence: 82 RPM Total Distance: 48 m Resistance Level: 20 Instantaneous Power: 97 Watt Average Power: 110 Watt Heart Rate: 0 HBM 11:42:02.952 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 14 00 28 33 00 ] 11:42:03.169 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:42:03.169 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 00 28 33 ] 11:42:03.264 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 5C 09 81 08 A2 00 A4 00 36 00 00 14 00 59 00 6C 00 00 ] 11:42:03.264 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 81 RPM Average Cadence: 82 RPM Total Distance: 54 m Resistance Level: 20 Instantaneous Power: 89 Watt Average Power: 108 Watt Heart Rate: 0 HBM 11:42:04.248 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 26 09 81 08 A6 00 A4 00 3C 00 00 14 00 52 00 69 00 00 ] 11:42:04.248 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 83 RPM Average Cadence: 82 RPM Total Distance: 60 m Resistance Level: 20 Instantaneous Power: 82 Watt Average Power: 105 Watt Heart Rate: 0 HBM 11:42:05.043 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 00 28 33 00 ] 11:42:05.137 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:42:05.137 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 00 28 33 ] 11:42:05.231 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 56 09 81 08 A8 00 A5 00 42 00 00 14 00 43 00 66 00 00 ] 11:42:05.231 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 84 RPM Average Cadence: 82 RPM Total Distance: 66 m Resistance Level: 20 Instantaneous Power: 67 Watt Average Power: 102 Watt Heart Rate: 0 HBM 11:42:06.225 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 3E 09 81 08 A2 00 A4 00 48 00 00 14 00 55 00 64 00 00 ] 11:42:06.225 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 81 RPM Average Cadence: 82 RPM Total Distance: 72 m Resistance Level: 20 Instantaneous Power: 85 Watt Average Power: 100 Watt Heart Rate: 0 HBM 11:42:07.145 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 25 00 28 33 00 ] 11:42:07.223 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 5B 09 81 08 A0 00 A4 00 4E 00 00 14 00 4A 00 62 00 00 ] 11:42:07.223 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 80 RPM Average Cadence: 82 RPM Total Distance: 78 m Resistance Level: 20 Instantaneous Power: 74 Watt Average Power: 98 Watt Heart Rate: 0 HBM 11:42:07.223 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:42:07.223 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 25 00 28 33 ] 11:42:08.206 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 4C 09 81 08 A0 00 A4 00 54 00 00 14 00 5D 00 62 00 00 ] 11:42:08.206 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 80 RPM Average Cadence: 82 RPM Total Distance: 84 m Resistance Level: 20 Instantaneous Power: 93 Watt Average Power: 98 Watt Heart Rate: 0 HBM 11:42:09.183 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 42 09 81 08 A0 00 A3 00 5A 00 00 14 00 55 00 61 00 00 ] 11:42:09.183 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 80 RPM Average Cadence: 81 RPM Total Distance: 90 m Resistance Level: 20 Instantaneous Power: 85 Watt Average Power: 97 Watt Heart Rate: 0 HBM 11:42:09.217 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 23 00 28 33 00 ] 11:42:09.375 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:42:09.375 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 00 28 33 ] 11:42:10.247 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 32 09 81 08 A2 00 A3 00 60 00 00 14 00 5F 00 61 00 00 ] 11:42:10.247 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 81 RPM Average Cadence: 81 RPM Total Distance: 96 m Resistance Level: 20 Instantaneous Power: 95 Watt Average Power: 97 Watt Heart Rate: 0 HBM 11:42:11.318 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 1C 00 28 33 00 ] 11:42:11.539 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 17 09 81 08 A0 00 A3 00 66 00 00 14 00 4E 00 60 00 00 ] 11:42:11.539 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 80 RPM Average Cadence: 81 RPM Total Distance: 102 m Resistance Level: 20 Instantaneous Power: 78 Watt Average Power: 96 Watt Heart Rate: 0 HBM 11:42:11.632 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:42:11.632 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 00 28 33 ] 11:42:12.349 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 4C 09 81 08 9E 00 A3 00 6C 00 00 14 00 53 00 5F 00 00 ] 11:42:12.349 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 79 RPM Average Cadence: 81 RPM Total Distance: 108 m Resistance Level: 20 Instantaneous Power: 83 Watt Average Power: 95 Watt Heart Rate: 0 HBM 11:42:13.427 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 0F 00 28 33 00 ] 11:42:13.490 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 46 09 81 08 9E 00 A2 00 72 00 00 14 00 56 00 5E 00 00 ] 11:42:13.490 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 79 RPM Average Cadence: 81 RPM Total Distance: 114 m Resistance Level: 20 Instantaneous Power: 86 Watt Average Power: 94 Watt Heart Rate: 0 HBM 11:42:13.569 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:42:13.614 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 0F 00 28 33 ] 11:42:14.223 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 0B 09 81 08 A2 00 A2 00 78 00 00 14 00 58 00 5E 00 00 ] 11:42:14.223 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 81 RPM Average Cadence: 81 RPM Total Distance: 120 m Resistance Level: 20 Instantaneous Power: 88 Watt Average Power: 94 Watt Heart Rate: 0 HBM 11:42:15.205 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 43 09 81 08 A0 00 A2 00 7E 00 00 14 00 5A 00 5E 00 00 ] 11:42:15.205 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 80 RPM Average Cadence: 81 RPM Total Distance: 126 m Resistance Level: 20 Instantaneous Power: 90 Watt Average Power: 94 Watt Heart Rate: 0 HBM 11:42:15.518 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ]
11:55:16.952 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 11:55:16.952 -> ----------------- Version 02.8 ------------------ 11:55:16.952 -> Initialise the Bluefruit nRF52 module: Client (Central) 11:55:16.952 -> FTMS and Chars 'initialized' 11:55:16.952 -> CPS and Chars 'initialized' 11:55:16.952 -> CSCS and Chars 'initialized' 11:55:16.952 -> GA and Chars 'initialized' 11:55:16.952 -> DIS and Chars 'initialized' 11:55:16.952 -> Start Scanning for CPS, CSC and FTMS! 11:55:16.952 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 11:55:16.952 -> Timestamp MAC Address Rssi Data 11:55:16.952 -> 000001201 F8:9C:FC:53:5E:49 -57 09-02-16-18-26-18-18-18-0A-18 11:55:16.952 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 11:55:16.952 -> Now checking all Client Services and Characteristics! 11:55:16.952 -> If Mandatory Services Fail --> the Client will disconnect! 11:55:16.960 -> First checking Generic Access and Device Information Services and Characteristics! 11:55:16.960 -> Found Client Generic Access 11:55:17.141 -> -> Client Reads Device Name: [Zwift Hub] 11:55:17.563 -> -> Client Reads Appearance: [0] 11:55:17.842 -> Found Client Device Information 11:55:18.310 -> -> Client Reads Manufacturer: [Zwift] 11:55:18.622 -> -> Client Reads Model Number: [06] 11:55:19.060 -> -> Client Reads Serial Number: [06-F89CFC535E49] 11:55:19.246 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 11:55:19.744 -> Discovering Client FTM Feature Characteristic ... Found it! 11:55:19.929 -> -> Client Reads Raw FTM Feature bytes: [8] [ 87 44 00 00 0C E0 00 00 ] 11:55:20.116 -> Discovering Client FTM Control Point Characteristic ... Found it! 11:55:20.660 -> Discovering Client FTM Status Characteristic ... Found it! 11:55:21.423 -> Enable Notify/Indicate of relevant Peripheral (Trainer) Characteristics 11:55:21.470 -> Discovering Client FTM Training Status Characteristic ... Ready to receive Client FTM Control Point Response Messages 11:55:21.747 -> Ready to receive Client FTM Status values 11:55:21.747 -> Not Found! Not Mandatory 11:55:21.964 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 11:55:22.147 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 00 00 00 00 ] 11:55:22.335 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 11:55:22.615 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 00 00 00 00 ] 11:55:22.802 -> Discovering Client FTM Indoor Bike Data Characteristic ... Not Found! Not Mandatory 11:55:23.068 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 11:55:23.502 -> Discovering Client CP Measurement characteristic ... Found it! 11:55:23.719 -> Discovering Client CP Control Point characteristic ... >>> Couldn't enable notify for Client FTM Training Status Characteristic. 11:55:23.856 -> Not Found! NOT Mandatory! 11:55:24.307 -> Discovering Client CP Feature characteristic ... Found it! 11:55:24.307 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 11:55:24.307 -> Wheel revolution data supported 11:55:24.307 -> Crank revolution data supported 11:55:24.572 -> Discovering Client CP Sensor Location characteristic ... Found it! 11:55:24.665 -> -> Client Reads CP Location Sensor: Loc#: 0 Other 11:55:24.930 -> Discovering Cycling Speed and Cadence (CSC) Service ... Found it! CSCS Max Payload: 20 Data Length: 27 11:55:25.565 -> Discovering Client CSC Measurement CHR ... Found it! 11:55:25.689 -> >>> Couldn't enable notify for Client FTM Indoor Bike Data Characteristic. 11:55:25.768 -> Discovering Client CSC Location CHR ... Ready to receive Client CP Measurement values 11:55:25.893 -> Found it! 11:55:25.893 -> -> Client Reads CSC Location Sensor: Loc#: 12 Rear wheel 11:55:26.207 -> Discovering Client CSC Feature CHR ... Found it! 11:55:26.207 -> -> Client Reads Raw CSC Feature bytes: [2] [ 03 00 ] 11:55:26.207 -> Wheel rev supported 11:55:26.207 -> Crank rev supported 11:55:27.766 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 11:55:27.806 -> Ready to receive Client CSC Measurement values 11:55:27.806 -> Client (Central) is Up and Running! 11:55:29.812 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 11:55:29.889 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 11:55:31.910 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ]
11:58:33.742 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 11:58:34.020 -> Discovering Client FTM Feature Characteristic ... Found it! 11:58:34.283 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 11:58:34.487 -> Discovering Client FTM Control Point Characteristic ... Found it! 11:58:35.014 -> Discovering Client FTM Status Characteristic ... Found it! 11:58:35.685 -> Enable Notify/Indicate of relevant Peripheral (Trainer) Characteristics 11:58:35.762 -> Ready to receive Client FTM Control Point Response Messages 11:58:35.762 -> Discovering Client FTM Training Status Characteristic ... Ready to receive Client FTM Status values 11:58:35.966 -> Not Found! Not Mandatory 11:58:36.151 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 11:58:36.323 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 00 00 00 00 ] 11:58:36.539 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 11:58:36.817 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 11:58:37.314 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 11:58:37.608 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 11:58:37.827 -> Discovering Client CP Measurement characteristic ... >>> Couldn't enable notify for Client FTM Training Status Characteristic. 11:58:37.905 -> Ready to receive Client FTM Indoor Bike Data values 11:58:37.905 -> Found it! 11:58:38.121 -> Ready to receive Client CP Measurement values 11:58:38.121 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 11:58:38.710 -> Discovering Client CP Feature characteristic ... Found it! 11:58:38.710 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 11:58:38.710 -> Wheel revolution data supported 11:58:38.710 -> Crank revolution data supported 11:58:39.161 -> Discovering Client CP Sensor Location characteristic ... Found it! 11:58:39.208 -> -> Client Reads CP Location Sensor: Loc#: 12 Rear wheel 11:58:39.548 -> Discovering Cycling Speed and Cadence (CSC) Service ... Found it! CSCS Max Payload: 20 Data Length: 27 11:58:39.907 -> Discovering Client CSC Measurement CHR ... Found it! 11:58:39.985 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 11:58:40.016 -> Ready to receive Client CSC Measurement values 11:58:40.016 -> Client (Central) is Up and Running! 11:58:40.110 -> Discovering Client CSC Location CHR ... Found it! 11:58:40.559 -> -> Client Reads CSC Location Sensor: Loc#: 12 Rear wheel 11:58:40.762 -> Discovering Client CSC Feature CHR ... Found it! 11:58:40.932 -> -> Client Reads Raw CSC Feature bytes: [2] [ 03 00 ] 11:58:40.932 -> Wheel rev supported 11:58:40.932 -> Crank rev supported 11:58:41.119 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 11:58:41.119 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 11:58:41.119 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 11:58:41.119 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 11:58:41.119 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 11:58:41.119 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 11:58:41.164 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 11:58:41.164 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance
:02:21.226 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 12:02:21.226 -> ----------------- Version 02.8 ------------------ 12:02:21.226 -> Initialise the Bluefruit nRF52 module: Client (Central) 12:02:21.435 -> FTMS and Chars 'initialized' 12:02:21.435 -> CPS and Chars 'initialized' 12:02:21.435 -> CSCS and Chars 'initialized' 12:02:21.435 -> GA and Chars 'initialized' 12:02:21.435 -> DIS and Chars 'initialized' 12:02:21.435 -> Start Scanning for CPS, CSC and FTMS! 12:02:21.435 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 12:02:21.435 -> Timestamp MAC Address Rssi Data 12:02:21.435 -> 000001359 F8:9C:FC:53:5E:49 -54 09-02-16-18-26-18-18-18-0A-18 12:02:21.440 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 12:02:21.440 -> Now checking all Client Services and Characteristics! 12:02:21.440 -> If Mandatory Services Fail --> the Client will disconnect! 12:02:21.468 -> First checking Generic Access and Device Information Services and Characteristics! 12:02:21.604 -> Found Client Generic Access 12:02:21.959 -> -> Client Reads Device Name: [Zwift Hub] 12:02:22.503 -> -> Client Reads Appearance: [1152] 12:02:22.831 -> Found Client Device Information 12:02:23.268 -> -> Client Reads Manufacturer: [Zwift] 12:02:24.091 -> -> Client Reads Serial Number: [06-F89CFC535E49] 12:02:24.296 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 12:02:24.574 -> Discovering Client FTM Feature Characteristic ... Found it! 12:02:24.716 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 12:02:24.946 -> Discovering Client FTM Control Point Characteristic ... Not Found! 12:02:24.946 -> Disconnecting since Client FTM Control Point Characteristic is mandatory! 12:02:24.993 -> Client Disconnected, reason = 0x16 12:02:24.993 -> >>> Restart the Feather nRF52 Client for a new run! <<< 12:02:26.206 -> Stopped! 12:02:46.062 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 12:02:46.062 -> ----------------- Version 02.8 ------------------ 12:02:46.062 -> Initialise the Bluefruit nRF52 module: Client (Central) 12:02:46.062 -> FTMS and Chars 'initialized' 12:02:46.062 -> CPS and Chars 'initialized' 12:02:46.062 -> CSCS and Chars 'initialized' 12:02:46.062 -> GA and Chars 'initialized' 12:02:46.062 -> DIS and Chars 'initialized' 12:02:46.062 -> Start Scanning for CPS, CSC and FTMS! 12:02:46.478 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 12:02:46.478 -> Timestamp MAC Address Rssi Data 12:02:46.478 -> 000001488 F8:9C:FC:53:5E:49 -52 09-02-16-18-26-18-18-18-0A-18 12:02:46.500 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 12:02:46.500 -> Now checking all Client Services and Characteristics! 12:02:46.500 -> If Mandatory Services Fail --> the Client will disconnect! 12:02:46.500 -> First checking Generic Access and Device Information Services and Characteristics! 12:02:46.592 -> Found Client Generic Access 12:02:46.964 -> -> Client Reads Device Name: [Zwift Hub] 12:02:47.320 -> -> Client Reads Appearance: [1152] 12:02:47.583 -> Found Client Device Information 12:02:47.880 -> -> Client Reads Manufacturer: [Zwift] 12:02:48.252 -> -> Client Reads Model Number: [06] 12:02:48.655 -> -> Client Reads Serial Number: [06-F89CFC535E49] 12:02:48.842 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 12:02:49.124 -> Discovering Client FTM Feature Characteristic ... Found it! 12:02:49.340 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 12:02:49.560 -> Discovering Client FTM Control Point Characteristic ... Found it! 12:02:50.137 -> Discovering Client FTM Status Characteristic ... Found it! 12:02:50.586 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 12:02:50.977 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Enable Notify/Indicate of relevant Peripheral (Trainer) Characteristics 12:02:51.020 -> Found it! 12:02:51.020 -> Ready to receive Client FTM Control Point Response Messages 12:02:51.066 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 12:02:51.252 -> Ready to receive Client FTM Status values 12:02:51.252 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 12:02:51.518 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 12:02:51.920 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 12:02:52.156 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 12:02:52.620 -> Discovering Client CP Measurement characteristic ... Found it! 12:02:52.979 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 12:02:53.119 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 12:02:53.165 -> Discovering Client CP Feature characteristic ... Ready to receive Client FTM Indoor Bike Data values 12:02:53.229 -> Found it! 12:02:53.229 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 12:02:53.229 -> Wheel revolution data supported 12:02:53.229 -> Crank revolution data supported 12:02:53.229 -> Ready to receive Client CP Measurement values 12:02:53.514 -> Discovering Client CP Sensor Location characteristic ... Found it! 12:02:53.607 -> -> Client Reads CP Location Sensor: Loc#: 12 Rear wheel 12:02:53.918 -> Discovering Cycling Speed and Cadence (CSC) Service ... Found it! CSCS Max Payload: 20 Data Length: 27 12:02:54.540 -> Discovering Client CSC Measurement CHR ... Found it! 12:02:54.898 -> Discovering Client CSC Location CHR ... Found it! 12:02:54.898 -> -> Client Reads CSC Location Sensor: Loc#: 12 Rear wheel 12:02:55.256 -> Discovering Client CSC Feature CHR ... Found it! 12:02:55.256 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 12:02:55.302 -> -> Client Reads Raw CSC Feature bytes: [2] [ 03 00 ] 12:02:55.302 -> Wheel rev supported 12:02:55.302 -> Crank rev supported 12:02:55.302 -> Ready to receive Client CSC Measurement values 12:02:55.302 -> Client (Central) is Up and Running! 12:02:55.489 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 12:02:55.489 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 12:02:55.489 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 12:02:55.489 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 12:02:56.207 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 12:02:56.207 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 12:02:57.216 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 12:02:57.216 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 12:02:57.293 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 12:02:57.371 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ]
Pfff, I cannot deny that I feel relieved! How come I did not propose this solution earlier? So stupid! It popped up only yesterday evening after I had studied and compared all your recent test results...
Even your HBM is zero now! Never thought you would be happy with such a result! 😉
If you want to, you can finetune the delay(SOME_TIME); and reach 10 out of 10 !!!
Have a nice weekend!
Op za 17 dec. 2022 12:18 schreef le-joebar @.***>:
Dear Jörghen,
I had to increase the delay to 200 The system starts in any direction 9/10 times
I have given you several examples of start-ups because I believe that certain services are there at certain start-ups and not at others!
The resistance is well felt during the test :)
JACKPOT !!!!!!! Congratulation !!! 👍
11:40:31.097 -> -> Client Reads Appearance: [1152] 11:40:31.210 -> Found Client Device Information 11:40:31.489 -> -> Client Reads Manufacturer: [Zwift] 11:40:31.944 -> -> Client Reads Model Number: [06] 11:40:32.161 -> -> Client Reads Serial Number: [06-F89CFC535E49] 11:40:32.302 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 11:40:32.537 -> Discovering Client FTM Feature Characteristic ... Found it! 11:40:32.742 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 11:40:32.835 -> Discovering Client FTM Control Point Characteristic ... Found it! 11:40:33.212 -> Discovering Client FTM Status Characteristic ... Found it! 11:40:33.620 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 11:40:34.229 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 11:40:34.403 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 11:40:34.497 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 11:40:34.747 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 00 00 00 00 ] 11:40:34.839 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 11:40:35.057 -> Enable Notify/Indicate of relevant Peripheral (Trainer) Characteristics 11:40:35.134 -> Discovering Client Cycling Power (CP) Service ... Ready to receive Client FTM Control Point Response Messages 11:40:35.181 -> Found it! CPS Max Payload: 20 Data Length: 27 11:40:35.273 -> Ready to receive Client FTM Status values 11:40:35.273 -> Discovering Client CP Measurement characteristic ... Found it! 11:40:35.756 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 11:40:36.023 -> Discovering Client CP Feature characteristic ... Found it! 11:40:36.023 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 11:40:36.023 -> Wheel revolution data supported 11:40:36.023 -> Crank revolution data supported 11:40:36.162 -> Discovering Client CP Sensor Location characteristic ... Found it! 11:40:36.255 -> -> Client Reads CP Location Sensor: Loc#: 0 Other 11:40:36.379 -> Discovering Cycling Speed and Cadence (CSC) Service ... Not Found! CSC Service is Not Mandatory! 11:40:37.221 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 11:40:37.300 -> Ready to receive Client FTM Indoor Bike Data values 11:40:37.300 -> Ready to receive Client CP Measurement values 11:40:38.365 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 11:40:38.365 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 11:40:39.220 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 0B 02 00 00 14 00 00 00 00 ] 11:40:39.220 -> Instant. Speed: 5 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 11:40:39.314 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 11:40:40.385 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 07 03 00 00 14 00 11 00 00 ] 11:40:40.385 -> Instant. Speed: 7 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 17 Watt Heart Rate: 0 HBM 11:40:41.272 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 58 04 00 00 14 00 40 00 00 ] 11:40:41.272 -> Instant. Speed: 11 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 64 Watt Heart Rate: 0 HBM 11:40:41.320 -> >>> Couldn't enable notify for Client CSC Measurement Characteristic. 11:40:41.320 -> Client (Central) is Up and Running! 11:40:42.206 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 78 05 00 00 14 00 90 00 00 ] 11:40:42.206 -> Instant. Speed: 14 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 144 Watt Heart Rate: 0 HBM 11:40:43.237 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 CF 05 20 00 14 00 71 00 00 ] 11:40:43.237 -> Instant. Speed: 14 KPH Instantaneous Cadence: 16 RPM Resistance Level: 20 Instantaneous Power: 113 Watt Heart Rate: 0 HBM 11:40:43.315 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 11:40:43.581 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 11:40:44.313 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 25 06 46 00 14 00 71 00 00 ] 11:40:44.313 -> Instant. Speed: 15 KPH Instantaneous Cadence: 35 RPM Resistance Level: 20 Instantaneous Power: 113 Watt Heart Rate: 0 HBM 11:40:45.311 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 96 06 5A 00 14 00 94 00 00 ] 11:40:45.311 -> Instant. Speed: 16 KPH Instantaneous Cadence: 45 RPM Resistance Level: 20 Instantaneous Power: 148 Watt Heart Rate: 0 HBM 11:40:45.405 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 11:40:45.763 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 11:40:46.212 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 D5 06 68 00 14 00 7E 00 00 ] 11:40:46.212 -> Instant. Speed: 17 KPH Instantaneous Cadence: 52 RPM Resistance Level: 20 Instantaneous Power: 126 Watt Heart Rate: 0 HBM 11:40:47.194 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 16 07 72 00 14 00 6D 00 00 ] 11:40:47.194 -> Instant. Speed: 18 KPH Instantaneous Cadence: 57 RPM Resistance Level: 20 Instantaneous Power: 109 Watt Heart Rate: 0 HBM 11:40:47.506 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 11:40:47.646 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 11:40:47.646 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 11:40:48.206 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 71 07 17 07 7A 00 7A 00 05 00 00 14 00 61 00 61 00 00 ] 11:40:48.206 -> Instant. Speed: 19 KPH Average Speed: 18 KPH Instantaneous Cadence: 61 RPM Average Cadence: 61 RPM Total Distance: 5 m Resistance Level: 20 Instantaneous Power: 97 Watt Average Power: 97 Watt Heart Rate: 0 HBM 11:40:49.611 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 11:40:49.690 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 EC 07 17 07 80 00 7D 00 0A 00 00 14 00 62 00 61 00 00 ] 11:40:49.737 -> Instant. Speed: 20 KPH Average Speed: 18 KPH Instantaneous Cadence: 64 RPM Average Cadence: 62 RPM Total Distance: 10 m Resistance Level: 20 Instantaneous Power: 98 Watt Average Power: 97 Watt Heart Rate: 0 HBM 11:40:49.814 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:40:49.814 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 11:40:50.545 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 1E 08 17 07 82 00 7E 00 0F 00 00 14 00 63 00 62 00 00 ] 11:40:50.545 -> Instant. Speed: 20 KPH Average Speed: 18 KPH Instantaneous Cadence: 65 RPM Average Cadence: 63 RPM Total Distance: 15 m Resistance Level: 20 Instantaneous Power: 99 Watt Average Power: 98 Watt Heart Rate: 0 HBM 11:40:51.247 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 D3 07 17 07 86 00 80 00 14 00 00 14 00 5F 00 61 00 00 ] 11:40:51.247 -> Instant. Speed: 20 KPH Average Speed: 18 KPH Instantaneous Cadence: 67 RPM Average Cadence: 64 RPM Total Distance: 20 m Resistance Level: 20 Instantaneous Power: 95 Watt Average Power: 97 Watt Heart Rate: 0 HBM 11:40:51.715 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 00 28 33 00 ] 11:40:51.887 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:40:51.887 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 11:40:52.338 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A2 07 17 07 88 00 82 00 19 00 00 14 00 6A 00 63 00 00 ] 11:40:52.338 -> Instant. Speed: 19 KPH Average Speed: 18 KPH Instantaneous Cadence: 68 RPM Average Cadence: 65 RPM Total Distance: 25 m Resistance Level: 20 Instantaneous Power: 106 Watt Average Power: 99 Watt Heart Rate: 0 HBM 11:40:53.228 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 19 08 17 07 88 00 83 00 1E 00 00 14 00 85 00 68 00 00 ] 11:40:53.228 -> Instant. Speed: 20 KPH Average Speed: 18 KPH Instantaneous Cadence: 68 RPM Average Cadence: 65 RPM Total Distance: 30 m Resistance Level: 20 Instantaneous Power: 133 Watt Average Power: 104 Watt Heart Rate: 0 HBM 11:40:53.821 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 11:40:54.224 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:40:54.224 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 11:40:54.224 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 38 08 17 07 88 00 83 00 23 00 00 14 00 74 00 6A 00 00 ] 11:40:54.224 -> Instant. Speed: 21 KPH Average Speed: 18 KPH Instantaneous Cadence: 68 RPM Average Cadence: 65 RPM Total Distance: 35 m Resistance Level: 20 Instantaneous Power: 116 Watt Average Power: 106 Watt Heart Rate: 0 HBM 11:40:55.302 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 4E 08 17 07 8A 00 84 00 28 00 00 14 00 67 00 69 00 00 ] 11:40:55.302 -> Instant. Speed: 21 KPH Average Speed: 18 KPH Instantaneous Cadence: 69 RPM Average Cadence: 66 RPM Total Distance: 40 m Resistance Level: 20 Instantaneous Power: 103 Watt Average Power: 105 Watt Heart Rate: 0 HBM 11:40:55.908 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 14 00 28 33 00 ] 11:40:56.034 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:40:56.034 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 00 28 33 ] 11:40:56.206 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 D1 08 3F 07 8C 00 85 00 2E 00 00 14 00 57 00 67 00 00 ] 11:40:56.206 -> Instant. Speed: 22 KPH Average Speed: 18 KPH Instantaneous Cadence: 70 RPM Average Cadence: 66 RPM Total Distance: 46 m Resistance Level: 20 Instantaneous Power: 87 Watt Average Power: 103 Watt Heart Rate: 0 HBM 11:40:57.159 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 7F 08 3B 07 94 00 86 00 33 00 00 14 00 5A 00 66 00 00 ] 11:40:57.205 -> Instant. Speed: 21 KPH Average Speed: 18 KPH Instantaneous Cadence: 74 RPM Average Cadence: 67 RPM Total Distance: 51 m Resistance Level: 20 Instantaneous Power: 90 Watt Average Power: 102 Watt Heart Rate: 0 HBM 11:40:57.986 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 00 28 33 00 ] 11:40:58.159 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:40:58.159 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 00 28 33 ] 11:40:58.284 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 AC 08 58 07 96 00 88 00 39 00 00 14 00 47 00 63 00 00 ] 11:40:58.284 -> Instant. Speed: 22 KPH Average Speed: 18 KPH Instantaneous Cadence: 75 RPM Average Cadence: 68 RPM Total Distance: 57 m Resistance Level: 20 Instantaneous Power: 71 Watt Average Power: 99 Watt Heart Rate: 0 HBM 11:40:59.254 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 84 08 71 07 96 00 89 00 3F 00 00 14 00 58 00 62 00 00 ] 11:40:59.254 -> Instant. Speed: 21 KPH Average Speed: 19 KPH Instantaneous Cadence: 75 RPM Average Cadence: 68 RPM Total Distance: 63 m Resistance Level: 20 Instantaneous Power: 88 Watt Average Power: 98 Watt Heart Rate: 0 HBM 11:41:00.125 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 25 00 28 33 00 ] 11:41:00.344 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E7 08 86 07 20 00 81 00 45 00 00 14 00 5F 00 62 00 00 ] 11:41:00.344 -> Instant. Speed: 22 KPH Average Speed: 19 KPH Instantaneous Cadence: 16 RPM Average Cadence: 64 RPM Total Distance: 69 m Resistance Level: 20 Instantaneous Power: 95 Watt Average Power: 98 Watt Heart Rate: 0 HBM 11:41:00.344 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:00.344 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 25 00 28 33 ] 11:41:01.324 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 C5 08 98 07 6E 00 7F 00 4B 00 00 14 00 57 00 61 00 00 ] 11:41:01.324 -> Instant. Speed: 22 KPH Average Speed: 19 KPH Instantaneous Cadence: 55 RPM Average Cadence: 63 RPM Total Distance: 75 m Resistance Level: 20 Instantaneous Power: 87 Watt Average Power: 97 Watt Heart Rate: 0 HBM 11:41:02.199 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 23 00 28 33 00 ] 11:41:02.245 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 B2 08 A8 07 8C 00 80 00 51 00 00 14 00 5C 00 61 00 00 ] 11:41:02.245 -> Instant. Speed: 22 KPH Average Speed: 19 KPH Instantaneous Cadence: 70 RPM Average Cadence: 64 RPM Total Distance: 81 m Resistance Level: 20 Instantaneous Power: 92 Watt Average Power: 97 Watt Heart Rate: 0 HBM 11:41:02.245 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:02.245 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 00 28 33 ] 11:41:03.228 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 BB 08 B5 07 94 00 81 00 57 00 00 14 00 5D 00 60 00 00 ] 11:41:03.228 -> Instant. Speed: 22 KPH Average Speed: 19 KPH Instantaneous Cadence: 74 RPM Average Cadence: 64 RPM Total Distance: 87 m Resistance Level: 20 Instantaneous Power: 93 Watt Average Power: 96 Watt Heart Rate: 0 HBM 11:41:04.228 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 1C 00 28 33 00 ] 11:41:04.306 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 07 09 C1 07 94 00 82 00 5D 00 00 14 00 55 00 60 00 00 ] 11:41:04.306 -> Instant. Speed: 23 KPH Average Speed: 19 KPH Instantaneous Cadence: 74 RPM Average Cadence: 65 RPM Total Distance: 93 m Resistance Level: 20 Instantaneous Power: 85 Watt Average Power: 96 Watt Heart Rate: 0 HBM 11:41:04.400 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:04.400 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 00 28 33 ] 11:41:05.210 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 D4 08 CC 07 98 00 84 00 63 00 00 14 00 5B 00 5F 00 00 ] 11:41:05.210 -> Instant. Speed: 22 KPH Average Speed: 19 KPH Instantaneous Cadence: 76 RPM Average Cadence: 66 RPM Total Distance: 99 m Resistance Level: 20 Instantaneous Power: 91 Watt Average Power: 95 Watt Heart Rate: 0 HBM 11:41:06.189 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E1 08 D5 07 9C 00 85 00 69 00 00 14 00 5E 00 5F 00 00 ] 11:41:06.190 -> Instant. Speed: 22 KPH Average Speed: 20 KPH Instantaneous Cadence: 78 RPM Average Cadence: 66 RPM Total Distance: 105 m Resistance Level: 20 Instantaneous Power: 94 Watt Average Power: 95 Watt Heart Rate: 0 HBM 11:41:06.329 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 0F 00 28 33 00 ] 11:41:06.829 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:06.829 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 0F 00 28 33 ] 11:41:07.264 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 BD 08 DE 07 9C 00 86 00 6F 00 00 14 00 61 00 5F 00 00 ] 11:41:07.264 -> Instant. Speed: 22 KPH Average Speed: 20 KPH Instantaneous Cadence: 78 RPM Average Cadence: 67 RPM Total Distance: 111 m Resistance Level: 20 Instantaneous Power: 97 Watt Average Power: 95 Watt Heart Rate: 0 HBM 11:41:08.339 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 1F 09 E6 07 98 00 87 00 75 00 00 14 00 58 00 5F 00 00 ] 11:41:08.339 -> Instant. Speed: 23 KPH Average Speed: 20 KPH Instantaneous Cadence: 76 RPM Average Cadence: 67 RPM Total Distance: 117 m Resistance Level: 20 Instantaneous Power: 88 Watt Average Power: 95 Watt Heart Rate: 0 HBM 11:41:08.431 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 11:41:08.618 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:08.618 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 11:41:09.414 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 D6 08 ED 07 9E 00 88 00 7B 00 00 14 00 54 00 5E 00 00 ] 11:41:09.414 -> Instant. Speed: 22 KPH Average Speed: 20 KPH Instantaneous Cadence: 79 RPM Average Cadence: 68 RPM Total Distance: 123 m Resistance Level: 20 Instantaneous Power: 84 Watt Average Power: 94 Watt Heart Rate: 0 HBM 11:41:10.240 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E6 08 F3 07 A2 00 89 00 81 00 00 14 00 53 00 5E 00 00 ] 11:41:10.240 -> Instant. Speed: 22 KPH Average Speed: 20 KPH Instantaneous Cadence: 81 RPM Average Cadence: 68 RPM Total Distance: 129 m Resistance Level: 20 Instantaneous Power: 83 Watt Average Power: 94 Watt Heart Rate: 0 HBM 11:41:10.550 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 F5 FF 28 33 00 ] 11:41:10.691 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:10.691 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 F5 FF 28 33 ] 11:41:11.235 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 C4 08 F9 07 9C 00 8A 00 87 00 00 14 00 44 00 5D 00 00 ] 11:41:11.235 -> Instant. Speed: 22 KPH Average Speed: 20 KPH Instantaneous Cadence: 78 RPM Average Cadence: 69 RPM Total Distance: 135 m Resistance Level: 20 Instantaneous Power: 68 Watt Average Power: 93 Watt Heart Rate: 0 HBM 11:41:12.235 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 04 09 FF 07 9C 00 8A 00 8D 00 00 14 00 43 00 5C 00 00 ] 11:41:12.235 -> Instant. Speed: 23 KPH Average Speed: 20 KPH Instantaneous Cadence: 78 RPM Average Cadence: 69 RPM Total Distance: 141 m Resistance Level: 20 Instantaneous Power: 67 Watt Average Power: 92 Watt Heart Rate: 0 HBM 11:41:12.639 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 E4 FF 28 33 00 ] 11:41:12.857 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:12.857 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 E4 FF 28 33 ] 11:41:13.217 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 09 09 04 08 A0 00 8B 00 93 00 00 14 00 4C 00 5B 00 00 ] 11:41:13.217 -> Instant. Speed: 23 KPH Average Speed: 20 KPH Instantaneous Cadence: 80 RPM Average Cadence: 69 RPM Total Distance: 147 m Resistance Level: 20 Instantaneous Power: 76 Watt Average Power: 91 Watt Heart Rate: 0 HBM 11:41:14.169 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E7 08 08 08 9E 00 8C 00 99 00 00 14 00 4A 00 5B 00 00 ] 11:41:14.216 -> Instant. Speed: 22 KPH Average Speed: 20 KPH Instantaneous Cadence: 79 RPM Average Cadence: 70 RPM Total Distance: 153 m Resistance Level: 20 Instantaneous Power: 74 Watt Average Power: 91 Watt Heart Rate: 0 HBM 11:41:14.745 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 CF FF 28 33 00 ] 11:41:14.902 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:14.902 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 CF FF 28 33 ] 11:41:15.183 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 1D 09 0D 08 9E 00 8D 00 9F 00 00 14 00 48 00 5A 00 00 ] 11:41:15.183 -> Instant. Speed: 23 KPH Average Speed: 20 KPH Instantaneous Cadence: 79 RPM Average Cadence: 70 RPM Total Distance: 159 m Resistance Level: 20 Instantaneous Power: 72 Watt Average Power: 90 Watt Heart Rate: 0 HBM 11:41:16.368 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 1E 09 11 08 A0 00 8D 00 A5 00 00 14 00 49 00 59 00 00 ] 11:41:16.368 -> Instant. Speed: 23 KPH Average Speed: 20 KPH Instantaneous Cadence: 80 RPM Average Cadence: 70 RPM Total Distance: 165 m Resistance Level: 20 Instantaneous Power: 73 Watt Average Power: 89 Watt Heart Rate: 0 HBM 11:41:16.853 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A8 FF 28 33 00 ] 11:41:16.992 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:16.992 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A8 FF 28 33 ] 11:41:17.366 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 17 09 14 08 9E 00 8E 00 AB 00 00 14 00 3F 00 58 00 00 ] 11:41:17.366 -> Instant. Speed: 23 KPH Average Speed: 20 KPH Instantaneous Cadence: 79 RPM Average Cadence: 71 RPM Total Distance: 171 m Resistance Level: 20 Instantaneous Power: 63 Watt Average Power: 88 Watt Heart Rate: 0 HBM 11:41:18.255 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 6F 09 18 08 A2 00 8E 00 B1 00 00 14 00 44 00 58 00 00 ] 11:41:18.255 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 81 RPM Average Cadence: 71 RPM Total Distance: 177 m Resistance Level: 20 Instantaneous Power: 68 Watt Average Power: 88 Watt Heart Rate: 0 HBM 11:41:18.941 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 84 FF 28 33 00 ] 11:41:19.158 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:19.158 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 84 FF 28 33 ] 11:41:19.252 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 65 09 1B 08 9E 00 8F 00 B7 00 00 14 00 4E 00 57 00 00 ] 11:41:19.252 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 79 RPM Average Cadence: 71 RPM Total Distance: 183 m Resistance Level: 20 Instantaneous Power: 78 Watt Average Power: 87 Watt Heart Rate: 0 HBM 11:41:20.216 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 5B 09 1E 08 A6 00 90 00 BD 00 00 14 00 39 00 56 00 00 ] 11:41:20.216 -> Instant. Speed: 23 KPH Average Speed: 20 KPH Instantaneous Cadence: 83 RPM Average Cadence: 72 RPM Total Distance: 189 m Resistance Level: 20 Instantaneous Power: 57 Watt Average Power: 86 Watt Heart Rate: 0 HBM 11:41:21.042 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 FF 28 33 00 ] 11:41:21.215 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 9C 09 21 08 B0 00 91 00 C3 00 00 14 00 32 00 55 00 00 ] 11:41:21.215 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 88 RPM Average Cadence: 72 RPM Total Distance: 195 m Resistance Level: 20 Instantaneous Power: 50 Watt Average Power: 85 Watt Heart Rate: 0 HBM 11:41:21.215 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:21.215 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 FF 28 33 ] 11:41:22.182 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A5 09 24 08 B0 00 91 00 C9 00 00 14 00 3A 00 55 00 00 ] 11:41:22.182 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 88 RPM Average Cadence: 72 RPM Total Distance: 201 m Resistance Level: 20 Instantaneous Power: 58 Watt Average Power: 85 Watt Heart Rate: 0 HBM 11:41:23.149 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5D FF 28 33 00 ] 11:41:23.196 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 8D 09 27 08 A2 00 92 00 CF 00 00 14 00 26 00 53 00 00 ] 11:41:23.196 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 81 RPM Average Cadence: 73 RPM Total Distance: 207 m Resistance Level: 20 Instantaneous Power: 38 Watt Average Power: 83 Watt Heart Rate: 0 HBM 11:41:23.196 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:23.196 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5D FF 28 33 ] 11:41:24.179 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 AC 09 29 08 8A 00 92 00 D5 00 00 14 00 26 00 52 00 00 ] 11:41:24.179 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 69 RPM Average Cadence: 73 RPM Total Distance: 213 m Resistance Level: 20 Instantaneous Power: 38 Watt Average Power: 82 Watt Heart Rate: 0 HBM 11:41:25.221 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5E FF 28 33 00 ] 11:41:25.441 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 7D 09 2B 08 66 00 90 00 DB 00 00 14 00 29 00 51 00 00 ] 11:41:25.441 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 51 RPM Average Cadence: 72 RPM Total Distance: 219 m Resistance Level: 20 Instantaneous Power: 41 Watt Average Power: 81 Watt Heart Rate: 0 HBM 11:41:25.549 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:25.549 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5E FF 28 33 ] 11:41:26.249 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 8C 09 2E 08 5A 00 8F 00 E1 00 00 14 00 29 00 50 00 00 ] 11:41:26.249 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 45 RPM Average Cadence: 71 RPM Total Distance: 225 m Resistance Level: 20 Instantaneous Power: 41 Watt Average Power: 80 Watt Heart Rate: 0 HBM 11:41:27.260 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 9A 09 30 08 5E 00 8E 00 E7 00 00 14 00 26 00 4F 00 00 ] 11:41:27.260 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 47 RPM Average Cadence: 71 RPM Total Distance: 231 m Resistance Level: 20 Instantaneous Power: 38 Watt Average Power: 79 Watt Heart Rate: 0 HBM 11:41:27.307 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 6F FF 28 33 00 ] 11:41:27.447 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:27.447 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 6F FF 28 33 ] 11:41:28.242 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 87 09 32 08 66 00 8D 00 ED 00 00 14 00 22 00 4E 00 00 ] 11:41:28.242 -> Instant. Speed: 24 KPH Average Speed: 20 KPH Instantaneous Cadence: 51 RPM Average Cadence: 70 RPM Total Distance: 237 m Resistance Level: 20 Instantaneous Power: 34 Watt Average Power: 78 Watt Heart Rate: 0 HBM 11:41:29.224 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 5C 09 34 08 66 00 8C 00 F3 00 00 14 00 2E 00 4D 00 00 ] 11:41:29.224 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 51 RPM Average Cadence: 70 RPM Total Distance: 243 m Resistance Level: 20 Instantaneous Power: 46 Watt Average Power: 77 Watt Heart Rate: 0 HBM 11:41:29.410 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 8A FF 28 33 00 ] 11:41:29.782 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:29.782 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8A FF 28 33 ] 11:41:30.296 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 EB 08 35 08 00 00 89 00 F9 00 00 14 00 00 00 4B 00 00 ] 11:41:30.296 -> Instant. Speed: 22 KPH Average Speed: 21 KPH Instantaneous Cadence: 0 RPM Average Cadence: 68 RPM Total Distance: 249 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 75 Watt Heart Rate: 0 HBM 11:41:31.196 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 AA 09 37 08 00 00 86 00 FF 00 00 14 00 00 00 49 00 00 ] 11:41:31.196 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 0 RPM Average Cadence: 67 RPM Total Distance: 255 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 73 Watt Heart Rate: 0 HBM 11:41:31.523 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 B8 FF 28 33 00 ] 11:41:31.757 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:31.757 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 B8 FF 28 33 ] 11:41:32.458 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 CB 09 39 08 50 00 84 00 05 01 00 14 00 35 00 49 00 00 ] 11:41:32.458 -> Instant. Speed: 25 KPH Average Speed: 21 KPH Instantaneous Cadence: 40 RPM Average Cadence: 66 RPM Total Distance: 261 m Resistance Level: 20 Instantaneous Power: 53 Watt Average Power: 73 Watt Heart Rate: 0 HBM 11:41:33.472 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E4 09 3A 08 56 00 83 00 0B 01 00 14 00 33 00 48 00 00 ] 11:41:33.472 -> Instant. Speed: 25 KPH Average Speed: 21 KPH Instantaneous Cadence: 43 RPM Average Cadence: 65 RPM Total Distance: 267 m Resistance Level: 20 Instantaneous Power: 51 Watt Average Power: 72 Watt Heart Rate: 0 HBM 11:41:33.612 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 11:41:33.830 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:33.830 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 11:41:34.376 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 25 0A 44 08 56 00 82 00 12 01 00 14 00 33 00 48 00 00 ] 11:41:34.376 -> Instant. Speed: 25 KPH Average Speed: 21 KPH Instantaneous Cadence: 43 RPM Average Cadence: 65 RPM Total Distance: 274 m Resistance Level: 20 Instantaneous Power: 51 Watt Average Power: 72 Watt Heart Rate: 0 HBM 11:41:35.450 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 1B 0A 4C 08 54 00 81 00 19 01 00 14 00 2E 00 47 00 00 ] 11:41:35.450 -> Instant. Speed: 25 KPH Average Speed: 21 KPH Instantaneous Cadence: 42 RPM Average Cadence: 64 RPM Total Distance: 281 m Resistance Level: 20 Instantaneous Power: 46 Watt Average Power: 71 Watt Heart Rate: 0 HBM 11:41:35.712 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A2 00 28 33 00 ] 11:41:35.993 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:35.993 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A2 00 28 33 ] 11:41:36.259 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 1F 0A 55 08 5E 00 81 00 20 01 00 14 00 27 00 47 00 00 ] 11:41:36.259 -> Instant. Speed: 25 KPH Average Speed: 21 KPH Instantaneous Cadence: 47 RPM Average Cadence: 64 RPM Total Distance: 288 m Resistance Level: 20 Instantaneous Power: 39 Watt Average Power: 71 Watt Heart Rate: 0 HBM 11:41:37.320 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 AE 09 56 08 64 00 80 00 26 01 00 14 00 27 00 46 00 00 ] 11:41:37.320 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 50 RPM Average Cadence: 64 RPM Total Distance: 294 m Resistance Level: 20 Instantaneous Power: 39 Watt Average Power: 70 Watt Heart Rate: 0 HBM 11:41:37.818 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 01 28 33 00 ] 11:41:38.148 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:38.148 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 01 28 33 ] 11:41:38.241 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 65 09 57 08 5C 00 7F 00 2C 01 00 14 00 1F 00 45 00 00 ] 11:41:38.241 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 46 RPM Average Cadence: 63 RPM Total Distance: 300 m Resistance Level: 20 Instantaneous Power: 31 Watt Average Power: 69 Watt Heart Rate: 0 HBM 11:41:39.209 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 0B 09 57 08 54 00 7E 00 32 01 00 14 00 1F 00 45 00 00 ] 11:41:39.209 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 42 RPM Average Cadence: 63 RPM Total Distance: 306 m Resistance Level: 20 Instantaneous Power: 31 Watt Average Power: 69 Watt Heart Rate: 0 HBM 11:41:39.909 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 4F 01 28 33 00 ] 11:41:40.021 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:40.021 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 4F 01 28 33 ] 11:41:40.301 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 19 09 58 08 50 00 7E 00 38 01 00 14 00 4C 00 45 00 00 ] 11:41:40.301 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 40 RPM Average Cadence: 63 RPM Total Distance: 312 m Resistance Level: 20 Instantaneous Power: 76 Watt Average Power: 69 Watt Heart Rate: 0 HBM 11:41:41.281 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 8B 08 59 08 50 00 7D 00 3E 01 00 14 00 7A 00 46 00 00 ] 11:41:41.281 -> Instant. Speed: 21 KPH Average Speed: 21 KPH Instantaneous Cadence: 40 RPM Average Cadence: 62 RPM Total Distance: 318 m Resistance Level: 20 Instantaneous Power: 122 Watt Average Power: 70 Watt Heart Rate: 0 HBM 11:41:41.999 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 01 28 33 00 ] 11:41:42.203 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:42.203 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 01 28 33 ] 11:41:42.203 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E7 08 5A 08 30 00 7B 00 44 01 00 14 00 7A 00 47 00 00 ] 11:41:42.203 -> Instant. Speed: 22 KPH Average Speed: 21 KPH Instantaneous Cadence: 24 RPM Average Cadence: 61 RPM Total Distance: 324 m Resistance Level: 20 Instantaneous Power: 122 Watt Average Power: 71 Watt Heart Rate: 0 HBM 11:41:43.463 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 27 08 54 08 70 00 7B 00 49 01 00 14 00 62 00 47 00 00 ] 11:41:43.463 -> Instant. Speed: 20 KPH Average Speed: 21 KPH Instantaneous Cadence: 56 RPM Average Cadence: 61 RPM Total Distance: 329 m Resistance Level: 20 Instantaneous Power: 98 Watt Average Power: 71 Watt Heart Rate: 0 HBM 11:41:44.118 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 57 FF 28 33 00 ] 11:41:44.258 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 85 08 55 08 86 00 7B 00 4F 01 00 14 00 C1 00 49 00 00 ] 11:41:44.258 -> Instant. Speed: 21 KPH Average Speed: 21 KPH Instantaneous Cadence: 67 RPM Average Cadence: 61 RPM Total Distance: 335 m Resistance Level: 20 Instantaneous Power: 193 Watt Average Power: 73 Watt Heart Rate: 0 HBM 11:41:44.337 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:44.337 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 57 FF 28 33 ] 11:41:45.414 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E0 08 55 08 8C 00 7C 00 55 01 00 14 00 B9 00 4B 00 00 ] 11:41:45.414 -> Instant. Speed: 22 KPH Average Speed: 21 KPH Instantaneous Cadence: 70 RPM Average Cadence: 62 RPM Total Distance: 341 m Resistance Level: 20 Instantaneous Power: 185 Watt Average Power: 75 Watt Heart Rate: 0 HBM 11:41:46.191 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 08 00 00 00 00 00 00 00 ] 11:41:46.238 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 28 09 56 08 8E 00 7C 00 5B 01 00 14 00 C6 00 4D 00 00 ] 11:41:46.238 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 71 RPM Average Cadence: 62 RPM Total Distance: 347 m Resistance Level: 20 Instantaneous Power: 198 Watt Average Power: 77 Watt Heart Rate: 0 HBM 11:41:46.238 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 08 03 ] 11:41:47.396 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 38 09 57 08 98 00 7C 00 61 01 00 14 00 71 00 4E 00 00 ] 11:41:47.396 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 76 RPM Average Cadence: 62 RPM Total Distance: 353 m Resistance Level: 20 Instantaneous Power: 113 Watt Average Power: 78 Watt Heart Rate: 0 HBM 11:41:48.212 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 81 09 58 08 9E 00 7D 00 67 01 00 14 00 3F 00 4E 00 00 ] 11:41:48.212 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 79 RPM Average Cadence: 62 RPM Total Distance: 359 m Resistance Level: 20 Instantaneous Power: 63 Watt Average Power: 78 Watt Heart Rate: 0 HBM 11:41:48.253 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 01 00 00 00 00 00 00 00 ] 11:41:48.394 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 01 01 ] 11:41:48.394 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 01 ] 11:41:49.269 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 C7 09 A6 00 14 00 31 00 00 ] 11:41:49.315 -> Instant. Speed: 25 KPH Instantaneous Cadence: 83 RPM Resistance Level: 20 Instantaneous Power: 49 Watt Heart Rate: 0 HBM 11:41:50.351 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 11:41:50.477 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 AB 09 AC 00 14 00 38 00 00 ] 11:41:50.477 -> Instant. Speed: 24 KPH Instantaneous Cadence: 86 RPM Resistance Level: 20 Instantaneous Power: 56 Watt Heart Rate: 0 HBM 11:41:50.570 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 11:41:51.365 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 B0 09 9E 00 14 00 3C 00 00 ] 11:41:51.365 -> Instant. Speed: 24 KPH Instantaneous Cadence: 79 RPM Resistance Level: 20 Instantaneous Power: 60 Watt Heart Rate: 0 HBM 11:41:52.239 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 E7 09 84 00 14 00 4C 00 00 ] 11:41:52.285 -> Instant. Speed: 25 KPH Instantaneous Cadence: 66 RPM Resistance Level: 20 Instantaneous Power: 76 Watt Heart Rate: 0 HBM 11:41:52.457 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 11:41:52.535 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 11:41:53.362 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 F0 09 7A 00 14 00 4C 00 00 ] 11:41:53.362 -> Instant. Speed: 25 KPH Instantaneous Cadence: 61 RPM Resistance Level: 20 Instantaneous Power: 76 Watt Heart Rate: 0 HBM 11:41:54.534 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 11:41:54.613 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 0A 90 00 14 00 58 00 00 ] 11:41:54.613 -> Instant. Speed: 25 KPH Instantaneous Cadence: 72 RPM Resistance Level: 20 Instantaneous Power: 88 Watt Heart Rate: 0 HBM 11:41:54.798 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 11:41:54.798 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 11:41:55.252 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A4 09 81 08 A2 00 A2 00 06 00 00 14 00 59 00 59 00 00 ] 11:41:55.252 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 81 RPM Average Cadence: 81 RPM Total Distance: 6 m Resistance Level: 20 Instantaneous Power: 89 Watt Average Power: 89 Watt Heart Rate: 0 HBM 11:41:56.231 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A7 09 81 08 AA 00 A6 00 0C 00 00 14 00 5A 00 59 00 00 ] 11:41:56.231 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 85 RPM Average Cadence: 83 RPM Total Distance: 12 m Resistance Level: 20 Instantaneous Power: 90 Watt Average Power: 89 Watt Heart Rate: 0 HBM 11:41:56.655 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 11:41:56.874 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:56.874 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 11:41:57.190 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 9E 09 81 08 A8 00 A6 00 12 00 00 14 00 53 00 57 00 00 ] 11:41:57.190 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 84 RPM Average Cadence: 83 RPM Total Distance: 18 m Resistance Level: 20 Instantaneous Power: 83 Watt Average Power: 87 Watt Heart Rate: 0 HBM 11:41:58.221 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 45 09 81 08 A8 00 A7 00 18 00 00 14 00 50 00 55 00 00 ] 11:41:58.221 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 84 RPM Average Cadence: 83 RPM Total Distance: 24 m Resistance Level: 20 Instantaneous Power: 80 Watt Average Power: 85 Watt Heart Rate: 0 HBM 11:41:58.736 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 00 28 33 00 ] 11:41:59.018 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:41:59.018 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 11:41:59.203 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 35 09 81 08 A6 00 A6 00 1E 00 00 14 00 73 00 5B 00 00 ] 11:41:59.203 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 83 RPM Average Cadence: 83 RPM Total Distance: 30 m Resistance Level: 20 Instantaneous Power: 115 Watt Average Power: 91 Watt Heart Rate: 0 HBM 11:42:00.276 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 60 09 81 08 A2 00 A6 00 24 00 00 14 00 B0 00 69 00 00 ] 11:42:00.276 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 81 RPM Average Cadence: 83 RPM Total Distance: 36 m Resistance Level: 20 Instantaneous Power: 176 Watt Average Power: 105 Watt Heart Rate: 0 HBM 11:42:00.833 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 11:42:01.239 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:42:01.285 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 11:42:01.285 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 8D 09 81 08 A4 00 A5 00 2A 00 00 14 00 9C 00 70 00 00 ] 11:42:01.285 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 82 RPM Average Cadence: 82 RPM Total Distance: 42 m Resistance Level: 20 Instantaneous Power: 156 Watt Average Power: 112 Watt Heart Rate: 0 HBM 11:42:02.267 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 71 09 81 08 A0 00 A5 00 30 00 00 14 00 61 00 6E 00 00 ] 11:42:02.267 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 80 RPM Average Cadence: 82 RPM Total Distance: 48 m Resistance Level: 20 Instantaneous Power: 97 Watt Average Power: 110 Watt Heart Rate: 0 HBM 11:42:02.952 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 14 00 28 33 00 ] 11:42:03.169 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:42:03.169 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 00 28 33 ] 11:42:03.264 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 5C 09 81 08 A2 00 A4 00 36 00 00 14 00 59 00 6C 00 00 ] 11:42:03.264 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 81 RPM Average Cadence: 82 RPM Total Distance: 54 m Resistance Level: 20 Instantaneous Power: 89 Watt Average Power: 108 Watt Heart Rate: 0 HBM 11:42:04.248 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 26 09 81 08 A6 00 A4 00 3C 00 00 14 00 52 00 69 00 00 ] 11:42:04.248 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 83 RPM Average Cadence: 82 RPM Total Distance: 60 m Resistance Level: 20 Instantaneous Power: 82 Watt Average Power: 105 Watt Heart Rate: 0 HBM 11:42:05.043 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 00 28 33 00 ] 11:42:05.137 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:42:05.137 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 00 28 33 ] 11:42:05.231 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 56 09 81 08 A8 00 A5 00 42 00 00 14 00 43 00 66 00 00 ] 11:42:05.231 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 84 RPM Average Cadence: 82 RPM Total Distance: 66 m Resistance Level: 20 Instantaneous Power: 67 Watt Average Power: 102 Watt Heart Rate: 0 HBM 11:42:06.225 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 3E 09 81 08 A2 00 A4 00 48 00 00 14 00 55 00 64 00 00 ] 11:42:06.225 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 81 RPM Average Cadence: 82 RPM Total Distance: 72 m Resistance Level: 20 Instantaneous Power: 85 Watt Average Power: 100 Watt Heart Rate: 0 HBM 11:42:07.145 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 25 00 28 33 00 ] 11:42:07.223 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 5B 09 81 08 A0 00 A4 00 4E 00 00 14 00 4A 00 62 00 00 ] 11:42:07.223 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 80 RPM Average Cadence: 82 RPM Total Distance: 78 m Resistance Level: 20 Instantaneous Power: 74 Watt Average Power: 98 Watt Heart Rate: 0 HBM 11:42:07.223 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:42:07.223 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 25 00 28 33 ] 11:42:08.206 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 4C 09 81 08 A0 00 A4 00 54 00 00 14 00 5D 00 62 00 00 ] 11:42:08.206 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 80 RPM Average Cadence: 82 RPM Total Distance: 84 m Resistance Level: 20 Instantaneous Power: 93 Watt Average Power: 98 Watt Heart Rate: 0 HBM 11:42:09.183 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 42 09 81 08 A0 00 A3 00 5A 00 00 14 00 55 00 61 00 00 ] 11:42:09.183 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 80 RPM Average Cadence: 81 RPM Total Distance: 90 m Resistance Level: 20 Instantaneous Power: 85 Watt Average Power: 97 Watt Heart Rate: 0 HBM 11:42:09.217 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 23 00 28 33 00 ] 11:42:09.375 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:42:09.375 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 00 28 33 ] 11:42:10.247 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 32 09 81 08 A2 00 A3 00 60 00 00 14 00 5F 00 61 00 00 ] 11:42:10.247 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 81 RPM Average Cadence: 81 RPM Total Distance: 96 m Resistance Level: 20 Instantaneous Power: 95 Watt Average Power: 97 Watt Heart Rate: 0 HBM 11:42:11.318 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 1C 00 28 33 00 ] 11:42:11.539 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 17 09 81 08 A0 00 A3 00 66 00 00 14 00 4E 00 60 00 00 ] 11:42:11.539 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 80 RPM Average Cadence: 81 RPM Total Distance: 102 m Resistance Level: 20 Instantaneous Power: 78 Watt Average Power: 96 Watt Heart Rate: 0 HBM 11:42:11.632 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:42:11.632 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 00 28 33 ] 11:42:12.349 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 4C 09 81 08 9E 00 A3 00 6C 00 00 14 00 53 00 5F 00 00 ] 11:42:12.349 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 79 RPM Average Cadence: 81 RPM Total Distance: 108 m Resistance Level: 20 Instantaneous Power: 83 Watt Average Power: 95 Watt Heart Rate: 0 HBM 11:42:13.427 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 0F 00 28 33 00 ] 11:42:13.490 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 46 09 81 08 9E 00 A2 00 72 00 00 14 00 56 00 5E 00 00 ] 11:42:13.490 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 79 RPM Average Cadence: 81 RPM Total Distance: 114 m Resistance Level: 20 Instantaneous Power: 86 Watt Average Power: 94 Watt Heart Rate: 0 HBM 11:42:13.569 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 11:42:13.614 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 0F 00 28 33 ] 11:42:14.223 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 0B 09 81 08 A2 00 A2 00 78 00 00 14 00 58 00 5E 00 00 ] 11:42:14.223 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 81 RPM Average Cadence: 81 RPM Total Distance: 120 m Resistance Level: 20 Instantaneous Power: 88 Watt Average Power: 94 Watt Heart Rate: 0 HBM 11:42:15.205 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 43 09 81 08 A0 00 A2 00 7E 00 00 14 00 5A 00 5E 00 00 ] 11:42:15.205 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 80 RPM Average Cadence: 81 RPM Total Distance: 126 m Resistance Level: 20 Instantaneous Power: 90 Watt Average Power: 94 Watt Heart Rate: 0 HBM 11:42:15.518 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ]
11:55:16.952 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 11:55:16.952 -> ----------------- Version 02.8 ------------------ 11:55:16.952 -> Initialise the Bluefruit nRF52 module: Client (Central) 11:55:16.952 -> FTMS and Chars 'initialized' 11:55:16.952 -> CPS and Chars 'initialized' 11:55:16.952 -> CSCS and Chars 'initialized' 11:55:16.952 -> GA and Chars 'initialized' 11:55:16.952 -> DIS and Chars 'initialized' 11:55:16.952 -> Start Scanning for CPS, CSC and FTMS! 11:55:16.952 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 11:55:16.952 -> Timestamp MAC Address Rssi Data 11:55:16.952 -> 000001201 F8:9C:FC:53:5E:49 -57 09-02-16-18-26-18-18-18-0A-18 11:55:16.952 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 11:55:16.952 -> Now checking all Client Services and Characteristics! 11:55:16.952 -> If Mandatory Services Fail --> the Client will disconnect! 11:55:16.960 -> First checking Generic Access and Device Information Services and Characteristics! 11:55:16.960 -> Found Client Generic Access 11:55:17.141 -> -> Client Reads Device Name: [Zwift Hub] 11:55:17.563 -> -> Client Reads Appearance: [0] 11:55:17.842 -> Found Client Device Information 11:55:18.310 -> -> Client Reads Manufacturer: [Zwift] 11:55:18.622 -> -> Client Reads Model Number: [06] 11:55:19.060 -> -> Client Reads Serial Number: [06-F89CFC535E49] 11:55:19.246 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 11:55:19.744 -> Discovering Client FTM Feature Characteristic ... Found it! 11:55:19.929 -> -> Client Reads Raw FTM Feature bytes: [8] [ 87 44 00 00 0C E0 00 00 ] 11:55:20.116 -> Discovering Client FTM Control Point Characteristic ... Found it! 11:55:20.660 -> Discovering Client FTM Status Characteristic ... Found it! 11:55:21.423 -> Enable Notify/Indicate of relevant Peripheral (Trainer) Characteristics 11:55:21.470 -> Discovering Client FTM Training Status Characteristic ... Ready to receive Client FTM Control Point Response Messages 11:55:21.747 -> Ready to receive Client FTM Status values 11:55:21.747 -> Not Found! Not Mandatory 11:55:21.964 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 11:55:22.147 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 00 00 00 00 ] 11:55:22.335 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 11:55:22.615 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 00 00 00 00 ] 11:55:22.802 -> Discovering Client FTM Indoor Bike Data Characteristic ... Not Found! Not Mandatory 11:55:23.068 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 11:55:23.502 -> Discovering Client CP Measurement characteristic ... Found it! 11:55:23.719 -> Discovering Client CP Control Point characteristic ... >>> Couldn't enable notify for Client FTM Training Status Characteristic. 11:55:23.856 -> Not Found! NOT Mandatory! 11:55:24.307 -> Discovering Client CP Feature characteristic ... Found it! 11:55:24.307 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 11:55:24.307 -> Wheel revolution data supported 11:55:24.307 -> Crank revolution data supported 11:55:24.572 -> Discovering Client CP Sensor Location characteristic ... Found it! 11:55:24.665 -> -> Client Reads CP Location Sensor: Loc#: 0 Other 11:55:24.930 -> Discovering Cycling Speed and Cadence (CSC) Service ... Found it! CSCS Max Payload: 20 Data Length: 27 11:55:25.565 -> Discovering Client CSC Measurement CHR ... Found it! 11:55:25.689 -> >>> Couldn't enable notify for Client FTM Indoor Bike Data Characteristic. 11:55:25.768 -> Discovering Client CSC Location CHR ... Ready to receive Client CP Measurement values 11:55:25.893 -> Found it! 11:55:25.893 -> -> Client Reads CSC Location Sensor: Loc#: 12 Rear wheel 11:55:26.207 -> Discovering Client CSC Feature CHR ... Found it! 11:55:26.207 -> -> Client Reads Raw CSC Feature bytes: [2] [ 03 00 ] 11:55:26.207 -> Wheel rev supported 11:55:26.207 -> Crank rev supported 11:55:27.766 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 11:55:27.806 -> Ready to receive Client CSC Measurement values 11:55:27.806 -> Client (Central) is Up and Running! 11:55:29.812 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 11:55:29.889 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 11:55:31.910 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ]
11:58:33.742 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 11:58:34.020 -> Discovering Client FTM Feature Characteristic ... Found it! 11:58:34.283 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 11:58:34.487 -> Discovering Client FTM Control Point Characteristic ... Found it! 11:58:35.014 -> Discovering Client FTM Status Characteristic ... Found it! 11:58:35.685 -> Enable Notify/Indicate of relevant Peripheral (Trainer) Characteristics 11:58:35.762 -> Ready to receive Client FTM Control Point Response Messages 11:58:35.762 -> Discovering Client FTM Training Status Characteristic ... Ready to receive Client FTM Status values 11:58:35.966 -> Not Found! Not Mandatory 11:58:36.151 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 11:58:36.323 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 00 00 00 00 ] 11:58:36.539 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 11:58:36.817 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 11:58:37.314 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 11:58:37.608 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 11:58:37.827 -> Discovering Client CP Measurement characteristic ... >>> Couldn't enable notify for Client FTM Training Status Characteristic. 11:58:37.905 -> Ready to receive Client FTM Indoor Bike Data values 11:58:37.905 -> Found it! 11:58:38.121 -> Ready to receive Client CP Measurement values 11:58:38.121 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 11:58:38.710 -> Discovering Client CP Feature characteristic ... Found it! 11:58:38.710 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 11:58:38.710 -> Wheel revolution data supported 11:58:38.710 -> Crank revolution data supported 11:58:39.161 -> Discovering Client CP Sensor Location characteristic ... Found it! 11:58:39.208 -> -> Client Reads CP Location Sensor: Loc#: 12 Rear wheel 11:58:39.548 -> Discovering Cycling Speed and Cadence (CSC) Service ... Found it! CSCS Max Payload: 20 Data Length: 27 11:58:39.907 -> Discovering Client CSC Measurement CHR ... Found it! 11:58:39.985 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 11:58:40.016 -> Ready to receive Client CSC Measurement values 11:58:40.016 -> Client (Central) is Up and Running! 11:58:40.110 -> Discovering Client CSC Location CHR ... Found it! 11:58:40.559 -> -> Client Reads CSC Location Sensor: Loc#: 12 Rear wheel 11:58:40.762 -> Discovering Client CSC Feature CHR ... Found it! 11:58:40.932 -> -> Client Reads Raw CSC Feature bytes: [2] [ 03 00 ] 11:58:40.932 -> Wheel rev supported 11:58:40.932 -> Crank rev supported 11:58:41.119 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 11:58:41.119 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 11:58:41.119 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 11:58:41.119 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 11:58:41.119 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 11:58:41.119 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 11:58:41.164 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 11:58:41.164 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance
:02:21.226 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 12:02:21.226 -> ----------------- Version 02.8 ------------------ 12:02:21.226 -> Initialise the Bluefruit nRF52 module: Client (Central) 12:02:21.435 -> FTMS and Chars 'initialized' 12:02:21.435 -> CPS and Chars 'initialized' 12:02:21.435 -> CSCS and Chars 'initialized' 12:02:21.435 -> GA and Chars 'initialized' 12:02:21.435 -> DIS and Chars 'initialized' 12:02:21.435 -> Start Scanning for CPS, CSC and FTMS! 12:02:21.435 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 12:02:21.435 -> Timestamp MAC Address Rssi Data 12:02:21.435 -> 000001359 F8:9C:FC:53:5E:49 -54 09-02-16-18-26-18-18-18-0A-18 12:02:21.440 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 12:02:21.440 -> Now checking all Client Services and Characteristics! 12:02:21.440 -> If Mandatory Services Fail --> the Client will disconnect! 12:02:21.468 -> First checking Generic Access and Device Information Services and Characteristics! 12:02:21.604 -> Found Client Generic Access 12:02:21.959 -> -> Client Reads Device Name: [Zwift Hub] 12:02:22.503 -> -> Client Reads Appearance: [1152] 12:02:22.831 -> Found Client Device Information 12:02:23.268 -> -> Client Reads Manufacturer: [Zwift] 12:02:24.091 -> -> Client Reads Serial Number: [06-F89CFC535E49] 12:02:24.296 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 12:02:24.574 -> Discovering Client FTM Feature Characteristic ... Found it! 12:02:24.716 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 12:02:24.946 -> Discovering Client FTM Control Point Characteristic ... Not Found! 12:02:24.946 -> Disconnecting since Client FTM Control Point Characteristic is mandatory! 12:02:24.993 -> Client Disconnected, reason = 0x16 12:02:24.993 -> >>> Restart the Feather nRF52 Client for a new run! <<< 12:02:26.206 -> Stopped! 12:02:46.062 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 12:02:46.062 -> ----------------- Version 02.8 ------------------ 12:02:46.062 -> Initialise the Bluefruit nRF52 module: Client (Central) 12:02:46.062 -> FTMS and Chars 'initialized' 12:02:46.062 -> CPS and Chars 'initialized' 12:02:46.062 -> CSCS and Chars 'initialized' 12:02:46.062 -> GA and Chars 'initialized' 12:02:46.062 -> DIS and Chars 'initialized' 12:02:46.062 -> Start Scanning for CPS, CSC and FTMS! 12:02:46.478 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 12:02:46.478 -> Timestamp MAC Address Rssi Data 12:02:46.478 -> 000001488 F8:9C:FC:53:5E:49 -52 09-02-16-18-26-18-18-18-0A-18 12:02:46.500 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 12:02:46.500 -> Now checking all Client Services and Characteristics! 12:02:46.500 -> If Mandatory Services Fail --> the Client will disconnect! 12:02:46.500 -> First checking Generic Access and Device Information Services and Characteristics! 12:02:46.592 -> Found Client Generic Access 12:02:46.964 -> -> Client Reads Device Name: [Zwift Hub] 12:02:47.320 -> -> Client Reads Appearance: [1152] 12:02:47.583 -> Found Client Device Information 12:02:47.880 -> -> Client Reads Manufacturer: [Zwift] 12:02:48.252 -> -> Client Reads Model Number: [06] 12:02:48.655 -> -> Client Reads Serial Number: [06-F89CFC535E49] 12:02:48.842 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 12:02:49.124 -> Discovering Client FTM Feature Characteristic ... Found it! 12:02:49.340 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 12:02:49.560 -> Discovering Client FTM Control Point Characteristic ... Found it! 12:02:50.137 -> Discovering Client FTM Status Characteristic ... Found it! 12:02:50.586 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 12:02:50.977 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Enable Notify/Indicate of relevant Peripheral (Trainer) Characteristics 12:02:51.020 -> Found it! 12:02:51.020 -> Ready to receive Client FTM Control Point Response Messages 12:02:51.066 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 12:02:51.252 -> Ready to receive Client FTM Status values 12:02:51.252 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 12:02:51.518 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 12:02:51.920 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 12:02:52.156 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 12:02:52.620 -> Discovering Client CP Measurement characteristic ... Found it! 12:02:52.979 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 12:02:53.119 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 12:02:53.165 -> Discovering Client CP Feature characteristic ... Ready to receive Client FTM Indoor Bike Data values 12:02:53.229 -> Found it! 12:02:53.229 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 12:02:53.229 -> Wheel revolution data supported 12:02:53.229 -> Crank revolution data supported 12:02:53.229 -> Ready to receive Client CP Measurement values 12:02:53.514 -> Discovering Client CP Sensor Location characteristic ... Found it! 12:02:53.607 -> -> Client Reads CP Location Sensor: Loc#: 12 Rear wheel 12:02:53.918 -> Discovering Cycling Speed and Cadence (CSC) Service ... Found it! CSCS Max Payload: 20 Data Length: 27 12:02:54.540 -> Discovering Client CSC Measurement CHR ... Found it! 12:02:54.898 -> Discover
Jörghen,
I took the FTMS_BRIDGE_V023 and added the delay as in the FTMS Client.
Here is the result :
The Cyclist moves correctly and power and cadence are correct.
I can't turn on the cardio frequency meter otherwise everything crashes!!
5:18:07.676 -> First checking Generic Access and Device Information Services and Characteristics! 15:18:07.676 -> Found Client Generic Access 15:18:07.697 -> -> Client Reads Device Name: [Zwift Hub] 15:18:07.860 -> -> Client Reads Appearance: [1152] 15:18:08.067 -> Found Client Device Information 15:18:08.697 -> -> Client Reads Manufacturer: [Zwift] 15:18:09.116 -> -> Client Reads Model Number: [06] 15:18:09.474 -> -> Client Reads Serial Number: [06-F89CFC535E49] 15:18:09.657 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 15:18:09.967 -> Discovering Client FTM Feature Characteristic ... Found it! 15:18:10.154 -> -> Client Reads Raw FTM Feature bytes: [8] [ 87 44 00 00 0C E0 00 00 ] 15:18:10.340 -> Discovering Client FTM Control Point Characteristic ... Found it! 15:18:10.947 -> Discovering Client FTM Status Characteristic ... Found it! 15:18:11.442 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 15:18:12.155 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 15:18:12.247 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 15:18:12.463 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 15:18:12.727 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 15:18:12.942 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 15:18:13.516 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 15:18:13.780 -> Discovering Client CP Measurement characteristic ... Found it! 15:18:14.197 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 15:18:14.570 -> Discovering Client CP Feature characteristic ... Found it! 15:18:14.723 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 15:18:14.723 -> Wheel revolution data supported 15:18:14.723 -> Crank revolution data supported 15:18:14.908 -> Discovering Client CP Sensor Location characteristic ... Found it! 15:18:15.186 -> -> Client Reads CP Location Sensor: Loc#: 12 Rear wheel 15:18:15.372 -> Discovering Cycling Speed and Cadence (CSC) Service ... Found it! CSCS Max Payload: 20 Data Length: 27 15:18:15.635 -> Discovering Client CSC Measurement CHR ... Found it! 15:18:15.977 -> Discovering Client CSC Location CHR ... Found it! 15:18:16.133 -> -> Client Reads CSC Location Sensor: Loc#: 12 Rear wheel 15:18:16.335 -> Discovering Client CSC Feature CHR ... Found it! 15:18:16.519 -> -> Client Reads Raw CSC Feature bytes: [2] [ 03 00 ] 15:18:16.519 -> Wheel rev supported 15:18:16.519 -> Crank rev supported 15:18:16.705 -> Configuring the Server Device Information Service 15:18:16.705 -> Configuring the Server Cycle Power Service 15:18:16.705 -> Configuring the Server Cadence and Speed Service 15:18:16.705 -> Configuring the Server Fitness Machine Service 15:18:16.705 -> Configuring the Server NUS Service 15:18:16.705 -> Setting up the Server-side advertising payload(s) 15:18:16.705 -> Setting Server Device Name to: [Sim Zwift] 15:18:16.705 -> Setting Server Appearance to: [1152] 15:18:16.705 -> Server-side is CPS, CSC and FTMS advertising! 15:18:17.278 -> Feather nRF52 (Peripheral) connected to Central device: [DESKTOP-1CC9OQN] MAC Address: 58:11:22:53:52:18 15:18:17.278 -> Ready to receive Client FTM Control Point Response Messages 15:18:17.278 -> Ready to receive Client FTM Status values 15:18:17.278 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 15:18:17.401 -> Ready to receive Client FTM Indoor Bike Data values 15:18:17.434 -> Ready to receive Client CP Measurement values 15:18:17.434 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 15:18:17.527 -> >>> Couldn't enable notify for Client CSC Measurement Characteristic. 15:18:17.527 -> Waiting for Central (Zwift) to set CCCD Notify/Indicate (enable) and start.... 15:18:22.114 -> Client- and Server-side are Up and Running! 15:18:22.469 -> Central Device Updated CCCD to: [1] --> Server CP: Measurement 'Notify' enabled 15:18:22.940 -> Central Device Updated CCCD to: [1] --> Server CSC: Measurement 'Notify' enabled 15:18:23.568 -> Central Device Updated CCCD to: [1] --> Server FTM: IndoorBikeData 'Notify' enabled 15:18:24.361 -> Central Device Updated CCCD to: [1] --> Server FTM: Status 'Notify' enabled 15:19:30.101 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 B2 FF 28 33 00 ] 15:19:30.101 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): -0.78 | Crr (10000): 0.00 | Cw (100): 0.51 15:19:30.271 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 15:19:30.271 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 B2 FF 28 33 ] 15:19:39.262 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 00 00 28 33 00 ] 15:19:39.262 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.00 | Crr (10000): 0.00 | Cw (100): 0.51 15:19:39.354 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 15:19:39.354 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ]
Dear Joel,
I took the FTMS_BRIDGE_V023 and added the delay as in the FTMS Client.
Well done! And....very good result.....
I can't turn on the cardio frequency meter otherwise everything crashes!!
That sounds dramatic.... However, I was just a little bit googling and ended up with a popular friend DCRainmaker:
->Protocol Compatibility: ANT+ FE-C, ANT+ Power, Bluetooth Smart Trainer Control, Bluetooth Smart Power (everything you need) –>Unique Party Trick: Can rebroadcast your heart rate sensor within a single channel, ideal for Apple TV Zwift users (who are Bluetooth channel limited)
Additionally, it’s here you can do heart rate bridging/pairing. This allows you to pair your chest strap with the Zwift Hub, and then get pass-through heart rate, so that the trainer handles the HR connection to the app on behalf of your strap. The main/singular reason you’d want to do this is for Apple TV usage of Zwift or other apps. That’s because Apple TV has a two concurrent connection limit (plus the remote). So if you wanted to do steering in Zwift, then this wouldn’t be possible since you’d have one connection for the trainer, and then one for your heart rate sensor (leaving none for steering).
But with HR bridging, the heart rate sensor data gets funneled in the same ‘channel’ as the trainer data, so it only counts as one channel – not two. You can simply search for your HR strap in this menu and then pair to it.
The question is: What is your setup? What settings do you use in the Zwift Hub Companion App with respect to HBM?
Now, before we start riding, we should double-check the Zwift app for any firmware updates. This is done via the Zwift Companion App (which is the smartphone one). You’ll see a new option for Zwift hardware, and you can check/update it there..
The bottom line is: Should the Simcline FTMS code in the end allocate Apple TV users that buy a Zwift Hub and expect HBM to be rebroadcasted? Notice that this feature is NOT FTMS standard but an extra goodie of the Zwift company!
Dear Joel, Did you spent any time on fine tuning the SOME_TIME in the FTMS_Client latest version? Before we are spending time on other parts we have to get this delay function to be optimized (for Zwift Hub specifically) and that is something I can't do, not having a Zwift Hub at hand... so I am relying on you. Regards, Jörgen.
Hello Jorghen,
Yes I tested several different delays from 200 to 300 ms I put the different ones for you results but for me 250 ms is the best at 200 I don't always have the same results at 250 it's perfect!
The cardio frequency meter problem is solved, I had disconnected it from the trainer with Zwift Compagion.
I put it back and now it's ok
300 ms
16:55:20.353 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 16:55:20.353 -> ----------------- Version 02.8 ------------------ 16:55:20.353 -> Initialise the Bluefruit nRF52 module: Client (Central) 16:55:20.353 -> FTMS and Chars 'initialized' 16:55:20.353 -> CPS and Chars 'initialized' 16:55:20.353 -> CSCS and Chars 'initialized' 16:55:20.353 -> GA and Chars 'initialized' 16:55:20.353 -> DIS and Chars 'initialized' 16:55:20.353 -> Start Scanning for CPS, CSC and FTMS! 16:55:20.354 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 16:55:20.354 -> Timestamp MAC Address Rssi Data 16:55:20.354 -> 000001217 F8:9C:FC:53:5E:49 -57 09-02-16-18-26-18-18-18-0A-18 16:55:20.354 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address:F8:9C:FC:53:5E:49 16:55:20.354 -> Now checking all Client Services and Characteristics! 16:55:20.354 -> If Mandatory Services Fail --> the Client will disconnect! 16:55:20.380 -> First checking Generic Access and Device Information Services and Characteristics! 16:55:20.380 -> Found Client Generic Access 16:55:20.381 -> -> Client Reads Device Name: [Zwift Hub] 16:55:20.720 -> -> Client Reads Appearance: [1152] 16:55:21.076 -> Found Client Device Information 16:55:21.463 -> -> Client Reads Manufacturer: [Zwift] 16:55:21.818 -> -> Client Reads Model Number: [06] 16:55:22.220 -> -> Client Reads Serial Number: [06-F89CFC535E49] 16:55:22.527 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 16:55:22.881 -> Discovering Client FTM Feature Characteristic ... Found it! 16:55:22.958 -> -> Client Reads Raw FTM Feature bytes: [8] [ 87 44 00 00 0C E0 00 00 ] 16:55:23.264 -> Discovering Client FTM Control Point Characteristic ... Found it! 16:55:23.709 -> Discovering Client FTM Status Characteristic ... Found it! 16:55:24.109 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 16:55:24.519 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Enable Notify/Indicate of relevant Peripheral (Trainer) Characteristics 16:55:24.558 -> Found it! 16:55:24.558 -> Ready to receive Client FTM Control Point Response Messages 16:55:24.604 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 16:55:24.880 -> Ready to receive Client FTM Status values 16:55:24.880 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 16:55:25.050 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 16:55:25.448 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 16:55:25.773 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 16:55:26.177 -> Discovering Client CP Measurement characteristic ... Found it! 16:55:26.640 -> Discovering Client CP Control Point characteristic ... >>> Couldn't enable notify for Client FTM Training Status Characteristic. 16:55:26.686 -> Not Found! NOT Mandatory! 16:55:26.765 -> Ready to receive Client FTM Indoor Bike Data values 16:55:26.765 -> Ready to receive Client CP Measurement values 16:55:27.089 -> Discovering Client CP Feature characteristic ... Found it! 16:55:27.089 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 16:55:27.089 -> Wheel revolution data supported 16:55:27.089 -> Crank revolution data supported 16:55:27.433 -> Discovering Client CP Sensor Location characteristic ... Found it! 16:55:27.479 -> -> Client Reads CP Location Sensor: Loc#: 12 Rear wheel 16:55:27.820 -> Discovering Cycling Speed and Cadence (CSC) Service ... Found it! CSCS Max Payload: 20 Data Length: 27 16:55:28.277 -> Discovering Client CSC Measurement CHR ... Found it! 16:55:28.629 -> Discovering Client CSC Location CHR ... Found it! 16:55:28.629 -> -> Client Reads CSC Location Sensor: Loc#: 12 Rear wheel 16:55:28.769 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 16:55:28.769 -> Ready to receive Client CSC Measurement values 16:55:28.769 -> Client (Central) is Up and Running! 16:55:28.940 -> Discovering Client CSC Feature CHR ... Found it! 16:55:29.034 -> -> Client Reads Raw CSC Feature bytes: [2] [ 03 00 ] 16:55:29.034 -> Wheel rev supported 16:55:29.034 -> Crank rev supported 16:55:29.342 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 16:55:29.342 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM
250 ms
16:51:06.619 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 16:51:06.619 -> ----------------- Version 02.8 ------------------ 16:51:06.619 -> Initialise the Bluefruit nRF52 module: Client (Central) 16:51:06.619 -> FTMS and Chars 'initialized' 16:51:06.619 -> CPS and Chars 'initialized' 16:51:06.619 -> CSCS and Chars 'initialized' 16:51:06.619 -> GA and Chars 'initialized' 16:51:06.619 -> DIS and Chars 'initialized' 16:51:06.619 -> Start Scanning for CPS, CSC and FTMS! 16:51:06.619 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 16:51:06.619 -> Timestamp MAC Address Rssi Data 16:51:06.619 -> 000001406 F8:9C:FC:53:5E:49 -56 09-02-16-18-26-18-18-18-0A-18 16:51:06.619 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 16:51:06.619 -> Now checking all Client Services and Characteristics! 16:51:06.619 -> If Mandatory Services Fail --> the Client will disconnect! 16:51:06.619 -> First checking Generic Access and Device Information Services and Characteristics! 16:51:06.620 -> Found Client Generic Access 16:51:06.629 -> -> Client Reads Device Name: [Zwift Hub] 16:51:06.891 -> -> Client Reads Appearance: [1152] 16:51:07.186 -> Found Client Device Information 16:51:07.498 -> -> Client Reads Manufacturer: [Zwift] 16:51:07.855 -> -> Client Reads Model Number: [06] 16:51:08.176 -> -> Client Reads Serial Number: [06-F89CFC535E49] 16:51:08.407 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 16:51:08.702 -> Discovering Client FTM Feature Characteristic ... Found it! 16:51:08.791 -> -> Client Reads Raw FTM Feature bytes: [8] [ 87 44 00 00 0C E0 00 00 ] 16:51:09.053 -> Discovering Client FTM Control Point Characteristic ... Found it! 16:51:09.395 -> Discovering Client FTM Status Characteristic ... Found it! 16:51:09.802 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 16:51:10.176 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 16:51:10.254 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 16:51:10.475 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 16:51:10.630 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 16:51:10.897 -> Discovering Client FTM Indoor Bike Data Characteristic ... Enable Notify/Indicate of relevant Peripheral (Trainer) Characteristics 16:51:10.897 -> Ready to receive Client FTM Control Point Response Messages 16:51:10.897 -> Found it! 16:51:11.177 -> Ready to receive Client FTM Status values 16:51:11.177 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 16:51:11.537 -> Discovering Client CP Measurement characteristic ... Found it! 16:51:11.896 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 16:51:12.256 -> Discovering Client CP Feature characteristic ... Found it! 16:51:12.256 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 16:51:12.256 -> Wheel revolution data supported 16:51:12.256 -> Crank revolution data supported 16:51:12.565 -> Discovering Client CP Sensor Location characteristic ... Found it! 16:51:12.581 -> -> Client Reads CP Location Sensor: Loc#: 12 Rear wheel 16:51:12.903 -> Discovering Cycling Speed and Cadence (CSC) Service ... Found it! CSCS Max Payload: 20 Data Length: 27 16:51:12.937 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 16:51:13.108 -> Ready to receive Client FTM Indoor Bike Data values 16:51:13.108 -> Ready to receive Client CP Measurement values 16:51:13.294 -> Discovering Client CSC Measurement CHR ... Found it! 16:51:13.635 -> Discovering Client CSC Location CHR ... Found it! 16:51:13.635 -> -> Client Reads CSC Location Sensor: Loc#: 12 Rear wheel 16:51:13.959 -> Discovering Client CSC Feature CHR ... Found it! 16:51:13.959 -> -> Client Reads Raw CSC Feature bytes: [2] [ 03 00 ] 16:51:13.959 -> Wheel rev supported 16:51:13.959 -> Crank rev supported 16:51:14.192 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 16:51:14.192 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM 16:51:14.192 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ]
200 ms
17:14:15.007 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 17:14:15.007 -> ----------------- Version 02.8 ------------------ 17:14:15.007 -> Initialise the Bluefruit nRF52 module: Client (Central) 17:14:15.422 -> FTMS and Chars 'initialized' 17:14:15.422 -> CPS and Chars 'initialized' 17:14:15.422 -> CSCS and Chars 'initialized' 17:14:15.422 -> GA and Chars 'initialized' 17:14:15.422 -> DIS and Chars 'initialized' 17:14:15.422 -> Start Scanning for CPS, CSC and FTMS! 17:14:15.422 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 17:14:15.422 -> Timestamp MAC Address Rssi Data 17:14:15.422 -> 000000633 F8:9C:FC:53:5E:49 -55 09-02-16-18-26-18-18-18-0A-18 17:14:15.422 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:14:15.422 -> Now checking all Client Services and Characteristics! 17:14:15.422 -> If Mandatory Services Fail --> the Client will disconnect! 17:14:15.422 -> First checking Generic Access and Device Information Services and Characteristics! 17:14:15.432 -> Found Client Generic Access 17:14:16.068 -> -> Client Reads Device Name: [Zwift Hub] 17:14:16.074 -> -> Client Reads Appearance: [0] 17:14:16.137 -> Found Client Device Information 17:14:16.494 -> -> Client Reads Manufacturer: [Zwift] 17:14:16.833 -> -> Client Reads Model Number: [06] 17:14:17.190 -> -> Client Reads Serial Number: [06-F89CFC535E49] 17:14:17.378 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 17:14:17.675 -> Discovering Client FTM Feature Characteristic ... Found it! 17:14:17.892 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 17:14:18.064 -> Discovering Client FTM Control Point Characteristic ... Found it! 17:14:18.467 -> Discovering Client FTM Status Characteristic ... Found it! 17:14:18.928 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 17:14:19.473 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 17:14:19.566 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 17:14:19.721 -> Enable Notify/Indicate of relevant Peripheral (Trainer) Characteristics 17:14:19.767 -> Ready to receive Client FTM Control Point Response Messages 17:14:19.767 -> Discovering Client FTM Supported Power Range Characteristic ... >>> Couldn't enable notify for Client FTM Status Characteristic. 17:14:19.845 -> FTMS (trainer) is controlled by another Client (Training App)! 17:14:19.845 -> Client (Central) is Up and Running! 17:14:19.969 -> Not Found! NOT mandatory! 17:14:20.173 -> Discovering Client FTM Indoor Bike Data Characteristic ... Not Found! Not Mandatory 17:14:20.344 -> Discovering Client Cycling Power (CP) Service ... Not Found! 17:14:20.344 -> Disconnecting since Client Cyling Power Service is mandatory! 17:14:20.344 -> Client Disconnected, reason = 0x16 17:14:20.344 -> >>> Restart the Feather nRF52 Client for a new run! <<<
200 ms
17:15:00.572 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 17:15:00.572 -> ----------------- Version 02.8 ------------------ 17:15:00.572 -> Initialise the Bluefruit nRF52 module: Client (Central) 17:15:00.572 -> FTMS and Chars 'initialized' 17:15:00.572 -> CPS and Chars 'initialized' 17:15:00.572 -> CSCS and Chars 'initialized' 17:15:00.572 -> GA and Chars 'initialized' 17:15:00.572 -> DIS and Chars 'initialized' 17:15:00.572 -> Start Scanning for CPS, CSC and FTMS! 17:15:00.572 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 17:15:00.572 -> Timestamp MAC Address Rssi Data 17:15:00.572 -> 000001199 F8:9C:FC:53:5E:49 -55 09-02-16-18-26-18-18-18-0A-18 17:15:00.595 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:15:00.595 -> Now checking all Client Services and Characteristics! 17:15:00.595 -> If Mandatory Services Fail --> the Client will disconnect! 17:15:00.595 -> First checking Generic Access and Device Information Services and Characteristics! 17:15:00.595 -> Found Client Generic Access 17:15:00.690 -> -> Client Reads Device Name: [Zwift Hub] 17:15:01.141 -> -> Client Reads Appearance: [1152] 17:15:01.422 -> Found Client Device Information 17:15:01.890 -> -> Client Reads Manufacturer: [Zwift] 17:15:02.356 -> -> Client Reads Model Number: [06] 17:15:02.682 -> -> Client Reads Serial Number: [06-F89CFC535E49] 17:15:02.899 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 17:15:03.349 -> Discovering Client FTM Feature Characteristic ... Found it! 17:15:03.489 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 17:15:03.690 -> Discovering Client FTM Control Point Characteristic ... Found it! 17:15:04.158 -> Discovering Client FTM Status Characteristic ... Found it! 17:15:04.763 -> Discovering Client FTM Training Status Characteristic ... Enable Notify/Indicate of relevant Peripheral (Trainer) Characteristics 17:15:05.073 -> Not Found! Not Mandatory 17:15:05.198 -> Ready to receive Client FTM Control Point Response Messages 17:15:05.198 -> Ready to receive Client FTM Status values 17:15:05.276 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 17:15:05.461 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 17:15:05.677 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 17:15:05.971 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 17:15:06.519 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 17:15:06.862 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 17:15:07.173 -> Discovering Client CP Measurement characteristic ... >>> Couldn't enable notify for Client FTM Training Status Characteristic. 17:15:07.220 -> Found it! 17:15:07.312 -> Ready to receive Client FTM Indoor Bike Data values 17:15:07.312 -> Ready to receive Client CP Measurement values 17:15:07.544 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 17:15:07.918 -> Discovering Client CP Feature characteristic ... Found it! 17:15:07.918 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 17:15:07.918 -> Wheel revolution data supported 17:15:07.918 -> Crank revolution data supported 17:15:08.199 -> Discovering Client CP Sensor Location characteristic ... Found it! 17:15:08.324 -> -> Client Reads CP Location Sensor: Loc#: 0 Other 17:15:08.513 -> Discovering Cycling Speed and Cadence (CSC) Service ... Not Found! CSC Service is Not Mandatory! 17:15:08.513 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 00 00 00 00 14 00 00 00 00 ] 17:15:08.513 -> Instant. Speed: 0 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 0 Watt Heart Rate: 0 HBM
Dear Joel, It looks like the Zwift Hub needs a 250 ms delay, indeed! This is surprisingly long, I know trainers that need a delay of 0.0 seconds to work perfectly....time after time! I have done some additional testing and changed the code in such a way that: 1) I have slightly changed the pattern of the delay calls in client connect, now there are 24 calls: delaying about 6 seconds.... 2) I have included the forced delay time elsewhere --> cluttering of the output is now minimized (I hope) 3) I have included code for decoding the FTM Feature Version 029 has been uploaded and you are invited to give it a try again with the Zwift Hub trainer! Best wishes, Jörgen
Hello Jorghen,
The HRM is connected but the value is not transmitted with each request! I don't know if it's serious?
Here are the results of FTMS_0.29 :
14:46:22.160 -> Feather nRF52 Client/Central: CPS, CSC and FTMS 14:46:22.160 -> ----------------- Version 02.9 ------------------ 14:46:22.160 -> Processor: Feather nRF52840 14:46:22.160 -> Initialise the Bluefruit nRF52 module: Client (Central) 14:46:22.161 -> FTMS and Chars 'initialized' 14:46:22.161 -> CPS and Chars 'initialized' 14:46:22.161 -> CSCS and Chars 'initialized' 14:46:22.161 -> GA and Chars 'initialized' 14:46:22.161 -> DIS and Chars 'initialized' 14:46:22.161 -> Start Scanning for CPS, CSC and FTMS! 14:46:22.161 -> Found advertising Peripheral with FTMS service!, see the Raw Data packet: 14:46:22.161 -> Timestamp MAC Address Rssi Data 14:46:22.161 -> 000001328 F8:9C:FC:53:5E:49 -59 09-02-16-18-26-18-18-18-0A-18 14:46:22.161 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 14:46:22.161 -> Now checking all Client Services and Characteristics! 14:46:22.161 -> If Mandatory Services Fail --> the Client will disconnect! 14:46:22.161 -> First checking Generic Access and Device Information Services and Characteristics! 14:46:22.183 -> Found Client Generic Access 14:46:22.183 -> -> Client Reads Device Name: [Zwift Hub] 14:46:22.524 -> -> Client Reads Appearance: [1152] 14:46:22.533 -> Found Client Device Information 14:46:22.832 -> -> Client Reads Manufacturer: [Zwift] 14:46:23.252 -> -> Client Reads Model Number: [06] 14:46:23.575 -> -> Client Reads Serial Number: [06-F89CFC535E49] 14:46:23.808 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 14:46:24.105 -> Discovering Client FTM Feature Characteristic ... Found it! 14:46:24.182 -> -> Client Reads Raw FTM Feature bytes: [8] [ 87 44 00 00 0C E0 00 00 ] 14:46:24.182 -> - Fitness Machine Features: 14:46:24.182 -> Average Speed Supported 14:46:24.182 -> Cadence Supported 14:46:24.182 -> Total Distance Supported 14:46:24.182 -> Resistance Level Supported 14:46:24.182 -> Heart Rate Measurement Supported 14:46:24.182 -> Power Measurement Supported 14:46:24.182 -> - Target Setting Features: 14:46:24.182 -> Resistance Target Setting Supported 14:46:24.182 -> Power Target Setting Supported 14:46:24.182 -> Indoor Bike Simulation Parameters Supported 14:46:24.182 -> Wheel Circumference Configuration Supported 14:46:24.182 -> Spin Down Control Supported 14:46:24.431 -> Discovering Client FTM Control Point Characteristic ... Found it! 14:46:24.788 -> Discovering Client FTM Status Characteristic ... Found it! 14:46:25.162 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 14:46:25.566 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 14:46:25.660 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 14:46:25.926 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 14:46:26.051 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 14:46:26.302 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 14:46:26.616 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 14:46:26.895 -> Discovering Client CP Measurement characteristic ... Found it! 14:46:27.206 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 14:46:27.560 -> Discovering Client CP Feature characteristic ... Found it! 14:46:27.636 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 14:46:27.636 -> Wheel revolution data supported 14:46:27.636 -> Crank revolution data supported 14:46:27.868 -> Discovering Client CP Sensor Location characteristic ... Found it! 14:46:27.959 -> -> Client Reads CP Location Sensor: Loc#: 12 Rear wheel 14:46:28.204 -> Discovering Cycling Speed and Cadence (CSC) Service ... Found it! CSCS Max Payload: 20 Data Length: 27 14:46:28.530 -> Discovering Client CSC Measurement CHR ... Found it! 14:46:28.853 -> Discovering Client CSC Location CHR ... Found it! 14:46:28.885 -> -> Client Reads CSC Location Sensor: Loc#: 12 Rear wheel 14:46:29.158 -> Discovering Client CSC Feature CHR ... Found it! 14:46:29.272 -> -> Client Reads Raw CSC Feature bytes: [2] [ 03 00 ] 14:46:29.272 -> Wheel rev supported 14:46:29.272 -> Crank rev supported 14:46:29.781 -> Enable Notify/Indicate of relevant Peripheral (Trainer) Characteristics 14:46:29.859 -> Ready to receive Client FTM Control Point Response Messages 14:46:29.859 -> Ready to receive Client FTM Status values 14:46:31.836 -> >>> Couldn't enable notify for Client FTM Training Status Characteristic. 14:46:31.975 -> Ready to receive Client FTM Indoor Bike Data values 14:46:31.975 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 E5 08 00 00 14 00 7D 00 00 ] 14:46:31.975 -> Instant. Speed: 22 KPH Instantaneous Cadence: 0 RPM Resistance Level: 20 Instantaneous Power: 125 Watt Heart Rate: 0 HBM 14:46:32.976 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 38 09 4C 00 14 00 78 00 00 ] 14:46:32.976 -> Instant. Speed: 23 KPH Instantaneous Cadence: 38 RPM Resistance Level: 20 Instantaneous Power: 120 Watt Heart Rate: 0 HBM 14:46:33.839 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 14:46:33.932 -> Ready to receive Client CP Measurement values 14:46:33.932 -> Ready to receive Client CSC Measurement values 14:46:33.978 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 67 09 70 00 14 00 79 00 00 ] 14:46:33.978 -> Instant. Speed: 24 KPH Instantaneous Cadence: 56 RPM Resistance Level: 20 Instantaneous Power: 121 Watt Heart Rate: 0 HBM 14:46:34.983 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 A7 09 7E 00 14 00 97 00 00 ] 14:46:34.983 -> Instant. Speed: 24 KPH Instantaneous Cadence: 63 RPM Resistance Level: 20 Instantaneous Power: 151 Watt Heart Rate: 0 HBM 14:46:35.938 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 14:46:35.970 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 CD 09 86 00 14 00 83 00 00 ] 14:46:35.970 -> Instant. Speed: 25 KPH Instantaneous Cadence: 67 RPM Resistance Level: 20 Instantaneous Power: 131 Watt Heart Rate: 0 HBM 14:46:35.970 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 14:46:36.973 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 A9 09 8A 00 14 00 84 00 00 ] 14:46:36.973 -> Instant. Speed: 24 KPH Instantaneous Cadence: 69 RPM Resistance Level: 20 Instantaneous Power: 132 Watt Heart Rate: 0 HBM 14:46:37.978 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 B9 09 8E 00 14 00 84 00 00 ] 14:46:37.978 -> Instant. Speed: 24 KPH Instantaneous Cadence: 71 RPM Resistance Level: 20 Instantaneous Power: 132 Watt Heart Rate: 0 HBM 14:46:37.978 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 00 00 00 00 00 00 00 00 ] 14:46:38.009 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 00 01 ] 14:46:38.965 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 CB 09 8E 00 14 00 75 00 4F ] 14:46:38.965 -> Instant. Speed: 25 KPH Instantaneous Cadence: 71 RPM Resistance Level: 20 Instantaneous Power: 117 Watt Heart Rate: 79 HBM 14:46:39.978 -> -> Client Rec'd Raw FTM Indoor Bike Data: [11] [ 64 02 71 09 8E 00 14 00 77 00 00 ] 14:46:39.978 -> Instant. Speed: 24 KPH Instantaneous Cadence: 71 RPM Resistance Level: 20 Instantaneous Power: 119 Watt Heart Rate: 0 HBM 14:46:40.017 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 07 00 00 00 00 00 00 00 ] 14:46:40.141 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 07 01 ] 14:46:40.141 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 14:46:40.975 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 5F 09 81 08 8C 00 8C 00 06 00 00 14 00 76 00 76 00 00 ] 14:46:40.975 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 70 RPM Average Cadence: 70 RPM Total Distance: 6 m Resistance Level: 20 Instantaneous Power: 118 Watt Average Power: 118 Watt Heart Rate: 0 HBM 14:46:42.040 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 74 09 81 08 8E 00 8D 00 0C 00 00 14 00 74 00 75 00 00 ] 14:46:42.040 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 71 RPM Average Cadence: 70 RPM Total Distance: 12 m Resistance Level: 20 Instantaneous Power: 116 Watt Average Power: 117 Watt Heart Rate: 0 HBM 14:46:42.118 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 01 28 33 00 ] 14:46:42.395 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:46:42.395 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 01 28 33 ] 14:46:43.042 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 49 09 81 08 8A 00 8C 00 12 00 00 14 00 73 00 74 00 00 ] 14:46:43.042 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 69 RPM Average Cadence: 70 RPM Total Distance: 18 m Resistance Level: 20 Instantaneous Power: 115 Watt Average Power: 116 Watt Heart Rate: 0 HBM 14:46:44.030 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 03 09 81 08 8A 00 8B 00 18 00 00 14 00 7F 00 77 00 00 ] 14:46:44.030 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 69 RPM Average Cadence: 69 RPM Total Distance: 24 m Resistance Level: 20 Instantaneous Power: 127 Watt Average Power: 119 Watt Heart Rate: 0 HBM 14:46:44.217 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 09 00 28 33 00 ] 14:46:44.387 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:46:44.387 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 14:46:45.022 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 5E 09 81 08 88 00 8A 00 1E 00 00 14 00 87 00 7A 00 00 ] 14:46:45.023 -> Instant. Speed: 23 KPH Average Speed: 21 KPH Instantaneous Cadence: 68 RPM Average Cadence: 69 RPM Total Distance: 30 m Resistance Level: 20 Instantaneous Power: 135 Watt Average Power: 122 Watt Heart Rate: 0 HBM 14:46:45.997 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 B7 09 81 08 88 00 8A 00 24 00 00 14 00 9F 00 80 00 56 ] 14:46:45.997 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 68 RPM Average Cadence: 69 RPM Total Distance: 36 m Resistance Level: 20 Instantaneous Power: 159 Watt Average Power: 128 Watt Heart Rate: 86 HBM 14:46:46.308 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 14:46:46.448 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:46:46.448 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 14:46:47.003 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 79 09 81 08 88 00 8A 00 2A 00 00 14 00 8B 00 81 00 00 ] 14:46:47.003 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 68 RPM Average Cadence: 69 RPM Total Distance: 42 m Resistance Level: 20 Instantaneous Power: 139 Watt Average Power: 129 Watt Heart Rate: 0 HBM 14:46:47.991 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A7 09 81 08 8A 00 8A 00 30 00 00 14 00 73 00 80 00 00 ] 14:46:47.991 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 69 RPM Average Cadence: 69 RPM Total Distance: 48 m Resistance Level: 20 Instantaneous Power: 115 Watt Average Power: 128 Watt Heart Rate: 0 HBM 14:46:48.411 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 14 00 28 33 00 ] 14:46:48.503 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:46:48.503 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 14 00 28 33 ] 14:46:48.983 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 B1 09 81 08 8C 00 8A 00 36 00 00 14 00 64 00 7C 00 00 ] 14:46:48.983 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 70 RPM Average Cadence: 69 RPM Total Distance: 54 m Resistance Level: 20 Instantaneous Power: 100 Watt Average Power: 124 Watt Heart Rate: 0 HBM 14:46:49.953 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 91 09 81 08 8C 00 8A 00 3C 00 00 14 00 66 00 7A 00 00 ] 14:46:49.953 -> Instant. Speed: 24 KPH Average Speed: 21 KPH Instantaneous Cadence: 70 RPM Average Cadence: 69 RPM Total Distance: 60 m Resistance Level: 20 Instantaneous Power: 102 Watt Average Power: 122 Watt Heart Rate: 0 HBM 14:46:50.511 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 22 00 28 33 00 ] 14:46:50.867 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:46:50.867 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 22 00 28 33 ] 14:46:51.131 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 FA 09 A2 08 8E 00 8A 00 43 00 00 14 00 5C 00 77 00 00 ] 14:46:51.131 -> Instant. Speed: 25 KPH Average Speed: 22 KPH Instantaneous Cadence: 71 RPM Average Cadence: 69 RPM Total Distance: 67 m Resistance Level: 20 Instantaneous Power: 92 Watt Average Power: 119 Watt Heart Rate: 0 HBM 14:46:52.042 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 C9 09 9F 08 90 00 8B 00 49 00 00 14 00 63 00 76 00 00 ] 14:46:52.042 -> Instant. Speed: 25 KPH Average Speed: 22 KPH Instantaneous Cadence: 72 RPM Average Cadence: 69 RPM Total Distance: 73 m Resistance Level: 20 Instantaneous Power: 99 Watt Average Power: 118 Watt Heart Rate: 0 HBM 14:46:52.597 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 25 00 28 33 00 ] 14:46:52.751 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:46:52.751 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 25 00 28 33 ] 14:46:53.028 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 B3 09 9D 08 90 00 8B 00 4F 00 00 14 00 5D 00 74 00 00 ] 14:46:53.028 -> Instant. Speed: 24 KPH Average Speed: 22 KPH Instantaneous Cadence: 72 RPM Average Cadence: 69 RPM Total Distance: 79 m Resistance Level: 20 Instantaneous Power: 93 Watt Average Power: 116 Watt Heart Rate: 0 HBM 14:46:54.015 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 B9 09 9B 08 92 00 8C 00 55 00 00 14 00 55 00 71 00 00 ] 14:46:54.015 -> Instant. Speed: 24 KPH Average Speed: 22 KPH Instantaneous Cadence: 73 RPM Average Cadence: 70 RPM Total Distance: 85 m Resistance Level: 20 Instantaneous Power: 85 Watt Average Power: 113 Watt Heart Rate: 0 HBM 14:46:54.709 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 23 00 28 33 00 ] 14:46:54.833 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:46:54.833 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 00 28 33 ] 14:46:55.003 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 AF 09 99 08 94 00 8C 00 5B 00 00 14 00 8F 00 73 00 00 ] 14:46:55.003 -> Instant. Speed: 24 KPH Average Speed: 22 KPH Instantaneous Cadence: 74 RPM Average Cadence: 70 RPM Total Distance: 91 m Resistance Level: 20 Instantaneous Power: 143 Watt Average Power: 115 Watt Heart Rate: 0 HBM 14:46:56.070 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 2B 0A AF 08 92 00 8C 00 62 00 00 14 00 50 00 71 00 00 ] 14:46:56.070 -> Instant. Speed: 26 KPH Average Speed: 22 KPH Instantaneous Cadence: 73 RPM Average Cadence: 70 RPM Total Distance: 98 m Resistance Level: 20 Instantaneous Power: 80 Watt Average Power: 113 Watt Heart Rate: 0 HBM 14:46:56.812 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 1C 00 28 33 00 ] 14:46:56.969 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:46:56.969 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 00 28 33 ] 14:46:56.969 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 F0 09 C1 08 94 00 8D 00 69 00 00 14 00 83 00 72 00 00 ] 14:46:56.969 -> Instant. Speed: 25 KPH Average Speed: 22 KPH Instantaneous Cadence: 74 RPM Average Cadence: 70 RPM Total Distance: 105 m Resistance Level: 20 Instantaneous Power: 131 Watt Average Power: 114 Watt Heart Rate: 0 HBM 14:46:57.983 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 B5 09 BE 08 94 00 8D 00 6F 00 00 14 00 74 00 72 00 00 ] 14:46:57.983 -> Instant. Speed: 24 KPH Average Speed: 22 KPH Instantaneous Cadence: 74 RPM Average Cadence: 70 RPM Total Distance: 111 m Resistance Level: 20 Instantaneous Power: 116 Watt Average Power: 114 Watt Heart Rate: 0 HBM 14:46:58.909 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 0F 00 28 33 00 ] 14:46:59.063 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A3 09 BA 08 90 00 8D 00 75 00 00 14 00 4E 00 70 00 00 ] 14:46:59.064 -> Instant. Speed: 24 KPH Average Speed: 22 KPH Instantaneous Cadence: 72 RPM Average Cadence: 70 RPM Total Distance: 117 m Resistance Level: 20 Instantaneous Power: 78 Watt Average Power: 112 Watt Heart Rate: 0 HBM 14:46:59.064 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:46:59.064 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 0F 00 28 33 ] 14:47:00.039 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A9 09 B8 08 90 00 8D 00 7B 00 00 14 00 63 00 70 00 00 ] 14:47:00.039 -> Instant. Speed: 24 KPH Average Speed: 22 KPH Instantaneous Cadence: 72 RPM Average Cadence: 70 RPM Total Distance: 123 m Resistance Level: 20 Instantaneous Power: 99 Watt Average Power: 112 Watt Heart Rate: 0 HBM 14:47:01.027 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 00 00 28 33 00 ] 14:47:01.027 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 09 0A C6 08 8E 00 8D 00 82 00 00 14 00 66 00 6F 00 00 ] 14:47:01.027 -> Instant. Speed: 25 KPH Average Speed: 22 KPH Instantaneous Cadence: 71 RPM Average Cadence: 70 RPM Total Distance: 130 m Resistance Level: 20 Instantaneous Power: 102 Watt Average Power: 111 Watt Heart Rate: 0 HBM 14:47:01.120 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:47:01.120 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 14:47:02.030 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 DC 09 C3 08 90 00 8E 00 88 00 00 14 00 6B 00 6F 00 00 ] 14:47:02.030 -> Instant. Speed: 25 KPH Average Speed: 22 KPH Instantaneous Cadence: 72 RPM Average Cadence: 71 RPM Total Distance: 136 m Resistance Level: 20 Instantaneous Power: 107 Watt Average Power: 111 Watt Heart Rate: 0 HBM 14:47:03.021 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E3 09 C0 08 90 00 8E 00 8E 00 00 14 00 63 00 6E 00 00 ] 14:47:03.021 -> Instant. Speed: 25 KPH Average Speed: 22 KPH Instantaneous Cadence: 72 RPM Average Cadence: 71 RPM Total Distance: 142 m Resistance Level: 20 Instantaneous Power: 99 Watt Average Power: 110 Watt Heart Rate: 0 HBM 14:47:03.085 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 F5 FF 28 33 00 ] 14:47:03.284 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:47:03.284 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 F5 FF 28 33 ] 14:47:04.006 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 09 0A CD 08 92 00 8E 00 95 00 00 14 00 6A 00 6E 00 00 ] 14:47:04.006 -> Instant. Speed: 25 KPH Average Speed: 22 KPH Instantaneous Cadence: 73 RPM Average Cadence: 71 RPM Total Distance: 149 m Resistance Level: 20 Instantaneous Power: 106 Watt Average Power: 110 Watt Heart Rate: 0 HBM 14:47:04.996 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 FF 09 D8 08 92 00 8E 00 9C 00 00 14 00 67 00 6E 00 00 ] 14:47:04.996 -> Instant. Speed: 25 KPH Average Speed: 22 KPH Instantaneous Cadence: 73 RPM Average Cadence: 71 RPM Total Distance: 156 m Resistance Level: 20 Instantaneous Power: 103 Watt Average Power: 110 Watt Heart Rate: 0 HBM 14:47:05.214 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 E4 FF 28 33 00 ] 14:47:05.353 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:47:05.353 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 E4 FF 28 33 ] 14:47:05.985 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 2F 0A E3 08 94 00 8E 00 A3 00 00 14 00 62 00 6D 00 61 ] 14:47:05.985 -> Instant. Speed: 26 KPH Average Speed: 22 KPH Instantaneous Cadence: 74 RPM Average Cadence: 71 RPM Total Distance: 163 m Resistance Level: 20 Instantaneous Power: 98 Watt Average Power: 109 Watt Heart Rate: 97 HBM 14:47:06.972 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 EA 09 DF 08 94 00 8E 00 A9 00 00 14 00 68 00 6D 00 61 ] 14:47:06.972 -> Instant. Speed: 25 KPH Average Speed: 22 KPH Instantaneous Cadence: 74 RPM Average Cadence: 71 RPM Total Distance: 169 m Resistance Level: 20 Instantaneous Power: 104 Watt Average Power: 109 Watt Heart Rate: 97 HBM 14:47:07.312 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 CF FF 28 33 00 ] 14:47:07.512 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:47:07.512 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 CF FF 28 33 ] 14:47:07.973 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 0A 0A E9 08 92 00 8E 00 B0 00 00 14 00 50 00 6C 00 00 ] 14:47:07.973 -> Instant. Speed: 25 KPH Average Speed: 22 KPH Instantaneous Cadence: 73 RPM Average Cadence: 71 RPM Total Distance: 176 m Resistance Level: 20 Instantaneous Power: 80 Watt Average Power: 108 Watt Heart Rate: 0 HBM 14:47:09.038 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 F0 09 F2 08 92 00 8F 00 B7 00 00 14 00 47 00 6B 00 00 ] 14:47:09.038 -> Instant. Speed: 25 KPH Average Speed: 22 KPH Instantaneous Cadence: 73 RPM Average Cadence: 71 RPM Total Distance: 183 m Resistance Level: 20 Instantaneous Power: 71 Watt Average Power: 107 Watt Heart Rate: 0 HBM 14:47:09.424 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 A8 FF 28 33 00 ] 14:47:09.549 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:47:09.594 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 A8 FF 28 33 ] 14:47:10.017 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 76 0A FA 08 94 00 8F 00 BE 00 00 14 00 5B 00 6A 00 00 ] 14:47:10.017 -> Instant. Speed: 26 KPH Average Speed: 22 KPH Instantaneous Cadence: 74 RPM Average Cadence: 71 RPM Total Distance: 190 m Resistance Level: 20 Instantaneous Power: 91 Watt Average Power: 106 Watt Heart Rate: 0 HBM 14:47:11.028 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 3A 0A 02 09 94 00 8F 00 C5 00 00 14 00 58 00 6A 00 00 ] 14:47:11.028 -> Instant. Speed: 26 KPH Average Speed: 23 KPH Instantaneous Cadence: 74 RPM Average Cadence: 71 RPM Total Distance: 197 m Resistance Level: 20 Instantaneous Power: 88 Watt Average Power: 106 Watt Heart Rate: 0 HBM 14:47:11.499 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 84 FF 28 33 00 ] 14:47:11.618 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:47:11.655 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 84 FF 28 33 ] 14:47:12.108 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 59 0A 09 09 96 00 8F 00 CC 00 00 14 00 4E 00 69 00 00 ] 14:47:12.108 -> Instant. Speed: 26 KPH Average Speed: 23 KPH Instantaneous Cadence: 75 RPM Average Cadence: 71 RPM Total Distance: 204 m Resistance Level: 20 Instantaneous Power: 78 Watt Average Power: 105 Watt Heart Rate: 0 HBM 14:47:12.996 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 CC 09 05 09 98 00 8F 00 D2 00 00 14 00 1F 00 67 00 00 ] 14:47:12.996 -> Instant. Speed: 25 KPH Average Speed: 23 KPH Instantaneous Cadence: 76 RPM Average Cadence: 71 RPM Total Distance: 210 m Resistance Level: 20 Instantaneous Power: 31 Watt Average Power: 103 Watt Heart Rate: 0 HBM 14:47:13.627 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 67 FF 28 33 00 ] 14:47:13.998 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:47:13.998 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 FF 28 33 ] 14:47:13.998 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 25 09 01 09 00 00 8B 00 D8 00 00 14 00 00 00 64 00 64 ] 14:47:13.998 -> Instant. Speed: 23 KPH Average Speed: 23 KPH Instantaneous Cadence: 0 RPM Average Cadence: 69 RPM Total Distance: 216 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 100 Watt Heart Rate: 100 HBM 14:47:14.971 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 82 08 FE 08 00 00 87 00 DE 00 00 14 00 00 00 61 00 00 ] 14:47:14.971 -> Instant. Speed: 21 KPH Average Speed: 23 KPH Instantaneous Cadence: 0 RPM Average Cadence: 67 RPM Total Distance: 222 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 97 Watt Heart Rate: 0 HBM 14:47:15.724 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5D FF 28 33 00 ] 14:47:15.972 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:47:15.972 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5D FF 28 33 ] 14:47:15.972 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 E7 07 F0 08 00 00 83 00 E3 00 00 14 00 00 00 5E 00 00 ] 14:47:15.972 -> Instant. Speed: 20 KPH Average Speed: 22 KPH Instantaneous Cadence: 0 RPM Average Cadence: 65 RPM Total Distance: 227 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 94 Watt Heart Rate: 0 HBM 14:47:16.973 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 4E 07 E3 08 00 00 80 00 E8 00 00 14 00 00 00 5B 00 00 ] 14:47:16.973 -> Instant. Speed: 18 KPH Average Speed: 22 KPH Instantaneous Cadence: 0 RPM Average Cadence: 64 RPM Total Distance: 232 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 91 Watt Heart Rate: 0 HBM 14:47:17.825 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 5E FF 28 33 00 ] 14:47:17.935 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:47:17.935 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5E FF 28 33 ] 14:47:18.014 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 BC 06 CE 08 00 00 7C 00 EC 00 00 14 00 00 00 59 00 00 ] 14:47:18.014 -> Instant. Speed: 17 KPH Average Speed: 22 KPH Instantaneous Cadence: 0 RPM Average Cadence: 62 RPM Total Distance: 236 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 89 Watt Heart Rate: 0 HBM 14:47:19.033 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 2A 06 B9 08 00 00 79 00 F0 00 00 14 00 00 00 57 00 00 ] 14:47:19.033 -> Instant. Speed: 15 KPH Average Speed: 22 KPH Instantaneous Cadence: 0 RPM Average Cadence: 60 RPM Total Distance: 240 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 87 Watt Heart Rate: 0 HBM 14:47:19.920 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 6F FF 28 33 00 ] 14:47:20.012 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:47:20.012 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 6F FF 28 33 ] 14:47:20.012 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 A0 05 9D 08 00 00 76 00 F3 00 00 14 00 00 00 55 00 00 ] 14:47:20.012 -> Instant. Speed: 14 KPH Average Speed: 22 KPH Instantaneous Cadence: 0 RPM Average Cadence: 59 RPM Total Distance: 243 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 85 Watt Heart Rate: 0 HBM 14:47:21.023 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 17 05 81 08 00 00 73 00 F6 00 00 14 00 00 00 52 00 00 ] 14:47:21.023 -> Instant. Speed: 13 KPH Average Speed: 21 KPH Instantaneous Cadence: 0 RPM Average Cadence: 57 RPM Total Distance: 246 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 82 Watt Heart Rate: 0 HBM 14:47:21.987 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 94 04 67 08 00 00 71 00 F9 00 00 14 00 00 00 50 00 00 ] 14:47:21.987 -> Instant. Speed: 11 KPH Average Speed: 21 KPH Instantaneous Cadence: 0 RPM Average Cadence: 56 RPM Total Distance: 249 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 80 Watt Heart Rate: 0 HBM 14:47:22.029 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 8A FF 28 33 00 ] 14:47:22.167 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:47:22.167 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8A FF 28 33 ] 14:47:22.985 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 15 04 46 08 00 00 6E 00 FB 00 00 14 00 00 00 4F 00 00 ] 14:47:22.985 -> Instant. Speed: 10 KPH Average Speed: 21 KPH Instantaneous Cadence: 0 RPM Average Cadence: 55 RPM Total Distance: 251 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 79 Watt Heart Rate: 0 HBM 14:47:23.993 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 99 03 27 08 00 00 6B 00 FD 00 00 14 00 00 00 4D 00 00 ] 14:47:23.993 -> Instant. Speed: 9 KPH Average Speed: 20 KPH Instantaneous Cadence: 0 RPM Average Cadence: 53 RPM Total Distance: 253 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 77 Watt Heart Rate: 0 HBM 14:47:24.132 -> Client sends Indoor Bike Simulation Parameters to Trainer's FTM Control Point: [ 11 00 00 B8 FF 28 33 00 ] 14:47:24.258 -> -> Client Rec'd Raw FTM Control Point Response Data: [ 80 11 01 ] 14:47:24.258 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 B8 FF 28 33 ] 14:47:24.939 -> -> Client Rec'd Raw FTM Indoor Bike Data: [20] [ FE 02 25 03 08 08 00 00 69 00 FF 00 00 14 00 00 00 4B 00 00 ] 14:47:24.939 -> Instant. Speed: 8 KPH Average Speed: 20 KPH Instantaneous Cadence: 0 RPM Average Cadence: 52 RPM Total Distance: 255 m Resistance Level: 20 Instantaneous Power: 0 Watt Average Power: 75 Watt Heart Rate: 0 HBM
Dear Joel, That looks perfect! The whole connect procedure took more than 7 seconds. No cluttering of print output anymore, no failing discover- or read actions! At the very moment the IBD Char is enabled the trainer starts to send IBD data. Perfect! The trainer is being ready!
IBD data will always contain an empty HBM value. No problem! This code does NOT support Zwift's special party trick for Apple TV users!
If you connect your heart rate strap: DO NOT connect it with the Zwift Hub trainer (switch OFF that feature in the Zwift Companion app) but connect it with Zwift (or Rouvy or any controlling app) directly using its specific name like 'Garmin HRM strap' or whatever name yours has! If you see on the Zwift pairing screen a Heart Rate connection with the name: 'Sim nRF52', you know that things are wrongly connected! That configuration is NOT supported!
Thanks for your testing effort! I will prepare now accordingly the FTMS_Zwift_Bridge code! Have a nice day! Jörgen.
Jörghen,
Concern the HRM and test bridge, it is by connecting it to the Zwift hub that the system works if I do not do so then the system breaks down !?
Sorry Joël, Please be more specific, this is far too cryptic for me!
Op di 20 dec. 2022 16:31 schreef le-joebar @.***>:
Jörghen,
Concern the HRM and test bridge, it is by connecting it to the Zwift hub that the system works if I do not do so then the system breaks down !?
— Reply to this email directly, view it on GitHub https://github.com/Berg0162/simcline/issues/7#issuecomment-1359568811, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANS5LST5NPEPEAACMVYEVRLWOHGMHANCNFSM6AAAAAASZDERFE . You are receiving this because you authored the thread.Message ID: @.***>
Dear Joel, Uploaded as promised an up-to-date version for FTMS_Zwift_Bridge_v024
I wondered, does the highlighted FTM Feature mean: trainer is NOW set for HRM rebroadcasting? If you switch it to OFF (with the Companion App) is this FTM Feature then missing (OFF state) ???
Client Reads Raw FTM Feature bytes: [8] [ 87 44 00 00 0C E0 00 00 ] 14:46:24.182 -> - Fitness Machine Features: 14:46:24.182 -> Average Speed Supported 14:46:24.182 -> Cadence Supported 14:46:24.182 -> Total Distance Supported 14:46:24.182 -> Resistance Level Supported 14:46:24.182 -> Heart Rate Measurement Supported 14:46:24.182 -> Power Measurement Supported 14:46:24.182 -> - Target Setting Features: 14:46:24.182 -> Resistance Target Setting Supported 14:46:24.182 -> Power Target Setting Supported 14:46:24.182 -> Indoor Bike Simulation Parameters Supported 14:46:24.182 -> Wheel Circumference Configuration Supported 14:46:24.182 -> Spin Down Control Supported
--> Not to difficult to test with Client_FTMS_v029.... NO Heart Rate band needed! Make the change and just check the decoded FTM Feature output...for a change! Reverse the process and see if the feature comes back again! Enjoy your day! Jörgen.
Hello Jorghen,
I tested the FTMS_BRIDGE V24 version
No problem encountered
Here are the results.
We find the "grade" value to evolve by half the value on Zwift, it's normal since I set the difficulty value of the trainer to 50%.
I checked the result with HRM connected via Companion or not. There is no change in the presentation of the service it remains present.
I don't think you need to look for an answer of why it works?
Just a question. What is the value: Wind speed (1000): 0.00 | Rank (100): 0.51 | Crr(10000): 0.00 | Cw(100): 0.51
17:31:54.953 -> Feather nRF52840 MITM supporting: CPS, CSC and FTMS 17:31:54.953 -> ------------------ Version 02.4 --------------------- 17:31:55.408 -> FTM Service and Chars are 'initialized' 17:31:55.408 -> CP Service and Chars are 'initialized' 17:31:55.408 -> CSC Service and Chars are 'initialized' 17:31:55.408 -> Generic Access Service and Chars are 'initialized' 17:31:55.408 -> Device Information Service and Chars are 'initialized' 17:31:55.408 -> Start Client-side Scanning for CPS, CSC and FTMS! 17:32:08.832 -> Found advertising Peripheral with FTMS enabled! See Raw data packet: 17:32:08.832 -> Timestamp Addr Rssi Data 17:32:08.832 -> 000015263 F8:9C:FC:53:5E:49 -58 09-02-16-18-26-18-18-18-0A-18 17:32:09.045 -> Feather nRF52 (Central) connected to Trainer (Peripheral) device: [Zwift Hub] MAC Address: F8:9C:FC:53:5E:49 17:32:09.045 -> Now checking all mandatory Client Services and Characteristics! 17:32:09.045 -> If Mandatory Services Fail --> the Client will disconnect! 17:32:09.294 -> First checking Generic Access and Device Information Services and Characteristics! 17:32:09.373 -> Found Client Generic Access 17:32:09.793 -> -> Client Reads Device Name: [Zwift Hub] 17:32:10.326 -> -> Client Reads Appearance: [0] 17:32:10.731 -> Found Client Device Information 17:32:11.087 -> -> Client Reads Manufacturer: [Zwift] 17:32:11.651 -> -> Client Reads Model Number: [06] 17:32:12.091 -> -> Client Reads Serial Number: [06-F89CFC535E49] 17:32:12.324 -> Discovering Mandatory Client Fitness Machine (FTM) Service ... Found it! FTMS Max Payload: 20 Data Length: 27 17:32:12.651 -> Discovering Client FTM Feature Characteristic ... Found it! 17:32:12.882 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ] 17:32:12.882 -> - Fitness Machine Features: 17:32:12.882 -> - Target Setting Features: 17:32:13.158 -> Discovering Client FTM Control Point Characteristic ... Found it! 17:32:13.702 -> Discovering Client FTM Status Characteristic ... Found it! 17:32:14.192 -> Discovering Client FTM Training Status Characteristic ... Not Found! Not Mandatory 17:32:14.566 -> Discovering Client FTM Supported Resistance Level Range Characteristic ... Found it! 17:32:14.656 -> -> Client Reads Raw FTM Supported Resistance Level Range bytes: [6] [ 00 00 64 00 01 00 ] 17:32:14.920 -> Discovering Client FTM Supported Power Range Characteristic ... Found it! 17:32:15.044 -> -> Client Reads Raw FTM Supported Power Range bytes: [6] [ 00 00 E8 03 01 00 ] 17:32:15.310 -> Discovering Client FTM Indoor Bike Data Characteristic ... Found it! 17:32:15.661 -> Discovering Client Cycling Power (CP) Service ... Found it! CPS Max Payload: 20 Data Length: 27 17:32:15.913 -> Discovering Client CP Measurement characteristic ... Found it! 17:32:16.268 -> Discovering Client CP Control Point characteristic ... Not Found! NOT Mandatory! 17:32:16.576 -> Discovering Client CP Feature characteristic ... Found it! 17:32:16.685 -> -> Client Reads Raw CP Feature bytes: [4] [ 0C 00 00 00 ] 17:32:16.685 -> Wheel revolution data supported 17:32:16.685 -> Crank revolution data supported 17:32:16.916 -> Discovering Client CP Sensor Location characteristic ... Found it! 17:32:17.009 -> -> Client Reads CP Location Sensor: Loc#: 12 Rear wheel 17:32:17.271 -> Discovering Cycling Speed and Cadence (CSC) Service ... Found it! CSCS Max Payload: 20 Data Length: 27 17:32:17.349 -> Configuring the Server Device Information Service 17:32:17.349 -> Configuring the Server Cycle Power Service 17:32:17.349 -> Configuring the Server Cadence and Speed Service 17:32:17.349 -> Configuring the Server Fitness Machine Service 17:32:17.349 -> Configuring the Server NUS Service 17:32:17.349 -> Setting up the Server-side advertising payload(s) 17:32:17.349 -> Setting Server Device Name to: [Sim Zwift] 17:32:17.349 -> Setting Server Appearance to: [0] 17:32:17.349 -> Server-side is CPS, CSC and FTMS advertising! 17:32:17.533 -> Discovering Client CSC Measurement CHR ... Found it! 17:32:17.919 -> Discovering Client CSC Location CHR ... Found it! 17:32:18.044 -> -> Client Reads CSC Location Sensor: Loc#: 0 Other 17:32:18.275 -> Discovering Client CSC Feature CHR ... Found it! 17:32:18.399 -> -> Client Reads Raw CSC Feature bytes: [2] [ 03 00 ] 17:32:18.399 -> Wheel rev supported 17:32:18.399 -> Crank rev supported 17:34:12.339 -> Client- and Server-side are Up and Running! 17:34:14.345 -> Ready to receive Client FTM Indoor Bike Data values 17:34:14.345 -> >>> Couldn't enable indicate for Client CP Control Point Characteristic. 17:34:14.383 -> Ready to receive Client CP Measurement values 17:34:14.430 -> Ready to receive Client CSC Measurement values 17:34:14.430 -> Waiting for Central (Zwift) to set CCCD Notify/Indicate (enable) and start.... 17:34:16.038 -> Central Device Updated CCCD to: [1] --> Server CP: Measurement 'Notify' enabled 17:34:16.586 -> Central Device Updated CCCD to: [1] --> Server CSC: Measurement 'Notify' enabled 17:34:17.291 -> Central Device Updated CCCD to: [1] --> Server FTM: IndoorBikeData 'Notify' enabled 17:34:18.057 -> Central Device Updated CCCD to: [1] --> Server FTM: Status 'Notify' enabled 17:34:42.216 -> -> Server Rec'd Raw FTM Control Point Data [len: 1] [OpCode: 00] [Values: 00 ] 17:34:42.216 -> Request Control of Machine! 17:34:42.311 -> -> Client Rec'd Control Point Response: [ 80 00 01 ] 17:34:42.451 -> -> Server Rec'd Raw FTM Control Point Data [len: 1] [OpCode: 01] [Values: 00 ] 17:34:42.451 -> Reset Machine! 17:34:42.451 -> -> Server Rec'd Raw FTM Control Point Data [len: 1] [OpCode: 00] [Values: 00 ] 17:34:42.451 -> Request Control of Machine! 17:34:42.593 -> -> Client Rec'd Control Point Response: [ 80 01 01 ] 17:34:42.593 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 01 ] 17:34:47.592 -> -> Server Rec'd Raw FTM Control Point Data [len: 1] [OpCode: 00] [Values: 00 ] 17:34:47.592 -> Request Control of Machine! 17:34:47.639 -> -> Client Rec'd Control Point Response: [ 80 00 01 ] 17:34:47.716 -> -> Server Rec'd Raw FTM Control Point Data [len: 1] [OpCode: 07] [Values: 00 ] 17:34:47.716 -> Start or Resume Machine! 17:34:47.811 -> -> Client Rec'd Control Point Response: [ 80 07 01 ] 17:34:47.811 -> -> Client Rec'd Raw FTM Machine Status Data: [1] [ 04 ] 17:34:48.743 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 FD 00 28 33 00 ] 17:34:48.743 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 2.53 | Crr (10000): 0.00 | Cw (100): 0.51 17:34:48.882 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:34:48.882 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 FD 00 28 33 ] 17:36:06.275 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 B1 00 28 33 00 ] 17:36:06.318 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.77 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:06.401 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:06.401 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 B1 00 28 33 ] 17:36:07.326 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 33 00 28 33 00 ] 17:36:07.326 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.51 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:07.372 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:07.372 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 33 00 28 33 ] 17:36:32.918 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 32 00 28 33 00 ] 17:36:32.918 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.50 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:33.010 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:33.010 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 32 00 28 33 ] 17:36:36.157 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 33 00 28 33 00 ] 17:36:36.157 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.51 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:36.267 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:36.267 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 33 00 28 33 ] 17:36:37.107 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 35 00 28 33 00 ] 17:36:37.107 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.53 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:37.154 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:37.199 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 35 00 28 33 ] 17:36:38.079 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 39 00 28 33 00 ] 17:36:38.079 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.57 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:38.156 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:38.156 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 39 00 28 33 ] 17:36:39.030 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 40 00 28 33 00 ] 17:36:39.030 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.64 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:39.155 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:39.155 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 40 00 28 33 ] 17:36:40.061 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 4E 00 28 33 00 ] 17:36:40.061 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.78 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:40.141 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:40.141 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 4E 00 28 33 ] 17:36:41.046 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 61 00 28 33 00 ] 17:36:41.046 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.97 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:41.311 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:41.311 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 61 00 28 33 ] 17:36:42.122 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 71 00 28 33 00 ] 17:36:42.122 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.13 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:42.387 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:42.387 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 71 00 28 33 ] 17:36:43.231 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 75 00 28 33 00 ] 17:36:43.231 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.17 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:43.278 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:43.278 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 75 00 28 33 ] 17:36:44.194 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 68 00 28 33 00 ] 17:36:44.194 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.04 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:44.273 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:44.273 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 68 00 28 33 ] 17:36:45.161 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 4E 00 28 33 00 ] 17:36:45.161 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.78 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:45.300 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:45.300 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 4E 00 28 33 ] 17:36:46.203 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 2A 00 28 33 00 ] 17:36:46.203 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.42 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:46.250 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:46.250 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 2A 00 28 33 ] 17:36:47.123 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 1C 00 28 33 00 ] 17:36:47.123 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.28 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:47.247 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:47.247 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1C 00 28 33 ] 17:36:48.139 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 21 00 28 33 00 ] 17:36:48.139 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.33 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:48.328 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:48.328 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 21 00 28 33 ] 17:36:49.215 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 1F 00 28 33 00 ] 17:36:49.215 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.31 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:49.324 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:49.324 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1F 00 28 33 ] 17:36:50.197 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 1A 00 28 33 00 ] 17:36:50.197 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.26 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:50.290 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:50.290 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 1A 00 28 33 ] 17:36:51.183 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 13 00 28 33 00 ] 17:36:51.183 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.19 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:51.276 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:51.276 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 13 00 28 33 ] 17:36:52.208 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 09 00 28 33 00 ] 17:36:52.208 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.09 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:52.286 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:52.286 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 09 00 28 33 ] 17:36:53.143 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 00 00 28 33 00 ] 17:36:53.143 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.00 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:53.221 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:53.221 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 00 00 28 33 ] 17:36:54.051 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 F9 FF 28 33 00 ] 17:36:54.051 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): -0.07 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:54.271 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:54.271 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 F9 FF 28 33 ] 17:36:55.143 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 EF FF 28 33 00 ] 17:36:55.143 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): -0.17 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:55.235 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:55.235 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 EF FF 28 33 ] 17:36:56.109 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 E3 FF 28 33 00 ] 17:36:56.109 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): -0.29 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:56.141 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:56.141 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 E3 FF 28 33 ] 17:36:56.998 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 D4 FF 28 33 00 ] 17:36:56.998 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): -0.44 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:57.044 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:57.044 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 D4 FF 28 33 ] 17:36:57.934 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 BE FF 28 33 00 ] 17:36:57.934 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): -0.66 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:58.044 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:58.044 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 BE FF 28 33 ] 17:36:58.901 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 9F FF 28 33 00 ] 17:36:58.901 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): -0.97 | Crr (10000): 0.00 | Cw (100): 0.51 17:36:59.072 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:36:59.072 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 9F FF 28 33 ] 17:36:59.932 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 86 FF 28 33 00 ] 17:36:59.932 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): -1.22 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:00.119 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:00.119 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 86 FF 28 33 ] 17:37:00.979 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 74 FF 28 33 00 ] 17:37:00.979 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): -1.40 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:01.105 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:01.105 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 74 FF 28 33 ] 17:37:01.980 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 6D FF 28 33 00 ] 17:37:01.980 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): -1.47 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:02.104 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:02.104 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 6D FF 28 33 ] 17:37:02.964 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 72 FF 28 33 00 ] 17:37:02.964 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): -1.42 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:03.183 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:03.183 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 72 FF 28 33 ] 17:37:04.026 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 88 FF 28 33 00 ] 17:37:04.026 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): -1.20 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:04.072 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:04.072 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 88 FF 28 33 ] 17:37:04.994 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 AD FF 28 33 00 ] 17:37:04.994 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): -0.83 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:05.180 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:05.180 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 AD FF 28 33 ] 17:37:05.974 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 E6 FF 28 33 00 ] 17:37:05.974 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): -0.26 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:06.053 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:06.053 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 E6 FF 28 33 ] 17:37:06.926 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 23 00 28 33 00 ] 17:37:06.926 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.35 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:07.037 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:07.037 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 23 00 28 33 ] 17:37:07.913 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 67 00 28 33 00 ] 17:37:07.913 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.03 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:08.039 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:08.039 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 00 28 33 ] 17:37:08.930 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 8B 00 28 33 00 ] 17:37:08.930 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.39 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:09.009 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:09.009 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8B 00 28 33 ] 17:37:09.993 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 96 00 28 33 00 ] 17:37:09.993 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.50 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:10.134 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:10.134 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 96 00 28 33 ] 17:37:11.022 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 93 00 28 33 00 ] 17:37:11.022 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.47 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:11.101 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:11.101 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 93 00 28 33 ] 17:37:11.973 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 8B 00 28 33 00 ] 17:37:11.973 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.39 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:12.160 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:12.160 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8B 00 28 33 ] 17:37:13.062 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 7F 00 28 33 00 ] 17:37:13.062 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.27 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:13.156 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:13.156 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 7F 00 28 33 ] 17:37:14.073 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 76 00 28 33 00 ] 17:37:14.073 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.18 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:14.340 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:14.340 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 76 00 28 33 ] 17:37:15.183 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 71 00 28 33 00 ] 17:37:15.183 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.13 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:15.322 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:15.322 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 71 00 28 33 ] 17:37:16.215 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 70 00 28 33 00 ] 17:37:16.215 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.12 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:16.305 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:16.305 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 70 00 28 33 ] 17:37:17.211 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 6D 00 28 33 00 ] 17:37:17.211 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.09 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:17.477 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:17.477 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 6D 00 28 33 ] 17:37:37.763 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 6B 00 28 33 00 ] 17:37:37.763 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.07 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:37.950 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:37.950 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 6B 00 28 33 ] 17:37:38.760 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 65 00 28 33 00 ] 17:37:38.760 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.01 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:38.808 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:38.808 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 65 00 28 33 ] 17:37:39.744 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 61 00 28 33 00 ] 17:37:39.744 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.97 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:39.916 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:39.916 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 61 00 28 33 ] 17:37:40.808 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 5B 00 28 33 00 ] 17:37:40.808 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.91 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:41.027 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:41.027 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5B 00 28 33 ] 17:37:41.945 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 56 00 28 33 00 ] 17:37:41.945 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.86 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:42.039 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:42.039 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 56 00 28 33 ] 17:37:42.909 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 57 00 28 33 00 ] 17:37:42.909 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.87 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:43.081 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:43.081 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 57 00 28 33 ] 17:37:43.954 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 5E 00 28 33 00 ] 17:37:43.954 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 0.94 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:44.032 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:44.032 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 5E 00 28 33 ] 17:37:44.982 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 67 00 28 33 00 ] 17:37:44.982 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.03 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:45.121 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:45.121 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 67 00 28 33 ] 17:37:45.979 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 6F 00 28 33 00 ] 17:37:45.979 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.11 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:46.103 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:46.103 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 6F 00 28 33 ] 17:37:46.957 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 75 00 28 33 00 ] 17:37:46.957 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.17 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:47.127 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:47.127 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 75 00 28 33 ] 17:37:48.183 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 7A 00 28 33 00 ] 17:37:48.183 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.22 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:48.277 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:48.277 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 7A 00 28 33 ] 17:37:49.026 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 7E 00 28 33 00 ] 17:37:49.026 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.26 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:49.165 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:49.165 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 7E 00 28 33 ] 17:37:49.989 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 80 00 28 33 00 ] 17:37:49.989 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.28 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:50.067 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:50.067 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 80 00 28 33 ] 17:37:50.941 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 83 00 28 33 00 ] 17:37:50.941 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.31 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:51.066 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:51.066 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 83 00 28 33 ] 17:37:51.796 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 84 00 28 33 00 ] 17:37:51.796 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.32 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:51.984 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:51.984 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 84 00 28 33 ] 17:37:52.936 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 86 00 28 33 00 ] 17:37:52.936 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.34 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:53.030 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:53.030 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 86 00 28 33 ] 17:37:53.949 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 88 00 28 33 00 ] 17:37:53.949 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.36 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:54.027 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:54.027 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 88 00 28 33 ] 17:37:54.792 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 8A 00 28 33 00 ] 17:37:54.792 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.38 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:54.961 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:54.961 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8A 00 28 33 ] 17:37:55.786 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 8B 00 28 33 00 ] 17:37:55.786 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.39 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:55.910 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:55.910 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8B 00 28 33 ] 17:37:56.766 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 8C 00 28 33 00 ] 17:37:56.766 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.40 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:56.797 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:56.797 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8C 00 28 33 ] 17:37:57.734 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 8D 00 28 33 00 ] 17:37:57.734 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.41 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:57.954 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:57.954 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8D 00 28 33 ] 17:37:59.588 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 8E 00 28 33 00 ] 17:37:59.588 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.42 | Crr (10000): 0.00 | Cw (100): 0.51 17:37:59.681 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:37:59.681 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8E 00 28 33 ] 17:38:02.050 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 8F 00 28 33 00 ] 17:38:02.050 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.43 | Crr (10000): 0.00 | Cw (100): 0.51 17:38:02.129 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:38:02.129 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8F 00 28 33 ] 17:38:05.208 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 90 00 28 33 00 ] 17:38:05.208 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.44 | Crr (10000): 0.00 | Cw (100): 0.51 17:38:05.366 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:38:05.366 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 90 00 28 33 ] 17:38:15.990 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 8F 00 28 33 00 ] 17:38:15.990 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.43 | Crr (10000): 0.00 | Cw (100): 0.51 17:38:16.069 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:38:16.069 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8F 00 28 33 ] 17:38:21.556 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 8E 00 28 33 00 ] 17:38:21.557 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.42 | Crr (10000): 0.00 | Cw (100): 0.51 17:38:21.648 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:38:21.648 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8E 00 28 33 ] 17:38:23.971 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 8D 00 28 33 00 ] 17:38:23.971 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.41 | Crr (10000): 0.00 | Cw (100): 0.51 17:38:24.158 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:38:24.158 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8D 00 28 33 ] 17:38:25.746 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 8C 00 28 33 00 ] 17:38:25.746 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.40 | Crr (10000): 0.00 | Cw (100): 0.51 17:38:25.918 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:38:25.918 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8C 00 28 33 ] 17:38:28.284 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 8B 00 28 33 00 ] 17:38:28.284 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.39 | Crr (10000): 0.00 | Cw (100): 0.51 17:38:28.409 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:38:28.409 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 8B 00 28 33 ] 17:39:28.747 -> -> Server Rec'd Raw FTM Control Point Data [len: 7] [OpCode: 11] [Values: 00 00 6D 00 28 33 00 ] 17:39:28.747 -> Set Indoor Bike Simulation Parameters --> Wind speed (1000): 0.00 | Grade (100): 1.09 | Crr (10000): 0.00 | Cw (100): 0.51 17:39:28.856 -> -> Client Rec'd Control Point Response: [ 80 11 01 ] 17:39:28.856 -> -> Client Rec'd Raw FTM Machine Status Data: [7] [ 12 00 00 6D 00 28 33 ] 17:40:21.715 -> Server disconnected from Central (Laptop): [], reason: [13]
Dear Joel, Thanks for your effort and well done! Not a bad result, however a few readings are missed in the beginning, that needs my(!) attention:
17:32:10.326 -> -> Client Reads Appearance: [0] 17:32:12.882 -> -> Client Reads Raw FTM Feature bytes: [8] [ 00 00 00 00 00 00 00 00 ]
You have to help me to clarify the HRM (Heart Rate Measurement) connection context, I need to precisely understand how critical devices are connected......that helps making the code more robust for different situations and "une déformation professionnelle" !
In the recent run, I see HRM is paired (on the screen shots you included) and showing real BPM (like 70 Beats Per Minute)
--> do you use a Heart Rate Strap, or an other device? Can you give me the type and brand name?
--> is the Zwift Game App (on the PC) connected directly with your Heart Rate Strap? OR
--> is the Zwift HUB Trainer connected with your Heart Rate Strap and then the trainer is connected with the Zwift Game App (on the PC)?
I am pleasantly surprised about the following Client_FTMS test result:
I checked the result with HRM connected via Companion or not. There is no change in the presentation of the service it remains present.
--> I assume that in both (above) cases the real time BPM data are shown, is that correct? Apparently the Zwift Game app (on the PC) is using the Indoor Bike Data for extracting the BPM when it is not connected directly with your heart rate strap. You have seen in previous FTMS_Client runs that a BPM field is present in IBData! I have to think about possible consequences but again this is a clever feature!
Now remains the following issue:
I can't turn on the cardio frequency meter otherwise everything crashes!!
What is the present status? Can you crash the code in certain situations?
I hope you will take some time to answer the questions and again thank you for doing the testing so quickly! Regards, Jörgen.
Here is the first result with FTMSClient v022
I don't know if it's good?
Next test when I receive the dongle for the Pc
Friendship, Joel
[CFG ] SoftDevice's RAM requires: 0x20002C78 FTMS and Chars 'initialized' CPS and Chars 'initialized' CSCS and Chars 'initialized' GA and Chars 'initialized' DIS and Chars 'initialized' Start Scanning for CPS, CSC and FTMS! [BLE ] BLE_GAP_EVT_ADV_REPORT : Conn Handle = 65535 [BLE ] BLE_GAP_EVT_ADV_REPORT : Conn Handle = 65535 Found advertising Peripheral with FTMS service!, see the Raw Data packet: Timestamp MAC Address Rssi Data 000000681 F8:9C:FC:53:5E:49 -60 09-02-16-18-26-18-18-18-0A-18 [BLE ] BLE_GAP_EVT_CONNECTED : Conn Handle = 0 [GAP ] MAC = F8:9C:FC:53:5E:49, Type = 1, Resolved = 0 [GAP ] Conn Interval = 20.00 ms, Latency = 0, Supervisor Timeout = 2000 ms [BLE ] BLE_GAP_EVT_DISCONNECTED : Conn Handle = 0 [GAP ] Disconnect Reason: CONN_FAILED_TO_BE_ESTABLISHED Feather nRF52 (Central) connected to Trainer (Peripheral) device: [] MAC Address: F8:9C:FC:53:5E:49 Now checking mandatory Client Services and Characteristics! Discovering Client Cycling Power (CP) Service ... [DISC ] [SVC] Handle start = 1 bool BLEDiscovery::_discoverService(uint16_t, BLEClientService&, uint16_t): 79: verify failed, error = BLE_ERROR_INVALID_CONN_HANDLE Not Found! Disconnecting since Client Cyling Power Service is mandatory! Client Disconnected, reason = 0x3E
BSP Library : 1.3.0 Bootloader : s140 6.1.1 Serial No : C2BA380FAD3CBBC2
--------- SoftDevice Config --------- Max UUID128 : 10 ATTR Table Size : 4096 Service Changed : 1 Central Connect Setting
--------- BLE Settings --------- Name : ItsyBitsy nRF52840 Express Max Connections : Peripheral = 0, Central = 1 Address : E2:AA:F7:E9:06:E0 (Static) TX Power : 0 dBm Conn Intervals : min = 20.00 ms, max = 30.00 ms Conn Timeout : 2000 ms Central Paired Devices:
Originally posted by @le-joebar in https://github.com/Berg0162/simcline/issues/5#issuecomment-1342980419