class Light(object): def __init__(self, logger=None): self._logger = logger if self._logger == None: self._logger = Logger('Light', Logger.INFO, "/home/pi/MVP/logs/obsv.log") self._logger.debug("Initialize RF Light") self._rf = RF_Sender(self._logger) self._persist = Persistence(self._logger) def __del__(self): self._rf.cleanup() def set_on(self, test=False): "Check state and turn on if needed" self._rf.set_on(lightPin, ) self.log_state("On", test) self._logger.debug('Light turned ON') def set_off(self, test=False): '''Check state and turn off if needed''' self._rf.set_off(lightPin) self.log_state("Off", test) self._logger.debug('Light turned Off') def log_state(self, value, test=False): """ Create Environment Observation """ status_qualifier = 'Success' if test: status_qualifier = 'Test' self._persist.save([ 'State_Change', '', 'Top', 'Lights', 'State', value, 'Boolean', 'Light', status_qualifier, '' ]) def check(self): env = Environ(self._logger) if env._state: self.set_on(test) else: self.set_off(test)
class Pump(object): def __init__(self, logger=None): self._rf = RF_Sender() self._logger = logger if self._logger == None: self._logger = Logger('Pump', Logger.INFO, "/home/pi/MVP/logs/obsv.log") self._persist = Persistence(self._logger) def __del__(self): ''' Don't call GPIO.cleanup() as need to leave pin state as is ''' pass def on(self, test=False): "Check state and turn on if needed" self._rf.set_on(pumpPin, ) self.log_state("On", test) self._logger.debug('Pump turned ON') def off(self, test=False): '''Check state and turn off if needed''' self._rf.set_off(pumpPin) self.log_state("Off", test) self._logger.debug('Pump turned Off') def log_state(self, value, test=False): """ Create Environment Observation """ status_qualifier = 'Success' if test: status_qualifier = 'Test' self._persist.save([ 'State_Change', '', 'Reservoir', 'Pump', 'State', value, 'Pump', 'state', status_qualifier, '' ])
class Fan(object): """Code associated with the exhaust fan""" ON = 1 OFF = 0 target_temp = 0 def __init__(self, logger=None): self._logger = logger if logger == None: self._logger = Logger("Relay", Logger.INFO) self._logger.debug("initialize Fan object") self._relay = Relay(self._logger) self.fan_relay = FAN_PIN self._persist = Persistence(self._logger) # flag for testing self._test = False def set(self, state): """Set the fan to state Args: state: condition from other source Returns: None Raises: None """ self._logger.debug("In set_state") prior = self._relay.get_state(self.fan_relay) self._relay.set_state(self.fan_relay, state) current = self._relay.get_state(self.fan_relay) if prior != current: self.log_state(state) def set_fan_on(self): """Turn the fan on Args: None Returns: None Raises: None """ self._logger.debug("In set_fan_on") self.set(ON, test) def set_fan_off(self): """Turn the fan off Args: None Returns: None Raises: None """ self._logger.debug("In set_fan_off") self.set(OFF, test) def log_state(self, value): """Send state change to database Args: value: state change (numeric value) test: flag for testing Returns: None Raises: None """ state = 'Off' if value > 0: state = 'On' status_qualifier = 'Success' if self._test: status_qualifier = 'Test' self._persist.save([ 'State_Change', '', 'Side', 'Fan', 'State', state, 'Boolean', 'Fan', status_qualifier, '' ]) self._logger.debug("{}, {:1}, {} {}".format( "Fan State Change: Value: ", value, " Status Qualifier: ", status_qualifier)) def getState(self): return self._relay.get_state(self.fan_relay)
class Reservoir: FULL = 0 EMPTY = 1 OK = 2 vol_per_mm = 0.3785 # estimate 1 gal per 10 mm, this is reservoir specific vol_per_sec = 0.3785 # estimate 100 ml per sec, this is reservoir specific def __init__(self): '''Get distances for determining reservoir levels''' self.res = {'full': full_ec, 'empty': empty_ec, 'timeout': timeout} self._activity_type = 'Agronomic_Activity' self._logger = Logger('LogReservoir', Logger.INFO) self._persist = Persistence(self._logger) self._logger.detail("Reservoir Initialized") # flag for testing self._test = False def getStatus(self): "Logic for calling the reservoir full" self._logger.detail("In getStatus") ec = self.getEC() if ec <= full_ec: self._logger.debug("{}, {}, {:10.1f}".format( "Reservoir Full", EC, ec)) return Reservoir.FULL, ec elif ec >= empty_ec: self._logger.debug("{}, {}, {:10.1f}".format( "Reservoir Empty", EC, ec)) return Reservoir.EMPTY, ec else: self._logger.debug("{}, {}, {:10.1f}".format( "Reservoir not Empty", EC, ec)) return Reservoir.OK, ec def isFull(self): self._logger.detail("In isFull") status, ec = self.getStatus() if status == Reservoir.FULL: return True else: return False def getEC(self): '''Get EC reading''' self._logger.detail("In getEC") snsr = EC(self._logger) return snsr.getEC() def fill(self, test=False): ''' Routine to control re-filling of the reservoir''' self._logger.detail("{}".format("In Fill")) start_ec = self.getEC() start_t = time.time() pump = Pump() pump.on() # Loop till filled or times out while (not self.isFull()) and self.isFilling(start_t): self._logger.detail("{}".format("In Fill Loop")) self._logger.detail("{}".format("Exit Fill Loop, close solenoid")) # Close valve pump.off() # Calculate amount filled stop_t = time.time() stop_ec = self.getEC() dif_t = stop_t - start_t volume = dif_t * self.vol_per_sec self._logger.detail("{}".format("Exit Fill")) return volume def isFilling(self, start_time, test=False): '''Check that actually filling: the distance is actually changing''' start_ec = self.getEC() self._logger.detail("{} {}".format("Filling, Start EC:", start_ec)) time.sleep(fill_time) # Check for level change first, else will never get to this logic till timeout end_ec = self.getEC() change = start_ec - end_ec if end_ec < start_ec: # need to see at least a 5mm change self._logger.detail("{} {} {} {} {} {}".format( "Still Filling, change:", change, "Start", start_ec, "End", end_ec)) return True else: self._logger.detail("{} {} {} {} {} {}".format( "Not Filling, no change:", change, "Start", start_ec, "End", end_ec)) return False # Check for timeout stop_time = time.time() if stop_time - start_time > self.res['timeout']: self._logger.detail("{}".format("Timeout")) return False else: return True def checkReservoir(self): '''Check condition of reservoir and fill if necessary''' self._logger.detail("{}".format("Check Reservoir")) status, ec = self.getStatus() self._logger.debug("{} {} {} {}".format("Status:", status, "EC", ec)) # Is full, log state if status == Reservoir.FULL: self._logger.detail("{}".format("Status: Full")) self._logger.info("{} {} {} {}".format("EC:", ec, "Full level:", self.res['full'], "Empty:", self.res['empty'])) return True else: # Needs filling self._logger.debug("{}".format("Status: Filling")) volume = self.fill() if volume > 0: # Filled, log volume self.logState(volume, 'Success') return True else: # Failure self._logger.debug("{}".format("Status: Failure")) level = 'Empty' if status == '2': level = 'Ok' self._logger.error("{}".format("Failure to fill Reservoir")) self._logger.error("{} {} {} {}".format( "EC:", ec, "Full level:", self.res['full'], "Empty:", self.res['empty'])) self.logState(volume, 'Failure') return False def logState(self, value, status_qualifier): if self._test: status_qualifier = 'Test' txt = { 'Volume': value, 'full_level': self.res['full'], 'empty_level': self.res['empty'], 'status': 'Full' } self._persist.save([ 'State_Change', '', 'Nutrient', 'Reservoir', 'Volume', value, 'Liter', 'Solenoid', status_qualifier, '' ]) self._logger.info(txt)
class LogSensorsExtra(object): def __init__(self, lvl=Logger.INFO): """Record optional sensor data Args: lvl: Logging level Returns: None Raises: None """ self._logger = Logger("LogSensor-Extra", lvl, file="/home/pi/MVP/logs/obsv.log") self._activity_type = "Environment_Observation" self._test = False self._persist = Persistence(self._logger) def getOneWire(self, test=False): """Loop OneWire temperature sensors Assumes there are four Args: test: flag for testing Returns: None Raises: None """ self._logger.debug("In getOneWire") from OneWireTemp import OneWireTemp for sensor in OneWireTemp.one_temp: self.logOneWire(sensor, OneWireTemp.one_temp[sensor]) def logOneWire(self, sensor, name, test=False): """Record OneWire temperature sensor Args: sensor: number of the sensor name: name of the sensor test: flag for testing Returns: None Raises: None """ self._logger.debug("In logOneWire") from OneWireTemp import OneWireTemp try: ow = OneWireTemp() temp = ow.getTempC(sensor) status_qualifier = 'Success' if self._test: status_qualifier = 'Test' rec = [ self._activity_type, '', name, 'Air', 'Temperature', "{:10.1f}".format(temp), 'Centigrade', 'DS18B20-' + str(sensor), status_qualifier, '' ] self._persist.save(rec) self._logger.info("{}, {}, {:10.1f}".format( name, status_qualifier, temp)) except Exception as e: status_qualifier = 'Failure' if test: status_qualifier = 'Test' rec = [ self._activity_type, '', name, 'Air', 'Temperature', '', 'Centigrade', 'DS18B20-' + str(sensor), status_qualifier, str(e) ] self._persist.save(rec) self._logger.error("{}, {}, {}".format(name, status_qualifier, e)) def getLux(self, test=False): """Record LUX sensor (TSL2561) Args: test: flag for testing Returns: None Raises: None """ from TSL2561 import TSL2561 lx = TSL2561() self._logger.info("TSL2561 - LUX") try: lux = lx.getLux() status_qualifier = 'Success' if test: status_qualifier = 'Test' rec = [ self._activity_type, '', 'Canopy', 'Light', 'LUX', "{:3.1f}".format(lux), 'lux', 'TSL2561', status_qualifier, '' ] self._persist.save(rec) self._logger.info("{}, {}, {:10.1f}".format( "LUX", status_qualifier, lux)) except Exception as e: status_qualifier = 'Failure' if test: status_qualifier = 'Test' rec = [ self._activity_type, '', 'Canopy', 'Light', 'LUX', '', 'lux', 'TSL2561', status_qualifier, str(e) ] self._persist.save(rec) self._logger.error("{}, {}, {}".format("LUX", status_qualifier, e)) def getEC(self, test=False): """Record EC sensor (EC - ADC reading) Args: test: flag for testing Returns: None Raises: None """ from EC import EC self._logger.info("EC") try: s = EC() ec = s.getEC() status_qualifier = 'Success' if test: status_qualifier = 'Test' print("{}, {}, {:10.1f}".format("EC", status_qualifier, ec)) rec = [ self._activity_type, '', 'Reservoir', 'Nutrient', 'EC', "{:3.1f}".format(ec), 'EC', 'EC', status_qualifier, '' ] self._persist.save(rec) self._logger.info("{}, {}, {:10.1f}".format( "EC", status_qualifier, ec)) except Exception as e: status_qualifier = 'Failure' if test: status_qualifier = 'Test' print("{}, {}, {:10.1f}".format("EC", status_qualifier, ec)) rec = [ self._activity_type, '', 'Reservoir', 'Nutrient', 'EC', '', 'EC', 'EC', status_qualifier, str(e) ] self._persist.save(rec) self._logger.error("{}, {}, {}".format("EC CCS811", status_qualifier, e)) def getCO2_NDIR(self, test=False): """Record CO2 sensor (NDIR) Args: test: flag for testing Returns: None Raises: None """ from NDIR import Sensor self._logger.info("CO2 - NDIR") try: sensor = Sensor() sensor.begin() co2 = sensor.getCO2() status_qualifier = 'Success' if test: status_qualifier = 'Test' print("{}, {}, {:10.1f}".format("CO2 Canopy", status_qualifier, co2)) rec = [ self._activity_type, '', 'Canopy', 'Air', 'CO2', "{:3.1f}".format(co2), 'ppm', 'MH-Z16-NDIR', status_qualifier, '' ] self._persist.save(rec) self._logger.debug("{}, {}, {:10.1f}".format( "CO2", status_qualifier, co2)) except Exception as e: status_qualifier = 'Failure' if test: status_qualifier = 'Test' print("{}, {}, {:10.1f}".format("CO2 Canopy", status_qualifier, co2)) rec = [ self._activity_type, '', 'Canopy', 'Air', 'CO2', '', 'ppm', 'MH-Z16-NDIR', status_qualifier, str(e) ] self._persist.save(rec) self._logger.error("{}, {}, {}".format("CO2 NDIR", status_qualifier, e)) def getCO2_CCS811(self, test=False): """Record CO2 sensor (CCS811) Args: test: flag for testing Returns: None Raises: None """ from CCS811 import CCS811 self._logger.info("CO2 CCS811") try: sensor = CCS811(SLAVE) co2 = sensor.get_co2() status_qualifier = 'Success' if test: status_qualifier = 'Test' print("{}, {}, {:10.1f}".format("CO2 Canopy", status_qualifier, co2)) rec = [ self._activity_type, '', 'Canopy', 'Air', 'CO2', "{:3.1f}".format(co2), 'ppm', 'CCS811', str(e) ] self._persist.save(rec) self._logger.debug("{}, {}, {:10.1f}".format( "CCS811 - CO2", status_qualifier, co2)) except Exception as e: status_qualifier = 'Failure' if test: status_qualifier = 'Test' print("{}, {}, {:10.1f}".format("CO2 Canopy", status_qualifier, co2)) rec = [ self._activity_type, '', 'Canopy', 'Air', 'CO2', '', 'ppm', 'CCS811', status_qualifier, str(e) ] self._persist.save(rec) self._logger.error("{}, {}, {}".format("CO2 CCS811", status_qualifier, e)) def getSCD(self): """Record CO2 sensor (scd30) Generates co2, temperature and relative humidity Args: None Returns: None Raises: None """ from scd30 import SCD30 self._scd = SCD30(self._logger) self._logger.debug("In SCD30") try: co2, temp, rh = self._scd.get_data() status = 'Success' if self._test: status = 'Test' c_rec = [ 'Environment_Observation', '', 'Top', 'Air', 'CO2', "{:10.1f}".format(co2), 'ppm', 'scd30', status, '' ] t_rec = [ 'Environment_Observation', '', 'Top', 'Air', 'Temperature', "{:10.1f}".format(temp), 'Centigrade', 'scd30', status, '' ] h_rec = [ 'Environment_Observation', '', 'Top', 'Air', 'Humidity', "{:10.1f}".format(rh), 'Percent', 'scd30', status, '' ] self._persist.save(c_rec) self._persist.save(t_rec) self._persist.save(h_rec) self._logger.info("{} {:6.1f}, {} {:3.1f}, {} {:3.1f}".format( "EnvObsv-CO2:", co2, "Temp", temp, "Humidity:", rh)) except Exception as e: status = 'Failure' if self._test: status = 'Test' c_rec = [ 'Environment_Observation', '', 'Top', 'Air', 'CO2', '', 'ppm', 'scd30', status, str(e) ] t_rec = [ 'Environment_Observation', '', 'Top', 'Air', 'Temperature', '', 'Centigrde', 'scd30', status, '' ] h_rec = [ 'Environment_Observation', '', 'Top', 'Air', 'Humidity', '', 'Percent', 'scd30', status, '' ] self._persist.save(c_rec) self._persist.save(t_rec) self._persist.save(h_rec) self._logger.debug("{} {}".format("EnvObsv-SCD30 Error:", e)) def log(self): '''Log extra sensors Uncomment desired sensors Imports are in the function to avoid loading unnecessary code ''' #self.getOneWire() self.getLux() self.getEC() self.getCO2_NDIR() #self.getCO2_CCS811() self.getSCD()