Skip to content

Commit bc3226e

Browse files
authored
Merge pull request #22 from jfsmig/fixes-ws-discovery-20220510
Misc. fixes in the WS discovery
2 parents d8d0fc3 + 9e25a01 commit bc3226e

File tree

209 files changed

+6363
-157
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

209 files changed

+6363
-157
lines changed

Device.go

+18-32
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package onvif
33
import (
44
"encoding/xml"
55
"errors"
6-
"fmt"
76
"io/ioutil"
87
"net/http"
98
"net/url"
@@ -108,50 +107,37 @@ func readResponse(resp *http.Response) string {
108107
}
109108

110109
//GetAvailableDevicesAtSpecificEthernetInterface ...
111-
func GetAvailableDevicesAtSpecificEthernetInterface(interfaceName string) []Device {
112-
/*
113-
Call an ws-discovery Probe Message to Discover NVT type Devices
114-
*/
115-
devices := wsdiscovery.SendProbe(interfaceName, nil, []string{"dn:" + NVT.String()}, map[string]string{"dn": "http://www.onvif.org/ver10/network/wsdl"})
110+
func GetAvailableDevicesAtSpecificEthernetInterface(interfaceName string) ([]Device, error) {
111+
// Call a ws-discovery Probe Message to Discover NVT type Devices
112+
devices, err := wsdiscovery.SendProbe(interfaceName, nil, []string{"dn:" + NVT.String()}, map[string]string{"dn": "http://www.onvif.org/ver10/network/wsdl"})
113+
if err != nil {
114+
return nil, err
115+
}
116+
117+
nvtDevicesSeen := make(map[string]bool)
116118
nvtDevices := make([]Device, 0)
117119

118120
for _, j := range devices {
119121
doc := etree.NewDocument()
120122
if err := doc.ReadFromString(j); err != nil {
121-
fmt.Errorf("%s", err.Error())
122-
return nil
123+
return nil, err
123124
}
124125

125-
endpoints := doc.Root().FindElements("./Body/ProbeMatches/ProbeMatch/XAddrs")
126-
for _, xaddr := range endpoints {
126+
for _, xaddr := range doc.Root().FindElements("./Body/ProbeMatches/ProbeMatch/XAddrs") {
127127
xaddr := strings.Split(strings.Split(xaddr.Text(), " ")[0], "/")[2]
128-
fmt.Println(xaddr)
129-
c := 0
130-
131-
for c = 0; c < len(nvtDevices); c++ {
132-
if nvtDevices[c].params.Xaddr == xaddr {
133-
fmt.Println(nvtDevices[c].params.Xaddr, "==", xaddr)
134-
break
128+
if !nvtDevicesSeen[xaddr] {
129+
dev, err := NewDevice(DeviceParams{Xaddr: strings.Split(xaddr, " ")[0]})
130+
if err != nil {
131+
// TODO(jfsmig) print a warning
132+
} else {
133+
nvtDevicesSeen[xaddr] = true
134+
nvtDevices = append(nvtDevices, *dev)
135135
}
136136
}
137-
138-
if c < len(nvtDevices) {
139-
continue
140-
}
141-
142-
dev, err := NewDevice(DeviceParams{Xaddr: strings.Split(xaddr, " ")[0]})
143-
144-
if err != nil {
145-
fmt.Println("Error", xaddr)
146-
fmt.Println(err)
147-
continue
148-
} else {
149-
nvtDevices = append(nvtDevices, *dev)
150-
}
151137
}
152138
}
153139

154-
return nvtDevices
140+
return nvtDevices, nil
155141
}
156142

157143
func (dev *Device) getSupportedServices(resp *http.Response) {

api/api.go

+64-70
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
package api
22

33
import (
4-
"errors"
5-
"fmt"
64
"io/ioutil"
75
"net/http"
6+
"os"
87
"path"
98
"reflect"
109
"regexp"
1110
"strings"
11+
"time"
12+
13+
"github.com/juju/errors"
14+
"github.com/rs/zerolog"
1215

1316
"github.com/beevik/etree"
1417
"github.com/gin-gonic/gin"
@@ -18,6 +21,18 @@ import (
1821
wsdiscovery "github.com/use-go/onvif/ws-discovery"
1922
)
2023

24+
var (
25+
// LoggerContext is the builder of a zerolog.Logger that is exposed to the application so that
26+
// options at the CLI might alter the formatting and the output of the logs.
27+
LoggerContext = zerolog.
28+
New(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).
29+
With().Timestamp()
30+
31+
// Logger is a zerolog logger, that can be safely used from any part of the application.
32+
// It gathers the format and the output.
33+
Logger = LoggerContext.Logger()
34+
)
35+
2136
func RunApi() {
2237
router := gin.Default()
2338

@@ -32,7 +47,7 @@ func RunApi() {
3247
xaddr := c.GetHeader("xaddr")
3348
acceptedData, err := c.GetRawData()
3449
if err != nil {
35-
fmt.Println(err)
50+
Logger.Debug().Err(err).Msg("Failed to get rawx data")
3651
}
3752

3853
message, err := callNecessaryMethod(serviceName, methodName, string(acceptedData), username, pass, xaddr)
@@ -49,71 +64,52 @@ func RunApi() {
4964

5065
interfaceName := context.GetHeader("interface")
5166

52-
var response = "["
53-
devices := wsdiscovery.SendProbe(interfaceName, nil, []string{"dn:NetworkVideoTransmitter"}, map[string]string{"dn": "http://www.onvif.org/ver10/network/wsdl"})
67+
devices, err := wsdiscovery.SendProbe(interfaceName, nil, []string{"dn:NetworkVideoTransmitter"}, map[string]string{"dn": "http://www.onvif.org/ver10/network/wsdl"})
68+
if err != nil {
69+
context.String(http.StatusInternalServerError, "error")
70+
} else {
71+
response := "["
5472

55-
for _, j := range devices {
56-
doc := etree.NewDocument()
57-
if err := doc.ReadFromString(j); err != nil {
58-
context.XML(http.StatusBadRequest, err.Error())
59-
} else {
73+
for _, j := range devices {
74+
doc := etree.NewDocument()
75+
if err := doc.ReadFromString(j); err != nil {
76+
context.XML(http.StatusBadRequest, err.Error())
77+
} else {
6078

61-
endpoints := doc.Root().FindElements("./Body/ProbeMatches/ProbeMatch/XAddrs")
62-
scopes := doc.Root().FindElements("./Body/ProbeMatches/ProbeMatch/Scopes")
79+
endpoints := doc.Root().FindElements("./Body/ProbeMatches/ProbeMatch/XAddrs")
80+
scopes := doc.Root().FindElements("./Body/ProbeMatches/ProbeMatch/Scopes")
6381

64-
flag := false
82+
flag := false
6583

66-
for _, xaddr := range endpoints {
67-
xaddr := strings.Split(strings.Split(xaddr.Text(), " ")[0], "/")[2]
68-
if strings.Contains(response, xaddr) {
69-
flag = true
84+
for _, xaddr := range endpoints {
85+
xaddr := strings.Split(strings.Split(xaddr.Text(), " ")[0], "/")[2]
86+
if strings.Contains(response, xaddr) {
87+
flag = true
88+
break
89+
}
90+
response += "{"
91+
response += `"url":"` + xaddr + `",`
92+
}
93+
if flag {
7094
break
7195
}
72-
response += "{"
73-
response += `"url":"` + xaddr + `",`
74-
}
75-
if flag {
76-
break
77-
}
78-
for _, scope := range scopes {
79-
re := regexp.MustCompile(`onvif:\/\/www\.onvif\.org\/name\/[A-Za-z0-9-]+`)
80-
match := re.FindStringSubmatch(scope.Text())
81-
response += `"name":"` + path.Base(match[0]) + `"`
96+
for _, scope := range scopes {
97+
re := regexp.MustCompile(`onvif:\/\/www\.onvif\.org\/name\/[A-Za-z0-9-]+`)
98+
match := re.FindStringSubmatch(scope.Text())
99+
response += `"name":"` + path.Base(match[0]) + `"`
100+
}
101+
response += "},"
82102
}
83-
response += "},"
84-
85103
}
86-
87-
}
88-
response = strings.TrimRight(response, ",")
89-
response += "]"
90-
if response != "" {
104+
response = strings.TrimRight(response, ",")
105+
response += "]"
91106
context.String(http.StatusOK, response)
92107
}
93108
})
94109

95110
router.Run()
96111
}
97112

98-
//func soapHandling(tp interface{}, tags* map[string]string) {
99-
// ifaceValue := reflect.ValueOf(tp).Elem()
100-
// typeOfStruct := ifaceValue.Type()
101-
// if ifaceValue.Kind() != reflect.Struct {
102-
// return
103-
// }
104-
// for i := 0; i < ifaceValue.NumField(); i++ {
105-
// field := ifaceValue.Field(i)
106-
// tg, err := typeOfStruct.FieldByName(typeOfStruct.Field(i).Name)
107-
// if err == false {
108-
// fmt.Println(err)
109-
// }
110-
// (*tags)[typeOfStruct.Field(i).Name] = string(tg.Tag)
111-
//
112-
// subStruct := reflect.New(reflect.TypeOf( field.Interface() ))
113-
// soapHandling(subStruct.Interface(), tags)
114-
// }
115-
//}
116-
117113
func callNecessaryMethod(serviceName, methodName, acceptedData, username, password, xaddr string) (string, error) {
118114
var methodStruct interface{}
119115
var err error
@@ -129,17 +125,17 @@ func callNecessaryMethod(serviceName, methodName, acceptedData, username, passwo
129125
return "", errors.New("there is no such service")
130126
}
131127
if err != nil { //done
132-
return "", err
128+
return "", errors.Annotate(err, "getStructByName")
133129
}
134130

135131
resp, err := xmlAnalize(methodStruct, &acceptedData)
136132
if err != nil {
137-
return "", err
133+
return "", errors.Annotate(err, "xmlAnalize")
138134
}
139135

140136
endpoint, err := getEndpoint(serviceName, xaddr)
141137
if err != nil {
142-
return "", err
138+
return "", errors.Annotate(err, "getEndpoint")
143139
}
144140

145141
soap := gosoap.NewEmptySOAP()
@@ -149,12 +145,12 @@ func callNecessaryMethod(serviceName, methodName, acceptedData, username, passwo
149145

150146
servResp, err := networking.SendSoap(new(http.Client), endpoint, soap.String())
151147
if err != nil {
152-
return "", err
148+
return "", errors.Annotate(err, "SendSoap")
153149
}
154150

155151
rsp, err := ioutil.ReadAll(servResp.Body)
156152
if err != nil {
157-
return "", err
153+
return "", errors.Annotate(err, "ReadAll")
158154
}
159155

160156
return string(rsp), nil
@@ -163,7 +159,7 @@ func callNecessaryMethod(serviceName, methodName, acceptedData, username, passwo
163159
func getEndpoint(service, xaddr string) (string, error) {
164160
dev, err := onvif.NewDevice(onvif.DeviceParams{Xaddr: xaddr})
165161
if err != nil {
166-
return "", err
162+
return "", errors.Annotate(err, "NewDevice")
167163
}
168164
pkg := strings.ToLower(service)
169165

@@ -193,7 +189,7 @@ func xmlAnalize(methodStruct interface{}, acceptedData *string) (*string, error)
193189

194190
doc := etree.NewDocument()
195191
if err := doc.ReadFromString(*acceptedData); err != nil {
196-
return nil, err
192+
return nil, errors.Annotate(err, "readFromString")
197193
}
198194
etr := doc.FindElements("./*")
199195
xmlUnmarshal(etr, &testunMarshal, &mas)
@@ -207,7 +203,7 @@ func xmlAnalize(methodStruct interface{}, acceptedData *string) (*string, error)
207203
lst := (testunMarshal)[lstIndex]
208204
elemName, attr, value, err := xmlMaker(&lst, &test, lstIndex)
209205
if err != nil {
210-
return nil, err
206+
return nil, errors.Annotate(err, "xmlMarker")
211207
}
212208

213209
if mas[lstIndex] == "Push" && lstIndex == 0 { //done
@@ -251,10 +247,10 @@ func xmlAnalize(methodStruct interface{}, acceptedData *string) (*string, error)
251247

252248
resp, err := document.WriteToString()
253249
if err != nil {
254-
return nil, err
250+
return nil, errors.Annotate(err, "writeToString")
255251
}
256252

257-
return &resp, err
253+
return &resp, nil
258254
}
259255

260256
func xmlMaker(lst *[]interface{}, tags *[]map[string]string, lstIndex int) (string, map[string]string, string, error) {
@@ -273,13 +269,13 @@ func xmlMaker(lst *[]interface{}, tags *[]map[string]string, lstIndex int) (stri
273269
if index == 0 && lstIndex == 0 {
274270
res, err := xmlProcessing(tg["XMLName"])
275271
if err != nil {
276-
return "", nil, "", err
272+
return "", nil, "", errors.Annotate(err, "xmlProcessing")
277273
}
278274
elemName = res
279275
} else if index == 0 {
280276
res, err := xmlProcessing(tg[conversion])
281277
if err != nil {
282-
return "", nil, "", err
278+
return "", nil, "", errors.Annotate(err, "xmlProcessing")
283279
}
284280
elemName = res
285281
} else {
@@ -314,8 +310,6 @@ func xmlProcessing(tg string) (string, error) {
314310
} else {
315311
return str[1][0:omitAttr], nil
316312
}
317-
318-
return "", errors.New("something went wrong")
319313
}
320314

321315
func mapProcessing(mapVar []map[string]string) []map[string]string {
@@ -343,9 +337,9 @@ func soapHandling(tp interface{}, tags *[]map[string]string) {
343337
}
344338
for i := 0; i < s.NumField(); i++ {
345339
f := s.Field(i)
346-
tmp, err := typeOfT.FieldByName(typeOfT.Field(i).Name)
347-
if err == false {
348-
fmt.Println(err)
340+
tmp, ok := typeOfT.FieldByName(typeOfT.Field(i).Name)
341+
if !ok {
342+
Logger.Debug().Str("field", typeOfT.Field(i).Name).Msg("reflection failed")
349343
}
350344
*tags = append(*tags, map[string]string{typeOfT.Field(i).Name: string(tmp.Tag)})
351345
subStruct := reflect.New(reflect.TypeOf(f.Interface()))

0 commit comments

Comments
 (0)