示例#1
0
   def start(self):
      
      Igniter.start(self)

      # Signals assignment
      signal.signal(signal.SIGTERM, self._shutdown)
      signal.signal(signal.SIGINT, self._shutdown)
      signal.signal(signal.SIGHUP, self._reload)
      self.logger.info("%s %s has been started" % (self.direction.capitalize(), self.flowName))
示例#2
0
   def __init__(self, direction, flowName, cmd, lockPath, logger=None):
      Igniter.__init__(self, cmd, lockPath) # Parent constructor
      self.direction = direction            # A string in ['sender', 'receiver']
      self.flowName = flowName              # Client or Source's name
      self.logger = logger                  # Logger object
      self.type = None                      # wmo, am, etc. (string)
      self.flow = None                      # Client or Source object
      self.gateway = None                   # Gateway object
      self.reloadMode = False               # Indicate if we are in reload mode or not

      eval("self." + cmd)()                 # Execute the command directly
示例#3
0
class unittest_Igniter(unittest.TestCase):
   
  def setUp(self):
    self.igniter = Igniter('ping localhost', '/tmp/')
    self.process = subprocess.Popen(['ping', 'localhost'], shell=False, stdout=subprocess.PIPE)
    #file = open('/tmp/.lock','w')
    #file.write(str(self.process.pid))   
    #file.close()
    #self.igniter.lock = '/tmp/.lock'
    #self.igniter.lockpid = self.process.pid    
    
  def test_Igniter(self):      
    self.assertEqual(self.igniter.makeLock(),None)
    self.igniter.lock = '/tmp/.lock'
    self.igniter.lockpid = self.process.pid    
    file = open('/tmp/.lock','w')
    file.write(str(self.process.pid))   
    file.close()    
    print '\n'
    self.assertEqual(self.igniter.isLocked(),self.process.pid)
    try:      
      self.igniter.start()
      self.igniter.lockpid =''
    except:
      self.assertEqual(self.igniter.lockpid,self.process.pid)
    try:      
      self.igniter.status()
      self.igniter.lockpid =''
    except:
      self.assertEqual(self.igniter.lockpid,self.process.pid)
    try:      
      self.igniter.stop()
      self.igniter.lockpid =''
    except:
      self.assertEqual(self.igniter.lockpid,self.process.pid)    
    try:      
      self.igniter.status()
      self.igniter.lockpid =''
    except:
      self.assertEqual(self.igniter.lockpid,self.process.pid)      
    #try:      
      #self.igniter.start()
      #self.igniter.lockpid =''
    #except:
      #self.assertEqual(self.igniter.lockpid,self.process.pid)        
    try:
      self.process.terminate()
    except:
      pass
示例#4
0
   def reload(self):
      """
      If the process is locked (presence of a .lock file) and running (ps), send a SIGHUP
      signal to it. The function _reload will be called because SIGHUP signal is assigned 
      to it.
      """
      # Verify user is not root
      if os.getuid() == 0:
         print "FATAL: Do not reload as root. It will be a mess."
         sys.exit(2)
         
      if Igniter.isLocked(self) and not commands.getstatusoutput('ps -p ' + str(self.lockpid))[0]:
         # SIGHUP is sent to initiate the reload
         os.kill(self.lockpid, signal.SIGHUP) 
      else:
         print "No process to reload for %s (%s %s)!" % (self.flowName, self.direction, self.type)

      # In any case, we exit!!
      sys.exit(2)
示例#5
0
    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()
示例#6
0
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()))
示例#7
0
 def setUp(self):
   self.igniter = Igniter('ping localhost', '/tmp/')
   self.process = subprocess.Popen(['ping', 'localhost'], shell=False, stdout=subprocess.PIPE)