add SSE for receiving failsafe status

This commit is contained in:
Sem van der Hoeven
2023-05-30 22:02:02 +02:00
parent 48e1ce8f5b
commit e6e1b11369
3 changed files with 81 additions and 43 deletions

View File

@@ -2,50 +2,79 @@ var express = require("express");
var app = express(); var app = express();
const WebSocket = require("ws"); const WebSocket = require("ws");
//# TODO SSE https://www.digitalocean.com/community/tutorials/nodejs-server-sent-events-build-realtime-app
var last_status = {}; var last_status = {};
var last_image; var last_image;
var received_picture = false; var received_picture = false;
var received_error = false; var received_error = false;
let sse_clients = [];
app.use(express.static("public")); app.use(express.static("public"));
app.use(express.json()); app.use(express.json());
var ws; var ws;
var api_connected = false; var api_connected = false;
var connect_to_api = function () { function send_events_to_clients(data) {
console.log("Connecting to API") sse_clients.forEach(client => client.response.write(`data: ${JSON.stringify(data)}\n\n`));
ws = new WebSocket("ws://10.100.0.40:9001/"); }
ws.on("open", function open() { function handle_sse_client(request, response, next) {
console.log("connected with websockets to API!"); const headers = {
api_connected = true; "Content-Type": "text/event-stream",
}); 'Connection': "keep-alive",
"Cache-Control": "no-cache",
ws.on("message", function message(message) { };
try { // response.writeHead(200, headers);
var msg = JSON.parse(message); // response.write("yeet\n\n");
if (msg.type == "STATUS") { const clientID = Date.now();
last_status = msg.data; const newClient = {
} else if (msg.type == "IMAGE") { id: clientID,
console.log("got picture"); response
// console.log(msg.image); };
last_image = msg.image;
received_picture = true;
}
} catch (error) {
console.log("could not parse as json")
} sse_clients.push(newClient);
});
request.on("close", () => {
ws.on("error", function error(err) { console.log(`${clientID} Connection closed`);
console.log("there was an error") sse_clients = sse_clients.filter(client => client.id !== clientID);
console.error("error: " + err);
received_error = true;
}); });
} }
var connect_to_api = function () {
console.log("Connecting to API");
ws = new WebSocket("ws://10.100.0.40:9001/");
ws.on("open", function open() {
console.log("connected with websockets to API!");
api_connected = true;
});
ws.on("message", function message(message) {
try {
var msg = JSON.parse(message);
if (msg.type == "STATUS") {
last_status = msg.data;
send_events_to_clients(message);
} else if (msg.type == "IMAGE") {
console.log("got picture");
// console.log(msg.image);
last_image = msg.image;
received_picture = true;
}
} catch (error) {
console.log("could not parse as json");
}
});
ws.on("error", function error(err) {
console.log("there was an error");
console.error("error: " + err);
received_error = true;
});
};
// set the view engine to ejs // set the view engine to ejs
app.set("view engine", "ejs"); app.set("view engine", "ejs");
@@ -61,12 +90,14 @@ app.get("/status", function (req, res) {
res.status(200).json(last_status); res.status(200).json(last_status);
}); });
app.get("/image", function (req, res) { app.get("/events", handle_sse_client);
app.get("/image", function (req, res) {
console.log("got picture request"); console.log("got picture request");
var request = JSON.stringify({ var request = JSON.stringify({
command: 5 command: 5,
}); });
console.log("sending picture request") console.log("sending picture request");
ws.send(request); ws.send(request);
res.status(200).send(last_image); res.status(200).send(last_image);
}); });
@@ -78,23 +109,22 @@ app.post("/move", function (req, res) {
up_down: req.body.up_down, up_down: req.body.up_down,
left_right: req.body.left_right, left_right: req.body.left_right,
forward_backward: req.body.forward_backward, forward_backward: req.body.forward_backward,
yaw: req.body.turn_left_right yaw: req.body.turn_left_right,
}); });
ws.send(request); ws.send(request);
}); });
app.get("/connect", function (req, res) { app.get("/connect", function (req, res) {
console.log("got connect request"); console.log("got connect request");
connect_to_api(); connect_to_api();
setTimeout(function () { setTimeout(function () {
if (api_connected) { if (api_connected) {
res.status(200).json({ connected: true }); res.status(200).json({ connected: true });
} else { } else {
received_error = false; received_error = false;
res.status(400).json({ connected: false }); res.status(400).json({ connected: false });
} }
}, 1000); }, 1000);
}); });
app.listen(8080); app.listen(8080);

View File

@@ -60,6 +60,12 @@
<script> <script>
var update_status = setInterval(update_status, 1000); var update_status = setInterval(update_status, 1000);
assign_button_callbacks(); assign_button_callbacks();
const events = new EventSource("/events");
events.onmessage = (event) => {
const parsedData = JSON.parse(event.data);
console.log("RECEIVED EVENT");
console.log(parsedData);
}
function assign_button_callbacks() { function assign_button_callbacks() {
var buttons = document.getElementsByClassName("movebutton"); var buttons = document.getElementsByClassName("movebutton");

View File

@@ -16,6 +16,8 @@ import base64
# communication: client always sends commands that have a command id. # communication: client always sends commands that have a command id.
# server always sends messages back that have a message type # server always sends messages back that have a message type
# TODO send video https://github.com/Jatin1o1/Python-Javascript-Websocket-Video-Streaming-/tree/main
class RequestCommand(Enum): class RequestCommand(Enum):
GET_COMMANDS_TYPES = -1 # to get the available commands and types GET_COMMANDS_TYPES = -1 # to get the available commands and types