Source code for decocare.records.tests

#!/usr/bin/python

from binascii import hexlify
from datetime import datetime
from pprint import pformat

import json
import difflib

from times import *
from bolus import *

# I don't know where else to put this.
"""
    #
    ( bytearray([ 0x07, 0x00 ])
    + bytearray([ ])
    + bytearray([ ])),
"""

_midnights = {
  'page_4': [
    # record 14 (2013, 0, 7, 6, 5, 0)
    # 1/8/13 00:00:00,34.9,ResultDailyTotal,"AMOUNT=34.9,
    # CONCENTRATION=null"
    ( bytearray([ 0x07, 0x00 ])
    + bytearray([ 0x00, 0x05, 0x26, 0x07, 0x8d, ])
    + bytearray([ 0x6d, 0x07, 0x8d, 0x05, 0x00, 0x94, 0x58, 0xd8,
                  0x07, 0x00, 0x00, 0x05, 0x26, 0x03, 0x72, 0x43,
                  0x01, 0xb4, 0x21, 0x00, 0x79, 0x01, 0xb4, 0x21,
                  0x01, 0x64, 0x52, 0x00, 0x50, 0x12, 0x00, 0x00,
                  0x00, 0x05, 0x04, 0x01, 0x00, 0x00, 0x0c, 0x00,
                  0xe8, 0x00, 0x00, 0x00, ])),

    # record 30 (2013, 0, 8, 20, 5, 0)
    # 1/9/13 00:00:00,27.4,ResultDailyTotal,"AMOUNT=27.35,
    # CONCENTRATION=null"
    ( bytearray([ 0x07, 0x00 ])
    + bytearray([ 0x00, 0x05, 0x74, 0x08, 0x8d, ])
    + bytearray([ 0x6d, 0x08, 0x8d, 0x05, 0x10, 0xf6, 0x8e, 0x8f,
                  0x05, 0x00, 0x00, 0x05, 0x74, 0x03, 0x74, 0x3f,
                  0x02, 0x00, 0x25, 0x00, 0x35, 0x02, 0x00, 0x25,
                  0x00, 0xa0, 0x1f, 0x01, 0x60, 0x45, 0x00, 0x00,
                  0x00, 0x04, 0x00, 0x03, 0x01, 0x00, 0x0c, 0x00,
                  0xe8, 0x00, 0x00, 0x00, ])),

    # record (2013, 0, 9, 6, 4, 0)
    # 1/10/13 00:00:00,33.2,ResultDailyTotal,"AMOUNT=33.15,
    # CONCENTRATION=null"
    ( bytearray([ 0x07, 0x00 ])
    + bytearray([ 0x00, 0x04, 0x46, 0x09, 0x8d, ])
    + bytearray([ 0x6d, 0x09, 0x8d, 0x05, 0x10, 0xd3, 0x62, 0x29,
                  0x03, 0x00, 0x00, 0x04, 0x46, 0x03, 0x76, 0x51,
                  0x00, 0xd0, 0x13, 0x00, 0x2c, 0x00, 0xd0, 0x13,
                  0x00, 0x7c, 0x3c, 0x00, 0x54, 0x28, 0x00, 0x00,
                  0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x0c, 0x00,
                  0xe8, 0x00, 0x00, 0x00, ])),
  ],

  'page_14': [
    # record 8 (2012, 0, 2, 6, 6, 0)
    # 12/3/12 00:00:00,32.3,ResultDailyTotal,"AMOUNT=32.3,
    # CONCENTRATION=null"
    ( bytearray([ 0x07, 0x00 ])
    + bytearray([ 0x00, 0x06, 0x06, 0xc2, 0x0c, ])
    + bytearray([ 0x6d, 0xc2, 0x0c, 0x05, 0x10, 0xb1, 0x60, 0x8b,
    0x09, 0x00, 0x00, 0x06, 0x06, 0x03, 0x7c, 0x3a,
    0x02, 0x8a, 0x2a, 0x00, 0x64, 0x02, 0x8a, 0x2a,
    0x01, 0x2e, 0x2e, 0x01, 0x5c, 0x36, 0x00, 0x00,
    0x00, 0x07, 0x03, 0x04, 0x00, 0x00, 0x0c, 0x00,
    0xe8, 0x00, 0x00, 0x00, ])),

    # record 22 (2012, 0, 3, 12, 5, 0)
    # 12/4/12 00:00:00,36.0,ResultDailyTotal,"AMOUNT=35.95,
    # CONCENTRATION=null"
    ( bytearray([ 0x07, 0x00 ])
    + bytearray([ 0x00, 0x05, 0x0c, 0xc3, 0x0c, ])
    + bytearray([ 0x6d, 0xc3, 0x0c, 0x05, 0x10, 0xb7, 0x4d, 0x14,
                  0x03, 0x00, 0x00, 0x05, 0x0c, 0x03, 0x7c, 0x45,
                  0x01, 0x90, 0x1f, 0x00, 0x5f, 0x01, 0x90, 0x1f,
                  0x01, 0x04, 0x41, 0x00, 0x8c, 0x23, 0x00, 0x00,
                  0x00, 0x04, 0x03, 0x01, 0x00, 0x00, 0x0c, 0x00,
                  0xe8, 0x00, 0x00, 0x00, ])),

    # record 35 (2012, 0, 4, 30, 5, 0)
    # 12/5/12 00:00:00,25.9,ResultDailyTotal,"AMOUNT=25.9,
    # CONCENTRATION=null"
    ( bytearray([ 0x07, 0x00 ])
    + bytearray([ 0x00, 0x05, 0x9e, 0xc4, 0x0c, ])
    + bytearray([ 0x6d, 0xc4, 0x0c, 0x05, 0x00, 0xaa, 0x89, 0xc6,
    0x03, 0x00, 0x00, 0x05, 0x9e, 0x03, 0x76, 0x3e,
    0x02, 0x28, 0x26, 0x00, 0x8f, 0x02, 0x28, 0x26,
    0x01, 0xb0, 0x4e, 0x00, 0x78, 0x16, 0x00, 0x00,
    0x00, 0x05, 0x03, 0x02, 0x00, 0x00, 0x0c, 0x00,
    0xe8, 0x00, 0x00, 0x00, ])),

  ],

  'page_29': [
    # record 9 (2012, 0, 8, 28, 5, 0)
    # 10/9/12 00:00:00,34.8,ResultDailyTotal,"AMOUNT=34.85,
    # CONCENTRATION=null"
    ( bytearray([ 0x07, 0x00 ])
    + bytearray([ 0x00, 0x05, 0x9c, 0xa8, 0x0c, ])
    + bytearray([ 0x6d, 0xa8, 0x0c, 0x05, 0x10, 0xab, 0x61, 0x1a,
                  0x03, 0x00, 0x00, 0x05, 0x9c, 0x03, 0x78, 0x3e,
                  0x02, 0x24, 0x26, 0x00, 0x8b, 0x02, 0x24, 0x26,
                  0x01, 0x9c, 0x4b, 0x00, 0x88, 0x19, 0x00, 0x00,
                  0x00, 0x04, 0x03, 0x01, 0x00, 0x00, 0x0c, 0x00,
                  0xe8, 0x00, 0x00, 0x00, ])),

    # record 24 (2012, 0, 9, 18, 5, 0)
    # 10/10/12 00:00:00,30.8,ResultDailyTotal,"AMOUNT=30.85,
    # CONCENTRATION=null"
    ( bytearray([ 0x07, 0x00 ])
    + bytearray([ 0x00, 0x05, 0x72, 0xa9, 0x0c, ])
    + bytearray([ 0x6d, 0xa9, 0x0c, 0x05, 0x00, 0x96, 0x73, 0xb6,
                  0x03, 0x00, 0x00, 0x05, 0x72, 0x03, 0x76, 0x40,
                  0x01, 0xfc, 0x24, 0x00, 0x91, 0x01, 0xfc, 0x24,
                  0x01, 0xb4, 0x56, 0x00, 0x48, 0x0e, 0x00, 0x00,
                  0x00, 0x07, 0x05, 0x02, 0x00, 0x00, 0x0c, 0x00,
                  0xe8, 0x00, 0x00, 0x00, ])),

    # record 39  (2012, 0, 10, 18, 4, 0)
    # 10/11/12 00:00:00,30.2,ResultDailyTotal,"AMOUNT=30.2,
    # CONCENTRATION=null"
    ( bytearray([ 0x07, 0x00 ])
    + bytearray([ 0x00, 0x04, 0xd2, 0xaa, 0x0c, ])
    + bytearray([ 0x6d, 0xaa, 0x0c, 0x05, 0x10, 0xb6, 0x8d, 0x23,
                  0x05, 0x00, 0x00, 0x04, 0xd2, 0x03, 0x72, 0x47,
                  0x01, 0x60, 0x1d, 0x00, 0x36, 0x01, 0x60, 0x1d,
                  0x00, 0xa0, 0x2d, 0x00, 0xc0, 0x37, 0x00, 0x00,
                  0x00, 0x04, 0x02, 0x02, 0x00, 0x00, 0x0c, 0x00,
                  0xe8, 0x00, 0x00, 0x00, ])),
  ],
  'page_35': [
    # record 2 (2012, 0, 13, 22, 4, 0)
    # 9/14/12 00:00:00,31.2,ResultDailyTotal,"AMOUNT=31.2,
    # CONCENTRATION=null"
    #
    ( bytearray([ 0x07, 0x00 ])
    + bytearray([ 0x00, 0x04, 0x96, 0x8d, 0x8c, ])
    + bytearray([ 0x6d, 0x8d, 0x8c, 0x05, 0x00, 0x80, 0x68, 0x97,
                  0x02, 0x00, 0x00, 0x04, 0x96, 0x03, 0x42, 0x47,
                  0x01, 0x54, 0x1d, 0x00, 0x6d, 0x01, 0x54, 0x1d,
                  0x01, 0x40, 0x5e, 0x00, 0x14, 0x06, 0x00, 0x00,
                  0x00, 0x05, 0x04, 0x01, 0x00, 0x00, 0x0c, 0x00,
                  0xe8, 0x00, 0x00, 0x00, ])),

    # record 18  (2012, 0, 14, 0, 4, 0)
    # correct is 9/15/12 00:00:00,28.2,ResultDailyTotal,"AMOUNT=28.15,
    # CONCENTRATION=null"
    ( bytearray([ 0x07, 0x00 ])
    + bytearray([ 0x00, 0x04, 0xe0, 0x8e, 0x8c, ])
    + bytearray([ 0x6d, 0x8e, 0x8c, 0x05, 0x00, 0x74, 0x66, 0x8e,
                  0x07, 0x00, 0x00, 0x04, 0xe0, 0x03, 0x74, 0x47,
                  0x01, 0x6c, 0x1d, 0x00, 0x7b, 0x01, 0x6c, 0x1d,
                  0x01, 0x6c, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x05, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00,
                  0xe8, 0x00, 0x00, 0x00, ])),

    # correct is something like: (2012, 0, 15, 6, 4, 0)
    # 2012-09:15T00:00:00 or
    # 2012-09-16T24:00:00
    # 32.8,ResultDailyTotal,"AMOUNT=32.8, CONCENTRATION=null"
    ( bytearray([ 0x07, 0x00 ])
    + bytearray([ 0x00, 0x04, 0x66, 0x8f, 0x8c, ])
    + bytearray([ 0x6d, 0x8f, 0x8c, 0x05, 0x00, 0x80, 0x42, 0xf2,
                  0x05, 0x00, 0x00, 0x04, 0x66, 0x03, 0x56, 0x4c,
                  0x01, 0x10, 0x18, 0x00, 0x5b, 0x01, 0x10, 0x18,
                  0x01, 0x10, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00,
                  0xe8, 0x00, 0x00, 0x00, ])),

    # correct is something like: (2012, 0, 16, 0, 5, 0))
    # 2012-09-16T24:00:00 or
    # 2012-09:17T00:00:00
    # 32.2,ResultDailyTotal,"AMOUNT=32.2, CONCENTRATION=null"
    ( bytearray([ 0x07, 0x00 ])
    + bytearray([ 0x00, 0x05, 0x20, 0x90, 0x8c ])
    + bytearray([ 0x6d, 0x90, 0x8c, 0x05, 0x00, 0x89, 0x6c, 0xaa,
                  0x03, 0x00, 0x00, 0x05, 0x20, 0x03, 0x78, 0x44,
                  0x01, 0xa8, 0x20, 0x00, 0x7e, 0x01, 0xa8, 0x20,
                  0x01, 0x80, 0x5b, 0x00, 0x28, 0x09, 0x00, 0x00,
                  0x00, 0x05, 0x03, 0x01, 0x01, 0x00, 0x0c, 0x00,
                  0xe8, 0x00, 0x00, 0x00, ]))
  ],
}

_bewest_dates = {
  # from https://github.com/bewest/decoding-carelink/blob/rewriting/analysis/bewest-pump/ReadHistoryData-page-19.data.list_opcodes.markdown
  'page-19': {
    0:  [ 0xaa, 0xf7, 0x40, 0x0c, 0x0c, ],
    1:  [ 0x40, 0x0c, 0x0c, 0x0a, 0x0c, ],
    2:  [ 0x0c, 0x8b, 0xc3, 0x28, 0x0c, ],
    3:  [ 0x8b, 0xc3, 0x28, 0x0c, 0x8c, ],
    4:  [ 0x28, 0x0c, 0x8c, 0x5b, 0x0c, ],
    5:  [ 0x8d, 0xc3, 0x08, 0x0c, 0x0c, ],
    6:  [ 0xaa, 0xf7, 0x00, 0x0c, 0x0c, ],
  }
}

def _test_decode_bolus( ):
  """
  ## correct
  >>> parse_date( bytearray( _bewest_dates['page-19'][6] ) ).isoformat( )
  '2012-11-12T00:55:42'

  ## correct
  >>> parse_date( bytearray( _bewest_dates['page-19'][0] ) ).isoformat( )
  '2012-11-12T00:55:42'

  ## this is wrong
  >>> parse_date( bytearray( _bewest_dates['page-19'][1] ) ).isoformat( )
  '2012-04-10T12:12:00'

  ## day,month is wrong, time H:M:S is correct
  # expected:
  >>> parse_date( bytearray( _bewest_dates['page-19'][2] ) ).isoformat( )
  '2012-02-08T03:11:12'

  ## correct
  >>> parse_date( bytearray( _bewest_dates['page-19'][3] ) ).isoformat( )
  '2012-11-12T08:03:11'

  #### not a valid date
  # >>> parse_date( bytearray( _bewest_dates['page-19'][4] ) ).isoformat( )

  ## correct
  >>> parse_date( bytearray( _bewest_dates['page-19'][5] ) ).isoformat( )
  '2012-11-12T08:03:13'


  """
  """

  0x5b 0x7e # bolus wizard,
  0xaa 0xf7 0x00 0x0c 0x0c # page-19[0]

  0x0f 0x50 0x0d 0x2d 0x6a 0x00 0x0b 0x00
  0x00 0x07 0x00 0x0b 0x7d 0x5c 0x08 0x58
  0x97 0x04 0x30 0x05 0x14 0x34 0xc8
  0x91 0xf8      # 0x91, 0xf8 = month=11, minute=56, seconds=17!
  0x00           # general parsing fails here
  0x00
  0xaa 0xf7 0x40 0x0c 0x0c # expected  - page-19[6]

  0x0a 0x0c
  0x8b 0xc3 0x28 0x0c 0x8c # page-19[3]


  0x5b 0x0c

  0x8d 0xc3 0x08 0x0c 0x0c # page-19[5]
  0x00 0x51 0x0d 0x2d 0x6a 0x1f 0x00 0x00 0x00 0x00 0x00
  """

### csv deconstructed
"""
395,11/12/12,00:55:42,11/12/12 00:55:42,Normal 1.1,1.1,BolusNormal
  "AMOUNT=1.1, CONCENTRATION=null, PROGRAMMED_AMOUNT=1.1,
  ACTION_REQUESTOR=pump, ENABLE=true, IS_DUAL_COMPONENT=false,
  UNABSORBED_INSULIN_TOTAL=null"
    9942920032,51974238,2086,Paradigm 522

396,11/12/12,00:56:17,11/12/12 00:56:17 JournalEntryPumpLowReservoir
  "AMOUNT=20, ACTION_REQUESTOR=pump"
    9942920033,51974238,2087,Paradigm 522


397,11/12/12,08:03:11,11/12/12 08:03:11 268 CalBGForPH
  "AMOUNT=268, ACTION_REQUESTOR=pump"
    9942920031,51974238,2085,Paradigm 522

398,11/12/12,08:03:13,11/12/12 08:03:13 UnabsorbedInsulin
  "BOLUS_ESTIMATE_DATUM=9942920029, INDEX=0, AMOUNT=1.1, RECORD_AGE=429,
  INSULIN_TYPE=null,
  INSULIN_ACTION_CURVE=240"
    9942920030,51974238,2084,Paradigm 522

399,11/12/12,08:03:13,11/12/12 08:03:13
  3.1,125,106,13,45,0,268,3.1,0,0.0
  BolusWizardBolusEstimate,"BG_INPUT=268, BG_UNITS=mg dl,
  CARB_INPUT=0, CARB_UNITS=grams, CARB_RATIO=13,
  INSULIN_SENSITIVITY=45, BG_TARGET_LOW=106, BG_TARGET_HIGH=125,
  BOLUS_ESTIMATE=3.1, CORRECTION_ESTIMATE=3.1, FOOD_ESTIMATE=0,
  UNABSORBED_INSULIN_TOTAL=0, UNABSORBED_INSULIN_COUNT=1,
  ACTION_REQUESTOR=pump"
    9942920029,51974238,2083,Paradigm 522

400,11/12/12,08:03:13,11/12/12 08:03:13 Normal
  3.1,3.1 BolusNormal "AMOUNT=3.1, CONCENTRATION=null,
  PROGRAMMED_AMOUNT=3.1, ACTION_REQUESTOR=pump, ENABLE=true,
  IS_DUAL_COMPONENT=false,
  UNABSORBED_INSULIN_TOTAL=null"
    9942920028,51974238,2082,Paradigm 522

401,11/12/12,08:50:31,11/12/12 08:50:31 JournalEntryPumpLowReservoir
  "AMOUNT=10, ACTION_REQUESTOR=pump"
    9942920027,51974238,2081,Paradigm 522

"""



_bad_days = [
    bytearray([ 0xa9, 0xf5, 0x15, 0x14, 0x0c, ]),
    bytearray([ 0xa6, 0xc7, 0x36, 0x14, 0x8c, ]),
    bytearray([ 0xa9, 0xf5, 0x15, 0x14, 0x0c, ]),
    bytearray([ 0xa6, 0xc7, 0x36, 0x14, 0x8c, ]),

    bytearray([ 0xa2, 0xe9, 0x10, 0x19, 0x0c, ]),
    bytearray([ 0xa0, 0xf6, 0x0d, 0x19, 0x0c, ]),
    bytearray([ 0xa5, 0xd9, 0x34, 0x1d, 0x0c, ]),

    bytearray([ 0xc2, 0x3b, 0x0e, 0x14, 0x0c, ]),
    bytearray([ 0xd9, 0x1c, 0x0f, 0x14, 0x0c, ]),
  ]

# days need 5 bits
[docs]def big_days(x=0): """ # page 17, RECORD 11 >>> parse_date( big_days(0) ).isoformat( ) '2012-11-20T21:53:41' # page 17, ~ RECORD 12 >>> parse_date( big_days(1) ).isoformat( ) '2012-11-20T22:07:38' >>> parse_date( big_days(2) ).isoformat( ) '2012-11-20T21:53:41' >>> parse_date( big_days(3) ).isoformat( ) '2012-11-20T22:07:38' # page 16, RECORD ~15 >>> parse_date( big_days(4) ).isoformat( ) '2012-11-25T16:41:34' >>> parse_date( big_days(5) ).isoformat( ) '2012-11-25T13:54:32' # page 15 >>> parse_date( big_days(6) ).isoformat( ) '2012-11-29T20:25:37' # page 0 >>> parse_date( big_days(7) ).isoformat( ) '2012-12-20T14:59:02' >>> parse_date( big_days(8) ).isoformat( ) '2012-12-20T15:28:25' """ return _bad_days[x]
_wizards = [ # 2382,1/19/13,21:50:15,1/19/13 # 21:50:15,5.9,125,106,13,45,87,75,-0.7,6.6,0.0,BolusWizardBolusEstimate,"BG_INPUT=75, # BG_UNITS=mg dl, CARB_INPUT=87, CARB_UNITS=grams, CARB_RATIO=13, # INSULIN_SENSITIVITY=45, BG_TARGET_LOW=106, BG_TARGET_HIGH=125, # BOLUS_ESTIMATE=5.9, CORRECTION_ESTIMATE=-0.7, FOOD_ESTIMATE=6.6, # UNABSORBED_INSULIN_TOTAL=0, UNABSORBED_INSULIN_COUNT=0, # ACTION_REQUESTOR=pump" # 9942918055,51974238,109,Paradigm 522 bytearray([ 0x5b, 0x4b, 0x0f, 0x72, 0x15, 0x13, 0x0d, 0x57, 0x50, 0x0d, 0x2d, 0x6a, 0xf9, 0x42, 0xf0, 0x00, 0x00, 0x00, 0x3b, 0x7d, ]), # 2295,1/14/13,22:36:00,1/14/13 # 22:36:00,6.7,125,106,13,45,94,83,-0.5,7.2,1.0,BolusWizardBolusEstimate,"BG_INPUT=83, # BG_UNITS=mg dl, CARB_INPUT=94, CARB_UNITS=grams, CARB_RATIO=13, # INSULIN_SENSITIVITY=45, BG_TARGET_LOW=106, BG_TARGET_HIGH=125, # BOLUS_ESTIMATE=6.7, CORRECTION_ESTIMATE=-0.5, FOOD_ESTIMATE=7.2, # UNABSORBED_INSULIN_TOTAL=1, UNABSORBED_INSULIN_COUNT=8, # ACTION_REQUESTOR=pump" # 9942918140,51974238,194,Paradigm 522 bytearray([ 0x5b, 0x53, 0x00, 0x64, 0x16, 0x0e, 0x0d, 0x5e, 0x50, 0x0d, 0x2d, 0x6a, 0xfb, 0x48, 0xf0, 0x00, 0x0a, 0x00, 0x43, 0x7d, ]), # bytearray([ ]), ] def _test_bolus_wizards( ): """ >>> rec = BolusWizard( _wizards[0][:2] ) >>> print pformat(rec.parse( _wizards[0] )) {'_byte[5]': 249, '_byte[7]': 240, 'bg': 75, 'bg_target_high': 125, 'bg_target_low': 106, 'bolus_estimate': 5.9, 'carb_input': 87, 'carb_ratio': 13, 'correction_estimate': -0.7, 'food_estimate': 6.6, 'sensitivity': 45, 'unabsorbed_insulin_count': '??', 'unabsorbed_insulin_total': 0.0, 'unknown_byte[10]': 0, 'unknown_byte[8]': 0} >>> print str(rec) BolusWizard 2013-01-19T21:50:15 head[2], body[13] op[0x5b] >>> rec = BolusWizard( _wizards[1][:2] ) >>> print pformat(rec.parse( _wizards[1] )) {'_byte[5]': 251, '_byte[7]': 240, 'bg': 83, 'bg_target_high': 125, 'bg_target_low': 106, 'bolus_estimate': 6.7, 'carb_input': 94, 'carb_ratio': 13, 'correction_estimate': -0.5, 'food_estimate': 7.2, 'sensitivity': 45, 'unabsorbed_insulin_count': '??', 'unabsorbed_insulin_total': 1.0, 'unknown_byte[10]': 0, 'unknown_byte[8]': 0} >>> print str(rec) BolusWizard 2013-01-14T22:36:00 head[2], body[13] op[0x5b] """ pass _bolus = [ # 2381,1/19/13,21:50:15,1/19/13 # 21:50:15,Dual/Normal,2.6,2.6,BolusNormal,"AMOUNT=2.6, # CONCENTRATION=null, PROGRAMMED_AMOUNT=2.6, ACTION_REQUESTOR=pump, # ENABLE=true, IS_DUAL_COMPONENT=true, # UNABSORBED_INSULIN_TOTAL=null" # 9942918054,51974238,108,Paradigm 522 bytearray([ 0x01, 0x1a, 0x1a, 0x00, 0x0f, 0x72, 0x95, 0x13, 0x0d, ]), # 2305,1/15/13,15:57:16,1/15/13 # 15:57:16,Normal,1.7,1.7,BolusNormal,"AMOUNT=1.7, # CONCENTRATION=null, PROGRAMMED_AMOUNT=1.7, ACTION_REQUESTOR=pump, # ENABLE=true, IS_DUAL_COMPONENT=false, # UNABSORBED_INSULIN_TOTAL=null" # 9942918131,51974238,185,Paradigm 522 bytearray([ 0x01, 0x11, 0x11, 0x00, 0x10, 0x79, 0x4f, 0x0f, 0x0d, ]), # bytearray([ ]), ] def _test_bolus( ): """ >>> rec = Bolus( _bolus[0][:2] ) >>> print pformat(rec.parse( _bolus[0] )) {'amount': 2.6, 'duration': 0, 'programmed': 2.6, 'type': 'normal'} >>> print str(rec) Bolus 2013-01-19T21:50:15 head[4], body[0] op[0x01] >>> rec = Bolus( _bolus[1][:2] ) >>> print pformat(rec.parse( _bolus[1] )) {'amount': 1.7, 'duration': 0, 'programmed': 1.7, 'type': 'normal'} >>> print str(rec) Bolus 2013-01-15T15:57:16 head[4], body[0] op[0x01] """
[docs]class TestSaraBolus: # model 722 hexdump = """ 5b 67 a1 51 0e 04 0d 0d 50 00 78 3c 64 00 00 28 00 00 14 00 28 78 5c 08 44 79 c0 3c 4b d0 01 00 28 00 28 00 14 00 a1 51 4e 04 0d 0a fc b4 54 2f 04 0d 5b fc b7 54 0f 04 0d 00 50 00 78 3c 64 58 00 00 00 00 1c 00 3c 78 5c 0b 28 40 c0 44 b8 c0 3c 8a d0 01 00 3c 00 3c 00 1c 00 b7 54 4f 04 0d """ csv_breakdown = """ 9/4/13 14:17:33,,,,,,,Normal,1.0,1.0,,,,,,,,,,,,,,,,,,,,,BolusNormal "AMOUNT=1 CONCENTRATION=null PROGRAMMED_AMOUNT=1 ACTION_REQUESTOR=pump ENABLE=true IS_DUAL_COMPONENT=false UNABSORBED_INSULIN_TOTAL=0.5" 11345487207,52554138,86,Paradigm Revel - 723 9/4/13 14:17:33,,,,,,,,,,,,,,,1.0,120,100,12,60,13,103,0,1,0.5,,,,,,BolusWizardBolusEstimate,"BG_INPUT=103 BG_UNITS=mg dl CARB_INPUT=13 CARB_UNITS=grams CARB_RATIO=12 INSULIN_SENSITIVITY=60 BG_TARGET_LOW=100 BG_TARGET_HIGH=120 BOLUS_ESTIMATE=1 CORRECTION_ESTIMATE=0 FOOD_ESTIMATE=1 UNABSORBED_INSULIN_TOTAL=0.5 UNABSORBED_INSULIN_COUNT=2 ACTION_REQUESTOR=pump" 11345487208,52554138,87,Paradigm Revel - 723 9/4/13 14:17:33,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,UnabsorbedInsulin,"BOLUS_ESTIMATE_DATUM=11345487208 INDEX=0 AMOUNT=1.7 RECORD_AGE=121 INSULIN_TYPE=null INSULIN_ACTION_CURVE=180" 11345487209,52554138,88,Paradigm Revel - 723 9/4/13 14:17:33,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,UnabsorbedInsulin,"BOLUS_ESTIMATE_DATUM=11345487208 INDEX=1 AMOUNT=1.5 RECORD_AGE=331 INSULIN_TYPE=null INSULIN_ACTION_CURVE=180" 11345487210,52554138,89,Paradigm Revel - 723 9/4/13 15:20:52,,,,,,,,,,,,,,,,,,,,,,,,,,252,,,,CalBGForPH,"AMOUNT=252, ACTION_REQUESTOR=pump" 11345487206,52554138,85,Paradigm Revel - 723 9/4/13 15:20:55,,,,,,,Normal,1.5,1.5,,,,,,,,,,,,,,,,,,,,,BolusNormal,"AMOUNT=1.5 CONCENTRATION=null PROGRAMMED_AMOUNT=1.5 ACTION_REQUESTOR=pump ENABLE=true IS_DUAL_COMPONENT=false UNABSORBED_INSULIN_TOTAL=0.7" 11345487201,52554138,80,Paradigm Revel - 723 9/4/13 15:20:55,,,,,,,,,,,,,,,1.5,120,100,12,60,0,252,2.2,0,0.7,,,,,,BolusWizardBolusEstimate,"BG_INPUT=252 BG_UNITS=mg dl CARB_INPUT=0 CARB_UNITS=grams CARB_RATIO=12 INSULIN_SENSITIVITY=60 BG_TARGET_LOW=100 BG_TARGET_HIGH=120 BOLUS_ESTIMATE=1.5 CORRECTION_ESTIMATE=2.2 FOOD_ESTIMATE=0 UNABSORBED_INSULIN_TOTAL=0.7 UNABSORBED_INSULIN_COUNT=3 ACTION_REQUESTOR=pump" 11345487202,52554138,81,Paradigm Revel - 723 9/4/13 15:20:55,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,UnabsorbedInsulin,"BOLUS_ESTIMATE_DATUM=11345487202 INDEX=0 AMOUNT=1 RECORD_AGE=64 INSULIN_TYPE=null INSULIN_ACTION_CURVE=180" 11345487203,52554138,82,Paradigm Revel - 723 9/4/13 15:20:55,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,UnabsorbedInsulin,"BOLUS_ESTIMATE_DATUM=11345487202 INDEX=1 AMOUNT=1.7 RECORD_AGE=184 INSULIN_TYPE=null INSULIN_ACTION_CURVE=180" 11345487204,52554138,83,Paradigm Revel - 723 9/4/13 15:20:55,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,UnabsorbedInsulin,"BOLUS_ESTIMATE_DATUM=11345487202 INDEX=2 AMOUNT=1.5 RECORD_AGE=394 INSULIN_TYPE=null INSULIN_ACTION_CURVE=180" 11345487205,52554138,84,Paradigm Revel - 723 9/4/13 16:11:57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,CurrentSensorMissedDataTime,TIME=1800000,11345487185,52554138,64,Paradigm Revel - 723 """ bolus_1_ok = { 'bg': 103, # 'BG_UNITS': 'mg dl' 'carb_input': 13, #'CARB_UNITS': 'grams', 'carb_ratio': 12, 'sensitivity': 60, 'bg_target_low': 100, 'bg_target_high': 120, 'bolus_estimate': 1, 'correction_estimate': 0, 'food_estimate': 1, 'unabsorbed_insulin_total': 0.5, 'unabsorbed_insulin_count': 2, #'action_requestor': 'pump' } bw_1_bytes = bytearray(''.join(""" 5b 67 a1 51 0e 04 0d 0d 50 00 78 3c 64 00 00 28 00 00 14 00 28 78 """.strip( ).split( )).decode('hex')) bw_2_bytes = bytearray(''.join(""" 5b fc b7 54 0f 04 0d 00 50 00 78 3c 64 58 00 00 00 00 1c 00 3c 78 """.strip( ).split( )).decode('hex')) cal_bg_bytes = bytearray(''.join(""" 0a fc b4 54 2f 04 0d """.strip( ).split( )).decode('hex')) @classmethod
[docs] def test_cal_bg(klass): """ >>> TestSaraBolus.test_cal_bg( ) CalBGForPH 2013-09-04T15:20:52 head[2], body[0] op[0x0a] { "amount": 252 } """ # 9/4/13 15:20:52,,,,,,,,,,,,,,,,,,,,,,,,,,252,,,,CalBGForPH,"AMOUNT=252, ACTION_REQUESTOR=pump" data = klass.cal_bg_bytes rec = CalBGForPH(data[:2]) d = rec.parse(data) print str(rec) print json.dumps(d, indent=2)
[docs]def dictlines(d): items = d.items( ) items.sort( ) d = [ "%s: %s\n" % (k, v) for (k, v) in items ] return d
[docs]def unsolved_bolus_wizard( ): """ # >>> unsolved_bolus_wizard( ) """ # these byte sequences line up with these records: bw_ok_1 = { 'bg_input': 103, 'carb_input': 13, 'carb_ratio': 12, 'insulin_sensitivity': 60, 'bg_target_low': 100, 'bg_target_high': 120, 'bolus_estimate': 1, 'correction_estimate': 0, 'food_estimate': 1, 'unabsorbed_insulin_total': 0.5, 'unabsorbed_insulin_count': 2, } bw_ok_2 = { 'bg_input': 252, 'carb_input': 0, 'carb_ratio': 12, 'insulin_sensitivity': 60, 'bg_target_low': 100, 'bg_target_high': 120, 'bolus_estimate': 1.5, 'correction_estimate': 2.2, 'food_estimate': 0, 'unabsorbed_insulin_total': 0.7, 'unabsorbed_insulin_count': 3, } found = decode_wizard(TestSaraBolus.bw_1_bytes) if found != bw_ok_1: print "FOUND:" print json.dumps(found, indent=2) print "EXPECTED:" print json.dumps(bw_ok_1, indent=2) found = decode_wizard(TestSaraBolus.bw_2_bytes) if found != bw_ok_2: print "FOUND:" print json.dumps(found, indent=2) print "EXPECTED:" print json.dumps(bw_ok_2, indent=2)
[docs]def decode_wizard(data): """ BYTE 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: """ head = data[:2] date = data[2:7] datetime = parse_date(date) body = data[7:] bg = lib.BangInt([ body[1] & 0x0f, head[1] ]) carb_input = int(body[0]) carb_ratio = int(body[2]) bg_target_low = int(body[5]) bg_target_high = int(body[3]) sensitivity = int(body[4]) print "BOLUS WIZARD", datetime.isoformat( ) wizard = { 'bg_input': bg, 'carb_input': carb_input, 'carb_ratio': carb_ratio, 'insulin_sensitivity': sensitivity, 'bg_target_low': bg_target_low, 'bg_target_high': bg_target_high, } return wizard
[docs]class BW722(BolusWizard):
[docs] def decode(self): self.parse_time( ) bg = lib.BangInt([ self.body[1] & 0x0f, self.head[1] ]) carb_input = int(self.body[0]) carb_ratio = int(self.body[2]) bg_target_low = int(self.body[5]) bg_target_high = int(self.body[3]) sensitivity = int(self.body[12]) # XXX: Most likely incorrect. correction = ( twos_comp( self.body[7], 8 ) + twos_comp( self.body[5] & 0x0f, 8 ) ) / 10.0 wizard = { 'bg': bg, 'carb_input': carb_input, 'carb_ratio': carb_ratio, 'sensitivity': sensitivity, 'bg_target_low': bg_target_low, 'bg_target_high': bg_target_high, #'bolus_estimate': int(self.body[6])/10.0, #'food_estimate': int(self.body[13])/10.0, #'unabsorbed_insulin_total': int(self.body[9])/10.0, #'unabsorbed_insulin_count': self.body[11], 'correction_estimate': correction, # '??': '??', # 'unabsorbed_insulin_total': int(self.body[9])/10.0, # 'food_estimate': int(self.body[0]), } return wizard
if __name__ == '__main__': import doctest doctest.testmod( ) ##### # EOF