comparison py/fridge.py @ 144:482d7852b511

a bit more, and some tests
author Matt Johnston <matt@ucc.asn.au>
date Mon, 26 Nov 2012 23:21:03 +0800
parents 0895f5ad7731
children 6517ddee3187
comparison
equal deleted inserted replaced
143:0895f5ad7731 144:482d7852b511
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 from utils import L,W,E 2 from utils import L,W,E,EX
3 import config 3 import config
4 import gevent
4 5
5 class Fridge(object): 6 class Fridge(gevent.Greenlet):
6 7
7 OVERSHOOT_MAX_DIV = 1800.0 # 30 mins 8 OVERSHOOT_MAX_DIV = 1800.0 # 30 mins
8 FRIDGE_AIR_MIN_RANGE = 4 # ºC 9 FRIDGE_AIR_MIN_RANGE = 4 # ºC
9 FRIDGE_AIR_MAX_RANGE = 4 10 FRIDGE_AIR_MAX_RANGE = 4
10 11
11 def __init__(self): 12 def __init__(self, server):
13 gevent.Greenlet.__init__(self)
14 self.server = server
12 self.setup_gpio() 15 self.setup_gpio()
13 self.wort_valid_clock = 0 16 self.wort_valid_clock = 0
14 self.fridge_on_clock = 0 17 self.fridge_on_clock = 0
15 self.fridge_off_clock = 0 18 self.fridge_off_clock = 0
16 19
43 if buf != '1': 46 if buf != '1':
44 E("Bad value read from gpio '%s': '%s'" 47 E("Bad value read from gpio '%s': '%s'"
45 % (self.value_file.name, buf)) 48 % (self.value_file.name, buf))
46 return True 49 return True
47 50
48 def run(self, server): 51 # greenlet subclassed
49 52 def _run(self):
50 while True: 53 while True:
51 self.do(server) 54 self.do()
52 gevent.sleep(config.FRIDGE_SLEEP) 55 gevent.sleep(config.FRIDGE_SLEEP)
53 56
54 def do(self, server): 57 def do(self)
55 """ this is the main fridge control logic """ 58 """ this is the main fridge control logic """
56 wort, fridge, ambient = server.current_temps() 59 wort, fridge = self.server.current_temps()
57 60
58 fridge_min = params.fridge_setpoint - self.FRIDGE_AIR_MIN_RANGE 61 fridge_min = params.fridge_setpoint - self.FRIDGE_AIR_MIN_RANGE
59 fridge_max = params.fridge_setpoint + self.FRIDGE_AIR_MAX_RANGE 62 fridge_max = params.fridge_setpoint + self.FRIDGE_AIR_MAX_RANGE
60 63
61 wort_max = params.fridge_setpoint + params.fridge_difference 64 wort_max = params.fridge_setpoint + params.fridge_difference
62 65
63 off_time = server.now() - self.fridge_off_clock 66 off_time = self.server.now() - self.fridge_off_clock
64 67
65 if off_time < config.FRIDGE_DELAY: 68 if off_time < config.FRIDGE_DELAY:
66 L("fridge skipping, too early") 69 L("fridge skipping, too early")
67 return 70 return
68 71
69 # handle broken wort sensor 72 # handle broken wort sensor
70 if wort is not None: 73 if wort is not None:
71 self.wort_valid_clock = server.now() 74 self.wort_valid_clock = self.server.now()
72 else: 75 else:
73 W("Invalid wort sensor") 76 W("Invalid wort sensor")
74 invalid_time = server.now() - self.wort_valid_clock 77 invalid_time = self.server.now() - self.wort_valid_clock
75 if invalid_time < config.FRIDGE_WORT_INVALID_TIME: 78 if invalid_time < config.FRIDGE_WORT_INVALID_TIME:
76 W("Has only been invalid for %d, waiting" % invalid_time) 79 W("Has only been invalid for %d, waiting" % invalid_time)
77 return 80 return
78 81
79 if fridge is None: 82 if fridge is None:
80 W("Invalid fridge sensor") 83 W("Invalid fridge sensor")
81 84
82 if self.is_on(): 85 if self.is_on():
83 turn_off = False 86 turn_off = False
84 on_time = server.now() - self.fridge_on_clock 87 on_time = self.server.now() - self.fridge_on_clock
85 88
86 overshoot = 0 89 overshoot = 0
87 if on_time > params.overshoot_delay: 90 if on_time > params.overshoot_delay:
88 overshoot = params.overshoot_factor \ 91 overshoot = params.overshoot_factor \
89 * min(self.OVERSHOOT_MAX_DIV, on_time) \ 92 * min(self.OVERSHOOT_MAX_DIV, on_time) \
94 if (wort - overshoot) < params.fridge_setpoint: 97 if (wort - overshoot) < params.fridge_setpoint:
95 L("wort has cooled enough") 98 L("wort has cooled enough")
96 turn_off = True 99 turn_off = True
97 else: 100 else:
98 # wort sensor is broken 101 # wort sensor is broken
99 if fridge is not None and last_fridge < fridge_min: 102 if fridge is not None and fridge < fridge_min:
100 W("fridge off fallback") 103 W("fridge off fallback")
101 turn_off = True 104 turn_off = True
102 105
103 if turn_off: 106 if turn_off:
104 L("Turning fridge off") 107 L("Turning fridge off")
105 self.off() 108 self.off()
106 self.fridge_off_clock = server.now() 109 self.fridge_off_clock = self.server.now()
107 110
108 else: 111 else:
109 # fridge is off 112 # fridge is off
110 turn_on = False 113 turn_on = False
111 if wort is not None: 114 if wort is not None:
119 turn_on = True 122 turn_on = True
120 123
121 if turn_on: 124 if turn_on:
122 L("Turning fridge on") 125 L("Turning fridge on")
123 self.on() 126 self.on()
124 fridge_on_clock = server.now() 127 fridge_on_clock = self.server.now()