const WebSocket = require('ws'); var grpc = require("./grpcConnection") var grpcJS = require('@grpc/grpc-js'); //Setup webserver const webSocketHost = "0.0.0.0" const webSocketPort = 9898 var projectorTarget = process.env.PROJECTOR_TARGET ||'127.0.0.1:50051'; //var target = "proveeprojectorservice:50051" var knnTarget = process.env.KNN_TARGET || '127.0.0.1:50052'; //"proveeknnservice:50052" const wsServer = new WebSocket.Server({ host: webSocketHost, port: webSocketPort }); console.log("Projector target " +projectorTarget); console.log("KNN target: " + knnTarget) var projectorPackage = grpc.getGRPCPackage( __dirname + '/../protos/v3/projector.proto'); var KNNPackage = grpc.getGRPCPackage(__dirname + '/../protos/v3/knn.proto'); var pointID = 0; class ProjectionRequest{ constructor(ws){ this.index = 0; this.ws = ws; this.projectorConn = null; this.knnConn = null; this.lineAmount = 0; } } wsServer.on('connection', function connection(ws) { console.log(`Client connected with websocket`); var currConnection = new ProjectionRequest(ws); ws.on('message', function incoming(message) { parseMessage(message, currConnection); }); ws.on('close', (code, reason) => { console.log("Closed"); if (currConnection.client) { grpc.closeClient(client); } }) }); //Notify client of error function sendError(ws,message){ ws.send(JSON.stringify({type: "error", message: message})); } function KNNNeighbourRequest(connection,words,k){ console.log("Requesting " + words); const meta = new grpcJS.Metadata(); meta.add('id',connection.knnConn.id); connection.knnConn.client.getKNNRequest({k:k,words: words},meta,function(err,response){ if(response){ console.log("got response"); sendNeighbour(response,connection.ws); return; } sendError(connection.ws,"No valid request: " + words) console.log(err); }); } //Parse the message from browser function parseMessage(message, connection) { const jsonMessage = JSON.parse(message); switch (jsonMessage["type"]) { case "requestPointStream": console.log("Requested stream"); sendRandomPointStream(connection); break; case "sendDataRow": grpc.sendRowToServer(jsonMessage["row"], [connection.projectorConn,connection.knnConn]); break; case "setLineCount": connection.lineAmount = parseInt(jsonMessage["amount"]); break; case "getKNNNeighbours": var k = parseInt(jsonMessage["amount"]); var words = jsonMessage["word"] if(!connection.knnConn){ console.log("No KNN microservice"); sendError(connection.ws,"No KNN microservice") break; } KNNNeighbourRequest(connection,words,k); break; case "getKNN": console.log("setup KNN"); connection.knnConn = grpc.getGRPCClient(knnTarget,KNNPackage,"KNN"); grpc.getKNNConnection(connection) break; case "setProjectorAmount": var amount = parseInt(jsonMessage["amount"]); connection.projectorConn =grpc.getGRPCClient(projectorTarget,projectorPackage,"Projector"); SetupKProjectors(amount,connection) break; default: console.log("Error! Unknown request:" + jsonMessage["type"]); } } function SetupKProjectors (amount,connection){ var allCalls = [] //Create that amount of grpc connections for(var i = 0; i< amount; i++){ var call = connection.projectorConn.client.getProjectionPoints() var grpcConnection = grpc.getGRPCBidirect(connection.ws,call,sendDataStreamToClient); allCalls.push(grpcConnection) } connection.projectorConn.calls = allCalls; } function generatePoints() { var pointChunk = [] for(var i = 0; i < 100; i++){ const id = pointID++; const x = Math.floor(Math.random() * 100); const y = Math.floor(Math.random() * 100); pointChunk.push({ id, x, y }) } return {points: pointChunk}; } //Get the stream function sendRandomPointStream(connection) { for (var i = 0; i < 1000; i++) { sendDataStreamToClient(generatePoints(), connection.ws); } } //Result from KNN request function sendNeighbour(response,ws){ if(!response || response["rows"].length == 0){ const errMSG = "The word (or one of the words) was not in the set (or hasnt been received yet)"; console.log(errMSG); sendError(ws,errMSG) return; } for(var i = 0; i < response["rows"].length; i++){ console.log(response["rows"][i]["id"] + " " + response["rows"][i]["distance"]); ws.send(JSON.stringify({type: "neighbour", neighbour: response["rows"][i]["id"],distance: response["rows"][i]["distance"].toString()})); } } //Send client to browser function sendDataStreamToClient(data, ws) { var rows = data["points"] ws.send(JSON.stringify({type: "points", points: rows})); }