enphase_local/
production.rs

1// Copyright 2024 the octopower authors.
2// This project is dual-licensed under Apache 2.0 and MIT terms.
3// See LICENSE-APACHE and LICENSE-MIT for details.
4
5//! Types returned by the production API.
6
7use chrono::{DateTime, Utc, serde::ts_seconds};
8use serde::{Deserialize, Serialize};
9
10#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
11pub struct Production {
12    pub production: Vec<Device>,
13    pub consumption: Vec<Device>,
14    pub storage: Vec<Device>,
15}
16
17#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
18#[serde(rename_all = "camelCase")]
19pub struct Device {
20    /// The type of device this is about.
21    #[serde(rename = "type")]
22    pub type_: DeviceType,
23    /// The number of active devices of this type.
24    pub active_count: u32,
25    pub measurement_type: Option<MeasurementType>,
26    /// The time at which the reading was taken.
27    #[serde(with = "ts_seconds")]
28    pub reading_time: DateTime<Utc>,
29    /// The power in watts currently measured.
30    pub w_now: f64,
31    pub wh_now: Option<f64>,
32    pub state: Option<AcBatteryState>,
33    pub lines: Option<Vec<Line>>,
34    #[serde(flatten)]
35    pub details: Option<Details>,
36}
37
38#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
39#[serde(rename_all = "camelCase")]
40pub struct Line {
41    /// The power in watts currently measured.
42    pub w_now: f64,
43    #[serde(flatten)]
44    pub details: Details,
45}
46
47#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
48#[serde(rename_all = "camelCase")]
49pub struct Details {
50    /// The number of watt-hours this device has measured.
51    pub wh_lifetime: f64,
52    /// The total leading volt-amp reactive hours this device has measured.
53    pub varh_lead_lifetime: f64,
54    /// The total lagging volt-amp reactive hours this device has measured.
55    pub varh_lag_lifetime: f64,
56    /// The total volt-amp hours this device has measured.
57    pub vah_lifetime: f64,
58    /// The root-mean-square current currently measured.
59    pub rms_current: f64,
60    /// The root-mean-square voltage currently measured.
61    pub rms_voltage: f64,
62    pub react_pwr: f64,
63    pub apprnt_pwr: f64,
64    pub pwr_factor: f64,
65    pub wh_today: f64,
66    pub wh_last_seven_days: f64,
67    pub vah_today: f64,
68    pub varh_lead_today: f64,
69    pub varh_lag_today: f64,
70}
71
72#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
73#[serde(rename_all = "lowercase")]
74pub enum DeviceType {
75    /// IQ Inverters.
76    Inverters,
77    /// The Envoy Integrated Meter built-in to the gateway.
78    Eim,
79    /// AC battery.
80    Acb,
81    /// Revenue Grade Meters.
82    Rgms,
83    /// Power Meter Units.
84    Pmus,
85}
86
87#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
88#[serde(rename_all = "kebab-case")]
89pub enum MeasurementType {
90    /// Energy producted from the inverters.
91    Production,
92    /// Load minus solar production.
93    NetConsumption,
94    /// Total load.
95    TotalConsumption,
96}
97
98#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
99#[serde(rename_all = "lowercase")]
100pub enum AcBatteryState {
101    Charging,
102    Discharging,
103    Full,
104    Idle,
105}
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110
111    #[test]
112    fn parse_example() {
113        assert_eq!(
114            serde_json::from_str::<Production>(
115                r#"{
116    "production": [
117        {
118            "type": "inverters",
119            "activeCount": 10,
120            "readingTime": 1672574917,
121            "wNow": 225,
122            "whLifetime": 22444
123        },
124        {
125            "type": "eim",
126            "activeCount": 0,
127            "measurementType": "production",
128            "readingTime": 1672575063,
129            "wNow": 63.302,
130            "whLifetime": 1513.493,
131            "varhLeadLifetime": 0.024,
132            "varhLagLifetime": 16902.01,
133            "vahLifetime": 23774.477,
134            "rmsCurrent": 2.154,
135            "rmsVoltage": 240.087,
136            "reactPwr": 453.423,
137            "apprntPwr": 517.896,
138            "pwrFactor": 0.13,
139            "whToday": 2.0,
140            "whLastSevenDays": 1520.0,
141            "vahToday": 5106.0,
142            "varhLeadToday": 0.0,
143            "varhLagToday": 3865.0
144        }
145    ],
146    "consumption": [
147        {
148            "type": "eim",
149            "activeCount": 0,
150            "measurementType": "total-consumption",
151            "readingTime": 1672575063,
152            "wNow": 61.709,
153            "whLifetime": 1371.426,
154            "varhLeadLifetime": 0.205,
155            "varhLagLifetime": 16918.508,
156            "vahLifetime": 2593.65,
157            "rmsCurrent": 1.792,
158            "rmsVoltage": 243.568,
159            "reactPwr": -452.024,
160            "apprntPwr": 436.397,
161            "pwrFactor": 0.14,
162            "whToday": 0.0,
163            "whLastSevenDays": 1465.0,
164            "vahToday": 695.65,
165            "varhLeadToday": 0.205,
166            "varhLagToday": 3875.508
167        },
168        {
169            "type": "eim",
170            "activeCount": 0,
171            "measurementType": "net-consumption",
172            "readingTime": 1672575063,
173            "wNow": -1.592,
174            "whLifetime": 0.001,
175            "varhLeadLifetime": 0.181,
176            "varhLagLifetime": 16.498,
177            "vahLifetime": 2593.65,
178            "rmsCurrent": 0.363,
179            "rmsVoltage": 247.049,
180            "reactPwr": 1.398,
181            "apprntPwr": 61.047,
182            "pwrFactor": 0.0,
183            "whToday": 0,
184            "whLastSevenDays": 0,
185            "vahToday": 0,
186            "varhLeadToday": 0,
187            "varhLagToday": 0
188        }
189    ],
190    "storage": [
191        {
192            "type": "acb",
193            "activeCount": 0,
194            "readingTime": 0,
195            "wNow": 0,
196            "whNow": 0,
197            "state": "idle"
198        }
199    ]
200}
201            "#,
202            )
203            .unwrap(),
204            Production {
205                production: vec![
206                    Device {
207                        type_: DeviceType::Inverters,
208                        active_count: 10,
209                        measurement_type: None,
210                        reading_time: "2023-01-01T12:08:37Z".parse().unwrap(),
211                        w_now: 225.0,
212                        wh_now: None,
213                        state: None,
214                        lines: None,
215                        details: None,
216                    },
217                    Device {
218                        type_: DeviceType::Eim,
219                        active_count: 0,
220                        measurement_type: Some(MeasurementType::Production),
221                        reading_time: "2023-01-01T12:11:03Z".parse().unwrap(),
222                        w_now: 63.302,
223                        wh_now: None,
224                        state: None,
225                        lines: None,
226                        details: Some(Details {
227                            wh_lifetime: 1513.493,
228                            varh_lead_lifetime: 0.024,
229                            varh_lag_lifetime: 16902.01,
230                            vah_lifetime: 23774.477,
231                            rms_current: 2.154,
232                            rms_voltage: 240.087,
233                            react_pwr: 453.423,
234                            apprnt_pwr: 517.896,
235                            pwr_factor: 0.13,
236                            wh_today: 2.0,
237                            wh_last_seven_days: 1520.0,
238                            vah_today: 5106.0,
239                            varh_lead_today: 0.0,
240                            varh_lag_today: 3865.0
241                        })
242                    }
243                ],
244                consumption: vec![
245                    Device {
246                        type_: DeviceType::Eim,
247                        active_count: 0,
248                        measurement_type: Some(MeasurementType::TotalConsumption),
249                        reading_time: "2023-01-01T12:11:03Z".parse().unwrap(),
250                        w_now: 61.709,
251                        wh_now: None,
252                        state: None,
253                        lines: None,
254                        details: Some(Details {
255                            wh_lifetime: 1371.426,
256                            varh_lead_lifetime: 0.205,
257                            varh_lag_lifetime: 16918.508,
258                            vah_lifetime: 2593.65,
259                            rms_current: 1.792,
260                            rms_voltage: 243.568,
261                            react_pwr: -452.024,
262                            apprnt_pwr: 436.397,
263                            pwr_factor: 0.14,
264                            wh_today: 0.0,
265                            wh_last_seven_days: 1465.0,
266                            vah_today: 695.65,
267                            varh_lead_today: 0.205,
268                            varh_lag_today: 3875.508
269                        })
270                    },
271                    Device {
272                        type_: DeviceType::Eim,
273                        active_count: 0,
274                        measurement_type: Some(MeasurementType::NetConsumption),
275                        reading_time: "2023-01-01T12:11:03Z".parse().unwrap(),
276                        w_now: -1.592,
277                        wh_now: None,
278                        state: None,
279                        lines: None,
280                        details: Some(Details {
281                            wh_lifetime: 0.001,
282                            varh_lead_lifetime: 0.181,
283                            varh_lag_lifetime: 16.498,
284                            vah_lifetime: 2593.65,
285                            rms_current: 0.363,
286                            rms_voltage: 247.049,
287                            react_pwr: 1.398,
288                            apprnt_pwr: 61.047,
289                            pwr_factor: 0.0,
290                            wh_today: 0.0,
291                            wh_last_seven_days: 0.0,
292                            vah_today: 0.0,
293                            varh_lead_today: 0.0,
294                            varh_lag_today: 0.0
295                        })
296                    }
297                ],
298                storage: vec![Device {
299                    type_: DeviceType::Acb,
300                    active_count: 0,
301                    measurement_type: None,
302                    reading_time: DateTime::from_timestamp_millis(0).unwrap(),
303                    w_now: 0.0,
304                    wh_now: Some(0.0),
305                    state: Some(AcBatteryState::Idle),
306                    details: None,
307                    lines: None,
308                }],
309            }
310        );
311    }
312}