<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5942935737519383180</id><updated>2012-01-29T22:04:11.191-08:00</updated><title type='text'>Hacking SenseWear / GoWearFit / BodyBugg</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://bodybugglinux.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://bodybugglinux.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Finnerty</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5942935737519383180.post-8192805157575030357</id><published>2009-07-18T14:05:00.000-07:00</published><updated>2009-07-18T14:21:18.305-07:00</updated><title type='text'>Searching for a Calorie Graph</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vKgaS5dCF3g/SmI5UodAe6I/AAAAAAAAAA8/IgJ3Qa8j2W8/s1600-h/EEvsCalorieGraph.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 186px;" src="http://3.bp.blogspot.com/_vKgaS5dCF3g/SmI5UodAe6I/AAAAAAAAAA8/IgJ3Qa8j2W8/s400/EEvsCalorieGraph.png" alt="" id="BLOGGER_PHOTO_ID_5359909533143563170" border="0" /&gt;&lt;/a&gt;Kenneth did some academic paper research and found that our EE column = Energy Expenditure which he thought was the crude calorie calculation on the device.&lt;br /&gt;&lt;br /&gt;I've plotted EE for an ~12 hr period in the top half of the graph above, and in the lower half is the calorie graph from the GoWearFit web service.  I'd say Kenneth is right!&lt;br /&gt;&lt;br /&gt;The web service obviously does slightly different processing.  I'm also not sure of the units for EE - the values range from ~113 - 1050, whereas the calorie chart range from ~1.5 - 7.5 calories-per-minute.  Maybe it is just a divide-by-100 and the more sophisticated web service processing is simply that much more accurate, but I'm not sure.  A summation over EE/100 gives a much larger calorie count than the web service.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5942935737519383180-8192805157575030357?l=bodybugglinux.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bodybugglinux.blogspot.com/feeds/8192805157575030357/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/searching-for-calorie-graph.html#comment-form' title='28 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/8192805157575030357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/8192805157575030357'/><link rel='alternate' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/searching-for-calorie-graph.html' title='Searching for a Calorie Graph'/><author><name>Finnerty</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_vKgaS5dCF3g/SmI5UodAe6I/AAAAAAAAAA8/IgJ3Qa8j2W8/s72-c/EEvsCalorieGraph.png' height='72' width='72'/><thr:total>28</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5942935737519383180.post-1536294313583296742</id><published>2009-07-16T18:39:00.001-07:00</published><updated>2009-07-18T13:42:31.761-07:00</updated><title type='text'>Memory Clear Ability</title><content type='html'>I was surprised to hear that if you have a wristband display for your GoWearFit armband, and don't subscribe to the web service, that you can no longer use the armband once its memory is full.&lt;br /&gt;&lt;br /&gt;If true, this seems rather unfair.  Also poor business practice - the person in question wanted to buy a second device+wristband to replace a lower quality competitor unit, but was unwilling to pay for two unused web subscriptions.  I seem to be driving multiple sales here...&lt;br /&gt;&lt;br /&gt;I tracked down the command to clear the device memory of sensor data the same way the BodyMedia app does it.&lt;br /&gt;&lt;br /&gt;A new bmhack update &lt;span style="font-weight: bold;"&gt;(bmhack-z717a)&lt;/span&gt; is available with a command line '--clear' command.&lt;br /&gt;See the updated &lt;a href="http://bodybugglinux.blogspot.com/2009/07/command-line-extraction-tool.html"&gt; "release post"&lt;/a&gt; for the download link.&lt;br /&gt;&lt;br /&gt;This feature, like everything else, is highly experimental.  I have not yet received a single end user report - please provide them if you've used bmhack.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;UPDATE 7/17: New version z717a.  TESTED UNDER WINDOWS.  More robust serial I/O.&lt;br /&gt;&lt;br /&gt;UPDATE 7/18: New version z718a.  New data record type added, thanks to Freak.  Enhanced device memory dump capabilities for improved debugging.&lt;br /&gt;&lt;br /&gt;UPDATE 7/18: New version z718b.  Fixed limited memory bug (thanks again Roy!).  Software can theoretically now handle a completely full device.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5942935737519383180-1536294313583296742?l=bodybugglinux.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bodybugglinux.blogspot.com/feeds/1536294313583296742/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/memory-clear-ability.html#comment-form' title='40 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/1536294313583296742'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/1536294313583296742'/><link rel='alternate' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/memory-clear-ability.html' title='Memory Clear Ability'/><author><name>Finnerty</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>40</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5942935737519383180.post-5598828177676652921</id><published>2009-07-15T21:53:00.000-07:00</published><updated>2009-07-15T22:20:52.803-07:00</updated><title type='text'>A Trivial Activity Classifier (that works!)</title><content type='html'>With low expectations, I thought I'd throw a simple classifier at the data records to see if it could differentiate between sleep, mundane activity, and strenuous activity.&lt;br /&gt;&lt;br /&gt;The results surprised me!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_vKgaS5dCF3g/Sl6zNDmLGBI/AAAAAAAAAA0/x9ZFT3JOLK4/s1600-h/z709a-activity-comparison.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 432px; height: 134px;" src="http://4.bp.blogspot.com/_vKgaS5dCF3g/Sl6zNDmLGBI/AAAAAAAAAA0/x9ZFT3JOLK4/s400/z709a-activity-comparison.png" alt="" id="BLOGGER_PHOTO_ID_5358917643502557202" border="0" /&gt;&lt;/a&gt;&lt;span style="font-style: italic;"&gt;Top: GoWearFit activity graph, Middle: k-means classifier, Bottom, GoWearFit Sleep Graph.  &lt;span style="font-weight: bold;"&gt;Click graphic for full resolution.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;I used a simple k-means clustering function out of the Open Source "R" statistical package (via the Python RPy interface).  I did _NO_ normalization on the data at all.  I just read in the tab-delimited data, stripped off the date fields, and fed it to the classifier.&lt;br /&gt;&lt;br /&gt;Each 1-minute data record became a point in 27-dimensional space, and I told the algorithm to divide them into 3 classes (hoping they would end up being "sleep", "vigorous", and "moderate").  And it simply worked!&lt;br /&gt;&lt;br /&gt;&lt;span&gt;The black-grey-and-white graph above is the output of the classifier for each minute in a ~18 hour period.  The blue graphs are the graphs provided by the GoWearFit web report, aligned manually.&lt;br /&gt;The peaks at 10:45am and Noon were bike rides/walks.  I took an afternoon nap, and went to sleep around 11:30pm.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5942935737519383180-5598828177676652921?l=bodybugglinux.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bodybugglinux.blogspot.com/feeds/5598828177676652921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/trivial-activity-classifier-that-works.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/5598828177676652921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/5598828177676652921'/><link rel='alternate' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/trivial-activity-classifier-that-works.html' title='A Trivial Activity Classifier (that works!)'/><author><name>Finnerty</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_vKgaS5dCF3g/Sl6zNDmLGBI/AAAAAAAAAA0/x9ZFT3JOLK4/s72-c/z709a-activity-comparison.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5942935737519383180.post-220106270159942698</id><published>2009-07-13T21:08:00.000-07:00</published><updated>2009-07-13T21:18:25.308-07:00</updated><title type='text'>Getting the Sensor Data Right</title><content type='html'>Over the past couple days I've made considerable progress on the GoWearFit command line extraction tool.  Be sure to get the latest version in &lt;a href="http://bodybugglinux.blogspot.com/2009/07/command-line-extraction-tool.html"&gt;my edited release post below.&lt;/a&gt;  &lt;br /&gt;&lt;br /&gt;The current version (z712a) 100% parses the device data memory, and there are only a few fields I still don't understand.  It also adds extracts date and time for the samples, and exports everything into one nice tab-delimited spreadsheet table.&lt;br /&gt;&lt;br /&gt;I added an example tab-delimited output file into the release post as well.&lt;br /&gt;&lt;br /&gt;Finally, I discovered that FileDropper hosting is not quite as free and forever as they claim.  So a lot of earlier data postings have disappeared.  Most are obsolete, but I thought I'd mention it.&lt;br /&gt;&lt;br /&gt;This is still very untested.  Let me know if works or not!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5942935737519383180-220106270159942698?l=bodybugglinux.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bodybugglinux.blogspot.com/feeds/220106270159942698/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/getting-sensor-data-right.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/220106270159942698'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/220106270159942698'/><link rel='alternate' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/getting-sensor-data-right.html' title='Getting the Sensor Data Right'/><author><name>Finnerty</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5942935737519383180.post-217136955019941412</id><published>2009-07-11T15:48:00.000-07:00</published><updated>2009-07-18T13:43:00.402-07:00</updated><title type='text'>Command Line Extraction Tool</title><content type='html'>&lt;span style="font-weight: bold;"&gt;PRE-ALPHA:  bmhack&lt;/span&gt; is a command line extraction tool which will extract and parse data from your (new model) BodyMedia ArmBand device into a variety of formats, including a tab-delimited spreadsheet-compatible file,  raw packets in ASCII HEX, and a full Python cPickle binary dump.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;THIS TOOL WILL NOT HELP YOU &lt;/span&gt;if you are looking for something to give you calorie counts or activity graphs&lt;span style="font-weight: bold;"&gt;.&lt;/span&gt;  It is in a very early state, and is only useful for technical people who wish to attempt to experiment with and analyze the raw data or learn more about their BodyMedia device.&lt;br /&gt;&lt;br /&gt;You must install &lt;span style="font-weight: bold;"&gt;Python 2.6&lt;/span&gt;, and the Python &lt;span style="font-weight: bold;"&gt;numpy&lt;/span&gt; libraries.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Windows&lt;/span&gt;: Python 2.6.2 from &lt;a href="http://www.python.org/download/releases/"&gt;http://www.python.org/download/releases/&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Windows: &lt;/span&gt;Numpy for 2.6.2 from &lt;a href="http://sourceforge.net/projects/numpy/files/"&gt;http://sourceforge.net/projects/numpy/files/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Download &lt;span style="font-weight: bold;"&gt;bmhack &lt;/span&gt;VERSION &lt;span style="font-weight: bold;"&gt;z718b&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;[June 18 update]&lt;/span&gt; from:&lt;br /&gt;&lt;a href="http://www.mediafire.com/?sharekey=26cf7e726ccc34f061d4646c62b381cbfe370e2ca4df676ac95965eaa7bc68bc"&gt;http://www.mediafire.com/?sharekey=26cf7e726ccc34f061d4646c62b381cbfe370e2ca4df676ac95965eaa7bc68bc&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Windows: &lt;/span&gt;Launch bmhack with C:\python26\python.exe bmhack.py&lt;br /&gt;&lt;br /&gt;There is also an example of several days of CSV output in that MediaFire directory, filename z705a.csv&lt;br /&gt;&lt;br /&gt;It is verified to work under Linux, and should work under Windows (let me know?).&lt;br /&gt;&lt;br /&gt;If you want to experiment with the less understood parts of the protocol, download the known_requests.pickle from the same site and move into your current directory when you run bmhack so you can use the --fromSerialFull command.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;MISSING&lt;br /&gt;&lt;/span&gt;-[&lt;span style="font-weight: bold;"&gt;DONE&lt;/span&gt; VERSION z713a] Timestamps - Pretty sure I know where time offsets live before each data table.  I output them to CSV, but can't intepret them yet.  I expect a global time field somewhere?&lt;br /&gt;&lt;br /&gt;-"Register" data - user attributes like height, serial number, etc are probably stored outside of the main data memory area.  I haven't really looked.&lt;br /&gt;&lt;br /&gt;-Other&lt;br /&gt;&lt;br /&gt;In addition to being a command line program, you can also import bmhack into a Python interpreter and manipulate the data or the device directly.  There are an array of analysis and display python functions.&lt;br /&gt;&lt;br /&gt;The bmhack.py code and comments also contain my (incomplete) documentation of the ArmBand data structures.  Look at ReadAllStruct() to start.&lt;br /&gt;&lt;br /&gt;Linux: How to force the ftdi_sci driver to recognize the BodyMedia Vendor/Product IDs:&lt;br /&gt;&lt;br /&gt;sudo modprobe ftdi_sio vendor=0x11f8 product=0x0007&lt;br /&gt;&lt;br /&gt;Verify that a new '/dev/ttyUSB*' device has been created.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;./bmhack.py -h&lt;br /&gt;THIS CODE IS DECLARED BY THE AUTHOR TO BE IN THE PUBLIC DOMAIN.&lt;br /&gt;NO WARRANTY EXPRESSED OR IMPLIED OF ANY KIND IS PROVIDED.&lt;br /&gt;USAGE: ./bmhack.py [SOURCE] [TARGET] [TARGET] ...&lt;br /&gt;Retrieve and convert data from a BodyMedia armband device&lt;br /&gt;Convert from a packet source to one or more target formats&lt;br /&gt;A packet source can be a live BodyMedia USB device, a cPickle&lt;br /&gt;dump file of packets, or a capture file form a serial port sniffer.&lt;br /&gt;&lt;br /&gt;SOURCES - specify only one&lt;br /&gt;--fromSerial=&lt;device&gt;  Extract data by quering a live USB device on the specified serial port&lt;br /&gt;--fromDump=&lt;filename&gt;  Read packets from a cPickle dump file saved previously&lt;br /&gt;--fromFSPM=&lt;filename&gt;  Parse packets from a 'Free Serial Port Monitor' by HDD Software.  &lt;filename&gt; is an export of the RequestView window.&lt;br /&gt;&lt;br /&gt;TARGETS - specify one or more&lt;br /&gt;--toDump=&lt;filename&gt;  Write cPickle dump of all packet data&lt;br /&gt;--toCsv=&lt;filename&gt;  Write a Spreadsheet-compatible tab delimited file of most of the data&lt;br /&gt;--toPackets=&lt;filename&gt;  Write parsed packets in human-readable HEX format&lt;br /&gt;&lt;br /&gt;NOTE: Specify '-' as a filename to toCsv and toPackets commands in order to write to stdout instead of a file&lt;br /&gt;&lt;/filename&gt;&lt;/filename&gt;&lt;/filename&gt;&lt;/filename&gt;&lt;/filename&gt;&lt;/filename&gt;&lt;/device&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5942935737519383180-217136955019941412?l=bodybugglinux.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bodybugglinux.blogspot.com/feeds/217136955019941412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/command-line-extraction-tool.html#comment-form' title='37 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/217136955019941412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/217136955019941412'/><link rel='alternate' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/command-line-extraction-tool.html' title='Command Line Extraction Tool'/><author><name>Finnerty</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>37</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5942935737519383180.post-7353989819678556816</id><published>2009-07-10T21:16:00.000-07:00</published><updated>2009-07-12T16:12:12.044-07:00</updated><title type='text'>HTTP Sniffing</title><content type='html'>I've tried USB sniffing, serial snooping, but some how neglected network sniffing of the HTTP traffic.  Back to my old friend Wireshark nee Ethereal.&lt;br /&gt;&lt;br /&gt;VERY promising results which hopefully will help solve the record field alignment puzzle.&lt;br /&gt;&lt;br /&gt;This is obviously the technique that Henry at &lt;a href="http://bodybugghacks.blogspot.com/"&gt;BodyBuggHacks&lt;/a&gt; used, at least for his initial postings (his later partial Java code posting indicated direct use of the serial port or a BodyMedia Java API).  The protocol has changed a bit - field names are different etc, but the structure is the same.&lt;br /&gt;&lt;br /&gt;Here is an edited sampling of the response to an HTTP POST during a sync:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;....sr.6com.bodymedia.common.shared.armband.comm.UploadRequestO...r.0....L..seri&lt;br /&gt;alPortBeant.,Lcom/bodymedia/device/serial/SerialPortBean;xr.,com.bodymedia.commo&lt;br /&gt;n.shared.comm.DataRequest...).z.n...L..handlert..Ljava/lang/String;L..mySessionI&lt;br /&gt;Dq.~..xpppsr.*com.bodymedia.device.serial.SerialPortBean.\.qBI.K...Z..cradle_mod&lt;br /&gt;eL..ageq.~..L..batteryq.~..L..birthdateq.~..L..boardq.~..L..boardSeriesq.~..L..c&lt;br /&gt;alibrationq.~..L..channelListq.~..[..channelst..[BL..epochq.~..L..gsrThresholdq.&lt;br /&gt;~..L..handq.~..L..heartTargetq.~..L..heightq.~..L..memoryq.~..L..productCodeq.~.&lt;br /&gt;.L..recordsq.~..L..serialq.~..L..sexq.~..L..smokerq.~..L..subjectq.~..L.&lt;br /&gt;systemTimeq.~..L..uptimeq.~..L..versionq.~..L..volumeq.~..L..weightq.~..xp.t..Ag&lt;br /&gt;e: 99 years ^M&lt;br /&gt;t.;Battery voltage: 4.160  Max voltage: 4.200 Charged to 94%^M&lt;br /&gt;t..Series: 16^M&lt;br /&gt;t./ 0: RAWACCTR INUSE   input: 698 output: 1763^M&lt;br /&gt;1: RAWACCLO INUSE   input: 707 output: 2343^M&lt;br /&gt;2: RAWACCTR INUSE   input: 2094 output: 1212^M&lt;br /&gt;3: RAWACCLO INUSE   input:&lt;br /&gt;2095 output: 2930^M&lt;br /&gt;4: RAWACCFW INUSE   input: 988 output: 2410^M&lt;br /&gt;5: RAWACCFW INUSE   input: 1964 output: 2818^M&lt;br /&gt;6:   RAWGSR INUSE   input: 0 output: 1366^M&lt;br /&gt;7:    RAWON INUSE   input: 0 output: 1367^M&lt;br /&gt;8: RAWTSKIN INUSE   input: 40000 output: 1416^M&lt;br /&gt;9:  RAWTCOV INUSE   input: 40000 output: 1416^M&lt;br /&gt;10: RAWTSKIN INUSE   input: 25002 output: 2048^M&lt;br /&gt;11:  RAWTCOV&lt;br /&gt;INUSE   input: 25002 output: 2048^M&lt;br /&gt;t..Chan#    Name ^M&lt;br /&gt;-----    ---- ^M&lt;br /&gt;  0    RAWACCFW^M&lt;br /&gt;  1    RAWTSKIN^M&lt;br /&gt;  2    RAWGSR^M&lt;br /&gt;  3    RAWACCTR^M&lt;br /&gt;  4    RAWACCLO^M&lt;br /&gt;  5    RAWVBAT^M&lt;br /&gt;  6    RAWTCOV^M&lt;br /&gt;  7    RAWON^M&lt;br /&gt;  8    EE^M&lt;br /&gt;  9    MOVTSKIN^M&lt;br /&gt; 10    MOVGSR^M&lt;br /&gt; 11    MOVACCTR^M&lt;br /&gt; 12    MOVACCLO^M&lt;br /&gt; 13    MOVVBAT^M&lt;br /&gt; 14    MOVTCOV^M&lt;br /&gt; 15    MOVON^M&lt;br /&gt; 16    MADACCTR^M&lt;br /&gt; 17    MADACCLO^M&lt;br /&gt; 18    F0CROSS^M&lt;br /&gt; 19    HRATE^M&lt;br /&gt; 20    PEDO3^M&lt;br /&gt; 21    PLATEAU^M&lt;br /&gt; 22    MADECG^M&lt;br /&gt; 23    TRPEAKS^M&lt;br /&gt; 24    MOVTHETA^M&lt;br /&gt; 25    FWPEAKS^M&lt;br /&gt; 26    FCOUNT^M&lt;br /&gt; 27    MOVACCFW^M&lt;br /&gt; 28    MADACCFW^M&lt;br /&gt; 29    TCOUNT^M&lt;br /&gt; 30    LCOUNT^M&lt;br /&gt; 31    PEDO3TOE^M&lt;br /&gt; 32    TIMESTMP^M&lt;br /&gt; 33    HEARTBT^M&lt;br /&gt; 34    T0CROSS^M&lt;br /&gt; 35    L0CROSS^M&lt;br /&gt; 36    RAWECG^M&lt;br /&gt; 37    LOGSWEEP^M&lt;br /&gt; 38    MADTHETA^M&lt;br /&gt; 39    LOPEAKS^M&lt;br /&gt; 40    COMPGSR^M&lt;br /&gt; 41    RAWCGSR^M&lt;br /&gt;&lt;br /&gt;[...SNIP...]&lt;br /&gt;&lt;br /&gt;SESSION-BEGIN0502Firefly2_00000000af1bc00e04a54d7ca00000000090c0000046500200780MOV&lt;br /&gt;TSKIN^M&lt;br /&gt;93494295095895d96396696996c96f97898098498598798998798598899199d9a29a099f9a29a29a&lt;br /&gt;19a39a29a39a39a099d99b99c99f9a19a49a69a59a59a79a99ab9ad9b09b09b19b39b69b89b99b89&lt;br /&gt;b99bb9bd9bf9c09bd9bd9c09bf9be9be9be9be9bf9c19c39c59c79c89ca9ca9ca9ca9ca9c89c69c5&lt;br /&gt;9c59c69c79c99c99c99c99c99c69c39c09c19c59c89cc9ce9d09d29d39d29d29d39d49d79db9dd9d&lt;br /&gt;d9df9de9dd9de9dc9d99d89d99da9de9e09db9d29ca9c59be9b99b59b19ae9ab9aa9aa9aa9ae9b29&lt;br /&gt;b39b49b49b39b39b29b29b29b39b39b39b49b49b49b49b59b59b69b69b79b89b99ba9bb9bb9bb9bb&lt;br /&gt;9bc9bc9bd9bd9bd9bf9bf9c09c09c19c29c19c19c29c29c39c39c49c59c59c29be9bc9bb9ba9bb9b&lt;br /&gt;b9bb9ba9ba9ba9ba9bb9bb9bc9bd9bd9be9be9be9c09c29c49c59c69c59c49c59c69c69c69c79c79&lt;br /&gt;c69c69c69c69c69c59c59c59c59c49c49c39c39c39c29c29c29c39c49c59c69c79c89c99ca9ca9ca&lt;br /&gt;9cb9cc9cc9cc9cc9cd9cd9cd9cc9cc9ca9c79c59c49c59c&lt;br /&gt;79c79c89c89c99ca9cb9cb9cb9cb9cb9cb9cb9cb9cb9cb9cb9ca9c99c79c69c59c69c89ca9cc9cd9&lt;br /&gt;cd9cd9cd9cd9cd9cd9cc9cc9cc9cc9cb9cb9cb9cb9cb9cb9ca9ca9ca9ca9ca9ca9ca9ca9ca9cb9cb&lt;br /&gt;9cc9cc9cd9cd9ce9ce9cf9cf9d19d29d49d59d79d89d89d99da9da9db9dc9dd9de9df9df9df9dd9d&lt;br /&gt;c9dc9dd9dd9de9de9df9df9e09e09e09e19e09dd9dc9dd9de9df9e09e09e19e19e19e09e09e19e29&lt;br /&gt;e39e59e69e69e79e89e99e99ea9e99e99e79&lt;br /&gt;&lt;br /&gt;[...SNIP....]&lt;br /&gt;&lt;br /&gt;t.DThere have been 1247284976 seconds since the epoch.  Time zone -9.^M&lt;br /&gt;t.&amp;amp;gthresh  offbody: 1376  onbody: 1371^M&lt;br /&gt;t..Handed: Left ^M&lt;br /&gt;t..heartrat&lt;br /&gt;e targets lo: 0 hi: 0t..Height: 67 inches^M&lt;br /&gt;t..FILE: 78339 bytes of 1048576, 7 percent used^M&lt;br /&gt;t..Product code: 173^M&lt;br /&gt;t..#  Type      Name     Div               Channels            Bytes^M&lt;br /&gt;-  ----  --------     ---  -------------------------------  -----^M&lt;br /&gt;0   16     V6RES1    1920    9  11  12  27  14  16  17  40    13^M&lt;br /&gt;1   17     V6RES2    1920   20  21  23&lt;br /&gt;24  38  29  37 254    12^M&lt;br /&gt;2   18     V6RES3    1920   30  34  35  31  39  13  28 254    12^M&lt;br /&gt;3   19     V6RES4    1920   26  18  25  10   8 254 254 254     9^M&lt;br /&gt;4   20     UNUSED       0  254 254 254 254 254 254 254 254     0^M&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;I am very excited by that table of record types (16-19) to channel numbers.  I had been parsing that table, but couldn't interpret the numbers before.  I believe this gives me the numbered field name to record mapping I've needed.&lt;br /&gt;&lt;br /&gt;I am willing to send you a full sample if you request via e-mail centibenzo at gmail.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;EDIT (7/11): BREAKTHROUGH:&lt;/span&gt;&lt;br /&gt; 1. The device stores data as 12-bit packed fields, not byte-aligned. &lt;br /&gt; 2. The "table headers" with apparent column labels do NOT correlate with the columns (baffling). &lt;br /&gt; 3. The actual record layout is obtained from the record type table (seen above in HTTP, but also in device mem) indexed into ANOTHER set of field names retrieved by individual request packets.  Weird.&lt;br /&gt;&lt;br /&gt;I should have full data extracts soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5942935737519383180-7353989819678556816?l=bodybugglinux.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bodybugglinux.blogspot.com/feeds/7353989819678556816/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/http-sniffing.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/7353989819678556816'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/7353989819678556816'/><link rel='alternate' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/http-sniffing.html' title='HTTP Sniffing'/><author><name>Finnerty</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5942935737519383180.post-4797603573606212110</id><published>2009-07-09T05:25:00.000-07:00</published><updated>2009-07-09T05:57:20.675-07:00</updated><title type='text'>20+ Hours of Sample Data</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vKgaS5dCF3g/SlXkCu49EYI/AAAAAAAAAAk/P4D85nARRHI/s1600-h/z709a-data-image.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 691px; height: 27px;" src="http://3.bp.blogspot.com/_vKgaS5dCF3g/SlXkCu49EYI/AAAAAAAAAAk/P4D85nARRHI/s800/z709a-data-image.png" alt="" id="BLOGGER_PHOTO_ID_5356438067424858498" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Full day activity image (click image for clear view)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here is an almost full day (~20hrs?) of activity, starting in mid-morning.&lt;br /&gt;&lt;br /&gt;It includes (in order) a ~10 min bike ride, a walk and ~5 min bike ride an hour later, an early afternoon nap (clearly visible in full-size image approx 1/3rd from left), and an eventual ~6-8hrs of broken sleep (dark right side).&lt;br /&gt;&lt;br /&gt;Here is the tab-delimited parsed data:&lt;br /&gt;&lt;a href="http://www.filedropper.com/z709a-full-serial"&gt;http://www.filedropper.com/z709a-full-serial&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here is a gzipped raw binary dump of the 200kbyte data memory (that I know of).  You can try to parse all my unknown data structure fields from this if you like Sudoku.&lt;br /&gt;&lt;a href="http://www.filedropper.com/z709a-mem-dump"&gt;http://www.filedropper.com/z709a-mem-dump&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;OBSERVATION: This dump had 1121 data records.  I wore the armband something like 20 hours.  That comes to 56 records per hour, which adds some evidence to my 1 record/minute estimate.&lt;br /&gt;&lt;br /&gt;OBSERVATION: this data dump came in one continuous data record table.  I believe this is because I put the armband on and kept it on for the entire day.  I think a new data record table is started whenever the armband is put on.&lt;br /&gt;&lt;br /&gt;OBSERVATION: this one day of data took ~50kbyte of device memory.  The device must have more than the 200kbyte memory I know about.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5942935737519383180-4797603573606212110?l=bodybugglinux.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bodybugglinux.blogspot.com/feeds/4797603573606212110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/20-hours-of-sample-data.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/4797603573606212110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/4797603573606212110'/><link rel='alternate' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/20-hours-of-sample-data.html' title='20+ Hours of Sample Data'/><author><name>Finnerty</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_vKgaS5dCF3g/SlXkCu49EYI/AAAAAAAAAAk/P4D85nARRHI/s72-c/z709a-data-image.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5942935737519383180.post-984873467926816180</id><published>2009-07-07T20:47:00.000-07:00</published><updated>2009-07-07T20:56:38.971-07:00</updated><title type='text'>Sample Data</title><content type='html'>Here is a tab-delimited text sample output of a day or two of data from my GoWearFit branded BodyMedia armband (device was not worn much except at night).&lt;br /&gt;&lt;br /&gt;You can import this data into a spreadsheet.  Note there are multiple structures dumped.&lt;br /&gt;&lt;br /&gt;Note that the column headers do NOT LINE UP with the data columns, I am just dumping one bytes per column - some values obviously are 16-bit or more.  If you solve this little puzzle, please let me know!&lt;br /&gt;&lt;br /&gt;This is the output of &lt;code&gt;the SaveStructTabDelim&lt;/code&gt;() function in my Python library for talking with the device.  See the code for detail.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.filedropper.com/z705a-full-serial"&gt;http://www.filedropper.com/z705a-full-serial&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Contact me to get a cPickle capture of the raw packets, which contain some transactions not representing in the processed tab-delimited form.&lt;br /&gt;&lt;br /&gt;I'm very curious what you all make of it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5942935737519383180-984873467926816180?l=bodybugglinux.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bodybugglinux.blogspot.com/feeds/984873467926816180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/sample-data.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/984873467926816180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/984873467926816180'/><link rel='alternate' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/sample-data.html' title='Sample Data'/><author><name>Finnerty</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5942935737519383180.post-6407516720577693034</id><published>2009-07-06T09:38:00.000-07:00</published><updated>2009-07-12T16:15:27.942-07:00</updated><title type='text'></title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_vKgaS5dCF3g/SlIqAqql5oI/AAAAAAAAAAY/Ai-3HTOZr_w/s1600-h/z706a-full-serial-one_night.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 29px;" src="http://4.bp.blogspot.com/_vKgaS5dCF3g/SlIqAqql5oI/AAAAAAAAAAY/Ai-3HTOZr_w/s320/z706a-full-serial-one_night.png" alt="" id="BLOGGER_PHOTO_ID_5355389097838241410" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;BodyMedia Reverse Engineering&lt;/h1&gt;centibenzo @t gmail d.t com&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I am documenting this work in the hopes that it spurs BodyMedia to create a&lt;br /&gt;Linux driver, or a third party to develop a similar Open Source Linux application.&lt;br /&gt;&lt;br /&gt;A partial reverse engineering of the BodyMedia ArmBand Mini device protocol was accomplished.&lt;br /&gt;&lt;br /&gt;A Python library was written to communicate with the device, and to parse the data.&lt;br /&gt;This library is compatible with both Linux and Windows (barely tested on Windows).&lt;br /&gt;&lt;br /&gt;There is a lot of work to do before this system becomes useful.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Accomplished&lt;/b&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_vKgaS5dCF3g/SlIqAqql5oI/AAAAAAAAAAY/Ai-3HTOZr_w/s1600-h/z706a-full-serial-one_night.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 427px; height: 38px;" src="http://4.bp.blogspot.com/_vKgaS5dCF3g/SlIqAqql5oI/AAAAAAAAAAY/Ai-3HTOZr_w/s320/z706a-full-serial-one_night.png" alt="" id="BLOGGER_PHOTO_ID_5355389097838241410" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;br /&gt;One night of RAW graphed data records, left-to-right, showing brief&lt;br /&gt;activity before sleep, quiet, and more activity after waking.&lt;/em&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Correct Linux driver and modprobe line discovered to make device function as a USB Serial port.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Basic structure of serial protocol decoded.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Memory dumps from device can be obtained by serial protocol.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Most data structures in memory, including data tables, can be parsed.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Crude "activity graph" can be made from the raw data tables which does show activity over time&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;To do&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Find and interpret data timestamps (presumably in each data table header)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Identification of type and size of individual data record fields&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Identification of actual MEANING of individual data record fields&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Development of heuristics to translate data into indentification of sleep, active, etc (Ph.D thesis)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Discoveries&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Device uses an FTDI USB&lt;-&gt;Serial chip, compatible with Linux ftdi_sci driver.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Under Windows, system uses a stock FTDI driver with changed Vendor and Product&lt;br /&gt;ID's to present a virtual com port to Java(?) software integrated with Web&lt;br /&gt;Browser.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Protocol is far more complex than the USB/Serial application would&lt;br /&gt;require.  It is geared for the wireless RF link (sync bytes, etc).  I suspect&lt;br /&gt;it derives from some RF vendor protocol.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;??? Device logs a data record only once per minute (?).  A little disappointing - perhaps the clinical models log more.  Or maybe it is variable rate???&lt;/li&gt;&lt;br /&gt;&lt;li&gt;??? Device has 200 kByte of memory for data logging???&lt;/li&gt;&lt;li&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Platform&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Device: &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Ubuntu Linux 9.04&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows XP&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;b&gt;Usage&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Python Code: &lt;span style="font-style: italic;"&gt;SEE NEWER VERSION ABOVE&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;Command List:&lt;/span&gt; &lt;span style="font-weight: bold; font-style: italic;"&gt;SEE NEWER VERSION ABOVE&lt;/span&gt;&lt;br /&gt;(Command list must be renamed to known_requests.cpickle for FullSerialDump() function.)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Linux:&lt;/b&gt; How to force the ftdi_sci driver to recognize the BodyMedia Vendor/Product IDs:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;sudo modprobe ftdi_sio vendor=0x11f8 product=0x0007&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Verify that a new '/dev/ttyUSB*' device has been created.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Windows:&lt;/b&gt; You don't need to install an FTDI driver if you already have the&lt;br /&gt;GoWearSense driver installed.  When you plug in the device, you will see a new&lt;br /&gt;COM14 (or similar) port appear which you can use within Python.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Examples of how to use the python library.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;import bodylib as bl&lt;br /&gt;import cPickle&lt;br /&gt;&lt;br /&gt;# Open, query, and close the device&lt;br /&gt;packets=bl.FullSerialDump(serialName="/dev/ttyUSB0")&lt;br /&gt;&lt;br /&gt;# Let me print all the packets sent and received&lt;br /&gt;bl.PrintPacket2(packets)&lt;br /&gt;&lt;br /&gt;# Parse packets and print all data in appropriate format in text tab-delimited format to file&lt;br /&gt;# This is a good human and spreadsheet readable dump of most of the device state.&lt;br /&gt;bl.SaveStructTabDelim(packets, "/tmp/foobar.txt")&lt;br /&gt;&lt;br /&gt;# If filename not specified, outputs to stdout for your inspection&lt;br /&gt;bl.SaveStructTabDelim(packets)&lt;br /&gt;&lt;br /&gt;# I usually save my device dumps in cPickle format for future reference&lt;br /&gt;cPickle.dump(packets,open("mydump.cpickle","w"))&lt;br /&gt;&lt;br /&gt;# Assemble the received data packets into a unified memory buffer&lt;br /&gt;mem=bl.AssembleDataFromPackets(packets)&lt;br /&gt;&lt;br /&gt;# Pretty Print the memory buffer.  We use 46 bytes/line to be periodic with the most common data record&lt;br /&gt;bl.HexPrintMod(mem, 46)&lt;br /&gt;&lt;br /&gt;# Parse memory data structures, including data records&lt;br /&gt;tables=bl.ReadAllStruct(mem)&lt;br /&gt;&lt;br /&gt;# Create image from data table&lt;br /&gt;bl.ToImage(tables.s4).show()&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Protocol Structure&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Serial baud rate must be set to 921,600 bps.&lt;br /&gt;&lt;br /&gt;The protocol is packet based, with packets of length 66 bytes including headers&lt;br /&gt;and sync bytes.&lt;br /&gt;&lt;br /&gt;The computer sends a Request packet ("Req" in my code), to which the device&lt;br /&gt;responds with one or more answer ("Ans") packets.&lt;br /&gt;&lt;br /&gt;All request types expect only a single "Ans" answer packet, except for requests&lt;br /&gt;to read from the data memory.  Data memory requests specify a starting memory&lt;br /&gt;offset and a length, and receive as many 66-byte packets as required in&lt;br /&gt;response.  I call this "Burst" mode in the code.&lt;br /&gt;&lt;br /&gt;All packets have a simple modulus 256 checksum byte.  This is a simple sum and&lt;br /&gt;modulus of all bytes in the packet, excluding sync bytes (leading or tailing&lt;br /&gt;"AB" or "BA").&lt;br /&gt;&lt;br /&gt;The device appears to ignore the checksums sent to it (I don't bother computing&lt;br /&gt;it).  However, the device always gives me correct checksums.&lt;br /&gt;&lt;br /&gt;The packet begins with a leading sync byte 0xAB.  Then a rather elaborate header&lt;br /&gt;almost all of which is unused or invariant (RF protocol related?).  Most&lt;br /&gt;importantly, a "command" byte defines the type of request.  There is also some&lt;br /&gt;form of sequence number byte on Req packets, but not device-generated Ans&lt;br /&gt;packets.  The sequence number appears to be ignored by the device.&lt;br /&gt;&lt;br /&gt;The "command" byte specifies the requestion type, and is the key element of the&lt;br /&gt;header.  Note that in my code, I call this the "Bank" byte, because I initially&lt;br /&gt;thought it was a device selection address.&lt;br /&gt;&lt;br /&gt;After the command and (sequence number if Req), the packet payload contains&lt;br /&gt;command-specific data.&lt;br /&gt;&lt;br /&gt;The command byte to read from the main data memory is 0x82.  The command byte&lt;br /&gt;for the Answer packets from the device is 0x02 (in my code I stip the high bit&lt;br /&gt;from the command/bank for clarity, so you may see 0x02 Requests).&lt;br /&gt;&lt;br /&gt;The payload to read from the main data memory consists of a 4-byte LSB offset&lt;br /&gt;uint32 and a 2-byte LSB length uint16.&lt;br /&gt;&lt;br /&gt;In addition to the block of main data memory, there are a number of other&lt;br /&gt;values which can be queried using other command types.  These usually return&lt;br /&gt;short strings or single binary values.  Examine the packet lists to find some&lt;br /&gt;examples.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Tools&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;"Free Serial Port Monitor" by HDD Software is GREAT - you can use this to snoop&lt;br /&gt;on the virtual serial port under Windows, and export the conversation to a file.&lt;br /&gt;&lt;br /&gt;Under Python I've created a parser for the "Free Serial Port Monitor" text&lt;br /&gt;export of the "RequestView" window.  See bodylib.ParseFile().&lt;br /&gt;&lt;br /&gt;Debug FS is very useful for monitoring USB traffic under Linux.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;sudo mount -t debugfs none_debugs /sys/kernel/debug&lt;br /&gt;cd /sys/kernel/debug/usbmon/&lt;br /&gt;cat 0u&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I use ipython, Python 2.6.2, numpy, PIL python libraries.  If you install on&lt;br /&gt;Windows you'll have to fetch each of them, or comment them out of the bodylib library.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;See Also&lt;/span&gt; http://bodybugghacks.blogspot.com/&lt;br /&gt;(apparently an attack at the Java API level, but the author is not forthcoming on details)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Units of Measure&lt;/b&gt; - from &lt;a href="http://bodybugghacks.blogspot.com/2008/07/code.html?showComment=1225132980000#c1498831675573385775"&gt;http://bodybugghacks.blogspot.com/2008/07/code.html?showComment=1225132980000#c1498831675573385775&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;Useful to determine figure out field structure?&lt;br /&gt;&lt;br /&gt;Accelerometers - The SenseWear® WMS Armband (2-axis) - The SenseWear® WMS Armband Mini (3-axis) Calibrated range is +/- 2.0g&lt;br /&gt;The minimum resolution is 0.01g&lt;br /&gt;Two-standard-deviation accuracy of +/-0.05g (longitudinal axis) and +/-0.06g (transverse &amp;amp; forward axis), up to 1.0g&lt;br /&gt;Two-standard-deviation accuracy of +/-12.0% of expected value otherwise&lt;br /&gt;Heat Flux&lt;br /&gt;Calibrated Range is 0.0 W/m2 to 300.0W/m2&lt;br /&gt;A minimum resolution of 1.0W/m2&lt;br /&gt;Two-standard-deviation of +/-10.0W/m2 at heat flux less than 50.0W/m2&lt;br /&gt;Two-standard-deviation of +/-35.0% of expected value otherwise&lt;br /&gt;Galvanic Skin Response&lt;br /&gt;Calibrated range is 56.0KΩ to 20.0MΩ (50.0 nSiemens – 17.00 uSiemens)&lt;br /&gt;Two-standard-deviation accuracy of +/- 7.0 nSiemens up to 233.34 nSiemens reading&lt;br /&gt;Two-standard-deviation accuracy of +/- 3.0% of expected value otherwise&lt;br /&gt;Skin Temperature&lt;br /&gt;Calibrated range is 20.0ºC to 40.0ºC&lt;br /&gt;A minimum resolution of 0.05ºC&lt;br /&gt;Two-standard deviation accuracy of +/- 0.80°C&lt;br /&gt;Classification of the device, as per 93/42 directives: IIa (rule 10)&lt;br /&gt;Certification procedure : 93/42/EEC, Annex VI, VII.&lt;br /&gt;Transmit Power Class 8 - Less than 10mW output power&lt;br /&gt;Duty Cycle Class 4 - permitted to operate at 100% duty cycle&lt;br /&gt;Receiver Class 3 - Standard reliable SRD communication media&lt;br /&gt;&lt;br /&gt;----&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5942935737519383180-6407516720577693034?l=bodybugglinux.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bodybugglinux.blogspot.com/feeds/6407516720577693034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/body-media-reverse-engineering.html#comment-form' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/6407516720577693034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5942935737519383180/posts/default/6407516720577693034'/><link rel='alternate' type='text/html' href='http://bodybugglinux.blogspot.com/2009/07/body-media-reverse-engineering.html' title=''/><author><name>Finnerty</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_vKgaS5dCF3g/SlIqAqql5oI/AAAAAAAAAAY/Ai-3HTOZr_w/s72-c/z706a-full-serial-one_night.png' height='72' width='72'/><thr:total>15</thr:total></entry></feed>
