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
136
137
//! # Modbus Discrete Input Models
//!
//! This module provides the data structures and logic for handling **Discrete Inputs**
//! (Function Code 0x02).
//!
//! Discrete Inputs are single-bit, read-only data objects typically used to represent
//! digital inputs from physical devices, such as limit switches or sensor states.
//!
//! ## Key Features
//! - **Memory Efficient**: Uses bit-packing to store up to 2000 inputs in a fixed-size buffer.
//! - **no_std Compatible**: Designed for embedded systems without heap allocation.
//! - **Safe Access**: Provides methods to retrieve individual bit states by their Modbus address
//! with automatic boundary checking.
//!
//! A collection of discrete input states retrieved from a Modbus server.
//!
//! This structure maintains the context of the read operation (starting address and quantity)
//! and stores the actual bit-packed values in a memory-efficient `heapless::Vec`, making it
//! suitable for `no_std` and embedded environments.
//!
//! Use the [`value()`](Self::value) method to extract individual boolean states without
//! manually performing bitwise operations.
//!
//! # Internal Representation
//! The `values` array stores these discrete input states. Each byte in `values` holds 8 input states,
//! where the least significant bit (LSB) of the first byte (`values[0]`) corresponds to the
//! `from_address`, the next bit to `from_address + 1`, and so on. This bit-packing is efficient
//! for memory usage and network transmission.
//!
//! The `MAX_DISCRETE_INPUT_BYTES` constant ensures that the `values` array has enough space to
//! accommodate the maximum possible number of discrete inputs allowed in a single Modbus PDU
//! (`MAX_DISCRETE_INPUTS_PER_PDU`).
//!
//! # Examples
//!
//! ```rust
//! use mbus_core::models::discrete_input::{DiscreteInputs, MAX_DISCRETE_INPUT_BYTES};
//! use mbus_core::errors::MbusError;
//!
//! // Initialize a block of 8 discrete inputs starting at Modbus address 100.
//! // Initially all inputs are OFF (0).
//! let mut inputs = DiscreteInputs::new(100, 8).unwrap();
//!
//! // Verify initial state: all inputs are false
//! assert_eq!(inputs.value(100).unwrap(), false);
//! assert_eq!(inputs.value(107).unwrap(), false);
//!
//! // Simulate receiving data where inputs at offsets 0 and 2 are ON (0b0000_0101)
//! let received_data = [0x05, 0x00, 0x00, 0x00]; // Only the first byte is relevant for 8 inputs
//! inputs = inputs.with_values(&received_data, 8).expect("Valid quantity and data");
//!
//! // Read individual input values
//! assert_eq!(inputs.value(100).unwrap(), true); // Address 100 (offset 0) -> LSB of 0x05 is 1
//! assert_eq!(inputs.value(101).unwrap(), false); // Address 101 (offset 1) -> next bit is 0
//! assert_eq!(inputs.value(102).unwrap(), true); // Address 102 (offset 2) -> next bit is 1
//! assert_eq!(inputs.value(107).unwrap(), false); // Address 107 (offset 7) -> MSB of 0x05 is 0
//!
//! // Accessing values out of bounds will return an error
//! assert_eq!(inputs.value(99), Err(MbusError::InvalidAddress));
//! assert_eq!(inputs.value(108), Err(MbusError::InvalidAddress));
//!
//! // Get the raw bit-packed bytes (only the first byte is active for 8 inputs)
//! assert_eq!(inputs.values(), &[0x05]);
//! ```
pub use *;