diff --git a/README.md b/README.md index 087b60fa..4cc9daec 100644 --- a/README.md +++ b/README.md @@ -7,74 +7,8 @@ > > **The current stable branch of device-onvif-camera is [Levski](https://github.com/edgexfoundry/device-onvif-camera/tree/levski).** -## Overview -The Open Network Video Interface Forum (ONVIF) Device Service is a microservice created to address the lack of standardization and automation of camera discovery and onboarding. EdgeX Foundry is a flexible microservice-based architecture created to promote the interoperability of multiple device interface combinations at the edge. In an EdgeX deployment, the ONVIF Device Service controls and communicates with ONVIF-compliant cameras, while EdgeX Foundry presents a standard interface to application developers. With normalized connectivity protocols and a vendor-neutral architecture, EdgeX paired with ONVIF Camera Device Service, simplifies deployment of edge camera devices. - - -Use the ONVIF Device Service to streamline and scale your edge camera device deployment. - -## How It Works -The figure below illustrates the software flow through the architecture components. - -![high-level-arch](./doc/images/ONVIFDeviceServiceArch.png) -

- Figure 1: Software Flow -

- -1. **EdgeX Device Discovery:** Camera device microservices probe network and platform for video devices at a configurable interval. Devices that do not currently exist and that satisfy Provision Watcher filter criteria are added to Core Metadata. -2. **Application Device Discovery:** Query Core Metadata for devices and associated configuration. -3. **Application Device Configuration:** Set configuration and initiate device actions through a REST API representing the resources of the video device (e.g. stream URI, Pan-Tilt-Zoom position, Firmware Update). -4. **Pipeline Control:** The application initiates Video Analytics Pipeline through HTTP Post Request. -5. **Publish Inference Events/Data:** Analytics inferences are formatted and passed to the destination message bus specified in the request. -6. **Export Data:** Publish prepared (transformed, enriched, filtered, etc.) and groomed (formatted, compressed, encrypted, etc.) data to external systems (be it analytics package, enterprise or on-premises application, cloud systems like Azure IoT, AWS IoT, or Google IoT Core, etc. - - -# Getting Started - -For a full walkthrough of using the default images, use this [guide.](./doc/guides/SimpleStartupGuide.md) - -For a full walkthrough of building custom images, use this [guide.](./doc/guides/CustomStartupGuide.md) - -A brief video demonstration of building and using the device service can be found [here.](https://www.youtube.com/watch?v=vZqd3j2Zn2Y) - -# Learn More - ### General -[Supported ONVIF features](./doc/ONVIF-protocol.md) -[Auto discovery](./doc/auto-discovery.md) -[Control-plane events](./doc/control-plane-events.md) -[Utility Scripts](./doc/utility-scripts.md) - - -### Custom Features -[Custom Metadata](./doc/custom-metadata-feature.md) -[Reboot Needed](./doc/custom-feature-rebootneeded.md) -[Friendly Name and Mac Address](./doc/get-set-friendlyname-mac.md) - -### API Support -[API Analytic Handling](./doc/api-analytic-support.md) -[API Event Handling](./doc/api-event-handling.md) -[API User Handling](./doc/api-usage-user-handling.md) - -### Miscellaneous -[Postman](./doc/test-with-postman.md) -[User Authentication](./doc/onvif-user-authentication.md) - -## Resources -[Learn more about EdgeX Core Metadata](https://app.swaggerhub.com/apis-docs/EdgeXFoundry1/core-metadata/2.1.0) -[Learn more about EdgeX Core Command](https://app.swaggerhub.com/apis-docs/EdgeXFoundry1/core-command/2.1.0) - - -## References - -- ONVIF Website: http://www.onvif.org -- EdgeX Foundry Project Wiki: https://wiki.edgexfoundry.org/ -- EdgeX Source Code: https://github.com/edgexfoundry -- Edgex Developer Guide: https://docs.edgexfoundry.org/2.1/ -- Docker Repos - - Docker https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository - - Docker Compose https://docs.docker.com/compose/install/#install-compose - +Visit the [EdgeX documentation page](https://docs.edgexfoundry.org/3.0/microservices/device/supported/device-onvif-camera/General/) to learn more about the latest release. ## License diff --git a/doc/ONVIF-protocol.md b/doc/ONVIF-protocol.md deleted file mode 100644 index f3251501..00000000 --- a/doc/ONVIF-protocol.md +++ /dev/null @@ -1,394 +0,0 @@ -# Onvif Camera Device Service Specifications - - -This Onvif Camera Device Service is developed to control/communicate ONVIF-compliant cameras accessible via http in an EdgeX deployment - -## Table of Contents - -- [Onvif Features](#onvif-features) -- [Custom Features](#custom-features) -- [How does the service work?](#how-does-the-device-service-work) -- [Tested Onvif Cameras](#tested-onvif-cameras) - -## OpenAPI Spec -The latest version 2.2.0 of the device service API specifications can be found -[here](https://app.swaggerhub.com/apis-docs/EdgeXFoundry1/device-onvif-camera/2.2.0). - - - -## Onvif Features -The device service supports the onvif features listed in the following table: - -| Feature | Onvif Web Service | Onvif Function | EdgeX Value Type | -|-------------------------------------------------------------------------|-------------------|---------------------------------------------------------------------------------------------------------------------------------|------------------| -| **[User Authentication](#user-authentication)** | Core | **WS-Usernametoken Authentication** | | -| | | **HTTP Digest** | | -| **[Auto Discovery](#auto-discovery)** | Core | **WS-Discovery** | | -| | Device | [GetDiscoveryMode](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.GetDiscoveryMode) | Object | -| | | [SetDiscoveryMode](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.SetDiscoveryMode) | Object | -| | | [GetScopes](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.GetScopes) | Object | -| | | [SetScopes](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.SetScopes) | Object | -| | | [AddScopes](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.AddScopes) | Object | -| | | [RemoveScopes](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.RemoveScopes) | Object | -| **[Network Configuration](#network-configuration)** | Device | [GetHostname](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.GetHostname) | Object | -| | | [SetHostname](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.SetHostname) | Object | -| | | [GetDNS](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.GetDNS) | Object | -| | | [SetDNS](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.SetDNS) | Object | -| | | [**GetNetworkInterfaces**](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.GetNetworkInterfaces) | Object | -| | | [**SetNetworkInterfaces**](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.SetNetworkInterfaces) | Object | -| | | [GetNetworkProtocols](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.GetNetworkProtocols) | Object | -| | | [SetNetworkProtocols](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.SetNetworkProtocols) | Object | -| | | [**GetNetworkDefaultGateway**](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.GetNetworkDefaultGateway) | Object | -| | | [**SetNetworkDefaultGateway**](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.SetNetworkDefaultGateway) | Object | -| **[System Function](#system-function)** | Device | [**GetDeviceInformation**](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.GetDeviceInformation) | Object | -| | | [GetSystemDateAndTime](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.GetSystemDateAndTime) | Object | -| | | [SetSystemDateAndTime](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.SetSystemDateAndTime) | Object | -| | | [SetSystemFactoryDefault](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.SetSystemFactoryDefault) | Object | -| | | [SystemReboot](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.SystemReboot) | Object | -| **[User Handling](#user-handling)** | Device | [**GetUsers**](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.GetUsers) | Object | -| | | [**CreateUsers**](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.CreateUsers) | Object | -| | | [**DeleteUsers**](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.DeleteUsers) | Object | -| | | [**SetUser**](https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.SetUser) | Object | -| **[Metadata Configuration](#metadata-configuration)** | Media | [GetMetadataConfiguration](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.GetMetadataConfiguration) | Object | -| | | [GetMetadataConfigurations](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.GetMetadataConfigurations) | Object | -| | | [GetCompatibleMetadataConfigurations](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.GetCompatibleMetadataConfigurations) | Object | -| | | [**GetMetadataConfigurationOptions**](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.GetMetadataConfigurationOptions) | Object | -| | | [AddMetadataConfiguration](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.AddMetadataConfiguration) | Object | -| | | [RemoveMetadataConfiguration](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.RemoveMetadataConfiguration) | Object | -| | | [**SetMetadataConfiguration**](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.SetMetadataConfiguration) | Object | -| **[Video Streaming](#video-streaming)** | Media | [**GetProfiles**](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.GetProfiles) | Object | -| | | [**GetStreamUri**](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.GetStreamUri) | Object | -| **[VideoEncoder Config](#videoencoder-config)** | Media | [GetVideoEncoderConfiguration](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.GetVideoEncoderConfiguration) | Object | -| | | [**SetVideoEncoderConfiguration**](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.SetVideoEncoderConfiguration) | Object | -| | | [GetVideoEncoderConfigurationOptions](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.GetVideoEncoderConfigurationOptions) | Object | -| **[PTZ Node](#ptz-node)** | PTZ | [GetNode](http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl#op.GetNode) | Object | -| | | [GetNodes](http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl#op.GetNodes) | Object | -| **[PTZ Configuration](#ptz-configuration)** | | [GetConfigurations](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.GetConfigurations) | Object | -| | | [GetConfiguration](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.GetConfiguration) | Object | -| | | [GetConfigurationOptions](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.GetConfigurationOptions) | Object | -| | | [SetConfiguration](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.SetConfiguration) | Object | -| | Media | [AddPTZConfiguration](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.AddPTZConfiguration) | Object | -| | Media | [RemovePTZConfiguration](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.RemovePTZConfiguration) | Object | -| **[PTZ Actuation](#ptz-actuation)** | PTZ | [AbsoluteMove](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.AbsoluteMove) | Object | -| | | [RelativeMove](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.RelativeMove) | Object | -| | | [ContinuousMove](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.ContinuousMove) | Object | -| | | [Stop](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.Stop) | Object | -| | | [GetStatus](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.GetStatus) | Object | -| | | [GetPresets](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.GetPresets) | Object | -| | | [GotoPreset](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.GotoPreset) | Object | -| | | [RemovePreset](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.RemovePreset) | Object | -| **[PTZ Home Position](#ptz-home-position)** | PTZ | [GotoHomePosition](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.GotoHomePosition) | Object | -| | | [SetHomePosition](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.SetHomePosition) | Object | -| **[PTZ Auxiliary Operations](#ptz-auxiliary-operations)** | PTZ | [SendAuxiliaryCommand](https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl#op.SendAuxiliaryCommand) | Object | -| **[Event Handling](#event-handling)** | Event | [Notify](https://docs.oasis-open.org/wsn/wsn-ws_base_notification-1.3-spec-os.pdf) | Object | -| | | [Subscribe](https://docs.oasis-open.org/wsn/wsn-ws_base_notification-1.3-spec-os.pdf) | Object | -| | | [Renew](https://docs.oasis-open.org/wsn/wsn-ws_base_notification-1.3-spec-os.pdf) | Object | -| | | [Unsubscribe](https://www.onvif.org/ver10/events/wsdl/event.wsdl#op.Unsubscribe) | Object | -| | | [CreatePullPointSubscription](https://www.onvif.org/ver10/events/wsdl/event.wsdl#op.CreatePullPointSubscription) | Object | -| | | [PullMessages](https://www.onvif.org/ver10/events/wsdl/event.wsdl#op.PullMessages) | Object | -| | | [TopicFilter](https://docs.oasis-open.org/wsn/wsn-ws_base_notification-1.3-spec-os.pdf) | Object | -| | | [MessageContentFilter](https://docs.oasis-open.org/wsn/wsn-ws_base_notification-1.3-spec-os.pdf) | Object | -| **[Analytics Profile Configuration](#analytics-profile-configuration)** | Media2 | [GetProfiles](https://www.onvif.org/ver20/media/wsdl/media.wsdl#op.GetProfiles) | Object | -| | | [GetAnalyticsConfigurations](https://www.onvif.org/ver20/media/wsdl/media.wsdl#op.GetAnalyticsConfigurations) | Object | -| | | [AddConfiguration](https://www.onvif.org/ver20/media/wsdl/media.wsdl#op.AddConfiguration) | Object | -| | | [RemoveConfiguration](https://www.onvif.org/ver20/media/wsdl/media.wsdl#op.RemoveConfiguration) | Object | -| **[Analytics Module Configuration](#analytics-module-configuration)** | Analytics | [GetSupportedAnalyticsModules](https://www.onvif.org/ver20/analytics/wsdl/analytics.wsdl#op.GetSupportedAnalyticsModules) | Object | -| | | [GetAnalyticsModules](https://www.onvif.org/ver20/analytics/wsdl/analytics.wsdl#op.GetAnalyticsModules) | Object | -| | | [CreateAnalyticsModules](https://www.onvif.org/ver20/analytics/wsdl/analytics.wsdl#op.CreateAnalyticsModules) | Object | -| | | [DeleteAnalyticsModules](https://www.onvif.org/ver20/analytics/wsdl/analytics.wsdl#op.DeleteAnalyticsModules) | Object | -| | | [GetAnalyticsModuleOptions](https://www.onvif.org/ver20/analytics/wsdl/analytics.wsdl#op.GetAnalyticsModuleOptions) | Object | -| | | [ModifyAnalyticsModules](https://www.onvif.org/ver20/analytics/wsdl/analytics.wsdl#op.ModifyAnalyticsModules) | Object | -| **[Rule Configuration](#rule-configuration)** | Analytics | [GetSupportedRules](https://www.onvif.org/ver20/analytics/wsdl/analytics.wsdl#op.GetSupportedRules) | Object | -| | | [GetRules](https://www.onvif.org/ver20/analytics/wsdl/analytics.wsdl#op.GetRules) | Object | -| | | [CreateRules](https://www.onvif.org/ver20/analytics/wsdl/analytics.wsdl#op.CreateRules) | Object | -| | | [DeleteRules](https://www.onvif.org/ver20/analytics/wsdl/analytics.wsdl#op.DeleteRules) | Object | -| | | [GetRuleOptions](https://www.onvif.org/ver20/analytics/wsdl/analytics.wsdl#op.GetRuleOptions) | Object | -| | | [ModifyRule](https://www.onvif.org/ver20/analytics/wsdl/analytics.wsdl#op.ModifyRules) | Object | - -**Note**: The functions in the bold text are **mandatory** for Onvif protocol. - -## Custom Features -The device service also include custom function to enhance the usage for the EdgeX user. - -| Feature | Service | Function | EdgeX Value Type | Description | -|-----------------|---------|------------------------|------------------|----------------------------------------------------------------------------------------| -| System Function | EdgeX | RebootNeeded | Bool | Read only. Used to indicate the camera should reboot to apply the configuration change | -| System Function | EdgeX | CameraEvent | Bool | A device resource which is used to send the async event to north bound | -| System Function | EdgeX | SubscribeCameraEvent | Bool | Create a subscription to subscribe the event from the camera | -| System Function | EdgeX | UnsubscribeCameraEvent | Bool | Unsubscribe all subscription from the camera | -| Media | EdgeX | GetSnapshot | Binary | Get Snapshot from the snapshot uri | -| Custom Metadata | EdgeX | CustomMetadata | Object | Read and write custom metadata to the camera entry in EdgeX | -| Custom Metadata | EdgeX | DeleteCustomMetadata | Object | Delete custom metadata fields from the camera entry in EdgeX | - -## How does the device service work? - -The Onvif camera uses Web Services standards such as XML, SOAP 1.2 and WSDL1.1 over an IP network. -- XML is used as the data description syntax -- SOAP is used for message transfer -- and WSDL is used for describing the services. - -The spec can refer to [ONVIF-Core-Specification](https://www.onvif.org/specs/core/ONVIF-Core-Specification-v221.pdf). - -For example, we can send a SOAP request to the Onvif camera as below: -```shell -curl --request POST 'http://192.168.12.128:2020/onvif/service' \ ---header 'Content-Type: application/soap+xml' \ ---data-raw ' - - - - - myUsername - +HKcvc+LCGClVwuros1sJuXepQY= - w490bn6rlib33d5rb8t6ulnqlmz9h43m - 2021-10-21T03:43:21.02075Z - - - - - - profile_1 - - - ' -``` -And the response should be like the following XML data: -```xml - - - - - - - rtsp://192.168.12.128:554/stream1 - false - false - PT0H0M2S - - - - -``` - -Since the SOAP message is an HTTP call, the device service can just do the transformation between REST(JSON) and SOAP(XML). - -For the concept of implementation: -- The device service accepts the REST request from the client, then transforms the request to SOAP format and forward it to the Onvif camera. -- Once the device service receives the response from the Onvif camera, the device service will transform the SOAP response to REST format for the client. -``` - - Onvif Web Service - - - Onvif Function ┌────────────────────┐ - │ │ -┌──────────────┐ - Input Parameter │ Device Service │ ┌─────────────────┐ -│ │ │ │ │ │ -│ │ REST request │ │ SOAP request │ │ -│ Client ──┼────────────────────┼──► Transform ────┼───────────────┼──► Onvif Camera │ -│ │ │ to SOAP request │ │ │ -│ │ │ │ │ │ -└──────────────┘ └────────────────────┘ └─────────────────┘ - - - ┌────────────────────┐ - │ │ -┌──────────────┐ │ Device Service │ ┌─────────────────┐ -│ │ │ │ │ │ -│ │ REST response │ │ SOAP response │ │ -│ Client ◄─┼────────────────────┼─── Transform ◄──┼───────────────┼── Onvif Camera │ -│ │ │ to REST response │ │ │ -│ │ │ │ │ │ -└──────────────┘ └────────────────────┘ └─────────────────┘ -``` - -## Tested Onvif Cameras -The following table shows the Onvif functions tested for various Onvif cameras: - -* '✔' means the function works for the specified camera. -* '❌' means the function does not work or is not implemented by the specified camera. -* 'ⓘ' means there is additional details available. Click it to read more. -* Empty cells means the function has not yet been tested. - -### User Authentication -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3| -|-------------------|------------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **Core** | WS-UsernameToken | ✔ | ✔ | ✔ | ✔ | ✔ | -| | HTTP Digest | ✔ | ❌ | ✔ | ❌ | ❌ | - -### Capabilities -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|------------------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **Device** | GetCapabilities | | ✔ | | | ❌ | -| | GetServiceCapabilities | | ✔ | | | ❌ | -| **Media** | GetServiceCapabilities | | ✔ | | | ✔ | -| **PTZ** | GetServiceCapabilities | | ✔ | | | ✔ | -| **Imaging** | GetServiceCapabilities | | ❌ | | | ✔ | -| **Event** | GetServiceCapabilities | | ✔ | | | ✔ | - -### Auto Discovery -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|----------------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **Core** | WS-Discovery | ✔ | ✔ | ✔ | ✔ | ✔ | -| **Device** | GetDiscoveryMode | ✔ | ✔ | ✔ | ✔ | ✔ | -| | SetDiscoveryMode | ✔ | ✔ | ✔ | ✔ | ✔ | -| | GetScopes | ✔ | ✔ | ✔ | ✔ | ✔ | -| | SetScopes | ✔ | ✔ | ✔ | ✔ | ❌ | -| | AddScopes | ✔ | ❌ | ✔ | ✔ | ✔ | -| | RemoveScopes | ✔ | ❌ | ✔ | ✔ | ✔ | -| | GetEndpointReference | | ❌ | ✔ | | ❌ | - -### Network Configuration -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|--------------------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **Device** | GetHostname | ✔ | ✔ | ✔ | ✔ | ✔ | -| | SetHostname | ✔ | ❌ | ✔ | ✔ | ✔ | -| | GetDNS | ✔ | ❌ | ✔ | ✔ | ✔ | -| | SetDNS | ✔ | ❌ | ✔ | ✔ | ✔ | -| | GetNetworkInterfaces | ✔ | ✔ | ✔ | ✔ | ✔ | -| | SetNetworkInterfaces | ✔ | ❌ | ✔ | ✔ | ❌ | -| | GetNetworkProtocols | ✔ | ✔ | ✔ | ✔ | ✔ | -| | SetNetworkProtocols | ✔ | ❌ | ✔ | ✔ | ✔ | -| | GetNetworkDefaultGateway | ✔ | ❌ | ✔ | ✔ | ✔ | -| | SetNetworkDefaultGateway | ✔ | ❌ | ✔ | ✔ | ✔ | - -### System Function -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|-------------------------|---------------------|------------------------------------------------------------|-----------------------------------|---------------------|---------------------| -| **Device** | GetDeviceInformation | ✔ | ✔ | ✔ | ✔ | ✔ | -| | GetSystemDateAndTime | ✔ | ✔ | ✔ | ✔ | ✔ | -| | SetSystemDateAndTime | ✔ | ✔ [ⓘ](onvif-footnotes.md#tapo-c200---setsystemdateandtime) | ✔ | ✔ | ✔ | -| | SetSystemFactoryDefault | ✔ | ✔ | ✔ | ✔ | ✔ | -| | SystemReboot | ✔ | ✔ | ✔ | ✔ | ✔ | - -### User Handling -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|----------------|---------------------|-------------------------------------------------------|-----------------------------------|---------------------|---------------------| -| **Device** | GetUsers | ✔ | ❌ [ⓘ](onvif-footnotes.md#tapo-c200---user-management) | ✔ | ✔ | ✔ | -| | CreateUsers | ✔ | ❌ [ⓘ](onvif-footnotes.md#tapo-c200---user-management) | ✔ | ✔ | ✔ | -| | DeleteUsers | ✔ | ❌ [ⓘ](onvif-footnotes.md#tapo-c200---user-management) | ✔ | ✔ | ✔ | -| | SetUser | ✔ | ❌ [ⓘ](onvif-footnotes.md#tapo-c200---user-management) | ✔ | ✔ | ✔ | - -### Metadata Configuration -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|-------------------------------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **Media** | GetMetadataConfigurations | ✔ | ❌ | ✔ | ✔ | ✔ | -| | GetMetadataConfiguration | ✔ | ❌ | ✔ | ✔ | ✔ | -| | GetCompatibleMetadataConfigurations | ✔ | ❌ | ✔ | ✔ | ✔ | -| | GetMetadataConfigurationOptions | ✔ | ❌ | ✔ | ✔ | ✔ | -| | AddMetadataConfiguration | ✔ | ❌ | ✔ | ✔ | ✔ | -| | RemoveMetadataConfiguration | ✔ | ❌ | ✔ | ✔ | ✔ | -| | SetMetadataConfiguration | ✔ | ❌ | ✔ | ✔ | ✔ | - -### Video Streaming -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|----------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **Media** | GetProfiles | ✔ | ✔ | ✔ | ✔ | ✔ | -| | GetStreamUri | ✔ | ✔ | ✔ | ✔ | ✔ | - -### VideoEncoder Config -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|-------------------------------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **Media** | GetVideoEncoderConfigurations | | | | | | -| | GetVideoEncoderConfiguration | ✔ | ✔ | ✔ | ✔ | ✔ | -| | SetVideoEncoderConfiguration | ✔ | ❌ | ✔ | ✔ | ✔ | -| | GetVideoEncoderConfigurationOptions | ✔ | ✔ | ✔ | ✔ | ✔ | - -### PTZ Node -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|----------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **PTZ** | GetNodes | ❌ | ✔ | ❌ | ❌ | ✔ | -| | GetNode | ❌ | ✔ | ❌ | ❌ | ✔ | - -### PTZ Configuration -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|-------------------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **PTZ** | GetConfigurations | ❌ | ✔ | ❌ | ❌ | ✔ | -| | GetConfiguration | ❌ | ✔ | ❌ | ❌ | ✔ | -| | GetConfigurationOptions | ❌ | ✔ | ❌ | ❌ | ✔ | -| | SetConfiguration | ❌ | ❌ | ❌ | ❌ | ✔ | -| **Media** | AddPTZConfiguration | ❌ | ❌ | ❌ | ❌ | ✔ | -| **Media** | RemovePTZConfiguration | ❌ | ❌ | ❌ | ❌ | ✔ | - -### PTZ Actuation -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|----------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **PTZ** | AbsoluteMove | ❌ | ✔ | ❌ | ❌ | ✔ | -| | RelativeMove | ❌ | ✔ | ❌ | ❌ | ✔ | -| | ContinuousMove | ❌ | ✔ | ❌ | ❌ | ✔ | -| | Stop | ❌ | ✔ | ❌ | ❌ | ✔ | -| | GetStatus | ❌ | ✔ | ❌ | ❌ | ✔ | - -### PTZ Preset -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|----------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **PTZ** | SetPreset | ❌ | ✔ | ❌ | ❌ | ✔ | -| | GetPresets | ❌ | ✔ | ❌ | ❌ | ✔ | -| | GotoPreset | ❌ | ✔ | ❌ | ❌ | ✔ | -| | RemovePreset | ❌ | ✔ | ❌ | ❌ | ✔ | - -### PTZ Home Position -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|------------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **PTZ** | GotoHomePosition | ❌ | ❌ | ❌ | ❌ | ✔ | -| | SetHomePosition | ❌ | ❌ | ❌ | ❌ | ✔ | - -### PTZ Auxiliary Operations -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|----------------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **PTZ** | SendAuxiliaryCommand | ❌ | ❌ | ❌ | ❌ | ❌ | - -### Event Handling -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|-----------------------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **Event** | Notify | ✔ | ❌ | ✔ | ❌ | | -| | Subscribe | ✔ | ❌ | ✔ | ❌ | | -| | Renew | ❌ | ❌ | ✔ | ❌ | | -| | Unsubscribe | ✔ | ❌ | ✔ | ❌ | | -| | CreatePullPointSubscription | ✔ | ❌ | ✔ | ❌ | | -| | PullMessages | ✔ | ❌ | ✔ | ❌ | | -| | TopicFilter | ✔ | ❌ | ✔ | ❌ | | -| | MessageContentFilter | ❌ | ❌ | ❌ | ❌ | | -| | GetEventProperties | | ✔ | | | | - -### Analytics Profile Configuration -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|----------------------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **Media2** | GetProfiles | ❌ | ❌ | ✔ | ❌ | ✔ | -| | GetAnalyticsConfigurations | ❌ | ❌ | ✔ | ❌ | ✔ | -| | AddConfiguration | ❌ | ❌ | ✔ | ❌ | ❌ | -| | RemoveConfiguration | ❌ | ❌ | ✔ | ❌ | ❌ | - -### Analytics Module Configuration -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|------------------------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **Analytics** | GetSupportedAnalyticsModules | ❌ | ❌ | ✔ | ❌ | ❌ | -| | GetAnalyticsModules | ❌ | ❌ | ✔ | ❌ | ❌ | -| | CreateAnalyticsModules | ❌ | ❌ | ❌ | ❌ | ❌ | -| | DeleteAnalyticsModules | ❌ | ❌ | ❌ | ❌ | ❌ | -| | GetAnalyticsModuleOptions | ❌ | ❌ | ✔ | ❌ | ❌ | -| | ModifyAnalyticsModules | ❌ | ❌ | ✔ | ❌ | ❌ | - -### Rule Configuration -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 | Hikvision DS-2DE2A404IW-DE3 | -|-------------------|-------------------|---------------------|-----------|-----------------------------------|---------------------|---------------------| -| **Analytics** | GetSupportedRules | ❌ | ❌ | ✔ | ❌ | ❌ | -| | GetRules | ❌ | ❌ | ✔ | ❌ | ❌ | -| | CreateRules | ❌ | ❌ | ✔ | ❌ | ❌ | -| | DeleteRules | ❌ | ❌ | ✔ | ❌ | ❌ | -| | GetRuleOptions | ❌ | ❌ | ✔ | ❌ | ❌ | -| | ModifyRules | ❌ | ❌ | ✔ | ❌ | ❌ | - -### Custom EdgeX -| Onvif Web Service | Onvif Function | Hikvision DFI6256TE | Tapo C200 | BOSCH DINION IP starlight 6000 HD | GeoVision GV-BX8700 |Hikvision DS-2DE2A404IW-DE3 | -|-------------------|----------------|---------------------|-----------|-----------------------------------------------|---------------------|---------------------| -| **EdgeX** | GetSnapshot | ✔ | ❌ | ✔ [ⓘ](onvif-footnotes.md#bosch---getsnapshot) | ❌ | ✔ | diff --git a/doc/api-analytic-support.md b/doc/api-analytic-support.md deleted file mode 100644 index 3d303f01..00000000 --- a/doc/api-analytic-support.md +++ /dev/null @@ -1,442 +0,0 @@ -# Analytic Support - -The device-onvif-camera implement the Analytic function according to `Onvif Profile M` to manage the Analytics Module and Rule configuration. - -The spec can refer to -- https://www.onvif.org/specs/srv/analytics/ONVIF-Analytics-Service-Spec.pdf -- https://www.onvif.org/ver20/analytics/wsdl/analytics.wsdl - -## Overview -This page uses the `BOSCH DINION IP starlight 6000 HD` as the test camera and used the `BOSCH Configuration Manager` as the camera viewer. -- The product page refer to https://commerce.boschsecurity.com/tw/en/DINION-IP-starlight-6000-HD/p/20827877387/ -- The configuration manager can download from https://downloadstore.boschsecurity.com/index.php?type=CM - -In the scope of profile M, the device-onvif-camera should be able to manage the `Analytics Module` and `Rule` configuration, we can illustrate the APIs scope as following example: - -![api-analytic-support-example](images/api-analytic-support-example.jpg) - -For more information, please refer to the Annex D. Radiometry https://www.onvif.org/specs/srv/analytics/ONVIF-Analytics-Service-Spec.pdf - -## Manage the Analytics Module Configuration - -### Query the Analytics Module - -```shell -curl --request GET 'http://0.0.0.0:59882/api/v2/device/name/Camera003/AnalyticsModules?jsonObject=eyJDb25maWd1cmF0aW9uVG9rZW4iOiIxIn0=' | jq . -{ - "apiVersion" : "v2", - "event" : { - ... - "profileName" : "onvif-camera", - "readings" : [ - { - ... - "objectValue" : { - "AnalyticsModule" : [ - { - "Name" : "Viproc", - "Parameters" : { - "SimpleItem" : [ - { - "Name" : "Mode", - "Value" : "Profile 1" - }, - { - "Name" : "AnalysisType", - "Value" : "Intelligent Video Analytics" - } - ] - }, - "Type" : "tt:Viproc" - } - ] - }, - } - ], - "sourceName" : "AnalyticsModules" - }, - "statusCode" : 200 -} -``` - -**Note**: The jsonObject parameter is encoded from `{"ConfigurationToken": "{ANALYTIC_CONFIG_TOKEN}"}` - -![query-analytics-module](images/api-analytic-support-query-analytics-module.jpg) - -### Query the Supported Analytics Module and Options - -```shell -curl --request GET 'http://0.0.0.0:59882/api/v2/device/name/Camera003/GetSupportedAnalyticsModules' | jq . - % Total % Received % Xferd Average Speed Time Time Time Current - Dload Upload Total Spent Left Speed -100 692 100 692 0 0 2134 0 --:--:-- --:--:-- --:--:-- 2217 -{ - "apiVersion" : "v2", - "event" : { - ... - "readings" : [ - { - "deviceName" : "Camera003", - "id" : "70545263-30e7-4c03-9741-0011300f2f9c", - "objectValue" : { - "SupportedAnalyticsModules" : { - "AnalyticsModuleDescription" : [ - { - "Fixed" : true, - "MaxInstances" : 1, - "Name" : "tt:Viproc", - "Parameters" : { - "SimpleItemDescription" : [ - { - "Name" : "Mode", - "Type" : "xs:string" - }, - { - "Name" : "AnalysisType", - "Type" : "xs:string" - } - ] - } - } - ] - } - }, - } - ], - "sourceName" : "GetSupportedAnalyticsModules" - }, - "statusCode" : 200 -} -``` -```shell -curl --request GET 'http://0.0.0.0:59882/api/v2/device/name/Camera003/GetAnalyticsModuleOptions?jsonObject=eyJDb25maWd1cmF0aW9uVG9rZW4iOiIxIn0=' | jq . -{ - "apiVersion" : "v2", - "event" : { - "deviceName" : "Camera003", - "profileName" : "onvif-camera", - ... - "readings" : [ - { - "deviceName" : "Camera003", - "id" : "43f0e59b-6f3e-4119-978e-299ccd59049d", - "objectValue" : { - "Options" : [ - { - "AnalyticsModule" : "tt:Viproc", - "Name" : "Mode", - "StringItems" : { - "Item" : [ - "Off", - "Silent VCA", - "Profile 1", - "Profile 2", - "Scheduled", - "Event Triggered" - ] - } - }, - { - "AnalyticsModule" : "tt:Viproc", - "Name" : "AnalysisType", - "StringItems" : { - "Item" : [ - "MOTION+", - "Intelligent Video Analytics" - ] - } - } - ] - }, - ... - "resourceName" : "GetAnalyticsModuleOptions", - "valueType" : "Object" - } - ], - "sourceName" : "GetAnalyticsModuleOptions" - }, - "statusCode" : 200 -} -``` -**Note**: The jsonObject parameter is encoded from `{"ConfigurationToken": "{ANALYTIC_CONFIG_TOKEN}"}` - -![query-analytics-module](images/api-analytic-support-query-analytics-module-options-1.jpg) -![query-analytics-module](images/api-analytic-support-query-analytics-module-options-2.jpg) - -### Modify the Analytics Module Options - -```shell -curl --request PUT 'http://0.0.0.0:59882/api/v2/device/name/Camera003/AnalyticsModules' \ ---header 'Content-Type: application/json' \ ---data-raw '{ - "AnalyticsModules": { - "ConfigurationToken": "1", - "AnalyticsModule": [ - { - "Name": "Viproc", - "Type": "tt:Viproc", - "Parameters": { - "SimpleItem": [ - { - "Name": "Mode", - "Value": "Profile 1" - }, - { - "Name": "AnalysisType", - "Value": "Intelligent Video Analytics" - } - ] - } - - } - ] - } -}' -``` - -## Manage the Rule Configuration - -### Query the Rules - -```shell -curl --request GET 'http://0.0.0.0:59882/api/v2/device/name/Camera003/Rules?jsonObject=eyJDb25maWd1cmF0aW9uVG9rZW4iOiIxIn0=' | jq . -{ - "apiVersion" : "v2", - "event" : { - "apiVersion" : "v2", - "deviceName" : "Camera003", - "profileName" : "onvif-camera", - ... - "readings" : [ - { - "deviceName" : "Camera003", - "id" : "1abea901-ad51-4a55-b9bb-0b00271307df", - "objectValue" : { - "Rule" : [ - { - "Name" : "Detect any object", - "Parameters" : { - "SimpleItem" : [ - { - "Name" : "Armed", - "Value" : "true" - } - ] - }, - "Type" : "tt:ObjectInField" - } - ] - }, - "origin" : 1639480270526564000, - "profileName" : "onvif-camera", - "resourceName" : "Rules", - "valueType" : "Object" - } - ], - "sourceName" : "Rules" - }, - "statusCode" : 200 -} -``` -**Note**: The jsonObject parameter is encoded from `{"ConfigurationToken": "{ANALYTIC_CONFIG_TOKEN}"}` - -![query-analytics-module](images/api-analytic-support-query-rules.jpg) - -### Query the Supported Rule and Options -```shell -curl --request GET 'http://0.0.0.0:59882/api/v2/device/name/Camera003/GetSupportedRules?jsonObject=eyJDb25maWd1cmF0aW9uVG9rZW4iOiIxIn0=' | jq . - % Total % Received % Xferd Average Speed Time Time Time Current - Dload Upload Total Spent Left Speed -100 9799 0 9799 0 0 9605 0 --:--:-- 0:00:01 --:--:-- 9740 -{ - "apiVersion" : "v2", - "event" : { - "apiVersion" : "v2", - "deviceName" : "Camera003", - "id" : "07f7b42e-835b-4ecc-97b1-fe4d5f52575b", - "origin" : 1639482296788863000, - "profileName" : "onvif-camera", - "readings" : [ - { - "deviceName" : "Camera003", - "id" : "6fca707b-3c52-4694-be37-2e23ecf65de1", - "objectValue" : { - "SupportedRules" : { - "RuleDescription" : [ - .... - { - "MaxInstances" : 16, - "Messages" : { - "Data" : { - "SimpleItemDescription" : [ - { - "Name" : "Count", - "Type" : "xs:int" - } - ] - }, - "IsProperty" : true, - "ParentTopic" : "tns1:RuleEngine/CountAggregation/Counter", - "Source" : { - "SimpleItemDescription" : [ - { - "Name" : "VideoSource", - "Type" : "tt:ReferenceToken" - }, - { - "Name" : "Rule", - "Type" : "xs:string" - } - ] - } - }, - "Name" : "tt:LineCounting", - "Parameters" : { - "ElementItemDescription" : [ - { - "Name" : "Segments" - } - ], - "SimpleItemDescription" : [ - { - "Name" : "Armed", - "Type" : "xs:boolean" - }, - { - "Name" : "Direction", - "Type" : "tt:Direction" - }, - { - "Name" : "MinObjectHeight", - "Type" : "xs:int" - }, - ... - { - "Name" : "ClassFilter", - "Type" : "tt:StringList" - } - ] - } - } - ] - } - }, - "origin" : 1639482296788863000, - "profileName" : "onvif-camera", - "resourceName" : "GetSupportedRules", - "valueType" : "Object" - } - ], - "sourceName" : "GetSupportedRules" - }, - "statusCode" : 200 -} -``` - -```shell -curl --request GET 'http://0.0.0.0:59882/api/v2/device/name/Camera003/GetRuleOptions?jsonObject=eyJDb25maWd1cmF0aW9uVG9rZW4iOiIxIn0=' | jq . - % Total % Received % Xferd Average Speed Time Time Time Current - Dload Upload Total Spent Left Speed -100 1168 100 1168 0 0 755 0 0:00:01 0:00:01 --:--:-- 759 -{ - "apiVersion" : "v2", - "event" : { - "apiVersion" : "v2", - "deviceName" : "Camera003", - "id" : "3ac81a5c-48f2-46d7-a3f9-d4919f97ae8d", - "origin" : 1639482979553667000, - "profileName" : "onvif-camera", - "readings" : [ - { - "deviceName" : "Camera003", - "id" : "6eae2e16-71f7-4b92-95b6-32e398be25ca", - "objectValue" : { - "RuleOptions" : [ - ... - { - "MaxOccurs" : "3", - "MinOccurs" : "0", - "Name" : "Field", - "PolygonOptions" : { - "VertexLimits" : { - "Max" : 16, - "Min" : 3 - } - } - }, - { - "IntRange" : { - "Max" : 16, - "Min" : 2 - }, - "MaxOccurs" : "3", - "MinOccurs" : "1", - "Name" : "Segments" - }, - { - "Name" : "Direction", - "StringList" : "Any Right Left" - }, - { - "Name" : "ClassFilter", - "StringList" : "Person Bike Car Truck" - } - ] - }, - "origin" : 1639482979553667000, - "profileName" : "onvif-camera", - "resourceName" : "GetRuleOptions", - "valueType" : "Object" - } - ], - "sourceName" : "GetRuleOptions" - }, - "statusCode" : 200 -} -``` - -### Add the Rule - -```shell -curl --location --request PUT 'http://0.0.0.0:59882/api/v2/device/name/Camera003/CreateRules' \ ---header 'Content-Type: application/json' \ ---data-raw '{ - "CreateRules": { - "ConfigurationToken": "1", - "Rule": [ - { - "Name": "Object Counting", - "Type": "tt:LineCounting", - "Parameters": { - "SimpleItem": [ - { - "Name":"Armed", - "Value":"true" - } - ], - "ElementItem": [ - { - "Name":"Segments", - "Polyline": { - "Point": [ - { - "x":"0.16", - "y": "0.5" - }, - { - "x":"0.16", - "y": "-0.5" - } - ] - } - } - ] - } - - } - ] - } -}' -``` - -![add-rule](images/api-analytic-support-add-rule.png) diff --git a/doc/api-event-handling.md b/doc/api-event-handling.md deleted file mode 100644 index e6ecb5a5..00000000 --- a/doc/api-event-handling.md +++ /dev/null @@ -1,173 +0,0 @@ -# Event Handling - -The device service shall be able to use at least one way to retrieve events out of the following: -* **PullPoint** - "Pull" using the CreatePullPointSubscription and PullMessage operations -* **BaseNotification** - "Push" using Notify, Subscribe and Renew operations from WSBaseNotification - -The spec can refer to https://www.onvif.org/ver10/events/wsdl/event.wsdl and https://docs.oasis-open.org/wsn/wsn-ws_base_notification-1.3-spec-os.pdf - - -## Define the device resources for Event Handling - -### Define a CameraEvent resource for device service to publish the event -Before receiving the event data from the camera, we must define a device resource for the event. -```yaml -- name: "CameraEvent" - isHidden: true - description: "This resource is used to send the async event reading to north bound" - attributes: - service: "EdgeX" - getFunction: "CameraEvent" - properties: - valueType: "Object" - readWrite: "R" -``` - -### Define device resource for PullPoint - -* Define a SubscribeCameraEvent resource with PullPoint subscribeType for creating the subscription - ```yaml - - name: "SubscribeCameraEvent" - isHidden: false - description: "Create a subscription to subscribe the event from the camera" - attributes: - service: "EdgeX" - setFunction: "SubscribeCameraEvent" - # PullPoint | BaseNotification - subscribeType: "PullPoint" - defaultSubscriptionPolicy: "" - defaultInitialTerminationTime: "PT1H" - defaultAutoRenew: true - defaultTopicFilter: "tns1:RuleEngine/TamperDetector" - defaultMessageContentFilter: "boolean(//tt:SimpleItem[@Name=”IsTamper”])" - defaultMessageTimeout: "PT5S" - defaultMessageLimit: 10 - properties: - valueType: "Object" - readWrite: "W" - ``` - -* Define a UnsubscribeCameraEvent resource for unsubscribing - ```yaml - - name: "UnsubscribeCameraEvent" - isHidden: false - description: "Unsubscribe all event from the camera" - attributes: - service: "EdgeX" - setFunction: "UnsubscribeCameraEvent" - properties: - valueType: "Object" - readWrite: "W" - ``` - -### Define device resource for BaseNotification - -* Define a SubscribeCameraEvent resource with BaseNotification subscribeType - ```yaml - - name: "SubscribeCameraEvent" - isHidden: false - description: "Create a subscription to subscribe the event ..." - attributes: - service: "EdgeX" - setFunction: "SubscribeCameraEvent" - # PullPoint | BaseNotification - subscribeType: "BaseNotification" - defaultSubscriptionPolicy: "" - defaultInitialTerminationTime: "PT1H" - defaultAutoRenew: true - defaultTopicFilter: "..." - defaultMessageContentFilter: "..." - properties: - valueType: "Object" - readWrite: "W" - ``` - -* Define a driver config BaseNotificationURL to indicate the device service network location - ``` - # configuration.yaml - AppCustom: - # BaseNotificationURL indicates the device service network location (which should be accessible from onvif devices on the network), when - # configuring an Onvif Event subscription. - BaseNotificationURL: 'http://192.168.12.112:59984' - ``` - -Device service will generate the following path for pushing event from Camera to device service: -- {BaseNotificationURL}/api/v2/resource/{DeviceName}/{ResourceName} -- {BaseNotificationURL}/api/v2/resource/Camera1/CameraEvent - -**Note**: The user can also override the config from the docker-compose environment variable: -```shell -export HOST_IP=$(ifconfig eth0 | grep "inet " | awk '{ print $2 }') -``` -```yaml -environment: - DRIVER_BASENOTIFICATIONURL: http://${HOST_IP}:59984 -``` -Then the device service can be accessed by the external camera from the other subnetwork. - -### Define device resource for unsubscribing the event -```yaml - - name: "UnsubscribeCameraEvent" - isHidden: true - description: "Unsubscribe all subscription from the camera" - attributes: - service: "EdgeX" - setFunction: "UnsubscribeCameraEvent" - properties: - valueType: "Object" - readWrite: "W" -``` - -## Find the supported Event Topics -Finding out what notifications a camera supports and what information they contain: - -```shell -curl --request GET 'http://localhost:59882/api/v2/device/name/Camera003/GetEventProperties' -``` - -## Create a Pull Point -User can create pull point with the following command: -```shell -curl --request PUT 'http://localhost:59882/api/v2/device/name/Camera003/PullPointSubscription' \ ---header 'Content-Type: application/json' \ ---data-raw '{ - "PullPointSubscription": { - "MessageContentFilter": "boolean(//tt:SimpleItem[@Name=\"Rule\"])", - "InitialTerminationTime": "PT120S", - "MessageTimeout": "PT20S" - } -}' -``` - -**Note**: -* Device service uses a loop to pull message, and the subscription auto-renew by camera -* Device service create a new pull point when the pull point expired -* User can unsubscribe the subscription, then the device service will stop the loop to pull the message and execute unsubscribe Onvif function. - -## Create a BaseNotification -User can create subscription, the InitialTerminationTime is required and should greater than ten seconds: -```shell -curl --request PUT 'http://localhost:59882/api/v2/device/name/Camera003/BaseNotificationSubscription' \ ---header 'Content-Type: application/json' \ ---data-raw '{ - "BaseNotificationSubscription": { - "TopicFilter": "tns1:RuleEngine/TamperDetector/Tamper", - "InitialTerminationTime": "PT180S" - } -}' -``` - -**Note**: -- Device service send Renew request every ten second before termination time -- User can unsubscribe the subscription, then the device service stop to renew the subscription - -## Unsubscribe all subscriptions -The user can unsubscribe all subscriptions(PullPoint and BaseNotification) from the camera with the following command: -```shell -curl --request PUT 'http://localhsot:59882/api/v2/device/name/Camera003/UnsubscribeCameraEvent' \ ---header 'Content-Type: application/json' \ ---data-raw '{ - "UnsubscribeCameraEvent": { - } -}' -``` diff --git a/doc/api-usage-user-handling.md b/doc/api-usage-user-handling.md deleted file mode 100644 index a0cc837c..00000000 --- a/doc/api-usage-user-handling.md +++ /dev/null @@ -1,68 +0,0 @@ -# User Handling - -The device service shall be able to create, list, modify and delete users from the device using the CreateUsers, GetUsers, SetUser and DeleteUsers operations. - -The spec can refer to https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl - -## GetUsers -This operation lists the registered users and corresponding credentials on a device. -```shell -curl --request GET 'http://0.0.0.0:59882/api/v2/device/name/Camera001/Users' -``` - -## CreateUsers -This operation creates new camera users and corresponding credentials on a device for authentication purposes. -```shell -curl --request PUT 'http://0.0.0.0:59882/api/v2/device/name/Camera001/CreateUsers' \ - --header 'Content-Type: application/json' \ - --data-raw '{ - "CreateUsers": { - "User": [ - { - "Username": "user1", - "Password": "Password1", - "UserLevel": "User" - }, - { - "Username": "user2", - "Password": "Password1", - "UserLevel": "User" - } - ] - } - }' -``` - -## SetUser -This operation updates the settings for one or several users on a device for authentication purposes. -```shell -curl --request PUT 'http://0.0.0.0:59882/api/v2/device/name/Camera001/Users' \ - --header 'Content-Type: application/json' \ - --data-raw '{ - "Users": { - "User": [ - { - "Username": "user1", - "UserLevel": "Administrator" - }, - { - "Username": "user2", - "UserLevel": "Operator" - } - ] - } - }' -``` - -## DeleteUsers -This operation deletes users on a device. -```shell -curl --request PUT 'http://0.0.0.0:59882/api/v2/device/name/Camera001/DeleteUsers' \ - --header 'Content-Type: application/json' \ - --data-raw '{ - "DeleteUsers": { - "Username": ["user1","user2"] - } - }' -``` - diff --git a/doc/auto-discovery.md b/doc/auto-discovery.md deleted file mode 100644 index bde518e0..00000000 --- a/doc/auto-discovery.md +++ /dev/null @@ -1,248 +0,0 @@ -# Auto Discovery -There are two methods that the device service can use to discover and add ONVIF -compliant cameras using WS-Discovery: multicast and netscan. - -For more info on how WS-Discovery works, see [here](ws-discovery.md). - - -## How To -> **NOTE:** Ensure that the cameras are all installed and configured before attempting discovery. - -Device discovery is triggered by the device SDK. Once the device service starts, it will discover the Onvif camera(s) at the specified interval. -> **Note:** You can also manually trigger discovery using this command: `curl -X POST http://:59984/api/v2/discovery` - -### Step 1. Discovery Configuration - -> _See [Configuration Section](#Configuration-Guide) for full details_ - -> **Note:** Alternatively, for `netscan` you can set the `DiscoverySubnets` automatically -> _after_ the service has been deployed by running the [bin/configure-subnets.sh](./utility-scripts.md#configure-subnetssh) script - -> For `Netscan`, there is a one line command to determine the `DiscoverySubnets` of your current machine: -> ```shell -> ip -4 -o route list scope link | sed -En "s/ dev ($(find /sys/class/net -mindepth 1 -maxdepth 2 -not -lname '*devices/virtual*' -execdir grep -q 'up' "{}/operstate" \; -printf '%f\n' | paste -sd\| -)).+//p" | grep -v "169.254.0.0/16" | sort -u | paste -sd, - -> ``` -> Example Output: `192.168.1.0/24` - -
-via configuration.yaml - -Define the following configurations in [cmd/res/configuration.yaml](../cmd/res/configuration.yaml) for auto-discovery mechanism: - -```yaml -Device: - # The location of Provision Watcher yaml files to import when using auto-discovery - ProvisionWatchersDir: ./res/provisionwatchers - Discovery: - Enabled: true - Interval: 1h - -# Custom configs -AppCustom: - DefaultSecretName: credentials001 - # Select which discovery mechanism(s) to use - DiscoveryMode: both # netscan, multicast, or both - # The target ethernet interface for multicast discovering - DiscoveryEthernetInterface: eth0 - # List of IPv4 subnets to perform netscan discovery on, in CIDR format (X.X.X.X/Y) - # separated by commas ex: "192.168.1.0/24,10.0.0.0/24" - DiscoverySubnets: "192.168.1.0/24" # Fill in with your actual subnet(s) -``` -
- -
-via Docker / Env Vars - -Define the following environment variables in `docker-compose.yaml`: -```yaml -device-onvif-camera: - environment: - DEVICE_DISCOVERY_ENABLED: "true" # enable device discovery - DEVICE_DISCOVERY_INTERVAL: "1h" # set to desired interval - - # The target ethernet interface for multicast discovering - APPCUSTOM_DISCOVERYETHERNETINTERFACE: "eth0" - # The Secret Name of the default credentials to use for devices - APPCUSTOM_DEFAULTSECRETNAME: "credentials001" - # Select which discovery mechanism(s) to use - APPCUSTOM_DISCOVERYMODE: "both" # netscan, multicast, or both - # List of IPv4 subnets to perform netscan discovery on, in CIDR format (X.X.X.X/Y) - # separated by commas ex: "192.168.1.0/24,10.0.0.0/24" - APPCUSTOM_DISCOVERYSUBNETS: "192.168.1.0/24" # Fill in with your actual subnet(s) -``` -
- -### Step 2. Set CredentialsMap -See [Credentials Guide](credentials.md) for more information. - -## Configuration Guide -### DiscoveryMode -> For docker, set the env var `APPCUSTOM_DISCOVERYMODE` - -`DiscoveryMode` allows you to select which discovery mechanism(s) to use. The three options are: `netscan`, `multicast`, and `both`. - -#### netscan -`netscan` works by sending unicast UDP [WS-Discovery](./ws-discovery.md) probes to a set of -IP addresses on the CIDR subnet(s) configured via [`DiscoverySubnets`](#DiscoverySubnets). - -For example, if the provided CIDR is `10.0.0.0/24`, it will probe the all IP addresses -from `10.0.0.1` to `10.0.0.254`. This will result in a total of 254 probes on the network. - -This method is a little slower and more network-intensive than multicast WS-Discovery, because it has to -make individual connections. However, it can reach a much wider set of networks and works -better behind NATs (such as docker networks). - -#### multicast -`multicast` works by sending a single multicast UDP [WS-Discovery](./ws-discovery.md) Probe to the multicast address `239.255.255.250` on port `3702`. -In certain networks this traffic is blocked, and it is also not forwarded across subnets, so it is not compatible with NATs -such as docker networks (except in the case of running an Onvif simulator inside the same docker network). - -multicast requires some additional configuration. edit the `add-device-onvif-camera.yml` in the `edgex-compose/compose-builder` as follows: - -> NOTE: use the instructions below to configure certain environment variables -```yml -services: - device-onvif-camera: - image: edgexfoundry/device-onvif-camera${ARCH}:0.0.0-dev - container_name: edgex-device-onvif-camera - hostname: edgex-device-onvif-camera - read_only: true - restart: always - network_mode: "host" - environment: - SERVICE_HOST: 192.168.93.151 # set to internal ip of your machine - MESSAGEQUEUE_HOST: localhost - EDGEX_SECURITY_SECRET_STORE: "false" - REGISTRY_HOST: localhost - CLIENTS_CORE_DATA_HOST: localhost - CLIENTS_CORE_METADATA_HOST: localhost - # Host Network Interface, IP, Subnet - APPCUSTOM_DISCOVERYETHERNETINTERFACE: wlp1s0 # determine this setting for your machine - APPCUSTOM_DISCOVERYSUBNETS: 192.168.93.0/24 # determine this setting for your machine - APPCUSTOM_DISCOVERYMODE: multicast - depends_on: - - consul - - data - - metadata - security_opt: - - no-new-privileges:true - user: "${EDGEX_USER}:${EDGEX_GROUP}" - command: --cp=consul.http://localhost:8500 -``` - -#### both -This option combines both [netscan](#netscan) and [multicast](#multicast). - -### DiscoverySubnets -> For docker, set the env var `APPCUSTOM_DISCOVERYSUBNETS` - -This is the list of IPv4 subnets to perform netscan discovery on, in CIDR format (X.X.X.X/Y) -separated by commas ex: "192.168.1.0/24,10.0.0.0/24". This value can be configured automatically via -the [bin/configure-subnets.sh](utility-scripts.md#configure-subnetssh) script. - -Also, the following one-line command can determine the subnets of your machine: -```shell -ip -4 -o route list scope link | sed -En "s/ dev ($(find /sys/class/net -mindepth 1 -maxdepth 2 -not -lname '*devices/virtual*' -execdir grep -q 'up' "{}/operstate" \; -printf '%f\n' | paste -sd\| -)).+//p" | grep -v "169.254.0.0/16" | sort -u | paste -sd, - -``` -Example Output: `192.168.1.0/24` - -### DiscoveryEthernetInterface -> For docker, set the env var `APPCUSTOM_DISCOVERYETHERNETINTERFACE` - -This is the target Ethernet Interface to use for [multicast](#multicast) discovering. Keep in mind this interface -is relative to the environment it is being run under. For example, when running in docker, those interfaces -are different from your host machine's interfaces. - -### ProbeAsyncLimit -> For docker, set the env var `APPCUSTOM_PROBEASYNCLIMIT` - -This is the maximum simultaneous network probes when running netscan discovery. - -### ProbeTimeoutMillis -> For docker, set the env var `APPCUSTOM_PROBETIMEOUTMILLIS` - -This is the maximum amount of milliseconds to wait for each IP probe before timing out. -This will also be the minimum time the discovery process can take. - -### MaxDiscoverDurationSeconds -> For docker, set the env var `APPCUSTOM_MAXDISCOVERDURATIONSECONDS` - -This is the maximum amount of seconds the discovery process is allowed to run before it will be cancelled. -It is especially important to have this configured in the case of larger subnets such as /16 and /8. - - -## Adding the Devices to EdgeX -```mermaid -sequenceDiagram - Onvif Device Service->>Onvif Camera: WS-Discovery Probe - Onvif Camera->>Onvif Device Service: Probe Response - Onvif Device Service->>Onvif Camera: GetDeviceInformation - Onvif Camera->>Onvif Device Service: GetDeviceInformation Response - Onvif Device Service->>Onvif Camera: GetNetworkInterfaces - Onvif Camera->>Onvif Device Service: GetNetworkInterfaces Response - Onvif Device Service->>EdgeX Core-Metadata: Create Device - EdgeX Core-Metadata->>Onvif Device Service: Device Added -``` - -## Rediscovery -The device service is able to rediscover and update devices that have been discovered previously. -Nothing additional is needed to enable this. It will run whenever the discover call is sent, regardless -of whether it is a manual or automated call to discover. - -The following logic to determine if the device is already registered or not. - -```mermaid -%% Note: The node and edge definitions are split up to make it easier to adjust the -%% links between the various nodes. -flowchart TD; - %% -------- Node Definitions -------- %% - Multicast[/Devices Discovered
via Multicast/] - Netscan[/Devices Discovered
via Netscan/] - DupeFilter[Filter Duplicate Devices
based on EndpointRef] - MACMatches{MAC Address
matches existing
device?} - RefMatches{EndpointRef
matches existing
device?} - IPChanged{IP Address
Changed?} - MACChanged{MAC Address
Changed?} - UpdateIP[Update IP Address] - UpdateMAC(Update MAC Address) - RegisterDevice(Register New Device
With EdgeX) - DeviceNotRegistered(Device Not Registered) - PWMatches{Device matches
Provision Watcher?} - - %% -------- Graph Definitions -------- %% - Multicast --> DupeFilter - Netscan --> DupeFilter - DupeFilter --> ForEachDevice - subgraph ForEachDevice[For Each Unique Device] - MACMatches -->|Yes| UpdateDevice - MACMatches -->|No| RefMatches - RefMatches -->|Yes| UpdateDevice - RefMatches -->|No| ForEachPW - - subgraph UpdateDevice[Update Existing Device] - direction TB - IPChanged -->|No| MACChanged - IPChanged -->|Yes| UpdateIP - UpdateIP --> MACChanged - MACChanged -->|Yes| UpdateMAC - end - - subgraph ForEachPW[For Each Provision Watcher] - direction TB - PWMatches -->|Yes| RegisterDevice - end - ForEachPW -->|No Matches| DeviceNotRegistered - end -``` - -## Troubleshooting - -#### netscan discovery was called, but DiscoverySubnets are empty! -This message occurs when you have not configured the `AppCustom.DiscoverySubnets` configuration. -It is required in order to know which subnets to scan for Onvif Cameras. -See [here](#DiscoverySubnets) - -#### route ip+net: no such network interface -This message occurs when you have multicast discovery enabled, but `AppCustom.DiscoveryEthernetInterface` -is configured to a network interface that does not exist. -See [here](#DiscoveryEthernetInterface) diff --git a/doc/control-plane-events.md b/doc/control-plane-events.md deleted file mode 100644 index 4e404f20..00000000 --- a/doc/control-plane-events.md +++ /dev/null @@ -1,7 +0,0 @@ -# Control Plane Events - -## Introduction -Control plane events have been added to enable the device service to emit events onto the message bus when a device has been added, updated, or deleted. - -See: https://docs.edgexfoundry.org/2.3/microservices/core/metadata/Ch-Metadata/#device-system-events - diff --git a/doc/credentials.md b/doc/credentials.md deleted file mode 100644 index 1c483561..00000000 --- a/doc/credentials.md +++ /dev/null @@ -1,241 +0,0 @@ -# Credentials -Camera credentials are stored in the EdgeX Secret Store and referenced by MAC Address. All -devices by default are configured with credentials from `DefaultSecretName` unless configured -as part of a group within `AppCustom.CredentialsMap`. - -Three things must be done in order to add an authenticated camera to EdgeX: -- Add device to EdgeX - - Manually or via auto-discovery -- Add `Credentials` to `Secret Store` - - Manually or via utility scripts -- Map `Credentials` to devices - - Manually or via utility scripts - - Configure as `DefaultSecretName` - -## Terminology / Definitions -- **Secret**: A generic map/object which is stored as multiple key/value pairs in the `Secret Store` under a specific `Secret Name` key. -- **Credentials**: A specific type of `Secret` which contains a mapping of `username`, `password`, and authentication `mode`. -- **Secret Store**: The place EdgeX stores all `Secrets` - - In secure mode this is `Vault` - - In non-secure mode this is the configuration provider (typically `Consul`). - They can be pre-configured via `configuration.yaml`'s `Writable.InsecureSecrets` section. -- **Secret Name**: The name/key of the `Secret` as they are stored in the `Secret Store`. -- **CredentialsMap**: (aka `AppCustom.CredentialsMap`) this contains the mappings between `Secret Name` and - `MAC Address`. Each key in the map is a `Secret Name` which points to `Credentials` in the `Secret Store`. The value - for each key is a comma separated list of `MAC Addresses` which should use those `Credentials`. -- **DefaultSecretName**: The `Secret Name` which points to the `Credentials` to use as the default for all devices - which are not configured in the `CredentialsMap`. -- **NoAuth**: A special `Secret Name` that does not exist in the `Secret Store`. It is pre-configured as `Credentials` - with `Authentication Mode` of `none`. `NoAuth` can be used most places where a `Secret Name` is expected. - -Camera credentials are stored in the EdgeX Secret Store, which is Vault in secure mode, and Consul in non-secure mode. -The term `Secret Name` is often used to refer to the name of the credentials as they are stored in the Secret Store. -Credentials are then mapped to devices either using the `DefaultSecretName` which applies to all devices by default, -or by configuring the `AppCustom.CredentialsMap` which maps one or more MAC Addresses to the desired credentials. - -## Credentials Structure -`Credentials` are `SecretData` comprised of three fields: -- `username`: the admin username for the camera -- `password`: the admin password -- `mode`: the type of Authentication to use - - `usernametoken`: use a username and token based authentication - - `digest`: use a digest based authentication - - `both`: use both `usernametoken` and `digest` - - `none`: do not send any authentication headers - -## Add Credentials to Secret Store -> **Note:** Credentials can be added and modified via [utility scripts](./utility-scripts.md) after the service is running - -### Non-Secure Mode -
-Helper Scripts - -See [here](./utility-scripts.md) for the full guide. -
- -
-Manual - -> **Note:** Replace `` with the name of the secret, `` with the username, -> `` with the password, and `` with the auth mode. - -Set SecretName to `` -```shell -curl -X PUT --data "" \ - "http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets//SecretName" -``` - -Set username to `` -```shell -curl -X PUT --data "" \ - "http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets//SecretData/username" -``` - -Set password to `` -```shell -curl -X PUT --data "" \ - "http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets//SecretData/password" -``` - -Set auth mode to `` -```shell -curl -X PUT --data "" \ - "http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets//SecretData/mode" -``` -
- -### Secure Mode -
-Helper Scripts - -See [here](./utility-scripts.md) for the full guide. -
- -
-Manual - -Credentials can be added via EdgeX Secrets: - -> **Note:** Replace `` with the name for the new secret, `` with the username, -> `` with the password, and `` with the authentication mode. - -```shell -curl --location --request POST 'http://localhost:59984/api/v2/secret' \ - --header 'Content-Type: application/json' \ - --data-raw ' -{ - "apiVersion":"v2", - "name": "", - "secretData":[ - { - "key":"username", - "value":"" - }, - { - "key":"password", - "value":"" - }, - { - "key":"mode", - "value":"" - } - ] -}' -``` -
- -## Mapping Credentials to Devices -> **Note:** Credential mappings can be set via [utility scripts](./utility-scripts.md) after the service is running - -The device service supports three types of credential mapping. All three types can be used -in conjunction with each other. - -- `1 to All` - All devices are given the default credentials based on `DefaultSecretName` -- `1 to Many` - In the `CredentialsMap`, one secret name can be assigned multiple MAC addresses -- `1 to 1` - In the `CredentialsMap`, assign each secret name 1 MAC Address - -### Manual Configuration -> **Note:** Any key present in `AppCustom.CredentialsMap` must also exist in the secret store! -```yaml -# AppCustom.CredentialsMap is a map of SecretName -> Comma separated list of mac addresses. - # Every SecretName used here must also exist as a valid secret in the Secret Store. - # - # Note: Anything not defined here will be assigned the default credentials configured via `DefaultSecretName`. - # - # Example: (Single mapping for 1 mac address to 1 credential) - # credentials001 = "aa:bb:cc:dd:ee:ff" - # - # Example: (Multi mapping for 3 mac address to 1 shared credentials) - # credentials002 = "11:22:33:44:55:66,ff:ee:dd:cc:bb:aa,ab:12:12:34:34:56:56" - # - # These mappings can also be referred to as "groups". In the above case, the `credentials001` group has 1 MAC - # Address, and the `credentials002` group has 3 MAC Addresses. - # - # The special group 'NoAuth' defines mac addresses of cameras where no authentication is needed. - # The 'NoAuth' key does not exist in the SecretStore. It is not required to add MAC Addresses in here, - # however it avoids sending the default credentials to cameras which do not need it. - # - # IMPORTANT: A MAC Address may only exist in one credential group. If a MAC address is defined in more - # than one group, it is unpredictable which group the MAC will end up in! If you wish to change the group a MAC - # address belongs to, first remove it from its existing group, and then add it to the new one. - CredentialsMap: - NoAuth: "" - credentials001: "aa:bb:cc:dd:ee:ff" - credentials002: "11:22:33:44:55:66,ff:ee:dd:cc:bb:aa,ab:12:12:34:34:56:56" -``` - -## Credential Lookup -Here is an in-depth look at the logic behind mapping `Credentials` to Devices. - -### During Discovery -```mermaid -%% Note: The node and edge definitions are split up to make it easier to adjust the -%% links between the various nodes. -flowchart TD; - %% -------- Node Definitions -------- %% - DiscoveredDevice[/Discovered Device/] - UseDefault[Use Default Credentials] - EndpointRefHasMAC{Does EndpointRef
contain
MAC Address?} - InNoAuthGroup{MAC Belongs
to NoAuth group?} - AuthModeNone[Set AuthMode to 'none'] - ApplyCreds[Apply Credentials] - InSecretStore{Credentials exist
in SecretStore?} - CreateClient[Create Onvif Client] - GetDeviceInfo[Get Device Information] - GetNetIfaces[Get Network Interfaces] - CreateDevice(Create Device:
<Mfg>-<Model>-<EndpointRef>) - CreateUnknownDevice(Create Device:
unknown_unknown_<EndpointRef>) - - %% -------- Graph Definitions -------- %% - DiscoveredDevice --> ForAllMAC - subgraph ForAllMAC[For all MAC Addresses in CredentialsMap] - EndpointRefHasMAC - end - EndpointRefHasMAC -->|Yes| InNoAuthGroup - EndpointRefHasMAC -- No Matches --> UseDefault - InNoAuthGroup -->|Yes| AuthModeNone - InNoAuthGroup -->|No| InSecretStore - UseDefault --> InSecretStore - AuthModeNone --> CreateClient - InSecretStore -->|Yes| ApplyCreds - InSecretStore -->|No| AuthModeNone - ApplyCreds --> CreateClient - CreateClient --> GetDeviceInfo - GetDeviceInfo -->|Failed| CreateUnknownDevice - GetDeviceInfo -->|Success| GetNetIfaces - GetNetIfaces ----> CreateDevice -``` - -### Connecting to Existing Devices -```mermaid -%% Note: The node and edge definitions are split up to make it easier to adjust the -%% links between the various nodes. -flowchart TD; - %% -------- Node Definitions -------- %% - ExistingDevice[/Existing Device/] - ContainsMAC{Device Metadata contains
MAC Address?} - ValidMAC{Is it a valid
MAC Address?} - InMap{MAC exists in
CredentialsMap?} - InNoAuth{MAC Belongs
to NoAuth group?} - UseDefault[Use Default Credentials] - InSecretStore{Credentials exist
in SecretStore?} - AuthModeNone(Set AuthMode to 'none') - ApplyCreds(Apply Credentials) - CreateClient(Create Onvif Client) - - %% -------- Edge Definitions -------- %% - ExistingDevice --> ContainsMAC - ContainsMAC -->|Yes| ValidMAC - ValidMAC -->|Yes| InMap - ValidMAC -->|No| AuthModeNone - InMap -->|Yes| InNoAuth - InMap -->|No| AuthModeNone - ContainsMAC -->|No| UseDefault - InNoAuth -->|Yes| AuthModeNone - InNoAuth -->|No| InSecretStore - UseDefault --> InSecretStore - InSecretStore -->|Yes| ApplyCreds - InSecretStore -->|No| AuthModeNone - AuthModeNone ----> CreateClient - ApplyCreds ----> CreateClient -``` \ No newline at end of file diff --git a/doc/custom-build.md b/doc/custom-build.md deleted file mode 100644 index 3a2adc2e..00000000 --- a/doc/custom-build.md +++ /dev/null @@ -1,213 +0,0 @@ -# ONVIF Device Service Custom Build Guide - -Follow this guide to make custom configurations and build the device service image from the source. - - -## Table of Contents - [Get the Source Code](#get-the-source-code) - [Configure the Pre-Defined Devices](#configure-the-pre-defined-devices) - [Configure the Device Profiles](#configure-the-device-profiles) - [Configure the Provision Watchers](#configure-the-provision-watchers) - [Build the Docker Image](#build-the-docker-image) - [Additional Configuration](#additional-configuration) - [Next Steps](#next-steps) - - -## Get the Source Code - -1. Clone the device-onvif-camera repository. - - ```bash - git clone https://github.com/edgexfoundry/device-onvif-camera.git - ``` - -2. Navigate into the directory - - ```bash - cd device-onvif-camera - ``` - - -## Configuration - -### Configure the Pre-Defined Devices - -Configuring pre-defined devices will allow the service to automatically provision them into core-metadata. Create a list of devices with the appropriate information as outlined below. - -1. Make a copy of the `camera.yaml.example`: - ```bash - cp ./cmd/res/devices/camera.yaml.example ./cmd/res/devices/camera.yaml - ``` - -1. Open the `cmd/res/devices/camera.yaml` file using your preferred text editor and update the `Address` and `Port` fields to match the IP address of the Camera and port used for ONVIF services: - - ```yaml - deviceList: - - name: Camera001 # Modify as desired - profileName: onvif-camera # Default profile - description: onvif conformant camera # Modify as desired - protocols: - Onvif: - Address: 191.168.86.34 # Set to your camera IP address - Port: '2020' # Set to the port your camera uses - SecretName: credentials001 - CustomMetadata: - CommonName: Outdoor camera - ``` -

- Sample: Snippet from camera.yaml -

- -1. Optionally, modify the `Name` and `Description` fields to more easily identify the camera. The `Name` is the camera name used when using ONVIF Device Service Rest APIs. The `Description` is simply a more detailed explanation of the camera. - -1. You can also optionally configure the `CustomMetadata` with custom fields and values to store any extra information you would like. - -1. To add more pre-defined devices, copy the above configuration and edit to match your extra devices. - - -### Configure the Device Service -1. Open the [configuration.yaml](./cmd/res/configuration.yaml) file using your preferred text editor - -1. Make sure `secret name` is set to match `SecretName` in `camera.yaml`. In the sample below, it is `"credentials001"`. If you have multiple cameras, make sure the secret names match. - -1. Under `secretName`, set `username` and `password` to your camera credentials. If you have multiple cameras copy the `Writable.InsecureSecrets` section and edit to include the new information. - -```yaml -Writable: - LogLevel: INFO - InsecureSecrets: - credentials001: - SecretName: credentials001 - SecretData: - username: - password: - mode: usernametoken # assign "digest" | "usernametoken" | "both" | "none" - credentials002: - SecretName: credentials002 - SecretData: - username: - password: - mode: usernametoken # assign "digest" | "usernametoken" | "both" | "none" -``` - -

- Sample: Snippet from configuration.yaml -

- -### Additional Configuration Options -For optional configurations, see [here.](#additional-configuration) - -## Build the Docker Image - -1. In the `device-onvif-camera` directory, run make docker: - - ```bash - make docker - ``` -
- [Optional] Build with NATS Messaging - - Currently, the NATS Messaging capability (NATS MessageBus) is opt-in at build time. This means that the published Docker image and Snaps do not include the NATS messaging capability. To build the docker image using NATS, run make docker-nats: - - ```bash - make docker-nats - ``` - - See [Compose Builder](https://github.com/edgexfoundry/edgex-compose/tree/main/compose-builder#gen) `nat-bus` option to generate compose file for NATS and local dev images. - -
- -1. Verify the ONVIF Device Service Docker image was successfully created: - - ```bash - docker images - ``` - ```docker - REPOSITORY TAG IMAGE ID CREATED SIZE - edgexfoundry-holding/device-onvif-camera 0.0.0-dev 75684e673feb 6 weeks ago 21.3MB - ``` - -1. Navigate to `edgex-compose` and enter the `compose-builder` directory. - - ```bash - cd edgex-compose/compose-builder - ``` - -1. Update `.env` file to add the registry and image version variable for device-onvif-camera: - - Add the following registry and version information: - ```env - DEVICE_ONVIFCAM_VERSION=0.0.0-dev - ``` - -4. Update the `add-device-onvif-camera.yml` to point to the local image. - - ```yml - services: - device-onvif-camera: - image: edgexfoundry/device-onvif-camera:${DEVICE_ONVIFCAM_VERSION} - ``` - -## Additional Configuration - -Here is some information on how to specially configure parts of the service beyond the provided defaults. - -### Configure the Device Profiles - -The device profile contains general information about the camera and includes all of the device resources and commands that the device resources can use to manage the cameras. The default [profile](../cmd/res/camera.yaml) contains all possible resources a camera could implement. Enable and disable supported resources in this file, or create an entirely new profile. It is important to set up the device profile to match the capabilities of the camera. Information on the resources supported by specific cameras can be found [here](./ONVIF-protocol.md#tested-onvif-cameras). Learn more about device profiles in EdgeX [here.](https://docs.edgexfoundry.org/1.2/microservices/device/profile/Ch-DeviceProfile/) - -```yaml -name: "onvif-camera" # general information about the profile -manufacturer: "Generic" -model: "Generic ONVIF" -labels: - - "onvif" -description: "EdgeX device profile for ONVIF-compliant IP camera." - -deviceResources: - # Network Configuration - - name: "Hostname" # an example of a resource with get/set values - isHidden: false - description: "Camera Hostname" - attributes: - service: "Device" - getFunction: "GetHostname" - setFunction: "SetHostname" - properties: - valueType: "Object" - readWrite: "RW" -``` -

- Sample: Snippet from camera.yaml -

- - -### Configure the Provision Watchers - -The provision watcher sets up parameters for EdgeX to automatically add devices to core-metadata. They can be configured to look for certain features, as well as block features. The default provision watcher is sufficient unless you plan on having multiple different cameras with different profiles and resources. Learn more about provision watchers [here](https://docs.edgexfoundry.org/2.2/microservices/core/metadata/Ch-Metadata/#provision-watcher). - -```json -{ - "name":"Generic-Onvif-Provision-Watcher", - "identifiers":{ // Use the identifiers to filter through specific features of the protocol - "Address": ".", - "Manufacturer": "Intel", // example of a feature to allow through - "Model": "DFI6256TE" - }, - "blockingIdentifiers":{ - }, - "serviceName": "device-onvif-camera", - "profileName": "onvif-camera", - "adminState":"UNLOCKED" -} -``` -

- Sample: Snippet from generic.provision.watcher.yaml -

- -## Next Steps -[Running and Verifying the device service](./running-guide.md) - -## License - -[Apache-1.0](https://github.com/edgexfoundry-holding/device-onvif-camera/blob/main/LICENSE) diff --git a/doc/custom-feature-rebootneeded.md b/doc/custom-feature-rebootneeded.md deleted file mode 100644 index e2bd5b32..00000000 --- a/doc/custom-feature-rebootneeded.md +++ /dev/null @@ -1,93 +0,0 @@ -# The custom feature - RebootNeeded - -## Why need the custom feature RebootNeeded? -Currently, only the SetNetworkInterfaces function returns the **RebootNeeded** value, if RebootNeeded is true, the user need to reboot the camera to apply the config changes. - -Since the Set command can't return the **RebootNeeded** value in command response, the device-onvif-camera will store the value in the memory, then the user can use the custom web service **EdgeX** and function **RebootNeeded** to check the value. - -## How does the RebootNeeded work with EdgeX? - -### 1. Execute Set command to change the networkInterfaces setting: -```shell -curl --request PUT 'http://0.0.0.0:59882/api/v2/device/name/Camera001/NetworkInterfaces' \ ---header 'Content-Type: application/json' \ ---data-raw '{ - "NetworkInterfaces": { - "InterfaceToken": "eth0", - "NetworkInterface": { - "Enabled": true, - "IPv4": { - "DHCP": true - } - } - } -}' -``` -### 2. Check the RebootNeeded value: -Using the **RebootNeeded** resource to check whether the camera need to reboot: -```shell -$ curl 'http://0.0.0.0:59882/api/v2/device/name/Camera001/RebootNeeded' | jq . -{ - "apiVersion" : "v2", - "event" : { - "apiVersion" : "v2", - "deviceName" : "Camera001", - "id" : "e370bbb5-55d2-4392-84ca-8d9e7f097dae", - "origin" : 1635750695886624000, - "profileName" : "onvif-camera", - "readings" : [ - { - "deviceName" : "Camera001", - "id" : "abd5c555-ef7d-44a7-9273-c1dbb4d14de2", - "origin" : 1635750695886624000, - "profileName" : "onvif-camera", - "resourceName" : "RebootNeeded", - "value" : "true", - "valueType" : "Bool" - } - ], - "sourceName" : "RebootNeeded" - }, - "statusCode" : 200 -} -``` - -The RebootNeeded is true which indicates the camera should reboot to apply the change. - -### 3. Reboot the camera to apply the change: -```shell -curl --request PUT 'http://0.0.0.0:59882/api/v2/device/name/Camera001/SystemReboot' \ ---header 'Content-Type: application/json' \ ---data-raw '{ - "SystemReboot": {} -}' -``` -The SystemReboot command also change the **RebootNeeded** value from `true` to `false`. - -### 4. Check The RebootNeeded value -```shell -$ curl 'http://0.0.0.0:59882/api/v2/device/name/Camera001/RebootNeeded' | jq . -{ - "apiVersion" : "v2", - "event" : { - "apiVersion" : "v2", - "deviceName" : "Camera001", - "id" : "53585696-ec1a-4ac7-9a42-7d480c0a75d9", - "origin" : 1635750854455262000, - "profileName" : "onvif-camera", - "readings" : [ - { - "deviceName" : "Camera001", - "id" : "87819d3a-25d0-4313-b69a-54c4a0c389ed", - "origin" : 1635750854455262000, - "profileName" : "onvif-camera", - "resourceName" : "RebootNeeded", - "value" : "false", - "valueType" : "Bool" - } - ], - "sourceName" : "RebootNeeded" - }, - "statusCode" : 200 -} -``` diff --git a/doc/custom-metadata-feature.md b/doc/custom-metadata-feature.md deleted file mode 100644 index 03d098d7..00000000 --- a/doc/custom-metadata-feature.md +++ /dev/null @@ -1,175 +0,0 @@ -# Custom Metadata - -Custom metadata can be applied and retrieved for each camera added to the service. - -## Usage - -- The `CustomMetadata` map is an element in the `ProtocolProperties` device field. It is initialized to be empty on discovery, so the user can add their desired fields. Otherwise, the user can pre-define this field in a camera.yaml file. - -### Preset Custom Metadata - -If you add pre-defined devices, set up the `CustomMetadata` object as shown in the [camera.yaml.example file](../cmd/res/devices/camera.yaml.example). - -```yaml -deviceList: - - name: Camera001 - profileName: onvif-camera - description: onvif conformant camera - protocols: - ... - CustomMetadata: - Location: Front door - Color: Black and white -``` - -### Set Custom Metadata - -Use the CustomMetadata resource to set the fields of `CustomMetadata`. Choose the key/value pairs to represent your custom fields. - -1. Use this command to put the data in the CustomMetadata field. -```shell -curl --request PUT 'http://0.0.0.0:59882/api/v2/device/name//CustomMetadata' \ - --header 'Content-Type: application/json' \ - --data-raw '{ - "CustomMetadata": { - "Location":"Front Door", - "Color":"Black and white", - "Condition": "Good working condition" - } - }' | jq . -``` -2. The response from the curl command. -``` -{ - "apiVersion": "v2", - "statusCode": 200 -} -``` ->Note: ensure all data is properly formatted json, and that all special characters are escaped if necessary - - -### Get Custom Metadata - -Use the CustomMetadata resource to get and display the fields of `CustomMetadata`. - -1. Use this command to return all of the data in the CustomMetadata field. - -```shell -curl http://localhost:59882/api/v2/device/name//CustomMetadata | jq . -``` -2. The repsonse from the curl command. -```shell -{ - "apiVersion" : "v2", - "event" : { - "apiVersion" : "v2", - "deviceName" : "3fa1fe68-b915-4053-a3e1-cc32e5000688", - "id" : "ba3987f9-b45b-480a-b582-f5501d673c4d", - "origin" : 1655409814077374935, - "profileName" : "onvif-camera", - "readings" : [ - { - "deviceName" : "3fa1fe68-b915-4053-a3e1-cc32e5000688", - "id" : "cf96e5c0-bde1-4c0b-9fa4-8f765c8be456", - "objectValue" : { - "Color" : "Black and white", - "Condition" : "Good working condition", - "Location" : "Front Door" - }, - "origin" : 1655409814077374935, - "profileName" : "onvif-camera", - "resourceName" : "CustomMetadata", - "value" : "", - "valueType" : "Object" - } - ], - "sourceName" : "CustomMetadata" - }, - "statusCode" : 200 -} -``` - - -### Get Specific Custom Metadata - -Pass the `CustomMetadata` resource a query to get specific field(s) in CustomMetadata. The query must be a base64 encoded json object with an array of fields you want to access. - -1. Json object holding an array of fields you want to query. -```json -'[ - "Color", - "Location" -]' -``` - -2. Use this command to convert the json object to base64. -```shell -echo '[ - "Color", - "Location" -]' | base64 -``` - -3. The response converted to base64. -```shell -WwogICAgIkNvbG9yIiwKICAgICJMb2NhdGlvbiIKXQo= -``` - -4. Use this command to query the fields you provided in the json object. -```shell -curl http://localhost:59882/api/v2/device/name//CustomMetadata?jsonObject=WwogICAgIkNvbG9yIiwKICAgICJMb2NhdGlvbiIKXQo= | jq . - -``` - -5. Curl response. -```shell -{ - "apiVersion" : "v2", - "event" : { - "apiVersion" : "v2", - "deviceName" : "3fa1fe68-b915-4053-a3e1-cc32e5000688", - "id" : "24c3eb0a-48b1-4afe-b874-965aeb2e42a2", - "origin" : 1655410556448058195, - "profileName" : "onvif-camera", - "readings" : [ - { - "deviceName" : "3fa1fe68-b915-4053-a3e1-cc32e5000688", - "id" : "d0c26303-20b5-4ccd-9e63-fb02b87b8ebc", - "objectValue" : { - "Color": "Black and white", - "Location" : "Front Door" - }, - "origin" : 1655410556448058195, - "profileName" : "onvif-camera", - "resourceName" : "CustomMetadata", - "value" : "", - "valueType" : "Object" - } - ], - "sourceName" : "CustomMetadata" - }, - "statusCode" : 200 -} -``` - -### Additional Usage - -Use the DeleteCustomMetadata resource to delete entries in custom metadata - -1. Use this command to delete fields. -```shell -curl --request PUT 'http://0.0.0.0:59882/api/v2/device/name//DeleteCustomMetadata' \ - --header 'Content-Type: application/json' \ - --data-raw '{ - "DeleteCustomMetadata": [ - "Color", "Condition" - ] - }' | jq . -``` -2. The response from the curl command. -``` -{ - "apiVersion": "v2", - "statusCode": 200 -} -``` diff --git a/doc/device-status.md b/doc/device-status.md deleted file mode 100644 index 5e7bd6f6..00000000 --- a/doc/device-status.md +++ /dev/null @@ -1,87 +0,0 @@ -# Device Status -The device status goes hand in hand with the rediscovery of the cameras, but goes beyond the scope of just discovery. -It is a separate background task running at a specified interval (default 30s) to determine the most accurate -operating status of the existing cameras. This applies to all devices regardless of how or where they were added from. - -## States and Descriptions -Currently, there are 4 different statuses that a camera can have - -- **UpWithAuth**: Can execute commands requiring credentials -- **UpWithoutAuth**: Can only execute commands that do not require credentials. Usually this means the camera's credentials have not been registered with the service yet, or have been changed. -- **Reachable**: Can be discovered but no commands can be received. -- **Unreachable**: Cannot be seen by service at all. Typically, this means that there is a connection issue either physically or with the network. - -### Status Check flow for each device -```mermaid -%% Note: The node and edge definitions are split up to make it easier to adjust the -%% links between the various nodes. -flowchart TD; - %% -------- Node Definitions -------- %% - CheckDeviceStatus(Check Device Status) - UpdateDeviceStatus[Update Device Status
in Core-Metadata] - SetLastSeen[Set LastSeen = Now] - UpdateMetadata[Update Core-Metadata] - CheckNowUpWithAuth{Status Changed
&&
Status == UpWithAuth?} - DeviceHasMAC{Device Has
MAC Address?} - CreateClient[Create Onvif Client] - GetCapabilities[Device::GetCapabilities] - CheckUpdatedMAC[Check CredentialsMap for
updated MAC Address] - TCPProbe[TCP Probe] - GetDeviceInfo[GetDeviceInformation] - UpdateDeviceInfo[Update Device Information] - UpdateMACAddress[Update MAC Address] - UpdateEndpointRef[Update EndpointRefAddress] - DeviceUnknown{Device Name
begins with
unknown_unknown_?} - RemoveDevice[Remove Device
unknown_unknown_<EndpointRef>] - CreateDevice[Create Device
<Mfg>-<Model>-<EndpointRef>] - - %% -------- Graph Definitions -------- %% - CheckDeviceStatus --> DeviceHasMAC - DeviceHasMAC -->|No| CheckUpdatedMAC - DeviceHasMAC -->|Yes| CreateClient - CheckUpdatedMAC --> CreateClient - - subgraph TestConnection[Test Connection Methods] - CreateClient --> GetCapabilities - GetCapabilities -->|Failed| TCPProbe - GetCapabilities -->|Success| GetDeviceInfo - GetDeviceInfo -->|Success| UpWithAuth - GetDeviceInfo -->|Failed| UpWithoutAuth - TCPProbe -->|Failed| Unreachable - TCPProbe -->|Success| Reachable - end - - UpWithAuth --> SetLastSeen - UpWithoutAuth --> SetLastSeen - Reachable --> SetLastSeen - Unreachable --> UpdateDeviceStatus - UpdateDeviceStatus --> CheckNowUpWithAuth - SetLastSeen --> UpdateDeviceStatus - CheckNowUpWithAuth -->|Yes| RefreshDevice - - subgraph RefreshDevice[Refresh Device] - UpdateDeviceInfo --> UpdateMACAddress - UpdateMACAddress --> UpdateEndpointRef - UpdateEndpointRef --> DeviceUnknown - DeviceUnknown -->|No| UpdateMetadata - DeviceUnknown -->|Yes| RemoveDevice - RemoveDevice --> CreateDevice - end -``` - -## Configuration Options -- Use `EnableStatusCheck` to enable the device status background service. -- `CheckStatusInterval` is the interval at which the service will determine the status of each camera. - -```yaml -# Enable or disable the built in status checking of devices, which runs every CheckStatusInterval. -EnableStatusCheck: true -# The interval in seconds at which the service will check the connection of all known cameras and update the device status -# A longer interval will mean the service will detect changes in status less quickly -# Maximum 300s (5 minutes) -CheckStatusInterval: 30 -``` - -## Automatic Triggers -Currently, there are some actions that will trigger an automatic status check: -- Any modification to the `CredentialsMap` from the config provider (Consul) diff --git a/doc/general-usage.md b/doc/general-usage.md deleted file mode 100644 index 4aace6f8..00000000 --- a/doc/general-usage.md +++ /dev/null @@ -1,312 +0,0 @@ - -# General Usage - -This document will describe how to execute some of the most important types of commands used with the device service. - -## Table of Contents - -[Get the Available Commands](#get-the-available-commands) -[Read a Single Resource](#execute-a-get-command---read-single-resource) -[Read Multiple Resources](#execute-a-get-command---read-multiple-resources) -[Set a Single Resource](#execute-a-set-command---write-single-resource) -[Set Multiple Resources](#execute-a-set-command---write-multiple-resource) -[Execute Commands Requiring Paramters](#execute-command-requiring-parameters) -[Next Steps](#next-steps) - -## Get the Available Commands -1. Check the available commands from core-command service: -```shell -curl http://localhost:59882/api/v2/device/name/Camera001 | jq -``` - -Example Output: - -```json -{ - "apiVersion": "v2", - "statusCode": 200, - "deviceCoreCommand": { - "deviceName": "Camera001", - "profileName": "onvif-camera", - "coreCommands": [ - { - "name": "NetworkDefaultGateway", - "get": true, - "set": true, - "path": "/api/v2/device/name/Camera001/NetworkDefaultGateway", - "url": "http://edgex-core-command:59882", - "parameters": [ - { - "resourceName": "NetworkDefaultGateway", - "valueType": "Object" - } - ] - }, - { - "name": "AddMetadataConfiguration", - "set": true, - "path": "/api/v2/device/name/Camera001/AddMetadataConfiguration", - "url": "http://edgex-core-command:59882", - "parameters": [ - { - "resourceName": "AddMetadataConfiguration", - "valueType": "Object" - } - ] - }, - ] - } -} -``` - ->NOTE: This response has been shortened, most device profiles will have many resources. - -## Execute a Get Command - Read Single Resource - -Example Command: -```shell -curl http://0.0.0.0:59882/api/v2/device/name/Camera001/Hostname | jq -``` -Example Output: - -```json -{ - "apiVersion" : "v2", - "event" : { - "apiVersion" : "v2", - "deviceName" : "Camera001", - "id" : "6b46d058-d8e0-4095-ba80-4a6de1787510", - "origin" : 1635749209227019000, - "profileName" : "onvif-camera", - "readings" : [ - { - "deviceName" : "Camera001", - "id" : "a1b0d809-c88a-4889-920e-8ac64e6aa658", - "objectValue" : { - "HostnameInformation" : { - "FromDHCP" : false, - "Name" : "localhost" - } - }, - "origin" : 1635749209227019000, - "profileName" : "onvif-camera", - "resourceName" : "Hostname", - "valueType" : "Object" - } - ], - "sourceName" : "Hostname" - }, - "statusCode" : 200 -} -``` - -## Execute a Get Command - Read Multiple Resources - -Example Command: -```shell -curl http://0.0.0.0:59882/api/v2/device/name/Camera001/NetworkConfiguration | jq -``` - -Example Output: -```json -{ - "apiVersion" : "v2", - "event" : { - "apiVersion" : "v2", - "sourceName" : "NetworkConfiguration", - "deviceName" : "Camera001", - "id" : "24d5e391-0dcd-48f5-8706-6abb11797d29", - "origin" : 1635868623002677000, - "profileName" : "onvif-camera", - "readings" : [ - { - "deviceName" : "Camera001", - "id" : "87d0bcfd-aecf-4ab7-a871-2b85a3c90f00", - "objectValue" : { - "HostnameInformation" : { - "FromDHCP" : false, - "Name" : "localhost" - } - }, - "origin" : 1635868623002677000, - "profileName" : "onvif-camera", - "resourceName" : "Hostname", - "valueType" : "Object" - }, - { - "deviceName" : "Camera001", - "id" : "edfa8d6f-a96e-49a8-96c9-595905cbe170", - "objectValue" : { - "DNSInformation" : { - "DNSManual" : { - "IPv4Address" : "192.168.12.1", - "Type" : "IPv4" - }, - "FromDHCP" : false - } - }, - "origin" : 1635868623002677000, - "profileName" : "onvif-camera", - "resourceName" : "DNS", - "valueType" : "Object" - }, - ... - ] - }, - "statusCode" : 200 -} -``` - -## Execute a Set Command - Write Single Resource -Example Command: -```shell -curl -X PUT -H 'Content-Type: application/json' 'http://0.0.0.0:59882/api/v2/device/name/Camera001/Hostname' \ - -d '{ - "Hostname": { - "Name": "localhost555" - } - }' -``` - -## Execute a Set Command - Write Multiple Resource -```shell -curl -X PUT -H 'Content-Type: application/json' 'http://0.0.0.0:59882/api/v2/device/name/Camera001/NetworkConfiguration' \ - -d '{ - "Hostname": { - "Name": "localhost" - }, - "DNS": { - "FromDHCP": false, - "DNSManual": { - "Type": "IPv4", - "IPv4Address": "192.168.12.1" - } - }, - "NetworkInterfaces": { - "InterfaceToken": "eth0", - "NetworkInterface": { - "Enabled": true, - "IPv4": { - "DHCP": false - } - } - - }, - "NetworkProtocols": { - "NetworkProtocols": [ - { - "Name": "HTTP", - "Enabled": true, - "Port": 80 - } - ] - }, - "NetworkDefaultGateway": { - "IPv4Address": "192.168.12.1" - } - }' -``` - -## Execute Command Requiring Parameters - -In this example, the GetStreamURI will be used as the example command. Some commands require a URL query to be passed, which is a base 64 encoded json object. The information needed for each command differs on an individual basis. This will walk you through how to get information from the device to pass as one of these queries, and use it appropriately. See the Swagger documentation (not implemented) for more information. - - -1. Get the profile token by executing the `GetProfiles` command: - - ```bash - curl http://0.0.0.0:59882/api/v2/device/name/Camera001/Profiles | jq - ``` - - Example Output: - ```json - { - "apiVersion": "v2", - "statusCode": 200, - "event": { - "apiVersion": "v2", - "id": "172bc5e6-cb6c-4c3d-aeb8-193cb968d304", - "deviceName": "TP-Link-C200-3fa1fe68-b915-4053-a3e1-cc32e5000688", - "profileName": "onvif-camera", - "sourceName": "Profiles", - "origin": 1657128504840230400, - "readings": [ - { - "id": "02e1c0cd-97f3-4846-85bf-dd5eff701e9f", - "origin": 1657128504840230400, - "deviceName": "TP-Link-C200-3fa1fe68-b915-4053-a3e1-cc32e5000688", - "resourceName": "Profiles", - "profileName": "onvif-camera", - "valueType": "Object", - "value": "", - "objectValue": { - "Profiles": [ - { - "Extension": null, - "Fixed": true, - "MetadataConfiguration": null, - "Name": "mainStream", - "PTZConfiguration": null, - "Token": "profile_1", - }, - ]} - }] - }} - ``` ->NOTE: This output has been trimmed to only show a necessary section. - -2. Convert the JSON input to Base64: - - >NOTE: Make sure to change the profile token to the one found in step 1. In this example, it is the string `profile_1`. - - ```json - { - "ProfileToken": "profile_1" - } - ``` - Example Output: - - ```bash - echo -n '{ - "ProfileToken": "profile_1" - }' | base64 - ewogICAgICAiUHJvZmlsZVRva2VuIjogInByb2ZpbGVfMSIKfQ== - ``` - -3. Execute `GetStreamURI` command to get RTSP URI from the ONVIF device. Make sure to put the Base64 JSON data after *?jsonObject=* in the command. - - ```bash - curl http://0.0.0.0:59882/api/v2/device/name/Camera001/StreamUri?jsonObject=ewogICAgICAiUHJvZmlsZVRva2VuIjogInByb2ZpbGVfMSIKfQ== | jq -r '"streamURI: " + '.event.readings[].objectValue.MediaUri.Uri'' - ``` - - Example Output: - - ```bash - streamURI: rtsp://192.168.86.34:554/stream1 - ``` - -4. Stream the RTSP stream: - - Alternatively, ffplay can be used to stream. The command follows this format: - - `ffplay -rtsp_transport tcp rtsp://'':''@:/`. - - Using the `streamURI` returned from the previous step, run ffplay: - - ```bash - ffplay -rtsp_transport tcp rtsp://'admin':'Password123'@192.168.86.34:554/stream1 - ``` - >NOTE: While the `streamURI` returned did not contain the username and password, those credentials are required in order to correctly authenticate the request and play the stream. Therefore, it is included in both the VLC and ffplay streaming examples. - >NOTE: If the password uses special characters, you must use percent-encoding. - -5. To shut down ffplay, use the ctrl-c command. - -## Next Steps -[Explore the Swagger documentation (not implemented)]() -[Explore auto discovery](./auto-discovery.md) - -Refer to the main [README](../README.md) to find links to the rest of the documents. - -# License - -[Apache-2.0](https://github.com/edgexfoundry-holding/device-onvif-camera/blob/main/LICENSE) diff --git a/doc/get-set-friendlyname-mac.md b/doc/get-set-friendlyname-mac.md deleted file mode 100644 index dbd2b655..00000000 --- a/doc/get-set-friendlyname-mac.md +++ /dev/null @@ -1,159 +0,0 @@ -# Get and Set Friendly Name and MAC Address - -Friendly name and MAC address can be set and retrieved for each camera added to the service. - - -## Preset FriendlyName -`FriendlyName` is an element in the `Onvif ProtocolProperties` device field. It is initialized to be empty or `` -if credentials are provided on discovery. The user can also pre-define this field in a camera.yaml file. - -If you add pre-defined devices, set up the `FriendlyName` field as shown in the -[camera.yaml.example file](../cmd/res/devices/camera.yaml.example). - -```yaml -# Pre-defined Devices -deviceList: - - name: Camera001 - profileName: onvif-camera - description: onvif conformant camera - protocols: - Onvif: - Address: 192.168.12.123 - Port: '80' - FriendlyName: Home camera - CustomMetadata: - Location: Front door -``` - -## Set Friendly Name - -Friendly name can also be set via Edgex device command. -FriendlyName device resource is used to set `FriendlyName` of a camera. - -1. Use this command to set FriendlyName field. - -```shell -curl --request PUT 'http://0.0.0.0:59882/api/v2/device/name//FriendlyName' \ - --header 'Content-Type: application/json' \ - --data-raw '{ - "FriendlyName":"Home camera" - }' | jq . -``` -2. The response from the curl command. -``` -{ - "apiVersion": "v2", - "statusCode": 200 -} -``` ->Note: ensure all data is properly formatted json, and that all special characters are escaped if necessary - - -## Get Friendly Name - -Use the FriendlyName device resource to retrieve `FriendlyName` of a camera. - -1. Use this command to return FriendlyName field. - -```shell -curl http://localhost:59882/api/v2/device/name//FriendlyName | jq . -``` -2. Response from the curl command. FriendlyName value can be found under `value` field in the json response. -```shell -{ - "apiVersion": "v2", - "statusCode": 200, - "event": { - "apiVersion": "v2", - "id": "5b924351-31c7-469e-a9ba-dea063fdbf3a", - "deviceName": "TP-Link-C200-3fa1fe68-b915-4053-a3e1-cc32e5000688", - "profileName": "onvif-camera", - "sourceName": "FriendlyName", - "origin": 1658441317910501400, - "readings": [ - { - "id": "62a0424b-a3c1-45ea-b640-58c7aa3ea476", - "origin": 1658441317910501400, - "deviceName": "TP-Link-C200-3fa1fe68-b915-4053-a3e1-cc32e5000688", - "resourceName": "FriendlyName", - "profileName": "onvif-camera", - "valueType": "String", - "value": "Home camera" - } - ] - } -} -``` - -## Preset MACAddress -`MACAddress` is an element in the `Onvif ProtocolProperties` device field. It will be set to empty string if no value is provided, or -it will be set with the MAC address value of the camera if valid credentials are provided. -The user can pre-define this field in a camera.yaml file. - - - -If you add pre-defined devices, set up the `MACAddress` field as shown in the -[camera.yaml.example file](../cmd/res/devices/camera.yaml.example). - -## Set MAC Address - -MACAddress can also be set via Edgex device command.This is useful for setting the MAC Address for devices which do not contain -the MAC Address in the Endpoint Reference Address, or have been added manually without a MAC Address. -Since the MAC is used to map credentials for cameras, it is important to have this field filled out. - -> Note: When a camera successfully becomes `UpWithAuth`, the MAC Address is automatically queried and overridden by the system if available. -Device resource MACAddress is used to set `MACAddress` of a camera. - -1. Use this command to set MACAddress field. -```shell -curl --request PUT 'http://0.0.0.0:59882/api/v2/device/name//MACAddress' \ - --header 'Content-Type: application/json' \ - --data-raw '{ - "MACAddress":"11:22:33:44:55:66" - }' | jq . -``` -2. The response from the curl command. -``` -{ - "apiVersion": "v2", - "statusCode": 200 -} -``` ->Note: ensure all data is properly formatted json, and that all special characters are escaped if necessary. - - -## Get MAC Address - -Use the MACAddress device resource to retrieve `MACAddress` of a camera. - -1. Use this command to return MACAddress field. - -```shell -curl http://localhost:59882/api/v2/device/name//MACAddress | jq . -``` -2. Response from the curl command. MACAddress value can be found under `value` field in the json response. -```shell -{ - "apiVersion": "v2", - "statusCode": 200, - "event": { - "apiVersion": "v2", - "id": "c13245b0-397f-47c0-84b2-4de3d2fb891d", - "deviceName": "TP-Link-C200-3fa1fe68-b915-4053-a3e1-1027f5ea8888", - "profileName": "onvif-camera", - "sourceName": "MACAddress", - "origin": 1658441498356294000, - "readings": [ - { - "id": "7a7735ed-3b61-4426-84df-5e9a524e4022", - "origin": 1658441498356294000, - "deviceName": "TP-Link-C200-3fa1fe68-b915-4053-a3e1-1027f5ea8888", - "resourceName": "MACAddress", - "profileName": "onvif-camera", - "valueType": "String", - "value": "11:22:33:44:55:66" - } - ] - } -} -``` diff --git a/doc/getting-started-with-docker-security.md b/doc/getting-started-with-docker-security.md deleted file mode 100644 index 0bd70b48..00000000 --- a/doc/getting-started-with-docker-security.md +++ /dev/null @@ -1,172 +0,0 @@ -# Getting Started With Docker (Security Mode) - -This section describes how to run **device-onvif-camera** with **docker** and **EdgeX security mode**. - -## 1. Build docker image -Build docker image named edgex/device-onvif-camera:0.0.0-dev with the following command: -```shell -make docker -``` - -## 2. Prepare edgex-compose/compose-builder -1. Download the [edgex-compose](https://github.com/edgexfoundry/edgex-compose) -2. Change directory to the `edgex-compose/compose-builder` - -## 3. Deploy services with the following command: -```shell -make run ds-onvif-camera -``` - -### 3.1 Check whether the services are running from Consul -1. Get the consul token for Consul Login -```shell -$ make get-consul-acl-token -14891947-51b3-603d-9e35-628fb82993f4 -``` -2. Navigate to `http://localhost:8500/` - -![Consul](images/getting-started-with-docker-consul.jpg) - -## 4. Add the Username and Password for the Onvif Camera -```shell -curl --location --request POST 'http://0.0.0.0:59984/api/v2/secret' \ ---header 'Content-Type: application/json' \ ---data-raw '{ - "apiVersion":"v2", - "secretName": "bosch", - "secretData":[ - { - "key":"username", - "value":"administrator" - }, - { - "key":"password", - "value":"Password1!" - }, - { - "key":"mode", - "value":"digest" - } - ] -}' -``` - - -## 5. Add the device profile to EdgeX -Change directory back to the `device-onvif-camera` and add the device profile to core-metadata service with the following command: -```shell -curl http://localhost:59881/api/v2/deviceprofile/uploadfile \ - -F "file=@./cmd/res/profiles/camera.yaml" -``` - -## 6. Add the device to EdgeX -Add the device data to core-metadata service with the following command: -```shell -curl -X POST -H 'Content-Type: application/json' \ - http://localhost:59881/api/v2/device \ - -d '[ - { - "apiVersion": "v2", - "device": { - "name":"Camera003", - "serviceName": "device-onvif-camera", - "profileName": "onvif-camera", - "description": "My test camera", - "adminState": "UNLOCKED", - "operatingState": "UNKNOWN", - "protocols": { - "Onvif": { - "Address": "192.168.12.148", - "Port": "80", - "AuthMode": "digest", - "SecretName": "bosch" - } - } - } - } - ]' -``` - -Check the available commands from core-command service: -```shell -$ curl http://localhost:59882/api/v2/device/name/Camera003 | jq . -{ - "apiVersion" : "v2", - "deviceCoreCommand" : { - "coreCommands" : [ - { - "get" : true, - "set" : true, - "name" : "DNS", - "parameters" : [ - { - "resourceName" : "DNS", - "valueType" : "Object" - } - ], - "path" : "/api/v2/device/name/Camera003/DNS", - "url" : "http://edgex-core-command:59882" - }, - ... - { - "get" : true, - "name" : "StreamUri", - "parameters" : [ - { - "resourceName" : "StreamUri", - "valueType" : "Object" - } - ], - "path" : "/api/v2/device/name/Camera003/StreamUri", - "url" : "http://edgex-core-command:59882" - } - ], - "deviceName" : "Camera003", - "profileName" : "onvif-camera" - }, - "statusCode" : 200 -} -``` - -## 7. Execute a Get Command -```shell -$ curl http://0.0.0.0:59882/api/v2/device/name/Camera003/Users | jq . -{ - "apiVersion" : "v2", - "event" : { - "apiVersion" : "v2", - "deviceName" : "Camera003", - "id" : "c0826f49-2840-421b-9474-7ad63a443302", - "origin" : 1639525215434025100, - "profileName" : "onvif-camera", - "readings" : [ - { - "deviceName" : "Camera003", - "id" : "d4dc823a-d75f-4fe1-8ee4-4220cc53ddc6", - "objectValue" : { - "User" : [ - { - "UserLevel" : "Operator", - "Username" : "user" - }, - { - "UserLevel" : "Administrator", - "Username" : "service" - }, - { - "UserLevel" : "Administrator", - "Username" : "administrator" - } - ] - }, - "origin" : 1639525215434025100, - "profileName" : "onvif-camera", - "resourceName" : "Users", - "valueType" : "Object" - } - ], - "sourceName" : "Users" - }, - "statusCode" : 200 -} -``` diff --git a/doc/guides/CustomStartupGuide.md b/doc/guides/CustomStartupGuide.md deleted file mode 100644 index fae37f7c..00000000 --- a/doc/guides/CustomStartupGuide.md +++ /dev/null @@ -1,846 +0,0 @@ -# ONVIF Device Service Custom Start Up Guide - -## Contents - -[System Requirements](#system-requirements) -[Dependencies](#dependencies) -[Get the Source Code](#get-the-source-code) -[Configuration](#configuration) -[Build the Docker Image](#build-the-docker-image) -[Deploy the Service](#deploy-edgex-and-onvif-device-camera-microservice) -[Verify the Service](#verify-service-and-device-profiles) -[Manage Devices](#manage-devices) -[Execute Example Command](#execute-getstreamuri-command-through-edgex) -[Shutting Down](#shutting-down) -[Additional Configuration](#additional-configuration) -[Next Steps](#summary-and-next-steps) - - -## System Requirements - -- Intel™ Core® processor -- Ubuntu 20.04.4 LTS -- ONVIF-compliant Camera - ->**NOTE:** The instructions in this guide were developed and tested using Ubuntu 20.04 LTS and the Tapo C200 Pan/Tilt Wi-Fi Camera. However, the software may work with other Linux distributions and ONVIF-compliant cameras. Refer to our [list of tested cameras for more information](../ONVIF-protocol.md#tested-onvif-cameras) - -**Time to Complete** - -20-30 minutes - -**Other Requirements** - -You must have administrator (sudo) privileges to execute the user guide commands. - -## How It Works -For an explanation of the architecture, see the [User Guide](../../README.md#how-it-works). - -## Dependencies -The software has dependencies, including Git, Docker, Docker Compose, and assorted tools. Follow the instructions below to install any dependency that is not already installed. - -### Install Git -Install Git from the official repository as documented on the [Git SCM](https://git-scm.com/download/linux) site. - -1. Update installation repositories: - ```bash - sudo apt update - ``` - -2. Add the Git repository: - ```bash - sudo add-apt-repository ppa:git-core/ppa -y - ``` - -3. Install Git: - ```bash - sudo apt install git - ``` - -### Install Docker -Install Docker from the official repository as documented on the [Docker](https://docs.docker.com/engine/install/ubuntu/) site. - -### Verify Docker -To enable running Docker commands without the preface of sudo, add the user to the Docker group. Then run Docker with the `hello-world` test. - -1. Create Docker group: - ```bash - sudo groupadd docker - ``` - >**NOTE:** If the group already exists, `groupadd` outputs a message: **groupadd: group `docker` already exists**. This is OK. - -2. Add User to group: - ```bash - sudo usermod -aG docker $USER - ``` - -3. Restart your computer for the changes to take effect. - -4. To verify the Docker installation, run `hello-world`: - - ```bash - docker run hello-world - ``` - A **Hello from Docker!** greeting indicates successful installation. - - ```bash - Unable to find image 'hello-world:latest' locally - latest: Pulling from library/hello-world - 2db29710123e: Pull complete - Digest: sha256:10d7d58d5ebd2a652f4d93fdd86da8f265f5318c6a73cc5b6a9798ff6d2b2e67 - Status: Downloaded newer image for hello-world:latest - - Hello from Docker! - This message shows that your installation appears to be working correctly. - ... - ``` - -### Install Docker Compose -Install Docker Compose from the official repository as documented on the [Docker Compose](https://docs.docker.com/compose/install/linux/#install-using-the-repository) site. - -### Download EdgeX Compose - 1. Clone the EdgeX compose repository: - - ```bash - git clone https://github.com/edgexfoundry/edgex-compose.git - ``` - 1. Navigate to the `edgex-compose` directory: - - ```bash - cd edgex-compose - ``` - - 1. Checkout the Levski release: - - ```bash - git checkout levski - ``` - - Note: The `levski` branch is the latest stable branch at the time of this update. - - 1. Navigate back to your home directory: - - ```bash - cd ~ - ``` - -### Install Tools -Install the build, media streaming, and parsing tools: - -```bash -sudo apt install build-essential ffmpeg jq curl -``` - -### Tool Descriptions -The table below lists command line tools this guide uses to help with EdgeX configuration and device setup. - -| Tool | Description | Note | -| ----------- | ----------- |----------- | -| **curl** | Allows the user to connect to services such as EdgeX. |Use curl to get transfer information either to or from this service. In the tutorial, use `curl` to communicate with the EdgeX API. The call will return a JSON object.| -| **jq** |Parses the JSON object returned from the `curl` requests. |The `jq` command includes parameters that are used to parse and format data. In this tutorial, the `jq` command has been configured to return and format appropriate data for each `curl` command that is piped into it. | -| **base64** | Converts data into the Base64 format.| | - ->Table 1: Command Line Tools - -## Get the Source Code - -1. Clone the device-onvif-camera repository: - - ```bash - git clone https://github.com/edgexfoundry/device-onvif-camera.git - ``` - -2. Navigate into the directory; - - ```bash - cd device-onvif-camera - ``` - -## Configuration - -### Configure Devices - -
-Manually Configure the Pre-Defined Devices - -Configuring pre-defined devices will allow the service to automatically provision them into core-metadata. Create a list of devices with the appropriate information as outlined below. - -1. Navigate to the `device-onvif-camera` directory: - - ```bash - cd device-onvif-camera - ``` - -2. Make a copy of the `camera.yaml.example`: - - ```bash - cp ./cmd/res/devices/camera.yaml.example ./cmd/res/devices/camera.yaml - ``` - -3. Open the `cmd/res/devices/camera.yaml` file using your preferred text editor and update the `Address` and `Port` fields to match the IP address of the Camera and port used for ONVIF services: - - ```yaml - deviceList: - - name: Camera001 # Modify as desired - profileName: onvif-camera # Default profile - description: onvif conformant camera # Modify as desired - protocols: - Onvif: - Address: 191.168.86.34 # Set to your camera IP address - Port: '2020' # Set to the port your camera uses - SecretName: credentials001 - CustomMetadata: - CommonName: Outdoor camera - ``` -

- Sample: Snippet from camera.yaml -

- -3. Optionally, modify the `Name` and `Description` fields to more easily identify the camera. The `Name` is the camera name used when using ONVIF Device Service Rest APIs. The `Description` is simply a more detailed explanation of the camera. - -4. You can also optionally configure the `CustomMetadata` with custom fields and values to store any extra information you would like. - -5. To add more pre-defined devices, copy the above configuration and edit to match your extra devices. - -
- -
-Configure Auto Discovery for ONVIF Devices - -ONVIF devices support WS-Discovery, which is a mechanism that supports probing a network to find ONVIF capable devices. Refer to [Auto Discovery](../auto-discovery.md) for detailed information on the auto-discovery mechanism. - -> The following one-line command can be used to discover subnets of your current machine: -> ```shell -> ip -4 -o route list scope link | sed -En "s/ dev ($(find /sys/class/net -mindepth 1 -maxdepth 2 -not -lname '*devices/virtual*' -execdir grep -q 'up' "{}/operstate" \; -printf '%f\n' | paste -sd\| -)).+//p" | grep -v "169.254.0.0/16" | sort -u | paste -sd, - -> ``` -> Example Output: `192.168.1.0/24` - -#### 1. Discovery Configuration - -> _See the [Auto Discovery Configuration Guide](../auto-discovery.md#Configuration-Guide) for full details_ -> -
-via Configuration File - -1. Navigate to the `device-onvif-camera` directory: - - ```bash - cd device-onvif-camera - ``` - -2. Define the following configurations in [cmd/res/configuration.yaml](../../cmd/res/configuration.yaml) for auto-discovery mechanism: - ```yaml - Device: - # The location of Provision Watcher yaml files to import when using auto-discovery - ProvisionWatchersDir: ./res/provisionwatchers - Discovery: - Enabled: true # enable device discovery - Interval: 1h # set to desired interval - - # Custom configs - AppCustom: - # The Secret Name of the default credentials to use for devices which do not have MAC Addresses defined, or do not - # have credentials defined in the CredentialsMap. The magic value of 'NoAuth' here will cause the devices to default - # to not using any authentication. If authentication is required, it would then need to be manually configured. - DefaultSecretName: credentials001 - # Select which discovery mechanism(s) to use - DiscoveryMode: both # netscan, multicast, or both - # The target ethernet interface for multicast discovering - DiscoveryEthernetInterface: eth0 - # List of IPv4 subnets to perform netscan discovery on, in CIDR format (X.X.X.X/Y) - # separated by commas ex: "192.168.1.0/24,10.0.0.0/24" - DiscoverySubnets: "192.168.1.0/24" # Fill in with your actual subnet(s) - ``` -
- -
-via Docker environment variables - -1. Navigate to the EdgeX `compose-builder` directory: - - ```bash - cd edgex-compose/compose-builder/ - ``` - -2. Add the following environment variables in `add-device-onvif-camera.yaml`: - - ```yaml - device-onvif-camera: - environment: - DEVICE_DISCOVERY_ENABLED: "true" # enable device discovery - DEVICE_DISCOVERY_INTERVAL: "1h" # set to desired interval - - # The target ethernet interface for multicast discovering - APPCUSTOM_DISCOVERYETHERNETINTERFACE: "eth0" - # The Secret Name of the default credentials to use for devices - APPCUSTOM_DEFAULTSECRETNAME: "credentials001" - # Select which discovery mechanism(s) to use - APPCUSTOM_DISCOVERYMODE: "both" # netscan, multicast, or both - # List of IPv4 subnets to perform netscan discovery on, in CIDR format (X.X.X.X/Y) - # separated by commas ex: "192.168.1.0/24,10.0.0.0/24" - APPCUSTOM_DISCOVERYSUBNETS: "192.168.1.0/24" # Fill in with your actual subnet(s) - ``` -
- -
- -
- -### Configure the Device Service - -1. Navigate to the `device-onvif-camera` directory: - - ```bash - cd device-onvif-camera - ``` - -2. Open the [configuration.yaml](../../cmd/res/configuration.yaml) file using your preferred text editor. - -3. Make sure `SecretName` is set to match `SecretName` in `camera.yaml`. In the sample below, it is `"credentials001"`. If you have multiple cameras, make sure the secret names match. - -4. Under `SecretName`, set `username` and `password` to your camera credentials. If you have multiple cameras copy the `Writable.InsecureSecrets` section and edit to include the new information. - - ```yaml - Writable: - InsecureSecrets: - credentials001: - SecretName: credentials001 - SecretData: - username: - password: - mode: usernametoken # assign "digest" | "usernametoken" | "both" | "none" - credentials002: - SecretName: credentials002 - SecretData: - username: - password: - mode: usernametoken # assign "digest" | "usernametoken" | "both" | "none" - ``` - -

- Sample: Snippet from configuration.yaml -

- - -### Additional Configuration Options -For optional configurations, see [here.](#additional-configuration) - -## Build the Docker Image - -1. In the `device-onvif-camera` directory, run make docker: - - ```bash - make docker - ``` -
- [Optional] Build with NATS Messaging - - Currently, the NATS Messaging capability (NATS MessageBus) is opt-in at build time. This means that the published Docker image and Snaps do not include the NATS messaging capability. To build the docker image using NATS, run make docker-nats: - - ```bash - make docker-nats - ``` - - See [Compose Builder](https://github.com/edgexfoundry/edgex-compose/tree/main/compose-builder#gen) `nat-bus` option to generate compose file for NATS and local dev images. - -
- -2. Verify the ONVIF Device Service Docker image was successfully created: - - ```bash - docker images - ``` - ```docker - REPOSITORY TAG IMAGE ID CREATED SIZE - edgexfoundry-holding/device-onvif-camera 0.0.0-dev 75684e673feb 6 weeks ago 21.3MB - ``` - -3. Navigate to the EdgeX `compose-builder` directory: - - ```bash - cd edgex-compose/compose-builder/ - ``` - -4. Update `.env` file to add the registry and image version variable for device-onvif-camera: - - Add the following registry and version information: - ```env - DEVICE_ONVIFCAM_VERSION=0.0.0-dev - ``` - -5. Update the `add-device-onvif-camera.yml` to point to the local image: - - ```yml - services: - device-onvif-camera: - image: edgexfoundry/device-onvif-camera:${DEVICE_ONVIFCAM_VERSION} - ``` - -## Deploy EdgeX and ONVIF Device Camera Microservice - -
-Run the Service using Docker - - 1. Navigate to the EdgeX `compose-builder` directory: - - ```bash - cd edgex-compose/compose-builder/ - ``` - - 1. Run EdgeX with the microservice in non-secure mode: - - ```bash - make run no-secty ds-onvif-camera - ``` - - 1. Run EdgeX with the microservice in secure mode: - - ```bash - make run ds-onvif-camera - ``` -
- -
-Run the Service natively - -
- ->**NOTE:** Go version 1.20+ is required to run natively. See [here](https://go.dev/doc/install) for more information. - -
- - 1. Navigate to the EdgeX `compose-builder` directory: - - ```bash - cd edgex-compose/compose-builder/ - ``` - - 1. Run EdgeX: - - ```bash - make run no-secty - ``` - - 1. Navigate out of the `edgex-compose` directory to the `device-onvif-camera` directory: - - ```bash - cd device-onvif-camera - ``` - 1. Run the service - ```bash - make run - ``` - -
- [Optional] Run with NATS - - ```bash - make run-nats - ``` - -
- -
- -## Verify Service and Device Profiles - -### Using Command Line -1. Check the status of the container: - - ```bash - docker ps - ``` - - The status column will indicate if the container is running, and how long it has been up. - - Example Output: - - ```docker - CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES - 33f9c5ecb70e edgexfoundry/device-onvif-camera:0.0.0-dev "/device-onvif-camer…" 7 weeks ago Up 48 minutes 127.0.0.1:59985->59985/tcp edgex-device-onvif-camera - ``` - -2. Check whether the device service is added to EdgeX: - - ```bash - curl -s http://localhost:59881/api/v2/deviceservice/name/device-onvif-camera | jq . - ``` - Successful: - ```json - { - "apiVersion": "v2", - "statusCode": 200, - "service": { - "created": 1657227634593, - "modified": 1657291447649, - "id": "e1883aa7-f440-447f-ad4d-effa2aeb0ade", - "name": "device-onvif-camera", - "baseAddress": "http://edgex-device-onvif-camera:59984", - "adminState": "UNLOCKED" - } - } - ``` - Unsuccessful: - ```json - { - "apiVersion": "v2", - "message": "fail to query device service by name device-onvif-camer", - "statusCode": 404 - } - ``` - - -3. Check whether the device profile is added: - - ```bash - curl -s http://localhost:59881/api/v2/deviceprofile/name/onvif-camera | jq -r '"profileName: " + '.profile.name' + "\nstatusCode: " + (.statusCode|tostring)' - - ``` - Good response: - ```bash - profileName: onvif-camera - statusCode: 200 - ``` - Bad response: - ```bash - profileName: - statusCode: 404 - ``` - >**NOTE:** The `jq -r` option is used to reduce the size of the displayed response. The entire device profile with all resources can be seen by removing `-r '"profileName: " + '.profile.name' + "\nstatusCode: " + (.statusCode|tostring)', and replacing it with '.'` - -### Using EdgeX UI -1. Visit http://localhost:4000 to go to the dashboard for EdgeX Console GUI: - - ![EdgeXConsoleDashboard](../images/EdgeXDashboard.png) -

- Figure 1: EdgeX Console Dashboard -

- -2. To see **Device Services**, **Devices**, or **Device Profiles**, click on their respective tab: - - ![EdgeXConsoleDeviceServices](../images/EdgeXDeviceServices.png) -

- Figure 2: EdgeX Console Device Service List -

- - ![EdgeXConsoleDeviceList](../images/EdgeXDeviceList.png) -

- Figure 3: EdgeX Console Device List -

- - ![EdgeXConsoleDeviceProfileList](../images/EdgeXDeviceProfiles.png) -

- Figure 4: EdgeX Console Device Profile List -

-## Manage Devices -Follow these instructions to update devices. - -### Curl Commands - -#### Add Device - ->**NOTE:** The scripts used here are from the device-onvif-camera repository. - -
-Manually - ->**NOTE:** Only use to manually add new devices that were not configured in the [Manually Configure the Pre-Defined Devices](#configuration) step. - -1. Edit the information to appropriately match the camera. The fields `Address`, `MACAddress` and `Port` should match that of the camera: - - ```bash - curl -X POST -H 'Content-Type: application/json' \ - http://localhost:59881/api/v2/device \ - -d '[ - { - "apiVersion": "v2", - "device": { - "name":"Camera001", - "serviceName": "device-onvif-camera", - "profileName": "onvif-camera", - "description": "My test camera", - "adminState": "UNLOCKED", - "operatingState": "UP", - "protocols": { - "Onvif": { - "Address": "10.0.0.0", - "Port": "10000", - "MACAddress": "aa:bb:cc:11:22:33", - "FriendlyName":"Default Camera" - }, - "CustomMetadata": { - "Location":"Front door" - } - } - } - } - ]' - ``` - - Example Output: - ```bash - [{"apiVersion":"v2","statusCode":201,"id":"fb5fb7f2-768b-4298-a916-d4779523c6b5"}] - ``` -
- -
-Auto Discovery - -
- ->**NOTE:** If auto discovery is required and was not configured with the [Configure Auto Discovery for ONVIF Devices](#configure-devices) steps above, the following steps will enable auto discovery using the `netscan` method _after_ the service has been deployed. - -ONVIF devices support WS-Discovery, which is a mechanism that supports probing a network to find ONVIF capable devices. Refer to [Auto Discovery](../auto-discovery.md) for detailed information on the auto-discovery mechanism. - ->**NOTE:** Ensure that the cameras are all installed and configured before attempting discovery. - -1. Navigate to the `device-onvif-camera` directory. - -2. Set the DiscoverySubnets by running `bin/configure-subnets.sh`. - -Device discovery is triggered by the device service. Once the device service starts, it will discover the Onvif camera(s) at the specified interval. ->**NOTE:** You can also manually trigger discovery using this command: `curl -X POST http://:59984/api/v2/discovery` - -
- -
- -1. Map credentials using the `map-credentials.sh` script. - a. Navigate to the `device-onvif-camera` directory - b. Run `bin/map-credentials.sh` - c. Select `(Create New)` - ![](../images/create_new.png) - d. Enter the Secret Name to associate with these credentials - ![](../images/secret_name.png) - e. Enter the username - ![](../images/set_username.png) - f. Enter the password - ![](../images/set_password.png) - g. Choose the Authentication Mode - ![](../images/auth_mode.png) - h. Assign one or more MAC Addresses to the credential group - ![](../images/assign_mac.png) - - >**NOTE:** The MAC address field can be left blank if the SecretName from the "Enter Secret Name ..." step above, is set to the DefaultSecretName (credentials001) from the [cmd/res/configuration.yaml](../../cmd/res/configuration.yaml). - - i. Learn more about updating credentials [here](../utility-scripts.md) - - Successful: - - ```bash - Dependencies Check: Success - Consul Check: ... - curl -X GET http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera?keys=true - Response [200] Success - curl -X GET http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap?keys=true - Response [200] - Secret Name: a - curl -X GET http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap/a?raw=true - Response [404] - Failed! curl returned a status code of '404' - Setting InsecureSecret: a/SecretName - curl --data "" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets/a/SecretName - Response [200] true - - - Setting InsecureSecret: a/SecretData/username - curl --data "" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets/a/SecretData/username - Response [200] true - - - Setting InsecureSecret: a/SecretData/password - curl --data "" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets/a/SecretData/password - Response [200] true - - - Setting InsecureSecret: a/SecretData/mode - curl --data "usernmetoken" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets/a/SecretData/mode - Response [200] true - - - Setting Credentials Map: a = '' - curl -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap/a - Response [200] true - - - - Secret Name: a - curl -X GET http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap/a?raw=true - Response [200] - Setting Credentials Map: a = '11:22:33:44:55:66' - curl --data "11:22:33:44:55:66" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap/a - Response [200] true - ``` - - - -2. Verify device(s) have been successfully added to core-metadata. - - ```bash - curl -s http://localhost:59881/api/v2/device/all | jq -r '"deviceName: " + '.devices[].name'' - ``` - - Example Output: - ```bash - deviceName: Camera001 - deviceName: device-onvif-camera - ``` - >**NOTE:** The device with name `device-onvif-camera` is a stand-in device and can be ignored. - >**NOTE:** The `jq -r` option is used to reduce the size of the displayed response. The entire device with all information can be seen by removing `-r '"deviceName: " + '.devices[].name'', and replacing it with '.'` - -#### Delete Device - - ```bash - curl -X 'DELETE' \ - 'http://localhost:59881/api/v2/device/name/' \ - -H 'accept: application/json' - ``` -## Execute GetStreamURI Command through EdgeX - -1. Get the profile token by executing the `GetProfiles` command: - - >**NOTE:** Make sure to replace `Camera001` in all the commands below, with the deviceName returned in the ["Verify device(s) have been successfully added to core-metadata"](#verify-device) step above. - - ```bash - curl -s http://0.0.0.0:59882/api/v2/device/name/Camera001/Profiles | jq -r '"profileToken: " + '.event.readings[].objectValue.Profiles[].Token'' - ``` - Example Output: - - ```bash - profileToken: profile_1 - profileToken: profile_2 - ``` - -2. To request an RTSP URI that can be used to initiate a live media stream from the ONVIF device, execute the following [`GetStreamURI`](https://www.onvif.org/ver10/media/wsdl/media.wsdl#op.GetStreamUri) command with the profileToken found in [step 1](#step1): - In this example, `profile_1` is the ProfileToken: - - ```bash - curl -s "http://0.0.0.0:59882/api/v2/device/name/Camera001/StreamUri?jsonObject=$(base64 -w 0 <<< '{ - "StreamSetup" : { - "Stream" : "RTP-Unicast", - "Transport" : { - "Protocol" : "RTSP" - } - }, - "ProfileToken": "profile_1" - }')" | jq -r '"streamURI: " + '.event.readings[].objectValue.MediaUri.Uri'' - ``` - - Example Output: - - ```bash - streamURI: rtsp://192.168.86.34:554/stream1 - ``` - -3. Stream the RTSP stream. - - ffplay can be used to stream. The command follows this format: - - `ffplay -rtsp_transport tcp "rtsp://:@:/"`. - - Using the `streamURI` returned from the previous step, run ffplay: - - ```bash - ffplay -rtsp_transport tcp "rtsp://admin:Password123@192.168.86.34:554/stream1" - ``` - - >**NOTE:** While the `streamURI` returned did not contain the username and password, those credentials are required in order to correctly authenticate the request and play the stream. Therefore, it is included in both the VLC and ffplay streaming examples. - >**NOTE:** If the password uses special characters, you must use percent-encoding. - -5. To shut down ffplay, use the ctrl-c command. - -## Shutting Down -To stop all EdgeX services (containers), execute the `make down` command. This will stop all services but not the images and volumes, which still exist. - -1. Navigate to the `edgex-compose/compose-builder` directory. -1. Run this command - ```bash - make down - ``` -1. To shut down and delete all volumes, run this command - ```bash - make clean - ``` - >**NOTE:** Since this command deletes all volumes, you will need to rerun the [Add Device](#add-device) steps to re-enable your device(s). - -## Additional Configuration - -Here is some information on how to specially configure parts of the service beyond the provided defaults. - -### Configure the Device Profiles - -The device profile contains general information about the camera and includes all the device resources and commands that the device resources can use to manage the cameras. The default [profile](../../cmd/res/profiles/camera.yaml) contains all possible resources a camera could implement. Enable and disable supported resources in this file, or create an entirely new profile. It is important to set up the device profile to match the capabilities of the camera. Information on the resources supported by specific cameras can be found [here](../ONVIF-protocol.md#tested-onvif-cameras). Learn more about device profiles in EdgeX [here.](https://docs.edgexfoundry.org/1.2/microservices/device/profile/Ch-DeviceProfile/) - -```yaml -name: "onvif-camera" # general information about the profile -manufacturer: "Generic" -model: "Generic ONVIF" -labels: - - "onvif" -description: "EdgeX device profile for ONVIF-compliant IP camera." - -deviceResources: - # Network Configuration - - name: "Hostname" # an example of a resource with get/set values - isHidden: false - description: "Camera Hostname" - attributes: - service: "Device" - getFunction: "GetHostname" - setFunction: "SetHostname" - properties: - valueType: "Object" - readWrite: "RW" -``` -

- Sample: Snippet from camera.yaml -

- - -### Configure the Provision Watchers - -The provision watcher sets up parameters for EdgeX to automatically add devices to core-metadata. They can be configured to look for certain features, as well as block features. The default provision watcher is sufficient unless you plan on having multiple different cameras with different profiles and resources. Learn more about provision watchers [here](https://docs.edgexfoundry.org/2.2/microservices/core/metadata/Ch-Metadata/#provision-watcher). - -```json -{ - "name":"Generic-Onvif-Provision-Watcher", - "identifiers":{ // Use the identifiers to filter through specific features of the protocol - "Address": ".", - "Manufacturer": "Intel", // example of a feature to allow through - "Model": "DFI6256TE" - }, - "blockingIdentifiers":{ - }, - "serviceName": "device-onvif-camera", - "profileName": "onvif-camera", - "adminState":"UNLOCKED" -} -``` -

- Sample: Snippet from generic.provision.watcher.yaml -

- -## Summary and Next Steps -This guide demonstrated how to: - -- deploy EdgeX with the ONVIF Device Service -- use the EdgeX REST APIs and the ONVIF Device Service to acquire the camera's RTSP stream - -### Next Steps - -[Explore how to further use this device service](../general-usage.md) - -Refer to the main [README](../../README.md) to find links to the rest of the documents. - -## References - -- ONVIF Website: http://www.onvif.org -- EdgeX Foundry Project Wiki: https://wiki.edgexfoundry.org/ -- EdgeX Source Code: https://github.com/edgexfoundry -- Edgex Developer Guide: https://docs.edgexfoundry.org/2.1/ -- Docker Repos - - Docker https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository - - Docker Compose https://docs.docker.com/compose/install/#install-compose - -# License - -[Apache-2.0](https://github.com/edgexfoundry-holding/device-onvif-camera/blob/main/LICENSE) diff --git a/doc/guides/SimpleStartupGuide.md b/doc/guides/SimpleStartupGuide.md deleted file mode 100644 index 08c5fe48..00000000 --- a/doc/guides/SimpleStartupGuide.md +++ /dev/null @@ -1,549 +0,0 @@ -# ONVIF Device Service Simple Start Up Guide - -## Contents - -[System Requirements](#system-requirements) -[Dependencies](#dependencies) -[Deploy the Service](#deploy-edgex-and-onvif-device-camera-microservice) -[Verify the Service](#verify-service-and-device-profiles) -[Manage Devices](#manage-devices) -[Execute Example Command](#execute-getstreamuri-command-through-edgex) -[Shutting Down](#shutting-down) - -## System Requirements - -- Intel™ Core® processor -- Ubuntu 20.04.4 LTS -- ONVIF-compliant Camera - ->**NOTE:** The instructions in this guide were developed and tested using Ubuntu 20.04 LTS and the Tapo C200 Pan/Tilt Wi-Fi Camera, referred to throughout this document as the **Tapo C200 Camera**. However, the software may work with other Linux distributions and ONVIF-compliant cameras. Refer to our [list of tested cameras for more information](../ONVIF-protocol.md#tested-onvif-cameras) - -**Time to Complete** - -10-20 minutes - -**Other Requirements** - -You must have administrator (sudo) privileges to execute the user guide commands. - -## How It Works -For an explanation of the architecture, see the [User Guide](../../README.md#how-it-works). - -## Dependencies -The software has dependencies, including Git, Docker, Docker Compose, and assorted tools. Follow the instructions below to install any dependency that is not already installed. - -### Install Git -Install Git from the official repository as documented on the [Git SCM](https://git-scm.com/download/linux) site. - -1. Update installation repositories: - ```bash - sudo apt update - ``` - -2. Add the Git repository: - ```bash - sudo add-apt-repository ppa:git-core/ppa -y - ``` - -3. Install Git: - ```bash - sudo apt install git - ``` - -### Install Docker -Install Docker from the official repository as documented on the [Docker](https://docs.docker.com/engine/install/ubuntu/) site. - -### Verify Docker -To enable running Docker commands without the preface of sudo, add the user to the Docker group. Then run Docker with the `hello-world` test. - -1. Create Docker group: - ```bash - sudo groupadd docker - ``` - >**NOTE:** If the group already exists, `groupadd` outputs a message: **groupadd: group `docker` already exists**. This is OK. - -2. Add User to group: - ```bash - sudo usermod -aG docker $USER - ``` - -3. Restart your computer for the changes to take effect. - -4. To verify the Docker installation, run `hello-world`: - - ```bash - docker run hello-world - ``` - A **Hello from Docker!** greeting indicates successful installation. - - ```bash - Unable to find image 'hello-world:latest' locally - latest: Pulling from library/hello-world - 2db29710123e: Pull complete - Digest: sha256:10d7d58d5ebd2a652f4d93fdd86da8f265f5318c6a73cc5b6a9798ff6d2b2e67 - Status: Downloaded newer image for hello-world:latest - - Hello from Docker! - This message shows that your installation appears to be working correctly. - ... - ``` - -### Install Docker Compose -Install Docker Compose from the official repository as documented on the [Docker Compose](https://docs.docker.com/compose/install/linux/#install-using-the-repository) site. - -### Download EdgeX Compose - 1. Clone the EdgeX compose repository: - - ```bash - git clone https://github.com/edgexfoundry/edgex-compose.git - ``` - 1. Navigate to the `edgex-compose` directory: - - ```bash - cd edgex-compose - ``` - - 1. Checkout the Levski release: - - ```bash - git checkout levski - ``` - - Note: The `levski` branch is the latest stable branch at the time of this update. - - 1. Navigate back to your home directory: - - ```bash - cd ~ - ``` - -### Install Tools -Install the build, media streaming, and parsing tools: - - ```bash - sudo apt install build-essential ffmpeg jq curl - ``` - -### Tool Descriptions -The table below lists command line tools this guide uses to help with EdgeX configuration and device setup. - -| Tool | Description | Note | -| ----------- | ----------- |----------- | -| **curl** | Allows the user to connect to services such as EdgeX. |Use curl to get transfer information either to or from this service. In the tutorial, use `curl` to communicate with the EdgeX API. The call will return a JSON object.| -| **jq** |Parses the JSON object returned from the `curl` requests. |The `jq` command includes parameters that are used to parse and format data. In this tutorial, the `jq` command has been configured to return and format appropriate data for each `curl` command that is piped into it. | -| **base64** | Converts data into the Base64 format.| | - ->Table 1: Command Line Tools - -## Get the Source Code - -Clone the device-onvif-camera repository: - - ```bash - git clone https://github.com/edgexfoundry/device-onvif-camera.git - ``` - -## Deploy EdgeX and ONVIF Device Camera Microservice - -### Run the Service - -
-Run the Service using Docker - - 1. Navigate to the EdgeX `compose-builder` directory: - - ```bash - cd edgex-compose/compose-builder/ - ``` - - 2. Run EdgeX with the microservice in non-secure mode: - - ```bash - make run no-secty ds-onvif-camera - ``` - - 3. Run EdgeX with the microservice in secure mode: - - ```bash - make run ds-onvif-camera - ``` -
- -
-Run the Service natively - -
- ->**NOTE:** Go version 1.20+ is required to run natively. - -
- - 1. Navigate to the EdgeX `compose-builder` directory: - - ```bash - cd edgex-compose/compose-builder/ - ``` - - 1. Run EdgeX: - - ```bash - make run no-secty - ``` - - 1. Navigate out of the `edgex-compose` directory to the `device-onvif-camera` directory: - - ```bash - cd device-onvif-camera - ``` - - 1. Run the service: - - ```bash - make run - ``` - -
- -## Verify Service and Device Profiles - -1. Check the status of the container: - - ```bash - docker ps - ``` - - The status column will indicate if the container is running and how long it has been up. - - Example Output: - - ```docker - CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES - 33f9c5ecb70e edgexfoundry/device-onvif-camera:0.0.0-dev "/device-onvif-camer…" 7 weeks ago Up 48 minutes 127.0.0.1:59985->59985/tcp edgex-device-onvif-camera - ``` - -2. Check that the device service is added to EdgeX: - - ```bash - curl -s http://localhost:59881/api/v2/deviceservice/name/device-onvif-camera | jq . - ``` - Successful: - ```json - { - "apiVersion": "v2", - "statusCode": 200, - "service": { - "created": 1657227634593, - "modified": 1657291447649, - "id": "e1883aa7-f440-447f-ad4d-effa2aeb0ade", - "name": "device-onvif-camera", - "baseAddress": "http://edgex-device-onvif-camera:59984", - "adminState": "UNLOCKED" - } - } - ``` - Unsuccessful: - ```json - { - "apiVersion": "v2", - "message": "fail to query device service by name device-onvif-camer", - "statusCode": 404 - } - ``` - - -3. Check that the device profile is added: - - ```bash - curl -s http://localhost:59881/api/v2/deviceprofile/name/onvif-camera | jq -r '"profileName: " + '.profile.name' + "\nstatusCode: " + (.statusCode|tostring)' - - ``` - Successful: - ```bash - profileName: onvif-camera - statusCode: 200 - ``` - Unsuccessful: - ```bash - profileName: - statusCode: 404 - ``` - >**NOTE:** The `jq -r` option is used to reduce the size of the displayed response. The entire device profile with all resources can be seen by removing `-r '"profileName: " + '.profile.name' + "\nstatusCode: " + (.statusCode|tostring)', and replacing it with '.'` - -## Manage Devices -Follow these instructions to update devices. - -### Curl Commands - -#### Add Device - ->**NOTE:** The scripts used here are from the device-onvif-camera repository. - -
-Manually - -1. Edit the information to appropriately match the camera. The fields `Address`, `MACAddress` and `Port` should match that of the camera: - - ```bash - curl -X POST -H 'Content-Type: application/json' \ - http://localhost:59881/api/v2/device \ - -d '[ - { - "apiVersion": "v2", - "device": { - "name":"Camera001", - "serviceName": "device-onvif-camera", - "profileName": "onvif-camera", - "description": "My test camera", - "adminState": "UNLOCKED", - "operatingState": "UP", - "protocols": { - "Onvif": { - "Address": "10.0.0.0", - "Port": "10000", - "MACAddress": "aa:bb:cc:11:22:33", - "FriendlyName":"Default Camera" - }, - "CustomMetadata": { - "Location":"Front door" - } - } - } - } - ]' - ``` - - Example Output: - ```bash - [{"apiVersion":"v2","statusCode":201,"id":"fb5fb7f2-768b-4298-a916-d4779523c6b5"}] - ``` -
- -
- -Auto Discovery - -
- -ONVIF devices support WS-Discovery, which is a mechanism that supports probing a network to find ONVIF capable devices. Refer to [How does WS-Discovery work?](https://github.com/EdgeX-Camera-Management/device-onvif-camera/blob/main/doc/ws-discovery.md) and [Auto Discovery](https://github.com/EdgeX-Camera-Management/device-onvif-camera/blob/main/doc/auto-discovery.md) for more information auto-discovery mechanism. The following steps will enable auto discovery using the `netscan` method _after_ the service has been deployed. - -> **NOTE:** Ensure that the cameras are all installed and configured before attempting discovery. - -1. Navigate to the `device-onvif-camera` directory. - -2. Set the DiscoverySubnets by running `bin/configure-subnets.sh`. - -Device discovery is triggered by the device service. Once the device service starts, it will discover the Onvif camera(s) at the specified interval. -> **Note:** You can also manually trigger discovery using this command: `curl -X POST http://:59984/api/v2/discovery` - -
- -
- -1. Map credentials using the `map-credentials.sh` script. - a. Navigate to the `device-onvif-camera` directory - b. Run `bin/map-credentials.sh` - c. Select `(Create New)` - ![](../images/create_new.png) - d. Enter the Secret Name to associate with these credentials - ![](../images/secret_name.png) - e. Enter the username - ![](../images/set_username.png) - f. Enter the password - ![](../images/set_password.png) - g. Choose the Authentication Mode - ![](../images/auth_mode.png) - h. Assign one or more MAC Addresses to the credential group - ![](../images/assign_mac.png) - - >**NOTE:** The MAC address field can be left blank if the SecretName from the "Enter Secret Name ..." step above, is set to the DefaultSecretName (credentials001) from the [cmd/res/configuration.yaml](../../cmd/res/configuration.yaml). - - i. Learn more about updating credentials [here](../utility-scripts.md) - - Successful: - - ```bash - Dependencies Check: Success - Consul Check: ... - curl -X GET http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera?keys=true - Response [200] Success - curl -X GET http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap?keys=true - Response [200] - Secret Name: a - curl -X GET http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap/a?raw=true - Response [404] - Failed! curl returned a status code of '404' - Setting InsecureSecret: a/SecretName - curl --data "" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets/a/SecretName - Response [200] true - - - Setting InsecureSecret: a/SecretData/username - curl --data "" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets/a/SecretData/username - Response [200] true - - - Setting InsecureSecret: a/SecretData/password - curl --data "" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets/a/SecretData/password - Response [200] true - - - Setting InsecureSecret: a/SecretData/mode - curl --data "usernmetoken" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets/a/SecretData/mode - Response [200] true - - - Setting Credentials Map: a = '' - curl -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap/a - Response [200] true - - - - Secret Name: a - curl -X GET http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap/a?raw=true - Response [200] - Setting Credentials Map: a = '11:22:33:44:55:66' - curl --data "11:22:33:44:55:66" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap/a - Response [200] true - ``` - - -2. Verify device(s) have been successfully added to core-metadata: - - ```bash - curl -s http://localhost:59881/api/v2/device/all | jq -r '"deviceName: " + '.devices[].name'' - ``` - - Example Output: - ```bash - deviceName: Camera001 - deviceName: device-onvif-camera - ``` - >**NOTE:** The device with name `device-onvif-camera` is a stand-in device and can be ignored. - >**NOTE:** The `jq -r` option is used in the curl command to reduce the size of the displayed response. The entire device with all information can be seen by removing `-r '"deviceName: " + '.devices[].name'', and replacing it with '.'` - -#### Delete Device - - ```bash - curl -X 'DELETE' \ - 'http://localhost:59881/api/v2/device/name/' \ - -H 'accept: application/json' - ``` - -### Use EdgeX Console to Verify Device Services, Devices, and Device Profiles -1. Visit http://localhost:4000 to go to the dashboard for EdgeX Console GUI: - - ![EdgeXConsoleDashboard](../images/EdgeXDashboard.png) -

- Figure 5: EdgeX Console Dashboard -

- -2. To get device status information, click on the tabs **Device Services**, **Devices**, or **Device Profiles**: - - ![EdgeXConsoleDeviceServices](../images/EdgeXDeviceServices.png) -

- Figure 6: EdgeX Console Device Service List -

- - ![EdgeXConsoleDeviceList](../images/EdgeXDeviceList.png) -

- Figure 7: EdgeX Console Device List -

- - ![EdgeXConsoleDeviceProfileList](../images/EdgeXDeviceProfiles.png) -

- Figure 8: EdgeX Console Device Profile List -

- -## Execute GetStreamURI Command through EdgeX - -1. Get the profile token by executing the `GetProfiles` command: - - >**NOTE:** Make sure to replace `Camera001` in all the commands below, with the deviceName returned in the ["Verify device(s) have been successfully added to core-metadata"](#verify-device) step above. - - ```bash - curl -s http://0.0.0.0:59882/api/v2/device/name/Camera001/Profiles | jq -r '"profileToken: " + '.event.readings[].objectValue.Profiles[].Token'' - ``` - Example Output: - - ```bash - profileToken: profile_1 - profileToken: profile_2 - ``` - -2. To get the RTSP URI from the ONVIF device, execute the `GetStreamURI` command, using a profileToken found in [step 1](#step1): - In this example, `profile_1` is the profileToken: - - ```bash - curl -s "http://0.0.0.0:59882/api/v2/device/name/Camera001/StreamUri?jsonObject=$(base64 -w 0 <<< '{ - "StreamSetup" : { - "Stream" : "RTP-Unicast", - "Transport" : { - "Protocol" : "RTSP" - } - }, - "ProfileToken": "profile_1" - }')" | jq -r '"streamURI: " + '.event.readings[].objectValue.MediaUri.Uri'' - ``` - - Example Output: - - ```bash - streamURI: rtsp://192.168.86.34:554/stream1 - ``` - -3. Stream the RTSP stream. - - ffplay can be used to stream. The command follows this format: - - `ffplay -rtsp_transport tcp "rtsp://:@:/"`. - - Using the `streamURI` returned from the previous step, run ffplay: - - ```bash - ffplay -rtsp_transport tcp "rtsp://admin:Password123@192.168.86.34:554/stream1" - ``` - - >**NOTE:** While the `streamURI` returned did not contain the username and password, those credentials are required in order to correctly authenticate the request and play the stream. Therefore, it is included in both the VLC and ffplay streaming examples. - >**NOTE:** If the password uses special characters, you must use percent-encoding. - -4. To shut down ffplay, use the ctrl-c command. - -## Shutting Down -To stop all EdgeX services (containers), execute the `make down` command: - -1. Navigate to the `edgex-compose/compose-builder` directory. -1. To shut down, run this command - ```bash - make down - ``` -1. To shut down and delete all volumes, run this command - ```bash - make clean - ``` - >**NOTE:** Since this command deletes all volumes, you will need to rerun the [Add Device](#add-device) steps to re-enable your device(s). - -## Summary and Next Steps -This guide demonstrated how to: - -- deploy EdgeX with the ONVIF Device Service -- use the EdgeX REST APIs and the ONVIF Device Service to acquire the camera's RTSP stream - -### Next Steps - -[Explore how to further use this device service](../general-usage.md) - -Refer to the main [README](../../README.md) to find links to the rest of the documents. - -## References - -- ONVIF Website: http://www.onvif.org -- EdgeX Foundry Project Wiki: https://wiki.edgexfoundry.org/ -- EdgeX Source Code: https://github.com/edgexfoundry -- Edgex Developer Guide: https://docs.edgexfoundry.org/2.1/ -- Docker Repos - - Docker https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository - - Docker Compose https://docs.docker.com/compose/install/#install-compose - -# License - -[Apache-2.0](https://github.com/edgexfoundry-holding/device-onvif-camera/blob/main/LICENSE) diff --git a/doc/images/EdgeXDashboard.png b/doc/images/EdgeXDashboard.png deleted file mode 100644 index 801bb0ac..00000000 Binary files a/doc/images/EdgeXDashboard.png and /dev/null differ diff --git a/doc/images/EdgeXDeviceList.png b/doc/images/EdgeXDeviceList.png deleted file mode 100644 index 9e1c0e90..00000000 Binary files a/doc/images/EdgeXDeviceList.png and /dev/null differ diff --git a/doc/images/EdgeXDeviceProfiles.png b/doc/images/EdgeXDeviceProfiles.png deleted file mode 100644 index 33ae4eb1..00000000 Binary files a/doc/images/EdgeXDeviceProfiles.png and /dev/null differ diff --git a/doc/images/EdgeXDeviceServices.png b/doc/images/EdgeXDeviceServices.png deleted file mode 100644 index dcb441db..00000000 Binary files a/doc/images/EdgeXDeviceServices.png and /dev/null differ diff --git a/doc/images/ONVIFDeviceServiceArch.png b/doc/images/ONVIFDeviceServiceArch.png deleted file mode 100644 index 90a10222..00000000 Binary files a/doc/images/ONVIFDeviceServiceArch.png and /dev/null differ diff --git a/doc/images/api-analytic-support-add-rule.png b/doc/images/api-analytic-support-add-rule.png deleted file mode 100644 index cabf8222..00000000 Binary files a/doc/images/api-analytic-support-add-rule.png and /dev/null differ diff --git a/doc/images/api-analytic-support-example.jpg b/doc/images/api-analytic-support-example.jpg deleted file mode 100644 index bed09295..00000000 Binary files a/doc/images/api-analytic-support-example.jpg and /dev/null differ diff --git a/doc/images/api-analytic-support-query-analytics-module-options-1.jpg b/doc/images/api-analytic-support-query-analytics-module-options-1.jpg deleted file mode 100644 index 7132c883..00000000 Binary files a/doc/images/api-analytic-support-query-analytics-module-options-1.jpg and /dev/null differ diff --git a/doc/images/api-analytic-support-query-analytics-module-options-2.jpg b/doc/images/api-analytic-support-query-analytics-module-options-2.jpg deleted file mode 100644 index e406a55d..00000000 Binary files a/doc/images/api-analytic-support-query-analytics-module-options-2.jpg and /dev/null differ diff --git a/doc/images/api-analytic-support-query-analytics-module.jpg b/doc/images/api-analytic-support-query-analytics-module.jpg deleted file mode 100644 index 0ecb9504..00000000 Binary files a/doc/images/api-analytic-support-query-analytics-module.jpg and /dev/null differ diff --git a/doc/images/api-analytic-support-query-rules.jpg b/doc/images/api-analytic-support-query-rules.jpg deleted file mode 100644 index ec538f91..00000000 Binary files a/doc/images/api-analytic-support-query-rules.jpg and /dev/null differ diff --git a/doc/images/assign_mac.png b/doc/images/assign_mac.png deleted file mode 100644 index 310fde81..00000000 Binary files a/doc/images/assign_mac.png and /dev/null differ diff --git a/doc/images/assign_mac_2.png b/doc/images/assign_mac_2.png deleted file mode 100644 index 82927eaf..00000000 Binary files a/doc/images/assign_mac_2.png and /dev/null differ diff --git a/doc/images/auth_mode.png b/doc/images/auth_mode.png deleted file mode 100644 index 929f33ef..00000000 Binary files a/doc/images/auth_mode.png and /dev/null differ diff --git a/doc/images/auth_mode_2.png b/doc/images/auth_mode_2.png deleted file mode 100644 index a5e62177..00000000 Binary files a/doc/images/auth_mode_2.png and /dev/null differ diff --git a/doc/images/auto-discovery-docker-overview.jpg b/doc/images/auto-discovery-docker-overview.jpg deleted file mode 100644 index c528f171..00000000 Binary files a/doc/images/auto-discovery-docker-overview.jpg and /dev/null differ diff --git a/doc/images/auto-discovery.jpg b/doc/images/auto-discovery.jpg deleted file mode 100644 index 37b30430..00000000 Binary files a/doc/images/auto-discovery.jpg and /dev/null differ diff --git a/doc/images/consul_acl.png b/doc/images/consul_acl.png deleted file mode 100644 index 5390b3dd..00000000 Binary files a/doc/images/consul_acl.png and /dev/null differ diff --git a/doc/images/consul_acl_sm.png b/doc/images/consul_acl_sm.png deleted file mode 100644 index ad11e9ea..00000000 Binary files a/doc/images/consul_acl_sm.png and /dev/null differ diff --git a/doc/images/create_new.png b/doc/images/create_new.png deleted file mode 100644 index 6cadecf8..00000000 Binary files a/doc/images/create_new.png and /dev/null differ diff --git a/doc/images/get-streamuri-input-parameter.jpg b/doc/images/get-streamuri-input-parameter.jpg deleted file mode 100644 index e5d1d63f..00000000 Binary files a/doc/images/get-streamuri-input-parameter.jpg and /dev/null differ diff --git a/doc/images/getting-started-with-docker-consul-keyvalue.jpg b/doc/images/getting-started-with-docker-consul-keyvalue.jpg deleted file mode 100644 index 6038126d..00000000 Binary files a/doc/images/getting-started-with-docker-consul-keyvalue.jpg and /dev/null differ diff --git a/doc/images/getting-started-with-docker-consul.jpg b/doc/images/getting-started-with-docker-consul.jpg deleted file mode 100644 index 4e2e1411..00000000 Binary files a/doc/images/getting-started-with-docker-consul.jpg and /dev/null differ diff --git a/doc/images/onvif-user-authentication-flow.jpg b/doc/images/onvif-user-authentication-flow.jpg deleted file mode 100644 index ebc2299f..00000000 Binary files a/doc/images/onvif-user-authentication-flow.jpg and /dev/null differ diff --git a/doc/images/onvif-user-authentication-usernametoken.jpg b/doc/images/onvif-user-authentication-usernametoken.jpg deleted file mode 100644 index 7fac47a3..00000000 Binary files a/doc/images/onvif-user-authentication-usernametoken.jpg and /dev/null differ diff --git a/doc/images/onvif-user-authentication.jpg b/doc/images/onvif-user-authentication.jpg deleted file mode 100644 index 5f1044c8..00000000 Binary files a/doc/images/onvif-user-authentication.jpg and /dev/null differ diff --git a/doc/images/password_change.png b/doc/images/password_change.png deleted file mode 100644 index c4d0d3bb..00000000 Binary files a/doc/images/password_change.png and /dev/null differ diff --git a/doc/images/pick_creds_2.png b/doc/images/pick_creds_2.png deleted file mode 100644 index d53c95e0..00000000 Binary files a/doc/images/pick_creds_2.png and /dev/null differ diff --git a/doc/images/secret_name.png b/doc/images/secret_name.png deleted file mode 100644 index b52d2d47..00000000 Binary files a/doc/images/secret_name.png and /dev/null differ diff --git a/doc/images/select_creds.png b/doc/images/select_creds.png deleted file mode 100644 index e7becc47..00000000 Binary files a/doc/images/select_creds.png and /dev/null differ diff --git a/doc/images/set-credentials-authmode.png b/doc/images/set-credentials-authmode.png deleted file mode 100644 index f0c73999..00000000 Binary files a/doc/images/set-credentials-authmode.png and /dev/null differ diff --git a/doc/images/set-credentials-password.png b/doc/images/set-credentials-password.png deleted file mode 100644 index 21603e89..00000000 Binary files a/doc/images/set-credentials-password.png and /dev/null differ diff --git a/doc/images/set-credentials-start.png b/doc/images/set-credentials-start.png deleted file mode 100644 index 24e413e4..00000000 Binary files a/doc/images/set-credentials-start.png and /dev/null differ diff --git a/doc/images/set-credentials-username.png b/doc/images/set-credentials-username.png deleted file mode 100644 index 2fce2cce..00000000 Binary files a/doc/images/set-credentials-username.png and /dev/null differ diff --git a/doc/images/set_password.png b/doc/images/set_password.png deleted file mode 100644 index 036152a5..00000000 Binary files a/doc/images/set_password.png and /dev/null differ diff --git a/doc/images/set_username.png b/doc/images/set_username.png deleted file mode 100644 index 27e6e6be..00000000 Binary files a/doc/images/set_username.png and /dev/null differ diff --git a/doc/images/username_change.png b/doc/images/username_change.png deleted file mode 100644 index f00edce7..00000000 Binary files a/doc/images/username_change.png and /dev/null differ diff --git a/doc/images/vlcstream1.png b/doc/images/vlcstream1.png deleted file mode 100644 index b5919701..00000000 Binary files a/doc/images/vlcstream1.png and /dev/null differ diff --git a/doc/images/vlcstream2.png b/doc/images/vlcstream2.png deleted file mode 100644 index d39b964e..00000000 Binary files a/doc/images/vlcstream2.png and /dev/null differ diff --git a/doc/images/vlcstream3.png b/doc/images/vlcstream3.png deleted file mode 100644 index f44a173b..00000000 Binary files a/doc/images/vlcstream3.png and /dev/null differ diff --git a/doc/onvif-footnotes.md b/doc/onvif-footnotes.md deleted file mode 100644 index 669d8865..00000000 --- a/doc/onvif-footnotes.md +++ /dev/null @@ -1,13 +0,0 @@ - -## Command Support -### Tapo C200 - User Management -Tapo returns `200 OK` for all User Management commands, but none of them actually -do anything. The only way to modify the users is through the Tapo app. - -### Tapo C200 - SetSystemDateAndTime -Tapo does not support setting the `DaylightSavings` field to `false`. Regardless of the setting, the camera will always use daylight savings time. - -### Bosch - GetSnapshot -You must use `Digest Auth` or `Both` as the Auth-Mode in order for this to work. - - diff --git a/doc/onvif-user-authentication.md b/doc/onvif-user-authentication.md deleted file mode 100644 index 86b5160d..00000000 --- a/doc/onvif-user-authentication.md +++ /dev/null @@ -1,129 +0,0 @@ -# Onvif User Authentication - -According to the Onvif user authentication flow, the device service shall: -* Implement WS-Usernametoken according to WS-security as covered by the core specification. -* Implement HTTP Digest as covered by the core specification. - -The spec can refer to https://www.onvif.org/specs/core/ONVIF-Core-Specification.pdf - -![onvif-user-authentication](images/onvif-user-authentication.jpg) - -## Usage -The user need to define the **AuthMode** and **SecretName**, and device service will send SOAP action with **WS-Usernametoken** or **Digest header**. - -For example: -```yaml -deviceList: - - name: test-camera - profileName: camera - description: HIKVISION camera - protocols: - Onvif: - Address: 192.168.12.123 - Port: '80' - AuthMode: usernametoken - SecretName: credentials001 -``` - -The AuthMode can be: -* digest -* usernametoken -* both -* none - -SecretName should contain: -* username -* password - -For development purpose, we can define the secrets in the configuration.yaml -```yaml -Writable: -... - InsecureSecrets: - Camera001: - SecretName: credentials001 - SecretData: - username: administrator - password: Password1 - Camera002: - SecretName: credentials002 - SecretData: - username: administrator - password: Password1 -``` - -## WS-Usernametoken -When the Onvif camera requires authentication through WS-UsernameToken, the device service must set user information with the appropriate privileges in WS-UsernameToken. - -This use case contains an example of setting that user information using GetHostname. - -WS-UsernameToken requires the following parameters: -* Username – The user name for a certified user. -* Password – The password for a certified user. According to the ONVIF specification, Password should not be set in plain text. Setting a password generates PasswordDigest, a digest that is calculated according to an algorithm defined in the specification for WS-UsernameToken: - Digest = B64ENCODE( SHA1( B64DECODE( Nonce ) + Date + Password ) ) -* Nonce – A random string generated by a client. -* Created – The UTC Time when the request is made. - -For example: -```shell -curl --request POST 'http://192.168.56.101:10000/onvif/device_service' \ - --header 'Content-Type: application/soap+xml' \ - -d ' - - - - - administrator - - +HKcvc+LCGClVwuros1sJuXepQY= - - - w490bn6rlib33d5rb8t6ulnqlmz9h43m - - - 2021-10-21T03:43:21.02075Z - - - - - - - - - ' -``` - -The spec can refer to https://www.onvif.org/wp-content/uploads/2016/12/ONVIF_WG-APG-Application_Programmers_Guide-1.pdf - -You can inspect the request by network tool like the Wireshark: -![onvif-user-authentication-usernametoken](images/onvif-user-authentication-usernametoken.jpg) - -## HTTP Digest -The Digest scheme is based on a simple challenge-response paradigm and the spec can refer to https://datatracker.ietf.org/doc/html/rfc2617#page-6 - -The authentication follow can be illustrated as below: -1. The device service sends the request without the acceptable Authorization header. -2. The Onvif camera return the response with a "401 Unauthorized" status code, and a WWW-Authenticate header. - - The WWW-Authenticate header contains the required data - - qop: Indicates what "quality of protection" the client has applied to the message. - - nonce: A server-specified data string which should be uniquely generated each time a 401 response is made. The onvif camera can limit the time of the nonce's validity. - - realm: name of the host performing the authentication - - And the device service will put the qop, nonce, realm in the header at next request -3. The device service sends the request again, and the Authorization header must contain: - - qop: retrieve from the previous response - - nonce: retrieve from the previous response - - realm: retrieve from the previous response - - username: The user's name in the specified realm. - - uri: Request uri - - nc: The nc-value is the hexadecimal count of the number of requests (including the current request) that the client has sent with the nonce value in this request. - - cnonce: A random string generated by a client. - - response: A string of 32 hex digits computed as defined below, which proves that the user knows a password. - - MD5( hash1:nonce:nc:cnonce:qop:hash2) - - hash1: MD5(username:realm:password) - - hash2: MD5(POST:uri) - -4. The Onvif camera return the response with a "200 OK" status code - - -Inspect the request by the Wireshark: -![onvif-user-authentication-flow](images/onvif-user-authentication-flow.jpg) diff --git a/doc/running-guide.md b/doc/running-guide.md deleted file mode 100644 index 57a14f0b..00000000 --- a/doc/running-guide.md +++ /dev/null @@ -1,328 +0,0 @@ -# ONVIF Device Service Running Guide - -## Table of Contents - -[Deploy EdgeX and ONVIF Device Service](#deploy-edgex-and-onvif-device-service) -[Verify Service and Device Profiles](#verify-service-and-device-profiles) -[Add Device](#add-device) -[Using EdgeX UI](#using-edgex-ui) -[Manage Devices](#manage-devices) -[Next Steps](#next-steps) - - -## Deploy EdgeX and ONVIF Device Camera Microservice - -
-Run the Service using Docker - - 1. Navigate to the EdgeX `compose-builder` directory: - - ```bash - cd edgex-compose/compose-builder/ - ``` - - 1. Run EdgeX with the microservice in non-secure mode: - - ```bash - make run no-secty ds-onvif-camera - ``` - - 1. Run EdgeX with the microservice in secure mode: - - ```bash - make run ds-onvif-camera - ``` -
- -
-Run the Service natively - - >**NOTE:** Go version 1.20+ is required to run natively. See [here](https://go.dev/doc/install) for more information. - - 1. Navigate to the EdgeX `compose-builder` directory: - - ```bash - cd edgex-compose/compose-builder/ - ``` - - 1. Run EdgeX: - - ```bash - make run no-secty - ``` - - 1. Navigate out of the `edgex-compose` directory to the `device-onvif-camera` directory: - - ```bash - cd device-onvif-camera - ``` - - 1. Run the service - ```bash - make run - ``` - -
- [Optional] Run with NATS - - ```bash - make run-nats - ``` - -
- -
- -## Verify Service and Device Profiles - -### Using Command Line -1. Check the status of the container: - - ```bash - docker ps - ``` - - The status column will indicate if the container is running, and how long it has been up. - - Example Output: - - ```docker - CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES - 33f9c5ecb70e nexus3.edgexfoundry.org:10004/device-onvif-camera:latest "/device-onvif-camer…" 7 weeks ago Up 48 minutes 127.0.0.1:59985->59985/tcp edgex-device-onvif-camera - ``` - -2. Check whether the device service is added to EdgeX: - - ```bash - curl -s http://localhost:59881/api/v2/deviceservice/name/device-onvif-camera | jq . - ``` - Good response: - ```json - { - "apiVersion": "v2", - "statusCode": 200, - "service": { - "created": 1657227634593, - "modified": 1657291447649, - "id": "e1883aa7-f440-447f-ad4d-effa2aeb0ade", - "name": "device-onvif-camera", - "baseAddress": "http://edgex-device-onvif-camera:59984", - "adminState": "UNLOCKED" - } - } - ``` - Bad response: - ```json - { - "apiVersion": "v2", - "message": "fail to query device service by name device-onvif-camer", - "statusCode": 404 - } - ``` - - -3. Check whether the device profile is added: - - ```bash - curl -s http://localhost:59881/api/v2/deviceprofile/name/onvif-camera | jq -r '"profileName: " + '.profile.name' + "\nstatusCode: " + (.statusCode|tostring)' - - ``` - Good response: - ```bash - profileName: onvif-camera - statusCode: 200 - ``` - Bad response: - ```bash - profileName: - statusCode: 404 - ``` - > note: `jq -r` is used to reduce the size of the displayed response. The entire device profile with all resources can be seen by removing `-r '"profileName: " + '.profile.name' + "\nstatusCode: " + (.statusCode|tostring)', and replacing it with '.'` - -### Using EdgeX UI -1. Visit http://localhost:4000 to go to the dashboard for EdgeX Console GUI: - - ![EdgeXConsoleDashboard](./images/EdgeXDashboard.png) -

- Figure 1: EdgeX Console Dashboard -

- -2. To see **Device Services**, **Devices**, or **Device Profiles**, click on their respective tab: - - ![EdgeXConsoleDeviceServices](./images/EdgeXDeviceServices.png) -

- Figure 2: EdgeX Console Device Service List -

- - ![EdgeXConsoleDeviceList](./images/EdgeXDeviceList.png) -

- Figure 3: EdgeX Console Device List -

- - ![EdgeXConsoleDeviceProfileList](./images/EdgeXDeviceProfiles.png) -

- Figure 4: EdgeX Console Device Profile List -

-## Manage Devices -Follow these instructions to update devices. - - -### Curl Commands - -#### Add Device - -1. Edit the information to appropriately match the camera. The fields `Address`, `MACAddress` and `Port` should match that of the camera: - - ```bash - curl -X POST -H 'Content-Type: application/json' \ - http://localhost:59881/api/v2/device \ - -d '[ - { - "apiVersion": "v2", - "device": { - "name":"Camera001", - "serviceName": "device-onvif-camera", - "profileName": "onvif-camera", - "description": "My test camera", - "adminState": "UNLOCKED", - "operatingState": "UP", - "protocols": { - "Onvif": { - "Address": "10.0.0.0", - "Port": "10000", - "MACAddress": "aa:bb:cc:11:22:33", - "FriendlyName":"Default Camera" - }, - "CustomMetadata": { - "Location":"Front door" - } - } - } - } - ]' - ``` - - Example Output: - ```bash - [{"apiVersion":"v2","statusCode":201,"id":"fb5fb7f2-768b-4298-a916-d4779523c6b5"}] - ``` - - Map credentials using the `map-credentials.sh` script. - a. Run `bin/map-credentials.sh` - b. Select `(Create New)` - ![](../images/create_new.png) - c. Enter the Secret Name to associate with these credentials - ![](../images/secret_name.png) - d. Enter the username - ![](../images/set_username.png) - e. Enter the password - ![](../images/set_password.png) - f. Choose the Authentication Mode - ![](../images/auth_mode.png) - g. Assign one or more MAC Addresses to the credential group - ![](../images/assign_mac.png) - h. Learn more about updating credentials [here](../utility-scripts.md) - - Successful: - - ```bash - Dependencies Check: Success - Consul Check: ... - curl -X GET http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera?keys=true - Response [200] Success - curl -X GET http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap?keys=true - Response [200] - Secret Name: a - curl -X GET http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap/a?raw=true - Response [404] - Failed! curl returned a status code of '404' - Setting InsecureSecret: a/SecretName - curl --data "" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets/a/SecretName - Response [200] true - - - Setting InsecureSecret: a/SecretData/username - curl --data "" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets/a/SecretData/username - Response [200] true - - - Setting InsecureSecret: a/SecretData/password - curl --data "" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets/a/SecretData/password - Response [200] true - - - Setting InsecureSecret: a/SecretData/mode - curl --data "usernmetoken" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/Writable/InsecureSecrets/a/SecretData/mode - Response [200] true - - - Setting Credentials Map: a = '' - curl -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap/a - Response [200] true - - - - Secret Name: a - curl -X GET http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap/a?raw=true - Response [200] - Setting Credentials Map: a = '11:22:33:44:55:66' - curl --data "11:22:33:44:55:66" -X PUT http://localhost:8500/v1/kv/edgex/v3/device-onvif-camera/AppCustom/CredentialsMap/a - Response [200] true - ``` - -1. Verify device(s) have been succesfully added to core-metadata. - - ```bash - curl -s http://localhost:59881/api/v2/device/all | jq -r '"deviceName: " + '.devices[].name'' - ``` - - Example Output: - ```bash - deviceName: Camera001 - deviceName: device-onvif-camera - ``` - >note: device with name `device-onvif-camera` is a stand-in device and can be ignored. - >note: `jq -r` is used to reduce the size of the displayed response. The entire device with all information can be seen by removing `-r '"deviceName: " + '.devices[].name'', and replacing it with '.'` - -#### Update Device - - There are multiple commands that can update aspects of the camera entry in meta-data. Refer to the [Swagger documentation]() for more information (not implemented). - -#### Delete Device - - ```bash - curl -X 'DELETE' \ - 'http://localhost:59881/api/v2/device/name/' \ - -H 'accept: application/json' - ``` - -## Shutting Down -To stop all EdgeX services (containers), execute the `make down` command. This will stop all services but not the images and volumes, which still exist. - -1. Navigate to the `edgex-compose/compose-builder` directory. -1. Run this command - ```bash - make down - ``` -1. To shut down and delete all volumes, run this command - ```bash - make clean - ``` - -## Next Steps - -[Learn how to use the device service](./general-usage.md) - -## References - -- ONVIF Website: http://www.onvif.org -- EdgeX Foundry Project Wiki: https://wiki.edgexfoundry.org/ -- EdgeX Source Code: https://github.com/edgexfoundry -- Edgex Developer Guide: https://docs.edgexfoundry.org/2.1/ -- Docker Repos - - Docker https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository - - Docker Compose https://docs.docker.com/compose/install/#install-compose - -# License - -[Apache-2.0](https://github.com/edgexfoundry-holding/device-onvif-camera/blob/main/LICENSE) diff --git a/doc/setup.md b/doc/setup.md deleted file mode 100644 index bc975498..00000000 --- a/doc/setup.md +++ /dev/null @@ -1,139 +0,0 @@ -# ONVIF Device Service Set Up Guide - -Follow this guide to set up your system to run the ONVIF Device Service. - -## Table of Contents - -[System Requirements](#system-requirements) -[Dependencies](#dependencies) -    [Git](#install-git) -    [Docker](#install-docker) -    [Docker Compose](#install-docker-compose) -    [Tools](#install-tools) -[Download EdgeX Compose](#download-edgex-compose) - -## System Requirements - -- Intel™ Core® processor -- Ubuntu 20.04.4 LTS -- ONVIF-compliant Camera - ->NOTE: The instructions in this guide were developed and tested using Ubuntu 20.04 LTS and the Tapo C200 Pan/Tilt Wi-Fi Camera, referred to throughout this document as the **Tapo C200 Camera**. However, the software may work with other Linux distributions and ONVIF-compliant cameras. Refer to our [list of tested cameras for more information](./ONVIF-protocol.md#tested-onvif-cameras) - -**Other Requirements** - -You must have administrator (sudo) privileges to execute the user guide commands. - -## Dependencies -The software has dependencies, including Git, Docker, Docker Compose, and assorted tools. Follow the instructions below to install any dependency that is not already installed. - -### Install Git -Install Git from the official repository as documented on the [Git SCM](https://git-scm.com/download/linux) site. - -1. Update installation repositories: - ```bash - sudo apt update - ``` - -2. Add the Git repository: - ```bash - sudo add-apt-repository ppa:git-core/ppa -y - ``` - -3. Install Git: - ```bash - sudo apt install git - ``` - -### Install Docker -Install Docker from the official repository as documented on the [Docker](https://docs.docker.com/engine/install/ubuntu/) site. - -### Verify Docker -To enable running Docker commands without the preface of sudo, add the user to the Docker group. Then run Docker with the `hello-world` test. - -1. Create Docker group: - ```bash - sudo groupadd docker - ``` - >NOTE: If the group already exists, `groupadd` outputs a message: **groupadd: group `docker` already exists**. This is OK. - -2. Add User to group: - ```bash - sudo usermod -aG docker $USER - ``` - -3. Restart your computer for the changes to take effect. - -4. To verify the Docker installation, run `hello-world`: - - ```bash - docker run hello-world - ``` - A **Hello from Docker!** greeting indicates successful installation. - - ```bash - Unable to find image 'hello-world:latest' locally - latest: Pulling from library/hello-world - 2db29710123e: Pull complete - Digest: sha256:10d7d58d5ebd2a652f4d93fdd86da8f265f5318c6a73cc5b6a9798ff6d2b2e67 - Status: Downloaded newer image for hello-world:latest - - Hello from Docker! - This message shows that your installation appears to be working correctly. - ... - ``` - -### Install Docker Compose -Install Docker Compose from the official repository as documented on the [Docker Compose](https://docs.docker.com/compose/install/linux/#install-using-the-repository) site. - -### Install Tools -Install the build, media streaming, and parsing tools: - -```bash -sudo apt install build-essential ffmpeg jq curl -``` - -### Tool Descriptions -The table below lists command line tools this guide uses to help with EdgeX configuration and device setup. - -| Tool | Description | Note | -| ----------- | ----------- |----------- | -| **curl** | Allows the user to connect to services such as EdgeX. |Use curl to get transfer information either to or from this service. In the tutorial, use `curl` to communicate with the EdgeX API. The call will return a JSON object.| -| **jq** |Parses the JSON object returned from the `curl` requests. |The `jq` command includes parameters that are used to parse and format data. In this tutorial, the `jq` command has been configured to return and format appropriate data for each `curl` command that is piped into it. | -| **base64** | Converts data into the Base64 format.| | - ->Table 1: Command Line Tools - -## Download EdgeX Compose - 1. Clone the EdgeX compose repository: - - ```bash - git clone https://github.com/edgexfoundry/edgex-compose.git - ``` - 1. Navigate to the `edgex-compose` directory: - - ```bash - cd edgex-compose - ``` - - 1. Checkout the Levski release: - - ```bash - git checkout levski - ``` - - Note: The `levski` branch is the latest stable branch at the time of this update. - - 1. Navigate back to your home directory: - - ```bash - cd ~ - ``` - -## Next Steps - [Running and using the default image and configurations](./running-guide.md) - [Configure and build from the source](./custom-build.md) - -## License - -[Apache-2.0](https://github.com/edgexfoundry-holding/device-onvif-camera/blob/main/LICENSE) diff --git a/doc/test-with-postman.md b/doc/test-with-postman.md deleted file mode 100644 index 94115282..00000000 --- a/doc/test-with-postman.md +++ /dev/null @@ -1,103 +0,0 @@ -# Test with Postman - -This instruction introduce how to test with the [Post REST client tool](https://www.postman.com/product/rest-client/). - -## Test ONVIF API - -Before using `device-onvif-camera`, the user can verify the camera's functionality via ONVIF APIs, we provide the following collections for testing: -- Capabilities -- Auto Discovery -- Network Configuration -- System Function -- User Handling -- Metadata Configuration -- Video Streaming -- Video Encoder Configuration -- PTZ -- Event Handling -- Analytics - -### Import the Postman collections - -Download and import the following JSON files into Postman REST client tool: -- [onvif.postman_collection.json](./postman/onvif.postman_collection.json) -- [onvif.postman_environment.json](./postman/onvif.postman_environment.json) - -### Set Up the Authentication for ONVIF security - -Replace the following onvif `environment variable` on the Postman REST client. -- WS_USERNAME - The username for a certified user -- WS_NONCE - A random, unique number generated by a client -- WS_UTC_TIME - The UtcTime when the request is made. -- WS_PASSWORD_DIGEST - a digest that is calculated according to an algorithm defined in the specification for WS-UsernameToken: - Digest = B64ENCODE( SHA1( B64DECODE( Nonce ) + Date + Password ) ) - -#### How to generate the PasswordDigest? -According to the ONVIF spec and [programmer guide](https://www.onvif.org/wp-content/uploads/2016/12/ONVIF_WG-APG-Application_Programmers_Guide-1.pdf), the client needs to provide the password digest for WS-UsernameToken. -For example, we can generate the password digest in golang: -```go -package main - -import ( - "crypto/sha1" - "encoding/base64" - "fmt" -) - -func main() { - nonce := "abcd" - password := "Password1!" - created := "2022-06-06T12:26:37.769698Z" - passwordDigest := generatePasswordDigest(nonce, created, password) - - fmt.Println("Nonce:", nonce) - fmt.Println("Created:", created) - fmt.Println("PasswordDigest:", passwordDigest) -} - -//Digest = B64ENCODE( SHA1( B64DECODE( Nonce ) + Date + Password ) ) -func generatePasswordDigest(Nonce string, Created string, Password string) string { - sDec, _ := base64.StdEncoding.DecodeString(Nonce) - hasher := sha1.New() - hasher.Write([]byte(string(sDec) + Created + Password)) - return base64.StdEncoding.EncodeToString(hasher.Sum(nil)) -} -``` -The runnable code: https://go.dev/play/p/ZnE2nZYorg9 - -### Set Up the API Endpoint - -Generally, the device web service endpoint is http:/${address}:${port}/onvif/device_service, then we can use `GetCapabilities` ONVIF function to query other web service's endpoint: -```xml - - - - - - - http://192.168.12.123/onvif/device_service - ... - - - http://192.168.12.123/onvif/Events - ... - - ... - - - -``` - -And we should replace the following onvif `environment variable` on the Postman REST client. -- DEVICE_ENDPOINT - device web service endpoint -- MEDIA_ENDPOINT - media web service endpoint -- EVENT_ENDPOINT - event web service endpoint -- PTZ_ENDPOINT - ptz web service endpoint - -Then we can execute other ONVIF function via Postman REST client tool. - -## Test device-onvif-camera API - -After adding the device according to the [Getting Started Guide](./getting-started-guide.md), then we can import the following Postman collections for testing the APIs: -- [onvif.postman_collection.json](./postman/device-onvif-camera.postman_collection.json) -- [onvif.postman_environment.json](./postman/device-onvif-camera.postman_environment.json) diff --git a/doc/utility-scripts.md b/doc/utility-scripts.md deleted file mode 100644 index 822c17de..00000000 --- a/doc/utility-scripts.md +++ /dev/null @@ -1,109 +0,0 @@ -# Utility Scripts - -> **NOTE:** If running EdgeX in Secure Mode, you will need a **[Consul ACL Token](https://docs.edgexfoundry.org/2.1/security/Ch-Secure-Consul/#how-to-get-consul-acl-token)** -> in order to use these scripts. - -## Use Cases -### Create new credentials and assign MAC Addresses -1. Run `bin/map-credentials.sh` -2. Select `(Create New)` - ![](images/create_new.png) -3. Enter the Secret Name to associate with these credentials - ![](images/secret_name.png) -4. Enter the username - ![](images/set_username.png) -5. Enter the password - ![](images/set_password.png) -6. Choose the Authentication Mode - ![](images/auth_mode.png) -7. Assign one or more MAC Addresses to the credential group - ![](images/assign_mac.png) - -### Assign MAC Addresses to existing credentials -> **Note:** Currently EdgeX is unable to provide a way to query the names of existing secrets from the secret store, so this method -> only works with credentials which have a key in the CredentialsMap. If the credentials were added via these -> utility scripts, a placeholder key was added for you to the CredentialsMap. - -1. Run `bin/map-credentials.sh` -2. Select the name of the existing credentials you want to assign devices to - ![](images/select_creds.png) -3. Assign one or more MAC Addresses to the credential group - ![](images/assign_mac_2.png) - -### Modify existing credentials -1. Run `bin/edit-credentials.sh` -2. Select the name of the existing credentials you want to modify - > **NOTE:** This will modify the username/password for ALL devices using these credentials. Proceed with caution! - - ![](images/pick_creds_2.png) - -3. Enter the new username - ![](images/username_change.png) -4. Enter the new password - ![](images/password_change.png) -5. Choose the new Authentication Mode - ![](images/auth_mode_2.png) - - -### List all existing credential mappings -1. Run `bin/query-mappings.sh` - -Output will look something like this: -``` - Credentials Map: - mycreds = 'aa:bb:cc:dd:ee:ff' - mycreds2 = '' - simcreds = 'cb:4f:86:30:ef:19,87:52:89:4d:66:4d,f0:27:d2:e8:9e:e1,9d:97:d9:d8:07:4b,99:70:6d:f5:c2:16' - tapocreds = '10:27:F5:EA:88:F3' -``` - -### Configure DiscoverySubnets -1. Run `bin/configure-subnets.sh` -2. (Optional) If running secure mode, enter Consul Token - ![](images/consul_acl_sm.png) - - -## configure-subnets.sh -### Usage -```shell -bin/configure-subnets.sh [-s/--secure-mode] [-t ] -``` -### About -The purpose of this script is to make it easier for an end user to configure Onvif device discovery -without the need to have knowledge about subnets and/or CIDR format. The `DiscoverySubnets` config -option defaults to blank in the `configuration.yaml` file, and needs to be provided before a discovery can occur. -This allows the device-onvif-camera device service to be run in a NAT-ed environment without host-mode networking, -because the subnet information is user-provided and does not rely on `device-onvif-camera` to detect it. - -This script finds the active subnet for any and all network interfaces that are on the machine -which are physical (non-virtual) and online (up). It uses this information to automatically fill out the -`DiscoverySubnets` configuration option through Consul of a deployed `device-onvif-camera` instance. - -## edit-credentials.sh -### Usage -```shell -bin/edit-credentials.sh [-s/--secure-mode] [-u ] [-p ] [--auth-mode {usernametoken|digest|both}] [-P secret-name] [-M mac-addresses] [-t ] -``` -### About -The purpose of this script is to allow end-users to modify credentials either through -EdgeX InsecureSecrets via Consul, or EdgeX Secrets via the device service. - -## map-credentials.sh -### Usage -```shell -bin/map-credentials.sh [-s/--secure-mode] [-u ] [-p ] [--auth-mode {usernametoken|digest|both}] [-P secret-name] [-M mac-addresses] [-t ] -``` -### About -The purpose of this script is to allow end-users to add credentials either through -EdgeX InsecureSecrets via Consul, or EdgeX Secrets via the device service. It then allows the -end-user to add a list of MAC Addresses to map to those credentials via Consul. - -## query-mappings.sh -### Usage -```shell -bin/query-mappings.sh [-s/--secure-mode] [-u ] [-p ] [--auth-mode {usernametoken|digest|both}] [-P secret-name] [-M mac-addresses] [-t ] -``` -### About -The purpose of this script is to allow end-users to see what MAC Addresses are -mapped to what credentials. - diff --git a/doc/ws-discovery.md b/doc/ws-discovery.md deleted file mode 100644 index 1f99f4fa..00000000 --- a/doc/ws-discovery.md +++ /dev/null @@ -1,98 +0,0 @@ -# How does WS-Discovery work? - -ONVIF devices support WS-Discovery, which is a mechanism that supports probing a network to find ONVIF capable devices. - -Probe messages are sent over UDP to a standardized multicast address and UDP port number. - - - -WS-Discovery is generally faster than netscan becuase it only sends out one broadcast signal. However, it is normally limited by the network segmentation since the multicast packages typically do not traverse routers. - -- Find the WS-Discovery programmer guide from https://www.onvif.org/profiles/whitepapers/ -- Wiki page https://en.wikipedia.org/wiki/WS-Discovery - -Example: -1. The client sends Probe message to find Onvif camera on the network. - ```xml - - - - http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe - uuid:a86f9421-b764-4256-8762-5ed0d8602a9c - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - urn:schemas-xmlsoap-org:ws:2005:04:discovery - - - - - - ``` - -2. The Onvif camera responds the Hello message according to the Probe message - > The Hello message from HIKVISION - ```xml - - - - urn:uuid:cea94000-fb96-11b3-8260-686dbc5cb15d - uuid:a86f9421-b764-4256-8762-5ed0d8602a9c - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches - - - - - - - urn:uuid:cea94000-fb96-11b3-8260-686dbc5cb15d - - dn:NetworkVideoTransmitter tds:Device - onvif://www.onvif.org/type/video_encoder onvif://www.onvif.org/Profile/Streaming onvif://www.onvif.org/MAC/68:6d:bc:5c:b1:5d onvif://www.onvif.org/hardware/DFI6256TE http:123 - http://192.168.12.123/onvif/device_service - 10 - - - - - ``` - - >The Hello message from Tapo C200 - ```xml - - - - uuid:a86f9421-b764-4256-8762-5ed0d8602a9c - uuid:a86f9421-b764-4256-8762-5ed0d8602a9c - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - urn:schemas-xmlsoap-org:ws:2005:04:discovery - http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches - - - - - - uuid:3fa1fe68-b915-4053-a3e1-c006c3afec0e - - ttl - - tdn:NetworkVideoTransmitter - onvif://www.onvif.org/name/TP-IPC onvif://www.onvif.org/hardware/MODEL onvif://www.onvif.org/Profile/Streaming onvif://www.onvif.org/location/ShenZhen onvif://www.onvif.org/type/NetworkVideoTransmitter - http://192.168.12.128:2020/onvif/device_service - 1 - - - - - ```