Python串口监听器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26047544/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 23:57:57  来源:igfitidea点击:

Python serial port listener

pythonserial-portinterruptpyserial

提问by user3817250

I've begun writing some code using PySerial to send and receive data to a serial device.

我已经开始使用 PySerial 编写一些代码来向串行设备发送和接收数据。

Up until now I've only been working on initiating a transaction from a terminal and receiving a response from the serial device.

到目前为止,我一直致力于从终端启动事务并从串行设备接收响应。

pseudo:

伪:

main:
    loop:
        message = get_message()
        send_to_serial(message)
        time_delay(1 second)
        read_response()

Now I'd like to implement a listener on that port in the case that the serial device is the one initiating the communication. Also to remove the time_delaywhich could end up way too long, or not long enough for the serial device to respond.

现在,如果串行设备是发起通信的设备,我想在该端口上实现一个侦听器。还要删除time_delay可能最终太长或不足以让串行设备响应的时间。

state = idle
register_interrupt(serial_device, read_response())

main:
    loop:
        message = get_message()
        state = sending
        send_to_serial(message)

So far I haven't found any PySerial code that uses an interrupt to communicate.

到目前为止,我还没有发现任何使用中断进行通信的 PySerial 代码。

I just have no idea how to set up an interrupt of any sort in python, how would

我只是不知道如何在 python 中设置任何类型的中断,怎么会

回答by James Johnson

It is possible to use the selectmodule to select on a serialconnection:

可以使用该select模块在serial连接上进行选择:

import serial
import select

timeout = 10
conn = serial.Serial(serial_name, baud_rate, timeout=0)
read,_,_ = select.select([conn], [], [], timeout)
read_data = conn.read(0x100)

Below is a full example that creates a pseudo-tty in the main thread. The main thread writes data to the pty in 5 second intervals. A child thread is created that attempts uses select.selectto wait for reading data, as well as using the normal serial.Serial.readmethod to read data from the pty:

下面是在主线程中创建伪 tty 的完整示例。主线程每隔 5 秒将数据写入 pty。创建一个子线程,尝试使用select.select等待读取数据,以及使用正常serial.Serial.read方法从 pty 读取数据:

#!/bin/bash

import os
import pty
import select
import serial
import threading
import time

def out(msg):
    print(msg, flush=True)

# child process
def serial_select():
    time.sleep(1)

    out("CHILD THREAD: connecting to serial {}".format(serial_name))
    conn = serial.Serial(serial_name, timeout=0)
    conn.nonblocking()

    out("CHILD THREAD: selecting on serial connection")
    avail_read, avail_write, avail_error = select.select([conn],[],[], 7)
    out("CHILD THREAD: selected!")

    output = conn.read(0x100)
    out("CHILD THREAD: output was {!r}".format(output))

    out("CHILD THREAD: normal read serial connection, set timeout to 7")
    conn.timeout = 7

    # len("GOODBYE FROM MAIN THREAD") == 24
    # serial.Serial.read will attempt to read NUM bytes for entire
    # duration of the timeout. It will only return once either NUM
    # bytes have been read, OR the timeout has been reached
    output = conn.read(len("GOODBYE FROM MAIN THREAD"))
    out("CHILD THREAD: read data! output was {!r}".format(output))

master, slave = pty.openpty()
serial_name = os.ttyname(slave)

child_thread = threading.Thread(target=serial_select)
child_thread.start()

out("MAIN THREAD: sleeping for 5")
time.sleep(5)

out("MAIN THREAD: writing to serial")
os.write(master, "HELLO FROM MAIN THREAD")

out("MAIN THREAD: sleeping for 5")
time.sleep(5)

out("MAIN THREAD: writing to serial")
os.write(master, "GOODBYE FROM MAIN THREAD")

child_thread.join()

PySerial internally uses select on the read method (if you're on a POSIXsystem), using the timeout provided. However, it will attempt to read NUM bytes until NUM bytes total have been read or until the timeout has been reached. This is why the example explicitly reads len("GOODBYE FROM MAIN THREAD")(24 bytes) from the pty so that the conn.readthe call would return immediately instead of waiting for the entire timeout.

PySerial 在内部使用 select 上的 read 方法(如果您在POSIX系统上),使用提供的超时。但是,它将尝试读取 NUM 字节,直到已读取 NUM 字节总数或直到达到超时。这就是为什么该示例len("GOODBYE FROM MAIN THREAD")从 pty显式读取(24 个字节)以便conn.read调用将立即返回而不是等待整个超时的原因。

TL;DRIt is possible to use serial.Serialconnections with select.select, which is what, I believe, you are looking for.

TL;DR可以使用serial.Serial与 的连接select.select,我相信这是您正在寻找的。