| 
									
										
										
										
											2014-10-16 06:31:49 +00:00
										 |  |  | import re | 
					
						
							| 
									
										
										
										
											2014-10-16 07:46:04 +00:00
										 |  |  | import time | 
					
						
							| 
									
										
										
										
											2014-10-23 04:46:35 +00:00
										 |  |  | import random | 
					
						
							| 
									
										
										
										
											2014-10-16 06:18:47 +00:00
										 |  |  | import datetime | 
					
						
							| 
									
										
										
										
											2014-10-16 07:46:04 +00:00
										 |  |  | import logging | 
					
						
							|  |  |  | import threading | 
					
						
							| 
									
										
										
										
											2014-10-21 21:21:43 +00:00
										 |  |  | from collections import deque, namedtuple | 
					
						
							| 
									
										
										
										
											2014-11-30 04:51:32 +00:00
										 |  |  | from math import isnan | 
					
						
							| 
									
										
										
										
											2014-10-16 06:18:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 07:46:04 +00:00
										 |  |  | logger = logging.getLogger("thermo") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 06:18:47 +00:00
										 |  |  | def temp_to_cone(temp): | 
					
						
							|  |  |  |     """Convert the current temperature to cone value using linear interpolation""" | 
					
						
							|  |  |  |     cones = [600,614,635,683,717,747,792,804,838,852,884,894,900,923,955,984,999,1046,1060,1101,1120,1137,1154,1162,1168,1186,1196,1222,1240,1263,1280,1305,1315,1326,1346] | 
					
						
							|  |  |  |     names = [str(i).replace('-', '0') for i in range(-22,0)] + [str(i) for i in range(1, 14)] | 
					
						
							|  |  |  |     for i in range(len(cones)-1): | 
					
						
							|  |  |  |         low, high = cones[i], cones[i+1] | 
					
						
							|  |  |  |         if low <= temp < high: | 
					
						
							|  |  |  |             frac = (temp - low) / float(high - low) | 
					
						
							|  |  |  |             return names[i]+'.%d'%int(frac*10) | 
					
						
							|  |  |  |     return "13+" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-21 21:21:43 +00:00
										 |  |  | tempsample = namedtuple("tempsample", ['time', 'temp']) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-22 19:11:46 +00:00
										 |  |  | class MAX31850(object): | 
					
						
							|  |  |  |     def __init__(self, name="3b-000000182b57", smooth_window=4): | 
					
						
							| 
									
										
										
										
											2014-10-16 06:18:47 +00:00
										 |  |  |         self.device = "/sys/bus/w1/devices/%s/w1_slave"%name | 
					
						
							| 
									
										
										
										
											2014-10-23 04:46:35 +00:00
										 |  |  |         self.history = deque(maxlen=smooth_window) | 
					
						
							| 
									
										
										
										
											2014-10-22 19:11:46 +00:00
										 |  |  |         self.last = None | 
					
						
							| 
									
										
										
										
											2014-10-16 06:18:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _read_temp(self): | 
					
						
							|  |  |  |         with open(self.device, 'r') as f: | 
					
						
							|  |  |  |             lines = f.readlines() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         while lines[0].strip()[-3:] != 'YES': | 
					
						
							|  |  |  |             time.sleep(0.2) | 
					
						
							|  |  |  |             with open(self.device, 'r') as f: | 
					
						
							|  |  |  |                 lines = f.readlines() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         match = re.match(r'^[0-9a-f\s]{27}t=(\d+)$', lines[1]) | 
					
						
							|  |  |  |         if match is not None: | 
					
						
							|  |  |  |             return float(match.group(1)) / 1000.0 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-22 19:11:46 +00:00
										 |  |  |     def get(self): | 
					
						
							|  |  |  |         """Blocking call to retrieve latest temperature sample""" | 
					
						
							| 
									
										
										
										
											2014-10-23 04:46:35 +00:00
										 |  |  |         self.history.append(self._read_temp()) | 
					
						
							| 
									
										
										
										
											2014-10-22 19:11:46 +00:00
										 |  |  |         self.last = time.time() | 
					
						
							|  |  |  |         return self.temperature | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @property | 
					
						
							|  |  |  |     def temperature(self): | 
					
						
							|  |  |  |         if self.last is None or time.time() - self.last > 5: | 
					
						
							|  |  |  |             return self.get() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return tempsample(self.last, sum(self.history) / float(len(self.history))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Simulate(object): | 
					
						
							| 
									
										
										
										
											2014-11-30 04:27:48 +00:00
										 |  |  |     def __init__(self, regulator, smooth_window=120): | 
					
						
							| 
									
										
										
										
											2014-10-22 19:11:46 +00:00
										 |  |  |         self.regulator = regulator | 
					
						
							| 
									
										
										
										
											2014-10-23 04:46:35 +00:00
										 |  |  |         self.history = deque(maxlen=smooth_window) | 
					
						
							|  |  |  |         self.last = None | 
					
						
							| 
									
										
										
										
											2014-10-22 19:11:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-23 04:46:35 +00:00
										 |  |  |     def _read_temp(self): | 
					
						
							| 
									
										
										
										
											2014-11-29 17:04:33 +00:00
										 |  |  |         time.sleep(.25) | 
					
						
							| 
									
										
										
										
											2014-10-23 04:46:35 +00:00
										 |  |  |         return max([self.regulator.output, 0]) * 1000. + 15+random.gauss(0,.2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get(self): | 
					
						
							|  |  |  |         self.history.append(self._read_temp()) | 
					
						
							|  |  |  |         self.last = time.time() | 
					
						
							| 
									
										
										
										
											2014-10-22 19:11:46 +00:00
										 |  |  |         return self.temperature | 
					
						
							| 
									
										
										
										
											2014-10-16 06:44:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 06:18:47 +00:00
										 |  |  |     @property | 
					
						
							|  |  |  |     def temperature(self): | 
					
						
							| 
									
										
										
										
											2014-10-23 04:46:35 +00:00
										 |  |  |         if self.last is None or time.time() - self.last > 5: | 
					
						
							|  |  |  |             return self.get() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return tempsample(self.last, sum(self.history) / float(len(self.history))) | 
					
						
							| 
									
										
										
										
											2014-10-22 19:11:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-29 17:04:33 +00:00
										 |  |  | class Breakout(object): | 
					
						
							| 
									
										
										
										
											2014-11-30 04:58:58 +00:00
										 |  |  |     def __init__(self, addr, smooth_window=16): | 
					
						
							| 
									
										
										
										
											2014-11-29 17:04:33 +00:00
										 |  |  |         import breakout | 
					
						
							|  |  |  |         self.device = breakout.Breakout(addr) | 
					
						
							| 
									
										
										
										
											2014-11-30 04:59:43 +00:00
										 |  |  |         self.history = deque(maxlen=smooth_window) | 
					
						
							| 
									
										
										
										
											2014-11-30 04:58:58 +00:00
										 |  |  |         self.last = None | 
					
						
							| 
									
										
										
										
											2014-11-29 17:04:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def get(self): | 
					
						
							|  |  |  |         time.sleep(.25) | 
					
						
							| 
									
										
										
										
											2014-11-30 04:58:58 +00:00
										 |  |  |         temp = self.device.temperature | 
					
						
							| 
									
										
										
										
											2014-12-17 06:34:47 +00:00
										 |  |  |         if not isnan(temp) and len(self.history) < 1 or abs(temp - self.history[-1]) < 15 or (time.time() - self.last) > 5: | 
					
						
							|  |  |  |             self.last = time.time() | 
					
						
							| 
									
										
										
										
											2014-11-30 04:58:58 +00:00
										 |  |  |             self.history.append(temp) | 
					
						
							|  |  |  |         return self.temperature | 
					
						
							| 
									
										
										
										
											2014-11-29 17:04:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @property | 
					
						
							|  |  |  |     def temperature(self): | 
					
						
							| 
									
										
										
										
											2014-11-30 04:58:58 +00:00
										 |  |  |         if self.last is None or time.time() - self.last > 5: | 
					
						
							|  |  |  |             return self.get() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return tempsample(self.last, sum(self.history) / float(len(self.history))) | 
					
						
							| 
									
										
										
										
											2014-11-29 17:04:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-22 19:11:46 +00:00
										 |  |  | class Monitor(threading.Thread): | 
					
						
							|  |  |  |     def __init__(self, cls=MAX31850, **kwargs): | 
					
						
							|  |  |  |         self.therm = cls(**kwargs) | 
					
						
							|  |  |  |         self.running = True | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         from Adafruit_alphanumeric import AlphaScroller | 
					
						
							|  |  |  |         self.display = AlphaScroller(interval=.4) | 
					
						
							|  |  |  |         self.display.start() | 
					
						
							|  |  |  |         self.display.hide() | 
					
						
							| 
									
										
										
										
											2014-10-16 06:18:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def run(self): | 
					
						
							| 
									
										
										
										
											2014-10-16 07:08:05 +00:00
										 |  |  |         while self.running: | 
					
						
							| 
									
										
										
										
											2014-10-22 19:11:46 +00:00
										 |  |  |             _, temp = self.therm.get() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if temp > 50: | 
					
						
							|  |  |  |                 if not self.display.shown: | 
					
						
							|  |  |  |                     self.display.show() | 
					
						
							|  |  |  |                 fahr = temp * 9. / 5. + 32. | 
					
						
							|  |  |  |                 text = list('%0.0f'%temp) + ['degree'] + list('C  %0.0f'%fahr)+['degree'] + list("F") | 
					
						
							|  |  |  |                 if 600 <= temp: | 
					
						
							|  |  |  |                     text += [' ', ' ', 'cone']+list(temp_to_cone(temp)) | 
					
						
							|  |  |  |                 self.display.set_text(text, reset=False) | 
					
						
							|  |  |  |             elif self.display.shown: | 
					
						
							|  |  |  |                 self.display.hide() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def stop(self): | 
					
						
							|  |  |  |         self.running = False | 
					
						
							|  |  |  |         self.display.stop() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 06:31:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							| 
									
										
										
										
											2014-10-22 19:11:46 +00:00
										 |  |  |     monitor = Monitor() | 
					
						
							| 
									
										
										
										
											2014-11-29 18:59:24 +00:00
										 |  |  |     monitor.start() |