Notifications¶
Notifications are implemented over WebSocket connection.
The standard way of using this feature is
- authentication + getting the WebSocket endpoint
- connection to the endpoint
- subscribing for events
- closing connection
Requesting endpoint¶
For getting WebSocket endpoint you need to call
POST https://the.suite.st/api/public/v4/notifications
Body can be empty. For authentication, only service token can be used.
Response:
{
"url": "wss://example.com/endpoint"
}
The returned url is the temporary endpoint for WebSocket connection. Please note that the url is valid only for a single connection.
Connection¶
Each connection has maximum duration of 24 hours. After that time, connection will be closed with the code 1001 (going away). For keeping the stream of events uninterrupted, it is needed to create an additional connection before expiration of the current one.
During connection, it is allowed to subscribe and unsubscribe to different events as needed. We strongly recommend unsubscribing from events which are not relevant anymore instead of ignoring them.
The total limit of connections is 3 for each organization. If an extra connection will be created it will be closed with the code 1008 (policy violation).
The WebSocket endpoint is also protected by IP whitelisting. If the connection comes from a not allowed IP address it will be refused before a WebSocket connection is established.
Messages¶
All messages are encoded in JSON and sent in text frames. Every subscribe/unsubscribe requested must have request id
parameter rid
of type string. This id is generated by a client, and it will be sent back with the response to the message.
It can be e.g. sequence number starting from 1 and incrementing with every message. We don't require this value to be
unique, but recommend to keep it unique during a single connection.
The notifications itself don't contain rid
identifier.
Responses generally have the following form in case of success:
{
rid: string,
ok: true
}
And the following in case of any errors:
{
rid: string,
ok: false,
errors: Array,
}
Typical errors include incorrectly formatted messages and attempting to subscribe to non-existing assets. Trying to subscribe to non-existing or non-accessible assets is considered as soft error. This means that if an application attempts to subscribe to a set of accessible and non-accessible assets, the subscription to accessible assets will succeed, while non-accessible assets will be reported.
Please note that in case of a major problem in the message format the connection will be closed with code 1002 (protocol error).
Subscribe to device status¶
Request¶
{
rid: string,
type: 'subscribeDeviceStatus',
scope: 'controlUnits'|'devices'|'videoCaptureDevices',
filter: '*'|string[]
}
The filter
contains either a list of ids which should be watched or *
which watches all accessible devices. In case
there is already an existing subscription for given scope adding other devices will extend the filter of existing subscription.
If *
is used, it will overwrite any previous explicit list of devices and everything will be listened to. Due to these
reasons it is not recommended to combine *
and an explicit list for the same scope.
The request initialize watching and the first notification contains the status of all watched devices. The following messages will contain only changes to the previous state.
It can happen that information about some item will be sent repeatedly even there is no change in the value. The receiver of these messages must be able to correctly handle this situation.
The events differ based on scope
:
Control Units¶
{
type: 'deviceStatus',
scope: 'controlUnits',
items: Array<{
id: Uuid,
online: boolean,
}>,
}
Devices¶
{
type: 'deviceStatus',
scope: 'devices',
items: Array<{
id: Uuid,
readyToTest: boolean,
cameraStatus: 'not-assigned'|'disconnected'|'busy'|'ready',
error: boolean,
status?: string,
failedPlatforms: string[],
}>,
}
Properties¶
readyToTest¶
true
if device is ready for testing and there is at least one working platform, false
in case of errors or when the
device is busy (e.g. executing another test).
cameraStatus¶
A test with recording requested will be launched only when status is not-assigned
, ready
or disconnected
.
For disconnected
it will be executed without recording, for busy
it will be delayed until a camera changes
state. ready
can also be shown when camera is streaming or recording.
error¶
true
if there is at least one failed platform or there is another issue (e.g. not connected controller)
status¶
Present only if error is true
. It contains device status returned in device detail feed.
failedPlatforms¶
Contains not working platforms, for verification that you can launch the test immediately, readyToTest
must be true
and the test platform must not be listed in failedPlatforms
Video capture devices (cameras)¶
{
type: 'deviceStatus',
scope: 'videoCaptureDevices',
items: Array<{
id: Uuid,
online: boolean,
batteryState?: {
isCharging: boolean,
batteryLevel: number,
},
needsUpdate?: boolean,
}>,
}
batteryState
is present only for online android cameras. batteryLevel
is percentage from 0 to 100.
needsUpdate
indicates that the android camera app does not meet minimal version requirement (it might be missing some features).
Unsubscribe device status¶
For unsubscribing, it is needed to use the filter
complement to subscribe. When subscribe was called with *
(all devices)
*
must be also used for unsubscribing.
{
rid: string,
type: 'unsubscribeDeviceStatus',
scope: 'controlUnits'|'devices'|'videoCaptureDevices',
filter: '*'|string[],
}
It can happen that shortly after unsubscribing the receiver will get some items which were already unsubscribed. This situation can not be completely prevented and the receiver must handle this situation gracefully.
Subscribe to test pack results¶
{
rid: string,
type: 'subscribeTestPack',
trigger: 'testPackFinished'|'testPackRecordingUploadFinished'|'firstTestFailed'
filter?: 'all'|'onlyFailed'
appVersionId?: string,
testPackId?: number,
}
Parameters¶
trigger¶
firstTestFailed
- is triggered on the first detected failure for each devicetestPackFinished
- is triggered when all tests of the test pack are finishedtestPackRecordingUploadFinished
- is triggered when all recorded videos are stored
filter¶
Filter is effective only for trigger testPackFinished
, for other triggers it is ignored.
all
- is reported for all test packsonlyFailed
- it reports only failed test packs
Default is all
.
appVersionId¶
Optional. Allows filtering by app version.
testPackId¶
Optional. Allows filtering by test pack id.
Incoming events¶
Trigger contains the same value as trigger field for subscribing.
{
type: 'testPack',
trigger: 'testPackFinished'|'testPackRecordingUploadFinished',
testPack: {
testPackId: number,
testPackRunId: string,
appId: string,
versionId: string,
}
}
{
type: 'testPack',
trigger: 'firstTestFailed',
testPack: {
testPackId: number,
testPackRunId: string,
appId: string,
versionId: string,
},
failedTest: {
deviceId: string,
definitionId: string,
}
}
Unsubscribe from test pack results¶
{
rid: string,
type: 'unsubscribeTestPack',
trigger: 'testPackFinished'|'testPackRecordingUploadFinished'|'firstTestFailed'
filter: 'all'|'onlyFailed'
appVersionId?: string,
testPackId?: number,
}
For unsubscribing, it is needed to unsubscribe with the same parameters as for subscribing. Otherwise, the subscription will not be removed.