From bfd6cb1bc83be554f89b06824f68acb19bacb6e6 Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Wed, 5 Mar 2025 10:02:59 -0600 Subject: [PATCH 01/19] Add code runtime metrics to ntTopics and export function --- server/connections/nt4.js | 12 +++++++++++- server/model/ntTopics.json | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/server/connections/nt4.js b/server/connections/nt4.js index 6ecc957..7e84e94 100644 --- a/server/connections/nt4.js +++ b/server/connections/nt4.js @@ -98,4 +98,14 @@ function getPowerStats() { return powerStats; } -module.exports = { getMotorTemperatures, getPDHCurrents, getPowerStats }; +function getCodeRuntime() { + const codeRuntime = ntTopics.find((t) => t.label === "Code Runtime"); + return codeRuntime && codeRuntime.value ? codeRuntime.value : null; +} + +module.exports = { + getMotorTemperatures, + getPDHCurrents, + getPowerStats, + getCodeRuntime, +}; diff --git a/server/model/ntTopics.json b/server/model/ntTopics.json index 8711d87..2ebe1c6 100644 --- a/server/model/ntTopics.json +++ b/server/model/ntTopics.json @@ -100,5 +100,23 @@ "path": "/AdvantageKit/PowerDistribution/Voltage", "type": "double", "dataCategory": "POWER_STATS" + }, + { + "label": "Full Cycle MS", + "path": "/RealOutputs/LoggedRobot/FullCycleMS", + "type": "double", + "dataCategory": "CODE_RUNTIME" + }, + { + "label": "Log Period MS", + "path": "/RealOutputs/LoggedRobot/LogPeriodicMS", + "type": "double", + "dataCategory": "CODE_RUNTIME" + }, + { + "label": "User Code MS", + "path": "/RealOutputs/LoggedRobot/UserCodeMS", + "type": "double", + "dataCategory": "CODE_RUNTIME" } ] From 90e7492fa7f97119c293e8983885983a378c392e Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Wed, 5 Mar 2025 10:28:10 -0600 Subject: [PATCH 02/19] Add runtime data handling and graph visualization to robot view --- server/connections/nt4.js | 6 +++++- views/robot.ejs | 29 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/server/connections/nt4.js b/server/connections/nt4.js index 7e84e94..9349b64 100644 --- a/server/connections/nt4.js +++ b/server/connections/nt4.js @@ -100,7 +100,11 @@ function getPowerStats() { function getCodeRuntime() { const codeRuntime = ntTopics.find((t) => t.label === "Code Runtime"); - return codeRuntime && codeRuntime.value ? codeRuntime.value : null; + if (codeRuntime && codeRuntime.value) { + return codeRuntime.value; + } else { + return "no code runtime data available"; + } } module.exports = { diff --git a/views/robot.ejs b/views/robot.ejs index 907ebc5..ea8a1b0 100644 --- a/views/robot.ejs +++ b/views/robot.ejs @@ -58,6 +58,35 @@
+ +
+

Graph Placeholder

+ + +
From 75271d007f244dba147551ff15e544e4e6e95581 Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Wed, 5 Mar 2025 10:29:02 -0600 Subject: [PATCH 03/19] Add styling for graph container in CSS --- assets/css/style.css | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/assets/css/style.css b/assets/css/style.css index 90ffd15..259d918 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -369,4 +369,10 @@ div.twitchstream iframe { .checklist { font-family: "Source Code Pro", monospace; font-size: 15px; -} \ No newline at end of file +} + +.graph-container { + border: 2px solid #fff; + padding: 10px; + margin: 10px 0; +} From b1f6db280fa2f900e778cad0ee320b9579ce9727 Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Wed, 12 Mar 2025 10:27:28 -0500 Subject: [PATCH 04/19] Add robot runtime graph visualization and data handling. remove the old graph for page runtime since it is not relevant. graph is not visible anywhere, possible style issue. --- assets/js/robot.js | 58 +++++++++++++++++++++++++---------------- server.js | 31 +++++++++++----------- server/socket/socket.js | 9 +++++++ server/views/robot.ejs | 3 +++ 4 files changed, 64 insertions(+), 37 deletions(-) create mode 100644 server/views/robot.ejs diff --git a/assets/js/robot.js b/assets/js/robot.js index 6daa562..4b8fc73 100644 --- a/assets/js/robot.js +++ b/assets/js/robot.js @@ -14,12 +14,40 @@ socket.on("pdhCurrents", (entry) => { pdhDisplay.innerHTML = entry; }); -socket.on("powerStats", (stats) => { - const runtimeDisplay = document.querySelector("div.runtime"); - const voltageDisplay = document.querySelector("div.voltage"); +// Setup chart for robot runtime graph (assumes using Chart.js or similar) +const ctx = document.getElementById("runtimeGraph").getContext("2d"); +const runtimeChart = new Chart(ctx, { + type: "line", + data: { + labels: [], // timestamps + datasets: [ + { + label: "Robot Code Runtime", + data: [], + borderColor: "rgba(75, 192, 192, 1)", + fill: false, + }, + ], + }, + options: { + scales: { + x: { display: true }, + y: { beginAtZero: true }, + }, + }, +}); - runtimeDisplay.innerHTML = stats.currentDisplay; - voltageDisplay.innerHTML = stats.voltageDisplay; +// Listen for robot runtime data similar to other measurements +socket.on("robotRuntime", (data) => { + // Assume data contains { timestamp, runtime } + runtimeChart.data.labels.push(data.timestamp); + runtimeChart.data.datasets[0].data.push(data.runtime); + // Maintain a fixed length of data points + if (runtimeChart.data.labels.length > 20) { + runtimeChart.data.labels.shift(); + runtimeChart.data.datasets[0].data.shift(); + } + runtimeChart.update(); }); async function fetchTemperatures() { @@ -42,31 +70,17 @@ async function fetchPDHCurrents() { } } -async function fetchPowerStats() { - const runtimeDisplay = document.querySelector("div.runtime"); - const voltageDisplay = document.querySelector("div.voltage"); - const response = await fetch("/powerStats"); - if (response.ok) { - const stats = await response.json(); - runtimeDisplay.innerHTML = stats.currentDisplay; - voltageDisplay.innerHTML = stats.voltageDisplay; - } else { - console.log("error fetching power stats"); - } -} - fetchTemperatures(); fetchPDHCurrents(); -fetchPowerStats(); // Select all checkboxes with a data-key attribute for persistence const checklist = document.querySelectorAll('input[type="checkbox"][data-key]'); checklist.forEach((checkbox) => { // Load persisted state on page load - const key = checkbox.getAttribute('data-key'); + const key = checkbox.getAttribute("data-key"); const saved = localStorage.getItem(key); - if (saved === 'true') { + if (saved === "true") { checkbox.checked = true; } @@ -74,7 +88,7 @@ checklist.forEach((checkbox) => { const label = event.target.closest("label"); const taskText = label.textContent.trim(); const isChecked = event.target.checked; - const key = event.target.getAttribute('data-key'); + const key = event.target.getAttribute("data-key"); // Save state to localStorage localStorage.setItem(key, isChecked); socket.emit("checklist", { taskText, isChecked }); diff --git a/server.js b/server.js index ac5ac7c..d58fa25 100644 --- a/server.js +++ b/server.js @@ -3,6 +3,10 @@ * this file is executed by the Node server */ +// load environment variables from the .env file into process.env +const dotenv = require("dotenv"); +dotenv.config({ path: ".env" }); + // import the http module, which provides an HTTP server const http = require("http"); @@ -17,22 +21,19 @@ const server = http.createServer(app); const { createSocketServer } = require("./server/socket/socket"); createSocketServer(server); -// load environment variables from the .env file into process.env -const dotenv = require("dotenv"); -dotenv.config({ path: ".env" }); - // connect to MongoDB using mongoose const mongoose = require("mongoose"); -mongoose.connect(process.env.MONGODB_URI, { - useNewUrlParser: true, - useUnifiedTopology: true -}) -.then(() => { - console.log("Connected to MongoDB"); -}) -.catch((err) => { - console.error("MongoDB connection error:", err); -}); +mongoose + .connect(process.env.MONGODB_URI, { + useNewUrlParser: true, + useUnifiedTopology: true, + }) + .then(() => { + console.log("Connected to MongoDB"); + }) + .catch((err) => { + console.error("MongoDB connection error:", err); + }); // add middleware to handle JSON in HTTP request bodies (used with POST commands) app.use(express.json()); @@ -54,4 +55,4 @@ app.use("/", require("./server/routes/router")); // start the server on port 8081 server.listen(8081, () => { console.log("server is listening on http://localhost:8081"); -}); \ No newline at end of file +}); diff --git a/server/socket/socket.js b/server/socket/socket.js index 55646b6..6031008 100644 --- a/server/socket/socket.js +++ b/server/socket/socket.js @@ -21,6 +21,15 @@ function createSocketServer(httpServer) { }); }); + // For example, emit robot runtime data every 2 seconds: + setInterval(() => { + const data = { + timestamp: new Date().toLocaleTimeString(), + runtime: Math.floor(Math.random() * 1000), // replace with real runtime value + }; + io.emit("robotRuntime", data); + }, 2000); + return io; } diff --git a/server/views/robot.ejs b/server/views/robot.ejs new file mode 100644 index 0000000..425cb0b --- /dev/null +++ b/server/views/robot.ejs @@ -0,0 +1,3 @@ +
+ +
From e22a3295de5d7ef27943b4eb22ffd77450336970 Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Thu, 13 Mar 2025 09:12:46 -0500 Subject: [PATCH 05/19] Refactor runtime graph implementation: remove old page runtime graph, add new robot code runtime endpoint and Chart.js visualization. --- assets/css/style.css | 18 +++++++++++--- server.js | 9 +++++++ views/robot.ejs | 59 +++++++++++++++++++++++--------------------- 3 files changed, 54 insertions(+), 32 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 259d918..fccc4d3 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -169,16 +169,26 @@ div.twitchstream iframe { } .runtime { - background-color: #24252a; margin: 10px; text-align: left; color: #ffffff; - border-radius: 10px; font-family: "Source Code Pro", monospace; - border: 2px solid white; /* Adjust thickness as needed */ + background: none; /* remove filled background */ + border: none; /* remove complete border */ + border-bottom: 2px solid white; /* line graph baseline */ width: calc(35vw / 2); - height: 20vh; + height: auto; /* remove fixed height */ float: left; + position: relative; +} + +.runtime::after { + content: ""; + position: absolute; + top: 50%; + left: 0; + width: 100%; + height: 0; /* no extra height */ } .voltage { diff --git a/server.js b/server.js index d58fa25..f87c2d5 100644 --- a/server.js +++ b/server.js @@ -48,6 +48,15 @@ app.use("/img", express.static("assets/img")); app.use("/js", express.static("assets/js")); app.use("/html", express.static("assets/html")); +// NEW: Endpoint that returns ROBOT CODE runtime info +app.get("/robot/api/runtimeInfo", (req, res) => { + const runtimeInfo = { + uptime: process.uptime(), + timestamp: new Date().toISOString(), + }; + res.json(runtimeInfo); +}); + // to keep this file manageable, we will move the routes to a separate file // the exported router object is an example of middleware app.use("/", require("./server/routes/router")); diff --git a/views/robot.ejs b/views/robot.ejs index ea8a1b0..4d81e6f 100644 --- a/views/robot.ejs +++ b/views/robot.ejs @@ -58,35 +58,38 @@
- -
-

Graph Placeholder

- - + + +
+

Robot Code Runtime Information

+
+ +
From 93aeff0e21f9575f381ac6e256b80911bbfdbf3c Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Fri, 14 Mar 2025 09:04:09 -0500 Subject: [PATCH 06/19] Implement line chart for runtime data visualization with real-time updates and data persistence -- currentl;y is displaying fake data since robot is not actually connected --- server/data/chartData.json | 1 + server/model/config.json | 3 +- server/public/js/chart.js | 58 ++++++++++++++++++++++++++++++++++++++ server/server.js | 54 +++++++++++++++++++++++++++++++++++ views/robot.ejs | 2 +- 5 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 server/data/chartData.json create mode 100644 server/public/js/chart.js create mode 100644 server/server.js diff --git a/server/data/chartData.json b/server/data/chartData.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/server/data/chartData.json @@ -0,0 +1 @@ +[] diff --git a/server/model/config.json b/server/model/config.json index 5366f59..e636fd7 100644 --- a/server/model/config.json +++ b/server/model/config.json @@ -2,5 +2,6 @@ "teamNumber": 3061, "eventKey": "2024ksla", "localTimeZone": "America/Chicago", - "streamURL": "https://player.twitch.tv/?channel=funroboticsnetwork&parent=pit.team3061.org" + "streamURL": "https://player.twitch.tv/?channel=funroboticsnetwork&parent=pit.team3061.org", + "graphType": "line" } diff --git a/server/public/js/chart.js b/server/public/js/chart.js new file mode 100644 index 0000000..b14f8c3 --- /dev/null +++ b/server/public/js/chart.js @@ -0,0 +1,58 @@ +// ...existing code setting up the line chart... +const ctx = document.getElementById("chart").getContext("2d"); +const chart = new Chart(ctx, { + type: "line", + data: { + labels: [], + datasets: [ + { + // ...existing dataset properties... + data: [], + borderColor: "white", // new white line color + backgroundColor: "rgba(255,255,255,0.2)", // new white translucent fill for points + }, + ], + }, + options: { + scales: { + x: { + ticks: { color: "white" }, // new white x-axis labels + grid: { color: "rgba(255,255,255,0.2)" }, // new white grid lines for x-axis + }, + y: { + ticks: { color: "white" }, // new white y-axis labels + grid: { color: "rgba(255,255,255,0.2)" }, // new white grid lines for y-axis + }, + }, + plugins: { + legend: { + labels: { color: "white" }, // new white legend text + }, + }, + }, +}); + +// Initialize socket.io client +const socket = io(); + +// Function to add a new point to the chart +function addPointToChart(point) { + // ...existing code to update chart instance... + chart.data.labels.push(point.label); + chart.data.datasets[0].data.push(point.value); + chart.update(); +} + +// Fetch persisted chart data on page load +fetch("/api/chart") + .then((res) => res.json()) + .then((data) => { + data.forEach((point) => { + addPointToChart(point); + }); + }); + +// Listen for real-time updates +socket.on("chartPointAdded", (point) => { + addPointToChart(point); +}); diff --git a/server/server.js b/server/server.js new file mode 100644 index 0000000..42fae54 --- /dev/null +++ b/server/server.js @@ -0,0 +1,54 @@ +const express = require("express"); +const http = require("http"); +const socketIo = require("socket.io"); +const fs = require("fs"); +const path = require("path"); + +const app = express(); +const server = http.createServer(app); +const io = socketIo(server); + +app.use(express.json()); + +const chartDataPath = path.join(__dirname, "data", "chartData.json"); + +// Utility functions for chart data persistence +function loadChartData() { + try { + return JSON.parse(fs.readFileSync(chartDataPath, "utf8")); + } catch (e) { + return []; + } +} + +function saveChartData(data) { + fs.writeFileSync(chartDataPath, JSON.stringify(data, null, 2)); +} + +// Endpoint to get existing chart points +app.get("/api/chart", (req, res) => { + const data = loadChartData(); + res.json(data); +}); + +// Endpoint to add a new chart point +app.post("/api/chart", (req, res) => { + const point = req.body; // assume point has properties like 'label' and 'value' + const data = loadChartData(); + data.push(point); + saveChartData(data); + // Broadcast new point to connected clients + io.emit("chartPointAdded", point); + res.status(200).json({ success: true }); +}); + +// Socket.io connection handling +io.on("connection", (socket) => { + // Optionally send the initial chart data + socket.emit("initialChartData", loadChartData()); +}); + +const PORT = process.env.PORT || 3000; +server.listen(PORT, () => { + console.log(`Server is running on port ${PORT}`); +}); diff --git a/views/robot.ejs b/views/robot.ejs index 4d81e6f..3cf2956 100644 --- a/views/robot.ejs +++ b/views/robot.ejs @@ -72,7 +72,7 @@ const data = await response.json(); const ctx = document.getElementById('runtimeChart').getContext('2d'); new Chart(ctx, { - type: 'bar', + type: 'line', data: { labels: ['Uptime (s)'], datasets: [{ From 5fad1eb25dbf0de8424b1974708344d8e69135be Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Fri, 14 Mar 2025 09:16:44 -0500 Subject: [PATCH 07/19] Adjust graph container and chart dimensions for improved layout and styling --- assets/css/style.css | 6 ++++-- server/public/js/chart.js | 23 +++++++++++++++-------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index fccc4d3..65809dc 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -383,6 +383,8 @@ div.twitchstream iframe { .graph-container { border: 2px solid #fff; - padding: 10px; - margin: 10px 0; + padding: 5px; + margin: 5px 0; + width: 300px; + height: 200px; } diff --git a/server/public/js/chart.js b/server/public/js/chart.js index b14f8c3..3103a75 100644 --- a/server/public/js/chart.js +++ b/server/public/js/chart.js @@ -1,5 +1,9 @@ // ...existing code setting up the line chart... -const ctx = document.getElementById("chart").getContext("2d"); +const canvas = document.getElementById("chart"); +canvas.width = 400; // reduced width +canvas.height = 300; // reduced height +const ctx = canvas.getContext("2d"); + const chart = new Chart(ctx, { type: "line", data: { @@ -8,27 +12,30 @@ const chart = new Chart(ctx, { { // ...existing dataset properties... data: [], - borderColor: "white", // new white line color - backgroundColor: "rgba(255,255,255,0.2)", // new white translucent fill for points + borderColor: "white", + backgroundColor: "rgba(255,255,255,0.2)", + borderWidth: 2, // reduced thickness + pointRadius: 3, // smaller points }, ], }, options: { scales: { x: { - ticks: { color: "white" }, // new white x-axis labels - grid: { color: "rgba(255,255,255,0.2)" }, // new white grid lines for x-axis + ticks: { color: "white" }, + grid: { color: "rgba(255,255,255,0.2)" }, }, y: { - ticks: { color: "white" }, // new white y-axis labels - grid: { color: "rgba(255,255,255,0.2)" }, // new white grid lines for y-axis + ticks: { color: "white" }, + grid: { color: "rgba(255,255,255,0.2)" }, }, }, plugins: { legend: { - labels: { color: "white" }, // new white legend text + labels: { color: "white" }, }, }, + responsive: false, // ensure canvas styling is respected }, }); From 9d37695c7584ecd109a0afb090639fea46d97a48 Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Fri, 14 Mar 2025 09:29:40 -0500 Subject: [PATCH 08/19] Add debugging log for raw chart data in chart.js -- but not printing in the console --- server/public/js/chart.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/public/js/chart.js b/server/public/js/chart.js index 3103a75..65aa64e 100644 --- a/server/public/js/chart.js +++ b/server/public/js/chart.js @@ -54,6 +54,7 @@ function addPointToChart(point) { fetch("/api/chart") .then((res) => res.json()) .then((data) => { + console.log("Raw chart data:", data); // new print statement for debugging data.forEach((point) => { addPointToChart(point); }); From 5fdcb20114a20924d7bbc35e9c0b4083742a9967 Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Fri, 14 Mar 2025 09:32:50 -0500 Subject: [PATCH 09/19] Add runtime graph canvas initialization and error handling --- server/public/js/robot.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 server/public/js/robot.js diff --git a/server/public/js/robot.js b/server/public/js/robot.js new file mode 100644 index 0000000..6210145 --- /dev/null +++ b/server/public/js/robot.js @@ -0,0 +1,19 @@ +document.addEventListener("DOMContentLoaded", function () { + const canvas = document.getElementById("chart"); + if (!canvas) { + console.error("Canvas element not found"); + return; + } + canvas.width = 400; // reduced width + canvas.height = 300; // reduced height + const ctx = canvas.getContext("2d"); + + const runtimeGraphCanvas = document.getElementById("runtimeGraph"); + if (!runtimeGraphCanvas) { + console.error("Canvas element with id 'runtimeGraph' not found"); + return; + } + const ctx = runtimeGraphCanvas.getContext("2d"); + + // ...existing code for creating the chart and other logic... +}); From 36680c0a75535ff58284b669fd70fd4ed826511d Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Wed, 19 Mar 2025 10:29:07 -0500 Subject: [PATCH 10/19] Enhance runtime chart: add annotation for 20 ms threshold, improve styling, and implement runtime data fetching --- assets/js/robot.js | 59 ++++++++++++++++++++++----- node_modules/.package-lock.json | 26 ++++++++++++ package-lock.json | 27 +++++++++++++ package.json | 1 + server/public/js/robot.js | 71 ++++++++++++++++++++++++++++----- 5 files changed, 164 insertions(+), 20 deletions(-) diff --git a/assets/js/robot.js b/assets/js/robot.js index 4b8fc73..3003b5e 100644 --- a/assets/js/robot.js +++ b/assets/js/robot.js @@ -32,23 +32,58 @@ const runtimeChart = new Chart(ctx, { options: { scales: { x: { display: true }, - y: { beginAtZero: true }, + y: { + beginAtZero: true, + // The suggested max can be set if needed + }, + }, + plugins: { + annotation: { + annotations: { + line1: { + type: "line", + yMin: 20, + yMax: 20, + borderColor: "red", + borderWidth: 2, + label: { + content: "20 ms", + enabled: true, + position: "center", + }, + }, + }, + }, }, + responsive: false, }, }); // Listen for robot runtime data similar to other measurements -socket.on("robotRuntime", (data) => { - // Assume data contains { timestamp, runtime } - runtimeChart.data.labels.push(data.timestamp); - runtimeChart.data.datasets[0].data.push(data.runtime); - // Maintain a fixed length of data points - if (runtimeChart.data.labels.length > 20) { - runtimeChart.data.labels.shift(); - runtimeChart.data.datasets[0].data.shift(); +// socket.on("robotRuntime", (data) => { +// // Assume data contains { timestamp, runtime } +// runtimeChart.data.labels.push(data.timestamp); +// runtimeChart.data.datasets[0].data.push(data.runtime); +// // Maintain a fixed length of data points +// if (runtimeChart.data.labels.length > 20) { +// runtimeChart.data.labels.shift(); +// runtimeChart.data.datasets[0].data.shift(); +// } +// runtimeChart.update(); +// }); + +async function fetchRuntime() { + const runtimeDisplay = document.querySelector("div.runtime"); + const response = await fetch("/runtime"); + if (response.ok) { + runtimeDisplay.innerHTML = await response.text(); + } else { + console.error("Error fetching runtime data"); } - runtimeChart.update(); -}); +} + +// Call the function to fetch runtime info on page load +fetchRuntime(); async function fetchTemperatures() { const temperatures = document.querySelector("div.temp"); @@ -94,3 +129,5 @@ checklist.forEach((checkbox) => { socket.emit("checklist", { taskText, isChecked }); }); }); + +; diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index 12452cb..51c36dd 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -102,6 +102,12 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, + "node_modules/@kurkle/color": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", + "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==", + "peer": true + }, "node_modules/@msgpack/msgpack": { "version": "3.0.0-beta2", "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.0.0-beta2.tgz", @@ -676,6 +682,26 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chart.js": { + "version": "4.4.8", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.8.tgz", + "integrity": "sha512-IkGZlVpXP+83QpMm4uxEiGqSI7jFizwVtF3+n5Pc3k7sMO+tkd0qxh2OzLhenM0K80xtmAONWGBn082EiBQSDA==", + "peer": true, + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=8" + } + }, + "node_modules/chartjs-plugin-annotation": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/chartjs-plugin-annotation/-/chartjs-plugin-annotation-3.1.0.tgz", + "integrity": "sha512-EkAed6/ycXD/7n0ShrlT1T2Hm3acnbFhgkIEJLa0X+M6S16x0zwj1Fv4suv/2bwayCT3jGPdAtI9uLcAMToaQQ==", + "peerDependencies": { + "chart.js": ">=4.0.0" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", diff --git a/package-lock.json b/package-lock.json index 90f2942..56781ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@msgpack/msgpack": "^3.0.0-beta2", "axios": "^1.7.9", + "chartjs-plugin-annotation": "^3.1.0", "dotenv": "^16.3.1", "ejs": "^3.1.9", "express": "^4.18.2", @@ -134,6 +135,12 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, + "node_modules/@kurkle/color": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", + "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==", + "peer": true + }, "node_modules/@msgpack/msgpack": { "version": "3.0.0-beta2", "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.0.0-beta2.tgz", @@ -708,6 +715,26 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chart.js": { + "version": "4.4.8", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.8.tgz", + "integrity": "sha512-IkGZlVpXP+83QpMm4uxEiGqSI7jFizwVtF3+n5Pc3k7sMO+tkd0qxh2OzLhenM0K80xtmAONWGBn082EiBQSDA==", + "peer": true, + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=8" + } + }, + "node_modules/chartjs-plugin-annotation": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/chartjs-plugin-annotation/-/chartjs-plugin-annotation-3.1.0.tgz", + "integrity": "sha512-EkAed6/ycXD/7n0ShrlT1T2Hm3acnbFhgkIEJLa0X+M6S16x0zwj1Fv4suv/2bwayCT3jGPdAtI9uLcAMToaQQ==", + "peerDependencies": { + "chart.js": ">=4.0.0" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", diff --git a/package.json b/package.json index 829f787..14611e6 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "dependencies": { "@msgpack/msgpack": "^3.0.0-beta2", "axios": "^1.7.9", + "chartjs-plugin-annotation": "^3.1.0", "dotenv": "^16.3.1", "ejs": "^3.1.9", "express": "^4.18.2", diff --git a/server/public/js/robot.js b/server/public/js/robot.js index 6210145..91cda40 100644 --- a/server/public/js/robot.js +++ b/server/public/js/robot.js @@ -1,19 +1,72 @@ document.addEventListener("DOMContentLoaded", function () { - const canvas = document.getElementById("chart"); - if (!canvas) { + const chartCanvas = document.getElementById("chart"); + if (!chartCanvas) { console.error("Canvas element not found"); return; } - canvas.width = 400; // reduced width - canvas.height = 300; // reduced height - const ctx = canvas.getContext("2d"); + chartCanvas.width = 400; // reduced width + chartCanvas.height = 300; // reduced height + const ctx = chartCanvas.getContext("2d"); - const runtimeGraphCanvas = document.getElementById("runtimeGraph"); - if (!runtimeGraphCanvas) { + const runtimeCanvas = document.getElementById("runtimeGraph"); + if (!runtimeCanvas) { console.error("Canvas element with id 'runtimeGraph' not found"); return; } - const ctx = runtimeGraphCanvas.getContext("2d"); + runtimeCanvas.width = 400; // optionally set size + runtimeCanvas.height = 300; + const runtimeCtx = runtimeCanvas.getContext("2d"); - // ...existing code for creating the chart and other logic... + const runtimeChart = new Chart(runtimeCtx, { + type: "line", + data: { + labels: [], // ...existing labels... + datasets: [ + { + label: "Runtime Data", + data: [], // ...existing dataset data... + borderColor: "blue", + backgroundColor: "rgba(0,0,255,0.2)", + borderWidth: 2, + pointRadius: 3, + }, + ], + }, + options: { + scales: { + x: { + ticks: { color: "white" }, + grid: { color: "rgba(255,255,255,0.2)" }, + }, + y: { + ticks: { color: "white" }, + grid: { color: "rgba(255,255,255,0.2)" }, + beginAtZero: true, + }, + }, + plugins: { + legend: { labels: { color: "white" } }, + annotation: { + annotations: { + line1: { + type: "line", + yMin: 20, + yMax: 20, + borderColor: "red", + borderWidth: 2, + label: { + enabled: true, + content: "20 ms", + backgroundColor: "red", + color: "white", + }, + }, + }, + }, + }, + responsive: false, + }, + }); + + // ...existing code for additional logic... }); From 4be7693d6db1444d553042c89a6c98a643bdb706 Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Wed, 26 Mar 2025 10:28:08 -0500 Subject: [PATCH 11/19] Refactor runtime chart: update title, adjust canvas size, add annotation for 20 ms threshold, and enhance styling --- views/robot.ejs | 59 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/views/robot.ejs b/views/robot.ejs index 3cf2956..06638bd 100644 --- a/views/robot.ejs +++ b/views/robot.ejs @@ -61,12 +61,12 @@
-

Robot Code Runtime Information

- +

Robot Code Runtime

+
+ +
From 83a9d99fe34823cdf667e5407ee82960c59333a3 Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Thu, 27 Mar 2025 09:19:17 -0500 Subject: [PATCH 12/19] Refactor robot view: adjust runtime graph position, update styling, and improve layout --- views/info.ejs | 4 ++-- views/robot.ejs | 18 +++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/views/info.ejs b/views/info.ejs index af41c56..8746300 100644 --- a/views/info.ejs +++ b/views/info.ejs @@ -22,7 +22,7 @@ Info icons created by Freepik - Flaticon

- - + 60+10+8+32+31+4+32+34 + 2+14+2+14+1+14 \ No newline at end of file diff --git a/views/robot.ejs b/views/robot.ejs index 06638bd..b33a82f 100644 --- a/views/robot.ejs +++ b/views/robot.ejs @@ -54,16 +54,18 @@

Deflector : 0°C

+
-
-
-
- - + +

Robot Code Runtime

+ +
+
+
; diff --git a/views/robot.ejs b/views/robot.ejs index b33a82f..58b0923 100644 --- a/views/robot.ejs +++ b/views/robot.ejs @@ -57,11 +57,8 @@
- -
-

Robot Code Runtime

- -
+ +
From 7c4d1f0ab33a721fab42a709c4489c0ada57e9ee Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Fri, 11 Apr 2025 09:19:26 -0500 Subject: [PATCH 15/19] Refactor runtime chart rendering: replace fetch with WebSocket listener for real-time data updates --- js/robot.js | 12 ++++++++++++ views/robot.ejs | 17 ++++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 js/robot.js diff --git a/js/robot.js b/js/robot.js new file mode 100644 index 0000000..3772511 --- /dev/null +++ b/js/robot.js @@ -0,0 +1,12 @@ +// Ensure the rest of the code uses the `socket` variable declared in the main HTML file + +// Example usage of the socket variable +socket.on("connect", () => { + console.log("Connected to server"); +}); + +socket.on("disconnect", () => { + console.log("Disconnected from server"); +}); + +// Add other socket event listeners and handlers as needed diff --git a/views/robot.ejs b/views/robot.ejs index 58b0923..34e950f 100644 --- a/views/robot.ejs +++ b/views/robot.ejs @@ -66,9 +66,9 @@ - + +
@@ -185,6 +185,9 @@ + From d9c3de3e521088fbcac4b546b5694e484f15f8ac Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Fri, 11 Apr 2025 09:33:33 -0500 Subject: [PATCH 16/19] Update dependencies: add socket.io-client and engine.io-client to package-lock.json install socket.io-client --- node_modules/.package-lock.json | 34 ++++++++++++++++++++++++++++++++ package-lock.json | 35 +++++++++++++++++++++++++++++++++ package.json | 1 + 3 files changed, 70 insertions(+) diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index 51c36dd..68112b7 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -1035,6 +1035,18 @@ "node": ">=10.2.0" } }, + "node_modules/engine.io-client": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", + "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, "node_modules/engine.io-parser": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", @@ -3894,6 +3906,20 @@ "ws": "~8.17.1" } }, + "node_modules/socket.io-client": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", @@ -4384,6 +4410,14 @@ } } }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package-lock.json b/package-lock.json index 56781ba..456d3fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "nodemon": "^3.0.2", "ntcore-ts-client": "^0.2.2", "socket.io": "^4.7.5", + "socket.io-client": "^4.8.1", "tslib": "^2.6.2", "uuid": "^9.0.1", "zod": "^3.23.4" @@ -1068,6 +1069,18 @@ "node": ">=10.2.0" } }, + "node_modules/engine.io-client": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", + "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, "node_modules/engine.io-parser": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", @@ -3940,6 +3953,20 @@ "ws": "~8.17.1" } }, + "node_modules/socket.io-client": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", @@ -4430,6 +4457,14 @@ } } }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index 14611e6..a96efdc 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "nodemon": "^3.0.2", "ntcore-ts-client": "^0.2.2", "socket.io": "^4.7.5", + "socket.io-client": "^4.8.1", "tslib": "^2.6.2", "uuid": "^9.0.1", "zod": "^3.23.4" From f7c57cd8fcc8e388e8fbdd6b8597e462a9916641 Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Tue, 15 Apr 2025 09:16:40 -0500 Subject: [PATCH 17/19] Enhance robot runtime display: update WebSocket listener and fetch function to include 'Runtime:' prefix in output --- assets/js/robot.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/assets/js/robot.js b/assets/js/robot.js index 9f6af85..511ff05 100644 --- a/assets/js/robot.js +++ b/assets/js/robot.js @@ -63,21 +63,25 @@ socket.on("pdhCurrents", (entry) => { // Add WebSocket listener for robotRuntime event socket.on("robotRuntime", (data) => { const runtimeDisplay = document.querySelector("div.runtime"); - runtimeDisplay.innerHTML = `Timestamp: ${data.timestamp}, Runtime: ${data.runtime} ms`; + runtimeDisplay.innerHTML = `Runtime: Timestamp: ${data.timestamp}, Runtime: ${data.runtime} ms`; }); async function fetchRuntime() { const runtimeDisplay = document.querySelector("div.runtime"); const response = await fetch("/runtime"); if (response.ok) { - runtimeDisplay.innerHTML = await response.text(); + runtimeDisplay.innerHTML = `Runtime: ${await response.text()}`; } else { console.error("Error fetching runtime data"); } } // Call the function to fetch runtime info on page load +// add a check to see if runtime data was fetched + fetchRuntime(); +const data = fetchRuntime(); +console.log("Fetched runtime data:", data); // Debugging statement async function fetchTemperatures() { const temperatures = document.querySelector("div.temp"); From 48f51c4ee62a2395851801e2fce5b72f4504dc47 Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Fri, 25 Apr 2025 09:29:22 -0500 Subject: [PATCH 18/19] Refactor socket initialization: ensure single declaration and attach to global window object --- assets/js/robot.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/assets/js/robot.js b/assets/js/robot.js index 511ff05..9f481ac 100644 --- a/assets/js/robot.js +++ b/assets/js/robot.js @@ -2,7 +2,12 @@ * contains client-side JavaScript functions * (primarily event handlers to fetch data from the Node server) */ -const socket = window.io(); + +// Ensure `socket` is declared only once and avoid redeclaration +if (!window.socket) { + window.socket = window.io(); // Attach `socket` to the global `window` object +} +const socket = window.socket; socket.on("temperatures", (entry) => { const temperatures = document.querySelector("div.temp"); @@ -15,6 +20,7 @@ socket.on("pdhCurrents", (entry) => { }); // new web socket connection for robot runtime data +// web dev code vid // Remove Chart.js setup and runtime graph logic // const ctx = document.getElementById("runtimeGraph").getContext("2d"); @@ -31,6 +37,7 @@ socket.on("pdhCurrents", (entry) => { // }, // ], // }, + // options: { // scales: { // x: { display: true }, From d408b914f2043da4c52cb5a3171223d6687889cb Mon Sep 17 00:00:00 2001 From: mmgokhale <117867154+mmgokhale@users.noreply.github.com> Date: Mon, 5 May 2025 09:33:31 -0500 Subject: [PATCH 19/19] Refactor socket initialization: ensure single declaration and remove redundant check --- assets/js/robot.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/js/robot.js b/assets/js/robot.js index 9f481ac..176d1af 100644 --- a/assets/js/robot.js +++ b/assets/js/robot.js @@ -4,9 +4,9 @@ */ // Ensure `socket` is declared only once and avoid redeclaration -if (!window.socket) { - window.socket = window.io(); // Attach `socket` to the global `window` object -} + +window.socket = window.io(); // Attach `socket` to the global `window` object + const socket = window.socket; socket.on("temperatures", (entry) => {