diff --git a/adafruit_emc2101/__init__.py b/adafruit_emc2101/__init__.py index f8116d7..d8289a4 100644 --- a/adafruit_emc2101/__init__.py +++ b/adafruit_emc2101/__init__.py @@ -39,6 +39,12 @@ from adafruit_emc2101 import emc2101_regs +try: + from typing import Tuple + from busio import I2C +except ImportError: + pass + __version__ = "0.0.0+auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EMC2101.git" @@ -175,7 +181,7 @@ class to add those features, at the cost of increased memory usage. """Set whether spin-up is aborted if measured speed is lower than the limit. Ignored unless _tach_mode_enable is 1.""" - def __init__(self, i2c_bus): + def __init__(self, i2c_bus: I2C) -> None: # These devices don't ship with any other address. self.i2c_device = i2cdevice.I2CDevice(i2c_bus, emc2101_regs.I2C_ADDR) part = self._part_id @@ -186,12 +192,12 @@ def __init__(self, i2c_bus): not part in [emc2101_regs.PART_ID_EMC2101, emc2101_regs.PART_ID_EMC2101R] or mfg != emc2101_regs.MFG_ID_SMSC ): - raise RuntimeError("No EMC2101 (part={}.{})".format(part, mfg)) + raise RuntimeError(f"No EMC2101 (part={part}.{mfg})") self._full_speed_lsb = None # See _calculate_full_speed(). self.initialize() - def initialize(self): + def initialize(self) -> None: """Reset the controller to an initial default configuration""" self._tach_mode_enable = True self._enabled_forced_temp = False @@ -199,14 +205,14 @@ def initialize(self): self._calculate_full_speed() @property - def part_info(self): + def part_info(self) -> Tuple[int, int, int]: """The part information: manufacturer, part id and revision. Normally returns (0x5d, 0x16, 0x1). """ return (self._mfg_id, self._part_id, self._part_rev) @property - def devconfig(self): + def devconfig(self) -> int: """Read the main device config register. See the CONFIG_* bit definitions in the emc2101_regs module, or refer to the datasheet for more detail. Note: this is not the Fan Config @@ -215,7 +221,7 @@ def devconfig(self): return self._config @property - def devstatus(self): + def devstatus(self) -> int: """Read device status (alerts) register. See the STATUS_* bit definitions in the emc2101_regs module, or refer to the datasheet for more detail. @@ -223,7 +229,7 @@ def devstatus(self): return self._status @property - def internal_temperature(self): + def internal_temperature(self) -> int: """The temperature as measured by the EMC2101's internal 8-bit temperature sensor, which validly ranges from 0 to 85 and does not support fractions (unlike the external readings). @@ -233,7 +239,7 @@ def internal_temperature(self): return self._int_temp @property - def external_temperature(self): + def external_temperature(self) -> float: """The temperature measured using the external diode. The value is read as a fixed-point 11-bit value ranging from -64 to approx 126, with fractional part of 1/8 degree. @@ -259,7 +265,7 @@ def external_temperature(self): return full_tmp @property - def fan_speed(self): + def fan_speed(self) -> float: """The current speed in Revolutions per Minute (RPM). :return: float fan speed rounded to 2dp. @@ -270,7 +276,7 @@ def fan_speed(self): raise OSError("Connection") return round(emc2101_regs.FAN_RPM_DIVISOR / val, 2) - def _calculate_full_speed(self, pwm_f=None, dac=None): + def _calculate_full_speed(self, pwm_f: int = None, dac: int = None) -> None: """Determine the LSB value for a 100% fan setting""" if dac is None: dac = self.dac_output_enabled @@ -287,12 +293,12 @@ def _calculate_full_speed(self, pwm_f=None, dac=None): # PWM_F=0 behaves like PWM_F=1. self._full_speed_lsb = 2.0 * max(1, pwm_f) - def _speed_to_lsb(self, percentage): + def _speed_to_lsb(self, percentage: int) -> int: """Convert a fan speed percentage to a Fan Setting byte value""" return round((percentage / 100.0) * self._full_speed_lsb) @property - def manual_fan_speed(self): + def manual_fan_speed(self) -> float: """The fan speed used while the LUT is being updated and is unavailable. The speed is given as the fan's PWM duty cycle represented as a float percentage. The value roughly approximates the percentage of the fan's maximum speed. @@ -304,7 +310,7 @@ def manual_fan_speed(self): return (raw_setting / fan_speed) * 100.0 @manual_fan_speed.setter - def manual_fan_speed(self, fan_speed): + def manual_fan_speed(self, fan_speed: float) -> None: """The fan speed used while the LUT is being updated and is unavailable. The speed is given as the fan's PWM duty cycle represented as a float percentage. The value roughly approximates the percentage of the fan's maximum speed. @@ -324,13 +330,13 @@ def manual_fan_speed(self, fan_speed): self._fan_lut_prog = lut_disabled @property - def dac_output_enabled(self): + def dac_output_enabled(self) -> int: """When set, the fan control signal is output as a DC voltage instead of a PWM signal.""" return self._dac_output_enabled @dac_output_enabled.setter - def dac_output_enabled(self, value): + def dac_output_enabled(self, value: int) -> None: """When set, the fan control signal is output as a DC voltage instead of a PWM signal. Be aware that the DAC output very likely requires different hardware to the PWM output. See datasheet and examples for info. @@ -339,7 +345,7 @@ def dac_output_enabled(self, value): self._calculate_full_speed(dac=value) @property - def lut_enabled(self): + def lut_enabled(self) -> bool: """Enable or disable the internal look up table used to map a given temperature to a fan speed. @@ -350,7 +356,7 @@ def lut_enabled(self): return not self._fan_lut_prog @property - def tach_limit(self): + def tach_limit(self) -> float: """The maximum speed expected for the fan. If the fan exceeds this speed, the status register TACH bit will be set. @@ -365,7 +371,7 @@ def tach_limit(self): return round(emc2101_regs.FAN_RPM_DIVISOR / limit, 2) @tach_limit.setter - def tach_limit(self, new_limit): + def tach_limit(self, new_limit: float) -> None: """Set the speed limiter on the fan PWM signal. The value of 15000 is arbitrary, but very few fans run faster than this. If the fan exceeds this speed, the status register TACH bit will be set. @@ -384,7 +390,7 @@ def tach_limit(self, new_limit): self._tach_limit_msb = (num >> 8) & 0xFF @property - def spinup_time(self): + def spinup_time(self) -> int: """The amount of time the fan will spin at the currently set drive strength. @@ -393,7 +399,7 @@ def spinup_time(self): return self._spin_time @spinup_time.setter - def spinup_time(self, spin_time): + def spinup_time(self, spin_time: int) -> None: """Set the time that the SpinupDrive value will be used to get the fan moving before the normal speed controls are activated. This is needed because fan motors typically need a 'kick' to get them moving, @@ -417,7 +423,7 @@ def spinup_time(self, spin_time): self._spin_time = spin_time @property - def spinup_drive(self): + def spinup_drive(self) -> int: """The drive strength of the fan on spinup in % max PWM duty cycle (which approximates to max fan speed). @@ -426,7 +432,7 @@ def spinup_drive(self): return self._spin_drive @spinup_drive.setter - def spinup_drive(self, spin_drive): + def spinup_drive(self, spin_drive: int) -> None: """Set the drive (pwm duty percentage) that the SpinupTime value is applied to move the fan before the normal speed controls are activated. This is needed because fan motors typically need a 'kick' to get them moving, but after this @@ -450,16 +456,16 @@ def spinup_drive(self, spin_drive): self._spin_drive = spin_drive @property - def conversion_rate(self): + def conversion_rate(self) -> int: """The rate at which temperature measurements are taken. :return int: corresponding to the ConversionRate enumeration.""" return self._conversion_rate @conversion_rate.setter - def conversion_rate(self, rate): + def conversion_rate(self, rate: int) -> None: """Set the rate at which the external temperature is checked by - by the device. Reducing this rate can reduce power consumption. + the device. Reducing this rate can reduce power consumption. Usage: diff --git a/adafruit_emc2101/emc2101_enums.py b/adafruit_emc2101/emc2101_enums.py index 68a4d19..06ca286 100644 --- a/adafruit_emc2101/emc2101_enums.py +++ b/adafruit_emc2101/emc2101_enums.py @@ -32,12 +32,19 @@ """ +try: + from typing import Iterable, Optional, Tuple +except ImportError: + pass + class CV: """struct helper""" @classmethod - def add_values(cls, value_tuples): + def add_values( + cls, value_tuples: Iterable[Tuple[str, int, str, Optional[float]]] + ) -> None: """Creates CV entries""" cls.string = {} cls.lsb = {} @@ -48,7 +55,7 @@ def add_values(cls, value_tuples): cls.lsb[value] = lsb @classmethod - def is_valid(cls, value): + def is_valid(cls, value: int) -> bool: "Returns true if the given value is a member of the CV" return value in cls.string diff --git a/adafruit_emc2101/emc2101_ext.py b/adafruit_emc2101/emc2101_ext.py index 3b9627c..f8e08e5 100644 --- a/adafruit_emc2101/emc2101_ext.py +++ b/adafruit_emc2101/emc2101_ext.py @@ -42,6 +42,12 @@ from adafruit_emc2101 import emc2101_regs from adafruit_emc2101 import EMC2101 +try: + import typing # pylint: disable=unused-import + from busio import I2C +except ImportError: + pass + __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EMC2101.git" @@ -137,22 +143,22 @@ class EMC2101_EXT(EMC2101): # pylint: disable=too-many-instance-attributes uses down but useful to catch limit or overtemp alerts. checks can also be made by calling check_status(). Default: ON""" - def __init__(self, i2c_bus): + def __init__(self, i2c_bus: I2C) -> None: super().__init__(i2c_bus) self.initialize() - def initialize(self): + def initialize(self) -> None: """Reset the controller to an initial default configuration.""" self.auto_check_status = False self._last_status = 0 super().initialize() - def _check_status(self): + def _check_status(self) -> None: if self.auto_check_status: self.check_status() @property - def last_status(self): + def last_status(self) -> int: """Read the saved copy of the device status register. This is kept because the action of reading the status register also clears any outstanding alert reports, so a second read will return 0 unless @@ -166,7 +172,7 @@ def last_status(self): # Overrides plain version, class EMC2101 doesn't store last status. @property - def devstatus(self): + def devstatus(self) -> int: """Read device status (alerts) register. See the STATUS_* bit definitions in the emc2101_regs module, or refer to the datasheet for more detail. @@ -178,7 +184,7 @@ def devstatus(self): self._last_status = self._status return self._last_status - def check_status(self): + def check_status(self) -> None: """Read the status register and check for a fault indicated. If one of the bits in STATUS_ALERT indicates an alert, raise an exception. @@ -194,7 +200,7 @@ def check_status(self): raise RuntimeError("Status alert") @property - def internal_temperature(self): + def internal_temperature(self) -> int: """The temperature as measured by the EMC2101's internal 8-bit temperature sensor. @@ -204,7 +210,7 @@ def internal_temperature(self): return super().internal_temperature @property - def external_temperature(self): + def external_temperature(self) -> float: """The temperature measured using the external diode. The value is read as a fixed-point 11-bit value ranging from -64 C to just over approx 126 C, with fractional part of 1/8 degree centigrade. @@ -221,7 +227,7 @@ def external_temperature(self): return super().external_temperature @property - def fan_speed(self): + def fan_speed(self) -> float: """The current speed in Revolutions per Minute (RPM). :return: float speed in RPM. @@ -230,7 +236,7 @@ def fan_speed(self): return super().fan_speed @property - def dev_temp_critical_limit(self): + def dev_temp_critical_limit(self) -> int: """The critical temperature limit for the device (measured by internal sensor), in degrees centigrade. @@ -246,7 +252,7 @@ def dev_temp_critical_limit(self): return self._tcrit_limit @property - def dev_temp_critical_hysteresis(self): + def dev_temp_critical_hysteresis(self) -> int: """The critical temperature hysteresis for the device (measured by the internal sensor), in degrees centigrade. @@ -257,18 +263,16 @@ def dev_temp_critical_hysteresis(self): number of degrees centigrade of this difference. The device does not to support setting this value to 0. - :param float temp: the new limit temperature - :raises ValueError: if the supplied temperature is out of range. """ self._check_status() return self._tcrit_hyst @dev_temp_critical_hysteresis.setter - def dev_temp_critical_hysteresis(self, hysteresis): + def dev_temp_critical_hysteresis(self, hysteresis: int) -> None: """The critical temperature hysteresis for the device (measured by the internal sensor), in degrees centigrade (1..10). - :param float temp: the new critical limit temperature + :param int hysteresis: the number of degrees centigrade of difference """ if not 0 <= hysteresis <= 10: raise ValueError("dev_temp_critical_hysteresis must be from 1..10") @@ -276,14 +280,14 @@ def dev_temp_critical_hysteresis(self, hysteresis): self._check_status() @property - def dev_temp_high_limit(self): + def dev_temp_high_limit(self) -> int: """The high limit temperature for the internal sensor, in degrees centigrade.""" self._check_status() return self._int_temp_limit @dev_temp_high_limit.setter - def dev_temp_high_limit(self, temp): + def dev_temp_high_limit(self, temp: int) -> None: """The high limit temperature for the internal sensor, in degrees centigrade (0..85).""" # Device specced from 0C to 85C @@ -293,7 +297,7 @@ def dev_temp_high_limit(self, temp): self._check_status() @property - def external_temp_low_limit(self): + def external_temp_low_limit(self) -> float: """The low limit temperature for the external sensor.""" self._check_status() # No ordering restrictions here. @@ -308,7 +312,7 @@ def external_temp_low_limit(self): return temp @external_temp_low_limit.setter - def external_temp_low_limit(self, temp: float): + def external_temp_low_limit(self, temp: float) -> None: """Set the low limit temperature for the external sensor. The device automatically compares live temp readings with this value and signal the current reading is too low by setting the status register. @@ -338,7 +342,7 @@ def external_temp_low_limit(self, temp: float): self._check_status() @property - def external_temp_high_limit(self): + def external_temp_high_limit(self) -> float: """The high limit temperature for the external sensor.""" self._check_status() @@ -355,7 +359,7 @@ def external_temp_high_limit(self): return full_tmp @external_temp_high_limit.setter - def external_temp_high_limit(self, temp: float): + def external_temp_high_limit(self, temp: float) -> None: """Set high limit temperature for the external sensor. The device automatically compares live temp readings with this value and signal the current reading is too high by setting the status register. diff --git a/adafruit_emc2101/emc2101_fanspeed.py b/adafruit_emc2101/emc2101_fanspeed.py index fd6bce9..00ef4ca 100644 --- a/adafruit_emc2101/emc2101_fanspeed.py +++ b/adafruit_emc2101/emc2101_fanspeed.py @@ -118,7 +118,7 @@ def __exit__(self, typ, val, tbk): self._defer_update = False self._update_lut() - def __getitem__(self, index): + def __getitem__(self, index: int): if not isinstance(index, int): raise IndexError if not index in self.lut_values: diff --git a/adafruit_emc2101/emc2101_lut.py b/adafruit_emc2101/emc2101_lut.py index 5d03261..be3153d 100644 --- a/adafruit_emc2101/emc2101_lut.py +++ b/adafruit_emc2101/emc2101_lut.py @@ -41,6 +41,12 @@ from adafruit_emc2101.emc2101_fanspeed import FanSpeedLUT from adafruit_emc2101.emc2101_ext import EMC2101_EXT +try: + import typing # pylint: disable=unused-import + from busio import I2C +except ImportError: + pass + __version__ = "0.0.0+auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EMC2101.git" @@ -63,13 +69,13 @@ class EMC2101_LUT(EMC2101_EXT): # pylint: disable=too-many-instance-attributes the lower entry's threshold, minus the hysteresis value. """ - def __init__(self, i2c_bus): + def __init__(self, i2c_bus: I2C) -> None: super().__init__(i2c_bus) self.initialize() self._lut = FanSpeedLUT(self) - def initialize(self): + def initialize(self) -> None: """Reset the controller to an initial default configuration. :raises RuntimeError: if auto_check_status and an alert status bit is set @@ -80,7 +86,7 @@ def initialize(self): super().initialize() self._check_status() - def set_pwm_clock(self, use_preset=False, use_slow=False): + def set_pwm_clock(self, use_preset: bool = False, use_slow: bool = False) -> None: """ Select the PWM clock source, choosing between two preset clocks or by configuring the clock with `pwm_frequency` and `pwm_frequency_divisor`. @@ -110,13 +116,13 @@ def set_pwm_clock(self, use_preset=False, use_slow=False): self._check_status() @property - def pwm_frequency(self): + def pwm_frequency(self) -> int: """Selects the base clock frequency used for the fan PWM output""" self._check_status() return self._pwm_freq @pwm_frequency.setter - def pwm_frequency(self, value): + def pwm_frequency(self, value: int) -> None: """Set the PWM (fan) output frequency, which is a value from the datasheet. @@ -131,7 +137,7 @@ def pwm_frequency(self, value): self._check_status() @property - def pwm_frequency_divisor(self): + def pwm_frequency_divisor(self) -> int: """The Divisor applied to the PWM frequency to set the final frequency. :raises RuntimeError: if auto_check_status and an alert status bit is set @@ -140,7 +146,7 @@ def pwm_frequency_divisor(self): return self._pwm_freq_div @pwm_frequency_divisor.setter - def pwm_frequency_divisor(self, divisor): + def pwm_frequency_divisor(self, divisor: int) -> None: """Set the PWM (fan) output frequency divisor, which is a value from the datasheet. @@ -154,7 +160,7 @@ def pwm_frequency_divisor(self, divisor): self._check_status() @property - def lut_enabled(self): + def lut_enabled(self) -> bool: """Enable or disable the internal look up table used to map a given temperature to a fan speed. When the LUT is disabled fan speed can be changed with `manual_fan_speed`. @@ -164,7 +170,7 @@ def lut_enabled(self): return not self._fan_lut_prog @lut_enabled.setter - def lut_enabled(self, enable_lut): + def lut_enabled(self, enable_lut: bool) -> None: """Enable or disable the internal look up table used to map a given temperature to a fan speed. When the LUT is disabled fan speed can be changed with `manual_fan_speed`.