Skip to content

Commit 254f9b3

Browse files
authored
fix: fix the retry-on-error logic (#17)
The code did not perform a retry in case a spurious I/O error occured and failed from time to time. The logic to perform a retry was already there, but it did not handle this situation properly and returned to early. Symptom: ``` > return read_device_registers(i2c_bus, reads, max_tries, timeout_ms).pop() E IndexError: pop from empty list .venv/lib/python3.11/site-packages/feeph/i2c/__init__.py:42: IndexError ------------------- Captured log call ------------------- WARNING i2c:__init__.py:88 [feeph.i2c] Failed to read register 0x03 (1/3): [Errno 121] Remote I/O error ```
1 parent 0c047ae commit 254f9b3

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

feeph/i2c/__init__.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def read_device_registers(i2c_bus: busio.I2C, reads: list[tuple[int, int, int]],
6767
if i2c_adr < 0 or i2c_adr > 255:
6868
raise ValueError(f"Provided I²C address {i2c_adr} is out of range! (allowed range: 0 <= x <= 255)")
6969
for cur_try in range(1, 1 + max_tries):
70+
is_success = False
7071
# make sure we have exclusive access to the I²C bus
7172
feeph.i2c.utility.try_lock_with_timeout(i2c_bus=i2c_bus, timeout_ms=timeout_ms)
7273
# read from the registers and unlock the bus again
@@ -83,6 +84,7 @@ def read_device_registers(i2c_bus: busio.I2C, reads: list[tuple[int, int, int]],
8384
i2c_bus.writeto_then_readfrom(address=i2c_adr, buffer_out=buf_r, buffer_in=buf_w)
8485
# TODO properly handle multi byte reads
8586
values.append(buf_w[0])
87+
is_success = True
8688
except OSError as e:
8789
# [Errno 121] Remote I/O error
8890
LH.warning("[%s] Failed to read register 0x%02X (%i/%i): %s", __name__, register, cur_try, max_tries, e)
@@ -92,7 +94,11 @@ def read_device_registers(i2c_bus: busio.I2C, reads: list[tuple[int, int, int]],
9294
time.sleep(0.1)
9395
finally:
9496
i2c_bus.unlock()
95-
return values
97+
# are we done yet?
98+
if is_success:
99+
return values
100+
else:
101+
LH.debug("Failed to process all reads. Retrying.")
96102
else:
97103
raise RuntimeError(f"Unable to read register 0x{register:02X} after {cur_try} attempts. Giving up.")
98104

@@ -144,6 +150,7 @@ def write_device_registers(i2c_bus: busio.I2C, writes: list[tuple[int, int, int,
144150
if i2c_adr < 0 or i2c_adr > 255:
145151
raise ValueError(f"Provided I²C address {i2c_adr} is out of range! (allowed range: 0 <= x <= 255)")
146152
for cur_try in range(1, 1 + max_tries):
153+
is_success = False
147154
# make sure we have exclusive access to the I²C bus
148155
feeph.i2c.utility.try_lock_with_timeout(i2c_bus=i2c_bus, timeout_ms=timeout_ms)
149156
# write to the registers and unlock the bus again
@@ -158,7 +165,7 @@ def write_device_registers(i2c_bus: busio.I2C, writes: list[tuple[int, int, int,
158165
buf[1] = value & 0xFF
159166
# TODO properly handle multi byte reads
160167
i2c_bus.writeto(address=i2c_adr, buffer=buf)
161-
return
168+
is_success = True
162169
except OSError as e:
163170
# [Errno 121] Remote I/O error
164171
LH.warning("[%s] Failed to read register 0x%02X (%i/%i): %s", __name__, register, cur_try, max_tries, e)
@@ -168,5 +175,10 @@ def write_device_registers(i2c_bus: busio.I2C, writes: list[tuple[int, int, int,
168175
time.sleep(0.1)
169176
finally:
170177
i2c_bus.unlock()
178+
# are we done yet?
179+
if is_success:
180+
return
181+
else:
182+
LH.debug("Failed to process all writes. Retrying.")
171183
else:
172184
raise RuntimeError(f"Unable to read register 0x{register:02X} after {cur_try} attempts. Giving up.")

0 commit comments

Comments
 (0)