use crate::enums::{FunctionCode, MessageIdentifier}; #[expect(clippy::big_endian_bytes, reason="Function is needed for the Protocol 300")] /// Calculate the checksum for a Protocol 300 message /// /// The inputs are seperate as the function is needed without have a construced /// `Protocol300Message` sometimes. pub fn calculate_checksum(length: u8, message_identifier: MessageIdentifier, function_code: FunctionCode, address: u16, data_length: u8, data: &[u8]) -> u8 { let mut checksum: u8 = 0; let [addr_hi, addr_lo] = address.to_be_bytes(); for byte in [length, message_identifier.into(), function_code.into(), data_length, addr_hi, addr_lo].iter().chain(data) { checksum = checksum.wrapping_add(*byte); } checksum } #[cfg(test)] mod tests { use crate::{enums::{FunctionCode, MessageIdentifier}, message::Protocol300Message, utils::calculate_checksum}; #[cfg(not(feature = "std"))] extern crate alloc; #[cfg(not(feature = "std"))] use alloc::vec; #[cfg(not(feature = "std"))] use alloc::vec::Vec; #[test] fn check_checksum_1() { let test_msg = Protocol300Message { data_address: 0x5525, telegram_length: 0x05, function_code: FunctionCode::VirtualREAD, message_identifier: MessageIdentifier::Request, data_length: 0x02, data: vec![], checksum: 0x82, }; assert_eq!(calculate_checksum(test_msg.telegram_length, test_msg.message_identifier, test_msg.function_code, test_msg.data_address, test_msg.data_length, &test_msg.data), 0x82); } #[test] fn check_checksum_2() { let test_msg = Protocol300Message { data_address: 0x5525, telegram_length: 0x07, function_code: FunctionCode::VirtualREAD, message_identifier: MessageIdentifier::Response, data_length: 0x02, data: vec![0x07, 0x01], checksum: 0x8D, }; assert_eq!(calculate_checksum(test_msg.telegram_length, test_msg.message_identifier, test_msg.function_code, test_msg.data_address, test_msg.data_length, &test_msg.data), 0x8D); } #[test] fn received_message_wrapping_add_from_bytes() { let checksum = calculate_checksum(0x06, MessageIdentifier::Request, FunctionCode::VirtualWRITE, 0x2323, 0x01, &[0xB6]); assert_eq!(checksum, 0x05); } }