Git Product home page Git Product logo

mio-serial's Introduction

Crates.io MIT licensed Build Status

mio-serial: A serial port IO library MIO.

mio-serial provides a serial port implementation using mio.

Usage

Add mio-serial to you Cargo.toml:

[dependencies]
mio-serial = "5.0.1"

Then add this to your crate root:

extern crate mio_serial;

Features

The "libudev" dependency of serialport-rs is enabled by default. For x86 linux systems this enables the available_ports function for port enumeration. Not all targets support udev, especially when cross-compiling. To disable this feature, compile with the --no-default-features option. For example:

cargo build --no-default-features

MSRV

The Minimum Supported Rust Version is 1.60.0 as found using cargo-msrv

Examples

A few examples can be found here.

Tests

Useful tests for serial ports require... serial ports, and serial ports are not often provided by online CI providers. As so, automated build testing are really only check whether the code compiles, not whether it works.

Integration tests are in the tests/ directory and typically require two serial ports to run. The names of the serial ports can be configured at run time by setting the TEST_PORT_NAMES environment variable to a semi-colon delimited string with the two serial port names. The default values are:

  • For Unix: TEST_PORT_NAMES=/dev/ttyUSB0;/dev/ttyUSB1
  • For Windows: TEST_PORT_NAMES=COM1;COM2

IMPORTANT To prevent multiple tests from talking to the same ports at the same time make sure to limit the number of test threads to 1 using:

cargo test -j1 -- --test-threads=1

License

This software is licensed under MIT.

This software builds upon the MPL-2.0 licensed serialport-rs and constitutes a "Larger Work" by that license. The source for serialport-rs can be found at https://gitlab.com/susurrus/serialport-rs.

mio-serial's People

Contributors

andful avatar berkowski avatar dvtomas avatar estokes avatar flosse avatar g0hl1n avatar macosten avatar mettz avatar ndusart avatar vleesvlieg avatar yuja avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mio-serial's Issues

how to control RTS and DTR?

in serialport, it provide port.write_request_to_send and port.write_data_terminal_ready.

but these two function in this lib is private

How to modify device parameters or stop the device during data reading?

for the example:
examples\read_serialport.rs

poll.registry()
        .register(&mut rx, SERIAL_TOKEN, Interest::READABLE)
        .unwrap();
loop {
        poll.poll(&mut events, None)?;
        // handle the read event
        // ...
}

How to modify device parameters or stop the device during data reading?

Any good ideas for implementing this? thanks~

Windows try_clone returns incorrect trait

If I call mio_serial::from_path I get back an instance of the mio_serial::Serial object and calling read/write calls the read/write traits implemented in the mio_serial's windows.rs file.

If I then call try_clone on that instance, it returns self.inner.try_clone which returns an instance of serialport's windows::COMPort and calling read/write on that calls the read/write from serialport rather than the read/write from mio_serial (verified by adding some println's.

This in turn causes a parameter error, since the mio_serial instance calls CreateFileW with the FILE_FLAG_OVERLAPPED flag, which in turns means that ReadFile/WriteFile need to be called with a non-NULL lpOverlapped parameter.

Here's my sample program which reproduces the problem. I was using a USB FTDI adapter with Tx jumpered to Rx so it should receive back what it sends.

use std::io::Read;
use std::io::Write;
use mio_serial::{SerialPort, SerialPortSettings};

fn main() {
  let settings = SerialPortSettings::default();
  if let Ok(mut rx_port) = mio_serial::Serial::from_path("COM6", &settings) {
    let mut tx_port = rx_port.try_clone().unwrap();
    let tx_result = tx_port.write("This is a test".as_bytes());
    println!("tx_result: {:?}", tx_result);
    
    let mut buf: [u8; 14] = [0; 14];
    let rx_result = rx_port.read(&mut buf);
    println!("rx_result: {:?}", rx_result);
  }
}

running this with a println! inside serialport/mio-serial's read/write methods yields this output:

serialport: write: [84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 116, 101, 115, 116] called handle = 0x94
tx_result: Err(Os { code: 87, kind: Other, message: "The parameter is incorrect." })
mio-serial: read called
rx_result: Err(Custom { kind: WouldBlock, error: "would block" })

So we can see that the serialport write function is being called rather than the mio-serial's write and we also get the Invalid parameter because serialport's write passes in NULL for lpOverlapped.

Add a repo description

No description, website, or topics provided.

From crates.io:

mio-serial: A serial port IO library MIO.
mio-serial provides a serial port implementation using mio.

Your tokio repo says:

A serial port implementation for tokio

How close is `Source` to a `Stream<..some bytes type..>`?

I'm trying to read and write a serial port using streaming, and would like to do it without Tokio dependencies.

mio-serial looks close, but I'm a newbie to Async Rust and cannot estimate "how close". Some observations:

  • Stream is not stable in Rust; I am aware of that
  • SerialStream in this repo does not implement futures::Stream. That is fine - things change and I am not complaining. Just that my initial expectation by the name was ... that it would. Silly me!

I am okey making some glue code in my own code. What I want is to implement the ASH protocol (Silicon Labs, PDF) in Rust. It's an async protocol for UART comms. Two messages can be "in flight" - very suitable for async/.await imho.

I noticed the code has Source but I am not sure what I can do with it.

How close is this to Stream and Sink of bytes, in the fashion that futures_util defines them?

Can't compile as dependency to another project

I'm getting this error when trying to compile a project that uses mio-serial as a dependency. However, I can clone this repo and build successfully. Any ideas on what to try?

error[E0308]: mismatched types
   --> C:\Users\zachkozar\.cargo\registry\src\github.com-1ecc6299db9ec823\mio-serial-5.0.2\src\lib.rs:822:42
    |
822 |         let r = unsafe { SetCommTimeouts(handle, &mut timeouts) };
    |                                          ^^^^^^ expected enum `winapi::ctypes::c_void`, found enum `std::ffi::c_void`
    |
    = note: expected raw pointer `*mut winapi::ctypes::c_void`
               found raw pointer `*mut std::ffi::c_void`

Are there more read/write examples or better docs available?

Hi,

currently trying to use this as part of an egui application to send SCPI commands via serial to a multimeter and then later on read the responses.

What I have working is sending something that does not prompt a response like 'SYST:REM', which also successfully puts theMultimeter in remote control mode.

                        self.serial = mio_serial::new(&self.serial_port, self.baud_rate)
                            .open_native_async()
                            .ok();
                        if let Some(serial) = &mut self.serial {
                            let res = self.poll.registry().register(
                                serial,
                                SERIAL_TOKEN,
                                Interest::READABLE | Interest::WRITABLE,
                            );
                            println!("Registry: {:?}", res);
                            serial.set_data_bits(DataBits::Eight);
                            serial.set_stop_bits(mio_serial::StopBits::One);
                            serial.set_parity(mio_serial::Parity::None);
                            let res = serial.write("SYST:REM\n".as_bytes());

But then I try the IDN command, which by itself runs:

                            let res = serial.write("*IDN?\n".as_bytes());
                            println!("*IDN?: {:?}", res);

But then I try to to read it, get nothing back, and the program hangs indefinetly and crashes:
(this if-block runs in the egui update function which is basically already an event loop, so at the start I check for open events
and try to gather the newest serial data before rendering the UI)

        if let Some(serial) = &mut self.serial {
            // Poll to check if we have serial events waiting for us.
            let res = self.poll.poll(&mut self.events, None);
            println!("Poll: {:?}", res);

            // buffer for read data
            let mut buf = vec![];

            // Process each event.
            for event in self.events.iter() {
                // Validate the token we registered our socket with,
                // in this example it will only ever be one but we
                // make sure it's valid none the less.
                match event.token() {
                    SERIAL_TOKEN => loop {
                        // In this loop we receive all packets queued for the socket.
                        match serial.read(&mut buf) {
                            Ok(count) => {
                                println!("{:?}", String::from_utf8_lossy(&buf[..count]));
                                self.device = String::from_utf8_lossy(&buf).to_string();
                            }
                            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                                println!("WouldBlock escape");
                                break;
                            }
                            Err(e) => {
                                println!("Quitting due to read error: {}", e);
                                // return Err(e);
                            }
                        }
                    },
                    _ => {
                        // This should never happen as there is only one port open
                    }
                }
            }
        }

So yeah, this probably isn't a 'classic' issue but I am lost and stuck with this and don't know why it does not work.
I tried using PUTTY to send the SCPI commands and all works as expected.

Missing 4.0.0-beta1 tag

Hello

I am running into a build issue described in detail here(stepfunc/dnp3#131) root cause of which seems to be that this repo is missing a tag called 4.0.0-beta1.

Seeing that there's now a tag called 4.0.0-beta2 tag I'm assuming beta1 used to exist but doesn't anymore?

I was wondering if you could restore the tag, since this was a breaking change

Thank you

mio-serial example on Windows 8 spams "Read would have blocked." and "Read timed out!"

Hello!

I'm running the example serial_printline.rs proggram on a Windows 8 machine with a USB Serial device attached.

The serial device emits the string "hello.\n" every second, which the serial_printline.rs example successfully prints, but the example also spams the "Read would have blocked" and "Read timed out" messages (which it does not in Linux).

I believe this is also affecting the tokio-serial example running in Windows. tokio::run() returns (almost) immediately in Windows in the tokio-serial example, while it runs indefinitely in Linux.

libudev problems

It fails to compile with: /usr/lib/libudev.so: file not recognized: File format not recognized
cargo build --target=armv7-unknown-linux-gnueabihf Any idea of how to solve that ?

My cargo file

[dependencies]
clap = "2.31.2"
libc = "0.2.*"
mio = "0.6"
mio-serial = "3.*"
serialport = "3.*"

Be ready for serialport-rs v2.0

Development work in the serialport-2 branch.

@ndusart provided the majority of the API adaption with #1.

TODO:

  • Fix upstream issues until OSX/BSD targets compile (when nix v0.10 releases?)
  • Pull windows implementation @ndusart (#4)
  • Tag serialport-rs to a released version instead of git in Cargo.toml
  • Tag nix to a released version instead of git in Cargo.toml

mio 0.7 support

I was about to fork and add support for mio 0.7. It's mostly a matter of switching from Evented to event::Source. However, @raffber has already done so in raffber/mio-serial. It would be great if his change could be pulled in and pushed to crates.io.

Better examples

I've been thinking about using mio-serial in a project but I'm a bit confused about the scope of this crate and how to properly used it.

Generally it looks a bit awkward to use 😕 so maybe that could be improved.

(Although I would be wondering if you're interested in talking about API design and the scope of what the library should do 😜)

Signaling WouldBlock with empty data?

Hi,
I'm a little bit confused about how a WouldBlock is signalled.

Mio doc states:

With edge-triggered events, operations must be performed on the Evented type until WouldBlock is returned. In other words, after receiving an event indicating readiness for a certain operation, one should assume that Poll::poll may never return another event for the same token and readiness until the operation returns WouldBlock.

But your example goes like this:

match rx.read(&mut rx_buf) {
	Ok(b) => match b {
		b if b > 0 => {
			println!("{:?}", String::from_utf8_lossy(&rx_buf[..b]))
		}
		_ => println!("Read would have blocked."),
	},
	Err(e) => println!("Error:  {}", e),
}

i.e. it seems that blocking, and thus a signal that we can stop performing read on the serial port, is signaled via empty data. Is this a behavior not obeying the specs, or just me misunderstanding something?

On a related note: In your example is this:

if is_closed(ready) {
	println!("Quitting due to event: {:?}", ready);
	break 'outer;
}

Can I decide not to handle is_closed() explicitly, and just rely on rx.read() returning an error if the port becomes closed?

mio-serial v3.0.0 not compatible with serialport v3.1.0

The serialport crate (https://docs.rs/crate/serialport/%5E3.0) which is listed as a dependency recently got updated to version 3.1.0 from version 3.0.0. In this change 3 new functions got added to the SerialPort trait, and as a result the Serial implementation in mio-serial won't compile:

...
Compiling serialport v3.1.0
Compiling mio-serial v3.0.0
error[E0046]: not all trait items implemented, missing: `bytes_to_read`, `bytes_to_write`, `clear`
   --> /home/nrt/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-serial-3.0.0/src/unix.rs:137:1
    |
137 | impl SerialPort for Serial {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `bytes_to_read`, `bytes_to_write`, `clear` in implementation
    |
    = note: `bytes_to_read` from trait: `fn(&Self) -> std::result::Result<u32, serialport::Error>`
    = note: `bytes_to_write` from trait: `fn(&Self) -> std::result::Result<u32, serialport::Error>`
    = note: `clear` from trait: `fn(&Self, serialport::ClearBuffer) -> std::result::Result<(), serialport::Error>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0046`.
error: Could not compile `mio-serial`.

Easiest fix would be to just update the cargo.toml to specify 3.0.0 until those functions can be implemented.

mio-serial-4.0.0-beta3 fails to compile due to StdIoErrorKind::Unsupported

Our CI server turned up the following new compilation error since the release of 4.0.0-beta3:

error[E0599]: no variant or associated item named `Unsupported` found for enum `std::io::ErrorKind` in the current scope
   --> /builds/straw/strand-braid/.cargo-proj/registry/src/github.com-1ecc6299db9ec823/mio-serial-4.0.0-beta3/src/lib.rs:516:50
    |
516 |             crate::ErrorKind::Io(StdIoErrorKind::Unsupported),
    |                                                  ^^^^^^^^^^^ variant or associated item not found in `std::io::ErrorKind`

Steps to reproduce:

git clone https://github.com/strawlab/strand-braid
cd strand-braid/camtrig
cargo check

This was using rustc 1.52.1 .

I'm really looking forward to mio-serial 4.0, thanks for your work on that!

Push for v4.0 before Ownership Transfer or Maintenence

My motivation to keep mio-serial up to date with the async ecosystem has long since waned and it shouldn't be the limiting factor for other people. I'd like to get this crate back in a usable state with mio 0.7, with then a planned transfer of ownership to someone more active in the space. Or failing such, explicit notice that the package will no longer be actively developed.

  • Get CI working again. travis-ci isn't viable anymore I guess.
  • Get mio 0.7 support working at least at a beta level
  • Transfer crates.io publishing key to new maintainer

It looks like the v4.0_serialstream branch is pretty close. It's already been merged to master. Seems like most of the effort here is figuring out a new CI solution for windows/linux/osx.

Windows support

The docs state At this time this crate ONLY provides a unix implementation but the crate seems to provide a Windows implementation. Are the docs just out of date or are there still issues with Windows support?

Invalid stop bits setting encountered

let mut rx = serialport::new(&args.port, args.baud_rate).open_native_async()?;

error on this line

Error: Custom { kind: Other, error: "Invalid stop bits setting encountered" }

some software serialport doesen't support this (like esp32c3's usb software serialport)

I change that line code to this, then it's ok

let stop_bits = port.stop_bits().unwrap_or(StopBits::One);

cann't open serial again

when SerialStream was dropped, the member "inner: mem::ManuallyDropserialport::COMPort" was not dropped, this will prevent to open the serial again.

image

in the code: examples\read_serialport.rs

image

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.