This Onvif Camera Device Service is developed to control/communicate ONVIF-compliant cameras accessible via http in an EdgeX deployment
The device service supports the onvif features listed in the following table:
Note: The functions in the bold text are mandatory for Onvif protocol.
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 |
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.
For example, we can send a SOAP request to the Onvif camera as below:
curl --request POST 'http://192.168.12.128:2020/onvif/service' \
--header 'Content-Type: application/soap+xml' \
--data-raw '<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://www.w3.org/2003/05/soap-envelope" xmlns:soap-enc="http://www.w3.org/2003/05/soap-encoding" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:onvif="http://www.onvif.org/ver10/schema" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" >
<soap-env:Header>
<Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<UsernameToken>
<Username>myUsername</Username>
<Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">+HKcvc+LCGClVwuros1sJuXepQY=</Password>
<Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">w490bn6rlib33d5rb8t6ulnqlmz9h43m</Nonce>
<Created xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2021-10-21T03:43:21.02075Z</Created>
</UsernameToken>
</Security>
</soap-env:Header>
<soap-env:Body>
<trt:GetStreamUri>
<trt:ProfileToken>profile_1</trt:ProfileToken>
</trt:GetStreamUri>
</soap-env:Body>
</soap-env:Envelope>'
And the response should be like the following XML data:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsdd="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:chan="http://schemas.microsoft.com/ws/2005/02/duplex"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsa5="http://www.w3.org/2005/08/addressing"
xmlns:xmime="http://tempuri.org/xmime.xsd" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:wsrfbf="http://docs.oasis-open.org/wsrf/bf-2"
xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:wsrfr="http://docs.oasis-open.org/wsrf/r-2" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2"
xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:ter="http://www.onvif.org/ver10/error" xmlns:tns1="http://www.onvif.org/ver10/topics"
xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl"
xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:tdn="http://www.onvif.org/ver10/network/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl"
xmlns:trp="http://www.onvif.org/ver10/replay/wsdl" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl">
<SOAP-ENV:Header></SOAP-ENV:Header>
<SOAP-ENV:Body>
<trt:GetStreamUriResponse>
<trt:MediaUri>
<tt:Uri>rtsp://192.168.12.128:554/stream1</tt:Uri>
<tt:InvalidAfterConnect>false</tt:InvalidAfterConnect>
<tt:InvalidAfterReboot>false</tt:InvalidAfterReboot>
<tt:Timeout>PT0H0M2S</tt:Timeout>
</trt:MediaUri>
</trt:GetStreamUriResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Since the SOAP is a 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 │ │ │
│ │ │ │ │ │
└──────────────┘ └────────────────────┘ └─────────────────┘
make test
make build
Build docker image named edgex/device-onvif-camera:0.0.0-dev with the following command:
make docker
The device resource should provide two attributes:
- service indicates the web service for the Onvif
- function indicates the SOAP action for the specified web service
For example:
deviceResources:
- name: "Hostname"
isHidden: false
description: "Camera Hostname"
attributes:
service: "Device"
getFunction: "GetHostname"
setFunction: "SetHostname"
properties:
valueType: "Object"
readWrite: "RW"
See the sample at cmd/res/profiles/camera.yaml
The device's protocol properties should contain:
- Address is the IP address of the Onvif camera
- Port is the server port of the Onvif camera
- AuthMode indicates the auth mode of the Onvif camera
- SecretPath indicates the path to retrieve the username and password
For example:
[[DeviceList]]
Name = "Camera001"
ProfileName = "camera"
Description = "My test camera"
[DeviceList.Protocols]
[DeviceList.Protocols.Onvif]
Address = "192.168.12.123"
Port = 80
# Assign AuthMode to "digest" | "usernametoken" | "both" | "none"
AuthMode = "usernametoken"
SecretPath = "credentials001"
See the sample at cmd/res/devices/camera.toml.example
- Getting started guide for developer
- Getting started guide for running docker container with none security mode
- Getting started guide for running docker container with security mode
Tested Onvif cameras with Onvif functions.
- User Handling
- Analytics Support
- Test with Postman - Test with Postman for ONVIF and device-onvif-camera APIs