From 90e9a2d81d555bd916f57d7538881966e77543e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Elio=20Petten=C3=B2?= Date: Mon, 16 Jan 2017 22:07:42 +0000 Subject: LifeScan devices: move lifescan_common to the support directory. This makes it easier to figure out which files represent drivers, and which ones are per-vendor support modules. --- glucometerutils/drivers/lifescan_common.py | 51 ------------------------------ glucometerutils/drivers/otultra2.py | 6 ++-- glucometerutils/drivers/otultraeasy.py | 4 +-- glucometerutils/drivers/otverio2015.py | 26 +++++++-------- glucometerutils/support/lifescan.py | 51 ++++++++++++++++++++++++++++++ test/test_otultra2.py | 8 ++--- test/test_otultraeasy.py | 6 ++-- 7 files changed, 76 insertions(+), 76 deletions(-) delete mode 100644 glucometerutils/drivers/lifescan_common.py create mode 100644 glucometerutils/support/lifescan.py diff --git a/glucometerutils/drivers/lifescan_common.py b/glucometerutils/drivers/lifescan_common.py deleted file mode 100644 index 1f8234d..0000000 --- a/glucometerutils/drivers/lifescan_common.py +++ /dev/null @@ -1,51 +0,0 @@ -# -*- coding: utf-8 -*- -"""Common utility functions for LifeScan meters.""" - -__author__ = 'Diego Elio Pettenò' -__email__ = 'flameeyes@flameeyes.eu' -__copyright__ = 'Copyright © 2013, Diego Elio Pettenò' -__license__ = 'MIT' - -from glucometerutils import exceptions - - -class MissingChecksum(exceptions.InvalidResponse): - """The response misses the expected 4-digits checksum.""" - def __init__(self, response): - self.message = 'Response is missing checksum: %s' % response - - -class InvalidSerialNumber(exceptions.Error): - """The serial number is not as expected.""" - def __init__(self, serial_number): - self.message = 'Serial number %s is invalid.' % serial_number - - -class MalformedCommand(exceptions.InvalidResponse): - def __init__(self, message): - exceptions.InvalidResponse.__init__( - self, 'Malformed command: %s' % message) - - -def crc_ccitt(data): - """Calculate the CRC-16-CCITT with LifeScan's common seed. - - Args: - data: (bytes) the data to calculate the checksum of - - Returns: - (int) The 16-bit integer value of the CRC-CCITT calculated. - - This function uses the non-default 0xFFFF seed as used by multiple - LifeScan meters. - """ - crc = 0xffff - - for byte in data: - crc = (crc >> 8) & 0xffff | (crc << 8) & 0xffff - crc ^= byte - crc ^= (crc & 0xff) >> 4 - crc ^= (((crc << 8) & 0xffff) << 4) & 0xffff - crc ^= (crc & 0xff) << 5 - - return (crc & 0xffff) diff --git a/glucometerutils/drivers/otultra2.py b/glucometerutils/drivers/otultra2.py index b484f6b..c87d270 100644 --- a/glucometerutils/drivers/otultra2.py +++ b/glucometerutils/drivers/otultra2.py @@ -13,7 +13,7 @@ import serial from glucometerutils import common from glucometerutils import exceptions -from glucometerutils.drivers import lifescan_common +from glucometerutils.support import lifescan # The following two hashes are taken directly from LifeScan's documentation _MEAL_CODES = { @@ -77,7 +77,7 @@ def _validate_and_strip_checksum(line): match = _RESPONSE_MATCH.match(line) if not match: - raise lifescan_common.MissingChecksum(line) + raise lifescan.MissingChecksum(line) response, checksum_string = match.groups() @@ -211,7 +211,7 @@ class Device(object): # '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_common.InvalidSerialNumber(serial_number) + raise lifescan.InvalidSerialNumber(serial_number) return serial_number diff --git a/glucometerutils/drivers/otultraeasy.py b/glucometerutils/drivers/otultraeasy.py index 4a61fe6..d3d2d67 100644 --- a/glucometerutils/drivers/otultraeasy.py +++ b/glucometerutils/drivers/otultraeasy.py @@ -16,7 +16,7 @@ import serial from glucometerutils import common from glucometerutils import exceptions -from glucometerutils.drivers import lifescan_common +from glucometerutils.support import lifescan _STX = 0x02 _ETX = 0x03 @@ -132,7 +132,7 @@ class _Packet(object): @property def checksum(self): - return lifescan_common.crc_ccitt(self.cmd[:_IDX_CHECKSUM].tobytes()) + return lifescan.crc_ccitt(self.cmd[:_IDX_CHECKSUM].tobytes()) @property def acknowledge(self): diff --git a/glucometerutils/drivers/otverio2015.py b/glucometerutils/drivers/otverio2015.py index 3e4c81b..b5e529d 100644 --- a/glucometerutils/drivers/otverio2015.py +++ b/glucometerutils/drivers/otverio2015.py @@ -19,7 +19,7 @@ from pyscsi.pyscsi.scsi_device import SCSIDevice from glucometerutils import common from glucometerutils import exceptions -from glucometerutils.drivers import lifescan_common +from glucometerutils.support import lifescan # Match the same values in the otultraeasy driver. _STX = 0x02 @@ -63,19 +63,19 @@ def _extract_message(register): """Parse the message preamble and verify checksums.""" stx, length = _STRUCT_PREAMBLE.unpack_from(register) if stx != _STX: - raise lifescan_common.MalformedCommand( + raise lifescan.MalformedCommand( 'invalid STX byte: %02x' % stx) if length > _REGISTER_SIZE: - raise lifescan_common.MalformedCommand( + raise lifescan.MalformedCommand( 'invalid length: %d > REGISTER_SIZE' % length) # 2 is the length of the checksum, so it should be ignored. - calculated_checksum = lifescan_common.crc_ccitt(register[:(length-2)]) + calculated_checksum = lifescan.crc_ccitt(register[:(length-2)]) coda_offset = length - _STRUCT_CODA.size etx, encoded_checksum = _STRUCT_CODA.unpack_from(register[coda_offset:]) if etx != _ETX: - raise lifescan_common.MalformedCommand( + raise lifescan.MalformedCommand( 'invalid ETX byte: %02x' % etx) if encoded_checksum != calculated_checksum: raise exceptions.InvalidChecksum(encoded_checksum, calculated_checksum) @@ -88,7 +88,7 @@ def _encode_message(cmd): length = len(cmd) + _STRUCT_PREAMBLE.size + _STRUCT_CODA.size preamble = _STRUCT_PREAMBLE.pack(_STX, length) message = preamble + cmd + bytes((_ETX,)) - checksum = _STRUCT_CHECKSUM.pack(lifescan_common.crc_ccitt(message)) + checksum = _STRUCT_CHECKSUM.pack(lifescan.crc_ccitt(message)) # Pad the message to match the size of the register. return message + checksum + bytes( @@ -143,7 +143,7 @@ class Device(object): def _query_string(self, query_key): response = self._send_message(_QUERY_REQUEST + query_key, 3) if response[0:2] != b'\x04\06': - raise lifescan_common.MalformedCommand( + raise lifescan.MalformedCommand( 'invalid response, expected 04 06, received %02x %02x' % ( response[0], response[1])) # Strings are encoded in wide characters (LE), but they should @@ -155,7 +155,7 @@ class Device(object): response = self._send_message( _READ_PARAMETER_REQUEST + parameter_key, 4) if response[0:2] != b'\x03\x06': - raise lifescan_common.MalformedCommand( + raise lifescan.MalformedCommand( 'invalid response, expected 03 06, received %02x %02x' % ( response[0], response[1])) return response[2:] @@ -169,7 +169,7 @@ class Device(object): def get_datetime(self): response = self._send_message(_READ_RTC_REQUEST, 3) if response[0:2] != b'\x04\06': - raise lifescan_common.MalformedCommand( + raise lifescan.MalformedCommand( 'invalid response, expected 04 06, received %02x %02x' % ( response[0], response[1])) (timestamp,) = _STRUCT_TIMESTAMP.unpack(response[2:]) @@ -184,7 +184,7 @@ class Device(object): response = self._send_message(_WRITE_RTC_REQUEST + timestamp_bytes, 3) if response[0:2] != b'\x04\06': - raise lifescan_common.MalformedCommand( + raise lifescan.MalformedCommand( 'invalid response, expected 04 06, received %02x %02x' % ( response[0], response[1])) @@ -195,14 +195,14 @@ class Device(object): def zero_log(self): response = self._send_message(_MEMORY_ERASE_REQUEST, 3) if response[0:2] != b'\x04\06': - raise lifescan_common.MalformedCommand( + raise lifescan.MalformedCommand( 'invalid response, expected 04 06, received %02x %02x' % ( response[0], response[1])) def _get_reading_count(self): response = self._send_message(_READ_RECORD_COUNT_REQUEST, 3) if response[0:2] != b'\x04\06': - raise lifescan_common.MalformedCommand( + raise lifescan.MalformedCommand( 'invalid response, expected 04 06, received %02x %02x' % ( response[0], response[1])) @@ -224,7 +224,7 @@ class Device(object): _READ_RECORD_REQUEST_SUFFIX) response = self._send_message(request, 3) if response[0:2] != b'\x04\06': - raise lifescan_common.MalformedCommand( + raise lifescan.MalformedCommand( 'invalid response, expected 04 06, received %02x %02x' % ( response[0], response[1])) diff --git a/glucometerutils/support/lifescan.py b/glucometerutils/support/lifescan.py new file mode 100644 index 0000000..1f8234d --- /dev/null +++ b/glucometerutils/support/lifescan.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +"""Common utility functions for LifeScan meters.""" + +__author__ = 'Diego Elio Pettenò' +__email__ = 'flameeyes@flameeyes.eu' +__copyright__ = 'Copyright © 2013, Diego Elio Pettenò' +__license__ = 'MIT' + +from glucometerutils import exceptions + + +class MissingChecksum(exceptions.InvalidResponse): + """The response misses the expected 4-digits checksum.""" + def __init__(self, response): + self.message = 'Response is missing checksum: %s' % response + + +class InvalidSerialNumber(exceptions.Error): + """The serial number is not as expected.""" + def __init__(self, serial_number): + self.message = 'Serial number %s is invalid.' % serial_number + + +class MalformedCommand(exceptions.InvalidResponse): + def __init__(self, message): + exceptions.InvalidResponse.__init__( + self, 'Malformed command: %s' % message) + + +def crc_ccitt(data): + """Calculate the CRC-16-CCITT with LifeScan's common seed. + + Args: + data: (bytes) the data to calculate the checksum of + + Returns: + (int) The 16-bit integer value of the CRC-CCITT calculated. + + This function uses the non-default 0xFFFF seed as used by multiple + LifeScan meters. + """ + crc = 0xffff + + for byte in data: + crc = (crc >> 8) & 0xffff | (crc << 8) & 0xffff + crc ^= byte + crc ^= (crc & 0xff) >> 4 + crc ^= (((crc << 8) & 0xffff) << 4) & 0xffff + crc ^= (crc & 0xff) << 5 + + return (crc & 0xffff) diff --git a/test/test_otultra2.py b/test/test_otultra2.py index 34078e3..3099604 100644 --- a/test/test_otultra2.py +++ b/test/test_otultra2.py @@ -14,8 +14,8 @@ import mock sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -from glucometerutils.drivers import lifescan_common from glucometerutils.drivers import otultra2 +from glucometerutils.support import lifescan from glucometerutils import exceptions class TestOTUltra2(unittest.TestCase): @@ -41,7 +41,7 @@ class TestOTUltra2(unittest.TestCase): def test_missing_checksum(self): self._set_return_string('INVALID') - self.assertRaises(lifescan_common.MissingChecksum, + self.assertRaises(lifescan.MissingChecksum, self.device.get_serial_number) def test_short_response(self): @@ -59,7 +59,7 @@ class TestOTUltra2(unittest.TestCase): def test_invalid_serial_number(self): self._set_return_string('@ "12345678O" 0297\r') - self.assertRaises(lifescan_common.InvalidSerialNumber, + self.assertRaises(lifescan.InvalidSerialNumber, self.device.get_serial_number) def test_invalid_checksum(self): @@ -71,7 +71,7 @@ class TestOTUltra2(unittest.TestCase): def test_broken_checksum(self): self._set_return_string('% 13AZ\r') - self.assertRaises(lifescan_common.MissingChecksum, + self.assertRaises(lifescan.MissingChecksum, self.device.get_serial_number) if __name__ == '__main__': diff --git a/test/test_otultraeasy.py b/test/test_otultraeasy.py index 07480d2..7b91d56 100644 --- a/test/test_otultraeasy.py +++ b/test/test_otultraeasy.py @@ -15,8 +15,8 @@ import mock sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -from glucometerutils.drivers import lifescan_common from glucometerutils.drivers import otultraeasy +from glucometerutils.support import lifescan from glucometerutils import exceptions class TestOTUltraMini(unittest.TestCase): @@ -31,12 +31,12 @@ class TestOTUltraMini(unittest.TestCase): def testCrc(self): self.assertEqual( 0x41cd, - lifescan_common.crc_ccitt(b'\x02\x06\x06\x03')) + lifescan.crc_ccitt(b'\x02\x06\x06\x03')) cmd_array = array.array('B', b'\x02\x06\x08\x03') self.assertEqual( 0x62C2, - lifescan_common.crc_ccitt(cmd_array)) + lifescan.crc_ccitt(cmd_array)) def testPacketUpdateChecksum(self): packet = otultraeasy._Packet() -- cgit v1.2.3