Files
Tobias GesellchenandClaude Opus 4.8 bd62fd6658 refactor: rename soundtouch-web to soundtouch-player (transitional alias) (refs #451)
The web player is intrinsically LAN-resident: it reaches speakers directly
and only delegates cloud-only features (e.g. TTS) to a possibly-remote
AfterTouch service via --service-url. That is exactly what a cloud-hosted
soundtouch-service cannot do, so the standalone player binary stays useful
and is not being deprecated. Rename it to state its purpose, with a
transition window so existing downloads keep working.

- cmd/soundtouch-web -> cmd/soundtouch-player; CLI name is now
  soundtouch-player. When the binary is invoked under its old name it prints
  a one-line rename notice (filepath.Base(os.Args[0])).
- Build/release both names from the same source: Makefile (build-player +
  build-web alias, dev-player* targets), Dockerfile (soundtouch-player image
  + transitional soundtouch-web image), release.yml and ci.yml (player +
  web artifacts, checksums, Docker images; release notes announce the
  rename). The soundtouch-web binary, image, and install script remain a
  transitional alias to be dropped in a future release (which will break
  stale fetch scripts and nudge users to the release notes).
- scripts/raspberry-pi/install-player.sh is canonical; install-web.sh keeps
  working but warns.
- Sweep docs, code comments, user-facing strings, and assets
  (soundtouch-web-ui.png, soundtouch-web-tunein.png, soundtouch-web-roadmap.md)
  to soundtouch-player; README documents the rename and why the player
  remains separate from the embedded /app.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 16:33:39 +02:00

26 KiB

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)

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)

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)

// 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)

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: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)

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

  • Go module setup with modern dependencies
  • HTTP Client with XML Support DONE
    • Basic client structure
    • GET/POST methods with XML marshaling
    • Error handling for HTTP + XML
    • Timeout and retry logic
  • Core XML models DONE
    • DeviceInfo - Device information endpoint
    • NowPlaying - Current playback status endpoint
    • Sources - Available audio sources endpoint
    • Name - Device name endpoint
    • Capabilities - Device capabilities endpoint
    • Presets - Configured presets endpoint
    • Key - Media control commands endpoint
    • Volume - Volume control endpoints
    • Custom XML unmarshaling for enums
    • Validation and defaults
  • Media Controls DONE
    • POST /key endpoint implementation
    • Press + Release key pattern (API compliant)
    • Play, pause, stop, track navigation
    • Volume up/down via keys
    • Preset selection (1-6)
    • Key validation and error handling
  • Volume Management DONE
    • GET /volume endpoint
    • POST /volume endpoint
    • Incremental volume control
    • Volume level validation and clamping
    • Safety features and warnings
  • Enhanced CLI tool DONE
    • Host:port parsing (host:8090 format)
    • Device discovery via UPnP
    • All informational endpoints
    • Media control commands
    • Volume management with safety
    • Comprehensive help and examples
  • Unit tests with mocks DONE
    • HTTP client tests
    • XML parsing tests
    • Key control tests
    • Volume control tests
    • Host:port parsing tests
    • Mock responses with real device data

Phase 2: Device Discovery & Management COMPLETE

  • UPnP SSDP Discovery DONE
    • M-SEARCH implementation
    • Response parsing
    • Device caching with TTL
  • CLI Device Selection DONE
    • Automatic discovery
    • Host:port parsing enhancement
    • Configuration-based device lists
  • Integration Tests DONE
    • Tests against real SoundTouch devices (SoundTouch 10 & 20)
    • Comprehensive real device validation
  • Error Handling & Logging DONE
    • Structured error messages
    • Graceful error handling
    • Network timeout management

Phase 3: Additional Control Endpoints 🎛️ COMPLETE

  • Source Management DONE
    • POST /select - Switch audio sources
    • Source validation and error handling
    • Convenience methods (SelectSpotify, SelectBluetooth, etc.)
  • 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
  • Balance Control DONE
    • GET/POST /balance - Stereo balance (-50 to +50)
    • Balance adjustment with clamping
    • Left/right convenience methods
  • Preset Management (Complete) DONE
    • Complete preset analysis and helper methods
    • Implemented /storePreset and /removePreset endpoints (discovered via SoundTouch Plus Wiki)
    • 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
  • 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

  • Implement WebSocket Client DONE
    • Connection Management
    • Event parsing and routing
    • Reconnection with exponential backoff
    • Automatic connection recovery
  • Event Handler System DONE
    • 12 typed event structs (NowPlayingUpdated, VolumeUpdated, etc.)
    • Handler Registration and callback system
    • Event Filtering and routing
    • Comprehensive event type coverage
  • CLI Real-time Monitoring DONE
    • Live Now-Playing Updates
    • Volume Change Monitoring
    • Connection Status Display
    • Real-time event streaming with formatted output
  • Event Management DONE
    • Event logging for debugging
    • Connection state monitoring
    • Error handling and recovery

Phase 5: Multiroom Zone Management 🏠 COMPLETE

  • Zone Information DONE
    • GET /getZone - Retrieve zone configuration
    • Zone status and membership queries
    • Master/slave device identification
  • Zone Operations DONE
    • POST /setZone - Create and modify zones
    • Zone creation with multiple devices
    • Add/remove devices from existing zones
    • Dissolve zones completely
  • Zone Management API DONE
    • CreateZone(), AddToZone(), RemoveFromZone()
    • IP validation and duplicate detection
    • Comprehensive error handling
    • Zone builder with fluent API
  • 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

  • DSP Audio Controls DONE
    • GET/POST /audiodspcontrols - DSP settings and audio modes
    • Video sync delay adjustment
    • Audio mode switching (movie, music, etc.)
  • Advanced Tone Controls DONE
    • GET/POST /audioproducttonecontrols - Advanced bass/treble
    • Professional-grade audio adjustment
    • Device capability detection
  • 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

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

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

# 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

// 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

# 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

# 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