- Fixed HTTP method mismatch: /playNotification endpoint expects GET, not POST - Updated PlayNotificationBeep() to use existing c.get() method with StationResponse model - Resolves HTTP 400 errors when using 'soundtouch-cli sp beep' command - Verified working with SoundTouch 20 hardware - Added comprehensive troubleshooting documentation - Updated feature history with bug fix details Fixes: go run ./cmd/soundtouch-cli --host <device> sp beep Previously failed with: 'API request failed with status 400' Now works correctly alongside: curl http://<device>:8090/playNotification
18 KiB
SoundTouch Troubleshooting Guide
Complete guide to diagnosing and fixing common SoundTouch Go client issues
This guide helps you quickly identify and resolve problems with the SoundTouch Go client library. Issues are organized by category with step-by-step solutions.
🚨 Quick Diagnostics
Test Your Setup
Run these commands to quickly diagnose your setup:
# 1. Test discovery
go run ./cmd/soundtouch-cli -discover
# 2. Test specific device connection
go run ./cmd/soundtouch-cli -host 192.168.1.100 -info
# 3. Test basic controls
go run ./cmd/soundtouch-cli -host 192.168.1.100 -volume
# 4. Test network connectivity
ping 192.168.1.100
🔍 Discovery Issues
❌ "No devices found"
Symptoms:
🔍 Discovering SoundTouch devices...
❌ No devices found on the network
Causes & Solutions:
1. Network Configuration
# Check if devices are on same network
ip route show default # Your gateway
arp -a | grep -i bose # Look for Bose devices
Solution: Ensure both your computer and SoundTouch are on the same subnet.
2. Firewall Issues
# Check if firewall is blocking UPnP
sudo ufw status # Ubuntu
netsh advfirewall show allprofiles # Windows
Solution: Allow UPnP traffic (port 1900 UDP) or temporarily disable firewall.
3. Device Not Ready
- Power cycle your SoundTouch device
- Wait 30 seconds for full boot
- Check device is connected to network (solid white LED)
4. Discovery Timeout Too Short
discoverer := discovery.NewDiscoverer(discovery.Config{
Timeout: 30 * time.Second, // Increase timeout
})
5. Use Manual IP
// Bypass discovery entirely
client := client.NewClientFromHost("192.168.1.100")
❌ "Discovery timeout"
Symptoms:
🔍 Discovering SoundTouch devices (timeout: 5s)...
❌ Discovery failed: context deadline exceeded
Solutions:
- Increase timeout:
discoverer := discovery.NewDiscoverer(discovery.Config{
Timeout: 15 * time.Second,
})
- Check network performance:
# Test network latency
ping -c 4 192.168.1.1
# Check for network congestion
iperf3 -c 192.168.1.1 # If iperf server available
- Use wired connection if possible
🌐 Connection Issues
❌ "Connection refused"
Symptoms:
Failed to connect: dial tcp 192.168.1.100:8090: connection refused
Diagnostic Steps:
1. Verify IP and Port
# Test if port 8090 is open
telnet 192.168.1.100 8090
# OR
nc -zv 192.168.1.100 8090
# Scan for open ports
nmap -p 8080-8100 192.168.1.100
2. Check Device Status
- Device LED should be solid white (connected)
- Blinking white = connecting
- Red = error state
3. Router/Network Issues
# Check routing
traceroute 192.168.1.100
# Test basic connectivity
ping -c 4 192.168.1.100
❌ "Timeout" / "Context deadline exceeded"
Symptoms:
Failed to get device info: context deadline exceeded
Solutions:
1. Increase Client Timeout
config := client.ClientConfig{
Host: "192.168.1.100",
Port: 8090,
Timeout: 30 * time.Second, // Increase from default 10s
}
2. Check Network Latency
# Test response time
ping -c 10 192.168.1.100
# Should be < 100ms typically
3. Device Performance Issues
- Device may be overloaded
- Try power cycling the device
- Check for firmware updates via Bose app
❌ "No such host"
Symptoms:
Failed to connect: dial tcp: lookup soundtouch.local: no such host
Solutions:
- Use IP instead of hostname:
client := client.NewClientFromHost("192.168.1.100") // Not "soundtouch.local"
- Fix DNS/mDNS:
# Test hostname resolution
nslookup soundtouch.local
dig soundtouch.local
# Install mDNS tools if needed (Linux)
sudo apt-get install avahi-utils
avahi-resolve -n soundtouch.local
🎵 Playback Control Issues
❌ "Play/Pause not working"
Symptoms:
- Commands succeed but no audio change
- Device shows wrong status
Diagnostic Steps:
1. Check Current Status
nowPlaying, err := client.GetNowPlaying()
if err == nil {
fmt.Printf("Status: %s, Source: %s\n",
nowPlaying.PlayStatus, nowPlaying.Source)
}
2. Verify Source Selection
sources, err := client.GetSources()
if err == nil {
for _, source := range sources.Sources {
fmt.Printf("Source: %s, Status: %s\n",
source.Source, source.Status)
}
}
Solutions:
- Select active source first:
client.SelectSpotify()
time.Sleep(2 * time.Second) // Wait for source change
client.Play()
- Use key commands instead:
client.SendKey("PLAY") // Instead of client.Play()
client.SendKey("PAUSE") // Instead of client.Pause()
- Check device isn't in setup mode
❌ "Source selection fails"
Symptoms:
Failed to select source: API request failed with status 500
Solutions:
- Check source availability:
sources, _ := client.GetSources()
for _, source := range sources.Sources {
if source.Source == "SPOTIFY" && source.Status == "READY" {
// Source is available
client.SelectSource("SPOTIFY", source.SourceAccount)
}
}
- Account-specific sources:
// For streaming services, include account
client.SelectSource("SPOTIFY", "your_account_id")
- Use convenience methods:
client.SelectSpotify() // Handles account automatically
client.SelectBluetooth()
client.SelectAux()
🔊 Volume & Audio Issues
❌ "Volume control not working"
Symptoms:
- Volume commands succeed but no change
- "Permission denied" errors
Diagnostic Steps:
1. Check Zone Status
zoneStatus, err := client.GetZoneStatus()
if err == nil {
fmt.Printf("Zone Status: %s\n", zoneStatus)
}
Solutions:
- Zone Member Issue:
// Only zone master can control volume
if zoneStatus == "MEMBER" {
fmt.Println("Device is zone member - only master controls volume")
// Find and use master device
zone, _ := client.GetZone()
// Connect to master device using zone.Master ID
}
- Use Safe Volume Methods:
client.SetVolumeSafe(50) // Clamps to valid range
client.IncreaseVolume(5) // Incremental control
client.DecreaseVolume(5)
- Check Current Volume:
volume, _ := client.GetVolume()
fmt.Printf("Target: %d, Actual: %d, Muted: %t\n",
volume.TargetVolume, volume.ActualVolume, volume.Muted)
❌ "Bass/Balance control not supported"
Symptoms:
Failed to set bass: API request failed with status 404
Solutions:
- Check device capabilities:
caps, err := client.GetCapabilities()
if err == nil {
fmt.Printf("Bass capable: %t\n", caps.BassCapable)
}
- Use safe methods:
client.SetBassSafe(-5) // Won't fail on unsupported devices
client.SetBalanceSafe(10) // Falls back gracefully
- Device-specific features:
- SoundTouch 10: Basic bass only
- SoundTouch 20/30: Full bass and balance
- Soundbar models: Advanced audio controls
🔔 Speaker Notification Issues
❌ "speaker beep" command fails with status 400
Symptoms:
$ go run ./cmd/soundtouch-cli --host 192.168.178.35 sp beep
Playing notification beep from 192.168.178.35:8090...
✗ Failed to play notification beep: API request failed with status 400
Cause:
This was a bug in earlier versions where the Go client incorrectly used POST instead of GET for the /playNotification endpoint.
Solution:
Update to the latest version. The fix changed the PlayNotificationBeep() method to use GET requests:
// Fixed implementation (v2025.02+)
func (c *Client) PlayNotificationBeep() error {
var status models.StationResponse
return c.get("/playNotification", &status)
}
Verification: Both commands should now work identically:
# CLI command
go run ./cmd/soundtouch-cli --host 192.168.178.35 sp beep
# Direct curl (for comparison)
curl http://192.168.178.35:8090/playNotification
❌ "speaker" commands not supported
Symptoms:
✗ Failed to play notification: endpoint not supported
Causes & Solutions:
1. Device Model Compatibility
- ✅ Supported: SoundTouch 10 (ST-10), SoundTouch 20 (ST-20)
- ❌ Not Supported: SoundTouch 300 (ST-300), older models
Solution: Verify device model with:
soundtouch-cli --host <device> info
2. Missing App Key (TTS/URL only)
TTS and URL playback require an app key, but beep does not:
# Beep - no app key needed
soundtouch-cli --host <device> speaker beep
# TTS - app key required
soundtouch-cli --host <device> speaker tts --text "Hello" --app-key "your-key"
❌ "Device is busy" during notifications
Symptoms:
✗ Failed to play notification: device is busy
Solutions:
1. Wait for Current Notification to Complete
Only one notification can play at a time. Wait a few seconds and retry.
2. Check Current Playback Status
nowPlaying, _ := client.GetNowPlaying()
fmt.Printf("Current source: %s, status: %s\n",
nowPlaying.Source, nowPlaying.PlayStatus)
📡 WebSocket Issues
❌ "WebSocket connection failed"
Symptoms:
Failed to connect WebSocket: dial ws://192.168.1.100:8080/: connection refused
Solutions:
1. Verify WebSocket Port (8080)
# WebSocket uses port 8080, not 8090
nc -zv 192.168.1.100 8080
2. Check Protocol Specification
// WebSocket client should auto-handle this
wsClient := client.NewWebSocketClient(nil)
// Manual connection (if needed)
url := "ws://192.168.1.100:8080/"
headers := http.Header{}
headers.Set("Sec-WebSocket-Protocol", "gabbo")
3. Connection Conflicts
- Only one WebSocket connection per device
- Close other apps using SoundTouch
- Restart SoundTouch device if needed
❌ "WebSocket disconnects frequently"
Symptoms:
- Connection drops every few minutes
- Constant reconnection messages
Solutions:
- Increase ping interval:
config := client.DefaultWebSocketConfig()
config.PingInterval = 60 * time.Second // Increase from 30s
config.PongTimeout = 20 * time.Second // Increase timeout
wsClient := client.NewWebSocketClient(config)
- Check network stability:
# Test for packet loss
ping -c 100 192.168.1.100 | grep loss
- Power management issues:
# Disable WiFi power saving (Linux)
sudo iwconfig wlan0 power off
# Check Windows power management
powercfg -devicequery wake_armed
❌ "Events not received"
Symptoms:
- WebSocket connects but no events
- Missing volume/playback updates
Solutions:
- Verify event handlers:
wsClient.OnVolumeUpdated(func(event *models.VolumeUpdatedEvent) {
fmt.Printf("Volume event received: %d\n", event.Volume.TargetVolume)
})
// Test by manually changing volume on device
- Check event parsing:
wsClient.OnUnknownEvent(func(event *models.WebSocketEvent) {
fmt.Printf("Unknown event: %+v\n", event)
})
- Device activity required:
- Events only sent when device state changes
- Try manual volume/source changes
- Check device isn't in standby
👥 Multiroom Issues
❌ "Zone creation fails"
Symptoms:
Failed to create zone: API request failed with status 400
Solutions:
1. Check Device Compatibility
// Get device capabilities
caps, _ := client.GetCapabilities()
// Look for multiroom support
// Verify devices are on same network
for _, client := range clients {
network, _ := client.GetNetworkInfo()
fmt.Printf("Device IP: %s\n", network.GetConnectedInterface().IPAddress)
}
2. Correct Device IDs
// Get exact device IDs
info, _ := client.GetDeviceInfo()
masterID := info.DeviceID // Use this, not MAC address
// Create zone with proper IDs
client.CreateZone(masterID, []string{member1ID, member2ID})
3. Sequential Zone Operations
// Don't create multiple zones simultaneously
client1.CreateZone(master1, []string{member1})
time.Sleep(2 * time.Second)
client2.CreateZone(master2, []string{member2})
❌ "Device won't join zone"
Symptoms:
- Zone creation succeeds but member doesn't join
- Member device shows as standalone
Solutions:
- Check device status:
status, _ := memberClient.GetZoneStatus()
fmt.Printf("Member status: %s\n", status)
if status == "STANDALONE" {
// Device didn't join - check network/permissions
}
- Firmware compatibility:
- Ensure all devices have recent firmware
- Update via Bose SoundTouch app
- Some very old devices don't support multiroom
- Network subnet issues:
# Verify devices can reach each other
ping -c 4 member_device_ip
🔧 Development & Debugging
Enable Detailed Logging
import "log"
// Enable verbose HTTP logging
log.SetFlags(log.LstdFlags | log.Lshortfile)
// Custom HTTP client with debug
transport := &http.Transport{
// Add debug transport if needed
}
config := client.ClientConfig{
Host: "192.168.1.100",
Port: 8090,
Timeout: 10 * time.Second,
}
Debug WebSocket Events
wsClient.OnUnknownEvent(func(event *models.WebSocketEvent) {
log.Printf("Raw event: %+v", event)
})
// Enable WebSocket debug logging
config := client.DefaultWebSocketConfig()
config.Logger = &client.DefaultLogger{} // Or custom logger
Network Debugging Tools
# Capture SoundTouch traffic
sudo tcpdump -i any host 192.168.1.100 and port 8090
# Monitor WebSocket traffic
sudo tcpdump -i any host 192.168.1.100 and port 8080
# HTTP debugging with curl
curl -v http://192.168.1.100:8090/info
curl -v http://192.168.1.100:8090/volume
📊 Performance Issues
High Memory Usage
Symptoms:
- Go process memory keeps growing
- Out of memory errors in long-running apps
Solutions:
- Connection cleanup:
// Always close WebSocket connections
defer wsClient.Disconnect()
// Use connection pools for multiple devices
pool := NewConnectionPool(10, 5*time.Minute)
defer pool.Close()
- Goroutine leaks:
// Use context for cancellation
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Monitor goroutines
go func() {
for {
fmt.Printf("Goroutines: %d\n", runtime.NumGoroutine())
time.Sleep(10 * time.Second)
}
}()
Slow Response Times
Solutions:
- Increase timeouts appropriately:
config := client.ClientConfig{
Timeout: 15 * time.Second, // Reasonable for network ops
}
- Use connection pooling:
// Reuse connections instead of creating new ones
pool := NewConnectionPool(5, 5*time.Minute)
client := pool.GetClient(host, port)
- Concurrent operations:
// Process multiple devices concurrently
var wg sync.WaitGroup
for _, client := range clients {
wg.Add(1)
go func(c *client.Client) {
defer wg.Done()
// Process device
}(client)
}
wg.Wait()
🚨 Emergency Procedures
Device Becomes Unresponsive
-
Power cycle device:
- Unplug for 10 seconds
- Reconnect and wait 30 seconds for boot
-
Network reset:
- Hold Bluetooth and Volume Down for 10 seconds
- Device will reset network settings
-
Factory reset (last resort):
- Hold Power for 10 seconds while plugged in
- Will lose all presets and settings
Multiple Devices Acting Strange
-
Check router:
- Restart router/access point
- Check for firmware updates
- Verify DHCP/IP assignment
-
Network interference:
- Check for 2.4GHz interference
- Try 5GHz WiFi if available
- Check for microwave/Bluetooth interference
App Crashes or Hangs
- Graceful shutdown:
// Always use context for cancellation
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// Cleanup resources
defer func() {
if wsClient != nil {
wsClient.Disconnect()
}
}()
- Resource monitoring:
// Monitor resource usage
go func() {
var m runtime.MemStats
for {
runtime.ReadMemStats(&m)
log.Printf("Alloc = %d KB, Sys = %d KB", m.Alloc/1024, m.Sys/1024)
time.Sleep(30 * time.Second)
}
}()
📋 Diagnostic Checklist
Use this checklist to systematically troubleshoot issues:
Network Connectivity
- Device power LED is solid white
- Both devices on same network subnet
- Firewall allows ports 8090 (HTTP) and 8080 (WebSocket)
- Can ping device IP address
- Can telnet to ports 8090 and 8080
Device Status
- Device not in setup mode (solid white LED)
- Recent firmware version (check Bose app)
- Device responds to Bose app
- No other apps connected to device
Code Configuration
- Correct IP address and ports
- Reasonable timeouts (10-30 seconds)
- Proper error handling
- Resource cleanup (defer statements)
Multiroom Specific
- All devices support multiroom
- Device IDs are correct (from GetDeviceInfo)
- Devices on same network subnet
- No existing zone conflicts
🛟 Getting More Help
Information to Gather
When reporting issues, include:
// Device information
info, _ := client.GetDeviceInfo()
fmt.Printf("Device: %s %s (ID: %s)\n", info.Type, info.Name, info.DeviceID)
// Network information
network, _ := client.GetNetworkInfo()
fmt.Printf("Network: %+v\n", network)
// Go version and OS
fmt.Printf("Go version: %s\n", runtime.Version())
fmt.Printf("OS: %s/%s\n", runtime.GOOS, runtime.GOARCH)
Useful Commands
# System information
go version
uname -a # Linux/macOS
systeminfo # Windows
# Network debugging
ip addr show # Linux
ifconfig # macOS
ipconfig /all # Windows
# SoundTouch specific
go run ./cmd/soundtouch-cli -host <ip> -info
go run ./cmd/soundtouch-cli -host <ip> -network-info
Support Resources
- GitHub Issues: Create detailed issue with logs and system info
- Documentation: Check
/docsdirectory for specific topics - Examples: Review
/examplesfor working code patterns - CLI Tool: Use built-in CLI for testing and debugging
Remember: Most issues are network-related. Start with basic connectivity testing before investigating code issues.