Professional Documents
Culture Documents
Self "%Y-%m-%dT%H:%M:%S. %:Z"
Self "%Y-%m-%dT%H:%M:%S. %:Z"
rs Strona 1
use chrono::Local;
use futures::future;
use lazy_static::lazy_static;
use rand::prelude::*;
use std::net::SocketAddr;
use std::sync::RwLock;
use tokio::{signal, time};
use tokio_modbus::prelude::*;
use tokio_modbus::server::{self, Service};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
lazy_static! {
static ref MEMORY: MbMemory = MbMemory {
holding_registers: RwLock::new(vec![0u16; u16::MAX.into()]),
input_registers: RwLock::new(vec![0u16; u16::MAX.into()]),
coils: RwLock::new(vec![false; u16::MAX.into()]),
discrete_inputs: RwLock::new(vec![false; u16::MAX.into()]),
};
}
async fn memory_context() {
tokio::join!(async {
let mut interval = time::interval(time::Duration::from_millis(8000));
loop {
interval.tick().await;
println!(
"{:<35} [MEM] Generating random data...",
Local::now().format(TIMESTAMP_FORMAT)
);
for v in MEMORY.holding_registers.write().unwrap().iter_mut() {
*v = random::<u16>();
}
for v in MEMORY.input_registers.write().unwrap().iter_mut() {
*v = random::<u16>();
}
for v in MEMORY.coils.write().unwrap().iter_mut() {
*v = random::<bool>();
}
for v in MEMORY.discrete_inputs.write().unwrap().iter_mut() {
*v = random::<bool>();
}
}
});
}
println!(
"{:<35} [CLI] Connecting to server...",
Local::now().format(TIMESTAMP_FORMAT)
);
let mut ctx = tcp::connect(socket_addr).await.unwrap();
loop {
interval.tick().await;
let timestamp = Local::now().format(TIMESTAMP_FORMAT);
//
// read_holding_registers
//
let addr = 0x0008u16;
let cnt = 7u16;
let response = ctx.read_holding_registers(addr, cnt).await.unwrap();
println!(
"{:<35} [CLI] ReadHoldingRegisters({:0>4x}, {:0>4x}) {:0>4x?}",
timestamp, addr, cnt, response
);
MEMORY.holding_registers.write().unwrap()
[(addr as usize)..(addr as usize + response.len())]
.copy_from_slice(&response);
//
// read_input_registers
//
let addr = 0x0002u16;
let cnt = 7u16;
let response = ctx.read_input_registers(addr, cnt).await.unwrap();
println!(
"{:<35} [CLI] ReadInputRegisters({:0>4x}, {:0>4x}) {:0>4x?}",
timestamp, addr, cnt, response
);
MEMORY.input_registers.write().unwrap()
[(addr as usize)..(addr as usize + response.len())]
.copy_from_slice(&response);
//
// read_coils
//
let addr = 0x0004u16;
let cnt = 7u16;
let response = ctx.read_coils(addr, cnt).await.unwrap();
println!(
"{:<35} [CLI] ReadCoils({:0>4x}, {:0>4x}) {:?}",
timestamp, addr, cnt, response
);
MEMORY.coils.write().unwrap()[(addr as usize)..(addr as usize + resp
onse.len())]
.copy_from_slice(&response);
main.rs Strona 4
//
// read_discrete_inputs
//
let addr = 0x0008u16;
let cnt = 7u16;
let response = ctx.read_discrete_inputs(addr, cnt).await.unwrap();
println!(
"{:<35} [CLI] ReadDiscreteInputs({:0>4x}, {:0>4x}) {:?}",
timestamp, addr, cnt, response
);
MEMORY.discrete_inputs.write().unwrap()
[(addr as usize)..(addr as usize + response.len())]
.copy_from_slice(&response);
//
// write_single_register
//
let addr = 0x0008u16;
let word = MEMORY.holding_registers.read().unwrap()[addr as usize];
let _ = ctx.write_single_register(addr, word).await.unwrap();
println!(
"{:<35} [CLI] WriteSingleRegister({:0>4x}, {:0>4x})",
timestamp, addr, word
);
//
// write_multiple_registers
//
let addr = 0x0008u16;
let cnt = 7u16;
let words = MEMORY.holding_registers.read().unwrap()
[(addr as usize)..(addr + cnt) as usize]
.to_vec();
let _ = ctx.write_multiple_registers(addr, &words).await.unwrap();
println!(
"{:<35} [CLI] WriteMultipleRegisters({:0>4x}, {:0>4x}) {:0>4x?}"
,
timestamp, addr, cnt, words
);
//
// write_single_coil
//
let addr = 0x0008u16;
let coil = MEMORY.coils.read().unwrap()[addr as usize];
let _ = ctx.write_single_coil(addr, coil).await.unwrap();
println!(
"{:<35} [CLI] WriteSingleCoil({:0>4x}, {:?})",
timestamp, addr, coil
);
//
// write_multiple_coils
//
let addr = 0x001fu16;
let cnt = 7u16;
let coils =
MEMORY.coils.read().unwrap()[(addr as usize)..(addr + cnt) as us
ize].to_vec();
let _ = ctx.write_multiple_coils(addr, &coils).await.unwrap();
println!(
"{:<35} [CLI] WriteMultipleCoils({:0>4x}, {:0>4x}) {:?}",
timestamp, addr, cnt, coils
);
//
// read_write_multiple_registers
//
let read_addr = 0x0008u16;
main.rs Strona 5
tokio::select! {
_ = memory_context() => unreachable!(),
_ = server_context(socket_addr) => unreachable!(),
_ = client_context(socket_addr) => unreachable!(),
//_ = client_context(socket_addr) => unreachable!(),
//_ = client_context(socket_addr) => unreachable!(),
//_ = client_context(socket_addr) => unreachable!(),
_ = signal::ctrl_c() => println!("Exiting"),
}
Ok(())
}