From 1cb92d8d2032309147ddd4eb06e120809279099f Mon Sep 17 00:00:00 2001 From: yakovlevdmv Date: Sat, 7 Apr 2018 17:31:48 +0300 Subject: [PATCH 01/16] Documenting with Readme.md --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f3e0a1..e8cba98 100644 --- a/README.md +++ b/README.md @@ -1 +1,7 @@ -# goonvif +# Goonvif +Библиотека Goonvif создана для упрощения взаимодействия с ONVIF устройствами. На данный момент в библиотеке реализована поддержка NVT(Network Video Transmitter) устройств, а именно следующих ONVIF сервисов: +- Core или DeviceManagement +- Media +- Imaging +- PTZ +- Video Analytics \ No newline at end of file From 1aee7f15e3ed0fc3d4bb8e6465876ea8d2d8eb3d Mon Sep 17 00:00:00 2001 From: yakovlevdmv Date: Sat, 7 Apr 2018 17:49:01 +0300 Subject: [PATCH 02/16] The scopes of device functions are edited --- Device.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Device.go b/Device.go index 118bb27..284b582 100644 --- a/Device.go +++ b/Device.go @@ -80,14 +80,17 @@ type device struct { } -func GetAvailableDevicesAtSpecificEthernetInterface(interfaceName string) { +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, len(devices)) for _, j := range devices { fmt.Println(j) + //nvtDevices[i] = NewDevice() } + return nil } func (dev *device) getSupportedServices() { @@ -172,14 +175,14 @@ func (dev device) CallMethod(method interface{}) (string, error) { //TODO: Get endpoint automatically if dev.login != "" && dev.password != "" { - return dev.CallAuthorizedMethod(endpoint, method) + return dev.сallAuthorizedMethod(endpoint, method) } else { - return dev.CallNonAuthorizedMethod(endpoint, method) + return dev.сallNonAuthorizedMethod(endpoint, method) } } //CallNonAuthorizedMethod functions call an method, defined struct without authentication data -func (dev device) CallNonAuthorizedMethod(endpoint string, method interface{}) (string, error) { +func (dev device) сallNonAuthorizedMethod(endpoint string, method interface{}) (string, error) { //TODO: Get endpoint automatically /* Converting struct to xml string representation @@ -208,7 +211,7 @@ func (dev device) CallNonAuthorizedMethod(endpoint string, method interface{}) ( } //CallMethod functions call an method, defined struct with authentication data -func (dev device) CallAuthorizedMethod(endpoint string, method interface{}) (string, error) { +func (dev device) сallAuthorizedMethod(endpoint string, method interface{}) (string, error) { /* Converting struct to xml string representation */ From 4966762ce017e95026e20deb3b51ce403680fe84 Mon Sep 17 00:00:00 2001 From: yakovlevdmv Date: Sat, 7 Apr 2018 18:22:03 +0300 Subject: [PATCH 03/16] README editted, reutrn error if got 404 and return error in device constructor --- Device.go | 39 +++++++++++++++++++++++++++++++-------- README.md | 23 +++++++++++++++++++++-- networking/networking.go | 7 +++++++ 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/Device.go b/Device.go index 284b582..ff8caea 100644 --- a/Device.go +++ b/Device.go @@ -2,16 +2,16 @@ package goonvif import ( "encoding/xml" - "log" "fmt" "github.com/beevik/etree" "github.com/yakovlevdmv/gosoap" "strconv" "github.com/yakovlevdmv/WS-Discovery" - "github.com/yakovlevdmv/goonvif/Networking" + "github.com/yakovlevdmv/goonvif/networking" "reflect" "strings" "github.com/yakovlevdmv/goonvif/Device" + "errors" ) var xlmns = map[string]string { @@ -96,31 +96,39 @@ func GetAvailableDevicesAtSpecificEthernetInterface(interfaceName string) []devi func (dev *device) getSupportedServices() { resp, err := dev.CallMethod(Device.GetCapabilities{}) if err != nil { - log.Println(err.Error()) + //log.Println(err.Error()) return } else { doc := etree.NewDocument() if err := doc.ReadFromString(resp); err != nil { - log.Println(err.Error()) + //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) + //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 { +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") + + systemDateTime := Device.GetDeviceInformation{} + _, err := dev.CallMethod(systemDateTime) + if err != nil { + panic(errors.New("camera is not available at " + xaddr + " or it does not support ONVIF services")) + return nil, err + } + dev.getSupportedServices() - return dev + return dev, nil } func (dev *device)addEndpoint(Key, Value string) { @@ -144,6 +152,7 @@ func buildMethodSOAP(msg string) (gosoap.SoapMessage, error) { doc := etree.NewDocument() if err := doc.ReadFromString(msg); err != nil { //log.Println("Got error") + return "", err } element := doc.Root() @@ -175,9 +184,23 @@ func (dev device) CallMethod(method interface{}) (string, error) { //TODO: Get endpoint automatically if dev.login != "" && dev.password != "" { + /*resp, err := dev.сallAuthorizedMethod(endpoint, method) + if err != nil { + panic(err) + return resp, err + } + + return resp, err*/ return dev.сallAuthorizedMethod(endpoint, method) } else { + /*resp, err := dev.сallAuthorizedMethod(endpoint, method) + if err != nil { + panic(err) + return resp, err + } + return resp, err*/ return dev.сallNonAuthorizedMethod(endpoint, method) + } } diff --git a/README.md b/README.md index e8cba98..b2fed44 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,26 @@ # Goonvif -Библиотека Goonvif создана для упрощения взаимодействия с ONVIF устройствами. На данный момент в библиотеке реализована поддержка NVT(Network Video Transmitter) устройств, а именно следующих ONVIF сервисов: +Библиотека **Goonvif** создана для упрощения взаимодействия с ONVIF устройствами. На данный момент в библиотеке реализована поддержка NVT(Network Video Transmitter) устройств, а именно следующих ONVIF сервисов: - Core или DeviceManagement - Media - Imaging - PTZ -- Video Analytics \ No newline at end of file +- Video Analytics +# Dependencies + +# Установка +Для установки библиотеки необходимо воспользоваться утилитой go get: +`go get github.com/yakovlevdmv/goonvif` + +# Начало работы +Чтобы начать работать с камерой, необходимо создать объект `device`. +Для этого необходимо воспользоваться функцией `func NewDevice(xaddr string) (*device, error)`, +которая принимает адрес ONVIF устройства и возвращает указатель на созданный объект. +Если камера не доступна, указан неверный адрес для ONVIF сервиса камеры (возможно находся по другому порту) или же камера вообще не поддерживает ONVIF +функция вызовет ошибку. +### Пример подключения к камере +Пусть камера в сети находится по адресу 192.168.13.42, а ее ONVIF сервисы расположены на 1234 порту. Тогда, +`dev := goonvif.NewDevice("192.168.13.42:1234")` +сработает успешно, а +`dev := goonvif.NewDevice("192.168.13.42:80")` +вызовет ошибку: +> camera is not available or it does not support ONVIF services diff --git a/networking/networking.go b/networking/networking.go index bd1a69d..928a610 100644 --- a/networking/networking.go +++ b/networking/networking.go @@ -4,6 +4,8 @@ import ( "net/http" "bytes" "io/ioutil" + "github.com/pkg/errors" + "strconv" ) func SendSoap(endpoint, message string) (string, error) { @@ -13,10 +15,15 @@ func SendSoap(endpoint, message string) (string, error) { if err != nil { return "", err } + if resp.StatusCode != http.StatusOK { + return "", errors.New("error: got HTTP response status " + strconv.Itoa(resp.StatusCode)) + } b, err := ioutil.ReadAll(resp.Body) if err != nil { return "", err } + //log.Println(resp.StatusCode) + return string(b),nil } From 86573fc414fb9a8ea3a3e8fddd7f94875222653d Mon Sep 17 00:00:00 2001 From: yakovlevdmv Date: Sat, 7 Apr 2018 18:54:57 +0300 Subject: [PATCH 04/16] Some improvements added. README edited --- Device.go | 20 ++++++++++---------- README.md | 36 ++++++++++++++++++++++++++++-------- networking/networking.go | 2 +- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/Device.go b/Device.go index ff8caea..9333289 100644 --- a/Device.go +++ b/Device.go @@ -80,6 +80,10 @@ type device struct { } +func (dev *device)GetServices() map[string]string { + return dev.endpoints +} + func GetAvailableDevicesAtSpecificEthernetInterface(interfaceName string) []device { /* Call an WS-Discovery Probe Message to Discover NVT type Devices @@ -123,8 +127,8 @@ func NewDevice(xaddr string) (*device, error) { systemDateTime := Device.GetDeviceInformation{} _, err := dev.CallMethod(systemDateTime) if err != nil { - panic(errors.New("camera is not available at " + xaddr + " or it does not support ONVIF services")) - return nil, err + //panic(errors.New("camera is not available at " + xaddr + " or it does not support ONVIF services")) + return nil, errors.New("camera is not available at " + xaddr + " or it does not support ONVIF services") } dev.getSupportedServices() @@ -135,10 +139,6 @@ func (dev *device)addEndpoint(Key, Value string) { dev.endpoints[Key]=Value } -func newDeviceEntity() *device { - return &device{} -} - //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 @@ -191,7 +191,7 @@ func (dev device) CallMethod(method interface{}) (string, error) { } return resp, err*/ - return dev.сallAuthorizedMethod(endpoint, method) + return dev.callAuthorizedMethod(endpoint, method) } else { /*resp, err := dev.сallAuthorizedMethod(endpoint, method) if err != nil { @@ -199,13 +199,13 @@ func (dev device) CallMethod(method interface{}) (string, error) { return resp, err } return resp, err*/ - return dev.сallNonAuthorizedMethod(endpoint, method) + return dev.callNonAuthorizedMethod(endpoint, method) } } //CallNonAuthorizedMethod functions call an method, defined struct without authentication data -func (dev device) сallNonAuthorizedMethod(endpoint string, method interface{}) (string, error) { +func (dev device) callNonAuthorizedMethod(endpoint string, method interface{}) (string, error) { //TODO: Get endpoint automatically /* Converting struct to xml string representation @@ -234,7 +234,7 @@ func (dev device) сallNonAuthorizedMethod(endpoint string, method interface{}) } //CallMethod functions call an method, defined struct with authentication data -func (dev device) сallAuthorizedMethod(endpoint string, method interface{}) (string, error) { +func (dev device) callAuthorizedMethod(endpoint string, method interface{}) (string, error) { /* Converting struct to xml string representation */ diff --git a/README.md b/README.md index b2fed44..df51d4a 100644 --- a/README.md +++ b/README.md @@ -6,21 +6,41 @@ - PTZ - Video Analytics # Dependencies - +[etree](https://github.com/beevik/etree) # Установка Для установки библиотеки необходимо воспользоваться утилитой go get: -`go get github.com/yakovlevdmv/goonvif` +``` +go get github.com/yakovlevdmv/goonvif +``` # Начало работы Чтобы начать работать с камерой, необходимо создать объект `device`. Для этого необходимо воспользоваться функцией `func NewDevice(xaddr string) (*device, error)`, -которая принимает адрес ONVIF устройства и возвращает указатель на созданный объект. +которая принимает адрес ONVIF устройства и возвращает указатель на созданный объект либо ошибку. Если камера не доступна, указан неверный адрес для ONVIF сервиса камеры (возможно находся по другому порту) или же камера вообще не поддерживает ONVIF -функция вызовет ошибку. +функция вернет не `nil` error, а в качестве указателя на объект вернет `nil`. ### Пример подключения к камере Пусть камера в сети находится по адресу 192.168.13.42, а ее ONVIF сервисы расположены на 1234 порту. Тогда, -`dev := goonvif.NewDevice("192.168.13.42:1234")` +```dev, err := goonvif.NewDevice("192.168.13.42:1234")``` сработает успешно, а -`dev := goonvif.NewDevice("192.168.13.42:80")` -вызовет ошибку: -> camera is not available or it does not support ONVIF services +```dev, err := goonvif.NewDevice("192.168.13.42:80")``` +вернет нулевой объект камеры и ошибку: +> camera is not available at 192.168.13.42:80 or it does not support ONVIF services +Модернизируем код, чтобы обрабатывать ошибку и получим: +``` + dev, err := goonvif.NewDevice("192.168.13.42:80") + if err != nil { + panic(err) + } + + ///Работа с камерой + +``` +### Поддерживаемые ONVIF сервисы +Теперь, когда камера доступна, можно приступать к работе с ней. Однако стандарт ONVIF имеет множество сервисов, точка доступа (endpoint) к которым не закреплена стандартом (кроме DeviceManagment: http://onvif_host/onvif/device_service). +Поэтому дальше встает вопрос о поддерживаемых камерой сервисах и определении их endpoint'ов. +Для получения поддерживаемых камерой сервисов необходимо вызвать метод GetCapabilities сервиса DeviceManagement. +Однако данная библиотека автоматизирует данный процесс, поэтому при создании объекта device при помощи `func NewDevice(xaddr string) (*device, error)` +библиотека одновременно обрабатывает поддерживаемые камерой сервисы. Таким образом чтобы получить поддерживаемые устройством сервисы, можно воспользоваться двумя путями: +1. Вызвать метод GetCapabilities сервиса DeviceManagement(как это сделать будет рассмотрено дальше) и обработать ответ. +2. Довериться библиотеке и вызвать функцию `func (dev *device)GetServices() map[string]string`, которая вернет map[string]string, ключом которой является название сервиса, а значением - endpoint данного сервиса \ No newline at end of file diff --git a/networking/networking.go b/networking/networking.go index 928a610..b4dfd84 100644 --- a/networking/networking.go +++ b/networking/networking.go @@ -4,8 +4,8 @@ import ( "net/http" "bytes" "io/ioutil" - "github.com/pkg/errors" "strconv" + "errors" ) func SendSoap(endpoint, message string) (string, error) { From 7b29927a99e2526425d6a933e277516421b39c60 Mon Sep 17 00:00:00 2001 From: yakovlevdmv Date: Sat, 7 Apr 2018 18:57:05 +0300 Subject: [PATCH 05/16] README bugs fixed --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index df51d4a..c836b2e 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,16 @@ go get github.com/yakovlevdmv/goonvif функция вернет не `nil` error, а в качестве указателя на объект вернет `nil`. ### Пример подключения к камере Пусть камера в сети находится по адресу 192.168.13.42, а ее ONVIF сервисы расположены на 1234 порту. Тогда, -```dev, err := goonvif.NewDevice("192.168.13.42:1234")``` +``` +dev, err := goonvif.NewDevice("192.168.13.42:1234") +``` сработает успешно, а -```dev, err := goonvif.NewDevice("192.168.13.42:80")``` +``` +dev, err := goonvif.NewDevice("192.168.13.42:80") +``` вернет нулевой объект камеры и ошибку: > camera is not available at 192.168.13.42:80 or it does not support ONVIF services + Модернизируем код, чтобы обрабатывать ошибку и получим: ``` dev, err := goonvif.NewDevice("192.168.13.42:80") From bb10a669f79328d1fdc317954d4497c02390519f Mon Sep 17 00:00:00 2001 From: yakovlevdmv Date: Sat, 7 Apr 2018 19:31:25 +0300 Subject: [PATCH 06/16] README.md modified --- README.md | 47 ++++++++++++++++++++++++++++------- img/exmp_GetCapabilities.png | Bin 0 -> 19566 bytes 2 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 img/exmp_GetCapabilities.png diff --git a/README.md b/README.md index c836b2e..ce70b44 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ - Media - Imaging - PTZ -- Video Analytics +- Analytics # Dependencies [etree](https://github.com/beevik/etree) # Установка @@ -31,15 +31,14 @@ dev, err := goonvif.NewDevice("192.168.13.42:80") вернет нулевой объект камеры и ошибку: > camera is not available at 192.168.13.42:80 or it does not support ONVIF services -Модернизируем код, чтобы обрабатывать ошибку и получим: +Модернизируем код, добавив обработку ошибки, и получим: ``` - dev, err := goonvif.NewDevice("192.168.13.42:80") - if err != nil { - panic(err) - } - - ///Работа с камерой +dev, err := goonvif.NewDevice("192.168.13.42:80") +if err != nil { + panic(err) +} +///Работа с камерой ``` ### Поддерживаемые ONVIF сервисы Теперь, когда камера доступна, можно приступать к работе с ней. Однако стандарт ONVIF имеет множество сервисов, точка доступа (endpoint) к которым не закреплена стандартом (кроме DeviceManagment: http://onvif_host/onvif/device_service). @@ -48,4 +47,34 @@ dev, err := goonvif.NewDevice("192.168.13.42:80") Однако данная библиотека автоматизирует данный процесс, поэтому при создании объекта device при помощи `func NewDevice(xaddr string) (*device, error)` библиотека одновременно обрабатывает поддерживаемые камерой сервисы. Таким образом чтобы получить поддерживаемые устройством сервисы, можно воспользоваться двумя путями: 1. Вызвать метод GetCapabilities сервиса DeviceManagement(как это сделать будет рассмотрено дальше) и обработать ответ. -2. Довериться библиотеке и вызвать функцию `func (dev *device)GetServices() map[string]string`, которая вернет map[string]string, ключом которой является название сервиса, а значением - endpoint данного сервиса \ No newline at end of file +2. Довериться библиотеке и вызвать функцию `func (dev *device)GetServices() map[string]string`, которая вернет map[string]string, ключом которой является название сервиса, а значением - endpoint данного сервиса +### Работка с камерой +Для работы с различными сервисами камерами необходимо отправить корректный SOAP запрос, в теле которого находится вызываемый метод и принимаемые им функции. +**Goonvif** берет на себя работу по созданию корректного SOAP запроса и его отправке. В **Goonvif** определены структуры, для каждой функции каждого (поддерживаемого данной бибилиотекой) сервиса ONVIF: +- [DeviceManagement Service](Device/types.go) +- [Media Service] (Media/types.go) +- [Imaging Service] (Imaging/types.go) +- [PTZ Service] (PTZ/types.go) +- [Analytics Service] (Analytics/types.go) +[Список всех сервисов стандарта (и документация к ним)] (https://www.onvif.org/profiles/specifications/) + +Рассмторим, как организована отправка запросов в **Goonvif** на нескольких примерах. +1. Метод GetCapabilities сервиса DeviceManagement +Все необходимые типы данных определены в пакете [Device](Device/types.go). +В файле (https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl) можно увидеть: +![GetCapabilities](img/exmp_GetCapabilities.png) +Таким образом, Функция GetCapabilities принимает в качестве аргумента перечисление: +`enum { 'All', 'Analytics', 'Device', 'Events', 'Imaging', 'Media', 'PTZ' }` +Чтобы вызвать данный метод создадим объект `Device.GetCapabilities`: +``` +capabilities := Device.GetCapabilities{Category:"All"} +``` +Для вызова данной функции воспользуемся методом `func (dev device) CallMethod(method interface{}) (string, error)`: +``` +resp, err := dev.CallMethod(capab) +if err != nil { + log.Println(err) +} else { + fmt.Println(resp) +} +``` \ No newline at end of file diff --git a/img/exmp_GetCapabilities.png b/img/exmp_GetCapabilities.png new file mode 100644 index 0000000000000000000000000000000000000000..60843cfb71502f04ecda8752e4c145dc36505a34 GIT binary patch literal 19566 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 Date: Sat, 7 Apr 2018 20:46:17 +0300 Subject: [PATCH 07/16] README edited --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index ce70b44..8068484 100644 --- a/README.md +++ b/README.md @@ -52,10 +52,15 @@ if err != nil { Для работы с различными сервисами камерами необходимо отправить корректный SOAP запрос, в теле которого находится вызываемый метод и принимаемые им функции. **Goonvif** берет на себя работу по созданию корректного SOAP запроса и его отправке. В **Goonvif** определены структуры, для каждой функции каждого (поддерживаемого данной бибилиотекой) сервиса ONVIF: - [DeviceManagement Service](Device/types.go) + - [Media Service] (Media/types.go) + - [Imaging Service] (Imaging/types.go) + - [PTZ Service] (PTZ/types.go) + - [Analytics Service] (Analytics/types.go) + [Список всех сервисов стандарта (и документация к ним)] (https://www.onvif.org/profiles/specifications/) Рассмторим, как организована отправка запросов в **Goonvif** на нескольких примерах. @@ -63,6 +68,7 @@ if err != nil { Все необходимые типы данных определены в пакете [Device](Device/types.go). В файле (https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl) можно увидеть: ![GetCapabilities](img/exmp_GetCapabilities.png) + Таким образом, Функция GetCapabilities принимает в качестве аргумента перечисление: `enum { 'All', 'Analytics', 'Device', 'Events', 'Imaging', 'Media', 'PTZ' }` Чтобы вызвать данный метод создадим объект `Device.GetCapabilities`: From 42867920f2cbc29b5af4ff60348b987042aa4633 Mon Sep 17 00:00:00 2001 From: yakovlevdmv Date: Sat, 7 Apr 2018 20:51:12 +0300 Subject: [PATCH 08/16] README.md --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8068484..c36876c 100644 --- a/README.md +++ b/README.md @@ -53,15 +53,15 @@ if err != nil { **Goonvif** берет на себя работу по созданию корректного SOAP запроса и его отправке. В **Goonvif** определены структуры, для каждой функции каждого (поддерживаемого данной бибилиотекой) сервиса ONVIF: - [DeviceManagement Service](Device/types.go) -- [Media Service] (Media/types.go) +- [Media Service](Media/types.go) -- [Imaging Service] (Imaging/types.go) +- [Imaging Service](Imaging/types.go) -- [PTZ Service] (PTZ/types.go) +- [PTZ Service](PTZ/types.go) -- [Analytics Service] (Analytics/types.go) +- [Analytics Service](Analytics/types.go) -[Список всех сервисов стандарта (и документация к ним)] (https://www.onvif.org/profiles/specifications/) +[Список всех сервисов стандарта (и документация к ним)](https://www.onvif.org/profiles/specifications/) Рассмторим, как организована отправка запросов в **Goonvif** на нескольких примерах. 1. Метод GetCapabilities сервиса DeviceManagement @@ -83,4 +83,5 @@ if err != nil { } else { fmt.Println(resp) } -``` \ No newline at end of file +``` +2. \ No newline at end of file From 33464e6c7aecb31faab69f75d638143481491d86 Mon Sep 17 00:00:00 2001 From: yakovlevdmv Date: Sat, 7 Apr 2018 21:11:39 +0300 Subject: [PATCH 09/16] README.md --- README.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c36876c..0de7b77 100644 --- a/README.md +++ b/README.md @@ -84,4 +84,24 @@ if err != nil { fmt.Println(resp) } ``` -2. \ No newline at end of file +2. Создание пользователя методом CreateUsers сервиса DeviceManagement +Все необходимые типы данных определены в пакете [Device](Device/types.go). +В файле (https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl) можно увидеть структуру запроса: +![GetCapabilities](img/exmp_CreateUsers.png) + +Создадим объект `Device.CreateUsers`: +``` +createUsers := Device.CreateUsers{User: onvif.User{Username:"korolev", Password:"qwerty", UserLevel:"User"}} +resp, err := dev.CallMethod(createUsers) +if err != nil { + log.Println(err) +} else { + fmt.Println(resp) +} +``` + +В данном примере можно наблюдать использования пакета onvif, в котором определено большинство типов, используемых в различных сервисах. +Поэтому при создании структур запросов необходимо это учитывать. + +#####**ВАЖНО** +Некоторые камеры работают специфично. Это означает, что в зависимости от модели камеры можно не получить ошибки при неправильном запросе. Поэтому советую проверять точно ли выполнилась операция. Например, для метода CreateUsers вывести список всех пользователей и сравнить. From 42e62d7f52b758f19511dda77e4e4c8da85c5017 Mon Sep 17 00:00:00 2001 From: yakovlevdmv Date: Sat, 7 Apr 2018 22:16:11 +0300 Subject: [PATCH 10/16] Bugs fixed --- Device.go | 34 +++++++++++++++++++++------------- README.md | 13 +++++++++++-- img/exmp_ContinuousMove.png | Bin 0 -> 30138 bytes img/exmp_CreateUsers.png | Bin 0 -> 41446 bytes networking/networking.go | 25 ++++++++++++------------- 5 files changed, 44 insertions(+), 28 deletions(-) create mode 100644 img/exmp_ContinuousMove.png create mode 100644 img/exmp_CreateUsers.png diff --git a/Device.go b/Device.go index 9333289..3c33521 100644 --- a/Device.go +++ b/Device.go @@ -12,6 +12,8 @@ import ( "strings" "github.com/yakovlevdmv/goonvif/Device" "errors" + "net/http" + "io/ioutil" ) var xlmns = map[string]string { @@ -98,13 +100,16 @@ func GetAvailableDevicesAtSpecificEthernetInterface(interfaceName string) []devi } func (dev *device) getSupportedServices() { - resp, err := dev.CallMethod(Device.GetCapabilities{}) + resp, err := dev.CallMethod(Device.GetCapabilities{Category:"All"}) if err != nil { //log.Println(err.Error()) return } else { doc := etree.NewDocument() - if err := doc.ReadFromString(resp); err != nil { + + data, _ := ioutil.ReadAll(resp.Body) + + if err := doc.ReadFromBytes(data); err != nil { //log.Println(err.Error()) return } @@ -124,9 +129,10 @@ func NewDevice(xaddr string) (*device, error) { dev.endpoints = make(map[string]string) dev.addEndpoint("Device", "http://"+xaddr+"/onvif/device_service") - systemDateTime := Device.GetDeviceInformation{} - _, err := dev.CallMethod(systemDateTime) - if err != nil { + systemDateTime := Device.GetSystemDateAndTime{} + resp, err := dev.CallMethod(systemDateTime) + + if err != nil || resp.StatusCode != http.StatusOK { //panic(errors.New("camera is not available at " + xaddr + " or it does not support ONVIF services")) return nil, errors.New("camera is not available at " + xaddr + " or it does not support ONVIF services") } @@ -169,7 +175,7 @@ func buildMethodSOAP(msg string) (gosoap.SoapMessage, error) { //CallMethod functions call an method, defined struct. //You should use Authenticate method to call authorized requests. -func (dev device) CallMethod(method interface{}) (string, error) { +func (dev device) CallMethod(method interface{}) (*http.Response, error) { pkgPath := strings.Split(reflect.TypeOf(method).PkgPath(),"/") pkg := pkgPath[len(pkgPath)-1] @@ -182,6 +188,8 @@ func (dev device) CallMethod(method interface{}) (string, error) { case "PTZ": endpoint = dev.endpoints["PTZ"] } + //fmt.Println("endpoint", endpoint) + //TODO: Get endpoint automatically if dev.login != "" && dev.password != "" { /*resp, err := dev.сallAuthorizedMethod(endpoint, method) @@ -205,7 +213,7 @@ func (dev device) CallMethod(method interface{}) (string, error) { } //CallNonAuthorizedMethod functions call an method, defined struct without authentication data -func (dev device) callNonAuthorizedMethod(endpoint string, method interface{}) (string, error) { +func (dev device) callNonAuthorizedMethod(endpoint string, method interface{}) (*http.Response, error) { //TODO: Get endpoint automatically /* Converting struct to xml string representation @@ -213,7 +221,7 @@ func (dev device) callNonAuthorizedMethod(endpoint string, method interface{}) ( output, err := xml.MarshalIndent(method, " ", " ") if err != nil { //log.Printf("error: %v\n", err.Error()) - return "", err + return nil, err } /* @@ -222,7 +230,7 @@ func (dev device) callNonAuthorizedMethod(endpoint string, method interface{}) ( soap, err := buildMethodSOAP(string(output)) if err != nil { //log.Printf("error: %v\n", err) - return "", err + return nil, err } soap.AddRootNamespaces(xlmns) @@ -234,14 +242,14 @@ func (dev device) callNonAuthorizedMethod(endpoint string, method interface{}) ( } //CallMethod functions call an method, defined struct with authentication data -func (dev device) callAuthorizedMethod(endpoint string, method interface{}) (string, error) { +func (dev device) callAuthorizedMethod(endpoint string, method interface{}) (*http.Response, error) { /* Converting struct to xml string representation */ output, err := xml.MarshalIndent(method, " ", " ") if err != nil { //log.Printf("error: %v\n", err.Error()) - return "", err + return nil, err } /* @@ -250,7 +258,7 @@ func (dev device) callAuthorizedMethod(endpoint string, method interface{}) (str soap, err := buildMethodSOAP(string(output)) if err != nil { //log.Printf("error: %v\n", err.Error()) - return "", err + return nil, err } /* @@ -269,7 +277,7 @@ func (dev device) callAuthorizedMethod(endpoint string, method interface{}) (str soapReq, err := xml.MarshalIndent(auth, "", " ") if err != nil { //log.Printf("error: %v\n", err.Error()) - return "", err + return nil, err } /* diff --git a/README.md b/README.md index 0de7b77..e189216 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ if err != nil { 2. Создание пользователя методом CreateUsers сервиса DeviceManagement Все необходимые типы данных определены в пакете [Device](Device/types.go). В файле (https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl) можно увидеть структуру запроса: -![GetCapabilities](img/exmp_CreateUsers.png) +![CreateUsers](img/exmp_CreateUsers.png) Создадим объект `Device.CreateUsers`: ``` @@ -103,5 +103,14 @@ if err != nil { В данном примере можно наблюдать использования пакета onvif, в котором определено большинство типов, используемых в различных сервисах. Поэтому при создании структур запросов необходимо это учитывать. -#####**ВАЖНО** +##### ВАЖНО Некоторые камеры работают специфично. Это означает, что в зависимости от модели камеры можно не получить ошибки при неправильном запросе. Поэтому советую проверять точно ли выполнилась операция. Например, для метода CreateUsers вывести список всех пользователей и сравнить. + +3. Метод ContinuousMove сервиса PTZ +Все необходимые типы данных определены в пакете [PTZ](PTZ/types.go). +В файле (https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl) можно увидеть структуру запроса: +![ContinuousMove](img/exmp_ContinuousMove.png) + +Так как данная команда определяется сервисом PTZ, необходимый тип находится в пакете [PTZ](PTZ/types.go). + +Создадим объект `PTZ.ContinuousMove`: diff --git a/img/exmp_ContinuousMove.png b/img/exmp_ContinuousMove.png new file mode 100644 index 0000000000000000000000000000000000000000..6ba4847a7b5854fdde88665b2497668280dc3f79 GIT binary patch literal 30138 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 Date: Sat, 7 Apr 2018 22:20:26 +0300 Subject: [PATCH 11/16] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e189216..9aa1722 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ if err != nil { Рассмторим, как организована отправка запросов в **Goonvif** на нескольких примерах. 1. Метод GetCapabilities сервиса DeviceManagement + Все необходимые типы данных определены в пакете [Device](Device/types.go). В файле (https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl) можно увидеть: ![GetCapabilities](img/exmp_GetCapabilities.png) @@ -85,6 +86,7 @@ if err != nil { } ``` 2. Создание пользователя методом CreateUsers сервиса DeviceManagement + Все необходимые типы данных определены в пакете [Device](Device/types.go). В файле (https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl) можно увидеть структуру запроса: ![CreateUsers](img/exmp_CreateUsers.png) @@ -107,6 +109,7 @@ if err != nil { Некоторые камеры работают специфично. Это означает, что в зависимости от модели камеры можно не получить ошибки при неправильном запросе. Поэтому советую проверять точно ли выполнилась операция. Например, для метода CreateUsers вывести список всех пользователей и сравнить. 3. Метод ContinuousMove сервиса PTZ + Все необходимые типы данных определены в пакете [PTZ](PTZ/types.go). В файле (https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl) можно увидеть структуру запроса: ![ContinuousMove](img/exmp_ContinuousMove.png) From c0589c604594ffc4d70fb3d360562ed083901b4a Mon Sep 17 00:00:00 2001 From: yakovlevdmv Date: Sat, 7 Apr 2018 22:44:40 +0300 Subject: [PATCH 12/16] Update README.md --- README.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/README.md b/README.md index 9aa1722..f97c8b4 100644 --- a/README.md +++ b/README.md @@ -115,5 +115,53 @@ if err != nil { ![ContinuousMove](img/exmp_ContinuousMove.png) Так как данная команда определяется сервисом PTZ, необходимый тип находится в пакете [PTZ](PTZ/types.go). +Из файла [PTZ](PTZ/types.go) можно заметить, что : +> ProfileToken [ReferenceToken] +> A reference to the **MediaProfile** that indicate what should be stopped. + +Таким образом, для того, чтобы начать работать с PTZ сервисом для начала необходимо получить **ProfileToken** сервиса **Media**. Как это сделать смотрите в примере 4. Сейчас же предположим, что нам известен нужный токен. Пусть ProfileToken = "Profile_1". Создадим объект `PTZ.ContinuousMove`: +``` +move := PTZ.ContinuousMove{ + ProfileToken:"Profile_1", + Velocity:onvif.PTZSpeed{ + PanTilt:onvif.Vector2D{ + X: 1, + Y: 1, + }, + Zoom:onvif.Vector1D{X:0.5}, + }, +} +``` + +**Заметим**, что объекты Velocity, PanTilt и Zoom определены в пакете onvif. Такая ситуация соответствует всем встроенным типам. + +Для вызова данной функции воспользуемся методом `func (dev device) CallMethod(method interface{}) (string, error)`: +``` +resp, err := dev.CallMethod(capab) +if err != nil { + log.Println(err) +} else { + fmt.Println(resp) +} +``` + +4. Получение списков Media профилей + +Все необходимые типы данных определены в пакете [Media](Media/types.go). +В файле (https://www.onvif.org/ver10/media/wsdl/media.wsdl) можно увидеть структуру запроса: +![ContinuousMove](img/exmp_GetProfiles.png) + +Вот пример создания и вызова запроса GetProfiles +``` +resp, err := dev.CallMethod(Media.GetProfiles{}) +if err != nil { + panic (err) +} else { + fmt.Println(readResponse(resp)) +} +``` + +**Важно** Обработка response'ов пока не реализована, поэтому данная задача ложится на Ваши плечи. Вы можете упростить обработку response при помощи библиотеки [etree](https://github.com/beevik/etree). Либо же воспользоваться сервисом (http://www.webtoolkitonline.com/xml-formatter.html) + From 89e65ee86e4538a75f3cbcdcf6b02fa86933dcc1 Mon Sep 17 00:00:00 2001 From: yakovlevdmv Date: Sat, 7 Apr 2018 22:45:45 +0300 Subject: [PATCH 13/16] README updating merge conflicts --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e189216..9aa1722 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ if err != nil { Рассмторим, как организована отправка запросов в **Goonvif** на нескольких примерах. 1. Метод GetCapabilities сервиса DeviceManagement + Все необходимые типы данных определены в пакете [Device](Device/types.go). В файле (https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl) можно увидеть: ![GetCapabilities](img/exmp_GetCapabilities.png) @@ -85,6 +86,7 @@ if err != nil { } ``` 2. Создание пользователя методом CreateUsers сервиса DeviceManagement + Все необходимые типы данных определены в пакете [Device](Device/types.go). В файле (https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl) можно увидеть структуру запроса: ![CreateUsers](img/exmp_CreateUsers.png) @@ -107,6 +109,7 @@ if err != nil { Некоторые камеры работают специфично. Это означает, что в зависимости от модели камеры можно не получить ошибки при неправильном запросе. Поэтому советую проверять точно ли выполнилась операция. Например, для метода CreateUsers вывести список всех пользователей и сравнить. 3. Метод ContinuousMove сервиса PTZ + Все необходимые типы данных определены в пакете [PTZ](PTZ/types.go). В файле (https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl) можно увидеть структуру запроса: ![ContinuousMove](img/exmp_ContinuousMove.png) From f76c49b1f80df5febac2c2bd76e280aebf84768f Mon Sep 17 00:00:00 2001 From: yakovlevdmv Date: Sat, 7 Apr 2018 22:46:13 +0300 Subject: [PATCH 14/16] README.md --- img/exmp_GetProfiles.png | Bin 0 -> 14358 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 img/exmp_GetProfiles.png diff --git a/img/exmp_GetProfiles.png b/img/exmp_GetProfiles.png new file mode 100644 index 0000000000000000000000000000000000000000..6e99ceb71a1abe6c68362934cbf681b4e129ff40 GIT binary patch literal 14358 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 X@c=a_gk65?Vd)QYYO>|hAHVz`rZeSz literal 0 HcmV?d00001 From b71dc183a27b45d3de372df8bd93b5a8052ac3b8 Mon Sep 17 00:00:00 2001 From: yakovlevdmv Date: Sat, 7 Apr 2018 23:33:43 +0300 Subject: [PATCH 15/16] Update README.md --- README.md | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index f97c8b4..da40c9b 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,11 @@ go get github.com/yakovlevdmv/goonvif # Начало работы Чтобы начать работать с камерой, необходимо создать объект `device`. Для этого необходимо воспользоваться функцией `func NewDevice(xaddr string) (*device, error)`, -которая принимает адрес ONVIF устройства и возвращает указатель на созданный объект либо ошибку. -Если камера не доступна, указан неверный адрес для ONVIF сервиса камеры (возможно находся по другому порту) или же камера вообще не поддерживает ONVIF -функция вернет не `nil` error, а в качестве указателя на объект вернет `nil`. +которая принимает IP адрес ONVIF устройства и возвращает указатель на созданный объект либо ошибку. +Если камера недоступна, указан неверный адрес для ONVIF сервиса камеры (возможно находится по другому порту) или же камера вообще не поддерживает ONVIF +функция вернет error не являющимся `nil`, а в качестве указателя на объект устройства вернет `nil`. ### Пример подключения к камере -Пусть камера в сети находится по адресу 192.168.13.42, а ее ONVIF сервисы расположены на 1234 порту. Тогда, +Пусть камера в сети находится по адресу 192.168.13.42, а ее ONVIF сервисы расположены на порте 1234. Тогда, ``` dev, err := goonvif.NewDevice("192.168.13.42:1234") ``` @@ -41,14 +41,14 @@ if err != nil { ///Работа с камерой ``` ### Поддерживаемые ONVIF сервисы -Теперь, когда камера доступна, можно приступать к работе с ней. Однако стандарт ONVIF имеет множество сервисов, точка доступа (endpoint) к которым не закреплена стандартом (кроме DeviceManagment: http://onvif_host/onvif/device_service). +Теперь, когда камера доступна, можно приступать к работе с ней. Однако стандарт ONVIF имеет множество сервисов, а также точку доступа (endpoint) которая не определена стандартом (кроме DeviceManagment: http://onvif_host/onvif/device_service). Поэтому дальше встает вопрос о поддерживаемых камерой сервисах и определении их endpoint'ов. Для получения поддерживаемых камерой сервисов необходимо вызвать метод GetCapabilities сервиса DeviceManagement. -Однако данная библиотека автоматизирует данный процесс, поэтому при создании объекта device при помощи `func NewDevice(xaddr string) (*device, error)` -библиотека одновременно обрабатывает поддерживаемые камерой сервисы. Таким образом чтобы получить поддерживаемые устройством сервисы, можно воспользоваться двумя путями: +Однако эта библиотека автоматизирует данный процесс, поэтому при создании объекта device при помощи `func NewDevice(xaddr string) (*device, error)` +библиотека одновременно обрабатывает поддерживаемые камерой сервисы. Таким образом есть два способа получения поддерживаемых устройством сервисов: 1. Вызвать метод GetCapabilities сервиса DeviceManagement(как это сделать будет рассмотрено дальше) и обработать ответ. 2. Довериться библиотеке и вызвать функцию `func (dev *device)GetServices() map[string]string`, которая вернет map[string]string, ключом которой является название сервиса, а значением - endpoint данного сервиса -### Работка с камерой +### Работа с камерой Для работы с различными сервисами камерами необходимо отправить корректный SOAP запрос, в теле которого находится вызываемый метод и принимаемые им функции. **Goonvif** берет на себя работу по созданию корректного SOAP запроса и его отправке. В **Goonvif** определены структуры, для каждой функции каждого (поддерживаемого данной бибилиотекой) сервиса ONVIF: - [DeviceManagement Service](Device/types.go) @@ -102,11 +102,10 @@ if err != nil { } ``` -В данном примере можно наблюдать использования пакета onvif, в котором определено большинство типов, используемых в различных сервисах. -Поэтому при создании структур запросов необходимо это учитывать. +В данном примере можно наблюдать использование пакета onvif, в котором определено большинство типов, используемых в поддерживаемых библиотекой сервисах, поэтому при создании структур запросов необходимо это учитывать. ##### ВАЖНО -Некоторые камеры работают специфично. Это означает, что в зависимости от модели камеры можно не получить ошибки при неправильном запросе. Поэтому советую проверять точно ли выполнилась операция. Например, для метода CreateUsers вывести список всех пользователей и сравнить. +Некоторые камеры работают специфично. Это означает, что в зависимости от модели камеры можно не получить ошибки при неправильном запросе. Поэтому советую проверять, точно ли выполнилась операция. Например, для метода CreateUsers надо вывести список всех пользователей и проверить добавился ли пользователь. 3. Метод ContinuousMove сервиса PTZ @@ -135,7 +134,7 @@ move := PTZ.ContinuousMove{ } ``` -**Заметим**, что объекты Velocity, PanTilt и Zoom определены в пакете onvif. Такая ситуация соответствует всем встроенным типам. +**Заметим**, что объекты Velocity, PanTilt и Zoom определены в пакете onvif. Такое применение свойственно для большинства встроенных в структуру типов. Для вызова данной функции воспользуемся методом `func (dev device) CallMethod(method interface{}) (string, error)`: ``` @@ -163,5 +162,10 @@ if err != nil { } ``` -**Важно** Обработка response'ов пока не реализована, поэтому данная задача ложится на Ваши плечи. Вы можете упростить обработку response при помощи библиотеки [etree](https://github.com/beevik/etree). Либо же воспользоваться сервисом (http://www.webtoolkitonline.com/xml-formatter.html) +**Важно** Обработка response'ов камеры пока не реализована, поэтому данная задача ложится на **Ваши** плечи. Вы можете упростить обработку response'ов при помощи библиотеки [etree](https://github.com/beevik/etree) либо же воспользоваться сервисом (http://www.webtoolkitonline.com/xml-formatter.html) +**Важно** Многие запросы требуют авторизованного доступа и для того, чтобы добавить аторизацию к конкретной камере, необходимо воспользоваться функцией `func (dev *device) Authenticate(username, password string)`. После применения данной функции все отправляемые камерой запросы будут авторизованными. +``` +device := onvif.NewDevice("192.168.13.42:1234") +device.Authenticate("username", "password") +``` From 36090abc65e820e4e284c70a05ede09923020bbd Mon Sep 17 00:00:00 2001 From: yakovlevdmv Date: Sun, 8 Apr 2018 02:04:58 +0300 Subject: [PATCH 16/16] Some improvements --- Device.go | 75 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 16 deletions(-) diff --git a/Device.go b/Device.go index 3c33521..0681cfe 100644 --- a/Device.go +++ b/Device.go @@ -86,25 +86,66 @@ func (dev *device)GetServices() map[string]string { return dev.endpoints } +func readResponse(resp *http.Response) string { + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + panic(err) + } + return string(b) +} + 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, len(devices)) + nvtDevices := make([]device, 0) + ////fmt.Println(devices) for _, j := range devices { - fmt.Println(j) + doc := etree.NewDocument() + if err := doc.ReadFromString(j); err != nil { + fmt.Errorf("%s", err.Error()) + return nil + } + ////fmt.Println(j) + endpoints := doc.Root().FindElements("./Body/ProbeMatches/ProbeMatch/XAddrs") + for _, xaddr := range endpoints { + //fmt.Println(xaddr.Tag,strings.Split(strings.Split(xaddr.Text(), " ")[0], "/")[2] ) + xaddr := strings.Split(strings.Split(xaddr.Text(), " ")[0], "/")[2] + fmt.Println(xaddr) + c := 0 + for c = 0; c < len(nvtDevices); c++ { + if nvtDevices[c].xaddr == xaddr { + fmt.Println(nvtDevices[c].xaddr, "==", xaddr) + break + } + } + if c < len(nvtDevices) { + continue + } + dev, err := NewDevice(strings.Split(xaddr, " ")[0]) + //fmt.Println(dev) + if err != nil { + fmt.Println("Error", xaddr) + fmt.Println(err) + continue + } else { + ////fmt.Println(dev) + nvtDevices = append(nvtDevices, *dev) + } + } + ////fmt.Println(j) //nvtDevices[i] = NewDevice() } - return nil + return nvtDevices } -func (dev *device) getSupportedServices() { - resp, err := dev.CallMethod(Device.GetCapabilities{Category:"All"}) - if err != nil { - //log.Println(err.Error()) - return - } else { +func (dev *device) getSupportedServices(resp *http.Response) { + //resp, err := dev.CallMethod(Device.GetCapabilities{Category:"All"}) + //if err != nil { + // log.Println(err.Error()) + //return + //} else { doc := etree.NewDocument() data, _ := ioutil.ReadAll(resp.Body) @@ -115,11 +156,11 @@ func (dev *device) getSupportedServices() { } services := doc.FindElements("./Envelope/Body/GetCapabilitiesResponse/Capabilities/*/XAddr") for _, j := range services{ - //fmt.Println(j.Text()) - //fmt.Println(j.Parent().Tag) + ////fmt.Println(j.Text()) + ////fmt.Println(j.Parent().Tag) dev.addEndpoint(j.Parent().Tag, j.Text()) } - } + //} } //NewDevice function construct a ONVIF Device entity @@ -129,15 +170,17 @@ func NewDevice(xaddr string) (*device, error) { dev.endpoints = make(map[string]string) dev.addEndpoint("Device", "http://"+xaddr+"/onvif/device_service") - systemDateTime := Device.GetSystemDateAndTime{} - resp, err := dev.CallMethod(systemDateTime) + getCapabilities := Device.GetCapabilities{Category: "All"} + resp, err := dev.CallMethod(getCapabilities) + //fmt.Println(resp.Request.Host) + //fmt.Println(readResponse(resp)) if err != nil || resp.StatusCode != http.StatusOK { //panic(errors.New("camera is not available at " + xaddr + " or it does not support ONVIF services")) return nil, errors.New("camera is not available at " + xaddr + " or it does not support ONVIF services") } - dev.getSupportedServices() + dev.getSupportedServices(resp) return dev, nil } @@ -188,7 +231,7 @@ func (dev device) CallMethod(method interface{}) (*http.Response, error) { case "PTZ": endpoint = dev.endpoints["PTZ"] } - //fmt.Println("endpoint", endpoint) + ////fmt.Println("endpoint", endpoint) //TODO: Get endpoint automatically if dev.login != "" && dev.password != "" {