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 @@
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
+
+
+