ptx2 / gymnasticon

Make obsolete and/or proprietary exercise bikes work with popular cycling training apps like Zwift, TrainerRoad, Rouvy and more.
https://ptx2.net/posts/unbricking-a-bike-with-a-raspberry-pi
MIT License
297 stars 38 forks source link

Add experimental Echelon support. #76

Open ptx2 opened 3 years ago

ptx2 commented 3 years ago

To try this out:

sudo apt-get install git
cd
git clone https://github.com/ptx2/gymnasticon.git
cd gymnasticon
sudo service gymnasticon stop
sudo setcap cap_net_raw+eip $(eval readlink -f $(which node))
git fetch origin pull/76/head:echelon-experimental
git checkout echelon-experimental
npm install
npm run build
npm link
gymnasticon --bike echelon
ghost commented 3 years ago

This is similar to what I had so far, although the parsing didn't work for me.

I just tested your branch, strangely enough it connects at first and then disconnects a few seconds later.

pi@gymnasticon:~/gymnasticon $ gymnasticon --bike echelon [2021-03-22T22:39:58.153Z] connecting to bike... [2021-03-22T22:40:28.490Z] bike disconnected e4:6e:d2:ee:d0:1a

I'm attaching the full debug log. gymnasticon.log

ptx2 commented 3 years ago

Thanks for testing this @EfficientSetting!

I just made a small change if you have time to try it out.

I think this should now be the same as what @doudar has working in SmartSpin2k.

I also had a quick look over the qdomyos-zwift Echelon support and a btsnoop log provided by a user. It seems to be doing the same but more. e.g. it sends some kind of regular poll message, and also subscribes to another characteristic. Perhaps necessary for some Echelon bikes/firmwares and not others? Can you share which model bike and firmware version you're testing with?

ghost commented 3 years ago

Hi!

Just tried it again, the disconnect is now "instant" after the connect beep.

I have a Echelon Connect Sport (Walmart), HW 7.00 FW 41.01.04

qdomyos-zwift is working on this bike with no issues, I haven't tried SmartSpin2k.

Let me know if you'd like to get the debug log again!

ptx2 commented 3 years ago

Hey, thanks for trying again!

Does it fail the same way each time?

A log would be great. A low-level log e.g. btmon -w echelon.log on Linux or PacketLogger app on macOS would be ideal but the DEBUG=* console output is also helpful, whatever you're able to grab.

doudar commented 3 years ago

Hey, thanks for trying again!

Does it fail the same way each time?

A log would be great. A low-level log e.g. btmon -w echelon.log on Linux or PacketLogger app on macOS would be ideal but the DEBUG=* console output is also helpful, whatever you're able to grab.

This was a good source for me: https://github.com/snowzach/echbt

ptx2 commented 3 years ago

Thanks @doudar! I A/B'd that one (and yours) with what I have here and can't seem to see a relevant difference. What I have here works against a mock Echelon device I threw together.

I'm wondering if noble/BlueZ is doing something different to NimBLE under-the-hood that the bike doesn't like. It wouldn't be the first time. Or perhaps I'm just overlooking something obvious :-)

doudar commented 3 years ago

Yah, I've noticed you guys need to do some stuff in noble that we don't in NimBLE and vice versa.

My guess is that it connects, gets a request to update connection parameters (timing) to something it doesn't like (or it updates to something noble doesn't like) and so disconnects.

Does noble have a method for getConnParameters() so maybe you could see what the device is requesting?

cagnulein commented 3 years ago

if you want (i'm the developer of qdomyos) i can help in the troubleshooting

ptx2 commented 3 years ago

@cagnulein @doudar Thank you both for the support!

I was thinking along similar lines @doudar. It actually looks like an issue we ran into on the IC4 bike, specific to noble's Linux (HCI) bindings. Noble sends a Read By Type request to find the CCCD handle so it can later write to it to enable notifications. The IC4 bike didn't respond to the Read By Type request. From the noble debug log attached above, the Echelon bike is not responding to that request either (and is also disconnecting).

@cagnulein I noticed you do some extra stuff in qdomyos-zwift like sendPoll() and also some extra initData which https://github.com/snowzach/echbt doesn't seem to do. Are there are different features or versions of the bike/firmware that require the polling?

@EfficientSetting I pushed up two alternate versions if you want to try:

# Note these only work on Linux (which it looks like you're using from that noble log)
# Also, if these do work then there's a good chance the original implementation `echelon` works on macOS

gymnasticon --bike echelon2   # uses Find Info instead of Read By Type (will only work on Linux)
gymnasticon --bike echelon3   # same as above, but also sends extra initialization packets
cagnulein commented 3 years ago

sendPoll is needed to keep the connection alive. initData shouldn't be necessary, but it's what the official app did.

Roberto Viola Software engineer and open source enthusiast http://robertoviola.cloud

Il giorno lun 29 mar 2021 alle ore 15:31 ptx2 @.***> ha scritto:

@cagnulein https://github.com/cagnulein @doudar https://github.com/doudar Thank you both for the support!

I was thinking along similar lines @doudar https://github.com/doudar. It actually looks like an issue we ran into on the IC4 bike, specific to noble's Linux (HCI) bindings. Noble sends a Read By Type request to find the CCCD handle so it can later write to it to enable notifications. The IC4 bike didn't respond to the Read By Type request. From the noble debug log attached above, the Echelon bike is not responding to that request either (and is also disconnecting).

@cagnulein https://github.com/cagnulein I noticed you do some extra stuff in qdomyos-zwift like sendPoll() and also some extra initData which https://github.com/snowzach/echbt doesn't seem to do. Are there are different features or versions of the bike/firmware that require the polling?

@EfficientSetting https://github.com/EfficientSetting I pushed up two alternate versions if you want to try:

Note these only work on Linux (which it looks like you're using from that noble log)

Also, if these do work then there's a good chance the original implementation echelon works on macOS

gymnasticon --bike echelon2 # uses Find Info instead of Read By Type (will only work on Linux) gymnasticon --bike echelon3 # same as above, but also sends extra initialization packets

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ptx2/gymnasticon/pull/76#issuecomment-809378931, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAALYWB76X53T3X6BFJEPVDTGB6K7ANCNFSM4ZSFF3NQ .

ghost commented 3 years ago

@cagnulein @doudar Thank you both for the support!

I was thinking along similar lines @doudar. It actually looks like an issue we ran into on the IC4 bike, specific to noble's Linux (HCI) bindings. Noble sends a Read By Type request to find the CCCD handle so it can later write to it to enable notifications. The IC4 bike didn't respond to the Read By Type request. From the noble debug log attached above, the Echelon bike is not responding to that request either (and is also disconnecting).

@cagnulein I noticed you do some extra stuff in qdomyos-zwift like sendPoll() and also some extra initData which https://github.com/snowzach/echbt doesn't seem to do. Are there are different features or versions of the bike/firmware that require the polling?

@EfficientSetting I pushed up two alternate versions if you want to try:

# Note these only work on Linux (which it looks like you're using from that noble log)
# Also, if these do work then there's a good chance the original implementation `echelon` works on macOS

gymnasticon --bike echelon2   # uses Find Info instead of Read By Type (will only work on Linux)
gymnasticon --bike echelon3   # same as above, but also sends extra initialization packets

Will test tonight! Thanks

ghost commented 3 years ago

@cagnulein @doudar Thank you both for the support!

I was thinking along similar lines @doudar. It actually looks like an issue we ran into on the IC4 bike, specific to noble's Linux (HCI) bindings. Noble sends a Read By Type request to find the CCCD handle so it can later write to it to enable notifications. The IC4 bike didn't respond to the Read By Type request. From the noble debug log attached above, the Echelon bike is not responding to that request either (and is also disconnecting).

@cagnulein I noticed you do some extra stuff in qdomyos-zwift like sendPoll() and also some extra initData which https://github.com/snowzach/echbt doesn't seem to do. Are there are different features or versions of the bike/firmware that require the polling?

@EfficientSetting I pushed up two alternate versions if you want to try:

# Note these only work on Linux (which it looks like you're using from that noble log)
# Also, if these do work then there's a good chance the original implementation `echelon` works on macOS

gymnasticon --bike echelon2   # uses Find Info instead of Read By Type (will only work on Linux)
gymnasticon --bike echelon3   # same as above, but also sends extra initialization packets

Both immediately disconnect unfortunately. Here's the output:

pi@gymnasticon:~/gymnasticon $ gymnasticon --bike echelon2
[2021-04-08T21:55:04.409Z] connecting to bike...
[2021-04-08T21:55:05.988Z] TypeError: Cannot read property 'writeValueAsync' of undefined
    at EchelonBikeClient2.connect (/home/pi/gymnasticon/lib/bikes/echelon2.js:96:16)
    at async App.run (/home/pi/gymnasticon/lib/app/app.js:145:7)
    at async /home/pi/gymnasticon/lib/app/cli.js:27:3
pi@gymnasticon:~/gymnasticon $ gymnasticon --bike echelon3
[2021-04-08T21:55:15.154Z] connecting to bike...
[2021-04-08T21:55:15.647Z] bike disconnected e4:6e:d2:ee:d0:1a
pi@gymnasticon:~/gymnasticon $ gymnasticon --bike echelon3
[2021-04-08T21:55:23.019Z] connecting to bike...
[2021-04-08T21:55:23.498Z] bike disconnected e4:6e:d2:ee:d0:1a

Let me know what kind of logging information you need, and I'm happy to provide