From f371538bc1e472b307c00d7376ac2046ff9b1024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Elio=20Petten=C3=B2?= Date: Thu, 23 Feb 2017 22:46:28 +0000 Subject: fslibre: new driver for Abbott FreeStyle Libre download. This is the first (draft) version of the driver, that only downloads the automatic sensor readings, marking them as (Sensor) in the comments. I'll follow up with downloading of the scans and blood tests, but wanted to have this pushed first. --- README | 2 ++ glucometerutils/drivers/fslibre.py | 73 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 glucometerutils/drivers/fslibre.py diff --git a/README b/README index c635bba..050dcaa 100644 --- a/README +++ b/README @@ -27,6 +27,7 @@ information on each of the devices. | LifeScan | OneTouch Verio (USB) | `otverio2015` | | LifeScan | OneTouch Select Plus | `otverio2015` | | Abbott | FreeStyle InsuLinx | `fsinsulinx` | +| Abbott | FreeStyle Libre | `fslibre` | | Abbott | FreeStyle Optium | `fsoptium` | | Abbott | FreeStyle Precision Neo | `fsprecisionneo` | | Roche | Accu-Chek Mobile | `accuchek_reports` | @@ -40,6 +41,7 @@ information on each of the devices. | `otultraeasy` | serialno, swver, unit | get and set | not supported by device | yes | | `otverio2015` | serialno, swver | get and set | no | yes | | `fsinsulinx` | serialno, swver | get and set | no | not supported by device | +| `fslibre` | serialno, swver | get and set | yes | not supported by device | | `fsoptium` | serialno, swver, unit | get and set | not supported by device | not supported by device | | `fsprecisionneo` | serialno, swver | get and set | not supported by device | not supported by device | | `accuchek_reports` | serialno, unit | no | yes | not supported by device | diff --git a/glucometerutils/drivers/fslibre.py b/glucometerutils/drivers/fslibre.py new file mode 100644 index 0000000..c213ccd --- /dev/null +++ b/glucometerutils/drivers/fslibre.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +"""Driver for FreeStyle Libre CGM devices.""" + +__author__ = 'Diego Elio Pettenò' +__email__ = 'flameeyes@flameeyes.eu' +__copyright__ = 'Copyright © 2017, Diego Elio Pettenò' +__license__ = 'MIT' + +import datetime + +from glucometerutils import common +from glucometerutils.support import freestyle + +# Fields of the records returned by $history? +# Tuple of pairs of idx and field name +_HISTORY_ENTRY_MAP = ( + (2, 'month'), + (3, 'day'), + (4, 'year'), # 2-digits + (5, 'hour'), + (6, 'minute'), + (7, 'second'), + (13, 'value'), + (15, 'errors'), +) + + +class Device(freestyle.FreeStyleHidDevice): + """Glucometer driver for FreeStyle Libre devices.""" + + def get_meter_info(self): + """Return the device information in structured form.""" + return common.MeterInfo( + 'FreeStyle Libre', + serial_number=self.get_serial_number(), + version_info=( + 'Software version: ' + self._get_version(),), + native_unit=self.get_glucose_unit()) + + def get_serial_number(self): + """Overridden function as the command is not compatible.""" + return self._send_text_command(b'$sn?').rstrip('\r\n') + + def get_glucose_unit(self): + """Returns the glucose unit of the device.""" + # TODO(Flameeyes): figure out how to identify the actual unit on the + # device. + return common.UNIT_MGDL + + def get_readings(self): + for record in self._get_multirecord(b'$history?'): + if not record: + continue + + parsed_record = { + key: int(record[idx]) + for idx, key in _HISTORY_ENTRY_MAP + } + + if parsed_record['errors'] != 0: + # The reading is considered invalid, so ignore it. + continue + + timestamp = datetime.datetime( + parsed_record['year'] + 2000, + parsed_record['month'], + parsed_record['day'], + parsed_record['hour'], + parsed_record['minute'], + parsed_record['second']) + + yield common.Reading(timestamp, parsed_record['value'], + comment='(Sensor)') -- cgit v1.2.3