I have a python program that is trying to read 14 bytes from a serial port that
are arriving very slowly. I want want to capture all of the bytes in a
bytearray[14]. I understand there are new byte array features in python 3.0, but
I'm only running python 2.6.6. Upgrading may have unexpected consequences so I have to
stick with 2.6.6.
Data only intermittently flows over the serial port. I get one message on the
port maybe every 2 minutes or so. This data flows very slowly. The problem I am seeing is
that my code does not relaibly read the data one byte at a time. I want to frame this
data at exactly 14 bytes, then process the data and start fresh with a new 14
bytes.
Am I taking the wrong approach here? Advice?
ser = serial.Serial('/dev/ttyUSB1', 1200, timeout=0)
ser.open()
print "connected to: " + ser.portstr
count=0
while True:
line =ser.readline(size=14) # should block, not take anything less than 14 bytes
if line:
# Here I want to process 14 bytes worth of data and have
# the data be consistent.
print "line(" + str(count) + ")=" + line
count=count+1
ser.close()
Here's what I'm expecting: line(1)=� 0~ 888.ABC� /ends in carriage return
----------begin output------
line(0)=0
line(1)=~ ??1. ABC � # here get some multiple bytes and stuff gets out of synch
�ine(2)=
line(3)=0
line(4)=~
line(5)=
line(6)=8
line(7)=8
line(8)=8
line(9)=.
line(10)=
line(11)=A
line(12)=B
line(13)=C
line(14)=
line(15)=�
line(16)=
#...
line(48)=
line(49)=�
line(50)=0
line(51)=~
line(52)=
line(53)=8
line(54)=8
line(55)=8
line(56)=.
line(57)=
line(58)=A
line(59)=B
line(60)=C
line(61)=
line(62)=�
line(63)=
line(64)=
----------end output------
The API documentation for PySerial says readline() reads until \n, or until size is reached. However, the read() function says it will block until size is reached. Both of these functions say they will return early if a timeout is set.
Possible values for the parameter timeout:
timeout = None: wait forever
timeout = 0: non-blocking mode (return immediately on read)
timeout = x: set timeout to x seconds (float allowed)
Maybe try timeout=None instead of timeout=0
Try this:
ser = Serial('/dev/ttyUSB1', 1200, timeout=0)
print "connected to: " + ser.portstr
count=0
while True:
for line in ser.readlines()
print "line(" + str(count) + ")=" + line
count=count+1
ser.close()
You might also be interested in the line.strip() function if you haven't used it. Also, emphasis on the s in ser.readlines(), different from .readline().
Change the baudrate.
ser = serial.Serial('/dev/ttyUSB1', 9600, timeout=0)
to a compatible baudrate.
For getting 14 byte data :
data = ser.read(size=14)
Related
I have a code, i want to run the function cek_paket() and delete_paket() at the same time. My friend suggest me to use thread. So shortly, im using this to sniffing arp packet, and save the information (source, destination address,and the amount of packet arrived) into list in dictionary python. So sniff() function is the function by scapy that i use to sniff packet. After the packet arrive, it will return it to cek_paket() to save the information to jumlah_reply list. And i use delete_reply() to delete the first list(jumlah_reply[0]) every 3 second. I have no problem in cek_paket() function. The problem is, why the sniffing() function only works? But delete_reply function did not work?
from scapy.all import*
import thread
import time
jumlah_reply = []
def cek_paket(pkt):
if pkt[ARP].op ==2:
destinasi = str(pkt[ARP].pdst)
source = str(pkt[ARP].psrc)
dikirim = {'src':source,'dst':destinasi}
if len(jumlah_reply)==0:
dikirim['count']=1
jumlah_reply.append(dikirim)
found = True
else:
found=False
for itung in jumlah_reply:
if itung['src']==dikirim['src'] and itung['dst']==dikirim['dst']:
itung['count']+=1
found = True
break
if not found:
jumlah_reply.append(dikirim)
dikirim['count']=1
print("reply")
print(jumlah_reply)
print("--------------------------------")
def delete_paket():
if len(jumlah_reply) > 0:
del jumlah_reply[0]
print("*********************")
print (jumlah_reply)
print("**********************")
time.sleep(3)
def sniffing():
sniff(prn=cek_paket,filter="arp",store=0)
try:
thread.start_new_thread(sniffing())
thread.start_new_thread(delete_paket())
except:
print("error")
while 1:
pass
I was expecting the output:
When there is a ARP reply packet, the information will be added into the list, and 3 second after it, the first item will be deleted. but the actual output is
As you can see the information packet have added into the list but i've run the code for a minute there is no action from delete_reply() function. Why this is happen? is the sniff() function from scapy lock all the process?
I am generating a protocol for a tcpip socket between python and matlab. While trying to setup some sort of a protocol, I ran into a problem. It has to do with this set of code below
FPath = Path('c:/test/dogg.jpg')
HASH = Commons.get_file_md5_hash((FPath))
msg = ('IDINFO'+FPath.name+'HASH'+ HASH+'\n')
generates the message
IDINFOdogg.jpgHASH7ad1a930dab3c099939b66267b5c57f8
I have in the message: IDINFO which will tell the server the name of the file and HASH which will tell the file details.
After this I open up the file using
f = open(FPath,"rb")
chunk = f.read(1020)
and build a package with the tag DATA in front
msg = b`DATA` + chunk + b'\n'
Problem is that the b'\n' is not the same as in the first message. as Matlab cannot read the delimiter and won't continue grabbing data chunks.
Matlab code for Below reference. This isn't the entire object just the part that is potentially causing trouble.
To setup a callback.
set(gh.tcpipServer, 'BytesAvailableFcnMode','Terminator');
set(gh.tcpipServer, 'BytesAvailableFcn', #(h,e)gh.Serverpull(h,e));
The Function for looking at the bytes
function Serverpull(gh,h,e)
gh.msg = fread(gh.tcpipServer,gh.tcpipServer.BytesAvailable);
gh.msgdecode = char(transpose(gh.msg));
if strfind(gh.msgdecode,'IDINFO')
Hst = strfind(gh.msgdecode,'HASH');
gh.Fname = gh.msgdecode(7:Hst-1);
gh.HASH = gh.msgdecode(Hst+4:end);
fwrite(gh.tcpipServer,'GoodToGo');
gh.PrepareforDataAq()
elseif strfind(gh.msgdecode,'DATA')
fwrite(gh.fileID,gh.msg(5:end),'double');
elseif strfind(gh.msgdecode,'EOF')
fclose(gh.fileID);
display('File Transfer Complete')
end
end
function PrepareforDataAq(gh)
path = fullfile('c:\temp\',gh.Fname);
gh.fileID = fopen(path,'w');
end
For the TLDR,
How to make the string '\n' the same as b \n when building a tcp message from binary instead of strings before encoding?
I am new to python,currently working on the project reading serial port from micro controller to capture sensor data. The serial data i received looks like this:
[5;17H 0.029[5;40H 0.736[5;63H 9.557[7;17H 0.038[7;40H 0.001 [7;63H 0.008[9;17H-34.199[9;40H 25.800[9;63H 13.799[14;17H -4.623[14;40H 0.597[14;63H218.920[19;14H
this serial data actually have escape sequence 'x1b' before open bracket. How do i get rid of them, escape sequence and text format(5;17H..) and just print sensor data x,y,z format line by line. Can somebody help me.. Thank you..
I'm using python serial code:
import serial
ser = serial.Serial('COM9', 115200, bytesize=8, timeout=0)
while True:
data = ser.read(size=8).decode("utf-8")
s = str(data)
print(data)
ser.close()
Sensor data record starts with \033, so split at this for instance:
data_list = data.split('\033')
for v in data:
print (v)
I have a log monitoring python script I'm working on. It sends messages when entries with the text "disconnected" are found. The script reads the log until it comes across a "End of log file" message. In its current state it sends the messages as they come across. This isn't optimal and I need to pool them for say 5 minutes before sending the collected entries. I am not sure what the best method for doing this is. Here is a simplified version of what I am trying to do. So far I’ve tried time.sleep and an elaborate incremental counter to no avail.
# Open log
f = open(log, 'r')
# Start while loop and read line
while(1):
# Check for Disconnected
if line.find("disconnected") != -1:
ltime = time.time()
print ("Disconnected Found in Log at " + ltime)
# Check for end of log file
if line.find("End of file") != -1:
# End script
break
Would this work for you?
Save current time in a variable and create an empty list before while loop.
Every time you find a "disconnect", append the message to the list.
In each iteration in the while loop, you compare the current time to the timestamp you saved (in step 1) - if more than 5 mins (300 sec) has passed you iterate through the list and send all messages.
Empty the list and save the current time in the variable from step 1.
Does this make sense? I can elaborate further if needed.
This is what I ended up doing.
# Disconnects that have already been recorded
rec_disconnects = []
# Disconnects to msg
send_disconnects = []
# Start while loop
while(1):
# Wait 5 minutes
time.sleep(300)
# If list isn't empty
if send_disconnects:
# Join all the disconnects from the send list
msg = '\n'.join(send_disconnects)
# print the disconnects
print (msg)
# Clear the list
send_disconnects = []
# Open the log file and read the lines
with open(log) as log:
for line in log:
# If disconnect is found log it
if line.find("disconnected") != -1:
ltime = time.time()
disconnect = ("Disconnected Found in Log at " + ltime)
# Check if disconnect is already in the list if not add it
# to the running list and the msg list
if (disconnect not in rec_disconnects):
rec_disconnects.append(disconnect)
send_disconnects.append(disconnect
I am having problems using the pyUSB library to read data from an ELM327 OBDII to USB device. I know that I need to write a command to the device on the write endpoint and read the received data back on the read endpoint. It doesn't seem to want to work for me though.
I wrote my own class obdusb for this:
import usb.core
class obdusb:
def __init__(self,_vend,_prod):
'''Handle to USB device'''
self.idVendor = _vend
self.idProduct = _prod
self._dev = usb.core.find(idVendor=_vend, idProduct=_prod)
return None
def GetDevice(self):
'''Must be called after constructor'''
return self._dev
def SetupEndpoint(self):
'''Must be called after constructor'''
try:
self._dev.set_configuration()
except usb.core.USBError as e:
sys.exit("Could not set configuration")
self._endpointWrite = self._dev[0][(0,0)][1]
self._endpointRead = self._dev[0][(0,0)][0]
#Resetting device and setting vehicle protocol (Auto)
#20ms is required as a delay between each written command
#ATZ resets device
self._dev.write(self._endpointWrite.bEndpointAddress,'ATZ',0)
sleep(0.002)
#ATSP 0 should set vehicle protocol automatically
self._dev.write(self._endpointWrite.bEndpointAddress,'ATSP 0',0)
sleep(0.02)
return self._endpointRead
def GetData(self,strCommand):
data = []
self._dev.write(self._endpintWrite.bEndpointAddress,strCommand,0)
sleep(0.002)
data = self._dev.read(self._endpointRead.bEndpointAddress, self._endpointRead.wMaxPacketSize)
return data
So I then use this class and call the GetData method using this code:
import obdusb
#Setting up library,device and endpoint
lib = obdusb.obdusb(0x0403,0x6001)
myDev = lib.GetDevice()
endp = lib.SetupEndpoint()
#Testing GetData function with random OBD command
#0902 is VIN number of vehicle being requested
dataArr = lib.GetData('0902')
PrintResults(dataArr)
raw_input("Press any key")
def PrintResults(arr):
size = len(arr)
print "Data currently in buffer:"
for i in range(0,size):
print "[" + str(i) + "]: " + str(make[i])
This only ever prints the numbers 1 and 60 from [0] and [1] element in the array. No other data has been return from the command. This is the case whether the device is connected to a car or not. I don't know what these 2 pieces of information are. I am expecting it to return a string of hexadecimal numbers. Does anyone know what I am doing wrong here?
If you don't use ATST or ATAT, you have to expect a timeout of 200ms at start, between every write/read combination.
Are you sending a '\r' after each command? It looks like you don't, so it's forever waiting for a Carriage Return.
And a hint: test with 010D or 010C or something. 09xx might be difficult what to expect.
UPDATE:
You can do that both ways. As long as you 'seperate' each command with a carriage return.
http://elmelectronics.com/ELM327/AT_Commands.pdf
http://elmelectronics.com/DSheets/ELM327DS.pdf (Expanded list).
That command list was quite usefull to me.
ATAT can be used to the adjust the timeout.
When you send 010D, the ELM chip will wait normally 200 ms, to get all possible reactions. Sometimes you can get more returns, so it waits the 200 ms.
What you also can do, and it's a mystery as only scantools tend to implement this:
'010D1/r'
The 1 after the command, specifies the ELM should report back, when it has 1 reply from the bus. So it reduces the delay quite efficiently, at the cost of not able to get more values from the address '010D'. (Which is speed!)
Sorry for my english, I hope send you in the right direction.