st3215/
group_sync_read.rs1use 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}