SignalR subscription and event reference
The Quix SignalR hub provides the subscriptions and events. You subscribe to channels of interest, and then you can write code that handles events on that channel if and when they occur.
Subscribe
You can subscribe to the following hub methods using the invoke
method of a HubConnection
:
Hub method (C#) | Description | Invocation code (JavaScript) |
---|---|---|
SubscribeToParameter(topicName, streamId, parameterId) |
Subscribe to a parameter data stream | connection.invoke("SubscribeToParameter", "your-topic-name", "your-stream-id", "your-parameter-id"); |
SubscribeToEvent(topicName, streamId, eventId) |
Subscribes to an event data stream | connection.invoke("SubscribeToEvent", "your-topic-name", "your-stream-id", "your-parameter-id"); |
IList<ActiveStream> SubscribeToActiveStreams(topicName) |
Subscribe to Active Streams List changes. The subscription method returns an initial list of the active streams existing in the topic | connection.invoke("SubscribeToActiveStreams", "your-topic-name"); |
IList<TopicMetrics> SubscribeToTopicMetrics(topicName) |
Subscribe to Topic metrics updates. The subscription method returns an initial list of the last 5 minutes of topic metrics | connection.invoke("SubscribeToTopicMetrics", "your-topic-name"); |
SubscribeToPackages(string topicName) |
Subscribe to Topic packages. A package is an abstraction for any message received in the topic | connection.invoke("SubscribeToTopicPackages", "your-topic-name"); |
Tip
When subscribing, you can use the wildcard *
for topics, streams, and parameters.
Unsubscribe
Each Subscribe method has its own Unsubscribe
method. Use them to avoid receiving data unnecessarily. The Unsubscribe
methods are detailed in the following table:
Method | Description |
---|---|
UnsubscribeFromParameter(topicName, streamId, parameterId) |
Unsubscribe from a parameter data stream |
UnsubscribeFromEvent(topicName, streamId, eventId) |
Unsubscribe from an event data stream |
UnsubscribeFromActiveStreams(string topicName) |
Unsubscribe from Streams List changes |
UnsubscribeFromTopicMetrics(topicName) |
Unsubscribe from Topic metrics updates |
UnsubscribeFromPackages(string topicName) |
Unsubscribe from Topic packages |
UnsubscribeFromStream(topicName, streamId) |
Unsubscribes from all subscriptions of the specified stream |
SignalR events
You can register a handler for SignalR events using the JavaScript on
method of a HubConnection
.
The following events are available:
-
ParameterDataReceived(parameterData)
-
EventDataReceived(eventData)
-
ActiveStreamsChanged(stream, action)
-
TopicMetricsUpdated(metrics)
-
PackageReceived(package)
Pass the event’s name as the first argument to the on
method, followed by a callback function. For example, to react to the ParameterDataReceived
event, use the following:
Each of the previously listed methods are described in the following sections.
ParameterDataReceived
Add a listener to ParameterDataReceived
event to receive parameter data from a SubscribeToParameter
subscription.
One event is generated each time a `ParameterData`` package is received in the topic and the data contains the parameter the user has subscribed to.
A more complete example is shown here:
var signalR = require("@microsoft/signalr");
const options = {
accessTokenFactory: () => '<your-PAT>'
};
const connection = new signalR.HubConnectionBuilder()
.withUrl("https://reader-joeengland-apitests-testing.platform.quix.io/hub", options)
.build();
// Establish connection
connection.start().then(() => {
console.log("Connected to Quix.");
// Subscribe to parameter data stream
connection.invoke("SubscribeToParameter", "f1-data", "*", "EngineRPM");
// Read parameter data from the stream
connection.on("ParameterDataReceived", data => {
console.log('topicId ', data.topicId);
console.log('streamId ', data.streamId);
console.log('streamId ', data.numericValues.EngineRPM);
// Unsubscribe from stream
connection.invoke("UnsubscribeFromParameter", "f1-data", "*", "EngineRPM");
});
});
Example payload:
{
topicId: 'joeengland-apitests-testing-f1-data',
topicName: 'f1-data',
streamId: '020aee7e-edba-4913-aee3-b1e493c78132',
epoch: 0,
timestamps: [ 1697025689418406000, 1697025689487857000 ],
numericValues: { EngineRPM: [ 11444, 11463 ] },
stringValues: {},
tagValues: {
DriverStatus: [ 'Flying_lap', 'Flying_lap' ],
LapNumber: [ '2', '2' ],
LapValidity: [ 'Valid', 'Valid' ],
PitStatus: [ 'None', 'None' ],
Sector: [ '0', '0' ],
streamId: [
'5a517ca4-efc3-4166-aedb-a5c57e2b9c59',
'5a517ca4-efc3-4166-aedb-a5c57e2b9c59'
]
},
binaryValues: {}
}
EventDataReceived
Add a listener to EventDataReceived
event to receive data from a SubscribeToEvent
subscription.
One event is generated each time a EventData package is received in the topic and the data contains the event the user has subscribed for.
A more complete example is shown here:
var signalR = require("@microsoft/signalr");
const options = {
accessTokenFactory: () => '<your-PAT>'
};
const connection = new signalR.HubConnectionBuilder()
.withUrl("https://reader-joeengland-apitests-testing.platform.quix.io/hub", options)
.build();
// Establish connection
connection.start().then(() => {
console.log("Connected to Quix.");
// Subscribe to event data stream
connection.invoke("SubscribeToEvent", "topic-1", "*", "EventA");
// Read event data from the stream
connection.on("EventDataReceived", data => {
console.log('data --> ', data);
// Unsubscribe from stream
connection.invoke("UnsubscribeFromEvent", "topic-1", "*", "EventA");
});
});
Example payload:
{
topicName: 'topic-1',
streamId: 'b45969d2-4624-4ab7-9779-c8f90ce79420'
id: 'EventA',
timestamp: 1591733990000000000,
value: 'val-a',
tags: {
tag1: 'val1'
}
}
ActiveStreamsChanged
This event is generated each time a change has been produced in the list of active streams in a topic.
Add a listener to ActiveStreamsChanged
event to receive data from a SubscribeToActiveStreams
subscription. This SignalR event returns two callback parameters:
Callback Parameter | Description |
---|---|
stream |
Payload of the stream that has been changed |
action |
It describes the type of operation has been applied to the list of active streams. Two actions are possible: AddUpdate : Stream added or updated. Remove : Stream has been removed. |
Example code:
var signalR = require("@microsoft/signalr");
const options = {
accessTokenFactory: () => '<your-PAT>'
};
const connection = new signalR.HubConnectionBuilder()
.withUrl("https://reader-joeengland-apitests-testing.platform.quix.io/hub", options)
.build();
// Establish connection
connection.start().then(() => {
console.log("Connected to Quix.");
connection.invoke("SubscribeToActiveStreams", "f1-data");
connection.on("ActiveStreamsChanged", (stream, action) => {
console.log('stream -----> ', stream);
console.log('action -----> ', action);
});
});
Might produce the following output:
[2023-10-09T15:23:27.993Z] Information: WebSocket connected to wss://reader-joeengland-apitests-testing.platform.quix.io/hub?id=o9Ctg5zdQ7aAzdQ2Cz4eMw.
Connected to Quix.
stream -----> {
streamId: '0a23798f-7d75-413d-9031-8d8386c2f8c7',
topicId: 'joeengland-apitests-testing-f1-data',
topicName: 'f1-data',
metadata: {},
parents: [],
parameters: {
EngineTemp: { dataType: 'Numeric' },
Motion_WorldPositionX: { dataType: 'Numeric' },
Steer: { dataType: 'Numeric' },
Brake: { dataType: 'Numeric' },
EngineRPM: { dataType: 'Numeric' },
Motion_WorldPositionZ: { dataType: 'Numeric' },
TotalLapDistance: { dataType: 'Numeric' },
LapDistance: { dataType: 'Numeric' },
Gear: { dataType: 'Numeric' },
original_timestamp: { dataType: 'Numeric' },
Motion_WorldPositionY: { dataType: 'Numeric' },
Speed: { dataType: 'Numeric' }
},
events: {},
firstSeen: '2023-10-09T15:23:29.7197985Z',
lastSeen: '2023-10-09T15:23:29.7198602Z',
status: 'Receiving',
lastData: '2023-10-09T15:23:29.7198603Z'
}
action -----> AddUpdate
Another stream payload example, showing more metadata:
{
"streamId": "5ecfc7ce-906c-4d3a-811c-a85ea75a24b3",
"topicName": "f1-data",
"name": "F1 Game - Swal - Sakhir Short 2022-04-08-09:00:39",
"location": "/Game/Codemasters/F1-2019/Sakhir Short",
"metadata": {
"GameVersion": "1.22",
"PacketFormat": "2019",
"Track": "Sakhir Short",
"SessionId": "237322236454500810",
"Player0_Name": "Swal",
"Player0_Id": "100"
},
"parents": [],
"timeOfRecording": "2022-04-08T09:00:39.3971666Z",
"parameters": {
"EngineRPM": {
"dataType": "Numeric",
"minimumValue": 0,
"maximumValue": 20000,
"location": "/Player/Telemetry/Engine"
},
"LapDistance": {
"dataType": "Numeric",
"unit": "m",
"location": "/Player/Telemetry/Misc"
},
"Brake": {
"description": "Amount of brake applied",
"dataType": "Numeric",
"minimumValue": 0,
"maximumValue": 1,
"location": "/Player/Telemetry/Input"
},
"Throttle": {
"dataType": "Unknown",
"minimumValue": 0,
"maximumValue": 1,
"location": "/Player/Telemetry/Input"
},
"Gear": {
"dataType": "Numeric",
"minimumValue": -1,
"maximumValue": 8,
"location": "/Player/Telemetry/Engine"
},
"Speed": {
"dataType": "Numeric",
"minimumValue": 0,
"maximumValue": 400,
"location": "/Player/Telemetry/Engine"
},
"Steer": {
"dataType": "Numeric",
"minimumValue": -1,
"maximumValue": 1,
"location": "/Player/Telemetry/Input"
},
},
"events": {
"Player_NewLap": {
"name": "Player NewLap",
"level": "Information",
"location": ""
},
"Player_Position_Changed": {
"name": "Player Position Changed",
"level": "Critical",
"location": ""
},
"RaceWinner": {
"name": "Race Winner",
"level": "Critical",
"location": ""
},
},
"firstSeen": "2022-04-08T08:57:40.3406586Z",
"lastSeen": "2022-04-08T09:00:39.6308255Z",
"status": "Receiving",
"lastData": "2022-04-08T09:00:39.6237312Z"
}
TopicMetricsUpdated
This event is generated periodically by the service to provide basic metrics about a Topic, like "Bytes per Second" or "Number of Active Streams".
Add a listener to TopicMetricsUpdated
event to receive data from a SubscribeToTopicMetrics
subscription.
Example code:
var signalR = require("@microsoft/signalr");
const options = {
accessTokenFactory: () => '<your-PAT>'
};
const connection = new signalR.HubConnectionBuilder()
.withUrl("https://reader-joeengland-apitests-testing.platform.quix.io/hub", options)
.build();
// Establish connection
connection.start().then(() => {
console.log("Connected to Quix.");
connection.invoke("SubscribeToTopicMetrics", "f1-data");
connection.on("TopicMetricsUpdated", (metrics) => {
console.log('metrics -----> ', metrics);
});
});
Topic Metrics payload examples:
{
timestamp: '2023-10-11T10:22:14.7787333Z',
topicId: 'joeengland-apitests-testing-f1-data',
topicName: 'f1-data',
bytesPerSecond: 8282,
activeStreams: 1
}
PackageReceived
Add a listener to PackageReceived
event to receive data from a SubscribeToPackages
subscription.
One event is generated each time a package is received in the topic. The package contains:
Parameter | Description |
---|---|
Type | Indicates the Quix client library model used to deserialize the package |
Value | Deserialized package object represented as a JSON string format |
Example code:
var signalR = require("@microsoft/signalr");
const options = {
accessTokenFactory: () => '<your-PAT>'
};
const connection = new signalR.HubConnectionBuilder()
.withUrl("https://reader-joeengland-apitests-testing.platform.quix.io/hub", options)
.build();
// Establish connection
connection.start().then(() => {
console.log("Connected to Quix.");
connection.invoke("SubscribeToPackages", "f1-data");
connection.on("PackageReceived", (package) => {
console.log('package -----> ', package);
});
});
Package payload example:
{
topicId: 'joeengland-apitests-testing-f1-data',
topicName: 'f1-data',
streamId: '020aee7e-edba-4913-aee3-b1e493c78132',
type: 'QuixStreams.Telemetry.Models.TimeseriesDataRaw',
value: '{"Epoch":0,"Timestamps":[1697020374684026880,1697020374737754880],"NumericValues":{"original_timestamp":[1.6871805934271606E+18,1.6871805934782164E+18],"Motion_WorldPositionZ":[-47.103004455566406,-51.53349304199219],"Motion_WorldPositionY":[91.16168212890624,91.1617202758789],"Motion_WorldPositionX":[-386.4772338867188,-386.242431640625],"TotalLapDistance":[7836.7548828125,7841.19189453125],"Steer":[0.0,0.0],"Speed":[312.0,312.0],"LapDistance":[184.69873046875,189.1357421875],"Gear":[8.0,8.0],"EngineTemp":[90.0,90.0],"EngineRPM":[11143.0,11153.0],"Brake":[0.0,0.0]},"StringValues":{},"BinaryValues":{},"TagValues":{"DriverStatus":["Flying_lap","Flying_lap"],"LapNumber":["3","3"],"LapValidity":["Valid","Valid"],"PitStatus":["None","None"],"Sector":["0","0"],"streamId":["5a517ca4-efc3-4166-aedb-a5c57e2b9c59","5a517ca4-efc3-4166-aedb-a5c57e2b9c59"]}}',
dateTime: '2023-10-11T10:32:54'
}