tobiasisenberg / OxiVis

This project uses a bluetooth-enabled pulse oximeter, an ESP32 microcontroller board, and a Linux server to capture a longer trace of the heart rate (in beats per minute, BPM), oxygen saturation level (SpO2) in percent, and photoplethysmograph (PPG) values and to visualize them. The intention is to capture a whole night's worth of data, and produce a PDF with the graphs of the values over time.
GNU General Public License v3.0
16 stars 3 forks source link

Adding support for Contec CMS50D-BT #2

Closed jokubasver closed 2 years ago

jokubasver commented 3 years ago

I am trying to adapt your code to support this Contec CMS50D-BT oximeter. But I am having issues.

You can see the changelog here: https://github.com/jokubasver/OxiVis/commit/35c159698ef362c76972c0efaa8cdb7894d65c26

Thanks to Android Bluetooth logging and Wireshark, I was able to read data from it - the main thing it needed was to send 0x9b011c to 0000ff01-0000-1000-8000-00805f9b34fb characteristics UUID for the other characteristics UUID (0000ff02-0000-1000-8000-00805f9b34fb) to spit out data.

0x9b011c needs to be sent often, as otherwise the meter only sends data for less than a minute and then stops, so I had to move the writeValue command into the void loop.

Also, pRemoteCharacteristicOximeter->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true); didn't work in my case, so I did it a bit differently, but I am not sure if I did it properly.

One issue I was having is an "Incorrect packet length" error on ESP serial. Not sure if this is a correct fix, but since the hex length in my case is 8:

Notify callback for characteristic 0000ff02-0000-1000-8000-00805f9b34fb of data length 8 data (HEX): EB 1 4 40 63 7F 0 12

I changed int packetCount to equel length / 2;.

With this change, the error goes away and I am able to see data via serial print commands, but it takes around 10 minutes for the data to be saved to csv, which seems too long. The data also has some garbage in the csv file too, so I'm not sure what's going on. Maybe there is an issue with the buffer while using this Contec meter.

I'm attaching an example csv file. oximeter-20211008-203743-12079.csv

Some data from MQTT Explorer:

data = ;�Ec����&LzEc����&R�Dc����&^gBc����&bOBc����&fBAc����&jAc����&n Ac����&u�@c����&~z?c����&�x@c����&�@c����&�Q@c����&��@c����&�dAc����&�4Ac����&�Ac����&�Bb����&��Bb����&��Bb����&��Cb����&��Eb����&��Fb����&�GFb����&��Gc����&��Hc����&�Ic����&��Ic����&Hc����&F�Gc����&MzGc����&URGc����&aeGc����&eMGc����&qGc����&x�Gc����&��Gc����&��Fc����&�.Fc����&�kFc����&��Fc����&�Fc����&�ZFc����&�yFc����&��Fc����&�Fc����&�jEc����&�FCc����&�zCc����& �Cc����&ECc����&{Dc����&KDc����&)gDc����&-�Dc����&REc����&g�Ec����&k�Ec����&o�Ec����&s�Ec����&w�Ec����&{pEc����&YEc����&�Ec����&�[Ec����&�8Ec����&��Dc����&��Dc����&�nDc����&ˆDc����&��Dc����&��Dc����&��Dc����&լEc����&ٔEc����&�NEc����&�Ec����&�PEc����&� Ec����&�Ec����& �Ec����&$1Bc����&,Ac����&3�@c����&<@c����&Lw@c����&W�@c����&]D@c����&f�@c����&j�@c����&n�@c����&s@c����&z�@c����&5@c����&�>@c����&�%@c����&�D@c����&��@c����&��?c����&��?c����&��?c����&�~@c����&�f@c����&�NAc����&�7Ac����&��Ac����&�EBc����&� Cc����&�Dc����&�JEc����&�Ec����&��Ec����&Ec����& rEc����&ZEc����&�Ec����&wEc����&^Ec����&#FEc����&'/Ec����&.�Fc����&6�Ic����&:�Jc����&>� Nc����&B�!Oc����&F�#Qc����&R'$Rc����&Y�$Rc����&a�$Rc����&e�$Rc����&i�$Rc����&m$Rc����&yD$Rc����&}$Rc����&�l$Rc����&��$Rc����&�p$Rc����&��$Rc����&�v#Qc����&�{#Qc����&�L!Oc����&�Lc����&��Jc����&ǼIc����&�wGc����&�\Gc����&�,Fc����&��Fc����&�HFc����&��Fc����&�Gc����&�4Gc����&Fc����&:Fc����&@Ec����&tEc����&*,Fc����&1�Fc����&9hGc����&A�Gc����&L�Fc����&RFc����&Y Fc����&\�Fc����&�Fc����&d�Fc����&h�Fb����&l�Fc����&teFc����&xMFc����&|5Ec����&�Ec����&�Ec����&��Ec����&��Ec����&��Ec����&�]Dc����&�EDc����&�.Dc����&�Ec����&��Ec����&��Ec����&�2Ec����&�Ec����&��Ec����&�7Ec����&ҊEc����&רDc����&�Ec����&��Ec����&��Ec����&��Ec����&��Ec����&��Ec����& Ec����&uEc����&!Ec����&(�Ec����&,�Ec����&0�Ec����&4�Fc����&8~Gc����&@OHb����&D8Hb����&HHb����&L�Gb����&W�Gb����&]BGb����&cwFb����&g_Ec����&kGEc����&o/Dc����&sDc����&wEc����&��Ec����&�Ec����&��Ec����&�8Ec����&��Fc����&��Fc����&�sGc����&�[Hc����&�+Ic����&��Hc����&��Jc����&ńJc����&�TJc����&�Jc����&�Ic����&�~Ic����&�dIc����&��Ib����&�Hb����&jHb����&PGb����& 9Fb����&�Fb����&�Fb����&'�Gc����&/`Gc����&71Gc����&;Gc����&B�Fc����&G6Fc����&OGc����&R�Fc����&W�Fc����&^�Ec����&b�Ec����&fuEc����&nEEc����&�UFc����&�tFc����&��Hb����&��Ib����&��Ib����&��Ib����&ȁIb����&�uIb����&�"Ib����&�6Ic����&��Jc����&�Jc����&�zJc����&�cIc����&�JIc����&�2Ic����&Gc����& �Fc����&AEc����&�Cc����& Bc����&&DBc�?��$�&�Bc����&.vAc����&2^Ac����&6FAc����&:/Ac����&>Ac����&A�Ac����&E�Bc����&I�Bc����&M�Bc����&RBc����&YoBc����&]WCc����&a?Cc����&e'Dc����&iDc����&l�Dc����&p�Ec����&t�Dc����&x�Cc����&|�Cc����&�Bc����&�sBc����&�OBc����&��Bc����&��Bc����&��Bc����&�<Cc����&��Cc����&��Cc����&��Cc����&��Cc����&��Cc����&�dCc����&�KCc����&�5Cc����&�Cc����&�Bc����&��Bc����&צAc����&ޤ@c����&�@c����&�}@c����&�x?c����&�H?c����& ?c����&
?c����& �@c����& sAc����& !pBc����& %�Cc����& 1Dc����& 8�Dc����& =,Dc����& D�Cc����& L�Cc����& P�Cc����& T�Cc����& X�Cc����& ]?Cc����& d=Cc����& h%Dc����& l Dc����& o�Dc����& w�Dc����& {�Eb����& �Fb����& �}Fb����& �eFb����& �MFb����& ��Fb����& �Fc����& ��Ec����& � Ec����& ��Dc����& ��Dc����& ��Dc����& �aDc����& �IDc����& �gDc����& ��Dc����& �BDc����& �Dc����& ��Dc����& �Cc����& �Cc����& �Cc����& �Cc����& �Bc����& �Bc����& �Bc����& %�Bc����& 4Cc����& 8ZCc����& ?�Cc����& OhDc����& SNDc����& W�Dc����& _Ec����& cREc����& hsEb����& r�Ec����& bpm = 63 spo2 = 99

I am also not quite sure yet where the PPG data is. It could be the last byte of that hex stream, but I also found that sending 0x9b001b gives a another stream of data, which might be the PPG stream.

Any help would be greatly appreciated.

jokubasver commented 3 years ago

Git didn't commit a few changes to my fork, so here they are: https://github.com/jokubasver/OxiVis/commit/cf6bcb0f298ddf9399ea905089665737574084d6

jokubasver commented 3 years ago

I think I found all the values.

I'll repeat myself to be clear: Writing 0x9b011c to characteristics UUID 0000ff01-0000-1000-8000-00805f9b34fb turns on data streaming/notifications. Data is streamed on 0000ff02-0000-1000-8000-00805f9b34fb characteristics UUID.

There are two separate hex strings:

---8 byte stream - SpO2, BPM--- Hex: eb 01 04 53 63 7f 00 25 Dec: 235 1 4 83 99 127 0 37

1st byte - 235 (Constant) 2nd byte - 1 (Identifier that the byte stream is for SpO2 and BPM) 3rd byte - 4/6 (Probably a finger detector - 04 when no finger, 06 when finger is in device) 4th byte - 83 (BPM) 5th byte - 99 (SpO2) 6th byte - 127 (Doesn't change) 7th byte - 0 (Doesn't change) 8th byte - 37 (Unknown, seems to be BPM but values are shifted down by 46 units)

8 byte stream

---6 byte stream (PPG, bar graph)--- Hex: eb 00 03 48 09 3f Dec: 235 0 3 72 9 63 Hex: eb 00 43 3c 07 71 Dec: 235 0 67 60 7 113

1st byte - 235 (Constant) 2nd byte - 0 (Identifier that the byte stream is for PPG) 3rd byte - PPG peak detector? (When PPG is at the highest peak, this 3rd byte goes high) 4th byte - PPG 5th byte - Bar graph? (Basically looks like a low resolution PPG when graphed to a line chart) 6th byte - PPG, but with exaggerated peaks and different scale

6 byte stream1 6 byte stream2

Graphs were made with extracted data from Android Bluetooth logs and Wireshark.

Some data points are missing from my own data extraction to Google Sheets, as sometimes the hex string arrives two or three times in a row (for example instead ofeb000348093f it's sometimes eb000348093feb000348093f)

Now I need to see what data is streamed when sending 0x9b001binstead of 0x9b011c

tobiasisenberg commented 3 years ago

Hi @jokubasver! Great that you try to make this work also for another device. I vaguely remember that there was also a low-res PPG value in my data. But since I do not have this specific oximeter I am afraid I cannot help much, but if you have a pull request that makes it possible to run the code on either device I would love to see it. Great work!

tobiasisenberg commented 2 years ago

Closing issue.