Giter VIP home page Giter VIP logo

decocare's Introduction

openaps utility belt

These are the core utilities needed to develop a self-built open source artificial pancreas.

This is part of a series of tools to support a self-driven DIY implementation based on the OpenAPS reference design. The tools may be categorized as monitor (collecting data about environment, and operational status of devices and/or aggregating as much data as is relevant into one place), predict (make predictions about what should happen next), or control (enacting changes, and feeding more data back into the monitor).

By proceeding using these tools or any piece within, you agree to the copyright (see LICENSE.txt for more information) and release any contributors from liability.

Check out the OpenAPS documentation to help get you started.

Note: This is intended to be a set of tools to support a self-driven DIY implementation and any person choosing to use these tools is solely responsible for testing and implement these tools independently or together as a system. The DIY part of OpenAPS is important. While formal training or experience as an engineer or a developer is not required, what is required is a growth mindset to learn what are essentially "building blocks" to implement an OpenAPS instance. This is not a "set and forget" system; it requires diligent and consistent testing and monitoring to ensure each piece of the system is monitoring, predicting, and performing as desired. The performance and quality of your system lies solely with you.

Additionally, this community of contributors believes in "paying it forward", and individuals who are implementing these tools are asked to contribute by asking questions, helping improve documentation, and contribute in other ways.

openaps example rig hardware setup

This is not an artificial pancreas, but rather tools which independently allow:

  • monitor - Collect data about environment, and operational status of devices. Aggregate as much data relevant to therapy as possible into one place. We propose a tool, openaps-use as a proof of concept.

  • predict - Can make predictions about what should happen next.

  • control - Can enact changes in the world: emails, placing phone calls, SMS, issuing commands to pumps.

Install

There are two ways to install openaps, from source, and as a python package via setuptools.

The following apt-get dependencies are required (they can be installed through variety of means, in debian/ubuntu and apt based systems the following packages are recommended/required:

sudo apt-get install python python-dev python-setuptools python-software-properties python-numpy

From source

To install from source clone this repo, and issue:

sudo python setup.py develop

From pypi

To install from pypi:

sudo pip install -U openaps

This installs openaps system wide. Do not use openaps commands in the the openaps repo. Only use the openaps directory for hacking on the core library, or for managing upgrades through git. Running openaps inside of the openaps source directory will error in the best case, and mess up your openaps install in the worst case.

Updating
sudo easy_install -ZU openaps

Usage

usage: openaps [-h] [-c C C] [-C CONFIG] [--version] [command] ...

openaps - openaps: a toolkit for DIY artificial pancreas system

positional arguments:
  • command
  • args

optional arguments:

-h, --help            show this help message and exit
-c C C
-C CONFIG, --config CONFIG
--version             show program's version number and exit

Utilities for developing an artificial pancreas system. openaps helps you manage and structure reports for various devices.

All of the device and report add and show commands modify openaps.ini in the current working directory, which is assumed to be a git repo explicitily dedicated to helping develop and configure a DIY artificial pancreas system. This means openaps is an SDK for an artificial pancreas system, not an artificial pancreas system.

See openaps init for setting up a brand new instance of your own openaps, or see the notes below for details on how to convert an existing git repo into an instance of openaps.

Common workflows:

openaps init
openaps device <cmd>
  
  Device commands allow you to match a device driver, with a name
  and a configuration.
  
  add     - add device config to `openaps.ini`
  remove  - remove device from `openaps.ini`
  show    - print device uri, list all by default

openaps use [--format <json,stdout,text>]
            [--output <filename>]
        <device>
        <use>
        [use-args...]

  For each device registered, the vendor implementation provides a
  number of uses.  This allows users to experiment with reports.

openaps report <cmd>

  Reports match a device use to a format and filename.

  add     - add report config to `openaps.ini`
  remove  - remove report from `openaps.ini`
  show    - print report uri, list all by default
  invoke  - run and save report in file

Init new openaps environment

Do not use openaps commands in the the openaps repo. Only use the openaps directory for hacking on the core library, or for managing upgrades through git. Instead change to a new directory, not managed by git: cd ~/Documents.

Setup of new instance:

openaps init myopenaps    - this creates an instance of openaps in a new
                            directory, called myopenaps


cd myopenaps - change directory to root of new repo

A valid instance of openaps is a git repo with a file called openaps.ini present.

openaps will track configuration and some status information inside of openaps.ini.

Init existing git repo as openaps-environment

If you already have a git repo which you would like to become a valid openaps environent, in the root of your repo, run:

touch openaps.ini
git add openaps.ini
git commit -avm 'init openaps'

Now, wth a valid openaps environment, you can register devices for use. A device is implemented by a vendor. openaps provides a modular, language and process independent environment for creating vendors and devices.

Managing devices

To register devices for use, see openaps device commands:

openaps device -h
openaps device add <name> <vendor> [opts...]
eg:
# register a medtronic device named pump
openaps device add pump medtronic 665455
# register a dexcom device named cgm
openaps device add cgm dexcom

Using devices

Now that devices are known, and we have a variety of commands available. We can explore how to produce reports by using devices with the openaps use command:

openaps use <device-name> <use-name> [opts]

openaps use commands can only be used after devices have been added to the openaps.ini config using openaps device add. Eg:

openaps use pump -h        - show available commands for the
                             device known as "pump"
openaps use pump iter_pump 100 - get last 100 pump history records
                             from the device called pump
openaps use cgm -h         - show available commands for the
                             device known as "cgm"
openaps use cgm glucose

Save reports

After experimenting with openaps use commands, users can save reports using the openaps report commands. openaps report commands map openaps use commands to filenames:

openaps report add

Adding a report means configuring a use command with a format and a output, most commonly, a filename is used as the output.

openaps report add <report-name> <report-formatter> <device> <use> [opts]

# add a report, saved in a file called pump-history.json, which is
# JSON format, from device pump using use iter_pump.
openaps report add pump-history.json JSON pump iter_pump 100

# add a report, saved in a file called glucose.json, which is
# JSON format, from device cgm using use glucose.
openaps report add glucose.json JSON cgm glucose

invoke reports to run and save the results of the use

openaps report invoke

Invoking a report means running a use command according to it's configuration.

# invoke the report to create glucose.json
openaps report invoke glucose.json

# invoke the report to create pump-history.json
openaps report invoke pump-history.json

All commands support tab completion, and -h help options to help explore the live help system.

Sample use commands

medtronic

Assuming device is named pump:

usage: openaps-use pump [-h]
                        {Session, bolus, iter_glucose, iter_pump,
                        model, mytest, read_basal_profile_A,
                        read_basal_profile_B,
                        read_basal_profile_std, read_carb_ratios,
                        read_clock, read_current_glucose_pages,
                        read_current_history_pages,
                        read_glucose_data, read_history_data,
                        read_selected_basal_profile,
                        read_settings, read_status,
                        read_temp_basal, reservoir, resume_pump,
                        scan, set_temp_basal, settings, status,
                        suspend_pump}
                        ...

positional arguments:
  {Session, bolus, iter_glucose, iter_pump, model, mytest,
  read_basal_profile_A, read_basal_profile_B,
  read_basal_profile_std, read_carb_ratios, read_clock,
  read_current_glucose_pages, read_current_history_pages,
  read_glucose_data, read_history_data,
  read_selected_basal_profile, read_settings, read_status,
  read_temp_basal, reservoir, resume_pump, scan, set_temp_basal,
  settings, status, suspend_pump}
                        Operation
    Session             session for pump
    bolus               Send bolus.
    iter_glucose        Read latest 100 glucose records
    iter_pump           Read latest 100 pump records
    model               Get model number
    mytest              Testing read_settings
    read_basal_profile_A
                        Read basal profile A.
    read_basal_profile_B
                        Read basal profile B.
    read_basal_profile_std
                        Read default basal profile.
    read_carb_ratios    Read carb_ratios.
    read_clock          Read date/time of pump
    read_current_glucose_pages
                        Read current glucose pages.
    read_current_history_pages
                        Read current history pages.
    read_glucose_data   Read pump glucose page
    read_history_data   Read pump history page
    read_selected_basal_profile
                        Fetch the currently selected basal profile.
    read_settings       Read settings.
    read_status         Get pump status
    read_temp_basal     Read temporary basal rates.
    reservoir           Get pump remaining insulin
    resume_pump         resume pumping.
    scan                scan for usb stick
    set_temp_basal      Set temporary basal rates.
    settings            Get pump settings
    status              Get pump status (alias for read_status)
    suspend_pump        Suspend pumping.

optional arguments:
  -h, --help            show this help message and exit

Some commands like read_glucose_data, read_history_data take a page parameter, describing which page to fetch.

Some commands like bolus, set_temp_basal, take an input parameter which may be - for stdin or a filename containing a json data structure which represents the request.

All commands support -h and --help output.

dexcom

usage: openaps-use cgm [-h] {glucose,iter_glucose,scan} ...

positional arguments:
  {glucose,iter_glucose,scan}
                        Operation
    glucose             glucose (will pull all records)
    iter_glucose <n>       glucose ('n' for the number of records you want)
    scan                scan for usb stick

optional arguments:
  -h, --help            show this help message and exit

License

MIT License

Copyright (c) 2016 Ben West Copyright (c) 2015 Ben West

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

decocare's People

Contributors

bewest avatar channemann avatar cjo20 avatar ecc1 avatar erobinson avatar fokko avatar gazhay avatar ianjorgensen avatar kenstack avatar loudnate avatar moomoobloo avatar oskarpearson avatar ps2 avatar scottleibrand avatar tghoward avatar tmecklem avatar trhodeos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

decocare's Issues

insulin sensitivities above 255 decoded incorrectly

ReadInsulinSensitivities assumes only 1 byte is used for insulin sensitivity. But when the sensitivity is > 255, the pump sets an additional overflow bit. That bit is currently being decoded as part of the time component, so both the time and sensitivity end up being wrong.

On a 523 pump I observed the following in both dev and master:
12am - 256

    {
      "i": 64, 
      "start": "08:00:00", 
      "sensitivity": 0, 
      "offset": 1920, 
      "x": 0
    }

11:30pm - 300

    {
      "i": 111, 
      "start": "07:30:00", 
      "sensitivity": 44, 
      "offset": 3330, 
      "x": 1
    }

parsing BolusWizard records depends on BG units

A user of a 753 pump is using mg/dL for BG units, so it is possible to change the units on at least some pumps that have MMOL_DEFAULT = True. As a result, his BolusWizard records are being parsed incorrectly, due to

https://github.com/openaps/decocare/blob/master/decocare/records/bolus.py#L141

I think the correct fix is to do a ReadBGUnits call during session initialization, after ReadPumpModel, and to use this dynamic value rather than a static default when decoding records.

bewest.io DNS lookup fail

bewest.io is referenced in readme, but DNS lookup fails:

PWS3v2 3726ms
1 ns-l1.io 80.249.100.57 NON-AUTH 156 ms Received 2 Referrals , rcode=NO_ERROR bewest.io. 86400 IN NS ns1.bewest.io,bewest.io. 86400 IN NS sysadmin.bewest.io,

2 ns1.bewest.io 184.169.177.192 NON-AUTH 156 ms Timeout after 3 sec, rcode=NO_ERROR

2 sysadmin.bewest.io 184.169.177.192 NON-AUTH 156 ms Loop Prevented, rcode=NO_ERROR

MiniMed 715 history parsing fails

I'm trying to get a 715 working with OpenAPS and it's clear the decocare history page parsing doesn't actually support this pump. Some of the events do parse correctly but not all. The two stack traces I've seen so far are:

settings/pumphistory-24h.json  raised  month must be in 1..12
Traceback (most recent call last):
  File "/usr/local/bin/openaps-report", line 6, in <module>
    exec(compile(open(__file__).read(), __file__, 'exec'))
  File "/home/edison/src/openaps/bin/openaps-report", line 82, in <module>
    app( )
  File "/home/edison/src/openaps/openaps/cli/__init__.py", line 51, in __call__
    self.run(self.args)
  File "/home/edison/src/openaps/bin/openaps-report", line 75, in run
    output = app(args, self)
  File "/home/edison/src/openaps/openaps/cli/subcommand.py", line 52, in __call__
    return self.method.main(args, app)
  File "/home/edison/src/openaps/openaps/reports/invoke.py", line 40, in main
    output = task.method(args, app)
  File "/home/edison/src/openaps/openaps/uses/use.py", line 45, in __call__
    output = self.main(args, app)
  File "/home/edison/src/openaps/openaps/vendors/medtronic.py", line 639, in main
    for rec in self.range( ):
  File "/usr/local/lib/python2.7/dist-packages/decocare/models/__init__.py", line 67, in __call__
    for record in page:
  File "/usr/local/lib/python2.7/dist-packages/decocare/models/__init__.py", line 46, in download_page
    for record in self.find_records(page):
  File "/usr/local/lib/python2.7/dist-packages/decocare/models/__init__.py", line 158, in find_records
    records = decoder.decode( )
  File "/usr/local/lib/python2.7/dist-packages/decocare/history.py", line 851, in decode
    record = parse_record(self.stream, B, larger=larger, model=self.model)
  File "/usr/local/lib/python2.7/dist-packages/decocare/history.py", line 782, in parse_record
    record.parse( head + date + body )
  File "/usr/local/lib/python2.7/dist-packages/decocare/records/base.py", line 66, in parse
    return self.decode( )
  File "/usr/local/lib/python2.7/dist-packages/decocare/history.py", line 73, in decode
    return (dict(valid_date=date(*mid).isoformat()))
ValueError: month must be in 1..12

and

Traceback (most recent call last):
  File "/usr/local/bin/openaps-report", line 6, in <module>
    exec(compile(open(__file__).read(), __file__, 'exec'))
  File "/home/edison/src/openaps/bin/openaps-report", line 82, in <module>
    app( )
  File "/home/edison/src/openaps/openaps/cli/__init__.py", line 51, in __call__
    self.run(self.args)
  File "/home/edison/src/openaps/bin/openaps-report", line 75, in run
    output = app(args, self)
  File "/home/edison/src/openaps/openaps/cli/subcommand.py", line 52, in __call__
    return self.method.main(args, app)
  File "/home/edison/src/openaps/openaps/reports/invoke.py", line 40, in main
    output = task.method(args, app)
  File "/home/edison/src/openaps/openaps/uses/use.py", line 45, in __call__
    output = self.main(args, app)
  File "/home/edison/src/openaps/openaps/vendors/medtronic.py", line 639, in main
    for rec in self.range( ):
  File "/home/edison/src/decocare/decocare/models/__init__.py", line 67, in __call__
    for record in page:
  File "/home/edison/src/decocare/decocare/models/__init__.py", line 46, in download_page
    for record in self.find_records(page):
  File "/home/edison/src/decocare/decocare/models/__init__.py", line 158, in find_records
    records = decoder.decode( )
  File "/home/edison/src/decocare/decocare/history.py", line 855, in decode
    record = parse_record(self.stream, B, larger=larger, model=self.model)
  File "/home/edison/src/decocare/decocare/history.py", line 786, in parse_record
    record.parse( head + date + body )
  File "/home/edison/src/decocare/decocare/records/base.py", line 66, in parse
    return self.decode( )
  File "/home/edison/src/decocare/decocare/history.py", line 598, in decode
    temp = { 0: 'absolute', 1: 'percent' }[self.head[1]]
KeyError: 81

I logged some of the packets and the date error seems to be caused by the date parser being handled bytes that cannot possibly be a date, resulting in the parsing completely failing or the date being bogus (year deciphered anywhere between 1970 to 2056).

Windows - Not sure

Using Windows. Looked at fuser.py and found is there a windows version of a fuser -k < > folder

decoding of insulin sensitivity > 255 is incorrect

I've found the extra bit for insulin sensitivities > 255: it's bit 6 of the previous byte. For example, here's a bolus wizard setup record in which I change from sensitivity 35 to 400 (the max on my 522 pump):

5A 0F 1C C6 11 01 11 15 21 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 78 78 0C 64 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 15 21 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 78 78 0C 64 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 44

You can see the "00 23" in the "before" section', which changes to "40 90" in the "after" section.

When that bit gets set, it breaks the decoding of the sensitivity schedule (since that bit is set in a byte that's used for the start time of that sensitivity and needs to be masked off). The bug is in history.py, line 459.

High carb ratios on x23 pumps are off by 10x

Per openaps/openaps#111:

On x23 pumps with carb ratios set > 25 grams / U, openaps reads the carb ratio incorrectly as 0.26, 0.27, etc.

$ openaps use 523 read_carb_ratios
{
  "units": "grams",
  "first": 1,
  "schedule": [
    {
      "q": 0,
      "start": "00:00:00",
      "r": 100,
      "ratio": 10.0,
      "offset": 0,
      "i": 0,
      "x": 0
    },
    {
      "q": 1,
      "start": "23:30:00",
      "r": 4,
      "ratio": 0.26,
      "offset": 1410,
      "i": 47,
      "x": 1
    }
  ]
}

What other info would be useful to collect to correct the decoding here?

Parsing history with a ChangeBolusWizardSetup record fails

On a 722 pump, a history page fails to decode after a ChangeBolusWizardSetup record is encountered. It appears this is due to an incorrect expectation of command length. The history page in question parses correctly in Rileylink iOS's MinimedKit, which declares the length of a ChangeBolusWizardSetup record to have 39 total bytes including the opcode (see https://github.com/ps2/rileylink_ios/blob/dev/MinimedKit/PumpEvents/ChangeBolusWizardSetupPumpEvent.swift#L17). Decocare declares the total length to be 47: 40 body + 5 byte timestamp + 2 byte opcode/param (see https://github.com/openaps/decocare/blob/master/decocare/history.py#L228). The decocare code causes an exception in this case (see below), while the Rilelylink code returns proper records and timestamps for the page records. This leads me to believe that the decocare ChangeBolusWizardSetup parsing should be changed to have a body size of 32. Making that change causes the rest of the history page to be decoded with plausibly correct records and timestamps like Rileylink. PR forthcoming with that change.

History page (raw): https://gist.github.com/tmecklem/d47c1dae50a7b29e2b059f9491f0f24c

History Page hex:

33 00 2F 98 07 4E 11 00 16 01 2F 98 07 4E 11 33 2C 35 A0 07 4E 11 00 16 01 35 A0 07 4E 11 33 00 35 AC 07 4E 11 00 16 01 35 AC 07 4E 11 33 4C 35 B4 07 4E 11 00 16 01 35 B4 07 4E 11 33 2C 01 8E 08 4E 11 00 16 01 01 8E 08 4E 11 33 44 19 93 08 4E 11 00 16 01 19 93 08 4E 11 33 5E 32 9D 08 4E 11 00 16 01 32 9D 08 4E 11 33 7E 2A A8 08 4E 11 00 16 01 2A A8 08 4E 11 33 7E 2B A8 08 4E 11 00 16 01 2B A8 08 4E 11 33 2C 00 BA 08 4E 11 00 16 01 00 BA 08 4E 11 5B 00 0E BB 08 0E 11 1E 50 09 23 4B 00 21 00 00 00 00 21 5A 5C 08 18 21 14 10 DF 14 01 21 21 00 0E BB 28 0E 11 0B 70 00 0D 9F 29 AE 11 4F 00 0C A1 09 0E 11 21 51 00 8C 37 28 1E 00 3C 14 00 1E 3C 25 85 3E 20 51 00 8C 37 28 1E 00 3C 14 00 1E 3C 25 85 3E 5B 00 2B A4 0D 0E 11 1E 50 07 23 4B 00 2A 00 00 00 00 2A 5A 5C 08 58 14 14 2C 1E 14 01 2A 2A 00 2B A4 2D 0E 11 1E 00 21 B8 0D 0E 11 1F 00 30 8E 0E 0E 11 4F 00 2B 99 0E 0E 11 20 51 00 8C 37 28 1E 00 3C 14 00 1E 3C 25 85 3E 21 51 00 8C 37 28 1E 00 3C 14 00 1E 3C 25 85 3E 0B 6D 00 3B 81 2F AE 11 0A 1E 27 82 2F 6E 91 3F 23 27 82 CF 6E 11 80 98 44 5B 1E 3A 82 0F 0E 11 00 51 07 23 4B 38 00 00 00 1B 00 1D 5A 5C 0B A8 5C 04 58 6A 14 2C 74 14 01 1D 1D 00 3B 82 2F 0E 11 33 8C 20 87 0F 4E 11 00 16 01 20 87 0F 4E 11 0B 68 00 1F 99 30 AE 11 0A CC 29 9C 30 6E 11 3F 19 29 9C 90 6E 11 80 98 44 5B CC 2B 9C 10 0E 11 00 50 06 23 4B 20 00 00 00 1B 00 05 5A 5C 0E 74 58 04 A8 B2 04 58 C0 14 2C CA 14 01 05 05 00 2B 9C 30 0E 11 33 8C 06 A1 10 4E 11 00 16 01 06 A1 10 4E 11 0B 65 CC 01 A9 30 AE 11 5B 00 13 AF 10 0E 11 14 50 06 23 4B 00 21 00 00 00 00 21 5A 5C 11 14 1B 04 74 6B 04 A8 C5 04 58 D3 14 2C DD 14 01 21 21 00 13 AF 30 0E 11 33 3C 07 B4 10 4E 11 00 16 01 07 B4 10 4E 11 33 36 3B 84 11 4E 11 00 16 01 3B 84 11 4E 11 33 36 3B 98 11 4E 11 00 16 01 3B 98 11 4E 11 33 36 01 AA 11 4E 11 00 16 01 01 AA 11 4E 11 33 36 0E BA 11 4E 11 00 16 01 0E BA 11 4E 11 33 8C 38 84 12 4E 11 00 16 01 38 84 12 4E 11 33 3E 34 9C 12 4E 11 00 16 01 34 9C 12 4E 11 33 8C 39 84 13 4E 11 00 16 01 39 84 13 4E 11 0B 65 8C 13 8F 33 AE 11 0A 68 2F 8F 33 0E 11 0B 69 00 00 9C 35 AE 11 0A 3F 29 9D 35 6E 11 3F 07 29 9D F5 6E 11 85 62 50 5B 3F 2A 9E 15 0E 11 0D 50 06 23 4B FC 15 F0 00 00 00 11 5A 5C 0B 84 22 14 14 36 14 74 86 14 01 11 11 00 2A 9E 35 0E 11 33 00 05 B6 16 0E 11 00 16 01 05 B6 16 0E 11 0A 2D 36 81 37 6E 11 3F 05 36 81 B7 6E 11 85 62 50 1E 00 0D A4 17 0E 11 0B 65 8F 1F AD 37 AE 11 07 00 00 07 4E 2E 11 6D 2E 11 05 10 84 2D 1E 07 00 00 07 4E 04 AA 40 02 A4 24 00 5D 02 A4 24 01 F4 4A 00 B0 1A 00 00 00 08 04 04 00 00 00 64 39 CC C5 04 0A 72 1D 9E 20 6F 11 3F 0E 1D 9E 40 6F 11 85 95 51 1F 00 31 9E 00 0F 11 5B 72 23 A4 00 0F 11 0F 50 0D 23 4B 06 0B 00 00 03 00 0E 5A 5C 08 44 BA 04 84 DC 14 01 0E 0E 00 23 A4 20 0F 11 0B 65 90 3B 81 21 AF 11 0B 65 C0 01 81 22 AF 11 0B 65 C8 3B 81 23 AF 11 0B 65 D3 01 81 24 AF 11 0B 65 E8 3B 81 25 AF 11 0B 65 E3 01 81 26 AF 11 0B 65 CF 3B 81 27 AF 11 0B 65 BC 01 81 28 AF 11 0A CA 21 82 28 6F 11 3F 19 21 82 48 6F 11 80 98 44 5B CA 2D 82 08 0F 11 00 50 09 23 4B 20 00 00 00 00 00 20 5A 5C 05 38 C4 14 01 20 20 00 2D 82 28 0F 11 00 00 00 00 00 00 00 B2 33

Output of history decoding (error occurs after the parsing of the ChangeBolusWizardSetup Record:

python bin/mm-decode-history-page.py --model 722 --data pump --no-larger ~/Desktop/ReadHistoryData-page-0.data 
## START /Users/tmecklem/Desktop/ReadHistoryData-page-0.data
Traceback (most recent call last):
  File "bin/mm-decode-history-page.py", line 143, in <module>
    main( )
  File "bin/mm-decode-history-page.py", line 121, in main
    records = find_records(stream, opts)
  File "bin/mm-decode-history-page.py", line 93, in find_records
    record = parse_record( stream, B, model=opts.model, larger=opts.larger )
  File "/Users/tmecklem/src/t1d/openaps/decocare/decocare/history.py", line 783, in parse_record
    record.parse( head + date + body )
  File "/Users/tmecklem/src/t1d/openaps/decocare/decocare/records/base.py", line 66, in parse
    return self.decode( )
  File "/Users/tmecklem/src/t1d/openaps/decocare/decocare/history.py", line 186, in decode
    temp = { 0: 'absolute', 1: 'percent' }[(self.body[0] >> 3)]
KeyError: 6

CalBGForPH parsing wrong

Using Medtronic 554 Veo, create a Bolus Wizard treatment where you enter 12 mmol as the blood glucose value. The following is output by decocare when parsing the logs. Note how the CalBGForPH value has taken the mmol value and multiplied it by 10 and the units definition is missing. The end-result is that the event is considered to represent 120 mgdl, which is around half of 12 mmol. @bewest any pointers where to look?

{
    "_type": "CalBGForPH", 
    "_description": "CalBGForPH 2017-04-04T04:05:08 head[2], body[0] op[0x0a]", 
    "timestamp": "2017-04-04T04:05:08", 
    "_body": "", 
    "_head": "0a78", 
    "amount": 120, 
    "_date": "4805440411"
  }
  {
    "_type": "BolusWizard", 
    "bg": 12.0, 
    "bg_target_high": 9.0, 
    "_description": "BolusWizard 2017-04-04T04:05:25 head[2], body[15] op[0x5b]", 
    "timestamp": "2017-04-04T04:05:25", 
    "_body": "0090008c483410000000000000105a", 
    "_head": "5b78", 
    "unabsorbed_insulin_total": 0.0, 
    "correction_estimate": 0.4, 
    "_date": "5905040411", 
    "bolus_estimate": 0.4, 
    "bg_target_low": 5.2, 
    "carb_ratio": 14.0, 
    "food_estimate": 0.0, 
    "carb_input": 0, 
    "sensitivity": 7.2
  }

decocare issue when retrieving CGM data from MDT CGM

Issue that I see happen all the time, this error happens almost every loop hence we have to have pump-loop try again when it fails.
but even when we try again, it fails a lot. This is one of the reason it takes so long to update the Nightscout site, with most data being 10 or more mins old.
Now I'm not sure if this is all MDT cgms or just my 723 with 2.4A 1.1

I'm not familiar enough with python to figure out where to go from the decocare lib.py line 235

But here is the error that happens.

Starting supermicrobolus pump-loop at Sun Oct 15 12:41:01 EDT 2017 with 15 second wait_for_silence:
MDT CGM configured; not waiting
Radio ok. Listening: .No pump comms detected from other rigs
Preflight OK. 
Attempting to retrieve MDT CGM data from pump
monitor/cgm-mm-glucosedirty.json  raised  need more than 0 values to unpack
Traceback (most recent call last):
  File "/usr/local/bin/openaps-report", line 82, in <module>
    app( )
  File "/usr/local/lib/python2.7/dist-packages/openaps/cli/__init__.py", line 51, in __call__
    self.run(self.args)
  File "/usr/local/bin/openaps-report", line 75, in run
    output = app(args, self)
  File "/usr/local/lib/python2.7/dist-packages/openaps/cli/subcommand.py", line 52, in __call__
    return self.method.main(args, app)
  File "/usr/local/lib/python2.7/dist-packages/openaps/reports/invoke.py", line 40, in main
    output = task.method(args, app)
  File "/usr/local/lib/python2.7/dist-packages/openaps/uses/use.py", line 45, in __call__
    output = self.main(args, app)
  File "/usr/local/lib/python2.7/dist-packages/openaps/vendors/medtronic.py", line 640, in main
    for rec in self.range( ):
  File "/usr/local/lib/python2.7/dist-packages/decocare/models/__init__.py", line 67, in __call__
    for record in page:
  File "/usr/local/lib/python2.7/dist-packages/decocare/models/__init__.py", line 46, in download_page
    for record in self.find_records(page):
  File "/usr/local/lib/python2.7/dist-packages/decocare/models/__init__.py", line 145, in find_records
    page = cgm.PagedData.Data(response.data, larger=self.inst.larger)
  File "/usr/local/lib/python2.7/dist-packages/decocare/cgm/__init__.py", line 84, in Data
    return klass(stream, **kwds)
  File "/usr/local/lib/python2.7/dist-packages/decocare/cgm/__init__.py", line 90, in __init__
    if lib.BangInt(crc) != computed:
  File "/usr/local/lib/python2.7/dist-packages/decocare/lib.py", line 235, in BangInt
    ( x, y ) = ints
ValueError: need more than 0 values to unpack

CGM data retrieval from pump disrupted, retrying in 5 seconds...
Reattempting to retrieve MDT CGM data
monitor/cgm-mm-glucosedirty.json  raised  need more than 0 values to unpack
Traceback (most recent call last):
  File "/usr/local/bin/openaps-report", line 82, in <module>
    app( )
  File "/usr/local/lib/python2.7/dist-packages/openaps/cli/__init__.py", line 51, in __call__
    self.run(self.args)
  File "/usr/local/bin/openaps-report", line 75, in run
    output = app(args, self)
  File "/usr/local/lib/python2.7/dist-packages/openaps/cli/subcommand.py", line 52, in __call__
    return self.method.main(args, app)
  File "/usr/local/lib/python2.7/dist-packages/openaps/reports/invoke.py", line 40, in main
    output = task.method(args, app)
  File "/usr/local/lib/python2.7/dist-packages/openaps/uses/use.py", line 45, in __call__
    output = self.main(args, app)
  File "/usr/local/lib/python2.7/dist-packages/openaps/vendors/medtronic.py", line 640, in main
    for rec in self.range( ):
  File "/usr/local/lib/python2.7/dist-packages/decocare/models/__init__.py", line 67, in __call__
    for record in page:
  File "/usr/local/lib/python2.7/dist-packages/decocare/models/__init__.py", line 46, in download_page
    for record in self.find_records(page):
  File "/usr/local/lib/python2.7/dist-packages/decocare/models/__init__.py", line 145, in find_records
    page = cgm.PagedData.Data(response.data, larger=self.inst.larger)
  File "/usr/local/lib/python2.7/dist-packages/decocare/cgm/__init__.py", line 84, in Data
    return klass(stream, **kwds)
  File "/usr/local/lib/python2.7/dist-packages/decocare/cgm/__init__.py", line 90, in __init__
    if lib.BangInt(crc) != computed:
  File "/usr/local/lib/python2.7/dist-packages/decocare/lib.py", line 235, in BangInt
    ( x, y ) = ints
ValueError: need more than 0 values to unpack

CGM data retrieval from pump disrupted, retrying in 5 seconds...
Reattempting to retrieve MDT CGM data
monitor/cgm-mm-glucosedirty.json  raised  
Traceback (most recent call last):
  File "/usr/local/bin/openaps-report", line 82, in <module>
    app( )
  File "/usr/local/lib/python2.7/dist-packages/openaps/cli/__init__.py", line 51, in __call__
    self.run(self.args)
  File "/usr/local/bin/openaps-report", line 75, in run
    output = app(args, self)
  File "/usr/local/lib/python2.7/dist-packages/openaps/cli/subcommand.py", line 52, in __call__
    return self.method.main(args, app)
  File "/usr/local/lib/python2.7/dist-packages/openaps/reports/invoke.py", line 40, in main
    output = task.method(args, app)
  File "/usr/local/lib/python2.7/dist-packages/openaps/uses/use.py", line 44, in __call__
    self.before_main(args, app)
  File "/usr/local/lib/python2.7/dist-packages/openaps/vendors/medtronic.py", line 64, in before_main
    self.check_session(app)
  File "/usr/local/lib/python2.7/dist-packages/openaps/vendors/medtronic.py", line 141, in check_session
    self.session = self.get_session_info( )
  File "/usr/local/lib/python2.7/dist-packages/openaps/vendors/medtronic.py", line 104, in get_session_info
    fields = self.create_session( )
  File "/usr/local/lib/python2.7/dist-packages/openaps/vendors/medtronic.py", line 129, in create_session
    self.pump.power_control(minutes=minutes)
  File "/usr/local/lib/python2.7/dist-packages/mmeowlink/handlers/stick.py", line 217, in power_control
    status = repeater(self.command, repetitions=500, ack_wait_seconds=12)
  File "/usr/local/lib/python2.7/dist-packages/mmeowlink/handlers/stick.py", line 176, in __call__
    self.wait_for_ack(timeout=ack_wait_seconds)
  File "/usr/local/lib/python2.7/dist-packages/mmeowlink/handlers/stick.py", line 84, in wait_for_ack
    resp = Packet.fromBuffer(buf)
  File "/usr/local/lib/python2.7/dist-packages/mmeowlink/packets/rf.py", line 97, in fromBuffer
    raise InvalidPacketReceived
mmeowlink.exceptions.InvalidPacketReceived

CGM data retrieval from pump disrupted, retrying in 5 seconds...
Reattempting to retrieve MDT CGM data
MDT CGM data retrieved
No new MDT CGM data to reformat

Is bewest.io:8080 still running?

I'm trying to use the non-equipment demo and when I run the socat_run_app script I get

milan@milan-ThinkPad-T490:~/OpenAPS/decoding-carelink$ ./bin/socat_run_app.sh

/usr/bin/socat  TCP-CONNECT:bewest.io:8080,reuseaddr pty,link=./carelink.ttyUSB0,b9600,raw
2020/07/09 10:04:40 socat[10113] E getaddrinfo("bewest.io", "NULL", {1,0,1,6}, {}): Name or service not known

Would it help if I had a Carelink USB?

bolus ack is incorrect

when bolusing the command is received but the ack response is incorrect

{'recieved': False, '_type': 'BolusRequest'}

I believe line 478 of commands.py is incorrect
received = True if self.data[0] is 0x0c else False

I think it should be similar to the basal ack 
received = True if (len(self.data) > 0 and self.data[0] is 0) else False

but I dont know enough about the data being received to verify, and it looks from the bolus ack that the 0x0c was not unintentional, so I cant be sure

CGM page decoding needs some enhancements and additional events

New cgm event discoveries from comparison with Excel dumps and decoding various example pages:

0x03 Sensor Calibration

  • two bytes including opcode
  • participates in relative offset like normal sgv event
  • calibration type in other byte, decoded as:
  • 0x00: meter_bg_now
  • 0x01: waiting
  • 0x02: cal_error

0x04 Sensor Packet

  • two bytes including opcode
  • participates in relative offset like normal sgv event
  • packet type in other byte, decoded as:
  • 0x02: init
  • 0x??: pre_init (found in csv but no pages yet obtained with this)
  • 0x??: burst (found in csv but no pages yet obtained with this)

0x05 Sensor Error

  • two bytes including opcode
  • participates in relative offset like normal sgv event
  • error type in other byte, decoded as:
  • 0x01: end

0x06 Sensor Data Low

  • sgv of 40
  • single byte event
  • participates in relative offset like normal sgv event

0x07 “Fokko-07” - Sensor Data High

  • sgv of 400
  • two bytes including opcode
  • other byte is unknown (perhaps raw sensor reading above 400?)
  • participates in relative offset like normal sgv event

0x08 Sensor Timestamp

  • 5 bytes including opcode
  • Third timestamp byte (in page order) has timestamp type encoded in top bits (& 0b01100000), decoded as:
  • 0b00100000: page_end - written as last event of every page
  • 0b01000000: gap - written whenever there is a gap in the events that require a reference sensor timestamp value
  • 0b00000000: last_rf - written whenever requested via rf command, such as carelink report data upload (this is important later in the algorithm changes)

0x0B Sensor Status

  • 5 bytes including opcode
  • Third timestamp byte (in page order) has status type encoded in top bits (& 0b01100000), decoded as:
  • 0b00000000: off
  • 0b00100000: on
  • 0b01000000: lost

0x0D Sensor Sync

  • 5 bytes including opcode
  • Third timestamp byte (in page order) has sync type encoded in top bits (& 0b01100000), decoded as:
  • 0b01100000: find
  • 0b00100000: new
  • 0b01000000: old

0x0E Cal BG For GH

  • 6 bytes including opcode
  • Third timestamp byte (in page order) has source type encoded in top bits (& 0b01100000), decoded as:
  • 0b00000000: rf
  • others not yet encountered

0x10 “10-Something”

  • 8 bytes long including opcode (not 5 as in current decocare)
  • other three bytes seem to always be 0x000001

0x11, 0x12 and 0x13 (aka "19-Something")

  • have been observed but do not appear in csv dumps
  • Perhaps sync bytes for the isig table?

Algorithms discoveries/changes needed:

  • Sensor Timestamps (0x08) are the only events that serve as a reference for sensor events that follow the 5 minute offset pattern
  • Sensor Timestamps serve as the reference point for events that precede them in time (current decocare algorithm offsets forward instead of backward)
  • Events that should be offset 5 minutes iteratively:
  • 0x02 sensor_weak_signal
  • 0x03 sensor_calibration
  • 0x04 sensor_packet
  • 0x05 sensor_error
  • 0x06 sensor_data_low
  • 0x07 sensor_data_high
  • >= 0x20 sensor_glucose_value
  • When a good reference sensor timestamp is not available, pump command 0x28 will write a sensor timestamp to the current cgm page.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.