示例#1
0
    def ProcessMessage(self, msg):
        self.messageCount += 1

        id = msg.hdr.GetMessageID()

        # if we write CSV to multiple files, we'd probably look up a hash table for this message id,
        # and open it and write a header
        if (id in self.outputFiles):
            outputFile = self.outputFiles[id]
        else:
            # create a new file
            outputFile = open(
                self.outputName + "/" + msg.MsgName().replace("/", "_") +
                ".csv", 'w')

            # store a pointer to it, so we can find it next time (instead of creating it again)
            self.outputFiles[id] = outputFile

            # add table header, one column for each message field
            tableHeader = msgcsv.csvHeader(
                msg, nameColumn=False, timeColumn=True) + '\n'
            outputFile.write(tableHeader)

        try:
            # \todo Detect time rolling.  this only matters when we're processing a log file
            # with insufficient timestamp size, such that time rolls over from a large number
            # to a small one, during the log.
            thisTimestamp = msg.hdr.GetTime()
            if thisTimestamp < self._lastTimestamp:
                self._timestampOffset += 1

            self._lastTimestamp = thisTimestamp

            timeSizeInBits = int(
                round(
                    math.log(
                        int(
                            Messaging.findFieldInfo(msg.hdr.fields,
                                                    "Time").maxVal), 2)))
            timestamp = (
                self._timestampOffset << timeSizeInBits) + thisTimestamp
            if Messaging.findFieldInfo(msg.hdr.fields, "Time").units == "ms":
                timestamp = timestamp / 1000.0
            text = str(timestamp) + ", "
        except AttributeError:
            text = "unknown, "

        text += msgcsv.toCsv(msg, nameColumn=False, timeColumn=False)
        text += '\n'
        outputFile.write(text)

        # This is not efficient, but if we don't flush during socket processing
        # and the user hits Ctrl-C, we'll drop a bunch of data and end up with empty files.
        # So flush each message as it comes in.
        if self.connectionType != 'file':
            outputFile.flush()
示例#2
0
 def HandleButtonPress(self):
     # when a button is used to start a log, the text of that button changes to "Stop".
     # starting any other log will stop the current one (changing it's text back to normal)
     button = self.sender()
     if "logtag" in button.options:
         if button == self.activeLogButton:
             self.CloseLogFile()
             button.setText(button.label)
             self.activeLogButton = None
         else:
             if self.activeLogButton != None:
                 self.activeLogButton.setText(self.activeLogButton.label)
             self.CreateLogFile(button.options["logtag"][0])
             button.setText("Stop")
             self.activeLogButton = button
     if "send" in button.options:
         for opts in button.options['send']:
             msgname = opts.split("[")[0]
             fields = opts.split("[")[1].replace("]","").split(",")
             msgClass = Messaging.MsgClassFromName[msgname]
             msg = msgClass()
             for field in fields:
                 parts = field.split("=")
                 name = parts[0]
                 value = parts[1]
                 Messaging.set(msg, Messaging.findFieldInfo(msgClass.fields, name), value)
             self.SendMsg(msg)
示例#3
0
 def HandleButtonPress(self):
     # when a button is used to start a log, the text of that button changes to "Stop".
     # starting any other log will stop the current one (changing it's text back to normal)
     button = self.sender()
     if "logtag" in button.options:
         if button == self.activeLogButton:
             self.CloseLogFile()
             button.setText(button.label)
             self.activeLogButton = None
         else:
             if self.activeLogButton != None:
                 self.activeLogButton.setText(self.activeLogButton.label)
             self.CreateLogFile(button.options["logtag"][0])
             button.setText("Stop")
             self.activeLogButton = button
     if "send" in button.options:
         for opts in button.options['send']:
             msgname = opts.split("[")[0]
             fields = opts.split("[")[1].replace("]", "").split(",")
             msgClass = Messaging.MsgClassFromName[msgname]
             msg = msgClass()
             for field in fields:
                 parts = field.split("=")
                 name = parts[0]
                 value = parts[1]
                 Messaging.set(
                     msg, Messaging.findFieldInfo(msgClass.fields, name),
                     value)
             self.SendMsg(msg)
示例#4
0
    def handle_query(self, msg):
        msgquery = msg.GetQuery()
        msgAndFieldName = msgquery.split(",")[0]
        msgname = msgAndFieldName.split(".")[0]
        fieldname = msgAndFieldName.split(".")[1]
        tagQuery = msgquery.split(",")[1]
        if tagQuery != "":
            tagQuery += " AND "
        
        start = msg.GetStartTime()
        end = msg.GetEndTime()
        averagingPeriod = msg.GetAveragingPeriod()

        if averagingPeriod != 0:
            dbquery = 'SELECT "' + fieldname + '" FROM "' + msgname + '"'
        else:
            dbquery = 'SELECT MEAN("' + fieldname + '") FROM "' + msgname + '"'
        dbquery += " WHERE " + tagQuery + "time > " + FormattedTime(start)
        if end != 0:
            dbquery += " AND time < " + FormattedTime(end)
        else:
            end = datetime.datetime.now()
        if averagingPeriod != 0:
            # limit averaging period such that we don't get too many data points
            if avg / (end - start) > MAX_POINTS:
                avg = MAX_POINTS * (end - start)
            dbquery += " GROUP BY *,time("+FormattedTime(avg)+")"

        dbquery += " LIMIT " + str(MAX_POINTS)

        # send query to database, get result
        result = self.db.query(dbquery)

        # output results
        resultMsg = Messaging.Messages.Network.History.Result()
        resultMsg.SetCookie(self.cookie)
        resultCount = f(result)
        resultMsg.SetResultCount(resultCount)
        resultMsg.SetQuery(msgquery)
        self.msgClient.send_message(resultMsg)

        dataInfo = Messaging.findFieldInfo(Messaging.Messages.Network.History.Data, "Data")
        maxDataPerMsg = dataInfo.count
        resultNumber = 0
        for something in result:
            dataMsg = Messaging.Messages.Network.History.Data()
            dataMsg.SetCookie(self.cookie)
            dataMsg.SetResultNumber(resultNumber)
            dataRange = min(maxDataPerMsg, tilEndOfResults)
            for index in range(0, dataRange,2):
                dataMsg.SetData(time(something), index)
                dataMsg.SetData(value(something), index+1)
            # truncate message buffer to actual amount of data
            dataMsg.hdr.SetDataLength(dataInfo.offset + dataInfo.size * dataRange)
            self.msgClient.send_message(dataMsg)
            resultNumber += 1

        # increment cookie so the next query's results are easy to tell apart from out query results
        # especially useful if two clients query at almost the same time!
        self.cookie += 1
    def handle_query(self, msg):
        msgquery = msg.GetQuery()
        msgAndFieldName = msgquery.split(",")[0]
        msgname = msgAndFieldName.split(".")[0]
        fieldname = msgAndFieldName.split(".")[1]
        tagQuery = msgquery.split(",")[1]
        if tagQuery != "":
            tagQuery += " AND "
        
        start = msg.GetStartTime()
        end = msg.GetEndTime()
        averagingPeriod = msg.GetAveragingPeriod()

        if averagingPeriod != 0:
            dbquery = 'SELECT "' + fieldname + '" FROM "' + msgname + '"'
        else:
            dbquery = 'SELECT MEAN("' + fieldname + '") FROM "' + msgname + '"'
        dbquery += " WHERE " + tagQuery + "time > " + FormattedTime(start)
        if end != 0:
            dbquery += " AND time < " + FormattedTime(end)
        else:
            end = datetime.datetime.now()
        if averagingPeriod != 0:
            # limit averaging period such that we don't get too many data points
            if avg / (end - start) > MAX_POINTS:
                avg = MAX_POINTS * (end - start)
            dbquery += " GROUP BY *,time("+FormattedTime(avg)+")"

        dbquery += " LIMIT " + str(MAX_POINTS)

        # send query to database, get result
        result = self.db.query(dbquery)

        # output results
        resultMsg = Messaging.Messages.Network.History.Result()
        resultMsg.SetCookie(self.cookie)
        resultCount = f(result)
        resultMsg.SetResultCount(resultCount)
        resultMsg.SetQuery(msgquery)
        self.msgClient.send_message(resultMsg)

        dataInfo = Messaging.findFieldInfo(Messaging.Messages.Network.History.Data, "Data")
        maxDataPerMsg = dataInfo.count
        resultNumber = 0
        for something in result:
            dataMsg = Messaging.Messages.Network.History.Data()
            dataMsg.SetCookie(self.cookie)
            dataMsg.SetResultNumber(resultNumber)
            dataRange = min(maxDataPerMsg, tilEndOfResults)
            for index in range(0, dataRange,2):
                dataMsg.SetData(time(something), index)
                dataMsg.SetData(value(something), index+1)
            # truncate message buffer to actual amount of data
            dataMsg.hdr.SetDataLength(dataInfo.offset + dataInfo.size * dataRange)
            self.msgClient.send_message(dataMsg)
            resultNumber += 1

        # increment cookie so the next query's results are easy to tell apart from out query results
        # especially useful if two clients query at almost the same time!
        self.cookie += 1
示例#6
0
    def ProcessMessage(self, msg):
        self.messageCount += 1
        
        id = msg.hdr.GetMessageID()

        # if we write CSV to multiple files, we'd probably look up a hash table for this message id,
        # and open it and write a header
        if(id in self.outputFiles):
            outputFile = self.outputFiles[id]
        else:
            # create a new file
            outputFile = open(self.outputName + "/" + msg.MsgName().replace("/","_") + ".csv", 'w')

            # store a pointer to it, so we can find it next time (instead of creating it again)
            self.outputFiles[id] = outputFile
            
            # add table header, one column for each message field
            tableHeader = msgcsv.csvHeader(msg, nameColumn=False, timeColumn=True) + '\n'
            outputFile.write(tableHeader)
        
        try:
            # \todo Detect time rolling.  this only matters when we're processing a log file
            # with insufficient timestamp size, such that time rolls over from a large number
            # to a small one, during the log.
            thisTimestamp = msg.hdr.GetTime()
            if thisTimestamp < self._lastTimestamp:
                self._timestampOffset+=1

            self._lastTimestamp = thisTimestamp

            timeSizeInBits = int(round(math.log(int(Messaging.findFieldInfo(msg.hdr.fields, "Time").maxVal), 2)))
            timestamp = (self._timestampOffset << timeSizeInBits) + thisTimestamp
            if Messaging.findFieldInfo(msg.hdr.fields, "Time").units == "ms":
                timestamp = timestamp / 1000.0
            text = str(timestamp) + ", "
        except AttributeError:
            text = "unknown, "

        text += msgcsv.toCsv(msg, nameColumn=False, timeColumn=False)
        text += '\n'
        outputFile.write(text)

        # This is not efficient, but if we don't flush during socket processing
        # and the user hits Ctrl-C, we'll drop a bunch of data and end up with empty files.
        # So flush each message as it comes in.
        if self.connectionType !='file':
            outputFile.flush()
示例#7
0
    def store_message(self, msg):
        try:
            timeVal = msg.hdr.GetTime()
            timeInfo = Messaging.findFieldInfo(msg.hdr.fields, "Time")
            # if it's not big enough to be an absolute timestamp, give up on using it and just use current time
            if float(timeInfo.maxVal) <= 2**32:
                raise AttributeError
            if timeInfo.units == "ms":
                timeVal = timeVal / 1000.0
            timeVal = datetime.datetime.fromtimestamp(timeVal,
                                                      datetime.timezone.utc)
        except AttributeError:
            timeVal = datetime.datetime.now()

        dbJson = {
            "time": str(timeVal),
            "measurement": msg.MsgName(),
            'fields': {},
            'tags': {}
        }

        for fieldInfo in msg.hdr.fields:
            if len(fieldInfo.bitfieldInfo) == 0:
                if fieldInfo.idbits == 0 and fieldInfo.name != "Time" and fieldInfo.name != "DataLength":
                    dbJson['tags'][fieldInfo.name] = Messaging.get(
                        msg.hdr, fieldInfo)
            else:
                for bitInfo in fieldInfo.bitfieldInfo:
                    if bitInfo.idbits == 0 and bitInfo.name != "Time" and bitInfo.name != "DataLength":
                        dbJson['tags'][bitInfo.name] = Messaging.get(
                            msg.hdr, bitInfo)

        msgClass = type(msg)
        for fieldInfo in msgClass.fields:
            if fieldInfo.count == 1:
                if len(fieldInfo.bitfieldInfo) == 0:
                    dbJson['fields'][
                        fieldInfo.name] = InfluxDBConnection.GetDBValue(
                            msg, fieldInfo)
                else:
                    for bitInfo in fieldInfo.bitfieldInfo:
                        dbJson['fields'][
                            bitInfo.name] = InfluxDBConnection.GetDBValue(
                                msg, bitInfo)
            # leave out arrays until we figure out how to handle them
            #else:
            #    arrayList = []
            #    for i in range(0,fieldInfo.count):
            #        arrayList.append(InfluxDBConnection.GetDBValue(msg, fieldInfo, i))
            #    dbJson['fields'][fieldInfo.name] = arrayList

        #print("Create a retention policy")
        #retention_policy = 'awesome_policy'
        #client.create_retention_policy(retention_policy, '3d', 3, default=True)
        self.db.write_points([dbJson])  #, retention_policy=retention_policy)
    def __init__(self, hdr, portName):
        super(SerialConnection, self).__init__(None)

        self.hdr = hdr

        self.settings = QtCore.QSettings("MsgTools",
                                         "MessageServer/SerialPlugin")

        # button to open/close serial port
        self.openCloseButton = QtWidgets.QPushButton("button")
        self.openCloseButton.pressed.connect(self.openCloseSwitch)

        # button select new serial port
        self.selectPortButton = QtWidgets.QPushButton("Select Port")
        self.selectPortButton.pressed.connect(self.selectPort)

        self.statusLabel = QtWidgets.QLabel()
        self.subscriptions = {}
        self.subMask = 0
        self.subValue = 0
        self.isHardwareLink = True

        # if port not specified, default to last used port
        if not portName:
            portName = self.settings.value("portName", None)

        self.serialPort = QSerialPort(portName)
        self.serialPort.setBaudRate(QSerialPort.Baud115200)
        self.serialPort.setFlowControl(QSerialPort.NoFlowControl)
        self.serialPort.setParity(QSerialPort.NoParity)
        self.serialPort.setDataBits(QSerialPort.Data8)
        self.serialPort.setStopBits(QSerialPort.OneStop)
        self.rxBuffer = bytearray()
        self.gotHeader = 0
        self.rxMsgCount = 0

        self.serialPort.readyRead.connect(self.onReadyRead)
        self.name = "Serial " + self.serialPort.portName()

        self.hdrTranslator = HeaderTranslator(hdr, Messaging.hdr)

        self.serialStartSeqField = Messaging.findFieldInfo(
            hdr.fields, "StartSequence")
        if self.serialStartSeqField != None:
            self.startSequence = int(hdr.GetStartSequence.default)
            self.startSeqSize = int(hdr.GetStartSequence.size)
        try:
            self.hdrCrcRegion = int(hdr.GetHeaderChecksum.offset)
        except AttributeError:
            self.hdrCrcRegion = None
        self.tmpRxHdr = ctypes.create_string_buffer(0)
    def addLine(self, msgClass, fieldName):
        fieldName, fieldIndex = MsgPlot.split_fieldname(fieldName)
        fieldInfo = Messaging.findFieldInfo(msgClass.fields, fieldName)
        if fieldInfo == None:
            raise MsgPlot.PlotError("Invalid field %s for message %s" %
                                    (fieldName, msgClass.MsgName()))

        if fieldInfo.units == "ASCII":
            raise MsgPlot.PlotError("Cannot plot %s.%s, it is a string" %
                                    (msgClass.MsgName(), fieldName))

        # don't add if it's already there!
        for line in self.lines:
            if fieldInfo == line.fieldInfo and fieldIndex == line.fieldSubindex:
                name = fieldInfo.name
                if fieldInfo.count > 1:
                    name = "%s[%d]" % (name, fieldIndex)
                raise MsgPlot.PlotError("Line %s already on plot" % name)
        if msgClass != self.msgClass:
            raise MsgPlot.NewPlotError(
                "Message %s != %s, cannot add to same plot" %
                (msgClass.__name__, self.msgClass.__name__))
        if fieldInfo.units != self.units:
            raise MsgPlot.NewPlotError("Units %s != %s, not adding to plot" %
                                       (fieldInfo.units, self.units))

        if fieldIndex != None:
            self._addLine(msgClass, fieldInfo, fieldIndex)
        elif fieldInfo.count == 1:
            self._addLine(msgClass, fieldInfo, 0)
        else:
            dups = []
            for fieldIndex in range(0, fieldInfo.count):
                duplicate = False
                for line in self.lines:
                    if fieldInfo == line.fieldInfo and fieldIndex == line.fieldSubindex:
                        dups.append(fieldIndex)
                        duplicate = True
                        break
                if not duplicate:
                    self._addLine(msgClass, fieldInfo, fieldIndex)
            if len(dups) > 0:
                if len(dups) == 1:
                    s = ' ' + str(dups[0])
                elif len(dups) == fieldInfo.count:
                    s = 's %d-%d' % (0, fieldInfo.count)
                else:
                    s = 's '
                    for d in dups:
                        s += '%s,' % d
                raise MsgPlot.PlotError("Line%s already on plot" % s)
示例#10
0
    def store_message(self, msg):
        try:
            timeVal = msg.hdr.GetTime()
            timeInfo = Messaging.findFieldInfo(msg.hdr.fields, "Time")
            # if it's not big enough to be an absolute timestamp, give up on using it and just use current time
            if float(timeInfo.maxVal) <= 2**32:
                raise AttributeError
            if timeInfo.units == "ms":
                timeVal = timeVal / 1000.0
            timeVal = datetime.datetime.fromtimestamp(timeVal, datetime.timezone.utc)
        except AttributeError:
            timeVal = datetime.datetime.now()

        dbJson = {
                "time": str(timeVal),
                "measurement": msg.MsgName(),
                'fields':  {},
                'tags': {}
            }

        for fieldInfo in msg.hdr.fields:
            if len(fieldInfo.bitfieldInfo) == 0:
                if fieldInfo.idbits == 0 and fieldInfo.name != "Time" and fieldInfo.name != "DataLength":
                    dbJson['tags'][fieldInfo.name] = Messaging.get(msg.hdr, fieldInfo)
            else:
                for bitInfo in fieldInfo.bitfieldInfo:
                    if bitInfo.idbits == 0 and bitInfo.name != "Time" and bitInfo.name != "DataLength":
                        dbJson['tags'][bitInfo.name] = Messaging.get(msg.hdr, bitInfo)
        
        msgClass = type(msg)
        for fieldInfo in msgClass.fields:
            if fieldInfo.count == 1:
                if len(fieldInfo.bitfieldInfo) == 0:
                    dbJson['fields'][fieldInfo.name] = InfluxDBConnection.GetDBValue(msg, fieldInfo)
                else:
                    for bitInfo in fieldInfo.bitfieldInfo:
                        dbJson['fields'][bitInfo.name] = InfluxDBConnection.GetDBValue(msg, bitInfo)
            # leave out arrays until we figure out how to handle them
            #else:
            #    arrayList = []
            #    for i in range(0,fieldInfo.count):
            #        arrayList.append(InfluxDBConnection.GetDBValue(msg, fieldInfo, i))
            #    dbJson['fields'][fieldInfo.name] = arrayList

        #print("Create a retention policy")
        #retention_policy = 'awesome_policy'
        #client.create_retention_policy(retention_policy, '3d', 3, default=True)
        self.db.write_points([dbJson]) #, retention_policy=retention_policy)
    def addData(self, msg):
        # TODO what to do for things that can't be numerically expressed?  just ascii strings, i guess?
        for line in self.lines:
            try:
                newDataPoint = Messaging.getFloat(msg, line.fieldInfo,
                                                  line.fieldSubindex)
            except ValueError:
                print("ERROR! Plot of %s.%s cannot accept value %s" %
                      (self.msgClass.MsgName(), line.fieldInfo.name,
                       Messaging.get(msg, line.fieldInfo, line.fieldSubindex)))
                continue
            try:
                timestamp = msg.hdr.GetTime()
                if Messaging.findFieldInfo(msg.hdr.fields,
                                           "Time").units == "ms":
                    timestamp = timestamp / 1000.0
                newTime = float(elapsedSeconds(timestamp))
                if newTime != 0:
                    self.useHeaderTime = 1
                if not self.useHeaderTime:
                    newTime = elapsedSeconds(datetime.now().timestamp())
            except AttributeError:
                # if header has no time, fallback to PC time.
                newTime = elapsedSeconds(datetime.now().timestamp())

            # add data in the array until MAX_LENGTH is reached, then drop data off start of array
            # such that plot appears to scroll.  The array size is limited to MAX_LENGTH.
            if len(line.dataArray) >= MsgPlot.MAX_LENGTH:
                line.dataArray[:-1] = line.dataArray[
                    1:]  # shift data in the array one sample left
                line.dataArray[-1] = newDataPoint
                line.timeArray[:-1] = line.timeArray[
                    1:]  # shift data in the array one sample left
                line.timeArray[-1] = newTime
            else:
                line.dataArray.append(newDataPoint)
                line.timeArray.append(newTime)

            if not self.pause:
                timeArray = line.timeArray
                dataArray = line.dataArray
                count = self.timeSlider.value()
                if len(line.dataArray) > count:
                    timeArray = timeArray[-count:]
                    dataArray = dataArray[-count:]
                line.curve.setData(timeArray, dataArray)
                line.curve.setPos(line.ptr1, 0)
示例#12
0
 def addLine(self, msgClass, fieldName):
     fieldName, fieldIndex = MsgPlot.split_fieldname(fieldName)
     fieldInfo = Messaging.findFieldInfo(msgClass.fields, fieldName)
     if fieldInfo == None:
         raise MsgPlot.PlotError("Invalid field %s for message %s" % (fieldName, msgClass.MsgName()))
     
     if fieldInfo.units == "ASCII":
         raise MsgPlot.PlotError("Cannot plot %s.%s, it is a string" % (msgClass.MsgName(), fieldName))
     
     # don't add if it's already there!
     for line in self.lines:
         if fieldInfo == line.fieldInfo and fieldIndex == line.fieldSubindex:
             name = fieldInfo.name
             if fieldInfo.count > 1:
                 name = "%s[%d]" % (name, fieldIndex)
             raise MsgPlot.PlotError("Line %s already on plot" % name)
     if msgClass != self.msgClass:
         raise MsgPlot.NewPlotError("Message %s != %s, cannot add to same plot" % (msgClass.__name__, self.msgClass.__name__))
     if fieldInfo.units != self.units:
         raise MsgPlot.NewPlotError("Units %s != %s, not adding to plot" % (fieldInfo.units, self.units))
     
     if fieldIndex != None:
         self._addLine(msgClass, fieldInfo, fieldIndex)
     elif fieldInfo.count == 1:
         self._addLine(msgClass, fieldInfo, 0)
     else:
         dups = []
         for fieldIndex in range(0, fieldInfo.count):
             duplicate = False
             for line in self.lines:
                 if fieldInfo == line.fieldInfo and fieldIndex == line.fieldSubindex:
                     dups.append(fieldIndex)
                     duplicate = True
                     break
             if not duplicate:
                 self._addLine(msgClass, fieldInfo, fieldIndex)
         if len(dups) > 0:
             if len(dups) == 1:
                 s = ' '+str(dups[0])
             elif len(dups) == fieldInfo.count:
                 s = 's %d-%d' % (0, fieldInfo.count)
             else:
                 s = 's '
                 for d in dups:
                     s += '%s,' % d
             raise MsgPlot.PlotError("Line%s already on plot" % s)
示例#13
0
    def __init__(self, argv, parent=None):
        msgtools.lib.gui.Gui.__init__(self, "Message Plot 0.1", argv, [],
                                      parent)

        vbox = QVBoxLayout()
        centralWidget = QWidget()
        centralWidget.setLayout(vbox)
        self.setCentralWidget(centralWidget)
        self.msgPlots = {}
        self.RxMsg.connect(self.ProcessMessage)

        if len(sys.argv) < 1:
            sys.stderr.write(
                'Usage: ' + sys.argv[0] +
                ' msg1=field1[,field2] [msg2=field1,field2,field3]\n')
            sys.exit(1)

        for arg in argv[1:]:
            argComponentList = arg.split("=")
            msgName = argComponentList[0]
            fieldNameList = argComponentList[1]

            self.msgClass = Messaging.MsgClassFromName[msgName]

            fieldNames = fieldNameList.split(",")
            firstField = 1
            for fieldName in fieldNames:
                fieldInfo = Messaging.findFieldInfo(self.msgClass.fields,
                                                    fieldName)
                if fieldInfo != None:
                    if firstField:
                        plot = MsgPlot(self.msgClass, fieldInfo, 0)
                        vbox.addWidget(plot.plotWidget)
                        firstField = 0
                        plotListForID = []
                        if self.msgClass.ID in self.msgPlots:
                            plotListForID = self.msgPlots[self.msgClass.ID]
                        else:
                            self.msgPlots[self.msgClass.ID] = plotListForID
                        plotListForID.append(plot)
                    else:
                        plot.addPlot(self.msgClass, fieldInfo, 0)
    def __init__(self, msgClass, fieldName):
        super(QWidget, self).__init__()

        newFieldName, fieldIndex = MsgPlot.split_fieldname(fieldName)
        fieldInfo = Messaging.findFieldInfo(msgClass.fields, newFieldName)
        if fieldInfo == None:
            raise MsgPlot.PlotError("Invalid field %s for message %s" %
                                    (newFieldName, msgClass.MsgName()))

        layout = QVBoxLayout()
        self.setLayout(layout)
        self.msgClass = msgClass
        self.pause = 0
        self.lineCount = 0
        self.units = fieldInfo.units
        self.lines = []

        yAxisLabel = fieldInfo.units
        xAxisLabel = "time (s)"
        self.plotWidget = pg.PlotWidget(labels={
            'left': yAxisLabel,
            'bottom': xAxisLabel
        })
        layout.addWidget(self.plotWidget)
        self.plotWidget.addLegend()
        self.addLine(msgClass, fieldName)

        # set up click handler to pause graph
        self.plotWidget.scene().sigMouseClicked.connect(self.mouseClicked)

        # add slider bar to control time scale
        self.timeSlider = QSlider(Qt.Horizontal)
        self.timeSlider.setMinimum(50)
        self.timeSlider.setMaximum(MsgPlot.MAX_LENGTH)
        self.timeSlider.setSingleStep(10)
        self.timeSlider.setPageStep(50)
        layout.addWidget(self.timeSlider)

        self.plotWidget.dragEnterEvent = self.dragEnterEvent
        self.plotWidget.dragMoveEvent = self.dragMoveEvent
        self.plotWidget.dropEvent = self.dropEvent
        self.plotWidget.setAcceptDrops(1)
示例#15
0
    def __init__(self, hdr, portName):
        super(SerialConnection, self).__init__("Serial", portName)

        self.hdr = hdr

        self.rxBuffer = bytearray()
        self.gotHeader = 0

        self.hdrTranslator = HeaderTranslator(hdr, Messaging.hdr)

        self.serialStartSeqField = Messaging.findFieldInfo(
            hdr.fields, "StartSequence")
        if self.serialStartSeqField != None:
            self.startSequence = int(hdr.GetStartSequence.default)
            self.startSeqSize = int(hdr.GetStartSequence.size)
        try:
            self.hdrCrcRegion = int(hdr.GetHeaderChecksum.offset)
        except AttributeError:
            self.hdrCrcRegion = None
        self.tmpRxHdr = ctypes.create_string_buffer(0)
示例#16
0
    def addData(self, msg):
        # TODO what to do for things that can't be numerically expressed?  just ascii strings, i guess?
        for line in self.lines:
            try:
                newDataPoint = Messaging.getFloat(msg, line.fieldInfo, line.fieldSubindex)
            except ValueError:
                print("ERROR! Plot of %s.%s cannot accept value %s" % (
                    self.msgClass.MsgName(),
                    line.fieldInfo.name,
                    Messaging.get(msg, line.fieldInfo, line.fieldSubindex)))
                continue
            try:
                timestamp = msg.hdr.GetTime()
                if Messaging.findFieldInfo(msg.hdr.fields, "Time").units == "ms":
                    timestamp = timestamp / 1000.0
                newTime = float(elapsedSeconds(timestamp))
                if newTime != 0:
                    self.useHeaderTime = 1
                if not self.useHeaderTime:
                    newTime = elapsedSeconds(datetime.now().timestamp())
            except AttributeError:
                # if header has no time, fallback to PC time.
                newTime = elapsedSeconds(datetime.now().timestamp())
            
            # add data in the array until MAX_LENGTH is reached, then drop data off start of array
            # such that plot appears to scroll.  The array size is limited to MAX_LENGTH.
            if len(line.dataArray) >= MsgPlot.MAX_LENGTH:
                line.dataArray[:-1] = line.dataArray[1:]  # shift data in the array one sample left
                line.dataArray[-1] = newDataPoint
                line.timeArray[:-1] = line.timeArray[1:]  # shift data in the array one sample left
                line.timeArray[-1] = newTime
            else:
                line.dataArray.append(newDataPoint)
                line.timeArray.append(newTime)

            if not self.pause:
                self.refreshLine(line)
示例#17
0
    def __init__(self, msgClass, fieldName, runButton = None, clearButton = None, timeSlider = None, displayControls=True):
        super(QWidget,self).__init__()
        
        newFieldName, fieldIndex = MsgPlot.split_fieldname(fieldName)
        fieldInfo = Messaging.findFieldInfo(msgClass.fields, newFieldName)
        if fieldInfo == None:
            raise MsgPlot.PlotError("Invalid field %s for message %s" % (newFieldName, msgClass.MsgName()))

        layout = QVBoxLayout()
        self.setLayout(layout)
        self.msgClass = msgClass
        self.pause = 0
        self.lineCount = 0
        self.units = fieldInfo.units
        self.lines = []

        yAxisLabel = fieldInfo.units
        xAxisLabel = "time (s)"
        self.plotWidget = pg.PlotWidget(labels={'left':yAxisLabel,'bottom':xAxisLabel})
        layout.addWidget(self.plotWidget)
        self.plotWidget.addLegend()
        self.addLine(msgClass, fieldName)

        # set up click handler to pause graph
        self.plotWidget.scene().sigMouseClicked.connect(self.mouseClicked)
        
        hLayout = QHBoxLayout()
        layout.addLayout(hLayout)
        
        # add a Pause/Run button
        if runButton == None:
            self.runButton = QPushButton("Pause")
        else:
            self.runButton = runButton
        self.runButton.clicked.connect(self.pauseOrRun)
        if displayControls:
            hLayout.addWidget(self.runButton)

        # add a 'Clear' button
        if clearButton == None:
            self.clearButton = QPushButton("Clear")
        else:
            self.clearButton = clearButton
        self.clearButton.clicked.connect(self.clearData)
        if displayControls:
            hLayout.addWidget(self.clearButton)

        # add slider bar to control time scale
        if timeSlider == None:
            self.timeSlider = QSlider(Qt.Horizontal)
            self.timeSlider.setMinimum(50)
            self.timeSlider.setMaximum(MsgPlot.MAX_LENGTH)
            self.timeSlider.setSingleStep(10)
            self.timeSlider.setPageStep(50)
        else:
            self.timeSlider = timeSlider
        self.timeSlider.valueChanged.connect(self.timeScaleChanged)
        if displayControls:
            hLayout.addWidget(QLabel("Time Scale"))
            hLayout.addWidget(self.timeSlider)
        
        self.plotWidget.dragEnterEvent = self.dragEnterEvent
        self.plotWidget.dragMoveEvent = self.dragMoveEvent
        self.plotWidget.dropEvent = self.dropEvent
        self.plotWidget.setAcceptDrops(1)
    def __init__(self, parent=None):

        parser = argparse.ArgumentParser(description=DESCRIPTION)
        parser.add_argument('msgs', nargs='*', help='''
            One or more messages that you wish to send.  This entire list is sent each 
            time the message period is up.  Network messages are ignored.  By default we 
            send all known messages.''')
        parser = msgtools.lib.gui.Gui.addBaseArguments(parser)
        args = parser.parse_args()

        msgtools.lib.gui.Gui.__init__(self, "Noise Maker 0.1", args, parent)
        
        self.timeInfo = Messaging.findFieldInfo(Messaging.hdr.fields, "Time")
        
        # event-based way of getting messages
        self.RxMsg.connect(self.ProcessMessage)
        
        self.currentTime = 0
        
        self.msgTimer = QtCore.QTimer(self)
        self.msgTimer.setInterval(50)
        self.msgTimer.timeout.connect(self.msgTimeout)

        vbox = QtWidgets.QVBoxLayout()
        w = QtWidgets.QWidget(self)
        w.setLayout(vbox)
        self.setCentralWidget(w)

        self.timeSlider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        self.timeSlider.setMinimum(1)
        self.timeSlider.setMaximum(5)
        vbox.addWidget(self.timeSlider)

        t = int(self.settings.value('time_slider', 10))
        self.timeSlider.setValue(t)
        self.timeSlider.valueChanged.emit(t)

        self.startStop = QtWidgets.QPushButton(self)
        self.startStop.setText('Stop')
        self.startStop.clicked.connect(self.startStopFn)
        vbox.addWidget(self.startStop)
        
        # check if user specified which messages we should output
        msgs = args.msgs
        
        # find a few messages to send at specified rates
        period = 0.1
        self.fieldNumber = 0
        self.msgPeriod = {}
        self.msgTxTime = {}
        for msgName in Messaging.MsgClassFromName:
            if not msgName.startswith("Network"):
                if len(msgs) > 0 and msgName not in msgs:
                    continue
                print("found message " + msgName)
                self.msgPeriod[msgName] = period
                period = period + 0.050
                if period > 0.5:
                    period = 0.1
                self.msgTxTime[msgName] = 0
       
        self.msgTimer.start()