WouterJD / FortiusANT

FortiusANT enables a pre-smart Tacx trainer (usb- or ANT-connected) to communicate with TrainerRoad, Rouvy or Zwift through ANT or Bluetooth LE.
GNU General Public License v3.0
153 stars 78 forks source link

ANT+ Data Page 16 (0x10) – General FE Data Byte nr.7 #185

Closed inonoob closed 3 years ago

inonoob commented 3 years ago

Hey,

I just checked the antDongle code and saw that I'm not sure about the byte nr.7 for ANT+ page 16.

Capabilities        = 0x30 | 0x03 | 0x00 | 0x00 # IN_USE | HRM | Distance | Speed

link to the code

This is how I read the document:

ANT+ Device Profil Fitness Equipment Page 29 8.5.2 Byte Description Length
7 Capabilities Bit Field 4 bits (0-3)
FE State Bit Field 3 bits (4-7)

ANT+ Device Profil Fitness Equipment Page 31 8.5.2.6 + ANT+ Device Profil Fitness Equipment Page 31 8.5.2.7

It is little endian example: Byte nr.7 for page 16 Lap Toggle Bit FE State Virtual Speed Flag Distance Traveled HR data source
0x31 (0b00110001) 0 011 0 0 01
Lap Toggle Bit: off FE State:IN_USE Virtual Speed Flag:off Distance Traveled:off HR Data Source:1

Or what did I miss ?

WouterJD commented 3 years ago

Good day @inonoob Welcome to the FortiusANT community


I'm always curious to know who I communicate with, where FortiusANT is used and what configuration is used. Please tell me what bundle did you buy, and what brake and what head unit do you use? I would therefore appreciate that you introduce yourself; perhaps leave a comment under issue #14.


WouterJD commented 3 years ago

@inonoob "Or what did I miss ?" I am curious about your exact question, what do you think it should be?

WouterJD commented 3 years ago

I admit I'm pretty much struggling with the way byte 7 is described; but since the capabilities bit field is "the lower 4 bits of byte 7" I assume that bit0 is the least significant bit. Therefore HRM = 0x03 would be "The source of the heart rate is hand contact sensor". I do not know anymore why that option has been chosen.

inonoob commented 3 years ago

Hey, the reason why I ask is I have the same problem to know exactly which one is correct. I'm currently building a kind of FortiusANT for a rowing machine called Waterrower. Thing is I finished to implement BLE for things like Zwift or Kinomap or Werow. But now I also would like to have ANT in order to send the data to the Garmin watch. I'm currently implementing the ANT+ with python-ant lib but those things, I try to understand more in depth because the FE and Rowing machine is not implemented. So I checked yours to see how you build the byte from the bits.
I though about little endian because I saw this kind of thing also in the FIT documents which is also Garmin. When they worked with bits that It would work that way. But I'm also confused. :(

switchabl commented 3 years ago

@inonoob Your example looks correct. As far as I know, "bit 0" in ANT documents always refers to the least significant bit. I'm not sure if this is ever stated explicitly, but like @WouterJD said it is implied in various places (and very common outside of ANT). I would refer to this as "LSB 0" bit ordering rather than "little endian" though because the latter is usually used to refer to byte ordering and things are confusing enough without mixing that up.

I guess FortiusANT should technically set HR source to 0x2 (5kHz HRM) if the data is from the Tacx head unit. In theory, I think the idea is that the FE display device can prioritize based on source: if the data is from a HRM strap (more accurate/realiable than contact sensor), just use that, otherwise keep looking for a ANT+ HRM source. In practice, I would expect it is usually ignored nowadays. When the FE profile was originally specified for treadmills in 2009, an FE display device might have been a battery-powered head unit with a limited UI...

Improving/verifying compliance with the profile specs is on my todo-list (there are also some automated tests), but not very high because the current implementation seems to mostly work with relevant display devices/CTPs.

@inonoob If you haven't already, I strongly suggest you look at SimulANT+ from the ANT download page. I have found it very useful for testing and to clear up some ambiguities. There is also https://www.thisisant.com/forum/ which may or may not be helpful.

WouterJD commented 3 years ago

Hey that's great; I'm curious what that is going to be ... Waterrower!

First: big/litte endian does not apply here; that affects byte-sequence in an int (short, long), not the bit-sequence in a byte.

For our case the solution is given on page 31 8.5.2.6 "capabilities = the lower 4 bits of byte 7"; based upon that I have concluded that bit0 is the least significant bit of the "lower four bits" and also the whole byte.

Therefore the table as you have drawn matches what I read now (although some confusion remains) and how it is implemented today. And I did not ghet any complaints that it would not work.

Regarding "how you build the byte from the bits"; I remember I was struggling with this and it's the only place where bits in a byte are addressed.

What I should have done to properly document the code:

#               bit  7... ...0
HRM              = 0b0000 0011 # 0b____ __xx bits 0-1 3 = hand contact sensor    (2020-12-28 Unclear why option chosen)
Distance         = 0b0000 0000 # 0b____ _x__ bit 2    0 = No distance in byte 3  (2020-12-28 Unclear why option chosen)
VirtualSpeedFlag = 0b0000 0000 # 0b____ x___ bit 3    0 = Real speed in byte 4/5 (2020-12-28 Could be virtual speed)
FEstate          = 0b0011 0000 # 0b_xxx ____ bits 4-6 3 = IN USE
LapToggleBit     = 0b0000 0000 # 0bx___ ____ bit 7    0 = No lap toggle

Capacilities = HRM | Distance | VirtualSpeedFlag | FEstate | LapToggleBit

Looking at the options today, I might have chosen differently.

WouterJD commented 3 years ago

@inonoob is your project already published?

inonoob commented 3 years ago

Hey,

Will Clean my code tonight and hopefully post the code on GitHub. I still have to test one thing this evening before publishing it.

Many thanks for the feedback.

Concerning th ant+ simulator. How can I have access to it. I'm not a company. And if I'm right you need to register. So I did look for the documents on the internet and study source code on GitHub to understand the ant protocol.

inonoob commented 3 years ago

Also nice documentation. That helped a lot.

Hey that's great; I'm curious what that is going to be ... Waterrower!

First: big/litte endian does not apply here; that affects byte-sequence in an int (short, long), not the bit-sequence in a byte.

For our case the solution is given on page 31 8.5.2.6 "capabilities = the lower 4 bits of byte 7"; based upon that I have concluded that bit0 is the least significant bit of the "lower four bits" and also the whole byte.

Therefore the table as you have drawn matches what I read now (although some confusion remains) and how it is implemented today. And I did not ghet any complaints that it would not work.

Regarding "how you build the byte from the bits"; I remember I was struggling with this and it's the only place where bits in a byte are addressed.

What I should have done to properly document the code:

#               bit  7... ...0
HRM              = 0b0000 0011 # 0b____ __xx bits 0-1 3 = hand contact sensor    (2020-12-28 Unclear why option chosen)
Distance         = 0b0000 0000 # 0b____ _x__ bit 2    0 = No distance in byte 3  (2020-12-28 Unclear why option chosen)
VirtualSpeedFlag = 0b0000 0000 # 0b____ x___ bit 3    0 = Real speed in byte 4/5 (2020-12-28 Could be virtual speed)
FEstate          = 0b0011 0000 # 0b_xxx ____ bits 4-6 3 = IN USE
LapToggleBit     = 0b0000 0000 # 0bx___ ____ bit 7    0 = No lap toggle

Capacilities = HRM | Distance | VirtualSpeedFlag | FEstate | LapToggleBit

Looking at the options today, I might have chosen differently.

switchabl commented 3 years ago

@inonoob Just register as an "ANT+ adopter" on thisisant.com. It is free and you don't need a company (at least that was the case last I checked). It should give you access to all the documents and tools you need. Just a few things to be aware of:

But using the info and tools to make your own open source implementation should be completely fine.

inonoob commented 3 years ago

Off-topic, let see how long ant+ will be a thing as more and more companies switch to the ble standard with the fitness machine profile and their services. Other thing I tried to get also connected to apple watches but they also have there own protocol called "gymkit" which is even more difficult to get information.

inonoob commented 3 years ago

Many thanks to everyone for the help. I think to topic can be closed

WouterJD commented 3 years ago

Just register as an "ANT+ adopter" on thisisant.com

That's what I did and it works fine untill today.

WouterJD commented 3 years ago

What I should have done to properly document the code:

#               bit  7... ...0
HRM              = 0b0000 0011 # 0b____ __xx bits 0-1 3 = hand contact sensor    (2020-12-28 Unclear why option chosen)
Distance         = 0b0000 0000 # 0b____ _x__ bit 2    0 = No distance in byte 3  (2020-12-28 Unclear why option chosen)
VirtualSpeedFlag = 0b0000 0000 # 0b____ x___ bit 3    0 = Real speed in byte 4/5 (2020-12-28 Could be virtual speed)
FEstate          = 0b0011 0000 # 0b_xxx ____ bits 4-6 3 = IN USE
LapToggleBit     = 0b0000 0000 # 0bx___ ____ bit 7    0 = No lap toggle

Capacilities = HRM | Distance | VirtualSpeedFlag | FEstate | LapToggleBit

Looking at the options today, I might have chosen differently.

@switchabl would you suggest to use other constants thsn the ones used now?

inonoob commented 3 years ago

Maybe consider to have options. As mentioned, I would like to implement ant beside ble to be able to send the data from my rowing machine to Garmin watches. And the flag "laps" is a big part of the Garmin fit files if you wanna import it to Garmin connect or Strava. I have a repo where I go very deep in detail what a fit file is and how it can be implemented in python. My code is not as nice as yours

WouterJD commented 3 years ago

Export TCX; feel free to copy tcxExport.py

inonoob commented 3 years ago

WouterJD at the end the FIT format gives you a lot more details for a training but beside that check this explanation why I took the hard way and went with fit files:

Quote from my repo:

But first let's talk background for garmin's file formats:

in the early days of data gathering for sport activities, Garmin developed the program Garmin Training Center link and along with the program the exchange file Training Center XML (TCX) has been developed. This file format has only 3 categories for sport : ( Running, Bike and Others). Garmin begun developing smartwatches and switched from being a gps for cars manufacture to a fitness gadget manufacture. In order to achiv to store a lot of data on small smartwatch, garmin decide to introduce a new format which is called the FIT format. Which has a lot more information and can be used for a lot of fitness IoT devices. Rowing machine, Smartscales and the list goes on. This new file is a binary file which has all the information needed. An example is each sport has an dedicated number. But also a lot of other things can be stored in that file. The Waterrower for example has the manufacture id 118 so it exist but not yet used. Garmin connect is complete centered and focused on the FIT file system. The TCX format is a legacy format which is still used as it is widely adopted for a lot of fitness tracking pages, apps and fitness machines.

But why have you made this script if the TCX file is working well... Well not quiet as you expect. The most annoying thing is that garmin doesn't respect their own tcx file format. The best example is the stroke amount. The coxswain implementation of the tcx file format respect to the letter the garmin nomenclature. But when this file is uploaded to Garmin connect as indoor-rowing. It just ignores the stroke amount. But isn't it possible to just edit this in Garmin connect ? Nop ... Garmin don't even let you edit because it completely missing.

WouterJD commented 3 years ago

Thanks for explaining

WouterJD commented 3 years ago

I implemented TCX because of the request to import manual rides into Strava; in fact FortiusANT is not the sports-application but a device driver.

inonoob commented 3 years ago

Hey

You are welcome. May I ask if I could use your ant code for my waterrowerAntble project.

My repo is now online: https://github.com/inonoob/WaterrowerAntBle

WouterJD commented 3 years ago

I'm fine; please document that you have borrowed code from the FortiusANT project. I think we can close this issue; please keep me informed on your progress.

Just for my curiosity: where are you from?

inonoob commented 3 years ago

Germany :)

inonoob commented 3 years ago

Many thanks again @WouterJD. The Ant+ part is now working in my project. I can use Bluetooth LE via Bluez and Ant+ to send the rowing data.