Skip to content

Async serial port plugin for Bevy game engine with enhanced error handling and convenience APIs

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

foxzool/bevy_serialport

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

38 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

bevy_serialport

Crates.io Downloads Documentation License CI

Async serial port plugin for the Bevy game engine, providing seamless integration between serial communication and Bevy's ECS system.

Features

  • โœจ Async Serial Communication: Non-blocking serial I/O using Tokio
  • ๐ŸŽฏ Event-Driven Architecture: Receive serial data through Bevy events
  • ๐Ÿ”ง Comprehensive Configuration: Full control over serial port settings
  • ๐Ÿ›ก๏ธ Enhanced Error Handling: Detailed error types with context
  • ๐Ÿš€ High Performance: Optimized for minimal overhead
  • ๐ŸŽฎ Multiple Port Support: Manage multiple serial connections simultaneously
  • ๐Ÿ”Œ Cross-Platform: Works on Windows, macOS, and Linux
  • ๐Ÿ“ฆ Utility Functions: Built-in helpers for port discovery and validation

Quick Start

Add this to your Cargo.toml:

[dependencies]
bevy_serialport = "0.9"
bevy = "0.16"

Basic Usage

use bevy::prelude::*;
use bevy_serialport::{SerialData, SerialPortPlugin, SerialResource, SerialPortRuntime};
use std::time::Duration;

fn main() {
    App::new()
        .add_plugins((
            DefaultPlugins,
            SerialPortPlugin,
        ))
        .add_systems(Startup, setup_serial)
        .add_systems(Update, handle_serial_data)
        .run();
}

fn setup_serial(
    mut serial_res: ResMut<SerialResource>, 
    rt: Res<SerialPortRuntime>
) {
    // Open a serial port with default settings (115200 baud, 8N1)
    if let Err(e) = serial_res.open(rt.clone(), "COM1", 115_200) {
        error!("Failed to open serial port: {}", e);
    }
}

fn handle_serial_data(
    mut serial_events: EventReader<SerialData>,
    mut serial_res: ResMut<SerialResource>,
) {
    for event in serial_events.read() {
        info!("Received from {}: {}", event.port, event.as_string_lossy());
        
        // Echo the data back
        let _ = serial_res.send_string(&event.port, "OK\n");
    }
}

Advanced Configuration

use bevy_serialport::{
    SerialPortSetting, DataBits, FlowControl, Parity, StopBits
};
use std::time::Duration;

fn setup_advanced_serial(
    mut serial_res: ResMut<SerialResource>,
    rt: Res<SerialPortRuntime>
) {
    let settings = SerialPortSetting::new("/dev/ttyUSB0", 9600)
        .with_data_bits(DataBits::Seven)
        .with_parity(Parity::Even)
        .with_stop_bits(StopBits::Two)
        .with_flow_control(FlowControl::Software)
        .with_timeout(Duration::from_millis(100));

    match serial_res.open_with_setting(rt.clone(), settings) {
        Ok(_) => info!("Serial port configured successfully"),
        Err(e) => error!("Configuration failed: {}", e),
    }
}

Port Discovery

use bevy_serialport::utils::*;

fn discover_ports() {
    match list_available_ports() {
        Ok(ports) => {
            info!("Available ports:");
            for port in ports {
                info!("  - {}", port);
            }
        }
        Err(e) => error!("Failed to list ports: {}", e),
    }
}

Multiple Ports

fn setup_multiple_ports(
    mut serial_res: ResMut<SerialResource>,
    rt: Res<SerialPortRuntime>
) {
    let ports = vec![
        ("sensor_port", "/dev/ttyUSB0", 9600),
        ("gps_port", "/dev/ttyUSB1", 4800),
        ("debug_port", "COM3", 115200),
    ];

    for (name, port, baud) in ports {
        if let Err(e) = serial_res.open(rt.clone(), port, baud) {
            error!("Failed to open {}: {}", name, e);
        } else {
            info!("Opened {} on {}", name, port);
        }
    }
}

fn handle_multiple_ports(mut serial_events: EventReader<SerialData>) {
    for event in serial_events.read() {
        match event.port.as_str() {
            "/dev/ttyUSB0" => handle_sensor_data(&event),
            "/dev/ttyUSB1" => handle_gps_data(&event),
            "COM3" => handle_debug_data(&event),
            _ => warn!("Unknown port: {}", event.port),
        }
    }
}

Error Handling

The library provides comprehensive error handling:

use bevy_serialport::SerialError;

fn robust_serial_setup(
    mut serial_res: ResMut<SerialResource>,
    rt: Res<SerialPortRuntime>
) {
    match serial_res.open(rt.clone(), "COM1", 115200) {
        Ok(_) => info!("Port opened successfully"),
        Err(SerialError::SerialPortError { port, source }) => {
            error!("Hardware error on {}: {}", port, source);
        }
        Err(SerialError::InvalidConfiguration { reason }) => {
            error!("Configuration error: {}", reason);
        }
        Err(SerialError::PortNotFound { port }) => {
            error!("Port {} not found", port);
        }
        Err(e) => error!("Other error: {}", e),
    }
}

SerialData API

The SerialData event provides convenient methods for data access:

fn process_serial_data(mut events: EventReader<SerialData>) {
    for event in events.read() {
        // Get data as string (lossy conversion)
        let text = event.as_string_lossy();
        
        // Try to get data as valid UTF-8 string
        match event.as_string() {
            Ok(valid_text) => info!("Valid UTF-8: {}", valid_text),
            Err(_) => warn!("Invalid UTF-8 data received"),
        }
        
        // Access raw bytes
        let bytes = event.as_bytes();
        info!("Received {} bytes from {}", bytes.len(), event.port);
        
        // Check if empty
        if event.is_empty() {
            warn!("Empty message received");
        }
    }
}

Examples

The repository includes several examples:

  • Basic Receiver: cargo run --example serial_receiver -- --port COM1
  • Basic Sender: cargo run --example serial_sender -- --port COM1
  • Advanced Usage: cargo run --example advanced_usage

Supported Platforms

Platform Status Notes
Windows โœ… COM ports (COM1, COM2, etc.)
Linux โœ… USB/UART devices (/dev/ttyUSB0, /dev/ttyACM0, etc.)
macOS โœ… USB/UART devices (/dev/cu., /dev/tty.)

Bevy Compatibility

Bevy Version bevy_serialport Version
0.16 0.9
0.15 0.8
0.14 0.7
0.13 0.6
0.12 0.5
0.11 0.4
0.10 0.3
0.9 0.2
0.8 0.1

Common Use Cases

  • ๐Ÿ”ฌ Scientific Instruments: Communicate with sensors and measurement devices
  • ๐Ÿค– Robotics: Control motors, read sensors, and communicate with microcontrollers
  • ๐ŸŽฎ Game Controllers: Interface with custom hardware controllers
  • ๐Ÿ“ก IoT Integration: Connect with embedded devices and sensors
  • ๐Ÿ”ง Development Tools: Debug interfaces and diagnostic tools

Performance Considerations

  • Uses Tokio's async runtime for non-blocking I/O
  • Minimal memory allocations in the hot path
  • Efficient message batching for high-throughput scenarios
  • Thread-safe design with minimal locking overhead

Troubleshooting

Port Not Found

# Linux: Check available ports
ls /dev/tty*

# Windows: Use Device Manager or PowerShell
Get-WmiObject -Class Win32_SerialPort | Select-Object Name,DeviceID

Permission Denied (Linux)

# Add user to dialout group
sudo usermod -a -G dialout $USER
# Then logout and login again

Port Already in Use

Ensure no other applications are using the serial port. On Linux, you can check with:

lsof /dev/ttyUSB0

Contributing

We welcome contributions! Please see our Contributing Guide for details.

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if applicable
  5. Submit a pull request

License

This project is dual-licensed under either:

At your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Acknowledgments

  • Built on top of tokio-serial for async serial communication
  • Inspired by the Bevy community's commitment to ergonomic game development
  • Thanks to all contributors and users who have helped improve this library

For more information, visit the documentation or check out the repository.

About

Async serial port plugin for Bevy game engine with enhanced error handling and convenience APIs

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages