Closed TedHerman closed 13 years ago
I still have this problem a lot too, in quite a few different situations (initial connect, post send, etc...). I've found that the protocol is very timing sensitive (that was a HUGE problem with bulk transfers), so I probably just need to work on figuring out what needs to be timed how.
If it makes any difference, here is the log of attaching the fit bit base station & then running fitbit.py:
usb 4-1: new full speed USB device using uhci_hcd and address 5
usb 4-1: New USB device found, idVendor=10c4, idProduct=84c4
usb 4-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 4-1: Product: Fitbit Base Station
usb 4-1: Manufacturer: Silicon Labs
usb 4-1: SerialNumber: (long string, omitted in this posting)
usb 4-1: reset full speed USB device using uhci_hcd and address 5
usb 4-1: reset full speed USB device using uhci_hcd and address 5
usb 4-1: reset full speed USB device using uhci_hcd and address 5
Running Linux version 2.6.37.6-smp (root@midas) (gcc version 4.5.2 (GCC) ) #2 SMP Sat Apr 9 23:39:07 CDT 2011
I didn't look to see if there are driver issues or timing parameters specifiable for the USB modules used.
One other thought. Can a device be used for read and write to fitbit? For instance, modprobe usbserial vendor=0x10c4 product=0x84c4 followed by plugging in the fitbit assigns /dev/ttyUSB0 to the fitbit. I see that libusb.py in antprotocol just has simple send/receive methods. Could these be read and write to the /dev/ttyUSB0 device, so I could try some things to debug the timeout problem? I tried a different computer today with the same timeout result.
There's a fork of libfitbit that has a pyserial class available, that will allow you to access the device via the tty route:
https://github.com/lawnjam/libfitbit/blob/master/python/antprotocol/pyserial.py
You'll want to pull just this file, as the rest of his fork is for working with the suunto t3 wrist watch, so it won't actually work with the fitbit. I'll try to bring this file into the library mainline ASAP too. Just need to set aside some testing time.
Never managed to get connected through pyserial on /dev/ttyUSB0, so I went back to investigate the libusb implementation in more detail. To do this, I recompiled libusb with debugging enabled. Apparently, there is communication, as you see below from the condensed log (removing most of the noise, just to show bytes transferred). Unfortunately the Python Ant protocol raises an error. Is this a version problem?
libusb:debug [bulk_transfer_cb] actual_length=0 --> ['a4', '09', '46', '00', '00', '00', '00', '00', '00', '00', '00', '00', 'eb'] libusb:debug [bulk_transfer_cb] actual_length=7 <-- ['a4', '03', '40', '00', '46', '00', 'a1'] --> ['a4', '03', '42', '00', '00', '00', 'e5'] <-- ['a4', '03', '40', '00', '42', '00', 'a5'] --> ['a4', '03', '43', '00', '00', '10', 'f4'] <-- ['a4', '03', '40', '00', '43', '00', 'a4'] --> ['a4', '02', '45', '00', '02', 'e1'] <-- ['a4', '03', '40', '00', '45', '00', 'a2'] --> ['a4', '02', '47', '00', '03', 'e2'] <-- ['a4', '03', '40', '00', '47', '00', 'a0'] --> ['a4', '02', '44', '00', 'ff', '1d'] <-- ['a4', '03', '40', '00', '44', '00', 'a3'] --> ['a4', '05', '51', '00', 'ff', 'ff', '01', '01', 'f0'] <-- ['a4', '03', '40', '00', '51', '00', 'b6'] --> ['a4', '01', '4b', '00', 'ee'] <-- ['a4', '03', '40', '00', '4b', '00', 'ac'] <-- ['a4', '09', '4e', '00', '99', 'b4', '00', '00', '00', '00', '00', '00', 'ce'] --> ['a4', '09', '4f', '00', '78', '01', '00', '00', '00', '00', '00', '00', '9b'] <-- ['a4', '09', '4e', '00', '99', 'b4', '00', '00', '00', '00', '00', '00', 'ce'] <-- ['a4', '03', '40', '00', '01', '05', 'e3'] --> ['a4', '09', '4f', '00', '78', '02', 'a6', '73', '00', '00', '00', '00', '4d'] <-- ['a4', '09', '4e', '00', '99', 'b4', '00', '00', '00', '00', '00', '00', 'ce'] <-- ['a4', '03', '40', '00', '01', '05', 'e3'] --> ['a4', '01', '4c', '00', 'e9'] <-- ['a4', '03', '40', '00', '4c', '00', 'ab'] --> ['a4', '09', '46', '00', '00', '00', '00', '00', '00', '00', '00', '00', 'eb'] <-- ['a4', '03', '40', '00', '46', '00', 'a1'] --> ['a4', '03', '42', '00', '00', '00', 'e5'] <-- ['a4', '03', '40', '00', '42', '15', 'b0'] Traceback (most recent call last): File "python/antprotocol/protocol.py", line 161, in _check_ok_response raise ANTStatusException("Message status %d does not match 0x0 (NO_ERROR)" % (status[5])) antprotocol.protocol.ANTStatusException: Message status 21 does not match 0x0 (NO_ERROR)
Info that I posted in my blog post at http://www.openyou.org/2011/08/07/libfitbit-hangups/ :
Whenever libfitbit connects to the tracker, the first transfer after plugging in the USB goes fine. We start communications with an ANT reset message, and we always get back a 0x6F package (Startup Message) with a payload of 0x00 (POWER_ON_RESET), which is what we expect since we just powered on the ANT stick. We then continue on through establishing a communications channel, running a beacon signal to find the tracker, and other steps as laid out in the fitbit protocol document.
The problem comes in on the second run of a libfitbit based utility. We try and reset the device, but instead of getting back a 0x6F packet, we usually receive something that looks like a bulk data receive packet, like we would expect back from a bank transfer. Further executions the utility will result in the same, until the point where the receive command from the reset completely times out, and continues to do so. The only way to fix things at this point is to unplug/replug the ANT stick, at which point things work fine again, for one round of communication.
The actual fitbit client doesn’t have to deal with this due to the fact that it grabs the device right when it starts up, and doesn’t let go until shutdown. I suppose I could try stopping and restarting the service with the base plugged in while watching an analyzer, and that may be my next step.
This bug is the major thing holding up library development right now. Until this is fixed, I can’t reliably run multiple sessions with the fitbit, and having to replug the USB stick isn’t a viable solution. I’m pretty sure I’m missing something about how connections should end or restart, but progress on this one is slow so far.
Grah. Fixed in local side code. We need a device reset when we first open the base, but it has to be done in a weird order. We need to set_configuration first (otherwise things die back in the ctypes for libusb), then reset, then set_configuration again. Just put it on a loop to test, works perfectly now, opening and closing. Will close out via commit.
Just starting with libfitbit, hope I can get this running. Documentation is impressive, especially the log/trace of the ANT protocol to the device. However, when I tried (both using latest download or git clone), there's a timeout error. Here's how it appears when I try:
Traceback (most recent call last): File "fitbit.py", line 373, in
sys.exit(main())
File "fitbit.py", line 294, in main
device.init_tracker_for_transfer()
File "fitbit.py", line 185, in init_tracker_for_transfer
self.init_fitbit()
File "fitbit.py", line 169, in init_fitbit
self.init_device_channel([0xff, 0xff, 0x01, 0x01])
File "fitbit.py", line 173, in init_device_channel
self.reset()
File "/home/herman/fitbit/libfitbit/python/antprotocol/protocol.py", line 165, in reset
self._check_reset_response()
File "/home/herman/fitbit/libfitbit/python/antprotocol/protocol.py", line 141, in _check_reset_response
data = self._receive()
File "/home/herman/fitbit/libfitbit/python/antprotocol/libusb.py", line 77, in _receive
r = self._connection.read(self.ep['in'], size, 0, self.timeout)
File "/usr/lib/python2.6/site-packages/usb/core.py", line 637, in read
self.__get_timeout(timeout)
File "/usr/lib/python2.6/site-packages/usb/_debug.py", line 52, in do_trace
return f(_args, *_named_args)
File "/usr/lib/python2.6/site-packages/usb/backend/libusb10.py", line 493, in bulk_read
timeout)
File "/usr/lib/python2.6/site-packages/usb/backend/libusb10.py", line 593, in __read
timeout))
File "/usr/lib/python2.6/site-packages/usb/backend/libusb10.py", line 357, in _check
raise USBError(_str_error[retval.value])
usb.core.USBError: Operation timed out
NOTE: thinking this might be a machine-specific timing issue, I manually changed the timeout value from 1000 to 10000, but the result was the same. Any ideas where I am going wrong?
-- Thanks, Ted.