class FermentControl: THREADS = 4 sensor_logger = None fridge_control = None logger = None control = None def __init__(self): print("OpenBrew - Ferment") # Setup the config parser self.config = ConfigParser() self.config.readfp(open('config.cfg')) # Make sure we have a connection to the database # http://initd.org/psycopg/docs/ dsn = "host=" + self.config['database']['host'] + " dbname=" + self.config['database']['database'] + " user="******" password="******"Running...") self.sensor_logger = SensorLogger(self.config, self.dbconn) self.fridge_control = FridgeControl(self.config, self.dbconn) self.control = ControlInterface(self.logger, self.dbconn, self.config) children = [] for process in range(self.THREADS): pid = os.fork() if pid: children.append(pid) else: self.runFermentThread(process) os._exit(0) for i, child in enumerate(children): os.waitpid(child, 0) def runFermentThread(self, process): print 'This is process thread {0} for fermenter tasks'.format(process) if process is 0: self.sensor_logger.actions() elif process is 1: self.fridge_control.actions(1) elif process is 2: self.fridge_control.actions(2) elif process is 3: self.control.interface()
def __init__(self, logger): #initialize super(MPU6050, self).__init__(logger) self.sensorlogger = SensorLogger('MPU6050',logger) self.mutex = threading.Semaphore(1) self.mpu = MPU6050BASE() self.mpu.dmpInitialize() self.mpu.setDMPEnabled(True) # get expected DMP packet size for later comparison self.packetSize = self.mpu.dmpGetFIFOPacketSize()
def __init__(self, logger, device): super(Serial, self).__init__(logger) #Logger for voltage sensor self.voltagelogger = SensorLogger('Voltage',logger) #Set serial with baudrate 9600 and a timeout of 3 seconds self.ser = serial.Serial(device, baudrate=9600, timeout=3.0) #Flushes the input. If we don't flush the input we will recieve old input. self.ser.flushInput() #Semaphores self.mutex1 = threading.Semaphore(1) self.mutex2 = threading.Semaphore(1) self.mutexVoltage = threading.Semaphore(1) self.mutexButton = threading.Semaphore(1)
def run(self): print("Running...") self.sensor_logger = SensorLogger(self.config, self.dbconn) self.fridge_control = FridgeControl(self.config, self.dbconn) self.control = ControlInterface(self.logger, self.dbconn, self.config) children = [] for process in range(self.THREADS): pid = os.fork() if pid: children.append(pid) else: self.runFermentThread(process) os._exit(0) for i, child in enumerate(children): os.waitpid(child, 0)
class Serial(Sensor): # Interval in seconds interval = 0.1 sensor1 = 0 sensor2 = 0 button = False voltage = 0 voltageCounter = 0 def __init__(self, logger, device): super(Serial, self).__init__(logger) #Logger for voltage sensor self.voltagelogger = SensorLogger('Voltage',logger) #Set serial with baudrate 9600 and a timeout of 3 seconds self.ser = serial.Serial(device, baudrate=9600, timeout=3.0) #Flushes the input. If we don't flush the input we will recieve old input. self.ser.flushInput() #Semaphores self.mutex1 = threading.Semaphore(1) self.mutex2 = threading.Semaphore(1) self.mutexVoltage = threading.Semaphore(1) self.mutexButton = threading.Semaphore(1) def run(self): while self.alive: #Gets the sensor values self.getValues() #Sleep time.sleep(self.interval) def getValues(self): #Readline from serial responses = self.ser.readline() responses = responses.decode('ascii') #Remove characters that we don't need responses = responses.replace("\r\n","") responses = responses.replace("\x00","") responses = responses.replace("n'","") responses = responses.replace("'","") #split the line responses = responses.split(',') #loop through the responses for response in responses: #Checks if we need the response if len(response) > 2: #Convert to int response = int(response) #Voltage if(response < 2000): voltage = float(response) / float(100) self.setVoltage(voltage) #First glove sensor if(response >= 2000 and response < 2500): sensor1 = response - 2000 self.setSensor1(sensor1) #Second glove sensor elif(response >= 2500 and response < 3000): sensor2 = response - 2500 self.setSensor2(sensor2) #Light sensor off elif(response == 3001): self.setButton(False) #Light sensor on elif(response == 3002): self.setButton(True) def stop(self): #Stop loop self.alive = False def start(self): #Start loop self.thread.start() def getSensor1(self): #Mutex self.mutex1.acquire() value = self.sensor1 self.mutex1.release() return value def setSensor1(self, value): #Mutex self.mutex1.acquire() self.sensor1 = value self.mutex1.release() def getSensor2(self): #Mutex self.mutex2.acquire() value = self.sensor2 self.mutex2.release() return value def setSensor2(self, value): #Mutex self.mutex2.acquire() self.sensor2 = value self.mutex2.release() def getButton(self): #Mutex self.mutexButton.acquire() value = self.button self.mutexButton.release() return value def setButton(self, value): #Mutex self.mutexButton.acquire() self.button = value self.mutexButton.release() def getVoltage(self): #Mutex self.mutexVoltage.acquire() value = self.voltage self.mutexVoltage.release() return value def setVoltage(self, value): #Mutex self.mutexVoltage.acquire() self.voltage = value #Log every ten times if self.voltageCounter == 0 or self.voltageCounter == 10: self.voltageCounter = 0 self.voltagelogger.log_waarde("{0:.2f}".format(self.voltage)) if self.voltageCounter <=9.2 and self.voltageCounter != 0 : import os os.system("sudo poweroff") self.mutexVoltage.release()
# Remove residual files from the previous run (removes all files in the current and processing dir) remove_residual_files() # Get a dictionary of sensors and their status sensors = get_sensors() # Join the LoRa network lora = False if (True in sensors.values() or gps_on) and config.get_config("LORA") == "ON": lora = LoRaWAN(status_logger) # Initialise temperature and humidity sensor thread with id: TEMP if sensors[s.TEMP]: TEMP_logger = SensorLogger(sensor_name=s.TEMP, terminal_out=True) if config.get_config(s.TEMP) == "SHT35": temp_sensor = TempSHT35(TEMP_logger, status_logger) status_logger.info("Temperature and humidity sensor initialised") # Initialise PM power circuitry PM_transistor = Pin('P20', mode=Pin.OUT) PM_transistor.value(0) if config.get_config(s.PM1) != "OFF" or config.get_config(s.PM2) != "OFF": PM_transistor.value(1) # Initialise PM sensor threads if sensors[s.PM1]: initialise_pm_sensor(sensor_name=s.PM1, pins=('P3', 'P17'), serial_id=1,
def pm_thread(sensor_name, status_logger, pins, serial_id): """ Method to run as a thread that reads, processes and logs readings form pm sensors according to their type :param sensor_name: PM1 or PM2 :type sensor_name: str :param status_logger: status logger :type status_logger: LoggerFactory object :param pins: serial bus pins (TX, RX) :type pins: tuple(int, int) :param serial_id: serial bus id (0, 1 or 2) :type serial_id: int """ status_logger.debug("Thread {} started".format(sensor_name)) sensor_logger = SensorLogger(sensor_name=sensor_name, terminal_out=True) sensor_type = config.get_config(sensor_name) init_time = int(config.get_config(sensor_name + "_init")) init_count = 0 if sensor_type == "PMS5003": # initialise sensor sensor = Plantower(pins=pins, id=serial_id) time.sleep(1) # warm up time - readings are not logged while init_count < init_time: try: time.sleep(1) sensor.read() init_count += 1 except PlantowerException as e: status_logger.exception("Failed to read from sensor PMS5003") blink_led((0x550000, 0.4, True)) elif sensor_type == "SPS030": # initialise sensor while True: try: sensor = Sensirion( retries=1, pins=pins, id=serial_id) # automatically starts measurement break except SensirionException as e: status_logger.exception("Failed to read from sensor SPS030") blink_led((0x550000, 0.4, True)) time.sleep(1) # warm up time - readings are not logged while init_count < init_time: try: time.sleep(1) sensor.read() init_count += 1 except SensirionException as e: status_logger.exception("Failed to read from sensor SPS030") blink_led((0x550000, 0.4, True)) # start a periodic timer interrupt to poll readings every second processing_alarm = Timer.Alarm(process_readings, arg=(sensor_type, sensor, sensor_logger, status_logger), s=1, periodic=True)
def run(self): print("Running..") brews = 1 brewcount = 0 # add the pumps hlt_recirc = Pump(Pump.PUMP_BROWN) mlt_recirc = Pump(Pump.PUMP_MARCH) transfer = Pump(Pump.PUMP_MARCH) # This will run forever. while True: # Initially this will just be doing a single batch at a time # but this could allow recipes to be stacked. try: # load the recipe xml recipe = Recipe('step_mash_recipe.xml') # parse the recipe xml recipe.parse() except Exception as e: error_str = "Recipe parsing failed!" self.logger.critical(error_str) print(error_str) print("Mash steps are:") mash_steps = recipe.get_mash_steps() for steps in mash_steps: print(steps.tag, steps.attrib) for step in steps: print(step.tag, step.text) # setup the vessels self.vessel_hlt = VesselHlt(self.logger, self.dbconn) self.vessel_hlt.strike_in_mlt(self.strike_in_mlt) self.vessel_hlt.set_target_strike_time() # UNIX timestamp self.vessel_hlt.add_steps(recipe.get_mash_steps()) self.vessel_mlt = VesselMlt(self.logger, self.dbconn) self.vessel_mlt.strike_in_mlt(self.strike_in_mlt) self.vessel_mlt.add_steps(recipe.get_mash_steps()) self.vessel_ktl = VesselKettle(self.logger, self.dbconn) self.sensor_logger = SensorLogger(self.logger, self.dbconn) self.control = ControlInterface(self.logger, self.dbconn) children = [] # Create forks for each vessel. # from http://www.petercollingridge.co.uk/blog/running-multiple-processes-python start_time = time.time() processes = self.VESSEL_COUNT + 2 # number of vessels plus the logger and webservice threads for process in range(self.VESSEL_COUNT): pid = os.fork() if pid: children.append(pid) else: self.processLauncher(process) os._exit(0) # Wait for all the vessels to complete. for i, child in enumerate(children): os.waitpid(child, 0) brewcount += 1 if(brewcount == brews): print("All batches completed. Exiting.") os._exit(0)
class BreweryControl(): vessel_hlt = None vessel_mlt = None vessel_ktl = None VESSEL_COUNT = 3 config = None sensors = None dbconn = None logger = None strike_in_mlt = True def __init__(self): print("OpenBrew init.") # https://docs.python.org/3/library/logging.html logging.basicConfig(format='%(message)s', level=logging.DEBUG) self.logger = logging.getLogger('BreweryControl').setLevel(logging.WARNING) # Setup the config parser self.config = ConfigParser() self.config.readfp(open('config.cfg')) #sensors = Sensors() #sensors.load(self.config) # Make sure we have a connection to the database # http://initd.org/psycopg/docs/ dsn = "dbname=" + self.config['database']['database'] + " user="******" password="******"Running..") brews = 1 brewcount = 0 # add the pumps hlt_recirc = Pump(Pump.PUMP_BROWN) mlt_recirc = Pump(Pump.PUMP_MARCH) transfer = Pump(Pump.PUMP_MARCH) # This will run forever. while True: # Initially this will just be doing a single batch at a time # but this could allow recipes to be stacked. try: # load the recipe xml recipe = Recipe('step_mash_recipe.xml') # parse the recipe xml recipe.parse() except Exception as e: error_str = "Recipe parsing failed!" self.logger.critical(error_str) print(error_str) print("Mash steps are:") mash_steps = recipe.get_mash_steps() for steps in mash_steps: print(steps.tag, steps.attrib) for step in steps: print(step.tag, step.text) # setup the vessels self.vessel_hlt = VesselHlt(self.logger, self.dbconn) self.vessel_hlt.strike_in_mlt(self.strike_in_mlt) self.vessel_hlt.set_target_strike_time() # UNIX timestamp self.vessel_hlt.add_steps(recipe.get_mash_steps()) self.vessel_mlt = VesselMlt(self.logger, self.dbconn) self.vessel_mlt.strike_in_mlt(self.strike_in_mlt) self.vessel_mlt.add_steps(recipe.get_mash_steps()) self.vessel_ktl = VesselKettle(self.logger, self.dbconn) self.sensor_logger = SensorLogger(self.logger, self.dbconn) self.control = ControlInterface(self.logger, self.dbconn) children = [] # Create forks for each vessel. # from http://www.petercollingridge.co.uk/blog/running-multiple-processes-python start_time = time.time() processes = self.VESSEL_COUNT + 2 # number of vessels plus the logger and webservice threads for process in range(self.VESSEL_COUNT): pid = os.fork() if pid: children.append(pid) else: self.processLauncher(process) os._exit(0) # Wait for all the vessels to complete. for i, child in enumerate(children): os.waitpid(child, 0) brewcount += 1 if(brewcount == brews): print("All batches completed. Exiting.") os._exit(0) # Program end. def processLauncher(self, process): if process is 0: self.sensor_logger.actions() elif process is 1: self.control.interface() elif process is 2: #self.logger.info("HLT Fork starting up") self.vessel_hlt.actions() elif process is 3: #self.logger.info("MLT Fork starting up") self.vessel_mlt.actions() elif process is 4: #self.logger.info("Kettle Fork starting up") self.vessel_ktl.actions()
class MPU6050(Sensor): # Interval in seconds interval = 1 # Default value current_value = {'yaw': 0, 'pitch': 0, 'roll': 0} def __init__(self, logger): #initialize super(MPU6050, self).__init__(logger) self.sensorlogger = SensorLogger('MPU6050',logger) self.mutex = threading.Semaphore(1) self.mpu = MPU6050BASE() self.mpu.dmpInitialize() self.mpu.setDMPEnabled(True) # get expected DMP packet size for later comparison self.packetSize = self.mpu.dmpGetFIFOPacketSize() #get Values def run(self): while self.alive: self.getValues() time.sleep(self.interval) def getValues(self): # Get INT_STATUS byte mpuIntStatus = self.mpu.getIntStatus() if mpuIntStatus >= 2: # check for DMP data ready interrupt (this should happen frequently) # get current FIFO count fifoCount = self.mpu.getFIFOCount() # check for overflow (this should never happen unless our code is too inefficient) if fifoCount == 1024: # reset so we can continue cleanly self.mpu.resetFIFO() # print('FIFO overflow!') # wait for correct available data length, should be a VERY short wait fifoCount = self.mpu.getFIFOCount() while fifoCount < self.packetSize: fifoCount = self.mpu.getFIFOCount() result = self.mpu.getFIFOBytes(self.packetSize) q = self.mpu.dmpGetQuaternion(result) g = self.mpu.dmpGetGravity(q) ypr = self.mpu.dmpGetYawPitchRoll(q, g) #save sensordata sensorData = {'yaw': ypr['yaw'] * 180 / math.pi, 'pitch': ypr['pitch'] * 180 / math.pi, 'roll': ypr['roll'] * 180 / math.pi} self.setValue(sensorData) fifoCount -= self.packetSize #log sensor self.sensorlogger.log_waarde("y:{0:.3f}, p:{1:.3f}, r:{2:.3f}".format(sensorData['yaw'], sensorData['pitch'], sensorData['roll'])) #stop thread def stop(self): self.alive = False #start thread def start(self): self.thread.start() #get yaw, pith, roll def getValue(self): self.mutex.acquire() value = self.current_value self.mutex.release() return value #set sensorData def setValue(self, value): self.mutex.acquire() self.current_value = value self.mutex.release()