boneIO 0.3.0.dev4__py3-none-any.whl → 0.3.0.dev6__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.
boneio/const.py CHANGED
@@ -113,6 +113,8 @@ BINARY_SENSOR = "binary_sensor"
113
113
  LM75 = "lm75"
114
114
  MCP_TEMP_9808 = "mcp9808"
115
115
  INPUT_SENSOR = "inputsensor"
116
+ DS2482 = "ds2482"
117
+ DALLAS = "dallas"
116
118
 
117
119
  BASE = "base"
118
120
  LENGTH = "length"
boneio/cover.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """Cover module."""
2
2
  import asyncio
3
3
  import logging
4
- from typing import Any, Callable
4
+ from typing import Callable
5
5
  from boneio.const import CLOSE, COVER, IDLE, OPEN, OPENING, CLOSING, CLOSED, STOP
6
6
  from boneio.helper.events import EventBus
7
7
  from boneio.helper.mqtt import BasicMqtt
@@ -44,7 +44,7 @@ class Cover(BasicMqtt):
44
44
  def __init__(
45
45
  self,
46
46
  id: str,
47
- open_relay: Any,
47
+ open_relay: MCPRelay,
48
48
  close_relay: MCPRelay,
49
49
  state_save: Callable,
50
50
  open_time: TimePeriod,
boneio/helper/__init__.py CHANGED
@@ -1,5 +1,4 @@
1
1
  """Helper dir for BoneIO."""
2
- from typing import Callable, TypeVar, Any
3
2
 
4
3
  from boneio.helper.gpio import (
5
4
  edge_detect,
@@ -35,20 +34,6 @@ from boneio.helper.exceptions import GPIOInputException, I2CError
35
34
  from boneio.helper.queue import UniqueQueue
36
35
  from boneio.helper.timeperiod import TimePeriod
37
36
 
38
- CALLABLE_T = TypeVar("CALLABLE_T", bound=Callable[..., Any])
39
- CALLBACK_TYPE = Callable[[], None]
40
-
41
-
42
- def callback(func: CALLABLE_T) -> CALLABLE_T:
43
- """Annotation to mark method as safe to call from within the event loop."""
44
- setattr(func, "_boneio_callback", True)
45
- return func
46
-
47
-
48
- def is_callback(func: Callable[..., Any]) -> bool:
49
- """Check if function is safe to be called in the event loop."""
50
- return getattr(func, "_boneio_callback", False) is True
51
-
52
37
 
53
38
  __all__ = [
54
39
  "CustomValidator",
@@ -80,4 +65,6 @@ __all__ = [
80
65
  "load_config_from_string",
81
66
  "load_config_from_file",
82
67
  "TimePeriod",
68
+ "callback",
69
+ "is_callback",
83
70
  ]
@@ -0,0 +1,10 @@
1
+ """Helper dir for DS2482."""
2
+ from boneio.helper.ds2482.ds2482 import DS2482, DS2482_ADDRESS
3
+ from boneio.helper.ds2482.onewire import OneWire, OneWireBus
4
+
5
+
6
+ def ds_address(rom: bytes) -> int:
7
+ return int.from_bytes(rom, "little")
8
+
9
+
10
+ __all__ = ["DS2482", "OneWire", "OneWireBus", "ds_address", "DS2482_ADDRESS"]
@@ -0,0 +1,163 @@
1
+ """DS2482 base class.
2
+ Module by https://github.com/fgervais/ds2482
3
+ """
4
+ import time
5
+
6
+ import adafruit_bus_device.i2c_device as i2c_device
7
+
8
+ # Default i2c address (AD0 = GND, AD1 = GND)
9
+ DS2482_ADDRESS = 0x18
10
+
11
+ # DS2482 device commands
12
+ COMMAND_DEVICE_RESET = 0xF0
13
+ COMMAND_SET_POINTER = 0xE1
14
+ COMMAND_WRITE_CONFIG = 0xD2
15
+ COMMAND_1W_RESET = 0xB4
16
+ COMMAND_1W_SINGLE_BIT = 0x87
17
+ COMMAND_1W_WRITE_BYTE = 0xA5
18
+ COMMAND_1W_READ_BYTE = 0x96
19
+ COMMAND_1W_TRIPLET = 0x78
20
+
21
+ # DS2482 read pointer codes
22
+ POINTER_STATUS = 0xF0
23
+ POINTER_DATA = 0xE1
24
+ POINTER_CONFIG = 0xC3
25
+
26
+ # DS2482 configuration register
27
+ CONFIG_ACTIVE_PULLUP = 0x01
28
+ CONFIG_STRONG_PULLUP = 0x04
29
+ CONFIG_1W_OVERDRIVE = 0x08
30
+
31
+ CONFIG_MASK = 0x0F
32
+
33
+ # DS2482 status register
34
+ STATUS_1W_BUSY = 0x01
35
+ STATUS_PRESENCE_PULSE = 0x02
36
+ STATUT_SHORT_DETECTED = 0x04
37
+ STATUS_LOGIC_LEVEL = 0x08
38
+ STATUS_DEVICE_RESET = 0x10
39
+ STATUS_SINGLE_BIT = 0x20
40
+ STATUS_TRIPLET_BIT = 0x40
41
+ STATUS_BRANCH_TAKEN = 0x80
42
+
43
+
44
+ class DS2482:
45
+ def __init__(self, i2c, address=DS2482_ADDRESS, active_pullup=False):
46
+ self._i2c = i2c_device.I2CDevice(i2c, address)
47
+ self.device_reset()
48
+ if active_pullup:
49
+ self.device_config = CONFIG_ACTIVE_PULLUP
50
+
51
+ # 1-Wire bus busy with STRONG_PULLUP
52
+ self._bus_busy = time.monotonic()
53
+
54
+ def device_reset(self):
55
+ """Terminate any 1-wire communication and reset the DS2482"""
56
+ with self._i2c as i2c:
57
+ i2c.write(bytes([COMMAND_DEVICE_RESET]))
58
+
59
+ @property
60
+ def device_status(self):
61
+ with self._i2c as i2c:
62
+ buf = bytearray([COMMAND_SET_POINTER, POINTER_STATUS])
63
+ i2c.write_then_readinto(buf, buf, in_end=1)
64
+ return buf[0]
65
+
66
+ @property
67
+ def device_config(self):
68
+ with self._i2c as i2c:
69
+ buf = bytearray([COMMAND_SET_POINTER, POINTER_CONFIG])
70
+ i2c.write_then_readinto(buf, buf, in_end=1)
71
+ return buf[0] & 0x0F
72
+
73
+ @device_config.setter
74
+ def device_config(self, config):
75
+ with self._i2c as i2c:
76
+ i2c.write(
77
+ bytes([COMMAND_WRITE_CONFIG, (config & 0x0F) | ((~config << 4) & 0xF0)])
78
+ )
79
+
80
+ def reset(self):
81
+ with self._i2c as i2c:
82
+ buf = bytearray([COMMAND_1W_RESET])
83
+ i2c.write(buf)
84
+ while True:
85
+ i2c.readinto(buf)
86
+ if not buf[0] & STATUS_1W_BUSY:
87
+ break
88
+ time.sleep(0.001)
89
+ return not buf[0] & STATUS_PRESENCE_PULSE
90
+
91
+ def single_bit(self, bit=1, strong_pullup=False, busy=None):
92
+ with self._i2c as i2c:
93
+ buf = bytearray(2)
94
+ if strong_pullup:
95
+ buf[0:2] = [COMMAND_SET_POINTER, POINTER_CONFIG]
96
+ i2c.write_then_readinto(buf, buf, in_start=1)
97
+ buf[0] = COMMAND_WRITE_CONFIG
98
+ buf[1] = buf[1] & CONFIG_MASK | CONFIG_STRONG_PULLUP
99
+ buf[1] |= (~buf[1] << 4) & 0xFF
100
+ i2c.write(buf)
101
+ buf[0:2] = [COMMAND_1W_SINGLE_BIT, 0x80 if bit else 0x00]
102
+ i2c.write(buf)
103
+ while True:
104
+ i2c.readinto(buf, end=1)
105
+ if not buf[0] & STATUS_1W_BUSY:
106
+ break
107
+ time.sleep(0.001)
108
+ if busy:
109
+ self._bus_busy = time.monotonic() + busy
110
+ return buf[0] & STATUS_SINGLE_BIT != 0
111
+
112
+ def write_byte(self, data, strong_pullup=False, busy=None):
113
+ with self._i2c as i2c:
114
+ buf = bytearray(2)
115
+ if strong_pullup:
116
+ buf[0:2] = [COMMAND_SET_POINTER, POINTER_CONFIG]
117
+ i2c.write_then_readinto(buf, buf, in_start=1)
118
+ buf[0] = COMMAND_WRITE_CONFIG
119
+ buf[1] = buf[1] & CONFIG_MASK | CONFIG_STRONG_PULLUP
120
+ buf[1] |= (~buf[1] << 4) & 0xFF
121
+ i2c.write(buf)
122
+ buf[0:2] = [COMMAND_1W_WRITE_BYTE, data]
123
+ i2c.write(buf)
124
+ while True:
125
+ i2c.readinto(buf, end=1)
126
+ if buf[0] & STATUS_1W_BUSY == 0:
127
+ break
128
+ time.sleep(0.001)
129
+ if busy:
130
+ self._bus_busy = time.monotonic() + busy
131
+
132
+ def read_byte(self):
133
+ with self._i2c as i2c:
134
+ buf = bytearray([COMMAND_1W_READ_BYTE, 0x00])
135
+ i2c.write(buf, end=1)
136
+ while True:
137
+ i2c.readinto(buf, end=1)
138
+ if not buf[0] & STATUS_1W_BUSY:
139
+ break
140
+ time.sleep(0.001)
141
+ buf[0:2] = [COMMAND_SET_POINTER, POINTER_DATA]
142
+ i2c.write_then_readinto(buf, buf, in_end=1)
143
+ return buf[0]
144
+
145
+ def wait_ready(self):
146
+ while True:
147
+ t = self._bus_busy - time.monotonic()
148
+ if t > 0:
149
+ time.sleep(t)
150
+ else:
151
+ break
152
+ with self._i2c as i2c:
153
+ buf = bytearray([COMMAND_SET_POINTER, POINTER_STATUS])
154
+ i2c.write(buf)
155
+ while True:
156
+ i2c.readinto(buf, end=1)
157
+ if not buf[0] & STATUS_1W_BUSY:
158
+ break
159
+ time.sleep(0.001)
160
+ return buf[0]
161
+
162
+ def triplet(self, dir):
163
+ pass
@@ -0,0 +1,44 @@
1
+ """OneWire base class for DS2482.
2
+ Module by https://github.com/fgervais/ds2482
3
+ """
4
+ import adafruit_onewire.bus
5
+ import busio
6
+
7
+
8
+ class OneWire(busio.OneWire):
9
+ def __init__(self, ds2482):
10
+ self.ds2482 = ds2482
11
+
12
+ def deinit(self):
13
+ """
14
+ Deinitialize the OneWire bus and release any hardware resources for reuse.
15
+ """
16
+ self.ds2482.device_reset()
17
+
18
+ def reset(self):
19
+ """
20
+ Reset the OneWire bus and read presence
21
+
22
+ :return: False when at least one device is present
23
+ """
24
+ return self.ds2482.reset()
25
+
26
+ def read_bit(self):
27
+ """
28
+ Read in a bit
29
+ """
30
+ return self.ds2482.single_bit()
31
+
32
+ def write_bit(self, value):
33
+ """
34
+ Write out a bit based on value.
35
+ """
36
+ self.ds2482.single_bit(value)
37
+
38
+
39
+ class OneWireBus(adafruit_onewire.bus.OneWireBus):
40
+ def __init__(self, ds2482):
41
+ self._ow = OneWire(ds2482)
42
+ self._readbit = self._ow.read_bit
43
+ self._writebit = self._ow.write_bit
44
+ self._maximum_devices = adafruit_onewire.bus._MAX_DEV
boneio/helper/events.py CHANGED
@@ -3,9 +3,9 @@ import datetime as dt
3
3
  import signal
4
4
  import logging
5
5
  import time
6
- from typing import Callable
6
+ from typing import Callable, Optional
7
7
  from datetime import datetime
8
- from boneio.helper import callback
8
+ from boneio.helper.util import callback
9
9
 
10
10
  _LOGGER = logging.getLogger(__name__)
11
11
  UTC = dt.timezone.utc
@@ -139,9 +139,9 @@ def async_track_point_in_time(
139
139
  # Ensure point_in_time is UTC
140
140
  utc_point_in_time = as_utc(point_in_time)
141
141
 
142
- # Since this is called once, we accept a HassJob so we can avoid
142
+ # Since this is called once, we accept a so we can avoid
143
143
  # having to figure out how to call the action every time its called.
144
- cancel_callback: asyncio.TimerHandle | None = None
144
+ cancel_callback: Optional[asyncio.TimerHandle] = None
145
145
 
146
146
  @callback
147
147
  def run_action(job) -> None:
@@ -13,5 +13,13 @@ class I2CError(BoneIOException):
13
13
  """I2C Exception."""
14
14
 
15
15
 
16
+ class OneWireError(BoneIOException):
17
+ """One Wire Exception."""
18
+
19
+
16
20
  class ConfigurationException(BoneIOException):
17
21
  """Configuration yaml exception."""
22
+
23
+
24
+ class CoverRelayException(BoneIOException):
25
+ """Cover configuration exception."""
boneio/helper/loader.py CHANGED
@@ -43,10 +43,13 @@ from boneio.helper import (
43
43
  ha_input_availabilty_message,
44
44
  ha_sensor_temp_availabilty_message,
45
45
  )
46
+ from adafruit_onewire.bus import OneWireAddress
47
+ from boneio.helper.ds2482 import DS2482, OneWireBus, ds_address, DS2482_ADDRESS
46
48
  from boneio.helper.ha_discovery import ha_cover_availabilty_message
47
49
  from boneio.helper.timeperiod import TimePeriod
48
50
  from boneio.input.gpio import GpioInputButton
49
51
  from boneio.helper.config import ConfigHelper
52
+ from boneio.sensor import DallasSensor
50
53
 
51
54
  # Typing imports that create a circular dependency
52
55
  if TYPE_CHECKING:
@@ -116,6 +119,7 @@ def create_temp_sensor(
116
119
  address=temp_def[ADDRESS],
117
120
  send_message=manager.send_message,
118
121
  topic_prefix=topic_prefix,
122
+ update_interval=temp_def.get(UPDATE_INTERVAL, TimePeriod(seconds=60)),
119
123
  )
120
124
  manager.send_ha_autodiscovery(
121
125
  id=id,
@@ -343,3 +347,47 @@ def configure_cover(
343
347
  availability_msg_func=ha_cover_availabilty_message,
344
348
  )
345
349
  return cover
350
+
351
+
352
+ def configure_ds2482(i2cbusio: I2C, address: str = DS2482_ADDRESS) -> OneWireBus:
353
+ ds2482 = DS2482(i2c=i2cbusio, address=address)
354
+ ow_bus = OneWireBus(ds2482=ds2482)
355
+ return ow_bus
356
+
357
+
358
+ def find_onewire_devices(ow_bus: OneWireBus):
359
+ devices = ow_bus.scan()
360
+ out = {}
361
+ for device in devices:
362
+ _addr: int = ds_address(device.rom)
363
+ _LOGGER.debug("Found device with address %s", hex(_addr))
364
+ out[_addr] = device
365
+ return out
366
+
367
+
368
+ def create_ds2482_dallas_sensor(
369
+ manager: Manager,
370
+ ds2482_bus: OneWireBus,
371
+ address: OneWireAddress,
372
+ config: dict,
373
+ **kwargs,
374
+ ):
375
+ name = config.get(ID) or hex(address)
376
+ id = name.replace(" ", "")
377
+ sensor = DallasSensor(
378
+ bus=ds2482_bus,
379
+ address=address,
380
+ id=id,
381
+ name=name,
382
+ update_interval=config.get(UPDATE_INTERVAL, TimePeriod(seconds=60)),
383
+ send_message=manager.send_message,
384
+ **kwargs,
385
+ )
386
+ if config.get(SHOW_HA, True):
387
+ manager.send_ha_autodiscovery(
388
+ id=sensor.id,
389
+ name=sensor.name,
390
+ ha_type=SENSOR,
391
+ availability_msg_func=ha_sensor_temp_availabilty_message,
392
+ )
393
+ return sensor
boneio/helper/util.py ADDED
@@ -0,0 +1,15 @@
1
+ from typing import Callable, TypeVar, Any
2
+
3
+ CALLABLE_T = TypeVar("CALLABLE_T", bound=Callable[..., Any])
4
+ CALLBACK_TYPE = Callable[[], None]
5
+
6
+
7
+ def callback(func: CALLABLE_T) -> CALLABLE_T:
8
+ """Annotation to mark method as safe to call from within the event loop."""
9
+ setattr(func, "_boneio_callback", True)
10
+ return func
11
+
12
+
13
+ def is_callback(func: Callable[..., Any]) -> bool:
14
+ """Check if function is safe to be called in the event loop."""
15
+ return getattr(func, "_boneio_callback", False) is True
boneio/manager.py CHANGED
@@ -7,6 +7,7 @@ from busio import I2C
7
7
 
8
8
  from boneio.const import (
9
9
  ACTION,
10
+ ADDRESS,
10
11
  BUTTON,
11
12
  CLOSE,
12
13
  COVER,
@@ -51,6 +52,7 @@ from boneio.helper.loader import (
51
52
  configure_relay,
52
53
  create_mcp23017,
53
54
  create_temp_sensor,
55
+ create_ds2482_dallas_sensor,
54
56
  )
55
57
  from boneio.helper.yaml_util import load_config_from_file
56
58
  from boneio.modbus import Modbus
@@ -75,6 +77,8 @@ class Manager:
75
77
  sensors: dict = {},
76
78
  modbus: dict = None,
77
79
  mcp23017: Optional[List] = None,
80
+ ds2482: Optional[dict] = None,
81
+ dallas: Optional[List] = None,
78
82
  oled: dict = {},
79
83
  adc_list: Optional[List] = None,
80
84
  covers: Optional[List] = [],
@@ -98,6 +102,8 @@ class Manager:
98
102
  self._oled = None
99
103
  self._tasks: List[asyncio.Task] = []
100
104
  self._covers = {}
105
+ self._ds_onewire = {}
106
+ self._ds_onewire_bus = {}
101
107
  self._temp_sensors = []
102
108
  self._modbus = None
103
109
  if modbus and modbus.get(UART) in UARTS:
@@ -130,6 +136,33 @@ class Manager:
130
136
  manager=self, mcp23017=mcp23017, i2cbusio=self._i2cbusio
131
137
  )
132
138
 
139
+ if ds2482:
140
+ _LOGGER.debug("Preparing DS2482 bus.")
141
+ from boneio.helper.loader import configure_ds2482, find_onewire_devices
142
+
143
+ self._ds_onewire_bus[ds2482[ID]] = configure_ds2482(
144
+ i2cbusio=self._i2cbusio, address=ds2482[ADDRESS]
145
+ )
146
+ self._ds_onewire = find_onewire_devices(
147
+ ow_bus=self._ds_onewire_bus[ds2482[ID]]
148
+ )
149
+ for sensor in dallas:
150
+ ds2482_bus_id = sensor.get("ds2482_id")
151
+ if ds2482_bus_id and ds2482_bus_id in self._ds_onewire_bus:
152
+ address = self._ds_onewire.get(sensor[ADDRESS])
153
+ if not address:
154
+ continue
155
+
156
+ self._temp_sensors.append(
157
+ create_ds2482_dallas_sensor(
158
+ manager=self,
159
+ ds2482_bus=self._ds_onewire_bus[ds2482_bus_id],
160
+ address=address,
161
+ topic_prefix=self._config_helper.topic_prefix,
162
+ config=sensor,
163
+ )
164
+ )
165
+
133
166
  if adc_list:
134
167
  from boneio.helper.loader import create_adc
135
168
 
@@ -171,6 +204,18 @@ class Manager:
171
204
  _id = _config[ID].replace(" ", "")
172
205
  open_relay = self._output.get(_config.get("open_relay"))
173
206
  close_relay = self._output.get(_config.get("close_relay"))
207
+ if not open_relay:
208
+ _LOGGER.error(
209
+ "Can't configure cover %s. This relay doesn't exist.",
210
+ _config.get("open_relay"),
211
+ )
212
+ continue
213
+ if not close_relay:
214
+ _LOGGER.error(
215
+ "Can't configure cover %s. This relay doesn't exist.",
216
+ _config.get("close_relay"),
217
+ )
218
+ continue
174
219
  if open_relay.output_type != NONE or close_relay.output_type != NONE:
175
220
  _LOGGER.error(
176
221
  "Can't configure cover %s. %s",
boneio/relay/mcp.py CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  import logging
4
4
  from adafruit_mcp230xx.mcp23017 import MCP23017, DigitalInOut
5
- from boneio.helper import callback
5
+ from boneio.helper.util import callback
6
6
  from boneio.relay.basic import BasicRelay
7
7
  from boneio.const import SWITCH, NONE
8
8
  from boneio.helper.events import async_track_point_in_time, utcnow
boneio/runner.py CHANGED
@@ -5,6 +5,7 @@ import os
5
5
  from boneio.const import (
6
6
  ADC,
7
7
  COVER,
8
+ DALLAS,
8
9
  ENABLED,
9
10
  HA_DISCOVERY,
10
11
  HOST,
@@ -20,6 +21,7 @@ from boneio.const import (
20
21
  PORT,
21
22
  TOPIC_PREFIX,
22
23
  USERNAME,
24
+ DS2482,
23
25
  )
24
26
 
25
27
  _LOGGER = logging.getLogger(__name__)
@@ -66,6 +68,8 @@ async def async_run(
66
68
  MODBUS: config.get("modbus_sensors"),
67
69
  },
68
70
  mcp23017=config.get(MCP23017, []),
71
+ ds2482=config.get(DS2482),
72
+ dallas=config.get(DALLAS, []),
69
73
  modbus=config.get(MODBUS),
70
74
  oled=config.get(OLED),
71
75
  adc_list=config.get(ADC, []),
boneio/schema/schema.yaml CHANGED
@@ -146,6 +146,17 @@ lm75:
146
146
  default: 0x48
147
147
  meta:
148
148
  label: Address of I2C
149
+ update_interval:
150
+ type:
151
+ - string
152
+ - timeperiod
153
+ coerce:
154
+ - str
155
+ - positive_time_period
156
+ required: True
157
+ default: 60s
158
+ meta:
159
+ label: Update interval.
149
160
 
150
161
 
151
162
  mcp9808:
@@ -162,7 +173,18 @@ mcp9808:
162
173
  required: True
163
174
  default: 0x18
164
175
  meta:
165
- label: GPIO of I2C SDA
176
+ label: Address of I2C device
177
+ update_interval:
178
+ type:
179
+ - string
180
+ - timeperiod
181
+ coerce:
182
+ - str
183
+ - positive_time_period
184
+ required: True
185
+ default: 60s
186
+ meta:
187
+ label: Update interval.
166
188
 
167
189
  mcp23017:
168
190
  type: list
@@ -356,6 +378,7 @@ adc:
356
378
  label: If you want you can disable discovering this input in HA.
357
379
  cover:
358
380
  type: list
381
+ required: False
359
382
  meta:
360
383
  label: Cover section
361
384
  schema:
@@ -414,3 +437,60 @@ cover:
414
437
  default: True
415
438
  meta:
416
439
  label: If you want you can disable discovering this input in HA.
440
+
441
+ ds2482:
442
+ type: dict
443
+ required: False
444
+ schema:
445
+ id:
446
+ type: string
447
+ required: True
448
+ meta:
449
+ label: Id of I2C to use in pin config
450
+ address:
451
+ type: string
452
+ required: True
453
+ default: 0x18
454
+ meta:
455
+ label: GPIO of I2C SDA
456
+
457
+ dallas:
458
+ type: list
459
+ required: False
460
+ meta:
461
+ label: Dallas DS18B20 section
462
+ schema:
463
+ type: dict
464
+ schema:
465
+ id:
466
+ type: string
467
+ required: False
468
+ meta:
469
+ label: Id to use in HA if needed. Default to address.
470
+ address:
471
+ type: integer
472
+ required: True
473
+ meta:
474
+ label: Address of Dallas device
475
+ ds2482_id:
476
+ type: string
477
+ required: False
478
+ meta:
479
+ label: Put DS2482 defined id if you want to add DS18B20 connected via DS2482.
480
+ show_in_ha:
481
+ type: boolean
482
+ required: True
483
+ default: True
484
+ meta:
485
+ label: If you want you can disable discovering this input in HA.
486
+ update_interval:
487
+ type:
488
+ - string
489
+ - timeperiod
490
+ coerce:
491
+ - str
492
+ - positive_time_period
493
+ required: True
494
+ default: 60s
495
+ meta:
496
+ label: Update interval.
boneio/sensor/__init__.py CHANGED
@@ -1,9 +1,12 @@
1
1
  """Sensor module."""
2
- from boneio.sensor.temp import LM75Sensor, MCP9808Sensor
2
+ from boneio.sensor.temp.lm75 import LM75Sensor
3
+ from boneio.sensor.temp.mcp9808 import MCP9808Sensor
4
+ from boneio.sensor.temp.dallas import DallasSensor
3
5
  from boneio.sensor.gpio import GpioInputSensor
4
6
  from boneio.sensor.adc import initialize_adc, GpioADCSensor
5
7
 
6
8
  __all__ = [
9
+ "DallasSensor",
7
10
  "LM75Sensor",
8
11
  "MCP9808Sensor",
9
12
  "GpioInputSensor",
@@ -22,6 +22,8 @@ from boneio.helper import BasicMqtt
22
22
  from boneio.helper.ha_discovery import modbus_sensor_availabilty_message
23
23
  from boneio.helper.timeperiod import TimePeriod
24
24
  from boneio.helper.config import ConfigHelper
25
+ from boneio.modbus import Modbus
26
+
25
27
 
26
28
  _LOGGER = logging.getLogger(__name__)
27
29
 
@@ -92,7 +94,7 @@ class ModbusSensor(BasicMqtt):
92
94
 
93
95
  def __init__(
94
96
  self,
95
- modbus,
97
+ modbus: Modbus,
96
98
  address: str,
97
99
  model: str,
98
100
  config_helper: ConfigHelper,
@@ -104,7 +106,7 @@ class ModbusSensor(BasicMqtt):
104
106
  super().__init__(
105
107
  id=id or address,
106
108
  topic_type=SENSOR,
107
- topic_prefix=self._config_helper.topic_prefix,
109
+ topic_prefix=config_helper.topic_prefix,
108
110
  **kwargs,
109
111
  )
110
112
  self._config_helper = config_helper
@@ -1,13 +1,21 @@
1
1
  """Manage BoneIO onboard temp sensors."""
2
2
 
3
3
  import asyncio
4
- from adafruit_pct2075 import PCT2075
5
- from adafruit_mcp9808 import MCP9808
6
- from boneio.const import STATE, SENSOR, LM75, MCP_TEMP_9808, TEMPERATURE
4
+ from datetime import datetime, timedelta
5
+ from typing import Optional
6
+
7
+ from boneio.const import STATE, SENSOR, TEMPERATURE
8
+
7
9
 
8
10
  from boneio.helper.exceptions import I2CError
9
11
  from boneio.helper import BasicMqtt
10
12
 
13
+ from boneio.helper.util import callback
14
+ from boneio.helper.events import async_track_point_in_time, utcnow
15
+
16
+
17
+ from boneio.helper.timeperiod import TimePeriod
18
+
11
19
 
12
20
  class TempSensor(BasicMqtt):
13
21
  """Represent Temp sensor in BoneIO."""
@@ -15,11 +23,22 @@ class TempSensor(BasicMqtt):
15
23
  SensorClass = None
16
24
  DefaultName = TEMPERATURE
17
25
 
18
- def __init__(self, i2c, address, id: str = DefaultName, **kwargs):
26
+ def __init__(
27
+ self,
28
+ i2c,
29
+ address: str,
30
+ id: str = DefaultName,
31
+ update_interval: int = TimePeriod(seconds=60),
32
+ **kwargs
33
+ ):
19
34
  """Initialize Temp class."""
20
35
  super().__init__(id=id, topic_type=SENSOR, **kwargs)
36
+ self._update_interval = update_interval
37
+ self._loop = asyncio.get_event_loop()
21
38
  try:
22
39
  self._pct = self.SensorClass(i2c_bus=i2c, address=address)
40
+ self._unsub_refresh = None
41
+ self._schedule_refresh(utcnow() + timedelta(seconds=2))
23
42
  except ValueError as err:
24
43
  raise I2CError(err)
25
44
 
@@ -28,25 +47,30 @@ class TempSensor(BasicMqtt):
28
47
  """Give rounded value of temperature."""
29
48
  return round(self._pct.temperature, 2)
30
49
 
31
- async def send_state(self):
32
- """Fetch temperature periodically and send to MQTT."""
33
- while True:
34
- self._send_message(
35
- topic=self._send_topic,
36
- payload={STATE: self.state},
37
- )
38
- await asyncio.sleep(60)
39
-
40
-
41
- class LM75Sensor(TempSensor):
42
- """Represent LM75 sensor in BoneIO."""
50
+ def _schedule_refresh(self, update_time: Optional[datetime] = None):
51
+ if self._unsub_refresh:
52
+ self._unsub_refresh()
53
+ self._unsub_refresh = None
54
+ if not update_time:
55
+ update_time = utcnow() + self._update_interval.as_timedelta
56
+ self._unsub_refresh = async_track_point_in_time(
57
+ loop=self._loop,
58
+ action=self._refresh,
59
+ point_in_time=update_time,
60
+ )
43
61
 
44
- SensorClass = PCT2075
45
- DefaultName = LM75
62
+ @callback
63
+ def _refresh(self, time: datetime):
64
+ if self._unsub_refresh:
65
+ self._unsub_refresh()
66
+ self._unsub_refresh = None
46
67
 
68
+ self.send_state()
69
+ self._schedule_refresh()
47
70
 
48
- class MCP9808Sensor(TempSensor):
49
- """Represent MCP9808 sensor in BoneIO."""
50
-
51
- SensorClass = MCP9808
52
- DefaultName = MCP_TEMP_9808
71
+ def send_state(self):
72
+ """Fetch temperature periodically and send to MQTT."""
73
+ self._send_message(
74
+ topic=self._send_topic,
75
+ payload={STATE: self.state},
76
+ )
@@ -0,0 +1,43 @@
1
+ """Dallas temp sensor."""
2
+
3
+ import asyncio
4
+ from datetime import timedelta
5
+
6
+ # from datetime import timedelta
7
+ from adafruit_ds18x20 import DS18X20
8
+ from adafruit_onewire.bus import OneWireAddress
9
+ from boneio.const import SENSOR, TEMPERATURE
10
+
11
+
12
+ from boneio.helper.exceptions import OneWireError
13
+ from boneio.helper import BasicMqtt
14
+
15
+ from boneio.helper.events import utcnow
16
+
17
+
18
+ from boneio.helper.timeperiod import TimePeriod
19
+ from . import TempSensor
20
+
21
+
22
+ class DallasSensor(TempSensor):
23
+ DefaultName = TEMPERATURE
24
+ SensorClass = DS18X20
25
+
26
+ def __init__(
27
+ self,
28
+ bus,
29
+ address: OneWireAddress,
30
+ id: str = DefaultName,
31
+ update_interval: int = TimePeriod(seconds=60),
32
+ **kwargs
33
+ ):
34
+ """Initialize Temp class."""
35
+ self._update_interval = update_interval
36
+ self._loop = asyncio.get_event_loop()
37
+ BasicMqtt.__init__(self, id=id, topic_type=SENSOR, **kwargs)
38
+ try:
39
+ self._pct = DS18X20(bus=bus, address=address)
40
+ self._unsub_refresh = None
41
+ self._schedule_refresh(utcnow() + timedelta(seconds=2))
42
+ except ValueError as err:
43
+ raise OneWireError(err)
@@ -0,0 +1,11 @@
1
+ """LM75 temp sensor."""
2
+ from . import TempSensor
3
+ from adafruit_pct2075 import PCT2075
4
+ from boneio.const import LM75
5
+
6
+
7
+ class LM75Sensor(TempSensor):
8
+ """Represent LM75 sensor in BoneIO."""
9
+
10
+ SensorClass = PCT2075
11
+ DefaultName = LM75
@@ -0,0 +1,12 @@
1
+ """MCP9808 temp sensor."""
2
+
3
+ from . import TempSensor
4
+ from adafruit_mcp9808 import MCP9808
5
+ from boneio.const import MCP_TEMP_9808
6
+
7
+
8
+ class MCP9808Sensor(TempSensor):
9
+ """Represent MCP9808 sensor in BoneIO."""
10
+
11
+ SensorClass = MCP9808
12
+ DefaultName = MCP_TEMP_9808
boneio/version.py CHANGED
@@ -1,2 +1,2 @@
1
1
  # flake8: noqa
2
- __version__ = "0.3.0.dev4"
2
+ __version__ = "0.3.0.dev6"
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: boneio
3
- Version: 0.3.0.dev4
3
+ Version: 0.3.0.dev6
4
4
  Summary: Python App for BoneIO
5
5
  Home-page: https://github.com/boneIO-eu/app_bbb
6
- Download-URL: https://github.com/boneIO-eu/app_bbb/archive/0.3.0.dev4.zip
6
+ Download-URL: https://github.com/boneIO-eu/app_bbb/archive/0.3.0.dev6.zip
7
7
  License: GNU General Public License v3.0
8
8
  Platform: UNKNOWN
9
9
  Classifier: Programming Language :: Python
@@ -14,6 +14,7 @@ Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: Adafruit-BBIO (==1.2.0)
16
16
  Requires-Dist: Adafruit-Blinka (==6.20.4)
17
+ Requires-Dist: adafruit-circuitpython-ds18x20 (==1.3.10)
17
18
  Requires-Dist: adafruit-circuitpython-mcp230xx (==2.5.3)
18
19
  Requires-Dist: adafruit-circuitpython-mcp9808 (==3.3.10)
19
20
  Requires-Dist: adafruit-circuitpython-pct2075 (==1.1.12)
@@ -1,13 +1,13 @@
1
1
  boneio/__init__.py,sha256=hoLKnu6h1uEsiCHA9Ql2MMDC7VQS0E-s_2cxBS-CTOg,147
2
2
  boneio/bonecli.py,sha256=Alvpbf3gZteV3IMX7DBUD6F_XV_-juKfZ1d4YpIM7PI,3093
3
- boneio/const.py,sha256=eBU9YNvTHvTRLvQtug0uqmsMZnVVNNcsKMZSow67fLM,2600
4
- boneio/cover.py,sha256=wKrnhaRGjJmEutUbisvDmPjVAYeDi4lYzV_de4nXxtA,8298
5
- boneio/manager.py,sha256=qfaND0Cw3qSAfBxV7eP1Gz41dQL9hps-9MRWWsbYeUg,14581
3
+ boneio/const.py,sha256=nkL8SAMnZT3SfQiNOhWQ5RKoxUIoJV_9dH0BwLAJzXI,2636
4
+ boneio/cover.py,sha256=Oi25Be0umRfKJ12kEBZYASw07bvRbLOT2s0emh4Kals,8298
5
+ boneio/manager.py,sha256=jyQSbPOTbXWj1YuLviwugs5F4eKnG2DIEhc4F0Uf3TY,16321
6
6
  boneio/modbus.py,sha256=QWUAYHXLcP7A_vVKTMbZ7x8KS72qLw65t_UzTDI3448,4003
7
7
  boneio/mqtt_client.py,sha256=Y_Vt0pKEETIy1XKQ-WFhowlRJhuv9tWLtyoD8Vdz7hk,6983
8
8
  boneio/oled.py,sha256=Be9QeTHX1mmCQOshYY1KNGvqt4nzEtJCD3gCE3gRSsc,4836
9
- boneio/runner.py,sha256=Y3Xx4N4WZchVr7a9gUtqskp_l5-_Cp7T_dVLfHSz8vQ,2064
10
- boneio/version.py,sha256=aRsCpG8-QTx0XdbEXY9OSFnuyhz5H629k_Tk-UN_tSk,42
9
+ boneio/runner.py,sha256=IdAV1Yu--LncQYbNjx6w2uGjqUDBxNcNPW5ZH3hZuBo,2162
10
+ boneio/version.py,sha256=x346uF6-PqYb8v3BN7X9RPPWeWgBJitJpH-sVmzKGEg,42
11
11
  boneio/example_config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  boneio/example_config/adc.yaml,sha256=KaNfPuZmrhpiKJVUKC6uQXQ0YRCp0DoXVxYtqsbiSGI,168
13
13
  boneio/example_config/config.yaml,sha256=_gNf0Yo6p10Ao_rcSmHA_gCGMtDsvAdso3jNt3r3gqE,322
@@ -16,13 +16,13 @@ boneio/example_config/input.yaml,sha256=U5pN5Dyb8XrhqHeXsa3rYE5VFI4Y_BapNJkv9c1i
16
16
  boneio/example_config/output24x16A.yaml,sha256=uCj6U1j8qrnb3-Ui78-UjSFNZ3h_evNlab1p6P0H3-g,1691
17
17
  boneio/example_config/output32x5A.yaml,sha256=HuNSZ7S1qGMQi_XDAGJiMDe-W-aPcigvm6v-FYPgMeE,2471
18
18
  boneio/fonts/danube__.ttf,sha256=KBRPUcGvmroCjrWC8zK4MulUb9lV8R0lXkOY7lNnQWc,19372
19
- boneio/helper/__init__.py,sha256=wOr2NWtGamuaWVmmQQP4vcNaj1I6pXeT2rDf-FzXKYk,2289
19
+ boneio/helper/__init__.py,sha256=zXVY9cTcFumVLf4wuNIutkL5UATTKL-ODcv8VjjxGfw,1816
20
20
  boneio/helper/config.py,sha256=WuHsEP7FazMuCB55Qgc6m-X2gMsSoscmXTS8BoX8vPE,881
21
- boneio/helper/events.py,sha256=oKXDpFXSmbfhnucSYTTCPlhaBBstcAYYg3bTIVS6D1w,5251
22
- boneio/helper/exceptions.py,sha256=4APZ9UrJtCWP-5hLqHUThJ9fLKOZr-LoulLy_1QAq-I,318
21
+ boneio/helper/events.py,sha256=jXRyWyq_yFJHURs0YPyhKo4tR6dQ7FvGGqen9RfGqp4,5261
22
+ boneio/helper/exceptions.py,sha256=2t7WvfE2vS17eK9cV4l_RmBEug1ZlkPXWLRMxDSPLFI,474
23
23
  boneio/helper/gpio.py,sha256=HOImpow_6rVOtgZ5FAZd-En61jNyigp2AVZMXYW0x3U,2765
24
24
  boneio/helper/ha_discovery.py,sha256=0Ab5xwplKoxArYTSwt5xyBtn5MaVbKlzdoRNw3tpRN8,5480
25
- boneio/helper/loader.py,sha256=lSkjp1o27dUCC5iSH8ymjcQCCBcMIRxguDMggYFs_94,9985
25
+ boneio/helper/loader.py,sha256=qF0AKEz6TQhB0WLCHMx8LVV8l2CkiFgooW1ejvJtc34,11427
26
26
  boneio/helper/logger.py,sha256=8B0qeNPALGG5Dlz0cfujjknbf-TOPv4axLF3xj_Bzs8,1800
27
27
  boneio/helper/mqtt.py,sha256=q_0K5TOWNZNCvmhpHuFWloRSVyGxdklogx0jYxc5cpg,741
28
28
  boneio/helper/oled.py,sha256=f0XYbaFstUbJ6ISmFe1vQCnmNVMctQWtnStNdROrblc,351
@@ -30,28 +30,35 @@ boneio/helper/queue.py,sha256=7fE7d344-BEW8sljN40wmqsbBr4kPLvz4ShBjkT04p8,1066
30
30
  boneio/helper/state_manager.py,sha256=3xBj2Uo9_YrfTxmpxhOg5EaRY71YRv0f9PgBOGtki-g,1994
31
31
  boneio/helper/stats.py,sha256=wMoRP7k8v6EeMljaPK8YUZbfW8rlb06tOoDy58fjm3k,4898
32
32
  boneio/helper/timeperiod.py,sha256=KUivnt9hGyb_0bSqvmr8tCCm4axL6axuyF2jlkW--b0,5653
33
+ boneio/helper/util.py,sha256=VG7VvPUX6L2M8ib6A3vK2mXh7_9KchahMsaXH9iaFr0,508
33
34
  boneio/helper/yaml_util.py,sha256=IQHE-MeaXlzuUAybw9Zkyr5cVYwkm14M1zfLk6gW5S8,10524
35
+ boneio/helper/ds2482/__init__.py,sha256=Zsh_6hLOta9gjognR_ECideMmwtMTYpWN757eybC6gc,311
36
+ boneio/helper/ds2482/ds2482.py,sha256=c2t_hdAMtFsHw4Vw41QzO_hEDDNMeb3J71mEwEMUBhM,5169
37
+ boneio/helper/ds2482/onewire.py,sha256=KTNFmFFhNQsxnu0ue_GpBjilv54F1XJnWgVly-0BTIU,1085
34
38
  boneio/input/__init__.py,sha256=u9wuehuC_TNizL4tyn7EygZW5LaTFjSnFaZeZr3zZ1U,99
35
39
  boneio/input/gpio.py,sha256=kLsi6KRD_cZGnmsIp758TZ3tj5hegNYQPyEXYlkmc-s,4318
36
40
  boneio/relay/__init__.py,sha256=L_Peoep10-DdeMrEe-5YnnNCS-mxHtavCqtAesTPWFQ,135
37
41
  boneio/relay/basic.py,sha256=QTax7fGU3YrVx1wBH2Z91w3Hv_ALMs8EiJ4Tdkh1xno,2629
38
42
  boneio/relay/gpio.py,sha256=miuE2fOozmBnFf2Es4wqa5RivtZlUR8NFDGNAoajUk0,1163
39
- boneio/relay/mcp.py,sha256=yGnAYpYNqNi85m1cIUPKWg2xe-p56mL3Q08Z_-IAAIg,2693
43
+ boneio/relay/mcp.py,sha256=Rx_JRxmRVOGPvA-fdoQN2KYglryHQPm5F7Jcb7TZQCg,2698
40
44
  boneio/schema/actions.yaml,sha256=HWBeyJLBVbJ_prSYj14ovP7f13QKXL3-9GRJgAOpHQ4,921
41
45
  boneio/schema/actions_sensor.yaml,sha256=LhXEsYsg6qs7iHqgQE6n-2jj-o-ZZRusDW_9nWIiZAY,129
42
46
  boneio/schema/actions_switch.yaml,sha256=qyooX0izkgl4wBEh8xUsYFEKMrvhbIAQYxOGTB5AROY,124
43
- boneio/schema/schema.yaml,sha256=pJHGIC92SlTLhCUqBUolIQOqsoIcevfgXRJhfPu9lpo,9458
44
- boneio/sensor/__init__.py,sha256=XJG-ktDfEPMs5RLt9hYT3gQmYhU_wMOR0Ud88-Q0KmM,305
47
+ boneio/schema/schema.yaml,sha256=uSA-o14-l7hcOb9Iu9OFiSGDHwBjlMEvsL4YWmyc5po,11124
48
+ boneio/sensor/__init__.py,sha256=jE2rgBN3eR0mh2nYA3J-H15RSjZB0J7k1eYNjnm47f4,419
45
49
  boneio/sensor/adc.py,sha256=mAxzgs0Eul1V6Fmye9V7TsJiPRnc59TQ-s7nb_PV7G8,1245
46
50
  boneio/sensor/gpio.py,sha256=9f_hNcCYvrEb7FvA00Xm-L5-fUXdH4SM-jZiOamOz2Q,1230
47
- boneio/sensor/modbus/__init__.py,sha256=O3Fvo_VtQhmZg7ZxSqahQTLhIA6Lt-rr09rkpwad_eM,8394
51
+ boneio/sensor/modbus/__init__.py,sha256=Pk1xrgRl126-9WkIXMair6H9HZWpD9_WoKfgFKVrA8M,8430
48
52
  boneio/sensor/modbus/sdm120.json,sha256=4sueFfSw7G6a77gdIUhbfJvE-MNVJFOeVbRvHDw5Rvk,4145
49
53
  boneio/sensor/modbus/sdm630.json,sha256=6LbIfXWk_PVRW-OuJwrsFEnRGLVEmEqqGIbj-1FDaiI,10969
50
54
  boneio/sensor/modbus/sofar.json,sha256=A_YztQN_ctyItIm2LH1tfcs-pSyG18I530qleLd2tOw,5592
51
- boneio/sensor/temp/__init__.py,sha256=lhvQqD76atQNyoxdeyskH8_fVOLCaHFoVnpzby6kqeE,1416
52
- boneio-0.3.0.dev4.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
53
- boneio-0.3.0.dev4.dist-info/METADATA,sha256=OZIapR0ZqXnK00bit9n4JHlfL3D7lEXNuavp5XYPiOU,1887
54
- boneio-0.3.0.dev4.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
55
- boneio-0.3.0.dev4.dist-info/entry_points.txt,sha256=JX7gluDIkQ6MBlzzxGHMItnBjciiJ73tsXwYcazMW_U,47
56
- boneio-0.3.0.dev4.dist-info/top_level.txt,sha256=ag9S5n1_KXZfyk9tN8R0YUDYbdA--e5a2w2FOD_yMdg,7
57
- boneio-0.3.0.dev4.dist-info/RECORD,,
55
+ boneio/sensor/temp/__init__.py,sha256=AgjEbpkyY1D2Wo7tOGSFKr_uD2LexwLiezkaYP36yEY,2182
56
+ boneio/sensor/temp/dallas.py,sha256=K-dOme8s1AGEvsbHeb3Tt3pkHrFwhX7_CAXiq8Se2uY,1168
57
+ boneio/sensor/temp/lm75.py,sha256=aTvNlG6z7Kk2QnKtjTxq6NLV46-BH7AVHFt7g9XExbY,241
58
+ boneio/sensor/temp/mcp9808.py,sha256=1DKfZyzFHA425xNSPS5is8nWWsClT-D0AbrQx9zgAJg,269
59
+ boneio-0.3.0.dev6.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
60
+ boneio-0.3.0.dev6.dist-info/METADATA,sha256=NUHm0qYpXDomocRBX9T2RPNAjqvi_HT9dmF5TPVcw-Y,1944
61
+ boneio-0.3.0.dev6.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
62
+ boneio-0.3.0.dev6.dist-info/entry_points.txt,sha256=JX7gluDIkQ6MBlzzxGHMItnBjciiJ73tsXwYcazMW_U,47
63
+ boneio-0.3.0.dev6.dist-info/top_level.txt,sha256=ag9S5n1_KXZfyk9tN8R0YUDYbdA--e5a2w2FOD_yMdg,7
64
+ boneio-0.3.0.dev6.dist-info/RECORD,,