use std::sync::Arc;
use oms_modbus::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let port_name = "COM20"; let baud_rate = 9600;
println!("═══ OMS Modbus — RTU Serial Server ═══\n");
println!("Port: {port_name} | Baud: {baud_rate} | Format: 8N1\n");
println!("[1/4] Opening {port_name} …");
let port = tokio_serial::SerialStream::open(
&tokio_serial::new(port_name, baud_rate)
.data_bits(tokio_serial::DataBits::Eight)
.parity(tokio_serial::Parity::None)
.stop_bits(tokio_serial::StopBits::One)
.flow_control(tokio_serial::FlowControl::None),
)
.map_err(|e| {
format!(
"Cannot open {port_name}: {e}\n\
Check: ① port exists ② not locked by another program"
)
})?;
println!(" ✓ Port opened (8N1, no flow control)\n");
println!("[2/4] Configuring bus timing …");
let bus_timing = Arc::new(BusTiming::rtu_35t(baud_rate)); println!(
" ✓ 3.5T ≈ {:.2} ms @ {baud_rate} baud\n",
bus_timing.min_spacing().as_secs_f64() * 1000.0,
);
println!("[3/4] Initializing SlaveStore …");
let store = Arc::new(SlaveStore::with_holding_registers(&[
(0, 1234), (1, 5678), (2, 100), (3, 42), (10, 500), (11, 600), (20, 0), ]));
store.write_input_register(0, 2400); store.write_input_register(1, 150);
store.write_coil(0, true); store.write_coil(1, false); store.write_coil(2, true);
store.write_discrete_input(0, true); store.write_discrete_input(1, false);
println!(" ✓ Store ready: 7 holding regs, 2 input regs, 3 coils, 2 DIs\n");
println!("[4/4] Creating RTU server …");
let server = rtu::RtuServer::new(port).with_bus_timing(bus_timing);
println!(" ✓ Server ready on {port_name}\n");
println!("─── Register Map ───");
println!(" Holding[ 0.. 3] = [1234, 5678, 100, 42]");
println!(" Holding[10..11] = [500, 600] (setpoints)");
println!(" Holding[20] = 0 (counter)");
println!(" Input[0..1] = [2400, 150] (analog inputs)");
println!(" Coils[0..2] = ON, OFF, ON");
println!(" DI[0..1] = ON, OFF\n");
println!("Serving … (press Ctrl+C to stop)\n");
server.serve_forever(store).await?;
Ok(())
}