Skip to main content

sunspec/models/
model404.rs

1//! String Combiner (Advanced)
2/// Type alias for [`StringCombinerAdvancedInputs`].
3pub type Model404 = StringCombinerAdvancedInputs;
4/// String Combiner (Advanced)
5///
6/// An advanced string combiner including voltage and energy measurements
7///
8/// Detail: This model supersedes model 402
9#[derive(Debug)]
10#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
11pub struct StringCombinerAdvancedInputs {
12    /// Current scale factor
13    pub dca_sf: i16,
14    /// Amp-hour scale factor
15    pub dc_ahr_sf: Option<i16>,
16    /// Voltage scale factor
17    pub dcv_sf: Option<i16>,
18    /// Power scale factor
19    pub dcw_sf: Option<i16>,
20    /// Energy scale factor
21    pub dc_wh_sf: Option<i16>,
22    /// Rating
23    ///
24    /// Maximum DC Current Rating
25    pub dca_max: u16,
26    /// N
27    ///
28    /// Number of Inputs
29    pub n: u16,
30    /// Event
31    ///
32    /// Bitmask value.  Events
33    pub evt: Evt,
34    /// Vendor Event
35    ///
36    /// Bitmask value.  Vendor defined events
37    pub evt_vnd: Option<EvtVnd>,
38    /// Amps
39    ///
40    /// Total measured current
41    pub dca: i16,
42    /// Amp-hours
43    ///
44    /// Total metered Amp-hours
45    pub dc_ahr: Option<u32>,
46    /// Voltage
47    ///
48    /// Output Voltage
49    pub dcv: Option<i16>,
50    /// Temp
51    ///
52    /// Internal operating temperature
53    pub tmp: Option<i16>,
54    /// Watts
55    ///
56    /// Output power
57    pub dcw: Option<i16>,
58    /// PR
59    ///
60    /// DC Performance ratio value
61    pub dcpr: Option<i16>,
62    /// Watt-hours
63    ///
64    /// Output energy
65    pub dc_wh: Option<u32>,
66    /// Current scale factor for inputs
67    pub in_dca_sf: Option<i16>,
68    /// Amp-hour scale factor for inputs
69    pub in_dc_ahr_sf: Option<i16>,
70    /// Voltage scale factor for inputs
71    pub in_dcv_sf: Option<i16>,
72    /// Power scale factor for inputs
73    pub in_dcw_sf: Option<i16>,
74    /// Energy scale factor for inputs
75    pub in_dc_wh_sf: Option<i16>,
76    #[allow(missing_docs)]
77    pub string: Vec<String>,
78}
79#[allow(missing_docs)]
80impl StringCombinerAdvancedInputs {
81    pub const DCA_SF: crate::Point<Self, i16> = crate::Point::new(0, 1, false);
82    pub const DC_AHR_SF: crate::Point<Self, Option<i16>> = crate::Point::new(1, 1, false);
83    pub const DCV_SF: crate::Point<Self, Option<i16>> = crate::Point::new(2, 1, false);
84    pub const DCW_SF: crate::Point<Self, Option<i16>> = crate::Point::new(3, 1, false);
85    pub const DC_WH_SF: crate::Point<Self, Option<i16>> = crate::Point::new(4, 1, false);
86    pub const DCA_MAX: crate::Point<Self, u16> = crate::Point::new(5, 1, false);
87    pub const N: crate::Point<Self, u16> = crate::Point::new(6, 1, false);
88    pub const EVT: crate::Point<Self, Evt> = crate::Point::new(7, 2, false);
89    pub const EVT_VND: crate::Point<Self, Option<EvtVnd>> = crate::Point::new(9, 2, false);
90    pub const DCA: crate::Point<Self, i16> = crate::Point::new(11, 1, false);
91    pub const DC_AHR: crate::Point<Self, Option<u32>> = crate::Point::new(12, 2, false);
92    pub const DCV: crate::Point<Self, Option<i16>> = crate::Point::new(14, 1, false);
93    pub const TMP: crate::Point<Self, Option<i16>> = crate::Point::new(15, 1, false);
94    pub const DCW: crate::Point<Self, Option<i16>> = crate::Point::new(16, 1, false);
95    pub const DCPR: crate::Point<Self, Option<i16>> = crate::Point::new(17, 1, false);
96    pub const DC_WH: crate::Point<Self, Option<u32>> = crate::Point::new(18, 2, false);
97    pub const IN_DCA_SF: crate::Point<Self, Option<i16>> = crate::Point::new(20, 1, false);
98    pub const IN_DC_AHR_SF: crate::Point<Self, Option<i16>> = crate::Point::new(21, 1, false);
99    pub const IN_DCV_SF: crate::Point<Self, Option<i16>> = crate::Point::new(22, 1, false);
100    pub const IN_DCW_SF: crate::Point<Self, Option<i16>> = crate::Point::new(23, 1, false);
101    pub const IN_DC_WH_SF: crate::Point<Self, Option<i16>> = crate::Point::new(24, 1, false);
102}
103impl crate::Group for StringCombinerAdvancedInputs {
104    const LEN: u16 = 25;
105}
106impl StringCombinerAdvancedInputs {
107    fn parse_group(data: &[u16]) -> Result<(&[u16], Self), crate::DecodeError> {
108        let nested_data = data
109            .get(usize::from(<Self as crate::Group>::LEN)..)
110            .unwrap_or(&[]);
111        let (nested_data, string) = String::parse_multiple(nested_data)?;
112        Ok((
113            nested_data,
114            Self {
115                dca_sf: Self::DCA_SF.from_data(data)?,
116                dc_ahr_sf: Self::DC_AHR_SF.from_data(data)?,
117                dcv_sf: Self::DCV_SF.from_data(data)?,
118                dcw_sf: Self::DCW_SF.from_data(data)?,
119                dc_wh_sf: Self::DC_WH_SF.from_data(data)?,
120                dca_max: Self::DCA_MAX.from_data(data)?,
121                n: Self::N.from_data(data)?,
122                evt: Self::EVT.from_data(data)?,
123                evt_vnd: Self::EVT_VND.from_data(data)?,
124                dca: Self::DCA.from_data(data)?,
125                dc_ahr: Self::DC_AHR.from_data(data)?,
126                dcv: Self::DCV.from_data(data)?,
127                tmp: Self::TMP.from_data(data)?,
128                dcw: Self::DCW.from_data(data)?,
129                dcpr: Self::DCPR.from_data(data)?,
130                dc_wh: Self::DC_WH.from_data(data)?,
131                in_dca_sf: Self::IN_DCA_SF.from_data(data)?,
132                in_dc_ahr_sf: Self::IN_DC_AHR_SF.from_data(data)?,
133                in_dcv_sf: Self::IN_DCV_SF.from_data(data)?,
134                in_dcw_sf: Self::IN_DCW_SF.from_data(data)?,
135                in_dc_wh_sf: Self::IN_DC_WH_SF.from_data(data)?,
136                string,
137            },
138        ))
139    }
140}
141bitflags::bitflags! {
142    #[doc = " Event"] #[doc = " "] #[doc = " Bitmask value.  Events"] #[derive(Copy,
143    Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde",
144    derive(::serde::Serialize, ::serde::Deserialize))] pub struct Evt : u32 {
145    #[allow(missing_docs)] const LowVoltage = 1; #[allow(missing_docs)] const LowPower =
146    2; #[allow(missing_docs)] const LowEfficiency = 4; #[allow(missing_docs)] const
147    Current = 8; #[allow(missing_docs)] const Voltage = 16; #[allow(missing_docs)] const
148    Power = 32; #[allow(missing_docs)] const Pr = 64; #[allow(missing_docs)] const
149    Disconnected = 128; #[allow(missing_docs)] const FuseFault = 256;
150    #[allow(missing_docs)] const CombinerFuseFault = 512; #[allow(missing_docs)] const
151    CombinerCabinetOpen = 1024; #[allow(missing_docs)] const Temp = 2048;
152    #[allow(missing_docs)] const Groundfault = 4096; #[allow(missing_docs)] const
153    ReversedPolarity = 8192; #[allow(missing_docs)] const Incompatible = 16384;
154    #[allow(missing_docs)] const CommError = 32768; #[allow(missing_docs)] const
155    InternalError = 65536; #[allow(missing_docs)] const Theft = 131072;
156    #[allow(missing_docs)] const ArcDetected = 262144; }
157}
158impl crate::Value for Evt {
159    fn decode(data: &[u16]) -> Result<Self, crate::DecodeError> {
160        let value = u32::decode(data)?;
161        Ok(Self::from_bits_retain(value))
162    }
163    fn encode(self) -> Box<[u16]> {
164        self.bits().encode()
165    }
166}
167impl crate::FixedSize for Evt {
168    const SIZE: u16 = 2u16;
169    const INVALID: Self = Self::from_bits_retain(4294967295u32);
170    fn is_invalid(&self) -> bool {
171        self.bits() == 4294967295u32
172    }
173}
174bitflags::bitflags! {
175    #[doc = " Vendor Event"] #[doc = " "] #[doc =
176    " Bitmask value.  Vendor defined events"] #[derive(Copy, Clone, Debug, Eq,
177    PartialEq)] #[cfg_attr(feature = "serde", derive(::serde::Serialize,
178    ::serde::Deserialize))] pub struct EvtVnd : u32 {}
179}
180impl crate::Value for EvtVnd {
181    fn decode(data: &[u16]) -> Result<Self, crate::DecodeError> {
182        let value = u32::decode(data)?;
183        Ok(Self::from_bits_retain(value))
184    }
185    fn encode(self) -> Box<[u16]> {
186        self.bits().encode()
187    }
188}
189impl crate::FixedSize for EvtVnd {
190    const SIZE: u16 = 2u16;
191    const INVALID: Self = Self::from_bits_retain(4294967295u32);
192    fn is_invalid(&self) -> bool {
193        self.bits() == 4294967295u32
194    }
195}
196#[allow(missing_docs)]
197#[derive(Debug)]
198#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
199pub struct String {
200    /// ID
201    ///
202    /// Uniquely identifies this input set
203    pub in_id: u16,
204    /// Input Event
205    ///
206    /// String Input Event Flags
207    pub in_evt: StringInEvt,
208    /// Input Event Vendor
209    ///
210    /// String Input Vendor Event Flags
211    pub in_evt_vnd: Option<StringInEvtVnd>,
212    /// Amps
213    ///
214    /// String Input Current
215    pub in_dca: i16,
216    /// Amp-hours
217    ///
218    /// String Input Amp-Hours
219    pub in_dc_ahr: Option<u32>,
220    /// Voltage
221    ///
222    /// String Input Voltage
223    pub in_dcv: Option<i16>,
224    /// Watts
225    ///
226    /// String Input Power
227    pub in_dcw: Option<i16>,
228    /// Watt-hours
229    ///
230    /// String Input Energy
231    pub in_dc_wh: Option<u32>,
232    /// PR
233    ///
234    /// String Performance Ratio
235    pub in_dcpr: Option<u16>,
236    /// N
237    ///
238    /// Number of modules in this input string
239    pub in_n: Option<u16>,
240}
241#[allow(missing_docs)]
242impl String {
243    pub const IN_ID: crate::Point<Self, u16> = crate::Point::new(0, 1, false);
244    pub const IN_EVT: crate::Point<Self, StringInEvt> = crate::Point::new(1, 2, false);
245    pub const IN_EVT_VND: crate::Point<Self, Option<StringInEvtVnd>> =
246        crate::Point::new(3, 2, false);
247    pub const IN_DCA: crate::Point<Self, i16> = crate::Point::new(5, 1, false);
248    pub const IN_DC_AHR: crate::Point<Self, Option<u32>> = crate::Point::new(6, 2, false);
249    pub const IN_DCV: crate::Point<Self, Option<i16>> = crate::Point::new(8, 1, false);
250    pub const IN_DCW: crate::Point<Self, Option<i16>> = crate::Point::new(9, 1, false);
251    pub const IN_DC_WH: crate::Point<Self, Option<u32>> = crate::Point::new(10, 2, false);
252    pub const IN_DCPR: crate::Point<Self, Option<u16>> = crate::Point::new(12, 1, false);
253    pub const IN_N: crate::Point<Self, Option<u16>> = crate::Point::new(13, 1, false);
254}
255impl crate::Group for String {
256    const LEN: u16 = 14;
257}
258impl String {
259    fn parse_group(data: &[u16]) -> Result<(&[u16], Self), crate::DecodeError> {
260        let nested_data = data
261            .get(usize::from(<Self as crate::Group>::LEN)..)
262            .unwrap_or(&[]);
263        Ok((
264            nested_data,
265            Self {
266                in_id: Self::IN_ID.from_data(data)?,
267                in_evt: Self::IN_EVT.from_data(data)?,
268                in_evt_vnd: Self::IN_EVT_VND.from_data(data)?,
269                in_dca: Self::IN_DCA.from_data(data)?,
270                in_dc_ahr: Self::IN_DC_AHR.from_data(data)?,
271                in_dcv: Self::IN_DCV.from_data(data)?,
272                in_dcw: Self::IN_DCW.from_data(data)?,
273                in_dc_wh: Self::IN_DC_WH.from_data(data)?,
274                in_dcpr: Self::IN_DCPR.from_data(data)?,
275                in_n: Self::IN_N.from_data(data)?,
276            },
277        ))
278    }
279    fn parse_multiple(data: &[u16]) -> Result<(&[u16], Vec<Self>), crate::DecodeError> {
280        let group_len = usize::from(<String as crate::Group>::LEN);
281        if group_len == 0 {
282            return Ok((data, Vec::new()));
283        }
284        if data.len() % group_len != 0 {
285            return Err(crate::DecodeError::OutOfBounds);
286        }
287        let group_count = data.len() / group_len;
288        let (data, groups) =
289            (0..group_count).try_fold((data, Vec::new()), |(data, mut groups), _| {
290                let (data, group) = String::parse_group(data)?;
291                groups.push(group);
292                Ok::<_, crate::DecodeError>((data, groups))
293            })?;
294        Ok((data, groups))
295    }
296}
297bitflags::bitflags! {
298    #[doc = " Input Event"] #[doc = " "] #[doc = " String Input Event Flags"]
299    #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde",
300    derive(::serde::Serialize, ::serde::Deserialize))] pub struct StringInEvt : u32 {
301    #[allow(missing_docs)] const LowVoltage = 1; #[allow(missing_docs)] const LowPower =
302    2; #[allow(missing_docs)] const LowEfficiency = 4; #[allow(missing_docs)] const
303    Current = 8; #[allow(missing_docs)] const Voltage = 16; #[allow(missing_docs)] const
304    Power = 32; #[allow(missing_docs)] const Pr = 64; #[allow(missing_docs)] const
305    Disconnected = 128; #[allow(missing_docs)] const FuseFault = 256;
306    #[allow(missing_docs)] const CombinerFuseFault = 512; #[allow(missing_docs)] const
307    CombinerCabinetOpen = 1024; #[allow(missing_docs)] const Temp = 2048;
308    #[allow(missing_docs)] const Groundfault = 4096; #[allow(missing_docs)] const
309    ReversedPolarity = 8192; #[allow(missing_docs)] const Incompatible = 16384;
310    #[allow(missing_docs)] const CommError = 32768; #[allow(missing_docs)] const
311    InternalError = 65536; #[allow(missing_docs)] const Theft = 131072;
312    #[allow(missing_docs)] const ArcDetected = 262144; }
313}
314impl crate::Value for StringInEvt {
315    fn decode(data: &[u16]) -> Result<Self, crate::DecodeError> {
316        let value = u32::decode(data)?;
317        Ok(Self::from_bits_retain(value))
318    }
319    fn encode(self) -> Box<[u16]> {
320        self.bits().encode()
321    }
322}
323impl crate::FixedSize for StringInEvt {
324    const SIZE: u16 = 2u16;
325    const INVALID: Self = Self::from_bits_retain(4294967295u32);
326    fn is_invalid(&self) -> bool {
327        self.bits() == 4294967295u32
328    }
329}
330bitflags::bitflags! {
331    #[doc = " Input Event Vendor"] #[doc = " "] #[doc =
332    " String Input Vendor Event Flags"] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
333    #[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] pub
334    struct StringInEvtVnd : u32 {}
335}
336impl crate::Value for StringInEvtVnd {
337    fn decode(data: &[u16]) -> Result<Self, crate::DecodeError> {
338        let value = u32::decode(data)?;
339        Ok(Self::from_bits_retain(value))
340    }
341    fn encode(self) -> Box<[u16]> {
342        self.bits().encode()
343    }
344}
345impl crate::FixedSize for StringInEvtVnd {
346    const SIZE: u16 = 2u16;
347    const INVALID: Self = Self::from_bits_retain(4294967295u32);
348    fn is_invalid(&self) -> bool {
349        self.bits() == 4294967295u32
350    }
351}
352impl crate::Model for StringCombinerAdvancedInputs {
353    const ID: u16 = 404;
354    fn addr(models: &crate::Models) -> crate::ModelAddr<Self> {
355        models.m404
356    }
357    fn parse(data: &[u16]) -> Result<Self, crate::ParseError<Self>> {
358        let (_, model) = Self::parse_group(data)?;
359        Ok(model)
360    }
361}