use {
byteorder::{self, ByteOrder},
rubble::link::ad_structure::AdStructure,
};
pub struct Data([u8; 17]);
impl<'a, 'b> Data
where
'a: 'b,
{
pub fn new(
interval: Interval,
pair_status: PairingStatus,
device_id: u64,
accessory_category: AccessoryCategory,
global_state_number: u16,
configuration_number: u8,
) -> Self {
let mut inner = [0u8; 17];
inner[0] = 0x4C;
inner[1] = 0x00;
inner[2] = 0x06;
inner[3] = interval.value();
inner[4] = pair_status.value();
byteorder::BigEndian::write_u48(&mut inner[5..12], device_id);
byteorder::BigEndian::write_u16(&mut inner[11..13], accessory_category.value());
byteorder::BigEndian::write_u16(&mut inner[13..15], global_state_number);
inner[15] = configuration_number;
inner[16] = 0x02;
Self(inner)
}
pub fn as_adstructure(&'a self) -> AdStructure<'b> {
AdStructure::Unknown {
ty: 0xFF,
data: &self.0,
}
}
}
pub enum Interval {
_10_25MS,
_26_100MS,
_101_300MS,
_301_500MS,
_501_1250MS,
_1251_2500MS,
_2500MS,
}
impl Interval {
fn value(&self) -> u8 {
match *self {
Interval::_10_25MS => 0x2D,
Interval::_26_100MS => 0x4D,
Interval::_101_300MS => 0x6D,
Interval::_301_500MS => 0x8D,
Interval::_501_1250MS => 0xAD,
Interval::_1251_2500MS => 0xCD,
Interval::_2500MS => 0xED,
}
}
}
pub enum PairingStatus {
Paired,
NotPaired,
}
impl PairingStatus {
fn value(&self) -> u8 {
match *self {
PairingStatus::Paired => 0b0,
PairingStatus::NotPaired => 0b1,
}
}
}
pub enum AccessoryCategory {
Other,
Bridge,
Fan,
Garage,
Lightbulb,
DoorLock,
Outlet,
Switch,
Thermostat,
Sensor,
SecuritySystem,
Door,
Window,
WindowCovering,
ProgrammableSwitch,
RangeExtender,
IPCamera,
VideoDoorBell,
AirPurifier,
Reserved,
}
impl AccessoryCategory {
fn value(&self) -> u16 {
match *self {
AccessoryCategory::Other => 1,
AccessoryCategory::Bridge => 2,
AccessoryCategory::Fan => 3,
AccessoryCategory::Garage => 4,
AccessoryCategory::Lightbulb => 5,
AccessoryCategory::DoorLock => 6,
AccessoryCategory::Outlet => 7,
AccessoryCategory::Switch => 8,
AccessoryCategory::Thermostat => 9,
AccessoryCategory::Sensor => 10,
AccessoryCategory::SecuritySystem => 11,
AccessoryCategory::Door => 12,
AccessoryCategory::Window => 13,
AccessoryCategory::WindowCovering => 14,
AccessoryCategory::ProgrammableSwitch => 15,
AccessoryCategory::RangeExtender => 16,
AccessoryCategory::IPCamera => 17,
AccessoryCategory::VideoDoorBell => 18,
AccessoryCategory::AirPurifier => 19,
AccessoryCategory::Reserved => 65535,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use insta::assert_debug_snapshot_matches;
#[test]
fn test_snapshots() {
assert_debug_snapshot_matches!(
"data_as_adstructure",
Data::new(
Interval::_501_1250MS,
PairingStatus::NotPaired,
188899839028173,
AccessoryCategory::Lightbulb,
1,
1,
)
.as_adstructure()
)
}
}