/
temp_sensor.py
198 lines (160 loc) · 6 KB
/
temp_sensor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
import struct, time, logging, threading
import dbus
from bluepy.btle import Scanner, DefaultDelegate, Peripheral, BTLEException
from bluepy import btle
logger = logging.getLogger('heating')
class TempSensor(object):
_scanning_lock = threading.Lock()
def __init__(self, peripheral):
self.mac = peripheral.addr
self.sent_alert = False
self.amb_temp = None
self.temp_job_id = None
self.peripheral = Peripheral(peripheral)
self.characteristics = {}
def connect(self):
self.tag.connect()
def disconnect(self):
self.tag.disconnect()
def get_ambient_temp(self):
pass
def _write_uuid(self, uuid, data):
try:
if not uuid in self.characteristics:
self.characteristics[uuid] = self.peripheral.getCharacteristics(uuid=uuid)[0]
#If there's still no characteristic, error
if not uuid in self.characteristics:
raise Exception('UUID ' + str(uuid) + ' not found on device ' + self.mac)
self.characteristics[uuid].write(data)
except BTLEException as e:
logger.warn(self.mac + ' disconnected. Try to reconnect.')
raise DisconnectedException(e.message)
def _read_uuid(self, uuid):
try:
if not uuid in self.characteristics:
self.characteristics[uuid] = self.peripheral.getCharacteristics(uuid=uuid)[0]
#If there's still no characteristic, error
if not uuid in self.characteristics:
raise Exception('UUID ' + str(uuid) + ' not found on device ' + self.mac)
return self.characteristics[uuid].read()
except BTLEException as e:
logger.warn(self.mac + ' disconnected. Try to reconnect.')
raise DisconnectedException(e.message)
@staticmethod
def find_temp_sensors(sensors):
TempSensor._scanning_lock.acquire()
logger.debug('Scanning for devices')
scanner = Scanner().withDelegate(ScanDelegate())
try:
devices = scanner.scan(10.0)
if sensors is None:
sensors = {}
for device in devices:
if device.addr in sensors:
continue
name = ''
if device.getValueText(9):
name = device.getValueText(9)
elif device.getValueText(8):
name = device.getValueText(8)
logger.debug('Device name: ' + name)
if 'SensorTag' in name:
logger.info('Found SensorTag with address: ' + device.addr)
sensors[device.addr] = SensorTag(device)
elif 'MetaWear' in name:
logger.info('Found MetaWear with address: ' + device.addr)
sensors[device.addr] = MetaWear(device)
logger.debug('Finished scanning for devices')
TempSensor._scanning_lock.release()
if len(sensors) == 0:
raise NoTagsFoundException('No sensors found!')
except BTLEException as e:
scanner.stop()
logger.warn('Got exception ' + e.message)
TempSensor._scanning_lock.release()
return sensors
class ScanDelegate(DefaultDelegate):
def __init__(self):
DefaultDelegate.__init__(self)
def handleDiscovery(self, dev, isNewDev, isNewData):
pass
class SensorTag(TempSensor):
def __init__(self, peripheral):
TempSensor.__init__(self, peripheral)
def get_ambient_temp(self):
tAmb = 0
failures = 0
while tAmb == 0 and failures < 4:
try:
#Turn red LED on
self._write_uuid('f000aa65-0451-4000-b000-000000000000', b'\x01')
self._write_uuid('f000aa66-0451-4000-b000-000000000000', b'\x01')
#Turn temperature sensor on
self._write_uuid('f000aa02-0451-4000-b000-000000000000', b'\x01')
time.sleep(0.1)
#Turn red LED off
self._write_uuid('f000aa65-0451-4000-b000-000000000000', b'\x00')
self._write_uuid('f000aa66-0451-4000-b000-000000000000', b'\x00')
#Wait for reading
count = 0
while tAmb == 0 and count < 8:
count += 1
time.sleep(0.2)
result = self._read_uuid('f000aa01-0451-4000-b000-000000000000')
(rawVobj, rawTamb) = struct.unpack('<hh', result)
tAmb = rawTamb / 128.0
#Turn temperature sensor off
self._write_uuid('f000aa02-0451-4000-b000-000000000000', b'\x00')
if count == 8:
failures += 1
else:
failures = 0
except DisconnectedException as e:
raise NoTemperatureException(e.message)
if tAmb == 0:
self.amb_temp = None
raise NoTemperatureException('Could not get temperature from ' + self.mac)
logger.info('Got temperature ' + str(tAmb) + ' from ' + self.mac)
self.amb_temp = tAmb
class MetaWear(TempSensor):
def __init__(self, peripheral):
TempSensor.__init__(self, peripheral)
def get_ambient_temp(self):
self.connect()
tAmb = 0
failures = 0
while tAmb == 0 and failures < 4:
try:
#Turn red LED on
self._write_uuid('326a9001-85cb-9195-d9dd-464cfbbae75a', b'\x02\x03\x01\x02\x1f\x1f\x00\x00\xd0\x07\x00\x00\xd0\x07\x00\x00\xff')
self._write_uuid('326a9001-85cb-9195-d9dd-464cfbbae75a', b'\x02\x01\x02')
#Turn temperature sensor on
self._write_uuid('326a9001-85cb-9195-d9dd-464cfbbae75a', b'\x04\x81\x01')
time.sleep(0.1)
#Turn red LED off
self._write_uuid('326a9001-85cb-9195-d9dd-464cfbbae75a', b'\x02\x02\x01')
#Wait for reading
count = 0
while tAmb == 0 and count < 8:
count += 1
time.sleep(0.2)
result = self._read_uuid('326a9006-85cb-9195-d9dd-464cfbbae75a')
(rawTamb,) = struct.unpack('<xxxh', str(result))
tAmb = rawTamb / 8.0
if count == 8:
failures += 1
else:
failures = 0
except DisconnectedException as e:
raise NoTemperatureException(e.message)
if tAmb == 0:
self.amb_temp = None
raise NoTemperatureException('Could not get temperature from ' + self.mac)
logger.info('Got temperature ' + str(tAmb) + ' from ' + self.mac)
self.amb_temp = tAmb
class NoTagsFoundException(Exception):
pass
class DisconnectedException(Exception):
pass
class NoTemperatureException(Exception):
pass