Skip to main content

sonos_api/
lib.rs

1//! High-level Sonos API for device control
2//!
3//! This crate provides a type-safe, trait-based API for controlling Sonos devices.
4//! It uses the private `soap-client` crate for low-level SOAP communication.
5//!
6//! # UPnP Architecture
7//!
8//! This API correctly implements the UPnP architecture used by Sonos devices:
9//!
10//! - **Control Operations**: Commands like Play, Pause, SetVolume are sent to `/Control` endpoints
11//! - **Event Subscriptions**: Subscriptions for state change notifications are sent to `/Event` endpoints
12//!
13//! These are completely separate and independent concepts that work together to provide
14//! both control and monitoring capabilities.
15//!
16//! # Enhanced Operation Framework
17//!
18//! The operation framework provides composable, declarative UPnP operations with validation,
19//! retry policies, and timeouts:
20//!
21//! ```rust,ignore
22//! use sonos_api::{SonosClient, services::av_transport, services::rendering_control};
23//! use sonos_api::operation::ValidationLevel;
24//!
25//! let client = SonosClient::new();
26//!
27//! // Simple operation execution
28//! let play_op = av_transport::play("1".to_string())
29//!     .with_validation(ValidationLevel::Comprehensive)
30//!     .build()?;
31//!
32//! client.execute_enhanced("192.168.1.100", play_op)?;
33//!
34//! // Composed operations
35//! let sequence = av_transport::play("1".to_string())
36//!     .build()?
37//!     .and_then(rendering_control::set_volume("Master".to_string(), 75).build()?);
38//!
39//! client.execute_sequence("192.168.1.100", sequence)?;
40//! ```
41//!
42//! # Event Subscription Management
43//!
44//! UPnP event subscriptions allow you to receive real-time state change notifications
45//! from Sonos devices. Subscriptions are managed separately from control operations:
46//!
47//! ## Client-Level Subscriptions
48//!
49//! Subscribe directly to any service using the client:
50//!
51//! ```rust,ignore
52//! use sonos_api::{SonosClient, Service};
53//!
54//! let client = SonosClient::new();
55//!
56//! // Subscribe to AVTransport events (play/pause state changes)
57//! let av_subscription = client.subscribe(
58//!     "192.168.1.100",
59//!     Service::AVTransport,
60//!     "http://192.168.1.50:8080/callback"
61//! )?;
62//!
63//! // Subscribe to RenderingControl events (volume changes)
64//! let rc_subscription = client.subscribe(
65//!     "192.168.1.100",
66//!     Service::RenderingControl,
67//!     "http://192.168.1.50:8080/callback"
68//! )?;
69//!
70//! // Custom timeout (default is 1800 seconds)
71//! let long_subscription = client.subscribe_with_timeout(
72//!     "192.168.1.100",
73//!     Service::AVTransport,
74//!     "http://192.168.1.50:8080/callback",
75//!     7200  // 2 hours
76//! )?;
77//! ```
78//!
79//! ## Service-Level Subscription Helpers
80//!
81//! Each service module provides convenient subscription helpers:
82//!
83//! ```rust,ignore
84//! use sonos_api::{SonosClient, services::av_transport, services::rendering_control};
85//!
86//! let client = SonosClient::new();
87//!
88//! // Subscribe to specific services using module helpers
89//! let av_subscription = av_transport::subscribe(
90//!     &client,
91//!     "192.168.1.100",
92//!     "http://192.168.1.50:8080/callback"
93//! )?;
94//!
95//! let rc_subscription = rendering_control::subscribe(
96//!     &client,
97//!     "192.168.1.100",
98//!     "http://192.168.1.50:8080/callback"
99//! )?;
100//!
101//! // With custom timeout
102//! let long_av_subscription = av_transport::subscribe_with_timeout(
103//!     &client,
104//!     "192.168.1.100",
105//!     "http://192.168.1.50:8080/callback",
106//!     3600
107//! )?;
108//! ```
109//!
110//! ## Subscription Lifecycle Management
111//!
112//! All subscriptions return a `ManagedSubscription` that handles lifecycle management:
113//!
114//! ```rust,ignore
115//! let subscription = client.subscribe(
116//!     "192.168.1.100",
117//!     Service::AVTransport,
118//!     "http://192.168.1.50:8080/callback"
119//! )?;
120//!
121//! // Check if renewal is needed and renew if so
122//! if subscription.needs_renewal() {
123//!     subscription.renew()?;
124//! }
125//!
126//! // Clean up when done
127//! subscription.unsubscribe()?;
128//! ```
129//!
130//! The `ManagedSubscription` handles all lifecycle management including expiration tracking,
131//! renewal logic, and proper cleanup.
132//!
133//! ## Control Operations and Subscriptions Together
134//!
135//! Control operations and subscriptions work independently but can be used together:
136//!
137//! ```rust,ignore
138//! use sonos_api::{SonosClient, Service, services::av_transport};
139//!
140//! let client = SonosClient::new();
141//!
142//! // Set up event subscription first
143//! let subscription = client.subscribe(
144//!     "192.168.1.100",
145//!     Service::AVTransport,
146//!     "http://192.168.1.50:8080/callback"
147//! )?;
148//!
149//! // Execute control operations
150//! let play_op = av_transport::play("1".to_string()).build()?;
151//! client.execute_enhanced("192.168.1.100", play_op)?;
152//!
153//! // The subscription will receive events about state changes
154//! // caused by the control operations
155//! ```
156
157pub mod client;
158pub mod error;
159pub mod events;
160pub mod operation; // Enhanced operation framework
161pub mod service;
162pub mod services; // Enhanced services
163pub mod subscription; // New event handling framework
164pub mod types;
165
166// Common types shared across the workspace
167pub use types::{GroupId, SpeakerId};
168
169// Legacy exports for backward compatibility
170pub use client::SonosClient;
171pub use error::{ApiError, Result};
172pub use operation::SonosOperation; // Legacy trait
173pub use service::{Service, ServiceInfo, ServiceScope};
174pub use subscription::ManagedSubscription;
175
176// New enhanced operation framework exports
177pub use operation::{
178    OperationBuilder, OperationMetadata, UPnPOperation, Validate, ValidationError, ValidationLevel,
179};
180
181// New event handling framework exports
182pub use events::{
183    extract_xml_value, EnrichedEvent, EventParser, EventParserRegistry, EventProcessor, EventSource,
184};
185
186// Enhanced services are available through the services module