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
use crate::prelude::*;
use libmodbus_sys as ffi;
use std::ffi::CString;
/// The TCP backend implements a Modbus variant used for communications over TCP/IPv4 networks.
/// It does not require a checksum calculation as lower layer takes care of the same.
///
/// * Create a Modbus TCP context
/// - [`new_tcp()`](struct.Modbus.html#method.new_tcp)
///
pub trait ModbusTCP {
fn new_tcp(ip: &str, port: i32) -> Result<Modbus, Error>;
fn tcp_accept(&mut self, socket: &mut i32) -> Result<i32, Error>;
fn tcp_listen(&mut self, num_connection: i32) -> Result<i32, Error>;
}
impl ModbusTCP for Modbus {
/// `new_tcp` - create a libmodbus context for TCP/IPv4
///
/// The [`new_tcp()`](#method.new_tcp) function shall allocate and initialize a modbus_t structure
/// to communicate with a Modbus TCP IPv4 server.
/// The **ip** argument specifies the IP address of the server to which the client wants to
/// establish a connection. A empty string `""` value can be used to listen any addresses in server mode.
/// The **port** argument is the TCP port to use. Set the port to `MODBUS_TCP_DEFAULT_PORT`
/// to use the default one (502). It’s convenient to use a port number greater than or
/// equal to 1024 because it’s not necessary to have administrator privileges.
///
/// # Examples
///
/// ```
/// use libmodbus::{Modbus, ModbusTCP};
///
/// let modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
/// let modbus = Modbus::new_tcp("127.0.0.1", Modbus::TCP_DEFAULT_PORT as i32).unwrap();
///
/// match modbus.connect() {
/// Ok(_) => { }
/// Err(e) => println!("Error: {}", e),
/// }
/// ```
fn new_tcp(ip: &str, port: i32) -> Result<Modbus, Error> {
unsafe {
let ip = CString::new(ip).unwrap();
let ctx = ffi::modbus_new_tcp(ip.as_ptr(), port);
if ctx.is_null() {
Err(Error::Tcp {
msg: "new_tcp".to_owned(),
source: ::std::io::Error::last_os_error(),
})
} else {
Ok(Modbus { ctx: ctx })
}
}
}
/// `tcp_accept` - accept a new connection on a TCP Modbus socket (IPv4)
///
/// The [`tcp_accept()`](#method.tcp_accept) function shall extract the first connection on the
/// queue of pending connections and create a new socket given as argument.
///
/// # Parameters
///
/// * `socket` - Socket
///
/// # Examples
///
/// ```rust,no_run
/// use libmodbus::{Modbus, ModbusTCP};
///
/// let mut modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
/// let mut socket = modbus.tcp_listen(1).unwrap();
///
/// modbus.tcp_accept(&mut socket);
/// ```
fn tcp_accept(&mut self, socket: &mut i32) -> Result<i32, Error> {
unsafe {
match ffi::modbus_tcp_accept(self.ctx, socket) {
-1 => Err(Error::Tcp {
msg: "tcp_accept".to_owned(),
source: ::std::io::Error::last_os_error(),
}),
socket => Ok(socket),
}
}
}
/// `tcp_listen` - create and listen a TCP Modbus socket (IPv4)
///
/// The [`tcp_listen()`](#method.tcp_listen) function shall create a socket and listen to maximum
/// `num_connection` incoming connections on the specified IP address.
/// If IP address is set to NULL or '0.0.0.0', any addresses will be listen.
///
/// # Parameters
///
/// * `num_connection` - maximum number of incoming connections on the specified IP address
///
/// # Examples
///
/// ```rust,no_run
/// use libmodbus::{Modbus, ModbusTCP};
///
/// let mut modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
///
/// let socket = modbus.tcp_listen(1);
/// ```
fn tcp_listen(&mut self, num_connection: i32) -> Result<i32, Error> {
unsafe {
match ffi::modbus_tcp_listen(self.ctx, num_connection) {
-1 => Err(Error::Tcp {
msg: "tcp_listen".to_owned(),
source: ::std::io::Error::last_os_error(),
}),
socket => Ok(socket),
}
}
}
}