Python Serial read challenge

Question:

I am trying to read out some serial data that is structured in a way that gives me a headache… This is the line I get:

b'x1b[2Jx1b[1;1fI Source:x1b[2;1fI Limit:x1b[3;1fV Source:x1b[4;1fV Min:x1b[5;1fmA Hours:x1b[1;12f 0.000x1b[2;12f 0.010x1b[3;12f 0.000x1b[4;12f 2.000x1b[5;12f 0.00'

This is how it looks in putty log:
I Source:I Limit:V Source:V Min:mA Hours: 0.000 0.010 0.000 2.000 0.00

And what I really need is simply just to get the numerical data i.e., 0.000 0.010 0.000 2.000 0.00 for me to log, plot and do math on…

Any hints to what could be done are appreciated !

Asked By: mognic

||

Answers:

If your outputs are exactly the same format every time, I have a quick and dirty way to do this.

for i in str1.decode('utf-8').replace('x1b','').split(' '): #remove the xlb string and split the string by spaces
    x = i.split('[')[0] #split the string again by '[', then take the first item
    if '.' in x:
        print(float(x)) #convert the item into a float if it contains a decimal point
    

Your output will be.

0.0
0.01
0.0
2.0
0.0

You can change the print line into making a list and appending it to a list so you can do something with it like this,

myList = []

for i in str1.decode('utf-8').replace('x1b','').split(' '):
    x = i.split('[')[0]
    if '.' in x:
        myList.append(float(x))

Now myList will contain a list of the floats.

I have found a better way, you can use regex to replace the ansi characters in the middle and get what you want like this.

ansi_escape = re.compile(r'x1B(?:[@-Z\-_]|[[0-?]*[ -/]*[@-~])')
result = ansi_escape.sub('', str1)
print(result)
x = result.split(':')[-1]
x = x.strip().split(' ')

myList = []
for i in x:
    if i:
        myList.append(float(i))

print(myList)

The output is this,

I Source:I Limit:V Source:V Min:mA Hours: 0.000 0.010 0.000 2.000  0.00

followed by,

[0.0, 0.01, 0.0, 2.0, 0.0]
Answered By: anarchy

So, just to sum up here. I used the first approach to sort the data. But firstly I read the data with my special EOL.

It’s not pretty as it is, but I am still relatively new to Python…
I’ll work on cleaning up the code and see if I can do my plotting a bit more elegant.

Thanks for the responses !

ser = serial.Serial(port="COM3", baudrate=115200, bytesize=8, timeout=2, stopbits=serial.STOPBITS_ONE)

response = ser.read()
numLines = 0
myList = []

while not b'x1b[2J' in response:
    response += ser.read()
    if b'x1b[2J' in response:
        for i in response.decode('utf-8').replace('x1b','').split(' '):
            x = i.split('[')[0]
            if '.' in x:
                myList.append(float(x))
        if len(myList) % 10 == 0:
            fig, axs = plt.subplots(3)
            axs[0].plot(myList[0:len(myList):5])       
            axs[1].plot(myList[1:len(myList):5])
            axs[2].plot(myList[2:len(myList):5])
            
            axs.flat[0].set(xlabel='Sample [#]', ylabel='Current PV [A]')
            axs.flat[1].set(xlabel='Sample [#]', ylabel='Current SP [A]')
            axs.flat[2].set(xlabel='Sample [#]', ylabel='Votlage [V]')
            axs.flat[0].yaxis.set_major_formatter(FormatStrFormatter('%.2f'))
            axs.flat[1].yaxis.set_major_formatter(FormatStrFormatter('%.2f'))
            axs.flat[2].yaxis.set_major_formatter(FormatStrFormatter('%.2f'))
            plt.show()
        response = ser.read()
        
    if keyboard.is_pressed('g'):  # if key 'g' is pressed 
        break  # finishing the loop
        
ser.close()
textfile = open("log.txt", "w")
for element in myList:
    textfile.write(str(element) + ";")
textfile.close()

#b'x1b[2Jx1b[1;1fI Source:x1b[2;1fI Limit:x1b[3;1fV Source:x1b[4;1fV Min:x1b[5;1fmA Hours:x1b[1;12f 0.000x1b[2;12f 0.010x1b[3;12f 0.000x1b[4;12f 2.000x1b[5;12f  0.00'
#I Source:I Limit:V Source:V Min:mA Hours: 0.000 1.500 0.160 2.000  3.41
Answered By: mognic
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.