示例#1
0
class AppWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.sensorAppInit()
        self.read_data()
        self.show()

    def sensorAppInit(self):

        # Initialize variables we need
        self.currentSensor = 1

        self.function_indicator = {
            1: self.ui.led_sensor,
            2: self.ui.led_temp,
            3: self.ui.led_hum,
            4: self.ui.led_t_alarm,
            5: self.ui.led_h_alarm
        }

        self.functionNumber = 1

        self.displayCelcius = False

        # Initialize the state of the UI
        self.ui.screen_output.setText("INITIALIZING")

        # Initialize UI timer for updates
        self.timer = QTimer()

        # Create instance of monitor class
        self.monitor = Monitor()

        # Register functions to corresponding event
        self.ui.pb_select.released.connect(self.select_button)
        self.ui.pb_up.released.connect(self.up_button)
        self.ui.pb_down.released.connect(self.down_button)
        self.ui.pb_convertTemp.released.connect(self.convertTemp_button)
        self.timer.timeout.connect(self.read_data)
        self.timer.start(10000)

    def select_button(self):

        # Uncheck current button
        for num in range(1, 6):
            self.function_indicator[self.functionNumber].setChecked(False)

        # Wrap around or not
        if (self.functionNumber < 5):
            self.functionNumber += 1
        else:
            self.functionNumber = 1

        # Check next box
        self.function_indicator[self.functionNumber].setChecked(True)

        self.updateOutput()

    # Up button released event
    def up_button(self):

        function = UI_Helper.UI_FUNCTIONS[self.functionNumber]

        if (function == 'SensorNumber'):
            if self.currentSensor < NUM_SENSORS:
                self.currentSensor += 1

        elif (function == 'TempAlarmCount' or function == 'HumAlarmCount'):

            alarm = UI_Helper.getSensorAlarm(self.currentSensor,
                                             self.functionNumber)['val']
            alarm += 1
            UI_Helper.setSensorAlarmVal(alarm, self.currentSensor,
                                        self.functionNumber)

        self.updateOutput()

    # Down Button released event
    def down_button(self):

        function = UI_Helper.UI_FUNCTIONS[self.functionNumber]

        if (function == 'SensorNumber'):
            if self.currentSensor > 1:
                self.currentSensor -= 1

        elif (function == 'TempAlarmCount' or function == 'HumAlarmCount'):

            alarm = UI_Helper.getSensorAlarm(self.currentSensor,
                                             self.functionNumber)['val']
            alarm -= 1
            UI_Helper.setSensorAlarmVal(alarm, self.currentSensor,
                                        self.functionNumber)

        self.updateOutput()

    def convertTemp_button(self):
        self.displayCelcius = ~(self.displayCelcius)
        self.updateOutput()

    def read_data(self):
        self.monitor.read_sensor_data()

        # for each sensor, get the last measurement and update the alarm count as needed
        for sensor in range(1, NUM_SENSORS + 1):
            lastMeasurement = self.monitor.get_last_sensor_data(sensor)
            if (lastMeasurement == None):
                return

            TAlarm = UI_Helper.getSensorAlarm(sensor, 4)['val']
            HAlarm = UI_Helper.getSensorAlarm(sensor, 5)['val']

            if (lastMeasurement['CurrentTemp'] > TAlarm
                    and lastMeasurement['CurrentTemp'] != 999):
                UI_Helper.incSensorAlarmCount(sensor, 4)

            if (lastMeasurement['CurrentHumidity'] > HAlarm
                    and lastMeasurement['CurrentHumidity'] != 999):
                UI_Helper.incSensorAlarmCount(sensor, 5)

        self.updateOutput()

    def updateOutput(self):
        # get the last measurement
        lastMeasurement = self.monitor.get_last_sensor_data(self.currentSensor)

        ## Ensure there is valid data to display
        if (lastMeasurement == None):
            self.ui.screen_output.setText(" INITIALIZING ")
            return

        neededData = lastMeasurement[UI_Helper.UI_FUNCTIONS[
            self.functionNumber]]

        errorCount = lastMeasurement['ErrorCount']

        # Construct standard part of display
        displayString = "S0" + str(self.currentSensor) + ":"

        # Format the data correctly
        dataString = " "

        function = UI_Helper.UI_FUNCTIONS[self.functionNumber]
        ## Display Temperature
        if (function == 'CurrentTemp'):

            if (self.displayCelcius):
                dataString = str(
                    self.monitor.fahrenheit_to_celsius(neededData)) + " Deg C "
            else:
                dataString = str(UI_Helper.roundFloat(neededData)) + " Deg F "

        elif (function == 'CurrentHumidity'):

            dataString = str(UI_Helper.roundFloat(neededData)) + " % RH  "

        elif (function == 'TempAlarmCount'):

            alarm = UI_Helper.getSensorAlarm(self.currentSensor,
                                             self.functionNumber)

            if (self.displayCelcius):
                dataString = "Thresh:" + str(
                    UI_Helper.roundFloat(
                        self.monitor.fahrenheit_to_celsius(
                            alarm['val']))) + " Deg C, Count:" + str(
                                alarm['count'])
            else:
                dataString = "Thresh:" + str(UI_Helper.roundFloat(
                    alarm['val'])) + " Deg F, Count:" + str(alarm['count'])

        elif (function == 'HumAlarmCount'):

            alarm = UI_Helper.getSensorAlarm(self.currentSensor,
                                             self.functionNumber)

            dataString = "Thresh:" + str(UI_Helper.roundFloat(
                alarm['val'])) + "% RH, Count:" + str(alarm['count'])

        displayString += dataString

        displayString += " Errors: " + str(errorCount)

        self.ui.screen_output.setText(displayString)
class AppWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.sensorAppInit()
        self.periodic_update()
        self.show()

    def sensorAppInit(self):

        # Initialize variables we need
        self.currentSensor = 1

        # dictionary of QT measurement output objects
        self.measurement_output_displays = {
            1: self.ui.s1_measurement_output,
            2: self.ui.s2_measurement_output,
            3: self.ui.s3_measurement_output,
            4: self.ui.s4_measurement_output,
            5: self.ui.s5_measurement_output,
            6: self.ui.s6_measurement_output
        }

        # dictionary of QT alarm input objects
        self.alarm_inputs = {
            1: {
                'Temp': self.ui.s1_T_alarm,
                'Hum': self.ui.s1_H_alarm
            },
            2: {
                'Temp': self.ui.s2_T_alarm,
                'Hum': self.ui.s2_H_alarm
            },
            3: {
                'Temp': self.ui.s3_T_alarm,
                'Hum': self.ui.s3_H_alarm
            },
            4: {
                'Temp': self.ui.s4_T_alarm,
                'Hum': self.ui.s4_H_alarm
            },
            5: {
                'Temp': self.ui.s5_T_alarm,
                'Hum': self.ui.s5_H_alarm
            },
            6: {
                'Temp': self.ui.s6_T_alarm,
                'Hum': self.ui.s6_H_alarm
            }
        }

        # dictionary of QT alarm output objects
        self.alarm_count_outputs = {
            1: {
                'Temp': self.ui.s1_Talarm_cnt_out,
                'Hum': self.ui.s1_Halarm_cnt_out
            },
            2: {
                'Temp': self.ui.s2_Talarm_cnt_out,
                'Hum': self.ui.s2_Halarm_cnt_out
            },
            3: {
                'Temp': self.ui.s3_Talarm_cnt_out,
                'Hum': self.ui.s3_Halarm_cnt_out
            },
            4: {
                'Temp': self.ui.s4_Talarm_cnt_out,
                'Hum': self.ui.s4_Halarm_cnt_out
            },
            5: {
                'Temp': self.ui.s5_Talarm_cnt_out,
                'Hum': self.ui.s5_Halarm_cnt_out
            },
            6: {
                'Temp': self.ui.s6_Talarm_cnt_out,
                'Hum': self.ui.s6_Halarm_cnt_out
            }
        }

        # dictionary of QT error output objects
        self.error_outputs = {
            1: self.ui.s1_error_output,
            2: self.ui.s2_error_output,
            3: self.ui.s3_error_output,
            4: self.ui.s4_error_output,
            5: self.ui.s5_error_output,
            6: self.ui.s6_error_output
        }

        # connect the F/C slider to the event handler function
        self.ui.slider_F_C.sliderReleased.connect(
            self.disp_format_slider_moved)

        # Connect alarm input boxes to event handler
        for sensor_num in self.alarm_inputs.keys():

            for input_field, sb_obj in self.alarm_inputs[sensor_num].items():
                sb_obj.valueChanged.connect(self.alarm_input_handler)

        # Boolean to prevent the UI from updating the alarms when we are updating them here
        self.editing_alarms = False

        self.ui.tabWidget.setCurrentIndex(0)

        # Initialize UI timer for updates
        self.timer = QTimer()

        # Create instance of monitor class
        self.monitor = Monitor()

        # Register functions to corresponding event
        self.timer.timeout.connect(self.periodic_update)
        self.timer.start(10000)
        self.updateOutput()

    def alarm_input_handler(self):

        if (not self.editing_alarms
            ):  # check that we're not manually editing the alarms
            # for all the alarms, update the local copy of the alarms with
            # the new values in the UI
            for num in self.alarm_inputs.keys():

                for input_field, sb_obj in self.alarm_inputs[num].items():
                    new_alarm_val = sb_obj.value()

                    if (input_field == 'Temp'):
                        UI_Helper.setSensorAlarmVal(new_alarm_val, num, 4)
                    else:
                        UI_Helper.setSensorAlarmVal(new_alarm_val, num, 5)

    # event handler for when the F/C slider is moved
    def disp_format_slider_moved(self):

        lastState = self.monitor.fahrenheit

        if (self.ui.slider_F_C.value() == 0):  # if we want Fahrenheit

            self.monitor.fahrenheit = True
            if (lastState != self.monitor.fahrenheit):
                UI_Helper.convertAlarmVals(self.monitor.fahrenheit)

        else:  # if we want Celcius
            self.monitor.fahrenheit = False
            if (lastState != self.monitor.fahrenheit):
                UI_Helper.convertAlarmVals(self.monitor.fahrenheit)

        # Update all of the data to use the new units and update the display
        self.monitor.read_sensor_data()
        self.updateOutput()

    # this function gets called every 10 seconds to read new data and update the UI
    def periodic_update(self):
        self.monitor.read_sensor_data()

        for sensor in self.measurement_output_displays.keys(
        ):  # for all sensors

            # Get the last measurement and set alarms as needed
            lastMeasurement = self.monitor.get_last_sensor_data(sensor)
            if (lastMeasurement == None):
                return

            TAlarm = UI_Helper.getSensorAlarm(sensor, 4)['val']
            HAlarm = UI_Helper.getSensorAlarm(sensor, 5)['val']

            if (lastMeasurement['CurrentTemp'] > TAlarm
                    and lastMeasurement['CurrentTemp'] != 999):
                UI_Helper.incSensorAlarmCount(sensor, 4)

            if (lastMeasurement['CurrentHumidity'] > HAlarm
                    and lastMeasurement['CurrentHumidity'] != 999):
                UI_Helper.incSensorAlarmCount(sensor, 5)

        # update the output
        self.updateOutput()

    def updateOutput(self):
        self.update_measurements()
        self.update_alarm_displays()
        self.update_errors()
        self.update_graphs()

    def update_graphs(self):
        temps = {}
        hums = {}

        if (self.monitor.all_sensor_data == {}):
            # if there isn't any sensor data yet, just return
            return

        # for all sensors
        for sensor_id, sensor_data in self.monitor.all_sensor_data.items():
            # add the sensor to temps and hums if it's not there already
            if sensor_id not in temps:
                temps[sensor_id] = []
                hums[sensor_id] = []

            # Go through all the data and add the temps and humidities to an
            # list that will be used for graphing, ignoring measurements that
            # are 999.0
            for entry in sensor_data:
                temp = entry['CurrentTemp']
                humidity = entry['CurrentHumidity']
                if temp == 999.0:
                    temp = np.nan
                if humidity == 999.0:
                    humidity = np.nan
                temps[sensor_id].append(temp)
                hums[sensor_id].append(humidity)

        # numEntries = len(temps[1])

        # timevals = np.arange(0, 10*numEntries, 10)

        self.ui.plotWidget.canvas.fig.clear()
        self.ui.plotWidget.canvas.ax = self.ui.plotWidget.canvas.fig.subplots(
            3, 2)

        # Plot all the sensor data!
        for sensor_id in self.monitor.all_sensor_data.keys():
            tempList = temps[sensor_id]
            humList = hums[sensor_id]

            numEntries = len(tempList)
            timevals = np.arange(0, 10 * numEntries, 10)
            title = 'Sensor ' + str(sensor_id)
            row = int((sensor_id - 1) / 2)
            col = (sensor_id - 1) % 2

            # plotting help from:
            # https://matplotlib.org/3.2.1/gallery/subplots_axes_and_figures/two_scales.html
            temp_color = 'tab:blue'
            hum_color = 'tab:orange'
            self.ui.plotWidget.canvas.ax[row][col].set_title(title)
            self.ui.plotWidget.canvas.ax[row][col].set_xlabel('time (s)')
            units = '(F)'
            if not self.monitor.fahrenheit:
                units = '(C)'
            self.ui.plotWidget.canvas.ax[row][col].set_ylabel('Temperature ' +
                                                              units,
                                                              color=temp_color)
            self.ui.plotWidget.canvas.ax[row][col].plot(timevals,
                                                        tempList,
                                                        color=temp_color)
            self.ui.plotWidget.canvas.ax[row][col].tick_params(
                axis='y', labelcolor=temp_color)

            # get a copy of the axis so we can plot both temperature and humidity
            # on the same graph
            ax_hum = self.ui.plotWidget.canvas.ax[row][col].twinx()
            ax_hum.plot(timevals, humList, color=hum_color)
            ax_hum.set_ylabel('Humidity (%)', color=hum_color)
            ax_hum.tick_params(axis='y', labelcolor=hum_color)

        # Finally, draw everything
        self.ui.plotWidget.canvas.draw()

    def update_measurements(self):
        # For each sensor, get the last measurement.
        # Try to round it and display it, but if there was an exception,
        # that means there isn't any valid data yet
        for sensor_num, display in self.measurement_output_displays.items():

            try:
                lastMeasurement = self.monitor.get_last_sensor_data(sensor_num)
                temp = UI_Helper.roundFloat(lastMeasurement['CurrentTemp'])
                hum = UI_Helper.roundFloat(lastMeasurement['CurrentHumidity'])

                if self.monitor.fahrenheit:
                    display_string = str(temp) + " F\n" + str(hum) + "% RH\n"
                else:
                    display_string = str(temp) + " C\n" + str(hum) + "% RH\n"

            except:
                display_string = '888'
                print("No Valid Data Yet")

            display.setText(display_string)

    def update_errors(self):
        # For each sensor, get the last error count, then display it. If there
        # isn't a last measurement, that means there isn't any valid data yet
        for sensor_num, display in self.error_outputs.items():
            try:
                lastMeasurement = self.monitor.get_last_sensor_data(sensor_num)
                num_errors = lastMeasurement['ErrorCount']
                if (num_errors == 1):
                    display_string = str(num_errors) + " Error"
                else:
                    display_string = str(num_errors) + " Errors"

            except:
                display_string = '888'
                print("No Valid Dat Yet")

            display.setText(display_string)

    def update_alarm_displays(self):

        self.editing_alarms = True  # set to true to prevent the UI from updating anything

        # For each sensor, get the latest alarm counts (for both temp and humidity)
        # and display them
        for sensor_num in self.alarm_count_outputs.keys():

            for alarm_field, display in self.alarm_count_outputs[
                    sensor_num].items():

                if (alarm_field == "Temp"):
                    alarm = UI_Helper.getSensorAlarm(sensor_num, 4)['count']
                    display.setText(str(alarm))
                else:
                    alarm = UI_Helper.getSensorAlarm(sensor_num, 5)['count']
                    display.setText(str(alarm))

        # For each sensor, get the latest alarm thresholds (for both temp and humidity)
        # and display them
        for sensor_num in self.alarm_inputs.keys():

            for alarm_field, display in self.alarm_inputs[sensor_num].items():

                if (alarm_field == "Temp"):
                    alarm = UI_Helper.getSensorAlarm(sensor_num, 4)['val']
                    display.setValue(int(alarm))
                else:
                    alarm = UI_Helper.getSensorAlarm(sensor_num, 5)['val']
                    display.setValue(int(alarm))

        self.editing_alarms = False  # allow the UI to update things again