Open kylemcdonald opened 10 years ago
I recall reading somewhere that the watch uses a combination of skin temperature and air temperature. How about looking at data with cycles in which the watch is cooled every other 5 minutes while the watch is being worn?
very clever @bennettbrowniowa! along those lines, the perspiration could probably be simulated with pressure on conductive foam, and the acceleration might be the easiest to automate...
Well thanks @kylemcdonald. Great generalization of the solution to RE the other sensors' encoding. Note the end user agrees in the Basis EULA not to reverse engineer or otherwise create software compatible with the hardware. So there might be some advantage to not being the end user when performing such experiments. Perhaps one could give one's watch to one's friend before doing any such work.
Is there a hex dump that a non-Basis owner could access? I'd love to take a look, but I don't have a band of my own.
@bennettbrowniowa another good point :) maybe basis can help out if they see there's demand, and no one will be tempted to break the EULA.
@notjosh there is a dump in this repo at https://github.com/beaugunderson/re-basis/tree/master/packets
one more potential place to look for reversing is the libBasisCore.dylib that comes with the osx sync app. it could be sending the raw data to the server instead of decoding it, but there's some evidence to the contrary:
$ strings libBasisCore.dylib | grep pulse
pulseDataSeries
Device has %1 bytes of pulse data available
Requesting number of containers of pulse data from device
Requesting pulseData container %1 of %2 from device
ReadPulseDataProcess container %1 has no pulse data in it!
Finished reading %1 bytes of pulse data from device
Requesting number of bytes of pulse data from device
From a quick look in Hopper, the type PulseDataSeries
does all of the transforms/management of data (incl a nice rawData()
call, and disk persistence methods), while the SyncPulseDataProcess
/ReadPulseDataProcess
classes might be interesting for exactly what the data structures are when they come across the wire.
Pulse
is the only prefix for *DataSeries
, so I think all data points are squeezed into that.
It seems the PulseDataSeries
object is simply written as XML with the data base64 encoded and shipped off to the server without ever actually deserialising the data into a useful structure. This seems to be useless to us.
However, there's a DevicePacket
type which seems to be used to read directly from the device which seems potentially more promising. It has type
, payloadBytes
and so on. I'm not sure if these map to actually useful data types, or if they're just part of the transport protocol.
Okay, back to the data. I've reformatted the output to be relative to the first timestamp, and each value is on one line: https://gist.github.com/notjosh/923c71cb9b4de2fb6843
The 0x29
events are every 60 seconds like, er, clockwork. I'd say they're discrete values (steps, beats, etc).
The 0x0c
and 0x2b
events happen at irregular intervals. 0x0c
always has data attached, while 0x2b
only sometimes does (and when it does, it seems to have repeating values).
Next step would be to add a vis layer on top of this, so it's easier to spot patterns.
some thoughts from looking briefly at the hex dump...
it feels like it's divided into minutes of data, with the bunch 00s signifying the end of a minute's worth of data (maybe it's padding). that would be around ~400-500 bytes per minute. which means there might be raw data in there! i.e., the heart rate might be post-processed by their servers and not on the device itself...
the sensors on the watch are:
uint16_t
representing inter-beat millisecond durations, so around 60bpm x 2bytes/beat = 120 bytesuint16_t
), but hopefully sending raw data. naive approach is 3xint16_t
per second but that's too much data... hard to say for this one.overall, 400-500 bytes per minute would be enough to store raw heart rate, temperature, perspiration, and steps. or raw acceleration, heart rate, and maybe perspiration with an averaged temperature.