1#![deny(missing_debug_implementations)]
2
3use std::io::{self, Read};
4use std::fmt;
5
6use dlms_cosem::{Error as DlmsError, Dlms, ObisMap};
7use mbusparse::{Error as MbusError, Telegram};
8
9#[derive(Debug)]
10pub enum Error {
11 Io(io::Error),
12 DecryptionFailed,
13}
14
15impl fmt::Display for Error {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 match self {
18 Self::Io(err) => err.fmt(f),
19 Self::DecryptionFailed => write!(f, "decryption failed"),
20 }
21 }
22}
23
24impl std::error::Error for Error {}
25
26#[derive(Debug)]
27pub struct SmartMeter<R> {
28 reader: R,
29 dlms: Dlms,
30 buffer: Vec<u8>,
31}
32
33impl<R> SmartMeter<R> {
34 pub fn new(reader: R, dlms: Dlms) -> Self {
35 SmartMeter { reader, dlms, buffer: Vec::new() }
36 }
37}
38
39impl<R: Read> Iterator for SmartMeter<R> {
40 type Item = Result<ObisMap, Error>;
41
42 fn next(&mut self) -> Option<Self::Item> {
44 let mut bytes_needed = 0;
45 let mut telegrams_needed = 1;
46
47 'outer: loop {
48 match (&mut self.reader).take(bytes_needed as u64).read_to_end(&mut self.buffer) {
49 Ok(_) => (),
50 Err(err) => return Some(Err(Error::Io(err))),
51 }
52
53 let mut telegrams = Vec::new();
54
55 let mut buffer = self.buffer.as_slice();
56 let mut telegram_1_len = 0;
57 let mut telegrams_len = 0;
58
59 for i in 0..telegrams_needed {
60 match Telegram::parse(buffer) {
61 Ok((next_buffer, telegram)) => {
62 let telegram_len = buffer.len() - next_buffer.len();
63 if i == 0 {
64 telegram_1_len = telegram_len;
65 }
66 telegrams_len += telegram_len;
67 buffer = next_buffer;
68 telegrams.push(telegram);
69 },
70 Err(MbusError::Incomplete(n)) => {
71 bytes_needed = n.map(|b| b.get()).unwrap_or(1);
72 continue 'outer
73 },
74 Err(MbusError::InvalidStartCharacter) => {
75 self.buffer.remove(0);
76 bytes_needed = 0;
77 continue 'outer
78 }
79 Err(MbusError::InvalidFormat | MbusError::ChecksumMismatch) => {
80 self.buffer.remove(0);
83 bytes_needed = 0;
84 continue 'outer
85 },
86 }
87 }
88 bytes_needed = 0;
89
90 match self.dlms.decrypt(&telegrams) {
91 Ok((_, obis_map)) => {
92 self.buffer.drain(0..telegrams_len);
93 return Some(Ok(obis_map))
94 },
95 Err(DlmsError::Incomplete(n)) => {
96 telegrams_needed += n.map(|t| t.get()).unwrap_or(1);
97 },
98 Err(DlmsError::InvalidFormat | DlmsError::ChecksumMismatch) => {
99 self.buffer.drain(0..telegram_1_len);
101 telegrams_needed = 1;
102 continue
103 },
104 Err(DlmsError::DecryptionFailed) => {
105 return Some(Err(Error::DecryptionFailed))
106 },
107 }
108 }
109 }
110}