首页 > 解决方案 > 如何将串行端口数据读入动态大小的缓冲区?

问题描述

我将此方法用作 WebSocket 客户端实现的一部分,以从串行端口读取数据并将其发送到服务器。我必须封装端口,Arc<Mutex<_>>因为我需要与其他方法共享它,以便在接收到 WebSocket 消息时写入串行端口。

我使用 128 字节u8的缓冲区来存储数据;有没有办法让缓冲区动态调整大小?包裹Arc<Mutex<_>>是必须的。

extern crate env_logger;
extern crate ws;
use std::thread;
use ws::{listen, CloseCode, Handler, Handshake, Message, Result, Sender};

fn on_open(&mut self, _: Handshake) -> Result<(), ws::Error> {
    let port_handle: Arc<Mutex<SystemPort>> = self.port_handle.clone();
    let out: Sender = self.out.clone();
    thread::spawn(move || {
        // read_from_serial(&mut port);
        let mut buffer = [0u8; 128];
        let mut msg: String;
        loop {
            let read_result: Result<usize, std::io::Error>;
            {
                read_result = port_handle
                    .lock()
                    .expect("Access port handle")
                    .read(&mut buffer);
            }
            if read_result.is_ok() {
                msg = buffer_to_string(&buffer);
                buffer = [0u8; 128];
                println!("Client sending message: '{}'", msg);
                out.send(msg).expect("Forward COM message to server");
            }
        }
    });
    Ok(())
}

编辑:这是使用 read_to_string 而不是 read 的相同代码。字符串长度是完全动态的,但唯一的问题是 read_result 总是 Err(Custom { kind: TimedOut, error: StringError("Operation timed out") }) 这里。作为临时修复,我决定不使用 Result 并使用 msg.len() > 0 来测试新的串行消息。

extern crate env_logger;
extern crate ws;
use std::thread;
use ws::{listen, CloseCode, Handler, Handshake, Message, Result, Sender};

fn on_open(&mut self, _: Handshake) -> Result<(), ws::Error> {
            let port_handle = self.port_handle.clone();
            let out = self.out.clone();
            thread::spawn(move || {
                // read_from_serial(&mut port);
                let mut buffer = String::new();
                let mut msg;
                loop {
                    {
                        port_handle
                            .lock()
                            .expect("Access port handle")
                            .read_to_string(&mut buffer);
                        msg = format!("{}", buffer);
                    }
                    if msg.len() > 0 {
                        buffer.clear();
                        println!("Client sending message: '{}'", msg);
                        out.send(msg).expect("Forward COM message to server");
                    }
                }
            });
            Ok(())
        }

编辑:我已经包含了以下最小示例并删除了所有其他不必要的代码。

extern crate env_logger;
extern crate serial;
use serial::prelude::*;
use std::io::Read;
use std::thread;
use std::time::Duration;

fn main() {
    let client = thread::spawn(move || {
        // setting up serial port
        let mut port = serial::open("/dev/tnt0").expect("Open serial port");
        let new_timeout = Duration::from_millis(1000);
        port.set_timeout(new_timeout).expect("Set port timeout");

        // setting up buffer
        let mut buffer = String::new();

        // looping to continuously read serial data
        loop {
            // unused Result returned by read_to_string
            // because when used, it always is an Err variant
            // `Custom { kind: TimedOut, error: StringError("Operation timed out") }`
            port.read_to_string(&mut buffer);
            // using string length to test for valid data instead of using Ok/Err
            if buffer.len() > 0 {
                println!("Client sending message: '{}'", buffer);
                // clearing buffer for next iteration
                buffer.clear();
            }
        }
    });

    // Wait for the worker threads to finish what they are doing
    let _ = client.join();
    println!("All done.")
}

标签: rustserial-portbuffer

解决方案


推荐阅读