use serde::{Deserialize, Serialize};
use std::net::IpAddr;
use std::time::{Duration, SystemTime};
use crate::registry::RegistrationId;
pub use sonos_api::services::av_transport::state::AVTransportState;
pub use sonos_api::services::group_management::state::GroupManagementState;
pub use sonos_api::services::group_rendering_control::state::GroupRenderingControlState;
pub use sonos_api::services::rendering_control::state::RenderingControlState;
pub use sonos_api::services::zone_group_topology::state::ZoneGroupTopologyState;
pub use sonos_api::services::zone_group_topology::events::{
NetworkInfo, SatelliteInfo, ZoneGroupInfo, ZoneGroupMemberInfo,
};
#[derive(Debug, Clone)]
pub struct EnrichedEvent {
pub registration_id: RegistrationId,
pub speaker_ip: IpAddr,
pub service: sonos_api::Service,
pub event_source: EventSource,
pub timestamp: SystemTime,
pub event_data: EventData,
}
impl EnrichedEvent {
pub fn new(
registration_id: RegistrationId,
speaker_ip: IpAddr,
service: sonos_api::Service,
event_source: EventSource,
event_data: EventData,
) -> Self {
Self {
registration_id,
speaker_ip,
service,
event_source,
timestamp: SystemTime::now(),
event_data,
}
}
}
#[derive(Debug, Clone)]
pub enum EventSource {
UPnPNotification {
subscription_id: String,
},
PollingDetection {
poll_interval: Duration,
},
}
#[derive(Debug, Clone)]
pub enum EventData {
AVTransport(AVTransportState),
RenderingControl(RenderingControlState),
DeviceProperties(DevicePropertiesEvent),
ZoneGroupTopology(ZoneGroupTopologyState),
GroupManagement(GroupManagementState),
GroupRenderingControl(GroupRenderingControlState),
}
impl EventData {
pub fn service_type(&self) -> sonos_api::Service {
match self {
EventData::AVTransport(_) => sonos_api::Service::AVTransport,
EventData::RenderingControl(_) => sonos_api::Service::RenderingControl,
EventData::DeviceProperties(_) => {
sonos_api::Service::ZoneGroupTopology
}
EventData::ZoneGroupTopology(_) => sonos_api::Service::ZoneGroupTopology,
EventData::GroupManagement(_) => sonos_api::Service::GroupManagement,
EventData::GroupRenderingControl(_) => sonos_api::Service::GroupRenderingControl,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DevicePropertiesEvent {
pub zone_name: Option<String>,
pub zone_icon: Option<String>,
pub configuration: Option<String>,
pub capabilities: Option<String>,
pub software_version: Option<String>,
pub model_name: Option<String>,
pub display_version: Option<String>,
pub hardware_version: Option<String>,
pub additional_properties: std::collections::HashMap<String, String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_enriched_event_creation() {
let reg_id = RegistrationId::new(1);
let ip: IpAddr = "192.168.1.100".parse().unwrap();
let service = sonos_api::Service::AVTransport;
let source = EventSource::UPnPNotification {
subscription_id: "uuid:123".to_string(),
};
let data = EventData::AVTransport(AVTransportState {
transport_state: Some("PLAYING".to_string()),
transport_status: None,
speed: None,
current_track_uri: None,
track_duration: None,
track_metadata: None,
rel_time: None,
abs_time: None,
rel_count: None,
abs_count: None,
play_mode: None,
next_track_uri: None,
next_track_metadata: None,
queue_length: None,
});
let event = EnrichedEvent::new(reg_id, ip, service, source, data);
assert_eq!(event.registration_id, reg_id);
assert_eq!(event.speaker_ip, ip);
assert_eq!(event.service, service);
}
#[test]
fn test_event_data_service_type() {
let av_event = EventData::AVTransport(AVTransportState {
transport_state: Some("PLAYING".to_string()),
transport_status: None,
speed: None,
current_track_uri: None,
track_duration: None,
track_metadata: None,
rel_time: None,
abs_time: None,
rel_count: None,
abs_count: None,
play_mode: None,
next_track_uri: None,
next_track_metadata: None,
queue_length: None,
});
assert_eq!(av_event.service_type(), sonos_api::Service::AVTransport);
let rc_event = EventData::RenderingControl(RenderingControlState {
master_volume: Some("50".to_string()),
master_mute: Some("false".to_string()),
lf_volume: None,
rf_volume: None,
lf_mute: None,
rf_mute: None,
bass: None,
treble: None,
loudness: None,
balance: None,
other_channels: std::collections::HashMap::new(),
});
assert_eq!(
rc_event.service_type(),
sonos_api::Service::RenderingControl
);
let gm_event = EventData::GroupManagement(GroupManagementState {
group_coordinator_is_local: Some(true),
local_group_uuid: None,
reset_volume_after: None,
virtual_line_in_group_id: None,
volume_av_transport_uri: None,
});
assert_eq!(gm_event.service_type(), sonos_api::Service::GroupManagement);
let grc_event = EventData::GroupRenderingControl(GroupRenderingControlState {
group_volume: Some(14),
group_mute: Some(false),
group_volume_changeable: Some(true),
});
assert_eq!(
grc_event.service_type(),
sonos_api::Service::GroupRenderingControl
);
}
}