71 lines
1.7 KiB
Go
71 lines
1.7 KiB
Go
// Copyright (c) 2024 Joshua Rich <joshua.rich@gmail.com>
|
|
//
|
|
// This software is released under the MIT License.
|
|
// https://opensource.org/licenses/MIT
|
|
|
|
package hass
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/grandcat/zeroconf"
|
|
|
|
"github.com/joshuar/go-hass-agent/internal/logging"
|
|
)
|
|
|
|
const (
|
|
haDiscoveryTimeout = 5 * time.Second
|
|
)
|
|
|
|
// FindServers is a helper function to generate a list of Home Assistant servers
|
|
// via local network auto-discovery.
|
|
func FindServers(ctx context.Context) ([]string, error) {
|
|
var serverList []string
|
|
|
|
// add http://localhost:8123 to the list of servers as a fall-back/default
|
|
serverList = append(serverList, "http://localhost:8123")
|
|
|
|
resolver, err := zeroconf.NewResolver(nil)
|
|
if err != nil {
|
|
return serverList, fmt.Errorf("failed to initialise resolver: %w", err)
|
|
}
|
|
|
|
entries := make(chan *zeroconf.ServiceEntry)
|
|
|
|
go func(results <-chan *zeroconf.ServiceEntry) {
|
|
for entry := range results {
|
|
var server string
|
|
|
|
for _, t := range entry.Text {
|
|
if value, found := strings.CutPrefix(t, "base_url="); found {
|
|
server = value
|
|
}
|
|
}
|
|
|
|
if server != "" {
|
|
serverList = append(serverList, server)
|
|
} else {
|
|
logging.FromContext(ctx).Log(ctx, logging.LevelTrace,
|
|
"Found a server malformed server, will not use.", "server", entry.HostName)
|
|
}
|
|
}
|
|
}(entries)
|
|
|
|
logging.FromContext(ctx).Info("Looking for Home Assistant servers on the local network...")
|
|
|
|
searchCtx, searchCancel := context.WithTimeout(ctx, haDiscoveryTimeout)
|
|
defer searchCancel()
|
|
|
|
err = resolver.Browse(searchCtx, "_home-assistant._tcp", "local.", entries)
|
|
if err != nil {
|
|
return serverList, fmt.Errorf("could not start search for Home Assistant servers: %w", err)
|
|
}
|
|
|
|
<-searchCtx.Done()
|
|
|
|
return serverList, nil
|
|
}
|