use std::time::Duration;
use tokio::time::sleep;
use voltage_modbus::{
regs_to_f32, ByteOrder, DeviceLimits, ModbusClient, ModbusTcpClient, ModbusValue,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("🚀 Voltage Modbus v0.4.2 Demo");
println!("=============================");
println!("Industrial Enhancement Features Showcase\n");
println!("📦 Part 1: Industrial Data Types (ModbusValue)");
println!("-----------------------------------------------");
let values = [
ModbusValue::U16(1234),
ModbusValue::I16(-500),
ModbusValue::U32(100000),
ModbusValue::I32(-50000),
ModbusValue::F32(std::f32::consts::PI),
ModbusValue::F64(std::f64::consts::E),
ModbusValue::Bool(true),
];
for value in &values {
println!(
" {} -> as_f64: {:.4}, registers: {}",
value,
value.as_f64(),
value.register_count()
);
}
println!("\n🔄 Part 2: Byte Order Handling");
println!("-------------------------------");
let byte_orders = [
ByteOrder::BigEndian,
ByteOrder::LittleEndian,
ByteOrder::BigEndianSwap,
ByteOrder::LittleEndianSwap,
];
let test_regs: [u16; 2] = [0x4248, 0x0000]; println!(
" Test registers: {:04X} {:04X}",
test_regs[0], test_regs[1]
);
for order in &byte_orders {
let f32_val = voltage_modbus::regs_to_f32(&test_regs, *order);
println!(" {:?} -> f32: {:.2}", order, f32_val);
}
println!("\n📊 Part 3: Data Encoding/Decoding");
println!("----------------------------------");
let f32_value: f32 = 123.456;
let f32_bytes = f32_value.to_be_bytes();
let encoded_f32 = [
u16::from_be_bytes([f32_bytes[0], f32_bytes[1]]),
u16::from_be_bytes([f32_bytes[2], f32_bytes[3]]),
];
println!(
" F32 {} -> registers: {:04X} {:04X}",
f32_value, encoded_f32[0], encoded_f32[1]
);
let decoded_f32 = regs_to_f32(&encoded_f32, ByteOrder::BigEndian);
println!(" Decoded F32: {:.3}", decoded_f32);
let u32_value: u32 = 0x12345678;
let encoded_u32 = [(u32_value >> 16) as u16, (u32_value & 0xFFFF) as u16];
println!(
" U32 0x{:08X} -> registers: {:04X} {:04X}",
u32_value, encoded_u32[0], encoded_u32[1]
);
println!("\n🎛️ Part 4: DeviceLimits - Protocol Configuration");
println!("-------------------------------------------------");
let default_limits = DeviceLimits::default();
println!(" Default limits:");
println!(
" Max read registers: {}",
default_limits.max_read_registers
);
println!(
" Max write registers: {}",
default_limits.max_write_registers
);
println!(" Max read coils: {}", default_limits.max_read_coils);
println!(
" Inter-request delay: {}ms",
default_limits.inter_request_delay_ms
);
let custom_limits = DeviceLimits::new()
.with_max_read_registers(50)
.with_max_write_registers(20)
.with_inter_request_delay_ms(100);
println!(" Custom limits:");
println!(
" Max read registers: {}",
custom_limits.max_read_registers
);
println!(
" Inter-request delay: {}ms",
custom_limits.inter_request_delay_ms
);
println!("\n🔌 Part 5: TCP Client Operations");
println!("---------------------------------");
let server_address = std::env::args()
.nth(1)
.unwrap_or_else(|| "127.0.0.1:502".to_string());
println!(" Connecting to {}...", server_address);
let timeout = Duration::from_secs(5);
let mut client = match ModbusTcpClient::from_address(&server_address, timeout).await {
Ok(client) => {
println!(" ✅ Connected successfully!");
client
}
Err(e) => {
println!(" ⚠️ Connection failed: {}", e);
println!(" (This is expected if no Modbus server is running)");
println!("\n🎉 Demo completed! (TCP operations skipped)");
return Ok(());
}
};
let slave_id = 1;
println!("\n 📖 Read Operations:");
match client.read_03(slave_id, 0, 5).await {
Ok(values) => {
println!(" FC03 Holding registers 0-4: {:?}", values);
if values.len() >= 2 {
let f32_val = regs_to_f32(&[values[0], values[1]], ByteOrder::BigEndian);
println!(" -> First 2 registers as F32: {:.4}", f32_val);
}
}
Err(e) => println!(" FC03 Error: {}", e),
}
sleep(Duration::from_millis(50)).await;
match client.read_01(slave_id, 0, 8).await {
Ok(coils) => {
let states: Vec<&str> = coils
.iter()
.map(|&c| if c { "ON" } else { "OFF" })
.collect();
println!(" FC01 Coils 0-7: {:?}", states);
}
Err(e) => println!(" FC01 Error: {}", e),
}
println!("\n ✏️ Write Operations:");
match client.write_06(slave_id, 100, 0x1234).await {
Ok(_) => println!(" FC06 Wrote register 100 = 0x1234"),
Err(e) => println!(" FC06 Error: {}", e),
}
sleep(Duration::from_millis(50)).await;
let temp: f32 = 98.6;
let temp_bytes = temp.to_be_bytes();
let f32_regs = [
u16::from_be_bytes([temp_bytes[0], temp_bytes[1]]),
u16::from_be_bytes([temp_bytes[2], temp_bytes[3]]),
];
match client.write_10(slave_id, 200, &f32_regs).await {
Ok(_) => println!(" FC16 Wrote F32 98.6 to registers 200-201"),
Err(e) => println!(" FC16 Error: {}", e),
}
let stats = client.get_stats();
println!("\n 📊 Statistics:");
println!(
" Requests: {}, Responses: {}",
stats.requests_sent, stats.responses_received
);
println!(
" Bytes sent: {}, received: {}",
stats.bytes_sent, stats.bytes_received
);
if let Err(e) = client.close().await {
eprintln!(" ⚠️ Close error: {}", e);
}
println!("\n🎉 Demo completed!");
println!("📚 Documentation: https://docs.rs/voltage_modbus");
println!("🔗 Repository: https://github.com/EvanL1/voltage_modbus");
Ok(())
}