Use the Events and State WebSocket API to subscribe to events in the VMS. Events will be pushed to the recipient through the established WebSocket connection. The API uses a filter mechanism to control the events of interest, this can be modified during the lifetime of the connection.
NOTE:
User credentials, bearer tokens, and other sensitive data are transmitted in cleartext. It is highly recommended to set up the VMS to be secured (using HTTPS / WSS).
Connect to the Events & State service to set up a session to start receiving events. To connect, start a secure WebSockets connection at:
wss://{api-gateway}/api/ws/events/v1
or if the VMS is unsecure:
ws://{api-gateway}/api/ws/events/v1
Key | Description |
---|---|
Authorization (optional) |
string An IDP token in bearer format: Bearer {token} Example: Bearer eyJhbG...ZGhCy4rg |
NOTE:
If the Authorization header is not provided, authentication must be done by means of the Authenticate command. See below.
The messages are JSON formatted Events and State commands.
NOTE:
In case of malformed commands then the connection will be closed.
Most common HTTP responses
Status | Description |
---|---|
101 | Upgrading to a WebSockets connection (Connection succeeded). |
401 | Unauthorized access, expired or missing authorization token. |
500 | Internal server error, generic error has occurred on the server. |
503 | Service unavailable, the server is temporarily unavailable. |
The authenticate command is an alternative to an Authorization header when establishing the WebSocket connection. It can be used to authenticate the connection after it has been established.
Functionality:
{
"command": "authenticate",
"commandId": 1,
"token": ""
}
Key | Type | Description |
---|---|---|
command |
string | authenticate |
commandId |
integer | Id of the command. Generated by the client. The id should be unique for each command, since this id is used for the command response. It is however the responsibility of the client, and is not checked server side. |
token |
string | string An IDP token in bearer format: Bearer {token} Example: Bearer eyJhbG...ZGhCy4rg |
Success
{
"commandId": 1,
"subscriptionId": "",
"status": 200
}
Client is already authenticated
{
"commandId": 1,
"status": 409,
"error":
{
"errorText" : "Client is already authenticated."
}
}
If validation fails:
| Close Status | Close Description | Description | | ------ | ----------- | | 1002 (Protocol Error) | No Authorization message received within the timeout period.|Connection timed out | 1008 (Policy Violation) | Unauthorized Access. |The provided token is invalid.| | 1008 (Policy Violation) | Expected Authenticate message. |First message after connection was not an Authenticate command.|
Once a client has established a connection it should either initiate a new session or attempt to resume an existing session.
Functionality:
EssResumeSessionTimeout
parameter defined in the Event Server configuration file (VideoOS.Event.Server.exe.config
).{
"command": "startSession",
"commandId": 1,
"sessionId": "",
"eventId": ""
}
Key | Type | Description |
---|---|---|
command |
string | startSession |
commandId |
integer | Id of the command. Generated by the client. The id should be unique for each command, since this id is used for the command response. It is however the responsibility of the client, and is not checked server side. |
sessionId |
string | Empty when a new session should be initiated. When specifying a valid GUID then an existing session having this id should be resumed. |
eventId |
string | Id of the last event that has been successfully received. This field is ignored when creating a new session. When resuming a session and specifying this id, the server will send all events that have occurred after this last received event. To ignore cached events this should be empty. |
Sample 1 - Create a new Session
{
"command": "startSession",
"commandId": 1,
"sessionId": "",
"eventId": ""
}
Sample 2 - Resume an existing Session, getting no cached events
{
"command": "startSession",
"commandId": 2,
"sessionId": "991FE95D-98FB-47EF-8A6E-635A184FBDBE",
"eventId": ""
}
Sample 3 - Resume an existing Session, requesting cached events
{
"command": "startSession",
"commandId": 3,
"sessionId": "991FE95D-98FB-47EF-8A6E-635A184FBDBE",
"eventId": "381F3948-AD23-4E88-840D-10BB61B4B3C2"
}
Success
{
"commandId": 1,
"sessionId": "",
"inactiveTimeoutSeconds": 30
"status": 200
}
Key | Type | Description |
---|---|---|
commandId |
integer | Id of the command that has been responded to. |
sessionId |
string | Id of the session that has been created or resumed. |
inactiveTimeoutSeconds |
integer | Number of seconds defining the lifetime of an inactive session. |
status |
integer | 200 when a session has been resumed, 201 when a new session has been created. |
Sample 1 - New session has been created
{
"commandId": 1,
"sessionId": "D129A5A0-BCF6-46C5-862D-C57F188DE369",
"inactiveTimeoutSeconds": 30
"status": 201
}
Sample 2 - An existing session has been resumed
{
"commandId": 2,
"sessionId": "991FE95D-98FB-47EF-8A6E-635A184FBDBE",
"inactiveTimeoutSeconds": 30
"status": 200
}
Sample 3 - Resuming an existing session failed - a new session has been created instead
{
"commandId": 3,
"sessionId": "1B73F389-6E73-4FE2-BE35-2547A778CE15",
"inactiveTimeoutSeconds": 30
"status": 201
}
Failure
{
"commandId": 1,
"status": 400,
"error":
{
"errorText" : ""
}
}
Key | Type | Description |
---|---|---|
commandId |
integer | Id of the command that has been responded to. |
status |
integer | HTTP error code stating the cause of the error. |
errorText |
string | Text describing the error. |
An error response will be returned if a session does not exist, if other commands are sent to the server, or if the command has malformed values.
To receive events a subscription must be made defining the events of interest. The subscription defines which event types, sources and resources that should be used for filtering the events that are raised in the VMS and should be pushed to the client. Use the addSubscription
command to apply a subscription.
Functionality:
startSession
command) before this command can be sent.{
"command": "addSubscription",
"commandId": 1,
"filters": [
{
"modifier": "",
"resourceTypes": [],
"sourceIds": [],
"eventTypes": []
}
]
}
Key | Type | Description |
---|---|---|
command |
string | addSubscription |
commandId |
integer | Id of the command. Generated by the client. The id should be unique for each command, since this id is used for the command response. It is however the responsibility of the client, and is not checked server side. |
filters |
array of objects | List of filters that includes and excludes events. By default no events are included. The list MUST contain at least one filter that has the include modifier. |
Filter content
Key | Type | Description |
---|---|---|
modifier |
string | include or exclude controls whether the events specified in the filter are included or excluded. Exclude modifiers has higher priority than Include modifiers. I.e. if an event is in anyway excluded by means of any exclude-filter it cannot be included by an include-filter. Thus one should be careful using * in exclude-filters. |
resourceTypes |
array of strings | A "*" (a list containing only this element) or a list defining resource types represented by strings and GUIDs. E.g. "cameras" , "microphones" , GUID representing a resource type. The strings are case insensitive and known by the system. If any of the strings does not match a known resource type, the subscription will fail, and an error response is returned. |
sourceIds |
array of strings | A "*" or a list of GUIDs that represents source that produced the event. |
eventTypes |
array of strings | A "*" (a list containing only this element) or a list of GUIDs that represents event type(s). E.g. a GUID representing ArchiveFailure , or a GUID representing DiskFull . |
NOTE:
When defining a"*"
in an array, then it MUST be the only element. When defining GUIDs these must be strings that can be parsed as GUIDs. Any valid GUID is accepted, however it is not validated whether it is known by the VMS.
Success
{
"commandId": 1,
"subscriptionId": "",
"status": 200
}
Key | Type | Description |
---|---|---|
commandId |
integer | Id of the command that has been responded to. |
subscriptionId |
string | Id of the subscription, created by the server. |
status |
integer | 200 when a new subscription has been added. |
Failure
{
"commandId": 1,
"status": 400,
"error":
{
"errorText" : ""
}
}
Key | Type | Description |
---|---|---|
commandId |
integer | Id of the command that has been responded to. |
status |
integer | HTTP error code stating the cause of the error. |
errorText |
string | Text describing the error. |
{
"command": "removeSubscription",
"commandId": 1,
"subscriptionId": "",
}
Key | Type | Description |
---|---|---|
command |
string | removeSubscription |
commandId |
integer | Id of the command. Generated by the client. The id should be unique for each command, since this id is used for the command response. It is however the responsibility of the client, and is not checked server side. |
subscriptionId |
string | This must be the id received as a response to a previous addSubscription command. If the subscription does not exist, the server will respond with an error. |
Success
{
"commandId": 1,
"status": 200
}
Key | Type | Description |
---|---|---|
commandId |
integer | Id of the command that has been responded to. |
status |
integer | 200 when a new subscription has been added. |
Failure
{
"commandId": 1,
"status": 400,
"error":
{
"errorText" : ""
}
}
Key | Type | Description |
---|---|---|
commandId |
integer | Id of the command that has been responded to. |
status |
integer | HTTP error code stating the cause of the error. |
errorText |
string | Text describing the error. |
The getState
command can be used to get the current state based on the stateful events that have been subscribed for.
It can be sent at any point in time during a session to resynchronize the states that a client may depend on.
Functionality:
stategroupid
.Example: If the subscription defines types A
and B
, but the current state has event type C
, then state C
is returned, event though the client will not receive the event that the state has changed to this value.
For this reason, it is recommended to subscribe to all event types within a state group.
{
"command": "getState",
"commandId": 1
}
Key | Type | Description |
---|---|---|
command |
string | getState |
commandId |
integer | Id of the command. Generated by the client. The id should be unique for each command, since this id is used for the command response. It is however the responsibility of the client, and is not checked server side. |
Success
{
"commandId": 1,
"status": 200,
"states": [
{
"specVersion": "1.0",
"type": "",
"source": "",
"time": "",
"stategroupid": ""
}
]
}
Key | Type | Description |
---|---|---|
commandId |
integer | Id of the command that has been responded to. |
status |
integer | 200 when a new subscription has been added. |
states |
array | List of states based on the defined subscriptions and the known state at the time of the query. |
States content
Key | Type | Description |
---|---|---|
specVersion |
string | 1.0 (constant) version of the event structure |
type |
string | Event Type, a GUID that represents an event. E.g. "DiskFull", "Recording Started" etc. |
source |
string | Format [resource path]/[GUID]. Identifying the source of the event in the VMS. The resource path refers to the type of hardware. The GUID uniquely identifies the hardware. Example: cameras/2313e29f-0a10-4463-9ce5-345e143d87c0 |
time |
string (date-time UTC) | Format: "yyyy-MM-ddTHH:mm:ss.fffffffZ". Indicates when the item entered the current state. The given timestamp indicates when the state was discovered. The item may have had this state for a longer time since the timestamp may indicate the time when the Event Server was started and collected the state from the system. |
stategroupid |
string | GUID that identifies the state group that the event belongs to. |
Events and states are received in event messages. The event messages are sent soonest possible after an event has been detected in the VMS. An event message can contain one or more events. The events in the event message are formatted according to the cloudevents specification JSON Event Format for CloudEvents and are following the JSON Scheme CloudEvents.
Events in an event message is ordered in the same order as the events were detected. Events messages are sent in the order that their contained events were detected.
I.e., when receiving an event message containing events A
,B
and subsequently receiving an event message containing events C
,D
, means that the events are detected in the order A
,B
,C
,D
.
Thus, when receiving stateful events, it is safe to assume that the last received event also reflects the current state in the VMS.
{
"events": [
{
"specversion": "",
"type": "",
"source": "",
"id": "",
"time": "",
"stategroupid": "",
"data": {}
},
{}
]
}
Key | Type | Description |
---|---|---|
specversion |
string | Version of the event format |
type |
string | GUID representing the event type in the VMS |
source |
string | Format [resource path]/[GUID]. Identifying the source of the event in the VMS |
id |
string | Unique ID of the event. Note this field may contain an empty GUID (00...) in rare cases where the event reflects a detected state that is not caused by an underlying stateful event. |
time |
string (date-time UTC) | The time when the event was detected |
stategroupid |
string | The field is not mandatory. If present the event is stateful, and this ID defines the state group the event belongs to. |
data |
object | This field may contain additional data. The content depends on the type of the event. |
{
"events": [
{
"specversion": "1.0",
"type": "698ef3b8-9545-4f7e-8c1f-2e4056c10f78",
"source": "cameras/11979584-2dab-496f-a8c2-527b1922da66",
"id": "4577f552-765a-438c-bc7d-e5ff1f754bc3",
"time": "2023-03-13T14:22:58.7379497Z",
"data": {
"description": "a nice description",
"startTime": "2023-03-13T14:22:58.7379497Z",
"endTime": "2023-03-13T14:22:58.7379497Z",
"location": "Copenhagen",
"count": 1,
"rules": [
{
"id": "cce6ee25-e43e-4c9e-8b85-f93e379a842d"
}
],
"objects": [
{
"id": "d9d9facb-dfdf-4517-85d8-1b1d3f09c95b",
"confidence": 0.0,
"alarmTrigger": false,
"removed": false,
"size": 0.0
}
],
"references": [
"cameras/11979584-2dab-496f-a8c2-527b1922da66"
],
"vendor": {
"name": "vendor 1"
}
}
}
]
}
Sequence diagram showing:
NOTE:
If resuming the session is not possible, due to for example exceeding timeout, the start session response will include a new session id and the status code 201 signaling a new session has been created.