boneIO 0.5.0__tar.gz → 0.5.0.dev1__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.5.0 → boneIO-0.5.0.dev1}/PKG-INFO +1 -1
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/bonecli.py +0 -3
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/const.py +0 -1
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/cover.py +14 -15
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/gpio.py +3 -2
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/ha_discovery.py +3 -5
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/loader.py +4 -10
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/stats.py +4 -24
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/yaml_util.py +1 -2
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/manager.py +20 -38
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/modbus.py +1 -1
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/oled.py +6 -19
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/schema/schema.yaml +85 -71
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/sensor/adc.py +3 -9
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/sensor/gpio.py +10 -10
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/sensor/modbus/__init__.py +27 -31
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/sensor/temp/__init__.py +3 -20
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/sensor/temp/dallas.py +1 -8
- boneIO-0.5.0.dev1/boneio/version.py +2 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/pyproject.toml +1 -1
- boneIO-0.5.0/boneio/helper/filter.py +0 -30
- boneIO-0.5.0/boneio/schema/filters.yaml +0 -11
- boneIO-0.5.0/boneio/schema/filters_adc.yaml +0 -12
- boneIO-0.5.0/boneio/schema/id.yaml +0 -4
- boneIO-0.5.0/boneio/schema/temp_unit.yaml +0 -4
- boneIO-0.5.0/boneio/schema/update_interval.yaml +0 -10
- boneIO-0.5.0/boneio/sensor/modbus/pt100.json +0 -21
- boneIO-0.5.0/boneio/version.py +0 -2
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/LICENSE +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/README.md +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/__init__.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/example_config/__init__.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/example_config/adc.yaml +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/example_config/config.yaml +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/example_config/cover.yaml +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/example_config/input.yaml +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/example_config/output24x16A.yaml +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/example_config/output32x5A.yaml +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/fonts/danube__.ttf +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/__init__.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/async_updater.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/config.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/events.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/exceptions.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/logger.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/mqtt.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/oled.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/onewire/W1ThermSensor.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/onewire/__init__.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/onewire/ds2482.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/onewire/onewire.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/queue.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/state_manager.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/timeperiod.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/helper/util.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/input/__init__.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/input/gpio.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/mqtt_client.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/relay/__init__.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/relay/basic.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/relay/gpio.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/relay/mcp.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/runner.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/schema/actions.yaml +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/schema/actions_sensor.yaml +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/schema/actions_switch.yaml +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/sensor/__init__.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/sensor/modbus/sdm120.json +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/sensor/modbus/sdm630.json +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/sensor/modbus/sofar.json +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/sensor/temp/lm75.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/boneio/sensor/temp/mcp9808.py +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/tests/32_5_config.yaml +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/tests/bandit.yaml +0 -0
- {boneIO-0.5.0 → boneIO-0.5.0.dev1}/tests/relay_32_5.py +0 -0
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"""Cover module."""
|
|
2
|
-
from __future__ import annotations
|
|
3
2
|
import asyncio
|
|
4
3
|
import logging
|
|
5
4
|
from typing import Callable
|
|
@@ -109,24 +108,24 @@ class Cover(BasicMqtt):
|
|
|
109
108
|
self._stop_cover(on_exit=True)
|
|
110
109
|
|
|
111
110
|
@property
|
|
112
|
-
def cover_state(self)
|
|
111
|
+
def cover_state(self):
|
|
113
112
|
"""Current state of cover."""
|
|
114
113
|
return CLOSED if self._closed else OPEN
|
|
115
114
|
|
|
116
|
-
def stop(self)
|
|
115
|
+
def stop(self):
|
|
117
116
|
"""Public Stop cover graceful."""
|
|
118
117
|
_LOGGER.info("Stopping cover %s.", self._id)
|
|
119
118
|
if self._current_operation != IDLE:
|
|
120
119
|
self._stop_cover(on_exit=False)
|
|
121
120
|
|
|
122
|
-
def send_state(self)
|
|
121
|
+
def send_state(self):
|
|
123
122
|
"""Send state of cover to mqtt."""
|
|
124
123
|
self._send_message(topic=f"{self._send_topic}/state", payload=self.cover_state)
|
|
125
124
|
pos = round(self._position, 0)
|
|
126
125
|
self._send_message(topic=f"{self._send_topic}/pos", payload=str(pos))
|
|
127
126
|
self._state_save(position=pos)
|
|
128
127
|
|
|
129
|
-
def _stop_cover(self, on_exit=False)
|
|
128
|
+
def _stop_cover(self, on_exit=False):
|
|
130
129
|
"""Stop cover."""
|
|
131
130
|
self._open.relay.turn_off()
|
|
132
131
|
self._close.relay.turn_off()
|
|
@@ -139,11 +138,11 @@ class Cover(BasicMqtt):
|
|
|
139
138
|
self._current_operation = IDLE
|
|
140
139
|
|
|
141
140
|
@property
|
|
142
|
-
def current_cover_position(self)
|
|
141
|
+
def current_cover_position(self):
|
|
143
142
|
"""Return the current position of the cover."""
|
|
144
143
|
return round(self._position, 0)
|
|
145
144
|
|
|
146
|
-
def listen_cover(self, *args)
|
|
145
|
+
def listen_cover(self, *args):
|
|
147
146
|
"""Listen for change in cover."""
|
|
148
147
|
if self._current_operation == IDLE:
|
|
149
148
|
return
|
|
@@ -179,7 +178,7 @@ class Cover(BasicMqtt):
|
|
|
179
178
|
|
|
180
179
|
self._closed = self.current_cover_position <= 0
|
|
181
180
|
|
|
182
|
-
async def close_cover(self)
|
|
181
|
+
async def close_cover(self):
|
|
183
182
|
"""Close cover."""
|
|
184
183
|
if self._position == 0:
|
|
185
184
|
return
|
|
@@ -194,7 +193,7 @@ class Cover(BasicMqtt):
|
|
|
194
193
|
current_operation=CLOSING,
|
|
195
194
|
)
|
|
196
195
|
|
|
197
|
-
async def open_cover(self)
|
|
196
|
+
async def open_cover(self):
|
|
198
197
|
"""Open cover."""
|
|
199
198
|
if self._position == 100:
|
|
200
199
|
return
|
|
@@ -209,7 +208,7 @@ class Cover(BasicMqtt):
|
|
|
209
208
|
current_operation=OPENING,
|
|
210
209
|
)
|
|
211
210
|
|
|
212
|
-
async def set_cover_position(self, position: int)
|
|
211
|
+
async def set_cover_position(self, position: int):
|
|
213
212
|
"""Move cover to a specific position."""
|
|
214
213
|
set_position = round(position, -1)
|
|
215
214
|
if self._position == position or set_position == self._set_position:
|
|
@@ -229,29 +228,29 @@ class Cover(BasicMqtt):
|
|
|
229
228
|
current_operation=current_operation,
|
|
230
229
|
)
|
|
231
230
|
|
|
232
|
-
def open(self)
|
|
231
|
+
def open(self):
|
|
233
232
|
_LOGGER.debug("Opening cover %s.", self._id)
|
|
234
233
|
asyncio.create_task(self.open_cover())
|
|
235
234
|
|
|
236
|
-
def close(self)
|
|
235
|
+
def close(self):
|
|
237
236
|
_LOGGER.debug("Closing cover %s.", self._id)
|
|
238
237
|
asyncio.create_task(self.close_cover())
|
|
239
238
|
|
|
240
|
-
def toggle(self)
|
|
239
|
+
def toggle(self):
|
|
241
240
|
_LOGGER.debug("Toggle cover %s from input.", self._id)
|
|
242
241
|
if self.cover_state == CLOSED:
|
|
243
242
|
self.close()
|
|
244
243
|
else:
|
|
245
244
|
self.open()
|
|
246
245
|
|
|
247
|
-
def toggle_open(self)
|
|
246
|
+
def toggle_open(self):
|
|
248
247
|
_LOGGER.debug("Toggle open cover %s from input.", self._id)
|
|
249
248
|
if self._current_operation != IDLE:
|
|
250
249
|
self.stop()
|
|
251
250
|
else:
|
|
252
251
|
self.open()
|
|
253
252
|
|
|
254
|
-
def toggle_close(self)
|
|
253
|
+
def toggle_close(self):
|
|
255
254
|
_LOGGER.debug("Toggle close cover %s from input.", self._id)
|
|
256
255
|
if self._current_operation != IDLE:
|
|
257
256
|
self.stop()
|
|
@@ -90,8 +90,9 @@ class GpioBaseClass:
|
|
|
90
90
|
) -> None:
|
|
91
91
|
"""Setup GPIO Input Button"""
|
|
92
92
|
self._pin = pin
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
gpio = kwargs.get("rest_pin", {GPIO_MODE: GPIO_STR})
|
|
94
|
+
gpio_mode = gpio.get(GPIO_MODE, GPIO_STR)
|
|
95
|
+
self._bounce_time = gpio.get("bounce_time", TimePeriod(milliseconds=10))
|
|
95
96
|
self._loop = asyncio.get_running_loop()
|
|
96
97
|
self._press_callback = press_callback
|
|
97
98
|
setup_input(pin=self._pin, pull_mode=gpio_mode)
|
|
@@ -109,9 +109,7 @@ def ha_binary_sensor_availabilty_message(id: str, name: str, topic: str = "boneI
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
|
|
112
|
-
def ha_sensor_temp_availabilty_message(
|
|
113
|
-
id: str, name: str, topic: str = "boneIO", **kwargs
|
|
114
|
-
):
|
|
112
|
+
def ha_sensor_temp_availabilty_message(id: str, name: str, topic: str = "boneIO"):
|
|
115
113
|
"""Create availability topic for HA."""
|
|
116
114
|
return {
|
|
117
115
|
"availability": [{"topic": f"{topic}/{STATE}"}],
|
|
@@ -127,8 +125,8 @@ def ha_sensor_temp_availabilty_message(
|
|
|
127
125
|
"unique_id": f"{topic}{SENSOR}{id}",
|
|
128
126
|
"device_class": "temperature",
|
|
129
127
|
"state_class": "measurement",
|
|
128
|
+
"unit_of_measurement": "°C",
|
|
130
129
|
"value_template": "{{ value_json.state }}",
|
|
131
|
-
**kwargs,
|
|
132
130
|
}
|
|
133
131
|
|
|
134
132
|
|
|
@@ -154,7 +152,7 @@ def modbus_sensor_availabilty_message(
|
|
|
154
152
|
},
|
|
155
153
|
"name": sensor_id,
|
|
156
154
|
"state_topic": f"{topic}/{device_type}/{id}/{state_topic_base}",
|
|
157
|
-
"unique_id": f"{topic}{sensor_id.replace('_', '').lower()}
|
|
155
|
+
"unique_id": f"{topic}{sensor_id.replace('_', '').lower()}",
|
|
158
156
|
**kwargs,
|
|
159
157
|
}
|
|
160
158
|
|
|
@@ -13,7 +13,6 @@ from boneio.const import (
|
|
|
13
13
|
BINARY_SENSOR,
|
|
14
14
|
COVER,
|
|
15
15
|
DEVICE_CLASS,
|
|
16
|
-
FILTERS,
|
|
17
16
|
GPIO,
|
|
18
17
|
ID,
|
|
19
18
|
INIT_SLEEP,
|
|
@@ -108,7 +107,7 @@ def create_temp_sensor(
|
|
|
108
107
|
topic_prefix: str,
|
|
109
108
|
sensor_type: str,
|
|
110
109
|
i2cbusio: I2C,
|
|
111
|
-
|
|
110
|
+
temp_def: dict = {},
|
|
112
111
|
):
|
|
113
112
|
"""Create LM sensor in manager."""
|
|
114
113
|
if sensor_type == LM75:
|
|
@@ -117,26 +116,23 @@ def create_temp_sensor(
|
|
|
117
116
|
from boneio.sensor import MCP9808Sensor as TempSensor
|
|
118
117
|
else:
|
|
119
118
|
return
|
|
120
|
-
name =
|
|
119
|
+
name = temp_def.get(ID)
|
|
121
120
|
id = name.replace(" ", "")
|
|
122
121
|
try:
|
|
123
122
|
temp_sensor = TempSensor(
|
|
124
123
|
id=id,
|
|
125
124
|
name=name,
|
|
126
125
|
i2c=i2cbusio,
|
|
127
|
-
address=
|
|
128
|
-
manager=manager,
|
|
126
|
+
address=temp_def[ADDRESS],
|
|
129
127
|
send_message=manager.send_message,
|
|
130
128
|
topic_prefix=topic_prefix,
|
|
131
|
-
update_interval=
|
|
132
|
-
filters=config.get(FILTERS, []),
|
|
129
|
+
update_interval=temp_def.get(UPDATE_INTERVAL, TimePeriod(seconds=60)),
|
|
133
130
|
)
|
|
134
131
|
manager.send_ha_autodiscovery(
|
|
135
132
|
id=id,
|
|
136
133
|
name=name,
|
|
137
134
|
ha_type=SENSOR,
|
|
138
135
|
availability_msg_func=ha_sensor_temp_availabilty_message,
|
|
139
|
-
unit_of_measurement=config.get("unit_of_measurement", "°C"),
|
|
140
136
|
)
|
|
141
137
|
return temp_sensor
|
|
142
138
|
except I2CError as err:
|
|
@@ -397,7 +393,6 @@ def create_dallas_sensor(
|
|
|
397
393
|
name=name,
|
|
398
394
|
update_interval=config.get(UPDATE_INTERVAL, TimePeriod(seconds=60)),
|
|
399
395
|
send_message=manager.send_message,
|
|
400
|
-
filters=config.get(FILTERS, []),
|
|
401
396
|
**kwargs,
|
|
402
397
|
)
|
|
403
398
|
if config.get(SHOW_HA, True):
|
|
@@ -406,6 +401,5 @@ def create_dallas_sensor(
|
|
|
406
401
|
name=sensor.name,
|
|
407
402
|
ha_type=SENSOR,
|
|
408
403
|
availability_msg_func=ha_sensor_temp_availabilty_message,
|
|
409
|
-
unit_of_measurement=config.get("unit_of_measurement", "°C"),
|
|
410
404
|
)
|
|
411
405
|
return sensor
|
|
@@ -4,8 +4,7 @@ from datetime import datetime
|
|
|
4
4
|
import socket
|
|
5
5
|
import time
|
|
6
6
|
from math import floor
|
|
7
|
-
from typing import Callable
|
|
8
|
-
from functools import partial
|
|
7
|
+
from typing import Callable
|
|
9
8
|
|
|
10
9
|
import psutil
|
|
11
10
|
|
|
@@ -118,32 +117,19 @@ def get_uptime():
|
|
|
118
117
|
class HostSensor(AsyncUpdater):
|
|
119
118
|
"""Host sensor."""
|
|
120
119
|
|
|
121
|
-
def __init__(
|
|
122
|
-
self,
|
|
123
|
-
update_function: Callable,
|
|
124
|
-
manager_callback: Callable,
|
|
125
|
-
static_data: dict,
|
|
126
|
-
id: str,
|
|
127
|
-
type: str,
|
|
128
|
-
**kwargs,
|
|
129
|
-
) -> None:
|
|
120
|
+
def __init__(self, update_function: Callable, static_data: dict, **kwargs) -> None:
|
|
130
121
|
self._update_function = update_function
|
|
131
122
|
self._static_data = static_data
|
|
132
123
|
self._state = None
|
|
133
|
-
self._type = type
|
|
134
|
-
self._manager_callback = manager_callback
|
|
135
|
-
self._loop = asyncio.get_event_loop()
|
|
136
|
-
self.id = id
|
|
137
124
|
super().__init__(**kwargs)
|
|
138
125
|
|
|
139
126
|
async def async_update(self, time: datetime) -> None:
|
|
140
127
|
self._state = self._update_function()
|
|
141
|
-
self._loop.call_soon_threadsafe(partial(self._manager_callback, self._type))
|
|
142
128
|
|
|
143
129
|
@property
|
|
144
130
|
def state(self) -> dict:
|
|
145
131
|
if self._static_data:
|
|
146
|
-
return {**self._static_data, self.
|
|
132
|
+
return {**self._static_data, **self._state}
|
|
147
133
|
return self._state
|
|
148
134
|
|
|
149
135
|
|
|
@@ -158,7 +144,6 @@ class HostData:
|
|
|
158
144
|
callback: Callable,
|
|
159
145
|
temp_sensor: Callable[[LM75Sensor, MCP9808Sensor], None],
|
|
160
146
|
manager: Manager,
|
|
161
|
-
enabled_screens: List[str],
|
|
162
147
|
) -> None:
|
|
163
148
|
"""Initialize HostData."""
|
|
164
149
|
self._hostname = socket.gethostname()
|
|
@@ -175,15 +160,10 @@ class HostData:
|
|
|
175
160
|
},
|
|
176
161
|
}
|
|
177
162
|
for k, _v in host_stats.items():
|
|
178
|
-
|
|
179
|
-
continue
|
|
180
|
-
self.data[k] = HostSensor(
|
|
163
|
+
self._data[k] = HostSensor(
|
|
181
164
|
update_function=_v["f"],
|
|
182
165
|
static_data=_v.get("static"),
|
|
183
166
|
manager=manager,
|
|
184
|
-
manager_callback=callback,
|
|
185
|
-
id=f"{k}_hoststats",
|
|
186
|
-
type=k,
|
|
187
167
|
update_interval=_v["update_interval"],
|
|
188
168
|
)
|
|
189
169
|
self._temp_sensor = temp_sensor
|
|
@@ -135,8 +135,6 @@ def load_config_from_string(config_yaml: str):
|
|
|
135
135
|
schema = load_yaml_file(schema_file)
|
|
136
136
|
v = CustomValidator(schema, purge_unknown=True)
|
|
137
137
|
v.validate(config_yaml)
|
|
138
|
-
if v.errors:
|
|
139
|
-
_LOGGER.error("There are errors in your config %s", v.errors)
|
|
140
138
|
doc = v.normalized(v.document, always_return_document=True)
|
|
141
139
|
# validated = v.validated(document=doc, normalize=True, always_return_document=True)
|
|
142
140
|
# doc = v.normalized(validated, always_return_document=True)
|
|
@@ -255,6 +253,7 @@ class CustomValidator(Validator):
|
|
|
255
253
|
|
|
256
254
|
def _normalize_coerce_positive_time_period(self, value) -> TimePeriod:
|
|
257
255
|
"""Validate and transform time period with time unit and integer value."""
|
|
256
|
+
|
|
258
257
|
if isinstance(value, int):
|
|
259
258
|
raise ConfigurationException(
|
|
260
259
|
f"Don't know what '{value}' means as it has no time *unit*! Did you mean '{value}s'?"
|
|
@@ -2,6 +2,7 @@ import asyncio
|
|
|
2
2
|
import logging
|
|
3
3
|
from collections import deque
|
|
4
4
|
from typing import Callable, Coroutine, List, Optional, Set, Union
|
|
5
|
+
|
|
5
6
|
from board import SCL, SDA
|
|
6
7
|
from busio import I2C
|
|
7
8
|
|
|
@@ -59,8 +60,6 @@ from boneio.helper.logger import configure_logger
|
|
|
59
60
|
from boneio.helper.yaml_util import load_config_from_file
|
|
60
61
|
from boneio.modbus import Modbus
|
|
61
62
|
|
|
62
|
-
from w1thermsensor.errors import KernelModuleLoadError
|
|
63
|
-
|
|
64
63
|
_LOGGER = logging.getLogger(__name__)
|
|
65
64
|
|
|
66
65
|
|
|
@@ -205,11 +204,8 @@ class Manager:
|
|
|
205
204
|
if oled.get("enabled", False):
|
|
206
205
|
from boneio.oled import Oled
|
|
207
206
|
|
|
208
|
-
screens = oled.get("screens")
|
|
209
|
-
|
|
210
207
|
self._host_data = HostData(
|
|
211
208
|
manager=self,
|
|
212
|
-
enabled_screens=screens,
|
|
213
209
|
output=self.grouped_outputs,
|
|
214
210
|
temp_sensor=self._temp_sensors[0] if self._temp_sensors else None,
|
|
215
211
|
callback=self._host_data_callback,
|
|
@@ -217,13 +213,12 @@ class Manager:
|
|
|
217
213
|
try:
|
|
218
214
|
self._oled = Oled(
|
|
219
215
|
host_data=self._host_data,
|
|
220
|
-
screen_order=screens,
|
|
221
216
|
output_groups=list(self.grouped_outputs),
|
|
222
217
|
sleep_timeout=oled.get("screensaver_timeout", 60),
|
|
223
218
|
)
|
|
224
219
|
except (GPIOInputException, I2CError) as err:
|
|
225
220
|
_LOGGER.error("Can't configure OLED display. %s", err)
|
|
226
|
-
|
|
221
|
+
self.prepare_button()
|
|
227
222
|
|
|
228
223
|
_LOGGER.info("BoneIO manager is ready.")
|
|
229
224
|
|
|
@@ -254,7 +249,6 @@ class Manager:
|
|
|
254
249
|
from boneio.helper.loader import (
|
|
255
250
|
configure_ds2482,
|
|
256
251
|
)
|
|
257
|
-
from boneio.sensor import DallasSensorDS2482
|
|
258
252
|
|
|
259
253
|
_ds_onewire_bus[_single_ds[ID]] = configure_ds2482(
|
|
260
254
|
i2cbusio=self._i2cbusio, address=_single_ds[ADDRESS]
|
|
@@ -270,35 +264,22 @@ class Manager:
|
|
|
270
264
|
_LOGGER.debug("Preparing Dallas bus.")
|
|
271
265
|
from boneio.helper.loader import configure_dallas
|
|
272
266
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
_one_wire_devices.update(
|
|
280
|
-
find_onewire_devices(
|
|
281
|
-
ow_bus=configure_dallas(),
|
|
282
|
-
bus_id=dallas[ID],
|
|
283
|
-
bus_type=DALLAS,
|
|
284
|
-
)
|
|
267
|
+
_one_wire_devices.update(
|
|
268
|
+
find_onewire_devices(
|
|
269
|
+
ow_bus=configure_dallas(),
|
|
270
|
+
bus_id=dallas[ID],
|
|
271
|
+
bus_type=DALLAS,
|
|
285
272
|
)
|
|
286
|
-
|
|
287
|
-
_LOGGER.error("Can't configure Dallas W1 device %s", err)
|
|
288
|
-
pass
|
|
289
|
-
|
|
273
|
+
)
|
|
290
274
|
for sensor in sensors:
|
|
291
275
|
address = _one_wire_devices.get(sensor[ADDRESS])
|
|
292
276
|
if not address:
|
|
293
277
|
continue
|
|
294
278
|
ds2482_bus_id = sensor.get("bus_id")
|
|
295
279
|
if ds2482_bus_id and ds2482_bus_id in _ds_onewire_bus:
|
|
296
|
-
kwargs = {
|
|
297
|
-
"bus": _ds_onewire_bus[ds2482_bus_id],
|
|
298
|
-
"cls": DallasSensorDS2482,
|
|
299
|
-
}
|
|
280
|
+
kwargs = {"bus": _ds_onewire_bus[ds2482_bus_id]}
|
|
300
281
|
else:
|
|
301
|
-
kwargs = {
|
|
282
|
+
kwargs = {}
|
|
302
283
|
_LOGGER.debug("Configuring sensor %s for boneIO", address)
|
|
303
284
|
self._temp_sensors.append(
|
|
304
285
|
create_dallas_sensor(
|
|
@@ -339,7 +320,7 @@ class Manager:
|
|
|
339
320
|
manager=self,
|
|
340
321
|
topic_prefix=self._config_helper.topic_prefix,
|
|
341
322
|
sensor_type=sensor_type,
|
|
342
|
-
|
|
323
|
+
temp_def=temp_def,
|
|
343
324
|
i2cbusio=self._i2cbusio,
|
|
344
325
|
)
|
|
345
326
|
if temp_sensor:
|
|
@@ -390,11 +371,11 @@ class Manager:
|
|
|
390
371
|
"""Retrieve asyncio tasks to run."""
|
|
391
372
|
return self._tasks
|
|
392
373
|
|
|
393
|
-
def
|
|
394
|
-
"""Prepare
|
|
374
|
+
def prepare_button(self) -> None:
|
|
375
|
+
"""Prepare buttons for reload."""
|
|
395
376
|
self.send_ha_autodiscovery(
|
|
396
377
|
id="Logger",
|
|
397
|
-
name="Logger
|
|
378
|
+
name="Logger",
|
|
398
379
|
ha_type=BUTTON,
|
|
399
380
|
availability_msg_func=ha_button_availabilty_message,
|
|
400
381
|
)
|
|
@@ -457,7 +438,7 @@ class Manager:
|
|
|
457
438
|
self._config_helper.add_autodiscovery_msg(topic=topic, payload=payload)
|
|
458
439
|
self.send_message(topic=topic, payload=payload, retain=True)
|
|
459
440
|
|
|
460
|
-
def resend_autodiscovery(self)
|
|
441
|
+
def resend_autodiscovery(self):
|
|
461
442
|
for msg in self._config_helper.autodiscovery_msgs:
|
|
462
443
|
self.send_message(**msg, retain=True)
|
|
463
444
|
|
|
@@ -519,10 +500,11 @@ class Manager:
|
|
|
519
500
|
_LOGGER.warn(
|
|
520
501
|
"Positon cannot be set. Not number between 0-100. %s", message
|
|
521
502
|
)
|
|
522
|
-
elif msg_type == BUTTON
|
|
523
|
-
if device_id == "logger" and
|
|
524
|
-
|
|
525
|
-
|
|
503
|
+
elif msg_type == BUTTON:
|
|
504
|
+
if device_id == "logger" and command == "set":
|
|
505
|
+
if message == "reload":
|
|
506
|
+
_LOGGER.info("Reloading logger configuration.")
|
|
507
|
+
self._logger_reload()
|
|
526
508
|
|
|
527
509
|
@property
|
|
528
510
|
def output(self) -> dict:
|
|
@@ -77,7 +77,7 @@ class Modbus:
|
|
|
77
77
|
"""Call sync. pymodbus."""
|
|
78
78
|
async with self._lock:
|
|
79
79
|
if not self._pymodbus_connect():
|
|
80
|
-
_LOGGER.error("Can't connect to Modbus
|
|
80
|
+
_LOGGER.error("Can't connect to Modbus.")
|
|
81
81
|
return None
|
|
82
82
|
kwargs = {"unit": unit, "count": count} if unit else {}
|
|
83
83
|
try:
|
|
@@ -28,7 +28,7 @@ fontSmall = make_font("DejaVuSans.ttf", 9)
|
|
|
28
28
|
fontExtraSmall = make_font("DejaVuSans.ttf", 7)
|
|
29
29
|
danube = make_font("danube__.ttf", 15, local=True)
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
screen_order = [UPTIME, NETWORK, CPU, DISK, MEMORY, SWAP]
|
|
32
32
|
|
|
33
33
|
STANDARD_ROWS = [17, 32, 47]
|
|
34
34
|
UPTIME_ROWS = list(range(22, 60, 10))
|
|
@@ -40,32 +40,19 @@ class Oled:
|
|
|
40
40
|
"""Oled display class."""
|
|
41
41
|
|
|
42
42
|
def __init__(
|
|
43
|
-
self,
|
|
44
|
-
host_data: HostData,
|
|
45
|
-
output_groups: List[str],
|
|
46
|
-
sleep_timeout: TimePeriod,
|
|
47
|
-
screen_order: List[str],
|
|
43
|
+
self, host_data: HostData, output_groups: List[str], sleep_timeout: TimePeriod
|
|
48
44
|
) -> None:
|
|
49
45
|
"""Initialize OLED screen."""
|
|
50
46
|
self._loop = asyncio.get_running_loop()
|
|
51
|
-
self.
|
|
52
|
-
|
|
53
|
-
_ind_screen = screen_order.index("outputs")
|
|
54
|
-
if not output_groups:
|
|
55
|
-
_LOGGER.debug("No outputs configured. Omitting in screen.")
|
|
56
|
-
screen_order.pop(_ind_screen)
|
|
57
|
-
screen_order[_ind_screen:_ind_screen] = output_groups
|
|
58
|
-
self._output_groups = output_groups
|
|
59
|
-
except ValueError:
|
|
60
|
-
pass
|
|
61
|
-
self._screen_order = cycle(screen_order)
|
|
47
|
+
self._screen_order = cycle(screen_order + output_groups)
|
|
48
|
+
self._output_groups = output_groups
|
|
62
49
|
self._current_screen = next(self._screen_order)
|
|
63
50
|
self._host_data = host_data
|
|
64
51
|
self._sleep = False
|
|
65
52
|
self._sleep_handle = None
|
|
66
53
|
self._sleep_timeout = sleep_timeout
|
|
67
54
|
setup_input(pin=OLED_PIN, pull_mode="gpio_pu")
|
|
68
|
-
edge_detect(pin=OLED_PIN, callback=self._handle_press, bounce=
|
|
55
|
+
edge_detect(pin=OLED_PIN, callback=self._handle_press, bounce=120)
|
|
69
56
|
try:
|
|
70
57
|
serial = i2c(port=2, address=0x3C)
|
|
71
58
|
self._device = sh1106(serial)
|
|
@@ -125,7 +112,7 @@ class Oled:
|
|
|
125
112
|
data = self._host_data.get(self._current_screen)
|
|
126
113
|
if data:
|
|
127
114
|
with canvas(self._device) as draw:
|
|
128
|
-
if self.
|
|
115
|
+
if self._current_screen in self._output_groups:
|
|
129
116
|
self._draw_output(data, draw)
|
|
130
117
|
elif self._current_screen == UPTIME:
|
|
131
118
|
self._draw_uptime(data, draw)
|