mirror of
				https://github.com/kerberos-io/onvif.git
				synced 2025-10-31 10:56:38 +08:00 
			
		
		
		
	Expose Device type for outer developer using & format code file
This commit is contained in:
		
							
								
								
									
										199
									
								
								Device.go
									
									
									
									
									
								
							
							
						
						
									
										199
									
								
								Device.go
									
									
									
									
									
								
							| @@ -2,40 +2,44 @@ package goonvif | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"encoding/xml" | 	"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" | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"net/http" | ||||||
| 	"reflect" | 	"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/goonvif/networking" | ||||||
|  | 	"github.com/yakovlevdmv/gosoap" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var Xlmns = map[string]string { | //Xlmns XML Scheam | ||||||
| 	"onvif":"http://www.onvif.org/ver10/schema", | var Xlmns = map[string]string{ | ||||||
| 	"tds":"http://www.onvif.org/ver10/device/wsdl", | 	"onvif":   "http://www.onvif.org/ver10/schema", | ||||||
| 	"trt":"http://www.onvif.org/ver10/media/wsdl", | 	"tds":     "http://www.onvif.org/ver10/device/wsdl", | ||||||
| 	"tev":"http://www.onvif.org/ver10/events/wsdl", | 	"trt":     "http://www.onvif.org/ver10/media/wsdl", | ||||||
| 	"tptz":"http://www.onvif.org/ver20/ptz/wsdl", | 	"tev":     "http://www.onvif.org/ver10/events/wsdl", | ||||||
| 	"timg":"http://www.onvif.org/ver20/imaging/wsdl", | 	"tptz":    "http://www.onvif.org/ver20/ptz/wsdl", | ||||||
| 	"tan":"http://www.onvif.org/ver20/analytics/wsdl", | 	"timg":    "http://www.onvif.org/ver20/imaging/wsdl", | ||||||
| 	"xmime":"http://www.w3.org/2005/05/xmlmime", | 	"tan":     "http://www.onvif.org/ver20/analytics/wsdl", | ||||||
| 	"wsnt":"http://docs.oasis-open.org/wsn/b-2", | 	"xmime":   "http://www.w3.org/2005/05/xmlmime", | ||||||
| 	"xop":"http://www.w3.org/2004/08/xop/include", | 	"wsnt":    "http://docs.oasis-open.org/wsn/b-2", | ||||||
| 	"wsa":"http://www.w3.org/2005/08/addressing", | 	"xop":     "http://www.w3.org/2004/08/xop/include", | ||||||
| 	"wstop":"http://docs.oasis-open.org/wsn/t-1", | 	"wsa":     "http://www.w3.org/2005/08/addressing", | ||||||
| 	"wsntw":"http://docs.oasis-open.org/wsn/bw-2", | 	"wstop":   "http://docs.oasis-open.org/wsn/t-1", | ||||||
| 	"wsrf-rw":"http://docs.oasis-open.org/wsrf/rw-2", | 	"wsntw":   "http://docs.oasis-open.org/wsn/bw-2", | ||||||
| 	"wsaw":"http://www.w3.org/2006/05/addressing/wsdl", | 	"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 | type DeviceType int | ||||||
|  |  | ||||||
|  | // Onvif Device Tyoe | ||||||
| const ( | const ( | ||||||
| 	NVD DeviceType = iota | 	NVD DeviceType = iota | ||||||
| 	NVS | 	NVS | ||||||
| @@ -44,7 +48,7 @@ const ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| func (devType DeviceType) String() string { | func (devType DeviceType) String() string { | ||||||
| 	stringRepresentation := []string { | 	stringRepresentation := []string{ | ||||||
| 		"NetworkVideoDisplay", | 		"NetworkVideoDisplay", | ||||||
| 		"NetworkVideoStorage", | 		"NetworkVideoStorage", | ||||||
| 		"NetworkVideoAnalytics", | 		"NetworkVideoAnalytics", | ||||||
| @@ -61,28 +65,26 @@ func (devType DeviceType) String() string { | |||||||
|  |  | ||||||
| //deviceInfo struct contains general information about ONVIF device | //deviceInfo struct contains general information about ONVIF device | ||||||
| type deviceInfo struct { | type deviceInfo struct { | ||||||
| 	Manufacturer string | 	Manufacturer    string | ||||||
| 	Model string | 	Model           string | ||||||
| 	FirmwareVersion string | 	FirmwareVersion string | ||||||
| 	SerialNumber string | 	SerialNumber    string | ||||||
| 	HardwareId 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 | //It contains methods, which helps to communicate with ONVIF device | ||||||
| type device struct { | type Device struct { | ||||||
|  | 	xaddr     string | ||||||
| 	xaddr string | 	login     string | ||||||
| 	login string | 	password  string | ||||||
| 	password string |  | ||||||
|  |  | ||||||
| 	endpoints map[string]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 | 	return dev.endpoints | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -94,12 +96,13 @@ func readResponse(resp *http.Response) string { | |||||||
| 	return string(b) | 	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 | 		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"}) | 	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) | 	nvtDevices := make([]Device, 0) | ||||||
| 	////fmt.Println(devices) | 	////fmt.Println(devices) | ||||||
| 	for _, j := range devices { | 	for _, j := range devices { | ||||||
| 		doc := etree.NewDocument() | 		doc := etree.NewDocument() | ||||||
| @@ -140,37 +143,37 @@ func GetAvailableDevicesAtSpecificEthernetInterface(interfaceName string) []devi | |||||||
| 	return nvtDevices | 	return nvtDevices | ||||||
| } | } | ||||||
|  |  | ||||||
| func (dev *device) getSupportedServices(resp *http.Response) { | func (dev *Device) getSupportedServices(resp *http.Response) { | ||||||
| 	//resp, err := dev.CallMethod(Device.GetCapabilities{Category:"All"}) | 	//resp, err := dev.CallMethod(Device.GetCapabilities{Category:"All"}) | ||||||
| 	//if err != nil { | 	//if err != nil { | ||||||
| 	//	log.Println(err.Error()) | 	//	log.Println(err.Error()) | ||||||
| 		//return | 	//return | ||||||
| 	//} else { | 	//} else { | ||||||
| 		doc := etree.NewDocument() | 	doc := etree.NewDocument() | ||||||
|  |  | ||||||
| 		data, _ := ioutil.ReadAll(resp.Body) | 	data, _ := ioutil.ReadAll(resp.Body) | ||||||
|  |  | ||||||
| 		if err := doc.ReadFromBytes(data); err != nil { | 	if err := doc.ReadFromBytes(data); err != nil { | ||||||
| 			//log.Println(err.Error()) | 		//log.Println(err.Error()) | ||||||
| 			return | 		return | ||||||
| 		} | 	} | ||||||
| 		services := doc.FindElements("./Envelope/Body/GetCapabilitiesResponse/Capabilities/*/XAddr") | 	services := doc.FindElements("./Envelope/Body/GetCapabilitiesResponse/Capabilities/*/XAddr") | ||||||
| 		for _, j := range services{ | 	for _, j := range services { | ||||||
| 			////fmt.Println(j.Text()) | 		////fmt.Println(j.Text()) | ||||||
| 			////fmt.Println(j.Parent().Tag) | 		////fmt.Println(j.Parent().Tag) | ||||||
| 			dev.addEndpoint(j.Parent().Tag, j.Text()) | 		dev.addEndpoint(j.Parent().Tag, j.Text()) | ||||||
| 		} | 	} | ||||||
| 	//} | 	//} | ||||||
| } | } | ||||||
|  |  | ||||||
| //NewDevice function construct a ONVIF Device entity | //NewDevice function construct a ONVIF Device entity | ||||||
| func NewDevice(xaddr string) (*device, error) { | func NewDevice(xaddr string) (*Device, error) { | ||||||
| 	dev := new(device) | 	dev := new(Device) | ||||||
| 	dev.xaddr = xaddr | 	dev.xaddr = xaddr | ||||||
| 	dev.endpoints = make(map[string]string) | 	dev.endpoints = make(map[string]string) | ||||||
| 	dev.addEndpoint("Device", "http://"+xaddr+"/onvif/device_service") | 	dev.addEndpoint("Device", "http://"+xaddr+"/onvif/device_service") | ||||||
|  |  | ||||||
| 	getCapabilities := Device.GetCapabilities{Category: "All"} | 	getCapabilities := device.GetCapabilities{Category: "All"} | ||||||
|  |  | ||||||
| 	resp, err := dev.CallMethod(getCapabilities) | 	resp, err := dev.CallMethod(getCapabilities) | ||||||
| 	//fmt.Println(resp.Request.Host) | 	//fmt.Println(resp.Request.Host) | ||||||
| @@ -184,25 +187,24 @@ func NewDevice(xaddr string) (*device, error) { | |||||||
| 	return dev, nil | 	return dev, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (dev *device)addEndpoint(Key, Value string) { | func (dev *Device) addEndpoint(Key, Value string) { | ||||||
| 	dev.endpoints[Key]=Value | 	dev.endpoints[Key] = Value | ||||||
| } | } | ||||||
|  |  | ||||||
| //Authenticate function authenticate client in the ONVIF Device. | //Authenticate function authenticate client in the ONVIF Device. | ||||||
| //Function takes <username> and <password> params. | //Function takes <username> and <password> params. | ||||||
| //You should use this function to allow authorized requests to the ONVIF Device | //You should use this function to allow authorized requests to the ONVIF Device | ||||||
| //To change auth data call this function again. | //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.login = username | ||||||
| 	dev.password = password | 	dev.password = password | ||||||
| } | } | ||||||
|  |  | ||||||
| //GetEndpoint returns specific ONVIF service endpoint address | //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] | 	return dev.endpoints[name] | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| func buildMethodSOAP(msg string) (gosoap.SoapMessage, error) { | func buildMethodSOAP(msg string) (gosoap.SoapMessage, error) { | ||||||
| 	doc := etree.NewDocument() | 	doc := etree.NewDocument() | ||||||
| 	if err := doc.ReadFromString(msg); err != nil { | 	if err := doc.ReadFromString(msg); err != nil { | ||||||
| @@ -212,7 +214,6 @@ func buildMethodSOAP(msg string) (gosoap.SoapMessage, error) { | |||||||
| 	} | 	} | ||||||
| 	element := doc.Root() | 	element := doc.Root() | ||||||
|  |  | ||||||
|  |  | ||||||
| 	soap := gosoap.NewEmptySOAP() | 	soap := gosoap.NewEmptySOAP() | ||||||
| 	soap.AddBodyContent(element) | 	soap.AddBodyContent(element) | ||||||
| 	//soap.AddRootNamespace("onvif", "http://www.onvif.org/ver10/device/wsdl") | 	//soap.AddRootNamespace("onvif", "http://www.onvif.org/ver10/device/wsdl") | ||||||
| @@ -220,21 +221,24 @@ func buildMethodSOAP(msg string) (gosoap.SoapMessage, error) { | |||||||
| 	return soap, nil | 	return soap, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //CallMethod functions call an method, defined <method> struct. | //CallMethod functions call an method, defined <method> struct. | ||||||
| //You should use Authenticate method to call authorized requests. | //You should use Authenticate method to call authorized requests. | ||||||
| func (dev device) CallMethod(method interface{}) (*http.Response, error) { | func (dev Device) CallMethod(method interface{}) (*http.Response, error) { | ||||||
| 	pkgPath := strings.Split(reflect.TypeOf(method).PkgPath(),"/") | 	pkgPath := strings.Split(reflect.TypeOf(method).PkgPath(), "/") | ||||||
| 	pkg := pkgPath[len(pkgPath)-1] | 	pkg := pkgPath[len(pkgPath)-1] | ||||||
|  |  | ||||||
| 	var endpoint string | 	var endpoint string | ||||||
| 	switch pkg { | 	switch pkg { | ||||||
| 		case "Device": endpoint = dev.endpoints["Device"] | 	case "Device": | ||||||
| 		case "Event": endpoint = dev.endpoints["Event"] | 		endpoint = dev.endpoints["Device"] | ||||||
| 		case "Imaging": endpoint = dev.endpoints["Imaging"] | 	case "Event": | ||||||
| 		case "Media": endpoint = dev.endpoints["Media"] | 		endpoint = dev.endpoints["Event"] | ||||||
| 		case "PTZ": endpoint = dev.endpoints["PTZ"] | 	case "Imaging": | ||||||
|  | 		endpoint = dev.endpoints["Imaging"] | ||||||
|  | 	case "Media": | ||||||
|  | 		endpoint = dev.endpoints["Media"] | ||||||
|  | 	case "PTZ": | ||||||
|  | 		endpoint = dev.endpoints["PTZ"] | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	//TODO: Get endpoint automatically | 	//TODO: Get endpoint automatically | ||||||
| @@ -246,11 +250,11 @@ func (dev device) CallMethod(method interface{}) (*http.Response, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| //CallNonAuthorizedMethod functions call an method, defined <method> struct without authentication data | //CallNonAuthorizedMethod functions call an method, defined <method> 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 | 	//TODO: Get endpoint automatically | ||||||
| 	/* | 	/* | ||||||
| 	Converting <method> struct to xml string representation | 		Converting <method> struct to xml string representation | ||||||
| 	 */ | 	*/ | ||||||
| 	output, err := xml.MarshalIndent(method, "  ", "    ") | 	output, err := xml.MarshalIndent(method, "  ", "    ") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		//log.Printf("error: %v\n", err.Error()) | 		//log.Printf("error: %v\n", err.Error()) | ||||||
| @@ -258,8 +262,8 @@ func (dev device) callNonAuthorizedMethod(endpoint string, method interface{}) ( | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	Build an SOAP request with <method> | 		Build an SOAP request with <method> | ||||||
| 	 */ | 	*/ | ||||||
| 	soap, err := buildMethodSOAP(string(output)) | 	soap, err := buildMethodSOAP(string(output)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		//log.Printf("error: %v\n", err) | 		//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) | 	soap.AddRootNamespaces(Xlmns) | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	Sending request and returns the response | 		Sending request and returns the response | ||||||
| 	 */ | 	*/ | ||||||
| 	return networking.SendSoap(endpoint, soap.String()) | 	return networking.SendSoap(endpoint, soap.String()) | ||||||
| } | } | ||||||
|  |  | ||||||
| //CallMethod functions call an method, defined <method> struct with authentication data | //CallMethod functions call an method, defined <method> 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 <method> struct to xml string representation | 		Converting <method> struct to xml string representation | ||||||
| 	 */ | 	*/ | ||||||
| 	output, err := xml.MarshalIndent(method, "  ", "    ") | 	output, err := xml.MarshalIndent(method, "  ", "    ") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		//log.Printf("error: %v\n", err.Error()) | 		//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 <method> | 		Build an SOAP request with <method> | ||||||
| 	 */ | 	*/ | ||||||
| 	soap, err := buildMethodSOAP(string(output)) | 	soap, err := buildMethodSOAP(string(output)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		//log.Printf("error: %v\n", err.Error()) | 		//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.AddRootNamespaces(Xlmns) | ||||||
| 	soap.AddWSSecurity(dev.login, dev.password) | 	soap.AddWSSecurity(dev.login, dev.password) | ||||||
|  |  | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	Sending request and returns the response | 		Sending request and returns the response | ||||||
| 	 */ | 	*/ | ||||||
| 	return networking.SendSoap(endpoint, soap.String()) | 	return networking.SendSoap(endpoint, soap.String()) | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Eamon
					Eamon