st3215/
group_sync_read.rs

1use crate::protocol_packet_handler::ProtocolPacketHandler;
2use crate::values::*;
3use std::collections::HashMap;
4
5pub struct GroupSyncRead {
6    start_address: u8,
7    data_length: usize,
8    last_result: bool,
9    is_param_changed: bool,
10    param: Vec<u8>,
11    data_dict: HashMap<u8, Vec<u8>>,
12}
13
14impl GroupSyncRead {
15    pub fn new(start_address: u8, data_length: usize) -> Self {
16        Self {
17            start_address,
18            data_length,
19            last_result: false,
20            is_param_changed: false,
21            param: Vec::new(),
22            data_dict: HashMap::new(),
23        }
24    }
25
26    fn make_param(&mut self) {
27        if self.data_dict.is_empty() {
28            return;
29        }
30
31        self.param.clear();
32        for scs_id in self.data_dict.keys() {
33            self.param.push(*scs_id);
34        }
35    }
36
37    pub fn add_param(&mut self, sts_id: u8) -> bool {
38        if self.data_dict.contains_key(&sts_id) {
39            return false;
40        }
41
42        self.data_dict.insert(sts_id, Vec::new());
43        self.is_param_changed = true;
44        true
45    }
46
47    pub fn remove_param(&mut self, sts_id: u8) {
48        if self.data_dict.remove(&sts_id).is_some() {
49            self.is_param_changed = true;
50        }
51    }
52
53    pub fn clear_param(&mut self) {
54        self.data_dict.clear();
55    }
56
57    pub fn tx_packet(&mut self, ph: &mut ProtocolPacketHandler) -> CommResult {
58        if self.data_dict.is_empty() {
59            return CommResult::NotAvailable;
60        }
61
62        if self.is_param_changed || self.param.is_empty() {
63            self.make_param();
64        }
65
66        ph.sync_read_tx(self.start_address, self.data_length as u8, &self.param)
67    }
68
69    pub fn rx_packet(&mut self, ph: &mut ProtocolPacketHandler) -> CommResult {
70        self.last_result = true;
71
72        if self.data_dict.is_empty() {
73            return CommResult::NotAvailable;
74        }
75
76        let (result, rxpacket) = ph.sync_read_rx(self.data_length, self.data_dict.len());
77
78        if rxpacket.len() >= (self.data_length + 6) {
79            for sts_id in self.data_dict.keys().copied().collect::<Vec<_>>() {
80                match self.read_rx(&rxpacket, sts_id, self.data_length) {
81                    (Some(data), CommResult::Success) => {
82                        self.data_dict.insert(sts_id, data);
83                    }
84                    _ => {
85                        self.last_result = false;
86                    }
87                }
88            }
89        } else {
90            self.last_result = false;
91        }
92
93        result
94    }
95
96    pub fn tx_rx_packet(&mut self, ph: &mut ProtocolPacketHandler) -> CommResult {
97        let result = self.tx_packet(ph);
98        if !result.is_success() {
99            return result;
100        }
101        self.rx_packet(ph)
102    }
103
104    fn read_rx(&self, rxpacket: &[u8], sts_id: u8, data_length: usize) -> (Option<Vec<u8>>, CommResult) {
105        let rx_length = rxpacket.len();
106        let mut rx_index = 0;
107
108        while (rx_index + 6 + data_length) <= rx_length {
109            let mut headpacket = [0u8; 3];
110            
111            while rx_index < rx_length {
112                headpacket[2] = headpacket[1];
113                headpacket[1] = headpacket[0];
114                headpacket[0] = rxpacket[rx_index];
115                rx_index += 1;
116                
117                if headpacket[2] == 0xFF && headpacket[1] == 0xFF && headpacket[0] == sts_id {
118                    break;
119                }
120            }
121
122            if (rx_index + 3 + data_length) > rx_length {
123                break;
124            }
125
126            if rxpacket[rx_index] != (data_length + 2) as u8 {
127                rx_index += 1;
128                continue;
129            }
130            rx_index += 1;
131
132            let error = rxpacket[rx_index];
133            rx_index += 1;
134
135            let mut cal_sum = sts_id.wrapping_add((data_length + 2) as u8).wrapping_add(error);
136            let mut data = vec![error];
137            
138            for i in 0..data_length {
139                if rx_index + i >= rx_length {
140                    return (None, CommResult::RxCorrupt);
141                }
142                data.push(rxpacket[rx_index + i]);
143                cal_sum = cal_sum.wrapping_add(rxpacket[rx_index + i]);
144            }
145            rx_index += data_length;
146
147            cal_sum = !cal_sum;
148
149            if rx_index >= rx_length {
150                return (None, CommResult::RxCorrupt);
151            }
152
153            if cal_sum != rxpacket[rx_index] {
154                return (None, CommResult::RxCorrupt);
155            }
156
157            return (Some(data), CommResult::Success);
158        }
159
160        (None, CommResult::RxCorrupt)
161    }
162
163    pub fn is_available(&self, sts_id: u8, address: u8, data_length: usize) -> (bool, u8) {
164        if !self.data_dict.contains_key(&sts_id) {
165            return (false, 0);
166        }
167
168        if address < self.start_address
169            || self.start_address + self.data_length as u8 - (data_length as u8) < address
170        {
171            return (false, 0);
172        }
173
174        if let Some(data) = self.data_dict.get(&sts_id) {
175            if data.is_empty() || data.len() < (data_length + 1) {
176                return (false, 0);
177            }
178            return (true, data[0]);
179        }
180
181        (false, 0)
182    }
183
184    pub fn get_data(&self, ph: &ProtocolPacketHandler, sts_id: u8, address: u8, data_length: usize) -> u32 {
185        if let Some(data) = self.data_dict.get(&sts_id) {
186            let offset = (address - self.start_address) as usize + 1;
187            
188            if data.len() <= offset {
189                return 0;
190            }
191
192            match data_length {
193                1 => data[offset] as u32,
194                2 => {
195                    if data.len() <= offset + 1 {
196                        return 0;
197                    }
198                    ph.sts_makeword(data[offset], data[offset + 1]) as u32
199                }
200                4 => {
201                    if data.len() <= offset + 3 {
202                        return 0;
203                    }
204                    ph.sts_makedword(
205                        ph.sts_makeword(data[offset], data[offset + 1]),
206                        ph.sts_makeword(data[offset + 2], data[offset + 3]),
207                    )
208                }
209                _ => 0,
210            }
211        } else {
212            0
213        }
214    }
215}