# HG changeset patch # User darius # Date 1190984711 0 # Node ID 32a56dd33e42aa10d5dce24708754dc01a852dd4 # Parent 1af7c85d5a0e5f4f8c11b978a9db69636bfc2c5b - Reduce hystersis down to 0.5C - Properly track stale data (hopefully anyway :) - Check if the monitor thread has died (ie unexpected exception) - Re-work some variable names to be clearer (& add comments) diff -r 1af7c85d5a0e -r 32a56dd33e42 beermon.py --- a/beermon.py Mon Sep 24 13:34:47 2007 +0000 +++ b/beermon.py Fri Sep 28 13:05:11 2007 +0000 @@ -4,7 +4,7 @@ # Monitor & control fermenter temperature # v1.0 # -# $Id: beermon.py,v 1.4 2007/09/24 13:34:47 darius Exp $ +# $Id: beermon.py,v 1.5 2007/09/28 13:05:11 darius Exp $ # # Depends on: Python 2.3 (I think) # @@ -42,10 +42,14 @@ class ROMReadError(Exception): pass +class ThreadDied(Exception): + pass + class Control(): targetTemp = 18 - hysteresis = 1 + hysteresis = 0.5 pollInterval = 30 + staleDataTime = 30 def __init__(self, m, _log): self.m = m @@ -66,18 +70,23 @@ log.debug("=== Starting ===") log.debug("Fermenter Fridge Ambient State New State") while True: - if (self.m.lastUpdate == 0): - log.debug("Invalid data") + # Check if our monitor thread has died + if (not self.m.isAlive()): + raise ThreadDied, "Monitor thread has died" + + # Check for stale data + if (self.m.lastUpdate[self.m.fermenterId] + self.staleDataTime < time.time()): + log.debug("Stale data") self.cv.wait(self.pollInterval) self.m.setState('idle') continue + # Work out what state we should go into nextState = "-" - diff = self.m.temps[self.m.fermenterId] - self.targetTemp if (self.m.currState == 'idle'): # If we're idle then only heat or cool if the temperate difference is out of the - # hysteresis range + # hysteresis band if (abs(diff) > self.hysteresis): if (diff < 0 and self.m.minHeatOffTime + self.m.lastHeatOff < time.time()): nextState = 'heat' @@ -88,18 +97,21 @@ if (diff < 0 and self.m.minCoolOnTime + self.m.lastCoolOn < time.time()): nextState = 'idle' elif (self.m.currState == 'heat'): + # Ditto if (diff > 0 and self.m.minHeatOnTime + self.m.lastHeatOn < time.time()): nextState = 'idle' else: + # Not possible.. raise KeyError log.debug("%3.2f %3.2f %3.2f %s %s" % (self.m.temps[self.m.fermenterId], self.m.temps[self.m.fridgeId], self.m.temps[self.m.ambientId], self.m.currState, nextState)) + if (nextState != "-"): self.m.setState(nextState) - + self.cv.wait(self.pollInterval) @@ -124,9 +136,16 @@ minHeatOnTime = 60 minHeatOffTime = 60 + # Dictionary of sensor IDs & temperatures temps = {} - lastUpdate = 0 + # Dictionary of sensor IDs & epoch times + lastUpdate = {} + # List of all device IDs + devs = [] + # List of temperature sensor IDs + tempdevs = [] + # Lock to gate access to the comms commsLock = None @@ -145,7 +164,7 @@ self.p.timeout = 3 self.setspeed() self.devs = self.find1wire() - self.temps = filter(self.istemp, self.devs) + self.tempdevs = filter(self.istemp, self.devs) self.start() @@ -203,12 +222,14 @@ return False def updateTemps(self): - tmp = {} - for i in self.temps: - tmp[i] = float(self.readTemp(i)) - - self.temps = tmp - self.lastUpdate = time.time() + for i in self.tempdevs: + try: + self.temps[i] = float(self.readTemp(i)) + self.lastUpdate[i] = time.time() + except ROMReadError: + # Ignore this - just results in no update reflected by lastUpdate + pass + return(self.temps) def readTemp(self, id): @@ -309,7 +330,7 @@ log = initLog() log.debug("=== Initing ===") - log.debug("$Id: beermon.py,v 1.4 2007/09/24 13:34:47 darius Exp $") + log.debug("$Id: beermon.py,v 1.5 2007/09/28 13:05:11 darius Exp $") m = None exitCode = 0