Skip to main content

knx_core/
apci.rs

1use core::convert::TryFrom;
2
3use crate::{KnxError, Result};
4
5const APCI_MASK: u8 = 0xc0;
6const GROUP_VALUE_READ_BITS: u8 = 0x00;
7const GROUP_VALUE_RESPONSE_BITS: u8 = 0x40;
8const GROUP_VALUE_WRITE_BITS: u8 = 0x80;
9
10/// Only group-value services are modeled; all other APCI codes decode as `InvalidFrame`
11/// (intentional scope limit).
12#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub enum Apci {
15    GroupValueRead,
16    GroupValueResponse,
17    GroupValueWrite,
18}
19
20impl Apci {
21    pub const fn service_bits(self) -> u8 {
22        match self {
23            Self::GroupValueRead => GROUP_VALUE_READ_BITS,
24            Self::GroupValueResponse => GROUP_VALUE_RESPONSE_BITS,
25            Self::GroupValueWrite => GROUP_VALUE_WRITE_BITS,
26        }
27    }
28}
29
30impl TryFrom<u8> for Apci {
31    type Error = KnxError;
32
33    fn try_from(value: u8) -> Result<Self> {
34        match value & APCI_MASK {
35            GROUP_VALUE_READ_BITS => Ok(Self::GroupValueRead),
36            GROUP_VALUE_RESPONSE_BITS => Ok(Self::GroupValueResponse),
37            GROUP_VALUE_WRITE_BITS => Ok(Self::GroupValueWrite),
38            _ => Err(KnxError::InvalidFrame("unsupported APCI service")),
39        }
40    }
41}