Camlytics Telemetry Interface
Jun 23 2023 at 12:00 AM
Introduction
Camlytics enables users to connect their camera systems to receive real-time statistics. This is accomplished by combining video monitoring, audience intelligence and space analytics software. Connect your existing private network camera system and get instant real-time statistics on people counting, vehicle counting, locations occupancy, queues, heatmaps and more.
Figure 1 - Camlytics logo
Aim
The statistics provided by Camlytics can be useful for the following use cases:
Vehicle counting
Occupancy monitoring
Queues
Approach
Device Functionality Overview
Camlytics is software installed on your computer. The camera you want to monitor is linked to the software using the camera’s IP address. You can then setup the different cameras in the Camlytics software to gather the statistics you require. This includes adding triggers to the camera. When anything (car, person, animal, etc.) passes through this trigger, the data will be analysed. The details can then be passed to an external source (in this case our driver) through Webhooks. An API is also available to retrieve details about the locations, cameras and triggers used by Camlytics.
Figure 2 - Camlytics overview
Capability
The following events can be detected by the Camlytics software:
- Tripwire crossed
- Tailgating
- Join region
- Leave region
- Motion within region
- Loitering
- Crowd on
- Sabotage
The software can also distinguish between pedestrians and vehicles. This even includes the type of vehicle, gender of pedestrian and age range of pedestrian.
Protocol information
Data is received from Camlytics using the following approaches:
- A REST API is used to retrieve data from Camlytics.
- Subscribing to webhook events to receive telemetry data from Camlytics.
The REST API retrieves the following information:
- Locations packet
{
"code": 0,
"msg": "Success",
"result": [
{
"id": 6418,
"hash": "Mo28m8Nscj8tYuy1sgmgMnl7ccLmq2ZQo9l8NlKwPGigndB9S3uy+cNLoeIyHEYYwCA4S6y/CdGxf7g5o8AlDb8sBuMpC9l8F94KPlbbmefGJOvFQhtp1WbnO+DC7RhPxRdrfCNo7ew=",
"name": "GRDDMOCCTV",
"version": "3.6.5",
"timezone_offset": "+02:00"
},
{
"id": 5567,
"hash": "SwU8JH3ldduwsZoxzamSCHxmuW3mX1APFykKwBdVMM5jDzUbXzePSYJzJ62FpFz8FP9JtOKgyIcsT2DvPt4hKtx3XeFag2pWAig8sidjwTL4rKIKUEodoA4odMWZdiDUiZnZSvDXhPWD5Uwb00a81g==",
"name": "LAPTOP-WV",
"version": "3.6.1",
"timezone_offset": "+02:00"
}
]
}
- Channels packet
{
"code": 0,
"msg": "Success",
"result": [
{
"id": "41490aeb-cda2-4710-9802-1b6c424747c1_0000442C",
"location_id": 6418,
"name": "G/House- Ground Floor Main Entrance",
"active": 1,
"paid": 0
},
{
"id": "d3a086e1-81bc-4a43-8175-32569dc1b337_0000442C",
"location_id": 6418,
"name": "G/Mews- Reception",
"active": 1,
"paid": 0
},
{
"id": "1d92704e-8d49-432a-8293-04d5d6bcda81_0000442C",
"location_id": 5567,
"name": "Manual device 30",
"active": 1,
"paid": 0
}
]
}
- Triggers packet
{
"code": 0,
"msg": "Success",
"result": [
{
"id": "0e7b1f2c-6c41-426f-b92f-0d2e98bbe119_0000442C",
"location_id": 6418,
"channel_id": "d3a086e1-81bc-4a43-8175-32569dc1b337_0000442C",
"name": "Exit",
"type": "Line",
"active": 1
},
{
"id": "551a98fb-0b59-407d-8e8a-bd4f7f87f9b5_0000442C",
"location_id": 6418,
"channel_id": "d3a086e1-81bc-4a43-8175-32569dc1b337_0000442C",
"name": "Enter",
"type": "Line",
"active": 1
},
{
"id": "d38cd09b-e756-4815-8834-fdb41754e740_0000442C",
"location_id": 6418,
"channel_id": "41490aeb-cda2-4710-9802-1b6c424747c1_0000442C",
"name": "Enter",
"type": "Line",
"active": 1
}
]
}
The webhook events we receive has the following structure:
[
{
"record_id" : 1635343534,
"event_type" : "TripwireCrossed",
"snapshot_id" : -235343534,
"trigger_id" : "0e7b1f2c-6c41-426f-b92f-0d2e98bbe119_0000442C",
"origin" : "Pedestrian",
"suborigin" : "Unknown",
"age_range" : "",
"gender" : "",
"id" : 34454545,
"channel_id" : "41490aeb-cda2-4710-9802-1b6c424747c1_0000442C",
"object_id" : 6,
"location_id" : 6418,
"event_time" : ""
},
{
"record_id" : 1635343534,
"event_type" : "TripwireCrossed",
"snapshot_id" : -235343534,
"trigger_id" : "551a98fb-0b59-407d-8e8a-bd4f7f87f9b5_0000442C",
"origin" : "Pedestrian",
"suborigin" : "",
"age_range" : "26 - 35",
"gender" : "Male",
"id" : 34454545,
"channel_id" : "41490aeb-cda2-4710-9802-1b6c424747c1_0000442C",
"object_id" : 6,
"location_id" : 6418,
"event_time" : ""
}
]
To interact with the REST API you have to generate an API key on your Camlytics profile and add the public and private key to the DeviceOptions.
Integration Plans
Design Specifications
This driver exposes a POST HTTP endpoint, which can be used to configure the Camlytics service, to POST data for events, to the driver. The driver also runs a daily refresh on data for locations, channels and triggers, which have been configured on Camlytics. This data is used to ensure the publish routing key used to push data to Commander, it is user friendly and does not have multiple ids.
Here is a run down of the drivers device configuration.
Device configuration options
{
"Devices": {
"Device1": {
"Enabled": true,
"DeviceType": "ScheduledReceptorCamlytics",
"Debug": true,
"GatewayId": "CAMLYTICS",
"ActionDelay": "120000",
"EventTypeFilter": [ "TripwireCrossed" ],
"EventOriginFilter": [ "Pedestrian" ],
"RequestLocationEndpoint": "/service/api/v1/locations",
"RequestChannelEndpoint": "/service/api/v1/channels",
"RequestTriggerEndpoint": "/service/api/v1/triggers",
"CamlyticsBaseUrl": "https://cloud.camlytics.com",
"PublicKey": "PUBLIC KEY HERE",
"PrivateKey": "PRIVATE KEY HERE",
"OverrideLocationName": true,
"LocationNameLookup": {
"5567": "Testing",
"6418": "ManhattanStores"
},
"OverrideChannelName": true,
"ChannelNameLookup": {
"41490aeb-cda2-4710-9802-1b6c424747c1_0000442C": "Lobby"
},
"OverrideTriggerName": true,
"ProcessMaxDegreeOfParallelism": {
"0e7b1f2c-6c41-426f-b92f-0d2e98bbe119_0000442C": "Enter",
"551a98fb-0b59-407d-8e8a-bd4f7f87f9b5_0000442C": "Exit"
},
"ProcessMaxDegreeOfParallelism": 1000,
"BoundedCapacity": 5000,
"DailyCountResetTime": "22:00:00"
}
}
}
Device configuration definitions
Property | Description | Type | Defaults |
---|---|---|---|
Device1 | The device name for this device. This has to be specified. | string | - |
Enabled | Gets or sets whether this device is enabled. | bool | false???? |
DeviceType | Gets or sets the type of this device. To use the Camlytics device, this has to be ‘ScheduledReceptorCamlytics’. Otherwise if defining a default device, it must be ‘DefaultProperties’. | string | - |
Debug | Gets or sets whether debug information is written to console/log file for this specific device. | bool | false??? |
GatewayId | Gets or sets the gateway identifier. | string | Leave this blank or null to use to the collector’s service identifier. Default is: CAMLYTICS |
ActionDelay | Specifies how frequently, in milliseconds, the device should check if it should reset the event counts and update the data that it retrieves from Camlytics. | int | - |
EventTypeFilter | Indicates the types of events the device should filter for. | string array | TripwireCrossed |
EventOriginFilter | Indicates the types of event origins the device should filter for. | string array | Pedestrian |
RequestLocationEndpoint | The url that is used to get all locations from Camlytics. | string | /service/api/v1/locations - This value should not normally have to change |
RequestChannelEndpoint | The url that is used to get all channels from Camlytics. | string | /service/api/v1/channels - This value should not normally have to change |
RequestTriggerEndpoint | The url that is used to get all triggers from Camlytics. | string | /service/api/v1/triggers - This value should not normally have to change |
CamlyticsBaseUrl | The url that is used to get all channels from Camlytics. | string | “https://cloud.camlytics.com” - This value should not normally have to change |
PublicKey | Public API key for the Camlytics API in order to retrieve location/channel/trigger data. | string | None - Request from Camlytics |
PrivateKey | Private API key for the Camlytics API in order to retrieve location/channel/trigger data. | string | None - Request from Camlytics |
OverrideLocationName | Flag indicating if location names should be overridden with pre-defined values. | bool | false |
LocationNameLookup | A dictionary containing the ids of locations and the names those locations should be overridden with. | dictionary with string key and string value | - |
OverrideChannelName | Flag indicating if channel names should be overridden with pre-defined values. | bool | false |
ChannelNameLookup | A dictionary containing the ids of channels and the names those channels should be overridden with. | dictionary with string key and string value | - |
OverrideTriggerName | Flag indicating if trigger names should be overridden with pre-defined values. | bool | false |
TriggerNameLookup | A dictionary containing the ids of triggers and the names those triggers should be overridden with. | dictionary with string key and string value | - |
ProcessMaxDegreeOfParallelism | Maximum number of messages that can be processed by the block. Must be >= 0. | int | 500 |
BoundedCapacity | Maximum number of messaged that can be buffered by the block. Must be >= 0. | int | 500 |
DailyCountResetTime | The time of day (UTC) that the device should reset its event counters and request new data for locations/channels/triggers from Camlytics. | Timespan | 22:00:00 |
Usage
Steps on how to deploy and configure the driver
The link below demonstrates the steps to follow when a user deploys and configures a V-Raptor driver:
Deployment Manager Application
Device Configuration Example and Walkthrough
Here is an example config, with a walkthrough below it.
{
"Devices": {
"WalkthroughDevice": {
"Enabled": true,
"DeviceType": "ScheduledReceptorCamlytics",
"Debug": true,
"GroupName": "CAMLYTICS",
"ActionDelay": 120000,
"EventTypeFilter": [ "TripwireCrossed" ],
"EventOriginFilter": [ "Pedestrian" ],
"PublicKey": "PUBLIC KEY HERE",
"PrivateKey": "PRIVATE KEY HERE",
"OverrideLocationName": true,
"LocationNameLookup": {
"5567": "Testing",
"6418": "ManhattanStores"
},
"OverrideChannelName": true,
"ChannelNameLookup": {
"41490aeb-cda2-4710-9802-1b6c424747c1_0000442C": "Lobby"
},
"OverrideTriggerName": true,
"TriggerNameLookup": {
"0e7b1f2c-6c41-426f-b92f-0d2e98bbe119_0000442C": "Enter",
"551a98fb-0b59-407d-8e8a-bd4f7f87f9b5_0000442C": "Exit"
},
"DailyCountResetTime": "20:00:00"
}
}
}
- Lets start by creating a new device called ‘WalkthroughDevice’.
- We want to implement the Camlytics device, so tell it that the device called ‘WalkthroughDevice’ is of type ‘ScheduledReceptorCamlytics’.
- We want this device to be enabled, so we set ‘enabled’ to true.
- We set the GroupName to ‘CAMLYTICS’.
- We set the action delay to 2 minutes.
- Next we configure the EventTypeFilter. In this case we only want to pass TripwireCrossed events to Commander.
- We configure the EventOriginFilter. In this case we only want to pass Pedestrian events to Commander.
- The next part involves specifying the public and private keys used to communicate with Camlytics.
- We set OverrideLocationName to true, meaning the mapping specified in LocationNameLookup will be applied. The mapping contains the LocationId along with the name we want to use for that location.
- We set OverrideChannelName to true, meaning the mapping specified in ChannelNameLookup will be applied. The mapping contains the ChannelId along with the name we want to use for that location.
- We set OverrideTriggerName to true, meaning the mapping specified in TriggerNameLookup will be applied. The mapping contains the TriggerId along with the name we want to use for that location.
- DailyCountResetTime is set to 20:00 UTC time. This means that the counters will be reset at this time.
Available Commander Endpoints
Standard Gateway Path: LocationName-ChannelName.CAMLYTICS:Origin|TriggerName.EventType-Value
Important note: The LocationName-ChannelName section removed spaces and underscores.
Example: ManhattanStores-Lobby.CAMLYTICS:Pedestrian|Enter.TripwireCrossed-Value
- Event Category Endpoints
The routing keys for the event category packets sent by Camlytics are constructed as follows:
var gatewayId = $"{locationName}-{channelName}";
deviceInfo.DeviceName = triggerName.Replace(" ", string.Empty).Replace("_", string.Empty);
deviceInfo.DeviceType = eventItem.Origin;
deviceInfo.GatewayId = gatewayId.Replace(" ", string.Empty).Replace("_", string.Empty);
deviceInfo.GroupName = Options.GroupName.Replace(" ", string.Empty).Replace("_", string.Empty);
And the available properties are constructed as follows:
var propToAdd = new List<IDevicePropertyObject>();
propToAdd.Add(CreateProperty<int>(EventType));
propToAdd.Add(CreateProperty<DateTime>("EventTime"));
Meaning these are the 2 properties to be sent:
Count | Property Name | Data Type | Comment |
---|---|---|---|
1 | EventType | int | EventType is the actual EventType, such as TripwireCrossed, while the value is the total count for that event. |
2 | EventTime | DateTime | The time the event was logged by Camlytics. |
External References
Release Notes
Version | Description | Release Date |
---|---|---|
4.0.49.1-alpha-2306081701 | Initial version of the driver | 2023-06-09 (QA approval pending) |