python 实现串口异步和同步接收,根据任意指定“字符”、“byte”、“行”返回接收

内容如题,研究了1天了,在串口控制不同类型的机械臂时碰到命令发出后,等待机械臂对指令、状态的反馈问题,直接上代码,供参考:

# -*- coding: utf-8 -*-
"""
Created on Sun Jul 11 10:19:11 2021

@author: JamesFei
"""


import serial
import time
import threading
import logging

class serial_client:
    ser=None #串口句柄
    exval={
            "com":"COM10",
            "baud":115200,
            "port":6666,
            "host":"localhost"
            }  
    recv_data=None
    def __init__(self, **kwargs): 
        """
        初始化类:
                串口:com="COM7"
                波特率:baud=115200
                web端口:port=6666
                主机地址:host="localhost"
        """
        self.mathods=dir(self) 
        
        for k,v in kwargs.items():
            if k in self.exval.keys():                
                self.exval[k]=v
                
        if self.arm_initialize():
            print("com started")
        
        #print(self.exval["com"])
    
    def arm_initialize(self):
        try:
            self.ser=serial.Serial(self.exval["com"],self.exval["baud"],timeout=0.5)#winsows系统使用com1口连接串行口            
            if self.ser:
                return True
            else:
                return False           
        except Exception as e:
            return False
            logging.error("机械手com---异常---:",e)

    def sendHex_and_receive(self,sendstr,maxt,**kwargs):
        
            """
            sendstr:发送的16进制字符串'10'=b'\x10',
            maxt:最大接收时间,超时强制返回接收
            onreceive:异步回调自定义函数,自定义返回
            stopbyte:接收到指定byte,v,如'\n'即返回接收
            stopword:接收到指定字符,v,如'stop',即返回接收
            stopline:接收到指定行,v,如'EXIT'即返回接收
            """       
            d=bytes.fromhex(sendstr)
            # 串口发送数据
            result=self.ser.write(d)
            #print('send result:',result)
            # 停止、等待数据,这一步非常关键。timeout压根没用
            #time.sleep(t)
            data=b''
            if kwargs:                
                for k,v in kwargs.items():
                    if k=="onreceive":
                        try:
                            self.recv_data=b''
                            print("start receive job!")
                            t0 = threading.Thread(target=v,args=(self,),name="serial_receive")                       
                            t0.setDaemon(True)  # 随着主线程结束而结束
                            t0.start()
                            #t0.join()                            
                            return True,t0
                        except Exception as e:
                            return False,b''
                            logging.error("串口接收---异常---:",e)
                    elif k=="stopbyte":
                        ti=0
                        dt=0.1
                        if type(v)!=type(b''):
                            v=b'\n'                            
                        while ti<maxt:
                            count=self.ser.inWaiting()
                            while count > 0:
                                byte=self.ser.read(1)
                                data += byte
                                if byte==v:
                                    return True,data
                                count-=1                                
                            time.sleep(dt)
                            ti+=dt
                            print("on receive...",ti)
                        if len(data)>0:
                            return True,data
                        else:
                            return False,b''          
                    elif k=="stopword":
                        tword=b''                        
                        ti=0
                        dt=0.1
                        if type(v)!=type(b'') :
                            if type(v)==type(''):
                                v=v.encode("utf-8")
                                logging.warning("wrong type, stopword must be b''!")
                            else:
                                logging.error("wrong type, stopword must be b''!")
                                return False,b''                            
                        while ti<maxt:
                            count=self.ser.inWaiting()                            
                            while count > 0:                                
                                byte=self.ser.read(1)
                                data += byte
                                if byte==b' 'or byte==b'\n' or byte==b'\r' :                                    
                                    if tword==v:
                                        return True,data
                                    else:
                                        tword=b''                                
                                else:
                                    tword+=byte                               
                                count-=1                                
                            time.sleep(dt)
                            ti+=dt
                            print("on receive...",ti)                            
                        if len(data)>0:
                            print("receive time out !")
                            return True,data
                        else:
                            return False,b''      
                    elif k=="stopline":
                        twords=b''                        
                        ti=0
                        dt=0.1
                        if type(v)!=type(b'') :
                            if type(v)==type(''):
                                v=v.encode("utf-8")
                                logging.warning("wrong type, stopword must be b''!")
                            else:
                                logging.error("wrong type, stopword must be b''!")
                                return False,b''                            
                        while ti<maxt:
                            count=self.ser.inWaiting()                            
                            while count > 0:                                
                                byte=self.ser.read(1)
                                data += byte
                                if byte==b'\n' or byte==b'\r' :                                    
                                    if twords==v:
                                        return True,data
                                    else:
                                        twords=b''                                
                                else:
                                    twords+=byte                               
                                count-=1                                
                            time.sleep(dt)
                            ti+=dt
                            print("on receive...",ti)                            
                        if len(data)>0:
                            print("receive time out !")
                            return True,data
                        else:
                            return False,b''   
                    
            else:                 
                # 数据的接收超时返回接收                 
                ti=0
                dt=0.1
                while ti<maxt:
                    count=self.ser.inWaiting()
                    if count > 0:
                        data += self.ser.read(count)
                    ti+=dt
                    time.sleep(dt)
                    print("on receive...",ti)
                if len(data)>0:
                    return True,data
                else:
                    return False,b''
def on_recv(cl): 
    data=b''
    re_outime=5
    ti=0
    dt=1    
    while ti<re_outime:
        count=cl.ser.inWaiting()
        if count > 0:
            data += cl.ser.read(count)             
        ti+=dt
        print("on_recv...",ti)
        time.sleep(dt)
    cl.recv_data=data
   
if __name__ == "__main__":    
    cl=serial_client(com="COM10")  

    #异步接收    
    res,t0=cl.sendHex_and_receive('10',5,onreceive=on_recv)
    print("do something other!")
    t0.join()
    print("receive data",cl.recv_data) 
    
    """
    #接收到指定字符,v,如'stop',即返回接收        
    print("receive data:",cl.sendHex_and_receive("10",5,stopword='stop'))
    
    #接收到指定byte,v,如'\n'即返回接收       
    print("receive data:",cl.sendHex_and_receive("10",5,stopbyte='\n'))

    
     #接收到指定行,v,如'end of line'即返回接收    
    print("receive data:",cl.sendHex_and_receive("10",10,stopline='End of line !'))
    """

    cl.ser.close()
    print("closed!")
    
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JAMES费

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值