mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-18 08:36:13 +00:00
## New Endpoints ### GET /name ✅ - Simple device name retrieval with XML parsing - Helper methods for name validation and display - Real device name integration with anonymization ### GET /capabilities ✅ - Comprehensive device capabilities detection - Complex XML structure with nested network, DSP, and system configurations - Smart categorization: System Features, Audio Features, Network Features - Capability-specific helper methods (HasLRStereoCapability, HasDualModeNetwork, etc.) - Extended capabilities parsing with URLs and metadata ### GET /presets ✅ - Complete preset management with timestamps and metadata - Spotify playlist integration with anonymized account information - Smart filtering: by source, used/empty slots, most recent, oldest presets - Comprehensive analysis: preset summaries with source breakdowns - Time-based operations: creation/update timestamps with formatted display ## Device Introspection Features ### Capability Detection - System capabilities: Light Switch, Clock Display, BCO Reset, Power Saving - Audio capabilities: L/R Stereo support, DSP Mono/Stereo availability - Network capabilities: Dual Mode, WSAPI Proxy, Hosted WiFi Configuration - Extended capabilities: Custom endpoint discovery with URL mapping ### Preset Analysis - Usage pattern analysis (used vs empty slots) - Source distribution (Spotify, TuneIn, etc.) - Temporal analysis (most recent, oldest presets) - Content metadata extraction (artwork URLs, display names) ## Enhanced CLI Tool ### New Commands - Added -name command with simple device identification - Added -capabilities command with categorized feature display - Added -presets command with comprehensive preset analysis - Enhanced help system with all new command examples ### Rich Output Formatting - Capability categorization with bullet-point display - Preset timeline with creation/update timestamps - Smart metadata display (artwork, source accounts, content types) - Device-specific feature highlighting (different capabilities per device) ## Real Device Integration ### Multi-Device Testing - Device 192.168.178.28: SoundTouch 10 with Light Switch, Clock Display, Hosted WiFi - Device 192.168.178.35: SoundTouch 20 with L/R Stereo, Dual Mode networking - Verified capability differences between device models - Real preset data with anonymized Spotify account information ### Edge Case Handling - Non-responsive endpoints (/trackInfo timeout handling) - Empty preset configurations - Missing capability sections - Device-specific feature variations ## Quality & Testing ### Comprehensive Test Coverage - 15+ unit tests for XML models with real device response patterns - Client integration tests with mock HTTP servers - Edge case validation (empty names, missing capabilities, no presets) - Timestamp parsing and validation with Unix epoch conversion ### Production-Ready Features - Type-safe XML unmarshaling with custom validation - Robust error handling for network and parsing failures - Privacy protection with anonymized real device data - Documentation updates with real-world usage examples ## API Coverage Progress ✅ Complete Information Endpoints: - GET /info - Device information - GET /name - Device name - GET /capabilities - Device capabilities - GET /presets - Configured presets - GET /now_playing - Current playback status - GET /sources - Available audio sources 🔄 Next Phase - Control Endpoints: - POST /key - Media controls - GET/POST /volume - Volume management - WebSocket / - Real-time events Features: ✅ Comprehensive device introspection and capability detection ✅ Smart preset management with timeline analysis ✅ Multi-device support with hardware-specific feature detection ✅ Production-ready error handling and data validation ✅ Rich CLI interface with categorized output formatting ✅ Real device integration with privacy-protected test data
202 lines
6.0 KiB
Go
202 lines
6.0 KiB
Go
package models
|
|
|
|
import "encoding/xml"
|
|
|
|
// Capabilities represents the response from /capabilities endpoint
|
|
type Capabilities struct {
|
|
XMLName xml.Name `xml:"capabilities"`
|
|
DeviceID string `xml:"deviceID,attr"`
|
|
NetworkConfig *NetworkConfig `xml:"networkConfig,omitempty"`
|
|
DSPConfig *DSPConfig `xml:"dspCapabilities,omitempty"`
|
|
Lightswitch bool `xml:"lightswitch,omitempty"`
|
|
ClockDisplay bool `xml:"clockDisplay,omitempty"`
|
|
Capability []Capability `xml:"capability,omitempty"`
|
|
LRStereo bool `xml:"lrStereoCapable,omitempty"`
|
|
BCOReset bool `xml:"bcoresetCapable,omitempty"`
|
|
PowerSaving bool `xml:"disablePowerSaving,omitempty"`
|
|
}
|
|
|
|
// NetworkConfig represents network configuration capabilities
|
|
type NetworkConfig struct {
|
|
HostedWifiConfig *HostedWifiConfig `xml:"hostedWifiConfigWebPage,omitempty"`
|
|
DualMode bool `xml:"dualMode,omitempty"`
|
|
WSAPIProxy bool `xml:"wsapiproxy,omitempty"`
|
|
AllInterfaceSupport *AllInterfaces `xml:"allInterfacesSupported,omitempty"`
|
|
WLANInterfaces *WLANInterfaces `xml:"wlanInterfaces,omitempty"`
|
|
Security *Security `xml:"security,omitempty"`
|
|
}
|
|
|
|
// HostedWifiConfig represents hosted wifi configuration settings
|
|
type HostedWifiConfig struct {
|
|
HostedBy string `xml:"hostedBy,attr,omitempty"`
|
|
Generation string `xml:"generation,attr,omitempty"`
|
|
Port string `xml:"port,attr,omitempty"`
|
|
Enabled bool `xml:",chardata"`
|
|
}
|
|
|
|
// AllInterfaces represents all network interfaces support
|
|
type AllInterfaces struct{}
|
|
|
|
// WLANInterfaces represents WLAN interfaces configuration
|
|
type WLANInterfaces struct{}
|
|
|
|
// Security represents security configuration
|
|
type Security struct{}
|
|
|
|
// DSPConfig represents DSP capabilities
|
|
type DSPConfig struct {
|
|
DSPMonoStereo *DSPMonoStereo `xml:"dspMonoStereo,omitempty"`
|
|
}
|
|
|
|
// DSPMonoStereo represents mono/stereo DSP capability
|
|
type DSPMonoStereo struct {
|
|
Available bool `xml:"available,attr"`
|
|
}
|
|
|
|
// Capability represents an individual device capability
|
|
type Capability struct {
|
|
Name string `xml:"name,attr"`
|
|
URL string `xml:"url,attr"`
|
|
Info string `xml:"info,attr"`
|
|
}
|
|
|
|
// HasLightswitch returns true if the device has a light switch
|
|
func (c *Capabilities) HasLightswitch() bool {
|
|
return c.Lightswitch
|
|
}
|
|
|
|
// HasClockDisplay returns true if the device has a clock display
|
|
func (c *Capabilities) HasClockDisplay() bool {
|
|
return c.ClockDisplay
|
|
}
|
|
|
|
// HasLRStereoCapability returns true if the device supports left/right stereo
|
|
func (c *Capabilities) HasLRStereoCapability() bool {
|
|
return c.LRStereo
|
|
}
|
|
|
|
// HasBCOResetCapability returns true if the device supports BCO reset
|
|
func (c *Capabilities) HasBCOResetCapability() bool {
|
|
return c.BCOReset
|
|
}
|
|
|
|
// HasPowerSavingDisabled returns true if power saving is disabled
|
|
func (c *Capabilities) HasPowerSavingDisabled() bool {
|
|
return c.PowerSaving
|
|
}
|
|
|
|
// HasDualModeNetwork returns true if the device supports dual mode networking
|
|
func (c *Capabilities) HasDualModeNetwork() bool {
|
|
return c.NetworkConfig != nil && c.NetworkConfig.DualMode
|
|
}
|
|
|
|
// HasWSAPIProxy returns true if the device supports WSAPI proxy
|
|
func (c *Capabilities) HasWSAPIProxy() bool {
|
|
return c.NetworkConfig != nil && c.NetworkConfig.WSAPIProxy
|
|
}
|
|
|
|
// HasHostedWifiConfig returns true if the device supports hosted wifi configuration
|
|
func (c *Capabilities) HasHostedWifiConfig() bool {
|
|
return c.NetworkConfig != nil &&
|
|
c.NetworkConfig.HostedWifiConfig != nil &&
|
|
c.NetworkConfig.HostedWifiConfig.Enabled
|
|
}
|
|
|
|
// GetHostedWifiPort returns the hosted wifi configuration port
|
|
func (c *Capabilities) GetHostedWifiPort() string {
|
|
if c.HasHostedWifiConfig() {
|
|
return c.NetworkConfig.HostedWifiConfig.Port
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetHostedWifiHostedBy returns who hosts the wifi configuration
|
|
func (c *Capabilities) GetHostedWifiHostedBy() string {
|
|
if c.HasHostedWifiConfig() {
|
|
return c.NetworkConfig.HostedWifiConfig.HostedBy
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// HasDSPMonoStereo returns true if DSP mono/stereo is available
|
|
func (c *Capabilities) HasDSPMonoStereo() bool {
|
|
return c.DSPConfig != nil &&
|
|
c.DSPConfig.DSPMonoStereo != nil &&
|
|
c.DSPConfig.DSPMonoStereo.Available
|
|
}
|
|
|
|
// GetCapabilityByName returns a capability by name
|
|
func (c *Capabilities) GetCapabilityByName(name string) *Capability {
|
|
for _, cap := range c.Capability {
|
|
if cap.Name == name {
|
|
return &cap
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// HasCapability returns true if the device has the specified capability
|
|
func (c *Capabilities) HasCapability(name string) bool {
|
|
return c.GetCapabilityByName(name) != nil
|
|
}
|
|
|
|
// GetCapabilityNames returns a list of all capability names
|
|
func (c *Capabilities) GetCapabilityNames() []string {
|
|
names := make([]string, len(c.Capability))
|
|
for i, cap := range c.Capability {
|
|
names[i] = cap.Name
|
|
}
|
|
return names
|
|
}
|
|
|
|
// GetNetworkCapabilities returns a summary of network capabilities
|
|
func (c *Capabilities) GetNetworkCapabilities() []string {
|
|
var capabilities []string
|
|
|
|
if c.HasDualModeNetwork() {
|
|
capabilities = append(capabilities, "Dual Mode")
|
|
}
|
|
if c.HasWSAPIProxy() {
|
|
capabilities = append(capabilities, "WSAPI Proxy")
|
|
}
|
|
if c.HasHostedWifiConfig() {
|
|
capabilities = append(capabilities, "Hosted WiFi Config")
|
|
}
|
|
|
|
return capabilities
|
|
}
|
|
|
|
// GetAudioCapabilities returns a summary of audio capabilities
|
|
func (c *Capabilities) GetAudioCapabilities() []string {
|
|
var capabilities []string
|
|
|
|
if c.HasLRStereoCapability() {
|
|
capabilities = append(capabilities, "L/R Stereo")
|
|
}
|
|
if c.HasDSPMonoStereo() {
|
|
capabilities = append(capabilities, "DSP Mono/Stereo")
|
|
}
|
|
|
|
return capabilities
|
|
}
|
|
|
|
// GetSystemCapabilities returns a summary of system capabilities
|
|
func (c *Capabilities) GetSystemCapabilities() []string {
|
|
var capabilities []string
|
|
|
|
if c.HasLightswitch() {
|
|
capabilities = append(capabilities, "Light Switch")
|
|
}
|
|
if c.HasClockDisplay() {
|
|
capabilities = append(capabilities, "Clock Display")
|
|
}
|
|
if c.HasBCOResetCapability() {
|
|
capabilities = append(capabilities, "BCO Reset")
|
|
}
|
|
if c.HasPowerSavingDisabled() {
|
|
capabilities = append(capabilities, "Power Saving Disabled")
|
|
}
|
|
|
|
return capabilities
|
|
}
|