pyserial readline() : SerialException - python

I'm writing a code used to send order to an avr. I send several information but between each write, I have to wait for an answer (I have to wait for the robot to reach a point on the coordinate system). As I read in the documentation, readline() should at least read until the timeout but as soon as I send the first coordinate, the readline() automatically return :
SerialException: device reports readiness to read but returned no data (device disconnected?)
When I put a sleep() between each write() in the for loop, everything works fine. I tried to use inWaiting() but it still does not work. Here is an example of how I used it:
for i in chemin_python:
self.serieInstance.ecrire("goto\n" + str(float(i.x)) + '\n' + str(float(-i.y)) + '\n')
while self.serieInstance.inWaiting():
pass
lu = self.serieInstance.readline()
lu = lu.split("\r\n")[0]
reponse = self.serieInstance.file_attente.get(lu)
if reponse != "FIN_GOTO":
log.logger.debug("Erreur asservissement (goto) : " + reponse)

Here an snipet how to use serial in python
s.write(command);
st = ''
initTime = time.time()
while True:
st += s.readline()
if timeout and (time.time() - initTime > t) : return TIMEOUT
if st != ERROR: return OK
else: return ERROR

This method allows you to separately control the timeout for gathering all the data for each line, and a different timeout for waiting on additional lines.
def serial_com(self, cmd):
'''Serial communications: send a command; get a response'''
# open serial port
try:
serial_port = serial.Serial(com_port, baudrate=115200, timeout=1)
except serial.SerialException as e:
print("could not open serial port '{}': {}".format(com_port, e))
# write to serial port
cmd += '\r'
serial_port.write(cmd.encode('utf-8'))
# read response from serial port
lines = []
while True:
line = serial_port.readline()
lines.append(line.decode('utf-8').rstrip())
# wait for new data after each line
timeout = time.time() + 0.1
while not serial_port.inWaiting() and timeout > time.time():
pass
if not serial_port.inWaiting():
break
#close the serial port
serial_port.close()
return lines

Related

Black Hat Python proxy tool no data

I recently bought the book Black Hat Python, 2nd Edition, by Justin Seitz, which seems to be a very good book about networking and all that (i am writing my code on Kali Linux)
I have a problem on the TCP Proxy Tool on chapter 2 :
Here is the code :
import sys
import socket
import threading
HEX_FILTER = ''.join(
[(len(repr(chr(i))) == 3) and chr(i) or '.' for i in range(256)])
def hexdump(src, length = 16, show = True):
# basically translates hexadecimal characters to readable ones
if isinstance(src, bytes):
src = src.decode()
results = list()
for i in range(0, len(src), length):
word = str(src[i:i+length])
printable = word.translate(HEX_FILTER)
hexa = ' '.join(['{ord(c):02X}' for c in word])
hexwidth = length*3
results.append('{i:04x} {hexa:<{hexwidth}} {printable}')
if show :
for line in results :
print(line)
else :
return results
def receive_from(connection):
buffer = b""
connection.settimeout(10)
try :
while True :
data = connection.recvfrom(4096)
if not data :
break
buffer += data
except Exception as e:
pass
return buffer
def request_handler(buffer):
# perform packet modifications
return buffer
def response_handler(buffer):
# perform packet modifications
return buffer
def proxy_handler(client_socket, remote_host, remote_port, receive_first):
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((remote_host, remote_port))
if receive_first :
# Check for any data to receive before
going into the main loop (i guess)
remote_buffer = receive_from(remote_socket)
hexdump(remote_buffer)
remote_buffer = response_handler(remote_buffer)
if len(remote_buffer):
print("[<==] Sending %d bytes to localhost." % len(remote_buffer))
client_socket.send(remote_buffer)
while True : # Start the loop
local_buffer = receive_from(client_socket)
if len(local_buffer):
line = "[==>] Received %d bytes from localhost." % len(local_buffer)
print(line)
hexdump(local_buffer)
local_buffer = request_handler(local_buffer)
remote_socket.send(local_buffer)
print("[==>] Sent to remote.")
remote_buffer = receive_from(remote_socket)
if len(remote_buffer):
print("[==>] Received %d bytes from remote." % len(remote_buffer))
hexdump(remote_buffer)
remote_buffer=response_handler(remote_buffer)
client_socket.send(remote_buffer)
print("[<==] Sent to localhost.")
if not len(local_buffer) or not len(remote_buffer):
# If no data is passed, close the sockets and breaks the loop
client_socket.close()
remote_socket.close()
print("[*] No more data. Closing connections. See you later !")
break
def server_loop(local_host, local_port, remote_host, remote_port, receive_first):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try :
server.bind((local_host, local_port)) # Bind the local host and the local port
except Exception as e:
print('Problem on bind : %r' %e)
# If an error occurs, prints a
print("[!] Failed to listen on %s:%d" % (local_host, local_port))
print("[!] Check for other listening sockets or correct permissions.")
sys.exit(0)
print("[*] Listening on %s:%d" % (local_host, local_port))
server.listen(5)
while True :
client_socket, addr = server.accept()
# print out the local connection information
line = "> Received incoming connection from %s:%d" % (addr[0], addr[1])
print(line)
# start a thread to talk to the remote host
proxy_thread = threading.Thread(
target = proxy_handler,
args=(client_socket,remote_host,
remote_port, receive_first))
proxy_thread.start()
def main():
if len(sys.argv[1:]) != 5:
print("Usage: ./proxy.py [localhost] [localport]")
print("[remotehost] [remoteport] [receive_first]")
print("Example : ./proxy.py 127.0.0.1 9000 192.168.56.1 9000 True")
sys.exit(0)
loca l_host = sys.argv[1]
local_port = int(sys.argv[2])
remote_host = sys.argv[3]
remote_port = int(sys.argv[4])
receive_first = sys.argv[5]
if "True" in receive_first:
receive_first = True
else :
receive_first = False
server_loop(local_host, local_port,
remote_host, remote_port, receive_first)
if __name__ == '__main__':
main()
(sorry, i had a bit of a trouble formatting it and it's quite long)
Now, normally, i just need to open 2 terminals and run the code with the command line :
sudo python proxy.py 127.0.0.1 21 ftp.dlptest.com 21 True
in one terminal, and :
ftp 127.0.0.1 21
in the other one.
My code seems to be working fine, except that... I receive no data. I tried different ftp servers (notice that i don't use the one quoted in the book), but it still doesn't work. It just says :
[*] Listening on 127.0.0.1
> Received incoming connection from 127.0.0.1:55856
but it doesn't actually displays anything until the connexion times out or that i stop the command with Ctrl + C.
I know this question has already been asked, but they don't resolve my problem.
Please tell me if i forgot a line of code (for example the one that prints the data on the screen lol) or did anything wrong :)
one the hexa variable you need to put and f'{ord(c):02x}' because you just have a string and not using the 'c' variable from the list comprehension. That's a small typo you missed fix that and try the whole process again.
hexa = ' '.join([f'{ord(c):02X}' for c in word])
The f should be here ^

Timer just runs the first time

First of all I am a complete noobie when it comes to python. Actually I started reading about it this morning when I needed to use it, so sorry if the code is a disaster.
I'd like to get this done:
A communication via serial between two devices. The device where the python program is running has to be listening for some data being sent by the other device and storing it in a file. But every 30 seconds of received data it has to send a command to the other device to tell it to stop sending and begin a scan that takes 10 seconds.
This is the code I've written. It's printing continuously Opening connection..
from serial import Serial
from threading import Timer
import time
MOVE_TIME = 30.0
SCAN_TIME = 10.0
DEVICE_ADDRESS = '/dev/ttyACM0'
BAUD_RATE = 9600
while True:
try:
print("Opening connection...")
ser = Serial(DEVICE_ADDRESS, BAUD_RATE
break
except SerialException:
print("No device attached")
def scan():
print("Scanning...")
timeout = time.time() + SCAN_TIME
while True:
#Some code I haven't thought of yet
if time.time() > timeout:
ser.write(b'r') #command to start
break
def send_stop_command():
print("Sending stop command")
ser.write(b's') #command to stop
scan()
t = Timer(MOVE_TIME + SCAN_TIME, send_stop_command)
t.start()
filename = time.strftime("%d-%m-%Y_%H:%M:%S") + ".txt"
while True:
data = ser.readline()
try:
with open(filename, "ab") as outfile:
outfile.write(data)
outfile.close()
except IOError:
print("Data could not be written")

Communicating with air-conditioner controller using pyserial

I am trying to the first time to send and receive information through serial port. The manual for the device with which I am trying to talk can be found here. I am trying for a start to send a set of hexadecimals to ask about the condition of the system and my purpose is to ask in real time about the temperature and store it. Until now my code is this:
import serial
import time
#import serial.tools.list_ports
#ports = list(serial.tools.list_ports.comports())
#for p in ports:
# print p
ser = serial.Serial(port= '/dev/ttyUSB0',
baudrate=9600,
parity=serial.PARITY_EVEN,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS, timeout=0, xonxoff=1, rtscts=1, dsrdtr=1)
command = "\x10\xFF\x29\x2C\x16"
command = command.decode("hex")
ser.write(command)
print command
#time.sleep(10)
ReceivedData = "\n nothing"
while ser.inWaiting() > 0:
ReceivedData = ser.read()
print ReceivedData
The problem is that I cannot get any response.
EDIT:
So I solved the communication problem. It turned out I was using an extension cable so the T and R channels were not correctly connected. Now The response that I receive is "\x00\x10\xFF\x29\x2C\x16" which is the same that I put in only with a \x00 in the front. Does this mean it is an error message? How do I calculate the 4th bit? Until now I am using an example from the manual.
dont use command = command.decode("hex")
just
command = "\x10\xFF\x29\x2C\x16"
ser.write(command)
should work i am sure it expects bytes like this
to put it differently
START_BYTE = "\x10"
ADDR_BYTE = "\xff"
FN_BYTE = "\x29"
CS_BYTE = "\x2C" # We assume you have calculated this right
END_BYTE = "\x16"
msg = START_BYTE+ADDR_BYTE+FN_BYTE+CS_BYTE+END_BYTE
ser.write(msg)
you can abstract this out since start and end and address are always the same
def send_fn(ser,FN_CMD):
START_BYTE = "\x10"
ADDR_BYTE = "\xff"
END_BYTE = "\x16"
CS_BYTE = chr((ord(ADDR_BYTE) + ord(FN_CMD))&0xFF)
msg = START_BYTE+ADDR_BYTE+FN_CMD+CS_BYTE+END_BYTE
ser.write(msg)

How to read input from port and print to terminal

here's the situation:
I have two stamps, one connected to port: /dev/ttyUSB1, and one external one, unconnected. The external one has a (Contiki based) program on it to send (every 2 seconds) a single letter across to the stamp that is plugged into the computer. stamp plugged into the computer has a program, also Contiki based, which reads this information via a radio signal.
Now, I have written a python program, making use of pyserial, which aims to read the information coming into the port and display it in terminal. I know the message is arriving correctly as I can print the message from the stamp connected via USB to terminal fine. But I am having trouble reading the information from the python code.
import serial, time, threading
ser = serial.Serial()
ser.port = "/dev/ttyUSB1"
ser.baudrate = 9600
ser.bytesize = serial.SEVENBITS
ser.parity = serial.PARITY_EVEN
ser.timeout = 0.1
ser.rtscts = 1
try:
ser.open()
except Exception, e:
print "error open serial port: " + str(e)
exit()
if ser.isOpen():
try:
numOfLines = 0
while True:
print ser.read()
numOfLines = numOfLines + 1
time.sleep(2)
if (numOfLines >= 50):
break
ser.close()
except Exception, e1:
print "error communicating...: " + str(e1)
else:
print "cannot open serial port "
When run, instead of printing the expected letter sent from the stamp every couple of seconds, it will print a few consistent, yet random letters. For example:
w
z
z
w
g
z
g
z
z
z
w
z
w
There is no output from the program when I remove the USB connected to the stamp. So it must be reading something from the port... Any help would be much appreciated.
It sounds like it could be a problem with the baudrate. you didn't post the code that does this:
ser = serial.Serial('/dev/ttyUSB1', timeout=1, baudrate=9600, rtscts=1)

Using pyserial for sending keystrokes

I have a task where I have to send keystrokes to a machine and to achieve the same I have two machine out of which one is Host Machine (running python scripts) and other is the target machine (where I have to send keystrokes). I am using "L3 Systems Inc's KeyAT device" on COM1.
Now the problem is I am unable to send keystrokes and following is the code I am running.
import serial, time
#initialization and open the port
#possible timeout values:
# 1. None: wait forever, block call
# 2. 0: non-blocking mode, return immediately
# 3. x, x is bigger than 0, float allowed, timeout block call
ser = serial.Serial()
#ser.port = "/dev/ttyUSB0"
ser.port = "COM1"
#ser.port = "/dev/ttyS2"
ser.baudrate = 9600
ser.bytesize = serial.EIGHTBITS #number of bits per bytes
ser.parity = serial.PARITY_NONE #set parity check: no parity
ser.stopbits = serial.STOPBITS_ONE #number of stop bits
#ser.timeout = None #block read
ser.timeout = 1 #non-block read
#ser.timeout = 2 #timeout block read
ser.xonxoff = False #disable software flow control
ser.rtscts = False #disable hardware (RTS/CTS) flow control
ser.dsrdtr = False #disable hardware (DSR/DTR) flow control
ser.writeTimeout = 2 #timeout for write
try:
ser.open()
except Exception, e:
print "error open serial port: " + str(e)
exit()
if ser.isOpen():
try:
ser.flushInput() #flush input buffer, discarding all its contents
ser.flushOutput()#flush output buffer, aborting current output
#and discard all that is in buffer
#write data
# ser.write("AT+CSQ")
ser.write("~~~~~~~~~~\r")
ser.write("~:04\r")
# ser.write('\x03')
#print("write data: AT+CSQ")
time.sleep(0.5) #give the serial port sometime to receive the data
numOfLines = 0
while True:
response = ser.readline()
print("read data: " + response)
numOfLines = numOfLines + 1
if (numOfLines >= 5):
break
ser.close()
except Exception, e1:
print "error communicating...: " + str(e1)
else:
print "cannot open serial port "
Can anyone please help
Thanks,
Vipul
The only problem is the ser.readline() returns binary , you need transform it into string: str(response), so it will work perfectly!

Categories