2
2
from glob import glob
3
3
import logging
4
4
import os
5
- import time
6
5
6
+ from pi1wire import (
7
+ InvalidCRCException ,
8
+ NotFoundSensorException ,
9
+ Pi1Wire ,
10
+ UnsupportResponseException ,
11
+ )
7
12
from pyownet import protocol
8
13
import voluptuous as vol
9
14
23
28
from .const import (
24
29
CONF_MOUNT_DIR ,
25
30
CONF_NAMES ,
31
+ CONF_TYPE_OWFS ,
32
+ CONF_TYPE_OWSERVER ,
33
+ CONF_TYPE_SYSBUS ,
26
34
DEFAULT_OWSERVER_PORT ,
27
35
DEFAULT_SYSBUS_MOUNT_DIR ,
28
36
)
54
62
"EF" : {"HobbyBoard" : "special" },
55
63
}
56
64
65
+ DEVICE_SUPPORT_SYSBUS = ["10" , "22" , "28" , "3B" , "42" ]
66
+
57
67
# EF sensors are usually hobbyboards specialized sensors.
58
68
# These can only be read by OWFS. Currently this driver only supports them
59
69
# via owserver (network protocol)
@@ -120,18 +130,32 @@ def hb_info_from_type(dev_type="std"):
120
130
121
131
def setup_platform (hass , config , add_entities , discovery_info = None ):
122
132
"""Set up 1-Wire platform."""
133
+ entities = get_entities (config )
134
+ add_entities (entities , True )
135
+
136
+
137
+ def get_entities (config ):
138
+ """Get a list of entities."""
123
139
base_dir = config [CONF_MOUNT_DIR ]
124
- owport = config [CONF_PORT ]
125
140
owhost = config .get (CONF_HOST )
141
+ owport = config [CONF_PORT ]
126
142
127
- devs = []
143
+ # Ensure type is configured
144
+ if owhost :
145
+ conf_type = CONF_TYPE_OWSERVER
146
+ elif base_dir == DEFAULT_SYSBUS_MOUNT_DIR :
147
+ conf_type = CONF_TYPE_SYSBUS
148
+ else :
149
+ conf_type = CONF_TYPE_OWFS
150
+
151
+ entities = []
128
152
device_names = {}
129
153
if CONF_NAMES in config :
130
154
if isinstance (config [CONF_NAMES ], dict ):
131
155
device_names = config [CONF_NAMES ]
132
156
133
157
# We have an owserver on a remote(or local) host/port
134
- if owhost :
158
+ if conf_type == CONF_TYPE_OWSERVER :
135
159
_LOGGER .debug ("Initializing using %s:%s" , owhost , owport )
136
160
try :
137
161
owproxy = protocol .proxy (host = owhost , port = owport )
@@ -166,7 +190,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
166
190
sensor_key = f"wetness_{ s_id } "
167
191
sensor_id = os .path .split (os .path .split (device )[0 ])[1 ]
168
192
device_file = os .path .join (os .path .split (device )[0 ], sensor_value )
169
- devs .append (
193
+ entities .append (
170
194
OneWireProxy (
171
195
device_names .get (sensor_id , sensor_id ),
172
196
device_file ,
@@ -176,19 +200,34 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
176
200
)
177
201
178
202
# We have a raw GPIO ow sensor on a Pi
179
- elif base_dir == DEFAULT_SYSBUS_MOUNT_DIR :
180
- _LOGGER .debug ("Initializing using SysBus %s" , base_dir )
181
- for device_family in DEVICE_SENSORS :
182
- for device_folder in glob (os .path .join (base_dir , f"{ device_family } [.-]*" )):
183
- sensor_id = os .path .split (device_folder )[1 ]
184
- device_file = os .path .join (device_folder , "w1_slave" )
185
- devs .append (
186
- OneWireDirect (
187
- device_names .get (sensor_id , sensor_id ),
188
- device_file ,
189
- "temperature" ,
190
- )
203
+ elif conf_type == CONF_TYPE_SYSBUS :
204
+ _LOGGER .debug ("Initializing using SysBus" )
205
+ for p1sensor in Pi1Wire ().find_all_sensors ():
206
+ family = p1sensor .mac_address [:2 ]
207
+ sensor_id = f"{ family } -{ p1sensor .mac_address [2 :]} "
208
+ if family not in DEVICE_SUPPORT_SYSBUS :
209
+ _LOGGER .warning (
210
+ "Ignoring unknown family (%s) of sensor found for device: %s" ,
211
+ family ,
212
+ sensor_id ,
191
213
)
214
+ continue
215
+
216
+ device_file = f"/sys/bus/w1/devices/{ sensor_id } /w1_slave"
217
+ entities .append (
218
+ OneWireDirect (
219
+ device_names .get (sensor_id , sensor_id ),
220
+ device_file ,
221
+ "temperature" ,
222
+ p1sensor ,
223
+ )
224
+ )
225
+ if not entities :
226
+ _LOGGER .error (
227
+ "No onewire sensor found. Check if dtoverlay=w1-gpio "
228
+ "is in your /boot/config.txt. "
229
+ "Check the mount_dir parameter if it's defined"
230
+ )
192
231
193
232
# We have an owfs mounted
194
233
else :
@@ -204,23 +243,15 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
204
243
device_file = os .path .join (
205
244
os .path .split (family_file_path )[0 ], sensor_value
206
245
)
207
- devs .append (
246
+ entities .append (
208
247
OneWireOWFS (
209
248
device_names .get (sensor_id , sensor_id ),
210
249
device_file ,
211
250
sensor_key ,
212
251
)
213
252
)
214
253
215
- if devs == []:
216
- _LOGGER .error (
217
- "No onewire sensor found. Check if dtoverlay=w1-gpio "
218
- "is in your /boot/config.txt. "
219
- "Check the mount_dir parameter if it's defined"
220
- )
221
- return
222
-
223
- add_entities (devs , True )
254
+ return entities
224
255
225
256
226
257
class OneWire (Entity ):
@@ -234,12 +265,6 @@ def __init__(self, name, device_file, sensor_type):
234
265
self ._state = None
235
266
self ._value_raw = None
236
267
237
- def _read_value_raw (self ):
238
- """Read the value as it is returned by the sensor."""
239
- with open (self ._device_file ) as ds_device_file :
240
- lines = ds_device_file .readlines ()
241
- return lines
242
-
243
268
@property
244
269
def name (self ):
245
270
"""Return the name of the sensor."""
@@ -300,24 +325,36 @@ def update(self):
300
325
class OneWireDirect (OneWire ):
301
326
"""Implementation of a 1-Wire sensor directly connected to RPI GPIO."""
302
327
328
+ def __init__ (self , name , device_file , sensor_type , owsensor ):
329
+ """Initialize the sensor."""
330
+ super ().__init__ (name , device_file , sensor_type )
331
+ self ._owsensor = owsensor
332
+
303
333
def update (self ):
304
334
"""Get the latest data from the device."""
305
335
value = None
306
- lines = self ._read_value_raw ()
307
- while lines [0 ].strip ()[- 3 :] != "YES" :
308
- time .sleep (0.2 )
309
- lines = self ._read_value_raw ()
310
- equals_pos = lines [1 ].find ("t=" )
311
- if equals_pos != - 1 :
312
- value_string = lines [1 ][equals_pos + 2 :]
313
- value = round (float (value_string ) / 1000.0 , 1 )
314
- self ._value_raw = float (value_string )
336
+ try :
337
+ self ._value_raw = self ._owsensor .get_temperature ()
338
+ value = round (float (self ._value_raw ), 1 )
339
+ except (
340
+ FileNotFoundError ,
341
+ InvalidCRCException ,
342
+ NotFoundSensorException ,
343
+ UnsupportResponseException ,
344
+ ) as ex :
345
+ _LOGGER .warning ("Cannot read from sensor %s: %s" , self ._device_file , ex )
315
346
self ._state = value
316
347
317
348
318
349
class OneWireOWFS (OneWire ):
319
350
"""Implementation of a 1-Wire sensor through owfs."""
320
351
352
+ def _read_value_raw (self ):
353
+ """Read the value as it is returned by the sensor."""
354
+ with open (self ._device_file ) as ds_device_file :
355
+ lines = ds_device_file .readlines ()
356
+ return lines
357
+
321
358
def update (self ):
322
359
"""Get the latest data from the device."""
323
360
value = None
0 commit comments