+ {subTypeList.map((st) => (
+
+ {
+ if (e.target.checked) {
+ if (!selectedSubTypeList.includes(st)) {
+ setSelectedSubTypeList([...selectedSubTypeList, st]);
+ console.log(selectedSubTypeList);
+ }
+ } else {
+ setSelectedSubTypeList(selectedSubTypeList.filter((item) => item !== st));
+ }
+ }}
+ />
+
+
+ ))}
+
+ );
+}
+
+export default SubtypeSelector;
diff --git a/gs/frontend/mcc/src/pages/Telemetry/components/TelemetryChart.tsx b/gs/frontend/mcc/src/pages/Telemetry/components/TelemetryChart.tsx
new file mode 100644
index 000000000..4f09aa6fc
--- /dev/null
+++ b/gs/frontend/mcc/src/pages/Telemetry/components/TelemetryChart.tsx
@@ -0,0 +1,72 @@
+import { Chart } from 'react-chartjs-2';
+import {
+ Chart as ChartJS,
+ LineElement,
+ PointElement,
+ LinearScale,
+ Title,
+ CategoryScale,
+ Legend,
+ Tooltip,
+} from 'chart.js';
+
+ChartJS.register(LineElement, PointElement, LinearScale, Title, CategoryScale, Legend, Tooltip);
+
+import type { TelemetryDataType } from '../../../utils/mockTelemetryData';
+
+type TelemetryChartProps = {
+ type: string;
+ telemetryData: TelemetryDataType[];
+};
+
+const COLORS = [
+ 'rgba(255, 99, 132, 1)',
+ 'rgba(54, 162, 235, 1)',
+ 'rgba(255, 206, 86, 1)',
+ 'rgba(75, 192, 192, 1)',
+ 'rgba(153, 102, 255, 1)',
+ 'rgba(255, 159, 64, 1)',
+];
+
+/**
+ * @brief Component for displaying selected telemetry data of the as a line chart.
+ */
+function TelemetryChart({ type, telemetryData }: TelemetryChartProps) {
+ const allTimestamps = telemetryData[0]?.datapoints.map(d => d.timestamp) || [];
+
+ const data = {
+ labels: allTimestamps,
+ datasets: telemetryData.map((entry, idx) => {
+ const subtype = entry.type;
+ return {
+ label: subtype,
+ data: entry.datapoints.map(d => d.value),
+ borderColor: COLORS[idx % COLORS.length],
+ backgroundColor: COLORS[idx % COLORS.length],
+ fill: false,
+ tension: 0.2,
+ };
+ }),
+ };
+
+ const options = {
+ responsive: true,
+ plugins: {
+ legend: { position: 'top' as const },
+ title: { display: true, text: `${type} Telemetry` },
+ },
+ // TODO: Update axes titles and formatting to match real telemetry data
+ scales: {
+ x: { title: { display: true, text: 'Timestamp' } },
+ y: { title: { display: true, text: 'Value' } },
+ },
+ };
+
+ return (
+
+
+ {telemetryTypes.map((t, i) => (
+ <>
+
+ {i !== telemetryTypes.length - 1 && (
+ |
+ )}
+ >
+ ))}
+
+
+ );
+}
+
+export default TypeSelector;
diff --git a/gs/frontend/mcc/src/utils/mockTelemetryData.ts b/gs/frontend/mcc/src/utils/mockTelemetryData.ts
new file mode 100644
index 000000000..79a04f28c
--- /dev/null
+++ b/gs/frontend/mcc/src/utils/mockTelemetryData.ts
@@ -0,0 +1,142 @@
+// Mock telemetry data for testing and developing the telemetry page.
+// This includes telemetry types, subtypes, and sample data points.
+// Currently, format of this data may not match real telemetry data structure - refactor as needed.
+
+export const telemetryTypes = ["Current", "Voltage", "Motor"];
+
+export const currentSubtypes = ["3v3", "5v", "12v"];
+export const voltageSubtypes = ["3v3", "5v", "7v"];
+export const motorSubtypes = ["Motor A", "Motor B", "Motor C"];
+
+export const telemetrySubtypes: { [key: string]: string[] } = {
+ Current: currentSubtypes,
+ Voltage: voltageSubtypes,
+ Motor: motorSubtypes,
+};
+
+
+export type TelemetryDataType = {
+ session: string;
+ telemetry: string;
+ type: string; // e.g. '3v3', '5v', 'Motor A'
+ packet: string;
+ datapoints: Array<{ timestamp: number; value: number }>;
+};
+
+
+export const telemetryData: { [type: string]: TelemetryDataType[] } = {
+ Current: [
+ {
+ session: "Session A",
+ telemetry: "Telemetry 1",
+ type: "3v3",
+ packet: "Packet Data 1",
+ datapoints: [
+ { timestamp: 1, value: 0.5 },
+ { timestamp: 2, value: 0.7 },
+ { timestamp: 3, value: 0.6 },
+ { timestamp: 4, value: 0.8 },
+ ],
+ },
+ {
+ session: "Session B",
+ telemetry: "Telemetry 2",
+ type: "5v",
+ packet: "Packet Data 2",
+ datapoints: [
+ { timestamp: 1, value: 1.2 },
+ { timestamp: 2, value: 1.1 },
+ { timestamp: 3, value: 1.3 },
+ { timestamp: 4, value: 1.4 },
+ ],
+ },
+ {
+ session: "Session C",
+ telemetry: "Telemetry 3",
+ type: "12v",
+ packet: "Packet Data 3",
+ datapoints: [
+ { timestamp: 1, value: 2.0 },
+ { timestamp: 2, value: 2.1 },
+ { timestamp: 3, value: 2.2 },
+ { timestamp: 4, value: 2.3 },
+ ],
+ },
+ ],
+ Voltage: [
+ {
+ session: "Session D",
+ telemetry: "Telemetry 4",
+ type: "3v3",
+ packet: "Packet Data 4",
+ datapoints: [
+ { timestamp: 1, value: 3.3 },
+ { timestamp: 2, value: 3.2 },
+ { timestamp: 3, value: 3.4 },
+ { timestamp: 4, value: 3.3 },
+ ],
+ },
+ {
+ session: "Session E",
+ telemetry: "Telemetry 5",
+ type: "5v",
+ packet: "Packet Data 5",
+ datapoints: [
+ { timestamp: 1, value: 5.0 },
+ { timestamp: 2, value: 5.1 },
+ { timestamp: 3, value: 5.0 },
+ { timestamp: 4, value: 5.2 },
+ ],
+ },
+ {
+ session: "Session F",
+ telemetry: "Telemetry 6",
+ type: "7v",
+ packet: "Packet Data 6",
+ datapoints: [
+ { timestamp: 1, value: 7.0 },
+ { timestamp: 2, value: 7.1 },
+ { timestamp: 3, value: 7.2 },
+ { timestamp: 4, value: 7.1 },
+ ],
+ },
+ ],
+ Motor: [
+ {
+ session: "Session G",
+ telemetry: "Telemetry 7",
+ type: "Motor A",
+ packet: "Packet Data 7",
+ datapoints: [
+ { timestamp: 1, value: 100 },
+ { timestamp: 2, value: 110 },
+ { timestamp: 3, value: 120 },
+ { timestamp: 4, value: 130 },
+ ],
+ },
+ {
+ session: "Session H",
+ telemetry: "Telemetry 8",
+ type: "Motor B",
+ packet: "Packet Data 8",
+ datapoints: [
+ { timestamp: 1, value: 90 },
+ { timestamp: 2, value: 95 },
+ { timestamp: 3, value: 92 },
+ { timestamp: 4, value: 98 },
+ ],
+ },
+ {
+ session: "Session I",
+ telemetry: "Telemetry 9",
+ type: "Motor C",
+ packet: "Packet Data 9",
+ datapoints: [
+ { timestamp: 1, value: 80 },
+ { timestamp: 2, value: 85 },
+ { timestamp: 3, value: 88 },
+ { timestamp: 4, value: 87 },
+ ],
+ },
+ ],
+};
diff --git a/gs/frontend/mcc/src/utils/nav-links.ts b/gs/frontend/mcc/src/utils/nav-links.ts
index cf2cd65e1..49e3b4d56 100644
--- a/gs/frontend/mcc/src/utils/nav-links.ts
+++ b/gs/frontend/mcc/src/utils/nav-links.ts
@@ -24,4 +24,8 @@ export const NAVIGATION_LINKS: NavLink[] = [
text: "Live Sessions",
url: "/live-sessions",
},
+ {
+ text: "Telemetry",
+ url: "/telemetry",
+ },
];