ads_client/
ads_write_control.rs

1use bytes::{Bytes, BytesMut};
2use log::info;
3use crate::{Client, Result, AdsCommand, AdsError, AdsErrorCode, StateInfo, HEADER_SIZE, LEN_WR_CTRL_MIN, misc::HandleData};
4
5impl Client {
6
7    fn pre_write_ctrl(&self, state : &StateInfo, data : Option<&[u8]>, invoke_id : u32) -> Bytes {
8        let mut data_length : u32 = 0;
9        
10        if let Some(v) = data {
11            data_length = v.len() as u32;
12        }
13        
14        let ams_header = self.c_init_ams_header(invoke_id, Some(LEN_WR_CTRL_MIN as u32 + data_length), AdsCommand::WriteControl);
15        let mut wr_ctrl_header : [u8; LEN_WR_CTRL_MIN] = [0; LEN_WR_CTRL_MIN];
16
17        wr_ctrl_header[0..2].copy_from_slice(&(state.ads_state as u16).to_ne_bytes());
18        wr_ctrl_header[2..4].copy_from_slice(&state.device_state.to_ne_bytes());
19        wr_ctrl_header[4..8].copy_from_slice(&data_length.to_ne_bytes());
20
21        let iter_ams_header = ams_header.into_iter();
22        let iter_wrt_ctrl   = wr_ctrl_header.into_iter();
23
24        let mut _wr_ctrl_request = BytesMut::with_capacity(HEADER_SIZE + LEN_WR_CTRL_MIN + data_length as usize);
25        
26        match data {
27            Some(data) => _wr_ctrl_request = iter_ams_header.chain(iter_wrt_ctrl.chain(data.iter().cloned())).collect(),
28            None => _wr_ctrl_request = iter_ams_header.chain(iter_wrt_ctrl).collect()
29        }
30        
31        _wr_ctrl_request.freeze()
32    }
33
34    fn post_write_ctrl(wr_ctrl_response : HandleData) -> Result<()>{
35        Client::eval_ams_error(wr_ctrl_response.ams_err)?;       
36
37        wr_ctrl_response.payload
38            .map(|p| Client::eval_return_code(p.as_ref()))
39            .ok_or_else(|| AdsError{n_error : AdsErrorCode::ADSERR_DEVICE_INVALIDDATA.into(), s_msg : String::from("Invalid data values")})??;
40
41        Ok(())
42    }
43
44    pub async fn write_control(&self, state : &StateInfo, data: Option<&[u8]>) -> Result<()>{
45        // Prepare write control request
46        let invoke_id = self.create_invoke_id();
47        let _wr_ctr_request = self.pre_write_ctrl(state, data, invoke_id);
48
49        info!("Submit Write Control Request: Invoke ID: {}", invoke_id);
50
51        // Create handle
52        self.register_command_handle(invoke_id, AdsCommand::WriteControl);
53
54        // Launch the CommandManager future
55        let cmd_man_future = self.create_cmd_man_future(invoke_id);
56
57        // Launch socket future
58        let socket_future = self.socket_write(&_wr_ctr_request);
59
60        tokio::try_join!(cmd_man_future, socket_future).and_then( | (wr_ctr_response, _) | Client::post_write_ctrl(wr_ctr_response))
61    }
62}