def __init__(self): # Setup temperature input, control, and history self.target_temp = self.get_target_temp() self.therm = thermometer.Thermometer() self.temp_history = TempHistory(local_config.temp_history_fpath) self.state = 'normal' self.last_state_change_time = time.time() # Setup outputs GPIO.setmode(local_config.pin_mode) self.fridge = outputs.OutputObject(local_config.fridge_pin) if local_config.led_pin is not None: self.flashingled = outputs.FlashingLED(local_config.led_pin) self.flashingled.start()
class Fermenter: def __init__(self): # Setup temperature input, control, and history self.target_temp = self.get_target_temp() self.therm = thermometer.Thermometer() self.temp_history = TempHistory(local_config.temp_history_fpath) self.state = 'normal' self.last_state_change_time = time.time() # Setup outputs GPIO.setmode(local_config.pin_mode) self.fridge = outputs.OutputObject(local_config.fridge_pin) if local_config.led_pin is not None: self.flashingled = outputs.FlashingLED(local_config.led_pin) self.flashingled.start() def __del__(self): self.fridge.turn_off() self.flashingled.stop() def get_target_temp(self): """ Reads target temp from file. Target temp file must contain either a single scalar or the word 'off'. """ for line in open('.target_temp'): temp = line.strip() if temp == 'off': return temp return float(temp) def run(self): # Starting main routing send_email('Starting fermenter at %gF' % self.target_temp) while True: self.regulate_and_record_temp() time.sleep(60) def regulate_and_record_temp(self): target_temp = self.get_target_temp() if target_temp != self.target_temp: temps = tuple(['off' if t == 'off' else '%gF' % t for t in (self.target_temp, target_temp)]) send_email('Changing temperature from %s to %s' % temps) self.target_temp = target_temp try: # try grabbing the current temp current_temp = self.therm.read_temp() stat_str = '%.2f (%g)' % (current_temp, self.target_temp) except: # send an email if you can't send_email("can't read the temperature") time.sleep(2) # deal with target_temp=off if self.target_temp == 'off': self.set_state('normal') if self.fridge.turn_off(): stat_str += ' on->off' else: stat_str += ' off' print stat_str self.temp_history.add_temp(time.time(), current_temp, -1, self.fridge.is_on()) return # regulate the temperature: if current_temp > self.target_temp + 1.0: if self.fridge.turn_on(): stat_str += ' off->on' self.set_state('normal') else: stat_str += ' on' if current_temp > self.target_temp + 2.0: stat_str += '\tWarning: High Temperatures' self.set_state('high_temp') elif current_temp < self.target_temp - 0.05: if self.fridge.turn_off(): stat_str += ' on->off' self.set_state('normal') else: stat_str += ' off' if current_temp < self.target_temp - 2.0: stat_str += '\tWarning: Low Temperatures' self.set_state('low_temp') else: if self.fridge.is_on(): stat_str += ' on' else: stat_str += ' off' print stat_str self.temp_history.add_temp(time.time(), current_temp, self.target_temp, self.fridge.is_on()) def set_state(self, state): assert state in ['high_temp', 'low_temp', 'normal'], state if self.state == state == 'normal': return elif self.state != state: self.last_state_change_time = time.time() self.state = state if state == 'normal': subject = 'Returned to Normal Operation' title = 'State: Normal Operation' event_times = None event_labels = None elif state == 'high_temp': subject = 'Warning: High Temp' title = 'State: High Temp' event_times = [self.last_state_change_time], event_labels = ['High Temp Begun'] else: subject = 'Warning: Low Temp' title = 'State: Low Temp' event_times = [self.last_state_change_time], event_labels = ['Low Temp Begun'] # Send updates roughly logarithmically in time for the first day, then once a day min_since_last_change = int(time.time() - self.last_state_change_time) / 60 times_to_contact = [0, 5, 10, 20] + range(30, 6*60, 30) + range(6*60, 24*60, 60) if min_since_last_change in times_to_contact or min_since_last_change % (24 * 60) == 0: # Send email with temp graph since state change and previous 12 hours start = self.last_state_change_time - 12 * 60 * 60 self.temp_history.plot_temp_history( start=start, stop=None, subject=subject, title=title, event_times=event_times, event_labels=event_labels, email=True)