-
Notifications
You must be signed in to change notification settings - Fork 7
/
device.go
101 lines (83 loc) · 2.43 KB
/
device.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package ssdp
import (
"encoding/xml"
"io"
"net/http"
"net/url"
"time"
)
type Device struct {
SpecVersion SpecVersion `xml:"specVersion"`
URLBase string `xml:"URLBase"`
DeviceType string `xml:"device>deviceType"`
FriendlyName string `xml:"device>friendlyName"`
Manufacturer string `xml:"device>manufacturer"`
ManufacturerURL string `xml:"device>manufacturerURL"`
ModelDescription string `xml:"device>modelDescription"`
ModelName string `xml:"device>modelName"`
ModelNumber string `xml:"device>modelNumber"`
ModelURL string `xml:"device>modelURL"`
SerialNumber string `xml:"device>serialNumber"`
UDN string `xml:"device>UDN"`
UPC string `xml:"device>UPC"`
PresentationURL string `xml:"device>presentationURL"`
Icons []Icon `xml:"device>iconList>icon"`
}
type SpecVersion struct {
Major int `xml:"major"`
Minor int `xml:"minor"`
}
type Icon struct {
MIMEType string `xml:"mimetype"`
Width int `xml:"width"`
Height int `xml:"height"`
Depth int `xml:"depth"`
URL string `xml:"url"`
}
func SearchForDevices(st string, mx time.Duration) ([]Device, error) {
responses, err := Search(st, mx)
if err != nil {
return nil, err
}
locations := reduceOnLocation(responses)
return collectDevices(locations)
}
func collectDevices(locations []url.URL) ([]Device, error) {
devices := make([]Device, 0, len(locations))
for _, location := range locations {
device, err := getDescriptionXml(location)
if err != nil {
return nil, err
}
devices = append(devices, *device)
}
return devices, nil
}
func getDescriptionXml(url url.URL) (*Device, error) {
response, err := http.Get(url.String())
if err != nil {
return nil, err
}
defer response.Body.Close()
return decodeDescription(response.Body)
}
func reduceOnLocation(responses []SearchResponse) []url.URL {
uniqueLocations := make(map[url.URL]bool)
for _, response := range responses {
uniqueLocations[*response.Location] = true
}
locations := make([]url.URL, 0, len(uniqueLocations))
for location, _ := range uniqueLocations {
locations = append(locations, location)
}
return locations
}
func decodeDescription(reader io.Reader) (*Device, error) {
decoder := xml.NewDecoder(reader)
device := &Device{}
err := decoder.Decode(device)
if err != nil {
return nil, err
}
return device, nil
}