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