Skip to main content

sunspec/models/
model64112.rs

1//! OutBack FM Charge Controller
2/// OutBack FM Charge Controller
3#[derive(Debug)]
4#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
5pub struct Model64112 {
6    /// Port Number
7    pub port: u16,
8    #[allow(missing_docs)]
9    pub v_sf: i16,
10    #[allow(missing_docs)]
11    pub c_sf: i16,
12    #[allow(missing_docs)]
13    pub h_sf: i16,
14    #[allow(missing_docs)]
15    pub p_sf: i16,
16    #[allow(missing_docs)]
17    pub ah_sf: i16,
18    #[allow(missing_docs)]
19    pub kwh_sf: i16,
20    /// Faults
21    pub cc_config_fault: CcConfigFault,
22    /// Absorb
23    pub cc_config_absorb_v: u16,
24    /// Absorb Time
25    pub cc_config_absorb_hr: u16,
26    /// Absorb End
27    pub cc_config_absorb_end_a: u16,
28    /// Rebulk
29    pub cc_config_rebulk_v: u16,
30    /// Float
31    pub cc_config_float_v: u16,
32    /// Maximum Charge
33    pub cc_config_max_chg_a: u16,
34    /// Equalize
35    pub cc_config_equalize_v: u16,
36    /// Equalize Time
37    pub cc_config_equalize_hr: u16,
38    /// Auto Equalize Interval
39    pub cc_config_auto_equalize: u16,
40    /// MPPT mode
41    pub cc_config_mppt_mode: CcConfigMpptMode,
42    /// Sweep Width
43    pub cc_config_sweep_width: CcConfigSweepWidth,
44    /// Sweep Maximum
45    pub cc_config_sweep_max: CcConfigSweepMax,
46    /// U-Pick PWM Duty Cycle
47    pub cc_config_u_pick_duty_cyc: u16,
48    /// Grid Tie Mode
49    pub cc_config_grid_tie: CcConfigGridTie,
50    /// Temp Comp Mode
51    pub cc_config_temp_comp: CcConfigTempComp,
52    /// Temp Comp Lower Limit
53    pub cc_config_temp_comp_llimt: u16,
54    /// Temp Comp Upper Limit
55    pub cc_config_temp_comp_hlimt: u16,
56    /// Auto Restart Mode
57    pub cc_config_auto_restart: CcConfigAutoRestart,
58    /// Wakeup VOC Change
59    pub cc_config_wakeup_voc: u16,
60    /// Snooze Mode
61    pub cc_config_snooze_mode_a: u16,
62    /// Wakeup Interval
63    pub cc_config_wakeup_interval: u16,
64    /// AUX Output Mode
65    pub cc_config_aux_mode: CcConfigAuxMode,
66    /// AUX Output Control
67    pub cc_config_aux_control: CcConfigAuxControl,
68    /// AUX Output State
69    pub cc_config_aux_state: CcConfigAuxState,
70    /// AUX Output Polarity
71    pub cc_config_aux_polarity: CcConfigAuxPolarity,
72    /// AUX Low Battery Disconnect
73    pub cc_config_aux_l_batt_disc: u16,
74    /// AUX Low Battery Reconnect
75    pub cc_config_aux_l_batt_rcon: u16,
76    /// AUX Low Battery Disconnect Delay
77    pub cc_config_aux_l_batt_dly: u16,
78    /// AUX Vent Fan
79    pub cc_config_aux_vent_fan_v: u16,
80    /// AUX PV Trigger
81    pub cc_config_aux_pv_trigger_v: u16,
82    /// AUX PV Trigger Hold Time
83    pub cc_config_aux_pv_trg_h_tm: u16,
84    /// AUX Night Light Threshold
85    pub cc_config_aux_nlite_thrs_v: u16,
86    /// AUX Night Light On Time
87    pub cc_config_aux_nlite_on_tm: u16,
88    /// AUX Night Light On Hysteresis
89    pub cc_config_aux_nlite_on_hist: u16,
90    /// AUX Night Light Off Hysteresis
91    pub cc_config_aux_nlite_off_hist: u16,
92    /// AUX Error Output Low Battery
93    pub cc_config_aux_error_batt_v: u16,
94    /// AUX Divert Hold Time
95    pub cc_config_aux_divert_h_time: u16,
96    /// AUX Divert Delay Time
97    pub cc_config_aux_divert_dly_time: u16,
98    /// AUX Divert Relative
99    pub cc_config_aux_divert_rel_v: u16,
100    /// AUX Divert Hysteresis
101    pub cc_config_aux_divert_hyst_v: u16,
102    /// FM CC Major Firmware Number
103    pub cc_config_major_fw_rev: u16,
104    /// FM CC Mid Firmware Number
105    pub cc_config_mid_fw_rev: u16,
106    /// FM CC Minor Firmware Number
107    pub cc_config_minor_fw_rev: u16,
108    /// Set Data Log Day Offset
109    pub cc_config_data_log_day_offset: u16,
110    /// Current Data Log Day Offset
111    pub cc_config_data_log_cur_day_off: u16,
112    /// Data Log Daily (Ah)
113    pub cc_config_data_log_daily_ah: u16,
114    /// Data Log Daily (kWh)
115    pub cc_config_data_log_daily_kwh: u16,
116    /// Data Log Daily Maximum Output (A)
117    pub cc_config_data_log_max_out_a: u16,
118    /// Data Log Daily Maximum Output (W)
119    pub cc_config_data_log_max_out_w: u16,
120    /// Data Log Daily Absorb Time
121    pub cc_config_data_log_absorb_t: u16,
122    /// Data Log Daily Float Time
123    pub cc_config_data_log_float_t: u16,
124    /// Data Log Daily Minimum Battery
125    pub cc_config_data_log_min_batt_v: u16,
126    /// Data Log Daily Maximum Battery
127    pub cc_config_data_log_max_batt_v: u16,
128    /// Data Log Daily Maximum Input
129    pub cc_config_data_log_max_input_v: u16,
130    /// Data Log Clear
131    pub cc_config_data_log_clear: u16,
132    /// Data Log Clear Complement
133    pub cc_config_data_log_clr_comp: u16,
134}
135#[allow(missing_docs)]
136impl Model64112 {
137    pub const PORT: crate::Point<Self, u16> = crate::Point::new(0, 1, false);
138    pub const V_SF: crate::Point<Self, i16> = crate::Point::new(1, 1, false);
139    pub const C_SF: crate::Point<Self, i16> = crate::Point::new(2, 1, false);
140    pub const H_SF: crate::Point<Self, i16> = crate::Point::new(3, 1, false);
141    pub const P_SF: crate::Point<Self, i16> = crate::Point::new(4, 1, false);
142    pub const AH_SF: crate::Point<Self, i16> = crate::Point::new(5, 1, false);
143    pub const KWH_SF: crate::Point<Self, i16> = crate::Point::new(6, 1, false);
144    pub const CC_CONFIG_FAULT: crate::Point<Self, CcConfigFault> = crate::Point::new(7, 1, false);
145    pub const CC_CONFIG_ABSORB_V: crate::Point<Self, u16> = crate::Point::new(8, 1, false);
146    pub const CC_CONFIG_ABSORB_HR: crate::Point<Self, u16> = crate::Point::new(9, 1, false);
147    pub const CC_CONFIG_ABSORB_END_A: crate::Point<Self, u16> = crate::Point::new(10, 1, false);
148    pub const CC_CONFIG_REBULK_V: crate::Point<Self, u16> = crate::Point::new(11, 1, false);
149    pub const CC_CONFIG_FLOAT_V: crate::Point<Self, u16> = crate::Point::new(12, 1, false);
150    pub const CC_CONFIG_MAX_CHG_A: crate::Point<Self, u16> = crate::Point::new(13, 1, false);
151    pub const CC_CONFIG_EQUALIZE_V: crate::Point<Self, u16> = crate::Point::new(14, 1, false);
152    pub const CC_CONFIG_EQUALIZE_HR: crate::Point<Self, u16> = crate::Point::new(15, 1, false);
153    pub const CC_CONFIG_AUTO_EQUALIZE: crate::Point<Self, u16> = crate::Point::new(16, 1, false);
154    pub const CC_CONFIG_MPPT_MODE: crate::Point<Self, CcConfigMpptMode> =
155        crate::Point::new(17, 1, false);
156    pub const CC_CONFIG_SWEEP_WIDTH: crate::Point<Self, CcConfigSweepWidth> =
157        crate::Point::new(18, 1, false);
158    pub const CC_CONFIG_SWEEP_MAX: crate::Point<Self, CcConfigSweepMax> =
159        crate::Point::new(19, 1, false);
160    pub const CC_CONFIG_U_PICK_DUTY_CYC: crate::Point<Self, u16> = crate::Point::new(20, 1, false);
161    pub const CC_CONFIG_GRID_TIE: crate::Point<Self, CcConfigGridTie> =
162        crate::Point::new(21, 1, false);
163    pub const CC_CONFIG_TEMP_COMP: crate::Point<Self, CcConfigTempComp> =
164        crate::Point::new(22, 1, false);
165    pub const CC_CONFIG_TEMP_COMP_LLIMT: crate::Point<Self, u16> = crate::Point::new(23, 1, false);
166    pub const CC_CONFIG_TEMP_COMP_HLIMT: crate::Point<Self, u16> = crate::Point::new(24, 1, false);
167    pub const CC_CONFIG_AUTO_RESTART: crate::Point<Self, CcConfigAutoRestart> =
168        crate::Point::new(25, 1, false);
169    pub const CC_CONFIG_WAKEUP_VOC: crate::Point<Self, u16> = crate::Point::new(26, 1, false);
170    pub const CC_CONFIG_SNOOZE_MODE_A: crate::Point<Self, u16> = crate::Point::new(27, 1, false);
171    pub const CC_CONFIG_WAKEUP_INTERVAL: crate::Point<Self, u16> = crate::Point::new(28, 1, false);
172    pub const CC_CONFIG_AUX_MODE: crate::Point<Self, CcConfigAuxMode> =
173        crate::Point::new(29, 1, false);
174    pub const CC_CONFIG_AUX_CONTROL: crate::Point<Self, CcConfigAuxControl> =
175        crate::Point::new(30, 1, false);
176    pub const CC_CONFIG_AUX_STATE: crate::Point<Self, CcConfigAuxState> =
177        crate::Point::new(31, 1, false);
178    pub const CC_CONFIG_AUX_POLARITY: crate::Point<Self, CcConfigAuxPolarity> =
179        crate::Point::new(32, 1, false);
180    pub const CC_CONFIG_AUX_L_BATT_DISC: crate::Point<Self, u16> = crate::Point::new(33, 1, false);
181    pub const CC_CONFIG_AUX_L_BATT_RCON: crate::Point<Self, u16> = crate::Point::new(34, 1, false);
182    pub const CC_CONFIG_AUX_L_BATT_DLY: crate::Point<Self, u16> = crate::Point::new(35, 1, false);
183    pub const CC_CONFIG_AUX_VENT_FAN_V: crate::Point<Self, u16> = crate::Point::new(36, 1, false);
184    pub const CC_CONFIG_AUX_PV_TRIGGER_V: crate::Point<Self, u16> = crate::Point::new(37, 1, false);
185    pub const CC_CONFIG_AUX_PV_TRG_H_TM: crate::Point<Self, u16> = crate::Point::new(38, 1, false);
186    pub const CC_CONFIG_AUX_NLITE_THRS_V: crate::Point<Self, u16> = crate::Point::new(39, 1, false);
187    pub const CC_CONFIG_AUX_NLITE_ON_TM: crate::Point<Self, u16> = crate::Point::new(40, 1, false);
188    pub const CC_CONFIG_AUX_NLITE_ON_HIST: crate::Point<Self, u16> =
189        crate::Point::new(41, 1, false);
190    pub const CC_CONFIG_AUX_NLITE_OFF_HIST: crate::Point<Self, u16> =
191        crate::Point::new(42, 1, false);
192    pub const CC_CONFIG_AUX_ERROR_BATT_V: crate::Point<Self, u16> = crate::Point::new(43, 1, false);
193    pub const CC_CONFIG_AUX_DIVERT_H_TIME: crate::Point<Self, u16> =
194        crate::Point::new(44, 1, false);
195    pub const CC_CONFIG_AUX_DIVERT_DLY_TIME: crate::Point<Self, u16> =
196        crate::Point::new(45, 1, false);
197    pub const CC_CONFIG_AUX_DIVERT_REL_V: crate::Point<Self, u16> = crate::Point::new(46, 1, false);
198    pub const CC_CONFIG_AUX_DIVERT_HYST_V: crate::Point<Self, u16> =
199        crate::Point::new(47, 1, false);
200    pub const CC_CONFIG_MAJOR_FW_REV: crate::Point<Self, u16> = crate::Point::new(48, 1, false);
201    pub const CC_CONFIG_MID_FW_REV: crate::Point<Self, u16> = crate::Point::new(49, 1, false);
202    pub const CC_CONFIG_MINOR_FW_REV: crate::Point<Self, u16> = crate::Point::new(50, 1, false);
203    pub const CC_CONFIG_DATA_LOG_DAY_OFFSET: crate::Point<Self, u16> =
204        crate::Point::new(51, 1, false);
205    pub const CC_CONFIG_DATA_LOG_CUR_DAY_OFF: crate::Point<Self, u16> =
206        crate::Point::new(52, 1, false);
207    pub const CC_CONFIG_DATA_LOG_DAILY_AH: crate::Point<Self, u16> =
208        crate::Point::new(53, 1, false);
209    pub const CC_CONFIG_DATA_LOG_DAILY_KWH: crate::Point<Self, u16> =
210        crate::Point::new(54, 1, false);
211    pub const CC_CONFIG_DATA_LOG_MAX_OUT_A: crate::Point<Self, u16> =
212        crate::Point::new(55, 1, false);
213    pub const CC_CONFIG_DATA_LOG_MAX_OUT_W: crate::Point<Self, u16> =
214        crate::Point::new(56, 1, false);
215    pub const CC_CONFIG_DATA_LOG_ABSORB_T: crate::Point<Self, u16> =
216        crate::Point::new(57, 1, false);
217    pub const CC_CONFIG_DATA_LOG_FLOAT_T: crate::Point<Self, u16> = crate::Point::new(58, 1, false);
218    pub const CC_CONFIG_DATA_LOG_MIN_BATT_V: crate::Point<Self, u16> =
219        crate::Point::new(59, 1, false);
220    pub const CC_CONFIG_DATA_LOG_MAX_BATT_V: crate::Point<Self, u16> =
221        crate::Point::new(60, 1, false);
222    pub const CC_CONFIG_DATA_LOG_MAX_INPUT_V: crate::Point<Self, u16> =
223        crate::Point::new(61, 1, false);
224    pub const CC_CONFIG_DATA_LOG_CLEAR: crate::Point<Self, u16> = crate::Point::new(62, 1, false);
225    pub const CC_CONFIG_DATA_LOG_CLR_COMP: crate::Point<Self, u16> =
226        crate::Point::new(63, 1, false);
227}
228impl crate::Group for Model64112 {
229    const LEN: u16 = 64;
230}
231impl Model64112 {
232    fn parse_group(data: &[u16]) -> Result<(&[u16], Self), crate::DecodeError> {
233        let nested_data = data
234            .get(usize::from(<Self as crate::Group>::LEN)..)
235            .unwrap_or(&[]);
236        Ok((
237            nested_data,
238            Self {
239                port: Self::PORT.from_data(data)?,
240                v_sf: Self::V_SF.from_data(data)?,
241                c_sf: Self::C_SF.from_data(data)?,
242                h_sf: Self::H_SF.from_data(data)?,
243                p_sf: Self::P_SF.from_data(data)?,
244                ah_sf: Self::AH_SF.from_data(data)?,
245                kwh_sf: Self::KWH_SF.from_data(data)?,
246                cc_config_fault: Self::CC_CONFIG_FAULT.from_data(data)?,
247                cc_config_absorb_v: Self::CC_CONFIG_ABSORB_V.from_data(data)?,
248                cc_config_absorb_hr: Self::CC_CONFIG_ABSORB_HR.from_data(data)?,
249                cc_config_absorb_end_a: Self::CC_CONFIG_ABSORB_END_A.from_data(data)?,
250                cc_config_rebulk_v: Self::CC_CONFIG_REBULK_V.from_data(data)?,
251                cc_config_float_v: Self::CC_CONFIG_FLOAT_V.from_data(data)?,
252                cc_config_max_chg_a: Self::CC_CONFIG_MAX_CHG_A.from_data(data)?,
253                cc_config_equalize_v: Self::CC_CONFIG_EQUALIZE_V.from_data(data)?,
254                cc_config_equalize_hr: Self::CC_CONFIG_EQUALIZE_HR.from_data(data)?,
255                cc_config_auto_equalize: Self::CC_CONFIG_AUTO_EQUALIZE.from_data(data)?,
256                cc_config_mppt_mode: Self::CC_CONFIG_MPPT_MODE.from_data(data)?,
257                cc_config_sweep_width: Self::CC_CONFIG_SWEEP_WIDTH.from_data(data)?,
258                cc_config_sweep_max: Self::CC_CONFIG_SWEEP_MAX.from_data(data)?,
259                cc_config_u_pick_duty_cyc: Self::CC_CONFIG_U_PICK_DUTY_CYC.from_data(data)?,
260                cc_config_grid_tie: Self::CC_CONFIG_GRID_TIE.from_data(data)?,
261                cc_config_temp_comp: Self::CC_CONFIG_TEMP_COMP.from_data(data)?,
262                cc_config_temp_comp_llimt: Self::CC_CONFIG_TEMP_COMP_LLIMT.from_data(data)?,
263                cc_config_temp_comp_hlimt: Self::CC_CONFIG_TEMP_COMP_HLIMT.from_data(data)?,
264                cc_config_auto_restart: Self::CC_CONFIG_AUTO_RESTART.from_data(data)?,
265                cc_config_wakeup_voc: Self::CC_CONFIG_WAKEUP_VOC.from_data(data)?,
266                cc_config_snooze_mode_a: Self::CC_CONFIG_SNOOZE_MODE_A.from_data(data)?,
267                cc_config_wakeup_interval: Self::CC_CONFIG_WAKEUP_INTERVAL.from_data(data)?,
268                cc_config_aux_mode: Self::CC_CONFIG_AUX_MODE.from_data(data)?,
269                cc_config_aux_control: Self::CC_CONFIG_AUX_CONTROL.from_data(data)?,
270                cc_config_aux_state: Self::CC_CONFIG_AUX_STATE.from_data(data)?,
271                cc_config_aux_polarity: Self::CC_CONFIG_AUX_POLARITY.from_data(data)?,
272                cc_config_aux_l_batt_disc: Self::CC_CONFIG_AUX_L_BATT_DISC.from_data(data)?,
273                cc_config_aux_l_batt_rcon: Self::CC_CONFIG_AUX_L_BATT_RCON.from_data(data)?,
274                cc_config_aux_l_batt_dly: Self::CC_CONFIG_AUX_L_BATT_DLY.from_data(data)?,
275                cc_config_aux_vent_fan_v: Self::CC_CONFIG_AUX_VENT_FAN_V.from_data(data)?,
276                cc_config_aux_pv_trigger_v: Self::CC_CONFIG_AUX_PV_TRIGGER_V.from_data(data)?,
277                cc_config_aux_pv_trg_h_tm: Self::CC_CONFIG_AUX_PV_TRG_H_TM.from_data(data)?,
278                cc_config_aux_nlite_thrs_v: Self::CC_CONFIG_AUX_NLITE_THRS_V.from_data(data)?,
279                cc_config_aux_nlite_on_tm: Self::CC_CONFIG_AUX_NLITE_ON_TM.from_data(data)?,
280                cc_config_aux_nlite_on_hist: Self::CC_CONFIG_AUX_NLITE_ON_HIST.from_data(data)?,
281                cc_config_aux_nlite_off_hist: Self::CC_CONFIG_AUX_NLITE_OFF_HIST.from_data(data)?,
282                cc_config_aux_error_batt_v: Self::CC_CONFIG_AUX_ERROR_BATT_V.from_data(data)?,
283                cc_config_aux_divert_h_time: Self::CC_CONFIG_AUX_DIVERT_H_TIME.from_data(data)?,
284                cc_config_aux_divert_dly_time: Self::CC_CONFIG_AUX_DIVERT_DLY_TIME
285                    .from_data(data)?,
286                cc_config_aux_divert_rel_v: Self::CC_CONFIG_AUX_DIVERT_REL_V.from_data(data)?,
287                cc_config_aux_divert_hyst_v: Self::CC_CONFIG_AUX_DIVERT_HYST_V.from_data(data)?,
288                cc_config_major_fw_rev: Self::CC_CONFIG_MAJOR_FW_REV.from_data(data)?,
289                cc_config_mid_fw_rev: Self::CC_CONFIG_MID_FW_REV.from_data(data)?,
290                cc_config_minor_fw_rev: Self::CC_CONFIG_MINOR_FW_REV.from_data(data)?,
291                cc_config_data_log_day_offset: Self::CC_CONFIG_DATA_LOG_DAY_OFFSET
292                    .from_data(data)?,
293                cc_config_data_log_cur_day_off: Self::CC_CONFIG_DATA_LOG_CUR_DAY_OFF
294                    .from_data(data)?,
295                cc_config_data_log_daily_ah: Self::CC_CONFIG_DATA_LOG_DAILY_AH.from_data(data)?,
296                cc_config_data_log_daily_kwh: Self::CC_CONFIG_DATA_LOG_DAILY_KWH.from_data(data)?,
297                cc_config_data_log_max_out_a: Self::CC_CONFIG_DATA_LOG_MAX_OUT_A.from_data(data)?,
298                cc_config_data_log_max_out_w: Self::CC_CONFIG_DATA_LOG_MAX_OUT_W.from_data(data)?,
299                cc_config_data_log_absorb_t: Self::CC_CONFIG_DATA_LOG_ABSORB_T.from_data(data)?,
300                cc_config_data_log_float_t: Self::CC_CONFIG_DATA_LOG_FLOAT_T.from_data(data)?,
301                cc_config_data_log_min_batt_v: Self::CC_CONFIG_DATA_LOG_MIN_BATT_V
302                    .from_data(data)?,
303                cc_config_data_log_max_batt_v: Self::CC_CONFIG_DATA_LOG_MAX_BATT_V
304                    .from_data(data)?,
305                cc_config_data_log_max_input_v: Self::CC_CONFIG_DATA_LOG_MAX_INPUT_V
306                    .from_data(data)?,
307                cc_config_data_log_clear: Self::CC_CONFIG_DATA_LOG_CLEAR.from_data(data)?,
308                cc_config_data_log_clr_comp: Self::CC_CONFIG_DATA_LOG_CLR_COMP.from_data(data)?,
309            },
310        ))
311    }
312}
313bitflags::bitflags! {
314    #[doc = " Faults"] #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature =
315    "serde", derive(::serde::Serialize, ::serde::Deserialize))] pub struct CcConfigFault
316    : u16 {}
317}
318impl crate::Value for CcConfigFault {
319    fn decode(data: &[u16]) -> Result<Self, crate::DecodeError> {
320        let value = u16::decode(data)?;
321        Ok(Self::from_bits_retain(value))
322    }
323    fn encode(self) -> Box<[u16]> {
324        self.bits().encode()
325    }
326}
327impl crate::FixedSize for CcConfigFault {
328    const SIZE: u16 = 1u16;
329    const INVALID: Self = Self::from_bits_retain(65535u16);
330    fn is_invalid(&self) -> bool {
331        self.bits() == 65535u16
332    }
333}
334/// MPPT mode
335#[derive(Copy, Clone, Debug, Eq, PartialEq)]
336#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
337pub enum CcConfigMpptMode {
338    #[allow(missing_docs)]
339    Auto,
340    #[allow(missing_docs)]
341    UPick,
342    #[allow(missing_docs)]
343    Wind,
344    /// Raw enum value not defined by the SunSpec model.
345    Invalid(u16),
346}
347impl crate::EnumValue for CcConfigMpptMode {
348    type Repr = u16;
349    const INVALID: Self::Repr = 65535;
350    fn from_repr(value: Self::Repr) -> Self {
351        match value {
352            0 => Self::Auto,
353            1 => Self::UPick,
354            2 => Self::Wind,
355            value => Self::Invalid(value),
356        }
357    }
358    fn to_repr(self) -> Self::Repr {
359        match self {
360            Self::Auto => 0,
361            Self::UPick => 1,
362            Self::Wind => 2,
363            Self::Invalid(value) => value,
364        }
365    }
366}
367impl crate::FixedSize for CcConfigMpptMode {
368    const SIZE: u16 = 1u16;
369    const INVALID: Self = Self::Invalid(65535);
370    fn is_invalid(&self) -> bool {
371        matches!(self, Self::Invalid(_))
372    }
373}
374/// Sweep Width
375#[derive(Copy, Clone, Debug, Eq, PartialEq)]
376#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
377pub enum CcConfigSweepWidth {
378    #[allow(missing_docs)]
379    Half,
380    #[allow(missing_docs)]
381    Full,
382    /// Raw enum value not defined by the SunSpec model.
383    Invalid(u16),
384}
385impl crate::EnumValue for CcConfigSweepWidth {
386    type Repr = u16;
387    const INVALID: Self::Repr = 65535;
388    fn from_repr(value: Self::Repr) -> Self {
389        match value {
390            0 => Self::Half,
391            1 => Self::Full,
392            value => Self::Invalid(value),
393        }
394    }
395    fn to_repr(self) -> Self::Repr {
396        match self {
397            Self::Half => 0,
398            Self::Full => 1,
399            Self::Invalid(value) => value,
400        }
401    }
402}
403impl crate::FixedSize for CcConfigSweepWidth {
404    const SIZE: u16 = 1u16;
405    const INVALID: Self = Self::Invalid(65535);
406    fn is_invalid(&self) -> bool {
407        matches!(self, Self::Invalid(_))
408    }
409}
410/// Sweep Maximum
411#[derive(Copy, Clone, Debug, Eq, PartialEq)]
412#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
413pub enum CcConfigSweepMax {
414    #[allow(missing_docs)]
415    EightyPercent,
416    #[allow(missing_docs)]
417    EightyFivePercent,
418    #[allow(missing_docs)]
419    NintyPercent,
420    #[allow(missing_docs)]
421    NintyNinePercent,
422    /// Raw enum value not defined by the SunSpec model.
423    Invalid(u16),
424}
425impl crate::EnumValue for CcConfigSweepMax {
426    type Repr = u16;
427    const INVALID: Self::Repr = 65535;
428    fn from_repr(value: Self::Repr) -> Self {
429        match value {
430            0 => Self::EightyPercent,
431            1 => Self::EightyFivePercent,
432            2 => Self::NintyPercent,
433            3 => Self::NintyNinePercent,
434            value => Self::Invalid(value),
435        }
436    }
437    fn to_repr(self) -> Self::Repr {
438        match self {
439            Self::EightyPercent => 0,
440            Self::EightyFivePercent => 1,
441            Self::NintyPercent => 2,
442            Self::NintyNinePercent => 3,
443            Self::Invalid(value) => value,
444        }
445    }
446}
447impl crate::FixedSize for CcConfigSweepMax {
448    const SIZE: u16 = 1u16;
449    const INVALID: Self = Self::Invalid(65535);
450    fn is_invalid(&self) -> bool {
451        matches!(self, Self::Invalid(_))
452    }
453}
454/// Grid Tie Mode
455#[derive(Copy, Clone, Debug, Eq, PartialEq)]
456#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
457pub enum CcConfigGridTie {
458    #[allow(missing_docs)]
459    Disabled,
460    #[allow(missing_docs)]
461    Enabled,
462    /// Raw enum value not defined by the SunSpec model.
463    Invalid(u16),
464}
465impl crate::EnumValue for CcConfigGridTie {
466    type Repr = u16;
467    const INVALID: Self::Repr = 65535;
468    fn from_repr(value: Self::Repr) -> Self {
469        match value {
470            0 => Self::Disabled,
471            1 => Self::Enabled,
472            value => Self::Invalid(value),
473        }
474    }
475    fn to_repr(self) -> Self::Repr {
476        match self {
477            Self::Disabled => 0,
478            Self::Enabled => 1,
479            Self::Invalid(value) => value,
480        }
481    }
482}
483impl crate::FixedSize for CcConfigGridTie {
484    const SIZE: u16 = 1u16;
485    const INVALID: Self = Self::Invalid(65535);
486    fn is_invalid(&self) -> bool {
487        matches!(self, Self::Invalid(_))
488    }
489}
490/// Temp Comp Mode
491#[derive(Copy, Clone, Debug, Eq, PartialEq)]
492#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
493pub enum CcConfigTempComp {
494    #[allow(missing_docs)]
495    Wide,
496    #[allow(missing_docs)]
497    Limited,
498    /// Raw enum value not defined by the SunSpec model.
499    Invalid(u16),
500}
501impl crate::EnumValue for CcConfigTempComp {
502    type Repr = u16;
503    const INVALID: Self::Repr = 65535;
504    fn from_repr(value: Self::Repr) -> Self {
505        match value {
506            0 => Self::Wide,
507            1 => Self::Limited,
508            value => Self::Invalid(value),
509        }
510    }
511    fn to_repr(self) -> Self::Repr {
512        match self {
513            Self::Wide => 0,
514            Self::Limited => 1,
515            Self::Invalid(value) => value,
516        }
517    }
518}
519impl crate::FixedSize for CcConfigTempComp {
520    const SIZE: u16 = 1u16;
521    const INVALID: Self = Self::Invalid(65535);
522    fn is_invalid(&self) -> bool {
523        matches!(self, Self::Invalid(_))
524    }
525}
526/// Auto Restart Mode
527#[derive(Copy, Clone, Debug, Eq, PartialEq)]
528#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
529pub enum CcConfigAutoRestart {
530    #[allow(missing_docs)]
531    Off,
532    #[allow(missing_docs)]
533    Every90Minutes,
534    #[allow(missing_docs)]
535    Every90MinutesIfAbsorbOrFloat,
536    /// Raw enum value not defined by the SunSpec model.
537    Invalid(u16),
538}
539impl crate::EnumValue for CcConfigAutoRestart {
540    type Repr = u16;
541    const INVALID: Self::Repr = 65535;
542    fn from_repr(value: Self::Repr) -> Self {
543        match value {
544            0 => Self::Off,
545            1 => Self::Every90Minutes,
546            2 => Self::Every90MinutesIfAbsorbOrFloat,
547            value => Self::Invalid(value),
548        }
549    }
550    fn to_repr(self) -> Self::Repr {
551        match self {
552            Self::Off => 0,
553            Self::Every90Minutes => 1,
554            Self::Every90MinutesIfAbsorbOrFloat => 2,
555            Self::Invalid(value) => value,
556        }
557    }
558}
559impl crate::FixedSize for CcConfigAutoRestart {
560    const SIZE: u16 = 1u16;
561    const INVALID: Self = Self::Invalid(65535);
562    fn is_invalid(&self) -> bool {
563        matches!(self, Self::Invalid(_))
564    }
565}
566/// AUX Output Mode
567#[derive(Copy, Clone, Debug, Eq, PartialEq)]
568#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
569pub enum CcConfigAuxMode {
570    #[allow(missing_docs)]
571    Float,
572    #[allow(missing_docs)]
573    DiversionRelay,
574    #[allow(missing_docs)]
575    DiversionSolidSt,
576    #[allow(missing_docs)]
577    LowBattDisconnect,
578    #[allow(missing_docs)]
579    Remote,
580    #[allow(missing_docs)]
581    VentFan,
582    #[allow(missing_docs)]
583    PvTrigger,
584    #[allow(missing_docs)]
585    ErrorOutput,
586    #[allow(missing_docs)]
587    NightLight,
588    /// Raw enum value not defined by the SunSpec model.
589    Invalid(u16),
590}
591impl crate::EnumValue for CcConfigAuxMode {
592    type Repr = u16;
593    const INVALID: Self::Repr = 65535;
594    fn from_repr(value: Self::Repr) -> Self {
595        match value {
596            0 => Self::Float,
597            1 => Self::DiversionRelay,
598            2 => Self::DiversionSolidSt,
599            3 => Self::LowBattDisconnect,
600            4 => Self::Remote,
601            5 => Self::VentFan,
602            6 => Self::PvTrigger,
603            7 => Self::ErrorOutput,
604            8 => Self::NightLight,
605            value => Self::Invalid(value),
606        }
607    }
608    fn to_repr(self) -> Self::Repr {
609        match self {
610            Self::Float => 0,
611            Self::DiversionRelay => 1,
612            Self::DiversionSolidSt => 2,
613            Self::LowBattDisconnect => 3,
614            Self::Remote => 4,
615            Self::VentFan => 5,
616            Self::PvTrigger => 6,
617            Self::ErrorOutput => 7,
618            Self::NightLight => 8,
619            Self::Invalid(value) => value,
620        }
621    }
622}
623impl crate::FixedSize for CcConfigAuxMode {
624    const SIZE: u16 = 1u16;
625    const INVALID: Self = Self::Invalid(65535);
626    fn is_invalid(&self) -> bool {
627        matches!(self, Self::Invalid(_))
628    }
629}
630/// AUX Output Control
631#[derive(Copy, Clone, Debug, Eq, PartialEq)]
632#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
633pub enum CcConfigAuxControl {
634    #[allow(missing_docs)]
635    Off,
636    #[allow(missing_docs)]
637    Auto,
638    #[allow(missing_docs)]
639    On,
640    /// Raw enum value not defined by the SunSpec model.
641    Invalid(u16),
642}
643impl crate::EnumValue for CcConfigAuxControl {
644    type Repr = u16;
645    const INVALID: Self::Repr = 65535;
646    fn from_repr(value: Self::Repr) -> Self {
647        match value {
648            0 => Self::Off,
649            1 => Self::Auto,
650            2 => Self::On,
651            value => Self::Invalid(value),
652        }
653    }
654    fn to_repr(self) -> Self::Repr {
655        match self {
656            Self::Off => 0,
657            Self::Auto => 1,
658            Self::On => 2,
659            Self::Invalid(value) => value,
660        }
661    }
662}
663impl crate::FixedSize for CcConfigAuxControl {
664    const SIZE: u16 = 1u16;
665    const INVALID: Self = Self::Invalid(65535);
666    fn is_invalid(&self) -> bool {
667        matches!(self, Self::Invalid(_))
668    }
669}
670/// AUX Output State
671#[derive(Copy, Clone, Debug, Eq, PartialEq)]
672#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
673pub enum CcConfigAuxState {
674    #[allow(missing_docs)]
675    Disabled,
676    #[allow(missing_docs)]
677    Enabled,
678    /// Raw enum value not defined by the SunSpec model.
679    Invalid(u16),
680}
681impl crate::EnumValue for CcConfigAuxState {
682    type Repr = u16;
683    const INVALID: Self::Repr = 65535;
684    fn from_repr(value: Self::Repr) -> Self {
685        match value {
686            0 => Self::Disabled,
687            1 => Self::Enabled,
688            value => Self::Invalid(value),
689        }
690    }
691    fn to_repr(self) -> Self::Repr {
692        match self {
693            Self::Disabled => 0,
694            Self::Enabled => 1,
695            Self::Invalid(value) => value,
696        }
697    }
698}
699impl crate::FixedSize for CcConfigAuxState {
700    const SIZE: u16 = 1u16;
701    const INVALID: Self = Self::Invalid(65535);
702    fn is_invalid(&self) -> bool {
703        matches!(self, Self::Invalid(_))
704    }
705}
706/// AUX Output Polarity
707#[derive(Copy, Clone, Debug, Eq, PartialEq)]
708#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
709pub enum CcConfigAuxPolarity {
710    #[allow(missing_docs)]
711    Low,
712    #[allow(missing_docs)]
713    High,
714    /// Raw enum value not defined by the SunSpec model.
715    Invalid(u16),
716}
717impl crate::EnumValue for CcConfigAuxPolarity {
718    type Repr = u16;
719    const INVALID: Self::Repr = 65535;
720    fn from_repr(value: Self::Repr) -> Self {
721        match value {
722            0 => Self::Low,
723            1 => Self::High,
724            value => Self::Invalid(value),
725        }
726    }
727    fn to_repr(self) -> Self::Repr {
728        match self {
729            Self::Low => 0,
730            Self::High => 1,
731            Self::Invalid(value) => value,
732        }
733    }
734}
735impl crate::FixedSize for CcConfigAuxPolarity {
736    const SIZE: u16 = 1u16;
737    const INVALID: Self = Self::Invalid(65535);
738    fn is_invalid(&self) -> bool {
739        matches!(self, Self::Invalid(_))
740    }
741}
742impl crate::Model for Model64112 {
743    const ID: u16 = 64112;
744    fn addr(models: &crate::Models) -> crate::ModelAddr<Self> {
745        models.m64112
746    }
747    fn parse(data: &[u16]) -> Result<Self, crate::ParseError<Self>> {
748        let (_, model) = Self::parse_group(data)?;
749        Ok(model)
750    }
751}