From 0589210fe17224f7c0cd9d41f67bcf0e9499968d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Szafer?= Date: Tue, 8 Aug 2023 21:14:14 +0200 Subject: [PATCH] initial support for pcf8575 relays --- boneio/helper/loader.py | 20 ++++++++++++++++---- boneio/helper/pcf8575.py | 13 +++++++++++++ boneio/input/gpio_beta.py | 2 +- boneio/manager.py | 25 +++++++++++-------------- boneio/relay/__init__.py | 3 ++- boneio/relay/pcf.py | 14 ++++++++------ boneio/schema/schema.yaml | 34 +++++++++++++++++++++++++++++++++- boneio/version.py | 2 +- 8 files changed, 85 insertions(+), 28 deletions(-) create mode 100644 boneio/helper/pcf8575.py diff --git a/boneio/helper/loader.py b/boneio/helper/loader.py index a7c29ee..8b81819 100644 --- a/boneio/helper/loader.py +++ b/boneio/helper/loader.py @@ -7,7 +7,6 @@ from adafruit_mcp230xx.mcp23017 import MCP23017 from adafruit_pca9685 import PCA9685 -from adafruit_pcf8575 import PCF8575 from boneio.const import ( ACTIONS, @@ -64,6 +63,7 @@ ) from boneio.helper.ha_discovery import ha_cover_availabilty_message from boneio.helper.timeperiod import TimePeriod +from boneio.helper.pcf8575 import PCF8575 from boneio.input import GpioEventButton, GpioEventButtonBeta from boneio.sensor import DallasSensorDS2482, GpioInputBinarySensor, GpioInputBinarySensorBeta from boneio.sensor.temp.dallas import DallasSensorW1 @@ -74,7 +74,7 @@ from busio import I2C -from boneio.relay import GpioRelay, MCPRelay, PWMPCA +from boneio.relay import GpioRelay, MCPRelay, PWMPCA, PCFRelay from boneio.sensor import GpioADCSensor, initialize_adc _LOGGER = logging.getLogger(__name__) @@ -153,12 +153,14 @@ def create_temp_sensor( _LOGGER.error("Can't configure Temp sensor. %s", err) pass + expander_class = { MCP: MCP23017, PCA: PCA9685, PCF: PCF8575 } + def create_expander( expander_dict: dict, expander_config: list, @@ -187,7 +189,6 @@ def create_expander( return grouped_outputs - def create_modbus_sensors(manager: Manager, sensors, **kwargs) -> None: """Create Modbus sensor for each device.""" from boneio.sensor.modbus import ModbusSensor @@ -230,7 +231,7 @@ def output_chooser(output_kind: str, config): return OutputEntry(PWMPCA, PCA, output_id) elif output_kind == PCF: output_id = config.pop(PCF_ID, None) - return OutputEntry(PWMPCA, PCF, output_id) + return OutputEntry(PCFRelay, PCF, output_id) else: raise GPIOOutputException(f"""Output type {output_kind} dont exists""") @@ -279,6 +280,17 @@ def configure_relay( "pca_id": getattr(output, "output_id"), "output_type": output_type, } + elif getattr(output, "output_kind") == PCF: + expander = manager.pcf.get(getattr(output, "output_id")) + if not expander: + _LOGGER.error("No such PCF configured!") + return None + kwargs = { + "pin": int(config.pop(PIN)), + "expander": expander, + "expander_id": getattr(output, "output_id"), + "output_type": output_type, + } elif getattr(output, "output_kind") == GPIO: if GPIO not in manager.grouped_outputs: manager.grouped_outputs[GPIO] = {} diff --git a/boneio/helper/pcf8575.py b/boneio/helper/pcf8575.py new file mode 100644 index 0000000..fc8e656 --- /dev/null +++ b/boneio/helper/pcf8575.py @@ -0,0 +1,13 @@ +from __future__ import annotations + +from adafruit_pcf8575 import PCF8575 as AdafruitPCF8575 +try: + from busio import I2C +except ImportError: + pass + + +class PCF8575(AdafruitPCF8575): + + def __init__(self, i2c: I2C, address: int, reset: bool) -> None: + super().__init__(i2c_bus=i2c, address=address) diff --git a/boneio/input/gpio_beta.py b/boneio/input/gpio_beta.py index e196ef0..37ad0ff 100644 --- a/boneio/input/gpio_beta.py +++ b/boneio/input/gpio_beta.py @@ -19,6 +19,7 @@ DOUBLE_CLICK_DURATION_MS = 300 LONG_PRESS_DURATION_MS = 600 + class GpioEventButtonBeta(GpioBaseClass): """Represent Gpio input switch.""" @@ -76,7 +77,6 @@ def check_state(self, channel) -> None: self._timer_long.reset() self._double_click_ran = False - def press_callback(self, click_type: ClickTypes): self.click_count = 0 self._loop.call_soon_threadsafe( diff --git a/boneio/manager.py b/boneio/manager.py index e1b734c..731cfff 100644 --- a/boneio/manager.py +++ b/boneio/manager.py @@ -145,21 +145,17 @@ def __init__( ) self.grouped_outputs.update( create_expander( - expander_dict=self._pcf, - expander_config=pcf8575, - exp_type=PCF, - i2cbusio=self._i2cbusio - ) - ) + expander_dict=self._pcf, + expander_config=pcf8575, + exp_type=PCF, + i2cbusio=self._i2cbusio)) self.grouped_outputs.update( create_expander( - expander_dict=self._pca, - expander_config=pca9685, - exp_type=PCA, - i2cbusio=self._i2cbusio - ) - ) - + expander_dict=self._pca, + expander_config=pca9685, + exp_type=PCA, + i2cbusio=self._i2cbusio)) + self._configure_adc(adc_list=adc) for _config in relay_pins: @@ -489,7 +485,8 @@ def press_callback( """Press callback to use in input gpio. If relay input map is provided also toggle action on relay or cover or mqtt.""" topic = f"{self._config_helper.topic_prefix}/{input_type}/{inpin}" - self.send_message(topic=topic, payload=x, retain=False) + payload = {"event_type": x} if input_type == INPUT else x + self.send_message(topic=topic, payload=payload, retain=False) for action_definition in actions: _LOGGER.debug("Executing action %s", action_definition) if action_definition[ACTION] == OUTPUT: diff --git a/boneio/relay/__init__.py b/boneio/relay/__init__.py index e21914c..9cd2dd9 100644 --- a/boneio/relay/__init__.py +++ b/boneio/relay/__init__.py @@ -1,6 +1,7 @@ """Relay module.""" from boneio.relay.gpio import GpioRelay from boneio.relay.mcp import MCPRelay +from boneio.relay.pcf import PCFRelay from boneio.relay.pca import PWMPCA -__all__ = ["MCPRelay", "GpioRelay", "PWMPCA"] +__all__ = ["MCPRelay", "GpioRelay", "PWMPCA", "PCFRelay"] diff --git a/boneio/relay/pcf.py b/boneio/relay/pcf.py index 5d865f1..960fc9a 100644 --- a/boneio/relay/pcf.py +++ b/boneio/relay/pcf.py @@ -2,10 +2,11 @@ import logging -from adafruit_pcf8575 import PCF8575, DigitalInOut +from adafruit_pcf8575 import DigitalInOut from boneio.const import NONE, SWITCH, PCF from boneio.helper.events import async_track_point_in_time, utcnow +from boneio.helper.pcf8575 import PCF8575 from boneio.relay.basic import BasicRelay _LOGGER = logging.getLogger(__name__) @@ -17,14 +18,14 @@ class PCFRelay(BasicRelay): def __init__( self, pin: int, - mcp: PCF8575, + expander: PCF8575, expander_id: str, output_type: str = SWITCH, restored_state: bool = False, **kwargs, ) -> None: """Initialize MCP relay.""" - self._pin: DigitalInOut = mcp.get_pin(pin) + self._pin: DigitalInOut = expander.get_pin(pin) if output_type == NONE: """Just in case to not restore state of covers etc.""" restored_state = False @@ -34,6 +35,7 @@ def __init__( ) self._pin_id = pin self._expander_id = expander_id + self._active_state = False _LOGGER.debug("Setup PCF with pin %s", self._pin_id) @property @@ -54,7 +56,7 @@ def expander_id(self) -> str: @property def is_active(self) -> bool: """Is relay active.""" - return self.pin.value + return self.pin.value == self._active_state @property def pin(self) -> str: @@ -63,7 +65,7 @@ def pin(self) -> str: def turn_on(self) -> None: """Call turn on action.""" - self.pin.value = True + self.pin.value = self._active_state if self._momentary_turn_on: async_track_point_in_time( loop=self._loop, @@ -74,7 +76,7 @@ def turn_on(self) -> None: def turn_off(self) -> None: """Call turn off action.""" - self.pin.value = False + self.pin.value = not self._active_state if self._momentary_turn_off: async_track_point_in_time( loop=self._loop, diff --git a/boneio/schema/schema.yaml b/boneio/schema/schema.yaml index 7cd0393..aee07d0 100644 --- a/boneio/schema/schema.yaml +++ b/boneio/schema/schema.yaml @@ -218,6 +218,33 @@ mcp23017: meta: label: How long to sleep for MCP to initialize. + +pcf8575: + type: list + required: False + meta: + label: pcf8575 Pin config + schema: + type: dict + schema: + id: !include id.yaml + address: + type: integer + required: True + meta: + label: GPIO of I2C SDA + init_sleep: + type: + - string + - timeperiod + coerce: + - str + - positive_time_period + required: True + default: 0s + meta: + label: How long to sleep for PCF to initialize. + pca9685: type: list required: False @@ -260,7 +287,7 @@ output: label: Id to send to use in HA and in GPIO Input. Default to `kind_pin` kind: type: string - allowed: ["gpio", "mcp", "pca"] + allowed: ["gpio", "mcp", "pca", "pcf"] meta: label: Either GPIO or i2c. mcp_id: @@ -273,6 +300,11 @@ output: required: False meta: label: PCA ID to connect + pcf_id: + type: string + required: False + meta: + label: PCF ID to connect pin: type: - string diff --git a/boneio/version.py b/boneio/version.py index ce39972..bab0b37 100644 --- a/boneio/version.py +++ b/boneio/version.py @@ -1,2 +1,2 @@ # flake8: noqa -__version__ = "0.7.0dev2" +__version__ = "0.7.0dev3"