Live Communications
Pegasus supports live communications via web-sockets.
Web sockets allow you to subscribe to a variety of events generated from pegasus. As a developer you can catch these events, and bring some life to your applications.
Pegasus Live communications ease programming by pushing the events to you, the developer, removing the need for periodic requests.
All live communications are handled by the server found in your site's api response under live_url
.
You can go use that site to find a demo on how it's used, once loaded use the JS console to see the payload of the devices.
The supported socket-io.client library is v2.5.0
Note that polling is disabled on the server, you must use websocket
as a transport to succesfully connect.
Note that we enforce an IP ban for clients that repeatedly get a 400; to avoid this use the
websocket
transport
Requirements
Pegasus' Live communications uses socket.io as its backbone. We highly recommend you take a look at their website to get a deeper understanding of how websockets work, as well as their implementation.
socket.io
In order to use the live functionality on your application. You need to download and run then socket.io client.
Get the socket client
Emits
The live server emits some basic data, simply register some callbacks to the following handlers
socket.on('...', function(data){...})
Handler | Description |
---|---|
_authenticated | Authentication successful, sent when the live server has validaded your token with your gateway's API. Includes output of resources handler. |
_error | Generic error message. Authentication not successful, missing permissinos, etc. |
_update | Generic update message. ex. 'Listening to ...', or 'Stopped listenting to ...', etc. |
resources | Returns the resources you are allowed to register to. (vehicle ids, for vehicle events, triggers, etc.) |
events | Primary events entry point. All events you have registered to will come in through here. |
You can also emit some messages, with data to the live server as soon as you connect.
Handler | Description |
---|---|
authenticate | Send source and auth token to inititate authentication with live server. |
resources | Request resources that are available to you. |
listen | subscribe to some or all entities for a given namespace |
stop | unsubscribe to some or all entities in a given namespace |
Namespaces
All events generated by the Pegasus Gateway fall into namespaces.
By understanding the namespaces in use, you can further tune your application to only the events you need. This allows for more specialized programming.
Currently the gateway manages the following Namespaces:
Namespace | Description |
---|---|
jobs | Job related events (running, error, finished, etc) |
triggers | Trigger fired, trigger disabled, etc. |
vehicle-events | events generated by the devices. |
vehicle-nstat* | deprecated on 1.9 changes in vehicle connectivity: ONLINE/OFFLINE state |
Creating a socket
// Initialize the socket
// you must use websocket as the transport, polling (default) is disabled
var socket = io('https://aws-live-0.pegasusgateway.com/socket', {transports: ['websocket']})
Once you have the socket.io client loaded, lets make a fresh socket by initializing it.
Authenticating
// Set up basic handlers
socket.on('_authenticated', function(data){
// this will fire when we are succesfully authenticated.
// 'data' is equal to the output of /api/user/resources
console.log(data)
})
socket.on('_error', function(message){
console.error(message)
})
socket.on('_update', function(message){
console.info(message)
})
socket.on('resources', function(resources){
console.log(resources)
})
socket.on('events', function(envelope){
console.log(envelope)
namespace = envelope.namespace
vehicle = envelope.object
events = envelope.payload
})
var credentials = {
pegasus: "https://cloud.pegasusgateway.com", // replace with your gateway.
auth : "aebf772e8aa25491ed273c699baf4d35aa5c4c0342cd7b51606bbf8c" // Retrieve the token by logging via /api/login
}
socket.emit("authenticate", credentials)
The first step in receiving events live from your Pegasus Gateway, is getting authenticated.
On successful authentication you'll be returned with the api/user response.
Now that you're authenticated you can subscribe to namespaces.
Listening
...
var envelope = {
"namespace":"vehicle-events",
"objects": 617, // [197,297] or "all"
}
socket.emit("listen", envelope)
In order to start listening to events, you must send an envelope via the listen
message to the live server.
the evenlope must have the following properties.
- namespace : Then namespace you are subscribing to (eg "vehicle-events")
- objects : id or list of ids that you are subscribing to. You may also pass "all" to subscribe to all entities you have access to.
Check the console for any error or info messages reporting the status of the operation. Remember that these were handled via the _error
and _update
callbacks.
If everything checks out you will start receiving envelopes from the vehicle-events
namespace via the events
message.
socket.on('events', function(envelope){ ... })
The envelope will contain the following properties :
object
: the object the events belong to.payload
: event or eventsnamespace
: namespace the events belong to.
Compact events
You may have noticed that each payload received by the event handler contains a lot of duplicated data. This may be too much overhead for some applications. Some applications want to monitor only the changes on some fields, and act accordingly.
The webSockets interface supports compacted payloads which will significantly reduce the bandwidth of your application. It is important that you support these as soon as possible within your application as this will be enforced at a later date for all webSocket Subscriptions.
In order to enable compaction you first need to load some utilities into your application.
You can copy the snippet below.
// Utils and libraries
import _mergeWith from 'lodash.mergewith'
const ws_merger = (objValue, srcValue, key, object, source, stack) => {
if (Array.isArray(objValue) && Array.isArray(srcValue)) return srcValue;
return undefined;
};
const __cache = {}
// receive cached payload, update with compressed update, and return full event
const digest_ws_event = (update) => {
const cached = __cache[update.primary_id] || {}
__cache[update.primary_id] = _mergeWith(cached, update, ws_merger)
const live_update = __cache[update.primary_id]
let { updates, event, _event_restore } = update
if (updates.includes('event')) {
const { event: cevent } = live_update
live_update.event = event
_event_restore ??= []
_event_restore.map((k) => {
live_update.event[k] = cevent[k] || cached.device.latest.data?.[k]?.value
})
return live_update
}
}
// event callback
const process_event = (update) => {
const payload = digest_ws_event(update.payload)
// application code
}
// cache callback
const cache_callback = (events) => events.map(process_event)
// attach function to events handler
socket.on('events', (event) => {
process_event(event)
})
We are creating a util that will cache the initial full payload, and then our merge function will apply the compacted updates, and send the event down to your application.
You then need to enable the compact
flag on the subscription
const envelope = {
"namespace":"vehicle-events",
"objects": 617, // [197,297] or "all" *
"compact": true
}
socket.emit("listen", envelope, cache_callback)
** subscribing to 'all'
Using objects: 'all'
with a cache_callback
function in the subscription envelope could result in a high amount of data being serialized and sent.
You may receive some messages on the _error
callback that represent the quotas being violated.
There is a limit of 250 entities per subscription that use the cache.
If you need to subscribe to multiple vehicles it is recommended you chunk/paginate your listen
requests.
You can use the ids provided via the resources
callback
import _chunk from 'lodash.chunk'
const $sleep = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms))
socket.on('resources', async function(resources){
// resources.vehicles and resources.assets represent all ids that you can subscribe to
for (const resource of ['vehicles', 'assets']) {
for (const chunk of _chunk(resources[resource], 100)) {
const envelope = {
"namespace":"vehicle-events",
"objects": chunk,
"compact": true
}
socket.emit('listen', envelope, cache_callback)
await $sleep(50) // recommended
}
}
})
Payload
The payload varies according to namespace.
vehicle-events
Received whenever a vehicle sends a tracking event.
The payload has a lot of keys, but the most important/relevant ones are:
device
- contains information about the device, like connection/network status, trip info, state of the Inputs/Outputs
event
- contains the values of the event keys reported
primary
- info on the primary object/entity (vehicle, asset, etc)
secondary
- info on the secondary object/entity (asset, bluetooth tag, etc)
updates
- tells you what key updated (the event, or device, or both)
As mentioned above the primary and secondary keys correspond to the vehicle or asset that reported the value.
For example, when a driver (an asset) is identified via an iButton with the vehicle, the primary would be the vehicle, and secondary would be the asset.
When the secondary_id
is null it means that the secondary
info shows the last active info.
In other words, if the secondary_id
shows a value it means the secondary
is current, if there's no value in secondary_id
the secondary
is the last known.
So this would be useful for knowing if a vehicle currently has an asset assigned, if so, which one, and if not, which was the last asset assigned.
The payload keys and values are the same as the one's you will expect when consulting via Rawdata
Please note that the same payload may be received twice, what you have to keep track of is the updates
key, because it will tell you if it's a device
update such as a connection state change (from online to offline for example) or an event
update, which means that a new event came in.
On your applications you'll want to show only when a new event
came in, and handle the connection states when the device
key is received.
Payload
Payload for vehicle-events
{
"$$hashKey": "object:1229",
"category": "vehicle",
"device": {"ios_state": {…}, "gpsknit": {…}, "network": {…}, "lastrx": {…}, "trip_setup": {…}, …},
"event": {"code": 12, "gpsknit_prev_lat": 3257884, "sv": 8, "dev_dist__mi": 3899, "event_time": 1504909832, …},
"pid": 1,
"primary": {"info": {…}, "associations": Array(3), "__updated": 1504110100.755031, "name": "Syrus 3 SIENNA", "trackers": Array(0), …},
"primary_id": 686,
"secondary_id": null,
"type": "events",
"updates": ["device"],
"_pkey": "pka.05",
"_site_url": "https://cloud.pegasusgateway.com",
"_source": "pcore.listener",
"_source_epoch": 1504910674.863004,
"_ver_core": "1.9.0-rc1",
"_ver_pcel": "2.1.1-r2"
}
Key | Description |
---|---|
category | event category (vehicle) |
device | information on the device |
event | event information reported by device |
pegasus_id | unique ID for the pegasus site |
pid | unique ID to the pegasus site |
primary | primary entity |
primary_id | primary entity id |
pseq | internal use |
route_state | state of the route |
secondary | secondary entity |
secondary_id | secondary entity id |
site_id | unique ID for the pegasus site |
type | type of payload |
updates | keys that are updated on this payload |
_pkey | internal use |
_site_url | pegasus site URL |
_source | internal use |
_source_epoch | internal use |
_ver_core | internal use |
_ver_pcel | internal use |
$$hashKey | internal use |
Detailed payload description
DEVICE
accel_state
Acceleration state
Key | Description |
---|---|
ap_cur_deg_x | current degrees x plane |
ap_cur_deg_y | current degrees y plane |
ap_cur_deg_z | current degrees z plane |
ap_cur_mag | current magnitude (vector force in the direction it's moving) |
ap_mov | true if moving |
ap_ref_deg_x | reference or configured x plane value at the time of calibration |
ap_ref_deg_y | reference or configured y plane value at the time of calibration |
ap_ref_deg_z | reference or configured z plane value at the time of calibration |
asset
asset information
Key | Description
----|------------
aid | asset id
aid_source | source of the asset, ib
for ibutton, btt
for bluetooth tag, fp
for fingerprint, rfid
for RFID
btt_mac | bluetooth tag mac address
bttag | bluetooth tag associated info
bttag.asset_id | bluetooth tag asset id
bttag.created_at | bluetooth tag date of creation
bttag.edited_at | bluetooth tag date of edition
bttag.mac | bluetooth tag mac address
bttag.short_code | bluetooth tag short code
ib | ibutton HEX ID
last_aid_source | the last asset id source
rfi_full_id | rfid
config
configuration description
Key | Description |
---|---|
devconfig_id | unique id for the device's configuration |
ky | unique key for managed configurations |
kydef | configuration definition data (includes information about support for accessories and names of inputs/outputs) |
kymissmatch | only present if the device is sending a ky different then the one configured on pegasus |
kymod | last configuration modification time |
pending | true if there's a configuration pending to be set |
pending_count | number of commands pending to be sent to the device from the new configuration |
safeimmo_support | true if it's using managed configuration and it supports safe_immobilization on output 1 |
total_count | total number of commands pending to be sent |
values | configuration values such as the speedlimit and rpm limit, among others. |
_config_state | 1 if pending, 3 if synchronized |
_epoch | time of the last config modification |
connection
connection state / information
Key | Description |
---|---|
last | last connection information |
off_codes | codes for reasons why it went offline |
on_codes | codes for reasons why it came back online |
online | true if device is online |
_epoch | epoch timestamp of last connection change |
dcounters
device counters
for a detailed description you can check the counters description
gpsknit
gps information
Key | Description |
---|---|
ack_id | internal use |
event_time__epoch | epoch timestamp of the event time |
lat | latitude |
lon | longitude |
no_gps_time_count | time in seconds with no gps coordinates |
no_location_count | number of consecutive events with no gps |
no_location_fepoch | no location epoch timestamp |
prev_ack_id | internal use |
prev_event_time__epoch | previous event epoch timestamp |
prev_lat | previous latitude |
prev_lon | previous longitude |
_epoch | epoch timestamp |
imei
IMEI is the imei of the device
ios_state
state of the inputs and outputs
for a detailed description you can check the master field list
lastrx
last communication time
Key | Description |
---|---|
msg_type | type of message |
value | timestamp it reported that message type |
_epoch | timestamp it was received |
latest
latest data reported by the device
lcounts
Listener counts, more information coming soon
legacy_set_out_state
current state of the outputs, useful for knowing if output is pending to be set/reset
Key | Description |
---|---|
io_out[index] | outputs 1-2 on device |
io_exp_out[index] | io expander output 1-4 |
cid | command id |
instruction | current instruction |
set_at | epoch time it was set at |
uid | user id that set it |
lrates
Listener rates, more information coming soon
muted_evs:
Muted or silenced events on the device information
net_reg
Network registration information
Key | Description |
---|---|
cf_cid | Cell ID |
cf_lac | Location Area Code |
cf_mcc | MCC |
cf_mnc | MNC |
cf_rssi | RSSI |
cf_type | Registration type (2g, 3g, lte, etc) |
_epoch | Network information last update epoch |
network
network information from device
Key | Description
----|-------------
cnum | carrier sim phone number (doesn't always reflect the number of the sim card due to restrictions from some carriers)
imsi | sim imsi
op | operator
sim | sim id
_epoch | epoch timestamp
outbox
Array with the commands pending to be sent to the device
Key | Description |
---|---|
ctype | Command type |
id | Command ID |
msg | Message to be sent to the device |
time | Time message was placed on queue |
uid | User ID that sent the message |
useky | Internal use |
photos
state of the cameras connected to the device
Key | Description |
---|---|
cams | object with each camera's event id |
evid | event id for photo captured |
ncams | number of cameras connected to device |
_epoch | timestamp the data was reported |
position_response
Information about the latest response to a position message while the device was offline.
satcom
Last satcom related information
safeimmo_state
current state of the safe immobilization
Key | Description |
---|---|
cid | command id |
instruction | current instruction |
set_at | epoch time it was set at |
uid | user id that set it |
_epoch | timestamp |
set_out_state
Output activation information, whether or not an instruction is pending to be sent to manipulate an output
sigfox
Last sigfox related information
sim
SIM card related information including iccid, imsi, operator, and more.
trip
device trip information
Key | Description |
---|---|
aid | asset id associated to trip |
dev_msgs | internal use |
groups | id of the groups the vehicle belongs to during trip |
id | trip id |
ky | device configuration |
method | trip's method (gps) |
moving | true if vehicle is currently on a trip, false means parked |
signal | internal use |
src_id | internal use |
src_type | internal use |
start_evdistance | distance traveled at the start of trip |
start_lat | start latitude |
start_lon | start longitude |
start_time_epoch | event time at start of trip |
system_time_epoch | system time at start of trip |
vid | vehicle id |
_epoch | epoch timestamp |
trip_session
device trip session information
Key | Description |
---|---|
closing_data | data that closes the trip |
first_event | opening event of trip |
latest_event | latest event |
max_speed | max speed in mph |
max_speed_hdop | max speed in hdop (value must be divided by 100) |
max_speed_lat | max speed location latitude |
max_speed_lon | max speed location longitude |
max_speed_time | epoch timestamp of max speed |
opened_at | time the trip session was opened |
__persistent | internal use |
__version | internal use |
_epoch | epoch timestamp of trip_session |
trip_setup
Key | Description |
---|---|
method | how the trip is formed (whether with tracker or gps events) |
state | raw trip message setup from Syrus, for more info check XATT on syrus manual |
_epoch | epoch timestamp |
vcounters
user editable vehicle counters, for more information go to counters
vehicle
vehicle information
version
Key | Description |
---|---|
device | device model |
extras | firmware extra information |
msg | device message |
number | version firmware number |
virtual_distance
virtual distance calculated via lat lon deltas
Key | Description |
---|---|
evtime_epoch | time the event was generated |
lat | latitude |
lon | longitude |
value | distance for device |
_epoch |
virtual_ignition
virtual ignition calculated based on the status of the io_ign
Key | Description |
---|---|
delta_dist | Delta total distance traveled |
event_time | Event time of last io_ign |
idle_buffer | Idle buffer |
idle_counter | Idle time in seconds |
ign_counter | Ignition time in seconds |
io_idle | Idle state |
io_ign | Ignition state |
vid | Vehicle ID |
_epoch | Time of last virtual_ignition change |
event
list of event parameters reported by device, check out master field list for more info
vehicle-nstat *
Deprecated on 1.9 Received whenever a vehicle changes its ONLINE/OFFLINE status.
As of version 1.9 the vehicle-nstat was changed into the vehicle-events payload under device -> connectionPayload keys:
imei
: (number) Device IMEIvid
: (number) Associated vehicle IDonline
: (boolean) Connectivity status
You may receive other keys, they exist for testing, they may not exist on future releases.
Stopping
...
var envelope2 = {
"namespace":"vehicle-events",
"objects": "all", // [197,297] or 617
}
socket.emit("stop", envelope2)
In order to stop receiving events from some objects in a certain namespace, you simply send an envelope identical to the one used for subscribing via the stop
message
FAQ
Device Network State
The device network state can be found under device.connection.online
, true whenever the device is ONLINE.
Valid Position
There are 3 keys that can be used to find out whether the position of the event is valid, they're all essentially the same:
device.data.valid_gps
also in the event's keys: event.valid_gps
device.data.valid_position
also in the event's keys: event.valid_position
device.latest.loc.valid
Authentication Errors
Try updating the socket.io client to version 2.0.3 or higher.
Updated 3 months ago