Add the option to have persistent switches (#266)

* Add the option to have persistent switches

* update README

* Make the same changes in the info.md file.
This commit is contained in:
Tomer 2024-07-19 15:49:11 +03:00 committed by GitHub
parent 87e6bcfd9c
commit 14516ec30a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 62 additions and 16 deletions

View File

@ -154,6 +154,7 @@ switch:
- port: 11
name: "Fan Office"
unique_id: "fan_office_switch_port_11"
persistent: true
- port: 12
name: "Light Desk"
unique_id: "light_desk_switch_port_12"
@ -168,6 +169,7 @@ switch:
| `name` | yes | | string | The name for the switch entity |
| `unique_id` | no | | string | An ID that uniquely identifies the switch. Set this to a unique value to allow customization through the UI |
| `invert_logic` | no | `false` | boolean | If true, inverts the output logic to ACTIVE LOW |
| `persistent` | no | `false` | boolean | If true, the switch state will be persistent in HA and will be restored if HA restart / crash |
For more details about the GPIO layout, visit the Wikipedia [article](https://en.wikipedia.org/wiki/Raspberry_Pi#General_purpose_input-output_(GPIO)_connector) about the Raspberry Pi.

View File

@ -1,5 +1,6 @@
"""Allows to configure a switch using RPi GPIO."""
from __future__ import annotations
from typing import Any
import voluptuous as vol
@ -10,20 +11,24 @@ from homeassistant.const import (
CONF_SWITCHES,
CONF_UNIQUE_ID,
DEVICE_DEFAULT_NAME,
STATE_ON,
)
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import setup_reload_service
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.helpers.restore_state import RestoreEntity
from . import DOMAIN, PLATFORMS, setup_output, write_output
CONF_PULL_MODE = "pull_mode"
CONF_PORTS = "ports"
CONF_INVERT_LOGIC = "invert_logic"
CONF_PERSISTENT = "persistent"
DEFAULT_INVERT_LOGIC = False
DEFAULT_PERSISTENT = False
_SWITCHES_LEGACY_SCHEMA = vol.Schema({cv.positive_int: cv.string})
@ -32,6 +37,7 @@ _SWITCH_SCHEMA = vol.Schema(
vol.Required(CONF_NAME): cv.string,
vol.Required(CONF_PORT): cv.positive_int,
vol.Optional(CONF_INVERT_LOGIC, default=DEFAULT_INVERT_LOGIC): cv.boolean,
vol.Optional(CONF_PERSISTENT, default=DEFAULT_PERSISTENT): cv.boolean,
vol.Optional(CONF_UNIQUE_ID): cv.string,
}
)
@ -45,6 +51,7 @@ PLATFORM_SCHEMA = vol.All(
cv.ensure_list, [_SWITCH_SCHEMA]
),
vol.Optional(CONF_INVERT_LOGIC, default=DEFAULT_INVERT_LOGIC): cv.boolean,
vol.Optional(CONF_PERSISTENT, default=DEFAULT_PERSISTENT): cv.boolean,
},
),
cv.has_at_least_one_key(CONF_PORTS, CONF_SWITCHES),
@ -65,31 +72,45 @@ def setup_platform(
switches_conf = config.get(CONF_SWITCHES)
if switches_conf is not None:
for switch in switches_conf:
switches.append(
RPiGPIOSwitch(
switch[CONF_NAME],
switch[CONF_PORT],
switch[CONF_INVERT_LOGIC],
switch.get(CONF_UNIQUE_ID),
if switch[CONF_PERSISTENT]:
switches.append(
PersistentRPiGPIOSwitch(
switch[CONF_NAME],
switch[CONF_PORT],
switch[CONF_INVERT_LOGIC],
switch.get(CONF_UNIQUE_ID),
)
)
else:
switches.append(
RPiGPIOSwitch(
switch[CONF_NAME],
switch[CONF_PORT],
switch[CONF_INVERT_LOGIC],
switch.get(CONF_UNIQUE_ID),
)
)
)
add_entities(switches, True)
return
invert_logic = config[CONF_INVERT_LOGIC]
persistent = config[CONF_PERSISTENT]
ports = config[CONF_PORTS]
for port, name in ports.items():
switches.append(RPiGPIOSwitch(name, port, invert_logic))
if persistent:
switches.append(PersistentRPiGPIOSwitch(name, port, invert_logic))
else:
switches.append(RPiGPIOSwitch(name, port, invert_logic))
add_entities(switches)
class RPiGPIOSwitch(SwitchEntity):
"""Representation of a Raspberry Pi GPIO."""
"""Representation of a Raspberry Pi GPIO."""
def __init__(self, name, port, invert_logic, unique_id=None):
def __init__(self, name, port, invert_logic, unique_id=None, skip_reset=False):
"""Initialize the pin."""
self._attr_name = name or DEVICE_DEFAULT_NAME
self._attr_unique_id = unique_id
@ -98,21 +119,42 @@ class RPiGPIOSwitch(SwitchEntity):
self._invert_logic = invert_logic
self._state = False
setup_output(self._port)
write_output(self._port, 1 if self._invert_logic else 0)
if not skip_reset:
write_output(self._port, 1 if self._invert_logic else 0)
@property
def is_on(self):
def is_on(self) -> bool | None:
"""Return true if device is on."""
return self._state
def turn_on(self, **kwargs):
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the device on."""
write_output(self._port, 0 if self._invert_logic else 1)
self._state = True
self.schedule_update_ha_state()
self.async_write_ha_state()
def turn_off(self, **kwargs):
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the device off."""
write_output(self._port, 1 if self._invert_logic else 0)
self._state = False
self.schedule_update_ha_state()
self.async_write_ha_state()
class PersistentRPiGPIOSwitch(RPiGPIOSwitch, RestoreEntity):
"""Representation of a persistent Raspberry Pi GPIO."""
def __init__(self, name, port, invert_logic, unique_id=None):
"""Initialize the pin."""
super().__init__(name, port, invert_logic, unique_id, True)
async def async_added_to_hass(self) -> None:
"""Call when the switch is added to hass."""
await super().async_added_to_hass()
state = await self.async_get_last_state()
if not state:
return
self._state = True if state.state == STATE_ON else False
if self._state:
await self.async_turn_on()
else:
await self.async_turn_off()

View File

@ -142,6 +142,7 @@ switch:
- port: 11
name: "Fan Office"
unique_id: "fan_office_switch_port_11"
persistent: true
- port: 12
name: "Light Desk"
unique_id: "light_desk_switch_port_12"
@ -156,6 +157,7 @@ switch:
| `name` | yes | | string | The name for the switch entity |
| `unique_id` | no | | string | An ID that uniquely identifies the switch. Set this to a unique value to allow customization through the UI |
| `invert_logic` | no | `false` | boolean | If true, inverts the output logic to ACTIVE LOW |
| `persistent` | no | `false` | boolean | If true, the switch state will be persistent in HA and will be restored if HA restart / crash |
For more details about the GPIO layout, visit the Wikipedia [article](https://en.wikipedia.org/wiki/Raspberry_Pi#General_purpose_input-output_(GPIO)_connector) about the Raspberry Pi.