With the arrival of the new year many people are recommitting themselves to their health. I've been physically active all year—it's a start—but there's more I can do to help myself and others: exploring liberation of medical monitoring devices, with a focus on wireless blood pressure monitors.
Why blood pressure? Does wireless actually matter? Blood pressure (the systolic/diastolic “120-over-80” numbers) is readily measurable but the underlying cause of elevated BP is poorly understood by physicians (“indeterminate cause”) in roughly 80% of cases. Hypertension can be controlled with medication along with changes to diet and exercise but, depending on the case, maintaining consistently-normal BP without large peaks or dropouts can be a challenge. And there's related conditions including pre-eclampsia and POTS that also warrant comprehensive testing and monitoring.
Blood pressure also fluctuates over the course of a given day so the best approach to understanding what's going on is to take continuous readings 24/7. Achieving such ‘ambulatory’ monitoring typically involves having a pneumatic tube and other wires dangling around as you go about daily activities, which, needless to say, nobody really wants.
There are, however, a few wireless BP cuffs on the market that operate over Bluetooth that can be worn discretely, continuously, and have requisite FDA approval. The features offered between the various on-market devices are more or less the same so I purchased an iHealth BP5 in hopes of converting it into an ambulatory monitor.
Results were mixed! Using a dex2jar in combination with JD-GUI on the Android iHealth app binary I was able to view and navigate my way through reconstructed source code. There was nothing especially remarkable in the app other than extraction of various command codes sent as byte arrays to control the device. A prototype Python script follows – it appears to connect properly to the BP5 but no return data is sent, probably because I've bungled the byte array sequencing. Intercepting and comparing the live traffic stream to the reconstructed source code using a rooted Android phone would be the next reverse engineering step and honestly doesn't appear to be that involved for a skilled programmer.
The internal BP5 hardware, however, appears to be inaccessible to the extent that it would be impractical to alter in any meaningful way other than cutting out the mainboard entirely and replacing it with DIY control circuitry while keeping the existing battery and air pumps. (Which doesn't seem all that impossible?)
There is unfortunately a medical risk to this type of work: if a code bug or other hardware error occurs while a wearer is sleeping there's risk of continued over-inflation, effectively turning the cuff into a tourniquet. To the best of my knowledge there's nothing that precludes the FDA from approving a libre-software/open-hardware design; in contrast, the FDA currently relies on self-certification by device manufacturers on code performance and responsibility in the approval process.1 Creating or altering devices on your own is not a great situation to be in, really, but maybe at least you stand a greater chance of successfully suing yourself (vs. large corporations) if things go awry.1
So, um, Happy 2016!
1. Sandler, Karen; Lysandra Ohrstrom; Laura Moy; Robert McVay. "Killed by Code: Software Transparency in Implantable Medical Devices." Software Freedom Law Center, 21-July-2010.
Photo: Anatomically-corrected figure adapted from: Blizard, William. "A Lecture, Containing Plain Descriptions of The Situation of The Large BLOOD-VESSELS of The Extremities; The Inſtrument Called TOURNIQUET; and The Methods of Making Effectual Pressure on The Arteries, In Cafes of Dangerous Effufions of Blood From Wounds, &c." J. W. Galabin, London, 1786, pp. 12-13 (foldout).
Related: Despite Samsung's yet-unfulfilled assertion of being an “open platform” their Simband monitor is totally worth keeping tabs on. And wireless EKG/ECGs are on their way too.
ihealthBP5-pressure.py #!/usr/bin/env python import serial import string import time import bluetooth def connect(): while(True): try: bpSocket = bluetoothBluetoothSocket(bluetoothRFCOMM) # BP5 has an open serial connection on RFCOMM port 6 bpSocketconnect(('8C:DE:52:12:14:B5', 6)) # Replace w/ BT address break except bluetoothbtcommonBluetoothError as error: bpSocketclose() print "Could not connect: ", error, "; Retrying in 5s..." timesleep(5) return bpSocket bpSocket = connect() while(True): try: # Byte arrays extracted from iHealth Android app: # Ask state = -80 4 0 1 -87 -23 -109 ≈ 5004000157176D # Connection = -80 4 0 1 -87 -15 -101 ≈ 50040001570F65 # Start measure = -95 49 0 0 75 0 41 0 27 30 ≈ 5F3100004B0029001B1E # interrupt measure = -95 55 0 0 0 # Get battery level = -95 32 0 0 0 # Angleno = -95 58 85 0 0 # Angleyes = -95 58 0 0 0 # getIdps (pressure sensor id?)= -95 -15 # packageData = -80 4 0 commandSeqNum(0-255 ring) -86 payload \\ # 0+commandSeqNum+(-86)+payload bpSocketsend('something') print("Data sent, starting receive") print bpSocketrecv(1024) except bluetoothbtcommonBluetoothError as error: print "Caught BluetoothError: ", error timesleep(5) bpSocket = connect() pass bpSocketclose()













