emogenet / accuchek

C++ code to read data from a Roche Accu-Chek Guide blood glucose monitor over bare metal USB
The Unlicense
27 stars 4 forks source link

Support for more (similar) devices. #1

Open DaveDavenport opened 1 year ago

DaveDavenport commented 1 year ago

The device with productId 0x21d7 (2 higher) also works with this code. Might be an idea to add an option to add for multiple productIds.

alex-t-grecu commented 1 year ago

With small parsing changes I can report the code will work also with productId 0x21cc which is one of the first glucometer models from the same company. Indeed it would be great to integrate support for as many devices as possible. I bought the device some time ago (at least 5 years) and it still works pretty fine, but unfortunately I could not extract the measurements before because it did not come with the software... Please, let me know if you're willing to continue development on the code.

emogenet commented 1 year ago

@DaveDavenport : e71afe3ce887b71ec1bcb0877ebb474ae31db842 should do what you want. NB: code currently makes no attempt to check if devices you add to config.txt are actually compatible.

emogenet commented 1 year ago

@alex-t-grecu would be very happy to add support for more devices. Please send me your "small parsing changes" so I can integrate them.

alex-t-grecu commented 1 year ago

Hi @emogenet , the patched version of the code which I just used to read again all values from my device is in the forked version of the main.cpp. I also modified config.txt to include the device ID. Here are some further details about the changes...

lsusb details:

Bus 002 Device 047: ID 173a:21cc
Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 8 idVendor 0x173a idProduct 0x21cc bcdDevice 0.06 iManufacturer 1 Roche Diagnostics GmbH iProduct 2 Accu-Chek Active USB iSerial 3 000000000 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 61 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 4 Accu-Chek Active USB bmAttributes 0x80 (Bus Powered) MaxPower 100mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 15 bInterfaceSubClass 0 bInterfaceProtocol 0 iInterface 6 Accu-Chek Active USB UNRECOGNIZED: 04 20 02 00 UNRECOGNIZED: 06 30 00 01 11 10 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x04 EP 4 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 255 DEVICE CLASS: 04 21 01 08 UNRECOGNIZED: 04 22 cc dd Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x84 EP 4 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 255 DEVICE CLASS: 04 21 01 08 UNRECOGNIZED: 07 22 ab cd ef 01 02 Device Status: 0x0000 (Bus Powered )

Some extracted data/measurements for a previous user with type-II diabetes (I cannot understand yet what the "status" field represents, but it should include information about the conditions when measurement is done e.g. pre/post-prandial. I can only keep an eye on values as I'm doing more measurements)

{ "id":   459, "epoch": 1437928140, "timestamp":"2015/07/26 18:29", "mg/dL":121, "mmol/L":  6.722222, "status": "0x55" },
{ "id":   460, "epoch": 1437975240, "timestamp":"2015/07/27 07:34", "mg/dL":318, "mmol/L": 17.666667, "status": "0x41" },
{ "id":   461, "epoch": 1438012260, "timestamp":"2015/07/27 17:51", "mg/dL":139, "mmol/L":  7.722222, "status": "0x15" },
{ "id":   462, "epoch": 1438108020, "timestamp":"2015/07/28 20:27", "mg/dL":150, "mmol/L":  8.333333, "status": "0x29" },
{ "id":   463, "epoch": 1438196820, "timestamp":"2015/07/29 21:07", "mg/dL":126, "mmol/L":  7.000000, "status": "0x47" },
{ "id":   464, "epoch": 1438290240, "timestamp":"2015/07/30 23:04", "mg/dL":104, "mmol/L":  5.777778, "status": "0x49" },
{ "id":   465, "epoch": 1438365540, "timestamp":"2015/07/31 19:59", "mg/dL":157, "mmol/L":  8.722222, "status": "0x26" },
HorusPi commented 1 year ago

Added config for Roche ACCU-CHEK Guide Me, plus instructions for raspberry pi debian installation of the correct libraries. PR submitted.

trholding commented 4 months ago

Okay I tried adding usb ID of Accu-Check Active in config.txt and I got a segfault.

config.txt entry:

vendor_0x173a_device_0x21cc 1 # Roche Accu-Chek Active USB

lsusb info:

Bus 001 Device 015: ID 173a:21cc Roche Accu-Chek Active USB
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 [unknown]
  bDeviceSubClass         0 [unknown]
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x173a Roche
  idProduct          0x21cc Accu-Chek Active USB
  bcdDevice            0.06
  iManufacturer           1 Roche Diagnostics GmbH
  iProduct                2 Accu-Chek Active USB
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0032
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        15 Personal Healthcare
      bInterfaceSubClass      0 [unknown]
      bInterfaceProtocol      0 
      iInterface              0 
      ** UNRECOGNIZED:  04 20 02 00
      ** UNRECOGNIZED:  06 30 00 01 11 10
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
        DEVICE CLASS:  04 21 01 08
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
        DEVICE CLASS:  04 21 01 08
Device Status:     0x0000
  (Bus Powered)

Dump:

./accuchek 
  0.543809(   +0.000000):nfo: 88377CB9:T 1:D  0:L1612:main.cpp:main: starting
  0.543876(   +0.000067):nfo: 88377CB9:T 1:D  0:L1534:main.cpp:openLibUSB: opening libusb
  0.549155(   +0.005279):nfo: 88377CB9:T 1:D  0:L1566:main.cpp:openLibUSB: libusb opened OK
  0.549209(   +0.000054):nfo: 88377CB9:T 1:D  0:L1477:main.cpp:findAndOperateAccuChek: getting list of all USB devices in system from libusb
  0.549240(   +0.000031):nfo: 88377CB9:T 1:D  0:L1479:main.cpp:findAndOperateAccuChek: found 9 USB devices in system
  0.549260(   +0.000020):nfo: 88377CB9:T 1:D  0:L1483:main.cpp:findAndOperateAccuChek: searching for valid accuchek devices
  0.549292(   +0.000032):nfo: 88377CB9:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 0 is an accuchek
  0.549321(   +0.000029):nfo: 88377CB9:T 1:D  0:L1327:main.cpp:addDeviceIfAccuChek: not a match, too many interfaces to be an accuchek
  0.549341(   +0.000020):nfo: 88377CB9:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 1 is an accuchek
  0.549361(   +0.000020):nfo: 88377CB9:T 1:D  0:L1327:main.cpp:addDeviceIfAccuChek: not a match, too many interfaces to be an accuchek
  0.549380(   +0.000019):nfo: 88377CB9:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 2 is an accuchek
  0.549398(   +0.000018):nfo: 88377CB9:T 1:D  0:L1379:main.cpp:addDeviceIfAccuChek: found a usb device that looks good, checking further by opening it
  0.550867(   +0.001469):nfo: 88377CB9:T 1:D  0:L1442:main.cpp:addDeviceIfAccuChek: ========> found a matching USB device
  0.550938(   +0.000071):nfo: 88377CB9:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 3 is an accuchek
  0.550960(   +0.000022):nfo: 88377CB9:T 1:D  0:L1345:main.cpp:addDeviceIfAccuChek: not a match, too many endpoints to be an accuchek
  0.550979(   +0.000019):nfo: 88377CB9:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 4 is an accuchek
  0.550998(   +0.000019):nfo: 88377CB9:T 1:D  0:L1345:main.cpp:addDeviceIfAccuChek: not a match, too many endpoints to be an accuchek
  0.551014(   +0.000016):nfo: 88377CB9:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 5 is an accuchek
  0.551033(   +0.000019):nfo: 88377CB9:T 1:D  0:L1345:main.cpp:addDeviceIfAccuChek: not a match, too many endpoints to be an accuchek
  0.551050(   +0.000017):nfo: 88377CB9:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 6 is an accuchek
  0.551068(   +0.000018):nfo: 88377CB9:T 1:D  0:L1327:main.cpp:addDeviceIfAccuChek: not a match, too many interfaces to be an accuchek
  0.551085(   +0.000017):nfo: 88377CB9:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 7 is an accuchek
  0.551103(   +0.000018):nfo: 88377CB9:T 1:D  0:L1327:main.cpp:addDeviceIfAccuChek: not a match, too many interfaces to be an accuchek
  0.551121(   +0.000018):nfo: 88377CB9:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 8 is an accuchek
  0.551139(   +0.000018):nfo: 88377CB9:T 1:D  0:L1345:main.cpp:addDeviceIfAccuChek: not a match, too many endpoints to be an accuchek
  0.551157(   +0.000018):nfo: 88377CB9:T 1:D  0:L1499:main.cpp:findAndOperateAccuChek: found altogether 1 accuchek devices
  0.551179(   +0.000022):nfo: 88377CB9:T 1:D  0:L 420:main.cpp:show: selecting accuchek device #0::

    bus number:    1
    dev address:   15
    cfg value:     1
    alt setting:   0
    alt interface number: 0
    vendor:        (0x173a) Roche Diagnostics GmbH
    product:       (0x21cc) Accu-Chek Active USB
    sndEndPnt:     1
    rcvEndPnt:     130

  0.553361(   +0.002182):nfo: 88377CB9:T 1:D  0:L 641:main.cpp:operateDevice: using device snd endpoint = 1
  0.553423(   +0.000062):nfo: 88377CB9:T 1:D  0:L 642:main.cpp:operateDevice: using device rcv endpoint = 130

  0.553444(   +0.000021):nfo: 88377CB9:T 1:D  0:L 761:main.cpp:operateDevice: phase 1: initial control transfer in
[root@linux accuchek]# ./accuchek 
  0.920126(   +0.000000):nfo: 1C42A0AC:T 1:D  0:L1612:main.cpp:main: starting
  0.920194(   +0.000068):nfo: 1C42A0AC:T 1:D  0:L1534:main.cpp:openLibUSB: opening libusb
  0.925410(   +0.005216):nfo: 1C42A0AC:T 1:D  0:L1566:main.cpp:openLibUSB: libusb opened OK
  0.925484(   +0.000074):nfo: 1C42A0AC:T 1:D  0:L1477:main.cpp:findAndOperateAccuChek: getting list of all USB devices in system from libusb
  0.925508(   +0.000024):nfo: 1C42A0AC:T 1:D  0:L1479:main.cpp:findAndOperateAccuChek: found 9 USB devices in system
  0.925514(   +0.000006):nfo: 1C42A0AC:T 1:D  0:L1483:main.cpp:findAndOperateAccuChek: searching for valid accuchek devices
  0.925518(   +0.000004):nfo: 1C42A0AC:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 0 is an accuchek
  0.925535(   +0.000017):nfo: 1C42A0AC:T 1:D  0:L1327:main.cpp:addDeviceIfAccuChek: not a match, too many interfaces to be an accuchek
  0.925542(   +0.000007):nfo: 1C42A0AC:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 1 is an accuchek
  0.925549(   +0.000007):nfo: 1C42A0AC:T 1:D  0:L1327:main.cpp:addDeviceIfAccuChek: not a match, too many interfaces to be an accuchek
  0.925554(   +0.000005):nfo: 1C42A0AC:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 2 is an accuchek
  0.925559(   +0.000005):nfo: 1C42A0AC:T 1:D  0:L1379:main.cpp:addDeviceIfAccuChek: found a usb device that looks good, checking further by opening it
  0.927161(   +0.001602):nfo: 1C42A0AC:T 1:D  0:L1442:main.cpp:addDeviceIfAccuChek: ========> found a matching USB device
  0.927209(   +0.000048):nfo: 1C42A0AC:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 3 is an accuchek
  0.927218(   +0.000009):nfo: 1C42A0AC:T 1:D  0:L1345:main.cpp:addDeviceIfAccuChek: not a match, too many endpoints to be an accuchek
  0.927222(   +0.000004):nfo: 1C42A0AC:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 4 is an accuchek
  0.927227(   +0.000005):nfo: 1C42A0AC:T 1:D  0:L1345:main.cpp:addDeviceIfAccuChek: not a match, too many endpoints to be an accuchek
  0.927231(   +0.000004):nfo: 1C42A0AC:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 5 is an accuchek
  0.927236(   +0.000005):nfo: 1C42A0AC:T 1:D  0:L1345:main.cpp:addDeviceIfAccuChek: not a match, too many endpoints to be an accuchek
  0.927240(   +0.000004):nfo: 1C42A0AC:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 6 is an accuchek
  0.927245(   +0.000005):nfo: 1C42A0AC:T 1:D  0:L1327:main.cpp:addDeviceIfAccuChek: not a match, too many interfaces to be an accuchek
  0.927249(   +0.000004):nfo: 1C42A0AC:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 7 is an accuchek
  0.927253(   +0.000004):nfo: 1C42A0AC:T 1:D  0:L1327:main.cpp:addDeviceIfAccuChek: not a match, too many interfaces to be an accuchek
  0.927256(   +0.000003):nfo: 1C42A0AC:T 1:D  0:L1485:main.cpp:findAndOperateAccuChek: checking if device 8 is an accuchek
  0.927261(   +0.000005):nfo: 1C42A0AC:T 1:D  0:L1345:main.cpp:addDeviceIfAccuChek: not a match, too many endpoints to be an accuchek
  0.927266(   +0.000005):nfo: 1C42A0AC:T 1:D  0:L1499:main.cpp:findAndOperateAccuChek: found altogether 1 accuchek devices
  0.927275(   +0.000009):nfo: 1C42A0AC:T 1:D  0:L 420:main.cpp:show: selecting accuchek device #0::

    bus number:    1
    dev address:   15
    cfg value:     1
    alt setting:   0
    alt interface number: 0
    vendor:        (0x173a) Roche Diagnostics GmbH
    product:       (0x21cc) Accu-Chek Active USB
    sndEndPnt:     1
    rcvEndPnt:     130

  0.928557(   +0.001282):nfo: 1C42A0AC:T 1:D  0:L 641:main.cpp:operateDevice: using device snd endpoint = 1
  0.928595(   +0.000038):nfo: 1C42A0AC:T 1:D  0:L 642:main.cpp:operateDevice: using device rcv endpoint = 130

  0.928599(   +0.000004):nfo: 1C42A0AC:T 1:D  0:L 761:main.cpp:operateDevice: phase 1: initial control transfer in
  0.928895(   +0.000296):nfo: 1C42A0AC:T 1:D  0:L 782:main.cpp:operateDevice: initial control transfer in succeeded
  0.928902(   +0.000007):nfo: 1C42A0AC:T 1:D  0:L 284:main.cpp:hexDumpWithHeader: hexdump of buffer:

BUFFER START "initial control transfer in" size=2 (0x2) ===============================================
00 00                                              ..
BUFFER END ============================================================================================

  0.928970(   +0.000068):nfo: 1C42A0AC:T 1:D  0:L 704:main.cpp:operator(): phase 2: receiving message pairing request
  0.929144(   +0.000174):nfo: 1C42A0AC:T 1:D  0:L 727:main.cpp:operator(): successfully read message "pairing request" from device
  0.929151(   +0.000007):nfo: 1C42A0AC:T 1:D  0:L 284:main.cpp:hexDumpWithHeader: hexdump of buffer:

BUFFER START "pairing request" size=0 (0x0) ===============================================
BUFFER END ============================================================================================

  0.929158(   +0.000007):nfo: 1C42A0AC:T 1:D  0:L 658:main.cpp:operator(): phase 3: sending message pairing confirmation
  0.929162(   +0.000004):nfo: 1C42A0AC:T 1:D  0:L 284:main.cpp:hexDumpWithHeader: hexdump of buffer:

BUFFER START "pairing confirmation" size=48 (0x30) ===============================================
E3 00 00 2C 00 03 50 79 00 26 80 00 00 02 80 00    ...,..Py.&......
80 00 00 00 00 00 00 00 80 00 00 00 00 08 12 34    ...............4
56 78 00 00 00 00 00 00 00 00 00 00 00 00 00 00    Vx..............
BUFFER END ============================================================================================

  0.930552(   +0.001390):nfo: 1C42A0AC:T 1:D  0:L 686:main.cpp:operator(): successfully wrote message pairing confirmation, size=48 (0x30):

  0.930611(   +0.000059):nfo: 1C42A0AC:T 1:D  0:L 704:main.cpp:operator(): phase 4: receiving message config info
  0.930766(   +0.000155):nfo: 1C42A0AC:T 1:D  0:L 727:main.cpp:operator(): successfully read message "config info" from device
  0.930774(   +0.000008):nfo: 1C42A0AC:T 1:D  0:L 284:main.cpp:hexDumpWithHeader: hexdump of buffer:

BUFFER START "config info" size=0 (0x0) ===============================================
BUFFER END ============================================================================================

  0.930782(   +0.000008):nfo: 1C42A0AC:T 1:D  0:L 751:main.cpp:operator(): invokeId after phase 5 is: 20601
  0.930787(   +0.000005):nfo: 1C42A0AC:T 1:D  0:L 932:main.cpp:operateDevice: parsing config info response
  0.930791(   +0.000004):nfo: 1C42A0AC:T 1:D  0:L 842:main.cpp:operator(): got 32768 object in config info response
Segmentation fault (core dumped)