boneIO 0.5.0dev1__tar.gz → 0.5.0dev3__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.

Potentially problematic release.


This version of boneIO might be problematic. Click here for more details.

Files changed (72) hide show
  1. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/PKG-INFO +1 -1
  2. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/const.py +1 -0
  3. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/cover.py +15 -14
  4. boneIO-0.5.0.dev3/boneio/helper/filter.py +26 -0
  5. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/loader.py +7 -4
  6. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/stats.py +24 -4
  7. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/manager.py +14 -11
  8. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/oled.py +19 -6
  9. boneIO-0.5.0.dev3/boneio/schema/filters.yaml +11 -0
  10. boneIO-0.5.0.dev3/boneio/schema/filters_adc.yaml +12 -0
  11. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/schema/schema.yaml +26 -50
  12. boneIO-0.5.0.dev3/boneio/schema/update_interval.yaml +10 -0
  13. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/sensor/adc.py +9 -3
  14. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/sensor/temp/__init__.py +15 -3
  15. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/sensor/temp/dallas.py +9 -1
  16. boneIO-0.5.0.dev3/boneio/version.py +2 -0
  17. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/pyproject.toml +1 -1
  18. boneIO-0.5.0.dev1/boneio/version.py +0 -2
  19. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/LICENSE +0 -0
  20. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/README.md +0 -0
  21. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/__init__.py +0 -0
  22. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/bonecli.py +0 -0
  23. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/example_config/__init__.py +0 -0
  24. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/example_config/adc.yaml +0 -0
  25. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/example_config/config.yaml +0 -0
  26. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/example_config/cover.yaml +0 -0
  27. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/example_config/input.yaml +0 -0
  28. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/example_config/output24x16A.yaml +0 -0
  29. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/example_config/output32x5A.yaml +0 -0
  30. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/fonts/danube__.ttf +0 -0
  31. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/__init__.py +0 -0
  32. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/async_updater.py +0 -0
  33. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/config.py +0 -0
  34. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/events.py +0 -0
  35. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/exceptions.py +0 -0
  36. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/gpio.py +0 -0
  37. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/ha_discovery.py +0 -0
  38. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/logger.py +0 -0
  39. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/mqtt.py +0 -0
  40. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/oled.py +0 -0
  41. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/onewire/W1ThermSensor.py +0 -0
  42. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/onewire/__init__.py +0 -0
  43. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/onewire/ds2482.py +0 -0
  44. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/onewire/onewire.py +0 -0
  45. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/queue.py +0 -0
  46. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/state_manager.py +0 -0
  47. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/timeperiod.py +0 -0
  48. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/util.py +0 -0
  49. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/helper/yaml_util.py +0 -0
  50. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/input/__init__.py +0 -0
  51. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/input/gpio.py +0 -0
  52. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/modbus.py +0 -0
  53. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/mqtt_client.py +0 -0
  54. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/relay/__init__.py +0 -0
  55. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/relay/basic.py +0 -0
  56. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/relay/gpio.py +0 -0
  57. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/relay/mcp.py +0 -0
  58. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/runner.py +0 -0
  59. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/schema/actions.yaml +0 -0
  60. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/schema/actions_sensor.yaml +0 -0
  61. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/schema/actions_switch.yaml +0 -0
  62. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/sensor/__init__.py +0 -0
  63. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/sensor/gpio.py +0 -0
  64. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/sensor/modbus/__init__.py +0 -0
  65. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/sensor/modbus/sdm120.json +0 -0
  66. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/sensor/modbus/sdm630.json +0 -0
  67. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/sensor/modbus/sofar.json +0 -0
  68. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/sensor/temp/lm75.py +0 -0
  69. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/boneio/sensor/temp/mcp9808.py +0 -0
  70. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/tests/32_5_config.yaml +0 -0
  71. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/tests/bandit.yaml +0 -0
  72. {boneIO-0.5.0.dev1 → boneIO-0.5.0.dev3}/tests/relay_32_5.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: boneIO
3
- Version: 0.5.0dev1
3
+ Version: 0.5.0dev3
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>
@@ -136,3 +136,4 @@ Gpio_Edges = Literal[BOTH, FALLING]
136
136
  InputTypes = Literal[INPUT, INPUT_SENSOR]
137
137
  DEVICE_CLASS = "device_class"
138
138
  DallasBusTypes = Literal[DS2482, DALLAS]
139
+ FILTERS = "filters"
@@ -1,4 +1,5 @@
1
1
  """Cover module."""
2
+ from __future__ import annotations
2
3
  import asyncio
3
4
  import logging
4
5
  from typing import Callable
@@ -108,24 +109,24 @@ class Cover(BasicMqtt):
108
109
  self._stop_cover(on_exit=True)
109
110
 
110
111
  @property
111
- def cover_state(self):
112
+ def cover_state(self) -> CLOSED | OPEN:
112
113
  """Current state of cover."""
113
114
  return CLOSED if self._closed else OPEN
114
115
 
115
- def stop(self):
116
+ def stop(self) -> None:
116
117
  """Public Stop cover graceful."""
117
118
  _LOGGER.info("Stopping cover %s.", self._id)
118
119
  if self._current_operation != IDLE:
119
120
  self._stop_cover(on_exit=False)
120
121
 
121
- def send_state(self):
122
+ def send_state(self) -> None:
122
123
  """Send state of cover to mqtt."""
123
124
  self._send_message(topic=f"{self._send_topic}/state", payload=self.cover_state)
124
125
  pos = round(self._position, 0)
125
126
  self._send_message(topic=f"{self._send_topic}/pos", payload=str(pos))
126
127
  self._state_save(position=pos)
127
128
 
128
- def _stop_cover(self, on_exit=False):
129
+ def _stop_cover(self, on_exit=False) -> None:
129
130
  """Stop cover."""
130
131
  self._open.relay.turn_off()
131
132
  self._close.relay.turn_off()
@@ -138,11 +139,11 @@ class Cover(BasicMqtt):
138
139
  self._current_operation = IDLE
139
140
 
140
141
  @property
141
- def current_cover_position(self):
142
+ def current_cover_position(self) -> int:
142
143
  """Return the current position of the cover."""
143
144
  return round(self._position, 0)
144
145
 
145
- def listen_cover(self, *args):
146
+ def listen_cover(self, *args) -> None:
146
147
  """Listen for change in cover."""
147
148
  if self._current_operation == IDLE:
148
149
  return
@@ -178,7 +179,7 @@ class Cover(BasicMqtt):
178
179
 
179
180
  self._closed = self.current_cover_position <= 0
180
181
 
181
- async def close_cover(self):
182
+ async def close_cover(self) -> None:
182
183
  """Close cover."""
183
184
  if self._position == 0:
184
185
  return
@@ -193,7 +194,7 @@ class Cover(BasicMqtt):
193
194
  current_operation=CLOSING,
194
195
  )
195
196
 
196
- async def open_cover(self):
197
+ async def open_cover(self) -> None:
197
198
  """Open cover."""
198
199
  if self._position == 100:
199
200
  return
@@ -208,7 +209,7 @@ class Cover(BasicMqtt):
208
209
  current_operation=OPENING,
209
210
  )
210
211
 
211
- async def set_cover_position(self, position: int):
212
+ async def set_cover_position(self, position: int) -> None:
212
213
  """Move cover to a specific position."""
213
214
  set_position = round(position, -1)
214
215
  if self._position == position or set_position == self._set_position:
@@ -228,29 +229,29 @@ class Cover(BasicMqtt):
228
229
  current_operation=current_operation,
229
230
  )
230
231
 
231
- def open(self):
232
+ def open(self) -> None:
232
233
  _LOGGER.debug("Opening cover %s.", self._id)
233
234
  asyncio.create_task(self.open_cover())
234
235
 
235
- def close(self):
236
+ def close(self) -> None:
236
237
  _LOGGER.debug("Closing cover %s.", self._id)
237
238
  asyncio.create_task(self.close_cover())
238
239
 
239
- def toggle(self):
240
+ def toggle(self) -> None:
240
241
  _LOGGER.debug("Toggle cover %s from input.", self._id)
241
242
  if self.cover_state == CLOSED:
242
243
  self.close()
243
244
  else:
244
245
  self.open()
245
246
 
246
- def toggle_open(self):
247
+ def toggle_open(self) -> None:
247
248
  _LOGGER.debug("Toggle open cover %s from input.", self._id)
248
249
  if self._current_operation != IDLE:
249
250
  self.stop()
250
251
  else:
251
252
  self.open()
252
253
 
253
- def toggle_close(self):
254
+ def toggle_close(self) -> None:
254
255
  _LOGGER.debug("Toggle close cover %s from input.", self._id)
255
256
  if self._current_operation != IDLE:
256
257
  self.stop()
@@ -0,0 +1,26 @@
1
+ """Filter class to adjust sensor values."""
2
+ from __future__ import annotations
3
+
4
+
5
+ FILTERS = {
6
+ "offset": lambda x, y: x + y,
7
+ "round": lambda x, y: round(x, y),
8
+ "multiply": lambda x, y: x * y,
9
+ "filter_out": lambda x, y: None if x == y else x,
10
+ "filter_out_greater": lambda x, y: None if x > y else x,
11
+ "filter_out_lower": lambda x, y: None if x < y else x,
12
+ }
13
+
14
+
15
+ class Filter:
16
+ _filters = []
17
+
18
+ def _apply_filters(self, value: float) -> float | None:
19
+ for filter in self._filters:
20
+ for k, v in filter.items():
21
+ if k not in FILTERS:
22
+ break
23
+ value = FILTERS[k](value, v)
24
+ if value is None:
25
+ return None
26
+ return value
@@ -13,6 +13,7 @@ from boneio.const import (
13
13
  BINARY_SENSOR,
14
14
  COVER,
15
15
  DEVICE_CLASS,
16
+ FILTERS,
16
17
  GPIO,
17
18
  ID,
18
19
  INIT_SLEEP,
@@ -107,7 +108,7 @@ def create_temp_sensor(
107
108
  topic_prefix: str,
108
109
  sensor_type: str,
109
110
  i2cbusio: I2C,
110
- temp_def: dict = {},
111
+ config: dict = {},
111
112
  ):
112
113
  """Create LM sensor in manager."""
113
114
  if sensor_type == LM75:
@@ -116,17 +117,18 @@ def create_temp_sensor(
116
117
  from boneio.sensor import MCP9808Sensor as TempSensor
117
118
  else:
118
119
  return
119
- name = temp_def.get(ID)
120
+ name = config.get(ID)
120
121
  id = name.replace(" ", "")
121
122
  try:
122
123
  temp_sensor = TempSensor(
123
124
  id=id,
124
125
  name=name,
125
126
  i2c=i2cbusio,
126
- address=temp_def[ADDRESS],
127
+ address=config[ADDRESS],
127
128
  send_message=manager.send_message,
128
129
  topic_prefix=topic_prefix,
129
- update_interval=temp_def.get(UPDATE_INTERVAL, TimePeriod(seconds=60)),
130
+ update_interval=config.get(UPDATE_INTERVAL, TimePeriod(seconds=60)),
131
+ filters=config.get(FILTERS, []),
130
132
  )
131
133
  manager.send_ha_autodiscovery(
132
134
  id=id,
@@ -393,6 +395,7 @@ def create_dallas_sensor(
393
395
  name=name,
394
396
  update_interval=config.get(UPDATE_INTERVAL, TimePeriod(seconds=60)),
395
397
  send_message=manager.send_message,
398
+ filters=config.get(FILTERS, []),
396
399
  **kwargs,
397
400
  )
398
401
  if config.get(SHOW_HA, True):
@@ -4,7 +4,8 @@ from datetime import datetime
4
4
  import socket
5
5
  import time
6
6
  from math import floor
7
- from typing import Callable
7
+ from typing import Callable, List
8
+ from functools import partial
8
9
 
9
10
  import psutil
10
11
 
@@ -117,19 +118,32 @@ def get_uptime():
117
118
  class HostSensor(AsyncUpdater):
118
119
  """Host sensor."""
119
120
 
120
- def __init__(self, update_function: Callable, static_data: dict, **kwargs) -> None:
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:
121
130
  self._update_function = update_function
122
131
  self._static_data = static_data
123
132
  self._state = None
133
+ self._type = type
134
+ self._manager_callback = manager_callback
135
+ self._loop = asyncio.get_event_loop()
136
+ self.id = id
124
137
  super().__init__(**kwargs)
125
138
 
126
139
  async def async_update(self, time: datetime) -> None:
127
140
  self._state = self._update_function()
141
+ self._loop.call_soon_threadsafe(partial(self._manager_callback, self._type))
128
142
 
129
143
  @property
130
144
  def state(self) -> dict:
131
145
  if self._static_data:
132
- return {**self._static_data, **self._state}
146
+ return {**self._static_data, self._type: self._state}
133
147
  return self._state
134
148
 
135
149
 
@@ -144,6 +158,7 @@ class HostData:
144
158
  callback: Callable,
145
159
  temp_sensor: Callable[[LM75Sensor, MCP9808Sensor], None],
146
160
  manager: Manager,
161
+ enabled_screens: List[str],
147
162
  ) -> None:
148
163
  """Initialize HostData."""
149
164
  self._hostname = socket.gethostname()
@@ -160,10 +175,15 @@ class HostData:
160
175
  },
161
176
  }
162
177
  for k, _v in host_stats.items():
163
- self._data[k] = HostSensor(
178
+ if k not in enabled_screens:
179
+ continue
180
+ self.data[k] = HostSensor(
164
181
  update_function=_v["f"],
165
182
  static_data=_v.get("static"),
166
183
  manager=manager,
184
+ manager_callback=callback,
185
+ id=f"{k}_hoststats",
186
+ type=k,
167
187
  update_interval=_v["update_interval"],
168
188
  )
169
189
  self._temp_sensor = temp_sensor
@@ -204,8 +204,11 @@ class Manager:
204
204
  if oled.get("enabled", False):
205
205
  from boneio.oled import Oled
206
206
 
207
+ screens = oled.get("screens")
208
+
207
209
  self._host_data = HostData(
208
210
  manager=self,
211
+ enabled_screens=screens,
209
212
  output=self.grouped_outputs,
210
213
  temp_sensor=self._temp_sensors[0] if self._temp_sensors else None,
211
214
  callback=self._host_data_callback,
@@ -213,12 +216,13 @@ class Manager:
213
216
  try:
214
217
  self._oled = Oled(
215
218
  host_data=self._host_data,
219
+ screen_order=screens,
216
220
  output_groups=list(self.grouped_outputs),
217
221
  sleep_timeout=oled.get("screensaver_timeout", 60),
218
222
  )
219
223
  except (GPIOInputException, I2CError) as err:
220
224
  _LOGGER.error("Can't configure OLED display. %s", err)
221
- self.prepare_button()
225
+ self.prepare_ha_buttons()
222
226
 
223
227
  _LOGGER.info("BoneIO manager is ready.")
224
228
 
@@ -320,7 +324,7 @@ class Manager:
320
324
  manager=self,
321
325
  topic_prefix=self._config_helper.topic_prefix,
322
326
  sensor_type=sensor_type,
323
- temp_def=temp_def,
327
+ config=temp_def,
324
328
  i2cbusio=self._i2cbusio,
325
329
  )
326
330
  if temp_sensor:
@@ -371,11 +375,11 @@ class Manager:
371
375
  """Retrieve asyncio tasks to run."""
372
376
  return self._tasks
373
377
 
374
- def prepare_button(self) -> None:
375
- """Prepare buttons for reload."""
378
+ def prepare_ha_buttons(self) -> None:
379
+ """Prepare HA buttons for reload."""
376
380
  self.send_ha_autodiscovery(
377
381
  id="Logger",
378
- name="Logger",
382
+ name="Logger reload",
379
383
  ha_type=BUTTON,
380
384
  availability_msg_func=ha_button_availabilty_message,
381
385
  )
@@ -438,7 +442,7 @@ class Manager:
438
442
  self._config_helper.add_autodiscovery_msg(topic=topic, payload=payload)
439
443
  self.send_message(topic=topic, payload=payload, retain=True)
440
444
 
441
- def resend_autodiscovery(self):
445
+ def resend_autodiscovery(self) -> None:
442
446
  for msg in self._config_helper.autodiscovery_msgs:
443
447
  self.send_message(**msg, retain=True)
444
448
 
@@ -500,11 +504,10 @@ class Manager:
500
504
  _LOGGER.warn(
501
505
  "Positon cannot be set. Not number between 0-100. %s", message
502
506
  )
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()
507
+ elif msg_type == BUTTON and command == "set":
508
+ if device_id == "logger" and message == "reload":
509
+ _LOGGER.info("Reloading logger configuration.")
510
+ self._logger_reload()
508
511
 
509
512
  @property
510
513
  def output(self) -> dict:
@@ -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
- screen_order = [UPTIME, NETWORK, CPU, DISK, MEMORY, SWAP]
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,19 +40,32 @@ class Oled:
40
40
  """Oled display class."""
41
41
 
42
42
  def __init__(
43
- self, host_data: HostData, output_groups: List[str], sleep_timeout: TimePeriod
43
+ self,
44
+ host_data: HostData,
45
+ output_groups: List[str],
46
+ sleep_timeout: TimePeriod,
47
+ screen_order: List[str],
44
48
  ) -> None:
45
49
  """Initialize OLED screen."""
46
50
  self._loop = asyncio.get_running_loop()
47
- self._screen_order = cycle(screen_order + output_groups)
48
- self._output_groups = output_groups
51
+ self._output_groups = None
52
+ try:
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)
49
62
  self._current_screen = next(self._screen_order)
50
63
  self._host_data = host_data
51
64
  self._sleep = False
52
65
  self._sleep_handle = None
53
66
  self._sleep_timeout = sleep_timeout
54
67
  setup_input(pin=OLED_PIN, pull_mode="gpio_pu")
55
- edge_detect(pin=OLED_PIN, callback=self._handle_press, bounce=120)
68
+ edge_detect(pin=OLED_PIN, callback=self._handle_press, bounce=240)
56
69
  try:
57
70
  serial = i2c(port=2, address=0x3C)
58
71
  self._device = sh1106(serial)
@@ -112,7 +125,7 @@ class Oled:
112
125
  data = self._host_data.get(self._current_screen)
113
126
  if data:
114
127
  with canvas(self._device) as draw:
115
- if self._current_screen in self._output_groups:
128
+ if self._output_groups and self._current_screen in self._output_groups:
116
129
  self._draw_output(data, draw)
117
130
  elif self._current_screen == UPTIME:
118
131
  self._draw_uptime(data, draw)
@@ -0,0 +1,11 @@
1
+ type: list
2
+ required: False
3
+ schema:
4
+ type: dict
5
+ keysrules:
6
+ type: string
7
+ allowed: ["offset", "round", "multiply", "filter_out", "filter_out_greater", "filter_out_lower"]
8
+ default:
9
+ - round: 2
10
+ meta:
11
+ label: List of filters to apply. Allowed filters visible in allowed section.
@@ -0,0 +1,12 @@
1
+ type: list
2
+ required: False
3
+ schema:
4
+ type: dict
5
+ keysrules:
6
+ type: string
7
+ allowed: ["offset", "round", "multiply", "filter_out", "filter_out_greater", "filter_out_lower"]
8
+ default:
9
+ - multiply: 1.8
10
+ - round: 2
11
+ meta:
12
+ label: List of filters to apply. Allowed filters visible in allowed section.
@@ -75,6 +75,18 @@ oled:
75
75
  default: False
76
76
  meta:
77
77
  label: Disable builtin screen.
78
+ screens:
79
+ type: list
80
+ required: True
81
+ allowed: ["uptime", "network", "cpu", "disk", "memory", "swap", "outputs"]
82
+ default:
83
+ - uptime
84
+ - network
85
+ - cpu
86
+ - disk
87
+ - memory
88
+ - swap
89
+ - outputs
78
90
  screensaver_timeout:
79
91
  type:
80
92
  - string
@@ -147,17 +159,8 @@ lm75:
147
159
  default: 0x48
148
160
  meta:
149
161
  label: Address of I2C
150
- update_interval:
151
- type:
152
- - string
153
- - timeperiod
154
- coerce:
155
- - str
156
- - positive_time_period
157
- required: True
158
- default: 60s
159
- meta:
160
- label: Update interval.
162
+ update_interval: !include update_interval.yaml
163
+ filters: !include filters.yaml
161
164
 
162
165
 
163
166
  mcp9808:
@@ -175,17 +178,8 @@ mcp9808:
175
178
  default: 0x18
176
179
  meta:
177
180
  label: Address of I2C device
178
- update_interval:
179
- type:
180
- - string
181
- - timeperiod
182
- coerce:
183
- - str
184
- - positive_time_period
185
- required: True
186
- default: 60s
187
- meta:
188
- label: Update interval.
181
+ update_interval: !include update_interval.yaml
182
+ filters: !include filters.yaml
189
183
 
190
184
  mcp23017:
191
185
  type: list
@@ -360,17 +354,7 @@ adc:
360
354
  allowed: ["P9_33", "P9_35", "P9_36", "P9_37", "P9_38", "P9_39", "P9_40"]
361
355
  meta:
362
356
  label: PIN to use.
363
- update_interval:
364
- required: True
365
- type:
366
- - string
367
- - timeperiod
368
- coerce:
369
- - str
370
- - positive_time_period
371
- default: 60s
372
- meta:
373
- label: Update interval.
357
+ update_interval: !include update_interval.yaml
374
358
  show_in_ha:
375
359
  type: boolean
376
360
  required: True
@@ -483,17 +467,18 @@ sensor:
483
467
  required: False
484
468
  meta:
485
469
  label: Id to use in HA if needed. Default to address.
470
+ platform:
471
+ type: string
472
+ required: True
473
+ default: dallas
474
+ allowed: ["dallas"]
475
+ meta:
476
+ label: Platform of sensor to use. Currently only Dallas platform is supported.
486
477
  address:
487
478
  type: integer
488
479
  required: True
489
480
  meta:
490
481
  label: Address of Dallas device
491
- via_ds2482:
492
- type: boolean
493
- required: True
494
- default: False
495
- meta:
496
- label: Choose if sensor is connected via DS2482 bus.
497
482
  bus_id:
498
483
  type: string
499
484
  required: False
@@ -505,14 +490,5 @@ sensor:
505
490
  default: True
506
491
  meta:
507
492
  label: If you want you can disable discovering this input in HA.
508
- update_interval:
509
- type:
510
- - string
511
- - timeperiod
512
- coerce:
513
- - str
514
- - positive_time_period
515
- required: True
516
- default: 60 s
517
- meta:
518
- label: Update interval.
493
+ filters: !include filters.yaml
494
+ update_interval: !include update_interval.yaml
@@ -0,0 +1,10 @@
1
+ type:
2
+ - string
3
+ - timeperiod
4
+ coerce:
5
+ - str
6
+ - positive_time_period
7
+ required: True
8
+ default: 60s
9
+ meta:
10
+ label: Update interval.
@@ -4,6 +4,7 @@ import logging
4
4
 
5
5
  from boneio.const import SENSOR
6
6
  from boneio.helper import BasicMqtt, AsyncUpdater
7
+ from boneio.helper.filter import Filter
7
8
 
8
9
  try:
9
10
  import Adafruit_BBIO.ADC as ADC
@@ -22,23 +23,28 @@ def initialize_adc():
22
23
  ADC.setup()
23
24
 
24
25
 
25
- class GpioADCSensor(BasicMqtt, AsyncUpdater):
26
+ class GpioADCSensor(BasicMqtt, AsyncUpdater, Filter):
26
27
  """Represent Gpio ADC sensor."""
27
28
 
28
29
  def __init__(self, pin: str, **kwargs) -> None:
29
30
  """Setup GPIO ADC Sensor"""
30
31
  super().__init__(topic_type=SENSOR, **kwargs)
31
32
  self._pin = pin
33
+ self._state = None
32
34
  AsyncUpdater.__init__(self, **kwargs)
33
35
  _LOGGER.debug("Configured sensor pin %s", self._pin)
34
36
 
35
37
  @property
36
- def state(self):
38
+ def state(self) -> float:
37
39
  """Give rounded value of temperature."""
38
- return round(ADC.read(self._pin) * 1.8, 2)
40
+ return self._state
39
41
 
40
42
  def update(self, time: datetime) -> None:
41
43
  """Fetch temperature periodically and send to MQTT."""
44
+ _state = self._apply_filters(value=ADC.read(self._pin))
45
+ if not _state:
46
+ return
47
+ self._state = _state
42
48
  self._send_message(
43
49
  topic=self._send_topic,
44
50
  payload=self.state,
@@ -6,18 +6,27 @@ from datetime import datetime
6
6
  from boneio.const import SENSOR, STATE, TEMPERATURE
7
7
  from boneio.helper import BasicMqtt, AsyncUpdater
8
8
  from boneio.helper.exceptions import I2CError
9
+ from boneio.helper.filter import Filter
9
10
 
10
11
 
11
- class TempSensor(BasicMqtt, AsyncUpdater):
12
+ class TempSensor(BasicMqtt, AsyncUpdater, Filter):
12
13
  """Represent Temp sensor in BoneIO."""
13
14
 
14
15
  SensorClass = None
15
16
  DefaultName = TEMPERATURE
16
17
 
17
- def __init__(self, i2c, address: str, id: str = DefaultName, **kwargs):
18
+ def __init__(
19
+ self,
20
+ i2c,
21
+ address: str,
22
+ id: str = DefaultName,
23
+ filters: list = ["round(x, 2)"],
24
+ **kwargs
25
+ ):
18
26
  """Initialize Temp class."""
19
27
  super().__init__(id=id, topic_type=SENSOR, **kwargs)
20
28
  self._loop = asyncio.get_event_loop()
29
+ self._filters = filters
21
30
  try:
22
31
  self._pct = self.SensorClass(i2c_bus=i2c, address=address)
23
32
  self._state: float | None = None
@@ -32,7 +41,10 @@ class TempSensor(BasicMqtt, AsyncUpdater):
32
41
 
33
42
  def update(self, time: datetime) -> None:
34
43
  """Fetch temperature periodically and send to MQTT."""
35
- self._state = round(self._pct.temperature, 2)
44
+ _temp = self._apply_filters(value=self._pct.temperature)
45
+ if not _temp:
46
+ return
47
+ self._state = _temp
36
48
  self._send_message(
37
49
  topic=self._send_topic,
38
50
  payload={STATE: self._state},
@@ -3,6 +3,7 @@
3
3
  import asyncio
4
4
  import logging
5
5
  from datetime import datetime
6
+ from ast import literal_eval
6
7
 
7
8
  from adafruit_ds18x20 import DS18X20
8
9
  from w1thermsensor import SensorNotReadyError
@@ -47,11 +48,13 @@ class DallasSensorW1(TempSensor, AsyncUpdater):
47
48
  self,
48
49
  address: OneWireAddress,
49
50
  id: str = DefaultName,
51
+ filters: list = ["round(x, 2)"],
50
52
  **kwargs,
51
53
  ):
52
54
  """Initialize Temp class."""
53
55
  self._loop = asyncio.get_event_loop()
54
56
  BasicMqtt.__init__(self, id=id, topic_type=SENSOR, **kwargs)
57
+ self._filters = filters
55
58
  try:
56
59
  self._pct = AsyncBoneIOW1ThermSensor(sensor_id=address)
57
60
  except ValueError as err:
@@ -60,7 +63,12 @@ class DallasSensorW1(TempSensor, AsyncUpdater):
60
63
 
61
64
  async def async_update(self, time: datetime) -> None:
62
65
  try:
63
- self._state = round(await self._pct.get_temperature(), 2)
66
+ _temp = await self._pct.get_temperature()
67
+ _LOGGER.debug("Fetched temperature %s. Applying filters.", _temp)
68
+ _temp = self._apply_filters(value=_temp)
69
+ if not _temp:
70
+ return
71
+ self._state = _temp
64
72
  self._send_message(
65
73
  topic=self._send_topic,
66
74
  payload={STATE: self._state},
@@ -0,0 +1,2 @@
1
+ # flake8: noqa
2
+ __version__ = "0.5.0dev3"
@@ -27,7 +27,7 @@ dependencies = [
27
27
  "w1thermsensor[async]>=2.0.0",
28
28
  ]
29
29
  requires-python = ">=3.7"
30
- version = "0.5.0dev1"
30
+ version = "0.5.0dev3"
31
31
 
32
32
  [project.license]
33
33
  text = "GNU General Public License v3.0"
@@ -1,2 +0,0 @@
1
- # flake8: noqa
2
- __version__ = "0.5.0dev1"
File without changes
File without changes