Using asyncio to read the output of a serial port - python

I have been doing some port-reading for work, and I need to know if I should use asyncIO to read the data that comes in from this port.
Here's some details about the way in which the system is constructed.
Multiple sensors are being read at the same time and might produce output that goes in at the same time. (all data comes in through a probee ZU10 connected to a usb port) All data must be timestamped as soon as it comes in.
The data is supposed to be processed and then sent to a django webapp through a REST API.
The thing Is, it's really important not to lose any data, I'm asking about this because I believe there must be an easier way to do this than the one I'm thinking of.
The way I want the data to come in is through an asyncronous process that takes in the data into a queue and timestamps it, this way there is no way in which loss of data is present, and timestamping may be no more than a few fractions of a second off, which is not a problem.
If anyone has got any ideas I would be thankful for them
Here's the code I'm using to open the port, take the data in and what I've got so far on the actually reading the meaningful data.
Here's the reading part:
import serial #for port opening
import sys #for exceptions
#
#configure the serial connections (the parameters differs on the device you are connecting to)
class Serializer:
def __init__(self, port, baudrate=9600, timeout=.1):
self.port = serial.Serial(port = port, baudrate=baudrate,
timeout=timeout, writeTimeout=timeout)
def open(self):
''' Abre Puerto Serial'''
self.port.open()
def close(self):
''' Cierra Puerto Serial'''
self.port.close()
def send(self, msg):
''' envía mensaje a dispositivo serial'''
self.port.write(msg)
def recv(self):
''' lee salidas del dispositivo serial '''
return self.port.readline()
PORT = '/dev/ttyUSB0' #Esto puede necesitar cambiarse
# test main class made for testing
def main():
test_port = Serializer(port = PORT)
while True:
print(test_port.recv())
if __name__ == "__main__":
main()
And a bit of what I'm going to be using to filter out the meaningful reads (bear with it, it might be full of awful errors and maybe a terrible RegEx):
import re
from Lector import ChecaPuertos
from Lector import entrada
patterns = [r'^{5}[0-9],2[0-9a-fA-F] $'] #pattern list
class IterPat:
def __init__(self, lect, pat = patterns):
self.pat = pat # lista de patrones posibles para sensores
self.lect = lect # lectura siendo analizada
self.patLen = len(pat) #Largo de patrones
def __iter__(self):
self.iteracion = 0 #crea la variable a iterar.
def __next__(self):
'''
Primero revisa si ya pasamos por todas las iteraciones posibles
luego revisa si la iteración es la que pensabamos, de ser así regresa una
tupla con el patrón correspondiente, y la lectura
de otra forma para el valor de ser mostrado
'''
pattern = re.compile(self.pat[self.iteracion])
comp = pattern.match(self.lect)
if comp == True:
re_value = (self.pattern, self.lect)
return re_value
else:
self.iteración += 1
def main():
puerto = ChecaPuertos.serial_ports()
serial = entrada.Serializer(port = puerto[0])
if serial != open:
serial.open()
while True:
iter = IterPat()
#This is incomplete right here.

I am using asyncio to read/write a serial port with pyserial. I am having my device on the other end of the serial connection write a single byte when it is ready to receive a payload. Asyncio watches for that byte then sends the payload. It looks something like this:
serial_f = serial.Serial(port=dev, baudrate=BAUDRATE, timeout=2)
def write_serial():
status = serial_f.read(1)
serial_f.write(buffer)
loop = asyncio.get_event_loop()
loop.add_reader(serial_f.fileno(), write_serial)

Related

Send a def with sockets in python

I have a problem with sockets, I wanna sent the especifications about my pc in a chat created with sockets, but when I use the sentence send() with the function the compiler throw this error... How can I send that information? Thanks. This is the server code.
#importar librerias
import psutil
import platform
from datetime import datetime
from socket import *
uname = platform.uname()
direccionServidor = "localhost"
puertoServidor = 9099
#Generar un nuevo socket
socketServidor = socket (AF_INET, SOCK_STREAM)
#Se establece conexion
socketServidor.bind((direccionServidor, puertoServidor))
socketServidor.listen()
def informacion():
print("="*40, "System Information", "="*40)
print(f"System: {uname.system}")
print(f"Node Name: {uname.node}")
print(f"Release: {uname.release}")
print(f"Version: {uname.version}")
print(f"Machine: {uname.machine}")
print(f"Processor: {uname.processor}")
while True:
# se establece conexion
socketConexion, addr = socketServidor.accept()
print("Conectado con cliente",addr)
while True:
#recibe el mensaje del cliente
mensajeRecibido = socketConexion.recv(4096).decode()
print(mensajeRecibido)
if mensajeRecibido == 'informacion':
socketConexion.send(informacion())
#condicion de salida
if mensajeRecibido == 'exit':
break
socketConexion.send(input().encode())
print("Desconectado del cliente",addr)
#cerramos conexion
socketConexion.close()
The error:
line 39, in <module>
socketConexion.send(informacion())
TypeError: a bytes-like object is required, not 'NoneType'
Like this:
def informacion():
msg = ["="*40, "System Information", "="*40]
msg.append(f"System: {uname.system}")
msg.append(f"Node Name: {uname.node}")
msg.append(f"Release: {uname.release}")
msg.append(f"Version: {uname.version}")
msg.append(f"Machine: {uname.machine}")
msg.append(f"Processor: {uname.processor}")
return '\n'.join(msg)
...
socketConexion.send(information().encode())

PyFirmata Button Doesnt Change Values

Im Using Pyfirmata For A While, And I Want To Connect A Joystick Button On It, I Made The Code (AI) And It Didnt Work, It Keeps Changing Like "True, False, False, True, True..." and doesnt do nothing, heres my python code (PS: im using standart_firmata)
from pyfirmata import *
import time
import speech_recognition as sr
import random
from math import *
class IA:
def __init__(self, board, maquina, analogx, analogy) -> None:
self.board = board
self.maquina = maquina
self.analogx = analogx
self.analogy = analogy
self.button = self.board.get_pin("d:8:i")
self.previous_button_state = 0
self.sr = sr.Recognizer()
def record(self):
with self.sr.Microphone() as source:
print("gravando")
self.sr.adjust_for_ambient_noise(source)
audio = self.sr.listen(source)
try:
frase = sr.recognize_google(audio,language='pt-BR')
frase = frase.lower()
pass
except sr.UnkownValueError:
self.maquina.say("Não Entendi")
self.maquina.runAndWait()
self.main()
if (frase == "olá"):
sentences = ["Olá","Opa","Eae","Oi","Haha Eae"]
sentence = random.choice(tuple(sentences))
self.maquina.say(sentence)
self.maquina.runAndWait()
def main(self):
while True:
print(floor(self.button.read()))
time.sleep(1)
def greet(self):
self.board.digital[2].write(135)
self.maquina.say("Olá! Sou Jesse, Bem Vindo Ao Meu Sistema")
self.maquina.runAndWait()
self.board.digital[2].write(90)
self.maquina.say("Posso Fazer Varias Coisas")
self.maquina.runAndWait()
self.board.digital[2].write(135)
self.maquina.say("Apenas Aperte No Botão Do Joystick E Fale Oque Quer! Divirta-se")
self.maquina.runAndWait()
self.board.digital[2].write(90)
self.board.digital[3].write(75)
self.main()
If anyone can help me, i will be grateful, thanks.

pynput presses are not being detected by some programs

I'm trying to create a remote using my phone for a game with sockets and pynput. Although some apps such as Chrome or Notepad detect and display the keys that have been pressed with the controller function of pynput (press and release), other ones (such as vba-m, the program I was interested in) just don't register any input. I've tried running the script with admin priviledges, but nothing has changed.
This is the code I'm using:
import socket,threading
from pynput.keyboard import Key, Controller
PORT=12345
SERVER="192.168.1.160"
ADDR=(SERVER, PORT)
FORMAT="utf-8"
TERMINATED="ADIOS"
server=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
conectados=[]
conectadosaddr=[]
keyboard = Controller()
def start(): #Función que se encarga de iniciar el servidor y escuchar nuevas conexiones
server.listen()
print("Servidor iniciado")
while True:
conn,addr=server.accept()
conectados.append(conn)
conectadosaddr.append(addr)
thread=threading.Thread(target=handle_client, args=(conn, addr))
thread.daemon=True
thread.start()
print(f"Conexiones activas: {len(conectados)}")
def handle_client(conn, addr): #Función que se encarga de manejar las conexiones
print(f"Nueva conexion de {addr}")
connected=True
while connected:
try:
data=conn.recv(1024).decode(FORMAT)
if data:
print(f"Recibido: {data} de {addr}")
if data==TERMINATED:
connected=False
print("Se ha cerrado la conexion pacíficamente de "+str(addr))
elif data in "WASDZX":
keyboard.press(data)
keyboard.release(data)
elif data=="BK":
keyboard.press(Key.backspace)
keyboard.release(Key.backspace)
elif data=="ST":
keyboard.press(Key.enter)
keyboard.release(Key.enter)
except Exception as e:
connected=False
print("ERROR: ",e)
print(f"{addr} se ha desconectado")
conectados.remove(conn)
conectadosaddr.remove(addr)
conn.close()
if __name__ == '__main__':
start()
I managed to fix the issue using a different library, called "pydirectinput". It does the same thing pynput does, but its presses are detected by vba-m and many other videogames

How to avoid data loss using socket and pyqt with multithread

I am continuously and simultaneously receiving images from multiple clients to a single server. I have used pyqt5 and QRunnable to achieve this. The code will accept the client connection pass it to a thread and start streaming image and data alongwith it in. However I observed that some images are not received/dropped in each thread. Here is my server side thread code which stream images from the clients:
class threading(QRunnable):
def __init__(self,t1,t2,index,ttype,ptype,test):
super(threading,self).__init__()
self.t1=t1
self.t2=t2
self.ch=index
self.ttype=ttype
self.ptype=ptype
self.test=test
self.top1=""
self.bot1=""
self.img1=np.zeros((161,182,3),dtype=np.uint8)
self.signals=WorkerSignals()
self.top_process=top_data()
self.bot_process=bot_data()
def recvall(self,sock, count):
buf = b''
while count:
if sock:
newbuf = sock.recv(count)
if not newbuf: return None
buf += newbuf
count -= len(newbuf)
return buf
def stream(self,conn):
length = '0'
length = (self.recvall(conn,5))
print ('data len',length)
if(length[3]==35):
stringData = self.recvall(conn, int(length[:3]))
elif(length[4]==35):
stringData = self.recvall(conn, int(length[:4]))
else:
stringData = self.recvall(conn, int(length))
print('act len',int(length))
#print('sting 3',stringData)
data = np.frombuffer(stringData, dtype='uint8')
decimg = cv2.imdecode(data,1)
#conn.close()
return decimg
def run(self):
c=1
print('thread',self.ch,self.test)
global b1,b2,b3,b4,b5,b6
if self.test==2:
for fille in os.listdir(b1[self.ch-1]):
if fille.endswith('.jpg'):
os.remove(b1[self.ch-1]+fille)
for fille in os.listdir(b2[self.ch-1]):
if fille.endswith('.jpg'):
os.remove(b2[self.ch-1]+fille)
for fille in os.listdir(b3[self.ch-1]):
if fille.endswith('.jpg'):
os.remove(b3[self.ch-1]+fille)
for fille in os.listdir(b4[self.ch-1]):
if fille.endswith('.jpg'):
os.remove(b4[self.ch-1]+fille)
for fille in os.listdir(b5[self.ch-1]):
if fille.endswith('.jpg'):
os.remove(b5[self.ch-1]+fille)
for fille in os.listdir(b6[self.ch-1]):
if fille.endswith('.jpg'):
os.remove(b6[self.ch-1]+fille)
for fille in os.listdir(b7[self.ch-1]):
if fille.endswith('.jpg'):
os.remove(b7[self.ch-1]+fille)
while not stopEvent.is_set():
img1=self.stream(self.t1)
d1=convertimg(img1)
if self.ch>=7:
self.bot1=self.recvall(self.t2,30)
if self.ch<=6:
self.top1=self.recvall(self.t2,40)
if self.test>0:
if self.ch<=6:
self.top_process.taskvar(self.top1,img1,self.ttype,self.ptype,self.test,self.ch)
self.top_process.start()
self.top_process.signals.finish.connect(self.sendata,Qt.DirectConnection)
if self.ch>=7:
self.bot_process.taskvar(self.bot1,img1,self.ttype,self.ptype,self.test,self.ch)
self.bot_process.start()
if self.ch==1:
self.signals.i1.emit(d1)
if self.ch==2:
self.signals.i2.emit(d1)
if self.ch==3:
self.signals.i3.emit(d1)
if self.ch==4:
self.signals.i4.emit(d1)
if self.ch==5:
self.signals.i5.emit(d1)
if self.ch==6:
self.signals.i6.emit(d1)
if self.ch==7:
self.signals.i7.emit(d1)
if self.ch==8:
self.signals.i8.emit(d1)
if self.ch==9:
self.signals.i9.emit(d1)
if self.ch==10:
self.signals.i10.emit(d1)
if self.ch==11:
self.signals.i11.emit(d1)
if self.ch==12:
self.signals.i12.emit(d1)
c=c+1
There are 12 clients which simultaneously send one image and one string to the server. Can someone tell me why there is a data loss?? is it a race condition or there is error in receiving code.
One way to solve this is to add a mutex.
from PyQt5.QtCore import QMutex
You put it in your init:
self.mutex = QMutex()
Then you lock that part of your code that receives the picture:
if self.mutex.tryLock():
# receive picture
self.mutex.unlock()
For more info and examples you could check the official documentation of
QMutex
Let me know if it works!

Building a server and client with xmlrpc in python

I'm trying to build a client and a server using xmlrpc in python, I HAVE to use a class named FunctionWrapper which has a method and the client use it, the method's name is sendMessage_wrapper(self, message), and the server is declared in another class, I'm trying to register the method in the server but when i call the method from de client I raise and error, can you help me, please?
Cliente:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer
from os import path
sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
from Constants.Constants import *
class MyApiClient:
def __init__(self, contact_port = DEFAULT_PORT,contact_ip=LOCALHOST_CLIENT):
self.contact_port = contact_port
self.contact_ip = contact_ip
self.proxy = xmlrpclib.ServerProxy(contact_ip+str(self.contact_port)+"/")
def sendMessage(self,message):
self.proxy.sendMessage_wrapper(message)
a = MyApiClient()
a.sendMessage("Hi")
a.sendMessage("WORKING")
Server:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer
from os import path
sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
from Constants.Constants import *
class MyApiServer:
def __init__(self,wrapper, my_port = DEFAULT_PORT):
self.port = my_port
self.server = SimpleXMLRPCServer((LOCALHOST,self.port))
self.wrapper = wrapper
self.server.register_instance(self.wrapper)
print("Running")
self.server.serve_forever()
class FunctionWrapper:
def __init__(self):
self.message = None
"""
Procedimiento que ofrece nuestro servidor, este metodo sera llamado
por el cliente con el que estamos hablando, debe de
hacer lo necesario para mostrar el texto en nuestra pantalla.
"""
def sendMessage_wrapper(self, message):
self.message = message
self.showMessage()
def showMessage(self):
print ("Mensaje "+self.message)
#raise NotImplementedError( "Should have implemented this" )
a = FunctionWrapper()
b = MyApiServer(a)
Here are the constants in case you need it
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#Nombres para etiquetas login local y remoto
MY_PORT_NUMBER_TITLE = "Cual es mi puerto?"
OTHER_PORT_NUMBER_TITLE = "Cual es el puerto de contacto?"
OTHER_IP_NUMBER_TITLE = "Cual es la direccion ip de contacto?"
LOGIN_TITLE = "Acceder"
#Nombres para las etiquetas del chat
CONVERSATION_TITLE = "Conversacion"
SEND_TITLE = "Responder"
#Titulo de las ventans GUI
LOGIN_WINDOW = "Login"
CHAT_WINDOW = "Chat"
#Modos de acceso al chat, local o remoto
LOCAL = "Local"
REMOTE = "Remote"
#Mensajes de error
WARNING = "¡Alerta!"
MISSING_MESSAGE = "No hay ningun mensaje para enviar"
#Localhost
LOCALHOST = "localhost"
DEFAULT_PORT = 5000
LOCALHOST_CLIENT = "http://localhost:"

Categories