teleinfo_parser/
hc.rs

1/*
2 * teleinfo-parser
3 * Copyright (c) 2018, 2021 Nicolas PENINGUY.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18
19use chrono::*;
20use frame::*;
21use std::io;
22
23/// All the usefull informations that can be extracted when in the Heures Creuses tariff option.
24#[derive(Debug)]
25pub struct HcInfos {
26
27    /// The date and time at which the frame was received.
28    pub date: DateTime<Local>,
29    /// The current tariff period, HP or HC
30    pub periode: String,
31    /// The value of the HC meter, in Wh.
32    pub hc: i32,
33    /// The value of the HP meter, in Wh.
34    pub hp: i32,
35    /// The current intensity in A (informative).
36    pub iinst: i32,
37    /// Apparent power, in W (informative).
38    pub papp: i32,
39    /// True if maximum subscribed intensity is exceeded.
40    pub alerte: bool
41}
42
43struct HcInfosBuilder {
44
45    date: Option<DateTime<Local>>,
46    periode: Option<String>,
47    hc: Option<i32>,
48    hp: Option<i32>,
49    iinst: Option<i32>,
50    papp: Option<i32>,
51    alerte: bool
52}
53
54macro_rules! get {
55    ($e:expr, $msg:expr) => (match $e { Some(e) => e, None => return Err(TeleinfoError::FrameError($msg.to_string())) })
56}
57
58impl HcInfos {
59
60    /// Try to read informations from the next frame. Any lowlevel error in the frame
61    /// (e.g. wrong checksum) will be returned as is. Additionnaly, the function will
62    /// ensure that all the expected fields are indeed present. If not, a FrameError will be
63    /// returned.
64    pub fn read<T: io::Read>(mut input: &mut T) -> Result<HcInfos, TeleinfoError> {
65
66        let frame = Frame::next_frame(&mut input)?;
67
68        return HcInfos::from(frame);
69    }
70
71    fn from(frame: Frame) -> Result<HcInfos, TeleinfoError> {
72
73        let mut builder = HcInfosBuilder::new();
74        let now: DateTime<Local> = Local::now();
75
76        builder.date(now);
77
78        for tag in frame.tags {
79            match tag {
80                Tag::PTEC(p) => {
81                    builder.periode(match p {
82                        PeriodeTarifaire::HP => "HP",
83                        PeriodeTarifaire::HC => "HC",
84                        _ => panic!("PeriodeTarifaire does not match HC")
85                    });
86                },
87                Tag::HCHC(v) => {
88                    builder.hc(v);
89                },
90                Tag::HCHP(v) => {
91                    builder.hp(v);
92                },
93                Tag::IINST(v) => {
94                    builder.iinst(v);
95                },
96                Tag::PAPP(v) => {
97                    builder.papp(v);
98                },
99                Tag::ADPS(_) => {
100                    builder.alerte(true);
101                },
102                _ => ()
103            };
104        }
105
106        builder.build()
107    }
108}
109
110impl HcInfosBuilder {
111
112    fn new() -> HcInfosBuilder {
113        HcInfosBuilder {
114            date: None,
115            periode: None,
116            hc: None,
117            hp: None,
118            iinst: None,
119            papp: None,
120            alerte: false
121        }
122    }
123
124    fn date(&mut self, date: DateTime<Local>) -> &mut HcInfosBuilder {
125        self.date = Some(date);
126        self
127    }
128
129    fn periode(&mut self, periode: &str) -> &mut HcInfosBuilder {
130        self.periode = Some(periode.to_string());
131        self
132    }
133
134    fn hc(&mut self, hc: i32) -> &mut HcInfosBuilder {
135        self.hc = Some(hc);
136        self
137    }
138
139    fn hp(&mut self, hp: i32) -> &mut HcInfosBuilder {
140        self.hp = Some(hp);
141        self
142    }
143
144    fn iinst(&mut self, iinst: i32) -> &mut HcInfosBuilder {
145        self.iinst = Some(iinst);
146        self
147    }
148
149    fn papp(&mut self, papp: i32) -> &mut HcInfosBuilder {
150        self.papp = Some(papp);
151        self
152    }
153
154    fn alerte(&mut self, alerte: bool) -> &mut HcInfosBuilder {
155        self.alerte = alerte;
156        self
157    }
158
159    fn build(self) -> Result<HcInfos, TeleinfoError> {
160        let infos = HcInfos {
161            date: get!(self.date, "Missing date"),
162            periode: get!(self.periode, "Missing periode"),
163            hc: get!(self.hc, "Missing hc"),
164            hp: get!(self.hp, "Missing hp"),
165            iinst: get!(self.iinst, "Missing iinst"),
166            papp: get!(self.papp, "Missing papp"),
167            alerte: self.alerte
168        };
169
170        Ok(infos)
171    }
172}