Identify the cause of \r artifacts when reading from a serial terminal? - linux
I'm trying to diagnose what is the cause of \r artifacts when reading from a serial terminal.
The following code can provoke the issue. There is an embedded Linux device connected to the physical end of the uart cable
import serial
ser = serial.Serial(
port='/dev/ttyUSB0',
baudrate=115200,
timeout=5)
ser.reset_input_buffer()
ser.reset_output_buffer()
b_NEW_LINE_WRITTEN = b'\n'
b_alphabet = b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z'
ser.write(b_alphabet + b_NEW_LINE_WRITTEN)
raw_line = ser.readline()
print(raw_line)
# b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q\rq R r S s T t U u V v W w X x Y y Z z\r\n'
The print the read data has an \r around the letter q.
When running a terminal emulator on top of /dev/ttyUSB0 the line starts wrapping around itself after 80 characters, similarly to
this question. This line wrapping seems to be a manifestation of the /r that I get when directly reading with the example python code.
When connected with a terminal emulator (picocom) this problem gets solved by running:
shopt -s checkwinsize
resize
there are no line wraps after that. I'm trying to understand why this is happening or where (is the host where /dev/tttyUSB0 what adds them or are they added by the embedded device being accessed), and how to workaround it without having to run external commands.
The following candidates could be causing the behavior:
driver settings for /dev/ttyUSB0 on the shot ps
driver settings for /dev/S0 on the target embedded device
shell on the target device
Setting /dev/ttyUSB0
Trying to modify /dev/ttyUSB0 in separate terminal while the device is consumed by the python script doesn't show any changes.
# Separate terminal on the host
stty -F /dev/ttyUSB0 cols 100
stty -F /dev/ttyUSB0 raw
stty -F /dev/ttyUSB0 -a
speed 115200 baud; rows 80; columns 100; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^A; eol = <undef>; eol2 = <undef>; swtch = <undef>;
start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O;
min = 1; time = 0;
-parenb -parodd -cmspar cs8 hupcl -cstopb cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany
-imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl -echoke
-flusho -extproc
#ipython
...
ser.write(b_alphabet + b_NEW_LINE_WRITTEN)
raw_line = ser.readline()
print(raw_line)
# b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q\rq R r S s T t U u V v W w X x Y y Z z\r\n'
Setting /dev/S0
Setting the target tty device also doesn't influence the artifacts existence.
stty_cmd_set = b'stty cols 200'
ser.write(stty_cmd_set + b_NEW_LINE_WRITTEN)
ser.reset_input_buffer()
ser.reset_output_buffer()
stty_cmd_confirm = b'stty -a'
ser.write(stty_cmd_confirm + b_NEW_LINE_WRITTEN)
# After reading a few lines there is a confirmation that the tty device on the target has indeed been set to 200
print(ser.readline())
b'speed 115200 baud; rows 56; columns 200; line = 0;\r\n'
ser.reset_input_buffer()
ser.reset_output_buffer()
ser.write(b_alphabet + b_NEW_LINE_WRITTEN)
raw_line = ser.readline()
print(raw_line)
# b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q\rq R r S s T t U u V v W w X x Y y Z z\r\n'
For example a workaround would be to somehow set a fixed amount of 200 columns before reading so that the serial terminal stops trying to be smart.
Reading between the lines, you are running something like a Linux shell on your embedded device.
This will have the same set of Linux app/TTY/driver hierarchy as your host and is defaulting to cooked mode processing of the input that it receives from your application. This is why running the command to change the number of columns (on your embedded application) works. It is telling the line discipline in that device to treat the screen as being 200 columns wide (and so the line-editing logic doesn't need to split the line).
Switching to raw input on both your host and embedded shell should fix it.
If you'd like to know more details of how Linux terminals handle input (and echoing of input back to the output stream), see https://www.linusakesson.net/programming/tty/
It is not clear what is actually happening but this is solution that seems to work.
It depends on existence of shopt -s checkwinsize and resize on the target board so it isn't a generic enough solution to be the accepted answer.
Also it doesn't provide an insight on how to apply a not runtime fix (by setting the driver defaults or some config in bash).
import serial
import time
ser = serial.Serial(
port='/dev/ttyUSB0',
baudrate=115200,
timeout=5)
b_NEW_LINE_WRITTEN = b'\n'
b_NEW_LINE_READ = b'\r\n'
b_alphabet = b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z'
ser.write(b_alphabet + b_NEW_LINE_WRITTEN)
print(ser.readline())
# b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q\rq R r S s T t U u V v W w X x Y y Z z\r\n'
shopt_cmd = b'shopt -s checkwinsize'
ser.write(shopt_cmd + b_NEW_LINE_WRITTEN)
ser.readline()
ser.readline()
resize_cmd = b'resize'
ser.write(resize_cmd + b_NEW_LINE_WRITTEN)
ser.readline()
ser.readline()
stty_cmd_set = b'stty cols 200'
ser.write(stty_cmd_set + b_NEW_LINE_WRITTEN)
ser.readline()
ser.readline()
ser.write(b_alphabet + b_NEW_LINE_WRITTEN)
print(ser.readline())
# b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z\r\n'
ser.reset_output_buffer()
stty_cmd_set = b'stty cols 5'
ser.write(stty_cmd_set + b_NEW_LINE_WRITTEN)
ser.readline()
ser.readline()
ser.write(b_alphabet + b_NEW_LINE_WRITTEN)
print(ser.readline())
# A a B \r b C c\rc D d \r E e F\rF f G \r g H h\rh I i \r J j K\rK k L \r l M m\rm N n \r O o P\rP p Q \r q R r\rr S s \r T t U\rU u V \r v W w\rw X x \r Y y Z\rZ z\r\n'
\r q is happening because your screen ends near q so it is moved to next line its carriage return of Unix. unix carriage return can be used as new line ,go to next line end of line both . Replace \r with empty.
Try auto wrap off
\r (Carriage Return) → moves the cursor to the beginning of the line without advancing to the next line
\n (Line Feed) → moves the cursor down to the next line without returning to the beginning of the line — In a *nix environment \n moves to the beginning of the line.
\r\n (End Of Line) → a combination of \r and \n
Related
pandas Iterate through Rows & Column and print it based on some condition
I have an excel file & I Processed that file for Data Analysis and Created a Data Frame(Pandas). Now I Need to Get the result , I'm trying to get it through iterating over pandas columns and rows using for & if Condition But I'm not getting desired output. I've Taken hyphen(-) in excel file so that I can apply some conditions. Excel File Input_File Required Output A -> B -> C -> E -> I F -> G ->L H -> J -> K A1 -> B1 C1 -> A1 Z -> X Note: Saving Output in Text file in plain. No need of Graph / Visualization code df = pd.read_excel('Test.xlsx') df.fillna('-') # Below code answer Z -> X for index, row in df.iterrows(): if row['Start_Name'] != '-': if row['End_Name'] != '-': print(row['Start_Name'] +' -> '+ row['End_Name']) # Below code answer A -> B / F -> G / H -> J / C1 -> A1 for index, row in df.iterrows(): if row['Start_Name'] != '-': if row['Mid_Name_1'] == '-': if row['Mid_Name_2'] != '-': print(row['Start_Name'] +' -> '+ row['Mid_Name_2']) # Below code answer B -> C / C -> E for index, row in df.iterrows(): if row['Mid_Name_1'] != '-': if row['Mid_Name_2'] != '-': print(row['Mid_Name_1'] +' -> '+ row['Mid_Name_2'])
Setup: Fronts dictionary holds value/position of the sequence that stars with name/key. Backs dictionary holds value/position of the sequence that ends with name/key. sequences is a list to hold all combined relations. position_counter stores position of last made sequence. from collections import deque import pandas as pd data = pd.read_csv("Names_relations.csv") fronts = dict() backs = dict() sequences = [] position_counter = 0 Extract_all. For each row select values that match regex-pattern selector = data.apply(lambda row: row.str.extractall("([\w\d]+)"), axis=1) For each relation from selector get extracted elements. Put them to the queue. Check if front of new relation can be attached to any previous sequence. If so: take position of that sequence. take sequence itself as llist2 remove last duplicated element from llist2 add the sequences update sequences with connected llists update backs with position of the current end of the seuquence and finally remove exausted ends of the previous sequence from fronts and backs Analogous to back in fronts.keys(): If no already existing sequence match to new relation: save that relation update fronts and backs with position of that relation update position counter for relation in selector: front, back = relation[0] llist = deque((front, back)) finb = front in backs.keys() # binf = back in fronts.keys() if finb: position = backs[front] llist2 = sequences[position] back_llist2 = llist2.pop() llist = llist2 + llist sequences[position] = llist backs[llist[-1]] = position if front in fronts.keys(): del fronts[front] if back_llist2 in backs.keys(): del backs[back_llist2] # if binf: # position = fronts[back] # llist2 = sequences[position] # front_llist2 = llist2.popleft() # llist = llist + llist2 # sequences[position] = llist # fronts[llist[0]] = position # if back in backs.keys(): # del backs[back] # if front_llist2 in fronts.keys(): # del fronts[front_llist2] # if not (finb or binf): if not finb: #(equivalent to 'else:') sequences.append(llist) fronts[front] = position_counter backs[back] = position_counter position_counter += 1 for s in sequences: print(' -> '.join(str(el) for el in s)) Outputs: A -> B -> C -> E -> I F -> G -> L H -> J -> K A1 -> B1 C1 -> A1 Z -> X #if binf is active: # A -> B -> C -> E -> I # F -> G -> L # H -> J -> K # C1 -> A1 -> B1 # Z -> X Name_relations.csv Start_Name,Mid_Name_1,Mid_Name_2,End_Name A,-,B,- -,B,C,- -,C,E,- F,-,G,- H,-,J,- -,E,-,I -,J,-,K -,G,-,L -,A1,-,B1 C1,-,A1,- Z,-,-,X
Is it possible to intercept the encrypted HTTP body in Biztalk AS2 connection?
Is it possible to see the full HTTP request that was made towards an AS2 endpoint? I tried Failed requests tracing from IIS but it does not show the body (probably because it is encrypted). I would like to be able to replay the AS2 call using something like this: POST http://aaa.com/PARTY/BTSHTTPReceive.dll HTTP/1.1 Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name="smime.p7m" Disposition-Notification-Options: signed-receipt-protocol=required,pkcs7-signature; signed-receipt- micalg=required,sha1 AS2-Version: 1.2 Content-Transfer-Encoding: binary Mime-Version: 1.0 Receipt-Delivery-Option: http://IPADDRESS/BiztalkMDN/BTSHTTPReceive.dll EDIINT-Features: multiple-attachments AS2-To: SOURCE Message-ID: <NC-AZ-HQ-BZ-ACC_19ED90F5-1E8F-455F-A800-22917F2C5DF0> AS2-From: DESTINATION Disposition-Notification-To: http://IPADRESS/BiztalkMDN/BTSHTTPReceive.dll User-Agent: Microsoft (R) BizTalk (R) Server Host: ... Content-Length: 2509 Expect: 100-continue Connection: Close 0 * H 0 1 Q0 M 050!10Uaaa.com- JΎKJ 7J- *0 * H f m zG$ jF9 Q1 : d, = T r E 5 C #/ qx M kR [ mV / NǦ ÿ a. =]: {yB_sgV [ `o zڛN L 1 ߭ R q jUۮy '/ p 7t :ƒ* l/Q " O QCF \ =cA# j (mV m x 3 = 'P & m(RR҉h0 K ) + #F pˮ PU0 Z * H 0* H 0 : 5& c.퀂0—D w | Θ y cO2 M z< pQL m 7 +%b fH *`f 8͚ ~=ԙ4b &9! b B # l1 " z \ Q S- . } " cZv >N.n% ̰| 3 a: :[1ӏZ k , W ̩J qjʉ =%7 7 l m b Inx : =Q p 1 + Gs :) T; .O Uf Chڑ i , E HV+ ߣ G d g „{ V. e Q .L < vx T ; t < pA j^J T O_ 9* [v=g4l c `5 Ԃ' H YS]߉ ' Ob $ 3 z 4 5 2 \3$IL : : T iy7; ԊE Z!{ [ \#x w k( OaaZ: | / h" U :! \u 4 V 8 v " M ϙv x "zL… p yĹ 2> +"p Ċ > t> v ӎ j l ąN)j , { ǗG5 +UK y ~ 9 ڣ: A ֙ (# Չ 4 ! .7y Aۣ . J j bhX .-j ) Z8( m^{=t哑[ | ^ Z )U 0[9V 5 L R3 , o ՝fj H!x 1J6 ( [F N <oq I ͓C a ': ˅ Ϊ ss{ ? hJ46 { Y>1 #- ֳ} 9* ʪ z tW U g8 o De b ) 0SD6 7 ) I N yW| f s e qUz.q 55 ]! 2 y 'Ў F) y e # F a3 h <k1 s 3 5 6 2 >6 2I5z|SNY / e 2?P ѽ. -U + h x >2 m/Œ f cYSD ˇA 2u + ' 7CDT"# h %; ~x R g Y K %> ?g| +h-:< , vT( c!1J h5 0 ) j T G 1 ʋL * ad 0pAv~XS - # ' gK~ u +fS | zr U U ҽ C ##m ӑ $ K CZ ̀ Y MixO 8 # IB %WwT: H M2 >˪ R Myn 0h$ 9# ' τ 7=+Vюx ` W{ b P Ob KB "қ pýG ;= 2UD ]ƜY+ bZ8) R +ٔL t QN Q 4ڎ #nJ+byK A p , U FS`i wY` U NwƽU< 27 ]* { 'CV ?QǓ L=`#C (! ^ 7k EJ? $ C )% f= A x L )^P t !Tu ~^A] 8" E/: t 3 P 5iG# "|J & U [MC $WUS&g %h)5 Ę mI ~ ÷ /mC Mq nNĝ Ǩ j *. }o E/ y G ד 1 h ?D m %˷ ^ DXy- mj_ [ dT SM珍 k?[ - i ; 3i B[W͵ <w R YP; KGaF . Up}^ : .W " 3 뙲E _ hI } SG 3 ι Œ hd * ++_Gz bc; D # و y p ۧy A D k ŧ ? 5 t ^ <. . I' .Vp /&nVo N y0 b K 0 3QE L vw tθ S /w 9 K նB x2Q#+Tj fC F R c <Ad/ 1tlSfպ- w O0o =) T鏺 Q
Is it possible to hide strings from Lua compiled code?
I have a path for a file specified as a string in my code, and I don't want to be visible after luac conversion. Is it possible obfuscate somehow the line? My code is: DIR1 = '../../../files/file1.txt' Thank you!
Yes. Example: local Key53 = 8186484168865098 local Key14 = 4887 function decode(str) local K, F = Key53, 16384 + Key14 return (str:gsub('%x%x', function(c) local L = K % 274877906944 -- 2^38 local H = (K - L) / 274877906944 local M = H % 128 c = tonumber(c, 16) local m = (c + (H - M) / 128) * (2*M + 1) % 256 K = L * F + H + c + m return string.char(m) end )) end local path = decode"beb81858c47a5fc7e11721921fb7f58ceeb530c4e74034df" print(path) --> ../../../files/file1.txt How to encode your own text
Python dictionaries formatting
Python3 I have a dictionary with alphabet count, shown below a 24873 b 5293 c 7301 d 15567 e 38088 f 6499 g 7109 h 20360 i 20283 j 751 k 3207 l 12780 m 7686 n 21510 o 24944 p 5275 q 191 r 16751 s 18831 t 30897 u 9624 v 2551 w 8390 x 439 y 7139 z 161 and i want a function to print it as e 38088 i 20283 w 8390 b 5293 q 191 t 30897 s 18831 m 7686 p 5275 z 161 o 24944 r 16751 c 7301 k 3207 a 24873 d 15567 y 7139 v 2551 n 21510 l 12780 g 7109 j 751 h 20360 u 9624 f 6499 x 439 I tried taking keys and values into lists but is randomly changing as a dictionary is not ordered. Thanks in advance for the help.
You can use dict.items() to get the key-value pairs as a list of tuples. Then sort this list by the value. For example: d = { 'a': 24873, 'b': 5293, 'c': 7301, 'd': 15567 } for k, v in sorted(d.items(), key=lambda x: x[1], reverse=True): print("{} {}".format(k, v)) #a 24873 #d 15567 #c 7301 #b 5293 We sort the key-value pair tuples using a custom key, lambda x: x[1], which gets the element at index 1 in the tuple. In this case, that element is the count. Also, we specify reverse=True to indicate that we want the sorted list to be in descending order.
from itertools import zip_longest def printCol(l, numCols=5): """Takes a sorted list 'l' and displays it in 'numCols', the first items get into col1, the next in col2 etc.""" # partition the sorted list steps = len(l)//numCols+1 part = [l[i:i+steps] for i in range(0,len(l),steps)] # transpose it into tuple-rows zpart = zip_longest(*part,()) for row in zpart: for t in row: if t: # zip_longest produces () - do not display them print(t[1],t[0], end = " ") print("") # newline You have to prepare your data a bit: d ={"a":24873,"b":5293 ,"c":7301 ,"d":15567 ,"e":38088 , "f":6499 ,"g":7109 ,"h":20360 ,"i":20283 ,"j":751 , "k":3207 ,"l":12780 ,"m":7686 ,"n":21510 ,"o":24944 , "p":5275 ,"q":191 ,"r":16751 ,"s":18831 ,"t":30897 ,"u":9624 , "v":2551 ,"w":8390 ,"x":439 ,"y":7139 ,"z":161 } # list comp: create tuples of (count, character) so sort will sort it by count l = [ (am,ch) for ch,am in d.items()] # create tuples, amount first for sorting l.sort(reverse=True) # sort descending by count, if equal, then by char printCol(l,5) # print it Output: e 38088 i 20283 w 8390 b 5293 q 191 t 30897 s 18831 m 7686 p 5275 z 161 o 24944 r 16751 c 7301 k 3207 a 24873 d 15567 y 7139 v 2551 n 21510 l 12780 g 7109 j 751 h 20360 u 9624 f 6499 x 439
This is the solution I figured out with just traditional loops and not many in built functions. ThankYou <pre> def printTable(value): no_of_rows = len(value)//5+1 i = 0 while(i < no_of_rows): for j in range(0, len(value), no_of_rows): if i+j < len(value): print(str(value[i+j][0]).rjust(3), str(value[i+j][1]).rjust(5), end=" ") print("") i += 1 d ={"a":24873, "b":5293, "c":7301, "d":15567, "e":38088, "f":6499, "g":7109, "h":20360, "i":20283, "j":751, "k":3207, "l":12780, "m":7686, "n":21510, "o":24944, "p":5275, "q":191, "r":16751, "s":18831, "t":30897, "u":9624, "v":2551, "w":8390, "x":439, "y":7139, "z":161} dic_to_sortlist = sorted(alph_freq.items(), key=operator.itemgetter(1), reverse=True) printTable(dic_to_sortlist) </pre>
Roy and Profile Picture
I need help with my code, i'm doing the code of Roy and Profile Picture in the hackearth, and when i going to run, this error appears: 'ValueError: invalid literal for int() with base 10:' This is my code: l = int(input()) n = int(input()) i = 0 while i < n: wh = str(input().split(' ')) w,h = int(wh[0]),int(wh[1]) if w == l and h == l: print('ACCEPTED') else: if w > l and h > l: print('CROP IT') else: print('UPLOAD ANOTHER') i+=1 sorry for my mistakes with the english, i'm learning. Is this in python 3.x
Correct Program is below: l = int(input()) n = int(input()) i = 0 while i < n: wh = (input().split()) w = int(wh[0]) h = int(wh[1]) if w < l or h < l: print('UPLOAD ANOTHER') else: if w == h and (w >= l and h >= l) : print('ACCEPTED') else: print('CROP IT') i+=1
Scanner s = new Scanner(System.in); int L = Integer.parseInt(s.nextLine()); int N = Integer.parseInt(s.nextLine()); int i = 0; while(i++ < N) { String[] arr = s.nextLine().split(" "); int W = Integer.parseInt(arr[0]); int H = Integer.parseInt(arr[1]); if(W < L || H < L) { System.out.println("UPLOAD ANOTHER"); } else if (W >= L && H >= L) { if(W == H) { System.out.println("ACCEPTED"); } else { System.out.println("CROP IT"); } } }