Example #1
0
    def startSensorReader(self, tunnelWindow, tunnelDataQ):
        useSimulatedData = self.config.getItem("General", "UseSimulatedData")
        if (useSimulatedData is None):
            self.sensorRdr = SensorReader(tunnelWindow, tunnelDataQ)

        if (useSimulatedData.lower() == "true"):
            print("Starting data simulator")
            self.sensorRdr = SensorSimulator(tunnelWindow, tunnelDataQ)
        else:
            self.sensorRdr = SensorReader(tunnelWindow, tunnelDataQ)

        self.sensorRdr.daemon = True
        self.sensorRdr.start()
Example #2
0
def main():
    parser = argparse.ArgumentParser(description='Send senor data over MQTT.')
    parser.add_argument(
        '--host',
        action="store",
        dest="mqtt_host",
        default="localhost",
        help='Location of the MQTT broker. Defaults to localhost.')
    parser.add_argument('--port',
                        action="store",
                        dest="mqtt_port",
                        default=1883,
                        type=int,
                        help='MQTT port for the broker. Defaults to 1883.')
    # parser.add_argument('--user', action="store", dest="mqtt_user", help="Username used to login to the broker.")
    # parser.add_argument('--pass', action="store", dest="mqtt_pass", help="Password used to login to the broker.")
    parser.add_argument('--topic',
                        action="store",
                        dest="mqtt_prefix",
                        default="",
                        help="Base topic to broadcast on. Defaults to none.")
    parser.add_argument(
        '--time',
        action="store",
        dest="sensor_time",
        default=0xD5,
        type=arg_sensor_time,
        help=
        """Integration time for the sensors, in milliseconds. Must be in range: [2.4, 612]. 
                        Defaults to 100.8ms""")
    parser.add_argument(
        '--gain',
        action="store",
        dest="sensor_gain",
        default=1,
        type=arg_sensor_gain,
        help="Gain for sensors. Must be one of: [1, 4, 16, 60] Defaults to 1.")
    parser.add_argument('--group',
                        action="store",
                        dest="group_id",
                        default="0",
                        help='Group id on MQTT.')
    args = parser.parse_args()

    # Create MQTT client
    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect(args.mqtt_host, args.mqtt_port, 60)

    # Start a background thread to handle the client
    client.loop_start()

    # Process sensor data
    try:
        print("Initializing sensors")
        # Create and init sensor reader
        sensor_reader = SensorReader(args.sensor_time, args.sensor_gain)
        sensor_reader.initialize()
        print("Initialization complete")

        print("Streaming data")
        while True:
            start_time = time.time()
            # Get readings from all sensors
            data = sensor_reader.read_sensors()
            # Publish readings
            for mux_id in range(0, len(data)):
                mux_data = data[mux_id]
                # Missing multiplexers will produce an empty list of readings
                for sensor_id in range(0, len(mux_data)):
                    sensor_data = mux_data[sensor_id]
                    # Check for sensor data, missing sensor will produce a None reading
                    if sensor_data is not None:
                        sensor_data.group_id = args.group_id
                        sensor_data.sensor_id = str(mux_id * 8 + sensor_id)
                        # Topic for data: <prefix>/group/<group-id>/sensor/<sensor-id>
                        topic = args.mqtt_prefix
                        topic += "/group/" + sensor_data.group_id
                        topic += "/sensor/" + sensor_data.sensor_id
                        # Payload is protobuf as binary
                        payload = bytearray(sensor_data.SerializeToString())
                        client.publish(topic, payload)
            # Calculate the time we need to sleep to prevent over-polling the sensors
            end_time = time.time()
            duration = end_time - start_time
            time_left = (args.sensor_time / 1000.0) - duration
            if time_left > 0:
                time.sleep(time_left)
            else:
                # Warn if we can't poll fast enough, if this happens a lot probably should stop
                print(
                    "Can't poll sensors fast enough. This is normally caused by a really short integration time."
                )

    except KeyboardInterrupt:
        print('Stopping...')

    print('Closing the MQTT client...')
    # Stop the client
    client.loop_stop()

    print('Done')
Example #3
0
class SingleMode:
    # init function, sets up global variables and objects, builds the GUI
    def __init__(self, master):

        # global variables
        self.master = master

        # available sensors list
        self.Sensors = ["----",
                        "TMP36",
                        "LMT86",
                        "ADXL335 X-axis",
                        "ADXL335 Y-axis",
                        "ADXL335 Z-axis",
                        "ADXL335 Total",
                        "BMP180 Temp",
                        "BMP180 Pressure",
                        "TSL2561"]

        # State controls if the software actively measures
        self.State = False

        # Interval controls the interval between measurements
        self.Interval = 100

        # Sensor_values displays actual measured values
        self.Sensor_value1 = Tk.StringVar(master)
        self.Sensor_value1.set("0.0")

        # SensorSelects controls which sensor are selected
        self.SensorSelect1 = Tk.StringVar(master)
        self.SensorSelect1.set(self.Sensors[0])

        # ChannelSelects controls which channels are selected
        self.ChannelSelect1 = Tk.IntVar(master)
        self.ChannelSelect1.set(0)

        # FreqeuncySelect controls frequency of measurements
        self.FrequencySelect = Tk.IntVar(master)
        self.FrequencySelect.set(10)

        # Sensor_units displays units of actively measured values
        self.Sensor_unit1 = Tk.StringVar(master)
        self.Sensor_unit1.set("--")

        # creates SensorReader and DataLogger objects
        self.sr = SensorReader(True, True, False)
        self.DL1 = DataLogger(False)


        # configures the grid layout
        master.columnconfigure(1, weight=0)
        master.columnconfigure(2, weight=2)
        master.columnconfigure(3, weight=1)
        master.columnconfigure(4, weight=1)
        master.rowconfigure(1, weight=1)
        master.rowconfigure(2, weight=0)
        master.rowconfigure(3, weight=0)
        master.rowconfigure(4, weight=0)

        # configures the window properties
        master.resizable(0, 0)
        master.geometry("500x250+300+300")
        master.title("LabPi SINGLE MODE")


        # GUI elements config
        # labels which display current value and unit
        self.sensor_value1 = Tk.Label(master, textvariable=self.Sensor_value1, font=("Helvetica", 60))
        self.sensor_value1.grid(row=1, column=1, columnspan=3)
        self.sensor_unit1 = Tk.Label(master, textvariable=self.Sensor_unit1, font=("Helvetica", 50))
        self.sensor_unit1.grid(row=1, column=4, columnspan=3)

        # static labels
        self.Select_label1 = Tk.Label(master, text="Sensor 1:")
        self.Select_label1.grid(row=2, column=1, sticky="nsew")
        self.Select_label2 = Tk.Label(master, text="Channel 1:")
        self.Select_label2.grid(row=3, column=1, sticky="nsew")
        self.Select_label3 = Tk.Label(master, text="Frequency:")
        self.Select_label3.grid(row=4, column=1, sticky="nsew")

        # optionmenus for configuring
        self.sensor_Select1 = Tk.OptionMenu(master, self.SensorSelect1, *self.Sensors)
        self.sensor_Select1.grid(row=2, column=2, sticky="nsew")
        self.channel_Select1 = Tk.OptionMenu(master, self.ChannelSelect1, 0, 1, 2, 3)
        self.channel_Select1.grid(row=3, column=2, sticky="nsew")
        self.frequency_Select = Tk.OptionMenu(master, self.FrequencySelect, 1, 2, 5, 10, 25, 50)
        self.frequency_Select.grid(row=4, column=2, sticky="nsew")

        # control buttons
        self.Start_button = Tk.Button(master, text="Start", command=self.start)
        self.Start_button.grid(row=2, column=3, sticky="nsew")
        self.Stop_button = Tk.Button(master, text="Stop", command=self.stop)
        self.Stop_button.grid(row=3, column=3, sticky="nsew")
        self.Save_button = Tk.Button(master, text="Save", command=self.save)
        self.Save_button.grid(row=2, column=4, sticky="nsew")
        self.Plot_button = Tk.Button(master, text="Plot", command=self.plot)
        self.Plot_button.grid(row=3, column=4, sticky="nsew")

    # refresh function, checks if State=True, then runs measurement again after set interval
    def refresh(self):
        if self.State:
            self.master.after(self.Interval, self.refresh)
            self.updateVar1()

    # start function, configures app for measurement, then starts the refresh function
    def start(self):

        # clean previously logged data
        self.DL1.eraseData()

        # update measuring frequency
        self.updateFrequency()

        # update unit
        self.updateUnit1()

        # write info block into data log
        self.DL1.writeInfo(info="sensor:" + str(self.SensorSelect1.get()) +
                               ", date:" + time.strftime("%Y-%m-%d %H:%M:%S") +
                               ", interval: " + str(self.Interval))

        # disable GUI elements
        self.sensor_Select1.configure(state="disabled")
        self.Start_button.configure(state="disabled")
        self.channel_Select1.configure(state="disabled")
        self.frequency_Select.configure(state="disabled")
        self.Save_button.configure(state="disabled")
        self.Plot_button.configure(state="disabled")

        # set state to True and run refresh function
        self.State = True
        self.refresh()

    # save function, saves the logged data via DataLogger function
    def save(self):
        self.DL1.saveData(location="measurements/", name=("Sensor1"+time.strftime("%Y-%m-%d-%H%M%S")))

    # plot function, plots logged data with pyplot, configure pyplot
    def plot(self):
        plt.plot(self.DL1.readData())
        plt.ylabel(self.Sensor_unit1.get())
        plt.xlabel("Samples")
        plt.grid(True)
        plt.show()

    # stop function, sets State to False, enables disabled GUI elements
    def stop(self):
        self.State = False
        self.sensor_Select1.configure(state="normal")
        self.Start_button.configure(state="normal")
        self.channel_Select1.configure(state="normal")
        self.frequency_Select.configure(state="normal")
        self.Save_button.configure(state="normal")
        self.Plot_button.configure(state="normal")

    # updateUnit function, updates displayed unit to proper one
    def updateUnit1(self):
        if self.SensorSelect1.get() == "----":
            self.Sensor_unit1.set("--")
        elif self.SensorSelect1.get() == "TMP36":
            self.Sensor_unit1.set("C")
        elif self.SensorSelect1.get() == "LMT86":
            self.Sensor_unit1.set("C")
        elif self.SensorSelect1.get() == "ADXL335 X-axis":
            self.Sensor_unit1.set("m/s2")
        elif self.SensorSelect1.get() == "ADXL335 Y-axis":
            self.Sensor_unit1.set("m/s2")
        elif self.SensorSelect1.get() == "ADXL335 Z-axis":
            self.Sensor_unit1.set("m/s2")
        elif self.SensorSelect1.get() == "ADXL335 Total":
            self.Sensor_unit1.set("m/s2")
        elif self.SensorSelect1.get() == "BMP180 Temp":
            self.Sensor_unit1.set("C")
        elif self.SensorSelect1.get() == "BMP180 Pressure":
            self.Sensor_unit1.set("Pa")
        elif self.SensorSelect1.get() == "TSL2561":
            self.Sensor_unit1.set("lux")

    # updateVar function, updates displayed unit to proper one, writes data to data log
    def updateVar1(self):
        if self.SensorSelect1.get() == "TMP36":
            value = self.sr.readTMP36(self.ChannelSelect1.get())
        elif self.SensorSelect1.get() == "LMT86":
            value = self.sr.readLMT86(self.ChannelSelect1.get())
        elif self.SensorSelect1.get() == "ADXL335 X-axis":
            value = self.sr.readADXL335XAccel(self.ChannelSelect1.get())
        elif self.SensorSelect1.get() == "ADXL335 Y-axis":
            value = self.sr.readADXL335YAccel(self.ChannelSelect1.get())
        elif self.SensorSelect1.get() == "ADXL335 Z-axis":
            value = self.sr.readADXL335ZAccel(self.ChannelSelect1.get())
        elif self.SensorSelect1.get() == "ADXL335 Total":
            value = self.sr.readADXL335TotalAccel(0, 1, 2)
        elif self.SensorSelect1.get() == "BMP180 Temp":
            value = self.sr.readBMP085Temp()
        elif self.SensorSelect1.get() == "BMP180 Pressure":
            value = self.sr.readBMP085Pressure()
        elif self.SensorSelect1.get() == "TSL2561":
            value = self.sr.readTSL2561Lux()
        else:
            value = 0
        self.Sensor_value1.set(str(value))
        self.DL1.writeData(value)

    # updateFrequency function, sets interval between measurements to selected value
    def updateFrequency(self):
        if self.FrequencySelect.get() == 1:
            self.Interval = 1000
        elif self.FrequencySelect.get() == 2:
            self.Interval = 500
        elif self.FrequencySelect.get() == 5:
            self.Interval = 200
        elif self.FrequencySelect.get() == 10:
            self.Interval = 100
        elif self.FrequencySelect.get() == 25:
            self.Interval = 40
        elif self.FrequencySelect.get() == 50:
            self.Interval = 20
Example #4
0
    def __init__(self, master):

        # global variables
        self.master = master

        # available sensors list
        self.Sensors = ["----",
                        "TMP36",
                        "LMT86",
                        "ADXL335 X-axis",
                        "ADXL335 Y-axis",
                        "ADXL335 Z-axis",
                        "ADXL335 Total",
                        "BMP180 Temp",
                        "BMP180 Pressure",
                        "TSL2561"]

        # State controls if the software actively measures
        self.State = False

        # Interval controls the interval between measurements
        self.Interval = 100

        # Sensor_values displays actual measured values
        self.Sensor_value1 = Tk.StringVar(master)
        self.Sensor_value1.set("0.0")

        self.Sensor_value2 = Tk.StringVar(master)
        self.Sensor_value2.set("0.0")

        # SensorSelects controls which sensor are selected
        self.SensorSelect1 = Tk.StringVar(master)
        self.SensorSelect1.set(self.Sensors[0])

        self.SensorSelect2 = Tk.StringVar(master)
        self.SensorSelect2.set(self.Sensors[0])

        # ChannelSelects controls which channels are selected
        self.ChannelSelect1 = Tk.IntVar(master)
        self.ChannelSelect1.set(0)

        self.ChannelSelect2 = Tk.IntVar(master)
        self.ChannelSelect2.set(0)

        # FreqeuncySelect controls frequency of measurements
        self.FrequencySelect = Tk.IntVar(master)
        self.FrequencySelect.set(10)

        # Sensor_units displays units of actively measured values
        self.Sensor_unit1 = Tk.StringVar(master)
        self.Sensor_unit1.set("--")

        self.Sensor_unit2 = Tk.StringVar(master)
        self.Sensor_unit2.set("--")

        # creates SensorReader and DataLogger objects
        self.sr = SensorReader(True, True, False)
        self.DL1 = DataLogger(False)
        self.DL2 = DataLogger(False)


        # configures the grid layout
        master.columnconfigure(1, weight=0)
        master.columnconfigure(2, weight=2)
        master.columnconfigure(3, weight=1)
        master.columnconfigure(4, weight=1)
        master.rowconfigure(1, weight=1)
        master.rowconfigure(2, weight=1)
        master.rowconfigure(3, weight=0)
        master.rowconfigure(4, weight=0)
        master.rowconfigure(5, weight=0)
        master.rowconfigure(6, weight=0)
        master.rowconfigure(7, weight=0)

        # configures the window properties
        master.resizable(0, 0)
        master.geometry("500x500+300+300")
        master.title("LabPi DUAL MODE")


        # GUI elements config
        # labels which display current value and unit
        self.sensor_value1 = Tk.Label(master, textvariable=self.Sensor_value1, font=("Helvetica", 60))
        self.sensor_value1.grid(row=1, column=1, columnspan=3)
        self.sensor_unit1 = Tk.Label(master, textvariable=self.Sensor_unit1, font=("Helvetica", 50))
        self.sensor_unit1.grid(row=1, column=4, columnspan=3)
        self.sensor_value2 = Tk.Label(master, textvariable=self.Sensor_value2, font=("Helvetica", 60))
        self.sensor_value2.grid(row=2, column=1, columnspan=3)
        self.sensor_unit2 = Tk.Label(master, textvariable=self.Sensor_unit2, font=("Helvetica", 50))
        self.sensor_unit2.grid(row=2, column=4, columnspan=3)

        # static labels
        self.Select_label1 = Tk.Label(master, text="Sensor 1:")
        self.Select_label1.grid(row=3, column=1, sticky="nsew")
        self.Select_label2 = Tk.Label(master, text="Channel 1:")
        self.Select_label2.grid(row=4, column=1, sticky="nsew")
        self.Select_label3 = Tk.Label(master, text="Sensor 2:")
        self.Select_label3.grid(row=5, column=1, sticky="nsew")
        self.Select_label4 = Tk.Label(master, text="Channel 2:")
        self.Select_label4.grid(row=6, column=1, sticky="nsew")
        self.Select_label5 = Tk.Label(master, text="Frequency:")
        self.Select_label5.grid(row=7, column=1, sticky="nsew")

        # optionmenus for configuring
        self.sensor_Select1 = Tk.OptionMenu(master, self.SensorSelect1, *self.Sensors)
        self.sensor_Select1.grid(row=3, column=2, sticky="nsew")
        self.channel_Select1 = Tk.OptionMenu(master, self.ChannelSelect1, 0, 1, 2, 3)
        self.channel_Select1.grid(row=4, column=2, sticky="nsew")
        self.sensor_Select2 = Tk.OptionMenu(master, self.SensorSelect2, *self.Sensors)
        self.sensor_Select2.grid(row=5, column=2, sticky="nsew")
        self.channel_Select2 = Tk.OptionMenu(master, self.ChannelSelect2, 0, 1, 2, 3)
        self.channel_Select2.grid(row=6, column=2, sticky="nsew")
        self.frequency_Select = Tk.OptionMenu(master, self.FrequencySelect, 1, 2, 5, 10, 25, 50)
        self.frequency_Select.grid(row=7, column=2, sticky="nsew")

        # control buttons
        self.Start_button = Tk.Button(master, text="Start", command=self.start)
        self.Start_button.grid(row=3, column=3, rowspan=2, sticky="nsew")
        self.Stop_button = Tk.Button(master, text="Stop", command=self.stop)
        self.Stop_button.grid(row=5, column=3, rowspan=2, sticky="nsew")
        self.Save_button = Tk.Button(master, text="Save", command=self.save)
        self.Save_button.grid(row=3, column=4, rowspan=2, sticky="nsew")
        self.Plot_button = Tk.Button(master, text="Plot", command=self.plot)
        self.Plot_button.grid(row=5, column=4, rowspan=2, sticky="nsew")
Example #5
0
class TunnelGui(QtWidgets.QMainWindow, Tunnel_Model.Ui_MainWindow):

    sensorRdr = None
    sampleCollector = None

    enableGraphs = False
    liftGraph = None
    dragGraph = None
    pitchMomentGraph = None
    airspeedGraph = None
    config = TunnelConfig()

    def __init__(self, qApp):
        super().__init__()
        self.qApp = qApp
        self.setupUi(self)

        # setup the calibrattion dialog
        self.dialogCalibrate = QtWidgets.QDialog()
        self.dialogCalibrateUi = Ui_DialogCalibrate()
        self.dialogCalibrateUi.setupUi(self.dialogCalibrate)

        # Update displayed sample rate
        sampleRate = self.config.getItem("General", "samplerate")

        self.outSampleRate.display(sampleRate)

        # Connect buttons to their corresponding functions
        self.btnCalibrate.clicked.connect(self.showCalibrateDialog)
        self.btnLoadTare.clicked.connect(self.loadTare)
        self.btnSaveResults.clicked.connect(self.saveResults)

        self.dialogCalibrateUi.btnDone.clicked.connect(self.calibrationDone)
        self.dialogCalibrateUi.btnAirspeedTare.clicked.connect(
            self.airspeedTare)
        self.dialogCalibrateUi.btnAoAWingTare.clicked.connect(self.aoaWingTare)
        self.dialogCalibrateUi.btnAoAPlatformTare.clicked.connect(
            self.aoaPlatformTare)

        # Initialize the platform offset from the persist file. Can't wait
        # until SampleCollector is alive, so we read it directly from the
        # file. Woe be unto me if I change the name of the persist value...
        aoaPlatformOffset = TunnelPersist().getItem("AoA", "PlatformOffset")
        if aoaPlatformOffset == None:
            aoaPlatformOffset = 0.0
        else:
            aoaPlatformOffset = float(aoaPlatformOffset)

        self.dialogCalibrateUi.inpAoAOffset.setValue(aoaPlatformOffset)
        self.setAoAOffset(aoaPlatformOffset)

        # Set the Saving... text to nothing for now. When the Save button
        # is clicked, we'll light it up for a moment.
        self.lblSaving.setText("")

        # Show the directory path
        destDirname = self.config.getItem("General", "DataDestinationDir")
        self.lblDirPath.setText(destDirname)

    def showCalibrateDialog(self):
        self.dialogCalibrate.show()

    def calibrationDone(self):
        offset = self.dialogCalibrateUi.inpAoAOffset.value()
        self.sampleCollector.setAoAPlatformOffset(offset)
        self.setAoAOffset(offset)

    def aoaWingTare(self):
        self.sampleCollector.setAoAWingTare()

    def aoaPlatformTare(self):
        self.sampleCollector.setAoAPlatformTare()

    def airspeedTare(self):
        self.sampleCollector.setAirspeedTare()

    def loadTare(self):
        self.sampleCollector.setLoadTare()

    def slugify(self, value):
        """
        Normalizes string, converts to lowercase, removes non-alpha characters,
        and converts spaces to hyphens. Borrowed from
        https://stackoverflow.com/questions/295135/turn-a-string-into-a-valid-filename
        """
        value = str(
            unicodedata.normalize('NFKD', value).encode('ascii', 'ignore'))
        # Chomp the leading 'b\'
        value = value[2:]
        value = str(re.sub("[^\w.\s-]", "", value).strip().lower())
        value = str(re.sub("[-\s]+", "-", value))
        return value

    def saveResults(self):
        fname = self.slugify(str(self.inpRunName.text()))
        if (fname == ""):
            fname = self.config.getItem("General", "DefaultFileName")

        # Append '.csh' if not already there
        if not fname.endswith(".csv"):
            fname += ".csv"

        fname = Path(fname)
        destDirname = self.config.getItem("General", "DataDestinationDir")

        if (destDirname is None):
            destDirname = Path.cwd()
        else:
            Path(destDirname).mkdir(parents=True, exist_ok=True)

        fname = destDirname / fname
        print("Save Results clicked: %s" % fname)

        self.lblSaving.setText("Saving...")

        self.sampleCollector.doSave(fname, str(self.inpRunName.text()),
                                    str(self.inpConfiguration.text()),
                                    str(self.inpComments.text()))

        dieTime = QTime.currentTime().addSecs(1)
        while (QTime.currentTime() < dieTime):
            self.qApp.processEvents()

        self.lblSaving.setText("")
        self.lblSaving.repaint()
        self.qApp.processEvents()

    def startReadingSensors(self):
        sampleRate = self.outSampleRate.value()
        print("Start sampling at " + str(sampleRate) + " samples/sec")

    def setAoa(self, aoa):
        aoa = float('%.1f' % aoa)
        self.outAoaDeg.display(str(aoa))

    def setAoAOffset(self, offset):
        offset = float('%.1f' % offset)
        self.outAoaOffsetDeg.display(str(offset))

    def setAirspeed(self, speed):
        speed = float('%.1f' % speed)
        self.outSpeedMPH.display(str(speed))
        speed = speed * 5280.0 / 3600.0
        speed = float('%.1f' % speed)
        self.outSpeedFps.display(str(speed))

    def setAnenometer(self, speed):
        speed = float('%.1f' % speed)
        self.outAnemometerFps.display(str(speed))
        speed = speed * 3600.0 / 5280.0
        speed = float('%.1f' % speed)
        self.outAnemometerMPH.display(str(speed))

    def setLift(self, lift, stddev):
        lift = float('%.2f' % lift)
        stddev = float('%.2f' % stddev)
        itemKg = QTableWidgetItem()
        itemKg.setData(Qt.DisplayRole, lift)
        self.tblLiftDragMoment.setItem(0, 0, itemKg)
        itemLb = QTableWidgetItem()
        itemLb.setData(Qt.DisplayRole, float('%.2f' % (lift * 2.2046)))
        self.tblLiftDragMoment.setItem(0, 1, itemLb)
        fItemKg = QTableWidgetItem()
        fItemKg.setData(Qt.DisplayRole, stddev)
        self.tblLiftDragMoment.setItem(0, 2, fItemKg)

    def setDrag(self, drag, stddev):
        drag = float('%.2f' % drag)
        stddev = float('%.2f' % stddev)
        itemKg = QTableWidgetItem()
        itemKg.setData(Qt.DisplayRole, drag)
        self.tblLiftDragMoment.setItem(1, 0, itemKg)
        itemLb = QTableWidgetItem()
        itemLb.setData(Qt.DisplayRole, float('%.2f' % (drag * 2.2046)))
        self.tblLiftDragMoment.setItem(1, 1, itemLb)
        fItemKg = QTableWidgetItem()
        fItemKg.setData(Qt.DisplayRole, stddev)
        self.tblLiftDragMoment.setItem(1, 2, fItemKg)

    def setMoment(self, moment, stddev):
        moment = float('%.2f' % moment)
        stddev = float('%.2f' % stddev)
        itemKgM = QTableWidgetItem()
        itemKgM.setData(Qt.DisplayRole, moment)
        self.tblLiftDragMoment.setItem(2, 0, itemKgM)
        itemLbFt = QTableWidgetItem()
        itemLbFt.setData(Qt.DisplayRole, float('%.2f' % (moment * 8.8507)))
        self.tblLiftDragMoment.setItem(2, 1, itemLbFt)
        fItemKgM = QTableWidgetItem()
        fItemKgM.setData(Qt.DisplayRole, stddev)
        self.tblLiftDragMoment.setItem(2, 2, fItemKgM)

    def setPower(self, power):
        power = float('%.1f' % power)
        self.outPower.display(str(power))

    def setRawAoA(self, aoa):
        self.dialogCalibrateUi.txtRawAoA.setText(str(aoa))

    def setRawAirspeed(self, airspeed):
        self.dialogCalibrateUi.txtRawAirspeed.setText(str(airspeed))

    def saveRunNameAndConfiguration(self):
        if self.savedRunNameText != self.inpRunName.text():
            self.savedRunNameText = self.inpRunName.text()
            self.sampleCollector.saveRunName(self.savedRunNameText)

        if self.savedConfigurationText != self.inpConfiguration.text():
            self.savedConfigurationText = self.inpConfiguration.text()
            self.sampleCollector.saveConfiguration(self.savedConfigurationText)

    @pyqtSlot(ProcessedSample)
    def refreshWindow(self, currentData):
        self.setRawAoA(currentData.rawAoA)
        self.setRawAirspeed(currentData.rawAirspeed)

        self.setPower(currentData.volts * currentData.amps)
        self.setAoa(currentData.wingAoA)
        self.setAirspeed(currentData.airspeed)
        self.setAnenometer(currentData.hotwire)

        self.tblLiftDragMoment.setUpdatesEnabled(False)
        self.setLift(currentData.totalLift, currentData.totalLiftStdDev)
        self.setDrag(currentData.drag, currentData.dragStdDev)
        self.setMoment(currentData.pitchMoment, currentData.pitchMomentStdDev)
        self.tblLiftDragMoment.setUpdatesEnabled(True)

        self.updateGraphs(currentData.totalLift, currentData.drag,
                          currentData.pitchMoment, currentData.airspeed)

        self.saveRunNameAndConfiguration()

    def startSensorReader(self, tunnelWindow, tunnelDataQ):
        useSimulatedData = self.config.getItem("General", "UseSimulatedData")
        if (useSimulatedData is None):
            self.sensorRdr = SensorReader(tunnelWindow, tunnelDataQ)

        if (useSimulatedData.lower() == "true"):
            print("Starting data simulator")
            self.sensorRdr = SensorSimulator(tunnelWindow, tunnelDataQ)
        else:
            self.sensorRdr = SensorReader(tunnelWindow, tunnelDataQ)

        self.sensorRdr.daemon = True
        self.sensorRdr.start()

    def stopSensorReader(self):
        self.sensorRdr.terminate()

    def startSampleCollector(self, tunnelDataQ):
        self.sampleCollector = SampleCollector(tunnelDataQ)
        self.sampleCollector.updateWindow.connect(self.refreshWindow)
        self.sampleCollector.daemon = True
        self.sampleCollector.start()

        # Once SampleCollector is up and running, we can ask it for the
        # previously saved run name and configuraiton
        self.savedRunNameText = self.sampleCollector.getRunName()
        self.savedConfigurationText = self.sampleCollector.getConfiguration()
        self.inpRunName.setText(self.savedRunNameText)
        self.inpConfiguration.setText(self.savedConfigurationText)

    def stopSampleCollector(self):
        self.sampleCollector.terminate()

    def startGraphs(self):

        enableGraphs = self.config.getItem("General", "EnableGraphs")

        if (enableGraphs is None):
            self.enableGraphs = False
            return

        if (enableGraphs.lower() != "true"):
            self.enableGraphs = False
            return

        self.enableGraphs = True
        self.liftGraph = LiveGraph(QtCore.QRect(50, 150, 500, 200), "Lift",
                                   "kg", True)
        self.liftGraph.show()

        self.dragGraph = LiveGraph(QtCore.QRect(50, 375, 500, 200), "Drag",
                                   "Kg", True)
        self.dragGraph.show()

        self.pitchMomentGraph = LiveGraph(QtCore.QRect(50, 600, 500, 200),
                                          "Moment", "Kg-M", True)
        self.pitchMomentGraph.show()

        self.airspeedGraph = LiveGraph(QtCore.QRect(50, 825, 500, 200),
                                       "Airspeed", "Kt", True)
        self.airspeedGraph.show()

    def updateGraphs(self, lift, drag, pitchMoment, airspeed):
        if (self.enableGraphs):
            self.liftGraph.addDataToGraph(lift)
            self.dragGraph.addDataToGraph(drag)
            self.pitchMomentGraph.addDataToGraph(pitchMoment)
            self.airspeedGraph.addDataToGraph(airspeed)
def main():

    parser = argparse.ArgumentParser(description='Send senor data over MQTT.')
    parser.add_argument('--host', action="store", dest="mqtt_host", default="localhost", help='Location of the MQTT broker. Defaults to localhost.')
    parser.add_argument('--port', action="store", dest="mqtt_port", default=1883, type=int, help='MQTT port for the broker. Defaults to 1883.')
    #parser.add_argument('--user', action="store", dest="mqtt_user", help="Username used to login to the broker.")
    #parser.add_argument('--pass', action="store", dest="mqtt_pass", help="Password used to login to the broker.")
    parser.add_argument('--topic', action="store", dest="mqtt_prefix", default="", help="Base topic to broadcast on. Defaults to none.")
    parser.add_argument('--time', action="store", dest="sensor_time", default=0xD5, type=arg_sensor_time, help="Integration time for the sensors, in milliseconds. Must be in range: [2.4, 612]. Defaults to 100.8ms")
    parser.add_argument('--gain', action="store", dest="sensor_gain", default=1, type=arg_sensor_gain, help="Gain for sensors. Must be one of: [1, 4, 16, 60] Defaults to 1.")
    parser.add_argument('--group', action="store", dest="group_id", default="0", help='Group id on MQTT.')
    args = parser.parse_args()

    # create mqtt client
    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect(args.mqtt_host, args.mqtt_port, 60)

    # Start a background thread to handle the client
    client.loop_start()

    # process sensor data
    try:
        print ("Initializing sensors")
        # create and init sensor reader
        sensor_reader = SensorReader(args.sensor_time, args.sensor_gain)
        sensor_reader.initialize()
        print ("Initialization complete")

        print ("Streaming data")
        while True:
            startTime = time.time()
            #read sensor data
            data = sensor_reader.ReadSensors();
            # publish
            for muxId in range(0, len(data)):
                muxData = data[muxId]
                # non existant muxes will produce an empty list
                for sensorId in range(0, len(muxData)):
                    sensorData = muxData[sensorId]
                    # check there is sensor data
                    # non existant sensors will produce an empty list
                    if len(sensorData) == 6:
                        # topic for data: <prefix>/group/<group-id>/sensor/<sensor-id>
                        topic = args.mqtt_prefix + "/group/" + str(args.group_id) + "/sensor/" + str(muxId * 8 + sensorId)
                        # payload is "R,G,B,W,t1,t2"
                        payload = str(sensorData[0]) + ", " + str(sensorData[1]) + ", " + str(sensorData[2])
                        payload += ", " + str(sensorData[3]) + ", " + str(sensorData[4]) + ", " + str(sensorData[5])
                        client.publish(topic, payload)
            # calculate the time we need to sleep to prevent over-polling the sensors
            endTime = time.time()
            duration = endTime - startTime
            timeLeft = (args.sensor_time / 1000.0) - duration
            if timeLeft > 0:
                time.sleep(timeLeft)
            else:
                # Stop if we can't poll fast enough, no point in continuing
                print ("Can't poll sensors fast enough. This is normally caused by a really short integration time.")
                # break

    except KeyboardInterrupt:
        print ('Stopping...')

    print ('Closing the MQTT client...')
    # Stop the client
    client.loop_stop()

    print ('Done')
Example #7
0
def thread_slice(pressure_data, index):
    sr = SensorReader(index)
    pressure = sr.read_pressure()
    pressure_data[index] = pressure
Example #8
0
import threading

from flask import Flask, render_template
import json

from SensorReader import SensorReader

app = Flask(__name__)


def load_json():
    with open('static/data.json') as f:
        return json.load(f)


@app.route('/')
def hello_world():
    return render_template('main.html.jinja', data=load_json())


if __name__ == '__main__':
    reader = SensorReader()
    threading.Thread(target=reader.loop)
    app.run()