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
146 stars 78 forks source link

Virtual USB-driver to run without hardware ANT+ dongle #172

Closed michelrdagenais closed 9 months ago

michelrdagenais commented 3 years ago

Have you considered using the Linux dummy_hcd module? This is the equivalent of a loopback device. You could feed data from FortiusANT into a "software" ANT+ usb device. Zwift/Rouvy would be happy seeing an ANT+ device, and there would be no need for 2 ANT+ dongles.

WouterJD commented 3 years ago

Hi @michelrdagenais Welcome to the FortiusANT community


I'm always curious to know where FortiusANT is used (Canada) and what configuration is used. Please tell me what bundle did you buy, and what brake and what head unit do you use?


The suggestion you do is very interesting! I do not have linux (windows only) but I would be interested to hear your suggestions.

michelrdagenais commented 3 years ago

I bought the "Tacx Fortius" with steering around 2008. The head unit is solid blue, motor control T1946.50, brake motor T1941. I traced the USB communication between the Tacx software and the unit to understand the protocol. I documented my findings and wrote a Linux driver with the help of Petr Blaha. My name appears in the credits of https://github.com/totalreverse/ttyT1941. However, TotalReverse went much further analyzing the Fortius. I am now looking at their documentation to improve the GoldenCheetah Fortius driver and add calibration.

I would also like to use FortiusAnt to run the Fortius with Zwift, without having to use two ANT+ dongles. Yes, it is possible to run Zwift on Linux, I run Zwift on Linux with my newer Wahoo Kickr Core using wine (https://zwiftinsider.com/zwift-on-linux/). To avoid using two ANT+ dongle, you need to emulate the ANT+ dongle seen by Zwift. This is possible on Linux with the dummy_hcd module. I do not use Windows but a quick search seems to indicate that it is also possible to emulate USB devices there with UDE (USB Device Emulation https://docs.microsoft.com/en-gb/windows-hardware/drivers/usbcon/developing-windows-drivers-for-emulated-usb-host-controllers-and-devices) which replaces DSF (Device Simulation Framework https://docs.microsoft.com/en-us/previous-versions/windows/hardware/dsf/ff538337(v=vs.85)?redirectedfrom=MSDN).

Thanks for the good work on FortiusAnt!

mattipee commented 3 years ago

Thanks for the good work on FortiusAnt!

@michelrdagenais thank you for your prior work on the Fortius!

I am currently about half way through a first pass to implement Fortius calibration in GC. Hoping to complete this today.

Related stuff: https://github.com/WouterJD/FortiusANT/issues/171 https://github.com/GoldenCheetah/GoldenCheetah/pull/3725 https://groups.google.com/g/golden-cheetah-users/c/8EDSFJiRLGU https://github.com/mattipee/GoldenCheetah/tree/tacx_fortius

switchabl commented 3 years ago

@michelrdagenais There is no reason this could not be done. I have explored several approaches before. The ANT dongle is quite sophisticated and there would be a lot of commands you need to support if you want to do this properly (https://www.thisisant.com/assets/resources/ANT%20Protocol/D00000652_ANT_Message_Protocol_and_Usage_Rev_5.1.pdf). If you only use Zwift you may get away with a subset (but it might break after the next Zwift update). You would probably still need one physical ANT dongle for other sensors (like HRM and power meter) as well AND you would need to merge that input into your virtual dongle.

This is probably the closest anyone got (an experimental firmware for T1942 head unit simulating an ANT USB dongle): https://github.com/totalreverse/ezTraCon

On Linux you should be able to create a "gadget" and attach that to your dummy_hcd in user-space (with functionfs/configfs?). On Windows I think you will be writing a kernel-mode driver, with all the complexity and signing/qualification implications that come with it. I have no idea what you would do on MacOS.

Other approaches might be:

In any case, there is a good chance a proper cross-platform implementation will end up being more complicated than FortiusANT itself. So I basically abandoned the idea. But I would be curious to see what you come up with and if I can help, I will.

WouterJD commented 3 years ago

will end up being more complicated than FortiusANT itself.

Good reason not to go this path. Especially since one dongle remains required (e.g. HRM) and (I assume) Zwift will use one dongle, not two.

WouterJD commented 3 years ago

I suggest to close; anybody creative ideas not to close and go for this instead?

michelrdagenais commented 3 years ago

When I find time, I will prototype something. It may take the form of a software ANT bridge between FortiusANT and the Training software, creating two dummy ANT devices and forwarding/adapting the serial port messages between the two. If you want to close the issue, this is fine.

switchabl commented 3 years ago

@WouterJD Don't get me wrong, it would be great to have this. Having to buy a (second) ANT dongle is maybe the biggest obstacles for new users. I just couldn't come up with a realiable way to do it that is not a lot of work.

If @michelrdagenais or someone else wants to attempt this (dummy_hcd/functionfs is probably one of the most straightforward ways, unfortunately it is also Linux-only) the good news is this: you don't even have to touch the FortiusANT code. You can just emulate two ANT dongles, one for FortiusANT and one for Zwift and virtually route between them.

For many real-world use-cases you would have to implement support for a physical ANT dongle as well, though. Take my personal setup: you would have to route

EDIT: @michelrdagenais Yes, that is the approach I had in mind as well. I am curious to see what you come up with. Let me know if you have any ANT related question I can help with.

WouterJD commented 3 years ago

Great!

A thought from my side: In stead of two dongles; FortiusANT should behave as a dongle itself (register itself as a USBdevice) so that Zwift can pair directly.

switchabl commented 3 years ago

@WouterJD Yes, would be nice, but it does mean a lot of changes and a lot of complexity in FortiusANT. At least for a prototype, to see it works and what approach is best, emulating two dongles and not changing FortiusANT at all seems like the more sensible way. If it turns out to work well, you can start thinking about built-in USB emulation. That step should be easy by comparison.

WouterJD commented 3 years ago

I understand it's considered a challenge.

I suggest we first define the outline: Option 1. No dongle at all

Option 2. One dongle

Succes!

WouterJD commented 3 years ago

My visual thoughts on the subject. Used assumption: Zwift will connect with one dongle and expect all it's devices on that dongle.

image image image

michelrdagenais commented 3 years ago

The Tacx Fortius came with an option for heartbeat. I suppose that many people use a different, non Tacx, device that requires ANT+.

WouterJD commented 3 years ago

Succes! And all this to save one ANTdongle?

WouterJD commented 3 years ago

See #204 CYCPLUS issues and ANT dongles hard to come by Who creates virtual-ANTdongles?

E-NINA commented 3 years ago

In line with this discussion, new proposed ethernet protocol wahoo introduced with "KICKR 2020 Direct Connect Cable", mith be a solution in future. Seems ZWIFT have alreday add compatibility on that, and wahoo is willing to open/share usage to other use that protocol

switchabl commented 3 years ago

That looks very interesting indeed. Implementing this is a lot more realistic than virtual USB. It may take a while before this is actually supported everywhere:

FulGaz: In beta builds, but not fully working yet in my testing
RGT: Fully functional in public production version
The Sufferfest: Supposed to be working in production, but not for me or others
TrainerRoad: In certain beta builds, but not fully working yet in my testing. Targeting early February for release.
Zwift: According to Zwift’s product & PR team, actual official target is “later this year”

(https://www.dcrainmaker.com/2021/01/wahoo-starts-shipping-kickr-2020-direct-connect-cable-hands-on-details.html)

Anyone want to email them at support@wahoofitness.com and see if they are open to sharing the specification?

WouterJD commented 3 years ago

OK. SO I understand after proprietary Tacx-USB-interface and Tacx-ANT-interface which we opened to standard ANT+ and BLE, now we get a next proprietary Wahoo-USB-interface?

switchabl commented 3 years ago

Kinda. They have apparently indicated that they are willing to share the specs but it is not clear how far they will go with that (maybe they will eventually offer it on their website along with their SDK?). And it looks like all major CTP have plans to support it.

But from a technical perspective it is very intriguing: it works over the network, not USB. So if we get the protocol details (or can reverse engineer them), we can implement a simple TCP server to make our trainers available to all devices on the our home network (including tablets and phones) with no dongles and no virtual USB.

I don't see this replacing ANT+/BLE either. This is a niche thing for e-sports or gyms (where wireless doesn't work so well because you have a lot of devices) and for people who have some bad interference issues.

WouterJD commented 3 years ago

Apart from niche: FortiusAnt enables OLD Tacx trainers to communicate. I gues these trainers are not in this scope :-)

switchabl commented 3 years ago

@WouterJD Oh I see, no that is not the point. We do not want to talk to a Kickr. We want to simulate a Kickr with Direct Connect (instead of an ANT+ FE-C trainer). Because then people wouldn't need the ANT dongles anymore. And Direct Connect uses the network instead of USB so this would be much much easier than a virtual USB dongle.

martin-vi commented 3 years ago

SO I understand after proprietary Tacx-USB-interface and Tacx-ANT-interface which we opened to standard ANT+ and BLE, now we get a next proprietary Wahoo-USB-interface?

I understand the pain, but when I read https://bikerumor.com/2021/01/26/dont-get-dropped-signals-w-wahoo-kickr-direct-connect-wired-ethernet-adapter/ the first thing that came to my mind was that FortiusANT should support it. As the article also points out, Wahoo Direct Connect is already support by many training system or will be supported soon.

In general, I think that other manufacturers will follow with Direct Connect. That is the next logical step. I also believe that the next generation will have directly integrated Wi-Fi. The manufacturers will agree on the lowest common denominator for the network protocol. Wahoo was the first, only Tacx/Garmin could possibly dictate something other with its power.

IMHO the advantages are obvious: no ant dongles, less cable clutter and better connection. Resulting in more users as the barrier to entry becomes lower. For me, the RassberryPi is generally connected to the WLAN. The Zwift PC anyway, so why not transfer the trainer data over it. Zwift offers in the companion app to receive via the ANT / BLE data and send directly to Zwift, without the in between Zwift PC. This would also be a possibility, however, that would then exclusively only work for Zwift. Not so good indeed.

The implementation should be simple: A Wahoo KICKR + Wahoo Direct Connect and a computer with Wireshark or tcpdump in between. I suspect the network protocol should be easy to analyze. The adaptation with Python I also imagine not difficult.

Now comes the hard part, where do we get a network dump from the Direct Connect Adapter? I am thinking of the following options:

Do you have any ideas about this?

switchabl commented 3 years ago

@martin-vi Yeah, asking Wahoo for some more info is probably step 1. Worst case is they say no.

There were some hints that it is some kind of BLE tunneled over TCP but I don't know if that is technically accurate or just an explanation the marketing department came up with. Working from a static Wireshark dump without the ability to actually inject your own data may be hard. And I don't know if the adapter by itself is going to do you much good. You would need to find a way to power it up without the KICKR and then chances are it won't do much at all.

The software situation doesn't seem to have improved either. RGT and Sufferfest seem to be the only apps that actually work right now. I am still very interested in this but I will probably wait for better software support before making a serious effort. That may make reverse-engineering a bit easier too.

cagnulein commented 2 years ago

I will be very happy to add this on my QZ app. Does anyone have this device? We can easily reverse engineered it. Let me know

switchabl commented 2 years ago

@cagnulein Your QZ app looks quite impressive, it is always nice to see more proprietary/legacy training devices being opened up.

I don't have a Direct Connect (it doesn't work without at KICKR anyway) but I have made some progress on the protocol anyway. It would still be nice to have a Wireshark capture from an actual device though. In short, it really is a BLE/GATT-like interface over TCP. You can enumerate services and characteristics and then do read/write/notify on them. Discovery is done using mDNS.

AND, unfortunately Zwift doesn't support it yet either. They claim to be working on it but until that happens it is not actually that useful for us. Not sure about the other apps. Still, I think this is our best chance to run FortiusANT without any USB dongles in the future, so I will keep working on it.

cagnulein commented 2 years ago

Hi @switchabl ! Thanks for your answer! Did you have already some code about it? Where did you take the information about the protocol? I tried to google it but i can't find almost anything. Thanks!

switchabl commented 2 years ago

@cagnulein I have only just started writing some code, so not yet (at least I have finally figured out how to do the mDNS advertisements). I have written up a preliminary specification that I am working from, but the usual disclaimer applies (WIP, untested, probably incomplete and inaccurate).

If you want to discuss details, feel free to drop me an email (switchabl at mailbox dot org).

cagnulein commented 2 years ago

@switchabl have a look at this https://github.com/cagnulein/qdomyos-zwift/issues/476#issuecomment-979240427

switchabl commented 2 years ago

@cagnulein Thanks, I will, that sounds great. I also have a mostly-working, still-unpublished DIRCON server implementation written in Rust. Unfortunately I didn't have the time to finish it yet it because I was busy with other things (mostly steering related). Sorry that I haven't been more active.

WouterJD commented 2 years ago

@switchabl thanks for all the effort! Don't apologize for not doing more. I'm curious what development will be released first...

switchabl commented 2 years ago

@WouterJD Well, it seems our friends from qdomyos-zwift have something working already. =) I was hoping to be of some more help to them, but I did give them something to start with I guess. Admittedly this is more of a side-experiment to me. App compatibilty is still somewhat meh:

KICKR Direct Connect is compatible with SYSTM, Trainer Road, Fulgaz, bKool, and RGT Cycling - with more 3rd party partners in the future.

And even for those it is not always supported on all platforms... The one thing that would really motivate me to put more work into it is Zwift adding support for it. Still, the protocol is mostly figured out and I have been successfully simulating a HRM and a FTMS service, sending random values to SYSTM. So definitely doable if/when we want to.

EDIT: I guess even with limited App support it would be an incredibly cheap option for people to get started. Basically, if you have an old Fortius or i-Magic, you could just download FortiusANT and the free version of RGT and you wouldn't need to buy anything else. That would be pretty big.

decodeais commented 2 years ago

Does anybody know the virtual Bluetooth device btvirt . It can easily generated by by compiling bluez with the a special compiler flag. --enable-testing. Then you get With the command sudo ./emulator/btvirt -l2 two dummy Bluetooth connections. FortitusAnt seemed to recognize them. So I tried to connect to GoldenCheatah. For GoldenCheatah I had to start bluetooth again with systemctl start bluetooth. Then I got the signals like power and heart rate in the BT4.0 connection list, but no signal from FortiusAnt. I know FortiusAnt does not work with systemctl start bluetooth. This was the moment I stopped this experiment. May be somebody else can fix this problem. This Solution would be too easy.

switchabl commented 2 years ago

@decodeais Unfortunately, I do not think this can work. btvirt seems to work at the BlueZ level, whereas FortiusANT currently bypasses the BlueZ stack completely. Maybe this will change at some point if we ever get a "native" BLE implementation. I may have spoken too soon. It seems to be backed by a kernel module that emulates a USB HCI controller. So maybe there is a way to make it work. I will take a closer look.

It does look interesting though. It might be very useful for integration testing.

decodeais commented 2 years ago

Nice to hear. I hoped there would be a possibility to reject only one virtual device from bluez but if it helps you debugging it is OK for me. I'm glad that somebody understood my question.

cagnulein commented 9 months ago

@WouterJD is it in now?

WouterJD commented 9 months ago

No, I closed all issues marked for future development to cleanup the list of issues.

They can always be retrieved with https://github.com/WouterJD/FortiusANT/issues?q=label%3A%22future+development%22+