1use crate::client::{receive_message, Parameters};
2use crate::connection::{ConnectionManager, ConnectionOptions};
3use crate::msg::{
4 get_hash, get_hash_size, CreateGroupMsg, GetParameterListMsg, GetParameterMsg,
5 GetParameterTreeMsg, GroupStatusMsg, Hash, LoginMsg, LogoutMsg, ParameterListMsg, ParameterMsg,
6 ParameterTreeMsg, RemoveGroupMsg, SetParameterListMsg, SetParameterMsg, StatusCode, StatusMsg,
7};
8use crate::parameter_value::{
9 decode_parameter_value, encode_parameter_value, GetParameterTuple, GetParameterValue,
10 SetParameterTuple, SetParameterValue,
11};
12use crate::ParameterTree;
13
14use prost::{DecodeError, Message};
15
16pub struct Request {
19 connection_data: ConnectionManager,
20 parameter_tree: ParameterTree,
22}
23
24impl Request {
25 pub fn new() -> Self {
27 let sock = unsafe {
28 let mut sock: nng_c_sys::nng_socket = std::mem::zeroed();
29 nng_c_sys::nng_req0_open(&mut sock);
30 sock
31 };
32 Self {
33 connection_data: ConnectionManager::new(sock),
34 parameter_tree: ParameterTree::new(),
35 }
36 }
37
38 pub fn connect(
48 &mut self,
49 url: &str,
50 connection_options: ConnectionOptions,
51 ) -> Result<(), String> {
52 self.connection_data.connect(url, connection_options)
53 }
54
55 pub fn disconnect(&mut self) -> Result<(), String> {
61 self.connection_data.disconnect()
62 }
63
64 pub fn login(&self, username: String, password: String) -> Result<StatusCode, String> {
74 let login_msg = LoginMsg {
75 header: None,
76 login: username,
77 password,
78 };
79
80 let buffer = Self::encode_with_hash(&login_msg)
81 .map_err(|e| format!("Failed to encode LoginMsg: {:?}", e))?;
82 self.send_message(&buffer)?;
83
84 let buf = receive_message(&self.connection_data.sock.as_ref().unwrap())
85 .map_err(|_| "Failed to receive status message".to_string())?;
86 let msg = Self::decode_status_msg(buf.as_slice())
87 .map_err(|e| format!("Failed to decode status message: {:?}", e))?;
88
89 Ok(StatusCode::try_from(msg.status).unwrap())
90 }
91
92 pub fn logout(&self) -> Result<StatusCode, String> {
98 let logout_msg = LogoutMsg { header: None };
99
100 let buffer = Self::encode_with_hash(&logout_msg)
101 .map_err(|e| format!("Failed to encode LogoutMsg: {:?}", e))?;
102 self.send_message(&buffer)?;
103
104 let buf = receive_message(&self.connection_data.sock.as_ref().unwrap())
105 .map_err(|_| "Failed to receive status message".to_string())?;
106 let msg = Self::decode_status_msg(buf.as_slice())
107 .map_err(|e| format!("Failed to decode status message: {:?}", e))?;
108
109 Ok(StatusCode::try_from(msg.status).unwrap())
110 }
111
112 pub fn request_parameter_tree(&mut self) -> Result<StatusCode, String> {
118 match self.get_parameter_tree() {
119 Ok((status_code, parameter_tree)) => {
120 self.parameter_tree = parameter_tree;
121 Ok(status_code)
122 }
123 Err(e) => Err(e),
124 }
125 }
126
127 pub fn set_parameter<V>(&self, path: &str, value: V) -> Result<StatusCode, String>
137 where
138 V: SetParameterValue + Default + PartialEq,
139 {
140 let data_type = self
141 .parameter_tree
142 .get_parameter_data_type(&path)
143 .ok_or((
144 StatusCode::WrongParameterPath,
145 format!("Parameter data type not found for path: {}", path),
146 ))
147 .unwrap();
148
149 let msg = SetParameterMsg {
150 header: None,
151 offset: None,
152 path: path.to_string(),
153 value: encode_parameter_value(data_type, &value),
154 };
155
156 let buffer = Self::encode_with_hash(&msg)
157 .map_err(|e| format!("Failed to encode SetParameter: {:?}", e))?;
158 self.send_message(&buffer)?;
159
160 let buf = receive_message(self.connection_data.sock.as_ref().unwrap())
161 .map_err(|_| "Failed to receive status message".to_string())?;
162 let msg = Self::decode_status_msg(buf.as_slice())
163 .map_err(|e| format!("Failed to decode status message: {:?}", e))?;
164
165 Ok(StatusCode::try_from(msg.status).unwrap())
166 }
167
168 pub fn set_parameters<T>(&self, paths: Vec<&str>, values: T) -> Result<StatusCode, String>
169 where
170 T: SetParameterTuple,
171 {
172 let mut msg = SetParameterListMsg {
173 header: None,
174 params: Vec::new(),
175 };
176
177 let mut i = 0;
178 for path in paths {
179 let data_type = self
180 .parameter_tree
181 .get_parameter_data_type(&path)
182 .ok_or((
183 StatusCode::WrongParameterPath,
184 format!("Parameter data type not found for path: {}", path),
185 ))
186 .unwrap();
187
188 msg.params.push(SetParameterMsg {
189 header: None,
190 offset: None,
191 path: path.to_string(),
192 value: T::get_tuple_element(&values, i, data_type)?,
193 });
194 i = i + 1
195 }
196
197 let buffer = Self::encode_with_hash(&msg)
198 .map_err(|e| format!("Failed to encode SetParameterList: {:?}", e))?;
199 self.send_message(&buffer)?;
200
201 let buf = receive_message(self.connection_data.sock.as_ref().unwrap())
202 .map_err(|_| "Failed to receive status message".to_string())?;
203 let msg = Self::decode_status_msg(buf.as_slice())
204 .map_err(|e| format!("Failed to decode status message: {:?}", e))?;
205
206 Ok(StatusCode::try_from(msg.status).unwrap())
207 }
208
209 pub fn get_parameter<V>(&self, path: &str) -> Result<V, String>
229 where
230 V: GetParameterValue + Default,
231 {
232 let data_type = self
233 .parameter_tree
234 .get_parameter_data_type(&path)
235 .ok_or((
236 StatusCode::WrongParameterPath,
237 format!("Parameter data type not found for path: {}", path),
238 ))
239 .unwrap();
240
241 let msg = GetParameterMsg {
242 header: None,
243 path: path.to_string(),
244 };
245
246 let buffer = Self::encode_with_hash(&msg)
247 .map_err(|e| format!("Failed to encode GetParameter: {:?}", e))?;
248 self.send_message(&buffer)?;
249
250 let buf = receive_message(self.connection_data.sock.as_ref().unwrap())
251 .map_err(|_| "Failed to receive parameter message".to_string())?;
252 let msg = Self::decode_parameter_msg(buf.as_slice())
253 .map_err(|e| format!("Failed to decode parameter message: {:?}", e))?;
254
255 Ok(decode_parameter_value(data_type, &msg.value))
256 }
257
258 pub fn get_parameters<T>(&self, paths: Vec<&str>) -> Result<T, String>
259 where
260 T: GetParameterTuple,
261 {
262 let mut msg = GetParameterListMsg {
263 header: None,
264 params: Vec::new(),
265 };
266
267 for path in paths {
268 msg.params.push(GetParameterMsg {
278 header: None,
279 path: path.to_string(),
280 })
281 }
282
283 let buffer = Self::encode_with_hash(&msg)
284 .map_err(|e| format!("Failed to encode GetParameterList: {:?}", e))?;
285 self.send_message(&buffer)?;
286
287 let buf = receive_message(self.connection_data.sock.as_ref().unwrap())
288 .map_err(|_| "Failed to receive parameter list message".to_string())?;
289 let msg = Self::decode_message::<ParameterListMsg>(buf.as_slice())
290 .map_err(|e| format!("Failed to decode parameter list message: {:?}", e))?;
291
292 let combined_iterator = msg.params.iter().map(|parameter| {
293 (
294 ¶meter.info.as_ref().unwrap().data_type,
295 parameter.value.as_slice(),
296 )
297 });
298
299 T::get_parameters(combined_iterator)
300 }
301
302 pub fn get_parameter_tree(&self) -> Result<(StatusCode, ParameterTree), String> {
311 let get_parameter_tree = GetParameterTreeMsg { header: None };
312 let buffer = Self::encode_with_hash(&get_parameter_tree)
313 .map_err(|e| format!("Failed to encode GetParameterTreeMsg: {:?}", e))?;
314 self.send_message(&buffer)?;
315
316 let buf = receive_message(self.connection_data.sock.as_ref().unwrap())
317 .map_err(|_| "Failed to receive parameter tree message".to_string())?;
318 let msg = Self::decode_parameter_tree_msg(buf.as_slice())
319 .map_err(|e| format!("Failed to decode parameter tree message: {:?}", e))?;
320
321 match ParameterTree::from_message(msg) {
322 Some(parameter_tree) => Ok((StatusCode::Ok, parameter_tree)),
323 None => Err("Failed to create ParameterTree: Invalid status code.".to_string()),
324 }
325 }
326
327 pub fn create_group<I>(
328 &self,
329 parameters: I,
330 group_name: &str,
331 frequency_divider: u32,
332 ) -> Result<GroupStatusMsg, String>
333 where
334 I: Parameters,
335 {
336 let create_group_msg = CreateGroupMsg {
337 header: None,
338 frq_divider: frequency_divider,
339 alias: group_name.to_string(),
340 paths: parameters.into_vec(),
341 };
342 let buffer = Self::encode_with_hash(&create_group_msg)
343 .map_err(|e| format!("Failed to encode CreateGroupMsg: {:?}", e))?;
344 self.send_message(&buffer)?;
345
346 let buf = receive_message(self.connection_data.sock.as_ref().unwrap())
347 .map_err(|_| "Failed to receive group status message".to_string())?;
348 let msg = Self::decode_message::<GroupStatusMsg>(buf.as_slice())
349 .map_err(|e| format!("Failed to decode group status message: {:?}", e))?;
350
351 Ok(msg)
352 }
353
354 pub fn remove_group(&self, group_name: &str) -> Result<StatusCode, String> {
355 let remove_group_msg = RemoveGroupMsg {
356 header: None,
357 alias: group_name.to_string(),
358 };
359 let buffer = Self::encode_with_hash(&remove_group_msg)
360 .map_err(|e| format!("Failed to encode RemoveGroupMsg: {:?}", e))?;
361 self.send_message(&buffer)?;
362
363 let buf = receive_message(self.connection_data.sock.as_ref().unwrap())
364 .map_err(|_| "Failed to receive status message".to_string())?;
365 let msg = Self::decode_status_msg(buf.as_slice())
366 .map_err(|e| format!("Failed to decode status message: {:?}", e))?;
367
368 if msg.status == StatusCode::Ok as i32 {
369 Ok(StatusCode::Ok)
370 } else {
371 Err("Failed to remove group".to_string())
372 }
373 }
374
375 fn encode_with_hash<M: Message + Hash>(message: &M) -> Result<Vec<u8>, String> {
384 let mut buffer: Vec<u8> = Vec::new();
385 buffer.extend(get_hash::<M>().to_le_bytes());
386 message
387 .encode(&mut buffer)
388 .map_err(|e| format!("Failed to encode message: {:?}", e))?;
389
390 Ok(buffer)
391 }
392
393 pub fn decode_message<T: Message + Default + Hash>(
402 reply_slice: &[u8],
403 ) -> Result<T, DecodeError> {
404 let hash_size = get_hash_size();
405
406 if hash_size > reply_slice.len() {
408 return Err(DecodeError::new("Invalid message length, hash missing"));
409 }
410
411 let provided_hash = u32::from_le_bytes(
413 reply_slice[..hash_size]
414 .try_into()
415 .map_err(|_| DecodeError::new("Failed to extract hash"))?,
416 );
417
418 if provided_hash != get_hash::<T>() {
420 return Err(DecodeError::new("Invalid message hash"));
421 }
422
423 let decode_slice = &reply_slice[hash_size..];
425 T::decode(decode_slice)
426 }
427
428 fn decode_parameter_tree_msg(reply_slice: &[u8]) -> Result<ParameterTreeMsg, DecodeError> {
439 Self::decode_message::<ParameterTreeMsg>(reply_slice)
440 }
441
442 fn decode_status_msg(reply_slice: &[u8]) -> Result<StatusMsg, DecodeError> {
453 Self::decode_message::<StatusMsg>(reply_slice)
454 }
455
456 fn decode_parameter_msg(reply_slice: &[u8]) -> Result<ParameterMsg, DecodeError> {
457 Self::decode_message::<ParameterMsg>(reply_slice)
458 }
459
460 fn send_message(&self, buffer: &[u8]) -> Result<(), String> {
471 unsafe {
472 let data_ptr = buffer.as_ptr() as *mut std::ffi::c_void;
474 let data_len = buffer.len();
475
476 let sock = self
478 .connection_data
479 .sock
480 .ok_or("Socket is not available. Connect first.")?;
481 let rv = nng_c_sys::nng_send(sock, data_ptr, data_len, 0);
482
483 if rv != 0 {
485 return Err(format!(
486 "Failed to send message via NNG. Error code: {}",
487 rv
488 ));
489 }
490 }
491
492 Ok(())
493 }
494}