Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
.cache
.mypy_cache/
.vscode/
.zed/
/MANIFEST
/dist/
__pycache__/
build
.idea/
*venv/
*.swp
.DS_Store
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ supported.
| Menarini | GlucoMen Nexus | `td42xx` | [construct] [pyserial]² [hidapi] |
| Aktivmed | GlucoCheck XL | `td42xx` | [construct] [pyserial]² [hidapi] |
| Ascensia | ContourUSB | `contourusb` | [construct] [hidapi]‡ |
| Ascensia | Contour Care | `contourcare` | [construct] [hidapi]‡ |
| Menarini | GlucoMen areo³ | `glucomenareo` | [pyserial] [crcmod] |

† Untested.
Expand Down
8 changes: 5 additions & 3 deletions glucometerutils/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ class Unit(enum.Enum):
# Constants for meal information
class Meal(enum.Enum):
NONE = ""
BEFORE = "Before Meal"
AFTER = "After Meal"
BEFORE = "before meal"
AFTER = "after meal"
FASTING = "fasting"


# Constants for measure method
Expand Down Expand Up @@ -66,14 +67,15 @@ class GlucoseReading:
validator=attr.validators.in_(MeasurementMethod),
)
extra_data: dict[str, Any] = attr.Factory(dict)
unit: Unit = attr.ib(default=Unit.MG_DL, validator=attr.validators.in_(Unit))

def get_value_as(self, to_unit: Unit) -> float:
"""Returns the reading value as the given unit.

Args:
to_unit: The unit to return the value to.
"""
return convert_glucose_unit(self.value, Unit.MG_DL, to_unit)
return convert_glucose_unit(self.value, self.unit, to_unit)

def as_csv(self, unit: Unit) -> str:
"""Returns the reading as a formatted comma-separated value string."""
Expand Down
8 changes: 8 additions & 0 deletions glucometerutils/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ def zero_log(self) -> None:
def get_readings(self) -> Generator[common.AnyReading, None, None]:
pass

@abc.abstractmethod
def get_patient_name(self) -> Optional[str]:
pass

@abc.abstractmethod
def set_patient_name(self, name: str) -> None:
pass


@dataclasses.dataclass
class Driver:
Expand Down
92 changes: 92 additions & 0 deletions glucometerutils/drivers/contourcare.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# -*- coding: utf-8 -*-
#
# SPDX-FileCopyrightText: © 2019 The glucometerutils Authors
# SPDX-License-Identifier: MIT
"""Driver for Contour Care devices.

Supported features:
- get readings (blood glucose), including comments;
- get date and time;
- get serial number and software version;
- get device info (e.g. unit)

Expected device path: /dev/hidraw4 or similar HID device. Optional when using
HIDAPI.
"""

import datetime
from collections.abc import Generator
from typing import NoReturn, Optional

from glucometerutils import common
from glucometerutils.support import contourcare

_MEAL_CODES = {
"T": common.Meal.NONE,
"B": common.Meal.BEFORE,
"A": common.Meal.AFTER,
"F": common.Meal.FASTING,
}

_UNIT_CODES = {
"mg/dL": common.Unit.MG_DL,
"mmol/L": common.Unit.MMOL_L,
}

PRODUCT_ID: int = 0x7950 # Contour Care


class Device(contourcare.ContourCareHidDevice):
"""Glucometer driver for Contour Care devices."""

def __init__(self, device: Optional[str]) -> None:
super().__init__(PRODUCT_ID, device)

def get_meter_info(self) -> common.MeterInfo:
self._get_info_record()
return common.MeterInfo(
"Contour Care",
serial_number=self.get_serial_number(),
version_info=("Meter versions: " + self.get_version(),),
native_unit=self.get_glucose_unit(),
)

def get_readings(self) -> Generator[common.AnyReading, None, None]:
"""
Get reading dump from download data mode(all readings stored)
This meter supports only blood samples
"""
for parsed_record in self._get_multirecord():
timestamp = self.parse_timestamp(parsed_record["datetime"])
value = float(parsed_record["value"])
yield common.GlucoseReading(
timestamp,
value,
_MEAL_CODES[parsed_record["meal"][0]],
measure_method=common.MeasurementMethod.BLOOD_SAMPLE,
unit=_UNIT_CODES[parsed_record["unit"]],
)

def get_serial_number(self) -> str:
return self._get_serial_number()

def get_version(self):
return self._get_version()

def get_glucose_unit(self) -> common.Unit:
if self._get_glucose_unit() == "0":
return common.Unit.MG_DL
else:
return common.Unit.MMOL_L

def _set_device_datetime(self, date: datetime.datetime) -> NoReturn:
raise NotImplementedError

def zero_log(self) -> NoReturn:
raise NotImplementedError

def get_patient_name(self) -> str:
raise NotImplementedError

def set_patient_name(self, name: str) -> None:
raise NotImplementedError
Loading