Files
Tobias Gesellchen 888348ac55 chore: bump Go to 1.26.6, refresh example go.mod pins
Bumps the go directive to 1.26.6 across the main module and both
standalone example modules (preset-management, navigation-station-demo),
plus the builder image in Dockerfile and the three mock-service images
in docker-compose.ci.yml.

Also refreshes the examples' require github.com/gesellix/bose-soundtouch
pin from the stale v0.118.0 to the current v0.123.0 release tag (the
replace directive means they build against local source regardless,
but the pin should still track reality). go mod tidy run in all three
modules; no other dependency changes.
2026-08-15 14:35:10 +02:00
..

Preset Management Example

This example demonstrates comprehensive preset management functionality for Bose SoundTouch devices.

Features Demonstrated

Core Preset Operations

  • List Presets: View all configured presets with details
  • Store Current Content: Save what's currently playing as a preset
  • Store Specific Content: Save Spotify playlists, radio stations, etc.
  • Select Presets: Choose and play a specific preset
  • Remove Presets: Delete unwanted presets
  • WebSocket Events: Monitor real-time preset updates

Content Types Supported

  • Spotify: Playlists, albums, artists, tracks
  • Radio Stations: TuneIn, local internet radio
  • Local Music: NAS storage, local libraries
  • Other Sources: Any presetable content source

Prerequisites

  1. Go 1.21+ installed on your system
  2. SoundTouch Device on your network
  3. Device IP Address (use discovery to find it)

Running the Example

1. Find Your Device IP

# From project root
go run ./cmd/soundtouch-cli discover devices

2. Run the Example

# Navigate to example directory
cd examples/preset-management

# Run with your device IP
go run . 192.0.2.100

What the Example Does

Step-by-Step Demonstration

  1. 📋 Current Presets: Lists all configured presets
  2. 🔍 Content Check: Analyzes what's currently playing
  3. 💾 Store Current: Saves current content as preset (if presetable)
  4. 💿 Store Spotify: Demonstrates storing a Spotify playlist
  5. 📻 Store Radio: Demonstrates storing a radio station
  6. 📋 Updated List: Shows presets after changes
  7. 🎯 Select Preset: Plays preset #1
  8. 📡 WebSocket Demo: Shows real-time preset events

Example Output

🎵 SoundTouch Preset Management Example
📱 Device: 192.0.2.100:8090

📋 Step 1: Getting current presets...
  📻 Found 2 configured presets:
    1. Morning Jazz
       Source: SPOTIFY
       Location: spotify:playlist:37i9dQZF1DXcBWIGoYBM5M
       Created: 2024-01-15 08:30:00

    2. K-LOVE Radio
       Source: TUNEIN
       Location: /v1/playback/station/s33828
       Created: 2024-01-15 09:15:00

  🆓 Available slots: [3 4 5 6]

🔍 Step 2: Checking current content...
  🎵 Now Playing: Bohemian Rhapsody
      Artist: Queen
      Source: SPOTIFY
      Presetable: true
      Location: spotify:track:17GmwQ9Q3MTAz05OokmNNB

💾 Step 3: Storing current content as preset...
  💾 Storing current content as preset 3...
  ✅ Successfully stored as preset 3

📡 Step 8: Demonstrating preset events...
  📡 Connecting to WebSocket for real-time events...
  ✅ WebSocket connected, listening for preset events...
  🔄 Making a preset change to trigger an event...
  💾 Storing test preset 4 to trigger event...
  ⏳ Waiting 3 seconds for WebSocket event...
  📡 Preset Update Event Received!
      Device: AABBCCDDEEFF
      Presets count: 4
      - Preset 1: Morning Jazz (SPOTIFY)
      - Preset 2: K-LOVE Radio (TUNEIN)
      - Preset 3: Bohemian Rhapsody (SPOTIFY)
      - Preset 4: BBC Radio 1 (TUNEIN)

✅ Preset management demo completed!

Understanding the Code

Basic Preset Operations

// Get all presets
presets, err := client.GetPresets()

// Check if current content can be saved
presetable, err := client.IsCurrentContentPresetable()

// Store current content
err = client.StoreCurrentAsPreset(slotNumber)

// Store specific content
contentItem := &models.ContentItem{
    Source:        "SPOTIFY",
    Type:          "uri",
    Location:      "spotify:playlist:37i9dQZF1DXcBWIGoYBM5M",
    SourceAccount: "username",
    IsPresetable:  true,
    ItemName:      "Today's Top Hits",
}
err = client.StorePreset(slotNumber, contentItem)

// Select a preset
err = client.SelectPreset(1)

// Remove a preset
err = client.RemovePreset(6)

WebSocket Event Handling

// Create WebSocket client
wsClient := client.NewWebSocketClient(nil)

// Handle preset events
wsClient.OnPresetUpdated(func(event *models.PresetUpdatedEvent) {
    fmt.Printf("Presets updated on device %s\n", event.DeviceID)
    for _, preset := range event.Presets.Preset {
        if !preset.IsEmpty() {
            fmt.Printf("Preset %d: %s\n", preset.ID, preset.GetDisplayName())
        }
    }
})

// Connect and listen
err := wsClient.Connect()
defer wsClient.Close()

Content Location Examples

Spotify Content

// Playlist
Location: "spotify:playlist:37i9dQZF1DXcBWIGoYBM5M"

// Album  
Location: "spotify:album:4aawyAB9vmqN3uQ7FjRGTy"

// Artist
Location: "spotify:artist:6APm8EjxOHSYM5B4i3vT3q"

// Track
Location: "spotify:track:17GmwQ9Q3MTAz05OokmNNB"

Radio Stations

// TuneIn
Location: "/v1/playback/station/s33828"

// Internet Radio
Location: "https://stream.example.com/radio"

Getting Content Locations

Method 1: From Currently Playing

# Show current content details (includes location)
go run ./cmd/soundtouch-cli --host 192.0.2.100 play now

Method 2: From Spotify URLs

Convert Spotify web URLs to URIs:

  • URL: https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M
  • URI: spotify:playlist:37i9dQZF1DXcBWIGoYBM5M

Error Scenarios

The example handles common error cases:

  • No Content Playing: Gracefully handles empty now playing
  • Non-Presetable Content: Shows when content can't be saved
  • Full Preset Slots: Finds available slots or handles full device
  • WebSocket Issues: Proper connection handling and cleanup

Integration with CLI

This example shows programmatic usage. For command-line usage:

# List presets
go run ./cmd/soundtouch-cli --host 192.0.2.100 preset list

# Store current content
go run ./cmd/soundtouch-cli --host 192.0.2.100 preset store-current --slot 1

# Store specific content
go run ./cmd/soundtouch-cli --host 192.0.2.100 preset store \
  --slot 2 \
  --source SPOTIFY \
  --location "spotify:playlist:37i9dQZF1DXcBWIGoYBM5M" \
  --name "My Playlist"

# Select preset
go run ./cmd/soundtouch-cli --host 192.0.2.100 preset select --slot 1

# Remove preset
go run ./cmd/soundtouch-cli --host 192.0.2.100 preset remove --slot 6

Troubleshooting

Device Not Found

Error: Failed to connect to device: connection refused

Solution: Verify device IP and ensure device is powered on

Preset Store Failed

Error: Failed to store preset: content is not presetable

Solution: Not all content can be saved as presets (e.g., Bluetooth, some radio streams)

No Available Slots

Error: All preset slots are occupied

Solution: Remove an existing preset first or use a specific slot number

Use Cases

This example demonstrates patterns for:

  • Smart Home Automation: Trigger presets based on time/events
  • Music Management: Organize favorite content into quick-access presets
  • Family Scenarios: Each person gets their own preset slots
  • Party Mode: Pre-configure playlists for different moods
  • Radio Favorites: Save frequently listened radio stations