From c082230de451bec7aa5599cbc0639d022e456902 Mon Sep 17 00:00:00 2001 From: vegano1 Date: Thu, 6 Jul 2023 14:16:47 -0400 Subject: [PATCH] _get_eeprom_info to get the name and size of the eeprom --- .../drivers/eeprom/__init__.py | 4 ++ .../drivers/eeprom/eeprom.py | 37 ++++++++++++++++++- .../drivers/eeprom/types.py | 6 ++- .../drivers/eeprom/test_driver.py | 20 ++++++++-- 4 files changed, 60 insertions(+), 7 deletions(-) diff --git a/hardware/opentrons_hardware/drivers/eeprom/__init__.py b/hardware/opentrons_hardware/drivers/eeprom/__init__.py index 668dc63a238..dc6fedfd681 100644 --- a/hardware/opentrons_hardware/drivers/eeprom/__init__.py +++ b/hardware/opentrons_hardware/drivers/eeprom/__init__.py @@ -4,6 +4,7 @@ EEPROMDriver, DEFAULT_BUS, DEFAULT_ADDRESS, + DEFAULT_READ_SIZE, ) from .types import ( @@ -11,6 +12,7 @@ PropType, Property, EEPROMData, + FORMAT_VERSION, ) @@ -22,4 +24,6 @@ "EEPROMDriver", "DEFAULT_BUS", "DEFAULT_ADDRESS", + "DEFAULT_READ_SIZE", + "FORMAT_VERSION", ] diff --git a/hardware/opentrons_hardware/drivers/eeprom/eeprom.py b/hardware/opentrons_hardware/drivers/eeprom/eeprom.py index 7cf26494386..486b626afa4 100644 --- a/hardware/opentrons_hardware/drivers/eeprom/eeprom.py +++ b/hardware/opentrons_hardware/drivers/eeprom/eeprom.py @@ -1,5 +1,6 @@ """Module to read/write to the eeprom on the Flex SOM.""" +import re import os import logging from datetime import datetime @@ -50,15 +51,27 @@ def __init__( self._eeprom_path = eeprom_path or Path( f"/sys/bus/i2c/devices/{bus}-{address}/eeprom" ) + self._size = 0 + self._name = "" self._eeprom_fd = -1 self._eeprom_data: EEPROMData = EEPROMData() self._properties: Set[Property] = set() @property def name(self) -> str: - """The name of the i2c device.""" + """The name of this eeprom device.""" + return self._name + + @property + def address(self) -> str: + """The address of the i2c device.""" return f"{self._bus}-{self._address}" + @property + def size(self) -> int: + """The size in bytes of the eeprom.""" + return self._size + @property def data(self) -> EEPROMData: """Object representing the serialized data stored in the eeprom.""" @@ -89,7 +102,11 @@ def __del__(self) -> None: def setup(self) -> None: """Setup the class and serialize the eeprom data.""" + # Open a file descriptor for the eeprom self._eeprom_fd = self.open() + # Get the eeeprom metadata + self._name, self._size = self._get_eeprom_info() + # Read and serialize eeprom data self.property_read() def open(self) -> int: @@ -97,6 +114,7 @@ def open(self) -> int: if self._eeprom_fd > 0: logger.warning("File descriptor already opened for eeprom") return self._eeprom_fd + try: self._eeprom_fd = os.open(self._eeprom_path, os.O_RDWR) except OSError: @@ -198,10 +216,25 @@ def _write(self, data: bytes, address: int = 0) -> int: return os.write(self._eeprom_fd, data) except TimeoutError: logging.error( - f"Could not write data to eeprom {self.name}, make sure the write bit is low." + f"Could not write data to eeprom {self.address}, make sure the write bit is low." ) raise + def _get_eeprom_info(self) -> Tuple[str, int]: + """This will get the name and size in bytes of the eeprom.""" + name = "" + size = 0 + eeprom_name = self._eeprom_path.parent / "name" + if os.path.exists(eeprom_name): + with open(eeprom_name) as fh: + name = fh.read().strip() + match = re.match(r"24c([\d]+)", name) + if match: + # The eeprom size is in kbytes so we need to + # multiply by 128 to get the bytes + size = int(match[1]) * 128 + return name, size + def _populate_data(self) -> EEPROMData: """This will create and populate the EEPROMData object.""" for prop in self._properties: diff --git a/hardware/opentrons_hardware/drivers/eeprom/types.py b/hardware/opentrons_hardware/drivers/eeprom/types.py index c44a024251f..64704cacaf7 100644 --- a/hardware/opentrons_hardware/drivers/eeprom/types.py +++ b/hardware/opentrons_hardware/drivers/eeprom/types.py @@ -6,6 +6,10 @@ from typing import Any, Optional +# The version of the properties format +FORMAT_VERSION = 1 + + # NOTE: a serialized property can be up-to 255 (0xff) bytes long, # this includes the property id (1b) + data length (1b) + data (1-253b) MAX_DATA_LEN = 253 @@ -59,7 +63,7 @@ class Property: class EEPROMData: """Dataclass that represents the serialized data from the eeprom.""" - format_version: int = 1 + format_version: int = FORMAT_VERSION serial_number: Optional[str] = None machine_type: Optional[str] = None machine_version: Optional[str] = None diff --git a/hardware/tests/opentrons_hardware/drivers/eeprom/test_driver.py b/hardware/tests/opentrons_hardware/drivers/eeprom/test_driver.py index ef821a8927d..ccb6485b8a9 100644 --- a/hardware/tests/opentrons_hardware/drivers/eeprom/test_driver.py +++ b/hardware/tests/opentrons_hardware/drivers/eeprom/test_driver.py @@ -19,10 +19,16 @@ @pytest.fixture def eeprom_api() -> Generator[EEPROMDriver, None, None]: - """Mock out OT3GPIO""" - with tempfile.NamedTemporaryFile() as eeprom_path: + """Mock out OT3GPIO and create a temp /eeprom and /name files.""" + with tempfile.TemporaryDirectory() as eeprom_dir: + # create eeprom and name files + eeprom_path = Path(eeprom_dir) / "eeprom" + eeprom_name_path = eeprom_path.parent / "name" + with open(eeprom_path, "wb"), open(eeprom_name_path, "w") as fh: + # write we can get the name and size of the eeprom + fh.write("24c128") gpio = mock.Mock(spec=OT3GPIO) - yield EEPROMDriver(gpio, eeprom_path=Path(eeprom_path.name)) + yield EEPROMDriver(gpio, eeprom_path=eeprom_path) def test_eeprom_setup(eeprom_api: EEPROMDriver) -> None: @@ -32,6 +38,8 @@ def test_eeprom_setup(eeprom_api: EEPROMDriver) -> None: fh.write(b"\x02\x11FLXA1020230602001") # Make sure we dont have any data loaded yet + assert eeprom_api._name == "" + assert eeprom_api._size == 0 assert eeprom_api._eeprom_fd == -1 assert len(eeprom_api._properties) == 0 assert eeprom_api.data.serial_number is None @@ -43,7 +51,11 @@ def test_eeprom_setup(eeprom_api: EEPROMDriver) -> None: # call the setup function eeprom_api.setup() - # We know have a file descriptor pointing to the eeprom + # We now have the name and size of the eeprom + assert eeprom_api.name == "24c128" + assert eeprom_api.size == 16384 + + # We now have a file descriptor pointing to the eeprom assert eeprom_api._eeprom_fd != -1 # As well as some properties the setup function deserialized assert len(eeprom_api._properties) == 1