From 46b7f3c6e75d19415f866c3f49ab86af9d5a0ab9 Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Fri, 9 Jan 2026 10:24:32 +0100 Subject: [PATCH] feat: Add system endpoints for clock/time management and network info - Implement GET/POST /clockTime endpoints for device time management - Implement GET/POST /clockDisplay endpoints for clock display configuration - Implement GET /networkInfo endpoint with real API structure - Add comprehensive models for ClockTime, ClockDisplay, and NetworkInformation - Update NetworkInformation to match real SoundTouch API responses: * WiFi interfaces with SSID, frequency, signal strength, and connection state * Ethernet interfaces with connection state * Proper attribute-based XML structure matching actual device responses - Add CLI support for all system endpoints with detailed output formatting - Add comprehensive test coverage for all new models and client methods - Update documentation to reflect real API structure and capabilities - Anonymize all personal data (IP addresses, device IDs, device names) - Add SYSTEM-ENDPOINTS.md documentation with real-world examples Features: - Clock time sync with current system time or specific timestamps - Clock display configuration (enable/disable, format, brightness, auto-dim) - Rich network interface information with WiFi signal quality and frequency bands - Support for both WiFi and Ethernet SoundTouch devices - Validated against real SoundTouch 10 and SoundTouch 20 device responses All tests pass and builds successfully. --- ANONYMIZATION-SUMMARY.md | 115 +++ Makefile | 4 +- README.md | 105 +-- cmd/soundtouch-cli/main.go | 411 ++++++++++- cmd/soundtouch-cli/main_test.go | 46 +- docs/API-Endpoints-Overview.md | 10 +- docs/BASS-CONTROLS.md | 2 +- docs/HOST-PORT-PARSING.md | 4 +- docs/KEY-CONTROLS.md | 4 +- docs/STATUS.md | 2 +- docs/SYSTEM-ENDPOINTS.md | 549 ++++++++++++++ docs/VOLUME-CONTROLS.md | 8 +- pkg/client/balance_test.go | 24 +- pkg/client/bass_test.go | 22 +- pkg/client/client.go | 90 +++ pkg/client/client_test.go | 16 +- pkg/client/system_test.go | 577 +++++++++++++++ pkg/client/testdata/capabilities_response.xml | 2 +- pkg/client/testdata/clockdisplay_response.xml | 2 + pkg/client/testdata/clocktime_response.xml | 2 + pkg/client/testdata/info_response.xml | 12 +- pkg/client/testdata/info_response_st20.xml | 10 +- pkg/client/testdata/name_response.xml | 2 +- .../networkinfo_ethernet_response.xml | 6 + pkg/client/testdata/networkinfo_response.xml | 7 + pkg/models/clockdisplay.go | 177 +++++ pkg/models/clockdisplay_test.go | 641 +++++++++++++++++ pkg/models/clocktime.go | 121 ++++ pkg/models/clocktime_test.go | 384 ++++++++++ pkg/models/networkinfo.go | 365 ++++++++++ pkg/models/networkinfo_test.go | 681 ++++++++++++++++++ 31 files changed, 4245 insertions(+), 156 deletions(-) create mode 100644 ANONYMIZATION-SUMMARY.md create mode 100644 docs/SYSTEM-ENDPOINTS.md create mode 100644 pkg/client/system_test.go create mode 100644 pkg/client/testdata/clockdisplay_response.xml create mode 100644 pkg/client/testdata/clocktime_response.xml create mode 100644 pkg/client/testdata/networkinfo_ethernet_response.xml create mode 100644 pkg/client/testdata/networkinfo_response.xml create mode 100644 pkg/models/clockdisplay.go create mode 100644 pkg/models/clockdisplay_test.go create mode 100644 pkg/models/clocktime.go create mode 100644 pkg/models/clocktime_test.go create mode 100644 pkg/models/networkinfo.go create mode 100644 pkg/models/networkinfo_test.go diff --git a/ANONYMIZATION-SUMMARY.md b/ANONYMIZATION-SUMMARY.md new file mode 100644 index 0000000..2057ed7 --- /dev/null +++ b/ANONYMIZATION-SUMMARY.md @@ -0,0 +1,115 @@ +# Data Anonymization Summary + +This document summarizes all changes made to anonymize personal and specific data throughout the Bose SoundTouch Go client codebase. + +## Overview + +All specific IP addresses, device IDs, device names, and other potentially personal information have been replaced with generic, example values to protect privacy while maintaining the functionality and usefulness of the documentation and test examples. + +## Changes Made + +### IP Addresses + +**Original → Anonymized:** +- `192.168.1.35` → `192.168.1.10` +- `192.168.1.100` → `192.168.1.10` +- `192.168.1.100` → `192.168.1.10` +- `192.168.1.101` → `192.168.1.11` +- `192.168.1.102` → `192.168.1.12` + +### Device IDs + +**Original → Anonymized:** +- `A81B6A536A98` → `ABCD1234EFGH` +- `1234567890AB` → `ABCD1234EFGH` +- `1234567890AC` → `ABCD1234EFGH` + +### Device Names + +**Original → Anonymized:** +- `Sound Machinechen` → `My SoundTouch Device` + +### MAC Addresses + +**Original → Anonymized:** +- `A81B6A536A98` → `AA:BB:CC:DD:EE:FF` +- `A81B6A849D99` → `AA:BB:CC:DD:EE:FF` +- `A8:1B:6A:53:6A:98` → `AA:BB:CC:DD:EE:FF` +- `A8:1B:6A:84:9D:99` → `AA:BB:CC:DD:EE:01` + +## Files Modified + +### Documentation Files +- `README.md` - Updated all IP addresses and device examples +- `Makefile` - Updated example IP addresses in help text +- `docs/SYSTEM-ENDPOINTS.md` - Anonymized all example data +- `docs/VOLUME-CONTROLS.md` - Updated device IDs and IP addresses +- `docs/KEY-CONTROLS.md` - Updated IP addresses +- `docs/BASS-CONTROLS.md` - Updated device IDs +- `docs/HOST-PORT-PARSING.md` - Updated IP addresses and device names +- `docs/STATUS.md` - Updated IP addresses + +### Source Code Files +- `cmd/soundtouch-cli/main.go` - Updated all example IP addresses in help text +- `cmd/soundtouch-cli/main_test.go` - Updated test IP addresses + +### Test Data Files +- `pkg/client/testdata/info_response.xml` - Updated device ID, name, and network info +- `pkg/client/testdata/info_response_st20.xml` - Updated device ID and network info +- `pkg/client/testdata/capabilities_response.xml` - Updated device ID +- `pkg/client/testdata/name_response.xml` - Updated device name +- `pkg/client/testdata/networkinfo_response.xml` - Updated device ID and network info +- `pkg/client/testdata/clockdisplay_response.xml` - Updated device ID + +### Test Files +- `pkg/client/client_test.go` - Updated device IDs, names, and IP addresses +- `pkg/client/system_test.go` - Updated device IDs and IP addresses +- `pkg/client/balance_test.go` - Updated device IDs in test responses +- `pkg/client/bass_test.go` - Updated device IDs in test responses +- `pkg/models/networkinfo_test.go` - Updated device IDs and network info + +## Anonymization Strategy + +### IP Addresses +- Used standard RFC 1918 private IP ranges (192.168.1.x) +- Maintained realistic network structure (same subnet for related devices) +- Used sequential numbering (.10, .11, .12) for clarity + +### Device IDs +- Used generic alphanumeric pattern `ABCD1234EFGH` +- Maintained consistent usage across all files +- Preserved original length and format + +### Device Names +- Used generic but descriptive names like "My SoundTouch Device" +- Removed any potentially personal identifiers + +### MAC Addresses +- Used standard placeholder format `AA:BB:CC:DD:EE:FF` +- Used sequential variants (EE:01) when multiple addresses needed +- Maintained proper MAC address format + +## Verification + +After anonymization: +- ✅ All tests continue to pass +- ✅ All builds succeed +- ✅ Documentation remains accurate and useful +- ✅ No personal data remains in examples +- ✅ Functionality is preserved + +## Benefits + +1. **Privacy Protection**: No personal network information exposed +2. **Professional Examples**: Clean, generic examples suitable for public documentation +3. **Consistency**: Uniform use of example data across all files +4. **Maintainability**: Easy to identify example vs. real data + +## Standards Used + +- **IP Addresses**: RFC 1918 private ranges (192.168.1.x/24) +- **Device IDs**: Generic alphanumeric placeholders +- **MAC Addresses**: Standard placeholder format +- **Device Names**: Generic descriptive names + +All changes maintain the original functionality while ensuring no personal or specific network information is exposed in the codebase. \ No newline at end of file diff --git a/Makefile b/Makefile index ecd4e51..8b29403 100644 --- a/Makefile +++ b/Makefile @@ -120,7 +120,7 @@ dev-discover: build-cli dev-info: build-cli @echo "Getting device info (requires -host flag)..." @if [ -z "$(HOST)" ]; then \ - echo "Usage: make dev-info HOST=192.168.1.100"; \ + echo "Usage: make dev-info HOST=192.168.1.10"; \ exit 1; \ fi $(BUILD_DIR)/$(BINARY_NAME) -host $(HOST) -info @@ -231,7 +231,7 @@ help: @echo "" @echo "Examples:" @echo " make dev-discover" - @echo " make dev-info HOST=192.168.1.100" + @echo " make dev-info HOST=192.168.1.10" @echo " make dev-mdns" @echo " make dev-mdns-verbose" @echo " make dev-mdns-timeout TIMEOUT=10s" diff --git a/README.md b/README.md index b2484b4..565092e 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,10 @@ A modern Go library and CLI tool for interacting with Bose SoundTouch devices vi - **Flexible Configuration**: Support for .env files and environment variables - **Unified Discovery**: Combines UPnP, mDNS, and configured device lists - **Safety Features**: Volume warnings, increment limits, error validation +- **System Management**: Clock/time settings, network information, device diagnostics ### 🔄 Planned - Real-time WebSocket events -- Source management (switching between Spotify, Bluetooth, etc.) -- Bass control - Preset management (create/update presets) - Web application interface - Multi-room zone support @@ -65,7 +64,7 @@ MDNS_ENABLED=true # Preferred Devices (alternative to UPnP) # Format: name@host:port;name@host:port;... -PREFERRED_DEVICES="Living Room@192.168.1.100;Kitchen@192.168.1.101;192.168.1.102:8091" +PREFERRED_DEVICES="Living Room@192.168.1.10;Kitchen@192.168.1.11;192.168.1.12:8091" # HTTP Client Settings HTTP_TIMEOUT=10s @@ -97,20 +96,20 @@ soundtouch-cli -discover -timeout 10s #### Device Information ```bash # Get device information by IP address -soundtouch-cli -host 192.168.1.100 -info +soundtouch-cli -host 192.168.1.10 -info # With custom port and timeout -soundtouch-cli -host 192.168.1.100 -port 8090 -timeout 15s -info +soundtouch-cli -host 192.168.1.10 -port 8090 -timeout 15s -info ``` #### Now Playing Status ```bash # Get current playback information -soundtouch-cli -host 192.168.1.100 -nowplaying +soundtouch-cli -host 192.168.1.10 -nowplaying # Example output: # Now Playing: -# Device ID: A81B6A536A98 +# Device ID: ABCD1234EFGH # Source: SPOTIFY # Status: Playing # Title: In Between Breaths - Paris Unplugged @@ -125,11 +124,11 @@ soundtouch-cli -host 192.168.1.100 -nowplaying #### Audio Sources ```bash # Get available audio sources -soundtouch-cli -host 192.168.1.100:8090 -sources +soundtouch-cli -host 192.168.1.10:8090 -sources # Example output: # Audio Sources: -# Device ID: A81B6A536A98 +# Device ID: ABCD1234EFGH # Total Sources: 14 # Ready Sources: 5 # @@ -149,64 +148,64 @@ soundtouch-cli -host 192.168.1.100:8090 -sources #### Media Controls ```bash # Basic playback controls -soundtouch-cli -host 192.168.1.100:8090 -play -soundtouch-cli -host 192.168.1.100:8090 -pause -soundtouch-cli -host 192.168.1.100:8090 -stop +soundtouch-cli -host 192.168.1.10:8090 -play +soundtouch-cli -host 192.168.1.10:8090 -pause +soundtouch-cli -host 192.168.1.10:8090 -stop # Track navigation -soundtouch-cli -host 192.168.1.100:8090 -next -soundtouch-cli -host 192.168.1.100:8090 -prev +soundtouch-cli -host 192.168.1.10:8090 -next +soundtouch-cli -host 192.168.1.10:8090 -prev # Volume controls (key-based) -soundtouch-cli -host 192.168.1.100:8090 -volume-up -soundtouch-cli -host 192.168.1.100:8090 -volume-down +soundtouch-cli -host 192.168.1.10:8090 -volume-up +soundtouch-cli -host 192.168.1.10:8090 -volume-down # Preset selection -soundtouch-cli -host 192.168.1.100:8090 -preset 1 -soundtouch-cli -host 192.168.1.100:8090 -preset 6 +soundtouch-cli -host 192.168.1.10:8090 -preset 1 +soundtouch-cli -host 192.168.1.10:8090 -preset 6 # Generic key command -soundtouch-cli -host 192.168.1.100:8090 -key STOP +soundtouch-cli -host 192.168.1.10:8090 -key STOP ``` #### Volume Management ```bash # Get current volume -soundtouch-cli -host 192.168.1.100:8090 -volume +soundtouch-cli -host 192.168.1.10:8090 -volume # Example output: # Current Volume: -# Device ID: A81B6A536A98 +# Device ID: ABCD1234EFGH # Current Level: 50 (Medium) # Target Level: 50 # Muted: false # Set specific volume (0-100, shows warning for >30) -soundtouch-cli -host 192.168.1.100:8090 -set-volume 25 -soundtouch-cli -host 192.168.1.100:8090 -set-volume 0 # Mute +soundtouch-cli -host 192.168.1.10:8090 -set-volume 25 +soundtouch-cli -host 192.168.1.10:8090 -set-volume 0 # Mute # Incremental volume control -soundtouch-cli -host 192.168.1.100:8090 -inc-volume 3 -soundtouch-cli -host 192.168.1.100:8090 -dec-volume 5 +soundtouch-cli -host 192.168.1.10:8090 -inc-volume 3 +soundtouch-cli -host 192.168.1.10:8090 -dec-volume 5 ``` #### Device Name ```bash # Get device name -soundtouch-cli -host 192.168.1.100 -name +soundtouch-cli -host 192.168.1.10 -name # Example output: -# Device Name: Sound Machinechen +# Device Name: My SoundTouch ``` #### Device Capabilities ```bash # Get device capabilities -soundtouch-cli -host 192.168.1.100 -capabilities +soundtouch-cli -host 192.168.1.10 -capabilities # Example output: # Device Capabilities: -# Device ID: A81B6A536A98 +# Device ID: ABCD1234EFGH # # System Features: # • Power Saving Disabled @@ -226,7 +225,7 @@ soundtouch-cli -host 192.168.1.100 -capabilities #### Configured Presets ```bash # Get configured presets -soundtouch-cli -host 192.168.1.100 -presets +soundtouch-cli -host 192.168.1.10 -presets # Example output: # Configured Presets: @@ -243,6 +242,26 @@ soundtouch-cli -host 192.168.1.100 -presets # Most Recent: Preset 4 (Movie Soundtrack) ``` +#### System Information +```bash +# Get device clock time +soundtouch-cli -host 192.168.1.10 -clock-time + +# Set device time to current system time +soundtouch-cli -host 192.168.1.10 -set-clock-time now + +# Get clock display settings +soundtouch-cli -host 192.168.1.10 -clock-display + +# Configure clock display +soundtouch-cli -host 192.168.1.10 -enable-clock +soundtouch-cli -host 192.168.1.10 -clock-format 24 +soundtouch-cli -host 192.168.1.10 -clock-brightness 75 + +# Get network information +soundtouch-cli -host 192.168.1.10 -network-info +``` + ### Go Library Usage ```go @@ -260,7 +279,7 @@ import ( func main() { // Option 1: Connect to known device - soundtouchClient := client.NewClientFromHost("192.168.1.100") + soundtouchClient := client.NewClientFromHost("192.168.1.10") deviceInfo, err := soundtouchClient.GetDeviceInfo() if err != nil { @@ -396,7 +415,7 @@ go test -v ./pkg/client go test -v ./pkg/discovery # Test with real devices -make dev-info HOST=192.168.1.100 +make dev-info HOST=192.168.1.10 # Test device discovery make dev-discover @@ -432,8 +451,12 @@ The SoundTouch Web API uses HTTP with XML payloads. Key endpoints include: - `GET /sources` - Available audio sources ✅ Implemented - `POST /key` - Send key commands (play, pause, etc.) ✅ Implemented - `GET/POST /volume` - Volume control ✅ Implemented -- `POST /select` - Source selection -- `GET/POST /bass` - Bass control +- `GET/POST /bass` - Bass control ✅ Implemented +- `GET/POST /balance` - Stereo balance control ✅ Implemented +- `POST /select` - Source selection ✅ Implemented +- `GET/POST /clockTime` - Device time management ✅ Implemented +- `GET/POST /clockDisplay` - Clock display settings ✅ Implemented +- `GET /networkInfo` - Network information ✅ Implemented - WebSocket `/` - Real-time event stream For complete API documentation, see: @@ -462,16 +485,16 @@ The `PREFERRED_DEVICES` environment variable supports multiple formats: ```bash # Host only (uses default port 8090) -PREFERRED_DEVICES="192.168.1.100" +PREFERRED_DEVICES="192.168.1.10" # Host with port -PREFERRED_DEVICES="192.168.1.100:8091" +PREFERRED_DEVICES="192.168.1.10:8091" # Named device -PREFERRED_DEVICES="Living Room@192.168.1.100" +PREFERRED_DEVICES="Living Room@192.168.1.10" # Multiple devices -PREFERRED_DEVICES="Living Room@192.168.1.100;Kitchen@192.168.1.101:8091" +PREFERRED_DEVICES="Living Room@192.168.1.10;Kitchen@192.168.1.11:8091" ``` ## Supported Devices @@ -486,8 +509,8 @@ Should work with all SoundTouch series devices that support the Web API. ### SoundTouch 10 Response ```xml - - Sound Machinechen + + My SoundTouch Device SoundTouch 10 sm2 rhino @@ -502,7 +525,7 @@ Should work with all SoundTouch series devices that support the Web API. ### SoundTouch 20 Response ```xml - + My SoundTouch Device SoundTouch 20 scm diff --git a/cmd/soundtouch-cli/main.go b/cmd/soundtouch-cli/main.go index 14ed672..4968d7b 100644 --- a/cmd/soundtouch-cli/main.go +++ b/cmd/soundtouch-cli/main.go @@ -83,6 +83,14 @@ func main() { spotify = flag.Bool("spotify", false, "Select Spotify source") bluetooth = flag.Bool("bluetooth", false, "Select Bluetooth source") aux = flag.Bool("aux", false, "Select AUX input source") + clockTime = flag.Bool("clock-time", false, "Get device clock time") + setClockTime = flag.String("set-clock-time", "", "Set device clock time (format: 'now' or Unix timestamp)") + clockDisplay = flag.Bool("clock-display", false, "Get clock display settings") + enableClock = flag.Bool("enable-clock", false, "Enable clock display") + disableClock = flag.Bool("disable-clock", false, "Disable clock display") + clockFormat = flag.String("clock-format", "", "Set clock display format (12, 24, auto)") + clockBright = flag.Int("clock-brightness", -1, "Set clock display brightness (0-100)") + networkInfo = flag.Bool("network-info", false, "Get network information") help = flag.Bool("help", false, "Show help") ) @@ -94,7 +102,7 @@ func main() { } // If no specific action is requested, show help - if !*discover && !*discoverAll && !*info && !*nowPlaying && !*sources && !*name && !*capabilities && !*presets && *key == "" && !*play && !*pause && !*stop && !*next && !*prev && !*volumeUp && !*volumeDown && !*power && !*mute && !*thumbsUp && !*thumbsDown && *preset == 0 && !*volume && *setVolume == -1 && *incVolume == 0 && *decVolume == 0 && !*bass && *setBass == -99 && *incBass == 0 && *decBass == 0 && !*balance && *setBalance == -99 && *incBalance == 0 && *decBalance == 0 && *selectSource == "" && !*spotify && !*bluetooth && !*aux && *host == "" { + if !*discover && !*discoverAll && !*info && !*nowPlaying && !*sources && !*name && !*capabilities && !*presets && *key == "" && !*play && !*pause && !*stop && !*next && !*prev && !*volumeUp && !*volumeDown && !*power && !*mute && !*thumbsUp && !*thumbsDown && *preset == 0 && !*volume && *setVolume == -1 && *incVolume == 0 && *decVolume == 0 && !*bass && *setBass == -99 && *incBass == 0 && *decBass == 0 && !*balance && *setBalance == -99 && *incBalance == 0 && *decBalance == 0 && *selectSource == "" && !*spotify && !*bluetooth && !*aux && !*clockTime && *setClockTime == "" && !*clockDisplay && !*enableClock && !*disableClock && *clockFormat == "" && *clockBright == -1 && !*networkInfo && *host == "" { printHelp() return } @@ -234,6 +242,28 @@ func main() { } return } + + // Handle clock/time commands + if *clockTime || *setClockTime != "" || *clockDisplay || *enableClock || *disableClock || *clockFormat != "" || *clockBright != -1 { + if *host == "" { + log.Fatal("Host is required for clock/time commands. Use -host flag or -discover to find devices.") + } + if err := handleClockCommands(finalHost, finalPort, *timeout, *clockTime, *setClockTime, *clockDisplay, *enableClock, *disableClock, *clockFormat, *clockBright); err != nil { + log.Fatalf("Failed to execute clock command: %v", err) + } + return + } + + // Handle network info command + if *networkInfo { + if *host == "" { + log.Fatal("Host is required for network info command. Use -host flag or -discover to find devices.") + } + if err := handleNetworkInfo(finalHost, finalPort, *timeout); err != nil { + log.Fatalf("Failed to get network info: %v", err) + } + return + } } func printHelp() { @@ -296,38 +326,56 @@ func printHelp() { fmt.Println(" -bluetooth Select Bluetooth source (requires -host)") fmt.Println(" -aux Select AUX input source (requires -host)") fmt.Println() + fmt.Println("System Information:") + fmt.Println(" -clock-time Get device clock time (requires -host)") + fmt.Println(" -set-clock-time