diff --git a/src/client/mod.rs b/src/client/mod.rs index 025293be..937c0dc9 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1,13 +1,4 @@ -#[cfg(feature = "rtu")] -pub mod rtu; - -#[cfg(feature = "sync")] -pub mod sync; - -#[cfg(feature = "tcp")] -pub mod tcp; - -use crate::{frame::*, slave::*}; +//! Modbus clients use std::{ fmt::Debug, @@ -16,24 +7,44 @@ use std::{ use async_trait::async_trait; -/// A transport independent asynchronous client trait. +use crate::{frame::*, slave::*}; + +#[cfg(feature = "sync")] +pub mod sync; + +#[cfg(feature = "rtu")] +pub mod rtu; + +#[cfg(feature = "tcp")] +pub mod tcp; + +/// Transport independent asynchronous client trait #[async_trait] pub trait Client: SlaveContext + Send + Debug { + /// Invoke a Modbus function async fn call(&mut self, request: Request) -> Result; } -/// An asynchronous Modbus reader. +/// Asynchronous Modbus reader #[async_trait] pub trait Reader: Client { + /// Read multiple coils (0x01) async fn read_coils(&mut self, _: Address, _: Quantity) -> Result, Error>; + /// Read multiple discrete inputs (0x02) async fn read_discrete_inputs(&mut self, _: Address, _: Quantity) -> Result, Error>; - async fn read_input_registers(&mut self, _: Address, _: Quantity) -> Result, Error>; - + /// Read multiple holding registers (0x03) async fn read_holding_registers(&mut self, _: Address, _: Quantity) -> Result, Error>; + /// Read multiple input registers (0x04) + async fn read_input_registers(&mut self, _: Address, _: Quantity) -> Result, Error>; + + /// Read and write multiple holding registers (0x17) + /// + /// The write operation is performed before the read unlike + /// the name of the operation might suggest! async fn read_write_multiple_registers( &mut self, _: Address, @@ -43,25 +54,30 @@ pub trait Reader: Client { ) -> Result, Error>; } -/// An asynchronous Modbus writer. +/// Asynchronous Modbus writer #[async_trait] pub trait Writer: Client { + /// Write a single coil (0x05) async fn write_single_coil(&mut self, _: Address, _: Coil) -> Result<(), Error>; - async fn write_multiple_coils(&mut self, _: Address, _: &[Coil]) -> Result<(), Error>; - + /// Write a single holding register (0x06) async fn write_single_register(&mut self, _: Address, _: Word) -> Result<(), Error>; + /// Write multiple coils (0x0F) + async fn write_multiple_coils(&mut self, _: Address, _: &[Coil]) -> Result<(), Error>; + + /// Write multiple holding registers (0x10) async fn write_multiple_registers(&mut self, _: Address, _: &[Word]) -> Result<(), Error>; } -/// An asynchronous Modbus client context. +/// Asynchronous Modbus client context #[derive(Debug)] pub struct Context { client: Box, } impl Context { + /// Disconnect the client pub async fn disconnect(&mut self) -> Result<(), Error> { // Disconnecting is expected to fail! let res = self.client.call(Request::Disconnect).await; diff --git a/src/client/rtu.rs b/src/client/rtu.rs index 3b50a4a6..ea65e8e1 100644 --- a/src/client/rtu.rs +++ b/src/client/rtu.rs @@ -1,4 +1,4 @@ -//! Connecting a Modbus RTU context +//! RTU client connections use super::*; diff --git a/src/client/sync/mod.rs b/src/client/sync/mod.rs index cc2d9b89..c08f3c8a 100644 --- a/src/client/sync/mod.rs +++ b/src/client/sync/mod.rs @@ -1,8 +1,13 @@ -//! Synchronous Modbus context access +//! Synchronous Modbus client +// TODO: Add missing documentation +#![allow(missing_docs)] + +/// RTU client connections #[cfg(feature = "rtu")] pub mod rtu; +/// TCP client connections #[cfg(feature = "tcp")] pub mod tcp; diff --git a/src/client/sync/rtu.rs b/src/client/sync/rtu.rs index f61fb53f..7a94eeb2 100644 --- a/src/client/sync/rtu.rs +++ b/src/client/sync/rtu.rs @@ -1,10 +1,10 @@ use super::{Context, Result}; +use tokio_serial::{SerialPortBuilder, SerialStream}; + use crate::client::rtu::connect_slave as async_connect_slave; use crate::slave::Slave; -use tokio_serial::{SerialPortBuilder, SerialStream}; - /// Connect to no particular Modbus slave device for sending /// broadcast messages. pub fn connect(builder: &SerialPortBuilder) -> Result { diff --git a/src/client/sync/tcp.rs b/src/client/sync/tcp.rs index f562bed1..19bab618 100644 --- a/src/client/sync/tcp.rs +++ b/src/client/sync/tcp.rs @@ -1,9 +1,12 @@ -use super::{Context, Result}; +//! TCP client connections + +use std::net::SocketAddr; use crate::client::tcp::connect_slave as async_connect_slave; use crate::slave::Slave; -use std::net::SocketAddr; +use super::{Context, Result}; + /// Establish a direct connection to a Modbus TCP coupler. pub fn connect(socket_addr: SocketAddr) -> Result { connect_slave(socket_addr, Slave::tcp_device()) diff --git a/src/client/tcp.rs b/src/client/tcp.rs index 75b4190f..8ef1e671 100644 --- a/src/client/tcp.rs +++ b/src/client/tcp.rs @@ -1,4 +1,4 @@ -//! Connecting a Modbus TCP context +//! TCP client connections use super::*; diff --git a/src/lib.rs b/src/lib.rs index 3232e530..c2001ad1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -144,8 +144,7 @@ #![deny(rust_2018_idioms)] #![deny(rust_2021_compatibility)] #![deny(missing_debug_implementations)] -// TODO: Add missing documentation -//#![deny(missing_docs)] +#![deny(missing_docs)] #![deny(rustdoc::broken_intra_doc_links)] #![deny(clippy::all)] #![deny(clippy::explicit_deref_methods)] @@ -162,6 +161,7 @@ pub mod prelude; pub mod client; + pub mod slave; #[cfg(feature = "server")] diff --git a/src/prelude.rs b/src/prelude.rs index a883145c..91ea8004 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,16 +1,23 @@ +//! Common types + /////////////////////////////////////////////////////////////////// /// Modules /////////////////////////////////////////////////////////////////// pub use crate::client; -#[cfg(feature = "server")] -pub use crate::server; +#[allow(missing_docs)] +#[cfg(feature = "sync")] +pub mod sync { + pub use crate::client::sync::*; +} +#[allow(missing_docs)] #[cfg(feature = "rtu")] pub mod rtu { pub use crate::client::rtu::*; } +#[allow(missing_docs)] #[cfg(feature = "tcp")] pub mod tcp { pub use crate::client::tcp::*; @@ -19,10 +26,8 @@ pub mod tcp { pub use crate::server::*; } -#[cfg(feature = "sync")] -pub mod sync { - pub use crate::client::sync::*; -} +#[cfg(feature = "server")] +pub use crate::server; /////////////////////////////////////////////////////////////////// /// Structs diff --git a/src/server/mod.rs b/src/server/mod.rs index 07bceda1..d71d5380 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1,5 +1,11 @@ +//! Modbus server skeletons + +// TODO: Add missing documentation +#![allow(missing_docs)] + #[cfg(feature = "rtu")] pub mod rtu; + #[cfg(feature = "tcp-server-unstable")] pub mod tcp; diff --git a/src/server/rtu.rs b/src/server/rtu.rs index 6041b8d4..a3bb5337 100644 --- a/src/server/rtu.rs +++ b/src/server/rtu.rs @@ -1,6 +1,4 @@ -/*! - * Modbus RTU server functionality - */ +//! Modbus RTU server skeleton use crate::{ codec, diff --git a/src/server/tcp.rs b/src/server/tcp.rs index 34260656..1996ae76 100644 --- a/src/server/tcp.rs +++ b/src/server/tcp.rs @@ -1,3 +1,5 @@ +//! Modbus TCP server skeleton + use crate::{ codec, frame::*, diff --git a/src/slave.rs b/src/slave.rs index 21f3d52a..994fec05 100644 --- a/src/slave.rs +++ b/src/slave.rs @@ -1,5 +1,8 @@ +//! Modbus devices + use std::{fmt, num::ParseIntError, str::FromStr}; +/// Slave identifier pub type SlaveId = u8; /// A single byte for addressing Modbus slave devices. @@ -39,14 +42,17 @@ impl Slave { Slave(255) } + /// Check if the [`SlaveId`] is used for broadcasting pub fn is_broadcast(self) -> bool { self == Self::broadcast() } + /// Check if the [`SlaveId`] addresses a single device pub fn is_single_device(self) -> bool { self >= Self::min_device() && self <= Self::max_device() } + /// Check if the [`SlaveId`] is reserved pub fn is_reserved(self) -> bool { self > Self::max_device() }