diff --git a/Cargo.lock b/Cargo.lock index 7ee72c1..f5d7ae7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -898,6 +898,8 @@ dependencies = [ "serde", "serde_json", "sha2", + "strum", + "strum_macros", "thiserror", "tokio", "x25519-dalek", @@ -1798,6 +1800,25 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +[[package]] +name = "strum" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" + +[[package]] +name = "strum_macros" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.48", +] + [[package]] name = "subtle" version = "2.4.1" diff --git a/homekit-controller/Cargo.toml b/homekit-controller/Cargo.toml index b82a127..da39c82 100644 --- a/homekit-controller/Cargo.toml +++ b/homekit-controller/Cargo.toml @@ -20,3 +20,5 @@ http = "1.0" httparse = "1.8" tokio = { version = "1.36", features = ["net"] } zeroconf = "0.14" +strum = "0.26" +strum_macros = "0.26" diff --git a/homekit-controller/src/pairing_data/characteristics.rs b/homekit-controller/src/pairing_data/characteristics.rs index 015208e..d970300 100644 --- a/homekit-controller/src/pairing_data/characteristics.rs +++ b/homekit-controller/src/pairing_data/characteristics.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Deserializer, Serialize}; +use strum_macros::Display; // data from https://github.com/oznu/homebridge-gsh/blob/master/src/hap-types.ts @@ -11,7 +12,8 @@ where CharacteristicTypeInner::deserialize(deserializer).map(|v| v.into()) } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Display)] +#[strum(serialize_all = "snake_case")] pub enum CharacteristicType { AccessControlLevel, @@ -239,241 +241,6 @@ pub enum CharacteristicType { Unknown, } -impl std::fmt::Display for CharacteristicType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::AccessControlLevel => "000000E5-0000-1000-8000-0026BB765291", - Self::AccessoryFlags => "000000A6-0000-1000-8000-0026BB765291", - Self::ProductData => "00000220-0000-1000-8000-0026BB765291", - Self::Active => "000000B0-0000-1000-8000-0026BB765291", - Self::AdministratorOnlyAccess => "00000001-0000-1000-8000-0026BB765291", - Self::AirParticulateDensity => "00000064-0000-1000-8000-0026BB765291", - Self::AirParticulateSize => "00000065-0000-1000-8000-0026BB765291", - Self::AirQuality => "00000095-0000-1000-8000-0026BB765291", - Self::AudioFeedback => "00000005-0000-1000-8000-0026BB765291", - Self::BatteryLevel => "00000068-0000-1000-8000-0026BB765291", - Self::Brightness => "00000008-0000-1000-8000-0026BB765291", - Self::CarbonDioxideDetected => "00000092-0000-1000-8000-0026BB765291", - Self::CarbonDioxideLevel => "00000093-0000-1000-8000-0026BB765291", - Self::CarbonDioxidePeakLevel => "00000094-0000-1000-8000-0026BB765291", - Self::CarbonMonoxideDetected => "00000069-0000-1000-8000-0026BB765291", - Self::CarbonMonoxideLevel => "00000090-0000-1000-8000-0026BB765291", - Self::CarbonMonoxidePeakLevel => "00000091-0000-1000-8000-0026BB765291", - Self::ChargingState => "0000008F-0000-1000-8000-0026BB765291", - Self::ColorTemperature => "000000CE-0000-1000-8000-0026BB765291", - Self::ContactSensorState => "0000006A-0000-1000-8000-0026BB765291", - Self::CoolingThresholdTemperature => "0000000D-0000-1000-8000-0026BB765291", - Self::CurrentAirPurifierState => "000000A9-0000-1000-8000-0026BB765291", - Self::CurrentAmbientLightLevel => "0000006B-0000-1000-8000-0026BB765291", - Self::CurrentDoorState => "0000000E-0000-1000-8000-0026BB765291", - Self::CurrentFanState => "000000AF-0000-1000-8000-0026BB765291", - Self::CurrentHeaterCoolerState => "000000B1-0000-1000-8000-0026BB765291", - Self::CurrentHeatingCoolingState => "0000000F-0000-1000-8000-0026BB765291", - Self::CurrentHorizontalTiltAngle => "0000006C-0000-1000-8000-0026BB765291", - Self::CurrentHumidifierDehumidifierState => "000000B3-0000-1000-8000-0026BB765291", - Self::CurrentPosition => "0000006D-0000-1000-8000-0026BB765291", - Self::CurrentRelativeHumidity => "00000010-0000-1000-8000-0026BB765291", - Self::CurrentSlatState => "000000AA-0000-1000-8000-0026BB765291", - Self::CurrentTemperature => "00000011-0000-1000-8000-0026BB765291", - Self::CurrentTiltAngle => "000000C1-0000-1000-8000-0026BB765291", - Self::CurrentVerticalTiltAngle => "0000006E-0000-1000-8000-0026BB765291", - Self::DigitalZoom => "0000011D-0000-1000-8000-0026BB765291", - Self::FilterChangeIndication => "000000AC-0000-1000-8000-0026BB765291", - Self::FilterLifeLevel => "000000AB-0000-1000-8000-0026BB765291", - Self::FirmwareRevision => "00000052-0000-1000-8000-0026BB765291", - Self::HardwareRevision => "00000053-0000-1000-8000-0026BB765291", - Self::HeatingThresholdTemperature => "00000012-0000-1000-8000-0026BB765291", - Self::HoldPosition => "0000006F-0000-1000-8000-0026BB765291", - Self::Hue => "00000013-0000-1000-8000-0026BB765291", - Self::Identify => "00000014-0000-1000-8000-0026BB765291", - Self::ImageMirroring => "0000011F-0000-1000-8000-0026BB765291", - Self::ImageRotation => "0000011E-0000-1000-8000-0026BB765291", - Self::InUse => "000000D2-0000-1000-8000-0026BB765291", - Self::IsConfigured => "000000D6-0000-1000-8000-0026BB765291", - Self::LeakDetected => "00000070-0000-1000-8000-0026BB765291", - Self::LockControlPoint => "00000019-0000-1000-8000-0026BB765291", - Self::LockCurrentState => "0000001D-0000-1000-8000-0026BB765291", - Self::LockLastKnownAction => "0000001C-0000-1000-8000-0026BB765291", - Self::LockManagementAutoSecurityTimeout => "0000001A-0000-1000-8000-0026BB765291", - Self::LockPhysicalControls => "000000A7-0000-1000-8000-0026BB765291", - Self::LockTargetState => "0000001E-0000-1000-8000-0026BB765291", - Self::Logs => "0000001F-0000-1000-8000-0026BB765291", - Self::Manufacturer => "00000020-0000-1000-8000-0026BB765291", - Self::Model => "00000021-0000-1000-8000-0026BB765291", - Self::MotionDetected => "00000022-0000-1000-8000-0026BB765291", - Self::Mute => "0000011A-0000-1000-8000-0026BB765291", - Self::Name => "00000023-0000-1000-8000-0026BB765291", - Self::NightVision => "0000011B-0000-1000-8000-0026BB765291", - Self::NitrogenDioxideDensity => "000000C4-0000-1000-8000-0026BB765291", - Self::ObstructionDetected => "00000024-0000-1000-8000-0026BB765291", - Self::OccupancyDetected => "00000071-0000-1000-8000-0026BB765291", - Self::On => "00000025-0000-1000-8000-0026BB765291", - Self::OpticalZoom => "0000011C-0000-1000-8000-0026BB765291", - Self::OutletInUse => "00000026-0000-1000-8000-0026BB765291", - Self::OzoneDensity => "000000C3-0000-1000-8000-0026BB765291", - Self::PairSetup => "0000004C-0000-1000-8000-0026BB765291", - Self::PairVerify => "0000004E-0000-1000-8000-0026BB765291", - Self::PairingFeatures => "0000004F-0000-1000-8000-0026BB765291", - Self::PairingPairings => "00000050-0000-1000-8000-0026BB765291", - Self::PasswordSetting => "000000E4-0000-1000-8000-0026BB765291", - Self::PM10Density => "000000C7-0000-1000-8000-0026BB765291", - Self::PM2_5Density => "000000C6-0000-1000-8000-0026BB765291", - Self::PositionState => "00000072-0000-1000-8000-0026BB765291", - Self::ProgramMode => "000000D1-0000-1000-8000-0026BB765291", - Self::ProgrammableSwitchEvent => "00000073-0000-1000-8000-0026BB765291", - Self::RelativeHumidityDehumidifierThreshold => "000000C9-0000-1000-8000-0026BB765291", - Self::RelativeHumidityHumidifierThreshold => "000000CA-0000-1000-8000-0026BB765291", - Self::RemainingDuration => "000000D4-0000-1000-8000-0026BB765291", - Self::ResetFilterIndication => "000000AD-0000-1000-8000-0026BB765291", - Self::RotationDirection => "00000028-0000-1000-8000-0026BB765291", - Self::RotationSpeed => "00000029-0000-1000-8000-0026BB765291", - Self::Saturation => "0000002F-0000-1000-8000-0026BB765291", - Self::SecuritySystemAlarmType => "0000008E-0000-1000-8000-0026BB765291", - Self::SecuritySystemCurrentState => "00000066-0000-1000-8000-0026BB765291", - Self::SecuritySystemTargetState => "00000067-0000-1000-8000-0026BB765291", - Self::SelectedRTPStreamConfiguration => "00000117-0000-1000-8000-0026BB765291", - Self::SerialNumber => "00000030-0000-1000-8000-0026BB765291", - Self::ServiceLabelIndex => "000000CB-0000-1000-8000-0026BB765291", - Self::ServiceLabelNamespace => "000000CD-0000-1000-8000-0026BB765291", - Self::SetDuration => "000000D3-0000-1000-8000-0026BB765291", - Self::SetupEndpoints => "00000118-0000-1000-8000-0026BB765291", - Self::SlatType => "000000C0-0000-1000-8000-0026BB765291", - Self::SmokeDetected => "00000076-0000-1000-8000-0026BB765291", - Self::StatusActive => "00000075-0000-1000-8000-0026BB765291", - Self::StatusFault => "00000077-0000-1000-8000-0026BB765291", - Self::StatusJammed => "00000078-0000-1000-8000-0026BB765291", - Self::StatusLowBattery => "00000079-0000-1000-8000-0026BB765291", - Self::StatusTampered => "0000007A-0000-1000-8000-0026BB765291", - Self::StreamingStatus => "00000120-0000-1000-8000-0026BB765291", - Self::SulphurDioxideDensity => "000000C5-0000-1000-8000-0026BB765291", - Self::SupportedAudioStreamConfiguration => "00000115-0000-1000-8000-0026BB765291", - Self::SupportedRTPConfiguration => "00000116-0000-1000-8000-0026BB765291", - Self::SupportedVideoStreamConfiguration => "00000114-0000-1000-8000-0026BB765291", - Self::SwingMode => "000000B6-0000-1000-8000-0026BB765291", - Self::TargetAirPurifierState => "000000A8-0000-1000-8000-0026BB765291", - Self::TargetAirQuality => "000000AE-0000-1000-8000-0026BB765291", - Self::TargetDoorState => "00000032-0000-1000-8000-0026BB765291", - Self::TargetFanState => "000000BF-0000-1000-8000-0026BB765291", - Self::TargetHeaterCoolerState => "000000B2-0000-1000-8000-0026BB765291", - Self::TargetHeatingCoolingState => "00000033-0000-1000-8000-0026BB765291", - Self::TargetHorizontalTiltAngle => "0000007B-0000-1000-8000-0026BB765291", - Self::TargetHumidifierDehumidifierState => "000000B4-0000-1000-8000-0026BB765291", - Self::TargetPosition => "0000007C-0000-1000-8000-0026BB765291", - Self::TargetRelativeHumidity => "00000034-0000-1000-8000-0026BB765291", - Self::TargetSlatState => "000000BE-0000-1000-8000-0026BB765291", - Self::TargetTemperature => "00000035-0000-1000-8000-0026BB765291", - Self::TargetTiltAngle => "000000C2-0000-1000-8000-0026BB765291", - Self::TargetVerticalTiltAngle => "0000007D-0000-1000-8000-0026BB765291", - Self::TemperatureDisplayUnits => "00000036-0000-1000-8000-0026BB765291", - Self::ValveType => "000000D5-0000-1000-8000-0026BB765291", - Self::Version => "00000037-0000-1000-8000-0026BB765291", - Self::VOCDensity => "000000C8-0000-1000-8000-0026BB765291", - Self::Volume => "00000119-0000-1000-8000-0026BB765291", - Self::WaterLevel => "000000B5-0000-1000-8000-0026BB765291", - Self::RecordingAudioActive => "00000226-0000-1000-8000-0026BB765291", - Self::SupportedCameraRecordingConfiguration => "00000205-0000-1000-8000-0026BB765291", - Self::SupportedVideoRecordingConfiguration => "00000206-0000-1000-8000-0026BB765291", - Self::SupportedAudioRecordingConfiguration => "00000207-0000-1000-8000-0026BB765291", - Self::SelectedCameraRecordingConfiguration => "00000209-0000-1000-8000-0026BB765291", - Self::CameraOperatingModeIndicator => "0000021D-0000-1000-8000-0026BB765291", - Self::EventSnapshotsActive => "00000223-0000-1000-8000-0026BB765291", - Self::DiagonalFieldOfView => "00000224-0000-1000-8000-0026BB765291", - Self::HomeKitCameraActive => "0000021B-0000-1000-8000-0026BB765291", - Self::ManuallyDisabled => "00000227-0000-1000-8000-0026BB765291", - Self::ThirdPartyCameraActive => "0000021C-0000-1000-8000-0026BB765291", - Self::PeriodicSnapshotsActive => "00000225-0000-1000-8000-0026BB765291", - Self::NetworkClientProfileControl => "0000020C-0000-1000-8000-0026BB765291", - Self::NetworkClientStatusControl => "0000020D-0000-1000-8000-0026BB765291", - Self::RouterStatus => "0000020E-0000-1000-8000-0026BB765291", - Self::SupportedRouterConfiguration => "00000210-0000-1000-8000-0026BB765291", - Self::WANConfigurationList => "00000211-0000-1000-8000-0026BB765291", - Self::WANStatusList => "00000212-0000-1000-8000-0026BB765291", - Self::ManagedNetworkEnable => "00000215-0000-1000-8000-0026BB765291", - Self::NetworkAccessViolationControl => "0000021F-0000-1000-8000-0026BB765291", - Self::WiFiSatelliteStatus => "0000021E-0000-1000-8000-0026BB765291", - Self::WakeConfiguration => "00000222-0000-1000-8000-0026BB765291", - Self::SupportedTransferTransportConfiguration => "00000202-0000-1000-8000-0026BB765291", - Self::SetupTransferTransport => "00000201-0000-1000-8000-0026BB765291", - Self::ActivityInterval => "0000021E-0000-1000-8000-0000023B", - Self::CCAEnergyDetectThreshold => "0000021E-0000-1000-8000-00000246", - Self::CCASignalDetectThreshold => "0000021E-0000-1000-8000-00000245", - Self::CharacteristicValueTransitionControl => "0000021E-0000-1000-8000-00000143", - Self::SupportedCharacteristicValueTransitionConfiguration => { - "0000021E-0000-1000-8000-00000144" - } - Self::CurrentTransport => "0000021E-0000-1000-8000-0000022B", - Self::DataStreamHAPTransport => "0000021E-0000-1000-8000-00000138", - Self::DataStreamHAPTransportInterrupt => "0000021E-0000-1000-8000-00000139", - Self::EventRetransmissionMaximum => "0000021E-0000-1000-8000-0000023D", - Self::EventTransmissionCounters => "0000021E-0000-1000-8000-0000023E", - Self::HeartBeat => "0000021E-0000-1000-8000-0000024A", - Self::MACRetransmissionMaximum => "0000021E-0000-1000-8000-00000247", - Self::MACTransmissionCounters => "0000021E-0000-1000-8000-00000248", - Self::OperatingStateResponse => "0000021E-0000-1000-8000-00000232", - Self::Ping => "0000021E-0000-1000-8000-0000023C", - Self::ReceiverSensitivity => "0000021E-0000-1000-8000-00000244", - Self::ReceivedSignalStrengthIndication => "0000021E-0000-1000-8000-0000023F", - Self::SleepInterval => "0000021E-0000-1000-8000-0000023A", - Self::SignalToNoiseRatio => "0000021E-0000-1000-8000-00000241", - Self::SupportedDiagnosticsSnapshot => "0000021E-0000-1000-8000-00000238", - Self::TransmitPower => "0000021E-0000-1000-8000-00000242", - Self::TransmitPowerMaximum => "0000021E-0000-1000-8000-00000243", - Self::VideoAnalysisActive => "0000021E-0000-1000-8000-00000229", - Self::WiFiCapabilities => "0000021E-0000-1000-8000-0000022C", - Self::WiFiConfigurationControl => "0000021E-0000-1000-8000-0000022D", - Self::AppMatchingIdentifier => "000000A4-0000-1000-8000-0026BB765291", - Self::ProgrammableSwitchOutputState => "00000074-0000-1000-8000-0026BB765291", - Self::SoftwareRevision => "00000054-0000-1000-8000-0026BB765291", - Self::AccessoryIdentifier => "00000057-0000-1000-8000-0026BB765291", - Self::Category => "000000A3-0000-1000-8000-0026BB765291", - Self::ConfigureBridgedAccessory => "000000A0-0000-1000-8000-0026BB765291", - Self::ConfigureBridgedAccessoryStatus => "0000009D-0000-1000-8000-0026BB765291", - Self::CurrentTime => "0000009B-0000-1000-8000-0026BB765291", - Self::DayoftheWeek => "00000098-0000-1000-8000-0026BB765291", - Self::DiscoverBridgedAccessories => "0000009E-0000-1000-8000-0026BB765291", - Self::DiscoveredBridgedAccessories => "0000009F-0000-1000-8000-0026BB765291", - Self::LinkQuality => "0000009C-0000-1000-8000-0026BB765291", - Self::Reachable => "00000063-0000-1000-8000-0026BB765291", - Self::RelayControlPoint => "0000005E-0000-1000-8000-0026BB765291", - Self::RelayEnabled => "0000005B-0000-1000-8000-0026BB765291", - Self::RelayState => "0000005C-0000-1000-8000-0026BB765291", - Self::TimeUpdate => "0000009A-0000-1000-8000-0026BB765291", - Self::TunnelConnectionTimeout => "00000061-0000-1000-8000-0026BB765291", - Self::TunneledAccessoryAdvertising => "00000060-0000-1000-8000-0026BB765291", - Self::TunneledAccessoryConnected => "00000059-0000-1000-8000-0026BB765291", - Self::TunneledAccessoryStateNumber => "00000058-0000-1000-8000-0026BB765291", - Self::ActiveIdentifier => "000000E7-0000-1000-8000-0026BB765291", - Self::ConfiguredName => "000000E3-0000-1000-8000-0026BB765291", - Self::SleepDiscoveryMode => "000000E8-0000-1000-8000-0026BB765291", - Self::ClosedCaptions => "000000DD-0000-1000-8000-0026BB765291", - Self::DisplayOrder => "00000136-0000-1000-8000-0026BB765291", - Self::CurrentMediaState => "000000E0-0000-1000-8000-0026BB765291", - Self::TargetMediaState => "00000137-0000-1000-8000-0026BB765291", - Self::PictureMode => "000000E2-0000-1000-8000-0026BB765291", - Self::PowerModeSelection => "000000DF-0000-1000-8000-0026BB765291", - Self::RemoteKey => "000000E1-0000-1000-8000-0026BB765291", - Self::InputSourceType => "000000DB-0000-1000-8000-0026BB765291", - Self::InputDeviceType => "000000DC-0000-1000-8000-0026BB765291", - Self::Identifier => "000000E6-0000-1000-8000-0026BB765291", - Self::CurrentVisibilityState => "00000135-0000-1000-8000-0026BB765291", - Self::TargetVisibilityState => "00000134-0000-1000-8000-0026BB765291", - Self::VolumeControlType => "000000E9-0000-1000-8000-0026BB765291", - Self::VolumeSelector => "000000EA-0000-1000-8000-0026BB765291", - Self::TargetControlSupportedConfiguration => "00000123-0000-1000-8000-0026BB765291", - Self::TargetControlList => "00000124-0000-1000-8000-0026BB765291", - Self::ButtonEvent => "00000126-0000-1000-8000-0026BB765291", - Self::SelectedAudioStreamConfiguration => "00000128-0000-1000-8000-0026BB765291", - Self::SiriInputType => "00000132-0000-1000-8000-0026BB765291", - Self::SupportedDataStreamTransportConfiguration => { - "00000130-0000-1000-8000-0026BB765291" - } - Self::SetupDataStreamTransport => "00000131-0000-1000-8000-0026BB765291", - Self::Unknown => "", - } - .fmt(f) - } -} - #[derive(Deserialize)] #[serde(field_identifier)] enum CharacteristicTypeInner { @@ -1228,7 +995,8 @@ where ServiceTypeInner::deserialize(deserializer).map(|v| v.into()) } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash, Display)] +#[strum(serialize_all = "snake_case")] pub enum ServiceType { AccessControl, AccessoryInformation, @@ -1301,83 +1069,6 @@ pub enum ServiceType { Unknown, } -impl std::fmt::Display for ServiceType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::AccessControl => "000000DA-0000-1000-8000-0026BB765291", - Self::AccessoryInformation => "0000003E-0000-1000-8000-0026BB765291", - Self::AirPurifier => "000000BB-0000-1000-8000-0026BB765291", - Self::AirQualitySensor => "0000008D-0000-1000-8000-0026BB765291", - Self::BatteryService => "00000096-0000-1000-8000-0026BB765291", - Self::CameraRTPStreamManagement => "00000110-0000-1000-8000-0026BB765291", - Self::CarbonDioxideSensor => "00000097-0000-1000-8000-0026BB765291", - Self::CarbonMonoxideSensor => "0000007F-0000-1000-8000-0026BB765291", - Self::ContactSensor => "00000080-0000-1000-8000-0026BB765291", - Self::Door => "00000081-0000-1000-8000-0026BB765291", - Self::Doorbell => "00000121-0000-1000-8000-0026BB765291", - Self::Fan => "00000040-0000-1000-8000-0026BB765291", - Self::Fanv2 => "000000B7-0000-1000-8000-0026BB765291", - Self::FilterMaintenance => "000000BA-0000-1000-8000-0026BB765291", - Self::Faucet => "000000D7-0000-1000-8000-0026BB765291", - Self::GarageDoorOpener => "00000041-0000-1000-8000-0026BB765291", - Self::HeaterCooler => "000000BC-0000-1000-8000-0026BB765291", - Self::HumidifierDehumidifier => "000000BD-0000-1000-8000-0026BB765291", - Self::HumiditySensor => "00000082-0000-1000-8000-0026BB765291", - Self::IrrigationSystem => "000000CF-0000-1000-8000-0026BB765291", - Self::LeakSensor => "00000083-0000-1000-8000-0026BB765291", - Self::LightSensor => "00000084-0000-1000-8000-0026BB765291", - Self::Lightbulb => "00000043-0000-1000-8000-0026BB765291", - Self::LockManagement => "00000044-0000-1000-8000-0026BB765291", - Self::LockMechanism => "00000045-0000-1000-8000-0026BB765291", - Self::Microphone => "00000112-0000-1000-8000-0026BB765291", - Self::MotionSensor => "00000085-0000-1000-8000-0026BB765291", - Self::OccupancySensor => "00000086-0000-1000-8000-0026BB765291", - Self::Outlet => "00000047-0000-1000-8000-0026BB765291", - Self::SecuritySystem => "0000007E-0000-1000-8000-0026BB765291", - Self::ServiceLabel => "000000CC-0000-1000-8000-0026BB765291", - Self::Slat => "000000B9-0000-1000-8000-0026BB765291", - Self::SmokeSensor => "00000087-0000-1000-8000-0026BB765291", - Self::SmartSpeaker => "00000228-0000-1000-8000-0026BB765291", - Self::Speaker => "00000113-0000-1000-8000-0026BB765291", - Self::StatelessProgrammableSwitch => "00000089-0000-1000-8000-0026BB765291", - Self::Switch => "00000049-0000-1000-8000-0026BB765291", - Self::TemperatureSensor => "0000008A-0000-1000-8000-0026BB765291", - Self::Thermostat => "0000004A-0000-1000-8000-0026BB765291", - Self::Valve => "000000D0-0000-1000-8000-0026BB765291", - Self::Window => "0000008B-0000-1000-8000-0026BB765291", - Self::WindowCovering => "0000008C-0000-1000-8000-0026BB765291", - Self::CameraOperatingMode => "0000021A-0000-1000-8000-0026BB765291", - Self::CameraEventRecordingManagement => "00000204-0000-1000-8000-0026BB765291", - Self::WiFiRouter => "0000020A-0000-1000-8000-0026BB765291", - Self::WiFiSatellite => "0000020F-0000-1000-8000-0026BB765291", - Self::PowerManagement => "00000221-0000-1000-8000-0026BB765291", - Self::TransferTransportManagement => "00000203-0000-1000-8000-0026BB765291", - Self::AccessoryRuntimeInformation => "00000203-0000-1000-8000-00000239", - Self::Diagnostics => "00000203-0000-1000-8000-00000237", - Self::WiFiTransport => "00000203-0000-1000-8000-0000022A", - Self::CameraControl => "00000111-0000-1000-8000-0026BB765291", - Self::StatefulProgrammableSwitch => "00000088-0000-1000-8000-0026BB765291", - Self::BridgeConfiguration => "000000A1-0000-1000-8000-0026BB765291", - Self::BridgingState => "00000062-0000-1000-8000-0026BB765291", - Self::Pairing => "00000055-0000-1000-8000-0026BB765291", - Self::ProtocolInformation => "000000A2-0000-1000-8000-0026BB765291", - Self::Relay => "0000005A-0000-1000-8000-0026BB765291", - Self::TimeInformation => "00000099-0000-1000-8000-0026BB765291", - Self::TunneledBTLEAccessoryService => "00000056-0000-1000-8000-0026BB765291", - Self::Television => "000000D8-0000-1000-8000-0026BB765291", - Self::InputSource => "000000D9-0000-1000-8000-0026BB765291", - Self::TelevisionSpeaker => "00000113-0000-1000-8000-0026BB765291", - Self::TargetControlManagement => "00000122-0000-1000-8000-0026BB765291", - Self::TargetControl => "00000125-0000-1000-8000-0026BB765291", - Self::AudioStreamManagement => "00000127-0000-1000-8000-0026BB765291", - Self::Siri => "00000133-0000-1000-8000-0026BB765291", - Self::DataStreamTransportManagement => "00000129-0000-1000-8000-0026BB765291", - Self::Unknown => "", - } - .fmt(f) - } -} - #[derive(Deserialize)] #[serde(field_identifier)] pub enum ServiceTypeInner { diff --git a/homekit-exporter/src/server.rs b/homekit-exporter/src/server.rs index 3208df9..4154aab 100644 --- a/homekit-exporter/src/server.rs +++ b/homekit-exporter/src/server.rs @@ -8,58 +8,58 @@ use crate::SENSORS; pub fn launch(paired: HashMap) -> rocket::Rocket { rocket::build() .manage(Mutex::new(paired)) - .mount("/", routes![index]) + .mount("/", routes![metrics]) } -#[get("/")] -pub async fn index(state: &State>>) -> Option { +#[get("/metrics")] +pub async fn metrics(state: &State>>) -> Option { let mut s = String::new(); let mut state = state.lock().await; + let mut shown_types = Vec::new(); for (name, connected) in state.deref_mut() { connected.update_characteristics().await.ok()?; - s.push_str(format!("{name}: [\n").as_str()); - for (aid, accessory) in &connected.accessories { - s.push_str(format!("\t{} ({}): [\n", accessory.name, aid).as_str()); - for (sid, service) in &accessory.services { + for service in accessory.services.values() { if !SENSORS.contains(&service.service_type) { continue; } - s.push_str( - format!( - "\t\t{} ({:?}) ({}): [\n", - service.name.as_ref().unwrap_or(&String::from("Unknown")), - service.service_type, - sid, - ) - .as_str(), - ); for (cid, characteristic) in &service.characteristics { - s.push_str( - format!( - "\t\t\t{:?} ({}): {}{}\n", - characteristic.characteristic_type, - cid, - match &characteristic.value { - Some(Data::String(s)) => s.clone(), - Some(other) => format!("{other:?}"), - None => String::from("no data"), - }, - characteristic - .unit - .map(|v| format!(" ({v:?})")) - .unwrap_or_default() + if let Some(value) = &characteristic.value { + if !shown_types.contains(&characteristic.characteristic_type) { + s.push_str( + format!("# TYPE {} gauge\n", characteristic.characteristic_type) + .as_str(), + ); + shown_types.push(characteristic.characteristic_type); + } + s.push_str( + format!( + "{}{{accessory=\"{}.{}.{}\"}} {}\n", + characteristic.characteristic_type, + name, + aid, + cid, + match value { + Data::Bool(v) => format!("{}", if *v { 1 } else { 0 }), + Data::Uint8(v) => format!("{v}"), + Data::Uint16(v) => format!("{v}"), + Data::Uint32(v) => format!("{v}"), + Data::Uint64(v) => format!("{v}"), + Data::Int(v) => format!("{v}"), + Data::Float(v) => format!("{v}"), + Data::String(v) => v.to_string(), + Data::Tlv8(v) => v.to_string(), + Data::Data(v) => v.to_string(), + } + ) + .as_str(), ) - .as_str(), - ); + } } - s.push_str("\t\t]\n"); } - s.push_str("\t]\n"); } - s.push_str("]\n"); } Some(s) }