1use crate::base::{DataValueRaw, ErrorCode, HasErrorCode};
2use crate::{
3 error, DataValueReaderExt, DataValueWriterExt, Endian,
4 ErrorCodeReaderExt, ErrorCodeWriterExt, HasFixedCommandId, IsRequest,
5 IsResponse, IsValidResponseFor, MessageExt, ReadExt, ReadFromPayload,
6 Result, TryFromResponse, WithFixedPayloadLength, WriteExt,
7};
8use std::io::{Read, Write};
9
10#[derive(Clone, Debug, PartialEq)]
11pub struct Request {
12 pub module_id: u16,
13 pub channel_index: u16,
14 pub value: DataValueRaw,
15}
16
17impl IsRequest for Request {
18 type Response = Response;
19}
20
21impl From<Request> for super::Request {
22 fn from(m: Request) -> Self {
23 super::Request::WriteValueToModuleChannel(m)
24 }
25}
26
27impl WithFixedPayloadLength for Request {
28 const FIXED_PAYLOAD_LENGTH: u16 = u16::FIXED_PAYLOAD_LENGTH
29 + u16::FIXED_PAYLOAD_LENGTH
30 + DataValueRaw::FIXED_PAYLOAD_LENGTH;
31}
32
33impl HasFixedCommandId for Request {
34 const COMMAND_ID: u16 = 0x3808;
35}
36
37impl MessageExt for Request {
38 fn payload_length(&self) -> u16 {
39 Self::FIXED_PAYLOAD_LENGTH
40 }
41
42 fn write_payload(&self, w: &mut dyn Write) -> Result<()> {
43 w.write_u16::<Endian>(self.module_id)?;
44 w.write_u16::<Endian>(self.channel_index)?;
45 w.write_data_value(&self.value)?;
46 Ok(())
47 }
48}
49
50impl ReadFromPayload for Request {
51 fn read_from_payload<R: Read>(
52 r: &mut R,
53 payload_length: u16,
54 ) -> Result<Self> {
55 Self::verify_payload_length(
56 payload_length,
57 "write_value_to_module_channel_request",
58 )?;
59 let module_id = r.read_u16::<Endian>()?;
60 let channel_index = r.read_u16::<Endian>()?;
61 let value = r.read_data_value()?;
62 Ok(Self {
63 module_id,
64 channel_index,
65 value,
66 })
67 }
68}
69
70#[cfg(test)]
71mod test_request {
72 use super::*;
73
74 #[test]
75 fn write_to() {
76 let mut buffer = Vec::new();
77 let options: u8 = 0x45;
78 let sequence: u8 = 0x93;
79
80 let message = Request {
81 module_id: 0x1122,
82 channel_index: 0x3344,
83 value: 0x42u64.into(),
84 };
85 message.write_to(&mut buffer, options, sequence).unwrap();
86 assert_eq!(
87 buffer,
88 [
89 0x45, 0x93, 0x08, 0x38, 0x0D, 0x00, 0x22, 0x11, 0x44, 0x33, 0x08, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]
109 );
110 }
111 #[test]
112 fn read_from_payload() {
113 let buffer = vec![
114 0x22, 0x11, 0x44, 0x33, 0x08, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
128 let len = buffer.len() as u16;
129 let message =
130 Request::read_from_payload(&mut buffer.as_slice(), len)
131 .unwrap();
132 assert_eq!(
133 message,
134 Request {
135 module_id: 0x1122,
136 channel_index: 0x3344,
137 value: 0x42u64.into(),
138 }
139 );
140 }
141}
142
143#[derive(Clone, Debug, PartialEq)]
144pub struct Response {
145 pub error: ErrorCode,
146}
147
148impl IsResponse for Response {
149 type Request = Request;
150}
151
152impl IsValidResponseFor for Response {
153 fn is_valid_response_for(&self, _request: &Request) -> bool {
154 true
155 }
156}
157
158impl HasErrorCode for Response {
159 fn error_code(&self) -> ErrorCode {
160 self.error
161 }
162}
163
164impl TryFromResponse for Response {
165 fn try_from_response(r: super::Response) -> Result<Self> {
166 if let super::Response::WriteValueToModuleChannel(r) = r {
167 Ok(r)
168 } else {
169 error::UnexpectedResponseType.fail()?
170 }
171 }
172}
173
174impl From<Response> for super::Response {
175 fn from(m: Response) -> Self {
176 super::Response::WriteValueToModuleChannel(m)
177 }
178}
179
180impl WithFixedPayloadLength for Response {
181 const FIXED_PAYLOAD_LENGTH: u16 = ErrorCode::FIXED_PAYLOAD_LENGTH;
182}
183
184impl HasFixedCommandId for Response {
185 const COMMAND_ID: u16 = 0x3809;
186}
187
188impl MessageExt for Response {
189 fn payload_length(&self) -> u16 {
190 Self::FIXED_PAYLOAD_LENGTH
191 }
192
193 fn write_payload(&self, w: &mut dyn Write) -> Result<()> {
194 w.write_error_code(self.error)?;
195 Ok(())
196 }
197}
198
199impl ReadFromPayload for Response {
200 fn read_from_payload<R: Read>(
201 r: &mut R,
202 payload_length: u16,
203 ) -> Result<Self> {
204 Self::verify_payload_length(
205 payload_length,
206 "write_value_to_module_channel_response",
207 )?;
208 let error = r.read_error_code()?;
209 Ok(Self { error })
210 }
211}
212
213#[cfg(test)]
214mod test_response {
215 use super::*;
216
217 #[test]
218 fn write_to() {
219 let mut buffer = Vec::new();
220 let options: u8 = 0x45;
221 let sequence: u8 = 0x93;
222
223 let message = Response {
224 error: ErrorCode::InvalidState, };
226 message.write_to(&mut buffer, options, sequence).unwrap();
227 assert_eq!(
228 buffer,
229 [
230 0x45, 0x93, 0x09, 0x38, 0x02, 0x00, 0x07, 0x01, ]
239 );
240 }
241 #[test]
242 fn read_from_payload() {
243 let buffer = vec![
244 0x07, 0x01, ];
247 let len = buffer.len() as u16;
248 let message =
249 Response::read_from_payload(&mut buffer.as_slice(), len)
250 .unwrap();
251 assert_eq!(
252 message,
253 Response {
254 error: ErrorCode::InvalidState, }
256 );
257 }
258}