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 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')
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
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")
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')
def thread_slice(pressure_data, index): sr = SensorReader(index) pressure = sr.read_pressure() pressure_data[index] = pressure
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()