// Command dummy-speaker runs an HTTP-only fake SoundTouch speaker and // optionally registers it with a running soundtouch-service so the web UI // has a device to display. // // Intended for documentation screenshots and local UI smoke checks. Do not // use against a real network — the fixture payload is synthetic and would // confuse other tooling that expects live device data. // // Example: // // dummy-speaker --port 8090 --register http://localhost:8000 package main import ( "bytes" "context" "encoding/json" "flag" "fmt" "log" "net/http" "os" "os/signal" "syscall" "time" "github.com/gesellix/bose-soundtouch/pkg/service/testing/fakespeaker" ) func main() { listen := flag.String("listen", "127.0.0.1:8090", "bind address for the fake speaker's HTTP API") telnetListen := flag.String("telnet-listen", "127.0.0.1:17000", "bind address for the fake speaker's telnet diagnostic shell (empty to disable)") register := flag.String("register", "", "service base URL (e.g. http://localhost:8000) to self-register with via POST /setup/devices") registerAs := flag.String("register-as", "", "address to send to /setup/devices (defaults to --listen)") flag.Parse() s, err := fakespeaker.Start(fakespeaker.Config{ HTTPListen: *listen, TelnetListen: *telnetListen, }) if err != nil { log.Fatalf("start fake speaker: %v", err) } log.Printf("fake speaker HTTP listening on http://%s", sanitizeLog(s.HTTPAddr())) if addr := s.TelnetAddr(); addr != "" { log.Printf("fake speaker telnet listening on tcp://%s", sanitizeLog(addr)) } if *register != "" { target := *registerAs if target == "" { target = s.HTTPAddr() } if err := registerWithService(*register, target); err != nil { log.Printf("self-register failed: %v (continuing anyway)", err) } else { log.Printf("registered %s with service at %s", sanitizeLog(target), sanitizeLog(*register)) } } sig := make(chan os.Signal, 1) signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) <-sig log.Printf("shutting down") ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() if err := s.Stop(ctx); err != nil { log.Printf("stop: %v", err) } } func registerWithService(serviceURL, deviceAddr string) error { body, err := json.Marshal(map[string]string{"ip": deviceAddr}) if err != nil { return err } ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() req, err := http.NewRequestWithContext(ctx, http.MethodPost, serviceURL+"/setup/devices", bytes.NewReader(body)) if err != nil { return err } req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer func() { _ = resp.Body.Close() }() if resp.StatusCode >= 300 { return fmt.Errorf("service responded %s", resp.Status) } return nil }