This commit is contained in:
Tobias Gesellchen
2026-06-06 19:11:24 +02:00
parent 51ad72adcf
commit 2c2bb54eff
3 changed files with 65 additions and 65 deletions
@@ -22,7 +22,7 @@ The current system uses multiple data collection methods to build a complete dev
Name string // From UPnP friendlyName
Host string // IP address
Port int // Usually 8090
ModelID string // From UPnP modelName
ModelID string // From UPnP modelName
SerialNo string // MAC address from UPnP
UPnPLocation string // Device description URL
UPnPUSN string // Unique service name
@@ -66,7 +66,7 @@ The current system uses multiple data collection methods to build a complete dev
```mermaid
sequenceDiagram
participant Service as SoundTouch Service
participant UPnP as UPnP Discovery
participant UPnP as UPnP Discovery
participant mDNS as mDNS Discovery
participant Device as SoundTouch Device
participant DataStore as Data Store
@@ -76,28 +76,28 @@ sequenceDiagram
Service->>UPnP: Start SSDP Discovery
Service->>mDNS: Start mDNS Discovery
UPnP->>UPnP: Send M-SEARCH multicast
Device->>UPnP: Respond with location URL
UPnP->>Device: Fetch device description XML
Device->>UPnP: Return basic device info
mDNS->>mDNS: Query _soundtouch._tcp
Device->>mDNS: Respond with service info
Service->>Service: Merge discovery results
Service->>Device: GET /info (enrich data)
Device->>Service: Return detailed device info
Service->>DataStore: Store discovered device
Note over User,DataStore: User Registration
User->>Service: POST /account/{id}/devices
Note right of User: deviceId + user-friendly name
Service->>DataStore: Link device to account
Note over Service,DataStore: Migration Process
Service->>Device: GET /info (device identification)
Device->>Service: Return device details
Device->>Service: Return device details
Service->>Service: Build migration summary
Service->>Device: Apply configuration changes
```
@@ -199,25 +199,25 @@ The `/power_on` endpoint receives comprehensive device data that could replace m
### Data Completeness Comparison
| Data Field | Current `/info` | `/power_on` | Gap Assessment |
|------------|----------------|-------------|----------------|
| **Device ID** | ✅ UUID format | ✅ MAC format | Different format |
| **Device Name** | ✅ Internal name | ❌ Missing | **Critical Gap** |
| **Device Type** | ✅ Model string | ✅ Product code | ✅ Available |
| **Account ID** | ✅ marge UUID | ❌ Missing | **Critical Gap** |
| **Service URL** | ✅ marge URL | ❌ Missing | **Important Gap** |
| **Firmware Version** | ✅ Full version | ✅ Full version | ✅ Available |
| **Serial Numbers** | ✅ Component serials | ✅ Device + Product | ✅ Available |
| **MAC Addresses** | ✅ Interface-specific | ✅ Multiple MACs | ✅ Enhanced |
| **IP Address** | ✅ Interface IPs | ✅ Current IP | ✅ Available |
| **Network Status** | ❌ Basic | ✅ Rich diagnostics | ✅ **Enhanced** |
| **Regional Settings** | ✅ Country/Region | ❌ Missing | **Important Gap** |
| Data Field | Current `/info` | `/power_on` | Gap Assessment |
|-----------------------|----------------------|--------------------|-------------------|
| **Device ID** | ✅ UUID format | ✅ MAC format | Different format |
| **Device Name** | ✅ Internal name | ❌ Missing | **Critical Gap** |
| **Device Type** | ✅ Model string | ✅ Product code | ✅ Available |
| **Account ID** | ✅ marge UUID | ❌ Missing | **Critical Gap** |
| **Service URL** | ✅ marge URL | ❌ Missing | **Important Gap** |
| **Firmware Version** | ✅ Full version | ✅ Full version | ✅ Available |
| **Serial Numbers** | ✅ Component serials | ✅ Device + Product | ✅ Available |
| **MAC Addresses** | ✅ Interface-specific | ✅ Multiple MACs | ✅ Enhanced |
| **IP Address** | ✅ Interface IPs | ✅ Current IP | ✅ Available |
| **Network Status** | ❌ Basic | ✅ Rich diagnostics | ✅ **Enhanced** |
| **Regional Settings** | ✅ Country/Region | ❌ Missing | **Important Gap** |
### Enhancement Benefits
#### 1. Network Independence
- ✅ Works across internet/WAN connections
- ✅ No multicast/broadcast requirements
- ✅ No multicast/broadcast requirements
- ✅ Firewall/NAT friendly
- ✅ Supports remote device management
@@ -246,21 +246,21 @@ func (s *Server) HandleMargePowerOn(w http.ResponseWriter, r *http.Request) {
// Fallback to existing discovery
return s.fallbackToDiscovery(r.RemoteAddr)
}
// Extract device information
deviceMAC := powerOnData.Device.ID
deviceIP := powerOnData.DiagnosticData.DeviceLandscape.IPAddress
// Lookup existing device data
deviceInfo := s.lookupDeviceByMAC(deviceMAC)
if deviceInfo == nil {
// New device - trigger registration flow
deviceInfo = s.createDeviceFromPowerOn(powerOnData)
}
// Update with power_on data
s.updateDeviceFromPowerOn(deviceInfo, powerOnData)
// Determine response actions
response := s.buildPowerOnResponse(deviceInfo)
s.sendResponse(w, response)
@@ -280,7 +280,7 @@ Address missing data through complementary mechanisms:
```mermaid
sequenceDiagram
participant Device as SoundTouch Device
participant Service as SoundTouch Service
participant Service as SoundTouch Service
participant DataStore as Data Store
participant User as User/App
@@ -293,7 +293,7 @@ sequenceDiagram
alt Device Unknown
Service->>DataStore: Create device record
Service->>User: Notify new device found
else Device Known
else Device Known
Service->>DataStore: Update device status
end
Service->>Device: Configuration response
@@ -360,11 +360,11 @@ type Migration struct {
### Immediate Actions (Phase 1)
1. **Enhance `/power_on` handler** to extract and store comprehensive device data
2. **Implement device lookup by MAC address** as primary identification method
2. **Implement device lookup by MAC address** as primary identification method
3. **Create hybrid discovery system** using both `/power_on` and existing methods
4. **Add network-independent device management** capabilities
### Medium-term Improvements (Phase 2)
### Medium-term Improvements (Phase 2)
1. **Implement account-device MAC mapping** for automatic association
2. **Add IP geolocation** for regional settings inference
3. **Create device registration UI** optimized for `/power_on` discovered devices
@@ -372,7 +372,7 @@ type Migration struct {
### Long-term Enhancements (Phase 3)
1. **Request firmware enhancement** to include missing data in `/power_on`
2. **Implement real-time device monitoring** via `/power_on` events
2. **Implement real-time device monitoring** via `/power_on` events
3. **Create centralized device management** independent of network topology
4. **Add predictive migration** based on device status patterns
@@ -387,8 +387,8 @@ type Migration struct {
The `/power_on` endpoint provides a significant opportunity to reduce network dependencies while enhancing device management capabilities. By implementing a hybrid approach that leverages `/power_on` data for primary device identification and status updates while maintaining existing registration workflows for user-controlled metadata, the system can achieve:
- **Network independence** for core device management
- **Enhanced real-time capabilities** through device-initiated communication
- **Enhanced real-time capabilities** through device-initiated communication
- **Improved scalability** across diverse network topologies
- **Better user experience** with automatic device discovery and status updates
The proposed implementation strategy provides a clear path to achieve these benefits while maintaining system reliability and user workflow compatibility.
The proposed implementation strategy provides a clear path to achieve these benefits while maintaining system reliability and user workflow compatibility.
+10 -10
View File
@@ -316,7 +316,7 @@ avahi-resolve -n soundtouch.local
```go
nowPlaying, err := client.GetNowPlaying()
if err == nil {
fmt.Printf("Status: %s, Source: %s\n",
fmt.Printf("Status: %s, Source: %s\n",
nowPlaying.PlayStatus, nowPlaying.Source)
}
```
@@ -326,7 +326,7 @@ if err == nil {
sources, err := client.GetSources()
if err == nil {
for _, source := range sources.Sources {
fmt.Printf("Source: %s, Status: %s\n",
fmt.Printf("Source: %s, Status: %s\n",
source.Source, source.Status)
}
}
@@ -490,7 +490,7 @@ if err == nil {
// 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
@@ -507,7 +507,7 @@ client.DecreaseVolume(5)
3. **Check Current Volume:**
```go
volume, _ := client.GetVolume()
fmt.Printf("Target: %d, Actual: %d, Muted: %t\n",
fmt.Printf("Target: %d, Actual: %d, Muted: %t\n",
volume.TargetVolume, volume.ActualVolume, volume.Muted)
```
@@ -586,7 +586,7 @@ curl http://192.0.2.10:8090/playNotification
**Causes & Solutions:**
#### 1. **Device Model Compatibility**
- ✅ **Supported**: SoundTouch 10 (ST-10), SoundTouch 20 (ST-20)
- ✅ **Supported**: SoundTouch 10 (ST-10), SoundTouch 20 (ST-20)
- ❌ **Not Supported**: SoundTouch 300 (ST-300), older models
**Solution:** Verify device model with:
@@ -619,7 +619,7 @@ Only one notification can play at a time. Wait a few seconds and retry.
#### 2. **Check Current Playback Status**
```go
nowPlaying, _ := client.GetNowPlaying()
fmt.Printf("Current source: %s, status: %s\n",
fmt.Printf("Current source: %s, status: %s\n",
nowPlaying.Source, nowPlaying.PlayStatus)
```
@@ -880,7 +880,7 @@ config.Logger = &client.DefaultLogger{} // Or custom logger
# Capture SoundTouch traffic
sudo tcpdump -i any host 192.0.2.100 and port 8090
# Monitor WebSocket traffic
# Monitor WebSocket traffic
sudo tcpdump -i any host 192.0.2.100 and port 8080
# HTTP debugging with curl
@@ -1024,7 +1024,7 @@ Use this checklist to systematically troubleshoot issues:
### Network Connectivity
- [ ] Device power LED is solid white
- [ ] Both devices on same network subnet
- [ ] 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
@@ -1041,7 +1041,7 @@ Use this checklist to systematically troubleshoot issues:
- [ ] Proper error handling
- [ ] Resource cleanup (defer statements)
### Multiroom Specific
### Multiroom Specific
- [ ] All devices support multiroom
- [ ] Device IDs are correct (from GetDeviceInfo)
- [ ] Devices on same network subnet
@@ -1286,4 +1286,4 @@ go run ./cmd/soundtouch-cli -host <ip> -network-info
- **Examples**: Review `/examples` for 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.
Remember: Most issues are network-related. Start with basic connectivity testing before investigating code issues.
+22 -22
View File
@@ -161,27 +161,27 @@ import (
func analyzeDevice(host string) {
// Create client
c := client.NewClient(&client.Config{Host: host})
// Get supported URLs with feature mapping
supportedURLs, err := c.GetSupportedURLs()
if err != nil {
log.Fatal(err)
}
// Get device capabilities overview
completeness, supported, total := supportedURLs.GetFeatureCompleteness()
fmt.Printf("Device supports %d%% of features (%d/%d)\n",
fmt.Printf("Device supports %d%% of features (%d/%d)\n",
completeness, supported, total)
// Check specific capabilities
if supportedURLs.HasMultiroomSupport() {
fmt.Println("✅ Device can create multiroom zones")
}
if supportedURLs.HasAdvancedAudioSupport() {
fmt.Println("✅ Device has advanced audio controls")
}
// Get missing essential features
missing := supportedURLs.GetMissingEssentialFeatures()
if len(missing) > 0 {
@@ -190,13 +190,13 @@ func analyzeDevice(host string) {
fmt.Printf(" • %s\n", feature.Name)
}
}
// Get features by category
featuresByCategory := supportedURLs.GetFeaturesByCategory()
for category, features := range featuresByCategory {
fmt.Printf("%s: %d features available\n", category, len(features))
}
// Check for partial implementations
partial := supportedURLs.GetPartiallyImplementedFeatures()
for _, feature := range partial {
@@ -211,10 +211,10 @@ func analyzeDevice(host string) {
func canDoAdvancedAudio(supportedURLs *models.SupportedURLsResponse) bool {
requiredEndpoints := []string{
"/audiodspcontrols",
"/audioproducttonecontrols",
"/audioproducttonecontrols",
"/audioproductlevelcontrols",
}
for _, endpoint := range requiredEndpoints {
if !supportedURLs.HasURL(endpoint) {
return false
@@ -226,19 +226,19 @@ func canDoAdvancedAudio(supportedURLs *models.SupportedURLsResponse) bool {
// Get device-specific recommendations
func getPersonalizedTips(supportedURLs *models.SupportedURLsResponse) []string {
var tips []string
if supportedURLs.HasURL("/presets") {
tips = append(tips, "Set up presets for your favorite stations")
}
if supportedURLs.HasURL("/setZone") {
tips = append(tips, "Create multiroom zones for whole-home audio")
}
if supportedURLs.HasURL("/search") && supportedURLs.HasURL("/addStation") {
tips = append(tips, "Search and save new radio stations")
}
return tips
}
```
@@ -289,7 +289,7 @@ soundtouch-cli audio level get # Get level controls
```bash
# Basic Playback (Essential)
soundtouch-cli play start # Start playback
soundtouch-cli play stop # Stop playback
soundtouch-cli play stop # Stop playback
soundtouch-cli play pause # Pause playback
soundtouch-cli play now # Get now playing info
@@ -306,7 +306,7 @@ soundtouch-cli key mute # Mute toggle
# Audio Sources
soundtouch-cli source list # List available sources
soundtouch-cli source select --source SPOTIFY # Select Spotify
soundtouch-cli source bluetooth # Select Bluetooth
soundtouch-cli source bluetooth # Select Bluetooth
soundtouch-cli source aux # Select AUX input
# Service Availability
@@ -321,7 +321,7 @@ soundtouch-cli browse tunein # Browse TuneIn content
soundtouch-cli browse pandora --source-account <account> # Browse Pandora
soundtouch-cli browse spotify --source-account <account> # Browse Spotify
# Station Management
# Station Management
soundtouch-cli station search-tunein --query "jazz" # Search TuneIn
soundtouch-cli station search-pandora --query "rock" --source-account <account>
soundtouch-cli station add --source TUNEIN --token <token> --name "Jazz FM"
@@ -354,7 +354,7 @@ soundtouch-cli zone remove --member 192.0.2.103 # Remove from zone
# Quick capability check
soundtouch-cli supported-urls | grep "Feature Coverage"
# Essential features verification
# Essential features verification
soundtouch-cli analyze | grep -A 5 "Missing Essential Features"
# Advanced features check
@@ -368,7 +368,7 @@ soundtouch-cli supported-urls --features | grep "Multiroom"
Based on feature support, devices are automatically classified:
- **Premium SoundTouch Speaker**: Multiroom + Advanced Audio + Full Feature Set
- **Standard SoundTouch Speaker**: Multiroom Capable + Core Features
- **Standard SoundTouch Speaker**: Multiroom Capable + Core Features
- **Basic SoundTouch Speaker**: Streaming + Presets + Core Features
- **Essential SoundTouch Device**: Core Playback Features Only
- **Limited SoundTouch Device**: Minimal Feature Set
@@ -384,7 +384,7 @@ soundtouch-cli supported-urls --features | grep -i "bass control"
# If not listed, device doesn't support bass control
```
**Issue**: "Multiroom not available"
**Issue**: "Multiroom not available"
```bash
# Verify multiroom support
soundtouch-cli analyze | grep "Multiroom"
@@ -405,7 +405,7 @@ soundtouch-cli supported-urls --features | grep "Content Navigation"
The feature mapping system provides personalized recommendations:
- **Missing Balance Control**: "No balance control available on this device"
- **Multiroom Available**: "Create speaker groups with other devices"
- **Multiroom Available**: "Create speaker groups with other devices"
- **Advanced Audio**: "Fine-tune sound with DSP controls"
- **Limited Features**: "Consider upgrading for full functionality"
@@ -417,4 +417,4 @@ The feature mapping system provides personalized recommendations:
4. **Review recommendations** for optimal device usage
5. **Monitor feature completeness** to understand device limitations
This comprehensive feature mapping system ensures you get the most out of your SoundTouch device by understanding exactly what it can do and how to use it effectively.
This comprehensive feature mapping system ensures you get the most out of your SoundTouch device by understanding exactly what it can do and how to use it effectively.