We developed an API that makes it easy to stream heart rate data from wearables and sensors and realized that there’s very little guidance on how to use WebSockets, so here’s a brief guide:
First of all, WebSockets is a technology for bidirectional, real-time communication between a web browser and a server. They allow for full-duplex communication, meaning that the server and the client can both send and receive data simultaneously.
WebSockets are created using the WebSocket protocol, which is a standard protocol for establishing a persistent, bi-directional connection between a web client and a server.
The WebSocket protocol uses the HTTP protocol to initiate the connection, but once the connection is established, the WebSocket protocol takes over and allows for full-duplex communication.
Maintaining the connection and establishing a handshake:
const WebSocket = require("ws")
const WS_CONNECTION = "wss://ws.tryterra.co/connect";
function initWS(token) {
const socket = new WebSocket(WS_CONNECTION)
var expectingHeartBeatAck = false
socket.addEventListener('open', function (event) {
console.log("Connection Established");
})
function heartBeat(){
if(!expectingHeartBeatAck){
var heartBeatPayload = JSON.stringify({
"op": 0
})
socket.send(heartBeatPayload)
console.log("↑ " + heartBeatPayload)
expectingHeartBeatAck = true
}
else socket.close()
}
socket.addEventListener('message', function (event) {
console.log("↓ " + event.data);
var message = JSON.parse(event.data)
if (message["op"] == 2){
heartBeat()
setInterval(heartBeat, message["d"]["heartbeat_interval"])
var payload = JSON.stringify(
{
"op": 3,
"d": {
"token": token,
"type": 1 //0 for user, 1 for developer
}
}
)
socket.send(payload)
}
if (message["op"] == 1){
expectingHeartBeatAck = false
}
})
socket.addEventListener('close', function (event) {
console.log('close');
console.log(event.reason);
})
socket.addEventListener('error', function (event) {
console.log('error');
console.log(event);
})
}
Running the function:
initWs(token)
Here’s what happens:
Connection Established
↓ {"op":2,"d":{"heartbeat_interval":40000}}
↑ {"op":0}
↑ {"op":3,"d":{"token":"dGVzdGluZ0VsbGlvdHQ.MU1fASa1nR9EpQWQx67xIN7veTFKFwudaB4HbN4kw9A","type":1}}
↓ {"op":1}
↓ {"op":4}
↑ {"op":0}
↓ {"op":1}
↓ {"op":5,"d":{"ts":"2022-06-01T14:47:08.055Z","val":86.0},"uid":"100b370c-d2be-42a2-b757-01fc85c41031","seq":12254,"t":"HEART_RATE"}
↓ {"op":5,"d":{"ts":"2022-06-01T14:47:08.701Z","val":87.0},"uid":"100b370c-d2be-42a2-b757-01fc85c41031","seq":12255,"t":"HEART_RATE"}
↓ {"op":5,"d":{"ts":"2022-06-01T14:47:09.698Z","val":86.0},"uid":"100b370c-d2be-42a2-b757-01fc85c41031","seq":12256,"t":"HEART_RATE"}
↓ {"op":5,"d":{"ts":"2022-06-01T14:47:11.041Z","val":86.0},"uid":"100b370c-d2be-42a2-b757-01fc85c41031","seq":12257,"t":"HEART_RATE"}
↓ {"op":5,"d":{"ts":"2022-06-01T14:47:12.049Z","val":86.0},"uid":"100b370c-d2be-42a2-b757-01fc85c41031","seq":12258,"t":"HEART_RATE"}
Each WebSocket server has its protocol and may not adhere to the same one. However, the idea is always the same: you initiate the connection, complete the handshake, and do something “on message, on open, and on close.”