diff options
author | Diego Elio Pettenò <flameeyes@flameeyes.eu> | 2018-12-12 23:16:57 +0100 |
---|---|---|
committer | Diego Elio Pettenò <flameeyes@flameeyes.eu> | 2018-12-12 23:16:57 +0100 |
commit | b1b2d814c0bdc883096bb8a23d397d5510189f9e (patch) | |
tree | 5e92df9bcad097d127c55be2240f47e05dff433e /glucometerutils/drivers/otultra2.py | |
parent | hiddevice: split handle_ and hidapi_handle_. (diff) | |
download | glucometerutils-b1b2d814c0bdc883096bb8a23d397d5510189f9e.tar glucometerutils-b1b2d814c0bdc883096bb8a23d397d5510189f9e.tar.gz glucometerutils-b1b2d814c0bdc883096bb8a23d397d5510189f9e.tar.bz2 glucometerutils-b1b2d814c0bdc883096bb8a23d397d5510189f9e.tar.lz glucometerutils-b1b2d814c0bdc883096bb8a23d397d5510189f9e.tar.xz glucometerutils-b1b2d814c0bdc883096bb8a23d397d5510189f9e.tar.zst glucometerutils-b1b2d814c0bdc883096bb8a23d397d5510189f9e.zip |
Diffstat (limited to '')
-rw-r--r-- | glucometerutils/drivers/otultra2.py | 386 |
1 files changed, 193 insertions, 193 deletions
diff --git a/glucometerutils/drivers/otultra2.py b/glucometerutils/drivers/otultra2.py index 762991e..a27d333 100644 --- a/glucometerutils/drivers/otultra2.py +++ b/glucometerutils/drivers/otultra2.py @@ -57,273 +57,273 @@ _DUMP_LINE_RE = re.compile( _RESPONSE_MATCH = re.compile(r'^(.+) ([0-9A-F]{4})\r$') def _calculate_checksum(bytestring): - """Calculate the checksum used by OneTouch Ultra and Ultra2 devices + """Calculate the checksum used by OneTouch Ultra and Ultra2 devices - Args: - bytestring: the string of which the checksum has to be calculated. + Args: + bytestring: the string of which the checksum has to be calculated. - Returns: - A string with the hexdecimal representation of the checksum for the input. + Returns: + A string with the hexdecimal representation of the checksum for the input. - The checksum is a very stupid one: it just sums all the bytes, - modulo 16-bit, without any parity. - """ - checksum = 0 + The checksum is a very stupid one: it just sums all the bytes, + modulo 16-bit, without any parity. + """ + checksum = 0 - for byte in bytestring: - checksum = (checksum + byte) & 0xffff + for byte in bytestring: + checksum = (checksum + byte) & 0xffff - return checksum + return checksum def _validate_and_strip_checksum(line): - """Verify the simple 16-bit checksum and remove it from the line. + """Verify the simple 16-bit checksum and remove it from the line. - Args: - line: the line to check the checksum of. + Args: + line: the line to check the checksum of. - Returns: - A copy of the line with the checksum stripped out. - """ - match = _RESPONSE_MATCH.match(line) + Returns: + A copy of the line with the checksum stripped out. + """ + match = _RESPONSE_MATCH.match(line) - if not match: - raise lifescan.MissingChecksum(line) + if not match: + raise lifescan.MissingChecksum(line) - response, checksum_string = match.groups() + response, checksum_string = match.groups() - try: - checksum_given = int(checksum_string, 16) - checksum_calculated = _calculate_checksum( - bytes(response, 'ascii')) + try: + checksum_given = int(checksum_string, 16) + checksum_calculated = _calculate_checksum( + bytes(response, 'ascii')) - if checksum_given != checksum_calculated: - raise exceptions.InvalidChecksum(checksum_given, - checksum_calculated) - except ValueError: - raise exceptions.InvalidChecksum(checksum_given, None) + if checksum_given != checksum_calculated: + raise exceptions.InvalidChecksum(checksum_given, + checksum_calculated) + except ValueError: + raise exceptions.InvalidChecksum(checksum_given, None) - return response + return response _DATETIME_RE = re.compile( r'^"[A-Z]{3}","([0-9]{2}/[0-9]{2}/[0-9]{2})","([0-9]{2}:[0-9]{2}:[0-9]{2}) "$') def _parse_datetime(response): - """Convert a response with date and time from the meter into a datetime. + """Convert a response with date and time from the meter into a datetime. - Args: - response: the response coming from a DMF or DMT command + Args: + response: the response coming from a DMF or DMT command - Returns: - A datetime object built according to the returned response. + Returns: + A datetime object built according to the returned response. - Raises: - InvalidResponse if the string cannot be matched by _DATETIME_RE. - """ - match = _DATETIME_RE.match(response) - if not match: - raise exceptions.InvalidResponse(response) + Raises: + InvalidResponse if the string cannot be matched by _DATETIME_RE. + """ + match = _DATETIME_RE.match(response) + if not match: + raise exceptions.InvalidResponse(response) - date, time = match.groups() - month, day, year = map(int, date.split('/')) - hour, minute, second = map(int, time.split(':')) + date, time = match.groups() + month, day, year = map(int, date.split('/')) + hour, minute, second = map(int, time.split(':')) - # Yes, OneTouch2's firmware is not Y2K safe. - return datetime.datetime(2000 + year, month, day, hour, minute, second) + # Yes, OneTouch2's firmware is not Y2K safe. + return datetime.datetime(2000 + year, month, day, hour, minute, second) class Device(serial.SerialDevice): - BAUDRATE = 9600 - DEFAULT_CABLE_ID = '067b:2303' # Generic PL2303 cable. + BAUDRATE = 9600 + DEFAULT_CABLE_ID = '067b:2303' # Generic PL2303 cable. - def connect(self): - return + def connect(self): + return - def disconnect(self): - return + def disconnect(self): + return - def _send_command(self, cmd): - """Send command interface. + def _send_command(self, cmd): + """Send command interface. - Args: - cmd: command and parameters to send (without newline) - """ - cmdstring = bytes('\x11\r' + cmd + '\r', 'ascii') - self.serial_.write(cmdstring) - self.serial_.flush() + Args: + cmd: command and parameters to send (without newline) + """ + cmdstring = bytes('\x11\r' + cmd + '\r', 'ascii') + self.serial_.write(cmdstring) + self.serial_.flush() - def _send_oneliner_command(self, cmd): - """Send command and read a one-line response. + def _send_oneliner_command(self, cmd): + """Send command and read a one-line response. - Args: - cmd: command and parameters to send (without newline) + Args: + cmd: command and parameters to send (without newline) - Returns: - A single line of text that the glucometer responds, without the checksum. - """ - self._send_command(cmd) + Returns: + A single line of text that the glucometer responds, without the checksum. + """ + self._send_command(cmd) - line = self.serial_.readline().decode('ascii') - return _validate_and_strip_checksum(line) + line = self.serial_.readline().decode('ascii') + return _validate_and_strip_checksum(line) - def get_meter_info(self): - """Fetch and parses the device information. + def get_meter_info(self): + """Fetch and parses the device information. - Returns: - A common.MeterInfo object. - """ - return common.MeterInfo( - 'OneTouch Ultra 2 glucometer', - serial_number=self.get_serial_number(), - version_info=( - 'Software version: ' + self.get_version(),), - native_unit=self.get_glucose_unit()) + Returns: + A common.MeterInfo object. + """ + return common.MeterInfo( + 'OneTouch Ultra 2 glucometer', + serial_number=self.get_serial_number(), + version_info=( + 'Software version: ' + self.get_version(),), + native_unit=self.get_glucose_unit()) - def get_version(self): - """Returns an identifier of the firmware version of the glucometer. + def get_version(self): + """Returns an identifier of the firmware version of the glucometer. - Returns: - The software version returned by the glucometer, such as - "P02.00.00 30/08/06". - """ - response = self._send_oneliner_command('DM?') + Returns: + The software version returned by the glucometer, such as + "P02.00.00 30/08/06". + """ + response = self._send_oneliner_command('DM?') - if response[0] != '?': - raise exceptions.InvalidResponse(response) + if response[0] != '?': + raise exceptions.InvalidResponse(response) - return response[1:] + return response[1:] - _SERIAL_NUMBER_RE = re.compile('^@ "([A-Z0-9]{9})"$') + _SERIAL_NUMBER_RE = re.compile('^@ "([A-Z0-9]{9})"$') - def get_serial_number(self): - """Retrieve the serial number of the device. + def get_serial_number(self): + """Retrieve the serial number of the device. - Returns: - A string representing the serial number of the device. + Returns: + A string representing the serial number of the device. - Raises: - exceptions.InvalidResponse: if the DM@ command returns a string not - matching _SERIAL_NUMBER_RE. - InvalidSerialNumber: if the returned serial number does not match - the OneTouch2 device as per specs. - """ - response = self._send_oneliner_command('DM@') + Raises: + exceptions.InvalidResponse: if the DM@ command returns a string not + matching _SERIAL_NUMBER_RE. + InvalidSerialNumber: if the returned serial number does not match + the OneTouch2 device as per specs. + """ + response = self._send_oneliner_command('DM@') - match = self._SERIAL_NUMBER_RE.match(response) - if not match: - raise exceptions.InvalidResponse(response) + match = self._SERIAL_NUMBER_RE.match(response) + if not match: + raise exceptions.InvalidResponse(response) - serial_number = match.group(1) + serial_number = match.group(1) - # 'Y' at the far right of the serial number is the indication of a OneTouch - # Ultra2 device, as per specs. - if serial_number[-1] != 'Y': - raise lifescan.InvalidSerialNumber(serial_number) + # 'Y' at the far right of the serial number is the indication of a OneTouch + # Ultra2 device, as per specs. + if serial_number[-1] != 'Y': + raise lifescan.InvalidSerialNumber(serial_number) - return serial_number + return serial_number - def get_datetime(self): - """Returns the current date and time for the glucometer. + def get_datetime(self): + """Returns the current date and time for the glucometer. - Returns: - A datetime object built according to the returned response. - """ - response = self._send_oneliner_command('DMF') - return _parse_datetime(response[2:]) + Returns: + A datetime object built according to the returned response. + """ + response = self._send_oneliner_command('DMF') + return _parse_datetime(response[2:]) - def set_datetime(self, date=datetime.datetime.now()): - """Sets the date and time of the glucometer. + def set_datetime(self, date=datetime.datetime.now()): + """Sets the date and time of the glucometer. - Args: - date: The value to set the date/time of the glucometer to. If none is - given, the current date and time of the computer is used. + Args: + date: The value to set the date/time of the glucometer to. If none is + given, the current date and time of the computer is used. - Returns: - A datetime object built according to the returned response. - """ - response = self._send_oneliner_command( - 'DMT' + date.strftime('%m/%d/%y %H:%M:%S')) + Returns: + A datetime object built according to the returned response. + """ + response = self._send_oneliner_command( + 'DMT' + date.strftime('%m/%d/%y %H:%M:%S')) - return _parse_datetime(response[2:]) + return _parse_datetime(response[2:]) - def zero_log(self): - """Zeros out the data log of the device. + def zero_log(self): + """Zeros out the data log of the device. - This function will clear the memory of the device deleting all the readings - in an irrecoverable way. - """ - response = self._send_oneliner_command('DMZ') - if response != 'Z': - raise exceptions.InvalidResponse(response) + This function will clear the memory of the device deleting all the readings + in an irrecoverable way. + """ + response = self._send_oneliner_command('DMZ') + if response != 'Z': + raise exceptions.InvalidResponse(response) - _GLUCOSE_UNIT_RE = re.compile(r'^SU\?,"(MG/DL |MMOL/L)"') + _GLUCOSE_UNIT_RE = re.compile(r'^SU\?,"(MG/DL |MMOL/L)"') - def get_glucose_unit(self): - """Returns a constant representing the unit displayed by the meter. + def get_glucose_unit(self): + """Returns a constant representing the unit displayed by the meter. - Returns: - common.Unit.MG_DL: if the glucometer displays in mg/dL - common.Unit.MMOL_L: if the glucometer displays in mmol/L + Returns: + common.Unit.MG_DL: if the glucometer displays in mg/dL + common.Unit.MMOL_L: if the glucometer displays in mmol/L - Raises: - exceptions.InvalidGlucoseUnit: if the unit is not recognized + Raises: + exceptions.InvalidGlucoseUnit: if the unit is not recognized - OneTouch meters will always dump data in mg/dL because that's their internal - storage. They will then provide a separate method to read the unit used for - display. This is not settable by the user in all modern meters. + OneTouch meters will always dump data in mg/dL because that's their internal + storage. They will then provide a separate method to read the unit used for + display. This is not settable by the user in all modern meters. - """ - response = self._send_oneliner_command('DMSU?') + """ + response = self._send_oneliner_command('DMSU?') - match = self._GLUCOSE_UNIT_RE.match(response) - unit = match.group(1) + match = self._GLUCOSE_UNIT_RE.match(response) + unit = match.group(1) - if unit == 'MG/DL ': - return common.Unit.MG_DL - elif unit == 'MMOL/L': - return common.Unit.MMOL_L - else: - raise exceptions.InvalidGlucoseUnit(string) + if unit == 'MG/DL ': + return common.Unit.MG_DL + elif unit == 'MMOL/L': + return common.Unit.MMOL_L + else: + raise exceptions.InvalidGlucoseUnit(string) - def get_readings(self): - """Iterates over the reading values stored in the glucometer. + def get_readings(self): + """Iterates over the reading values stored in the glucometer. - Args: - unit: The glucose unit to use for the output. + Args: + unit: The glucose unit to use for the output. - Yields: - A tuple (date, value) of the readings in the glucometer. The value is a - floating point in the unit specified; if no unit is specified, the default - unit in the glucometer will be used. + Yields: + A tuple (date, value) of the readings in the glucometer. The value is a + floating point in the unit specified; if no unit is specified, the default + unit in the glucometer will be used. - Raises: - exceptions.InvalidResponse: if the response does not match what expected. - """ - self._send_command('DMP') - data = self.serial_.readlines() + Raises: + exceptions.InvalidResponse: if the response does not match what expected. + """ + self._send_command('DMP') + data = self.serial_.readlines() - header = data.pop(0).decode('ascii') - match = _DUMP_HEADER_RE.match(header) - if not match: - raise exceptions.InvalidResponse(header) + header = data.pop(0).decode('ascii') + match = _DUMP_HEADER_RE.match(header) + if not match: + raise exceptions.InvalidResponse(header) - count = int(match.group(1)) - assert count == len(data) + count = int(match.group(1)) + assert count == len(data) - for line in data: - line = _validate_and_strip_checksum(line.decode('ascii')) + for line in data: + line = _validate_and_strip_checksum(line.decode('ascii')) - match = _DUMP_LINE_RE.match(line) - if not match: - raise exceptions.InvalidResponse(line) + match = _DUMP_LINE_RE.match(line) + if not match: + raise exceptions.InvalidResponse(line) - line_data = match.groupdict() + line_data = match.groupdict() - date = _parse_datetime(line_data['datetime']) - meal = _MEAL_CODES[line_data['meal']] - comment = _COMMENT_CODES[line_data['comment']] + date = _parse_datetime(line_data['datetime']) + meal = _MEAL_CODES[line_data['meal']] + comment = _COMMENT_CODES[line_data['comment']] - # OneTouch2 always returns the data in mg/dL even if the glucometer is set - # to mmol/L, so there is no conversion required. - yield common.GlucoseReading( - date, float(line_data['value']), meal=meal, comment=comment) + # OneTouch2 always returns the data in mg/dL even if the glucometer is set + # to mmol/L, so there is no conversion required. + yield common.GlucoseReading( + date, float(line_data['value']), meal=meal, comment=comment) |