Code Monkey home page Code Monkey logo

fortiusant's Issues

CYPLUS ANT+ Dongle - "Device does not work correctly" error

Hello !
I have in mind since a few days to connect my old i-magic trainer to Zwyft, and I have bought two ant+ dongle (from Amazon, labelled CYCPLUS, id 0fcf:1008, Dynastream Innovation Inc.) and tried to run FortiusANT as well as antifier both on my linux and windows machine.

So far I haven't been able to run it successfully as I encountered several problems. Maybe would you have a clue about what it is ?

So, on linux the ANT didn't allow connection (errno 16: Busy) and I managed to overcome that by disabling the kernel drivers on code (basically copy-paste of https://stackoverflow.com/a/36505328). Now the ANT device is recognized as well as the trainer, but as soon as I click "Start" the console get flooded with read/write error (errno 30), happening directly after the dongle reset, from what I have been able to debug.

On windows the situation is the same, the ANT device is recognized as well as the trainer, but on clicking start I get this :

19:03:21,672: ------------------
19:03:21,672: Version info for the components
19:03:21,673:         FortiusAnt = 2020-04-07
19:03:21,673:          antDongle = 2020-03-31
19:03:21,674:             antHRM = 2020-02-18
19:03:21,675:              antFE = 2020-02-18
19:03:21,675:              debug = 2020-03-04
19:03:21,676:  FortiusAntCommand = 2020-03-25
19:03:21,676:      FortiusAntGui = 2020-04-07
19:03:21,677:            logfile = 2020-03-24
19:03:21,677:    structConstants = 2020-01-25
19:03:21,677:         usbTrainer = 2020-03-29
19:03:21,678:           argparse = 1.1
19:03:21,678:              numpy = 1.17.4
19:03:21,679:             pickle = 4.0
19:03:21,684:           platform = 1.0.8
19:03:21,685:       sys (python) = 3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:21:23) [MSC v.1916 32 bit (Intel)]
19:03:21,685:                usb = 1.0.2
19:03:21,686:                 wx = 4.0.7.post2
19:03:22,210: Dongle    receive: synch=0xa4, len= 1, id=0x6f Start up             , check=0xea, info="20"
19:03:22,233: Dongle    timeout
19:03:22,234: Dongle - Using CYCPLUS dongle
19:03:22,234: Tacx   - Simulated Trainer
19:03:22,235: ResetDongle()
19:03:22,236: Dongle    send   : synch=0xa4, len= 1, id=0x4a Reset System         , check=0xef, info="00"
19:03:22,737: Calibrate()
19:03:22,737: ResetDongle()
19:03:22,738: Dongle    send   : synch=0xa4, len= 1, id=0x4a Reset System         , check=0xef, info="00"
19:03:23,239: Dongle    send   : synch=0xa4, len= 2, id=0x4d Request Message      , check=0xbf, info="00 54" msg=0x54
19:03:23,239: Dongle    drop   : synch=0xa4, len= 1, id=0x6f Start up             , check=0xea, info="20"
19:03:23,263: Dongle    timeout

and then `SendToDongle write error, reaping request failed, win error : * a device attached to the system is not functionning*, and multiple ReadFromDongle read error.

So the problem seems to come from the dongle, however running antifier from linux, which from what I understand uses instead the serial interface of the dongle, I was able to connect from Zwyft to antifier (even if the head unit wasn't supported).

So here I am. I don't know what I could try next or event where the problem come from. Has someone any clue ? Thanks a lot in advance...

Support for Data Page 50 - Wind Resistance

To allow wind resistance coefficient and head/tail wind to be provided and incorporated into calculation of GradeToPower().

No rush, statement of intent, as I may get round to implementing this myself.

Motivation - I enjoy re-riding .gpx files and would like to simulate approximate wind conditions.

Small question

Ant+ stick don't detect in Windows OS in PyCharm IDE in debug mode. Used Python27.
And worked with your compiled exe file.

For example:

def ComposeMessage(id, info):
    fSynch      = sc.unsigned_char
    fLength     = sc.unsigned_char
    fId         = sc.unsigned_char
    fInfo       = str(len(info)) + sc.char_array  # 9 character string

    format  =    sc.no_alignment + fSynch + fLength + fId + fInfo
    data    = struct.pack (format, 0xa4,    len(info), id,  info)
    #---------------------------------------------------------------------------
    # Add the checksum
    # (antifier added \00\00 after each message for unknown reason)
    #---------------------------------------------------------------------------
    data += calc_checksum(data)    
    
    return data

data = struct.pack (format, 0xa4, len(info), id, info)
data - string with raw data here

further :

def calc_checksum(message):
    return CalcChecksum (message)           # alias for compatibility
    
def CalcChecksum (message):
    xor_value = 0
    length    = message[1]                  # byte 1; length of info
    length   += 3                           # Add synch, len, id
    for i in range (0, length):             # Process bytes as defined in length
        xor_value = xor_value ^ message[i]

#   print('checksum', logfile.HexSpace(message), xor_value, bytes([xor_value]))


    return bytes([xor_value])

length = message[1]
lenght - char with symbol from index 1 in message string variable

length = ord(message[1])
retturn correct int val

How does it work for you??

Fortius I-Magic T1902 and Zwift | Windows XP on imac

System :WIN XP running on partition on IMAC using Virtual box
Have Fortius I-magic with T1902 head and TACX TTS3.
Cannot get RLV rides to load as system keeps crashing.
Want to use Swift if possible.
Any ideas?

Linux Ant+ Serial

(Follow up on the dependencies Issue) I have been trying to run FortiusANT in Linux (Mint). After satisfying all python dependencies (Python 3.5) I run into problems with the ANT+ stick. I have been debugging the code a bit and it seems the code gets stuck at reply = ResetDongle(devAntDongle).

I think the code ends up in an infinite loop in the ReadFromDongle subroutine. Once trv=b'\xa4\x01o \xea', afterwards it is empty each time. Probably some difference in the serial behavior in Windows and Linux?

Rouvy (not AR but workouts)

Hey all,

i gave up on the FortiusANT software on Linux and went back to Windows.
i have everything installed and functioning.
i am able to get the old iFlow recognized and paired to Zwift......it recognized it right away. i also have a Flow Smart right next to my old iFlow. Zwift is able to pickup both devices with no problems. i am a big fan of the RouvyAR application and want to use that.

Rouvy gives a message that Bluetooth needs to be enabled and ANT+ is "coming soon". from what i can see on their website ANT+ is already supported. How does this work? i also see that there are closed tickets in the FortiusANT archives indicating that it works.

what am i doing wrong? is there a different rouvy software than the RouvyAR that is on their website?

please advise.

Get struct error: unpack requires a buffer of 64 bytes

Hello Wouter,

As per our chat on Strava I'm reporting an error than stops me from use FortiusAnt.
Let me first identify the configuration I'm using:
I'm running FortiusAnt on Windows10 and I've downloaded Python 3.8.2
As Usb ANT+ Dongle I'm using is Garmin. This is the one that connects to Fortius trainer
As to connect with tha App, I'm currently using Rouvy as Zwift doesn't recognizes my trainer, I'm currently using an Android phone with ANT+ services support.
I'm running FortiusAnt from a CMD window using the following arguments:
FortiusAnt -d DEBUG -b 2096,55/34,11/34 -g
The program starts identifying both the USBTrainer and the ANT+ Dongle and opens the GUI. Once the Start Button on the GUI is clicked the FE-C trainer is recognized on the app.
But at the same time, just after the Start button is clicked the following error appears on the Debug Window:

struct.error: unpack requires a buffer of 64 bytes
Traceback (most recent call last):
File "FortiusAntGui.py", line 738, in OnTimer
self.callIdleFunction()
File "FortiusAnt.py", line 131, in callIdleFunction
import antHRM as hrm
File "FortiusAnt.py", line 208, in IdleFunction
logfile.Write (msg)
File "usbTrainer.py", line 619, in ReceiveFromTrainer
data = False

I tried to run FortiusAnt.py on the Python Shell and the same error occurs.

I'm not familiar at all with Python so no idea of what I can do to solve the issue.

Do you have any clue on this?

Thanks in advance for your support

How many dongles required to use FortiusANT?

Hi, Id just like to understand a little more about using FortiusANT & zwift.
I currently have a Tacx Fortius trainer connected via the normal USB cable to a win10 laptop and Id like to use it with zwift. If I wanted to run zwift on an ipad I understand I'd need two USBant sticks in the laptop to connect data to the iPad, but do I still need the USBant sticks if zwift is running on the laptop?
Also why two USBant sticks, is that pwr and speed?
And assume this should be 2way if it works correctly and will control the motor to create a gradient?

Thanks

Feature suggestion: HTTP interface

I have just bought a Raspberry PI with the intention of running a headless FortiusANT on it.

One motivation is that it would be handy to be able to view/control FortiusANT over the network.

Indeed, some of my other ideas are around making visible the current state of the various internal variables (eg all the values provided in the ANT+ pages for a start), tweaking virtual speed curve, etc... and perhaps some live graphing - cadence/speed/power etc.

It would be possible to make it useful stand-alone in this way, eg manual grade/power controls, but the intention really is just to allow it to do it's job as an ANT->USB or ANT->ANT bridge, but to give visibility of internal state, and perhaps recent history, and to allow access to tunable parameters at runtime.

The python GUI may be more difficult to modify than it might be to present a few different pages/tables/graphs and/or API calls over HTTP. Also the GUI appears unstable in Linux due to threading issues - not unresolvable, but a separate issue.

I see an HTTP interface as being a good compromise - works both locally and remotely, and Python has good support for coding such things.

Put yourself on the FortiusANT map!

Of cources I'm curious what athletes actually use the software and a post is appreciated, perhaps with picture and/or reference to strava or else...
The list of FortiusANT users is growing:
image

My strava experiences can be found on: https://www.strava.com/athletes/2885978
Riding, using Trainer Road and Zwift interfacing to FortiusANT simultaneously:
mYCmxBiWQ2FWdAGi0FDSWQxNTFRbSpH5WDsLSHxNvpk-1152x2048

Feature suggestion: LCD display for headless Raspberry PI

A simple little 16x02 or 20x04 character LCD interface might be an easy addition for Raspberry PI users.

For example:

 --------------------
| Grade     -0.5 %   |
| Power    100   W   |
| Speed     46.5 km/h|
| Cadence   50   rpm |
 --------------------

 ----------------
| -0.5%  46.5km/h|
|  100W    50rpm |
 ----------------

Support iFlow 1932 on Mac OS?

I'm looking to set up my tacx trainer on my mac - is there something similar for mac? Or can this be run on mac OS?

ModuleNotFoundError: No module name 'antHRM'

When trying to launch the latest version (1eacb8d) with python FortiusANT.py I get the following error:

Traceback (most recent call last):
  File "FortiusAnt.py", line 124, in <module>
    import antHRM            as hrm
ModuleNotFoundError: No module named 'antHRM'

ANT FE-C page 54 not supported

I don't have access to protocol specs, but I have an issue.

Trying to perform either ERG or Slope workouts in GoldenCheetah, I am not receiving any power or slope values into FortiusANT, whereas I do see these values from Zwift.

Looking into GoldenCheetah source, it uses some bit-field values in ANT/ANT.h:
#define FITNESS_EQUIPMENT_RESIST_MODE_CAPABILITY 0x01
#define FITNESS_EQUIPMENT_POWER_MODE_CAPABILITY 0x02
#define FITNESS_EQUIPMENT_SIMUL_MODE_CAPABILITY 0x04

from:
#define FITNESS_EQUIPMENT_TRAINER_CAPABILITIES_PAGE 0x36

0x36 is 54 in decimal.

I can see that in FortiusANT I am getting request(s) for this page, but it is unhandled.

Without a response to this request listing the device capabilities, specifically the MODEs above, GoldenCheetah will not send power/slope values to FortiusANT.

The message that FortiusANT should reply with is read by GoldenCheetah as follows:

            case FITNESS_EQUIPMENT_TRAINER_CAPABILITIES_PAGE:
                 fecMaxResistance         = message[9];
                 fecMaxResistance        |= (message[10]) << 8;
                 fecCapabilities          = message[11];
                 break;

What USB ANT+ BLE dongles to use and where to buy?

ANT dongles

FortiusANT supports USB dongles with the ID's 4104 (Suunto), 4105 (Garmin) or 4100 (Older).

USB-dongles can be bought on miscellaneous shops, Google for "usb ant+ dongle"...

Currently (April 2020...Jan 2021) it appears there is a high demand and therefore some links to suppliers to give you suggestions - sorry for suggestions in the Dutch area and that some reference appear to be out-of-stock.

Read this post for general information.

Warning (CYCPLUS, Amazon, Aliexpress) , read this first. Dongles from manufacturer=CYCPLUS (also advertised as Antself, sold by Amazon) are reported not working well with FortiusANT (#45 #65). See also tacxfaqx.com. Some recovery from errors is implemented in FortiusANT 3.0 but behavior remains poor.
Refer to this post from Ilja for some explanation.

Because of the worldwide audience it's impossible to give a clear direction where to buy and we can only provide suggestions - use this page to post questions and others may help you.
Please understand these are only references to ANT+ dongles and please understand that this does not imply any guarantee from our side!

Bluetooth Low Energy (BLE) Dongles

Onboard Windows Bluetooth is not supported; a separate BLE-dongle is required.

When using - b (node.js) supported dongles are (see documentation) and node-bluetooth-hci-socket:

  • BCM920702 Bluetooth 4.0
  • BCM20702A0 Bluetooth 4.0
  • CSR8510 A10
  • Asus BT-400
  • Intel Wireless Bluetooth 6235, 7260, 7265 or 8265
  • Belkin BCM20702A0

Known good models:

Other suppliers

USB-hubs

You use a USB-hub AND have connection problems? Read this

Support for Data Page 51 - Coefficient of Rolling Resistance

Already parsed in page 51, but would like to be able to actually use a non-default received value in the physical calculation of required power in Grade2Power().
Suppose need to check that "use default value" 0xFF is provided by sending system (Zwift/etc..) if unused, or use if present?

Use FortiusANT with "Raspberry Pi Zero"

Hi, not sure if I should post this here or in #3

Well I sort of figured out and fixed the replugging thing so I no longer have to replug it every time, I think the program is not shutting down properly. I fixed it by initiating a reset when it times out, and I've progressed passed that to get this working on a Raspberry Pi Zero, thanks to the above closed thread.

What I am trying to do now is get your code to acknowledge a regular speed+cadence sensor.
Speed/cadence only displays on data page 0, but since I am new to Ant+ I am unsure how to read this and either bypass the trainer check and put it in the simulated trainer, or add it as a trainer type. I made this crudely to see if I can get it displaying (also added the other bits like ChannelConfig etc.)

def msgPage0_CombinedSpeedCadence(Channel, Spec1, Spec2, Spec3, Spec4, BikeSpeedEventTime):

    DataPageNumber = 0
    Spec1 = int(min(0xff, Spec1))
    Spec2 = int(min(0xff, Spec2))
    Spec3 = int(min(0xff, Spec3))
    BikeSpeedEventTime = int(
        min(0xffff, BikeSpeedEventTime * 1000 / 1024))  # Convert seconds into 1024seconds (since ever)
    fChannel = sc.unsigned_char  # First byte of the ANT+ message content
    fDataPageNumber = sc.unsigned_char  # First byte of the ANT+ datapage (payload)
    fSpec1 = sc.unsigned_char
    fSpec2 = sc.unsigned_char
    fSpec3 = sc.unsigned_char
    fBikeSpeedEventTime = sc.unsigned_short

    format = sc.no_alignment + fChannel + fDataPageNumber + fSpec1 + fSpec2 + fSpec3 + fBikeSpeedEventTime
    info = struct.pack(format, Channel, DataPageNumber, Spec1, Spec2, Spec3, BikeSpeedEventTime)

    return info

What would I need to do to actually open the channel and read from the new sensor? I was thinking of adding an option in GetTrainer(). However, I'm a bit confused as to what to use for idVendor and idpl if the sensor is just a generic speed/cadence sensor (I have the sensor ID that Simulant+ picks up, would I use that?)

Originally posted by @Alanimus in #8 (comment)

Must remove ANT+ dongle every time program is restarted

Hi, I think this is great and exactly what I was looking for. I am using it to control a servo on a dumb trainer to interface with Zwift so not exactly the intended use, but I noticed one issue, every almost time I completely stop the app to alter the code for instance, I must unplug and reconnect the ANT+ dongle or it can't see the dongles. I have two dongles in as well and neither can be found till I reconnect.
I am using it on Windows.

Checksum error mid way through ride (Cadence magneto)

Hey @WouterJD

Adding this as a new issue, couldn't find anything similar and I have a couple of questions.

Now I'm connected (wahoo!) I was trying out my first proper ride (see strava here). Mid way through I noticed power was constant at 135W regardless or stopping, or increasing my output. Checking terminal I got the following message:

06:52:31,903: GetTrainer - Trainer found: 0x1932
06:58:38,936: Processing longer than 0.25 seconds: 1.80
07:30:47,349: error: checksum incorrect checksum="01" expected="a5" data="a4 03 40 03 40 01 01"
07:30:47,349: ReadFromDongle error: checksum incorrect
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 926, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/iain/Downloads/FortiusANT-master 3/pythoncode/FortiusAntGui.py", line 830, in OnClick_btnStart_Thread
    self.callTacx2Dongle()
  File "FortiusAnt.py", line 165, in callTacx2Dongle
    return Tacx2Dongle(self)
  File "FortiusAnt.py", line 625, in Tacx2Dongle
    data = ant.SendToDongle(messages, devAntDongle, '', True, False)
  File "/Users/iain/Downloads/FortiusANT-master 3/pythoncode/antDongle.py", line 491, in SendToDongle
    data = ReadFromDongle(devAntDongle, drop)
  File "/Users/iain/Downloads/FortiusANT-master 3/pythoncode/antDongle.py", line 553, in ReadFromDongle
    while trv[skip] != 0xa4 and skip < len(trv):
IndexError: array index out of range

You can see this on the power in strava too.]

So, 2 questions:

  1. Is there something I need to do differently to avoid that error? After this error I FortuisANT showed no results so the error basically ended my ride

  2. I tried to exit FortiusANT and restart, unplug the dongles but Zwift wouldn't pair when paused - I would need to end the ride and restart Zwift. Is there a way to get this reconnected to resume the rise?

Side note - I'm not convinced cadence is working properly as it doesn't seem to match my input - but this FortiusANT doesn't pick up Cadence so I think this is somthing with the trainer - will try and get that working of buy a new Cadence sensor to confirm.

Virtual flywheel weight configurable?

I need to do a bit more testing, but I thought I'd raise the issue now for comments.

I noticed in code that when setting resistance in grade mode, the virtual flywheel value you send is 0x0a.

            Weight = 0x0a                                   # weight=0x0a is a good fly-wheel value
                                                            # UserAndBikeWeight is not used!        
                                                            #       an 100kg flywheels gives undesired behaviour :-)

During a GoldenCheetah test ride this afternoon, there were a number of minor slope changes which felt unnaturally sharp. I changed the value to reflect body weight and the result felt more natural. Interested to know what your undesired behaviour was. I suppose in the end, it may just be preference.

Perhaps a configuration parameter could allow the user to choose? I understand body/bike weight can be provided over ANT too, though perhaps can't assume it will be, or may wish to override it anyway for testing.

Eg:

  • use ANT-provided value
  • set as fixed value (default 0x0a)

Tacx IMagic (1902) Support

Congratulation for your amazing work, and for the amazing work of totalreverse in reverse engineering the tacx communication protocol.
It gives me the hope that I may finally be able to get my Tacx Imagic 1902 back in service,

I noticed that FortiusANT does not support 1902 yet, and I spent a few hours at trying to understand what it woud mean to support it. I am not yet sure to completely grasp all what it would require, but I would like to explain how far I came within my understanding (I am willing to put some work in this, but I am definitely not a developer...):

Platform: Windows 10
Trainer: Tacx Imagic (1902 headend device)

  • Using your wiki, I (successfully) installed libusb-win32 (using Zadig)
  • The device is visible in the device manager, and reports itself with the expected ID
    image
  • A learned in the totalreverse/ttyT1941 github repository wiki, that 1902 requires the firmware to be loaded each time the fitness equipment powers-up.
  • I managed to rip the iMagic-Firmware using totalreverse/cutFirmwareIMagic from the Imagic driver (I-magic.sys) located in the original CD
  • Then I could install the firmware onto the fitness device using totalreverse/fxload (I did not yet do extensive tests, but I could at least see the Heart rate LED blinking as expected on the fitness device). The 1902 requires the same firmware loading procedure as the 1942 each time the connection is initialized: see here. So, the usbTrainer.py file could be extended to make that possible for the 1902 too.
  • Next I added the the ID of my fitness device in your device list, and ran python FortiusAnt.py -d 127 -m. The good news is that it detected the 1902. But then FortiusANT crashed (See output below). Do you have an idea what the reason for this crash could be?

This is how far I could go until now.
I also learned from the totalreverse/ttyT1941 wiki that the 1902 uses another protocol than most of the other tacx trainers. So there is clearly some few lines of codes to be written until 1902 can be supported. I will try to see how far I can come with my limited skills in the next weeks.

C:\Users\julien\Documents\GitHub\FortiusANT\pythoncode>python FortiusAnt.py -d 127 -m
17:59:45,538: FortiusANT started
17:59:45,538: -d 127 (0b1111111)
17:59:45,540: -m
17:59:45,540: ------------------
17:59:45,540: Version info for the components
17:59:45,540:         FortiusAnt = 2020-02-10
17:59:45,540:          antDongle = 2020-02-10
17:59:45,540:              debug = 2020-01-25
17:59:45,540:  FortiusAntCommand = 2020-02-09
17:59:45,540:      FortiusAntGui = 2020-02-09
17:59:45,540:            logfile = 2020-02-02
17:59:45,540:    structConstants = 2020-01-25
17:59:45,541:         usbTrainer = 2020-01-25
17:59:45,541:           argparse = 1.1
17:59:45,541:              numpy = 1.18.1
17:59:45,541:             pickle = 4.0
17:59:45,541:           platform = 1.0.8
17:59:45,541:       sys (python) = 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 22:39:24) [MSC v.1916 32 bit (Intel)]
17:59:45,541:                usb = 1.0.2
17:59:45,541:                 wx = 4.0.7.post2
17:59:45,541: Scan for hardware
17:59:45,541: Get Dongle
17:59:45,541: Dongle - Simulated Dongle (manual mode)
17:59:45,542: Get USB trainer
17:59:45,542: GetTrainer()
17:59:45,542: GetTrainer - Check for trainer 0x1902
DEVICE ID 3561:1902 on Bus 000 Address 001 =================
 bLength                :   0x12 (18 bytes)
 bDescriptorType        :    0x1 Device
 bcdUSB                 :  0x100 USB 1.0
 bDeviceClass           :   0xff Vendor-specific
 bDeviceSubClass        :   0xff
 bDeviceProtocol        :   0xff
 bMaxPacketSize0        :   0x40 (64 bytes)
 idVendor               : 0x3561
 idProduct              : 0x1902
 bcdDevice              : 0x2001 Device 32.01
 iManufacturer          :    0x0
 iProduct               :    0x0
 iSerialNumber          :    0x0
 bNumConfigurations     :    0x1
  CONFIGURATION 1: 100 mA ==================================
   bLength              :    0x9 (9 bytes)
   bDescriptorType      :    0x2 Configuration
   wTotalLength         :   0xda (218 bytes)
   bNumInterfaces       :    0x1
   bConfigurationValue  :    0x1
   iConfiguration       :    0x0
   bmAttributes         :   0x80 Bus Powered
   bMaxPower            :   0x32 (100 mA)
    INTERFACE 0: Vendor Specific ===========================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x0
     bAlternateSetting  :    0x0
     bNumEndpoints      :    0x0
     bInterfaceClass    :   0xff Vendor Specific
     bInterfaceSubClass :   0xff
     bInterfaceProtocol :   0xff
     iInterface         :    0x0
    INTERFACE 0, 1: Vendor Specific ========================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x0
     bAlternateSetting  :    0x1
     bNumEndpoints      :    0xd
     bInterfaceClass    :   0xff Vendor Specific
     bInterfaceSubClass :   0xff
     bInterfaceProtocol :   0xff
     iInterface         :    0x0
      ENDPOINT 0x81: Interrupt IN ==========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x81 IN
       bmAttributes     :    0x3 Interrupt
       wMaxPacketSize   :   0x10 (16 bytes)
       bInterval        :    0xa
      ENDPOINT 0x82: Bulk IN ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x82 IN
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
      ENDPOINT 0x2: Bulk OUT ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x2 OUT
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
      ENDPOINT 0x84: Bulk IN ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x84 IN
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
      ENDPOINT 0x4: Bulk OUT ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x4 OUT
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
      ENDPOINT 0x86: Bulk IN ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x86 IN
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
      ENDPOINT 0x6: Bulk OUT ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x6 OUT
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
      ENDPOINT 0x88: Isochronous IN ========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x88 IN
       bmAttributes     :    0x1 Isochronous
       wMaxPacketSize   :   0x10 (16 bytes)
       bInterval        :    0x1
      ENDPOINT 0x8: Isochronous OUT ========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x8 OUT
       bmAttributes     :    0x1 Isochronous
       wMaxPacketSize   :   0x10 (16 bytes)
       bInterval        :    0x1
      ENDPOINT 0x89: Isochronous IN ========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x89 IN
       bmAttributes     :    0x1 Isochronous
       wMaxPacketSize   :   0x10 (16 bytes)
       bInterval        :    0x1
      ENDPOINT 0x9: Isochronous OUT ========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x9 OUT
       bmAttributes     :    0x1 Isochronous
       wMaxPacketSize   :   0x10 (16 bytes)
       bInterval        :    0x1
      ENDPOINT 0x8A: Isochronous IN ========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x8a IN
       bmAttributes     :    0x1 Isochronous
       wMaxPacketSize   :   0x10 (16 bytes)
       bInterval        :    0x1
      ENDPOINT 0xA: Isochronous OUT ========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0xa OUT
       bmAttributes     :    0x1 Isochronous
       wMaxPacketSize   :   0x10 (16 bytes)
       bInterval        :    0x1
    INTERFACE 0, 2: Vendor Specific ========================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x0
     bAlternateSetting  :    0x2
     bNumEndpoints      :    0xd
     bInterfaceClass    :   0xff Vendor Specific
     bInterfaceSubClass :   0xff
     bInterfaceProtocol :   0xff
     iInterface         :    0x0
      ENDPOINT 0x81: Interrupt IN ==========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x81 IN
       bmAttributes     :    0x3 Interrupt
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0xa
      ENDPOINT 0x82: Bulk IN ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x82 IN
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
      ENDPOINT 0x2: Bulk OUT ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x2 OUT
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
      ENDPOINT 0x84: Bulk IN ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x84 IN
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
      ENDPOINT 0x4: Bulk OUT ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x4 OUT
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
      ENDPOINT 0x86: Bulk IN ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x86 IN
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
      ENDPOINT 0x6: Bulk OUT ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x6 OUT
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
      ENDPOINT 0x88: Isochronous IN ========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x88 IN
       bmAttributes     :    0x1 Isochronous
       wMaxPacketSize   :  0x100 (256 bytes)
       bInterval        :    0x1
      ENDPOINT 0x8: Isochronous OUT ========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x8 OUT
       bmAttributes     :    0x1 Isochronous
       wMaxPacketSize   :  0x100 (256 bytes)
       bInterval        :    0x1
      ENDPOINT 0x89: Isochronous IN ========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x89 IN
       bmAttributes     :    0x1 Isochronous
       wMaxPacketSize   :   0x10 (16 bytes)
       bInterval        :    0x1
      ENDPOINT 0x9: Isochronous OUT ========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x9 OUT
       bmAttributes     :    0x1 Isochronous
       wMaxPacketSize   :   0x10 (16 bytes)
       bInterval        :    0x1
      ENDPOINT 0x8A: Isochronous IN ========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x8a IN
       bmAttributes     :    0x1 Isochronous
       wMaxPacketSize   :   0x10 (16 bytes)
       bInterval        :    0x1
      ENDPOINT 0xA: Isochronous OUT ========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0xa OUT
       bmAttributes     :    0x1 Isochronous
       wMaxPacketSize   :   0x10 (16 bytes)
       bInterval        :    0x1
17:59:45,591: GetTrainer - Trainer found: 0x1902
17:59:45,591: GetTrainer() returns, trainertype=0x1902
17:59:45,591: Tacx   - GetTrainer - Trainer found: 0x1902
17:59:45,591: Tacx   - GetTrainer - Trainer found: 0x1902
17:59:45,591: InitialiseTrainer data="02 00 00 00" (len=4)
Traceback (most recent call last):
  File "FortiusAnt.py", line 1059, in <module>
    if LocateHW(x):
  File "FortiusAnt.py", line 259, in LocateHW
    usbTrainer.InitialiseTrainer(devTrainer)     #initialise trainer
  File "C:\Users\julien\Documents\GitHub\FortiusANT\pythoncode\usbTrainer.py", line 408, in InitialiseTrainer
    dev.write(0x02,data)
  File "C:\Users\julien\AppData\Local\Programs\Python\Python38-32\lib\site-packages\usb\core.py", line 943, in write
    return fn(
  File "C:\Users\julien\AppData\Local\Programs\Python\Python38-32\lib\site-packages\usb\backend\libusb0.py", line 529, in bulk_write
    return self.__write(_lib.usb_bulk_write,
  File "C:\Users\julien\AppData\Local\Programs\Python\Python38-32\lib\site-packages\usb\backend\libusb0.py", line 611, in __write
    return int(_check(fn(
  File "C:\Users\julien\AppData\Local\Programs\Python\Python38-32\lib\site-packages\usb\backend\libusb0.py", line 431, in _check
    raise USBError(errmsg, ret)
usb.core.USBError: [Errno None] b'libusb0-dll:err [submit_async] submitting request failed, win error: Falscher Parameter.\r\n'

GUI in Ubuntu

I am setting up a "new" compuer for FortiusANT/Zwift/GoldenCheetah/etc.

I can run the GUI but when I press start I get this error:

[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python3: ../../src/xcb_io.c:165: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
Aborted (core dumped)

Any ideas?

Python dependencies

I noticed your project on the antifier GitHub page... I am very eager to get your solution working.

When trying to run your software on the same software as I was using antifier (Python 2.7) in run into the following error

File "FortiusAnt.py", line 865 clv.print() ^ SyntaxError: invalid syntax

Right now I am trying to satisfy requirements in Python 3.5 but run into problems with wxPython

Error running configure ERROR: failed building wxWidgets Traceback (most recent call last): File "build.py", line 1468, in cmd_build_wx wxbuild.main(wxDir(), build_options) File "/tmp/pip-build-mmr8jqj1/wxPython/buildtools/build_wxwidgets.py", line 372, in main "Error running configure") File "/tmp/pip-build-mmr8jqj1/wxPython/buildtools/build_wxwidgets.py", line 85, in exitIfError raise builder.BuildError(msg) buildtools.builder.BuildError: Error running configure

and Pyinput

Invalid requirement: 'python-xlib>=0.17; linux in "sys_platform"' Traceback (most recent call last):

I will look into this in more detail, guess the error is more related to my local installation.

Rouvy slopes are presented different in FortiusANT

When riding uphill in rouvy with a slope of 10%, FortiusANT shows a slope of 25%.

Is caused by function msgUnpage51_TrackResistance() in antDongle.py where the returned slope is multiplied by 2.5; commented as "empirically" but never properly verfied and remained in the code without proper justfication.
It may be caused by initial superficial tests with Zwift.

I will check whether this factor should remain there; it seems candidate to be removed,

Trainer not correctly detected by ZWIFT, Dongle not supported

Hello, due to this situation about Corona I was also checking my old trainner. I just relaised that Tacx Trainner Software isn't supported anymore. I've try fortiusAnt and I get working parcially as I have some issues.
I'm from Portugal, Evora and I've a Fortius T1932.
I've 2 ANT dongles but I realised one is very old (GARMIN USB) and as only 4 channels so no detected as a ANT dongle by ExplorANT.exe (I don't know if this is soposly to be like that but left here for reference).
The other dongle works correct and is dected by ExplorANT.exe.
I'm able to go ahead as I've a tablet with ANT integrated.
So running fortiusant windows exe file I got the following:

  • on ZWIFT detects HR but not the trainner.
  • on ROUVY detects HR and also the trainer (but as soon I start pedal - fortiusant crashes)
    Runing PY files
  • on ZWIFT detects HR but not the trainner.
  • on ROUVY detects HR and also the trainer and app runs smothly.

Any hit why ZWIFT can't detect trainner?

Originally posted by @E-NINA in #14 (comment)

Frequency of data capture - sufficient for pedal stroke analysis? - YES!

The main loop performing trainer read/write and ANT send/recv appears to be intentionally limited to 4/sec. Is the rate limiting specifically to slow down ANT message frequency?

When I was implementing 20km/h calibration in antifier, at one point I had a loop without sleeps and observed ~60Hz updates from the trainer.

Seems feasible to decouple trainer comms from ANT comms in the main loop, rather than being in lock-step as they are now. Motivation for this could be implementation of a polar view for pedal stroke analysis.

Defining powercurve for Fortius...

Just to be clear, I do not really have a lot of experience with Tacx, neither with Zwift. I primarily decided to buy the Fortius because I stumbled upon antifier and through antifier upon your solution.

I used the original Tacx software (3.5) once and did a video bike ride (Amstel Gold). During that ride I really noticed that the wheel speed is similar to the virtual speed. When I climbed a mountain, I really had to change gears to cope with the increased resistance.... downhill I really could stop pedalling because the rear wheel was driven bij the Fortius motor. I just finished my first real Zwift ride and noticed that it basically measures my power delivered and depending on the slope it changes my virtual bike speed (which really does not correspond with my real wheel speed). I have to read in detail through your wiki, but is this the behaviour you suspect? Apparently my Zwift trial period is ending... I think I will extend to continue optimising your solution....

Originally posted by @mtbiker22 in #3 (comment)

Anyone have this working on Linux?

I have downloaded all of the repository files and when i try to run the FortiusANT.py program I receive the following:
Traceback (most recent call last):
File "FortiusAnt.py", line 119, in
import numpy
ModuleNotFoundError: No module named 'numpy'

I am running Lubuntu 18.04.
I have 1 Ant 2 Stick and 1932 Head Unit.

Thanks
Mike

Using FortiusANT directly on a RaspberryPi without a head-unit

I obtained a non functioning Fortius Trainer (T1932 blue-ring, T1941 motor brake) a good while back. At that stage I tried to get it running through GoldenCheetah and some old Tacx software with no luck.

The current "Lock-down" rekindled my interest to get it running . A few searches later I found FortiusANT, installed it and connected the trainer. When I "start to pedal" the motor starts running forever, but I get no sensor feedback to FortiusANT. My suspicion is that there is an issue with the rx signal. I did open the head-unit and found a lot of corrosion and oxidation.
*Note that I don't have the cadence sensor, is this required?

Upon your reference to "totalreverse/ttyT1941" it got me thinking to get FortiusANT running without a head-unit, using serial communication.
Now here comes my questions:

  • Will this be possible?
  • How could I achieve this technically?
  • Will an old RPi model B be sufficient? (Processing power, single core, ram ect...)

My end goal is to have FortiusANT running on the Pi, and to transmit and receive an ANT+ signal that I can use with Zwift.

I am more mechanically inclined, but I can help myself around electronics and coding with the help of google. If you can give me some guidance it will be greatly appreciated.

I did note that @Alanimus uses a RPi Zero. I'm not sure about how he's using it on his system.

Thank you

iMagic Speed computation issue

It seem that the raw speed (called WheelSpeed in the app) values (byte 1-2) returned by the Imagic (legacy protocol) differ from those of the Fortius (new protocol). This as the consequence that the speed reading are wronging displayed (much to low in case of imagic)

Tacx Fortius #1941 with motor break doesn't show the correct Grade and Power

Regarding the behavior of the current configuration of FortiusAnt, If I'm not mistaking the actual setup is for the use of Imagic trainer and, as I own an old Fortius with motor not magnets, the algorithms to calculate Power and resistance had to be twik. I'm currently working on this.
Nevertheless the program is usable with both Zwift and Rouvy and Fullgaz even though the resistance is not responding linear to Grade.

requirements.txt

@fritz-hh FortiusANT is depending on usb (import usb.core) and fxload.
Also, on python version 3

Is this something that can be defined in requirements.txt?

Thanks in advance for info!

iMagic + Zwift | Powercalibration and -curve

IMagic + Zwift
image

PowerMeter + Garmin
image

Сurrent issues:

  1. The power coincides with some error, but it starts to differ greatly when the gradient changes.
  2. The brake force does not match the gradient. When riding horizontally or downhill, I ride as if constantly uphill.

From totalreverse wiki:

Range is 0x00...0xFF
0x80 is 'neutral' (electrical magnetic field switched off).
Values less than 0x80 reduce brake force (electrical magnetic field reduces the static magnetic fields) and values greater than 0x80 increase the brake force (electrical magnetic field increase the static magnetic fields).

But the value 0x80 does not match the gradient 0%. This is approximately a slope of 3-4%.
0x25 .. 0x35 = 0%.
This is all according to my feelings.

Originally posted by @yegorvin in #11 (comment)

FortiusANT and GoldenCheetah

Hi, this is a great facility for us who don't have or can't get smart trainers. (Cost!) Thank you for you efforts. I've connected my Fortius (0x1932) and can see output data for all parameters, however in 'Run mode' the Target stays fixed at 100W. I'm using GoldenCheetah (GC) as the trainer app, and it seems that either GC is not sending data to Fortius, or Fortius is not accepting. Even if I use manual ERG mode and increase or decrease load, there is no change on the trainer.

  1. Where does the Target come from?
  2. Does FortiAnt send info back to the trainer?

Thanks again for this utility.

B.

Originally posted by @brianrow in #14 (comment)

Grade2Resistance() configurable?

Before I found your project, I was about to implement the standard equations in antifier to account for rolling resistance, drag and slope.

You quote , I had also found

I understand you have put some effort into making resistance work for you. Personally, I didn't like the default 150/100. I understand also that Zwift for example just works on power - speed, gear, cadence is meaningless. But having just got GoldenCheetah to let me replay .gpx files, realism is my aim for now. I implemented an "option 4" which was just a pure real-world-power to resistance calculation, no scaling or top/bottom end adjustments. It felt ok - even better with flywheel weight. Only one ride, and I guess there's nothing perfect, but that's half the fun - having a play with code while pedalling.

So whatever algorithm I find feels best, is the one I will use. And I can modify code to suit me, all good.

But allowing the algorithms and parameters to be configurable and then providing some defaults seems good.

The Grade2Resistance() routine and the tuning of it is a big deal for ride simulation. The use of virtual flywheel weight I posted in the previous issue is also a feel-factor.

More command line parameters might be easiest but perhaps not ideal. I guess there might be considerable GUI work to allow full customisability.

working with powermeter

Hello

Congrats on the great work

Have some questions about this. If i run FortiusANT, and a powermeter (so i can have correct power numbers, and specially, simply because i have one), will i have any issues? I mean, is Zwift, when starting there is this possibility. Don't know if it will work correctly. Also, as my powermeter is on crank spider, i also have cadence available through it, as well as hrm sensor. So, what i'm saying is that i only want FortiusANT, to control the trainer. I don't want any other feedback from it, as i can give that to Zwift through individual sensors. So, is all this possible?

Thanks

usbTrainer.py refactor?

Hi,

I have, for the last hour or two, been having a play in and around usbTrainer.py and FortiusAnt.py.

My thoughts to begin with were to encapsulate a little

  • don't pass devTrainer to Send() and Receive() functions, rather call Send() and Receive() on a trainer object
  • don't return tuple from Receive() function, rather set the returned values as properties of the trainer object and use them as required
  • get rid of the global trainer_type and LegacyProtocol variables and instead put them inside the trainer object.

Having broken simulation, and reached the point in the evening where I will stop, I though I'd post this issue for discussion.

Having two very distinct sets of behaviour (around LegacyProtocol for the iMagic), and now introducing the iVortex into the mix, it seems to me like a sensible direction to refactor further and separate concerns... each trainer type (or family) having it's own trainer class perhaps, with it's own send()/receive() implementations, yet sharing a common interface, and beginning to abstract a little to setLoad() or setGrade() functions, and a periodic doUpdate() or similar, as opposed to the manual Send/Receive pattern in FortiusAnt currently.

I've been bitten before refactoring someone else's code and there are several things to consider. I can be over keen. Even if there is appetite, timing can be important. That said, it feels like with work towards iVortex it could be both challenging and rewarding to refactor at this point. It would only really work with clear, helpful, incremental changes. Otherwise too much just becomes a fork that may never integrate, and that is unhelpful.

I've pushed to a "Refactor" branch in my fork. Feel free to have a look.

If you do have a look and get your head around my changes, worth perhaps me adding here some quick notes on my thoughts on next steps for context:

  • trainer class gets split to four??... "fortius, magic, vortex, simulation", perhaps with a base for shared code, GetTrainer() decides which one to create.
  • simulation therefore just becomes another device which you can peek/poke
  • with that done, LegacyProtocol goes away, the various resistance/power/speed function implementations get split according to what kind of trainer, common code refactored
  • perhaps then a setLoad()/setGrade() pair, and generally decoupling the main loop

The first step would be for me to restore simulation, discuss/fix my break to SpeedT, CadenceT etc, and consider raising a PR of something working, moving in an agreed direction.

Interested to hear your thoughts on this. Whether it's welcomed, if so thoughts on timing, direction, scope, scale, etc... if not, I'll be happy enough to just Ride On. :)

I am of course very grateful for the software as is - I stumbled across the trainer for not-too-much-money last year, and am delighted that it appears as capable as it is, even now. Thanks to you and those before you. A great lockdown activity.

Support for Data Page 71 - Command Status

Yet to identify controller that uses this, but just as I go through the spec, seems like a sensible thing to cover off or at least record here. No immediate requirement.

Unable to communicate with i-Magic

Hello @WouterJD

I hope you're well during these difficult times, you're doing a great job with this project.

I have installed the software on win10 (working on installing it on a Raspberry Pi, i'll let you know how it goes!) but i'm receiving errors from the communication to the FE. Please see the log below.

Any thoughts?

Thanks very much,

Marty

FortiusANT_log.txt

A little help please... Tacx shows as Fortius in device manager

Went through these steps a couple of times. Windows 10 running two ANT devices with Tacx Fortius 1942 blue control box

  • Uninstalled device (Jungo showing Fortius) Delete driver software checked
  • Unplugged/Replugged in Fortius, showed up as unknown
  • Right click and select "update driver software"
  • Select libusb-win32 devices
  • Select ANT USB Stick 2

Fortius shows up in Device Manager as new ANT USB Stick 2 device (one of three)

  • Ran FortiusANT.exe

Fortius shows up again each time in Device Manager as Jungo device with Tacx Driver and can't be discovered by Zwift or similar.

Please tell me I'm missing something easy here or is there another (Tacx?) file I need to delete?

Thanks!

Crash if (non bundled) application called from another directory

A crash occurs, if the non bundled application is started from within another directory (see example below)

C:\Users\julien\Documents\GitHub\FortiusANT>python pythoncode\FortiusAnt.py -m -g
13:14:39,093: FortiusANT started
13:14:39,093: -g
13:14:39,094: -m
13:14:39,094: ------------------
Traceback (most recent call last):
  File "C:\Users\julien\Documents\GitHub\FortiusANT\pythoncode\FortiusAntGui.py", line 704, in OnPaint
    dc.DrawBitmap(self.BackgroundBitmap, 0, 0)          # LeftTop in pixels
wx._core.wxAssertionError: C++ assertion "bmp.IsOk()" failed at ..\..\src\msw\dc.cpp(1313) in wxMSWDCImpl::DoDrawBitmap(): invalid bitmap in wxMSWDCImpl::DrawBitmap

Undefined `legacyResistance2Power`

The function legacyResistance2Power.
It should be replaced by legacyResistance2Power as the latter function supports both the new and the legacy protocols.

tacx app

Hi, I wanted to know if you could use FortiusAnt for Tacx app descktop windows. I have tried but it seems that it cannot connect. Thanks AR

Errors Using Rundown Test Through GUI

All other aspects of GUI work (Locate, Start, Stop) but I'm getting the following errors when selecting Rundown (Python 3.8). Paths to files below are correct, Thanks!

FortiusAnt.py -g

19:34:48,439: GetTrainer - Trainer found: 0x1942
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\Users\Jeff\AppData\Local\Programs\Python\Python38\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "C:\Users\Jeff\AppData\Local\Programs\Python\Python38\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "C:\temp\Downloads\FortiusAnt\FortiusANT-master\FortiusANT-master\pythoncode\FortiusAntGui.py", line 794, in OnClick_btnRunoff_Thread
self.callRunoff()
File "C:\temp\Downloads\FortiusAnt\FortiusANT-master\FortiusANT-master\pythoncode\FortiusAnt.py", line 162, in callRunoff
return Runoff(self)
File "C:\temp\Downloads\FortiusAnt\FortiusANT-master\FortiusANT-master\pythoncode\FortiusAnt.py", line 356, in Runoff
PedalEcho, SpeedKmh, Cadence, Calibrate, False)
NameError: name 'Calibrate' is not defined

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.