pub const DEFAULT_MAX_READ_REGISTERS: u16 = 125;
pub const DEFAULT_MAX_WRITE_REGISTERS: u16 = 123;
pub const DEFAULT_MAX_READ_COILS: u16 = 2000;
pub const DEFAULT_MAX_WRITE_COILS: u16 = 1968;
pub const DEFAULT_INTER_REQUEST_DELAY_MS: u64 = 0;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DeviceLimits {
pub max_read_registers: u16,
pub max_write_registers: u16,
pub max_read_coils: u16,
pub max_write_coils: u16,
pub inter_request_delay_ms: u64,
}
impl DeviceLimits {
pub fn new() -> Self {
Self::default()
}
pub fn conservative() -> Self {
Self {
max_read_registers: 50,
max_write_registers: 50,
max_read_coils: 500,
max_write_coils: 500,
inter_request_delay_ms: 10,
}
}
pub fn with_max_read_registers(mut self, count: u16) -> Self {
self.max_read_registers = count;
self
}
pub fn with_max_write_registers(mut self, count: u16) -> Self {
self.max_write_registers = count;
self
}
pub fn with_max_read_coils(mut self, count: u16) -> Self {
self.max_read_coils = count;
self
}
pub fn with_max_write_coils(mut self, count: u16) -> Self {
self.max_write_coils = count;
self
}
pub fn with_inter_request_delay_ms(mut self, delay_ms: u64) -> Self {
self.inter_request_delay_ms = delay_ms;
self
}
pub fn read_request_count(&self, total_registers: u16) -> u16 {
if total_registers == 0 {
return 0;
}
total_registers.div_ceil(self.max_read_registers)
}
pub fn write_request_count(&self, total_registers: u16) -> u16 {
if total_registers == 0 {
return 0;
}
total_registers.div_ceil(self.max_write_registers)
}
pub fn is_read_within_limits(&self, register_count: u16) -> bool {
register_count <= self.max_read_registers
}
pub fn is_write_within_limits(&self, register_count: u16) -> bool {
register_count <= self.max_write_registers
}
pub fn is_coil_read_within_limits(&self, coil_count: u16) -> bool {
coil_count <= self.max_read_coils
}
pub fn is_coil_write_within_limits(&self, coil_count: u16) -> bool {
coil_count <= self.max_write_coils
}
}
impl Default for DeviceLimits {
fn default() -> Self {
Self {
max_read_registers: DEFAULT_MAX_READ_REGISTERS,
max_write_registers: DEFAULT_MAX_WRITE_REGISTERS,
max_read_coils: DEFAULT_MAX_READ_COILS,
max_write_coils: DEFAULT_MAX_WRITE_COILS,
inter_request_delay_ms: DEFAULT_INTER_REQUEST_DELAY_MS,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_limits() {
let limits = DeviceLimits::default();
assert_eq!(limits.max_read_registers, DEFAULT_MAX_READ_REGISTERS);
assert_eq!(limits.max_write_registers, DEFAULT_MAX_WRITE_REGISTERS);
assert_eq!(limits.max_read_coils, DEFAULT_MAX_READ_COILS);
assert_eq!(limits.max_write_coils, DEFAULT_MAX_WRITE_COILS);
assert_eq!(
limits.inter_request_delay_ms,
DEFAULT_INTER_REQUEST_DELAY_MS
);
}
#[test]
fn test_conservative_limits() {
let limits = DeviceLimits::conservative();
assert_eq!(limits.max_read_registers, 50);
assert_eq!(limits.max_write_registers, 50);
assert_eq!(limits.inter_request_delay_ms, 10);
}
#[test]
fn test_builder_pattern() {
let limits = DeviceLimits::new()
.with_max_read_registers(60)
.with_max_write_registers(40)
.with_inter_request_delay_ms(5);
assert_eq!(limits.max_read_registers, 60);
assert_eq!(limits.max_write_registers, 40);
assert_eq!(limits.inter_request_delay_ms, 5);
}
#[test]
fn test_read_request_count() {
let limits = DeviceLimits::new().with_max_read_registers(50);
assert_eq!(limits.read_request_count(0), 0);
assert_eq!(limits.read_request_count(50), 1);
assert_eq!(limits.read_request_count(51), 2);
assert_eq!(limits.read_request_count(100), 2);
assert_eq!(limits.read_request_count(101), 3);
}
#[test]
fn test_write_request_count() {
let limits = DeviceLimits::new().with_max_write_registers(100);
assert_eq!(limits.write_request_count(0), 0);
assert_eq!(limits.write_request_count(100), 1);
assert_eq!(limits.write_request_count(101), 2);
assert_eq!(limits.write_request_count(250), 3);
}
#[test]
fn test_is_read_within_limits() {
let limits = DeviceLimits::new().with_max_read_registers(100);
assert!(limits.is_read_within_limits(100));
assert!(!limits.is_read_within_limits(101));
}
#[test]
fn test_is_write_within_limits() {
let limits = DeviceLimits::new().with_max_write_registers(80);
assert!(limits.is_write_within_limits(80));
assert!(!limits.is_write_within_limits(81));
}
#[test]
fn test_is_coil_within_limits() {
let limits = DeviceLimits::new()
.with_max_read_coils(1000)
.with_max_write_coils(500);
assert!(limits.is_coil_read_within_limits(1000));
assert!(!limits.is_coil_read_within_limits(1001));
assert!(limits.is_coil_write_within_limits(500));
assert!(!limits.is_coil_write_within_limits(501));
}
}