def __init__(self): super(Brumulus, self).__init__() # self.logger = logger # self.flight_recorder_file = open('brumulus.csv', 'a') # self.flight_recorder = csv.writer(self.flight_recorder_file) #TODO make this configurable self.temp = TemperatureSensor(device_id='28-000004f2300b') self.temp_2 = TemperatureSensor(device_id='28-000004f17ab8') self.control = ControlTemperature() self.setpoint = ControlSetPoint() self.chiller = ControlledOutput(ProtectedOutput(min_state_time=180, pin=17), name='Chiller') self.heater = ControlledOutput(ProtectedOutput(min_state_time=30, pin=23), name='Heater', control_scale=-1) self.target_temp = self.setpoint.get_setpoint() self.datetime = None self.current_temp = None
def addTemperatureSensor(self, sensor_type='boiler', sensoridentifier='28-0000092c44f8'): temperatureSensor = TemperatureSensor(sensorAddress=sensoridentifier) temperatureSensor.setupSensor() if sensor_type == 'boiler': self._boilerTempSensors.append(temperatureSensor) self._boilerTempSensorsIter = cycle(self._boilerTempSensors) elif sensor_type == 'steam': self._steamTempSensors.append(temperatureSensor) else: raise ValueError('sensor_type must be "boiler" or "steam"')
def __init__(self, ip_address, port, name, config): self.client = Client(ip_address, port, timeout=1) self.name = name self.ledstrip = None self.temperature_sensor = None self.humidity_sensor = None self.light_sensor = None self.motion_sensor = None self.light_control = None for node in self.client.root.get_children(): if node.get_name() == 'LEDSTRIP': self.ledstrip = LedStrip(node) elif node.get_name() == 'HTU': self.temperature_sensor = TemperatureSensor(node) self.humidity_sensor = HumiditySensor(node) elif node.get_name() == 'LIGHT': self.light_sensor = LightSensor(self.client.root.LIGHT) elif node.get_name() == 'MOTION': self.motion_sensor = MotionSensor(self.client.root.MOTION) if self.ledstrip and self.light_sensor and self.motion_sensor: self.light_control = LightControl(config, self.ledstrip, self.light_sensor, self.motion_sensor)
def __init__(self): super(Brumulus, self).__init__() # TODO make this configurable self.temp = TemperatureSensor(device_id='28-000004f2300b') self.temp_2 = TemperatureSensor(device_id='28-000004f17ab8') self.control = ControlTemperature() self.setpoint = ControlSetPoint() self.chiller = ControlledOutput( ProtectedOutput(EnergenieOutput(1), min_state_time=180), name='Chiller') self.heater = ControlledOutput( ProtectedOutput(EnergenieOutput(2), min_state_time=30), name='Heater', control_scale=-1) self.target_temp = self.setpoint.get_setpoint() self.datetime = None self.current_temp = None
class Brumulus(object): """docstring for Brumulus""" def __init__(self): super(Brumulus, self).__init__() # self.logger = logger # self.flight_recorder_file = open('brumulus.csv', 'a') # self.flight_recorder = csv.writer(self.flight_recorder_file) #TODO make this configurable self.temp = TemperatureSensor(device_id='28-000004f2300b') self.temp_2 = TemperatureSensor(device_id='28-000004f17ab8') self.control = ControlTemperature() self.setpoint = ControlSetPoint() self.chiller = ControlledOutput(ProtectedOutput(min_state_time=180, pin=17), name='Chiller') self.heater = ControlledOutput(ProtectedOutput(min_state_time=30, pin=23), name='Heater', control_scale=-1) self.target_temp = self.setpoint.get_setpoint() self.datetime = None self.current_temp = None # self.thingsspeak = Thingsspeak() # self.control_loop_timer = task.LoopingCall(self.control_loop) # self.lager_api = LagerThread(self) # self.history = deque() # self.history_max = 20 # def start(self): # self.control_loop_timer.start(30) # self.lager_api.start() # reactor.run() # # def stop(self): # try: # reactor.callFromThread(reactor.stop) # except: # pass # # try: # self.lager_api.stop() # except: # pass def control_loop(self): prev_datetime = self.datetime prev_temp = self.current_temp self.target_temp = self.setpoint.get_setpoint() self.datetime = datetime.now() self.time = str(self.datetime.isoformat(' ')) self.err = '' self.current_temp = self.temp.read_temp_decimal() self.current_temp_2 = self.temp_2.read_temp_decimal() print "current_temp: {} setpoint: {}".format(self.current_temp, self.target_temp) # if self.current_temp is None: # self.err = "current_temp cannot be read" # print self.err # else: # try: # self.temp_delta = self.get_temp_delta(prev_datetime, prev_temp) # print "Temp delta ", self.temp_delta # self.control_value = self.control.get_output(self.current_temp, self.target_temp, self.temp_delta) # print "control_value", self.control_value # self.chiller.control(self.control_value) # self.heater.control(self.control_value) # # # self.recorder() # # values = self.get_all() # # self.history.append(values) # # if len(self.history) > self.history_max: # # self.history.popleft() # # self.thingsspeak.send(values) # except Exception as e: # print e # self.err = str(e) # print '-' * 60 # traceback.print_exc(file=sys.stdout) # print '-' * 60 def get_temp_delta(self, prev_datetime, prev_temp): if (prev_datetime is None or prev_temp is None): return 0 time_delta = Decimal((self.datetime - prev_datetime).total_seconds()) temp_delta = self.current_temp - prev_temp return Decimal((temp_delta / time_delta) * 60) # def recorder(self): # data = [self.time, self.target_temp, '{0:.3f}'.format(self.current_temp), self.chiller_ssr_raw, self.control_value, self.err] # print data # self.flight_recorder.writerow(data) actions = {'increment_target_temp', 'decrement_target_temp'} def action(self, action): if action == 'decrement_target_temp': return self.decrement_target_temp() if action == 'increment_target_temp': return self.increment_target_temp() if action == 'get_all': return self.get_all() if action == 'toggle_chiller_mode': self.chiller.mode_toggle() if action == 'toggle_heater_mode': self.heater.mode_toggle() if action == 'get_history': return self.get_history() def decrement_target_temp(self): self.setpoint.set_gui_setpoint(self.target_temp - 1) self.target_temp = self.setpoint.get_setpoint() return self.get_all() def increment_target_temp(self): self.setpoint.set_gui_setpoint(self.target_temp + 1) self.target_temp = self.setpoint.get_setpoint() return self.get_all() def get_history(self, count=60): print "current hist: {}".format(self.history) return list(self.history)[-1 * count:] def get_all(self): values = {'created_at': self.time, 'target_temp': str(self.target_temp), 'target_temp_mode': self.setpoint.get_mode(), 'current_temp': '{0:.3f}'.format(self.current_temp), 'current_temp_2': '{0:.3f}'.format(self.current_temp_2), 'temp_delta': '{0:.3f}'.format(self.temp_delta), 'control_value': '{0:.0f}'.format(self.control_value), 'chiller': self.chiller.get_state_str(), 'chiller_raw': self.chiller.get_raw(), 'chiller_info': self.chiller.get_info(), 'chiller_mode': self.chiller.get_mode(), 'heater': self.heater.get_state_str(), 'heater_info': self.heater.get_info(), 'heater_raw': self.heater.get_raw(), 'heater_mode': self.heater.get_mode(), } return values
from flask import Flask app = Flask(__name__) from TemperatureSensor import TemperatureSensor from Led import Led from flask import render_template lightr = Led(18) lightb = Led(24) pierre = TemperatureSensor() @app.route('/hello') def hello_world(): return 'Hello World!' @app.route('/') def index(): return render_template('base.html') @app.route('/<bleu_rouge>/<on_off>') def ledonb(bleu_rouge, on_off): if on_off == 'on' and bleu_rouge == 'bleu': lightb.on() elif on_off == 'off' and bleu_rouge == 'bleu': lightb.off()
class Brumulus(object): """docstring for Brumulus""" def __init__(self): super(Brumulus, self).__init__() # self.logger = logger # self.flight_recorder_file = open('brumulus.csv', 'a') # self.flight_recorder = csv.writer(self.flight_recorder_file) #TODO make this configurable self.temp = TemperatureSensor(device_id='28-000004f2300b') self.temp_2 = TemperatureSensor(device_id='28-000004f17ab8') self.control = ControlTemperature() self.setpoint = ControlSetPoint() self.chiller = ControlledOutput(ProtectedOutput(min_state_time=180, pin=17), name='Chiller') self.heater = ControlledOutput(ProtectedOutput(min_state_time=30, pin=23), name='Heater', control_scale=-1) self.target_temp = self.setpoint.get_setpoint() self.datetime = None self.current_temp = None # self.thingsspeak = Thingsspeak() # self.control_loop_timer = task.LoopingCall(self.control_loop) # self.lager_api = LagerThread(self) # self.history = deque() # self.history_max = 20 # def start(self): # self.control_loop_timer.start(30) # self.lager_api.start() # reactor.run() # # def stop(self): # try: # reactor.callFromThread(reactor.stop) # except: # pass # # try: # self.lager_api.stop() # except: # pass def control_loop(self): prev_datetime = self.datetime prev_temp = self.current_temp self.target_temp = self.setpoint.get_setpoint() self.datetime = datetime.now() self.time = str(self.datetime.isoformat(' ')) self.err = '' self.current_temp = self.temp.read_temp_decimal() self.current_temp_2 = self.temp_2.read_temp_decimal() print "current_temp: {} setpoint: {}".format(self.current_temp, self.target_temp) # if self.current_temp is None: # self.err = "current_temp cannot be read" # print self.err # else: # try: # self.temp_delta = self.get_temp_delta(prev_datetime, prev_temp) # print "Temp delta ", self.temp_delta # self.control_value = self.control.get_output(self.current_temp, self.target_temp, self.temp_delta) # print "control_value", self.control_value # self.chiller.control(self.control_value) # self.heater.control(self.control_value) # # # self.recorder() # # values = self.get_all() # # self.history.append(values) # # if len(self.history) > self.history_max: # # self.history.popleft() # # self.thingsspeak.send(values) # except Exception as e: # print e # self.err = str(e) # print '-' * 60 # traceback.print_exc(file=sys.stdout) # print '-' * 60 def get_temp_delta(self, prev_datetime, prev_temp): if (prev_datetime is None or prev_temp is None): return 0 time_delta = Decimal((self.datetime - prev_datetime).total_seconds()) temp_delta = self.current_temp - prev_temp return Decimal((temp_delta / time_delta) * 60) # def recorder(self): # data = [self.time, self.target_temp, '{0:.3f}'.format(self.current_temp), self.chiller_ssr_raw, self.control_value, self.err] # print data # self.flight_recorder.writerow(data) actions = {'increment_target_temp', 'decrement_target_temp'} def action(self, action): if action == 'decrement_target_temp': return self.decrement_target_temp() if action == 'increment_target_temp': return self.increment_target_temp() if action == 'get_all': return self.get_all() if action == 'toggle_chiller_mode': self.chiller.mode_toggle() if action == 'toggle_heater_mode': self.heater.mode_toggle() if action == 'get_history': return self.get_history() def decrement_target_temp(self): self.setpoint.set_gui_setpoint(self.target_temp - 1) self.target_temp = self.setpoint.get_setpoint() return self.get_all() def increment_target_temp(self): self.setpoint.set_gui_setpoint(self.target_temp + 1) self.target_temp = self.setpoint.get_setpoint() return self.get_all() def get_history(self, count=60): print "current hist: {}".format(self.history) return list(self.history)[-1 * count:] def get_all(self): values = { 'created_at': self.time, 'target_temp': str(self.target_temp), 'target_temp_mode': self.setpoint.get_mode(), 'current_temp': '{0:.3f}'.format(self.current_temp), 'current_temp_2': '{0:.3f}'.format(self.current_temp_2), 'temp_delta': '{0:.3f}'.format(self.temp_delta), 'control_value': '{0:.0f}'.format(self.control_value), 'chiller': self.chiller.get_state_str(), 'chiller_raw': self.chiller.get_raw(), 'chiller_info': self.chiller.get_info(), 'chiller_mode': self.chiller.get_mode(), 'heater': self.heater.get_state_str(), 'heater_info': self.heater.get_info(), 'heater_raw': self.heater.get_raw(), 'heater_mode': self.heater.get_mode(), } return values
print("Running Production Environment Configuration") environment = cfg.env_prod # Application constants from Environment and Configuration file sampleTime = cfg.sampleTime debug = cfg.debug deviceID = cfg.deviceID webApiUrl = environment["webApi"] webApiUsername = environment["username"] webApiPassword = environment["password"] # Create an indicator LED on GPIO pin 17 led = LED(17) # Create the Temperature Sensor on GPIO pin 4 temperatureSensor = TemperatureSensor(4) # Dictionary to hold Temperature Sensor data temperatureData = {} # Sit in a loop reading the sensors every sampleTime, convert result to JSON, and POST to the Web API while True: # Turn LED ON led.on() # Read the Temperature Sensor temperatureSensor.read() if temperatureSensor.valid: # Save the Temperature Sensor results in a Temperature Data Object temperatureData["deviceID"] = deviceID temperatureData["temperature"] = temperatureSensor.temperatureF
def __init__(self, parent=None): super(ECUI, self).__init__(parent) # Settings self.autoabortEnabled = True # Hedgehog self.stack = ExitStack() self.hedgehog = self.stack.enter_context( connect(endpoint='tcp://raspberrypi.local:10789')) # FIXME # Simulated Hedgehog #self.hedgehog = SimulatedHedgehog() #Strain data received self.measure = StrainData() #Neopixel test self.socket_neo(b'SafeOn') # Actuators and Sensors self.servo_fuel = Servo(name='fuel', hedgehog=self.hedgehog, servoPort=0, feedbackPort=0) self.servo_oxidizer = Servo(name='oxidizer', hedgehog=self.hedgehog, servoPort=1, feedbackPort=1) self.igniter_arc = Igniter(name='arc', hedgehog=self.hedgehog, igniterPort=0) self.igniter_pyro = Igniter(name='pyro', hedgehog=self.hedgehog, igniterPort=1, feedbackPort=2) self.pressureSensor_fuel = PressureSensor(name='fuel', hedgehog=self.hedgehog, port=8) self.pressureSensor_oxidizer = PressureSensor(name='oxidizer', hedgehog=self.hedgehog, port=9) self.pressureSensor_chamber = PressureSensor(name='chamber', hedgehog=self.hedgehog, port=10) self.temperatureSensor_chamber = TemperatureSensor( name='chamber', hedgehog=self.hedgehog, port=11) # Countdown Timer and Sequence self.countdownTimer = CountdownTimer(self.countdownEvent) self.sequence = Sequence() # Regular Timer self.timer = QTimer() self.timer.setInterval(100) self.timer.timeout.connect(self.__timerTick) self.inputVoltage = 0.0 self.set_safe = True self.set_igniter = False self.loggingValues = [] # Main tab self.tab_main = QWidget() self.tab_main.layout = QVBoxLayout(self) self.tab_main.setLayout(self.tab_main.layout) self.label_countdownClock = QLabel(self.countdownTimer.getTimeString(), self) self.label_countdownClock.setStyleSheet('color: #000000') self.label_countdownClock.setToolTip("Countdown Clock") self.label_inputVoltage = QLabel("Input Voltage: 0.0V", self) self.label_inputVoltage.setStyleSheet('color: #000000') self.label_inputVoltage.setToolTip("Input Voltage") self.btn_countdownStartStop = QPushButton("Start", self) self.btn_countdownStartStop.setToolTip("Start the Countdown") self.btn_countdownStartStop.clicked.connect( self.countdownStartStopReset) self.btn_countdownStartStop.resize( self.btn_countdownStartStop.sizeHint()) self.btn_countdownStartStop.setStyleSheet('background-color: #00ff00;') self.layout_countdown = QHBoxLayout() self.layout_countdown.addWidget(self.label_inputVoltage, alignment=Qt.AlignLeft) self.layout_countdown.addWidget(self.label_countdownClock, alignment=Qt.AlignCenter) self.layout_countdown.addWidget(self.btn_countdownStartStop, alignment=Qt.AlignRight) self.tab_main.layout.addLayout(self.layout_countdown) self.sequencePlot = SequencePlot(self, sequence=self.sequence, countdownTimer=self.countdownTimer, width=5, height=4) self.tab_main.layout.addWidget(self.sequencePlot, alignment=Qt.AlignTop) self.checkbox_manualControl = QCheckBox("Manual Control", self) self.checkbox_manualControl.setToolTip("Enable Manual Control") self.checkbox_manualControl.clicked.connect( self.manualControlEnableDisable) self.checkbox_manualControl.resize( self.checkbox_manualControl.sizeHint()) self.checkbox_manualControlIgniter = QCheckBox("Igniter", self) self.checkbox_manualControlIgniter.setToolTip("Igniter Manual Control") self.checkbox_manualControlIgniter.clicked.connect( self.manualControlIgniterEnableDisable) self.checkbox_manualControlIgniter.resize( self.checkbox_manualControlIgniter.sizeHint()) self.checkbox_manualControlIgniter.setEnabled(False) self.label_manualControlFuel = QLabel( "Fuel Target: %3d%% Fuel Currently: %3d%% Fuel Pressure: %2.1fbar" % (self.servo_fuel.getPositionTargetPercent(), self.servo_fuel.getPositionCurrentPercent(), self.pressureSensor_fuel.getValue()), self) self.slider_manualControlFuel = QSlider( Qt.Horizontal ) # FIXME: buggy when slided manually, goes out of range or doesnt reach limits self.slider_manualControlFuel.setToolTip("Fuel Manual Control") self.slider_manualControlFuel.setRange(0, 100) self.slider_manualControlFuel.sliderMoved.connect( self.manualControlFuelChange) self.slider_manualControlFuel.resize( self.slider_manualControlFuel.sizeHint()) self.slider_manualControlFuel.setEnabled(False) self.layout_manualControlFuel = QVBoxLayout() self.layout_manualControlFuel.addWidget(self.label_manualControlFuel, alignment=Qt.AlignLeft) self.layout_manualControlFuel.addWidget(self.slider_manualControlFuel, alignment=Qt.AlignTop) self.label_manualControlOxidizer = QLabel( "Oxidizer Target: %3d%% Oxidizer Currently: %3d%% Oxidizer Pressure: %2.1fbar" % (self.servo_oxidizer.getPositionTargetPercent(), self.servo_oxidizer.getPositionCurrentPercent(), self.pressureSensor_oxidizer.getValue()), self) self.slider_manualControlOxidizer = QSlider( Qt.Horizontal ) # FIXME: buggy when slided manually, goes out of range or doesnt reach limits self.slider_manualControlOxidizer.setToolTip("Oxidizer Manual Control") self.slider_manualControlOxidizer.setRange(0, 100) self.slider_manualControlOxidizer.sliderMoved.connect( self.manualControlOxidizerChange) self.slider_manualControlOxidizer.resize( self.slider_manualControlOxidizer.sizeHint()) self.slider_manualControlOxidizer.setEnabled(False) self.layout_manualControlOxidizer = QVBoxLayout() self.layout_manualControlOxidizer.addWidget( self.label_manualControlOxidizer, alignment=Qt.AlignLeft) self.layout_manualControlOxidizer.addWidget( self.slider_manualControlOxidizer, alignment=Qt.AlignTop) self.layout_manualControl = QVBoxLayout() self.layout_manualControl.addWidget(self.checkbox_manualControl, alignment=Qt.AlignLeft) self.layout_manualControl.addWidget(self.checkbox_manualControlIgniter, alignment=Qt.AlignLeft) self.layout_manualControl.addLayout(self.layout_manualControlFuel) self.layout_manualControl.addLayout(self.layout_manualControlOxidizer) self.tab_main.layout.addLayout(self.layout_manualControl) # Settings tab self.tab_settings = QWidget() self.tab_settings.layout = QHBoxLayout(self) self.tab_settings.setLayout(self.tab_settings.layout) self.checkbox_calibration = QCheckBox("Servo Calibration", self) self.checkbox_calibration.setToolTip("Enable Servo Calibration Mode") self.checkbox_calibration.clicked.connect( self.calibrationEnableDisable) self.checkbox_calibration.resize(self.checkbox_calibration.sizeHint()) self.label_cal_fuel = QLabel( "Fuel (min=%dus, max=%dus)" % (self.servo_fuel.getMinUs(), self.servo_fuel.getMaxUs()), self) self.spinbox_cal_fuel = QSpinBox(self) self.spinbox_cal_fuel.setMinimum(500) self.spinbox_cal_fuel.setMaximum(2500) self.spinbox_cal_fuel.setSingleStep(1) self.spinbox_cal_fuel.setValue(self.servo_fuel.getPositionTargetUs()) self.spinbox_cal_fuel.setEnabled(False) self.spinbox_cal_fuel.valueChanged.connect(self.calFuelValueChanged) self.btn_cal_fuel_min = QPushButton("Set Min", self) self.btn_cal_fuel_min.setToolTip( "Set the Minimum Value, corresponds to 0%") self.btn_cal_fuel_min.clicked.connect(self.calFuelSetMin) self.btn_cal_fuel_min.setEnabled(False) self.btn_cal_fuel_min.resize(self.btn_cal_fuel_min.sizeHint()) self.btn_cal_fuel_max = QPushButton("Set Max", self) self.btn_cal_fuel_max.setToolTip( "Set the Maximum Value, corresponds to 100%") self.btn_cal_fuel_max.clicked.connect(self.calFuelSetMax) self.btn_cal_fuel_max.setEnabled(False) self.btn_cal_fuel_max.resize(self.btn_cal_fuel_max.sizeHint()) self.label_cal_oxidizer = QLabel( "Oxidizer (min=%dus, max=%dus)" % (self.servo_oxidizer.getMinUs(), self.servo_oxidizer.getMaxUs()), self) self.spinbox_cal_oxidizer = QSpinBox(self) self.spinbox_cal_oxidizer.setMinimum(500) self.spinbox_cal_oxidizer.setMaximum(2500) self.spinbox_cal_oxidizer.setSingleStep(1) self.spinbox_cal_oxidizer.setValue( self.servo_oxidizer.getPositionTargetUs()) self.spinbox_cal_oxidizer.setEnabled(False) self.spinbox_cal_oxidizer.valueChanged.connect( self.calOxidizerValueChanged) self.btn_cal_oxidizer_min = QPushButton("Set Min", self) self.btn_cal_oxidizer_min.setToolTip( "Set the Minimum Value, corresponds to 0%") self.btn_cal_oxidizer_min.clicked.connect(self.calOxidizerSetMin) self.btn_cal_oxidizer_min.setEnabled(False) self.btn_cal_oxidizer_min.resize(self.btn_cal_oxidizer_min.sizeHint()) self.btn_cal_oxidizer_max = QPushButton("Set Max", self) self.btn_cal_oxidizer_max.setToolTip( "Set the Maximum Value, corresponds to 100%") self.btn_cal_oxidizer_max.clicked.connect(self.calOxidizerSetMax) self.btn_cal_oxidizer_max.setEnabled(False) self.btn_cal_oxidizer_max.resize(self.btn_cal_oxidizer_max.sizeHint()) self.layout_calibration_fuel = QHBoxLayout() self.layout_calibration_fuel.addWidget(self.label_cal_fuel, alignment=Qt.AlignTop) self.layout_calibration_fuel.addWidget(self.spinbox_cal_fuel, alignment=Qt.AlignTop) self.layout_calibration_fuel.addWidget(self.btn_cal_fuel_min, alignment=Qt.AlignTop) self.layout_calibration_fuel.addWidget(self.btn_cal_fuel_max, alignment=Qt.AlignTop) self.layout_calibration_oxidizer = QHBoxLayout() self.layout_calibration_oxidizer.addWidget(self.label_cal_oxidizer, alignment=Qt.AlignTop) self.layout_calibration_oxidizer.addWidget(self.spinbox_cal_oxidizer, alignment=Qt.AlignTop) self.layout_calibration_oxidizer.addWidget(self.btn_cal_oxidizer_min, alignment=Qt.AlignTop) self.layout_calibration_oxidizer.addWidget(self.btn_cal_oxidizer_max, alignment=Qt.AlignTop) self.layout_calibration = QVBoxLayout() self.layout_calibration.addWidget(self.checkbox_calibration, alignment=Qt.AlignTop) self.layout_calibration.addLayout(self.layout_calibration_fuel) self.layout_calibration.addLayout(self.layout_calibration_oxidizer) self.tab_settings.layout.addLayout(self.layout_calibration) # Tabs self.tabs = QTabWidget() self.tabs.resize(300, 200) self.tabs.addTab(self.tab_main, "Main") self.tabs.addTab(self.tab_settings, "Settings") # Window self.layout = QVBoxLayout(self) self.layout.addWidget(self.tabs, alignment=Qt.AlignTop) self.setLayout(self.layout) self.setGeometry(500, 200, 900, 700) self.setWindowTitle("Engine Control UI") self.setWindowIcon(QIcon('icon.png')) #Timer self.timer.start()
class ECUI(QWidget): def __init__(self, parent=None): super(ECUI, self).__init__(parent) # Settings self.autoabortEnabled = True # Hedgehog self.stack = ExitStack() self.hedgehog = self.stack.enter_context( connect(endpoint='tcp://raspberrypi.local:10789')) # FIXME # Simulated Hedgehog #self.hedgehog = SimulatedHedgehog() #Strain data received self.measure = StrainData() #Neopixel test self.socket_neo(b'SafeOn') # Actuators and Sensors self.servo_fuel = Servo(name='fuel', hedgehog=self.hedgehog, servoPort=0, feedbackPort=0) self.servo_oxidizer = Servo(name='oxidizer', hedgehog=self.hedgehog, servoPort=1, feedbackPort=1) self.igniter_arc = Igniter(name='arc', hedgehog=self.hedgehog, igniterPort=0) self.igniter_pyro = Igniter(name='pyro', hedgehog=self.hedgehog, igniterPort=1, feedbackPort=2) self.pressureSensor_fuel = PressureSensor(name='fuel', hedgehog=self.hedgehog, port=8) self.pressureSensor_oxidizer = PressureSensor(name='oxidizer', hedgehog=self.hedgehog, port=9) self.pressureSensor_chamber = PressureSensor(name='chamber', hedgehog=self.hedgehog, port=10) self.temperatureSensor_chamber = TemperatureSensor( name='chamber', hedgehog=self.hedgehog, port=11) # Countdown Timer and Sequence self.countdownTimer = CountdownTimer(self.countdownEvent) self.sequence = Sequence() # Regular Timer self.timer = QTimer() self.timer.setInterval(100) self.timer.timeout.connect(self.__timerTick) self.inputVoltage = 0.0 self.set_safe = True self.set_igniter = False self.loggingValues = [] # Main tab self.tab_main = QWidget() self.tab_main.layout = QVBoxLayout(self) self.tab_main.setLayout(self.tab_main.layout) self.label_countdownClock = QLabel(self.countdownTimer.getTimeString(), self) self.label_countdownClock.setStyleSheet('color: #000000') self.label_countdownClock.setToolTip("Countdown Clock") self.label_inputVoltage = QLabel("Input Voltage: 0.0V", self) self.label_inputVoltage.setStyleSheet('color: #000000') self.label_inputVoltage.setToolTip("Input Voltage") self.btn_countdownStartStop = QPushButton("Start", self) self.btn_countdownStartStop.setToolTip("Start the Countdown") self.btn_countdownStartStop.clicked.connect( self.countdownStartStopReset) self.btn_countdownStartStop.resize( self.btn_countdownStartStop.sizeHint()) self.btn_countdownStartStop.setStyleSheet('background-color: #00ff00;') self.layout_countdown = QHBoxLayout() self.layout_countdown.addWidget(self.label_inputVoltage, alignment=Qt.AlignLeft) self.layout_countdown.addWidget(self.label_countdownClock, alignment=Qt.AlignCenter) self.layout_countdown.addWidget(self.btn_countdownStartStop, alignment=Qt.AlignRight) self.tab_main.layout.addLayout(self.layout_countdown) self.sequencePlot = SequencePlot(self, sequence=self.sequence, countdownTimer=self.countdownTimer, width=5, height=4) self.tab_main.layout.addWidget(self.sequencePlot, alignment=Qt.AlignTop) self.checkbox_manualControl = QCheckBox("Manual Control", self) self.checkbox_manualControl.setToolTip("Enable Manual Control") self.checkbox_manualControl.clicked.connect( self.manualControlEnableDisable) self.checkbox_manualControl.resize( self.checkbox_manualControl.sizeHint()) self.checkbox_manualControlIgniter = QCheckBox("Igniter", self) self.checkbox_manualControlIgniter.setToolTip("Igniter Manual Control") self.checkbox_manualControlIgniter.clicked.connect( self.manualControlIgniterEnableDisable) self.checkbox_manualControlIgniter.resize( self.checkbox_manualControlIgniter.sizeHint()) self.checkbox_manualControlIgniter.setEnabled(False) self.label_manualControlFuel = QLabel( "Fuel Target: %3d%% Fuel Currently: %3d%% Fuel Pressure: %2.1fbar" % (self.servo_fuel.getPositionTargetPercent(), self.servo_fuel.getPositionCurrentPercent(), self.pressureSensor_fuel.getValue()), self) self.slider_manualControlFuel = QSlider( Qt.Horizontal ) # FIXME: buggy when slided manually, goes out of range or doesnt reach limits self.slider_manualControlFuel.setToolTip("Fuel Manual Control") self.slider_manualControlFuel.setRange(0, 100) self.slider_manualControlFuel.sliderMoved.connect( self.manualControlFuelChange) self.slider_manualControlFuel.resize( self.slider_manualControlFuel.sizeHint()) self.slider_manualControlFuel.setEnabled(False) self.layout_manualControlFuel = QVBoxLayout() self.layout_manualControlFuel.addWidget(self.label_manualControlFuel, alignment=Qt.AlignLeft) self.layout_manualControlFuel.addWidget(self.slider_manualControlFuel, alignment=Qt.AlignTop) self.label_manualControlOxidizer = QLabel( "Oxidizer Target: %3d%% Oxidizer Currently: %3d%% Oxidizer Pressure: %2.1fbar" % (self.servo_oxidizer.getPositionTargetPercent(), self.servo_oxidizer.getPositionCurrentPercent(), self.pressureSensor_oxidizer.getValue()), self) self.slider_manualControlOxidizer = QSlider( Qt.Horizontal ) # FIXME: buggy when slided manually, goes out of range or doesnt reach limits self.slider_manualControlOxidizer.setToolTip("Oxidizer Manual Control") self.slider_manualControlOxidizer.setRange(0, 100) self.slider_manualControlOxidizer.sliderMoved.connect( self.manualControlOxidizerChange) self.slider_manualControlOxidizer.resize( self.slider_manualControlOxidizer.sizeHint()) self.slider_manualControlOxidizer.setEnabled(False) self.layout_manualControlOxidizer = QVBoxLayout() self.layout_manualControlOxidizer.addWidget( self.label_manualControlOxidizer, alignment=Qt.AlignLeft) self.layout_manualControlOxidizer.addWidget( self.slider_manualControlOxidizer, alignment=Qt.AlignTop) self.layout_manualControl = QVBoxLayout() self.layout_manualControl.addWidget(self.checkbox_manualControl, alignment=Qt.AlignLeft) self.layout_manualControl.addWidget(self.checkbox_manualControlIgniter, alignment=Qt.AlignLeft) self.layout_manualControl.addLayout(self.layout_manualControlFuel) self.layout_manualControl.addLayout(self.layout_manualControlOxidizer) self.tab_main.layout.addLayout(self.layout_manualControl) # Settings tab self.tab_settings = QWidget() self.tab_settings.layout = QHBoxLayout(self) self.tab_settings.setLayout(self.tab_settings.layout) self.checkbox_calibration = QCheckBox("Servo Calibration", self) self.checkbox_calibration.setToolTip("Enable Servo Calibration Mode") self.checkbox_calibration.clicked.connect( self.calibrationEnableDisable) self.checkbox_calibration.resize(self.checkbox_calibration.sizeHint()) self.label_cal_fuel = QLabel( "Fuel (min=%dus, max=%dus)" % (self.servo_fuel.getMinUs(), self.servo_fuel.getMaxUs()), self) self.spinbox_cal_fuel = QSpinBox(self) self.spinbox_cal_fuel.setMinimum(500) self.spinbox_cal_fuel.setMaximum(2500) self.spinbox_cal_fuel.setSingleStep(1) self.spinbox_cal_fuel.setValue(self.servo_fuel.getPositionTargetUs()) self.spinbox_cal_fuel.setEnabled(False) self.spinbox_cal_fuel.valueChanged.connect(self.calFuelValueChanged) self.btn_cal_fuel_min = QPushButton("Set Min", self) self.btn_cal_fuel_min.setToolTip( "Set the Minimum Value, corresponds to 0%") self.btn_cal_fuel_min.clicked.connect(self.calFuelSetMin) self.btn_cal_fuel_min.setEnabled(False) self.btn_cal_fuel_min.resize(self.btn_cal_fuel_min.sizeHint()) self.btn_cal_fuel_max = QPushButton("Set Max", self) self.btn_cal_fuel_max.setToolTip( "Set the Maximum Value, corresponds to 100%") self.btn_cal_fuel_max.clicked.connect(self.calFuelSetMax) self.btn_cal_fuel_max.setEnabled(False) self.btn_cal_fuel_max.resize(self.btn_cal_fuel_max.sizeHint()) self.label_cal_oxidizer = QLabel( "Oxidizer (min=%dus, max=%dus)" % (self.servo_oxidizer.getMinUs(), self.servo_oxidizer.getMaxUs()), self) self.spinbox_cal_oxidizer = QSpinBox(self) self.spinbox_cal_oxidizer.setMinimum(500) self.spinbox_cal_oxidizer.setMaximum(2500) self.spinbox_cal_oxidizer.setSingleStep(1) self.spinbox_cal_oxidizer.setValue( self.servo_oxidizer.getPositionTargetUs()) self.spinbox_cal_oxidizer.setEnabled(False) self.spinbox_cal_oxidizer.valueChanged.connect( self.calOxidizerValueChanged) self.btn_cal_oxidizer_min = QPushButton("Set Min", self) self.btn_cal_oxidizer_min.setToolTip( "Set the Minimum Value, corresponds to 0%") self.btn_cal_oxidizer_min.clicked.connect(self.calOxidizerSetMin) self.btn_cal_oxidizer_min.setEnabled(False) self.btn_cal_oxidizer_min.resize(self.btn_cal_oxidizer_min.sizeHint()) self.btn_cal_oxidizer_max = QPushButton("Set Max", self) self.btn_cal_oxidizer_max.setToolTip( "Set the Maximum Value, corresponds to 100%") self.btn_cal_oxidizer_max.clicked.connect(self.calOxidizerSetMax) self.btn_cal_oxidizer_max.setEnabled(False) self.btn_cal_oxidizer_max.resize(self.btn_cal_oxidizer_max.sizeHint()) self.layout_calibration_fuel = QHBoxLayout() self.layout_calibration_fuel.addWidget(self.label_cal_fuel, alignment=Qt.AlignTop) self.layout_calibration_fuel.addWidget(self.spinbox_cal_fuel, alignment=Qt.AlignTop) self.layout_calibration_fuel.addWidget(self.btn_cal_fuel_min, alignment=Qt.AlignTop) self.layout_calibration_fuel.addWidget(self.btn_cal_fuel_max, alignment=Qt.AlignTop) self.layout_calibration_oxidizer = QHBoxLayout() self.layout_calibration_oxidizer.addWidget(self.label_cal_oxidizer, alignment=Qt.AlignTop) self.layout_calibration_oxidizer.addWidget(self.spinbox_cal_oxidizer, alignment=Qt.AlignTop) self.layout_calibration_oxidizer.addWidget(self.btn_cal_oxidizer_min, alignment=Qt.AlignTop) self.layout_calibration_oxidizer.addWidget(self.btn_cal_oxidizer_max, alignment=Qt.AlignTop) self.layout_calibration = QVBoxLayout() self.layout_calibration.addWidget(self.checkbox_calibration, alignment=Qt.AlignTop) self.layout_calibration.addLayout(self.layout_calibration_fuel) self.layout_calibration.addLayout(self.layout_calibration_oxidizer) self.tab_settings.layout.addLayout(self.layout_calibration) # Tabs self.tabs = QTabWidget() self.tabs.resize(300, 200) self.tabs.addTab(self.tab_main, "Main") self.tabs.addTab(self.tab_settings, "Settings") # Window self.layout = QVBoxLayout(self) self.layout.addWidget(self.tabs, alignment=Qt.AlignTop) self.setLayout(self.layout) self.setGeometry(500, 200, 900, 700) self.setWindowTitle("Engine Control UI") self.setWindowIcon(QIcon('icon.png')) #Timer self.timer.start() def socket_neo(self, string): #Socket for neopixel self.clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.clientsocket.connect(('raspberrypi.local', 25565)) self.clientsocket.send(string) self.clientsocket.close() def closeEvent(self, event): if self.btn_countdownStartStop.text() == "Abort": reply = QMessageBox.question( self, 'Message', "The countdown is running.\nQuit anyways?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) else: reply = QMessageBox.Yes if reply == QMessageBox.Yes: event.accept() else: event.ignore() def cleanup(self): self.servo_fuel.disable() self.servo_oxidizer.disable() self.stack.close() self.countdownTimer.stop() self.sequence.saveSequence() self.servo_fuel.saveSettings() self.servo_oxidizer.saveSettings() def countdownStartStopReset(self): if self.btn_countdownStartStop.text() == "Start": self.socket_neo(b'Testing') self.checkbox_calibration.setEnabled(False) self.calibrationDisable() self.checkbox_manualControl.setEnabled(False) self.manualControlDisable() self.countdownTimer.start() self.sequence.setStatus('running') self.btn_countdownStartStop.setText("Abort") self.btn_countdownStartStop.setToolTip("Stop the Countdown") self.btn_countdownStartStop.setStyleSheet( 'background-color: #FF0000;') self.servo_fuel.enable() self.servo_oxidizer.enable() elif self.btn_countdownStartStop.text() == "Abort": self.socket_neo(b'Error') if self.countdownTimer.getTime() < 0: self.countdownTimer.stop() self.btn_countdownStartStop.setText("Reset and Save Log") self.btn_countdownStartStop.setToolTip( "Reset the countdown and save logging data to a file") os.system("espeak -v en+f3 \"hold, hold, hold\" &") else: self.btn_countdownStartStop.setText("Stop") self.btn_countdownStartStop.setToolTip("Stop logging") os.system("espeak -v en+f3 \"abort\" &") self.sequence.setStatus('abort') self.countdownEvent() self.label_countdownClock.setStyleSheet('color: #ff0000') self.btn_countdownStartStop.setStyleSheet( 'background-color: #EEEEEE;') elif self.btn_countdownStartStop.text() == "Stop": self.countdownTimer.stop() os.system("espeak -v en+f3 \"stopped logging\" &") self.sequence.setStatus('abort') self.countdownEvent() self.label_countdownClock.setStyleSheet('color: #ff0000') self.btn_countdownStartStop.setText("Reset and Save Log") self.btn_countdownStartStop.setToolTip( "Reset the countdown and save logging data to a file") self.btn_countdownStartStop.setStyleSheet( 'background-color: #EEEEEE;') elif self.btn_countdownStartStop.text() == "Reset and Save Log": self.socket_neo(b'NoConn') self.set_safe = False logfile_name = f"{datetime.datetime.now():%Y%m%d_%H%M%S}.csv" # TODO: move logging to own class logfile_name_dir = 'log/' + logfile_name os.makedirs( os.path.dirname(logfile_name_dir), exist_ok=True) # generate log directory if non existent with open(logfile_name_dir, 'w', newline='') as logfile: fieldnames = [ 'Timestamp', 'ServoFuelPercentageTarget', 'ServoOxidizerPercentageTarget', 'ServoFuelPercentageCurrent', 'ServoOxidizerPercentageCurrent', 'PressureFuel', 'PressureOxidizer', 'PressureChamber', 'TemperatureChamber', 'Strain_data' ] writer = csv.DictWriter(logfile, fieldnames=fieldnames) writer.writeheader() for line in self.loggingValues: writer.writerow(line) self.loggingValues.clear() self.checkbox_calibration.setEnabled(True) self.checkbox_manualControl.setEnabled(True) self.countdownTimer.reset() self.sequence.setStatus('reset') self.countdownEvent() self.label_countdownClock.setStyleSheet('color: #000000') self.btn_countdownStartStop.setText("Start") self.btn_countdownStartStop.setToolTip("Start the Countdown") self.btn_countdownStartStop.setStyleSheet( 'background-color: #00FF00;') else: print("Error: invalid button state") def __timerTick( self ): # FIXME: bc of the hedgehog commands this often takes longer than 100ms, slowing down the countdown self.servo_fuel.updatePositionCurrentPercent() self.servo_oxidizer.updatePositionCurrentPercent() self.igniter_pyro.updateArmed() self.pressureSensor_fuel.updateValue() self.pressureSensor_oxidizer.updateValue() self.pressureSensor_chamber.updateValue() self.temperatureSensor_chamber.updateValue() voltageNew = self.hedgehog.get_analog(0x80) / 1000 self.inputVoltage = self.inputVoltage * 0.6 + voltageNew * 0.4 self.label_inputVoltage.setText("Input Voltage: %.1fV" % self.inputVoltage) self.label_manualControlFuel.setText( "Fuel Target: %3d%% Fuel Currently: %3d%% Fuel Pressure: %2.1fbar" % (self.servo_fuel.getPositionTargetPercent(), self.servo_fuel.getPositionCurrentPercent(), self.pressureSensor_fuel.getValue())) self.label_manualControlOxidizer.setText( "Oxidizer Target: %3d%% Oxidizer Currently: %3d%% Oxidizer Pressure: %2.1fbar" % (self.servo_oxidizer.getPositionTargetPercent(), self.servo_oxidizer.getPositionCurrentPercent(), self.pressureSensor_oxidizer.getValue())) if self.igniter_pyro.getArmed() is not None: if self.igniter_pyro.getArmed() is True: self.checkbox_manualControlIgniter.setText("Igniter (Armed)") if not self.set_igniter: self.socket_neo(b'Error') self.set_igniter = True else: self.checkbox_manualControlIgniter.setText( "Igniter (Disarmed)") if self.set_igniter: if (not self.set_safe) and ( self.pressureSensor_oxidizer.getValue() < 0.5 and self.pressureSensor_fuel.getValue() < 0.5): self.socket_neo(b'SafeOn') self.set_safe = True if self.set_safe and ( self.pressureSensor_oxidizer.getValue() > 2 and self.pressureSensor_fuel.getValue() > 2): self.socket_neo(b'NoConn') self.set_safe = False self.set_igniter = False else: self.checkbox_manualControlIgniter.setText("Igniter (Unknown)") if (not self.set_safe) and ( self.pressureSensor_oxidizer.getValue() < 0.5 and self.pressureSensor_fuel.getValue() < 0.5): self.socket_neo(b'SafeOn') self.set_safe = True if self.set_safe and (self.pressureSensor_oxidizer.getValue() > 2 or self.pressureSensor_fuel.getValue() > 2): self.socket_neo(b'NoConn') self.set_safe = False def countdownEvent(self): # abort if no ignition detected TODO: improve if self.autoabortEnabled: if self.pressureSensor_chamber.getValue( ) < self.sequence.getChamberPressureMinAtTime( self.countdownTimer.getTime( )) and not self.btn_countdownStartStop.text() == "Stop": self.socket_neo(b'Error') self.btn_countdownStartStop.setText("Stop") os.system("espeak -v en+f3 \"auto abort\" &") #self.countdownTimer.stop() # TODO: make timer continue self.sequence.setStatus('abort') self.label_countdownClock.setStyleSheet('color: #ff0000') self.btn_countdownStartStop.setToolTip("Stop logging") self.btn_countdownStartStop.setStyleSheet( 'background-color: #EEEEEE;') if self.countdownTimer.getTime() > 3 + self.sequence.getTimestampList( )[len(self.sequence.getTimestampList()) - 2] and ( self.btn_countdownStartStop.text() == "Abort" or self.btn_countdownStartStop.text() == "Stop") and self.servo_fuel.getPositionTargetPercent( ) == 0 and self.servo_oxidizer.getPositionTargetPercent( ) == 0: #Yes I hate myself for this crude fix self.btn_countdownStartStop.setText("Reset and Save Log") os.system("espeak -v en+f3 \"sequence finished\" &") self.countdownTimer.stop() self.sequence.setStatus('abort') self.countdownEvent() self.label_countdownClock.setStyleSheet('color: #ff0000') self.btn_countdownStartStop.setToolTip( "Reset the countdown and save logging data to a file") self.btn_countdownStartStop.setStyleSheet( 'background-color: #EEEEEE;') # outputs set values self.label_countdownClock.setText(self.countdownTimer.getTimeString()) self.servo_fuel.setPositionTargetPercent( self.sequence.getFuelAtTime(self.countdownTimer.getTime())) self.servo_oxidizer.setPositionTargetPercent( self.sequence.getOxidizerAtTime(self.countdownTimer.getTime())) self.igniter_arc.set( self.sequence.getIgniterAtTime(self.countdownTimer.getTime())) self.igniter_pyro.set( self.sequence.getIgniterAtTime(self.countdownTimer.getTime())) self.sequencePlot.redrawMarkers() # update ui self.checkbox_manualControlIgniter.setChecked( self.sequence.getIgniterAtTime(self.countdownTimer.getTime())) self.slider_manualControlFuel.setValue( self.sequence.getFuelAtTime(self.countdownTimer.getTime())) self.slider_manualControlOxidizer.setValue( self.sequence.getOxidizerAtTime(self.countdownTimer.getTime())) # sensors get values self.loggingValues.append({ 'Timestamp': self.countdownTimer.getTime(), 'ServoFuelPercentageTarget': self.servo_fuel.getPositionTargetPercent(), 'ServoOxidizerPercentageTarget': self.servo_oxidizer.getPositionTargetPercent(), 'ServoFuelPercentageCurrent': self.servo_fuel.getPositionCurrentPercent(), 'ServoOxidizerPercentageCurrent': self.servo_oxidizer.getPositionCurrentPercent(), 'PressureFuel': self.pressureSensor_fuel.getValue(), 'PressureOxidizer': self.pressureSensor_oxidizer.getValue(), 'PressureChamber': self.pressureSensor_chamber.getValue(), 'TemperatureChamber': self.temperatureSensor_chamber.getValue(), 'Strain_data': self.measure.read_data() }) def manualControlEnable(self): print("Manual Control Enabled") os.system("espeak -v en+f3 -s 140 \"manuel override enable\" &") self.checkbox_manualControl.setChecked(True) self.btn_countdownStartStop.setEnabled( False) # FIXME: doesn't do anything?! self.checkbox_calibration.setEnabled(False) self.calibrationDisable() self.checkbox_manualControlIgniter.setEnabled(True) self.slider_manualControlFuel.setEnabled(True) self.slider_manualControlOxidizer.setEnabled(True) self.servo_fuel.enable() self.servo_oxidizer.enable() def manualControlDisable(self): print("Manual Control Disabled") #os.system("espeak -v en+f3 -s 140 \"manuel override disabled\" &") self.checkbox_manualControl.setChecked(False) self.checkbox_manualControlIgniter.setEnabled(False) self.checkbox_manualControlIgniter.setChecked(False) self.slider_manualControlFuel.setEnabled(False) self.slider_manualControlOxidizer.setEnabled(False) self.manualControlIgniterDisable() self.countdownEvent() self.btn_countdownStartStop.setEnabled(True) self.checkbox_calibration.setEnabled(True) def manualControlEnableDisable( self ): # TODO: rename to __checkbox_manualControl_onClick, same for other callbacks if self.checkbox_manualControl.isChecked(): self.manualControlEnable() else: self.manualControlDisable() def manualControlIgniterEnable(self): print("Manual Igniter ON") self.igniter_arc.set(True) self.igniter_pyro.set(True) def manualControlIgniterDisable(self): print("Manual Igniter OFF") self.igniter_arc.set(False) self.igniter_pyro.set(False) def manualControlIgniterEnableDisable(self): if self.checkbox_manualControlIgniter.isChecked(): self.manualControlIgniterEnable() else: self.manualControlIgniterDisable() def manualControlFuelChange(self): self.servo_fuel.setPositionTargetPercent( self.slider_manualControlFuel.value()) self.label_manualControlFuel.setText( "Fuel Target: %3d%% Fuel Currently: %3d%% Fuel Pressure: %2.1fbar" % (self.servo_fuel.getPositionTargetPercent(), self.servo_fuel.getPositionCurrentPercent(), self.pressureSensor_fuel.getValue())) def manualControlOxidizerChange(self): self.servo_oxidizer.setPositionTargetPercent( self.slider_manualControlOxidizer.value()) self.label_manualControlOxidizer.setText( "Oxidizer Target: %3d%% Oxidizer Currently: %3d%% Oxidizer Pressure: %2.1fbar" % (self.servo_oxidizer.getPositionTargetPercent(), self.servo_oxidizer.getPositionCurrentPercent(), self.pressureSensor_oxidizer.getValue())) def calibrationEnable(self): print("Calibration Mode Enabled") self.btn_countdownStartStop.setEnabled(False) self.checkbox_manualControl.setEnabled(False) self.manualControlDisable() self.checkbox_calibration.setChecked(True) self.spinbox_cal_fuel.setEnabled(True) self.spinbox_cal_oxidizer.setEnabled(True) self.btn_cal_fuel_min.setEnabled(True) self.btn_cal_fuel_max.setEnabled(True) self.btn_cal_oxidizer_min.setEnabled(True) self.btn_cal_oxidizer_max.setEnabled(True) self.servo_fuel.enable() self.servo_oxidizer.enable() def calibrationDisable(self): print("Calibration Mode Disabled") self.checkbox_calibration.setChecked(False) self.spinbox_cal_fuel.setEnabled(False) self.spinbox_cal_oxidizer.setEnabled(False) self.btn_cal_fuel_min.setEnabled(False) self.btn_cal_fuel_max.setEnabled(False) self.btn_cal_oxidizer_min.setEnabled(False) self.btn_cal_oxidizer_max.setEnabled(False) self.countdownEvent() self.btn_countdownStartStop.setEnabled(True) self.checkbox_manualControl.setEnabled(True) def calibrationEnableDisable(self): if self.checkbox_calibration.isChecked(): self.calibrationEnable() else: self.calibrationDisable() def calFuelValueChanged(self): if self.checkbox_calibration.isChecked(): self.servo_fuel.setPositionTargetUs(self.spinbox_cal_fuel.value()) def calOxidizerValueChanged(self): if self.checkbox_calibration.isChecked(): self.servo_oxidizer.setPositionTargetUs( self.spinbox_cal_oxidizer.value()) def calFuelSetMin(self): if self.checkbox_calibration.isChecked(): self.servo_fuel.calMin() self.label_cal_fuel.setText( "Fuel (min=%dus, max=%dus)" % (self.servo_fuel.getMinUs(), self.servo_fuel.getMaxUs())) def calFuelSetMax(self): if self.checkbox_calibration.isChecked(): self.servo_fuel.calMax() self.label_cal_fuel.setText( "Fuel (min=%dus, max=%dus)" % (self.servo_fuel.getMinUs(), self.servo_fuel.getMaxUs())) def calOxidizerSetMin(self): if self.checkbox_calibration.isChecked(): self.servo_oxidizer.calMin() self.label_cal_oxidizer.setText("Oxidizer (min=%dus, max=%dus)" % (self.servo_oxidizer.getMinUs(), self.servo_oxidizer.getMaxUs())) def calOxidizerSetMax(self): if self.checkbox_calibration.isChecked(): self.servo_oxidizer.calMax() self.label_cal_oxidizer.setText("Oxidizer (min=%dus, max=%dus)" % (self.servo_oxidizer.getMinUs(), self.servo_oxidizer.getMaxUs()))
def main(): # Declare paths. src = './CompostMonitoringData' destination = '/media/pi/537D-B88D/Sensor_Data' # Change the destination according to your uSB address. save_timer = 0 # Declare the lcd display screen. lcd = lcddriver.lcd() # Declaring the objects. moisture_one = MoistureSensor(MCP.P0) moisture_two = MoistureSensor(MCP.P1) moisture_three = MoistureSensor(MCP.P3) temp_one = TemperatureSensor(0) temp_two = TemperatureSensor(1) temp_three = TemperatureSensor(2) # Calibrates the sensors in parallel. p1 = Process(target=moisture_one.calibrate()) p1.start() p2 = Process(target=moisture_two.calibrate()) p2.start() p3 = Process(target=moisture_three.calibrate()) p3.start() p1.join() p2.join() p3.join() db = PickleShareDB('./CompostMonitoringData') while (True): # Sets up the temperature variables. temperature_one = temp_one.read_temp() temperature_two = temp_two.read_temp() temperature_three = temp_three.read_temp() current_M1_Val = moisture_one.mapSensorVals() current_M2_Val = moisture_two.mapSensorVals() current_M3_Val = moisture_three.mapSensorVals() dt_string = dt.now().strftime("%d/%m/%Y %H:%M:%S") # Loads the json from the database. if 'data' not in db.keys(): db['data'] = [] # Stores existing data from pickleShare db into existing_data. existing_data = db['data'] # Creates a dict of the current vals. curr_data = { 'moisture_value_1': current_M1_Val, 'moisture_value_2': current_M2_Val, 'moisture_value_3': current_M3_Val, 'temp_value_1': temperature_one, 'temp_value_2': temperature_two, 'temp_value_3': temperature_three, 'time': dt_string, } # Appends the new data. existing_data.append(curr_data) # if(check_connection()): # db.clear() store_locally(db, existing_data) # Prints the current values. print("Current value", current_M1_Val, current_M2_Val, current_M3_Val, '\n\tCurrent Time:', dt_string) print("Current Temps:\n\t" + str(temperature_one) + "\n\t" + str(temperature_two) + "\n\t" + str(temperature_three)) avg_moisture_val = (current_M1_Val + current_M2_Val + current_M3_Val) / 3 avg_temperature = (temperature_one + temperature_two + temperature_three) / 3 # Display the values on the lcd. lcd.lcd_display_string( "Avg Val: " + str(avg_moisture_val) + " " + str(avg_temperature), 1) lcd.lcd_display_string( "Probe 1: " + str(current_M1_Val) + " " + str(temperature_one), 2) lcd.lcd_display_string( "Probe 2: " + str(current_M2_Val) + " " + str(temperature_two), 3) lcd.lcd_display_string( "Probe 3: " + str(current_M3_Val) + " " + str(temperature_three), 4) save_timer += 1 # Tries to save data to removable drive every 30 minutes. if (save_timer == 1800): store_to_removable(src, destination) if store_to_removable == 1: save_timer = 0 else: # If it can't save it tries every 10 minutes save_timer = 1200 time.sleep(5)
socketio = SocketIO(app) @app.route("/") def index(): return render_template('index.html') #def message_loop(): # while True: # message = input('Mouvement détecté') # socketio.emit('alert', message, Broadcast=True) # Vue que notre méthode pour lire nos message est une boucle infinie # Elle bloquerait notre serveur. Qui ne pourrait répondre à aucune requête. # Ici nous créons un Thread qui va permettre à notre fonction de se lancer # en parallèle du serveur. #read_messages = threading.Thread(target=message_loop) #read_messages.start() mouvement = Mouvement(17) temp_c = TemperatureSensor() read_mouvement = threading.Thread(target=mouvement.mouvement_loop, args=(socketio, )) read_mouvement.start() read_temperature = threading.Thread(target=temp_c.temperature_loop, args=(socketio, )) read_temperature.start()
from time import sleep from Wifi import is_connected from Server import Server from TemperatureSensor import TemperatureSensor from config import config if not is_connected(): print('No connection found, exiting...') exit() sensor = TemperatureSensor(pin_id=config['sensor']['pin']) server = Server( host=config['server']['host'], port=config['server']['port'], ) while True: temperatures = sensor.read() if not temperatures: print('Error while reading temperatures, exiting...') exit() print('Temperatures read:', temperatures) server.post('sensor/' + config['sensor']['id'], {'temperature': temperatures[0]}) sleep(config['measure']['period'])