diff --git a/Device.go b/Device.go index 1e27252..292983f 100644 --- a/Device.go +++ b/Device.go @@ -2,40 +2,44 @@ package goonvif import ( "encoding/xml" - "fmt" - "github.com/beevik/etree" - "github.com/yakovlevdmv/gosoap" - "strconv" - "net/http" - "io/ioutil" - "github.com/yakovlevdmv/WS-Discovery" - "strings" - "github.com/yakovlevdmv/goonvif/Device" "errors" + "fmt" + "io/ioutil" + "net/http" "reflect" + "strconv" + "strings" + + "github.com/beevik/etree" + "github.com/use-go/go-onvif/device" + "github.com/yakovlevdmv/WS-Discovery" "github.com/yakovlevdmv/goonvif/networking" + "github.com/yakovlevdmv/gosoap" ) -var Xlmns = map[string]string { - "onvif":"http://www.onvif.org/ver10/schema", - "tds":"http://www.onvif.org/ver10/device/wsdl", - "trt":"http://www.onvif.org/ver10/media/wsdl", - "tev":"http://www.onvif.org/ver10/events/wsdl", - "tptz":"http://www.onvif.org/ver20/ptz/wsdl", - "timg":"http://www.onvif.org/ver20/imaging/wsdl", - "tan":"http://www.onvif.org/ver20/analytics/wsdl", - "xmime":"http://www.w3.org/2005/05/xmlmime", - "wsnt":"http://docs.oasis-open.org/wsn/b-2", - "xop":"http://www.w3.org/2004/08/xop/include", - "wsa":"http://www.w3.org/2005/08/addressing", - "wstop":"http://docs.oasis-open.org/wsn/t-1", - "wsntw":"http://docs.oasis-open.org/wsn/bw-2", - "wsrf-rw":"http://docs.oasis-open.org/wsrf/rw-2", - "wsaw":"http://www.w3.org/2006/05/addressing/wsdl", +//Xlmns XML Scheam +var Xlmns = map[string]string{ + "onvif": "http://www.onvif.org/ver10/schema", + "tds": "http://www.onvif.org/ver10/device/wsdl", + "trt": "http://www.onvif.org/ver10/media/wsdl", + "tev": "http://www.onvif.org/ver10/events/wsdl", + "tptz": "http://www.onvif.org/ver20/ptz/wsdl", + "timg": "http://www.onvif.org/ver20/imaging/wsdl", + "tan": "http://www.onvif.org/ver20/analytics/wsdl", + "xmime": "http://www.w3.org/2005/05/xmlmime", + "wsnt": "http://docs.oasis-open.org/wsn/b-2", + "xop": "http://www.w3.org/2004/08/xop/include", + "wsa": "http://www.w3.org/2005/08/addressing", + "wstop": "http://docs.oasis-open.org/wsn/t-1", + "wsntw": "http://docs.oasis-open.org/wsn/bw-2", + "wsrf-rw": "http://docs.oasis-open.org/wsrf/rw-2", + "wsaw": "http://www.w3.org/2006/05/addressing/wsdl", } +//DeviceType alias for int type DeviceType int +// Onvif Device Tyoe const ( NVD DeviceType = iota NVS @@ -44,7 +48,7 @@ const ( ) func (devType DeviceType) String() string { - stringRepresentation := []string { + stringRepresentation := []string{ "NetworkVideoDisplay", "NetworkVideoStorage", "NetworkVideoAnalytics", @@ -61,28 +65,26 @@ func (devType DeviceType) String() string { //deviceInfo struct contains general information about ONVIF device type deviceInfo struct { - Manufacturer string - Model string + Manufacturer string + Model string FirmwareVersion string - SerialNumber string - HardwareId string - + SerialNumber string + HardwareId string } -//deviceInfo struct represents an abstract ONVIF device. +//Device for a new device of onvif and deviceInfo +//struct represents an abstract ONVIF device. //It contains methods, which helps to communicate with ONVIF device -type device struct { - - xaddr string - login string - password string - +type Device struct { + xaddr string + login string + password string endpoints map[string]string - info deviceInfo - + info deviceInfo } -func (dev *device)GetServices() map[string]string { +//GetServices return available endpoints +func (dev *Device) GetServices() map[string]string { return dev.endpoints } @@ -94,12 +96,13 @@ func readResponse(resp *http.Response) string { return string(b) } -func GetAvailableDevicesAtSpecificEthernetInterface(interfaceName string) []device { +//GetAvailableDevicesAtSpecificEthernetInterface ... +func GetAvailableDevicesAtSpecificEthernetInterface(interfaceName string) []Device { /* - Call an WS-Discovery Probe Message to Discover NVT type Devices - */ - devices := WS_Discovery.SendProbe(interfaceName, nil, []string{"dn:"+NVT.String()}, map[string]string{"dn":"http://www.onvif.org/ver10/network/wsdl"}) - nvtDevices := make([]device, 0) + Call an WS-Discovery Probe Message to Discover NVT type Devices + */ + devices := WS_Discovery.SendProbe(interfaceName, nil, []string{"dn:" + NVT.String()}, map[string]string{"dn": "http://www.onvif.org/ver10/network/wsdl"}) + nvtDevices := make([]Device, 0) ////fmt.Println(devices) for _, j := range devices { doc := etree.NewDocument() @@ -140,37 +143,37 @@ func GetAvailableDevicesAtSpecificEthernetInterface(interfaceName string) []devi return nvtDevices } -func (dev *device) getSupportedServices(resp *http.Response) { +func (dev *Device) getSupportedServices(resp *http.Response) { //resp, err := dev.CallMethod(Device.GetCapabilities{Category:"All"}) //if err != nil { // log.Println(err.Error()) - //return + //return //} else { - doc := etree.NewDocument() + doc := etree.NewDocument() - data, _ := ioutil.ReadAll(resp.Body) + data, _ := ioutil.ReadAll(resp.Body) - if err := doc.ReadFromBytes(data); err != nil { - //log.Println(err.Error()) - return - } - services := doc.FindElements("./Envelope/Body/GetCapabilitiesResponse/Capabilities/*/XAddr") - for _, j := range services{ - ////fmt.Println(j.Text()) - ////fmt.Println(j.Parent().Tag) - dev.addEndpoint(j.Parent().Tag, j.Text()) - } + if err := doc.ReadFromBytes(data); err != nil { + //log.Println(err.Error()) + return + } + services := doc.FindElements("./Envelope/Body/GetCapabilitiesResponse/Capabilities/*/XAddr") + for _, j := range services { + ////fmt.Println(j.Text()) + ////fmt.Println(j.Parent().Tag) + dev.addEndpoint(j.Parent().Tag, j.Text()) + } //} } //NewDevice function construct a ONVIF Device entity -func NewDevice(xaddr string) (*device, error) { - dev := new(device) +func NewDevice(xaddr string) (*Device, error) { + dev := new(Device) dev.xaddr = xaddr dev.endpoints = make(map[string]string) dev.addEndpoint("Device", "http://"+xaddr+"/onvif/device_service") - getCapabilities := Device.GetCapabilities{Category: "All"} + getCapabilities := device.GetCapabilities{Category: "All"} resp, err := dev.CallMethod(getCapabilities) //fmt.Println(resp.Request.Host) @@ -184,25 +187,24 @@ func NewDevice(xaddr string) (*device, error) { return dev, nil } -func (dev *device)addEndpoint(Key, Value string) { - dev.endpoints[Key]=Value +func (dev *Device) addEndpoint(Key, Value string) { + dev.endpoints[Key] = Value } //Authenticate function authenticate client in the ONVIF Device. //Function takes and params. //You should use this function to allow authorized requests to the ONVIF Device //To change auth data call this function again. -func (dev *device) Authenticate(username, password string) { +func (dev *Device) Authenticate(username, password string) { dev.login = username dev.password = password } //GetEndpoint returns specific ONVIF service endpoint address -func (dev *device) GetEndpoint(name string) string { +func (dev *Device) GetEndpoint(name string) string { return dev.endpoints[name] } - func buildMethodSOAP(msg string) (gosoap.SoapMessage, error) { doc := etree.NewDocument() if err := doc.ReadFromString(msg); err != nil { @@ -212,7 +214,6 @@ func buildMethodSOAP(msg string) (gosoap.SoapMessage, error) { } element := doc.Root() - soap := gosoap.NewEmptySOAP() soap.AddBodyContent(element) //soap.AddRootNamespace("onvif", "http://www.onvif.org/ver10/device/wsdl") @@ -220,21 +221,24 @@ func buildMethodSOAP(msg string) (gosoap.SoapMessage, error) { return soap, nil } - - //CallMethod functions call an method, defined struct. //You should use Authenticate method to call authorized requests. -func (dev device) CallMethod(method interface{}) (*http.Response, error) { - pkgPath := strings.Split(reflect.TypeOf(method).PkgPath(),"/") +func (dev Device) CallMethod(method interface{}) (*http.Response, error) { + pkgPath := strings.Split(reflect.TypeOf(method).PkgPath(), "/") pkg := pkgPath[len(pkgPath)-1] var endpoint string switch pkg { - case "Device": endpoint = dev.endpoints["Device"] - case "Event": endpoint = dev.endpoints["Event"] - case "Imaging": endpoint = dev.endpoints["Imaging"] - case "Media": endpoint = dev.endpoints["Media"] - case "PTZ": endpoint = dev.endpoints["PTZ"] + case "Device": + endpoint = dev.endpoints["Device"] + case "Event": + endpoint = dev.endpoints["Event"] + case "Imaging": + endpoint = dev.endpoints["Imaging"] + case "Media": + endpoint = dev.endpoints["Media"] + case "PTZ": + endpoint = dev.endpoints["PTZ"] } //TODO: Get endpoint automatically @@ -246,11 +250,11 @@ func (dev device) CallMethod(method interface{}) (*http.Response, error) { } //CallNonAuthorizedMethod functions call an method, defined struct without authentication data -func (dev device) callNonAuthorizedMethod(endpoint string, method interface{}) (*http.Response, error) { +func (dev Device) callNonAuthorizedMethod(endpoint string, method interface{}) (*http.Response, error) { //TODO: Get endpoint automatically /* - Converting struct to xml string representation - */ + Converting struct to xml string representation + */ output, err := xml.MarshalIndent(method, " ", " ") if err != nil { //log.Printf("error: %v\n", err.Error()) @@ -258,8 +262,8 @@ func (dev device) callNonAuthorizedMethod(endpoint string, method interface{}) ( } /* - Build an SOAP request with - */ + Build an SOAP request with + */ soap, err := buildMethodSOAP(string(output)) if err != nil { //log.Printf("error: %v\n", err) @@ -267,21 +271,21 @@ func (dev device) callNonAuthorizedMethod(endpoint string, method interface{}) ( } /* - Adding namespaces - */ + Adding namespaces + */ soap.AddRootNamespaces(Xlmns) /* - Sending request and returns the response - */ + Sending request and returns the response + */ return networking.SendSoap(endpoint, soap.String()) } //CallMethod functions call an method, defined struct with authentication data -func (dev device) callAuthorizedMethod(endpoint string, method interface{}) (*http.Response, error) { +func (dev Device) callAuthorizedMethod(endpoint string, method interface{}) (*http.Response, error) { /* - Converting struct to xml string representation - */ + Converting struct to xml string representation + */ output, err := xml.MarshalIndent(method, " ", " ") if err != nil { //log.Printf("error: %v\n", err.Error()) @@ -289,8 +293,8 @@ func (dev device) callAuthorizedMethod(endpoint string, method interface{}) (*ht } /* - Build an SOAP request with - */ + Build an SOAP request with + */ soap, err := buildMethodSOAP(string(output)) if err != nil { //log.Printf("error: %v\n", err.Error()) @@ -298,14 +302,13 @@ func (dev device) callAuthorizedMethod(endpoint string, method interface{}) (*ht } /* - Adding namespaces and WS-Security headers - */ + Adding namespaces and WS-Security headers + */ soap.AddRootNamespaces(Xlmns) soap.AddWSSecurity(dev.login, dev.password) - /* - Sending request and returns the response - */ + Sending request and returns the response + */ return networking.SendSoap(endpoint, soap.String()) -} \ No newline at end of file +}