예제 #1
0
class ApplicationWindow(QMainWindow):
    def __init__(self):

        #Initialization stuff

        QMainWindow.__init__(self)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.setWindowTitle("Turtle Window")  #Name of the specific window

        self.setStyleSheet("""
        QMainWindow {
            background-color:#437919;
        }

        QMenuBar {
            background-color:#313131;
            color: rgb(255,255,255);
            border: 1px solid #000;
        }

        QMenuBar::item {
            background-color: rgb(49,49,49);
            color: rgb(255,255,255);
        }

        QMenuBar::item::selected {
            background-color: rgb(30,30,30);
        }

        QMenu {
            background-color: rgb(49,49,49);
            color: rgb(255,255,255);
            border: 1px solid #000;
        }

        QMenu::item::selected {
            background-color: rgb(30,30,30);
        }

        QStatusBar {
            background-color:#313131;
            color: rgb(255,255,255);
            border: 1px solid #000;
        }

        """)

        #Serial Setup
        self.serialObject = serial.Serial()
        self.serialObject.baudrate = 9600
        self.serialObject.parity = serial.PARITY_NONE
        self.serialObject.stopbits = serial.STOPBITS_ONE
        self.serialObject.bytesize = serial.EIGHTBITS
        self.serialObject.timeout = None
        self.serialObject.setWriteTimeout(0.01)

        #Variables
        self.liveUpdate = False

        self.datapulls = 0

        self.dataSamples = []

        self.dataXaccelSamples = []
        self.dataZgyroSamples = []
        self.dataTickSamples = []
        self.dataTickSamplesCount = 0

        self.laps = []
        self.speeds = []

        #Data stuff
        self.com_monitor = None
        self.com_data_puller = None
        self.com_data_Xaccel_q = None
        self.com_data_Zgyro_q = None
        self.com_data_Tick_q = None
        self.com_data_Lap_q = None
        self.com_terminal_q = None

        self.liveFeed = LiveDataFeed()

        self.dataTimerUpdateRate = 10

        self.plotUpdater = QTimer(self)
        self.plotUpdater.timeout.connect(self.UpdateData)
        self.dataToPlot = "Live"
        self.dataBeingPlot = "Live"

        #Menues

        #File menu

        self.file_menu = QMenu('&File', self)
        self.file_menu.addAction('&Quit', self.fileQuit,
                                 QtCore.Qt.CTRL + QtCore.Qt.Key_Q)
        self.menuBar().addMenu(self.file_menu)

        #Help menu

        self.help_menu = QMenu('&Help', self)
        self.menuBar().addSeparator()
        self.menuBar().addMenu(self.help_menu)
        self.help_menu.addAction('&About', self.about)

        #Serial Menu

        self.serial_menu = QMenu('&Serial', self)
        self.menuBar().addSeparator()
        self.menuBar().addMenu(self.serial_menu)

        serialConnectAction = self.serial_menu.addAction('Connect')
        serialConnectAction.setShortcut(QtCore.Qt.Key_C)
        serialConnectAction.triggered.connect(self.serialConnect)
        serialConnectAction.setIcon(QIcon('SerialConnect.png'))

        serialReconnectAction = self.serial_menu.addAction('Reconnect')
        serialReconnectAction.setShortcut(QtCore.Qt.Key_R)
        serialReconnectAction.triggered.connect(self.serialReconnect)
        serialReconnectAction.setIcon(QIcon('SerialReconnect.png'))

        serialDisconnectAction = self.serial_menu.addAction('Disconnect')
        serialDisconnectAction.triggered.connect(self.serialDisconnect)
        serialDisconnectAction.setIcon(QIcon('SerialDisconnect.png'))

        #GUI

        #Stats
        self.labelLapTime = QLabel('LapTime', self)
        self.labelLapTime.setStyleSheet("background-color:#FFFFFF")
        self.labelLapTime.setAlignment(Qt.AlignLeft)

        self.labelLapTicks = QLabel('LapTicks', self)
        self.labelLapTicks.setStyleSheet("background-color:#FFFFFF")
        self.labelLapTicks.setAlignment(Qt.AlignLeft)

        self.labelSpeed = QLabel('Speed', self)
        self.labelSpeed.setStyleSheet("background-color:#FFFFFF")
        self.labelSpeed.setAlignment(Qt.AlignLeft)

        self.labelSpeedAvg = QLabel('Speed avg.', self)
        self.labelSpeedAvg.setStyleSheet("background-color:#FFFFFF")
        self.labelSpeedAvg.setAlignment(Qt.AlignLeft)

        self.listDataSets = QListWidget(self)
        self.listDataSets.setMaximumWidth(200)
        self.listDataSets.addItem('Live')
        self.listDataSets.itemClicked.connect(self.chooseDataSet)

        self.ButtonLiveSave = QPushButton('Save')
        self.ButtonLiveSave.setStyleSheet("background-color:#00FF00")
        self.ButtonLiveSave.clicked.connect(self.SaveData)
        statbox = QVBoxLayout()
        statbox.addWidget(self.listDataSets)
        statbox.addWidget(self.labelLapTime)
        statbox.addWidget(self.labelLapTicks)
        statbox.addWidget(self.labelSpeed)
        statbox.addWidget(self.labelSpeedAvg)
        statbox.addWidget(self.ButtonLiveSave)

        #Start/Stop interface
        self.buttonStart = QPushButton('Start', self)
        self.buttonStart.setStyleSheet("background-color:#00FF00")
        self.buttonStart.clicked.connect(self.buttonStartPressed)

        buttonStop = QPushButton('Stop', self)
        buttonStop.setStyleSheet("background-color:#FF6666")
        buttonStop.clicked.connect(self.CarStop)

        self.buttonData = QPushButton('Datacollection', self)
        self.buttonData.setStyleSheet("background-color:#a2adff")
        self.buttonData.setCheckable(True)
        self.buttonData.clicked[bool].connect(self.buttonDataToggle)

        self.lineEditSpeed = QLineEdit('35')
        self.lineEditSpeed.setStyleSheet("background-color:#FFFFFF")
        self.lineEditSpeed.returnPressed.connect(self.buttonStartPressed)
        self.lineEditSpeed.setSizePolicy(QSizePolicy.Minimum,
                                         QSizePolicy.Fixed)

        #Terminal
        self.labelTerminal = QLabel('>>Terminal Ready<br />', self)
        self.labelTerminal.setAlignment(Qt.AlignLeft | Qt.AlignTop)
        self.labelTerminal.setWordWrap(True)
        self.labelTerminal.setStyleSheet(
            "background-color:#000000; color:#FFFFFF")
        self.labelTerminal.setTextFormat(Qt.RichText)

        self.scrollAreaTerminal = QScrollArea()
        self.scrollAreaTerminal.setWidget(self.labelTerminal)
        self.scrollAreaTerminal.setWidgetResizable(True)
        self.scrollAreaTerminal.verticalScrollBar().rangeChanged.connect(
            self.terminalScrollToBottom)

        self.lineEditTerminal = QLineEdit()
        self.lineEditTerminal.setStyleSheet("background-color:#FFFFFF")
        self.lineEditTerminal.returnPressed.connect(self.terminalLineEditEnter)
        self.lineEditTerminal.setToolTip('Use , to seperate bytes')

        self.comboboxTerminalType = QComboBox(self)
        self.comboboxTerminalType.addItem("HEX")
        self.comboboxTerminalType.addItem("DEC")

        #Layout

        self.main_widget = QWidget(self)

        turtlePicLabel = QLabel(self)
        turtlePic = QPixmap("Turtle.jpg")
        turtlePicLabel.setPixmap(turtlePic)

        hbox = QHBoxLayout()
        vbox = QVBoxLayout()
        vbox.setAlignment(Qt.AlignRight)
        vbox.addWidget(turtlePicLabel)
        vbox.addWidget(self.lineEditSpeed)
        vbox.addWidget(self.buttonStart)
        vbox.addWidget(buttonStop)
        vbox.addWidget(self.buttonData)
        vbox.addStretch(1)

        v2box = QVBoxLayout()

        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)
        self.canvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.canvas.updateGeometry()
        self.canvas.draw()
        self.Toolbar = NavigationToolbar(self.canvas, self, coordinates=True)

        drawingBox = QVBoxLayout()

        drawingBox.addWidget(self.canvas)
        drawingBox.addWidget(self.Toolbar)

        hbox.addLayout(drawingBox)

        hbox.addLayout(statbox)
        hbox.addLayout(vbox)

        hbox2 = QHBoxLayout()
        hbox2.addWidget(self.lineEditTerminal)
        hbox2.addWidget(self.comboboxTerminalType)

        v2box.addLayout(hbox)
        v2box.addWidget(self.scrollAreaTerminal)
        v2box.addLayout(hbox2)

        self.main_widget.setLayout(v2box)

        self.main_widget.setFocus()
        self.setCentralWidget(self.main_widget)

    def chooseDataSet(self, item):
        if (item.text() == 'Live'):
            self.dataToPlot = "Live"
        else:
            self.dataToPlot = item.text().lstrip('Lap: ')

    def updateLaptime(self):
        self.labelLapTime.setText("LapTime: " +
                                  str(self.laps[len(self.laps) - 1][0]))
        ticks = self.laps[len(self.laps) - 1][1]
        distance = ((ticks / 12) * 2.5 * math.pi) / 100
        self.labelLapTicks.setText("LapTicks: " + str(ticks) + "/" +
                                   "%.2f" % distance + "m")

    def listDataSetsUpdate(self):
        self.listDataSets.addItem("Lap: " + str((len(self.dataSamples) - 1)))

    def read_serial_data(self):

        qdata = list(get_all_from_queue(self.com_data_Xaccel_q))
        if (len(qdata) > 0):
            print("Received Xaccel data")
            for dataSet in qdata:
                self.dataXaccelSamples.append(dataSet)

        qdata = list(get_all_from_queue(self.com_data_Zgyro_q))
        if (len(qdata) > 0):
            #print("Received Zgyro data")
            for dataSet in qdata:
                self.dataZgyroSamples.append(dataSet)

        qdata = list(get_all_from_queue(self.com_data_Tick_q))
        if (len(qdata) > 0):
            #print("Received ticks data")
            for dataSet in qdata:
                self.dataTickSamples.append(dataSet)

        qdata = list(get_all_from_queue(self.com_data_Lap_q))
        if (len(qdata) > 0):
            try:
                indexEnd = self.dataTickSamples.index('e')
                self.dataSamples.append((self.dataTickSamples[0:indexEnd]))
                del (self.dataTickSamples[0:indexEnd + 1])
                self.laps.append(qdata[0])
                self.updateLaptime()
                self.listDataSetsUpdate()
            except ValueError:
                print('Lap has updated, but no "e" in datasamples')

    def SaveData(self):
        self.dataSamples.append((self.dataTickSamples))
        self.listDataSetsUpdate()

    def UpdateData(self):
        self.read_serial_data()
        if (self.dataToPlot == "Live"):
            self.dataBeingPlot = self.dataToPlot
            self.plot(self.dataTickSamples)
        elif ((self.dataToPlot != None)
              and (self.dataToPlot != self.dataBeingPlot)):
            self.dataBeingPlot = self.dataToPlot
            self.plot(self.dataSamples[int(self.dataToPlot)])
        else:
            print('No data yet')
        '''
        if(len(self.dataTickSamples) > self.dataTickSamplesCount and len(self.dataTickSamples) >=2):
            self.dataTickSamplesCount = len(self.dataTickSamples)
            sampleLast = self.dataTickSamples[len(self.dataTickSamples)-1]
            sampleSecondLast = self.dataTickSamples[len(self.dataTickSamples)-2]

            ticks = sampleLast[0] - sampleSecondLast[0]
            time = sampleLast[1] - sampleSecondLast[1]

            distance = ((ticks/12)*math.pi*2.5)/100
            speed = distance/time
            self.speeds.append(speed)
            self.labelSpeed.setText("Speed: " + "%.2f" %speed)

            if(len(self.speeds)>0):
                speedAvg = np.mean(self.speeds)
                self.labelSpeedAvg.setText("Speed: " + "%.2f" %speedAvg)
        '''

    def plot(self, data):

        if (len(data) >= 2):
            ax = self.figure.add_subplot(111)
            ax.hold(False)

            x_list = [y for [x, y] in data]
            y_list = [x for [x, y] in data]

            ax.plot(x_list, y_list, 'r')
            ax.set_title('Gyro over time')
            ax.set_ylabel('Z-Gyro')
            ax.set_xlabel('Time in ms')
            #ax.set_xlim([0, 5])
            #ax.set_ylim([0, 65535])
            #ax.autoscale(True)
            self.figure.tight_layout()
            self.canvas.draw()
        else:
            print('Not enough data yet')

    def terminalLineEditEnter(self):
        if self.serialObject.isOpen() == True:
            input_text = self.lineEditTerminal.text()

            input_type = 'None'

            input_bytes = input_text.split(',')

            if self.comboboxTerminalType.currentText() == "HEX":
                input_type = "HEX"
                for byte in range(0, len(input_bytes)):
                    input_bytes[byte] = int(input_bytes[byte], 16)

                print('It was hex')

            elif self.comboboxTerminalType.currentText() == "DEC":
                input_type = "DEC"
                for byte in range(0, len(input_bytes)):
                    input_bytes[byte] = int(input_bytes[byte])

                print('It was ascii')

            self.terminalAppend(">><font color=#FFFF00>" + input_type + "(" +
                                input_text + ")" + "</font> <br />")

            command = bytearray(input_bytes)
            self.serialObject.write(command)
        else:
            self.terminalAppend(">><font color=#FF0000>" +
                                "Serial port not open!" + "</font> <br />")
        self.lineEditTerminal.setText("")

    def terminalScrollToBottom(self, min, max):
        self.scrollAreaTerminal.verticalScrollBar().setValue(max)

    def terminalAppend(self, textToAppend):
        text = self.labelTerminal.text()
        text += textToAppend
        self.labelTerminal.setText(text)

    def buttonDataToggle(self, state):
        if (state):
            self.com_data_puller.start()
            print('Es ist true')
        else:
            self.com_data_puller.stop()
            print('Es ist false')

    def buttonStartPressed(self):
        text = self.lineEditSpeed.text()
        self.lineEditSpeed.setText("")
        try:
            value = int(text)
        except ValueError:
            return

        if (value <= 100 and value >= 0):
            self.CarStart(value)

    def CarStart(self, speed):
        if self.serialObject.isOpen():
            command = bytearray([ord('\x55'), ord('\x10'), speed])
            self.serialObject.write(command)
            self.terminalAppend(">><font color=#00FF00>" +
                                "Starting the car with " + str(speed) +
                                "% speed!" + "</font> <br />")

    def CarStop(self):
        if self.serialObject.isOpen():
            command = bytearray([ord('\x55'), ord('\x11'), 0])
            self.serialObject.write(command)
            self.terminalAppend(">><font color=#FF0000>" +
                                "Stopping the car!" + "</font> <br />")

    def serialConnect(self):
        if self.serialObject.isOpen():
            self.statusBar().showMessage(
                "Serial communication is already running on " +
                self.serialObject.port + "!", 3000)
        else:
            portSelected, ok = SerialConnectDialog.getPort(self)
            if (ok == True):
                try:
                    self.serialObject.port = portSelected
                    self.serialObject.open()
                    self.statusBar().showMessage(
                        "Opened serial communication on " + portSelected + "!",
                        3000)

                    self.startDaemons()

                except serial.SerialException:
                    self.statusBar().showMessage(
                        "Could not open serial connection on " + portSelected +
                        "!", 3000)

            else:
                self.statusBar().showMessage("Serial connection cancelled!",
                                             3000)

    def startDaemons(self):
        self.plotUpdater.start(self.dataTimerUpdateRate)

        self.com_data_Xaccel_q = queue.Queue()
        self.com_data_Zgyro_q = queue.Queue()
        self.com_data_Tick_q = queue.Queue()
        self.com_terminal_q = queue.Queue()
        self.com_data_Lap_q = queue.Queue()
        self.com_monitor = ComMonitorThread(self.com_data_Xaccel_q,
                                            self.com_data_Zgyro_q,
                                            self.com_data_Tick_q,
                                            self.com_data_Lap_q,
                                            self.com_terminal_q,
                                            self.serialObject)
        self.com_monitor.daemon = True
        self.com_monitor.start()
        self.com_data_puller = ComDataPullerThread(self.serialObject, 25)

    def serialReconnect(self):
        if self.serialObject.isOpen():
            self.statusBar().showMessage(
                "Serial communication is already running on " +
                self.serialObject.port + "!", 3000)
        else:
            try:
                self.serialObject.open()
                self.statusBar().showMessage(
                    "Opened serial communication on " +
                    self.serialObject.port + "!", 3000)
                self.startDaemons()

            except serial.SerialException:
                self.statusBar().showMessage(
                    "Could not open serial connection on " +
                    self.serialObject.port + "!", 3000)

    def serialDisconnect(self):
        if self.serialObject.isOpen():
            #self.com_monitor.join()
            self.com_monitor = None
            self.com_data_puller.stop()
            self.com_data_puller = None
            self.serialObject.close()
            self.statusBar().showMessage(
                "Closed serial communication on " + self.serialObject.port +
                "!", 3000)
        else:
            self.statusBar().showMessage("No serial port to be closed!", 3000)

    def fileQuit(self):
        self.close()

    def closeEvent(self, ce):
        self.fileQuit()

    def about(self):
        QMessageBox.about(
            self, "About",
            """This is the turtle interface used for monitoring and modifying the behaviour of the Turtle Car"""
        )
예제 #2
0
class PlottingDataMonitor(QMainWindow):
    def __init__(self, parent=None):
        super(PlottingDataMonitor, self).__init__(parent)

        self.monitor_active = False
        self.logger_active = False
        self.com_monitor = None
        self.com_data_q = None
        self.com_error_q = None
        self.livefeed = LiveDataFeed()
        self.temperature_samples = []
        self.timer = QTimer()


        self.create_menu()
        self.create_main_frame()
        self.create_status_bar()


    def make_data_box(self, name):
        label = QLabel(name)
        qle = QLineEdit()
        qle.setEnabled(False)
        qle.setFrame(False)
        return (label, qle)

    def create_plot(self):
        plot = Qwt.QwtPlot(self)
        plot.setCanvasBackground(Qt.black)

        #plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 10000, 1000)



        plot.setAxisTitle(Qwt.QwtPlot.xBottom, 'Time')
        plot.setAxisScaleDraw(Qwt.QwtPlot.xBottom, DateTimeScaleDraw())
        plot.setAxisLabelRotation(Qwt.QwtPlot.xBottom, -45.0 )
        plot.setAxisLabelAlignment(Qwt.QwtPlot.xBottom, QtCore.Qt.AlignLeft | QtCore.Qt.AlignBottom )

        plot.setAxisTitle(Qwt.QwtPlot.yLeft, 'CDC Counts')
        plot.setAxisAutoScale(Qwt.QwtPlot.yLeft)
        #plot.setAxisScale(Qwt.QwtPlot.yLeft, 0, 8000000, 1000000)
        #plot.replot()

        curve = Qwt.QwtPlotCurve('')
        curve.setRenderHint(Qwt.QwtPlotItem.RenderAntialiased)
        pen = QPen(QColor('limegreen'))
        pen.setWidth(2)
        curve.setPen(pen)
        curve.attach(plot)

        return plot, curve

    def create_status_bar(self):
        self.status_text = QLabel('Monitor idle')
        self.statusBar().addWidget(self.status_text, 1)

    def create_main_frame(self):
        # Edit Box
        #
        self.editbox = QTextEdit()
        self.editbox.setReadOnly(True)
        editbox_layout = QVBoxLayout()
        editbox_layout.addWidget(self.editbox)
        editbox_layout.addStretch(1)
        editbox_groupbox = QGroupBox('CDC Counts')
        editbox_groupbox.setLayout(editbox_layout)
        # Port name
        #
        portname_l, self.portname = self.make_data_box('COM Port:')
        portname_layout = QHBoxLayout()
        portname_layout.addWidget(portname_l)
        portname_layout.addWidget(self.portname, 0)
        portname_layout.addStretch(1)
        portname_groupbox = QGroupBox('COM Port')
        portname_groupbox.setLayout(portname_layout)
        # Period Box
        #
        periodBox_l, self.periodBox = self.make_data_box('Period:')
        meanBox_l, self.meanBox = self.make_data_box('Mean:')
        deviationBox_l, self.deviationBox = self.make_data_box('Deviation:')
        countBox_l, self.countBox = self.make_data_box('Counts:')

        self.resetButton = QPushButton(QIcon('lucia.png'), 'Reset')
        self.resetButton.setGeometry(10, 10, 100, 30)
        self.resetButton.clicked.connect(self.periodReset)

        self.stopButton = QPushButton(QIcon('lucia.png'), 'Stop')
        self.stopButton.setGeometry(10,10,100,30)
        self.stopButton.clicked.connect(self.periodStop)

        periodBox_layout = QHBoxLayout()

        periodBox_layout.addWidget(periodBox_l)
        periodBox_layout.addWidget(self.periodBox, 0)

        #periodBox_layout.addWidget(meanBox_l)
        #periodBox_layout.addWidget(self.meanBox, 0)

        periodBox_layout.addWidget(deviationBox_l)
        periodBox_layout.addWidget(self.deviationBox, 0)

        periodBox_layout.addWidget(countBox_l)
        periodBox_layout.addWidget(self.countBox, 0)

        periodBox_layout.addWidget(self.resetButton)
        periodBox_layout.addWidget(self.stopButton)
        self.stop = 1


        periodBox_layout.addStretch(1)
        periodBox_groupbox = QGroupBox('Period Calculation')
        self.periodBox.setText('0')
        #self.meanBox.setText('M0')
        self.deviationBox.setText('0')
        self.countBox.setText('0')
        periodBox_groupbox.setLayout(periodBox_layout)
        # Add The Plot
        #
        self.plot, self.curve = self.create_plot()
        plot_layout = QVBoxLayout()
        plot_layout.addWidget(self.plot)
        plot_groupbox = QGroupBox('Capacitive to Digital Sensor Graph')
        plot_groupbox.setLayout(plot_layout)
        # Add The Zoomer
        #
        self.zoomer = Qwt.QwtPlotZoomer(
            Qwt.QwtPlot.xBottom,
            Qwt.QwtPlot.yLeft,
            Qwt.QwtPicker.DragSelection,
            Qwt.QwtPicker.AlwaysOff,
            self.plot.canvas())
        self.zoomer.setRubberBandPen(QPen(Qt.red))
        #self.zoomer.setZoomBase(True)
        # Main frame and layout
        #
        self.main_frame = QWidget()
        main_layout = QVBoxLayout()
        main_layout.addWidget(portname_groupbox)
        main_layout.addWidget(plot_groupbox)
        main_layout.addWidget(periodBox_groupbox)
        main_layout.addWidget(editbox_groupbox)
        main_layout.addStretch(1)
        self.main_frame.setLayout(main_layout)
        self.setCentralWidget(self.main_frame)
        self.set_actions_enable_state()

    def periodReset(self):
        print('Reset')
        self.periodAvg = []
        self.periodCount = 0
        self.stop = 0
        self.startTime=time.clock()
        self.r = Tk()
        self.r.withdraw()
        self.r.clipboard_clear()


    def periodStop(self):
        print('Stop')
        self.stop = 1
        try:
            for elem in self.periodAvg[2:len(self.periodAvg)]:
                self.r.clipboard_append(str(elem))
                self.r.clipboard_append('\n')
            self.r.destroy()
        except:
            print('There is nothing in the clipboard')

        #win32clipboard.OpenClipboard()
        #win32clipboard.EmptyClipboard()
        #win32clipboard.SetClipboardText(str(self.periodAvg[1:len(self.periodAvg)]))

        #win32clipboard.CloseClipboard()


    def create_menu(self):
        # The File Menu
        #
        self.file_menu = self.menuBar().addMenu("&File")
        selectport_action = self.create_action("Select COM &Port...",
            shortcut="Ctrl+P", slot=self.on_select_port, tip="Select a COM port")
        self.startMon_action = self.create_action("&Start monitor",
            shortcut="Ctrl+M", slot=self.on_startMon, tip="Start the data monitor")
        self.stopMon_action = self.create_action("&Stop monitor",
            shortcut="Ctrl+T", slot=self.on_stopMon, tip="Stop the data monitor")
        self.startLog_action = self.create_action("&Start logger",
            shortcut="Ctrl+L", slot=self.on_startLog, tip="Start the data logger")
        self.stopLog_action = self.create_action("&Stop logger",
            shortcut="Ctrl+T", slot=self.on_stopLog, tip="Stop the data logger")


        self.openFile = QAction(QIcon('open.png'), 'Open Graph', self)
        self.openFile.setShortcut('Ctrl+O')
        self.openFile.setStatusTip('Open Graph File')
        self.openFile.triggered.connect(self.on_Open)







        exit_action = self.create_action("E&xit", slot=self.close,
            shortcut="Ctrl+X", tip="Exit the application")
        self.startMon_action.setEnabled(False)
        self.stopMon_action.setEnabled(False)

        self.startLog_action.setEnabled(False)
        self.stopLog_action.setEnabled(False)

        self.add_actions(self.file_menu,
            (   selectport_action, self.openFile, self.startMon_action, self.stopMon_action, self.startLog_action, self.stopLog_action,
                None, exit_action))

        self.help_menu = self.menuBar().addMenu("&Help")
        about_action = self.create_action("&About",
            shortcut='F1', slot=self.on_about,
            tip='About the monitor')

        self.add_actions(self.help_menu, (about_action,))

    def selected(self, _):
        self.showInfo()

    def meanstdv(self, x):
        """ Calculate mean and standard deviation of data x[]:
        mean = {\sum_i x_i \over n} std = sqrt(\sum_i (x_i - mean)^2 \over n-1)
        """
        from math import sqrt
        n, mean, std = len(x), 0, 0
        for a in x:
            mean = mean + a
        mean = mean / float(n)
        for a in x:
            std = std + (a - mean)**2
        std = sqrt(std / float(n-1))
        return mean, std

    def on_Open(self):
        cdc_data = []
        index = []
        fname = QFileDialog.getOpenFileName(self, 'Open file', 'QDir::currentPath()')


        if fname.isEmpty() == False:
            f = open(fname, 'r')
            cdc_data = f.readlines()
            f.close()
            cdc_data.pop(0) #Pop the first and the last to get rid of bad data
            cdc_data.pop(-1)
            cdc_data_float = map(float, cdc_data)
            index = [i for i in range(len(cdc_data))]

            # Draw the Graph
            #

            self.curve.setData(index, cdc_data_float)
            #self.curve.setData(index[0:3600], cdc_data_float[0:3600])
            #Set up the axis scales
            self.plot.setAxisAutoScale(Qwt.QwtPlot.xBottom)
            self.plot.setAxisAutoScale(Qwt.QwtPlot.yLeft)
            self.zoomer.setZoomBase(True)

            #self.plot.replot()

    def set_actions_enable_state(self):
        if self.portname.text() == '':
            startMon_enable = stopMon_enable = False
            startLog_enable = stopLog_enable = False
        else:
            startMon_enable = not self.monitor_active
            stopMon_enable = self.monitor_active
            startLog_enable = not self.logger_active
            stopLog_enable = self.logger_active

        self.startLog_action.setEnabled(startLog_enable)
        self.startMon_action.setEnabled(startMon_enable)

        self.stopLog_action.setEnabled(stopLog_enable)
        self.stopMon_action.setEnabled(stopMon_enable)

    def on_about(self):
        msg = __doc__
        QMessageBox.about(self, "About cdcLogger", msg.strip())

    def on_select_port(self):
        ports = list(enumerate_serial_ports())
        if len(ports) == 0:
            QMessageBox.critical(self, 'No ports',
                'No serial ports found')
            return

        item, ok = QInputDialog.getItem(self, 'Select a port',
                    'Serial port:', ports, 0, False)

        if ok and not item.isEmpty():
            self.portname.setText(item)
            self.set_actions_enable_state()

    def on_stopMon(self):
        if self.com_monitor is not None:
            self.com_monitor.join(10)
            self.com_monitor = None

        self.monitor_active = False
        self.timer.stop()
        self.set_actions_enable_state()
        self.status_text.setText('Monitor idle')

    def on_startMon(self):
        if self.com_monitor is not None or self.portname.text() == '':
           return

        # First define a couple of variables that will be used to calculate the period
        #self.startTime = 1.1
        self.mark = 'False'
        self.periodAvg = []
        self.periodCount = 0


        self.data_q = Queue.Queue()
        self.error_q = Queue.Queue()
        self.com_monitor = ComMonitorThread(
            self.data_q,
            self.error_q,
            full_port_name(str(self.portname.text())),
            57600)
        self.com_monitor.start()

        com_error = get_item_from_queue(self.error_q)
        if com_error is not None:
            QMessageBox.critical(self, 'ComMonitorThread error', com_error)
            self.com_monitor = None

        self.monitor_active = True
        self.set_actions_enable_state()

        self.timer = QTimer()
        self.connect(self.timer, SIGNAL('timeout()'), self.on_timer)

        self.timer.start(.005)
        self.status_text.setText('Monitor running')

    def on_startLog(self):
        self.log()
        self.logger_active = True
        self.set_actions_enable_state()

    def on_stopLog(self):
        self.logger_active = False
        self.set_actions_enable_state()

    def on_timer(self):
        """ Executed periodically when the monitor update timer
            is fired.
        """
        self.read_serial_data()
        self.update_monitor()

    def log(self):
        self.log_state = True
        self.reading_num = 0

        self.today = str(datetime.date.today())
        self.logname = '%s.csv' % self.today
        self.file = open(self.logname, "wb")
        self.file_cvs = csv.writer(self.file)

    def save_data(self,reading):
        self.file_cvs.writerow ([reading])

    def save_data_stamps(self,reading_num,reading,timestamp,utimestamp):
        self.file_cvs.writerow ([reading_num,reading,timestamp,utimestamp])

    def update_monitor(self):
        """ Updates the state of the monitor window with new
            data. The livefeed is used to find out whether new
            data was received since the last update. If not,
            nothing is updated.
        """
        if self.livefeed.has_new_data:
            data = self.livefeed.read_data()



            # time.time() is a timestamp for the graph X axis ticks
            # This may be a good place to add period calculation
            #
            self.temperature_samples.append((time.time(), data['temperature']))
            if len(self.temperature_samples) > 765:
                self.temperature_samples.pop(0)

            xdata = [s[0] for s in self.temperature_samples]
            ydata = [s[1] for s in self.temperature_samples]


            if (len(self.temperature_samples) > 2 and self.stop == 0):

                if data['temperature'] > self.temperature_samples[-2][1]:
                    self.mark = 1
                elif (data['temperature'] < self.temperature_samples[-2][1]) and (self.mark == 1):
                    endTime = time.clock()
                    period = (endTime - self.startTime)
                    self.periodAvg.append(period)
                    if (len(self.periodAvg) <= 3):
                        self.periodBox.setText('0')
                        self.deviationBox.setText('0')
                        self.countBox.setText('Waiting')


                    if (len(self.periodAvg) > 3):
                        self.Average, self.Deviation = self.meanstdv(self.periodAvg[2:len(self.periodAvg)])
                        self.periodBox.setText(str(self.Average))
                        self.deviationBox.setText(str(self.Deviation))
                        self.countBox.setText(str(len(self.periodAvg)-2))






                    self.startTime = endTime
                    self.periodCount += 1
                    self.mark = 0

            #avg = sum(ydata) / float(len(ydata))


            self.plot.setAxisAutoScale(Qwt.QwtPlot.yLeft)
            self.plot.setAxisScale(Qwt.QwtPlot.xBottom, xdata[0], max(20, xdata[-1]))
            self.curve.setData(xdata, ydata)

            self.plot.replot()

            #self.plot.setAxisAutoScale(Qwt.QwtPlot.xBottom)
            #self.zoomer.setZoomBase(True)
            #self.thermo.setValue(avg)

    def read_serial_data(self):
        """ Called periodically by the update timer to read data
            from the serial port.
        """
        qdata = list(get_all_from_queue(self.data_q))
        if len(qdata) > 0: # At this point qdata object is a list type
            count = 0

            # Updates the text box with the incoming values
            # Clears the text box every 4096 values so that
            # Memory does not fill up with scrolling text
            for elem in list(qdata):
                self.editbox.append(qdata[count][0])
                if self.editbox.document().blockCount() == 4096:
                    self.editbox.clear()
                data = dict(timestamp=qdata[count][1],temperature=int(qdata[count][0]))
                self.livefeed.add_data(data)


                if self.logger_active:
                    self.reading_num = self.reading_num + 1

                    #Uncomment for stamps
                    #

                    #utimestamp = time.time() #A unix style timestamp for the log
                    #self.save_data_stamps(self.reading_num,int(qdata[count][0]),qdata[count][1],utimestamp)


                    if self.today != str(datetime.date.today()):
                        self.file.close()
                        self.log();
                        self.reading_num = self.reading_num + 1

                    self.save_data(int(qdata[count][0]))

                count=count+1

            #data = dict(timestamp=qdata[-1][1],
            #           temperature=int(qdata[-1][0]))

            #self.livefeed.add_data(data)

    def add_actions(self, target, actions):
        '''The following two methods are utilities for simpler creation
        and assignment of actions
        '''
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def create_action(  self, text, slot=None, shortcut=None,
                        icon=None, tip=None, checkable=False,
                        signal="triggered()"):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(":/%s.png" % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot)
        if checkable:
            action.setCheckable(True)
        return action

    def closeEvent(self, event):
        self.editbox.append("closing PyQtTest")
class PlottingDataMonitor(QMainWindow):
    def __init__(self, parent=None):
        super(PlottingDataMonitor, self).__init__(parent)

        self.setWindowTitle('ADXL345 Realtime Monitor')
        self.resize(800, 600)
        
        self.port           = ""
        self.baudrate       = 9600
        self.monitor_active = False                 # on/off monitor state
        self.com_monitor    = None                  # monitor reception thread
        self.com_data_q     = None
        self.com_error_q    = None
        self.livefeed       = LiveDataFeed()
        self.timer          = QTimer()
        self.g_samples      = [[], [], []]
        self.curve          = [None]*3
        self.gcurveOn       = [1]*3                 # by default all curve are plotted
        self.csvdata        = []
        
        self.create_menu()
        self.create_main_frame()
        self.create_status_bar()

        # Activate start-stop button connections
        self.connect(self.button_Connect, SIGNAL("clicked()"),
                    self.OnStart)
        self.connect(self.button_Disconnect, SIGNAL("clicked()"),
                    self.OnStop)
    #----------------------------------------------------------


    def create_com_box(self):
        """
        Purpose:   create the serial com groupbox
        Return:    return a layout of the serial com
        """
        self.com_box = QGroupBox("COM Configuration")

        com_layout = QGridLayout()

        self.radio115200    =    QRadioButton("115200")
        self.radio115200.setChecked(1)
        self.radio19200    =    QRadioButton("19200")
        self.radio9600     =    QRadioButton("9600")
        self.Com_ComboBox  =    QComboBox()

        com_layout.addWidget(self.Com_ComboBox,0,0,1,3)
        com_layout.addWidget(self.radio115200,1,0)
        com_layout.addWidget(self.radio19200,1,1)
        com_layout.addWidget(self.radio9600,1,2)
        self.fill_ports_combobox()

        self.button_Connect      =   QPushButton("Start")
        self.button_Disconnect   =   QPushButton("Stop")
        self.button_Disconnect.setEnabled(False)

        com_layout.addWidget(self.button_Connect,0,3)
        com_layout.addWidget(self.button_Disconnect,1,3)

        return com_layout
    #---------------------------------------------------------------------


    def create_plot(self):
        """ 
        Purpose:   create the pyqwt plot
        Return:    return a list containing the plot and the list of the curves
        """
        plot = Qwt.QwtPlot(self)
        plot.setCanvasBackground(Qt.black)
        plot.setAxisTitle(Qwt.QwtPlot.xBottom, 'Time')
        plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 10, 1)
        plot.setAxisTitle(Qwt.QwtPlot.yLeft, 'Acceleration')
        plot.setAxisScale(Qwt.QwtPlot.yLeft, YMIN, YMAX, (YMAX-YMIN)/10)
        plot.replot()
        
        curve = [None]*3
        pen = [QPen(QColor('limegreen')), QPen(QColor('red')) ,QPen(QColor('yellow')) ]
        for i in range(3):
            curve[i] =  Qwt.QwtPlotCurve('')
            curve[i].setRenderHint(Qwt.QwtPlotItem.RenderAntialiased)
            pen[i].setWidth(2)
            curve[i].setPen(pen[i])
            curve[i].attach(plot)

        return plot, curve
    #---------------------------------------------------


    def create_knob(self):
        """ 
        Purpose:   create a knob
        Return:    return a the knob widget
        """
        knob = Qwt.QwtKnob(self)
        knob.setRange(0, 180, 0, 1)
        knob.setScaleMaxMajor(10)
        knob.setKnobWidth(50)
        knob.setValue(180)
        return knob
    #---------------------------------------------------


    def create_status_bar(self):
        self.status_text = QLabel('Monitor idle')
        self.statusBar().addWidget(self.status_text, 1)
    #---------------------------------------------------


    def create_checkbox(self, label, color, connect_fn, connect_param):
        """
        Purpose:    create a personalized checkbox
        Input:      the label, color, activated function and the transmitted parameter
        Return:     return a checkbox widget
        """
        checkBox = QCheckBox(label)
        checkBox.setChecked(1)
        checkBox.setFont( QFont("Arial", pointSize=12, weight=QFont.Bold ) )
        green = QPalette()
        green.setColor(QPalette.Foreground, color)
        checkBox.setPalette(green)
        self.connect(checkBox, SIGNAL("clicked()"), partial(connect_fn,connect_param))
        return checkBox
        #---------------------------------------------------


    def create_main_frame(self):
        """
        Purpose:    create the main frame Qt widget
        """
        # Serial communication combo box
        portname_layout = self.create_com_box()
        self.com_box.setLayout(portname_layout)
        
        # Update speed knob
        self.updatespeed_knob = self.create_knob()
        self.connect(self.updatespeed_knob, SIGNAL('valueChanged(double)'),
            self.on_knob_change)
        self.knob_l = QLabel('Update speed = %s (Hz)' % self.updatespeed_knob.value())
        self.knob_l.setAlignment(Qt.AlignTop | Qt.AlignHCenter)

        # Create the plot and curves
        self.plot, self.curve = self.create_plot()

        # Create the configuration horizontal panel
        self.max_spin    = QSpinBox()
        self.max_spin.setMaximum(10000)
        self.max_spin.setValue(10000)
        spins_hbox      = QHBoxLayout()
        spins_hbox.addWidget(QLabel('Save every'))
        spins_hbox.addWidget(self.max_spin)
        spins_hbox.addWidget( QLabel('Lines'))
        #spins_hbox.addStretch(1)

        self.gCheckBox   =  [   self.create_checkbox("Acceleration(x)", Qt.green, self.activate_curve, 0),
                                self.create_checkbox("Acceleration(y)", Qt.red, self.activate_curve, 1),
                                self.create_checkbox("Acceleration(z)", Qt.yellow, self.activate_curve, 2)
                            ]

        self.button_clear      =   QPushButton("Clear screen")

        self.connect(self.button_clear, SIGNAL("clicked()"),
                    self.clear_screen)

        # Place the horizontal panel widget
        plot_layout = QGridLayout()
        plot_layout.addWidget(self.plot,0,0,8,7)
        plot_layout.addWidget(self.gCheckBox[0],0,8)
        plot_layout.addWidget(self.gCheckBox[1],1,8)
        plot_layout.addWidget(self.gCheckBox[2],2,8)
        plot_layout.addWidget(self.button_clear,3,8)
        plot_layout.addLayout(spins_hbox,4,8)
        plot_layout.addWidget(self.updatespeed_knob,5,8)
        plot_layout.addWidget(self.knob_l,6,8)
        
        plot_groupbox = QGroupBox('Acceleration')
        plot_groupbox.setLayout(plot_layout)
        
        # Place the main frame and layout
        self.main_frame = QWidget()
        main_layout 	= QVBoxLayout()
        main_layout.addWidget(self.com_box)
        main_layout.addWidget(plot_groupbox)
        main_layout.addStretch(1)
        self.main_frame.setLayout(main_layout)
        
        self.setCentralWidget(self.main_frame)
    #----------------------------------------------------------------------


    def clear_screen(self):
        self.g_samples = [[], [], []]
        self.plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 10)
        for i in range(3):
            self.curve[i].setData([], [])
        self.plot.replot()
    #-----------------------------


    def activate_curve(self, axe):
        if self.gCheckBox[axe].isChecked():
            self.gcurveOn[axe]  = 1
        else:
            self.gcurveOn[axe]  = 0
    #---------------------------------------


    def create_menu(self):
        self.file_menu = self.menuBar().addMenu("&File")
        
        selectport_action = self.create_action("Select COM &Port...",
            shortcut="Ctrl+P", slot=self.on_select_port, tip="Select a COM port")
        self.start_action = self.create_action("&Start monitor",
            shortcut="Ctrl+M", slot=self.OnStart, tip="Start the data monitor")
        self.stop_action = self.create_action("&Stop monitor",
            shortcut="Ctrl+T", slot=self.OnStop, tip="Stop the data monitor")
        exit_action = self.create_action("E&xit", slot=self.close, 
            shortcut="Ctrl+X", tip="Exit the application")
        
        self.start_action.setEnabled(False)
        self.stop_action.setEnabled(False)
        
        self.add_actions(self.file_menu, 
            (   selectport_action, self.start_action, self.stop_action,
                None, exit_action))
            
        self.help_menu = self.menuBar().addMenu("&Help")
        about_action = self.create_action("&About",
            shortcut='F1', slot=self.on_about,
            tip='About the monitor')
        
        self.add_actions(self.help_menu, (about_action,))
    #----------------------------------------------------------------------


    def set_actions_enable_state(self):
        if self.portname.text() == '':
            start_enable = stop_enable = False
        else:
            start_enable = not self.monitor_active
            stop_enable = self.monitor_active
        
        self.start_action.setEnabled(start_enable)
        self.stop_action.setEnabled(stop_enable)
    #-----------------------------------------------


    def on_about(self):
        msg = __doc__
        QMessageBox.about(self, "About the demo", msg.strip())
    #-----------------------------------------------


    def on_select_port(self):
        
        ports = enumerate_serial_ports()
        
        if len(ports) == 0:
            QMessageBox.critical(self, 'No ports',
                'No serial ports found')
            return
        
        item, ok = QInputDialog.getItem(self, 'Select a port',
                    'Serial port:', ports, 0, False)
        
        if ok and not item.isEmpty():
            self.portname.setText(item)
            self.set_actions_enable_state()
    #-----------------------------------------------


    def fill_ports_combobox(self):
        """ Purpose: rescan the serial port com and update the combobox
        """
        vNbCombo = ""
        self.Com_ComboBox.clear()
        self.AvailablePorts = enumerate_serial_ports()
        for value in self.AvailablePorts:
            self.Com_ComboBox.addItem(value)
            vNbCombo += value + " - "
        vNbCombo = vNbCombo[:-3]

        debug(("--> Les ports series disponibles sont: %s " % (vNbCombo)))
    #----------------------------------------------------------------------


    def OnStart(self):
        """ Start the monitor: com_monitor thread and the update timer
        """
        if self.radio115200.isChecked():
            self.baudrate = 115200
            print "--> baudrate is 115200 bps"
        if self.radio19200.isChecked():
            self.baudrate = 19200
            print "--> baudrate is 19200 bps"
        if self.radio9600.isChecked():
            self.baudrate = 9600
            print "--> baudrate is 9600 bps"

        vNbCombo    = self.Com_ComboBox.currentIndex()
        self.port   = self.AvailablePorts[vNbCombo]

        self.button_Connect.setEnabled(False)
        self.button_Disconnect.setEnabled(True)
        self.Com_ComboBox.setEnabled(False)

        self.data_q      =  Queue.Queue()
        self.error_q     =  Queue.Queue()
        self.com_monitor =  ComMonitorThread(
                                            self.data_q,
                                            self.error_q,
                                            self.port,
                                            self.baudrate)
        
        self.com_monitor.start()

        com_error = get_item_from_queue(self.error_q)
        if com_error is not None:
            QMessageBox.critical(self, 'ComMonitorThread error',
                com_error)
            self.com_monitor = None  

        self.monitor_active = True

        self.connect(self.timer, SIGNAL('timeout()'), self.on_timer)
        
        update_freq = self.updatespeed_knob.value()
        if update_freq > 0:
            self.timer.start(1000.0 / update_freq)
        
        self.status_text.setText('Monitor running')
        debug('--> Monitor running')
    #------------------------------------------------------------


    def OnStop(self):
        """ Stop the monitor
        """
        if self.com_monitor is not None:
            self.com_monitor.join(1000)
            self.com_monitor = None

        self.monitor_active = False
        self.button_Connect.setEnabled(True)
        self.button_Disconnect.setEnabled(False)
        self.Com_ComboBox.setEnabled(True)
        self.timer.stop()
        self.status_text.setText('Monitor idle')
        debug('--> Monitor idle')
    #-----------------------------------------------


    def on_timer(self):
        """ Executed periodically when the monitor update timer
            is fired.
        """
        self.read_serial_data()
        self.update_monitor()
    #-----------------------------------------------


    def on_knob_change(self):
        """ When the knob is rotated, it sets the update interval
            of the timer.
        """
        update_freq = self.updatespeed_knob.value()
        self.knob_l.setText('Update speed = %s (Hz)' % self.updatespeed_knob.value())

        if self.timer.isActive():
            update_freq = max(0.01, update_freq)
            self.timer.setInterval(1000.0 / update_freq)
    #-----------------------------------------------


    def update_monitor(self):
        """ Updates the state of the monitor window with new 
            data. The livefeed is used to find out whether new
            data was received since the last update. If not, 
            nothing is updated.
        """
        if self.livefeed.has_new_data:
            data = self.livefeed.read_data()

            self.csvdata.append([data['timestamp'], data['gx'], data['gy'], data['gz']] )
            if len(self.csvdata) > self.max_spin.value():
                f = open(time.strftime("%H%M%S")+".csv", 'wt')
                try:
                    writer = csv.writer(f)
                    for i in range(self.max_spin.value()):
                        writer.writerow( self.csvdata[i] )
                    print 'transfer data to csv after 10000 samples'
                finally:
                    f.close()
                self.csvdata = []

            self.g_samples[0].append(
                (data['timestamp'], data['gx']))
            if len(self.g_samples[0]) > 1000:
                self.g_samples[0].pop(0)

            self.g_samples[1].append(
                (data['timestamp'], data['gy']))
            if len(self.g_samples[1]) > 1000:
                self.g_samples[1].pop(0)

            self.g_samples[2].append(
                (data['timestamp'], data['gz']))
            if len(self.g_samples[2]) > 1000:
                self.g_samples[2].pop(0)

            tdata = [s[0] for s in self.g_samples[2]]

            for i in range(3):
                data[i] = [s[1] for s in self.g_samples[i]]
                if self.gcurveOn[i]:
                    self.curve[i].setData(tdata, data[i])

            """
            debug("xdata", data[0])
            debug("ydata", data[1])
            debug("tdata", data[2])
            """

            #self.plot.setAxisScale(Qwt.QwtPlot.xBottom, tdata[0], max(10, tdata[-1]) )

            self.plot.replot()
    #-----------------------------------------------


    def read_serial_data(self):
        """ Called periodically by the update timer to read data
            from the serial port.
        """
        qdata = list(get_all_from_queue(self.data_q))
        # get just the most recent data, others are lost
        #print "qdata" , qdata
        if len(qdata) > 0:
            data = dict(timestamp=qdata[-1][1], 
                        gx=qdata[-1][0][0],
                        gy=qdata[-1][0][1],
                        gz=qdata[-1][0][2]
                        )
            self.livefeed.add_data(data)
    #-----------------------------------------------


    # The following two methods are utilities for simpler creation
    # and assignment of actions
    #
    def add_actions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)
    #-----------------------------------------------


    def create_action(  self, text, slot=None, shortcut=None, 
                        icon=None, tip=None, checkable=False, 
                        signal="triggered()"):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(":/%s.png" % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot)
        if checkable:
            action.setCheckable(True)
        return action
예제 #4
0
class ProdGui(QMainWindow):
    def __init__(self, parent = None):
        super(ProdGui, self).__init__(parent)
        
        # counters
        self.face_count = 0
        self.device_count = 1
        self.current_device_no = 1
        
        # Create the queues for data transfer from serial
        self.q_Data = None
        self.q_Error = None
        # Create (serial) event monitor flag
        self.event_monitor = False
        self.com_monitor = None
        # Create a data class
        self.livefeed = LiveDataFeed()
        self.value_samples = []
        # Create a Timer Class
        self.timer = QTimer()
        
        #Init the UI
        self.create_main_frame()
        self.create_menu()
        
        #text file we will be saving in
        # ACC | GSM | GSM_SNR | RTC | SD | NRF_SPI | STN | V_BAT | GPS | GPS_ANT | NRF-ACC | NRF_SD | NRF_OTA
        self.failed_checks = {"acc":0,"gsm":0,"gsm_snr":0,"rtc":0,"sd":0,"nrf_spi":0,"stn":0,"v_bat":0,
                              "gps":0,"gps_ant":0,"nrf_acc":0,"nrf_sd":0,"nrf_ota":0}
        
        self.setWindowTitle("Carnot Production")
        
        #advanced stuff
        self.advanced_set = False
        self.timer_counter = 0
        self.small_string_flag = 0
        
    def create_main_frame(self):
        self.createFaces()
        self.create_next_button()
        self.create_status_bar()
        
        self.leftGroupBox.setEnabled(False)
        self.middleGroupBox.setEnabled(False)
        self.rightGroupBox.setEnabled(False)
        self.basicGroupBox.setEnabled(False)
        self.leftGroupBox.hide()
        self.middleGroupBox.hide()
        self.rightGroupBox.hide()
        
        self.basic.pixelLabel.setPixmap(QPixmap("images/logo.png"))
        self.left.pixelLabel.setPixmap(QPixmap("images/logo.png"))
        self.basic.saveToText.clicked.connect(self.on_save_txt)
        self.basic.submitButton.clicked.connect(self.on_submit)
        self.basic.device_text.append(str(self.current_device_no))
        self.basic.nextButton.clicked.connect(self.on_flash_button)
#         self.left.device_id.append(str(self.current_device_no))
        
        self.main_frame = QWidget()
        
        face_widget = QWidget()
        face_layout = QHBoxLayout()
        face_layout.addWidget(self.leftGroupBox);
        face_layout.addWidget(self.middleGroupBox);
        face_layout.addWidget(self.rightGroupBox);
        face_layout.addWidget(self.basicGroupBox)
        face_widget.setLayout(face_layout)
        
        main_layout = QVBoxLayout()
        main_layout.addWidget(face_widget)
        main_layout.addWidget(self.next_button)
        self.main_frame.setLayout(main_layout)
        self.setCentralWidget(self.main_frame)
        
    def on_flash_button(self):
        
        print("\n\nFlashing NRF\n")
        os.system("flashNRF.cmd")
        os.system('testing_main1.cmd')
        time.sleep(5)
    
    def create_menu(self):
        self.menu = self.menuBar().addMenu("&File")
        
        self.start_qc = self.create_action("Start &QC", 
                                           shortcut = "Ctrl+Q", slot = self.on_start, 
                                           tip = "Start the QC process")
        self.advanced = self.create_action("&Advanced", 
                                           shortcut = "Ctrl+C", slot = self.on_advanced, 
                                           tip = "Super Saiyan")
        self.menu.addAction(self.start_qc)
        self.menu.addAction(self.advanced) 
        
     
    def createFaces(self):
        self.leftGroupBox = QGroupBox("Step 1")
        self.left = LeftWidget()
        layout1 = QVBoxLayout()
        layout1.addWidget(self.left)
        self.leftGroupBox.setLayout(layout1)
        self.leftGroupBox.setMaximumSize(400, 450)
        
        self.middleGroupBox = QGroupBox("Step 2")
        self.middle = MiddleWidget()
        layout2 = QVBoxLayout()
        layout2.addWidget(self.middle)
        self.middleGroupBox.setLayout(layout2)
        self.middleGroupBox.setMaximumSize(450, 450)
        
        self.rightGroupBox = QGroupBox("Step 3")
        self.right = RightWidget()
        layout3 = QVBoxLayout()
        layout3.addWidget(self.right)
        self.rightGroupBox.setLayout(layout3)
        self.rightGroupBox.setMaximumSize(400, 450)
        # adding the next device button the right widget
        self.right.nextButton.clicked.connect(self.new_device)
        
        self.basicGroupBox = QGroupBox("Carnot")
        self.basic = BasicWidget()
        layout4 = QVBoxLayout()
        layout4.addWidget(self.basic)
        self.basicGroupBox.setLayout(layout4)
        self.basicGroupBox.setMinimumSize(400, 550)
        self.basicGroupBox.setMaximumSize(400, 1000)
        #self.basic.nextButton.clicked.connect(self.new_device())
        
    
    def create_next_button(self):
        self.next_button = QPushButton("Next")
        #self.next_button.clicked.connect(self.__next_face)
        self.next_button.clicked.connect(self.new_device)
        self.next_button.setEnabled(False)
        
    def create_status_bar(self):
        self.status_text = QLabel("Idle  (No QC?)")
        #self.statusBar().addWidget(self.status_text)
    
    def create_action(  self, text, slot=None, shortcut=None, 
                        icon=None, tip=None, checkable=False, 
                        signal="triggered()"):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(":/%s.png" % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            action.triggered.connect(slot)
        if checkable:
            action.setCheckable(True)
        return action   
        
    def new_device(self):
        
        #inclease device number
        self.basic.device_text.clear()
        self.basic.device_text.append(str(int(self.current_device_no) + 1))
        self.current_device_no = int(self.current_device_no) + 1
        #disable the buttons
        self.basic.saveToText.setEnabled(False)
        self.basic.submitButton.setEnabled(False)
        self.basic.nextButton.setEnabled(False) 
        self.basic.pixelLabel.setPixmap(QPixmap("images/logo.png"))
        #refresh_face
        #self.update_faces()
        '''
        self.leftGroupBox.setEnabled(False)
        self.middleGroupBox.setEnabled(False)
        self.rightGroupBox.setEnabled(False)
        self.leftGroupBox.setEnabled(True)
        self.next_button.setEnabled(True)
        print("device count:", self.device_count, '\n')
        self.left.update(self.on_serial_ports(),"Checked", qr_code(self.device_count))
        '''
        
    def __next_face(self):
        
        if self.face_count == 0:
            self.middleGroupBox.setEnabled(True)
            self.face_count += 1
            self.update_faces()
        elif self.face_count == 1:
            self.rightGroupBox.setEnabled(True)
            self.face_count = 0
            self.next_button.setEnabled(False)
            self.device_count += 1
            
            
    def on_serial_ports(self):
        ''' get a list of ports available.
        '''
        
        port_list = serial_ports()
        if len(port_list) == 0:
            QMessageBox.critical(self, "Check Connection",
                                  "Device Not Connected")
            return
        port = port_list
        return port
    
    def on_timer(self):
        """Executed periodically when qc update timer is launched""" 
        self.read_serial_data()
        
    def on_advanced(self):
        self.leftGroupBox.show()
        self.middleGroupBox.show()
        self.advanced_set = True
        if self.basicGroupBox.isEnabled():
            self.leftGroupBox.setEnabled(True)
            self.middleGroupBox.setEnabled(True)
        else:
            self.leftGroupBox.setEnabled(False)
            self.middleGroupBox.setEnabled(False)
    
    def on_start(self):
        ''' Start session -> on_serial_ports, then com_monitor
        thread 
        '''
        # this will call the flashing cmd scripts
        print("\n\nFlashing NRF\n")
        os.system("flashNRF.cmd")
        os.system("testing_main1.cmd")
        # so on start we will flash the device
        #then we sleep for 5 seconds so that the system is ready
        time.sleep(5)
        
        self.basicGroupBox.setEnabled(True)
        self.next_button.setEnabled(True)
#         self.basic.pixelLabel.setPixmap(QPixmap("images/cross-1.png"))
        self.basic.pixelLabel.setEnabled(True)
        
        if self.advanced_set:
            self.leftGroupBox.setEnabled(True)
            self.middleGroupBox.setEnabled(True)
        
        if self.com_monitor is not None and self.left.com_set() == "":
            return
        self.q_Data = queue.Queue()
        self.q_Error = queue.Queue()
        self.com_monitor = ComMonitorThread(
            self.q_Data,
            self.q_Error,
            self.on_serial_ports(),
            9600)
        self.com_monitor.start()
        
        com_error = get_item_from_queue(self.q_Error)
        if com_error is not None:
            QMessageBox.critical(self, 'ComMonitorThread error',
                com_error)
            self.com_monitor = None
            
        self.event_monitor = True
        
        self.timer = QTimer()
#         self.connect(self.timer, SIGNAL('timeout()'), self.on_timer)
        self.timer.timeout.connect(self.on_timer)
        self.timer.start(500.0)
        
        #self.status_text.setText("Bad Batch")
        
    def read_serial_data(self):
        """Called periodically to see if serial buffer
        data available"""
        
        ''' each qdata has a list which with-in has a list with 
        single character plus time stamp.
        '''
        #[STAT]: ACC | GSM | GSM_SNR | RTC | SD | NRF_SPI | STN | GPS | GPS_ANT | NRF-ACC
        #[INFO]: STM_FW | STM_ID | STN_FW | GSM_Ver | CCID | NRF_ID_low | NRF_ID_high
        
        b = []
        self.timer_counter += 1
        #every 1 sec
        if self.timer_counter > 2:
            self.timer_counter = 0
            qdata = list(get_all_from_queue(self.q_Data))
            print(qdata)
            if len(qdata) > 0 and b'S' in qdata[0][0]:
                qdata = qdata[1:] #skip the first S
                if len(qdata) > 70:
                    self.left.update(self.on_serial_ports(),"Checked", qr_code(self.device_count))
                for i_a in qdata:
                    if b'\r' in i_a:
                        break
                    b.append(i_a[0])
                #TODO: there is a glich in the code, if we do advanced while running the QC,
                # we only get a portion of the UART string
                if len(b) > 120:
                    if b[1] == b'A':
                        #in b we dont need the last 3 values \r \n and b'S'
                        #and in the bedinning we dont need b'TAT'
                        data = []
#                         print(b)
                        for i in range(0,len(b)):
                            data.append(b[i].decode("utf-8"))
                            
                        #find position of "I" for STAT string ending
                        #find position of "S" or "\r" for INFT string ending
#                         print(data)
                        if "I" in data:
                            data_stat = data[4:(data.index("I")-1)]
                            data_info = data[data.index("I")+5:]
                            print(data_stat)
                            print(data_info)
                            data_stat = "".join(data_stat)
                            data_info = "".join(data_info)
                            data_stat = data_stat.split(",")
                            data_info = data_info.split(",")
                            # now we have our data in the above variables
                            '''ACC | GSM | GSM_SNR | RTC | SD | NRF_SPI | STN | V_BAT | GPS | GPS_ANT | NRF-ACC | NRF_SD | NRF_OTA
                               STM_FW | STM_ID | STN_FW | GSM_Ver | CCID | NRF_ID_low | NRF_ID_high
                            '''
                            print(data_stat)
                            print(data_info)
                            self.livefeed.add_status(data_stat)
                            self.livefeed.add_info(data_info)
                            self.update_faces()
                else:
                    self.small_string_flag += 1
                    if self.small_string_flag > 10:
                        QMessageBox.information(self, "Check Connections", "Receiving less data, maybe NRF SPI has failed")
                        self.small_string_flag = 5
            else:
                pass
            
        self.current_device_no = self.basic.device_text.toPlainText()
        if self.current_device_no != "":
            self.basic.qr.clear()
            self.basic.qr.append(qr_code(self.current_device_no))
        #the following is for data from Teensy
        '''data = qdata[0]
        data = data[0].decode("utf-8")
        data_stat = "".join(data[5:34])
        data_info = ''.join(data[41:])
        
        data_stat = data_stat.split(",")
        data_info = data_info.split(",")
        print(data_stat)
        print(data_info)
        self.livefeed.add_status(data_stat)
        self.livefeed.add_info(data_info)
        self.update_faces()'''
        
        
    def update_faces(self):
        '''ACC | GSM | GSM_SNR | RTC | SD | NRF_SPI | STN | V_BAT | GPS | GPS_ANT | NRF-ACC | NRF_SD | NRF_OTA
           STM_FW | STM_ID | STN_FW | GSM_Ver | CCID | NRF_ID_low | NRF_ID_high | NRF_Version
        '''
        if self.livefeed.has_new_status:
            data_status = self.livefeed.read_status()
            #update battery voltage
            self.basic.text1.clear()
            self.basic.text1.append(data_status[7])
            #read info
            data_info = self.livefeed.read_info()
            if self.check_stm_status(data_status,data_info):
                print("All stats good")
            else:
                print("Error\n")
                   
        if self.livefeed.has_new_info:
            data_info = self.livefeed.read_info()
        else:
            pass
        
        '''if self.livefeed.has_new_status:
            data_status = self.livefeed.read_status()
            if self.check_stm_status(data_status):
                self.middle.update_middle_status(data_status[-1])
            else:
                print("Error\n")
            
#             self.middle.update_middle(data[0], data[1], data[2], data[3:])   
        if self.livefeed.has_new_info:
            data_info = self.livefeed.read_info()
            #format stm_id, nrf_id, stm_ver, nrf_ver
            if self.check_stm_status(data_status):
                self.middle.update_middle(data_info[1], data_info[-1], data_info[0], data_info[2])
            else:
                print("Error\n")
        else:
            pass'''
        
    def check_stm_status(self,data,info):
        '''ACC | GSM | GSM_SNR | RTC | SD | NRF_SPI | STN | V_BAT | GPS | GPS_ANT | NRF-ACC | NRF_SD | NRF_OTA
           STM_FW | STM_ID | STN_FW | GSM_Ver | CCID | NRF_ID_low | NRF_ID_high | NRF_version
        '''
        #this is used for teensy debugging
        #[STAT]: //ACC | GSM | GSM_SNR | RTC | SD | NRF_SPI | STN | V_BAT | GPS | GPS_ANT | NRF-ACC | NRF_SD | NRF_OTA
        #self.middle.update_status_flags(data[6], data[1], data[0], data[3], data[5],data[2],
        #                                data[4], data[7], data[8], data[9])
        if self.advanced_set:
            print(info[8])
            if 'S' not in info[8]:
                self.middle.update_middle(*info)
                self.middle.update_status_flags(data[6], data[1], data[0], data[3], data[5], data[2],
                                                 data[4], data[8], data[9], data[10], data[11], data[12])
            else:
                print("Bad info string received\n")
        
        
        #print(data)
        if '0' in data:
            print(data)
            number_fails = data.count('0')
            fail = ""
            failed_devices = []
            if data[0] == '0':
                failed_devices.append("ACC")
            if data[1] == '0':
                failed_devices.append("GSM")
            if data[2] == '0':
                failed_devices.append("GSM-SNR")
            if data[3] == '0':
                failed_devices.append("RTC")
            if data[4] == '0':
                failed_devices.append("SD")
            if data[5] == '0':
                failed_devices.append("NRF-SPI")
            if data[6] == '0':
                failed_devices.append("STN")
            if data[7] == '0':
                failed_devices.append("GPS")
            if data[8] == '0':
                failed_devices.append("GPS-ANT")
            if data[9] == '0':
                failed_devices.append("NRF-ACC")
            print(failed_devices)
            fail = " ".join(failed_devices)
            print(fail)
            
            QMessageBox.critical(self, "Device Modules Failed", "%s module(s) failed"% fail)
            self.basic.pixelLabel.setPixmap(QPixmap("images/cross-1.png"))
            #TODO: Disable this popup from comming again and again
            return 0
        elif int(data[2]) < 12:
            QMessageBox.critical(self, "GSM Antenna", "Please reconnect it")
        else:
            #TODO: Enable all the buttons
            self.basic.pixelLabel.setPixmap(QPixmap("images/tick-black.png"))
            self.basic.submitButton.setEnabled(True)
            self.basic.saveToText.setEnabled(True)
            self.basic.nextButton.setEnabled(True)
            return 1
        
    def on_submit(self):
        self.basic.pixelLabel.setPixmap(QPixmap("images/wait_1.jpg"))
        time.sleep(1)
        data_status = self.livefeed.read_status()
        data_info = self.livefeed.read_info()
        user_input_voltage = self.basic.text2.toPlainText()
        if user_input_voltage != "":
            user_input_voltage = float(user_input_voltage)
        else:
            QMessageBox.information(self, "Please enter value", "Measure the voltage value.")
            return
        if data_info[4] == "":
            print("no ccid") 
            data_info[4] = "123456789"
        if data_info[3] == "":
            print("No gsm version")
            data_info[3] = 255
        if data_info[2] == "":
            print("no STN version")
            data_info[2] = "255"
            
            
        '''
            stms_i = stnFlag
            nrfs_st= string of nrf_sd+unplug+gps+acc
            nrfs_i = gps
            gsmv = gsm version
            
            gpsv = we dont currently have gps version
            
        '''
        stm_status_bk = str(data_status[0]+data_status[1]+data_status[3]+data_status[4]+data_status[5]+data_status[6]+
                            data_status[7]+data_status[8]+data_status[9])
        data_to_backend = {"lb":int(self.current_device_no), "pc":str(qr_code(int(self.current_device_no))),
                           "flg":1, "stm":str(data_info[1]), "stmv": int(data_info[0]),
                           "nrf":str(data_info[5] + data_info[6]), "nrfv":int(data_info[-1]),
                            "simcc":str(data_info[4]), "stms_st":stm_status_bk,
                           "stms_i":int(data_status[6]), "nrfs_st": "1111","nrfs_i": int(data_status[8]),
                            "gsmv": data_info[3] ,"pwr": data_status[7],"hbn":int(data_info[-1]),
                            "stnv":str(data_info[2]),"gpsv":"123456789A", "vltDevice":int(user_input_voltage)}
        
        print(data_to_backend)
        r = requests.post('http://carnot-staging.herokuapp.com/devices/log/', data = json.dumps(data_to_backend), 
                          headers = {"ApiKey":"JXn8e6C29jhZ065i8wyQktY33YD3s9zy"})
        #print(r.content)
        y = r.content.decode("utf-8")
        # now we have a string
        if "true" in y:
            QMessageBox.information(self, "Server", "Data saved to backed")
            self.new_device()
        else:
            QMessageBox.critical(self, "Server", "Check internet connection")
    
    def on_save_txt(self):
        data_status = self.livefeed.read_status()
        data_info = self.livefeed.read_info()
        self.local_file = open("carnot_device.csv","a+")
        self.local_file.write("%d, " % int(self.current_device_no))
        self.local_file.write("%s, " % (qr_code(int(self.current_device_no))))
        for i in data_info:
            self.local_file.write("%s, " % i)
        for i in data_status:
            print(i)
            self.local_file.write("%s, " % (data_status))
        self.local_file.write("\r\n")
        self.local_file.close()
class PlottingDataMonitor(QMainWindow):
    def __init__(self, parent=None):
        super(PlottingDataMonitor, self).__init__(parent)

        self.monitor_active = False
        self.com_monitor = None
        self.livefeed = LiveDataFeed()
        self.temperature_samples = []
        self.timer = QTimer()

        # menu
        #
        self.file_menu = self.menuBar().addMenu("&File")
        selectport_action = QAction('Select TTY &Port...', self)
        selectport_action.triggered.connect(self.on_select_port)
        self.file_menu.addAction(selectport_action)

        self.start_action = QAction('&Start monitor')
        self.start_action.triggered.connect(self.on_start)
        self.start_action.setEnabled(False)
        self.file_menu.addAction(self.start_action)

        self.stop_action = QAction('&Stop monitor')
        self.stop_action.triggered.connect(self.on_stop)

        # main widget
        #
        # port
        portname_label = QLabel('tty port:')
        self.portname = QLineEdit()
        self.portname.setEnabled(False)
        self.portname.setFrame(False)
        portname_layout = QHBoxLayout()
        portname_layout.addWidget(portname_label)
        portname_layout.addWidget(self.portname, 0)
        portname_layout.addStretch(1)
        portname_groupbox = QGroupBox('Port')
        portname_groupbox.setLayout(portname_layout)

        # plot widget
        self.plot = qwt.QwtPlot(self)
        self.plot.setCanvasBackground(Qt.black)
        self.plot.setAxisTitle(qwt.QwtPlot.xBottom, 'Time')
        self.plot.setAxisScale(qwt.QwtPlot.xBottom, 0, 10, 1)
        self.plot.setAxisTitle(qwt.QwtPlot.yLeft, 'Temperature')
        self.plot.setAxisScale(qwt.QwtPlot.yLeft, 0, 250, 40)
        self.plot.replot()

        # curve widget
        self.curve = qwt.QwtPlotCurve('')
        self.curve.setRenderHint(qwt.QwtPlotItem.RenderAntialiased)
        pen = QPen(QColor('limegreen'))
        pen.setWidth(2)
        self.curve.setPen(pen)
        self.curve.attach(self.plot)

        # dial
        #
        self.dial = QDial()
        self.dial.setNotchesVisible(True)
        self.dial.setRange(0, 20)
        self.dial.setValue(10)
        self.dial.valueChanged.connect(self.on_dial_change)

        self.dial_label = QLabel('Update speed = %s (Hz)' % self.dial.value())
        self.dial_label.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
        dial_layout = QVBoxLayout()
        dial_layout.addWidget(self.dial)
        dial_layout.addWidget(self.dial_label)

        # plot layout
        plot_layout = QVBoxLayout()
        plot_layout.addWidget(self.plot)
        plot_layout.addLayout(dial_layout)

        plot_groupbox = QGroupBox('Temperature')
        plot_groupbox.setLayout(plot_layout)

        # main
        self.main_frame = QWidget()
        main_layout = QVBoxLayout()
        main_layout.addWidget(portname_groupbox)
        main_layout.addWidget(plot_groupbox)
        main_layout.addStretch(1)
        self.main_frame.setLayout(main_layout)

        self.setCentralWidget(self.main_frame)

        # status
        #
        self.status_text = QLabel('Monitor idle')
        self.statusBar().addWidget(self.status_text, 1)

    def set_actions_enable_state(self):
        if self.portname.text() == '':
            start_enable = stop_enable = False
        else:
            start_enable = not self.monitor_active
            stop_enable = self.monitor_active

        self.start_action.setEnabled(start_enable)
        self.stop_action.setEnabled(stop_enable)

    def read_serial_data(self):
        '''Called periodically be the update timer to read data from the
serial port.

        '''
        qdata = list(get_all_from_queue(self.data_q))
        if len(qdata) > 0:
            # print(len(qdata))

            data = dict(timestamp=qdata[-1][1], temperature=ord(qdata[-1][0]))
            # print(data)
            self.livefeed.add_data(data)
        else:
            print('no data')

    def update_monitor(self):
        '''Updates the state of the monitor window with new data. The
livefeed is used to dind out whether new data was received since last
update. If not, nothing is updated.

        '''
        if self.livefeed.has_new_data:
            data = self.livefeed.read_data()
            # print(data)
            self.temperature_samples.append(
                (data['timestamp'], data['temperature']))
            if len(self.temperature_samples) > 100:
                self.temperature_samples.pop(0)

            xdata = [s[0] for s in self.temperature_samples]
            ydata = [s[1] for s in self.temperature_samples]

            avg = sum(ydata) / float(len(ydata))

            self.plot.setAxisScale(qwt.QwtPlot.xBottom, xdata[0],
                                   max(20, xdata[-1]))
            self.curve.setData(xdata, ydata)
            self.plot.replot()

    # slots
    def on_select_port(self):
        text, ok = QInputDialog.getText(self, 'Port Name', 'Enter tty:')
        if ok:
            self.portname.setText(str(text))
            self.set_actions_enable_state()

    def on_start(self):
        '''Start the monitor: com_monitor thread and the update timer'''
        if self.com_monitor is not None or self.portname.text() == '':
            return

        self.data_q = Queue()
        self.error_q = Queue()
        self.com_monitor = ComMonitorThread(self.data_q, self.error_q,
                                            self.portname.text(), 38400)
        self.com_monitor.start()
        com_error = None
        try:
            com_error = self.error_q.get(True, 0.01)
        except Empty:
            pass
        if com_error is not None:
            QMessageBox.critical(self, 'ComMonitorThread error', com_error)
            self.com_monitor = None

        self.monitor_active = True
        self.set_actions_enable_state()

        self.timer = QTimer()
        self.timer.timeout.connect(self.on_timer)

        update_freq = self.dial.value()
        if update_freq > 0:
            self.timer.start(1000 / update_freq)

        self.status_text.setText('Monitor running')

    def on_stop(self):
        '''Stop the monitor'''
        if self.com_monitor is not None:
            self.com_monitor.join(0.01)
            self.com_monitor = None

        self.monitor_actibe = False
        self.timer.stop()
        self.set_actions_enable_state()

        self.status_text.setText('Monitor idle')

    def on_timer(self):
        '''Executed periodically when the monitor update timer is fired.'''
        self.read_serial_data()
        self.update_monitor()

    def on_dial_change(self):
        '''When the dial is rotated, it sets the update interval of the
timer'''
        update_freq = self.dial.value()
        self.dial_label.setText('Update speed = %s (Hz)' % self.dial.value())

        if self.timer.isActive():
            update_freq = max(0.01, update_freq)
            self.timer.setInterval(1000 / update_freq)
class PlottingDataMonitor(QMainWindow):
    def __init__(self, parent=None):
        super(PlottingDataMonitor, self).__init__(parent)

        self.monitor_active = False
        self.com_monitor = None
        self.com_data_q = None
        self.com_error_q = None
        self.livefeed = LiveDataFeed()
        self.temperature_samples = []
        self.timer = QTimer()

        self.create_menu()
        self.create_main_frame()
        self.create_status_bar()

    #        self.showFullScreen()

    def make_data_box(self, name):
        label = QLabel(name)
        qle = QLineEdit()
        qle.setEnabled(False)
        qle.setFrame(False)
        return (label, qle)

    def create_plot(self):
        plot = Qwt.QwtPlot(self)
        plot.setCanvasBackground(Qt.black)
        plot.setAxisTitle(Qwt.QwtPlot.xBottom, "Time")
        plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 10, 1)
        plot.setAxisTitle(Qwt.QwtPlot.yLeft, "val")
        plot.setAxisScale(Qwt.QwtPlot.yLeft, 0, 30000, 40)

        plot.setAxisAutoScale(Qwt.QwtPlot.yLeft)

        plot.replot()

        curve = Qwt.QwtPlotCurve("")
        #        curve.setRenderHint(Qwt.QwtPlotItem.RenderAntialiased)
        pen = QPen(QColor("limegreen"))
        pen.setWidth(2)
        curve.setPen(pen)
        curve.attach(plot)
        return plot, curve

    def create_status_bar(self):
        self.status_text = QLabel("Monitor idle")
        self.statusBar().addWidget(self.status_text, 1)

    def create_main_frame(self):
        # Port name
        #
        portname_l, self.portname = self.make_data_box("Serial port:")

        portname_layout = QHBoxLayout()
        portname_layout.addWidget(portname_l)
        portname_layout.addWidget(self.portname, 0)
        portname_layout.addStretch(1)
        portname_groupbox = QGroupBox("Serial Port")
        portname_groupbox.setLayout(portname_layout)

        # Plot and thermo
        #
        self.plot, self.curve = self.create_plot()
        #        self.thermo = self.create_thermo()

        plot_layout = QVBoxLayout()
        plot_layout.addWidget(self.plot)
        plot_groupbox = QGroupBox("Value")
        plot_groupbox.setLayout(plot_layout)

        # Main frame and layout
        #
        self.main_frame = QWidget()
        main_layout = QVBoxLayout()
        main_layout.addWidget(portname_groupbox)
        main_layout.addWidget(plot_groupbox)
        main_layout.addStretch(1)
        self.main_frame.setLayout(main_layout)

        self.setCentralWidget(self.main_frame)
        self.set_actions_enable_state()

    def create_menu(self):
        self.file_menu = self.menuBar().addMenu("&File")

        selectport_action = self.create_action(
            "Select serial &Port...", shortcut="Ctrl+P", slot=self.on_select_port, tip="Select a serial port"
        )
        self.start_action = self.create_action(
            "&Start monitor", shortcut="Ctrl+M", slot=self.on_start, tip="Start the data monitor"
        )
        self.stop_action = self.create_action(
            "&Stop monitor", shortcut="Ctrl+T", slot=self.on_stop, tip="Stop the data monitor"
        )
        exit_action = self.create_action("E&xit", slot=self.close, shortcut="Ctrl+X", tip="Exit the application")

        self.start_action.setEnabled(False)
        self.stop_action.setEnabled(False)

        self.add_actions(self.file_menu, (selectport_action, self.start_action, self.stop_action, None, exit_action))

        self.help_menu = self.menuBar().addMenu("&Help")
        about_action = self.create_action("&About", shortcut="F1", slot=self.on_about, tip="About the monitor")

        self.add_actions(self.help_menu, (about_action,))

    def set_actions_enable_state(self):
        if self.portname.text() == "":
            start_enable = stop_enable = False
        else:
            start_enable = not self.monitor_active
            stop_enable = self.monitor_active

        self.start_action.setEnabled(start_enable)
        self.stop_action.setEnabled(stop_enable)

    def on_about(self):
        msg = __doc__
        QMessageBox.about(self, "About the demo", msg.strip())

    def on_select_port(self):
        ports = list(enumerate_serial_ports())
        if len(ports) == 0:
            QMessageBox.critical(self, "No ports", "No serial ports found")
            return

        item, ok = QInputDialog.getItem(self, "Select a port", "Serial port:", ports, 0, False)

        if ok and not item.isEmpty():
            self.portname.setText(item)
            self.set_actions_enable_state()

    def on_stop(self):
        """ Stop the monitor
        """
        if self.com_monitor is not None:
            self.com_monitor.join(0.01)
            self.com_monitor = None

        self.monitor_active = False
        self.timer.stop()
        self.set_actions_enable_state()

        self.status_text.setText("Monitor idle")

    def on_start(self):
        """ Start the monitor: com_monitor thread and the update
            timer
        """
        if self.com_monitor is not None or self.portname.text() == "":
            return

        self.data_q = Queue.Queue()
        self.error_q = Queue.Queue()
        self.com_monitor = ComMonitorThread(self.data_q, self.error_q, full_port_name(str(self.portname.text())), 9600)
        self.com_monitor.start()

        com_error = get_item_from_queue(self.error_q)
        if com_error is not None:
            QMessageBox.critical(self, "ComMonitorThread error", com_error)
            self.com_monitor = None

        self.monitor_active = True
        self.set_actions_enable_state()

        self.timer = QTimer()
        self.connect(self.timer, SIGNAL("timeout()"), self.on_timer)

        update_freq = 20
        self.timer.start(1000.0 / update_freq)

        self.status_text.setText("Monitor running")

    def on_timer(self):
        """ Executed periodically when the monitor update timer
            is fired.
        """
        self.read_serial_data()
        self.update_monitor()

    def update_monitor(self):
        """ Updates the state of the monitor window with new 
            data. The livefeed is used to find out whether new
            data was received since the last update. If not, 
            nothing is updated.
        """
        if self.livefeed.has_new_data:
            data = self.livefeed.read_data()

            self.temperature_samples.append((data["timestamp"], data["temperature"]))
            if len(self.temperature_samples) > 100:
                self.temperature_samples.pop(0)

            xdata = [s[0] for s in self.temperature_samples]
            ydata = [s[1] for s in self.temperature_samples]

            #            self.plot.setAxisScale(Qwt.QwtPlot.xBottom, xdata[0], max(10, xdata[-1]))
            self.plot.setAxisScale(Qwt.QwtPlot.xBottom, xdata[0], xdata[0] + 5)
            self.curve.setData(xdata, ydata)
            self.plot.replot()

    def read_serial_data(self):
        """ Called periodically by the update timer to read data
            from the serial port.
        """
        qdata = list(get_all_from_queue(self.data_q))
        if len(qdata) > 0:
            #            print qdata
            data = dict(timestamp=qdata[-1][1], temperature=int(qdata[-1][0]))
            self.livefeed.add_data(data)

    # The following two methods are utilities for simpler creation
    # and assignment of actions
    #
    def add_actions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def create_action(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(":/%s.png" % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot)
        if checkable:
            action.setCheckable(True)
        return action
class PlottingDataMonitor(QMainWindow):
    def __init__(self, parent=None):
        super(PlottingDataMonitor, self).__init__(parent)

        self.setWindowTitle('ADXL345 Realtime Monitor')
        self.resize(800, 600)
        
        self.port           = ""
        self.baudrate       = 9600
        self.monitor_active = False                 # on/off monitor state
        self.com_monitor    = None                  # monitor reception thread
        self.com_data_q     = None
        self.com_error_q    = None
        self.livefeed       = LiveDataFeed()
        self.timer          = QTimer()
        self.g_samples      = [[], [], []]
        self.curve          = [None]*3
        self.gcurveOn       = [1]*3                 # by default all curve are plotted
        self.csvdata        = []    
        
        self.create_menu()
        self.create_main_frame()
        self.create_status_bar()

        # Activate start-stop button connections
        self.connect(self.button_Connect, SIGNAL("clicked()"),
                    self.OnStart)
        self.connect(self.button_Disconnect, SIGNAL("clicked()"),
                    self.OnStop)
    #----------------------------------------------------------


    def create_com_box(self):
        """ 
        Purpose:   create the serial com groupbox
        Return:    return a layout of the serial com
        """
        self.com_box = QGroupBox("COM Configuration")

        com_layout = QGridLayout()

        self.radio9600     =    QRadioButton("9600")
        self.radio9600.setChecked(1)
        self.radio19200    =    QRadioButton("19200")
        self.Com_ComboBox  =    QComboBox()

        com_layout.addWidget(self.Com_ComboBox,0,0,1,2)
        com_layout.addWidget(self.radio9600,1,0)
        com_layout.addWidget(self.radio19200,1,1)
        self.fill_ports_combobox()

        self.button_Connect      =   QPushButton("Start")
        self.button_Disconnect   =   QPushButton("Stop")
        self.button_Disconnect.setEnabled(False)

        com_layout.addWidget(self.button_Connect,0,2)
        com_layout.addWidget(self.button_Disconnect,1,2)        

        return com_layout
    #---------------------------------------------------------------------
   

    def create_plot(self):
        """ 
        Purpose:   create the pyqwt plot
        Return:    return a list containing the plot and the list of the curves
        """
        plot = Qwt.QwtPlot(self)
        plot.setCanvasBackground(Qt.black)
        plot.setAxisTitle(Qwt.QwtPlot.xBottom, 'Time')
        plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 10, 1)
        plot.setAxisTitle(Qwt.QwtPlot.yLeft, 'Acceleration')
        plot.setAxisScale(Qwt.QwtPlot.yLeft, YMIN, YMAX, (YMAX-YMIN)/10)
        plot.replot()
        
        curve = [None]*3
        pen = [QPen(QColor('limegreen')), QPen(QColor('red')) ,QPen(QColor('yellow')) ]
        for i in range(3):
            curve[i] =  Qwt.QwtPlotCurve('')
            curve[i].setRenderHint(Qwt.QwtPlotItem.RenderAntialiased)
            pen[i].setWidth(2)
            curve[i].setPen(pen[i])
            curve[i].attach(plot)

        return plot, curve
    #---------------------------------------------------


    def create_knob(self):
        """ 
        Purpose:   create a knob
        Return:    return a the knob widget
        """
        knob = Qwt.QwtKnob(self)
        knob.setRange(0, 180, 0, 1)
        knob.setScaleMaxMajor(10)
        knob.setKnobWidth(50)
        knob.setValue(10)
        return knob
    #---------------------------------------------------


    def create_status_bar(self):
        self.status_text = QLabel('Monitor idle')
        self.statusBar().addWidget(self.status_text, 1)
    #---------------------------------------------------


    def create_checkbox(self, label, color, connect_fn, connect_param):
        """ 
        Purpose:    create a personalized checkbox
        Input:      the label, color, activated function and the transmitted parameter
        Return:     return a checkbox widget
        """
        checkBox = QCheckBox(label)
        checkBox.setChecked(1)
        checkBox.setFont( QFont("Arial", pointSize=12, weight=QFont.Bold ) )
        green = QPalette()
        green.setColor(QPalette.Foreground, color)
        checkBox.setPalette(green)
        self.connect(checkBox, SIGNAL("clicked()"), partial(connect_fn,connect_param))
        return checkBox
        #---------------------------------------------------


    def create_main_frame(self):
        """ 
        Purpose:    create the main frame Qt widget
        """
        # Serial communication combo box
        portname_layout = self.create_com_box()
        self.com_box.setLayout(portname_layout)
        
        # Update speed knob
        self.updatespeed_knob = self.create_knob()
        self.connect(self.updatespeed_knob, SIGNAL('valueChanged(double)'),
            self.on_knob_change)
        self.knob_l = QLabel('Update speed = %s (Hz)' % self.updatespeed_knob.value())
        self.knob_l.setAlignment(Qt.AlignTop | Qt.AlignHCenter)

        # Create the plot and curves
        self.plot, self.curve = self.create_plot()

        # Create the configuration horizontal panel
        self.max_spin    = QSpinBox()
        self.max_spin.setMaximum(1000)
        self.max_spin.setValue(1000)
        spins_hbox      = QHBoxLayout()
        spins_hbox.addWidget(QLabel('Save every'))
        spins_hbox.addWidget(self.max_spin)
        spins_hbox.addWidget( QLabel('Lines'))
        #spins_hbox.addStretch(1)

        self.gCheckBox   =  [   self.create_checkbox("Acceleration(x)", Qt.green, self.activate_curve, 0),
                                self.create_checkbox("Acceleration(y)", Qt.red, self.activate_curve, 1),
                                self.create_checkbox("Acceleration(z)", Qt.yellow, self.activate_curve, 2)
                            ]

        self.button_clear      =   QPushButton("Clear screen")

        self.connect(self.button_clear, SIGNAL("clicked()"),
                    self.clear_screen)
        
        # Place the horizontal panel widget
        plot_layout = QGridLayout()
        plot_layout.addWidget(self.plot,0,0,8,7)
        plot_layout.addWidget(self.gCheckBox[0],0,8)
        plot_layout.addWidget(self.gCheckBox[1],1,8)
        plot_layout.addWidget(self.gCheckBox[2],2,8)
        plot_layout.addWidget(self.button_clear,3,8)
        plot_layout.addLayout(spins_hbox,4,8)
        plot_layout.addWidget(self.updatespeed_knob,5,8)
        plot_layout.addWidget(self.knob_l,6,8)
        
        plot_groupbox = QGroupBox('Acceleration')
        plot_groupbox.setLayout(plot_layout)
        
        # Place the main frame and layout
        self.main_frame = QWidget()
        main_layout 	= QVBoxLayout()
        main_layout.addWidget(self.com_box)
        main_layout.addWidget(plot_groupbox)
        main_layout.addStretch(1)
        self.main_frame.setLayout(main_layout)
        
        self.setCentralWidget(self.main_frame)
    #----------------------------------------------------------------------


    def clear_screen(self):
        g_samples[0] = []
    #-----------------------------
        

    def activate_curve(self, axe):
        if self.gCheckBox[axe].isChecked():
            self.gcurveOn[axe]  = 1
        else:
            self.gcurveOn[axe]  = 0
    #---------------------------------------


    def create_menu(self):
        self.file_menu = self.menuBar().addMenu("&File")
        
        selectport_action = self.create_action("Select COM &Port...",
            shortcut="Ctrl+P", slot=self.on_select_port, tip="Select a COM port")
        self.start_action = self.create_action("&Start monitor",
            shortcut="Ctrl+M", slot=self.OnStart, tip="Start the data monitor")
        self.stop_action = self.create_action("&Stop monitor",
            shortcut="Ctrl+T", slot=self.OnStop, tip="Stop the data monitor")
        exit_action = self.create_action("E&xit", slot=self.close, 
            shortcut="Ctrl+X", tip="Exit the application")
        
        self.start_action.setEnabled(False)
        self.stop_action.setEnabled(False)
        
        self.add_actions(self.file_menu, 
            (   selectport_action, self.start_action, self.stop_action,
                None, exit_action))
            
        self.help_menu = self.menuBar().addMenu("&Help")
        about_action = self.create_action("&About", 
            shortcut='F1', slot=self.on_about, 
            tip='About the monitor')
        
        self.add_actions(self.help_menu, (about_action,))
    #----------------------------------------------------------------------


    def set_actions_enable_state(self):
        if self.portname.text() == '':
            start_enable = stop_enable = False
        else:
            start_enable = not self.monitor_active
            stop_enable = self.monitor_active
        
        self.start_action.setEnabled(start_enable)
        self.stop_action.setEnabled(stop_enable)
    #-----------------------------------------------


    def on_about(self):
        msg = __doc__
        QMessageBox.about(self, "About the demo", msg.strip())
    #-----------------------------------------------

    

    def on_select_port(self):
        
        ports = enumerate_serial_ports()
        
        if len(ports) == 0:
            QMessageBox.critical(self, 'No ports',
                'No serial ports found')
            return
        
        item, ok = QInputDialog.getItem(self, 'Select a port',
                    'Serial port:', ports, 0, False)
        
        if ok and not item.isEmpty():
            self.portname.setText(item)            
            self.set_actions_enable_state()
    #-----------------------------------------------


    def fill_ports_combobox(self):
        """ Purpose: rescan the serial port com and update the combobox
        """
        vNbCombo = ""
        self.Com_ComboBox.clear()
        self.AvailablePorts = enumerate_serial_ports()
        for value in self.AvailablePorts:
            self.Com_ComboBox.addItem(value)
            vNbCombo += value + " - "
        vNbCombo = vNbCombo[:-3] 

        debug(("--> Les ports series disponibles sont: %s " % (vNbCombo)))
    #----------------------------------------------------------------------


    def OnStart(self):
        """ Start the monitor: com_monitor thread and the update timer     
        """
        if self.radio19200.isChecked():
            self.baudrate = 19200
            print "--> baudrate is 19200 bps"
        if self.radio9600.isChecked():
            self.baudrate = 9600
            print "--> baudrate is 9600 bps"  

        vNbCombo    = self.Com_ComboBox.currentIndex()
        self.port   = self.AvailablePorts[vNbCombo]

        self.button_Connect.setEnabled(False)
        self.button_Disconnect.setEnabled(True)
        self.Com_ComboBox.setEnabled(False)

        self.data_q      =  Queue.Queue()
        self.error_q     =  Queue.Queue()
        self.com_monitor =  ComMonitorThread(
                                            self.data_q,
                                            self.error_q,
                                            self.port,
                                            self.baudrate)
        
        self.com_monitor.start()  

        com_error = get_item_from_queue(self.error_q)
        if com_error is not None:
            QMessageBox.critical(self, 'ComMonitorThread error',
                com_error)
            self.com_monitor = None  

        self.monitor_active = True

        self.connect(self.timer, SIGNAL('timeout()'), self.on_timer)
        
        update_freq = self.updatespeed_knob.value()
        if update_freq > 0:
            self.timer.start(1000.0 / update_freq)
        
        self.status_text.setText('Monitor running')
        debug('--> Monitor running')
    #------------------------------------------------------------


    def OnStop(self):
        """ Stop the monitor
        """
        if self.com_monitor is not None:
            self.com_monitor.join(1000)
            self.com_monitor = None

        self.monitor_active = False
        self.button_Connect.setEnabled(True)
        self.button_Disconnect.setEnabled(False)
        self.Com_ComboBox.setEnabled(True)
        self.timer.stop()
        self.status_text.setText('Monitor idle')
        debug('--> Monitor idle')
    #-----------------------------------------------


    def on_timer(self):
        """ Executed periodically when the monitor update timer
            is fired.
        """
        self.read_serial_data()
        self.update_monitor()
	#-----------------------------------------------


    def on_knob_change(self):
        """ When the knob is rotated, it sets the update interval
            of the timer.
        """
        update_freq = self.updatespeed_knob.value()
        self.knob_l.setText('Update speed = %s (Hz)' % self.updatespeed_knob.value())

        if self.timer.isActive():
            update_freq = max(0.01, update_freq)
            self.timer.setInterval(1000.0 / update_freq)
    #-----------------------------------------------


    def update_monitor(self):
        """ Updates the state of the monitor window with new 
            data. The livefeed is used to find out whether new
            data was received since the last update. If not, 
            nothing is updated.
        """
        if self.livefeed.has_new_data:
            data = self.livefeed.read_data()

            self.csvdata.append([data['timestamp'], data['gx'], data['gy'], data['gz']] )
            if len(self.csvdata) > self.max_spin.value():
                f = open(time.strftime("%H%M%S")+".csv", 'wt')
                try:
                    writer = csv.writer(f)
                    for i in range(self.max_spin.value()):
                        writer.writerow( self.csvdata[i] )
                    print 'transfert data to csv after 1000 samples'
                finally:
                    f.close()
                self.csvdata = []
            
            self.g_samples[0].append(
                (data['timestamp'], data['gx']))
            if len(self.g_samples[0]) > 100:
                self.g_samples[0].pop(0)

            self.g_samples[1].append(
                (data['timestamp'], data['gy']))
            if len(self.g_samples[1]) > 100:
                self.g_samples[1].pop(0)

            self.g_samples[2].append(
                (data['timestamp'], data['gz']))
            if len(self.g_samples[2]) > 100:
                self.g_samples[2].pop(0)

            tdata = [s[0] for s in self.g_samples[2]]

            for i in range(3):
                data[i] = [s[1] for s in self.g_samples[i]]
                if self.gcurveOn[i]:
                    self.curve[i].setData(tdata, data[i])

            """
            debug("xdata", data[0])
            debug("ydata", data[1])
            debug("tdata", data[2])
            """

            self.plot.setAxisScale(Qwt.QwtPlot.xBottom, tdata[0], max(5, tdata[-1]) )        
            
            self.plot.replot()
    #-----------------------------------------------
            
            
    def read_serial_data(self):
        """ Called periodically by the update timer to read data
            from the serial port.
        """
        qdata = list(get_all_from_queue(self.data_q))
        # get just the most recent data, others are lost
        #print "qdata" , qdata
        if len(qdata) > 0:
            data = dict(timestamp=qdata[-1][1], 
                        gx=qdata[-1][0][0],
                        gy=qdata[-1][0][1],
                        gz=qdata[-1][0][2]
                        )
            self.livefeed.add_data(data)
    #-----------------------------------------------


    
    # The following two methods are utilities for simpler creation
    # and assignment of actions
    #
    def add_actions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)
    #-----------------------------------------------


    def create_action(  self, text, slot=None, shortcut=None, 
                        icon=None, tip=None, checkable=False, 
                        signal="triggered()"):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(":/%s.png" % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot)
        if checkable:
            action.setCheckable(True)
        return action
예제 #8
0
class nanoScat_PD(QtGui.QMainWindow):
    ui = None
    stepperCOMPort = None
    ATrtAddr = 255
    currentAngle = 0
    prevMove = ([0, 0], [0, 0])
    line0, line1, line_sig, line_ref, line_ref_norm, line5, line6, line7 = None, None, None, None, None, None, None, None
    lines = [
        line0, line1, line_sig, line_ref, line_ref_norm, line5, line6, line7
    ]
    steppingTimer = None
    calibrTimer = None
    measTimer = None
    stepperStateTimer = None
    FWCalibrationCounter = 0
    FWCalibrationCounterList = []

    angleSensorSerial = None
    com_monitor = None
    angleUpdateTimer = None
    angleUpdateThread = None
    lastDirection = 1
    tmpData = None
    num = 10
    calibrData = np.array([])
    measData = np.array([])
    intStepCounter = 0
    moveFlag = 0
    extLaserStrob = None
    extDataBuffer = None

    oscillo = None
    oscReadTimerTimer = None
    lastFiltChTime = None
    lastDivChange = time.time()
    oscilloLastMaster = None
    oscilloLastIndex = [-1, -1]

    #et = ET1255()
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)
        self.ui = uic.loadUi("mainwindow.ui")
        self.ui.closeEvent = self.closeEvent
        self.steppingTimer = QtCore.QTimer()
        self.calibrTimer = QtCore.QTimer()
        self.calibrHomeTimer = QtCore.QTimer()
        self.calibrFWTimer = QtCore.QTimer()
        self.measTimer = QtCore.QTimer()
        self.angleUpdateTimer = QtCore.QTimer()

        self.stepperStateTimer = QtCore.QTimer()
        self.oscReadTimer = QtCore.QTimer()

        self.config = configparser.ConfigParser()
        self.config.read('settings.ini')
        print(sys.argv[0], self.config.sections())

        self.globalSettingsDict = self.config[
            'GLOBAL']  #.read('globalSettings.ini')
        self.updateSettingsTable()

        self.uiConnect()
        self.initUi()

        self.fileDialog = QFileDialog(self)

        #self.initET1255()
        self.tmpData = []  #[[0,0,0]]
        self.calibrData = np.array([])  #[0,0,0])
        #self.SMD = SMD004()
        #self.extLaserStrob = laserStrob(0.1)
        self.oscillo = HAMEG()
        self.oscilloLastMaster = 'HAMEG'

        #self.startLaserStrob(0.02)
    def updateSettingsTable(self):
        if 'GLOBAL' in self.config.sections():
            section = self.config['GLOBAL']
            self.ui.globalConfig.setVerticalHeaderLabels(list(section))
            for row, key in enumerate(section):
                print(row, key)
                for column, val in enumerate(section[key].split(',')):
                    print(column, val)
                    newitem = QTableWidgetItem(val)
                    self.ui.globalConfig.setItem(row, column, newitem)

        if 'FILTERS' in self.config.sections():
            section = self.config['FILTERS']
            self.ui.filtersTab.setVerticalHeaderLabels(list(section))
            for row, key in enumerate(section):
                print(row, key)
                for column, val in enumerate(section[key].split(',')):
                    print(column, val)
                    newitem = QTableWidgetItem(val)
                    self.ui.filtersTab.setItem(row, column, newitem)
        #for column, key in enumerate(section):
        #   newitem = QTableWidgetItem(item)
        #   for row, item in enumerate(self.data[key]):
        #       newitem = QTableWidgetItem(item)
        #       self.setItem(row, column, newitem)

    def saveConfig(self):
        if 'GLOBAL' in self.config.sections():
            section = self.config['GLOBAL']
            rows = self.ui.globalConfig.rowCount()
            columns = self.ui.globalConfig.columnCount()

            for row in range(rows):
                key = self.ui.globalConfig.verticalHeaderItem(row).text()
                val = []
                for column in range(columns):
                    try:
                        val.append(
                            self.ui.globalConfig.item(row, column).text())
                    except:
                        break
                section[key] = ','.join(val)
                print(key, val)

        if 'FILTERS' in self.config.sections():
            section = self.config['FILTERS']
            rows = self.ui.filtersTab.rowCount()
            columns = self.ui.filtersTab.columnCount()

            for row in range(rows):
                key = self.ui.filtersTab.verticalHeaderItem(row).text()
                val = []
                for column in range(columns):
                    try:
                        val.append(self.ui.filtersTab.item(row, column).text())
                    except:
                        break
                section[key] = ','.join(val)
                print(key, val)

        with open('settings.ini', 'w') as configfile:
            self.config.write(configfile)
        ''' 
			for row,key in enumerate(section):
				print(row,key)
				for column,val in enumerate(section[key].split(',')):
					print(column,val)
					newitem = QTableWidgetItem(val)
					self.ui.globalConfig.setItem(row,column,newitem)

		if 'FILTERS' in self.config.sections():
			section = self.config['FILTERS']
			self.ui.globalConfig.setVerticalHeaderLabels(list(section))
			for row,key in enumerate(section):
				print(row,key)
				newitem = QTableWidgetItem(key)
				self.ui.filtersTab.setItem(row,0,newitem)
				for column,val in enumerate(section[key].split(',')):
					print(column,val)
					newitem = QTableWidgetItem(val)
					self.ui.filtersTab.setItem(row,column+1,newitem)
		'''

    def initUi(self):
        self.pw = pg.PlotWidget(
            name='Plot1'
        )  ## giving the plots names allows us to link their axes together
        self.ui.l.addWidget(self.pw)
        self.pw2 = pg.PlotWidget(name='Plot2')
        self.ui.l.addWidget(self.pw2)
        self.osc_pw = pg.PlotWidget(name='Plot3')
        self.ui.oscilloPlot.addWidget(self.osc_pw)
        #self.osc_pw.setXRange(0, 360)
        #self.osc_pw.showAxis('bottom', False)
        self.osc_pw.showGrid(x=True, y=True)
        self.pw.showGrid(x=True, y=True)
        self.pw2.showGrid(x=True, y=True)

        #self.osc_pw.showAxis('bottom', False)
        self.osc_pw.setYRange(0, 256)
        self.osc_pw.setMinimumWidth(300)
        self.osc_pw.setMinimumHeight(200)
        self.ui.show()

        ## Create an empty plot curve to be filled later, set its pen
        colors = [
            'red', "green", 'blue', 'cyan', 'magenta', 'yellow', 'purple',
            'olive'
        ]
        #for i in range(0,self.ui.channelsSettings.rowCount()):
        #   self.lines[i] = self.pw.plot()
        #   self.lines[i].setPen(QtGui.QColor(colors[i]))
        self.line0 = self.pw2.plot()
        print(self.line0)
        self.line0.setPen(QtGui.QColor('cyan'))
        self.line1 = self.pw.plot()
        self.line1.setPen(QtGui.QColor("orange"))
        self.line5 = self.pw.plot()
        self.line5.setPen(QtGui.QColor("red"))
        self.line_sig = self.osc_pw.plot()
        self.line_sig.setPen(QtGui.QColor("orange"))
        self.line_ref = self.osc_pw.plot()
        self.line_ref.setPen(QtGui.QColor("cyan"))
        self.line_ref_norm = self.osc_pw.plot()
        self.line_ref_norm.setPen(QtGui.QColor("red"))

        self.pw.setLabel('left', 'Signal', units='arb. un.')
        self.pw.setLabel('bottom', 'Angle', units='deg.')
        self.pw.setXRange(0, 360)
        self.pw.setYRange(0, 1e10)
        self.pw2.setMaximumHeight(300)

    def setStepperParam(self):
        pass

    def getCorrectedAngle(self):
        angle = self.ui.steppingAngle.value()
        #calibr = float(self.config['STEPPER1']['calibrationCoefficient']) #self.ui.steppingCalibr.value()
        #tmp_angle = int(angle*calibr)/calibr
        #self.ui.steppingAngle.setValue(tmp_angle)
        #return int(tmp_angle*calibr), tmp_angle
        return angle, angle

    def steps2angle(self, steps, motor=1):
        calibr = float(
            self.config['STEPPER' + str(motor)]
            ['calibrationCoefficient'])  #self.ui.steppingCalibr.value()
        return steps / calibr

    def prepInternCounter(self, direction):
        if direction != self.lastDirection:
            #self.SMD.eClearSteps()#SMD_ClearStep(self.ATrtAddr)
            self.lastDirection = direction

    def relCCWMove(self):
        val = self.ui.relAngleIncrement.value()
        self.com_monitor.serial_port.write(b"REL=" + str(val).encode('utf-8') +
                                           b"\n")
        #r = self.com_monitor.serial_port.readline()
        #print(r)

    def relCWMove(self):
        val = self.ui.relAngleIncrement.value()
        self.com_monitor.serial_port.write(b"REL=" +
                                           str(-val).encode('utf-8') + b"\n")
        #r = self.com_monitor.serial_port.readline()
        #print(r)

    def CCWMoveToStop(self):
        print("CCWMoveToStop")
        self.com_monitor.serial_port.write(b"CCW\n")
        #r = self.com_monitor.serial_port.readline()
        #print(r)

    def CWMoveToStop(self):
        print("CWMoveToStop")
        self.com_monitor.serial_port.write(b"CW\n")
        #r = self.com_monitor.serial_port.readline()
        #print(r)

    def CCWHome(self):
        print("CCWHome")
        self.com_monitor.serial_port.write(b"HOME=CCW\n")
        #r = self.com_monitor.serial_port.readline()
        #print(r)

    def CWHome(self):
        print("CWHome")
        self.com_monitor.serial_port.write(b"HOME=CW\n")
        #r = self.com_monitor.serial_port.readline()
        #print(r)

    def getCurrentFilter(self):
        row = self.ui.filtersTab.currentRow()
        try:
            name = self.ui.filtersTab.item(row, 0).text()
        except:
            name = 'none'
        try:
            val = self.ui.filtersTab.item(row, 1).text()
        except:
            val = 'none'
        #   return (None, None)
        return name, val, row

    def prevFilter(self):
        row = self.ui.filtersTab.currentRow()
        if row > 0:
            print(b"FW=" + str(row - 1).encode('utf-8') + b"\n")
            self.com_monitor.serial_port.write(b"FW=" +
                                               str(row - 1).encode('utf-8') +
                                               b"\n")
            #r = self.com_monitor.serial_port.readline()
            #print(r)
            self.ui.filtersTab.setCurrentCell(row - 1, 0)
            self.lastFiltChTime = datetime.now()
            #self.ui.oscilloVdiv2.setCurrentIndex(10)
            #self.oscillo.vdiv2(10)
            #ch2_v = self.oscillo.get_vdiv2()
            #print(ch2_v)
            return 1
        else:
            return 0

    def nextFilter(self):
        row = self.ui.filtersTab.currentRow()
        if row < 5:
            print(b"FW=" + str(row + 1).encode('utf-8') + b"\n")
            self.com_monitor.serial_port.write(b"FW=" +
                                               str(row + 1).encode('utf-8') +
                                               b"\n")
            #r = self.com_monitor.serial_port.readline()
            #print(r)
            self.lastFiltChTime = datetime.now()
            #self.ui.oscilloVdiv2.setCurrentIndex(3)
            #self.oscillo.vdiv2(3)
            #ch2_v = self.oscillo.get_vdiv2()
            #print(ch2_v)
            return 1
        else:
            return 0

    def stepperStop(self):
        self.com_monitor.serial_port.write(b"STOP\n")
        #r = self.com_monitor.serial_port.readline()
        #print(r)

    def stepperLock(self, state):
        if state:
            self.com_monitor.serial_port.write(b"ON\n")
        else:
            self.com_monitor.serial_port.write(b"OFF\n")
        #r = self.com_monitor.serial_port.readline()
        #print(r)

    def setStepperSpeed(self):
        speed = self.ui.stepperSpeed.value()
        self.com_monitor.serial_port.write(b"SPEED=" +
                                           str(speed).encode('utf-8') + b"\n")
        #r = self.com_monitor.serial_port.readline()
        #print(r)

    def updateAngle(self, new_angle=0, angle_counter=0, mode='None'):
        if self.sender().objectName() == "resetAngle": mode = "reset"
        if mode == "reset":
            self.currentAngle = 0
            self.com_monitor.serial_port.write(b"ANGLE=" +
                                               str(0).encode('utf-8') + b"\n")
        elif mode == "set":
            self.currentAngle = new_angle  # in deg
            val = new_angle / float(self.config['GLOBAL']['anglecalibr'])
            self.com_monitor.serial_port.write(b"ANGLE=" +
                                               str(val).encode('utf-8') +
                                               b"\n")
            #r = self.com_monitor.serial_port.readline()
            #print(r)
        else:
            try:
                self.currentAngle = new_angle * float(
                    self.config['GLOBAL']['anglecalibr'])
            except:
                pass
        self.ui.currentAngle.setText(str(self.currentAngle))
        self.ui.currentAngleCounter.setText(str(angle_counter))
        return self.currentAngle

    def setCustomAngle(self):
        dlg = QtGui.QInputDialog(self)
        dlg.setInputMode(QtGui.QInputDialog.DoubleInput)
        dlg.setLabelText("Angle:")
        dlg.setDoubleDecimals(6)
        dlg.setDoubleRange(-999999, 999999)
        ok = dlg.exec_()
        angle = dlg.doubleValue()
        if ok:
            self.updateAngle(angle, mode='set')

    def moveToAngle(self):
        dlg = QtGui.QInputDialog(self)
        dlg.setInputMode(QtGui.QInputDialog.DoubleInput)
        dlg.setLabelText("Angle:")
        dlg.setDoubleDecimals(6)
        dlg.setDoubleRange(-999999, 999999)
        ok = dlg.exec_()
        angle = dlg.doubleValue()
        if ok:
            self.com_monitor.serial_port.write(b"ABS=" +
                                               str(angle).encode('utf-8') +
                                               b"\n")
            #r = self.com_monitor.serial_port.readline()
            print(r)

    def startMeasurement(self, state):
        if state:
            if self.isStepperConnected():
                self.steppingTimer.start()
                self.ui.startMeasurement.setText("Stop")
                self.getCurrentFilter(self)

            else:
                self.ui.startMeasurement.setChecked(False)
                self.ui.startMeasurement.setText("Start")
        else:
            self.steppingTimer.stop()
            self.ui.startMeasurement.setText("Start")
            self.num = 0
            self.calibrData = []

    def stepperOn(self):
        pass

    def getStepperState(self):
        state = [i.value for i in getState(self.ATrtAddr, 1)]
        #if sum(state) == 0:
        #   state [0] = 1
        return state

    def startCalibr(self, state):
        if state:
            self.calibrTimer.start(self.ui.plotPeriod.value())

            direction = -1 if self.ui.measurementDirCW.isChecked() else 1
            self.line0.setData(x=[], y=[])
            self.line1.setData(x=[], y=[])
            self.line2.setData(x=[], y=[])
            self.line3.setData(x=[], y=[])
            self.line5.setData(x=[], y=[])

        else:

            self.calibrTimer.stop()
            self.calibrData = np.array([])

    def onCalibrTimer(self):
        r = []
        #chanels=[0,1,2]
        #####################################################################################
        #r=et.getDataProcN(2,100,chanels,True)
        name, tmp_filt, index = self.getCurrentFilter()
        print('Filter:', name, tmp_filt, index)
        r = self.oscilloGetData()
        y0 = r[1]
        y1 = r[0] / float(tmp_filt)

        if len(self.calibrData) > 0:

            self.calibrData = np.vstack((self.calibrData, [y0, y1]))
        else:
            self.calibrData = np.array([y0, y1])
        data = self.calibrData

        self.line0.setData(x=np.arange(len(data)), y=data[:, 0])
        self.line1.setData(x=np.arange(len(data)), y=data[:, 1])
        self.updateAngle(len(data))
        app.processEvents()

    def startContMeas(self, state):
        if state:
            self.angleUpdateTimer.stop()

            with open(self.ui.saveToPath.text(), 'a') as f:
                f.write("\n#$Filter:" + self.getCurrentFilter()[0] + "\n")
                for row in range(6):
                    name = self.ui.filtersTab.item(row, 0).text()
                    val = self.ui.filtersTab.item(row, 1).text()
                    f.write("#$\t" + str(row) + "\t" + name + "\t" + val +
                            '\n')
                f.write("#$POWER:" +
                        self.config['GLOBAL']['power'].replace('\n', '\t') +
                        '\n')
                f.write(
                    "#$WAVELENGTH:" +
                    self.config['GLOBAL']['wavelength'].replace('\n', '\t') +
                    '\n')
                f.write("#$OBJECT:" +
                        self.config['GLOBAL']['object'].replace('\n', '\t') +
                        '\n')

                f.write(
                    "angle\tangle_counter\tref\tsignal\tsignal_std\tfilter\tTime\tfreq\tduty_cycle\n"
                )

            self.measTimer.start(self.ui.plotPeriod.value())

            direction = -1 if self.ui.measurementDirCW.isChecked() else 1
            if direction == 1:
                self.CWMoveToStop()
            else:
                self.CCWMoveToStop()

            self.line0.setData(x=[], y=[])
            self.line1.setData(x=[], y=[])

        else:

            self.stepperStop()
            #et.ET_stopStrobData()
            #try:

            #   self.SMD.eStop()
            #except:
            #   print('Err')
            self.measTimer.stop()
            #self.openAngleSensorPort(True)
            self.angleUpdateTimer.start()
            self.calibrData = np.array([])
            #data = np.loadtxt(self.ui.saveToPath.text(),comments='#')
            #self.line2.setData(x=data[:,4], y=data[:,1])
            #self.line3.setData(x=data[:,-1], y=data[:,2])

    def onContMeasTimer(self):
        r = []
        #chanels=[0,1,2]
        ############################################################################
        r = self.oscilloGetData()
        y0 = r[1]
        y1 = r[0]
        y1_std = r[2]

        name, tmp_filt, index = self.getCurrentFilter()
        print('Filter:', name, float(tmp_filt), index)
        info = self.getNanoScatInfo(['angle', 'FW', 'angle_counter'])
        angle = float(self.ui.currentAngle.text())
        angle_counter = float(
            self.ui.currentAngleCounter.text())  #info['angle']
        filt = info['FW']
        freq = float(self.ui.oscilloFreq.text())
        duty_cycle = float(self.ui.duty_cycle.text())
        #try:
        #self.currentAngle = angle#et.getAngle()
        #except:
        #   pass
        print("angle", angle)
        #self.ui.currentAngle.setText(str(self.currentAngle))

        x = angle
        x_c = angle_counter

        with open(self.ui.saveToPath.text(), 'a') as f:
            f.write(
                str(x) + "\t" + str(x_c) + "\t" + str(y0) + "\t" + str(y1) +
                "\t" + str(y1_std) + '\t' + str(filt) + "\t" +
                str(time.time()) + "\t" + str(freq) + "\t" + str(duty_cycle) +
                "\n")

        #print(self.measData)
        if len(self.measData) > 0:

            self.measData = np.vstack(
                (self.measData, [x, y0, y1 / float(tmp_filt), x_c]))
        else:
            self.measData = np.array([x, y0, y1 / float(tmp_filt), x_c])
        data = self.measData
        #print(data)

        self.line0.setData(x=data[:, 0], y=data[:, 1])
        self.line1.setData(x=data[:, 0], y=data[:, 2])
        self.line5.setData(x=data[:, 3], y=data[:, 2])
        #self.updateAngle(x)
        app.processEvents()

    def saveToBtn(self):
        filename = self.fileDialog.getSaveFileName(self)
        print(filename)
        self.ui.saveToPath.setText(filename)

    def openAngleSensorPort(self, state):
        if state:

            print(">>>>>>open")

            #port = '/dev/ttyUSB'+str(self.ui.angleSensorPort.value())
            self.data_q = queue.Queue()
            self.error_q = queue.Queue()
            self.port = list(list_ports.grep("0403:0000"))[0][0]
            self.com_monitor = ComMonitorThread(self.data_q, self.error_q,
                                                self.port, 9600)
            self.com_monitor.start()
            #self.angleSensorSerial = serial.Serial(port,baudrate=9600,timeout=0.1)#.port = port
            print(self.port)
            time.sleep(2)
            #self.angleSensorSerial.port = port
            #self.angleSensorSerial.baudrate = 19200
            #self.angleSensorSerial.timeout = 4
            #self.angleSensorSerial.open()
            #self.angleSensorSerial.setDTR(True)
            #self.angleSensorSerial.write(b'')
            #self.angleSensorSerial.flush()
            #self.angleSensorSerial.flushInput()
            #self.angleSensorSerial.flushOutput()
            #a=self.angleSensorSerial.read(5)
            print("0>>", self.data_q)
            #self.angleSensorSerial.write(b"STATE?\n")
            #a=self.angleSensorSerial.readline()
            #print("1>>",a)

            self.angleUpdateTimer.start(self.ui.plotPeriod.value())

        else:
            self.angleUpdateTimer.stop()
            self.com_monitor.stop()

    def getNanoScatInfo(self, keys=['angle']):
        if not self.com_monitor.serial_port.isOpen():
            self.openAngleSensorPort(True)
            return None
        else:
            outDict = {}
            #self.angleSensorSerial.flush()
            #self.angleSensorSerial.flushInput()
            #self.angleSensorSerial.flushOutput()
            self.com_monitor.serial_port.write(b"STATE?\n")
            #line = self.angleSensorSerial.readline().decode("utf-8")
            prev_data = []
            while not self.com_monitor.data_q.empty():
                prev_data.append(self.com_monitor.data_q.get())
            data = ''
            for i in prev_data:
                data += i[0].decode()
            line = data.split('\n')
            if len(line) < 2:
                line = line[0]
            elif len(line) >= 2:
                line = line[-2]
            print(">>", line)
            self.ui.statusBar.showMessage(line)
            if 'angle' in keys:
                try:
                    outDict['angle'] = float(
                        line.split('A:')[-1].split('\t')[0])
                    outDict['angle_counter'] = float(
                        line.split('c:')[-1].split('\t')[0])
                    self.updateAngle(outDict['angle'],
                                     angle_counter=outDict['angle_counter'])
                except ValueError:
                    outDict['angle'] = None

            if 'zero' in keys:
                try:
                    outDict['zero'] = int(line.split('Z:')[-1].split('\t')[0])
                except ValueError:
                    outDict['zero'] = None
            if 'FW' in keys:
                try:
                    outDict['FW'] = int(line.split('FW:')[-1].split('\t')[0])
                except ValueError:
                    outDict['FW'] = None

            if 'freqMode' in keys:
                try:
                    outDict['freqMode'] = [
                        float(i) for i in (
                            line.split('\tFM:')[-1].split('\t')[0]).split('x')
                    ]
                except ValueError:
                    outDict['freqMode'] = [None, None]
            return outDict

    def onAngleUpdateTimer(self):

        info = self.getNanoScatInfo(['angle', 'FW', 'angle_counter'])
        angle = info['angle']
        angle_counter = info['angle_counter']
        filt = info['FW']
        try:
            #self.currentAngle = angle#et.getAngle()
            self.ui.filtersTab.setCurrentCell(filt, 0)
        except:
            pass
        print("angle", angle)
        self.updateAngle(angle, angle_counter=angle_counter)
        #self.ui.currentAngle.setText(str(self.currentAngle))

    def checkStepperState(self):
        pass

    #def setADCAmplif(self, value):
    #et.ET_SetAmplif(value)

    def cleanPlot(self):
        self.calibrData = np.array([])
        self.measData = np.array([])
        self.line0.setData(x=[], y=[])
        self.line1.setData(x=[], y=[])
        self.line5.setData(x=[], y=[])

    def closeEvent(self, event):
        print("event")
        reply = QtGui.QMessageBox.question(self, 'Message',
                                           "Are you sure to quit?",
                                           QtGui.QMessageBox.Yes,
                                           QtGui.QMessageBox.No)

        if reply == QtGui.QMessageBox.Yes:
            self.com_monitor.stop()
            self.oscillo.disconnect()
            self.oscillo.close()
            event.accept()
            #self.stopLaserStrob()
            #self.stopDataBuffering()
        else:
            event.ignore()

    def oscilloConnect(self, state):
        if state:
            self.oscillo.connect()
            r = self.oscillo.init()
            print(r)
            r = self.oscillo.vers()
            print(r)
            ch1_v = self.oscillo.get_vdiv1()
            if self.ui.CH1_AC_DC.isChecked():
                ch1_v -= 64
            print(ch1_v)

            self.ui.oscilloVdiv1.setCurrentIndex(ch1_v)
            yp1 = self.oscillo.get_ypos1()
            print(yp1)
            self.ui.oscilloYpos1.setValue(yp1)

            ch2_v = self.oscillo.get_vdiv2()
            if self.ui.CH2_AC_DC.isChecked():
                ch1_v -= 64
            print(ch2_v)
            self.ui.oscilloVdiv2.setCurrentIndex(ch2_v)
            yp2 = self.oscillo.get_ypos2()
            self.oscilloLastIndex = [ch1_v, ch2_v]
            print(yp2)
            self.ui.oscilloYpos2.setValue(yp2)

            td = self.oscillo.get_tdiv()
            print(td)
            self.ui.oscilloTdiv.setCurrentIndex(td)

            self.oscReadTimer.start(400)

        else:
            self.oscReadTimer.stop()
            self.oscillo.disconnect()
            self.oscillo.close()

    def oscilloGetData(self):
        div = (0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5,
               10, 20)
        div_t = self.ui.oscilloTdiv.currentText()
        print(div_t)
        tdiv_val, t_order = div_t.split(' ')

        scales = {'ns': 1e-9, 'mks': 1e-3, 'ms': 1e-3, 's': 1}
        tdiv_val = float(tdiv_val) * scales[t_order]

        res1 = self.oscillo.rdwf1()
        sig = np.array([int(i) for i in res1[50:]])
        self.line_sig.setData(x=np.arange(len(sig)), y=sig)
        index1 = self.ui.oscilloVdiv1.currentIndex()

        res2 = self.oscillo.rdwf2()
        ref = np.array([int(i) for i in res2[50:]])
        self.line_ref.setData(x=np.arange(len(ref)), y=ref)
        index2 = self.ui.oscilloVdiv2.currentIndex()

        Vpp1, STD, HIGH, LOW, ref_norm, f, duty_cycle = peak2peak(
            ref, sig, ref_mode='triangle')
        self.line_ref_norm.setData(x=np.arange(len(ref_norm)), y=ref_norm)

        frequency = 1 / (0.1 / 2048 * 10 / f)
        self.ui.oscilloFreq.setText(str(frequency))
        self.ui.duty_cycle.setText(str(duty_cycle))

        val1 = self.oscillo.dig2Volts(
            Vpp1, div[index1])  #(Vpp1)/256*(div[index1]*8)*1.333333
        STD1 = self.oscillo.dig2Volts(
            STD, div[index1])  #(STD)/256*(div[index1]*8)*1.333333
        self.ui.CH1Val.setText(str(val1))
        self.ui.CH1Val_std.setText(str(STD1))

        ref = medfilt(ref, 5)
        Vpp2 = ref.max() - ref.min()
        print("Vpp1:", Vpp1, "Vpp2:", Vpp2)
        val2 = self.oscillo.dig2Volts(
            Vpp2, div[index2])  #(Vpp2)/256*(div[index2]*8)*1.333333
        self.ui.CH2Val.setText(str(val2))

        if LOW > HIGH:
            tmp = HIGH
            HIGH = LOW
            LOW = tmp

        if self.ui.oscilloAuto.isChecked() and (time.time() -
                                                self.lastDivChange) > 1:
            self.lastDivChange = time.time()
            ac_dc1 = self.ui.CH1_AC_DC.isChecked()
            if LOW < 20:
                index1 = self.ui.oscilloVdiv1.currentIndex()
                if self.oscilloLastMaster == 'HAMEG':
                    #if self.oscilloLastIndex[0] == index1+1:
                    #   self.oscilloLastMaster = 'FM'
                    if index1 < 12:
                        self.oscilloLastIndex[0] = index1
                        self.oscillo.vdiv1(index1 + 1, ac_dc1)
                        self.ui.oscilloVdiv1.setCurrentIndex(index1 + 1)
                        #self.oscilloAutoSet()
                        #self.oscillo.tdiv(17)
                        #self.ui.oscilloTdiv.setCurrentIndex(17)
                    #else:
                    #   self.oscilloLastMaster = 'FM'
                else:

                    #self.nextFilter()
                    #self.oscilloAutoSet()
                    #self.oscillo.tdiv(17)
                    #self.ui.oscilloTdiv.setCurrentIndex(17)
                    self.oscilloLastIndex == 'HAMEG'

            elif HIGH > 230:
                index1 = self.ui.oscilloVdiv1.currentIndex()
                if self.oscilloLastMaster == 'HAMEG':
                    #if self.oscilloLastIndex[0] == index1+1:
                    #   self.oscilloLastMaster = 'FM'
                    if index1 > 1:
                        self.oscilloLastIndex[0] = index1
                        self.oscillo.vdiv1(index1 - 1, ac_dc1)
                        self.ui.oscilloVdiv1.setCurrentIndex(index1 - 1)

                        #self.oscilloAutoSet()
                        #self.oscillo.tdiv(17)
                        #self.ui.oscilloTdiv.setCurrentIndex(17)
                    #else:
                    #   self.oscilloLastMaster = 'FM'
                else:

                    #self.nextFilter()
                    #self.oscilloAutoSet()
                    #self.oscillo.tdiv(17)
                    #self.ui.oscilloTdiv.setCurrentIndex(17)
                    self.oscilloLastIndex == 'HAMEG'

            elif abs(Vpp1) < 10:
                index1 = self.ui.oscilloVdiv1.currentIndex()
                if self.oscilloLastMaster == 'HAMEG':
                    #if self.oscilloLastIndex[0] == index1-1:
                    #   self.oscilloLastMaster = 'FM'
                    if index1 > 1:
                        self.oscilloLastIndex[0] = index1
                        self.ui.oscilloVdiv1.setCurrentIndex(index1 - 1)
                        self.oscillo.vdiv1(index1 - 1, ac_dc1)
                        #self.oscilloAutoSet()
                        #self.oscillo.tdiv(17)
                        #self.ui.oscilloTdiv.setCurrentIndex(17)
                    #else:
                    #   self.oscilloLastMaster = 'FM'
                else:
                    #self.prevFilter()
                    #self.oscilloAutoSet()
                    #self.oscillo.tdiv(17)
                    #self.ui.oscilloTdiv.setCurrentIndex(17)
                    self.oscilloLastIndex == 'HAMEG'

            print(Vpp1, self.oscilloLastMaster)
        return [val1, val2, STD1]

    def onOscReadTimer(self):
        start = time.time()
        self.oscReadTimer.stop()
        res = self.oscilloGetData()
        self.oscReadTimer.start(400)
        end = time.time()
        print("oscillo_dt:\t", end - start)
        print(res)

    def oscilloAutoSet(self):
        r = self.oscillo.autoset()
        print(r)
        ch1_v = self.oscillo.get_vdiv1()
        print(ch1_v)
        self.ui.oscilloVdiv1.setCurrentIndex(ch1_v)
        yp1 = self.oscillo.get_ypos1()
        print(yp1)
        self.ui.oscilloYpos1.setValue(yp1)

        ch2_v = self.oscillo.get_vdiv2()
        print(ch2_v)
        self.ui.oscilloVdiv2.setCurrentIndex(ch2_v)
        yp2 = self.oscillo.get_ypos2()
        print(yp2)
        self.ui.oscilloYpos2.setValue(yp2)

        td = self.oscillo.get_tdiv()
        print(td)
        self.ui.oscilloTdiv.setCurrentIndex(td)

    def oscilloSet(self):
        v1 = self.ui.oscilloVdiv1.currentIndex()
        ac_dc1 = self.ui.CH1_AC_DC.isChecked()
        r = self.oscillo.vdiv1(v1, ac_dc1)
        print(r)
        ac_dc2 = self.ui.CH2_AC_DC.isChecked()
        v2 = self.ui.oscilloVdiv2.currentIndex()
        r = self.oscillo.vdiv2(v2, ac_dc2)
        print(r)

        td = self.ui.oscilloTdiv.currentIndex()
        r = self.oscillo.tdiv(td)
        print(r)

        y1 = self.ui.oscilloYpos1.value()
        r = self.oscillo.ypos1(y1)
        print(r)

        y2 = self.ui.oscilloYpos2.value()
        r = self.oscillo.ypos2(y2)
        print(r)

    def uiConnect(self):
        #self.ui.btnExit.clicked.connect(self.closeAll)
        #self.ui.actionExit.triggered.connect(self.closeAll)
        #self.ui.measurementDirCW.clicked.connect(lambda state: (self.ui.measurementDirCCW.setChecked(False), self.ui.measurementDirCW.setEnabled(False),self.ui.measurementDirCCW.setEnabled(True)))
        #self.ui.measurementDirCCW.clicked.connect(lambda state: (self.ui.measurementDirCW.setChecked(False), self.ui.measurementDirCCW.setEnabled(False),self.ui.measurementDirCW.setEnabled(True)))

        self.ui.startCalibr.toggled[bool].connect(self.startCalibr)
        self.ui.startMeasurement.toggled[bool].connect(self.startContMeas)

        self.ui.oscilloConnect.toggled[bool].connect(self.oscilloConnect)
        self.ui.oscilloAutoSet.clicked.connect(self.oscilloAutoSet)
        self.ui.oscilloSet.clicked.connect(self.oscilloSet)
        #self.ui.ADCAmplif.valueChanged[int].connect(self.setADCAmplif)
        #self.ui.laserFreq.valueChanged[int].connect(self.setLaserFreq)

        #self.ui.pauseMeasurements.toggled[bool].connect(self.pauseMeasurements)
        #self.ui.openCOMPort_btn.toggled[bool].connect(self.Open_CloseStepperCOMPort)
        self.ui.openAngleSensorPort.toggled[bool].connect(
            self.openAngleSensorPort)
        self.ui.setCustomAngle.clicked.connect(self.setCustomAngle)
        self.ui.moveToAngle.clicked.connect(self.moveToAngle)

        #self.ui.editStepperSettings.clicked.connect(self.setStepperParam)
        self.ui.relCWMove.clicked.connect(self.relCWMove)
        self.ui.relCCWMove.clicked.connect(self.relCCWMove)

        self.ui.cleanPlot.clicked.connect(self.cleanPlot)

        self.ui.CCWMoveToStop.clicked.connect(self.CCWMoveToStop)
        self.ui.CWMoveToStop.clicked.connect(self.CWMoveToStop)
        self.ui.CCWHome.clicked.connect(self.CCWHome)
        self.ui.CWHome.clicked.connect(self.CWHome)
        self.ui.setStepperSpeed.clicked.connect(self.setStepperSpeed)
        self.ui.stepperSpeed.valueChanged[int].connect(
            self.ui.stepperSpeedValue.setValue)
        self.ui.stepperSpeedValue.valueChanged[int].connect(
            self.ui.stepperSpeed.setValue)

        self.ui.nextFilter.clicked.connect(self.nextFilter)
        self.ui.prevFilter.clicked.connect(self.prevFilter)

        self.ui.stepperStop.clicked.connect(self.stepperStop)
        self.ui.stepperLock.toggled[bool].connect(self.stepperLock)

        self.ui.saveToBtn.clicked.connect(self.saveToBtn)
        #self.ui.resetAngle.clicked.connect(self.updateAngle)
        #self.ui.setCustomAngle.toggled[bool].connect(self.setCustomAngle)

        #self.ui.calibrFW.clicked.connect(self.calibrFW)

        #self.ui.startMeasurement.clicked.connect(self.startMeasurement)

        #self.steppingTimer.timeout.connect(self.stepMeasurement)
        self.calibrTimer.timeout.connect(self.onCalibrTimer)
        self.measTimer.timeout.connect(self.onContMeasTimer)
        self.angleUpdateTimer.timeout.connect(self.onAngleUpdateTimer)
        #self.calibrHomeTimer.timeout.connect(self.onCalibrHomeTimer)
        self.oscReadTimer.timeout.connect(self.onOscReadTimer)
        #self.calibrFWTimer.timeout.connect(self.onCalibrFWTimer)
        #self.stepperStateTimer.timeout.connect(self.checkStepperState)
        #self.laserStrobTimer.timeout.connect(self.laserStrob)

        self.ui.saveConfig.clicked.connect(self.saveConfig)

        self.ui.actionClose.triggered.connect(self.close)
예제 #9
0
class mainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)
        uifile = os.path.join(
            os.path.abspath(os.path.dirname(__file__)), 'ui_data', 'main.ui')
        uic.loadUi(uifile, self)

        self.adsrw = adsrWidget()
        self.adsrList = adsrList()
        self.adsrw.adsr = self.adsrList
        self.adsrWidgetContainer.addWidget(self.adsrw)

        self.current_adsr = None
        self.monitor_adsr = True

        self.players = []
        self.invert_control = False
        self.trigger_shadow = False
        self.sounds = []

        self.plotw = PlotWindow()
        self.plotw.plot.setAxisScale(Qwt.QwtPlot.yLeft, 0, 1024, 1024 / 8)
        self.plotw.plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 20, 20. / 10)
        self.plotWindowContainer.addWidget(self.plotw)

        for curve in 'Entrada d/dT Umbral Salida'.split():
            self.plotw.add_curve(curve)

        self._idx = 0

        self.plotw.show()

        self.timer = QtCore.QTimer()

        self.open_port()

        self.load_config()

    def load_config(self):
        config.load()

        adsrconf = config.get('adsr')
        if adsrconf:
            for k, v in adsrconf.iteritems():
                setattr(self.adsrList, k, v)
            self.adsrw.adsr = self.adsrList

        sounds = config.get('sounds')
        if sounds:
            for snd in sounds['files']:
                self.add_sound(str(snd))

        globs = config.get('globals')
        if globs:
            self.invert_control = globs['invert_control']
            self.trigger_shadow = globs['trigger_shadow']
            if self.invert_control:
                self.invert.setCheckState(QtCore.Qt.Checked)
            if self.trigger_shadow:
                self.invert_slope.setCheckState(QtCore.Qt.Checked)

            self.sldVolumen.setValue(globs['default_volume'])

            for x in xrange(globs['sensor_count']):
                self.add_sensor()

    def closeEvent(self, event):
        self.save_config()
        event.accept()

    def save_config(self):
        adsrconf = config.get('adsr')
        for param in adsr_params.keys():
            adsrconf[param] = getattr(self.adsrList, param)

        sounds = config.get('sounds')
        sounds['files'] = self.sounds[:]

        globs = config.get('globals')
        globs['invert_control'] = self.invert_control
        globs['trigger_shadow'] = self.trigger_shadow
        globs['default_volume'] = self.sldVolumen.value()
        globs['sensor_count'] = len(self.players)

        config.save()

    def add_sensor(self):
        play = SensorPlayer(gui=False)
        self.players.append(play)
        self.adsrList.append(play.adsr)

        play.invert_control = self.invert_control
        play.trigger_on_light = not self.trigger_shadow

        self.sensorList.addItem('Sensor %i' % len(self.adsrList))

    @QtCore.pyqtSlot()
    def on_sensorAdd_clicked(self):
        self.add_sensor()

    @QtCore.pyqtSlot()
    def on_sensorDelete_clicked(self):
        idx = self.sensorList.count()
        if idx == 0:
            return

        item = self.sensorList.takeItem(idx - 1)
        del item
        self.adsrList.pop()
        p = self.players.pop()
        #FIXME: matar el vlc hijo
        p.stop()

    @QtCore.pyqtSlot(bool)
    def on_plotWindowGroup_clicked(self, checked):
        #FIXME: desconectar el grafico  y borrar datos
        if checked:
            self.monitor_adsr = True
        else:
            self.monitor_adsr = False

        self.connect_adsr()

    @QtCore.pyqtSlot(int)
    def on_invert_stateChanged(self, state):
        if state:
            self.invert_control = True
        else:
            self.invert_control = False

        for player in self.players:
            player.invert_control = self.invert_control

    @QtCore.pyqtSlot(int)
    def on_invert_slope_stateChanged(self, state):
        if state:
            self.trigger_shadow = True
        else:
            self.trigger_shadow = False

        for player in self.players:
            player.trigger_on_light = not self.trigger_shadow

    @QtCore.pyqtSlot(int)
    def on_sldVolumen_valueChanged(self, value):
        for player in self.players:
            player.default_volume = value

    def add_sound(self, filename):
        self.sounds.append(filename)
        self.soundList.addItem(filename)

    @QtCore.pyqtSlot()
    def on_soundAdd_clicked(self):
        fn = QtGui.QFileDialog.getOpenFileName()
        if fn:
            fn = str(fn)
            self.add_sound(fn)

    @QtCore.pyqtSlot()
    def on_soundDelete_clicked(self):
        idx = self.soundList.currentRow()
        if idx == -1:
            return
        item = self.soundList.takeItem(idx)
        del item
        del self.sounds[idx]

    @QtCore.pyqtSlot(bool)
    def on_Start_clicked(self, checked):
        if checked:
            for idx in xrange(min(len(self.players), len(self.sounds))):
                player = self.players[idx]
                player.playlist.clear()
                player.default_volume = self.sldVolumen.value()
                player.playlist.append(self.sounds[idx])
                player.start()
        else:
            for player in self.players:
                player.stop()

    @QtCore.pyqtSlot(int)
    def on_sensorList_currentRowChanged(self, row):
        self.connect_adsr(self.adsrList[row])

    def connect_adsr(self, adsr=None):
        if self.monitor_adsr:
            self.plotw.clear()
            self._idx = 0
            if adsr is not None and adsr is not self.current_adsr:
                if self.current_adsr:
                    self.current_adsr.internal_state_changed.disconnect(
                        self.adsr_internal_cb)
                self.current_adsr = adsr
                self.current_adsr.internal_state_changed.connect(
                    self.adsr_internal_cb)
            else:
                if self.current_adsr:
                    self.current_adsr.internal_state_changed.connect(
                        self.adsr_internal_cb)
        else:
            if self.current_adsr:
                self.current_adsr.internal_state_changed.disconnect(
                    self.adsr_internal_cb)

    def adsr_internal_cb(self, *args, **kwargs):
        salida, trig, entrada, dx = args
        idx = self._idx + .1
        self._idx = idx
        self.plotw.add_datapoint(idx, entrada, abs(dx), self.adsrList.umbral,
                                 salida)

    def open_port(self):
        self.data_q = Queue.Queue()
        self.error_q = Queue.Queue()
        self.com_monitor = ComMonitorThread(self.data_q, self.error_q,
                                            '/dev/ttyACM0', 115200)
        self.com_monitor.start()
        com_error = get_item_from_queue(self.error_q)
        if com_error is not None:
            QtGui.QMessageBox.critical(self, 'ComMonitorThread error',
                                       com_error)
            self.com_monitor = None

        self.monitor_active = True

        self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.on_timer)

        self.timer.start(1000.0 / 10)

    def on_timer(self, *args):
        data = list(get_all_from_queue(self.data_q))
        # (timestamp, [x0, x1, x2, etc])
        if (len(data) == 0):
            return

        for row in data:
            for idx in xrange(min(len(row[1]), len(self.players))):
                self.players[idx].adsr(row[1][idx])
예제 #10
0
def main():
    time.sleep(10)
    Irma3Dflag = False
    tpmsflag = False
    counter = 0
    gpsflag = False
    weigthflag = False
    inflag = False
    lasttiempo = 0
    global saveflag
    saveflag = False
    logging.basicConfig(
        filename='home/pi/report.log',
        level=logging.DEBUG,
        format='%(levelname)s:(%(threadName)-10s) %(asctime)s %(message)s')
    config.read("/home/pi/config.ini")
    for section in config.sections():
        if (config.has_option(section, 'sensorname')):
            if ((config.get(section, 'sensorname') == 'tpms')
                    and (config.getboolean(section, 'connected'))):
                tpmsflag = True
                baudrate = config.getint(section, 'baudrate')
                print baudrate
                port = config.get(section, 'port')
                data_q = Queue.Queue()
                error_q = Queue.Queue()
                sensor_name = config.get(section, 'sensorname')
                com_monitor = ComMonitorThread(data_q, error_q, port, baudrate,
                                               tpmsflag)
                logging.info('Iniciando puerto Serial')
                com_monitor.start()
                com_error = get_item_from_queue(error_q)
                if com_error is not None:
                    logging.critical('ComMonitorThread error')
                    print com_error
                    com_monitor = None

            if ((config.get(section, 'sensorname') == 'weight')
                    and (config.getboolean(section, 'connected'))):
                weigthflag = True
                baudrate = config.getint(section, 'baudrate')
                print baudrate
                port = config.get(section, 'port')
                data_w = Queue.Queue()
                error_w = Queue.Queue()
                sensor_name = config.get(section, 'sensorname')
                com_monitor = weigthMonitor(data_w, error_w, port, baudrate,
                                            weigthflag)
                logging.info('Iniciando puerto Serial')
                com_monitor.start()
                com_error = get_item_from_queue(error_w)
                if com_error is not None:
                    logging.critical('weigthThread error')
                    print com_error
                    com_monitor = None

            if ((config.get(section, 'sensorname') == 'hanover')
                    and (config.getboolean(section, 'connected'))):
                hanover = True
                baudrate = config.getint(section, 'baudrate')
                port = config.get(section, 'port')
                data_z = Queue.Queue()
                error_z = Queue.Queue()
                sensor_name = config.get(section, 'sensorname')
                hanover_monitor = HanoverSignController(
                    data_z, error_z, port, baudrate, hanover)
                logging.info('Iniciando Hanover Service')
                usb_monitor.start()
                usb_error = get_item_from_queue(error_z)
                if usb_error is not None:
                    logging.critical('Hanover Thread error')
                    print usb_error
                    usb_monitor = None

            if ((config.get(section, 'sensorname') == 'Irma3D')
                    and (config.getboolean(section, 'connected'))):
                Irma3Dflag = True
                baudrate = config.getint(section, 'baudrate')
                port = config.get(section, 'port')
                data_u = Queue.Queue()
                error_u = Queue.Queue()
                sensor_name = config.get(section, 'sensorname')
                usb_monitor = UsbMonitorThread(data_u, error_u, port, baudrate,
                                               Irma3Dflag)
                logging.info('Iniciando puerto USB Serial')
                usb_monitor.start()
                usb_error = get_item_from_queue(error_u)
                if usb_error is not None:
                    logging.critical('USBMonitorThread error')
                    print usb_error
                    usb_monitor = None

    while True:
        if (config.getboolean('reportmethod', 'time')):
            tiempo = config.getint('reportmethod', 'reportime')
            if (inflag):
                GPIO.cleanup()
                inflag = False
                counter = 0
            if (tiempo != lasttiempo):
                try:
                    schedule.every(tiempo).minutes.do(saving_flag2)
                except Exception as e:
                    print(e)
                print("siguiente ejecucion en: " + str(tiempo))
                lasttiempo = tiempo
            try:
                schedule.run_pending()
            except Exception as e:
                print(e)
            time.sleep(1)
        elif (config.getboolean('reportmethod', 'input')):
            try:
                for section in config.sections():
                    if (config.has_option(section, 'sensorname')):
                        if ((config.get(section, 'sensorname') == 'report')
                                and (config.getboolean(section, 'connected'))):
                            puerto = config.getint(section, 'port')
                    #print(puerto)
            except Exception as e:
                print(e)
            if (counter == 0):
                try:
                    GPIO.setmode(GPIO.BOARD)
                    GPIO.setup(puerto, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
                    GPIO.add_event_detect(puerto,
                                          GPIO.RISING,
                                          callback=saving_flag,
                                          bouncetime=300)
                    inflag = True
                    counter = counter + 1
                except Exception as e:
                    print(e)
        if (gpsflag):
            out_msg = configuration.read_serial_data(data_g, config)
            if out_msg is not None:
                data_o.put(out_msg)
        if (Irma3Dflag):
            if (saveflag):
                read_usb_data(data_u, Irma3Dflag)
        if (weigthflag):
            if (saveflag):
                read_weight_data(data_w, weigthflag)
        if (tpmsflag):
            if (saveflag):
                read_serial_data(data_q, tpmsflag)
                saveflag = False
예제 #11
0
class CAN_Sniffer(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(CAN_Sniffer, self).__init__(parent)

        self.ui = Ui_MainWindow()

        self.ui.setupUi(self)

        self.monitor_active = False
        self.com_monitor = None
        self.com_data_q = None
        self.com_error_q = None
        self.data = ""
        # self.livefeed = LiveDataFeed()
        # self.temperature_samples = []
        self.timer = QtCore.QTimer()

        self.ui.serialPortSelectPb.clicked.connect(self.on_select_port)
        self.ui.serialConnectPb.clicked.connect(self.on_start)
        self.ui.serialDisconnectPb.clicked.connect(self.on_stop)
        self.ui.serialConnectPb.setEnabled(False)
        self.ui.serialDisconnectPb.hide()

    # @QtCore.pyqtSlot(int)
    # def on_inputSpinBox1_valueChanged(self, value):
    #     self.ui.outputWidget.setText(str(value + self.ui.inputSpinBox2.value()))

    # @QtCore.pyqtSlot(int)
    # def on_inputSpinBox2_valueChanged(self, value):
    #     self.ui.outputWidget.setText(str(value + self.ui.inputSpinBox1.value()))

        self.ui.dataTable.setColumnWidth(0,50)
        self.ui.dataTable.setColumnWidth(1,50)
        # for i in range(2,10):
        #     self.ui.dataTable.setColumnWidth(i,25)

        # self.update_data(512, [2,3,4,5,6,7,8,9])
        # self.update_data(654, [1,1,1,1,1,1,1,1])
        # self.update_data(543, [6,8,4,8,2,6,5,8])
        # self.update_data(456, [4,5,7,9,23,7,9,3])
        # self.update_data(512, [5,8,2,78,9,2,78,8])
        # self.update_data(512, [3,78,9,23,78,8,3])
        # self.update_data(512, [3,78,10,23,78])

    def on_select_port(self):
        ports = list(enumerate_serial_ports())
        if len(ports) == 0:
            QMessageBox.critical(self, 'No ports',
                'No serial ports found')
            return
        
        item, ok = QtGui.QInputDialog.getItem(self, 'Select a port',
                    'Serial port:', ports, 0, False)
        
        if ok and not item.isEmpty():
            self.ui.serialConnectPb.setEnabled(True)
            self.ui.serialPortLbl.setText(item)            
            # self.set_actions_enable_state()

    def on_stop(self):
        """ Stop the monitor
        """
        if self.com_monitor is not None:
            self.com_monitor.join(0.01)
            self.com_monitor = None

        self.monitor_active = False
        self.timer.stop()
        # self.set_actions_enable_state()
        
        self.ui.statusbar.showMessage('Monitor idle')
        self.ui.serialConnectPb.show()
        self.ui.serialDisconnectPb.hide()

    
    def on_start(self):
        """ Start the monitor: com_monitor thread and the update
            timer
        """
        if self.com_monitor is not None or self.ui.serialPortLbl.text() == '':
            return
        
        self.data_q = Queue.Queue()
        self.error_q = Queue.Queue()
        self.com_monitor = ComMonitorThread(
            self.data_q,
            self.error_q,
            full_port_name(str(self.ui.serialPortLbl.text())),
            38400)
        self.com_monitor.start()
        
        com_error = get_item_from_queue(self.error_q)
        if com_error is not None:
            QMessageBox.critical(self, 'ComMonitorThread error',
                com_error)
            self.com_monitor = None

        self.monitor_active = True
        # self.set_actions_enable_state()
        
        # self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.on_timer)
        # self.connect(self.timer, SIGNAL('timeout()'), self.on_timer)
        
        update_freq = 100
        if update_freq > 0:
            self.timer.start(1000.0 / update_freq)
        
        self.ui.statusbar.showMessage('Monitor running')
        self.ui.serialConnectPb.hide()
        self.ui.serialDisconnectPb.show()

    
    def on_timer(self):
        """ Executed periodically when the monitor update timer
            is fired.
        """
        self.read_serial_data()
        # self.update_monitor()

    def read_serial_data(self):
        """ Called periodically by the update timer to read data
            from the serial port.
        """
        qdata = list(get_all_from_queue(self.data_q))
        if len(qdata) > 0:
            data = self.data+''.join(qdata)
            while data.find("Id: ")!=-1:
                msgStart = data.find("Id: ")
                msgEnd = data.find("\n",msgStart)
                if msgEnd == -1:
                    break

                packet = data[msgStart:msgEnd-1]
                # print "msg: [%s]" % packet
                msgId = int(packet[4:8],16)
                # print "msgId: %d [%x]" % (msgId, msgId)
                msgData = map(lambda x: int(x,16) ,packet[16:].split(" "))
                # print "data: ", msgData
                self.update_data(msgId, msgData)

                data = data[msgEnd:]
            self.data = data

    def update_data(self, msgId, msgData):
        rowCount = self.ui.dataTable.rowCount()
        print rowCount
        msgIdExists = False
        for i in range(rowCount):
            if self.ui.dataTable.item(i, 0).text() == "%04X" % msgId:
                msgIdExists = True
                count = int(self.ui.dataTable.item(i, 1).text())
                self.ui.dataTable.item(i, 1).setText(str(count+1))
                for j in range(8):
                    try:
                        txt = "%02X" % msgData[j]
                    except IndexError:
                        txt = ""
                    if self.ui.dataTable.item(i, 2+j).text() != txt:
                        self.ui.dataTable.item(i, 2+j).setText(txt)
                        self.ui.dataTable.item(i, 2+j).setBackground(QtGui.QColor('red'))
                    else:
                        self.ui.dataTable.item(i, 2+j).setBackground(QtGui.QColor('white'))



        if not msgIdExists:
            self.ui.dataTable.insertRow(rowCount)
            print "msgId: %d [%x]" % (msgId, msgId)
            item = QtGui.QTableWidgetItem("%04X" % msgId)
            self.ui.dataTable.setItem(rowCount,0,item)
            item = QtGui.QTableWidgetItem("1")
            self.ui.dataTable.setItem(rowCount,1,item)
            for i in range(8):
                try:
                    item = QtGui.QTableWidgetItem("%02X" % msgData[i])
                except IndexError:
                    item = QtGui.QTableWidgetItem("")
                self.ui.dataTable.setItem(rowCount,2+i,item)
예제 #12
0
class nS_SMFW():
    data_q = None
    error_q = None
    com_monitor = None
    port = None

    def __init__(self, parent=None):
        self.data_q = queue.Queue()
        self.error_q = queue.Queue()

    def open(self):
        self.port = list(list_ports.grep("0403:0000"))[0][
            0]  #'/dev/ttyUSB'+str(self.ui.angleSensorPort.value())
        self.com_monitor = ComMonitorThread(self.data_q, self.error_q,
                                            self.port, 9600)
        self.com_monitor.daemon = True
        self.com_monitor.start()

    def close(self):
        self.com_monitor.stop()

    def getData(self):
        prev_data = []
        while not self.data_q.empty():
            prev_data.append(self.data_q.get())
        return prev_data

    def insertToSerialFlow(function_to_decorate):
        out = None

        def wrapper(*args, **kw):
            self = args[0]
            print('Readout locked')
            self.com_monitor.lock_readout()
            try:
                #self.getData()
                out = function_to_decorate(*args, **kw)
            except serial.SerialException as e:
                self.error_q.put(e)
            self.com_monitor.release_readout()
            print('Readout released')
            return out

        return wrapper

    @insertToSerialFlow
    def setFilter(self, filterIndex):
        #try:
        self.com_monitor.serial_port.write(b"FW:" +
                                           str(filterIndex).encode('utf-8') +
                                           b"\n")
        r = self.com_monitor.read()
        print(r, '@@@')
        return r

    #except AttributeError:
    #return None

    @insertToSerialFlow
    def getNanoScatInfo(self, keys=['angle']):
        outDict = {}
        self.com_monitor.serial_port.write(b"STATE?\n")
        data = self.getData()
        #if data[-1][0].decode()
        #print(data)
        line = ''
        for i in data:
            tmp = i[0].decode()
            #if not '>' in tmp and not '<' in tmp:
            line += tmp
        line = re.sub('>.*?<', '', line)
        print(">", line)
        line = line.split('\t\r\n')
        #print(">>",line)
        if len(line) < 2: return None
        else: line = line[-2]
        print(">>>", line)
        if 'angle' in keys:
            try:
                outDict['angle'] = float(line.split('A:')[-1].split('\t')[0])
                #self.updateAngle(outDict['angle'])
            except ValueError:
                outDict['angle'] = None
        if 'zero' in keys:
            try:
                outDict['zero'] = int(line.split('Z:')[-1].split('\t')[0])
            except ValueError:
                outDict['zero'] = None
        if 'FW' in keys:
            try:
                outDict['FW'] = int(line.split('FW:')[-1].split('\t')[0])
            except ValueError:
                outDict['FW'] = None

        if 'freqMode' in keys:
            try:
                outDict['freqMode'] = [
                    float(i) for i in (
                        line.split('\tFM:')[-1].split('\t')[0]).split('x')
                ]
            except ValueError:
                outDict['freqMode'] = [None, None]
        return outDict

    @insertToSerialFlow
    def setStepperSpeed(self, speed):
        #speed = self.ui.stepperSpeed.value()
        self.com_monitor.serial_port.write(b"SPEED:" +
                                           str(speed).encode('utf-8') + b"\n")
        r = self.com_monitor.read()
        print(r)
예제 #13
0
class PlottingDataMonitor(QMainWindow):
    def __init__(self, parent=None):
        super(PlottingDataMonitor, self).__init__(parent)
        
        self.monitor_active = False
        self.com_monitor = None
        self.com_data_q = None
        self.com_error_q = None
        self.livefeed = LiveDataFeed()
        self.temperature_samples = []
        self.timer = QTimer()
        
        self.create_menu()
        self.create_main_frame()
        self.create_status_bar()
        
    def make_data_box(self, name):
        label = QLabel(name)
        qle = QLineEdit()
        qle.setEnabled(False)
        qle.setFrame(False)
        return (label, qle)
        
    def create_plot(self):
        plot = Qwt.QwtPlot(self)
        plot.setCanvasBackground(Qt.black)
        plot.setAxisTitle(Qwt.QwtPlot.xBottom, 'Time')
        plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 10, 1)
        plot.setAxisTitle(Qwt.QwtPlot.yLeft, 'Temperature')
        plot.setAxisScale(Qwt.QwtPlot.yLeft, 0, 250, 40)
        plot.replot()
        
        curve = Qwt.QwtPlotCurve('')
        curve.setRenderHint(Qwt.QwtPlotItem.RenderAntialiased)
        pen = QPen(QColor('limegreen'))
        pen.setWidth(2)
        curve.setPen(pen)
        curve.attach(plot)
        
        return plot, curve

    def create_thermo(self):
        thermo = Qwt.QwtThermo(self)
        thermo.setPipeWidth(6)
        thermo.setRange(0, 120)
        thermo.setAlarmLevel(80)
        thermo.setAlarmEnabled(True)
        thermo.setFillColor(Qt.green)
        thermo.setAlarmColor(Qt.red)
        thermo.setOrientation(Qt.Horizontal, Qwt.QwtThermo.BottomScale)
        
        return thermo

    def create_knob(self):
        knob = Qwt.QwtKnob(self)
        knob.setRange(0, 20, 0, 1)
        knob.setScaleMaxMajor(10)
        knob.setKnobWidth(50)
        knob.setValue(10)
        return knob

    def create_status_bar(self):
        self.status_text = QLabel('Monitor idle')
        self.statusBar().addWidget(self.status_text, 1)

    def create_main_frame(self):
        # Port name
        #
        portname_l, self.portname = self.make_data_box('COM Port:')
        
        portname_layout = QHBoxLayout()
        portname_layout.addWidget(portname_l)
        portname_layout.addWidget(self.portname, 0)
        portname_layout.addStretch(1)
        portname_groupbox = QGroupBox('COM Port')
        portname_groupbox.setLayout(portname_layout)
        
        # Plot and thermo
        #
        self.plot, self.curve = self.create_plot()
        self.thermo = self.create_thermo()
        
        thermo_l = QLabel('Average')
        thermo_layout = QHBoxLayout()
        thermo_layout.addWidget(thermo_l)
        thermo_layout.addWidget(self.thermo)
        thermo_layout.setSpacing(5)
        
        self.updatespeed_knob = self.create_knob()
        self.connect(self.updatespeed_knob, SIGNAL('valueChanged(double)'),
            self.on_knob_change)
        self.knob_l = QLabel('Update speed = %s (Hz)' % self.updatespeed_knob.value())
        self.knob_l.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
        knob_layout = QVBoxLayout()
        knob_layout.addWidget(self.updatespeed_knob)
        knob_layout.addWidget(self.knob_l)
        
        plot_layout = QVBoxLayout()
        plot_layout.addWidget(self.plot)
        plot_layout.addLayout(thermo_layout)
        plot_layout.addLayout(knob_layout)
        
        plot_groupbox = QGroupBox('Temperature')
        plot_groupbox.setLayout(plot_layout)
        
        # Main frame and layout
        #
        self.main_frame = QWidget()
        main_layout = QVBoxLayout()
        main_layout.addWidget(portname_groupbox)
        main_layout.addWidget(plot_groupbox)
        main_layout.addStretch(1)
        self.main_frame.setLayout(main_layout)
        
        self.setCentralWidget(self.main_frame)
        self.set_actions_enable_state()

    def create_menu(self):
        self.file_menu = self.menuBar().addMenu("&File")
        
        selectport_action = self.create_action("Select COM &Port...",
            shortcut="Ctrl+P", slot=self.on_select_port, tip="Select a COM port")
        self.start_action = self.create_action("&Start monitor",
            shortcut="Ctrl+M", slot=self.on_start, tip="Start the data monitor")
        self.stop_action = self.create_action("&Stop monitor",
            shortcut="Ctrl+T", slot=self.on_stop, tip="Stop the data monitor")
        exit_action = self.create_action("E&xit", slot=self.close, 
            shortcut="Ctrl+X", tip="Exit the application")
        
        self.start_action.setEnabled(False)
        self.stop_action.setEnabled(False)
        
        self.add_actions(self.file_menu, 
            (   selectport_action, self.start_action, self.stop_action,
                None, exit_action))
            
        self.help_menu = self.menuBar().addMenu("&Help")
        about_action = self.create_action("&About", 
            shortcut='F1', slot=self.on_about, 
            tip='About the monitor')
        
        self.add_actions(self.help_menu, (about_action,))

    def set_actions_enable_state(self):
        if self.portname.text() == '':
            start_enable = stop_enable = False
        else:
            start_enable = not self.monitor_active
            stop_enable = self.monitor_active
        
        self.start_action.setEnabled(start_enable)
        self.stop_action.setEnabled(stop_enable)

    def on_about(self):
        msg = __doc__
        QMessageBox.about(self, "About the demo", msg.strip())
    
    def on_select_port(self):
        ports = list(enumerate_serial_ports())
        if len(ports) == 0:
            QMessageBox.critical(self, 'No ports',
                'No serial ports found')
            return
        
        item, ok = QInputDialog.getItem(self, 'Select a port',
                    'Serial port:', ports, 0, False)
        
        if ok and not item.isEmpty():
            self.portname.setText(item)            
            self.set_actions_enable_state()

    def on_stop(self):
        """ Stop the monitor
        """
        if self.com_monitor is not None:
            self.com_monitor.join(0.01)
            self.com_monitor = None

        self.monitor_active = False
        self.timer.stop()
        self.set_actions_enable_state()
        
        self.status_text.setText('Monitor idle')
    
    def on_start(self):
        """ Start the monitor: com_monitor thread and the update
            timer
        """
        if self.com_monitor is not None or self.portname.text() == '':
            return
        
        self.data_q = queue.Queue()
        self.error_q = queue.Queue()
        self.com_monitor = ComMonitorThread(
            self.data_q,
            self.error_q,
            full_port_name(str(self.portname.text())),
            38400)
        self.com_monitor.start()
        
        com_error = get_item_from_queue(self.error_q)
        if com_error is not None:
            QMessageBox.critical(self, 'ComMonitorThread error',
                com_error)
            self.com_monitor = None

        self.monitor_active = True
        self.set_actions_enable_state()
        
        self.timer = QTimer()
        self.connect(self.timer, SIGNAL('timeout()'), self.on_timer)
        
        update_freq = self.updatespeed_knob.value()
        if update_freq > 0:
            self.timer.start(1000.0 / update_freq)
        
        self.status_text.setText('Monitor running')
    
    def on_timer(self):
        """ Executed periodically when the monitor update timer
            is fired.
        """
        self.read_serial_data()
        self.update_monitor()

    def on_knob_change(self):
        """ When the knob is rotated, it sets the update interval
            of the timer.
        """
        update_freq = self.updatespeed_knob.value()
        self.knob_l.setText('Update speed = %s (Hz)' % self.updatespeed_knob.value())

        if self.timer.isActive():
            update_freq = max(0.01, update_freq)
            self.timer.setInterval(1000.0 / update_freq)

    def update_monitor(self):
        """ Updates the state of the monitor window with new 
            data. The livefeed is used to find out whether new
            data was received since the last update. If not, 
            nothing is updated.
        """
        if self.livefeed.has_new_data:
            data = self.livefeed.read_data()
            
            self.temperature_samples.append(
                (data['timestamp'], data['temperature']))
            if len(self.temperature_samples) > 100:
                self.temperature_samples.pop(0)
            
            xdata = [s[0] for s in self.temperature_samples]
            ydata = [s[1] for s in self.temperature_samples]
            
            avg = sum(ydata) / float(len(ydata))
                
            self.plot.setAxisScale(Qwt.QwtPlot.xBottom, xdata[0], max(20, xdata[-1]))
            self.curve.setData(xdata, ydata)
            self.plot.replot()
            
            self.thermo.setValue(avg)
            
    def read_serial_data(self):
        """ Called periodically by the update timer to read data
            from the serial port.
        """
        qdata = list(get_all_from_queue(self.data_q))
        if len(qdata) > 0:
            data = dict(timestamp=qdata[-1][1], 
                        temperature=ord(qdata[-1][0]))
            self.livefeed.add_data(data)
    
    # The following two methods are utilities for simpler creation
    # and assignment of actions
    #
    def add_actions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def create_action(  self, text, slot=None, shortcut=None, 
                        icon=None, tip=None, checkable=False, 
                        signal="triggered()"):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(":/%s.png" % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot)
        if checkable:
            action.setCheckable(True)
        return action
예제 #14
0
class DataMonitor(QMainWindow):
    def __init__(self, parent=None):
        super(DataMonitor, self).__init__(parent)
       
        self.timer = QTimer() 
        self.com_monitor = None    
        
        self.main_frame = QWidget()
        main_layout = QVBoxLayout()
        self.main_frame.setLayout(main_layout)
        self.setCentralWidget(self.main_frame)

        
        hl = QHBoxLayout()
        sb = QPushButton('Iniciar')
        sb.setCheckable(True)
        self.sb = sb
        hl.addWidget(sb)

        self.connect(sb, SIGNAL('toggled(bool)'), self.onoff)

        self.portname = QLineEdit(DEFAULT_PORT)
        hl.addWidget(self.portname)

        main_layout.addLayout(hl)

        self.modules = QListWidget()
        self.modules.itemChanged.connect(self.mod_onoff)
        
        main_layout.addWidget(self.modules)
    
        self.fill_plugins()



    def fill_plugins(self):
        for p in plugins.all:
            it = QListWidgetItem(p.name)
            it.setCheckState(Qt.Unchecked)
            it.ob = p()
            self.modules.addItem(it)


    def onoff(self, checked):
        if checked:
            self.sb.setChecked(self.on_start())
        else:
            self.on_stop()


    def mod_onoff(self,item):
        if item.checkState():
            item.ob.start()
        else:
            item.ob.stop()

    def on_timer(self,*args):
        data = list(get_all_from_queue(self.data_q))
        if (len(data)==0):
            return

        for idx in xrange(self.modules.count()):
            plug = self.modules.item(idx)
            if plug.checkState():
                plug.ob.new_data(data)

    def on_stop(self):
        """ Stop the monitor
        """
        if self.com_monitor is not None:
            self.com_monitor.join(0.01)
            self.com_monitor = None

        self.monitor_active = False
        self.timer.stop()
        
    
    def on_start(self):
        """ Start the monitor: com_monitor thread and the update
            timer
        """


        if self.com_monitor is not None or self.portname.text() == '':
            return False
        
        self.data_q = Queue.Queue()
        self.error_q = Queue.Queue()
        self.com_monitor = ComMonitorThread(
            self.data_q,
            self.error_q,
            full_port_name(str(self.portname.text())),
            115200)
        self.com_monitor.start()
#        self.com_monitor.invert = True 
        com_error = get_item_from_queue(self.error_q)
        if com_error is not None:
            QMessageBox.critical(self, 'ComMonitorThread error',
                com_error)
            self.com_monitor = None

        self.monitor_active = True
        
        self.timer = QTimer()
        self.connect(self.timer, SIGNAL('timeout()'), self.on_timer)
        
        update_freq = 10
        if update_freq > 0:
            self.timer.start(1000.0 / update_freq)
        
        return True

    def closeEvent(self, event):
        for idx in xrange(self.modules.count()):
            plug = self.modules.item(idx)
            plug.ob.destroy()
        event.accept()