| name | add-service |
| description | Add a complete new Sonos service across all SDK layers (api → stream → state → sdk). This orchestrator skill coordinates the 4 layer-specific skills for full-stack service implementation. |
Add Service Orchestrator
Overview
This skill coordinates the implementation of a new Sonos UPnP service across all 4 SDK layers:
- sonos-api - UPnP operations (SOAP requests/responses)
- sonos-stream - Event streaming and polling
- sonos-state - Reactive state management
- sonos-sdk - DOM-like public API
Prerequisites
Before starting, gather:
- Service documentation URL (e.g.,
https://sonos.svrooij.io/services/queue)
- List of operations to implement
- List of properties to expose
- Access to a real Sonos speaker for testing
Quick Start
python .claude/skills/add-service/scripts/service_status.py NewService
python .claude/skills/add-service/scripts/integration_test.py NewService 192.168.1.100
Complete Workflow
Step 1: API Layer (sonos-api)
Use /implement-service skill to implement UPnP operations.
Files Modified:
sonos-api/src/services/{service}/mod.rs - Service module
sonos-api/src/services/{service}/operations.rs - Operation structs
sonos-api/src/services/mod.rs - Service registration
sonos-api/src/lib.rs - Re-exports
Key Tasks:
- Extract operations from service documentation
- Generate operation structs with macros
- Test against real speakers
- Add validation and error handling
Verify:
cargo test -p sonos-api
cargo run --example cli_example -- <speaker_ip> NewService OperationName
Step 2: Stream Layer (sonos-stream)
Use /implement-service-stream skill to add event streaming support.
Files Modified:
sonos-stream/src/events/types.rs - Event struct + EventData variant
sonos-stream/src/events/processor.rs - Event processor case
sonos-stream/src/polling/strategies.rs - ServicePoller impl
Key Tasks:
- Define event struct with all state fields
- Add EventData enum variant
- Implement convert_api_event_data() case
- Implement ServicePoller for polling fallback
Verify:
cargo test -p sonos-stream
python .claude/skills/implement-service-stream/scripts/analyze_stream_events.py --validate
python .claude/skills/implement-service-stream/scripts/test_polling.py <speaker_ip> NewService
Step 3: State Layer (sonos-state)
Use /implement-service-state skill to add reactive state management.
Files Modified:
sonos-state/src/property.rs - Property structs
sonos-state/src/decoder.rs - PropertyChange variants + decoder
sonos-state/src/lib.rs - Re-exports
Key Tasks:
- Define property structs with Property + SonosProperty traits
- Add PropertyChange enum variants
- Implement decoder function
- Update decode_event() switch
Verify:
cargo test -p sonos-state
python .claude/skills/implement-service-state/scripts/analyze_properties.py --coverage
Step 4: SDK Layer (sonos-sdk)
Use /implement-service-sdk skill to expose properties through DOM-like API.
Files Modified:
sonos-sdk/src/property/handles.rs - Fetchable impl + type alias
sonos-sdk/src/speaker.rs - Speaker struct fields
sonos-sdk/src/lib.rs - Re-exports
Key Tasks:
- Implement Fetchable trait (if property has Get operation)
- Create type aliases for handles
- Add fields to Speaker struct
- Initialize handles in Speaker::new()
Verify:
cargo test -p sonos-sdk
python .claude/skills/implement-service-sdk/scripts/analyze_handles.py --coverage
Step 5: Integration Testing
After all layers are complete:
cargo test
python .claude/skills/add-service/scripts/integration_test.py NewService <speaker_ip>
cargo run -p sonos-sdk --example basic_usage
Layer Responsibilities Reference
| Layer | Crate | Purpose | Key Files |
|---|
| API | sonos-api | UPnP SOAP operations | services/{service}/operations.rs |
| Stream | sonos-stream | Event streaming/polling | events/types.rs, polling/strategies.rs |
| State | sonos-state | Reactive state store | property.rs, decoder.rs |
| SDK | sonos-sdk | DOM-like public API | property/handles.rs, speaker.rs |
Data Flow
UPnP Events
│
▼
┌─────────────────────────────────────────────────────────────┐
│ sonos-stream: EventData enum, ServicePoller │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ sonos-state: decode_event() → PropertyChange → StateStore │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ sonos-sdk: PropertyHandle.get() / watch() / fetch() │
└─────────────────────────────────────────────────────────────┘
│
▼
User Code
Common Issues
Events Not Showing Up
- Check EventData variant exists in
sonos-stream/src/events/types.rs
- Check
convert_api_event_data() handles the service
- Check decoder exists in
sonos-state/src/decoder.rs
Properties Not Updating
- Check PropertyChange variant exists
- Check
key() and service() match arms
- Check decoder function parses all fields
fetch() Not Available
The property may be event-only (no dedicated Get operation). Document this and use get() with watch().
Watch Mode Always CacheOnly
Event manager not configured. Call system.configure_events() first.
Rollback Procedure
If implementation fails, revert in reverse order:
- SDK layer changes
- State layer changes
- Stream layer changes
- API layer changes
Use git diff to identify changes in each crate:
git diff sonos-sdk/
git diff sonos-state/
git diff sonos-stream/
git diff sonos-api/
References