boneIO 0.6.0dev4__py3-none-any.whl → 0.6.0dev5__py3-none-any.whl
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.
Potentially problematic release.
This version of boneIO might be problematic. Click here for more details.
- {boneIO-0.6.0.dev4.dist-info → boneIO-0.6.0.dev5.dist-info}/METADATA +13 -13
- {boneIO-0.6.0.dev4.dist-info → boneIO-0.6.0.dev5.dist-info}/RECORD +21 -21
- boneIO-0.6.0.dev5.dist-info/WHEEL +4 -0
- boneio/bonecli.py +9 -3
- boneio/helper/config.py +32 -6
- boneio/helper/exceptions.py +5 -0
- boneio/helper/ha_discovery.py +9 -3
- boneio/helper/loader.py +1 -0
- boneio/helper/mqtt.py +2 -2
- boneio/input/gpio.py +1 -1
- boneio/manager.py +54 -33
- boneio/mqtt_client.py +43 -17
- boneio/relay/basic.py +3 -4
- boneio/runner.py +20 -9
- boneio/schema/actions_sensor.yaml +1 -1
- boneio/schema/actions_switch.yaml +1 -1
- boneio/schema/schema.yaml +6 -0
- boneio/sensor/gpio.py +13 -12
- boneio/version.py +1 -1
- boneIO-0.6.0.dev4.dist-info/WHEEL +0 -4
- {boneIO-0.6.0.dev4.dist-info → boneIO-0.6.0.dev5.dist-info}/entry_points.txt +0 -0
- {boneIO-0.6.0.dev4.dist-info → boneIO-0.6.0.dev5.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: boneIO
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.0dev5
|
|
4
4
|
Summary: Python App for BoneIO
|
|
5
5
|
License: GNU General Public License v3.0
|
|
6
6
|
Author-email: Paweł Szafer <pszafer@gmail.com>
|
|
7
7
|
Requires-Python: >=3.7
|
|
8
8
|
Requires-Dist: Adafruit-BBIO>=1.2.0
|
|
9
|
-
Requires-Dist: Adafruit-Blinka>=8.0
|
|
9
|
+
Requires-Dist: Adafruit-Blinka>=8.19.0
|
|
10
10
|
Requires-Dist: Cerberus>=1.3.4
|
|
11
11
|
Requires-Dist: PyYAML>=6.0
|
|
12
|
-
Requires-Dist: adafruit-circuitpython-ds18x20>=1.3.
|
|
13
|
-
Requires-Dist: adafruit-circuitpython-mcp230xx>=2.5.
|
|
14
|
-
Requires-Dist: adafruit-circuitpython-mcp9808>=3.3.
|
|
12
|
+
Requires-Dist: adafruit-circuitpython-ds18x20>=1.3.16
|
|
13
|
+
Requires-Dist: adafruit-circuitpython-mcp230xx>=2.5.9
|
|
14
|
+
Requires-Dist: adafruit-circuitpython-mcp9808>=3.3.19
|
|
15
15
|
Requires-Dist: adafruit-circuitpython-onewire>=2.0.4
|
|
16
|
-
Requires-Dist: adafruit-circuitpython-pca9685>=3.4.
|
|
17
|
-
Requires-Dist: adafruit-circuitpython-pct2075>=1.1.
|
|
18
|
-
Requires-Dist: asyncio-mqtt>=0.
|
|
19
|
-
Requires-Dist: colorlog>=6.
|
|
20
|
-
Requires-Dist: gpio>=0.
|
|
21
|
-
Requires-Dist: luma
|
|
22
|
-
Requires-Dist: luma
|
|
23
|
-
Requires-Dist: psutil>=5.9.
|
|
16
|
+
Requires-Dist: adafruit-circuitpython-pca9685>=3.4.8
|
|
17
|
+
Requires-Dist: adafruit-circuitpython-pct2075>=1.1.18
|
|
18
|
+
Requires-Dist: asyncio-mqtt>=0.16.1
|
|
19
|
+
Requires-Dist: colorlog>=6.7.0
|
|
20
|
+
Requires-Dist: gpio>=1.0.0
|
|
21
|
+
Requires-Dist: luma-core>=2.4.0
|
|
22
|
+
Requires-Dist: luma-oled>=3.12.0
|
|
23
|
+
Requires-Dist: psutil>=5.9.5
|
|
24
24
|
Requires-Dist: pymodbus>=2.5.3
|
|
25
25
|
Requires-Dist: pyserial-asyncio>=0.6
|
|
26
26
|
Requires-Dist: w1thermsensor[async]>=2.0.0
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
boneio/__init__.py,sha256=hoLKnu6h1uEsiCHA9Ql2MMDC7VQS0E-s_2cxBS-CTOg,147
|
|
2
|
-
boneio/bonecli.py,sha256=
|
|
2
|
+
boneio/bonecli.py,sha256=VhY1BMt6OaZz-752UjhEexdn8fDJkJaDWcGQNhCmgN0,3341
|
|
3
3
|
boneio/const.py,sha256=jowaP49OLdHOK2Bop2KDVPVKRVbqjBPHl_Fgl5aRzIg,2924
|
|
4
4
|
boneio/cover.py,sha256=nr76ft5smAPdBB8Jytk-uFd6RWuqtcZiG6EE129OUjw,8454
|
|
5
5
|
boneio/example_config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -14,15 +14,15 @@ boneio/fonts/danube__.ttf,sha256=KBRPUcGvmroCjrWC8zK4MulUb9lV8R0lXkOY7lNnQWc,193
|
|
|
14
14
|
boneio/helper/__init__.py,sha256=r-9dubCtDlrs_HFF2OGPQEPmw1XREgb4qQF6I486Li4,2039
|
|
15
15
|
boneio/helper/async_updater.py,sha256=BVh5mXFxgaZqoekjQbQSCTssfyVIdCQ80LCJny-rOo4,985
|
|
16
16
|
boneio/helper/click_timer.py,sha256=blWofzFIwuYcF_yFfCGDtI8nGSMpSdXdl9qMLXlKdXc,1169
|
|
17
|
-
boneio/helper/config.py,sha256=
|
|
17
|
+
boneio/helper/config.py,sha256=hhM4KUNaAFVXgQ1ZX56Zu7XV0pjp636vrcBuwoTH18g,2233
|
|
18
18
|
boneio/helper/events.py,sha256=EHYJy507RF1LikWQ2s4r990JRvR9rO4z7FkaJqt1Mrk,7494
|
|
19
|
-
boneio/helper/exceptions.py,sha256=
|
|
19
|
+
boneio/helper/exceptions.py,sha256=vyYSUojwB7OttOPUjbxeHFM7C_o5ZQmRUcZ_vYpxYYI,717
|
|
20
20
|
boneio/helper/filter.py,sha256=UcjifjaC5wHDW2He7wmwCX2IjSSeLVhXyhrXHeT8RmA,885
|
|
21
21
|
boneio/helper/gpio.py,sha256=v4QrJfwlhIOqRCcD1SCpwPVcY6zsTlm1tens0eLbazM,2718
|
|
22
|
-
boneio/helper/ha_discovery.py,sha256=
|
|
23
|
-
boneio/helper/loader.py,sha256=
|
|
22
|
+
boneio/helper/ha_discovery.py,sha256=s80gwx1Fik2_vtq-6kqabUqPx4KwwZUt4G1Oy6RgGgU,6278
|
|
23
|
+
boneio/helper/loader.py,sha256=dKlk42tI7RkyI_FmX6CneN3FIGnHQ55c20sfn11B_bk,13547
|
|
24
24
|
boneio/helper/logger.py,sha256=zyF_Vk3o2eSHuXypJhNzK99eZgkWDWybuB5KcJgurDs,1801
|
|
25
|
-
boneio/helper/mqtt.py,sha256=
|
|
25
|
+
boneio/helper/mqtt.py,sha256=UVa4KaxvVif6By_sVMdSMiYI_doZjiXF4LS9RFltxJk,765
|
|
26
26
|
boneio/helper/oled.py,sha256=f0XYbaFstUbJ6ISmFe1vQCnmNVMctQWtnStNdROrblc,351
|
|
27
27
|
boneio/helper/onewire/W1ThermSensor.py,sha256=Pu5Fp29pKbxjJqDbFs05Mjg3Vy-9z_DTVoBpSWM_byA,2430
|
|
28
28
|
boneio/helper/onewire/__init__.py,sha256=4djH-uxiq5XhAiFTOxyqjvWVoJe0c8U8iN0BfmH8nSU,448
|
|
@@ -35,29 +35,29 @@ boneio/helper/timeperiod.py,sha256=xpg9oe30Z5WiLDQPq3EBKKScejOnN47NhcpeFvDd3bY,5
|
|
|
35
35
|
boneio/helper/util.py,sha256=QfSoT3H3WnOQAKO5bFRIBCy62HT5NMa9Ek-FmfTW_rw,508
|
|
36
36
|
boneio/helper/yaml_util.py,sha256=gAX7hCaHUlPgkhGCIQ4zjv0Vj9JmLzQsSyF51ZmSb9g,11304
|
|
37
37
|
boneio/input/__init__.py,sha256=u9wuehuC_TNizL4tyn7EygZW5LaTFjSnFaZeZr3zZ1U,99
|
|
38
|
-
boneio/input/gpio.py,sha256=
|
|
39
|
-
boneio/manager.py,sha256=
|
|
38
|
+
boneio/input/gpio.py,sha256=7teo2fDyDUarorCn9REF5sGFMIimRrWaKOqildYG8_Y,2597
|
|
39
|
+
boneio/manager.py,sha256=cs2vy-26kvQROWHjHopACY2U1OLufcsu522RjShVXyQ,21023
|
|
40
40
|
boneio/modbus.py,sha256=eA_sGnmdcIneXX75ZcXOI223-UkKN1UYmWFqiJBAhJo,4176
|
|
41
|
-
boneio/mqtt_client.py,sha256=
|
|
41
|
+
boneio/mqtt_client.py,sha256=NYvok8y_g8iRXDopVojzcDGVnDJEFqHBEYhOGy8m7T8,8331
|
|
42
42
|
boneio/oled.py,sha256=d_ofDQHc7zr3j0qOR0B_L3C8TJhvRH85nnb9Le-88nk,5244
|
|
43
43
|
boneio/relay/__init__.py,sha256=iLEUL8kxnEndCQtgDIJfHqUZOfyWfWmuOrqSYAUxb2w,181
|
|
44
|
-
boneio/relay/basic.py,sha256=
|
|
44
|
+
boneio/relay/basic.py,sha256=QEWG8HodBqEqLpQxcQm29hdPIxO7c6ep0uDgfo3pcco,2623
|
|
45
45
|
boneio/relay/gpio.py,sha256=s64FBf6zlxciF57xJ6nrvy0t5Rie0uiXlwos0HL3RKM,1163
|
|
46
46
|
boneio/relay/mcp.py,sha256=DhgqZbFHB6TucL9hJaJiqdVAbkw4Rv5VPHm_khSBIFo,2669
|
|
47
47
|
boneio/relay/pca.py,sha256=tCwXvMJcsxzFj48ZO2tPYyvElZfyIRTFmEMp7ENKvtk,4873
|
|
48
|
-
boneio/runner.py,sha256=
|
|
48
|
+
boneio/runner.py,sha256=eLRd3NtE8c5fqYu76B4Kz7vs5ftNDSZ_L-KHbipRu90,2569
|
|
49
49
|
boneio/schema/actions.yaml,sha256=WD0LR9SxVPgwU12x10RvFaTeyDiCjdRiicfkrCGLNvc,1030
|
|
50
|
-
boneio/schema/actions_sensor.yaml,sha256=
|
|
51
|
-
boneio/schema/actions_switch.yaml,sha256=
|
|
50
|
+
boneio/schema/actions_sensor.yaml,sha256=U_VfdjqdorQZHYD6dZOzhlRKnOGwsnTJ3CDGiqrKxW8,124
|
|
51
|
+
boneio/schema/actions_switch.yaml,sha256=sdqhwz0LrcfaiAN3-RfAR_xApxo5dh9RxXQubuKcsjk,129
|
|
52
52
|
boneio/schema/filters.yaml,sha256=WopX1SmCZsSZXNiGccLoi7uMCsUpdbs0eVfsAjmbay4,286
|
|
53
53
|
boneio/schema/filters_adc.yaml,sha256=3e0ts92MoFKOnfGOOn6WYIHxu0-tnZe9OjAjN9m7hiI,304
|
|
54
54
|
boneio/schema/id.yaml,sha256=vHI_6dxkJwoiGp5ien_pPpyaWA1F06eirTgfWMyWa1E,75
|
|
55
|
-
boneio/schema/schema.yaml,sha256=
|
|
55
|
+
boneio/schema/schema.yaml,sha256=GHqcUaCUJypX2JD7tXVKoIZ3XO4rqLaoHW0ppWFWvzU,12988
|
|
56
56
|
boneio/schema/temp_unit.yaml,sha256=m32VGz9RTW92Lz08l9n6RftkcVNZquOGPPr5mc3eZVc,65
|
|
57
57
|
boneio/schema/update_interval.yaml,sha256=L_YLddAZdybcdO-T57Qhlv1GaWIVDwhvH-GadD1oOIo,133
|
|
58
58
|
boneio/sensor/__init__.py,sha256=VjFBEQQv_U0T2ENkzefuBdzmqNvBTEv4M-gQKScc8o0,431
|
|
59
59
|
boneio/sensor/adc.py,sha256=Yf5F8JcZJt0K4ijpPqI8do0BqDfLvfja_LE8_Zu3u7U,1281
|
|
60
|
-
boneio/sensor/gpio.py,sha256=
|
|
60
|
+
boneio/sensor/gpio.py,sha256=oAUYHGLX0_JK6AJMplmDBnLBIAZ2GaDJ7ts8AceljvQ,1303
|
|
61
61
|
boneio/sensor/modbus/__init__.py,sha256=LEOnMqBACNxZmCN2adZtTsq76gPbsNba5JewMiUENBw,8500
|
|
62
62
|
boneio/sensor/modbus/dts1964_3f.json,sha256=WABph_2X4OgMidSM28vw4dLd9ZByRoiUP-RqE0UMpR8,8810
|
|
63
63
|
boneio/sensor/modbus/pt100.json,sha256=bzKNYDc3lMto94Ut8gutVIsHytQiMobwFCkonOiMegs,526
|
|
@@ -69,9 +69,9 @@ boneio/sensor/temp/__init__.py,sha256=h5rGbkC8K6y2GJSNHtm9f8EmoBS3wFlSNIFjcrRj47
|
|
|
69
69
|
boneio/sensor/temp/dallas.py,sha256=xrvd1LNBh1fRcjz_yd_9S29Lv26ItVtLCmhZgVQWJos,2485
|
|
70
70
|
boneio/sensor/temp/lm75.py,sha256=-mpOv78429plRPBp9s09Ljz1x2Bdxuagalqz40vlAKE,243
|
|
71
71
|
boneio/sensor/temp/mcp9808.py,sha256=yAh5yJzZLGTqa39xV4fyqsruj7oy3niOZAUV2W6eyCM,271
|
|
72
|
-
boneio/version.py,sha256=
|
|
73
|
-
boneIO-0.6.0.
|
|
74
|
-
boneIO-0.6.0.
|
|
75
|
-
boneIO-0.6.0.
|
|
76
|
-
boneIO-0.6.0.
|
|
77
|
-
boneIO-0.6.0.
|
|
72
|
+
boneio/version.py,sha256=MRoHBbiT0xKVNIGf8uc_weaaaOMvuoXa9HcssIlg3_0,41
|
|
73
|
+
boneIO-0.6.0.dev5.dist-info/entry_points.txt,sha256=Igl1SMDEWwMg144bwRz28UOCb80hdxomC99QJ3u6qC0,46
|
|
74
|
+
boneIO-0.6.0.dev5.dist-info/WHEEL,sha256=B19PGBCYhWaz2p_UjAoRVh767nYQfk14Sn4TpIZ-nfU,87
|
|
75
|
+
boneIO-0.6.0.dev5.dist-info/METADATA,sha256=b5xgbS9_foPU_jVQq9CPRUDE1XV9Ceq_LlI0e6KBz9U,1698
|
|
76
|
+
boneIO-0.6.0.dev5.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
77
|
+
boneIO-0.6.0.dev5.dist-info/RECORD,,
|
boneio/bonecli.py
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"""Bonecli script."""
|
|
2
|
+
from __future__ import annotations
|
|
2
3
|
import argparse
|
|
3
4
|
import asyncio
|
|
4
5
|
import logging
|
|
5
6
|
import sys
|
|
6
7
|
import os
|
|
8
|
+
from typing import Any
|
|
7
9
|
|
|
8
10
|
os.environ["W1THERMSENSOR_NO_KERNEL_MODULE"] = "1"
|
|
9
11
|
|
|
@@ -12,7 +14,7 @@ from yaml import MarkedYAMLError
|
|
|
12
14
|
|
|
13
15
|
from boneio.const import ACTION
|
|
14
16
|
from boneio.helper import load_config_from_file
|
|
15
|
-
from boneio.helper.exceptions import ConfigurationException
|
|
17
|
+
from boneio.helper.exceptions import ConfigurationException, RestartRequestException
|
|
16
18
|
from boneio.helper.logger import configure_logger
|
|
17
19
|
from boneio.runner import async_run
|
|
18
20
|
from boneio.version import __version__
|
|
@@ -69,7 +71,7 @@ def get_arguments() -> argparse.Namespace:
|
|
|
69
71
|
return arguments
|
|
70
72
|
|
|
71
73
|
|
|
72
|
-
def run(config: str, debug: int, mqttusername: str = "", mqttpassword: str = ""):
|
|
74
|
+
def run(config: str, debug: int, mqttusername: str = "", mqttpassword: str = "") -> int:
|
|
73
75
|
"""Run BoneIO."""
|
|
74
76
|
_LOGGER.info("BoneIO %s starting.", __version__)
|
|
75
77
|
try:
|
|
@@ -78,7 +80,7 @@ def run(config: str, debug: int, mqttusername: str = "", mqttpassword: str = "")
|
|
|
78
80
|
_LOGGER.error("Config not loaded. Exiting.")
|
|
79
81
|
return 1
|
|
80
82
|
configure_logger(log_config=_config.get("logger"), debug=debug)
|
|
81
|
-
|
|
83
|
+
asyncio.run(
|
|
82
84
|
async_run(
|
|
83
85
|
config=_config,
|
|
84
86
|
config_file=config,
|
|
@@ -86,6 +88,10 @@ def run(config: str, debug: int, mqttusername: str = "", mqttpassword: str = "")
|
|
|
86
88
|
mqttpassword=mqttpassword,
|
|
87
89
|
),
|
|
88
90
|
)
|
|
91
|
+
return 0
|
|
92
|
+
except RestartRequestException as err:
|
|
93
|
+
_LOGGER.info(err)
|
|
94
|
+
return 0
|
|
89
95
|
except (ConfigurationException, MarkedYAMLError) as err:
|
|
90
96
|
_LOGGER.error("Failed to load config. %s Exiting.", err)
|
|
91
97
|
return 1
|
boneio/helper/config.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Module to provide basic config options.
|
|
3
3
|
"""
|
|
4
|
+
from __future__ import annotations
|
|
4
5
|
from _collections_abc import dict_values
|
|
5
|
-
|
|
6
|
-
from boneio.const import BONEIO, HOMEASSISTANT
|
|
6
|
+
from boneio.const import BONEIO, HOMEASSISTANT, LIGHT, SENSOR, COVER, BUTTON, SWITCH, BINARY_SENSOR
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class ConfigHelper:
|
|
@@ -16,7 +16,16 @@ class ConfigHelper:
|
|
|
16
16
|
self._topic_prefix = topic_prefix
|
|
17
17
|
self._ha_discovery = ha_discovery
|
|
18
18
|
self._ha_discovery_prefix = ha_discovery_prefix
|
|
19
|
-
self.
|
|
19
|
+
self._fetch_old_discovery = None
|
|
20
|
+
self._autodiscovery_messages = {
|
|
21
|
+
SWITCH: {},
|
|
22
|
+
LIGHT: {},
|
|
23
|
+
BINARY_SENSOR: {},
|
|
24
|
+
SENSOR: {},
|
|
25
|
+
COVER: {},
|
|
26
|
+
BUTTON: {}
|
|
27
|
+
}
|
|
28
|
+
self.manager_ready: bool = False
|
|
20
29
|
|
|
21
30
|
@property
|
|
22
31
|
def topic_prefix(self) -> str:
|
|
@@ -38,11 +47,28 @@ class ConfigHelper:
|
|
|
38
47
|
def subscribe_topic(self) -> str:
|
|
39
48
|
return f"{self.cmd_topic_prefix}+/+/#"
|
|
40
49
|
|
|
41
|
-
def add_autodiscovery_msg(self, topic: str, payload: str):
|
|
50
|
+
def add_autodiscovery_msg(self, ha_type: str, topic: str, payload: str):
|
|
42
51
|
"""Add autodiscovery message."""
|
|
43
|
-
self._autodiscovery_messages[topic] = {"topic": topic, "payload": payload}
|
|
52
|
+
self._autodiscovery_messages[ha_type][topic] = {"topic": topic, "payload": payload}
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def ha_types(self) -> list[str]:
|
|
56
|
+
return list(self._autodiscovery_messages.keys())
|
|
57
|
+
|
|
58
|
+
def is_topic_in_autodiscovery(self, topic: str) -> bool:
|
|
59
|
+
topic_parts_raw = topic[len(f"{self._ha_discovery_prefix}/") :].split("/")
|
|
60
|
+
ha_type = topic_parts_raw[0]
|
|
61
|
+
if ha_type in self._autodiscovery_messages:
|
|
62
|
+
if topic in self._autodiscovery_messages[ha_type]:
|
|
63
|
+
return True
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
|
|
44
67
|
|
|
45
68
|
@property
|
|
46
69
|
def autodiscovery_msgs(self) -> dict_values:
|
|
47
70
|
"""Get autodiscovery messages"""
|
|
48
|
-
|
|
71
|
+
output = {}
|
|
72
|
+
for ha_type in self._autodiscovery_messages:
|
|
73
|
+
output.update(self._autodiscovery_messages[ha_type])
|
|
74
|
+
return output.values()
|
boneio/helper/exceptions.py
CHANGED
|
@@ -8,6 +8,7 @@ class BoneIOException(Exception):
|
|
|
8
8
|
class GPIOInputException(BoneIOException):
|
|
9
9
|
"""GPIOInput Exception."""
|
|
10
10
|
|
|
11
|
+
|
|
11
12
|
class GPIOOutputException(BoneIOException):
|
|
12
13
|
"""GPIOInput Exception."""
|
|
13
14
|
|
|
@@ -30,3 +31,7 @@ class CoverRelayException(BoneIOException):
|
|
|
30
31
|
|
|
31
32
|
class ModbusUartException(BoneIOException):
|
|
32
33
|
"""Cover configuration exception."""
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class RestartRequestException(BoneIOException):
|
|
37
|
+
"""Restart exception."""
|
boneio/helper/ha_discovery.py
CHANGED
|
@@ -51,6 +51,7 @@ def ha_light_availabilty_message(id: str, topic: str = "boneIO", **kwargs):
|
|
|
51
51
|
msg["state_value_template"] = "{{ value_json.state }}"
|
|
52
52
|
return msg
|
|
53
53
|
|
|
54
|
+
|
|
54
55
|
def ha_led_availabilty_message(id: str, topic: str = "boneIO", **kwargs):
|
|
55
56
|
"""Create LED availability topic for HA."""
|
|
56
57
|
msg = ha_availabilty_message(device_type=RELAY, topic=topic, id=id, **kwargs)
|
|
@@ -64,11 +65,14 @@ def ha_led_availabilty_message(id: str, topic: str = "boneIO", **kwargs):
|
|
|
64
65
|
msg["brightness_value_template"] = "{{ value_json.brightness }}"
|
|
65
66
|
return msg
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
|
|
69
|
+
def ha_button_availabilty_message(
|
|
70
|
+
id: str, topic: str = "boneIO", payload_press: str = "reload", **kwargs
|
|
71
|
+
):
|
|
68
72
|
"""Create BUTTON availability topic for HA."""
|
|
69
73
|
msg = ha_availabilty_message(device_type="button", topic=topic, id=id, **kwargs)
|
|
70
74
|
msg["command_topic"] = f"{topic}/cmd/button/{id}/set"
|
|
71
|
-
msg["payload_press"] =
|
|
75
|
+
msg["payload_press"] = payload_press
|
|
72
76
|
return msg
|
|
73
77
|
|
|
74
78
|
|
|
@@ -102,9 +106,11 @@ def ha_sensor_availabilty_message(unit_of_measurement: str = None, **kwargs):
|
|
|
102
106
|
return msg
|
|
103
107
|
|
|
104
108
|
|
|
105
|
-
def ha_binary_sensor_availabilty_message(id: str, name: str, topic: str = "boneIO"):
|
|
109
|
+
def ha_binary_sensor_availabilty_message(id: str, name: str, device_class: str, topic: str = "boneIO"):
|
|
106
110
|
"""Create availability topic for HA."""
|
|
111
|
+
kwargs = {"device_class": device_class} if device_class else {}
|
|
107
112
|
return {
|
|
113
|
+
**kwargs,
|
|
108
114
|
"availability": [{"topic": f"{topic}/{STATE}"}],
|
|
109
115
|
"device": {
|
|
110
116
|
"identifiers": [topic],
|
boneio/helper/loader.py
CHANGED
boneio/helper/mqtt.py
CHANGED
|
@@ -21,11 +21,11 @@ class BasicMqtt:
|
|
|
21
21
|
self._send_topic = f"{topic_prefix}/{topic_type}/{self.id}"
|
|
22
22
|
|
|
23
23
|
@property
|
|
24
|
-
def id(self) ->
|
|
24
|
+
def id(self) -> str:
|
|
25
25
|
"""Id of the module."""
|
|
26
26
|
return self._id
|
|
27
27
|
|
|
28
28
|
@property
|
|
29
|
-
def name(self):
|
|
29
|
+
def name(self) -> str:
|
|
30
30
|
"""Return name of the sensor."""
|
|
31
31
|
return self._name
|
boneio/input/gpio.py
CHANGED
|
@@ -53,7 +53,7 @@ class GpioInputButton(GpioBaseClass):
|
|
|
53
53
|
self.check_state(state=self.is_pressed)
|
|
54
54
|
await asyncio.sleep(self._bounce_time.total_in_seconds)
|
|
55
55
|
|
|
56
|
-
def check_state(self, state):
|
|
56
|
+
def check_state(self, state: bool) -> None:
|
|
57
57
|
if state == self._state:
|
|
58
58
|
return
|
|
59
59
|
self._state = state
|
boneio/manager.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import logging
|
|
3
3
|
from collections import deque
|
|
4
|
-
from typing import Callable, Coroutine, List, Optional, Set, Union
|
|
4
|
+
from typing import Callable, Coroutine, List, Optional, Set, Union, Awaitable
|
|
5
5
|
from board import SCL, SDA
|
|
6
6
|
from busio import I2C
|
|
7
7
|
|
|
@@ -80,34 +80,35 @@ class Manager:
|
|
|
80
80
|
def __init__(
|
|
81
81
|
self,
|
|
82
82
|
send_message: Callable[[str, Union[str, dict], bool], None],
|
|
83
|
+
stop_client: Callable[[], Awaitable[None]],
|
|
83
84
|
state_manager: StateManager,
|
|
84
85
|
config_helper: ConfigHelper,
|
|
85
86
|
config_file_path: str,
|
|
86
87
|
relay_pins: List = [],
|
|
87
88
|
input_pins: List = [],
|
|
88
89
|
sensors: dict = {},
|
|
89
|
-
modbus: dict =
|
|
90
|
-
pca9685:
|
|
91
|
-
mcp23017:
|
|
90
|
+
modbus: dict = {},
|
|
91
|
+
pca9685: list = [],
|
|
92
|
+
mcp23017: list = [],
|
|
92
93
|
ds2482: Optional[List] = [],
|
|
93
94
|
dallas: Optional[dict] = None,
|
|
94
95
|
oled: dict = {},
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
adc: Optional[List] = None,
|
|
97
|
+
cover: list = [],
|
|
97
98
|
) -> None:
|
|
98
99
|
"""Initialize the manager."""
|
|
99
100
|
_LOGGER.info("Initializing manager module.")
|
|
100
101
|
|
|
101
102
|
self._loop = asyncio.get_event_loop()
|
|
102
|
-
|
|
103
|
+
|
|
103
104
|
self._config_helper = config_helper
|
|
104
105
|
self._host_data = None
|
|
105
106
|
self._config_file_path = config_file_path
|
|
106
107
|
self._state_manager = state_manager
|
|
107
108
|
self._event_bus = EventBus(self._loop)
|
|
108
|
-
self._autodiscovery_messages = []
|
|
109
109
|
|
|
110
110
|
self.send_message = send_message
|
|
111
|
+
self.stop_client = stop_client
|
|
111
112
|
self._input_pins = input_pins
|
|
112
113
|
self._i2cbusio = I2C(SCL, SDA)
|
|
113
114
|
self._mcp = {}
|
|
@@ -135,7 +136,7 @@ class Manager:
|
|
|
135
136
|
create_pca9685(manager=self, pca9685=pca9685, i2cbusio=self._i2cbusio)
|
|
136
137
|
)
|
|
137
138
|
|
|
138
|
-
self._configure_adc(adc_list=
|
|
139
|
+
self._configure_adc(adc_list=adc)
|
|
139
140
|
|
|
140
141
|
for _config in relay_pins:
|
|
141
142
|
_id = _config[ID].replace(" ", "")
|
|
@@ -166,7 +167,7 @@ class Manager:
|
|
|
166
167
|
out.send_state,
|
|
167
168
|
)
|
|
168
169
|
|
|
169
|
-
for _config in
|
|
170
|
+
for _config in cover:
|
|
170
171
|
_id = _config[ID].replace(" ", "")
|
|
171
172
|
open_relay = self._output.get(_config.get("open_relay"))
|
|
172
173
|
close_relay = self._output.get(_config.get("close_relay"))
|
|
@@ -204,24 +205,12 @@ class Manager:
|
|
|
204
205
|
)
|
|
205
206
|
|
|
206
207
|
_LOGGER.info("Initializing inputs. This will take a while.")
|
|
207
|
-
|
|
208
|
-
pin = gpio.pop(PIN)
|
|
209
|
-
if pin in used_pins:
|
|
210
|
-
_LOGGER.warn("This PIN %s is already configured. Omitting it.", pin)
|
|
211
|
-
continue
|
|
212
|
-
used_pins.add(
|
|
213
|
-
configure_input(
|
|
214
|
-
gpio=gpio,
|
|
215
|
-
pin=pin,
|
|
216
|
-
press_callback=self.press_callback,
|
|
217
|
-
send_ha_autodiscovery=self.send_ha_autodiscovery,
|
|
218
|
-
)
|
|
219
|
-
)
|
|
208
|
+
self.configure_inputs(reload_config=False)
|
|
220
209
|
|
|
221
210
|
if oled.get("enabled", False):
|
|
222
211
|
from boneio.oled import Oled
|
|
223
212
|
|
|
224
|
-
screens = oled.get("screens")
|
|
213
|
+
screens = oled.get("screens", [])
|
|
225
214
|
|
|
226
215
|
self._host_data = HostData(
|
|
227
216
|
manager=self,
|
|
@@ -240,9 +229,26 @@ class Manager:
|
|
|
240
229
|
except (GPIOInputException, I2CError) as err:
|
|
241
230
|
_LOGGER.error("Can't configure OLED display. %s", err)
|
|
242
231
|
self.prepare_ha_buttons()
|
|
243
|
-
|
|
244
232
|
_LOGGER.info("BoneIO manager is ready.")
|
|
245
233
|
|
|
234
|
+
def configure_inputs(self, reload_config: bool = False):
|
|
235
|
+
used_pins = set()
|
|
236
|
+
if reload_config:
|
|
237
|
+
load_config_from_file(self._config_file_path)
|
|
238
|
+
for gpio in self._input_pins:
|
|
239
|
+
pin = gpio.pop(PIN)
|
|
240
|
+
if pin in used_pins:
|
|
241
|
+
_LOGGER.warn("This PIN %s is already configured. Omitting it.", pin)
|
|
242
|
+
continue
|
|
243
|
+
used_pins.add(
|
|
244
|
+
configure_input(
|
|
245
|
+
gpio=gpio,
|
|
246
|
+
pin=pin,
|
|
247
|
+
press_callback=self.press_callback,
|
|
248
|
+
send_ha_autodiscovery=self.send_ha_autodiscovery,
|
|
249
|
+
)
|
|
250
|
+
)
|
|
251
|
+
|
|
246
252
|
def append_task(self, coro: Coroutine, name: str = "Unknown") -> asyncio.Future:
|
|
247
253
|
"""Add task to run with asyncio loop."""
|
|
248
254
|
_LOGGER.debug("Appending update task for %s", name)
|
|
@@ -337,20 +343,22 @@ class Manager:
|
|
|
337
343
|
)
|
|
338
344
|
|
|
339
345
|
def _configure_modbus(self, modbus: dict) -> None:
|
|
340
|
-
|
|
346
|
+
uart = modbus.get(UART)
|
|
347
|
+
if uart and uart in UARTS:
|
|
341
348
|
try:
|
|
342
|
-
self._modbus = Modbus(UARTS[
|
|
349
|
+
self._modbus = Modbus(UARTS[uart])
|
|
343
350
|
except ModbusUartException:
|
|
344
351
|
_LOGGER.error(
|
|
345
352
|
"This UART %s can't be used for modbus communication.",
|
|
346
|
-
|
|
353
|
+
uart,
|
|
347
354
|
)
|
|
348
355
|
self._modbus = None
|
|
349
356
|
|
|
350
357
|
def _configure_temp_sensors(self, sensors: dict) -> None:
|
|
351
358
|
for sensor_type in (LM75, MCP_TEMP_9808):
|
|
352
|
-
|
|
353
|
-
|
|
359
|
+
sensor = sensors.get(sensor_type)
|
|
360
|
+
if sensor:
|
|
361
|
+
for temp_def in sensor:
|
|
354
362
|
temp_sensor = create_temp_sensor(
|
|
355
363
|
manager=self,
|
|
356
364
|
topic_prefix=self._config_helper.topic_prefix,
|
|
@@ -409,10 +417,19 @@ class Manager:
|
|
|
409
417
|
def prepare_ha_buttons(self) -> None:
|
|
410
418
|
"""Prepare HA buttons for reload."""
|
|
411
419
|
self.send_ha_autodiscovery(
|
|
412
|
-
id="
|
|
420
|
+
id="logger",
|
|
413
421
|
name="Logger reload",
|
|
414
422
|
ha_type=BUTTON,
|
|
415
423
|
availability_msg_func=ha_button_availabilty_message,
|
|
424
|
+
entity_category="config",
|
|
425
|
+
)
|
|
426
|
+
self.send_ha_autodiscovery(
|
|
427
|
+
id="restart",
|
|
428
|
+
name="Restart boneIO",
|
|
429
|
+
ha_type=BUTTON,
|
|
430
|
+
payload_press="restart",
|
|
431
|
+
availability_msg_func=ha_button_availabilty_message,
|
|
432
|
+
entity_category="config",
|
|
416
433
|
)
|
|
417
434
|
|
|
418
435
|
@property
|
|
@@ -431,7 +448,7 @@ class Manager:
|
|
|
431
448
|
"""Press callback to use in input gpio.
|
|
432
449
|
If relay input map is provided also toggle action on relay or cover or mqtt."""
|
|
433
450
|
topic = f"{self._config_helper.topic_prefix}/{input_type}/{inpin}"
|
|
434
|
-
self.send_message(topic=topic, payload=x)
|
|
451
|
+
self.send_message(topic=topic, payload=x, retain=False)
|
|
435
452
|
for action_definition in actions:
|
|
436
453
|
_LOGGER.debug("Executing action %s", action_definition)
|
|
437
454
|
if action_definition[ACTION] == OUTPUT:
|
|
@@ -480,13 +497,14 @@ class Manager:
|
|
|
480
497
|
payload = availability_msg_func(topic=topic_prefix, id=id, name=name, **kwargs)
|
|
481
498
|
topic = f"{self._config_helper.ha_discovery_prefix}/{ha_type}/{topic_prefix}/{id}/config"
|
|
482
499
|
_LOGGER.debug("Sending HA discovery for %s, %s.", ha_type, name)
|
|
483
|
-
self._config_helper.add_autodiscovery_msg(topic=topic, payload=payload)
|
|
500
|
+
self._config_helper.add_autodiscovery_msg(topic=topic, ha_type=ha_type, payload=payload)
|
|
484
501
|
self.send_message(topic=topic, payload=payload, retain=True)
|
|
485
502
|
|
|
486
503
|
def resend_autodiscovery(self) -> None:
|
|
487
504
|
for msg in self._config_helper.autodiscovery_msgs:
|
|
488
505
|
self.send_message(**msg, retain=True)
|
|
489
506
|
|
|
507
|
+
|
|
490
508
|
async def receive_message(self, topic: str, message: str) -> None:
|
|
491
509
|
"""Callback for receiving action from Mqtt."""
|
|
492
510
|
_LOGGER.debug("Processing topic %s with message %s.", topic, message)
|
|
@@ -558,6 +576,9 @@ class Manager:
|
|
|
558
576
|
if device_id == "logger" and message == "reload":
|
|
559
577
|
_LOGGER.info("Reloading logger configuration.")
|
|
560
578
|
self._logger_reload()
|
|
579
|
+
elif device_id == "restart" and message == "restart":
|
|
580
|
+
_LOGGER.info("Exiting process. Systemd should restart it soon.")
|
|
581
|
+
await self.stop_client()
|
|
561
582
|
|
|
562
583
|
@property
|
|
563
584
|
def output(self) -> dict:
|
boneio/mqtt_client.py
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
Provide an MQTT client for providing BoneIO MQTT broker.
|
|
3
3
|
Code based on cgarwood/python-openzwave-mqtt.
|
|
4
4
|
"""
|
|
5
|
+
from __future__ import annotations
|
|
5
6
|
import asyncio
|
|
6
7
|
import json
|
|
7
8
|
import logging
|
|
8
9
|
import uuid
|
|
9
10
|
from contextlib import AsyncExitStack
|
|
10
|
-
from typing import Any, Callable, Optional, Set,
|
|
11
|
+
from typing import Any, Callable, Optional, Set, Union, Awaitable
|
|
11
12
|
|
|
12
13
|
import paho.mqtt.client as mqtt
|
|
13
14
|
from asyncio_mqtt import Client as AsyncioClient
|
|
@@ -18,6 +19,8 @@ from paho.mqtt.subscribeoptions import SubscribeOptions
|
|
|
18
19
|
from boneio.const import ONLINE, PAHO, STATE
|
|
19
20
|
from boneio.helper import UniqueQueue
|
|
20
21
|
from boneio.helper.config import ConfigHelper
|
|
22
|
+
from boneio.manager import Manager
|
|
23
|
+
from boneio.helper.exceptions import RestartRequestException
|
|
21
24
|
|
|
22
25
|
_LOGGER = logging.getLogger(__name__)
|
|
23
26
|
|
|
@@ -45,6 +48,8 @@ class MQTTClient:
|
|
|
45
48
|
self.reconnect_interval = 1
|
|
46
49
|
self._connection_established = False
|
|
47
50
|
self.publish_queue: UniqueQueue = UniqueQueue()
|
|
51
|
+
self._discovery_topics = [f"{self._config_helper.ha_discovery_prefix}/{ha_type}/{self._config_helper.topic_prefix}/#" for ha_type in self._config_helper.ha_types] if self._config_helper.ha_discovery else []
|
|
52
|
+
self._topics = [self._config_helper.subscribe_topic, "homeassistant/status"]
|
|
48
53
|
|
|
49
54
|
def create_client(self) -> None:
|
|
50
55
|
"""Create the asyncio client."""
|
|
@@ -85,7 +90,7 @@ class MQTTClient:
|
|
|
85
90
|
|
|
86
91
|
async def subscribe( # pylint:disable=too-many-arguments
|
|
87
92
|
self,
|
|
88
|
-
topics:
|
|
93
|
+
topics: list[str],
|
|
89
94
|
qos: int = 0,
|
|
90
95
|
options: Optional[SubscribeOptions] = None,
|
|
91
96
|
properties: Optional[Properties] = None,
|
|
@@ -108,7 +113,10 @@ class MQTTClient:
|
|
|
108
113
|
await self.asyncio_client.subscribe(topic=args, **params, timeout=timeout)
|
|
109
114
|
|
|
110
115
|
async def unsubscribe(
|
|
111
|
-
self,
|
|
116
|
+
self,
|
|
117
|
+
topics: list[str],
|
|
118
|
+
properties: Optional[Properties] = None,
|
|
119
|
+
timeout: float = 10.0,
|
|
112
120
|
) -> None:
|
|
113
121
|
"""Unsubscribe from topic.
|
|
114
122
|
|
|
@@ -118,10 +126,10 @@ class MQTTClient:
|
|
|
118
126
|
if properties:
|
|
119
127
|
params["properties"] = properties
|
|
120
128
|
|
|
121
|
-
await self.asyncio_client.unsubscribe(topic, **params)
|
|
129
|
+
await self.asyncio_client.unsubscribe(topic=topics, **params)
|
|
122
130
|
|
|
123
131
|
def send_message(
|
|
124
|
-
self, topic: str, payload: Union[str, dict], retain: bool = False
|
|
132
|
+
self, topic: str, payload: Union[str, dict, None], retain: bool = False
|
|
125
133
|
) -> None:
|
|
126
134
|
"""Send a message from the manager options."""
|
|
127
135
|
to_publish = (
|
|
@@ -138,7 +146,7 @@ class MQTTClient:
|
|
|
138
146
|
await self.publish(*to_publish)
|
|
139
147
|
self.publish_queue.task_done()
|
|
140
148
|
|
|
141
|
-
async def start_client(self, manager:
|
|
149
|
+
async def start_client(self, manager: Manager) -> None:
|
|
142
150
|
"""Start the client with the manager."""
|
|
143
151
|
# Reconnect automatically until the client is stopped.
|
|
144
152
|
while True:
|
|
@@ -155,7 +163,13 @@ class MQTTClient:
|
|
|
155
163
|
await asyncio.sleep(self.reconnect_interval)
|
|
156
164
|
self.create_client() # reset connect/reconnect futures
|
|
157
165
|
|
|
158
|
-
async def
|
|
166
|
+
async def stop_client(self) -> None:
|
|
167
|
+
await self.unsubscribe(
|
|
168
|
+
topics=self._topics
|
|
169
|
+
)
|
|
170
|
+
raise RestartRequestException("Restart requested.")
|
|
171
|
+
|
|
172
|
+
async def _subscribe_manager(self, manager: Manager) -> None:
|
|
159
173
|
"""Connect and subscribe to manager topics + host stats."""
|
|
160
174
|
async with AsyncExitStack() as stack:
|
|
161
175
|
tasks: Set[asyncio.Task] = set()
|
|
@@ -170,11 +184,11 @@ class MQTTClient:
|
|
|
170
184
|
|
|
171
185
|
# Messages that doesn't match a filter will get logged and handled here.
|
|
172
186
|
messages = await stack.enter_async_context(
|
|
173
|
-
self.asyncio_client.
|
|
187
|
+
self.asyncio_client.messages()
|
|
174
188
|
)
|
|
175
189
|
|
|
176
190
|
messages_task = asyncio.create_task(
|
|
177
|
-
handle_messages(messages, manager.receive_message)
|
|
191
|
+
self.handle_messages(messages, manager.receive_message)
|
|
178
192
|
)
|
|
179
193
|
if not self._connection_established:
|
|
180
194
|
self._connection_established = True
|
|
@@ -183,16 +197,28 @@ class MQTTClient:
|
|
|
183
197
|
tasks.add(messages_task)
|
|
184
198
|
|
|
185
199
|
await self.subscribe(
|
|
186
|
-
topics=
|
|
200
|
+
topics=self._topics
|
|
201
|
+
)
|
|
202
|
+
await self.subscribe(
|
|
203
|
+
topics=self._discovery_topics
|
|
187
204
|
)
|
|
188
205
|
|
|
189
206
|
# Wait for everything to complete (or fail due to, e.g., network errors).
|
|
190
207
|
await asyncio.gather(*tasks)
|
|
191
208
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
209
|
+
async def handle_messages(self, messages: Any, callback: Callable[[str, str], Awaitable[None]]):
|
|
210
|
+
"""Handle messages with callback or remove osbolete HA discovery messages."""
|
|
211
|
+
async for message in messages:
|
|
212
|
+
payload = message.payload.decode()
|
|
213
|
+
callback_start = True
|
|
214
|
+
for discovery_topic in self._discovery_topics:
|
|
215
|
+
if message.topic.matches(discovery_topic):
|
|
216
|
+
callback_start = False
|
|
217
|
+
topic = str(message.topic)
|
|
218
|
+
if message.payload and not self._config_helper.is_topic_in_autodiscovery(topic):
|
|
219
|
+
_LOGGER.info("Removing unused discovery entity %s", topic)
|
|
220
|
+
self.send_message(topic=topic, payload=None, retain=True)
|
|
221
|
+
break
|
|
222
|
+
if callback_start:
|
|
223
|
+
_LOGGER.debug("Received message topic: %s, payload: %s", message.topic, payload)
|
|
224
|
+
await callback(str(message.topic), payload)
|
boneio/relay/basic.py
CHANGED
|
@@ -49,13 +49,13 @@ class BasicRelay(BasicMqtt):
|
|
|
49
49
|
return self._output_type == LIGHT
|
|
50
50
|
|
|
51
51
|
@property
|
|
52
|
-
def id(self) ->
|
|
52
|
+
def id(self) -> str:
|
|
53
53
|
"""Id of the relay.
|
|
54
54
|
Has to be trimmed out of spaces because of MQTT handling in HA."""
|
|
55
55
|
return self._id or self._pin
|
|
56
56
|
|
|
57
57
|
@property
|
|
58
|
-
def name(self) ->
|
|
58
|
+
def name(self) -> str:
|
|
59
59
|
"""Not trimmed id."""
|
|
60
60
|
return self._name or self._pin
|
|
61
61
|
|
|
@@ -70,8 +70,7 @@ class BasicRelay(BasicMqtt):
|
|
|
70
70
|
self._state = state
|
|
71
71
|
if self.output_type != NONE:
|
|
72
72
|
self._send_message(
|
|
73
|
-
topic=self._send_topic,
|
|
74
|
-
payload={STATE: state},
|
|
73
|
+
topic=self._send_topic, payload={STATE: state}, retain=True
|
|
75
74
|
)
|
|
76
75
|
self._loop.call_soon_threadsafe(self._callback)
|
|
77
76
|
|
boneio/runner.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"""Runner code for boneIO. Based on HA runner."""
|
|
2
|
+
from __future__ import annotations
|
|
2
3
|
import asyncio
|
|
3
4
|
import logging
|
|
4
5
|
import os
|
|
6
|
+
from typing import Any
|
|
5
7
|
|
|
6
8
|
from boneio.const import (
|
|
7
9
|
ADC,
|
|
@@ -34,13 +36,24 @@ from boneio.mqtt_client import MQTTClient
|
|
|
34
36
|
|
|
35
37
|
_LOGGER = logging.getLogger(__name__)
|
|
36
38
|
|
|
39
|
+
config_modules = [
|
|
40
|
+
{"name": MCP23017, "default": []},
|
|
41
|
+
{"name": PCA9685, "default": []},
|
|
42
|
+
{"name": DS2482, "default": []},
|
|
43
|
+
{"name": ADC, "default": []},
|
|
44
|
+
{"name": COVER, "default": []},
|
|
45
|
+
{"name": MODBUS, "default": {}},
|
|
46
|
+
{"name": OLED, "default": {}},
|
|
47
|
+
{"name": DALLAS, "default": None},
|
|
48
|
+
]
|
|
49
|
+
|
|
37
50
|
|
|
38
51
|
async def async_run(
|
|
39
52
|
config: dict,
|
|
40
53
|
config_file: str,
|
|
41
54
|
mqttusername: str = "",
|
|
42
55
|
mqttpassword: str = "",
|
|
43
|
-
):
|
|
56
|
+
) -> list[Any]:
|
|
44
57
|
"""Run BoneIO."""
|
|
45
58
|
|
|
46
59
|
_config_helper = ConfigHelper(
|
|
@@ -56,9 +69,14 @@ async def async_run(
|
|
|
56
69
|
port=config[MQTT].get(PORT, 1883),
|
|
57
70
|
config_helper=_config_helper,
|
|
58
71
|
)
|
|
72
|
+
manager_kwargs = {
|
|
73
|
+
item["name"]: config.get(item["name"], item["default"])
|
|
74
|
+
for item in config_modules
|
|
75
|
+
}
|
|
59
76
|
|
|
60
77
|
manager = Manager(
|
|
61
78
|
send_message=client.send_message,
|
|
79
|
+
stop_client=client.stop_client,
|
|
62
80
|
relay_pins=config.get(OUTPUT, []),
|
|
63
81
|
input_pins=config.get(INPUT, []),
|
|
64
82
|
config_file_path=config_file,
|
|
@@ -72,14 +90,7 @@ async def async_run(
|
|
|
72
90
|
MODBUS: config.get("modbus_sensors"),
|
|
73
91
|
ONEWIRE: config.get(SENSOR, []),
|
|
74
92
|
},
|
|
75
|
-
|
|
76
|
-
pca9685=config.get(PCA9685, []),
|
|
77
|
-
ds2482=config.get(DS2482, []),
|
|
78
|
-
dallas=config.get(DALLAS),
|
|
79
|
-
modbus=config.get(MODBUS),
|
|
80
|
-
oled=config.get(OLED),
|
|
81
|
-
adc_list=config.get(ADC, []),
|
|
82
|
-
covers=config.get(COVER, []),
|
|
93
|
+
**manager_kwargs,
|
|
83
94
|
)
|
|
84
95
|
tasks = set()
|
|
85
96
|
tasks.update(manager.get_tasks())
|
boneio/schema/schema.yaml
CHANGED
|
@@ -376,6 +376,12 @@ input:
|
|
|
376
376
|
required: True
|
|
377
377
|
meta:
|
|
378
378
|
label: Check if sensor type is inverted. Only aplicable for sensor kind.
|
|
379
|
+
device_class:
|
|
380
|
+
type: string
|
|
381
|
+
required: False
|
|
382
|
+
allowed: ["battery", "battery_charging", "carbon_monoxide", "cold", "connectivity", "door", "garage_door", "gas", "heat", "light", "lock", "moisture", "motion", "moving", "occupancy", "opening", "plug", "power", "presence", "problem", "running", "safety", "smoke", "sound", "tamper", "vibration", "window"]
|
|
383
|
+
meta:
|
|
384
|
+
label: Device class to use in HA
|
|
379
385
|
actions:
|
|
380
386
|
required: False
|
|
381
387
|
type: dict
|
boneio/sensor/gpio.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""GPIOInputButton to receive signals."""
|
|
2
2
|
import logging
|
|
3
3
|
from functools import partial
|
|
4
|
-
|
|
4
|
+
import asyncio
|
|
5
5
|
from boneio.const import BOTH, PRESSED, RELEASED
|
|
6
6
|
from boneio.helper import GpioBaseClass, edge_detect
|
|
7
7
|
|
|
@@ -14,24 +14,25 @@ class GpioInputSensor(GpioBaseClass):
|
|
|
14
14
|
def __init__(self, **kwargs) -> None:
|
|
15
15
|
"""Setup GPIO Input Button"""
|
|
16
16
|
super().__init__(**kwargs)
|
|
17
|
+
self._state = self.is_pressed
|
|
17
18
|
self._click_type = (
|
|
18
19
|
(RELEASED, PRESSED)
|
|
19
20
|
if kwargs.get("inverted", False)
|
|
20
21
|
else (PRESSED, RELEASED)
|
|
21
22
|
)
|
|
22
|
-
edge_detect(
|
|
23
|
-
self._pin,
|
|
24
|
-
callback=self._handle_press,
|
|
25
|
-
bounce=self._bounce_time.total_milliseconds,
|
|
26
|
-
edge=BOTH,
|
|
27
|
-
)
|
|
28
|
-
self._loop.call_soon(self._handle_press, self._pin)
|
|
29
23
|
_LOGGER.debug("Configured sensor pin %s", self._pin)
|
|
24
|
+
asyncio.create_task(self._run())
|
|
25
|
+
|
|
26
|
+
async def _run(self) -> None:
|
|
27
|
+
while True:
|
|
28
|
+
self.check_state(state=self.is_pressed)
|
|
29
|
+
await asyncio.sleep(self._bounce_time.total_in_seconds)
|
|
30
30
|
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
def check_state(self, state: bool) -> None:
|
|
32
|
+
if state == self._state:
|
|
33
|
+
return
|
|
34
|
+
self._state = state
|
|
35
|
+
click_type = self._click_type[0] if state else self._click_type[1]
|
|
35
36
|
_LOGGER.debug("%s event on pin %s", click_type, self._pin)
|
|
36
37
|
self._loop.call_soon_threadsafe(
|
|
37
38
|
partial(self._press_callback, click_type, self._pin)
|
boneio/version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# flake8: noqa
|
|
2
|
-
__version__ = "0.6.
|
|
2
|
+
__version__ = "0.6.0dev5"
|
|
File without changes
|
|
File without changes
|