Skip to content

Add missing type annotations #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 3, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 38 additions & 34 deletions adafruit_tsl2561.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@
from adafruit_bus_device.i2c_device import I2CDevice
from micropython import const

try:
from typing import Optional, Tuple, Union
from busio import I2C
except ImportError:
pass

__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_TSL2561.git"

Expand Down Expand Up @@ -60,66 +66,66 @@
class TSL2561:
"""Class which provides interface to TSL2561 light sensor."""

def __init__(self, i2c, address=_DEFAULT_ADDRESS):
def __init__(self, i2c: I2C, address: int = _DEFAULT_ADDRESS) -> None:
self.buf = bytearray(3)
self.i2c_device = I2CDevice(i2c, address)
partno, revno = self.chip_id
# data sheet says TSL2561 = 0001, reality says 0101
if not partno == 5:
raise RuntimeError(
"Failed to find TSL2561! Part 0x%x Rev 0x%x" % (partno, revno)
f"Failed to find TSL2561! Part {hex(partno)} Rev {hex(revno)}"
)
self.enabled = True

@property
def chip_id(self):
def chip_id(self) -> Tuple[int, int]:
"""A tuple containing the part number and the revision number."""
chip_id = self._read_register(_REGISTER_ID)
partno = (chip_id >> 4) & 0x0F
revno = chip_id & 0x0F
return (partno, revno)

@property
def enabled(self):
def enabled(self) -> bool:
"""The state of the sensor."""
return (self._read_register(_REGISTER_CONTROL) & 0x03) != 0

@enabled.setter
def enabled(self, enable):
def enabled(self, enable: bool) -> None:
"""Enable or disable the sensor."""
if enable:
self._enable()
else:
self._disable()

@property
def lux(self):
def lux(self) -> Optional[float]:
"""The computed lux value or None when value is not computable."""
return self._compute_lux()

@property
def broadband(self):
def broadband(self) -> int:
"""The broadband channel value."""
return self._read_broadband()

@property
def infrared(self):
def infrared(self) -> int:
"""The infrared channel value."""
return self._read_infrared()

@property
def luminosity(self):
def luminosity(self) -> Tuple[int, int]:
"""The overall luminosity as a tuple containing the broadband
channel and the infrared channel value."""
return (self.broadband, self.infrared)

@property
def gain(self):
def gain(self) -> int:
"""The gain. 0:1x, 1:16x."""
return self._read_register(_REGISTER_TIMING) >> 4 & 0x01

@gain.setter
def gain(self, value):
def gain(self, value: int) -> None:
"""Set the gain. 0:1x, 1:16x."""
value &= 0x01
value <<= 4
Expand All @@ -130,13 +136,13 @@ def gain(self, value):
i2c.write(self.buf, end=2)

@property
def integration_time(self):
def integration_time(self) -> int:
"""The integration time. 0:13.7ms, 1:101ms, 2:402ms, or 3:manual"""
current = self._read_register(_REGISTER_TIMING)
return current & 0x03

@integration_time.setter
def integration_time(self, value):
def integration_time(self, value: int) -> None:
"""Set the integration time. 0:13.7ms, 1:101ms, 2:402ms, or 3:manual."""
value &= 0x03
current = self._read_register(_REGISTER_TIMING)
Expand All @@ -146,50 +152,50 @@ def integration_time(self, value):
i2c.write(self.buf, end=2)

@property
def threshold_low(self):
def threshold_low(self) -> int:
"""The low light interrupt threshold level."""
low, high = self._read_register(_REGISTER_TH_LOW, 2)
return high << 8 | low

@threshold_low.setter
def threshold_low(self, value):
def threshold_low(self, value: int) -> None:
self.buf[0] = _COMMAND_BIT | _WORD_BIT | _REGISTER_TH_LOW
self.buf[1] = value & 0xFF
self.buf[2] = (value >> 8) & 0xFF
with self.i2c_device as i2c:
i2c.write(self.buf)

@property
def threshold_high(self):
def threshold_high(self) -> int:
"""The upper light interrupt threshold level."""
low, high = self._read_register(_REGISTER_TH_HIGH, 2)
return high << 8 | low

@threshold_high.setter
def threshold_high(self, value):
def threshold_high(self, value: int) -> None:
self.buf[0] = _COMMAND_BIT | _WORD_BIT | _REGISTER_TH_HIGH
self.buf[1] = value & 0xFF
self.buf[2] = (value >> 8) & 0xFF
with self.i2c_device as i2c:
i2c.write(self.buf)

@property
def cycles(self):
def cycles(self) -> int:
"""The number of integration cycles for which an out of bounds
value must persist to cause an interrupt."""
value = self._read_register(_REGISTER_INT_CTRL)
return value & 0x0F

@cycles.setter
def cycles(self, value):
def cycles(self, value: int) -> None:
current = self._read_register(_REGISTER_INT_CTRL)
self.buf[0] = _COMMAND_BIT | _REGISTER_INT_CTRL
self.buf[1] = current | (value & 0x0F)
with self.i2c_device as i2c:
i2c.write(self.buf, end=2)

@property
def interrupt_mode(self):
def interrupt_mode(self) -> int:
"""The interrupt mode selection.

==== =========================
Expand All @@ -205,20 +211,20 @@ def interrupt_mode(self):
return (self._read_register(_REGISTER_INT_CTRL) >> 4) & 0x03

@interrupt_mode.setter
def interrupt_mode(self, value):
def interrupt_mode(self, value: int) -> None:
current = self._read_register(_REGISTER_INT_CTRL)
self.buf[0] = _COMMAND_BIT | _REGISTER_INT_CTRL
self.buf[1] = (current & 0x0F) | ((value & 0x03) << 4)
with self.i2c_device as i2c:
i2c.write(self.buf, end=2)

def clear_interrupt(self):
def clear_interrupt(self) -> None:
"""Clears any pending interrupt."""
self.buf[0] = 0xC0
with self.i2c_device as i2c:
i2c.write(self.buf, end=1)

def _compute_lux(self):
def _compute_lux(self) -> Optional[float]:
"""Based on datasheet for FN package."""
ch0, ch1 = self.luminosity
if ch0 == 0:
Expand Down Expand Up @@ -247,36 +253,34 @@ def _compute_lux(self):
lux *= _TIME_SCALE[self.integration_time]
return lux

def _enable(self):
def _enable(self) -> None:
self._write_control_register(_CONTROL_POWERON)

def _disable(self):
def _disable(self) -> None:
self._write_control_register(_CONTROL_POWEROFF)

def _read_register(self, reg, count=1):
# pylint: disable=no-else-return
# Disable should be removed when refactor can be tested
def _read_register(self, reg: int, count: int = 1) -> Union[int, Tuple[int, int]]:
if count not in (1, 2):
raise RuntimeError("Can only read up to 2 consecutive registers")
self.buf[0] = _COMMAND_BIT | reg
if count == 2:
self.buf[0] |= _WORD_BIT
with self.i2c_device as i2c:
i2c.write_then_readinto(self.buf, self.buf, out_end=1, in_start=1)
if count == 1:
return self.buf[1]
elif count == 2:
return self.buf[1], self.buf[2]
return None
return self.buf[1], self.buf[2]

def _write_control_register(self, reg):
def _write_control_register(self, reg: int) -> None:
self.buf[0] = _COMMAND_BIT | _REGISTER_CONTROL
self.buf[1] = reg
with self.i2c_device as i2c:
i2c.write(self.buf, end=2)

def _read_broadband(self):
def _read_broadband(self) -> int:
low, high = self._read_register(_REGISTER_CHAN0_LOW, 2)
return high << 8 | low

def _read_infrared(self):
def _read_infrared(self) -> int:
low, high = self._read_register(_REGISTER_CHAN1_LOW, 2)
return high << 8 | low