1use embedded_hal::delay::DelayNs;
30use error::UartError;
31
32pub mod error;
33#[cfg(test)]
34mod tests;
35
36const SEGMENT_READ: usize = 64;
38const SEGMENT_WRITE: usize = 8;
40const READ_DATA_SIZE: usize = 61;
42const SEGMENT_WRITE_CHANGE_BIT_RATE: usize = 11;
44
45const CHANNEL_1_OFFSET: usize = 3;
47const CHANNEL_2_OFFSET: usize = 35;
49
50const VOLTAGE: usize = 0;
52const CURRENT: usize = 4;
54const POWER: usize = 8;
56const POSITIVE_ENERGY: usize = 12;
58const FACTOR: usize = 16;
60const NEGATIVE_ENERGY: usize = 20;
62
63const FREQUENCY: usize = 31;
65const POWER_SIGN_1: usize = 27;
67const POWER_SIGN_2: usize = 28;
69
70type CrcCheck = fn(&[u8]) -> bool;
71
72fn is_crc_ok(buf: &[u8]) -> bool {
74 let mut crc: u16 = 0xFFFF;
75 let low = buf.len() - 2;
76 let hi = buf.len() - 1;
77 let buf_crc: u16 = (buf[hi] as u16) * 256 + (buf[low] as u16);
78
79 for current_byte in buf.iter().take(buf.len() - 2) {
80 crc ^= *current_byte as u16; for _ in (0..8).rev() {
83 if (crc & 0x0001) != 0 {
85 crc >>= 1; crc ^= 0xA001;
88 } else {
89 crc >>= 1; }
92 }
93 }
94 crc == buf_crc
96}
97
98fn crc_always_ok(_buf: &[u8]) -> bool {
99 true
100}
101
102#[inline(always)]
104fn conv8to32(hi_byte: u8, mid_byte_2: u8, mid_byte_1: u8, lo_byte: u8) -> u32 {
105 lo_byte as u32
106 + ((mid_byte_1 as u32) << 8)
107 + ((mid_byte_2 as u32) << 16)
108 + ((hi_byte as u32) << 24)
109}
110
111fn get_data(segment_read: &[u8; SEGMENT_READ], n: usize) -> u32 {
113 conv8to32(
114 segment_read[n],
115 segment_read[n + 1],
116 segment_read[n + 2],
117 segment_read[n + 3],
118 )
119}
120
121#[inline(always)]
123fn power(segment_read: &[u8; SEGMENT_READ], power: usize, sign: usize) -> f32 {
124 let p = (get_data(segment_read, power) as f32) * 0.0001;
125
126 if segment_read[sign] == 1 && p > 0.0 {
127 return -p;
128 }
129
130 p
131}
132
133pub enum ChangeBitrate {
135 B4800,
136 B9600,
137 B19200,
138 B38400,
139}
140
141pub trait Uart {
143 fn read(&mut self, buf: &mut [u8], timeout: u32) -> Result<usize, error::UartError>;
145
146 fn write(&mut self, bytes: &[u8]) -> Result<usize, error::UartError>;
148
149 fn change_baudrate(&mut self, f: u32) -> Result<(), error::UartError> ;
151}
152
153pub struct Channel {
155 data_offset: usize,
156 power_sign: usize,
157 voltage: f32,
158 current: f32,
159 positive_energy: f32,
160 negative_energy: f32,
161 power: f32,
162 factor: f32,
163}
164
165impl Channel {
166 pub fn new(data_offset: usize, power_sign: usize) -> Self {
167 Self {
168 data_offset,
169 power_sign,
170 voltage: 0.0,
171 current: 0.0,
172 positive_energy: 0.0,
173 negative_energy: 0.0,
174 power: 0.0,
175 factor: 0.0,
176 }
177 }
178
179 pub fn voltage(&self) -> f32 {
181 self.voltage
182 }
183
184 pub fn current(&self) -> f32 {
186 self.current
187 }
188
189 pub fn positive_energy(&self) -> f32 {
191 self.positive_energy
192 }
193
194 pub fn negative_energy(&self) -> f32 {
196 self.negative_energy
197 }
198
199 pub fn power(&self) -> f32 {
201 self.power
202 }
203
204 pub fn factor(&self) -> f32 {
206 self.factor
207 }
208
209 fn update(&mut self, segment_read: &[u8; SEGMENT_READ]) {
211 self.voltage = (get_data(segment_read, self.data_offset + VOLTAGE) as f32) * 0.0001;
212 self.current = (get_data(segment_read, self.data_offset + CURRENT) as f32) * 0.0001;
213 self.positive_energy =
214 (get_data(segment_read, self.data_offset + POSITIVE_ENERGY) as f32) * 0.0001;
215 self.negative_energy =
216 (get_data(segment_read, self.data_offset + NEGATIVE_ENERGY) as f32) * 0.0001;
217 self.factor = (get_data(segment_read, self.data_offset + FACTOR) as f32) * 0.001;
218 self.power = power(segment_read, self.data_offset + POWER, self.power_sign);
219 }
220}
221
222pub struct JsyMk194<U, D>
224where
225 U: Uart,
226 D: DelayNs,
227{
228 uart: U,
229 delay: D,
230 segment_write: [u8; SEGMENT_WRITE], segment_read: [u8; SEGMENT_READ],
232 is_crc_valid: CrcCheck,
233 frequency: f32,
234
235 pub channel1: Channel,
236 pub channel2: Channel,
237}
238
239impl<U, D> JsyMk194<U, D>
240where
241 U: Uart,
242 D: DelayNs,
243{
244 pub fn new(uart: U, delay: D) -> Self {
246 Self {
247 uart,
248 delay,
249 segment_write: [0x01, 0x03, 0x00, 0x48, 0x00, 0x0e, 0x44, 0x18],
250 segment_read: [0; SEGMENT_READ],
251 is_crc_valid: is_crc_ok,
252 channel1: Channel::new(CHANNEL_1_OFFSET, POWER_SIGN_1),
253 channel2: Channel::new(CHANNEL_2_OFFSET, POWER_SIGN_2),
254 frequency: 0.0,
255 }
256 }
257
258 pub fn new_without_crc_check(uart: U, delay: D) -> Self {
260 Self {
261 uart,
262 delay,
263 segment_write: [0x01, 0x03, 0x00, 0x48, 0x00, 0x0e, 0x44, 0x18],
264 segment_read: [0; SEGMENT_READ],
265 is_crc_valid: crc_always_ok,
266 channel1: Channel::new(CHANNEL_1_OFFSET, POWER_SIGN_1),
267 channel2: Channel::new(CHANNEL_2_OFFSET, POWER_SIGN_2),
268 frequency: 0.0,
269 }
270 }
271
272 pub fn read(&mut self) -> Result<(), error::UartError> {
274 self.read_with_timeout(100)
275 }
276
277 pub fn read_with_timeout(&mut self, timeout_ms: u32) -> Result<(), error::UartError> {
279 self.uart.write(&self.segment_write)?;
281
282 let is_read_data = self.uart.read(&mut self.segment_read, timeout_ms);
283
284 match is_read_data {
285 Ok(data_size) => {
286 if data_size != READ_DATA_SIZE {
287 return Err(error::UartError::new(
288 error::UartErrorKind::ReadInsuffisantBytes,
289 format!(
290 "Try to read {} bytes, but Uart read only {} bytes",
291 READ_DATA_SIZE, data_size
292 ),
293 ));
294 }
295
296 if (self.is_crc_valid)(&self.segment_read[0..data_size]) {
297 self.channel1.update(&self.segment_read);
298 self.channel2.update(&self.segment_read);
299 self.frequency = (get_data(&self.segment_read, FREQUENCY) as f32) * 0.01;
300 Ok(())
301 } else {
302 Err(error::UartError::from(error::UartErrorKind::BadCrc))
303 }
304 }
305 Err(e) => Err(e),
306 }
307 }
308
309 pub fn frequency(&self) -> f32 {
311 self.frequency
312 }
313
314 pub fn change_bitrate(
318 &mut self,
319 new_bitrate: ChangeBitrate,
320 ) -> Result<(), error::ChangeBitrateError> {
321 let mut segment: [u8; SEGMENT_WRITE_CHANGE_BIT_RATE] = [
322 0x00, 0x10, 0x00, 0x04, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x00,
323 ];
324
325 match new_bitrate {
326 ChangeBitrate::B9600 => self.update_segment(&mut segment, 0x06, 0x2b, 0xd6),
327 ChangeBitrate::B19200 => self.update_segment(&mut segment, 0x07, 0xea, 0x16),
328 ChangeBitrate::B38400 => self.update_segment(&mut segment, 0x08, 0xaa, 0x12),
329 _ => self.update_segment(&mut segment, 0x05, 0x6B, 0xD7),
330 }
331
332 self.delay.delay_ms(1000);
333
334 let result = self.uart.write(&segment);
335
336 match result {
337 Ok(write_size) => {
338 if write_size == segment.len() {
339 return Ok(());
340 }
341
342 Err(error::ChangeBitrateError::new(error::UartError::new(
343 error::UartErrorKind::WriteInsuffisantBytes,
344 format!(
345 "Try to write {} bytes, but Uart write only {} bytes",
346 segment.len(),
347 write_size
348 ),
349 )))
350 }
351 Err(e) => Err(error::ChangeBitrateError::new(e)),
352 }
353 }
354
355 pub fn change_baudrate(&mut self, f: u32) -> Result<(), UartError> {
356 self.uart.change_baudrate(f)
357 }
358
359 fn update_segment(
360 &self,
361 data: &mut [u8; SEGMENT_WRITE_CHANGE_BIT_RATE],
362 value: u8,
363 crc1: u8,
364 crc2: u8,
365 ) {
366 data[8] = value;
367 data[9] = crc1;
368 data[10] = crc2;
369 }
370
371 #[cfg(test)]
372 fn get_uart(&self) -> &U {
373 &self.uart
374 }
375}