Skip to content

Commit

Permalink
_get_eeprom_info to get the name and size of the eeprom
Browse files Browse the repository at this point in the history
  • Loading branch information
vegano1 committed Jul 6, 2023
1 parent c55e2cf commit c082230
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 7 deletions.
4 changes: 4 additions & 0 deletions hardware/opentrons_hardware/drivers/eeprom/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
EEPROMDriver,
DEFAULT_BUS,
DEFAULT_ADDRESS,
DEFAULT_READ_SIZE,
)

from .types import (
PropId,
PropType,
Property,
EEPROMData,
FORMAT_VERSION,
)


Expand All @@ -22,4 +24,6 @@
"EEPROMDriver",
"DEFAULT_BUS",
"DEFAULT_ADDRESS",
"DEFAULT_READ_SIZE",
"FORMAT_VERSION",
]
37 changes: 35 additions & 2 deletions hardware/opentrons_hardware/drivers/eeprom/eeprom.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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."""
Expand Down Expand Up @@ -89,14 +102,19 @@ 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:
"""Opens up the eeprom file and returns the file descriptor."""
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:
Expand Down Expand Up @@ -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:
Expand Down
6 changes: 5 additions & 1 deletion hardware/opentrons_hardware/drivers/eeprom/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
20 changes: 16 additions & 4 deletions hardware/tests/opentrons_hardware/drivers/eeprom/test_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand All @@ -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
Expand Down

0 comments on commit c082230

Please sign in to comment.