def GetAverage(self, nStart, nEnd):
        """Return a SweepData object with average data 

        Parameters:
            nStart -- Start frequency for the average calculation  
            nEnd   -- End frequency for the average calculation
        Returns:
            RFESweepData object with average data, None otherwise
		"""
        #string sDebugText = ""

        if (nStart > self.m_nUpperBound or nEnd > self.m_nUpperBound
                or nStart > nEnd):
            return None

        try:
            objReturn = RFESweepData(self.m_arrData[nEnd].StartFrequencyMHZ,
                                     self.m_arrData[nEnd].StepFrequencyMHZ,
                                     self.m_arrData[nEnd].TotalSteps)

            for nSweepInd in objReturn.TotalSteps:
                #sDebugText += "[" + nSweepInd + "]:"
                fSweepValue = 0.0

                nIterationInd = nStart
                while (nIterationInd <= nEnd):
                    if (nSweepInd == 0):
                        #check all the sweeps use the same configuration, but
                        #only in first loop to reduce overhead
                        if (not self.m_arrData[nIterationInd].
                                IsSameConfiguration(objReturn)):
                            return None

                    fSweepValue += self.m_arrData[
                        nIterationInd].GetAmplitudeDBM(nSweepInd, None, False)
                    #sDebugText +=
                    #str(self.m_arrData[nIterationInd].GetAmplitudeDBM(nSweepInd))
                    #+ ","
                    nIterationInd += 1

                fSweepValue = fSweepValue / (nEnd - nStart + 1)
                #sDebugText += "(" + str(fSweepValue) + ")"
                objReturn.SetAmplitudeDBM(nSweepInd, fSweepValue)

        except Exception as obEx:
            objReturn = None
            print("Error in RFESweedDataCollection - GetAverage(): " +
                  str(obEx))

        return objReturn
Пример #2
0
    def Add(self, SweepData):
        """This function add a single sweep data in the collection 

        Parameters:
            SweepData -- A single sweep data
        Returns:
            Boolean True it sweep data is added, False otherwise
        """
        try:
            if (self.IsFull()):
                return False

            if (not self.m_MaxHoldData):
                self.m_MaxHoldData = RFESweepData(SweepData.StartFrequencyMHZ,
                                                  SweepData.StepFrequencyMHZ,
                                                  SweepData.TotalSteps)
            if (self.m_nUpperBound >= (len(self.m_arrData) - 1)):
                if (self.m_bAutogrow):
                    self.ResizeCollection(10 * 1000)  #add 10K samples more
                else:
                    #move all items one position down, lose the older one at position 0
                    self.m_nUpperBound = len(self.m_arrData) - 2
                    self.m_arrData[0] = None
                    for nInd in range(self.m_nUpperBound):
                        self.m_arrData[nInd] = self.m_arrData[nInd + 1]

            self.m_nUpperBound += 1
            self.m_arrData[self.m_nUpperBound] = SweepData

            nInd = 0
            while nInd < SweepData.TotalSteps:
                if (SweepData.GetAmplitudeDBM(nInd, None, False) >
                        self.m_MaxHoldData.GetAmplitudeDBM(nInd, None, False)):
                    self.m_MaxHoldData.SetAmplitudeDBM(
                        nInd, SweepData.GetAmplitudeDBM(nInd, None, False))
                nInd += 1

        except Exception as obEx:
            print("Error in RFESweepDataCollection - Add(): " + str(obEx))
            return False

        return True
class RFESweepDataCollection:
    """ Allocates up to nCollectionSize elements to start with the container.
	"""
    def __init__(self, nCollectionSize, bAutogrow):
        self.m_arrData = []  #Collection of available spectrum data items
        self.m_MaxHoldData = None  #Single data set, defined for the whole collection and updated with Add, to
        #keep the Max Hold values
        self.m_nUpperBound = -1  #Max value for index with available data
        self.m_nInitialCollectionSize = 0

        if (nCollectionSize > RFE_Common.CONST_MAX_ELEMENTS):
            nCollectionSize = RFE_Common.CONST_MAX_ELEMENTS

        self.m_bAutogrow = bAutogrow  #true if the array bounds may grow up to _MAX_ELEMENTS, otherwise will
        #be limited to initial collection size

        self.m_nInitialCollectionSize = nCollectionSize

        self.CleanAll()

    @property
    def MaxHoldData(self):
        """Single data set, defined for the whole collection and updated with Add, to keep the Max Hold values 
		"""
        return self.m_MaxHoldData

    @property
    def Count(self):
        """ Returns the total of elements with actual data allocated.
		"""
        return int(self.m_nUpperBound + 1)

    @property
    def UpperBound(self):
        """ Returns the highest valid index of elements with actual data allocated.
		"""
        return self.m_nUpperBound

    @classmethod
    def FileHeaderVersioned_001(cls):
        """File format constant - 001

        Returns:
            String 001 File header version
		"""
        return "RFExplorer PC Client - Format v001"

    @classmethod
    def FileHeaderVersioned(cls):
        """File format constant indicates the latest known and supported file format 

        Returns:
            String File header version
		"""
        return "RFExplorer PC Client - Format v" + "{:03d}".format(
            RFE_Common.CONST_FILE_VERSION)

    def GetData(self, nIndex):
        """ Return the data pointed by the zero-starting index
        
        Parameters:
            nIndex -- Index to find specific data inside the data array
        Returns:
		    RFESweepData None if no data is available with this index
		"""
        if (nIndex <= self.m_nUpperBound):
            return self.m_arrData[nIndex]
        else:
            return None

    def IsFull(self):
        """ True when the absolute maximum of allowed elements in the container is allocated
                
        Returns:
		    Boolean True when the absolute maximum of allowed elements in the container is allocated, False otherwise
		"""
        return (self.m_nUpperBound >= RFE_Common.CONST_MAX_ELEMENTS)

    def Add(self, SweepData):
        """This function add a single sweep data in the collection 

        Parameters:
            SweepData -- A single sweep data
        Returns:
            Boolean True it sweep data is added, False otherwise
		"""
        try:
            if (self.IsFull()):
                return False

            if (not self.m_MaxHoldData):
                self.m_MaxHoldData = RFESweepData(SweepData.StartFrequencyMHZ,
                                                  SweepData.StepFrequencyMHZ,
                                                  SweepData.TotalSteps)
            if (self.m_nUpperBound >= (len(self.m_arrData) - 1)):
                if (self.m_bAutogrow):
                    self.ResizeCollection(10 * 1000)  #add 10K samples more
                else:
                    #move all items one position down, lose the older one at position 0
                    self.m_nUpperBound = len(self.m_arrData) - 2
                    self.m_arrData[0] = None
                    for nInd in self.m_nUpperBound:
                        self.m_arrData[nInd] = self.m_arrData[nInd + 1]

            self.m_nUpperBound += 1
            self.m_arrData[self.m_nUpperBound] = SweepData

            nInd = 0
            while nInd < SweepData.TotalSteps:
                if (SweepData.GetAmplitudeDBM(nInd, None, False) >
                        self.m_MaxHoldData.GetAmplitudeDBM(nInd, None, False)):
                    self.m_MaxHoldData.SetAmplitudeDBM(
                        nInd, SweepData.GetAmplitudeDBM(nInd, None, False))
                nInd += 1
        except Exception as obEx:
            print("Error in RFESweepDataCollection - Add(): " + str(obEx))
            return False

        return True

    def CleanAll(self):
        """Initialize internal data
		"""
        self.m_arrData = [RFESweepData] * self.m_nInitialCollectionSize
        self.m_MaxHoldData = None
        self.m_nUpperBound = -1

    def Dump(self):
        """Dump a CSV string line with sweep data collection

        Returns:
            String All sweep data collection
		"""
        sDump = ""
        for nIndex in range(self.Count):
            objSweep = self.m_arrData[nIndex]
            if (sDump != ""):
                sDump += '\n'
            if (objSweep):
                sDump += objSweep.Dump()
            else:
                sDump += "Sweep {null}"
        return sDump

    def GetMedianAverage(self, nStart, nEnd):
        """Return a SweepData object with median average data 

        Parameters:
            nStart -- Start frequency for the median average calculation  
            nEnd   -- End frequency for the median average calculation
        Returns:
            RFESweepData object with median average data, None otherwise
		"""
        #string sDebugText = ""
        if (nStart > self.m_nUpperBound or nEnd > self.m_nUpperBound
                or nStart > nEnd):
            return None

        nTotalIterations = nEnd - nStart + 1
        try:
            objReturn = RFESweepData(self.m_arrData[nEnd].StartFrequencyMHZ,
                                     self.m_arrData[nEnd].StepFrequencyMHZ,
                                     self.m_arrData[nEnd].TotalSteps)

            for nSweepInd in objReturn.TotalSteps:
                #sDebugText += "[" + nSweepInd + "]:"
                fSweepValue = 0.0
                arrSweepValues = [0.0] * nTotalIterations

                nIterationInd = nStart
                while (nIterationInd <= nEnd):
                    if (nSweepInd == 0):
                        #check all the sweeps use the same configuration, but
                        #only in first loop to reduce overhead
                        if (not self.m_arrData[nIterationInd].
                                IsSameConfiguration(objReturn)):
                            return None
                    arrSweepValues[nIterationInd - nStart] = self.m_arrData[
                        nIterationInd].GetAmplitudeDBM(nSweepInd, None, False)
                    #sDebugText += str(self.m_arrData[nIterationInd].GetAmplitudeDBM(nSweepInd)) + ","
                    nIterationInd += 1

                arrSweepValues.sort()
                fSweepValue = arrSweepValues[nTotalIterations / 2]
                #sDebugText += "(" + str(fSweepValue) + ")"
                objReturn.SetAmplitudeDBM(nSweepInd, fSweepValue)
        except Exception as obEx:
            print("Error in RFESweedDataCollection - GetMedianAverage(): " +
                  str(obEx))
            objReturn = None

        return objReturn

    def GetAverage(self, nStart, nEnd):
        """Return a SweepData object with average data 

        Parameters:
            nStart -- Start frequency for the average calculation  
            nEnd   -- End frequency for the average calculation
        Returns:
            RFESweepData object with average data, None otherwise
		"""
        #string sDebugText = ""

        if (nStart > self.m_nUpperBound or nEnd > self.m_nUpperBound
                or nStart > nEnd):
            return None

        try:
            objReturn = RFESweepData(self.m_arrData[nEnd].StartFrequencyMHZ,
                                     self.m_arrData[nEnd].StepFrequencyMHZ,
                                     self.m_arrData[nEnd].TotalSteps)

            for nSweepInd in objReturn.TotalSteps:
                #sDebugText += "[" + nSweepInd + "]:"
                fSweepValue = 0.0

                nIterationInd = nStart
                while (nIterationInd <= nEnd):
                    if (nSweepInd == 0):
                        #check all the sweeps use the same configuration, but
                        #only in first loop to reduce overhead
                        if (not self.m_arrData[nIterationInd].
                                IsSameConfiguration(objReturn)):
                            return None

                    fSweepValue += self.m_arrData[
                        nIterationInd].GetAmplitudeDBM(nSweepInd, None, False)
                    #sDebugText +=
                    #str(self.m_arrData[nIterationInd].GetAmplitudeDBM(nSweepInd))
                    #+ ","
                    nIterationInd += 1

                fSweepValue = fSweepValue / (nEnd - nStart + 1)
                #sDebugText += "(" + str(fSweepValue) + ")"
                objReturn.SetAmplitudeDBM(nSweepInd, fSweepValue)

        except Exception as obEx:
            objReturn = None
            print("Error in RFESweedDataCollection - GetAverage(): " +
                  str(obEx))

        return objReturn

    def SaveFileCSV(self, sFilename, cCSVDelimiter, AmplitudeCorrection):
        """Will write large, complex, multi-sweep CSV file. No save anything, if there are no data

        Parameters:
            sFilename           -- Full path filename
            cCSVDelimiter       -- Comma delimiter to use
            AmplitudeCorrection -- Optional parameter, can be None. If different than None, use the amplitude correction table
		"""
        if (self.m_nUpperBound <= 0):
            return

        objFirst = self.m_arrData[0]
        try:
            with open(sFilename, 'w') as objWriter:
                objWriter.write("RF Explorer CSV data file: " + self.FileHeaderVersioned() + '\n' + \
                    "Start Frequency: " + str(objFirst.StartFrequencyMHZ) + "MHZ" + '\n' + \
                    "Step Frequency: " + str(objFirst.StepFrequencyMHZ * 1000) + "KHZ" + '\n' + \
                    "Total data entries: " + str(self.m_nUpperBound) + '\n' + \
                    "Steps per entry: " + str(objFirst.TotalSteps)+ '\n')

                sHeader = "Sweep" + cCSVDelimiter + "Date" + cCSVDelimiter + "Time" + cCSVDelimiter + "Milliseconds"

                for nStep in range(objFirst.TotalSteps):
                    dFrequency = objFirst.StartFrequencyMHZ + nStep * (
                        objFirst.StepFrequencyMHZ)
                    sHeader += cCSVDelimiter + "{:08.3f}".format(dFrequency)

                objWriter.write(sHeader + '\n')

                for nSweepInd in range(self.m_nUpperBound):
                    objWriter.write(str(nSweepInd) + cCSVDelimiter)

                    objWriter.write(str(self.m_arrData[nSweepInd].CaptureTime.date()) + cCSVDelimiter + \
                        str(self.m_arrData[nSweepInd].CaptureTime.time())[:-7] + cCSVDelimiter + \
                        '.' +'{:03}'.format(int(str(getattr(self.m_arrData[nSweepInd].CaptureTime.time(), 'microsecond'))[:-3])) + cCSVDelimiter)

                    if (not self.m_arrData[nSweepInd].IsSameConfiguration(
                            objFirst)):
                        break

                    for nStep in range(objFirst.TotalSteps):
                        objWriter.write(
                            str(self.m_arrData[nSweepInd].GetAmplitudeDBM(
                                nStep, AmplitudeCorrection,
                                (AmplitudeCorrection != None))))
                        if (nStep != (objFirst.TotalSteps - 1)):
                            objWriter.write(cCSVDelimiter)

                    objWriter.write('\n')

        except Exception as objEx:
            print("Error in RFESweepDataCollection - SaveFileCSV(): " +
                  str(objEx))

    def GetTopBottomDataRange(self, dTopRangeDBM, dBottomRangeDBM,
                              AmplitudeCorrection):
        """Return estimated Top and Bottom level using data collection, no return anything if sweep data collection is empty

        Parameters:
            dTopRangeDBM        -- Bottom level in dBm
            dBottomRangeDBM     -- Top level in dBm
            AmplitudeCorrection -- Optional parameter, can be None. If different than None, use the amplitude correction table
        Returns:
            Float Bottom level in dBm
            Float Top level in dBm
		"""
        dTopRangeDBM = RFE_Common.CONST_MIN_AMPLITUDE_DBM
        dBottomRangeDBM = RFE_Common.CONST_MAX_AMPLITUDE_DBM

        if (self.m_nUpperBound <= 0):
            return

        for nIndSample in self.m_nUpperBound:
            for nIndStep in self.m_arrData[0].TotalSteps:
                dValueDBM = self.m_arrData[nIndSample].GetAmplitudeDBM(
                    nIndStep, AmplitudeCorrection,
                    (AmplitudeCorrection != None))
                if (dTopRangeDBM < dValueDBM):
                    dTopRangeDBM = dValueDBM
                if (dBottomRangeDBM > dValueDBM):
                    dBottomRangeDBM = dValueDBM

        return dTopRangeDBM, dBottomRangeDBM

    def ResizeCollection(self, nSizeToAdd):
        """Change data collection size 

        Parameters:
            nSizeToAdd -- Number of sample to add to the sweep data collection
		"""
        self.m_arrData += [RFESweepData] * nSizeToAdd
    def ReceiveThreadfunc(self):
        """Where all data coming from the device are processed and queued
		"""
        nBytes = 0
        nTotalSpectrumDataDumps = 0
        while self.m_objRFECommunicator.RunReceiveThread:
            strReceived = ""
            while (self.m_objRFECommunicator.PortConnected
                   and self.m_objRFECommunicator.RunReceiveThread):
                sNewText = ""
                self.m_hSerialPortLock.acquire()
                try:
                    if (self.m_objSerialPort.is_open):
                        #print("port open")
                        nBytes = self.m_objSerialPort.in_waiting
                        if (nBytes > 0):
                            sNewText = self.m_objSerialPort.read(
                                nBytes).decode("latin_1")
                except Exception as obEx:
                    print("Serial port Exception: " + str(obEx))
                finally:
                    self.m_hSerialPortLock.release()
                if (len(sNewText) > 0):
                    if (self.m_objRFECommunicator.VerboseLevel > 5):
                        print(sNewText)
                    strReceived += str(sNewText)
                    sNewText = ""
                if (len(strReceived) > 66 * 1024):
                    #Safety code, some error prevented the string from being processed in several loop cycles.Reset it.
                    if (self.m_objRFECommunicator.VerboseLevel > 5):
                        print("Received string truncated (" +
                              len(strReceived) + ")")
                    strReceived = ""
                nLen = len(strReceived)
                if (nLen > 1):
                    if (self.m_objRFECommunicator.VerboseLevel > 9):
                        print(strReceived)
                    if (strReceived[0] == '#'):
                        nEndPos = strReceived.find("\r\n")
                        if (nEndPos >= 0):
                            sNewLine = strReceived[:nEndPos]
                            sLeftOver = strReceived[nEndPos + 2:]
                            strReceived = sLeftOver
                            #print(sNewLine)

                            if ((len(sNewLine) > 5) and
                                ((sNewLine[:6] == "#C2-F:") or
                                 ((sNewLine[:4] == "#C3-") and
                                  (sNewLine[4] != 'M')))
                                    or sNewLine.startswith("#C4-F:")):
                                if (self.m_objRFECommunicator.VerboseLevel >
                                        5):
                                    print("Received Config:" +
                                          str(len(strReceived)))

                                #Standard configuration expected
                                objNewConfiguration = RFEConfiguration(None)
                                #print("sNewLine: "+ sNewLine)
                                if (objNewConfiguration.ProcessReceivedString(
                                        sNewLine)):
                                    self.m_objCurrentConfiguration = RFEConfiguration(
                                        objNewConfiguration)
                                    self.m_hQueueLock.acquire()
                                    self.m_objQueue.put(objNewConfiguration)
                                    self.m_hQueueLock.release()
                            else:
                                self.m_hQueueLock.acquire()
                                self.m_objQueue.put(sNewLine)
                                self.m_hQueueLock.release()
                    elif (strReceived[0] == '$'):
                        if (nLen > 4 and (strReceived[1] == 'C')):
                            nSize = 2  #account for cr+lf
                            #calibration data
                            if (strReceived[2] == 'c'):
                                nSize += int(strReceived[3]) + 4
                            elif (strReceived[2] == 'b'):
                                nSize += (int(strReceived[4]) + 1) * 16 + 10
                            if (nSize > 2 and nLen >= nSize):
                                nEndPos = strReceived.find("\r\n")
                                sNewLine = strReceived[:nEndPos]
                                sLeftOver = strReceived[nEndPos:]
                                strReceived = sLeftOver
                                #print(" [" + " ".join("{:02X}".format(ord(c)) for
                                #c in sNewLine) + "]")
                                self.m_hQueueLock.acquire()
                                self.m_objQueue.put(sNewLine)
                                self.m_hQueueLock.release()
                        elif (nLen > 2 and ((strReceived[1] == 'q') or
                                            (strReceived[1] == 'Q'))):
                            #this is internal calibration data dump
                            nReceivedLength = ord(strReceived[2])
                            nExtraLength = 3
                            if (strReceived[1] == 'Q'):
                                nReceivedLength += int(0x100 * strReceived[3])
                                nExtraLength = 4

                            bLengthOK = (len(strReceived) >=
                                         (nExtraLength + nReceivedLength + 2))
                            if (bLengthOK):
                                self.m_hQueueLock.acquire()
                                self.m_objQueue.put(strReceived)
                                self.m_hQueueLock.release()
                                strReceived = strReceived[(nExtraLength +
                                                           nReceivedLength +
                                                           2):]
                        elif (nLen > 1 and (strReceived[1] == 'D')):
                            #This is dump screen data
                            if (self.m_objRFECommunicator.VerboseLevel > 5):
                                print("Received $D" + len(strReceived))

                            if (len(strReceived) >= (4 + 128 * 8)):
                                pass
                        elif (nLen > 2 and ((strReceived[1] == "S") or
                                            (strReceived[1] == 's') or
                                            (strReceived[1] == 'z'))):
                            #Standard spectrum analyzer data
                            nReceivedLength = ord(strReceived[2])
                            nSizeChars = 3
                            if (strReceived[1] == 's'):
                                if (nReceivedLength == 0):
                                    nReceivedLength = 256
                                nReceivedLength *= 16
                            elif (strReceived[1] == 'z'):
                                nReceivedLength *= 256
                                nReceivedLength += ord(strReceived[3])
                                nSizeChars += 1
                            if (self.m_objRFECommunicator.VerboseLevel > 9):
                                print("Spectrum data: " +
                                      str(nReceivedLength) + " " + str(nLen))
                            bLengthOK = (
                                nLen >= (nSizeChars + nReceivedLength + 2)
                            )  #OK if received data >= header command($S,$s or $z) + data length + end of line('\n\r')
                            bFullStringOK = False
                            if (
                                    bLengthOK
                            ):  ## Ok if data length are ok and end of line('\r\n') is in the correct place
                                ## (at the end).  Prevents corrupted data
                                bFullStringOK = bLengthOK and (
                                    ord(strReceived[nSizeChars +
                                                    nReceivedLength:][0])
                                    == ord('\r')) and (ord(
                                        strReceived[nSizeChars +
                                                    nReceivedLength:][1])
                                                       == ord('\n'))
                            if (self.m_objRFECommunicator.VerboseLevel > 9):
                                print("bLengthOK " + str(bLengthOK) +
                                      "bFullStringOK " + str(bFullStringOK) +
                                      " " + str(
                                          ord(strReceived[nSizeChars +
                                                          nReceivedLength:]
                                              [1])) + " - " +
                                      strReceived[nSizeChars +
                                                  nReceivedLength:])
                            if (bFullStringOK):
                                nTotalSpectrumDataDumps += 1
                                if (self.m_objRFECommunicator.VerboseLevel >
                                        9):
                                    print("Full dump received: " +
                                          str(nTotalSpectrumDataDumps))

                                #So we are here because received the full set of chars expected, and all them are apparently of valid characters
                                if (nReceivedLength <=
                                        RFE_Common.CONST_MAX_SPECTRUM_STEPS):
                                    sNewLine = "$S" + strReceived[nSizeChars:(
                                        nSizeChars + nReceivedLength)]
                                    if (self.m_objRFECommunicator.VerboseLevel
                                            > 9):
                                        print("New line:\n" + " [" +
                                              "".join("{:02X}".format(ord(c))
                                                      for c in sNewLine) + "]")
                                    if (self.m_objCurrentConfiguration):
                                        nSweepSteps = self.m_objCurrentConfiguration.nFreqSpectrumSteps
                                        objSweep = RFESweepData(
                                            self.m_objCurrentConfiguration.
                                            fStartMHZ, self.
                                            m_objCurrentConfiguration.fStepMHZ,
                                            nSweepSteps)
                                        if (objSweep.ProcessReceivedString(
                                                sNewLine,
                                                self.m_objCurrentConfiguration.
                                                fOffset_dB,
                                                self.m_objRFECommunicator.
                                                UseByteBLOB,
                                                self.m_objRFECommunicator.
                                                UseStringBLOB)):
                                            if (self.m_objRFECommunicator.
                                                    VerboseLevel > 5):
                                                print(objSweep.Dump())
                                            if (
                                                    nSweepSteps > 5
                                            ):  #check this is not an incomplete scan (perhaps from a stopped SNA tracking step)
                                                #Normal spectrum analyzer sweep data
                                                self.m_hQueueLock.acquire()
                                                self.m_objQueue.put(objSweep)
                                                self.m_hQueueLock.release()
                                        else:
                                            self.m_hQueueLock.acquire()
                                            self.m_objQueue.put(sNewLine)
                                            self.m_hQueueLock.release()
                                    else:
                                        if (self.m_objRFECommunicator.
                                                VerboseLevel > 5):
                                            print(
                                                "Configuration not available yet. $S string ignored."
                                            )
                                else:
                                    self.m_hQueueLock.acquire()
                                    self.m_objQueue.put(
                                        "Ignored $S of size " +
                                        str(nReceivedLength) + " expected " +
                                        str(self.m_objCurrentConfiguration.
                                            nFreqSpectrumSteps))
                                    self.m_hQueueLock.release()
                                strReceived = strReceived[(nSizeChars +
                                                           nReceivedLength +
                                                           2):]
                                if (self.m_objRFECommunicator.VerboseLevel >
                                        5):
                                    sText = "New String: "
                                    nLength = len(strReceived)
                                    if (nLength > 10):
                                        nLength = 10
                                    if (nLength > 0):
                                        sText += strReceived[:nLength]
                                    print(sText)
                            elif (bLengthOK):
                                #So we are here because the string doesn't end with the expected chars, but has the right length.
                                #The most likely cause is a truncated string was received, and some chars are from next string, not
                                #this one therefore we truncate the line to avoid being much larger, and start over again next time.
                                nPosNextLine = strReceived.index("\r\n")
                                if (nPosNextLine >= 0):
                                    strReceived = strReceived[nPosNextLine +
                                                              2:]
                    else:
                        nEndPos = strReceived.find("\r\n")
                        if (nEndPos >= 0):
                            sNewLine = strReceived[:nEndPos]
                            sLeftOver = strReceived[nEndPos + 2:]
                            strReceived = sLeftOver
                            self.m_hQueueLock.acquire()
                            self.m_objQueue.put(sNewLine)
                            self.m_hQueueLock.release()
                            if (self.m_objRFECommunicator.VerboseLevel > 9):
                                print("sNewLine: " + sNewLine)
                        elif (self.m_objRFECommunicator.VerboseLevel > 5):
                            print("DEBUG partial:" + strReceived)
                if (self.m_objRFECommunicator.Mode !=
                        RFE_Common.eMode.MODE_TRACKING):
                    time.sleep(0.01)
            time.sleep(0.5)