Humon Hex Bluetooth Protocol

AKA Reverse Engineering the Humon Hex Muscle Oxygenation Sensor’s Bluetooth Protocol

Athletes (or I suppose more generally mammals) have muscles. Muscles consume oxygen when they do work and output carbon dioxide into the host system’s blood. If insufficient oxygen is present, the muscle starts consuming glycogen, which is a somewhat finite resource and results in lactate as a byproduct of the consumption. Work done through the consumption of oxygen is aerobic work and work done with reduced oxygen is anaerobic work.

The transition between these two states is caused by a balance between a muscle’s ability to consume oxygen and the host system’s ability to supply oxygen to that muscle. Generally heart rate is the most-easily acquired indicator of whether or not the host system is struggling to supply enough oxygen to its peripherals, but heart rate has high hysteresis and varies per person, amongst other issues. As a result, Muscle Oxygenation “moxy” sensors are useful because they’re precise, provide absolute readings and they’re fast. They are analogous to reading a car’s engine RPM directly vs trying to figure out the RPM by looking at the water temperature.

Unfortunately, moxy sensors have historically been very pricey with units like the Moxy and BSX Insight in the range of several hundred dollars. A coach told me recently that athletes generally go to a lab to be measured (?!). A new company on the block, called Humon, has released a product called the Hex and the Hex does moxy. The Hex is less than half the price of its competitors. It’s also small and modern, with wireless charging. It’s generally a very very cool device.

A Humon Hex
The underside of a Humon Hex

The Hex transmits data on both ANT+ and Bluetooth Low Energy (BLE/Smart). The ANT+ variant of the data is standardised and easy to acquire if you have the correct radio to do it. The BLE variant of the data unfortunately is not standardised and Humon declined my request for the protocol specification… this guide is both to help others and a reminder to myself how the device works and more generally how to access BLE sensors on Linux.

I want a small logging device for my bicycle 😉 but I don’t want something that has a display because I don’t want to be distracted. I just want the data for later review, so the logging device should ideally be small enough to be tucked away in or under the bicycle’s seat. In order to achieve this I figured I’d build a logging device out of THE AMAZING Raspberry Pi Zero W. The Zero W has a built-in wifi and bluetooth radio but said radio doesn’t support ANT+ and adding ANT+ would increase the size of the device, look crap and use more battery power. Bluetooth Low Energy is therefore the best option.

Everything that follows should work on any device running Linux with BLE support and running a recent version of Bluez (5.40 up).

Start by putting the Hex on you, press the power button once to start it up. The LED will rapidly fly through some colours and then go red. Double-push the button, the LED will go blue and after a while, it’ll go green. Green seems to mean the device is both calibrated and transmitting.

Get yourself a screen/byobu session : screen
Run bluetoothctl
In the interactive console :
power on – this powers on the BLE radio
scan on – this begins scanning for hardware
Wait for the device to show up as a detected device.

The hex will show up as “Hex XXXX”. This next step may not entirely be necessary :
In the terminal enter :
scan off – to stop the scan, we know what devices are present now
agent on – this is to enable pairing authentication
default-agent – this exchanges some keys but doesn’t ask for input
pair 00:00:00:00:00 – replace the zeroes with the mac address of your Hex

The device should now be paired.
connect 00:00:00:00:00 – connects to the device
info – if you want some cool info:
Name: Hex A2C6 Alias: Hex A2C6 Paired: yes Trusted: no Blocked: no Connected: yes LegacyPairing: no UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb) UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb) UUID: Device Information (0000180a-0000-1000-8000-00805f9b34fb) UUID: Battery Service (0000180f-0000-1000-8000-00805f9b34fb) UUID: Vendor specific (0000f00d-1212-efde-1523-785fef13d123)

This next part requires a “characteristc”. I’m going to demonstrate the 0000deef-1212-efde-1523-785fef13d123 characteristic, but the others I’ve looked at are listed at the bottom of this page. the deef characteristic is listed in the Humon Hex APK source code as HUMON_CALCULATED_DATA_CHARACTERISTIC.

In the terminal : select-attribute /org/bluez/hci0/dev_F5_63_A2_C6_8D_8D/service001a/char0024
and then read. The result will look like this :

And yes, I gave some thought to whether or now I should leave the MAC addresses in… it’s a moxy sensor 😀

The resulting values count as 16 bytes in total, which seems like… a float maybe ? I couldn’t figure it out easily, so I grabbed a copy of the Humon Hex Android APK and decompiled it. It took a lot of digging as the app is a React Native application with most of the logic minified into a horrible blob of Javascript… BUT grep exists, so yay. After much grep’ping I came across this :

apk/assets/shell-app.bundle:__d(function(E,R,_,A,T){Object.defineProperty(A,"__esModule",{value:!0});var C='0000-1000-8000-00805f9b34fb';A.BleUuid={DFU_SERVICE:"0000FE59-"+C,HUMON_DEVICE_INFORMATION_SERVICE:"0000180a-"+C,HUMON_MODEL_CHARACTERISTIC:"00002a24-"+C,HUMON_SERIAL_CHARACTERISTIC:"00002a25-"+C,HUMON_FIRMWARE_VERSION_CHARACTERISTIC:"00002a26-"+C,HUMON_HARDWARE_VERSION_CHARACTERISTIC:"00002a27-"+C,HUMON_SOFTWARE_VERSION_CHARACTERISTIC:"00002a28-"+C,HUMON_MANUFACTURER_CHARACTERISTIC:"00002a29-"+C,HUMON_DATA_SERVICE:"0000f00d-1212-efde-1523-785fef13d123",HUMON_RAW_DATA_CHARACTERISTIC:"0000beef-1212-efde-1523-785fef13d123",HUMON_CALCULATED_DATA_CHARACTERISTIC:"0000deef-1212-efde-1523-785fef13d123",HUMON_COMMAND_CHARACTERISTIC:"0000abcd-1212-efde-1523-785fef13d123",HUMON_STATE_CHARACTERISTIC:"0000abc0-1212-efde-1523-785fef13d123",HUMON_BATTERY_SERVICE:"0000180f-"+C,HUMON_BATTERY_CHARACTERISTIC:"00002a19-"+C,HEART_RATE_SERVICE:"0000180d-

This told me what the characteristics on the device do. EVEN MOARRRRRR grep’ping later I found some of the code the app uses to reconstruct the data from the device. This is the cleaned up version :

groupNBytes = function(bytesArray, sizeOfGroup) { var n = Object.keys(bytesArray).map(function(sizeOfGroup) { return bytesArray[sizeOfGroup] }); return n.reduce(function(bytesArray, t, a) { return a % sizeOfGroup == 0 && bytesArray.push(n.slice(a, a + sizeOfGroup)), bytesArray }, []) }

byteArrayToFloat = function(r) { var e = r[3] << 24 | r[2] << 16 | r[1] << 8 | r[0], n = new ArrayBuffer(4); return new Int32Array(n)[0] = e, new Float32Array(n)[0] }

Take the values from the terminal, build an array with them and then curry them together to get something cool :
[0] 37.44892501831055
[1] 68.58602905273438
[2] 0.6468204259872437
[3] 3

In this case [2] very closely matches the value my Wahoo ElMENT Bolt showed when I executed the read command in the terminal (multiplied by 100x).

You can stream these values by entering notify on once the attribute has been selected.

That’s about it for now, the next step is building a logger.

P.S. The battery level can be found on this characteristic :
select-attribute /org/bluez/hci0/dev_F5_63_A2_C6_8D_8D/service000b/char000c
0002a19-0000-1000-8000-00805f9b34fb

Update: 12 February 2020 : Humon shuts down and leaves users stranded with old device firmware

Humon sent an email (quoted below), essentially saying they’ve shut down (not shutting down but rather shut down). With no advance notice they took all their public facing services down including the backing services for their web, Android and iOS apps. This also includes the resources used to do firmware updates.

Many Humon Hexes have subsequently hit the market and been snapped up (they’re awesome devices). Unfortunately many of these devices have old firmware on them. I recently received one such device and it *was* unusable without a firmware update.

Humon’s servers are down but fortunately their iOS app, which has also been removed from the App Store, caches firmware update files. As a result I now have a second Hex with updated firmware on it. This information has been relayed to another user who has successfully extracted the firmware update/DFU zip file from his iOS device.

The letter:

Dear Humon Athlete,

I’m reaching out with an important update about the future of Humon.

We started Humon in 2015 with the mission of empowering people with the body insights that they need to become their better selves. After years of research and development we released our first product, the Hex, in 2018. In the years that followed we were lucky to count amongst our customers some of the most talented athletes, professional teams, gyms, medical centers and academic researchers in the world. These people were able to leverage the Hex and Humon's software and algorithms to improve their performance, reduce injury and push the world of research forward. To this day we remain convinced that muscle oxygen is the best metric of exertion that exists.

That said, it is still a new and somewhat misunderstood metric that requires sustained levels of market education to exist. Sadly, Humon will no longer be able to further develop this technology and make muscle oxygen available and understandable to the world.

As of February 13th, 2020 we regrettably have no choice but to shut down most of the Humon service. Our iOS and Android mobile application will no longer be available for new downloads on the Apple App Store and Google Play Store, our cloud backend and web platform will be shut down, and our support channels closed. That said, you’ll still continue to be able to use your Hex with your Garmin data field that will remain available to download on the Connect IQ Store.

We understand that this comes as a major disappointment to those of you who do not use Garmin products but it is the necessary path forward today. It is also why we stopped selling the Hex in early January, as we began to realize that this would be the case.

This is not an uncommon story in the world of startups, but it is also how innovations can flourish and end up benefiting millions in the long run. On behalf of the Humon team we wanted to thank you all for you trust, support, and help in bringing this product to market. Together, we’ve written a chapter in the history of muscle oxygen.

Best,
Humon

Leave a Reply