chore: sweep example LAN IPs to RFC-5737 in source and config files

Completes the docs-tier RFC-5737 rollout by sweeping the remaining
192.168.1.x references that lived outside .md / .txt / test files:

  - .env.example                                — active PREFERRED_DEVICES default + examples
  - .github/ISSUE_TEMPLATE/*.yml + workflows    — issue template + CI examples
  - cmd/websocket-demo/main.go, doc.go          — top-level docs
  - examples/*/main.go (7 files)                — example program comments
  - pkg/client/client.go                        — godoc examples
  - pkg/models/doc.go                           — package godoc
  - pkg/service/{amazon,spotify,zeroconf}/zeroconf.go — godoc comments
  - pkg/service/handlers/web/index.html         — placeholder text in the UI
  - scripts/prepare-release.sh                  — example invocations
  - scripts/spotify/spotify-prime-speaker.sh    — usage comment
  - tests/integration/http-client/http-client.env.json — fixture IPs

Same mapping as the docs commit (136d24a): 192.168.1.X → 192.0.2.X
preserving the last octet.

One semantic carve-out: the three zeroconf `zcBaseURL` godoc comments
in pkg/service/{amazon,spotify,zeroconf}/zeroconf.go switched to
192.168.10.10 instead of the doc range, because validateZcBaseURL
only accepts RFC-1918 / loopback / link-local. The comment must show
a value the validator actually accepts — see the matching test fix
in 92f66a2 for the same reason.

go build ./... clean. go test ./... clean except the pre-existing
TestDocsConsistency (untracked DEVICE-LOCAL-INSTALL.md, unrelated).
golangci-lint run ./... — 0 issues after a gofmt fix on
examples/zone-slave-operations/main.go.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tobias Gesellchen
2026-05-17 22:05:13 +02:00
co-authored by Claude Opus 4.7
parent feadc478d5
commit 702092d772
23 changed files with 49 additions and 49 deletions
+4 -4
View File
@@ -43,16 +43,16 @@ CACHE_TTL=30s
# Examples:
# Single device with default port:
# PREFERRED_DEVICES="192.168.1.100"
# PREFERRED_DEVICES="192.0.2.100"
# Single device with custom name:
# PREFERRED_DEVICES="Living Room@192.168.1.100"
# PREFERRED_DEVICES="Living Room@192.0.2.100"
# Single device with custom port:
# PREFERRED_DEVICES="192.168.1.100:8091"
# PREFERRED_DEVICES="192.0.2.100:8091"
# Multiple devices with mixed configurations:
PREFERRED_DEVICES="Living Room@192.168.1.100:8090;Kitchen@192.168.1.101;192.168.1.102:8091"
PREFERRED_DEVICES="Living Room@192.0.2.100:8090;Kitchen@192.0.2.101;192.0.2.102:8091"
# Example — replace with your speakers' names and IPs:
# PREFERRED_DEVICES="Living Room SoundTouch@192.0.2.10;Kitchen SoundTouch@192.0.2.11"
+1 -1
View File
@@ -163,7 +163,7 @@ body:
label: Network Configuration
description: Details about your network setup (if relevant to the issue)
placeholder: |
- Device IP: 192.168.1.100
- Device IP: 192.0.2.100
- Network type: WiFi/Ethernet
- Router model:
- Any firewalls or network restrictions:
+1 -1
View File
@@ -131,7 +131,7 @@ body:
render: go
placeholder: |
// Example of how you envision using this feature
client := soundtouch.New("192.168.1.100", 8090)
client := soundtouch.New("192.0.2.100", 8090)
// Your desired API call
result, err := client.NewFeature(options)
+1 -1
View File
@@ -275,7 +275,7 @@ jobs:
func main() {
// Test basic client creation
c := client.NewClientFromHost("192.168.1.100")
c := client.NewClientFromHost("192.0.2.100")
fmt.Printf("Client created for %s\n", c.BaseURL())
// Test models can be imported
+1 -1
View File
@@ -358,7 +358,7 @@ jobs:
func main() {
// Create client
c := client.New("192.168.1.100", 8090)
c := client.New("192.0.2.100", 8090)
// Get device info
info, err := c.GetInfo()
+3 -3
View File
@@ -546,13 +546,13 @@ func printHelp() {
fmt.Printf(" %s -discover\n", os.Args[0])
fmt.Println()
fmt.Println(" # Connect to specific device and monitor volume events only")
fmt.Printf(" %s -host 192.168.1.10 -filter volume\n", os.Args[0])
fmt.Printf(" %s -host 192.0.2.10 -filter volume\n", os.Args[0])
fmt.Println()
fmt.Println(" # Monitor for 5 minutes with verbose output")
fmt.Printf(" %s -host 192.168.1.10 -duration 5m -verbose\n", os.Args[0])
fmt.Printf(" %s -host 192.0.2.10 -duration 5m -verbose\n", os.Args[0])
fmt.Println()
fmt.Println(" # Monitor now playing and volume events")
fmt.Printf(" %s -host 192.168.1.10 -filter nowPlaying,volume\n", os.Args[0])
fmt.Printf(" %s -host 192.0.2.10 -filter nowPlaying,volume\n", os.Args[0])
fmt.Println()
fmt.Println("Event Types:")
fmt.Println(" 🎵 nowPlaying - Track changes, playback status")
+2 -2
View File
@@ -27,7 +27,7 @@
// func main() {
// // Create a client for your SoundTouch device
// config := &client.Config{
// Host: "192.168.1.100",
// Host: "192.0.2.100",
// Port: 8090,
// }
// client := client.NewClient(config)
@@ -70,7 +70,7 @@
// soundtouch-cli discover devices
//
// # Control a device
// soundtouch-cli --host 192.168.1.100 play start
// soundtouch-cli --host 192.0.2.100 play start
//
// # Supported Features
//
+1 -1
View File
@@ -13,7 +13,7 @@ import (
func main() {
// Configure the SoundTouch client
config := &client.Config{
Host: "192.168.1.100", // Replace with your device IP
Host: "192.0.2.100", // Replace with your device IP
Port: 8090,
Timeout: 10 * time.Second,
}
+1 -1
View File
@@ -11,7 +11,7 @@ import (
func main() {
// Configure your device
deviceIP := "192.168.1.100" // Replace with your SoundTouch device IP
deviceIP := "192.0.2.100" // Replace with your SoundTouch device IP
// Create client
soundtouchClient := client.NewClientFromHost(deviceIP)
+2 -2
View File
@@ -163,7 +163,7 @@ func demoLocalMusic(c *client.Client) error {
location := "album:983"
sourceAccount := "3f205110-4a57-4e91-810a-123456789012" // Example GUID
itemName := "Welcome to the New"
containerArt := "http://192.168.1.14:8085/v1/albums/983/image"
containerArt := "http://192.0.2.14:8085/v1/albums/983/image"
fmt.Printf(" Album: %s\n", itemName)
fmt.Printf(" Location: %s\n", location)
@@ -276,7 +276,7 @@ func printUsage() {
fmt.Printf(" %s <device_ip>\n", os.Args[0])
fmt.Println()
fmt.Println("Example:")
fmt.Printf(" %s 192.168.1.100\n", os.Args[0])
fmt.Printf(" %s 192.0.2.100\n", os.Args[0])
fmt.Println()
fmt.Println("Prerequisites:")
fmt.Println("• SoundTouch device on your network")
+4 -4
View File
@@ -239,7 +239,7 @@ func printUsage() {
fmt.Printf(" %s <device_ip>\n", os.Args[0])
fmt.Println()
fmt.Println("Example:")
fmt.Printf(" %s 192.168.1.100\n", os.Args[0])
fmt.Printf(" %s 192.0.2.100\n", os.Args[0])
fmt.Println()
fmt.Println("Prerequisites:")
fmt.Println("• SoundTouch device on your network")
@@ -247,7 +247,7 @@ func printUsage() {
fmt.Println("• Device powered on and connected")
fmt.Println()
fmt.Println("CLI Equivalent Commands:")
fmt.Println("• Browse: soundtouch-cli --host 192.168.1.100 browse tunein")
fmt.Println("• Search: soundtouch-cli --host 192.168.1.100 station search-tunein --query jazz")
fmt.Println("• Add: soundtouch-cli --host 192.168.1.100 station add --source TUNEIN --token <token> --name <name>")
fmt.Println("• Browse: soundtouch-cli --host 192.0.2.100 browse tunein")
fmt.Println("• Search: soundtouch-cli --host 192.0.2.100 station search-tunein --query jazz")
fmt.Println("• Add: soundtouch-cli --host 192.0.2.100 station add --source TUNEIN --token <token> --name <name>")
}
+1 -1
View File
@@ -378,7 +378,7 @@ func printUsage() {
fmt.Printf(" %s <device_ip>\n", os.Args[0])
fmt.Println()
fmt.Println("Example:")
fmt.Printf(" %s 192.168.1.100\n", os.Args[0])
fmt.Printf(" %s 192.0.2.100\n", os.Args[0])
fmt.Println()
fmt.Println("Prerequisites:")
fmt.Println("• SoundTouch device on your network")
+1 -1
View File
@@ -16,7 +16,7 @@ func main() {
host := getSoundTouchHost()
if host == "" {
fmt.Println("Usage: go run main.go <soundtouch-host>")
fmt.Println(" or: SOUNDTOUCH_TEST_HOST=192.168.1.100 go run main.go")
fmt.Println(" or: SOUNDTOUCH_TEST_HOST=192.0.2.100 go run main.go")
os.Exit(1)
}
+3 -3
View File
@@ -11,7 +11,7 @@ import (
func main() {
// Configure your device
deviceIP := "192.168.1.100" // Replace with your SoundTouch device IP
deviceIP := "192.0.2.100" // Replace with your SoundTouch device IP
// Create client
soundtouchClient := client.NewClientFromHost(deviceIP)
@@ -24,7 +24,7 @@ func main() {
masterDeviceID := "ABCD1234EFGH" // Replace with actual master device ID
slaveDeviceID := "WXYZ5678IJKL" // Replace with actual slave device ID
slaveIP := "192.168.1.101" // Replace with actual slave IP
slaveIP := "192.0.2.101" // Replace with actual slave IP
err := soundtouchClient.AddZoneSlave(masterDeviceID, slaveDeviceID, slaveIP)
if err != nil {
@@ -117,7 +117,7 @@ func main() {
fmt.Println("\n8. Error handling example...")
// Try to add a non-existent device to demonstrate error handling
err = soundtouchClient.AddZoneSlave("INVALID123", "NOTFOUND456", "192.168.1.999")
err = soundtouchClient.AddZoneSlave("INVALID123", "NOTFOUND456", "192.0.2.999")
if err != nil {
fmt.Printf("⚠️ Expected error for invalid operation: %v\n", err)
fmt.Println(" This demonstrates proper error handling for invalid device IDs or IPs")
+6 -6
View File
@@ -9,7 +9,7 @@
// Create a client and control your SoundTouch device:
//
// config := &client.Config{
// Host: "192.168.1.100",
// Host: "192.0.2.100",
// Port: 8090,
// Timeout: 10 * time.Second,
// }
@@ -74,10 +74,10 @@
//
// // Create a new zone with multiple speakers
// newZone := &models.ZoneRequest{
// Master: "192.168.1.100",
// Master: "192.0.2.100",
// Members: []models.MemberEntry{
// {IP: "192.168.1.101"},
// {IP: "192.168.1.102"},
// {IP: "192.0.2.101"},
// {IP: "192.0.2.102"},
// },
// }
// err = client.SetZone(newZone)
@@ -120,7 +120,7 @@
// The Config struct supports various options:
//
// config := &client.Config{
// Host: "192.168.1.100",
// Host: "192.0.2.100",
// Port: 8090,
// Timeout: 15 * time.Second,
// UserAgent: "MyApp/1.0",
@@ -901,7 +901,7 @@ func (c *Client) SelectLocalInternetRadio(location, sourceAccount, itemName, con
//
// Example:
//
// err := client.SelectLocalMusic("album:983", "3f205110-4a57-4e91-810a-123456789012", "Welcome to the New", "http://192.168.1.14:8085/v1/albums/983/image")
// err := client.SelectLocalMusic("album:983", "3f205110-4a57-4e91-810a-123456789012", "Welcome to the New", "http://192.0.2.14:8085/v1/albums/983/image")
func (c *Client) SelectLocalMusic(location, sourceAccount, itemName, containerArt string) error {
if location == "" {
return fmt.Errorf("location cannot be empty")
+4 -4
View File
@@ -41,10 +41,10 @@
// Creating zone configurations:
//
// zone := models.Zone{
// Master: "192.168.1.100",
// Master: "192.0.2.100",
// Members: []models.ZoneMember{
// {IPAddress: "192.168.1.101"},
// {IPAddress: "192.168.1.102"},
// {IPAddress: "192.0.2.101"},
// {IPAddress: "192.0.2.102"},
// },
// }
//
@@ -89,7 +89,7 @@
//
// device := models.DiscoveredDevice{
// Name: "Living Room",
// Host: "192.168.1.100",
// Host: "192.0.2.100",
// Port: 8090,
// SerialNo: "AA123456789",
// Location: "/device.xml",
+1 -1
View File
@@ -9,7 +9,7 @@ var ErrAddUserNoOp = zeroconf.ErrAddUserNoOp
// PushAmazonCredentials pushes Amazon Music credentials to a speaker using the
// ZeroConf DH key exchange protocol. Falls back to simplified token push if
// the speaker does not support DH (older firmware).
// zcBaseURL is the base URL of the ZeroConf endpoint, e.g. "http://192.168.1.10:8200/zc".
// zcBaseURL is the base URL of the ZeroConf endpoint, e.g. "http://192.168.10.10:8200/zc".
func PushAmazonCredentials(zcBaseURL, username, accessToken string) error {
return zeroconf.PushCredentials(zcBaseURL, username, accessToken)
}
+2 -2
View File
@@ -148,7 +148,7 @@
<strong>Note:</strong> These URLs must be
<strong>accessible from your SoundTouch devices</strong>.
Use the IP address of this server on your local network
(e.g., <code>http://192.168.1.100:8000</code>) rather than
(e.g., <code>http://192.0.2.100:8000</code>) rather than
<code>localhost</code>.
</p>
<div style="margin-bottom: 20px">
@@ -379,7 +379,7 @@
<input
type="text"
id="add-manual-ip"
placeholder="Manual IP (e.g. 192.168.1.100)"
placeholder="Manual IP (e.g. 192.0.2.100)"
style="margin-left: 20px; padding: 4px"
/>
<button onclick="addManualDevice()">Add Device</button>
+1 -1
View File
@@ -15,7 +15,7 @@ func ZeroConfGetInfo(zcBaseURL string) ([]byte, error) {
// PushSpotifyCredentials pushes Spotify credentials to a speaker using the full
// ZeroConf DH key exchange protocol. Falls back to simplified token push if
// the speaker does not support DH (older firmware).
// zcBaseURL is the base URL of the ZeroConf endpoint, e.g. "http://192.168.1.10:8200/zc".
// zcBaseURL is the base URL of the ZeroConf endpoint, e.g. "http://192.168.10.10:8200/zc".
func PushSpotifyCredentials(zcBaseURL, username, accessToken string) error {
return zeroconf.PushCredentials(zcBaseURL, username, accessToken)
}
+1 -1
View File
@@ -300,7 +300,7 @@ func GetInfo(zcBaseURL string) ([]byte, error) {
// PushCredentials pushes OAuth credentials to a speaker using the ZeroConf DH
// key exchange protocol. If getInfo fails (older firmware without DH support),
// it falls back to the simplified tokenType=accesstoken approach.
// zcBaseURL is the base URL of the ZeroConf endpoint, e.g. "http://192.168.1.10:8200/zc".
// zcBaseURL is the base URL of the ZeroConf endpoint, e.g. "http://192.168.10.10:8200/zc".
func PushCredentials(zcBaseURL, username, accessToken string) error {
base, err := validateZcBaseURL(zcBaseURL)
if err != nil {
+3 -3
View File
@@ -133,7 +133,7 @@ import (
func main() {
// Create client
c := client.New("192.168.1.100", 8090)
c := client.New("192.0.2.100", 8090)
// Get device info
info, err := c.GetInfo()
@@ -161,10 +161,10 @@ Download the CLI tool for your platform from the releases below:
./soundtouch-cli -discover
# Get device information
./soundtouch-cli -host 192.168.1.100 -info
./soundtouch-cli -host 192.0.2.100 -info
# Monitor real-time events
./soundtouch-cli -host 192.168.1.100 -nowplaying
./soundtouch-cli -host 192.0.2.100 -nowplaying
\`\`\`
## 🧪 Tested Hardware
+1 -1
View File
@@ -14,7 +14,7 @@
# ./spotify-prime-speaker SPEAKER_IP ACCESS_TOKEN
#
# Example:
# ./spotify-prime-speaker 192.168.1.143 BQDj...your_token...
# ./spotify-prime-speaker 192.0.2.143 BQDj...your_token...
#
# How to get an access token:
# - Spotify Developer Console: https://developer.spotify.com
@@ -6,8 +6,8 @@
"serialNumber": "K12345",
"productCode": "SoundTouch test",
"productSerialNumber": "237983",
"gatewayIp": "192.168.1.1",
"deviceIp": "192.168.1.100",
"gatewayIp": "192.0.2.1",
"deviceIp": "192.0.2.100",
"macAddress1": "B05ECAFE",
"macAddress2": "B05ECAFF",
"accountId": "7654321",
@@ -29,8 +29,8 @@
"serialNumber": "K12345",
"productCode": "SoundTouch test",
"productSerialNumber": "237983",
"gatewayIp": "192.168.1.1",
"deviceIp": "192.168.1.100",
"gatewayIp": "192.0.2.1",
"deviceIp": "192.0.2.100",
"macAddress1": "B05ECAFE",
"macAddress2": "B05ECAFF",
"accountId": "7654321",