wemo/wemodiscovery/scan.go

76 lines
1.8 KiB
Go

package wemodiscovery
import (
"encoding/xml"
"fmt"
"net/http"
"io/ioutil"
"time"
"github.com/fromkeith/gossdp"
)
var responses []gossdp.ResponseMessage
type belkinListener struct {
// Response func(message gossdp.ResponseMessage)
}
func (l belkinListener) Response(message gossdp.ResponseMessage) {
responses = append(responses, message)
}
// Scan detects Belkin devices on the network. The devices that are returned have
// limited information in the Scan field, to get more detailed information you will
// have to call Load() on the device
func Scan(dt DeviceType, waitTimeSeconds int) ([]*Device, error) {
responses = []gossdp.ResponseMessage{}
l := belkinListener{}
c, err := gossdp.NewSsdpClientWithLogger(l, gossdp.DefaultLogger{})
if err != nil {
return nil, fmt.Errorf("failed to start ssdp discovery client: %s", err)
}
defer c.Stop()
go c.Start()
err = c.ListenFor(string(dt))
if err != nil {
return nil, fmt.Errorf("discovery failed: %s", err)
}
time.Sleep(time.Duration(waitTimeSeconds) * time.Second)
devices := make([]*Device, len(responses))
for i, response := range responses {
devices[i] = &Device{Scan: response}
}
return devices, nil
}
// Load fetches all of the device specific information and updates the calling struct. The timeout
// parameter specifies how long to wait to connect and get a response before giving up
func (d *Device) Load(timeout time.Duration) error {
client := http.Client{Timeout: timeout}
resp, err := client.Get(d.Scan.Location)
if resp != nil {
defer resp.Body.Close()
}
if err != nil {
return fmt.Errorf("error fetching device info: %s", err)
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("error reading response from device: %s", err)
}
var root root
root.Device = d
err = xml.Unmarshal(b, &root)
if err != nil {
return err
}
return nil
}