Skip to content
Snippets Groups Projects
webSocketGateway.js 4.72 KiB
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}));
}