WebSocket
Subscribe to specific assets and stream incoming data via a native WebSocket connection over WSS.
Prerequisites
Before fetching telemetry via the REST API, ensure you have:
Generated an active API key (see API Key Generation).
Built your local lookup table to obtain the target Asset UUID (
id.id) (see Common API Requests).
Authentication
Although an API Key is the recommended authentication method for the REST API, using the same API Key for the WebSocket connection is currently under development. In the meantime, a JWT authentication process is used.
Token TTL: ~2.5 hours
Refresh strategy: token is refreshed 5 minutes before expiry
Log In
A JWT token is obtained using the login endpoint:
const response = await fetch(`https://iotpro.iotsolutions.com.mt/api/auth/login`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: JSON.stringify({
username: IOTPRO_USERNAME,
password: IOTPRO_PASSWORD
})
}
);The returned JWT is cached and used for subsequent API calls and WebSocket authentication.
Refresh Token
The token is refreshed using this endpoint:
const response = await fetch(`https://iotpro.iotsolutions.com.mt/api/auth/token`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
refreshToken: iotproRefreshToken
})
});Usage
The iotpro-socket-client.js client, available under Resources at the bottom of this page, provides an example WebSocket implementation.
Socket URL: wss://iotpro.iotsolutions.com.mt/api/ws
Creating a Connection
const socketUrl = "wss://iotpro.iotsolutions.com.mt/api/ws";
const ws = new WebSocket(socketUrl);Authentication and Subscription
ws.on("open", () => {
const msg = {
authCmd: {
cmdId: 0,
token: jwt
},
// NOTE commands are created according to the number of assets and PAGE_SIZE
cmds: [
{
cmdId: 1,
type: "ENTITY_DATA",
query: {
entityFilter: {
type: "entityType",
entityType: "ASSET"
},
pageLink: {
pageSize: 1000,
page: 0
},
entityFields: [
{ type: "ENTITY_FIELD", key: "name" }
],
latestValues: []
},
latestCmd: {
keys: [
// NOTE add relevant keys for required asset profiles
{ type: "TIME_SERIES", key: "device_id" },
{ type: "TIME_SERIES", key: "telemetry_param_latitude" },
{ type: "TIME_SERIES", key: "telemetry_param_longitude" }
]
}
}
]
};
ws.send(JSON.stringify(msg));
});Retrieving Latest Values on Connection
The latestValues section can be used to request the latest telemetry values when the WebSocket subscription is created. Initial response contains the full result set in data, as opposed to the update field as described in Incoming Message Handling.
"latestValues": [
{ "type": "TIME_SERIES", "key": "device_id" },
{ "type": "TIME_SERIES", "key": "telemetry_param_latitude" },
{ "type": "TIME_SERIES", "key": "telemetry_param_longitude" }
]By default, this subscribes to all assets. To subscribe only to specific assets or assets of a specific type, replace the entityFilter above. Both filters are paginated according to pageSize, so continue paging if the result exceeds a single page.
Asset UUID list
{
"type": "entityList",
"entityType": "ASSET",
"entityList": [
"90e26dc0-7140-11f1-9149-354d377a0bc8",
"94945230-7140-11f1-9149-354d377a0bc8"
]
}Asset Type
Leave assetNameFilter empty to match all assets of those profiles, or set a name prefix to narrow further.
{
"type": "assetType",
"assetTypes": ["23_IOTPRO-VehicleTracking", "3_IOTPRO-PressureSubmersible"],
"assetNameFilter": ""
}Incoming Message Handling
Incoming WebSocket messages contain telemetry updates for subscribed assets. Each message is associated to a specific subscription via cmdId, which identifies the originating command in the initial WebSocket request.
All incoming messages follow the structure below:
{
"cmdId": 1,
"update": [
{
"entityId": { "id": "..." },
"latest": { "TIME_SERIES": { ... } }
}
]
}cmdId: Identifier of the subscription commandupdate: Array of entity updates returned for the subscriptionentityId.id: Unique asset identifierlatest.TIME_SERIES: Latest telemetry values for the asset
Incoming messages are parsed and mapped to cached asset metadata.
ws.on("message", (raw) => {
const msg = JSON.parse(raw.toString());
const updates = [];
for (const update of msg.update) {
const id = update.entityId?.id;
if (!id || !assetsLookup[id]) continue;
const timeSeries = update.latest?.TIME_SERIES;
if (!timeSeries || Object.keys(timeSeries).length === 0) continue;
updates.push({
name: assetsLookup[id].name,
profile: assetsLookup[id].type,
data: timeSeries
});
}
return updates;
});