use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::sync::Arc;
use std::time::Duration;
use oms_modbus::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("═══ OMS Modbus — All Function Codes Demo ═══\n");
println!("[1/2] Starting TCP server …");
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0);
let server = tcp::TcpServer::bind(addr).await?;
let bind_addr = server.local_addr()?;
let store = Arc::new(SlaveStore::with_holding_registers(&[
(0, 100), (1, 200), (10, 500), (20, 1000), (21, 2000),
(22, 3000),
]));
store.write_coil(0, true);
store.write_coil(1, false);
store.write_coil(2, true);
let svc = store.clone();
tokio::spawn(async move {
server.serve_forever(svc).await.ok();
});
tokio::time::sleep(Duration::from_millis(50)).await;
let cap = Arc::new(BusCapture::unbounded());
let opts = ClientOptions::default()
.with_timeout(Duration::from_secs(3))
.with_tap(cap.clone());
let client = tcp::with_options(bind_addr, opts).await?;
println!(" ✓ Server on {bind_addr}\n");
println!("[2/2] Demonstrating all function codes …\n");
println!("─── FC01 Read Coils ───");
let coils = client.read_coils(1, 0, 8).await?;
println!(" Coils[0..8] = {coils:?}");
println!("\n─── FC02 Read Discrete Inputs ───");
let inputs = client.read_discrete_inputs(1, 0, 4).await?;
println!(" DiscreteInputs[0..4] = {inputs:?}");
println!("\n─── FC03 Read Holding Registers ───");
let regs = client.read_holding_registers(1, 0, 3).await?;
println!(" Holding[0..3] = {regs:?}");
println!("\n─── FC04 Read Input Registers ───");
let regs = client.read_input_registers(1, 0, 2).await?;
println!(" InputReg[0..2] = {regs:?}");
println!("\n─── FC05 Write Single Coil ───");
println!(" Before: Coil[1] = {}", coils[1]);
client.write_single_coil(1, 1, true).await?;
let coils = client.read_coils(1, 0, 3).await?;
println!(" After: Coil[1] = {}", coils[1]);
println!("\n─── FC06 Write Single Register ───");
client.write_single_register(1, 0, 7777).await?;
let regs = client.read_holding_registers(1, 0, 1).await?;
println!(" Holding[0] = {} (was 100, now 7777)", regs[0]);
println!("\n─── FC15 Write Multiple Coils ───");
client
.write_multiple_coils(1, 0, &[true, true, false, false])
.await?;
let coils = client.read_coils(1, 0, 4).await?;
println!(" Coils[0..4] = {coils:?}");
println!("\n─── FC16 Write Multiple Registers ───");
client
.write_multiple_registers(1, 0, &[111, 222, 333])
.await?;
let regs = client.read_holding_registers(1, 0, 3).await?;
println!(" Holding[0..3] = {regs:?}");
println!("\n─── FC22 Mask Write Register ───");
println!(
" Before: Holding[10] = {}",
store.read_holding_register(10)
);
client.mask_write_register(1, 10, 0x00FF, 0xFF00).await?;
let regs = client.read_holding_registers(1, 10, 1).await?;
println!(
" After: Holding[10] = {:#06X} (AND=0x00FF, OR=0xFF00)",
regs[0]
);
println!("\n─── FC23 Read/Write Multiple Registers ───");
let read_back = client
.read_write_multiple_registers(1, 20, 4, 20, &[100, 200, 300])
.await?;
println!(" Old values [20..23] = {read_back:?}");
let regs = client.read_holding_registers(1, 20, 4).await?;
println!(" New values [20..23] = {regs:?}");
println!("\n═══ Capture Summary ═══");
println!(" Requests: {}", cap.count_requests());
println!(" Responses: {}", cap.count_responses());
println!(" Errors: {}", cap.count_errors());
println!("\n═══ Summary ═══");
println!(" ✓ All 10 standard function codes demonstrated");
println!(
" ✓ BusCapture monitoring: {}/{} success rate",
cap.count_responses(),
cap.count_requests()
);
Ok(())
}