Skip to content

Commit 14516ec

Browse files
authored
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.
1 parent 87e6bcf commit 14516ec

File tree

3 files changed

+62
-16
lines changed

3 files changed

+62
-16
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ switch:
154154
- port: 11
155155
name: "Fan Office"
156156
unique_id: "fan_office_switch_port_11"
157+
persistent: true
157158
- port: 12
158159
name: "Light Desk"
159160
unique_id: "light_desk_switch_port_12"
@@ -168,6 +169,7 @@ switch:
168169
| `name` | yes | | string | The name for the switch entity |
169170
| `unique_id` | no | | string | An ID that uniquely identifies the switch. Set this to a unique value to allow customization through the UI |
170171
| `invert_logic` | no | `false` | boolean | If true, inverts the output logic to ACTIVE LOW |
172+
| `persistent` | no | `false` | boolean | If true, the switch state will be persistent in HA and will be restored if HA restart / crash |
171173

172174
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.
173175

custom_components/rpi_gpio/switch.py

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Allows to configure a switch using RPi GPIO."""
22
from __future__ import annotations
3+
from typing import Any
34

45
import voluptuous as vol
56

@@ -10,20 +11,24 @@
1011
CONF_SWITCHES,
1112
CONF_UNIQUE_ID,
1213
DEVICE_DEFAULT_NAME,
14+
STATE_ON,
1315
)
1416
from homeassistant.core import HomeAssistant
1517
import homeassistant.helpers.config_validation as cv
1618
from homeassistant.helpers.entity_platform import AddEntitiesCallback
1719
from homeassistant.helpers.reload import setup_reload_service
1820
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
21+
from homeassistant.helpers.restore_state import RestoreEntity
1922

2023
from . import DOMAIN, PLATFORMS, setup_output, write_output
2124

2225
CONF_PULL_MODE = "pull_mode"
2326
CONF_PORTS = "ports"
2427
CONF_INVERT_LOGIC = "invert_logic"
28+
CONF_PERSISTENT = "persistent"
2529

2630
DEFAULT_INVERT_LOGIC = False
31+
DEFAULT_PERSISTENT = False
2732

2833
_SWITCHES_LEGACY_SCHEMA = vol.Schema({cv.positive_int: cv.string})
2934

@@ -32,6 +37,7 @@
3237
vol.Required(CONF_NAME): cv.string,
3338
vol.Required(CONF_PORT): cv.positive_int,
3439
vol.Optional(CONF_INVERT_LOGIC, default=DEFAULT_INVERT_LOGIC): cv.boolean,
40+
vol.Optional(CONF_PERSISTENT, default=DEFAULT_PERSISTENT): cv.boolean,
3541
vol.Optional(CONF_UNIQUE_ID): cv.string,
3642
}
3743
)
@@ -45,6 +51,7 @@
4551
cv.ensure_list, [_SWITCH_SCHEMA]
4652
),
4753
vol.Optional(CONF_INVERT_LOGIC, default=DEFAULT_INVERT_LOGIC): cv.boolean,
54+
vol.Optional(CONF_PERSISTENT, default=DEFAULT_PERSISTENT): cv.boolean,
4855
},
4956
),
5057
cv.has_at_least_one_key(CONF_PORTS, CONF_SWITCHES),
@@ -65,31 +72,45 @@ def setup_platform(
6572
switches_conf = config.get(CONF_SWITCHES)
6673
if switches_conf is not None:
6774
for switch in switches_conf:
68-
switches.append(
69-
RPiGPIOSwitch(
70-
switch[CONF_NAME],
71-
switch[CONF_PORT],
72-
switch[CONF_INVERT_LOGIC],
73-
switch.get(CONF_UNIQUE_ID),
75+
if switch[CONF_PERSISTENT]:
76+
switches.append(
77+
PersistentRPiGPIOSwitch(
78+
switch[CONF_NAME],
79+
switch[CONF_PORT],
80+
switch[CONF_INVERT_LOGIC],
81+
switch.get(CONF_UNIQUE_ID),
82+
)
83+
)
84+
else:
85+
switches.append(
86+
RPiGPIOSwitch(
87+
switch[CONF_NAME],
88+
switch[CONF_PORT],
89+
switch[CONF_INVERT_LOGIC],
90+
switch.get(CONF_UNIQUE_ID),
91+
)
7492
)
75-
)
7693

7794
add_entities(switches, True)
7895
return
7996

8097
invert_logic = config[CONF_INVERT_LOGIC]
98+
persistent = config[CONF_PERSISTENT]
8199

82100
ports = config[CONF_PORTS]
83101
for port, name in ports.items():
84-
switches.append(RPiGPIOSwitch(name, port, invert_logic))
102+
if persistent:
103+
switches.append(PersistentRPiGPIOSwitch(name, port, invert_logic))
104+
else:
105+
switches.append(RPiGPIOSwitch(name, port, invert_logic))
85106

86107
add_entities(switches)
87108

88109

89110
class RPiGPIOSwitch(SwitchEntity):
90-
"""Representation of a Raspberry Pi GPIO."""
111+
"""Representation of a Raspberry Pi GPIO."""
91112

92-
def __init__(self, name, port, invert_logic, unique_id=None):
113+
def __init__(self, name, port, invert_logic, unique_id=None, skip_reset=False):
93114
"""Initialize the pin."""
94115
self._attr_name = name or DEVICE_DEFAULT_NAME
95116
self._attr_unique_id = unique_id
@@ -98,21 +119,42 @@ def __init__(self, name, port, invert_logic, unique_id=None):
98119
self._invert_logic = invert_logic
99120
self._state = False
100121
setup_output(self._port)
101-
write_output(self._port, 1 if self._invert_logic else 0)
122+
if not skip_reset:
123+
write_output(self._port, 1 if self._invert_logic else 0)
102124

103125
@property
104-
def is_on(self):
126+
def is_on(self) -> bool | None:
105127
"""Return true if device is on."""
106128
return self._state
107129

108-
def turn_on(self, **kwargs):
130+
async def async_turn_on(self, **kwargs: Any) -> None:
109131
"""Turn the device on."""
110132
write_output(self._port, 0 if self._invert_logic else 1)
111133
self._state = True
112-
self.schedule_update_ha_state()
134+
self.async_write_ha_state()
113135

114-
def turn_off(self, **kwargs):
136+
async def async_turn_off(self, **kwargs: Any) -> None:
115137
"""Turn the device off."""
116138
write_output(self._port, 1 if self._invert_logic else 0)
117139
self._state = False
118-
self.schedule_update_ha_state()
140+
self.async_write_ha_state()
141+
142+
143+
class PersistentRPiGPIOSwitch(RPiGPIOSwitch, RestoreEntity):
144+
"""Representation of a persistent Raspberry Pi GPIO."""
145+
146+
def __init__(self, name, port, invert_logic, unique_id=None):
147+
"""Initialize the pin."""
148+
super().__init__(name, port, invert_logic, unique_id, True)
149+
150+
async def async_added_to_hass(self) -> None:
151+
"""Call when the switch is added to hass."""
152+
await super().async_added_to_hass()
153+
state = await self.async_get_last_state()
154+
if not state:
155+
return
156+
self._state = True if state.state == STATE_ON else False
157+
if self._state:
158+
await self.async_turn_on()
159+
else:
160+
await self.async_turn_off()

info.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ switch:
142142
- port: 11
143143
name: "Fan Office"
144144
unique_id: "fan_office_switch_port_11"
145+
persistent: true
145146
- port: 12
146147
name: "Light Desk"
147148
unique_id: "light_desk_switch_port_12"
@@ -156,6 +157,7 @@ switch:
156157
| `name` | yes | | string | The name for the switch entity |
157158
| `unique_id` | no | | string | An ID that uniquely identifies the switch. Set this to a unique value to allow customization through the UI |
158159
| `invert_logic` | no | `false` | boolean | If true, inverts the output logic to ACTIVE LOW |
160+
| `persistent` | no | `false` | boolean | If true, the switch state will be persistent in HA and will be restored if HA restart / crash |
159161

160162
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.
161163

0 commit comments

Comments
 (0)