1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! A pure Rust implementation of MODBUS protocol.
//!
//! `rs-modbus` is designed as a layered architecture, including the physical layer
//! and the application layer:
//!
//! - **Physical layer** implements Serial Port, TCP/IP and UDP/IP.
//! - **Application layer** implements RTU, ASCII and TCP.
//!
//! Both client (master) and server (slave) are provided.
//!
//! ## Features
//!
//! - Full Modbus standard protocol implementation
//! - Support for custom function codes
//! - Support broadcasting
//! - Very lightweight project
//!
//! ### Supported function codes
//!
//! | Code | Name |
//! | ----- | ------------------------------ |
//! | 01 | Read Coils |
//! | 02 | Read Discrete Inputs |
//! | 03 | Read Holding Registers |
//! | 04 | Read Input Registers |
//! | 05 | Write Single Coil |
//! | 06 | Write Single Register |
//! | 15 | Write Multiple Coils |
//! | 16 | Write Multiple Registers |
//! | 17 | Report Server ID |
//! | 22 | Mask Write Register |
//! | 23 | Read/Write Multiple Registers |
//! | 43/14 | Read Device Identification |
//!
//! ### Supported protocols
//!
//! - Modbus RTU
//! - Modbus ASCII
//! - Modbus TCP/IP
//! - Modbus UDP/IP
//! - Modbus RTU/ASCII Over TCP/IP
//! - Modbus RTU/ASCII Over UDP/IP
//!
//! ## Examples
//!
//! ### Modbus TCP Master
//!
//! ```no_run
//! use rs_modbus::layers::application::TcpApplicationLayer;
//! use rs_modbus::layers::physical::TcpClientPhysicalLayer;
//! use rs_modbus::master::{ModbusMaster, ModbusMasterOptions};
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let physical = TcpClientPhysicalLayer::new();
//! let application = TcpApplicationLayer::new(physical.clone());
//! let master = ModbusMaster::new(
//! application,
//! physical,
//! ModbusMasterOptions {
//! timeout_ms: 5000,
//! concurrent: false,
//! },
//! );
//!
//! master.open(None).await?;
//! let res = master.read_holding_registers(1, 0, 10, None).await?;
//! println!("{:?}", res.map(|r| r.data));
//! master.destroy().await;
//!
//! Ok(())
//! }
//! ```
//!
//! ### Modbus TCP Slave
//!
//! ```no_run
//! use rs_modbus::layers::application::TcpApplicationLayer;
//! use rs_modbus::layers::physical::TcpServerPhysicalLayer;
//! use rs_modbus::slave::{ModbusSlave, ModbusSlaveModel};
//! use rs_modbus::types::AddressRange;
//! use async_trait::async_trait;
//!
//! struct SimpleModel;
//!
//! #[async_trait]
//! impl ModbusSlaveModel for SimpleModel {
//! fn unit(&self) -> u8 { 1 }
//! fn address_range(&self) -> AddressRange {
//! AddressRange::default()
//! }
//! async fn read_holding_registers(
//! &self, _address: u16, length: u16,
//! ) -> Result<Vec<u16>, rs_modbus::error::ModbusError> {
//! Ok(vec![0; length as usize])
//! }
//! }
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let physical = TcpServerPhysicalLayer::new();
//! let application = TcpApplicationLayer::new(physical.clone());
//! let slave = ModbusSlave::new(application, physical);
//!
//! slave.add(Box::new(SimpleModel));
//! slave.open(None).await?;
//!
//! Ok(())
//! }
//! ```
// Re-export commonly used types for convenience
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;