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:


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.


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 command

  • update: Array of entity updates returned for the subscription

  • entityId.id: Unique asset identifier

  • latest.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;
});


Resources