串口通信不太完美! Python 跨平台真的太棒了!

670 阅读2分钟

基于 pyserial 开发!

这个程序很简单,自动连接串口,发送一条指令后退出!

这个程序需要在Windows,和Ubuntu上面跑。

唯一改动的就是文件格式,需要转换为 unix 格式  vim 命令 set ff=unix

厉害的是 pyinstaller 居然可以在两个平台上无改动编译成功!太棒了!

配置文件 是json格式。一个字典内套一个字典!

statusLight.py:
实现串口通信
bpsList = [38400, 921600] 这个是波特率的集合,我们这个项目只用到这两种

`#!/usr/bin/env python3

-- coding: utf-8 --

import serial import serial.tools.list_ports import os import sys

class StatusLight(object): ''' 连接串口,实现通信类 '''

# 兼容频率
bpsList = [38400, 921600]
# 端口
ports = serial.tools.list_ports.comports()
 
 
def __init__(self, sendStr, receive, timeout=0.2):
    ''' args:
        sendStr 发送数据 
        reverse 接送数据
        timeout 超时
        # portn 端口
        # bps 波特率
    '''
    self.portn = ""
    self.bps = ""
    self.sendStr = sendStr
    self.receive = receive
    self.timeout = timeout
    self.serial = None # type pyserial.Serial
 
def _connect(self):
    ''' 连接串口 '''
    result = True
    try:
        self.serial = serial.Serial(self.portn, self.bps, timeout=self.timeout)
        self.checkDevice()
    except Exception as e:
        result = False
    return result
     
def setInfo(self, portn, bps, timeout=0.2):
    self.portn = portn
    self.bps = bps
    self.timeout = timeout
    if not self._connect():
        self.automaticAddressing()
 
def close(self):
    ''' 关闭串口通信 '''
    self.serial.close()

def automaticAddressing(self):
    ''' 
        自动寻找设备
        实现方法 发送 sendStr 接受返回 数据 与 receive 匹配
    '''
    breakFlag = False
    for n in StatusLight.ports:
        self.portn = n.device
        for b in StatusLight.bpsList:
            self.bps = b
            if self._connect():
                breakFlag = True
                break
        if breakFlag:
            break
    if breakFlag:
        print('-' * 20)
        print(f'Device   = {self.portn}')
        print(f'Baudrate = {self.bps}')
        print('-' * 20)
    else:
        print("Failed to connect to serial device!")
        sys.exit(1)
 
def checkDevice(self):
    ''' 验证设备 '''
    self.write(self.sendStr)
    serial.time.sleep(0.1)
    byteDate = self.serial.read(1)
    if byteDate != self.receive.encode('gbk'):
        raise ValueError(f"check Device Failed: {send} not equal to {receive}")
         
def write(self, string):
    ''' 发送数据 '''
    self.serial.reset_input_buffer() # 清空输入缓冲器(清空返回值)
    self.serial.write(string.encode('gbk'))
     
def read(self, count=1):
    ''' 读取数据 count = 字节数'''
    return self.serial.read(count)

if name == "main": ser = StatusLight('COM4', 38400) ser.automaticAddressing() print(ser.serial.write("b".encode('gbk'))) serial.time.sleep(0.5) ser.serial.write("d".encode('gbk')) ser.close()`

`#!/usr/bin/env python3# -- coding: utf-8 --

import json import sys import re import os from statusLight import StatusLight

命令行参数

configF = "statusLight" sendStr = "" version = 0.1

def errorPrint(string): print("eg: exe -send=a") print(string) print(sys.argv) sys.exit(1)

def parseCommandLine(): ''' 解析命令行参数 ''' global sendStr, version argv = sys.argv # configFRex = re.compile("-configF=(.+)") sendStrRex = re.compile("-send=(.+)") if len(argv) <= 1: print("eg: exe -send=a") print(f"version: {version}") print("Parse CommandLine Error !") input("Type any key to exit!") sys.exit(1)

for n in argv[1:]:    
    stripN = n.strip()
    # res = configFRex.match(stripN)
    # if res:
        # configF = res.group(1)
    res = sendStrRex.match(stripN)
    if res:
        sendStr = res.group(1)
     
 
if sendStr == "":
    errorPrint("Parse CommandLine Error !")
 

parseCommandLine()

加载本地配置文件

if not os.path.exists(configF): errorPrint(f"file does not exit: {configF}")

config = None with open(configF, encoding='utf-8') as f: config = json.load(f)

s = config['check'].get('s', None) e = config['check'].get('e', None) if s is None or e is None: errorPrint("parse file fail!")

rgb = StatusLight(s, e) rgb.automaticAddressing() rgb.write(sendStr) rgb.close() sys.exit(0)`