#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum PropertyDataType {
#[default]
Control = 0x00,
Char = 0x01,
UnsignedChar = 0x02,
Int = 0x03,
UnsignedInt = 0x04,
KnxFloat = 0x05,
Date = 0x06,
Time = 0x07,
Long = 0x08,
UnsignedLong = 0x09,
Float = 0x0A,
Double = 0x0B,
CharBlock = 0x0C,
PollGroupSetting = 0x0D,
ShortCharBlock = 0x0E,
DateTime = 0x0F,
VariableLength = 0x10,
Generic01 = 0x11,
Generic02 = 0x12,
Generic03 = 0x13,
Generic04 = 0x14,
Generic05 = 0x15,
Generic06 = 0x16,
Generic07 = 0x17,
Generic08 = 0x18,
Generic09 = 0x19,
Generic10 = 0x1A,
Function = 0x3E,
}
impl PropertyDataType {
pub const fn size(self) -> u8 {
match self {
Self::Control | Self::Char | Self::UnsignedChar | Self::Generic01 => 1,
Self::Int | Self::UnsignedInt | Self::KnxFloat | Self::Generic02 => 2,
Self::Date | Self::Time | Self::PollGroupSetting | Self::Generic03 => 3,
Self::Long | Self::UnsignedLong | Self::Float | Self::Generic04 => 4,
Self::ShortCharBlock | Self::Generic05 => 5,
Self::Generic06 => 6,
Self::Generic07 => 7,
Self::Double | Self::DateTime | Self::Generic08 => 8,
Self::Generic09 => 9,
Self::CharBlock | Self::Generic10 => 10,
Self::VariableLength | Self::Function => 0, }
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum PropertyId {
#[default]
ObjectType = 1,
LoadStateControl = 5,
RunStateControl = 6,
TableReference = 7,
ServiceControl = 8,
FirmwareRevision = 9,
SerialNumber = 11,
ManufacturerId = 12,
ProgramVersion = 13,
DeviceControl = 14,
OrderInfo = 15,
PeiType = 16,
PortConfiguration = 17,
Table = 23,
Version = 25,
McbTable = 27,
ErrorCode = 28,
ObjectIndex = 29,
DownloadCounter = 30,
RoutingCount = 51,
ProgMode = 54,
MaxApduLength = 56,
SubnetAddr = 57,
DeviceAddr = 58,
IoList = 71,
HardwareType = 78,
DeviceDescriptor = 83,
}
impl TryFrom<u8> for PropertyId {
type Error = u8;
fn try_from(v: u8) -> Result<Self, Self::Error> {
match v {
1 => Ok(Self::ObjectType),
5 => Ok(Self::LoadStateControl),
6 => Ok(Self::RunStateControl),
7 => Ok(Self::TableReference),
8 => Ok(Self::ServiceControl),
9 => Ok(Self::FirmwareRevision),
11 => Ok(Self::SerialNumber),
12 => Ok(Self::ManufacturerId),
13 => Ok(Self::ProgramVersion),
14 => Ok(Self::DeviceControl),
15 => Ok(Self::OrderInfo),
16 => Ok(Self::PeiType),
17 => Ok(Self::PortConfiguration),
23 => Ok(Self::Table),
25 => Ok(Self::Version),
27 => Ok(Self::McbTable),
28 => Ok(Self::ErrorCode),
29 => Ok(Self::ObjectIndex),
30 => Ok(Self::DownloadCounter),
51 => Ok(Self::RoutingCount),
54 => Ok(Self::ProgMode),
56 => Ok(Self::MaxApduLength),
57 => Ok(Self::SubnetAddr),
58 => Ok(Self::DeviceAddr),
71 => Ok(Self::IoList),
78 => Ok(Self::HardwareType),
83 => Ok(Self::DeviceDescriptor),
_ => Err(v),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum LoadState {
Unloaded = 0,
Loaded = 1,
Loading = 2,
Error = 3,
Unloading = 4,
LoadCompleting = 5,
}
impl From<u8> for LoadState {
fn from(v: u8) -> Self {
match v {
1 => Self::Loaded,
2 => Self::Loading,
3 => Self::Error,
4 => Self::Unloading,
5 => Self::LoadCompleting,
_ => Self::Unloaded,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum LoadEvent {
Noop = 0,
StartLoading = 1,
LoadCompleted = 2,
AdditionalLoadControls = 3,
Unload = 4,
}
impl LoadEvent {
pub const fn from_byte(v: u8) -> Option<Self> {
match v {
0 => Some(Self::Noop),
1 => Some(Self::StartLoading),
2 => Some(Self::LoadCompleted),
3 => Some(Self::AdditionalLoadControls),
4 => Some(Self::Unload),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum AccessLevel {
#[default]
None = 0x00,
WriteLow = 0x01,
WriteMedium = 0x02,
WriteHigh = 0x03,
}
impl From<u8> for AccessLevel {
fn from(v: u8) -> Self {
match v {
0x01 => Self::WriteLow,
0x02 => Self::WriteMedium,
0x03 => Self::WriteHigh,
_ => Self::None,
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct PropertyDescription {
pub id: PropertyId,
pub write_enable: bool,
pub data_type: PropertyDataType,
pub max_elements: u16,
pub access: AccessLevel,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn property_data_type_sizes() {
assert_eq!(PropertyDataType::UnsignedChar.size(), 1);
assert_eq!(PropertyDataType::UnsignedInt.size(), 2);
assert_eq!(PropertyDataType::UnsignedLong.size(), 4);
assert_eq!(PropertyDataType::Generic05.size(), 5);
assert_eq!(PropertyDataType::Generic10.size(), 10);
}
#[test]
fn load_state_from_u8_roundtrip() {
assert_eq!(LoadState::from(0), LoadState::Unloaded);
assert_eq!(LoadState::from(1), LoadState::Loaded);
assert_eq!(LoadState::from(2), LoadState::Loading);
assert_eq!(LoadState::from(3), LoadState::Error);
assert_eq!(LoadState::from(4), LoadState::Unloading);
assert_eq!(LoadState::from(5), LoadState::LoadCompleting);
assert_eq!(LoadState::from(6), LoadState::Unloaded);
assert_eq!(LoadState::from(255), LoadState::Unloaded);
}
#[test]
fn load_event_from_byte() {
assert_eq!(LoadEvent::from_byte(0), Some(LoadEvent::Noop));
assert_eq!(LoadEvent::from_byte(1), Some(LoadEvent::StartLoading));
assert_eq!(LoadEvent::from_byte(2), Some(LoadEvent::LoadCompleted));
assert_eq!(
LoadEvent::from_byte(3),
Some(LoadEvent::AdditionalLoadControls)
);
assert_eq!(LoadEvent::from_byte(4), Some(LoadEvent::Unload));
assert_eq!(LoadEvent::from_byte(5), None);
assert_eq!(LoadEvent::from_byte(255), None);
}
}