Skip to main content

sunspec/models/
model125.rs

1//! Pricing
2/// Type alias for [`Pricing`].
3pub type Model125 = Pricing;
4/// Pricing
5///
6/// Pricing Signal
7///
8/// Detail: Ref 3: 8.7.5.1; Ref 4: 6
9#[derive(Debug)]
10#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
11pub struct Pricing {
12    /// ModEna
13    ///
14    /// Is price-based charge/discharge mode active?
15    pub mod_ena: ModEna,
16    /// SigType
17    ///
18    /// Meaning of the pricing signal. When a Price schedule is used, type must match the schedule range variable description.
19    pub sig_type: Option<SigType>,
20    /// Sig
21    ///
22    /// Utility/ESP specific pricing signal. Content depends on pricing signal type. When H/M/L type is specified. Low=0; Med=1; High=2.
23    pub sig: i16,
24    /// WinTms
25    ///
26    /// Time window for charge/discharge pricing change.
27    pub win_tms: Option<u16>,
28    /// RvtTms
29    ///
30    /// Timeout period for charge/discharge pricing change.
31    pub rvt_tms: Option<u16>,
32    /// RmpTms
33    ///
34    /// Ramp time for moving from current charge or discharge level to new level.
35    pub rmp_tms: Option<u16>,
36    /// Sig_SF
37    ///
38    /// Pricing signal scale factor.
39    pub sig_sf: i16,
40}
41#[allow(missing_docs)]
42impl Pricing {
43    pub const MOD_ENA: crate::Point<Self, ModEna> = crate::Point::new(0, 1, true);
44    pub const SIG_TYPE: crate::Point<Self, Option<SigType>> = crate::Point::new(1, 1, true);
45    pub const SIG: crate::Point<Self, i16> = crate::Point::new(2, 1, true);
46    pub const WIN_TMS: crate::Point<Self, Option<u16>> = crate::Point::new(3, 1, true);
47    pub const RVT_TMS: crate::Point<Self, Option<u16>> = crate::Point::new(4, 1, true);
48    pub const RMP_TMS: crate::Point<Self, Option<u16>> = crate::Point::new(5, 1, true);
49    pub const SIG_SF: crate::Point<Self, i16> = crate::Point::new(6, 1, false);
50}
51impl crate::Group for Pricing {
52    const LEN: u16 = 8;
53}
54impl Pricing {
55    fn parse_group(data: &[u16]) -> Result<(&[u16], Self), crate::DecodeError> {
56        let nested_data = data
57            .get(usize::from(<Self as crate::Group>::LEN)..)
58            .unwrap_or(&[]);
59        Ok((
60            nested_data,
61            Self {
62                mod_ena: Self::MOD_ENA.from_data(data)?,
63                sig_type: Self::SIG_TYPE.from_data(data)?,
64                sig: Self::SIG.from_data(data)?,
65                win_tms: Self::WIN_TMS.from_data(data)?,
66                rvt_tms: Self::RVT_TMS.from_data(data)?,
67                rmp_tms: Self::RMP_TMS.from_data(data)?,
68                sig_sf: Self::SIG_SF.from_data(data)?,
69            },
70        ))
71    }
72}
73bitflags::bitflags! {
74    #[doc = " ModEna"] #[doc = " "] #[doc =
75    " Is price-based charge/discharge mode active?"] #[derive(Copy, Clone, Debug, Eq,
76    PartialEq)] #[cfg_attr(feature = "serde", derive(::serde::Serialize,
77    ::serde::Deserialize))] pub struct ModEna : u16 { #[allow(missing_docs)] const Enable
78    = 1; }
79}
80impl crate::Value for ModEna {
81    fn decode(data: &[u16]) -> Result<Self, crate::DecodeError> {
82        let value = u16::decode(data)?;
83        Ok(Self::from_bits_retain(value))
84    }
85    fn encode(self) -> Box<[u16]> {
86        self.bits().encode()
87    }
88}
89impl crate::FixedSize for ModEna {
90    const SIZE: u16 = 1u16;
91    const INVALID: Self = Self::from_bits_retain(65535u16);
92    fn is_invalid(&self) -> bool {
93        self.bits() == 65535u16
94    }
95}
96/// SigType
97///
98/// Meaning of the pricing signal. When a Price schedule is used, type must match the schedule range variable description.
99#[derive(Copy, Clone, Debug, Eq, PartialEq)]
100#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
101pub enum SigType {
102    #[allow(missing_docs)]
103    Unknown,
104    #[allow(missing_docs)]
105    Absolute,
106    #[allow(missing_docs)]
107    Relative,
108    #[allow(missing_docs)]
109    Multiplier,
110    #[allow(missing_docs)]
111    Level,
112    /// Raw enum value not defined by the SunSpec model.
113    Invalid(u16),
114}
115impl crate::EnumValue for SigType {
116    type Repr = u16;
117    const INVALID: Self::Repr = 65535;
118    fn from_repr(value: Self::Repr) -> Self {
119        match value {
120            0 => Self::Unknown,
121            1 => Self::Absolute,
122            2 => Self::Relative,
123            3 => Self::Multiplier,
124            4 => Self::Level,
125            value => Self::Invalid(value),
126        }
127    }
128    fn to_repr(self) -> Self::Repr {
129        match self {
130            Self::Unknown => 0,
131            Self::Absolute => 1,
132            Self::Relative => 2,
133            Self::Multiplier => 3,
134            Self::Level => 4,
135            Self::Invalid(value) => value,
136        }
137    }
138}
139impl crate::FixedSize for SigType {
140    const SIZE: u16 = 1u16;
141    const INVALID: Self = Self::Invalid(65535);
142    fn is_invalid(&self) -> bool {
143        matches!(self, Self::Invalid(_))
144    }
145}
146impl crate::Model for Pricing {
147    const ID: u16 = 125;
148    fn addr(models: &crate::Models) -> crate::ModelAddr<Self> {
149        models.m125
150    }
151    fn parse(data: &[u16]) -> Result<Self, crate::ParseError<Self>> {
152        let (_, model) = Self::parse_group(data)?;
153        Ok(model)
154    }
155}