# Bose SoundTouch API Client - Golang Implementation Plan ## Overview This document describes the planning for a Golang-based API client for the Bose SoundTouch Web API. The client follows modern Go patterns and supports both native Go library and WASM integration with embedded web UI. **New insights from pattern analysis:** - Single binary deployment with embedded assets - Multi-target build system (Native + WASM) - CORS proxy pattern for browser integration - Robust XML API client patterns - Production-ready configuration management ## API Fundamentals ### Basic Information - **Protocol**: HTTP REST-like - **Data format**: XML Request/Response - **Port**: 8090 (default) - **Authentication**: No complex authentication required - **Real-time updates**: WebSocket connection available - **Device discovery**: UPnP discovery possible ### Core API Endpoints - `GET /info` - Device information - `GET /now_playing` - Currently playing music - `POST /key` - Send key commands (PLAY, PAUSE, etc.) - `GET/POST /volume` - Control volume - `GET/POST /bass` - Bass settings - `GET/POST /sources` - Available sources - `POST /select` - Select source - `GET /presets` - Read presets (1-6) ✅ COMPLETE - `POST /storePreset` - Store/update presets ✅ COMPLETE (via SoundTouch Plus Wiki) - `POST /removePreset` - Remove presets ✅ COMPLETE (via SoundTouch Plus Wiki) - `WebSocket /` - Live updates for events ## Architecture Based on Modern Go Patterns ### Final Project Structure ``` github.com/gesellix/bose-soundtouch/ ├── cmd/ │ ├── cli/ # CLI Tool (Main Application) │ │ └── main.go │ ├── webapp/ # Web Application with embedded Assets │ │ ├── main.go │ │ └── web/ # Embedded HTML/CSS/JS │ │ ├── index.html │ │ ├── app.js │ │ └── style.css │ └── wasm/ # WASM Entry Point │ └── main.go ├── pkg/ # Public API (external usage) │ ├── client/ # HTTP Client with XML Support │ ├── discovery/ # UPnP Device Discovery │ ├── models/ # Type-safe XML Data Models │ ├── websocket/ # Event Streaming Client │ ├── wasm/ # WASM JavaScript Bridge │ └── config/ # Configuration Management ├── internal/ # Private Implementation Details │ ├── xml/ # XML Parsing Utilities │ ├── http/ # HTTP Utilities & Middleware │ └── testing/ # Mock Client & Test Utilities ├── web/ # Frontend Development Assets │ ├── src/ # Source files │ └── dist/ # Build output → cmd/webapp/web/ ├── examples/ # Usage Examples & Demos ├── test/ # Integration Tests & Docker ├── Makefile # Comprehensive Build System ├── .env.example # Configuration Template ├── .air-webapp.toml # Hot Reload Config ├── .air-wasm.toml # WASM Development Config ├── docker-compose.yml # Development Environment ├── PROJECT-PATTERNS.md # Pattern Documentation ├── API-Endpoints-Overview.md # API Reference ├── go.mod └── README.md ``` ### Core Components (Updated) #### 1. HTTP Client with XML Support (`pkg/client`) ```go type Client struct { baseURL string httpClient *http.Client timeout time.Duration userAgent string } type ClientConfig struct { Host string Port int Timeout time.Duration UserAgent string } // Core API methods func NewClient(config ClientConfig) *Client func (c *Client) GetDeviceInfo() (*models.DeviceInfo, error) func (c *Client) GetNowPlaying() (*models.NowPlaying, error) func (c *Client) SetVolume(volume int) error func (c *Client) GetVolume() (*models.Volume, error) func (c *Client) SendKey(key models.Key) error func (c *Client) GetSources() (*models.Sources, error) func (c *Client) SelectSource(source models.ContentItem) error func (c *Client) GetPresets() (*models.Presets, error) func (c *Client) SetPreset(id int, content models.ContentItem) error // HTTP utilities with XML handling func (c *Client) get(endpoint string, result interface{}) error func (c *Client) post(endpoint string, data interface{}, result interface{}) error ``` #### 2. UPnP Device Discovery (`pkg/discovery`) ```go type DiscoveryService struct { timeout time.Duration cache map[string]*Device cacheTTL time.Duration mutex sync.RWMutex } type Device struct { Name string `json:"name"` Host string `json:"host"` Port int `json:"port"` ModelID string `json:"modelId"` SerialNo string `json:"serialNo"` Location string `json:"location"` LastSeen time.Time `json:"lastSeen"` } func NewDiscoveryService(timeout time.Duration) *DiscoveryService func (d *DiscoveryService) DiscoverDevices() ([]Device, error) func (d *DiscoveryService) DiscoverDevice(name string) (*Device, error) func (d *DiscoveryService) GetCachedDevices() []Device func (d *DiscoveryService) ClearCache() // SSDP/UPnP implementation func (d *DiscoveryService) sendMSearch() error func (d *DiscoveryService) parseResponse(response string) (*Device, error) ``` #### 3. Typsichere XML Models (`pkg/models`) ```go // Base XML response with error handling type XMLResponse struct { XMLName xml.Name `xml:",innerxml"` Error *APIError `xml:"error,omitempty"` } type APIError struct { Code string `xml:"code,attr"` Message string `xml:",innerxml"` } // Device Info type DeviceInfo struct { XMLResponse XMLName xml.Name `xml:"info"` DeviceID string `xml:"deviceID,attr"` Name string `xml:"name"` Type string `xml:"type"` Components []string `xml:"components>component"` // ... additional fields } // Now Playing with complete structure type NowPlaying struct { XMLResponse XMLName xml.Name `xml:"nowPlaying"` DeviceID string `xml:"deviceID,attr"` Source string `xml:"source,attr"` Content ContentItem `xml:"ContentItem"` Track string `xml:"track"` Artist string `xml:"artist"` Album string `xml:"album"` Art Art `xml:"art"` PlayStatus PlayStatus `xml:"playStatus"` Position Position `xml:"position,omitempty"` } // Enum types with validation type PlayStatus string const ( PlayStatusPlaying PlayStatus = "PLAY_STATE" PlayStatusPaused PlayStatus = "PAUSE_STATE" PlayStatusStopped PlayStatus = "STOP_STATE" ) type Key string const ( KeyPlay Key = "PLAY" KeyPause Key = "PAUSE" KeyStop Key = "STOP" KeyPrevTrack Key = "PREV_TRACK" KeyNextTrack Key = "NEXT_TRACK" KeyVolumeUp Key = "VOLUME_UP" KeyVolumeDown Key = "VOLUME_DOWN" KeyMute Key = "MUTE" KeyPower Key = "POWER" KeyPreset1 Key = "PRESET_1" KeyPreset2 Key = "PRESET_2" KeyPreset3 Key = "PRESET_3" KeyPreset4 Key = "PRESET_4" KeyPreset5 Key = "PRESET_5" KeyPreset6 Key = "PRESET_6" ) ``` #### 4. WebSocket Event Client (`pkg/websocket`) ```go type EventClient struct { client *client.Client conn *websocket.Conn handlers map[string]EventHandler stopChan chan bool reconnect bool backoff time.Duration maxBackoff time.Duration } type EventHandler func(event Event) type Event struct { Type string `xml:"type,attr"` DeviceID string `xml:"deviceID,attr"` Data interface{} `xml:",innerxml"` Timestamp time.Time `json:"timestamp"` } func NewEventClient(client *client.Client) *EventClient func (e *EventClient) Subscribe(eventType string, handler EventHandler) func (e *EventClient) Unsubscribe(eventType string) func (e *EventClient) Start() error func (e *EventClient) Stop() error func (e *EventClient) IsConnected() bool // Event types const ( EventNowPlayingUpdated = "nowPlayingUpdated" EventVolumeUpdated = "volumeUpdated" EventConnectionState = "connectionStateUpdated" EventPresetUpdated = "presetUpdated" ) ``` #### 5. WASM JavaScript Bridge (`pkg/wasm`) ```go //go:build wasm // +build wasm import "syscall/js" // Global WASM API registration func RegisterWASMFunctions() // Device Discovery (via proxy) func wasmDiscoverDevices(this js.Value, args []js.Value) interface{} // Client Management func wasmCreateClient(this js.Value, args []js.Value) interface{} func wasmGetNowPlaying(this js.Value, args []js.Value) interface{} func wasmSendKey(this js.Value, args []js.Value) interface{} func wasmSetVolume(this js.Value, args []js.Value) interface{} func wasmGetSources(this js.Value, args []js.Value) interface{} // Event Streaming func wasmStartEventStream(this js.Value, args []js.Value) interface{} func wasmStopEventStream(this js.Value, args []js.Value) interface{} ``` #### 6. Configuration Management (`pkg/config`) ```go type Config struct { // Server configuration WebPort int `env:"WEB_PORT" default:"8080"` APITimeout time.Duration `env:"API_TIMEOUT" default:"10s"` // Discovery configuration DiscoveryTimeout time.Duration `env:"DISCOVERY_TIMEOUT" default:"5s"` CacheDevices bool `env:"CACHE_DEVICES" default:"true"` CacheTTL time.Duration `env:"CACHE_TTL" default:"5m"` // CORS configuration (for web proxy) CORSOrigins []string `env:"CORS_ORIGINS" default:"*"` // Logging LogLevel string `env:"LOG_LEVEL" default:"info"` LogFormat string `env:"LOG_FORMAT" default:"json"` // Development DevMode bool `env:"DEV_MODE" default:"false"` } func Load() Config func LoadFromFile(filename string) (Config, error) func (c Config) Validate() error ``` ## Implementation Roadmap (Updated) ### Phase 1: Foundation & Core API ⭐ ✅ COMPLETE - [x] Go module setup with modern dependencies - [x] **HTTP Client with XML Support** ✅ DONE - [x] Basic client structure - [x] GET/POST methods with XML marshaling - [x] Error handling for HTTP + XML - [x] Timeout and retry logic - [x] **Core XML models** ✅ DONE - [x] DeviceInfo - Device information endpoint - [x] NowPlaying - Current playback status endpoint - [x] Sources - Available audio sources endpoint - [x] Name - Device name endpoint - [x] Capabilities - Device capabilities endpoint - [x] Presets - Configured presets endpoint - [x] Key - Media control commands endpoint - [x] Volume - Volume control endpoints - [x] Custom XML unmarshaling for enums - [x] Validation and defaults - [x] **Media Controls** ✅ DONE - [x] POST /key endpoint implementation - [x] Press + Release key pattern (API compliant) - [x] Play, pause, stop, track navigation - [x] Volume up/down via keys - [x] Preset selection (1-6) - [x] Key validation and error handling - [x] **Volume Management** ✅ DONE - [x] GET /volume endpoint - [x] POST /volume endpoint - [x] Incremental volume control - [x] Volume level validation and clamping - [x] Safety features and warnings - [x] **Enhanced CLI tool** ✅ DONE - [x] Host:port parsing (host:8090 format) - [x] Device discovery via UPnP - [x] All informational endpoints - [x] Media control commands - [x] Volume management with safety - [x] Comprehensive help and examples - [x] **Unit tests with mocks** ✅ DONE - [x] HTTP client tests - [x] XML parsing tests - [x] Key control tests - [x] Volume control tests - [x] Host:port parsing tests - [x] Mock responses with real device data ### Phase 2: Device Discovery & Management ✅ COMPLETE - [x] **UPnP SSDP Discovery** ✅ DONE - [x] M-SEARCH implementation - [x] Response parsing - [x] Device caching with TTL - [x] **CLI Device Selection** ✅ DONE - [x] Automatic discovery - [x] Host:port parsing enhancement - [x] Configuration-based device lists - [x] **Integration Tests** ✅ DONE - [x] Tests against real SoundTouch devices (SoundTouch 10 & 20) - [x] Comprehensive real device validation - [x] **Error Handling & Logging** ✅ DONE - [x] Structured error messages - [x] Graceful error handling - [x] Network timeout management ### Phase 3: Additional Control Endpoints 🎛️ ✅ COMPLETE - [x] **Source Management** ✅ DONE - POST /select - Switch audio sources - Source validation and error handling - Convenience methods (SelectSpotify, SelectBluetooth, etc.) - [x] **Bass Control** ✅ DONE - GET /bass - Get bass settings - POST /bass - Set bass level (-9 to +9) - Range validation and safety features - Incremental bass control methods - [x] **Balance Control** ✅ DONE - GET/POST /balance - Stereo balance (-50 to +50) - Balance adjustment with clamping - Left/right convenience methods - [x] **Preset Management (Complete)** ✅ DONE - Complete preset analysis and helper methods - ✅ Implemented `/storePreset` and `/removePreset` endpoints (discovered via [SoundTouch Plus Wiki](https://github.com/thlucas1/homeassistantcomponent_soundtouchplus/wiki/SoundTouch-WebServices-API)) - Full CRUD operations: Create, Read, Update, Delete presets - CLI commands: `preset store`, `preset store-current`, `preset remove` - Note: Official docs marked POST /presets as "N/A" but working endpoints found via community documentation - [x] **System Features** ✅ DONE - GET/POST /clockTime - Device time management - GET/POST /clockDisplay - Clock display settings - GET /networkInfo - Network diagnostics - GET /name, POST /name - Device name management - GET /bassCapabilities - Bass capability detection ### Phase 4: WebSocket Real-time Events 📡 ✅ COMPLETE - [x] **Implement WebSocket Client** ✅ DONE - Connection Management - Event parsing and routing - Reconnection with exponential backoff - Automatic connection recovery - [x] **Event Handler System** ✅ DONE - 12 typed event structs (NowPlayingUpdated, VolumeUpdated, etc.) - Handler Registration and callback system - Event Filtering and routing - Comprehensive event type coverage - [x] **CLI Real-time Monitoring** ✅ DONE - Live Now-Playing Updates - Volume Change Monitoring - Connection Status Display - Real-time event streaming with formatted output - [x] **Event Management** ✅ DONE - Event logging for debugging - Connection state monitoring - Error handling and recovery ### Phase 5: Multiroom Zone Management 🏠 ✅ COMPLETE - [x] **Zone Information** ✅ DONE - GET /getZone - Retrieve zone configuration - Zone status and membership queries - Master/slave device identification - [x] **Zone Operations** ✅ DONE - POST /setZone - Create and modify zones - Zone creation with multiple devices - Add/remove devices from existing zones - Dissolve zones completely - [x] **Zone Management API** ✅ DONE - CreateZone(), AddToZone(), RemoveFromZone() - IP validation and duplicate detection - Comprehensive error handling - Zone builder with fluent API - [x] **Low-Level Zone API** ✅ DONE - POST /addZoneSlave - Individual slave addition - POST /removeZoneSlave - Individual slave removal - Direct device ID and IP-based operations ### Phase 6: Advanced Audio Controls 🎛️ ✅ COMPLETE - [x] **DSP Audio Controls** ✅ DONE - GET/POST /audiodspcontrols - DSP settings and audio modes - Video sync delay adjustment - Audio mode switching (movie, music, etc.) - [x] **Advanced Tone Controls** ✅ DONE - GET/POST /audioproducttonecontrols - Advanced bass/treble - Professional-grade audio adjustment - Device capability detection - [x] **Speaker Level Controls** ✅ DONE - GET/POST /audioproductlevelcontrols - Individual speaker levels - Front-center and rear-surround adjustment - Multi-channel audio management ### Phase 7: Web Application & CORS Proxy 🌐 (Future Enhancement) - [ ] **Create Embedded Web UI** - HTML/CSS/JS for SoundTouch control - Responsive design for mobile - Real-time Updates via WebSocket - [ ] **CORS-Proxy Server** - HTTP proxy to local SoundTouch devices - WebSocket proxy for events - CORS Header Management - [ ] **Single Binary with Embedded Assets** - go:embed for web assets - Static File Serving - SPA Routing Support - [ ] **Web-UI Features** - Device Discovery & Selection - Now playing display with album art - Volume & Bass Controls - Source Selection - Preset Management ### Phase 8: WASM Browser Integration 🧩 (Future Enhancement) - [ ] **WASM Build Configuration** - Build tags and conditional compilation - WASM-specific HTTP client (via proxy) - JavaScript Promise Integration - [ ] **WASM JavaScript Bridge** - Go function export to JavaScript - Asynchronous API calls - Error handling via promise rejection - [ ] **Browser Demo Application** - Pure Frontend SoundTouch Control - Local Network Device Discovery (via Proxy) - Real-time Event Updates - [ ] **Cross-Origin Solutions** - Local proxy server for development - Browser Extension Support - Documentation for CORS issues ### Phase 9: Production Features & Polish 🚀 (Future Enhancement) - [ ] **Advanced Configuration** - Environment-based Config - Configuration File Support - Runtime Configuration Updates - [ ] **Multi-Device Support** - Multiple Device Connections - Device Groups/Zones - Synchronized Operations - [ ] **Preset & Source Management** - Preset Backup/Restore - Custom Source Integration - Playlist Management - [ ] **Performance Optimizations** - Connection Pooling - Request Caching - Lazy Loading - [ ] **Documentation & Examples** - Comprehensive API Documentation - Usage examples for all use cases - Best Practices Guide ## Build System Based on Modern Patterns ### Makefile with Multi-Target Support ```makefile BINARY_NAME=soundtouch VERSION?=$(shell git describe --tags --always --dirty 2>/dev/null || echo "dev") BUILD_TIME=$(shell date -u '+%Y-%m-%d_%H:%M:%S') GO_VERSION=$(shell go version | cut -d ' ' -f 3) LDFLAGS=-ldflags "-X main.Version=$(VERSION) -X main.BuildTime=$(BUILD_TIME) -X main.GoVersion=$(GO_VERSION)" BUILD_FLAGS=-trimpath $(LDFLAGS) # Development builds build: go build $(BUILD_FLAGS) -o $(BINARY_NAME) ./cmd/cli build-webapp: go build $(BUILD_FLAGS) -o $(BINARY_NAME)-webapp ./cmd/webapp # WASM build build-wasm: GOOS=js GOARCH=wasm go build $(BUILD_FLAGS) -o web/soundtouch.wasm ./cmd/wasm cp "$(shell go env GOROOT)/misc/wasm/wasm_exec.js" web/ # Cross-platform builds build-all: build-linux build-darwin build-windows # Development with hot reload dev-cli: air -c .air-cli.toml dev-webapp: air -c .air-webapp.toml dev-wasm: air -c .air-wasm.toml # Testing test: go test -v -race ./... test-coverage: go test -v -coverprofile=coverage.out ./... go tool cover -html=coverage.out -o coverage.html # Quality checks check: fmt vet lint test # Docker development environment docker-dev: docker compose up --build # Release packaging release: build-all mkdir -p dist tar -czf dist/$(BINARY_NAME)-$(VERSION)-linux-amd64.tar.gz $(BINARY_NAME)-linux-amd64 tar -czf dist/$(BINARY_NAME)-$(VERSION)-darwin-amd64.tar.gz $(BINARY_NAME)-darwin-amd64 zip dist/$(BINARY_NAME)-$(VERSION)-windows-amd64.zip $(BINARY_NAME)-windows-amd64.exe ``` ## Technical Solution Approaches (Updated) ### WASM Browser Integration 1. **CORS Proxy Pattern**: Go web app as proxy between browser and SoundTouch devices 2. **Local Development Server**: CORS headers for local development 3. **WebSocket Proxy**: Real-time events via secure WebSocket connection 4. **Graceful Degradation**: Functionality depending on browser environment ### XML API Robustness 1. **Type-Safe Models**: Strict Go structs with validation 2. **Custom Unmarshaling**: Enum validation and error recovery 3. **Timeout Handling**: Robust network calls with retry logic 4. **Connection Pooling**: Efficient HTTP client reuse ### Multi-Platform Deployment 1. **Single Binary**: Embedded assets eliminate external dependencies 2. **Cross-Compilation**: Native binaries for all platforms 3. **Docker Support**: Containerized development and deployment 4. **Progressive Enhancement**: CLI → WebApp → WASM depending on requirements ## Example Usage (Updated) ### Native Go Library ```go package main import ( "fmt" "log" "time" "github.com/gesellix/bose-soundtouch/pkg/client" "github.com/gesellix/bose-soundtouch/pkg/discovery" "github.com/gesellix/bose-soundtouch/pkg/models" ) func main() { // Discover devices discoveryService := discovery.NewDiscoveryService(5 * time.Second) devices, err := discoveryService.DiscoverDevices() if err != nil { log.Fatal(err) } if len(devices) == 0 { log.Fatal("No SoundTouch devices found") } // Create client for first device client := client.NewClient(client.ClientConfig{ Host: devices[0].Host, Port: 8090, Timeout: 10 * time.Second, }) // Get device info info, err := client.GetDeviceInfo() if err != nil { log.Fatal(err) } fmt.Printf("Connected to: %s\n", info.Name) // Get current playback nowPlaying, err := client.GetNowPlaying() if err != nil { log.Fatal(err) } if nowPlaying.PlayStatus == models.PlayStatusPlaying { fmt.Printf("Playing: %s - %s (%s)\n", nowPlaying.Artist, nowPlaying.Track, nowPlaying.Album) } // Control playback if nowPlaying.PlayStatus == models.PlayStatusPlaying { client.SendKey(models.KeyPause) fmt.Println("Paused playback") } else { client.SendKey(models.KeyPlay) fmt.Println("Started playback") } } ``` ### CLI Usage ```bash # Discover devices soundtouch discover # Device operations soundtouch --device 192.0.2.100 info soundtouch --device 192.0.2.100 play soundtouch --device 192.0.2.100 volume 50 soundtouch --device 192.0.2.100 preset 1 # Interactive mode soundtouch interactive # Web interface soundtouch-playerapp --port 8080 ``` ### JavaScript/WASM Usage ```javascript // Load WASM module await loadWASM('/soundtouch.wasm'); // Discover devices (via proxy) const devices = await boseAPI.discoverDevices(); console.log('Found devices:', devices); // Create client const client = boseAPI.createClient(devices[0].host, 8090); // Get now playing const nowPlaying = await client.getNowPlaying(); console.log(`Playing: ${nowPlaying.artist} - ${nowPlaying.track}`); // Control playback await client.sendKey('PAUSE'); // Volume control await client.setVolume(75); // Real-time events client.startEventStream((event) => { if (event.type === 'nowPlayingUpdated') { updateUI(event.data); } }); ``` ## Testing Strategy (Enhanced) ### Unit Tests - **Mock HTTP Client**: Simulierte SoundTouch-Responses - **XML Parsing Tests**: Robustness für verschiedene Response-Formate - **Model Validation**: Enum-Validation und Edge-Cases - **Error Handling**: Network Failures und API Errors ### Integration Tests - **Real Device Tests**: Gegen echte SoundTouch-Hardware - **Docker Mock Server**: Simulierte SoundTouch-API für CI/CD - **Discovery Tests**: UPnP SSDP in verschiedenen Netzwerk-Szenarien - **WebSocket Tests**: Event-Streaming und Reconnection ### E2E Tests - **CLI Tests**: Command-Line Interface Validation - **Web Interface Tests**: Browser-basierte Tests mit Headless Chrome - **WASM Tests**: Browser WASM Module Loading und Execution - **Cross-Platform Tests**: Builds auf Linux/macOS/Windows ## Deployment Strategies ### Single Binary Distribution ```bash # CLI Tool ./soundtouch-linux-amd64 discover ./soundtouch-linux-amd64 --device IP play # Web Application (embedded assets) ./soundtouch-playerapp-linux-amd64 --port 8080 # Docker docker run -p 8080:8080 soundtouch-playerapp ``` ### Development Environment ```bash # Local development with hot reload make dev-webapp # Web app development make dev-wasm # WASM development make dev-cli # CLI development # Full development environment docker compose up # Mock devices + web app ``` ## Success Criteria ### Phase 1-2 (Foundation) ✅ COMPLETE - ✅ Stable HTTP API connection to SoundTouch devices - ✅ XML model coverage for all core APIs (DeviceInfo, NowPlaying, Sources, Name, Capabilities, Presets, Volume, Key controls) - ✅ Automatic device discovery via UPnP and mDNS - ✅ Comprehensive CLI tool with all endpoint commands - ✅ Media controls with proper press+release key patterns - ✅ Volume management with safety features - ✅ Real device validation on SoundTouch 10 and 20 ### Phase 3-4 (Audio Controls & Real-time Events) ✅ COMPLETE - ✅ Source selection with convenience methods (Spotify, Bluetooth, etc.) - ✅ Bass control with range validation (-9 to +9) - ✅ Balance control for stereo devices (-50 to +50) - ✅ Clock and display management (time, brightness, format) - ✅ Network information retrieval - ✅ WebSocket event streaming with 12 event types - ✅ Automatic reconnection and connection management ### Phase 5-6 (Multiroom & Advanced Audio) ✅ COMPLETE - ✅ Complete multiroom zone management (create, modify, dissolve) - ✅ Zone status and membership queries - ✅ Advanced audio controls (DSP, tone, speaker levels) - ✅ Professional-grade audio adjustment features - ✅ Device capability detection and validation ### Phase 7+ (Future Enhancements) - ✅ WASM integration with JavaScript bridge - ✅ Multi-Device Support - ✅ Production-ready Configuration Management - ✅ Comprehensive documentation and examples ## Resources & References - [Bose SoundTouch Web API Documentation](https://assets.bosecreative.com/m/496577402d128874/original/SoundTouch-Web-API.pdf) - [Go WebAssembly](https://github.com/golang/go/wiki/WebAssembly) - [UPnP Device Architecture](http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.0.pdf) - [Go Embed Directive](https://pkg.go.dev/embed) - [Gorilla WebSocket](https://github.com/gorilla/websocket) - [PROJECT-PATTERNS.md](../content/docs/appendix/PROJECT-PATTERNS.md) - Detailed pattern documentation