boneIO 0.7.0.dev1__tar.gz → 0.7.0.dev3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/PKG-INFO +1 -1
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/bonecli.py +4 -2
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/const.py +4 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/click_timer.py +2 -1
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/events.py +1 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/gpio.py +2 -1
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/loader.py +49 -41
- boneIO-0.7.0.dev3/boneio/helper/pcf8575.py +13 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/input/gpio_beta.py +7 -7
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/manager.py +40 -10
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/mqtt_client.py +22 -17
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/relay/__init__.py +2 -1
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/relay/basic.py +6 -1
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/relay/mcp.py +8 -14
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/relay/pca.py +4 -4
- boneIO-0.7.0.dev3/boneio/relay/pcf.py +86 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/runner.py +4 -2
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/schema/schema.yaml +33 -1
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/gpio_beta.py +2 -1
- boneIO-0.7.0.dev3/boneio/version.py +2 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/pyproject.toml +2 -3
- boneIO-0.7.0.dev1/boneio/version.py +0 -2
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/LICENSE +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/README.md +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/__init__.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/cover.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/example_config/__init__.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/example_config/adc_v0_4.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/example_config/binary_sensor.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/example_config/config.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/example_config/cover.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/example_config/event.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/example_config/led32x4A.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/example_config/output24x16A.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/example_config/output24x16A_v0.3.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/example_config/output32x5A.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/fonts/danube__.ttf +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/__init__.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/async_updater.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/config.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/exceptions.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/filter.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/ha_discovery.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/logger.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/mqtt.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/oled.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/onewire/W1ThermSensor.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/onewire/__init__.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/onewire/ds2482.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/onewire/onewire.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/queue.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/state_manager.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/stats.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/timeperiod.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/util.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/helper/yaml_util.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/input/__init__.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/input/gpio.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/modbus.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/oled.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/relay/gpio.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/schema/actions.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/schema/actions_sensor.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/schema/actions_switch.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/schema/filters.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/schema/filters_adc.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/schema/id.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/schema/temp_unit.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/schema/update_interval.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/__init__.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/adc.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/gpio.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/modbus/__init__.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/modbus/dts1964_3f.json +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/modbus/pt100.json +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/modbus/r4dcb08.json +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/modbus/sdm120.json +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/modbus/sdm630.json +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/modbus/sofar.json +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/temp/__init__.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/temp/dallas.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/temp/lm75.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/boneio/sensor/temp/mcp9808.py +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/tests/32_5_config.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/tests/bandit.yaml +0 -0
- {boneIO-0.7.0.dev1 → boneIO-0.7.0.dev3}/tests/relay_32_5.py +0 -0
|
@@ -15,6 +15,7 @@ from yaml import MarkedYAMLError
|
|
|
15
15
|
from boneio.const import ACTION
|
|
16
16
|
from boneio.helper import load_config_from_file
|
|
17
17
|
from boneio.helper.exceptions import ConfigurationException, RestartRequestException
|
|
18
|
+
from boneio.helper.events import GracefulExit
|
|
18
19
|
from boneio.helper.logger import configure_logger
|
|
19
20
|
from boneio.runner import async_run
|
|
20
21
|
from boneio.version import __version__
|
|
@@ -89,8 +90,9 @@ def run(config: str, debug: int, mqttusername: str = "", mqttpassword: str = "")
|
|
|
89
90
|
),
|
|
90
91
|
)
|
|
91
92
|
return 0
|
|
92
|
-
except RestartRequestException as err:
|
|
93
|
-
|
|
93
|
+
except (RestartRequestException, GracefulExit) as err:
|
|
94
|
+
if err is not None:
|
|
95
|
+
_LOGGER.info(err)
|
|
94
96
|
return 0
|
|
95
97
|
except (ConfigurationException, MarkedYAMLError) as err:
|
|
96
98
|
_LOGGER.error("Failed to load config. %s Exiting.", err)
|
|
@@ -104,10 +104,13 @@ TOPIC_PREFIX = "topic_prefix"
|
|
|
104
104
|
# I2C, PCA and MCP CONST
|
|
105
105
|
ADDRESS = "address"
|
|
106
106
|
MCP23017 = "mcp23017"
|
|
107
|
+
PCF8575 = "pcf8575"
|
|
107
108
|
PCA9685 = "pca9685"
|
|
108
109
|
MCP = "mcp"
|
|
110
|
+
PCF = "pcf"
|
|
109
111
|
MCP_ID = "mcp_id"
|
|
110
112
|
PCA_ID = "pca_id"
|
|
113
|
+
PCF_ID = "pcf_id"
|
|
111
114
|
INIT_SLEEP = "init_sleep"
|
|
112
115
|
|
|
113
116
|
# SENSOR CONST
|
|
@@ -141,6 +144,7 @@ OledDataTypes = Literal[UPTIME, NETWORK, CPU, DISK, MEMORY, SWAP, OUTPUT]
|
|
|
141
144
|
Gpio_States = Literal[HIGH, LOW]
|
|
142
145
|
Gpio_Edges = Literal[BOTH, FALLING]
|
|
143
146
|
InputTypes = Literal[INPUT, INPUT_SENSOR]
|
|
147
|
+
ExpanderTypes = Literal[MCP23017, PCA9685, PCF8575]
|
|
144
148
|
DEVICE_CLASS = "device_class"
|
|
145
149
|
DallasBusTypes = Literal[DS2482, DALLAS]
|
|
146
150
|
FILTERS = "filters"
|
|
@@ -24,9 +24,10 @@ class ClickTimer:
|
|
|
24
24
|
self._remove_listener = None
|
|
25
25
|
|
|
26
26
|
async def _start_async_timer(self) -> None:
|
|
27
|
+
start = time.time()
|
|
27
28
|
await asyncio.sleep(self._delay)
|
|
28
29
|
self._remove_listener = None
|
|
29
|
-
self._action(time.time())
|
|
30
|
+
self._action(round(time.time() - start, 2))
|
|
30
31
|
|
|
31
32
|
def start_timer(self) -> None:
|
|
32
33
|
"""Start timer."""
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import asyncio
|
|
2
3
|
import logging
|
|
3
4
|
|
|
@@ -104,7 +105,7 @@ class GpioBaseClass:
|
|
|
104
105
|
"""Base class for initialize GPIO"""
|
|
105
106
|
|
|
106
107
|
def __init__(
|
|
107
|
-
self, pin: str, press_callback: Callable[[ClickTypes, str], None], **kwargs
|
|
108
|
+
self, pin: str, press_callback: Callable[[ClickTypes, str, bool | None], None], **kwargs
|
|
108
109
|
) -> None:
|
|
109
110
|
"""Setup GPIO Input Button"""
|
|
110
111
|
self._pin = pin
|
|
@@ -37,7 +37,11 @@ from boneio.const import (
|
|
|
37
37
|
SHOW_HA,
|
|
38
38
|
UPDATE_INTERVAL,
|
|
39
39
|
DallasBusTypes,
|
|
40
|
-
EVENT_ENTITY
|
|
40
|
+
EVENT_ENTITY,
|
|
41
|
+
ExpanderTypes,
|
|
42
|
+
PCF,
|
|
43
|
+
PCA,
|
|
44
|
+
PCF_ID
|
|
41
45
|
)
|
|
42
46
|
from boneio.cover import Cover
|
|
43
47
|
from boneio.helper import (
|
|
@@ -59,6 +63,7 @@ from boneio.helper.onewire import (
|
|
|
59
63
|
)
|
|
60
64
|
from boneio.helper.ha_discovery import ha_cover_availabilty_message
|
|
61
65
|
from boneio.helper.timeperiod import TimePeriod
|
|
66
|
+
from boneio.helper.pcf8575 import PCF8575
|
|
62
67
|
from boneio.input import GpioEventButton, GpioEventButtonBeta
|
|
63
68
|
from boneio.sensor import DallasSensorDS2482, GpioInputBinarySensor, GpioInputBinarySensorBeta
|
|
64
69
|
from boneio.sensor.temp.dallas import DallasSensorW1
|
|
@@ -69,7 +74,7 @@ if TYPE_CHECKING:
|
|
|
69
74
|
|
|
70
75
|
from busio import I2C
|
|
71
76
|
|
|
72
|
-
from boneio.relay import GpioRelay, MCPRelay, PWMPCA
|
|
77
|
+
from boneio.relay import GpioRelay, MCPRelay, PWMPCA, PCFRelay
|
|
73
78
|
from boneio.sensor import GpioADCSensor, initialize_adc
|
|
74
79
|
|
|
75
80
|
_LOGGER = logging.getLogger(__name__)
|
|
@@ -149,49 +154,37 @@ def create_temp_sensor(
|
|
|
149
154
|
pass
|
|
150
155
|
|
|
151
156
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
"""Create MCP23017."""
|
|
158
|
-
grouped_outputs = {}
|
|
159
|
-
for mcp in mcp23017:
|
|
160
|
-
id = mcp[ID] or mcp[ADDRESS]
|
|
161
|
-
try:
|
|
162
|
-
manager._mcp[id] = MCP23017(i2c=i2cbusio, address=mcp[ADDRESS], reset=False)
|
|
163
|
-
sleep_time = mcp.get(INIT_SLEEP, TimePeriod(seconds=0))
|
|
164
|
-
_LOGGER.debug(
|
|
165
|
-
f"Sleeping for {sleep_time.total_seconds}s while MCP {id} is initializing."
|
|
166
|
-
)
|
|
167
|
-
time.sleep(sleep_time.total_seconds)
|
|
168
|
-
grouped_outputs[id] = {}
|
|
169
|
-
except TimeoutError as err:
|
|
170
|
-
_LOGGER.error("Can't connect to MCP %s. %s", id, err)
|
|
171
|
-
pass
|
|
172
|
-
return grouped_outputs
|
|
157
|
+
expander_class = {
|
|
158
|
+
MCP: MCP23017,
|
|
159
|
+
PCA: PCA9685,
|
|
160
|
+
PCF: PCF8575
|
|
161
|
+
}
|
|
173
162
|
|
|
174
163
|
|
|
175
|
-
def
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
164
|
+
def create_expander(
|
|
165
|
+
expander_dict: dict,
|
|
166
|
+
expander_config: list,
|
|
167
|
+
exp_type: ExpanderTypes,
|
|
168
|
+
i2cbusio: I2C
|
|
179
169
|
) -> dict:
|
|
180
|
-
"""Create MCP23017."""
|
|
181
170
|
grouped_outputs = {}
|
|
182
|
-
for
|
|
183
|
-
id =
|
|
171
|
+
for expander in expander_config:
|
|
172
|
+
id = expander[ID] or expander[ADDRESS]
|
|
184
173
|
try:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
sleep_time
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
174
|
+
expander_dict[id] = expander_class[exp_type](i2c=i2cbusio, address=expander[ADDRESS], reset=False)
|
|
175
|
+
sleep_time = expander.get(INIT_SLEEP, TimePeriod(seconds=0))
|
|
176
|
+
if sleep_time.total_seconds > 0:
|
|
177
|
+
_LOGGER.debug(
|
|
178
|
+
f"Sleeping for {sleep_time.total_seconds}s while {exp_type} {id} is initializing."
|
|
179
|
+
)
|
|
180
|
+
time.sleep(sleep_time.total_seconds)
|
|
181
|
+
else:
|
|
182
|
+
_LOGGER.debug(
|
|
183
|
+
f"{exp_type} {id} is initializing."
|
|
184
|
+
)
|
|
192
185
|
grouped_outputs[id] = {}
|
|
193
186
|
except TimeoutError as err:
|
|
194
|
-
_LOGGER.error("Can't connect to
|
|
187
|
+
_LOGGER.error("Can't connect to %s %s. %s", exp_type, id, err)
|
|
195
188
|
pass
|
|
196
189
|
return grouped_outputs
|
|
197
190
|
|
|
@@ -236,6 +229,9 @@ def output_chooser(output_kind: str, config):
|
|
|
236
229
|
elif output_kind == PCA:
|
|
237
230
|
output_id = config.pop(PCA_ID, None)
|
|
238
231
|
return OutputEntry(PWMPCA, PCA, output_id)
|
|
232
|
+
elif output_kind == PCF:
|
|
233
|
+
output_id = config.pop(PCF_ID, None)
|
|
234
|
+
return OutputEntry(PCFRelay, PCF, output_id)
|
|
239
235
|
else:
|
|
240
236
|
raise GPIOOutputException(f"""Output type {output_kind} dont exists""")
|
|
241
237
|
|
|
@@ -284,6 +280,17 @@ def configure_relay(
|
|
|
284
280
|
"pca_id": getattr(output, "output_id"),
|
|
285
281
|
"output_type": output_type,
|
|
286
282
|
}
|
|
283
|
+
elif getattr(output, "output_kind") == PCF:
|
|
284
|
+
expander = manager.pcf.get(getattr(output, "output_id"))
|
|
285
|
+
if not expander:
|
|
286
|
+
_LOGGER.error("No such PCF configured!")
|
|
287
|
+
return None
|
|
288
|
+
kwargs = {
|
|
289
|
+
"pin": int(config.pop(PIN)),
|
|
290
|
+
"expander": expander,
|
|
291
|
+
"expander_id": getattr(output, "output_id"),
|
|
292
|
+
"output_type": output_type,
|
|
293
|
+
}
|
|
287
294
|
elif getattr(output, "output_kind") == GPIO:
|
|
288
295
|
if GPIO not in manager.grouped_outputs:
|
|
289
296
|
manager.grouped_outputs[GPIO] = {}
|
|
@@ -342,12 +349,13 @@ def configure_event_sensor(
|
|
|
342
349
|
GpioEventButtonClass = GpioEventButton if gpio.get("detection_type", "stable") == "stable" else GpioEventButtonBeta
|
|
343
350
|
GpioEventButtonClass(
|
|
344
351
|
pin=pin,
|
|
345
|
-
press_callback=lambda x, i: press_callback(
|
|
352
|
+
press_callback=lambda x, i, z: press_callback(
|
|
346
353
|
x=x,
|
|
347
354
|
inpin=i,
|
|
348
355
|
actions=gpio.get(ACTIONS, {}).get(x, []),
|
|
349
356
|
input_type=INPUT,
|
|
350
|
-
empty_message_after=gpio.get("clear_message", False)
|
|
357
|
+
empty_message_after=gpio.get("clear_message", False),
|
|
358
|
+
duration=z
|
|
351
359
|
),
|
|
352
360
|
**gpio,
|
|
353
361
|
)
|
|
@@ -373,7 +381,7 @@ def configure_binary_sensor(
|
|
|
373
381
|
"""Configure input sensor or button."""
|
|
374
382
|
try:
|
|
375
383
|
GpioInputBinarySensorClass = GpioInputBinarySensor if gpio.get("detection_type", "stable") == "stable" else GpioInputBinarySensorBeta
|
|
376
|
-
|
|
384
|
+
GpioInputBinarySensorClass(
|
|
377
385
|
pin=pin,
|
|
378
386
|
press_callback=lambda x, i: press_callback(
|
|
379
387
|
x=x,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from adafruit_pcf8575 import PCF8575 as AdafruitPCF8575
|
|
4
|
+
try:
|
|
5
|
+
from busio import I2C
|
|
6
|
+
except ImportError:
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class PCF8575(AdafruitPCF8575):
|
|
11
|
+
|
|
12
|
+
def __init__(self, i2c: I2C, address: int, reset: bool) -> None:
|
|
13
|
+
super().__init__(i2c_bus=i2c, address=address)
|
|
@@ -19,6 +19,7 @@ _LOGGER = logging.getLogger(__name__)
|
|
|
19
19
|
DOUBLE_CLICK_DURATION_MS = 300
|
|
20
20
|
LONG_PRESS_DURATION_MS = 600
|
|
21
21
|
|
|
22
|
+
|
|
22
23
|
class GpioEventButtonBeta(GpioBaseClass):
|
|
23
24
|
"""Represent Gpio input switch."""
|
|
24
25
|
|
|
@@ -38,7 +39,7 @@ class GpioEventButtonBeta(GpioBaseClass):
|
|
|
38
39
|
)
|
|
39
40
|
self._timer_long = ClickTimer(
|
|
40
41
|
delay=TimePeriod(milliseconds=LONG_PRESS_DURATION_MS),
|
|
41
|
-
action=lambda x: self.press_callback(click_type=LONG),
|
|
42
|
+
action=lambda x: self.press_callback(click_type=LONG, duration=x),
|
|
42
43
|
)
|
|
43
44
|
self._double_click_ran = False
|
|
44
45
|
self._is_waiting_for_second_click = False
|
|
@@ -51,7 +52,7 @@ class GpioEventButtonBeta(GpioBaseClass):
|
|
|
51
52
|
def double_click_press_callback(self):
|
|
52
53
|
self._is_waiting_for_second_click = False
|
|
53
54
|
if not self._state and not self._timer_long.is_waiting():
|
|
54
|
-
self.press_callback(click_type=SINGLE)
|
|
55
|
+
self.press_callback(click_type=SINGLE, duration=None)
|
|
55
56
|
|
|
56
57
|
def check_state(self, channel) -> None:
|
|
57
58
|
time_now = time.time()
|
|
@@ -64,7 +65,7 @@ class GpioEventButtonBeta(GpioBaseClass):
|
|
|
64
65
|
if self._timer_double.is_waiting():
|
|
65
66
|
self._timer_double.reset()
|
|
66
67
|
self._double_click_ran = True
|
|
67
|
-
self.press_callback(click_type=DOUBLE)
|
|
68
|
+
self.press_callback(click_type=DOUBLE, duration=None)
|
|
68
69
|
return
|
|
69
70
|
self._timer_double.start_timer()
|
|
70
71
|
self._is_waiting_for_second_click = True
|
|
@@ -72,13 +73,12 @@ class GpioEventButtonBeta(GpioBaseClass):
|
|
|
72
73
|
else:
|
|
73
74
|
if not self._is_waiting_for_second_click and not self._double_click_ran:
|
|
74
75
|
if self._timer_long.is_waiting():
|
|
75
|
-
self.press_callback(click_type=SINGLE)
|
|
76
|
+
self.press_callback(click_type=SINGLE, duration=None)
|
|
76
77
|
self._timer_long.reset()
|
|
77
78
|
self._double_click_ran = False
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
def press_callback(self, click_type: ClickTypes):
|
|
80
|
+
def press_callback(self, click_type: ClickTypes, duration: float | None = None):
|
|
81
81
|
self.click_count = 0
|
|
82
82
|
self._loop.call_soon_threadsafe(
|
|
83
|
-
partial(self._press_callback, click_type, self._pin)
|
|
83
|
+
partial(self._press_callback, click_type, self._pin, duration)
|
|
84
84
|
)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import asyncio
|
|
2
3
|
import logging
|
|
3
4
|
from collections import deque
|
|
@@ -37,6 +38,9 @@ from boneio.const import (
|
|
|
37
38
|
LIGHT,
|
|
38
39
|
LED,
|
|
39
40
|
SET_BRIGHTNESS,
|
|
41
|
+
MCP,
|
|
42
|
+
PCA,
|
|
43
|
+
PCF
|
|
40
44
|
)
|
|
41
45
|
from boneio.helper import (
|
|
42
46
|
GPIOInputException,
|
|
@@ -57,8 +61,7 @@ from boneio.helper.loader import (
|
|
|
57
61
|
configure_binary_sensor,
|
|
58
62
|
configure_relay,
|
|
59
63
|
create_dallas_sensor,
|
|
60
|
-
|
|
61
|
-
create_pca9685,
|
|
64
|
+
create_expander,
|
|
62
65
|
create_temp_sensor,
|
|
63
66
|
)
|
|
64
67
|
from boneio.helper.logger import configure_logger
|
|
@@ -92,6 +95,7 @@ class Manager:
|
|
|
92
95
|
modbus: dict = {},
|
|
93
96
|
pca9685: list = [],
|
|
94
97
|
mcp23017: list = [],
|
|
98
|
+
pcf8575: list = [],
|
|
95
99
|
ds2482: Optional[List] = [],
|
|
96
100
|
dallas: Optional[dict] = None,
|
|
97
101
|
oled: dict = {},
|
|
@@ -107,7 +111,7 @@ class Manager:
|
|
|
107
111
|
self._host_data = None
|
|
108
112
|
self._config_file_path = config_file_path
|
|
109
113
|
self._state_manager = state_manager
|
|
110
|
-
self._event_bus = EventBus(self._loop)
|
|
114
|
+
self._event_bus = EventBus(loop=self._loop)
|
|
111
115
|
|
|
112
116
|
self.send_message = send_message
|
|
113
117
|
self.stop_client = stop_client
|
|
@@ -115,6 +119,7 @@ class Manager:
|
|
|
115
119
|
self._binary_pins = binary_pins
|
|
116
120
|
self._i2cbusio = I2C(SCL, SDA)
|
|
117
121
|
self._mcp = {}
|
|
122
|
+
self._pcf = {}
|
|
118
123
|
self._pca = {}
|
|
119
124
|
self._output = {}
|
|
120
125
|
self._oled = None
|
|
@@ -132,13 +137,25 @@ class Manager:
|
|
|
132
137
|
dallas=dallas, ds2482=ds2482, sensors=sensors.get(ONEWIRE)
|
|
133
138
|
)
|
|
134
139
|
|
|
135
|
-
self.grouped_outputs =
|
|
136
|
-
|
|
140
|
+
self.grouped_outputs = create_expander(
|
|
141
|
+
expander_dict=self._mcp,
|
|
142
|
+
expander_config=mcp23017,
|
|
143
|
+
exp_type=MCP,
|
|
144
|
+
i2cbusio=self._i2cbusio
|
|
137
145
|
)
|
|
138
146
|
self.grouped_outputs.update(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
147
|
+
create_expander(
|
|
148
|
+
expander_dict=self._pcf,
|
|
149
|
+
expander_config=pcf8575,
|
|
150
|
+
exp_type=PCF,
|
|
151
|
+
i2cbusio=self._i2cbusio))
|
|
152
|
+
self.grouped_outputs.update(
|
|
153
|
+
create_expander(
|
|
154
|
+
expander_dict=self._pca,
|
|
155
|
+
expander_config=pca9685,
|
|
156
|
+
exp_type=PCA,
|
|
157
|
+
i2cbusio=self._i2cbusio))
|
|
158
|
+
|
|
142
159
|
self._configure_adc(adc_list=adc)
|
|
143
160
|
|
|
144
161
|
for _config in relay_pins:
|
|
@@ -456,14 +473,27 @@ class Manager:
|
|
|
456
473
|
def pca(self):
|
|
457
474
|
"""Get PCA by it's id."""
|
|
458
475
|
return self._pca
|
|
476
|
+
|
|
477
|
+
@property
|
|
478
|
+
def pcf(self):
|
|
479
|
+
"""Get PCF by it's id."""
|
|
480
|
+
return self._pcf
|
|
459
481
|
|
|
460
482
|
def press_callback(
|
|
461
|
-
self, x: ClickTypes, inpin: str, actions: List, input_type: InputTypes = INPUT, empty_message_after: bool = False
|
|
483
|
+
self, x: ClickTypes, inpin: str, actions: List, input_type: InputTypes = INPUT, empty_message_after: bool = False, duration: float | None = None
|
|
462
484
|
) -> None:
|
|
463
485
|
"""Press callback to use in input gpio.
|
|
464
486
|
If relay input map is provided also toggle action on relay or cover or mqtt."""
|
|
465
487
|
topic = f"{self._config_helper.topic_prefix}/{input_type}/{inpin}"
|
|
466
|
-
|
|
488
|
+
|
|
489
|
+
def generate_payload():
|
|
490
|
+
if input_type == INPUT:
|
|
491
|
+
if duration:
|
|
492
|
+
return {"event_type": x, "duration": duration}
|
|
493
|
+
return {"event_type": x}
|
|
494
|
+
return x
|
|
495
|
+
|
|
496
|
+
self.send_message(topic=topic, payload=generate_payload(), retain=False)
|
|
467
497
|
for action_definition in actions:
|
|
468
498
|
_LOGGER.debug("Executing action %s", action_definition)
|
|
469
499
|
if action_definition[ACTION] == OUTPUT:
|
|
@@ -15,9 +15,10 @@ from aiomqtt import Client as AsyncioClient, MqttError, Will
|
|
|
15
15
|
from paho.mqtt.properties import Properties
|
|
16
16
|
from paho.mqtt.subscribeoptions import SubscribeOptions
|
|
17
17
|
|
|
18
|
-
from boneio.const import
|
|
18
|
+
from boneio.const import OFFLINE, PAHO, STATE
|
|
19
19
|
from boneio.helper import UniqueQueue
|
|
20
20
|
from boneio.helper.config import ConfigHelper
|
|
21
|
+
from boneio.helper.events import GracefulExit
|
|
21
22
|
from boneio.manager import Manager
|
|
22
23
|
from boneio.helper.exceptions import RestartRequestException
|
|
23
24
|
|
|
@@ -58,7 +59,7 @@ class MQTTClient:
|
|
|
58
59
|
self.port,
|
|
59
60
|
will=Will(
|
|
60
61
|
topic=f"{self._config_helper.topic_prefix}/{STATE}",
|
|
61
|
-
payload=
|
|
62
|
+
payload=OFFLINE,
|
|
62
63
|
qos=0,
|
|
63
64
|
retain=False,
|
|
64
65
|
),
|
|
@@ -128,7 +129,7 @@ class MQTTClient:
|
|
|
128
129
|
await self.asyncio_client.unsubscribe(topic=topics, **params)
|
|
129
130
|
|
|
130
131
|
def send_message(
|
|
131
|
-
self, topic: str, payload: Union[str, dict, None], retain: bool = False
|
|
132
|
+
self, topic: str, payload: Union[str, int, dict, None], retain: bool = False
|
|
132
133
|
) -> None:
|
|
133
134
|
"""Send a message from the manager options."""
|
|
134
135
|
to_publish = (
|
|
@@ -148,26 +149,30 @@ class MQTTClient:
|
|
|
148
149
|
async def start_client(self, manager: Manager) -> None:
|
|
149
150
|
"""Start the client with the manager."""
|
|
150
151
|
# Reconnect automatically until the client is stopped.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
152
|
+
try:
|
|
153
|
+
while True:
|
|
154
|
+
try:
|
|
155
|
+
await self._subscribe_manager(manager)
|
|
156
|
+
except MqttError as err:
|
|
157
|
+
self.reconnect_interval = min(self.reconnect_interval * 2, 900)
|
|
158
|
+
_LOGGER.error(
|
|
159
|
+
"MQTT error: %s. Reconnecting in %s seconds",
|
|
160
|
+
err,
|
|
161
|
+
self.reconnect_interval,
|
|
162
|
+
)
|
|
163
|
+
self._connection_established = False
|
|
164
|
+
await asyncio.sleep(self.reconnect_interval)
|
|
165
|
+
self.create_client() # reset connect/reconnect futures
|
|
166
|
+
except (asyncio.CancelledError, GracefulExit):
|
|
167
|
+
_LOGGER.info("MQTT client task canceled.")
|
|
168
|
+
pass
|
|
164
169
|
|
|
165
170
|
async def stop_client(self) -> None:
|
|
166
171
|
await self.unsubscribe(
|
|
167
172
|
topics=self._topics
|
|
168
173
|
)
|
|
169
174
|
raise RestartRequestException("Restart requested.")
|
|
170
|
-
|
|
175
|
+
|
|
171
176
|
async def _subscribe_manager(self, manager: Manager) -> None:
|
|
172
177
|
"""Connect and subscribe to manager topics + host stats."""
|
|
173
178
|
async with AsyncExitStack() as stack:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Relay module."""
|
|
2
2
|
from boneio.relay.gpio import GpioRelay
|
|
3
3
|
from boneio.relay.mcp import MCPRelay
|
|
4
|
+
from boneio.relay.pcf import PCFRelay
|
|
4
5
|
from boneio.relay.pca import PWMPCA
|
|
5
6
|
|
|
6
|
-
__all__ = ["MCPRelay", "GpioRelay", "PWMPCA"]
|
|
7
|
+
__all__ = ["MCPRelay", "GpioRelay", "PWMPCA", "PCFRelay"]
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import logging
|
|
5
5
|
from typing import Callable
|
|
6
|
-
|
|
6
|
+
from boneio.helper.util import callback
|
|
7
7
|
from boneio.const import LIGHT, NONE, OFF, ON, RELAY, STATE, SWITCH
|
|
8
8
|
from boneio.helper import BasicMqtt
|
|
9
9
|
|
|
@@ -82,6 +82,11 @@ class BasicRelay(BasicMqtt):
|
|
|
82
82
|
else:
|
|
83
83
|
self.turn_on()
|
|
84
84
|
|
|
85
|
+
@callback
|
|
86
|
+
def _momentary_callback(self, time, action):
|
|
87
|
+
_LOGGER.info("Momentary callback at %s", time)
|
|
88
|
+
action()
|
|
89
|
+
|
|
85
90
|
@property
|
|
86
91
|
def is_active(self) -> bool:
|
|
87
92
|
"""Is active check."""
|
|
@@ -4,9 +4,8 @@ import logging
|
|
|
4
4
|
|
|
5
5
|
from adafruit_mcp230xx.mcp23017 import MCP23017, DigitalInOut
|
|
6
6
|
|
|
7
|
-
from boneio.const import NONE, SWITCH
|
|
7
|
+
from boneio.const import NONE, SWITCH, MCP
|
|
8
8
|
from boneio.helper.events import async_track_point_in_time, utcnow
|
|
9
|
-
from boneio.helper.util import callback
|
|
10
9
|
from boneio.relay.basic import BasicRelay
|
|
11
10
|
|
|
12
11
|
_LOGGER = logging.getLogger(__name__)
|
|
@@ -34,23 +33,23 @@ class MCPRelay(BasicRelay):
|
|
|
34
33
|
**kwargs, output_type=output_type, restored_state=restored_state
|
|
35
34
|
)
|
|
36
35
|
self._pin_id = pin
|
|
37
|
-
self.
|
|
36
|
+
self._expander_id = mcp_id
|
|
38
37
|
_LOGGER.debug("Setup MCP with pin %s", self._pin_id)
|
|
39
38
|
|
|
40
39
|
@property
|
|
41
|
-
def
|
|
42
|
-
"""Check
|
|
43
|
-
return
|
|
40
|
+
def expander_type(self) -> str:
|
|
41
|
+
"""Check expander type."""
|
|
42
|
+
return MCP
|
|
44
43
|
|
|
45
44
|
@property
|
|
46
|
-
def pin_id(self) ->
|
|
45
|
+
def pin_id(self) -> int:
|
|
47
46
|
"""Return PIN id."""
|
|
48
47
|
return self._pin_id
|
|
49
48
|
|
|
50
49
|
@property
|
|
51
|
-
def
|
|
50
|
+
def expander_id(self) -> str:
|
|
52
51
|
"""Retrieve parent MCP ID."""
|
|
53
|
-
return self.
|
|
52
|
+
return self._expander_id
|
|
54
53
|
|
|
55
54
|
@property
|
|
56
55
|
def is_active(self) -> bool:
|
|
@@ -62,11 +61,6 @@ class MCPRelay(BasicRelay):
|
|
|
62
61
|
"""PIN of the relay"""
|
|
63
62
|
return self._pin
|
|
64
63
|
|
|
65
|
-
@callback
|
|
66
|
-
def _momentary_callback(self, time, action):
|
|
67
|
-
_LOGGER.info("Momentary callback at %s", time)
|
|
68
|
-
action()
|
|
69
|
-
|
|
70
64
|
def turn_on(self) -> None:
|
|
71
65
|
"""Call turn on action."""
|
|
72
66
|
self.pin.value = True
|
|
@@ -9,7 +9,7 @@ from adafruit_pca9685 import PCA9685, PCAChannels
|
|
|
9
9
|
from boneio.helper.events import async_track_point_in_time, utcnow
|
|
10
10
|
from boneio.helper.util import callback
|
|
11
11
|
|
|
12
|
-
from boneio.const import LED, NONE, OFF, ON, STATE, SWITCH, BRIGHTNESS, RELAY
|
|
12
|
+
from boneio.const import LED, NONE, OFF, ON, STATE, SWITCH, BRIGHTNESS, RELAY, PCA
|
|
13
13
|
from boneio.helper import BasicMqtt
|
|
14
14
|
|
|
15
15
|
_LOGGER = logging.getLogger(__name__)
|
|
@@ -58,9 +58,9 @@ class PWMPCA(BasicMqtt):
|
|
|
58
58
|
_LOGGER.debug("Setup PCA with pin %s", self._pin_id)
|
|
59
59
|
|
|
60
60
|
@property
|
|
61
|
-
def
|
|
62
|
-
"""Check
|
|
63
|
-
return
|
|
61
|
+
def expander_type(self) -> str:
|
|
62
|
+
"""Check expander type."""
|
|
63
|
+
return PCA
|
|
64
64
|
|
|
65
65
|
@property
|
|
66
66
|
def output_type(self) -> str:
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""PCF8575 Relay module."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from adafruit_pcf8575 import DigitalInOut
|
|
6
|
+
|
|
7
|
+
from boneio.const import NONE, SWITCH, PCF
|
|
8
|
+
from boneio.helper.events import async_track_point_in_time, utcnow
|
|
9
|
+
from boneio.helper.pcf8575 import PCF8575
|
|
10
|
+
from boneio.relay.basic import BasicRelay
|
|
11
|
+
|
|
12
|
+
_LOGGER = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class PCFRelay(BasicRelay):
|
|
16
|
+
"""Represents PCF Relay output"""
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
pin: int,
|
|
21
|
+
expander: PCF8575,
|
|
22
|
+
expander_id: str,
|
|
23
|
+
output_type: str = SWITCH,
|
|
24
|
+
restored_state: bool = False,
|
|
25
|
+
**kwargs,
|
|
26
|
+
) -> None:
|
|
27
|
+
"""Initialize MCP relay."""
|
|
28
|
+
self._pin: DigitalInOut = expander.get_pin(pin)
|
|
29
|
+
if output_type == NONE:
|
|
30
|
+
"""Just in case to not restore state of covers etc."""
|
|
31
|
+
restored_state = False
|
|
32
|
+
self._pin.switch_to_output(value=restored_state)
|
|
33
|
+
super().__init__(
|
|
34
|
+
**kwargs, output_type=output_type, restored_state=restored_state
|
|
35
|
+
)
|
|
36
|
+
self._pin_id = pin
|
|
37
|
+
self._expander_id = expander_id
|
|
38
|
+
self._active_state = False
|
|
39
|
+
_LOGGER.debug("Setup PCF with pin %s", self._pin_id)
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def expander_type(self) -> str:
|
|
43
|
+
"""Check expander type."""
|
|
44
|
+
return PCF
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def pin_id(self) -> int:
|
|
48
|
+
"""Return PIN id."""
|
|
49
|
+
return self._pin_id
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def expander_id(self) -> str:
|
|
53
|
+
"""Retrieve parent MCP ID."""
|
|
54
|
+
return self._expander_id
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def is_active(self) -> bool:
|
|
58
|
+
"""Is relay active."""
|
|
59
|
+
return self.pin.value == self._active_state
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def pin(self) -> str:
|
|
63
|
+
"""PIN of the relay"""
|
|
64
|
+
return self._pin
|
|
65
|
+
|
|
66
|
+
def turn_on(self) -> None:
|
|
67
|
+
"""Call turn on action."""
|
|
68
|
+
self.pin.value = self._active_state
|
|
69
|
+
if self._momentary_turn_on:
|
|
70
|
+
async_track_point_in_time(
|
|
71
|
+
loop=self._loop,
|
|
72
|
+
action=lambda x: self._momentary_callback(time=x, action=self.turn_off),
|
|
73
|
+
point_in_time=utcnow() + self._momentary_turn_on.as_timedelta,
|
|
74
|
+
)
|
|
75
|
+
self._loop.call_soon_threadsafe(self.send_state)
|
|
76
|
+
|
|
77
|
+
def turn_off(self) -> None:
|
|
78
|
+
"""Call turn off action."""
|
|
79
|
+
self.pin.value = not self._active_state
|
|
80
|
+
if self._momentary_turn_off:
|
|
81
|
+
async_track_point_in_time(
|
|
82
|
+
loop=self._loop,
|
|
83
|
+
action=lambda x: self._momentary_callback(time=x, action=self.turn_on),
|
|
84
|
+
point_in_time=utcnow() + self._momentary_turn_off.as_timedelta,
|
|
85
|
+
)
|
|
86
|
+
self._loop.call_soon_threadsafe(self.send_state)
|
|
@@ -17,6 +17,7 @@ from boneio.const import (
|
|
|
17
17
|
EVENT_ENTITY,
|
|
18
18
|
LM75,
|
|
19
19
|
MCP23017,
|
|
20
|
+
PCF8575,
|
|
20
21
|
PCA9685,
|
|
21
22
|
MCP_TEMP_9808,
|
|
22
23
|
MODBUS,
|
|
@@ -34,11 +35,13 @@ from boneio.helper import StateManager
|
|
|
34
35
|
from boneio.helper.config import ConfigHelper
|
|
35
36
|
from boneio.manager import Manager
|
|
36
37
|
from boneio.mqtt_client import MQTTClient
|
|
38
|
+
from boneio.helper.events import EventBus
|
|
37
39
|
|
|
38
40
|
_LOGGER = logging.getLogger(__name__)
|
|
39
41
|
|
|
40
42
|
config_modules = [
|
|
41
43
|
{"name": MCP23017, "default": []},
|
|
44
|
+
{"name": PCF8575, "default": []},
|
|
42
45
|
{"name": PCA9685, "default": []},
|
|
43
46
|
{"name": DS2482, "default": []},
|
|
44
47
|
{"name": ADC, "default": []},
|
|
@@ -56,7 +59,6 @@ async def async_run(
|
|
|
56
59
|
mqttpassword: str = "",
|
|
57
60
|
) -> list[Any]:
|
|
58
61
|
"""Run BoneIO."""
|
|
59
|
-
|
|
60
62
|
_config_helper = ConfigHelper(
|
|
61
63
|
topic_prefix=config[MQTT].pop(TOPIC_PREFIX),
|
|
62
64
|
ha_discovery=config[MQTT][HA_DISCOVERY].pop(ENABLED),
|
|
@@ -98,4 +100,4 @@ async def async_run(
|
|
|
98
100
|
tasks.update(manager.get_tasks())
|
|
99
101
|
_LOGGER.info("Connecting to MQTT.")
|
|
100
102
|
tasks.add(client.start_client(manager))
|
|
101
|
-
return await asyncio.gather(*tasks)
|
|
103
|
+
return await asyncio.gather(*tasks, return_exceptions=True)
|
|
@@ -218,6 +218,33 @@ mcp23017:
|
|
|
218
218
|
meta:
|
|
219
219
|
label: How long to sleep for MCP to initialize.
|
|
220
220
|
|
|
221
|
+
|
|
222
|
+
pcf8575:
|
|
223
|
+
type: list
|
|
224
|
+
required: False
|
|
225
|
+
meta:
|
|
226
|
+
label: pcf8575 Pin config
|
|
227
|
+
schema:
|
|
228
|
+
type: dict
|
|
229
|
+
schema:
|
|
230
|
+
id: !include id.yaml
|
|
231
|
+
address:
|
|
232
|
+
type: integer
|
|
233
|
+
required: True
|
|
234
|
+
meta:
|
|
235
|
+
label: GPIO of I2C SDA
|
|
236
|
+
init_sleep:
|
|
237
|
+
type:
|
|
238
|
+
- string
|
|
239
|
+
- timeperiod
|
|
240
|
+
coerce:
|
|
241
|
+
- str
|
|
242
|
+
- positive_time_period
|
|
243
|
+
required: True
|
|
244
|
+
default: 0s
|
|
245
|
+
meta:
|
|
246
|
+
label: How long to sleep for PCF to initialize.
|
|
247
|
+
|
|
221
248
|
pca9685:
|
|
222
249
|
type: list
|
|
223
250
|
required: False
|
|
@@ -260,7 +287,7 @@ output:
|
|
|
260
287
|
label: Id to send to use in HA and in GPIO Input. Default to `kind_pin`
|
|
261
288
|
kind:
|
|
262
289
|
type: string
|
|
263
|
-
allowed: ["gpio", "mcp", "pca"]
|
|
290
|
+
allowed: ["gpio", "mcp", "pca", "pcf"]
|
|
264
291
|
meta:
|
|
265
292
|
label: Either GPIO or i2c.
|
|
266
293
|
mcp_id:
|
|
@@ -273,6 +300,11 @@ output:
|
|
|
273
300
|
required: False
|
|
274
301
|
meta:
|
|
275
302
|
label: PCA ID to connect
|
|
303
|
+
pcf_id:
|
|
304
|
+
type: string
|
|
305
|
+
required: False
|
|
306
|
+
meta:
|
|
307
|
+
label: PCF ID to connect
|
|
276
308
|
pin:
|
|
277
309
|
type:
|
|
278
310
|
- string
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""GpioInputBinarySensor to receive signals."""
|
|
2
2
|
import logging
|
|
3
3
|
from functools import partial
|
|
4
|
-
from boneio.const import PRESSED, RELEASED
|
|
4
|
+
from boneio.const import PRESSED, RELEASED, BOTH
|
|
5
5
|
from boneio.helper import GpioBaseClass
|
|
6
6
|
from boneio.helper.gpio import add_event_callback, add_event_detect
|
|
7
|
+
|
|
7
8
|
_LOGGER = logging.getLogger(__name__)
|
|
8
9
|
|
|
9
10
|
|
|
@@ -26,9 +26,10 @@ dependencies = [
|
|
|
26
26
|
"adafruit-circuitpython-onewire>=2.0.5",
|
|
27
27
|
"w1thermsensor[async]>=2.0.0",
|
|
28
28
|
"adafruit-circuitpython-pca9685>=3.4.10",
|
|
29
|
+
"adafruit-circuitpython-pcf8575>=1.0.2",
|
|
29
30
|
]
|
|
30
31
|
requires-python = ">=3.7"
|
|
31
|
-
version = "0.7.0.
|
|
32
|
+
version = "0.7.0.dev3"
|
|
32
33
|
|
|
33
34
|
[project.license]
|
|
34
35
|
text = "GNU General Public License v3.0"
|
|
@@ -42,8 +43,6 @@ Changelog = "https://github.com/boneIO-eu/app_bbb/releases"
|
|
|
42
43
|
[project.scripts]
|
|
43
44
|
boneio = "boneio.bonecli:main"
|
|
44
45
|
|
|
45
|
-
[project.optional-dependencies]
|
|
46
|
-
|
|
47
46
|
[tool.pdm.version]
|
|
48
47
|
from = "boneio/version.py"
|
|
49
48
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|