BodyMedia Reverse Engineeringcentibenzo @t gmail d.t com
I am documenting this work in the hopes that it spurs BodyMedia to create a
Linux driver, or a third party to develop a similar Open Source Linux application.
A partial reverse engineering of the BodyMedia ArmBand Mini device protocol was accomplished.
A Python library was written to communicate with the device, and to parse the data.
This library is compatible with both Linux and Windows (barely tested on Windows).
There is a lot of work to do before this system becomes useful.
One night of RAW graphed data records, left-to-right, showing brief
activity before sleep, quiet, and more activity after waking.
- Correct Linux driver and modprobe line discovered to make device function as a USB Serial port.
- Basic structure of serial protocol decoded.
- Memory dumps from device can be obtained by serial protocol.
- Most data structures in memory, including data tables, can be parsed.
- Crude "activity graph" can be made from the raw data tables which does show activity over time
- Find and interpret data timestamps (presumably in each data table header)
- Identification of type and size of individual data record fields
- Identification of actual MEANING of individual data record fields
- Development of heuristics to translate data into indentification of sleep, active, etc (Ph.D thesis)
- Device uses an FTDI USB<->Serial chip, compatible with Linux ftdi_sci driver.
- Under Windows, system uses a stock FTDI driver with changed Vendor and Product
ID's to present a virtual com port to Java(?) software integrated with Web
- Protocol is far more complex than the USB/Serial application would
require. It is geared for the wireless RF link (sync bytes, etc). I suspect
it derives from some RF vendor protocol.
- ??? Device logs a data record only once per minute (?). A little disappointing - perhaps the clinical models log more. Or maybe it is variable rate???
- ??? Device has 200 kByte of memory for data logging???
- Ubuntu Linux 9.04
- Windows XP
Python Code: SEE NEWER VERSION ABOVE
Command List: SEE NEWER VERSION ABOVE
(Command list must be renamed to known_requests.cpickle for FullSerialDump() function.)
Linux: How to force the ftdi_sci driver to recognize the BodyMedia Vendor/Product IDs:
sudo modprobe ftdi_sio vendor=0x11f8 product=0x0007
Verify that a new '/dev/ttyUSB*' device has been created.
Windows: You don't need to install an FTDI driver if you already have the
GoWearSense driver installed. When you plug in the device, you will see a new
COM14 (or similar) port appear which you can use within Python.
Examples of how to use the python library.
import bodylib as bl
# Open, query, and close the device
# Let me print all the packets sent and received
# Parse packets and print all data in appropriate format in text tab-delimited format to file
# This is a good human and spreadsheet readable dump of most of the device state.
# If filename not specified, outputs to stdout for your inspection
# I usually save my device dumps in cPickle format for future reference
# Assemble the received data packets into a unified memory buffer
# Pretty Print the memory buffer. We use 46 bytes/line to be periodic with the most common data record
# Parse memory data structures, including data records
# Create image from data table
Serial baud rate must be set to 921,600 bps.
The protocol is packet based, with packets of length 66 bytes including headers
and sync bytes.
The computer sends a Request packet ("Req" in my code), to which the device
responds with one or more answer ("Ans") packets.
All request types expect only a single "Ans" answer packet, except for requests
to read from the data memory. Data memory requests specify a starting memory
offset and a length, and receive as many 66-byte packets as required in
response. I call this "Burst" mode in the code.
All packets have a simple modulus 256 checksum byte. This is a simple sum and
modulus of all bytes in the packet, excluding sync bytes (leading or tailing
"AB" or "BA").
The device appears to ignore the checksums sent to it (I don't bother computing
it). However, the device always gives me correct checksums.
The packet begins with a leading sync byte 0xAB. Then a rather elaborate header
almost all of which is unused or invariant (RF protocol related?). Most
importantly, a "command" byte defines the type of request. There is also some
form of sequence number byte on Req packets, but not device-generated Ans
packets. The sequence number appears to be ignored by the device.
The "command" byte specifies the requestion type, and is the key element of the
header. Note that in my code, I call this the "Bank" byte, because I initially
thought it was a device selection address.
After the command and (sequence number if Req), the packet payload contains
The command byte to read from the main data memory is 0x82. The command byte
for the Answer packets from the device is 0x02 (in my code I stip the high bit
from the command/bank for clarity, so you may see 0x02 Requests).
The payload to read from the main data memory consists of a 4-byte LSB offset
uint32 and a 2-byte LSB length uint16.
In addition to the block of main data memory, there are a number of other
values which can be queried using other command types. These usually return
short strings or single binary values. Examine the packet lists to find some
"Free Serial Port Monitor" by HDD Software is GREAT - you can use this to snoop
on the virtual serial port under Windows, and export the conversation to a file.
Under Python I've created a parser for the "Free Serial Port Monitor" text
export of the "RequestView" window. See bodylib.ParseFile().
Debug FS is very useful for monitoring USB traffic under Linux.
sudo mount -t debugfs none_debugs /sys/kernel/debug
I use ipython, Python 2.6.2, numpy, PIL python libraries. If you install on
Windows you'll have to fetch each of them, or comment them out of the bodylib library.
See Also http://bodybugghacks.blogspot.com/
(apparently an attack at the Java API level, but the author is not forthcoming on details)
Units of Measure - from http://bodybugghacks.blogspot.com/2008/07/code.html?showComment=1225132980000#c1498831675573385775
Useful to determine figure out field structure?
Accelerometers - The SenseWear® WMS Armband (2-axis) - The SenseWear® WMS Armband Mini (3-axis) Calibrated range is +/- 2.0g
The minimum resolution is 0.01g
Two-standard-deviation accuracy of +/-0.05g (longitudinal axis) and +/-0.06g (transverse & forward axis), up to 1.0g
Two-standard-deviation accuracy of +/-12.0% of expected value otherwise
Calibrated Range is 0.0 W/m2 to 300.0W/m2
A minimum resolution of 1.0W/m2
Two-standard-deviation of +/-10.0W/m2 at heat flux less than 50.0W/m2
Two-standard-deviation of +/-35.0% of expected value otherwise
Galvanic Skin Response
Calibrated range is 56.0KΩ to 20.0MΩ (50.0 nSiemens – 17.00 uSiemens)
Two-standard-deviation accuracy of +/- 7.0 nSiemens up to 233.34 nSiemens reading
Two-standard-deviation accuracy of +/- 3.0% of expected value otherwise
Calibrated range is 20.0ºC to 40.0ºC
A minimum resolution of 0.05ºC
Two-standard deviation accuracy of +/- 0.80°C
Classification of the device, as per 93/42 directives: IIa (rule 10)
Certification procedure : 93/42/EEC, Annex VI, VII.
Transmit Power Class 8 - Less than 10mW output power
Duty Cycle Class 4 - permitted to operate at 100% duty cycle
Receiver Class 3 - Standard reliable SRD communication media