mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-23 01:21:40 +00:00
Improve websocket reconnect robustness (#706)
Replace with stripped down NT4 client Co-authored-by: Mohammad Durrani <46766905+mdurrani808@users.noreply.github.com>
This commit is contained in:
74
photon-client/src/plugins/ReconnectingWebsocket.js
Normal file
74
photon-client/src/plugins/ReconnectingWebsocket.js
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Auto-reconnecting Websocket, a stripped down version of the NT4 client from
|
||||
* https://raw.githubusercontent.com/wpilibsuite/NetworkTablesClients/2f8d378ac08d5ca703d590cfb019fc4af062db89/nt4/js/src/nt4.js
|
||||
*/
|
||||
export class ReconnectingWebsocket {
|
||||
constructor(serverAddr,
|
||||
onDataIn_in,
|
||||
onConnect_in,
|
||||
onDisconnect_in) {
|
||||
|
||||
this.onDataIn = onDataIn_in;
|
||||
this.onConnect = onConnect_in;
|
||||
this.onDisconnect = onDisconnect_in;
|
||||
|
||||
// WS Connection State (with defaults)
|
||||
this.serverAddr = serverAddr;
|
||||
this.serverConnectionActive = false;
|
||||
|
||||
//Trigger the websocket to connect automatically
|
||||
this.ws_connect();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Websocket connection Maintenance
|
||||
|
||||
ws_onOpen() {
|
||||
// Set the flag allowing general server communication
|
||||
this.serverConnectionActive = true;
|
||||
|
||||
console.log("[WebSocket] Connected!");
|
||||
|
||||
// User connection-opened hook
|
||||
this.onConnect();
|
||||
}
|
||||
|
||||
ws_onClose(e) {
|
||||
//Clear flags to stop server communication
|
||||
this.ws = null;
|
||||
this.serverConnectionActive = false;
|
||||
|
||||
// User connection-closed hook
|
||||
this.onDisconnect();
|
||||
|
||||
console.log('[WebSocket] Socket is closed. Reconnect will be attempted in 0.5 second.', e.reason);
|
||||
setTimeout(this.ws_connect.bind(this), 500);
|
||||
|
||||
if (!e.wasClean) {
|
||||
console.error('Socket encountered error!');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ws_onError(e) {
|
||||
console.log("[WebSocket] Websocket error - " + e.toString());
|
||||
this.ws.close();
|
||||
}
|
||||
|
||||
ws_onMessage(e) {
|
||||
this.onDataIn(e);
|
||||
}
|
||||
|
||||
ws_connect() {
|
||||
this.ws = new WebSocket(this.serverAddr);
|
||||
this.ws.binaryType = "arraybuffer";
|
||||
this.ws.onopen = this.ws_onOpen.bind(this);
|
||||
this.ws.onmessage = this.ws_onMessage.bind(this);
|
||||
this.ws.onclose = this.ws_onClose.bind(this);
|
||||
this.ws.onerror = this.ws_onError.bind(this);
|
||||
|
||||
console.log("[WebSocket] Starting...");
|
||||
}
|
||||
}
|
||||
|
||||
export default { ReconnectingWebsocket }
|
||||
@@ -1,121 +0,0 @@
|
||||
//https://gomakethings.com/getting-the-differences-between-two-objects-with-vanilla-js/
|
||||
export const diff = function (obj1, obj2) {
|
||||
|
||||
// Make sure an object to compare is provided
|
||||
if (!obj2 || Object.prototype.toString.call(obj2) !== '[object Object]') {
|
||||
return obj1;
|
||||
}
|
||||
|
||||
//
|
||||
// Variables
|
||||
//
|
||||
|
||||
let diffs = {};
|
||||
let key;
|
||||
|
||||
|
||||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Check if two arrays are equal
|
||||
* @param {Array} arr1 The first array
|
||||
* @param {Array} arr2 The second array
|
||||
* @return {Boolean} If true, both arrays are equal
|
||||
*/
|
||||
const arraysMatch = function (arr1, arr2) {
|
||||
|
||||
// Check if the arrays are the same length
|
||||
if (arr1.length !== arr2.length) return false;
|
||||
|
||||
// Check if all items exist and are in the same order
|
||||
for (let i = 0; i < arr1.length; i++) {
|
||||
if (arr1[i] !== arr2[i]) return false;
|
||||
}
|
||||
|
||||
// Otherwise, return true
|
||||
return true;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Compare two items and push non-matches to object
|
||||
* @param {*} item1 The first item
|
||||
* @param {*} item2 The second item
|
||||
* @param {String} key The key in our object
|
||||
*/
|
||||
const compare = function (item1, item2, key) {
|
||||
|
||||
// Get the object type
|
||||
let type1 = Object.prototype.toString.call(item1);
|
||||
let type2 = Object.prototype.toString.call(item2);
|
||||
|
||||
// If type2 is undefined it has been removed
|
||||
if (type2 === '[object Undefined]') {
|
||||
diffs[key] = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// If items are different types
|
||||
if (type1 !== type2) {
|
||||
diffs[key] = item2;
|
||||
return;
|
||||
}
|
||||
|
||||
// If an object, compare recursively
|
||||
if (type1 === '[object Object]') {
|
||||
let objDiff = diff(item1, item2);
|
||||
if (Object.keys(objDiff).length > 1) {
|
||||
diffs[key] = objDiff;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If an array, compare
|
||||
if (type1 === '[object Array]') {
|
||||
if (!arraysMatch(item1, item2)) {
|
||||
diffs[key] = item2;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Else if it's a function, convert to a string and compare
|
||||
// Otherwise, just compare
|
||||
if (type1 === '[object Function]') {
|
||||
if (item1.toString() !== item2.toString()) {
|
||||
diffs[key] = item2;
|
||||
}
|
||||
} else {
|
||||
if (item1 !== item2) {
|
||||
diffs[key] = item2;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Compare our objects
|
||||
//
|
||||
|
||||
// Loop through the first object
|
||||
for (key in obj1) {
|
||||
if (obj1.hasOwnProperty(key)) {
|
||||
compare(obj1[key], obj2[key], key);
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through the second object and find missing items
|
||||
for (key in obj2) {
|
||||
if (obj2.hasOwnProperty(key)) {
|
||||
if (!obj1[key] && obj1[key] !== obj2[key] ) {
|
||||
diffs[key] = obj2[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the object of differences
|
||||
return diffs;
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user