pub mod request;
pub mod response;
pub use mbus_core::models::discrete_input::*;
mod apis;
mod service;
#[cfg(test)]
mod tests {
use heapless::Vec;
use crate::services::discrete_input::{
self, request::ReqPduCompiler, response::ResponseParser,
};
use mbus_core::{
data_unit::common::Pdu, errors::MbusError, function_codes::public::FunctionCode,
models::discrete_input::DiscreteInputs, transport::TransportType,
};
#[test]
fn test_read_discrete_inputs_request_valid() {
let pdu = ReqPduCompiler::read_discrete_inputs_request(0x00C4, 0x0016).unwrap();
assert_eq!(pdu.function_code(), FunctionCode::ReadDiscreteInputs);
assert_eq!(pdu.data().as_slice(), &[0x00, 0xC4, 0x00, 0x16]);
}
#[test]
fn test_read_discrete_inputs_request_min_max_quantity() {
let pdu = ReqPduCompiler::read_discrete_inputs_request(0, 1).unwrap();
assert_eq!(pdu.data().as_slice(), &[0x00, 0x00, 0x00, 0x01]);
let pdu = ReqPduCompiler::read_discrete_inputs_request(0, 2000).unwrap();
assert_eq!(pdu.data().as_slice(), &[0x00, 0x00, 0x07, 0xD0]);
}
#[test]
fn test_read_discrete_inputs_request_invalid_quantity() {
assert_eq!(
ReqPduCompiler::read_discrete_inputs_request(0, 0).unwrap_err(),
MbusError::InvalidPduLength
);
assert_eq!(
ReqPduCompiler::read_discrete_inputs_request(0, 2001).unwrap_err(),
MbusError::InvalidPduLength
);
}
#[test]
fn test_parse_read_discrete_inputs_response_valid() {
let response_data = [0x03, 0xAC, 0xDB, 0x35]; let pdu = Pdu::new(
FunctionCode::ReadDiscreteInputs,
Vec::from_slice(&response_data).unwrap(),
4,
);
let inputs = ResponseParser::parse_read_discrete_inputs_response(&pdu, 196, 22).unwrap();
assert_eq!(&inputs.values()[..3], &[0xAC, 0xDB, 0x35]);
}
#[test]
fn test_parse_read_discrete_inputs_response_wrong_fc() {
let pdu = Pdu::new(FunctionCode::ReadCoils, Vec::new(), 0);
assert_eq!(
ResponseParser::parse_read_discrete_inputs_response(&pdu, 1, 1).unwrap_err(),
MbusError::InvalidFunctionCode
);
}
#[test]
fn test_parse_read_discrete_inputs_response_empty_data() {
let pdu = Pdu::new(FunctionCode::ReadDiscreteInputs, Vec::new(), 0);
assert_eq!(
ResponseParser::parse_read_discrete_inputs_response(&pdu, 1, 1).unwrap_err(),
MbusError::InvalidPduLength
);
}
#[test]
fn test_parse_read_discrete_inputs_response_byte_count_mismatch_pdu_len() {
let data = [0x02, 0x00];
let pdu = Pdu::new(
FunctionCode::ReadDiscreteInputs,
Vec::from_slice(&data).unwrap(),
2,
);
assert_eq!(
ResponseParser::parse_read_discrete_inputs_response(&pdu, 1, 16).unwrap_err(),
MbusError::InvalidByteCount
);
}
#[test]
fn test_parse_read_discrete_inputs_response_byte_count_mismatch_expected_quantity() {
let data = [0x01, 0xFF];
let pdu = Pdu::new(
FunctionCode::ReadDiscreteInputs,
Vec::from_slice(&data).unwrap(),
2,
);
assert_eq!(
ResponseParser::parse_read_discrete_inputs_response(&pdu, 2, 16).unwrap_err(),
MbusError::InvalidQuantity
);
}
#[test]
fn test_discrete_inputs_value_access() {
let mut values = [0u8; mbus_core::models::discrete_input::MAX_DISCRETE_INPUT_BYTES];
values[0] = 0xAC;
values[1] = 0xDB;
values[2] = 0x35;
let inputs = DiscreteInputs::new(196, 22)
.unwrap()
.with_values(&values, 22)
.expect("Should load values");
assert_eq!(inputs.value(196).unwrap(), false); assert_eq!(inputs.value(198).unwrap(), true);
assert_eq!(inputs.value(203).unwrap(), true);
assert_eq!(inputs.value(195).unwrap_err(), MbusError::InvalidAddress); assert_eq!(
inputs.value(196 + 22).unwrap_err(),
MbusError::InvalidAddress
); }
#[test]
fn test_service_read_discrete_inputs_tcp() {
let adu = discrete_input::service::ServiceBuilder::read_discrete_inputs(
0x1234,
1,
0,
10,
TransportType::StdTcp,
)
.unwrap();
let expected = [
0x12, 0x34, 0x00, 0x00, 0x00, 0x06, 0x01, 0x02, 0x00, 0x00, 0x00, 0x0A, ];
assert_eq!(adu.as_slice(), &expected);
}
#[test]
fn test_service_handle_response() {
let data = [0x01, 0x01]; let pdu = Pdu::new(
FunctionCode::ReadDiscreteInputs,
Vec::from_slice(&data).unwrap(),
2,
);
let result = discrete_input::response::ResponseParser::parse_read_discrete_inputs_response(
&pdu, 0, 8,
);
assert!(result.is_ok());
let inputs = result.unwrap();
assert_eq!(inputs.quantity(), 8);
assert_eq!(inputs.values(), &[0x01]);
}
#[test]
fn test_service_handle_response_wrong_fc() {
let pdu = Pdu::new(FunctionCode::ReadCoils, Vec::new(), 0);
let result = discrete_input::response::ResponseParser::parse_read_discrete_inputs_response(
&pdu, 0, 8,
);
assert_eq!(result.unwrap_err(), MbusError::InvalidFunctionCode);
}
}