Skip to content

Commit

Permalink
Merge pull request #41 from Ritika8081/main
Browse files Browse the repository at this point in the history
Formated code according to new arduino firmware.
  • Loading branch information
lorforlinux authored Sep 14, 2024
2 parents 2c4defc + d92eb39 commit b9d265b
Show file tree
Hide file tree
Showing 14 changed files with 303 additions and 148 deletions.
19 changes: 1 addition & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,7 @@ Chords is an application based on Web Serial connection, you can connect boards

- **Connection**: Experience a smooth connection/disconnection with board in single click.
- **Real-time Visualization**: Visualize incoming data without any jitter from the board in real-time on SmoothieCharts.
- **Recording**: Record the signals data in csv files, multiple instances can be recorded and downloaded as zip of csv's.
- **Bi Directional Communication**: We can also write data in the board, the table below shows what we recieve if sent data is:
<div>

| Sent Data | Data Received | Value |
| :-------: | ------------- | --------------------- |
| 'c' | Channel Count | 6 |
| 'n' | Board Name | "Arduino" |
| 's' | Sampling Rate | {125, 250, 500, 1000} |
| 'r' | Resolution | 10 |

</div>

## Compatible Browsers

| Feature | Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Safari iOS | Samsung Internet | WebView Android |
| ------- | ------ | ---- | ------- | ----- | ------ | -------------- | ------------------- | ---------- | ---------------- | --------------- |
||||||||||||
- **Recording**: Record the signals data and download data in csv file.

## How to use

Expand Down
124 changes: 108 additions & 16 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions public/CNAME
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
chords.upsidedownlabs.tech
7 changes: 3 additions & 4 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@
@apply bg-background text-foreground;
}
}
/* globals.css */

@layer utilities {
.text-gradient {
background: linear-gradient(to right, #f472b6, #a855f7, #3b82f6);
background: linear-gradient(to right, #f472b6, #a855f7, #1c1d1f);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
/* styles/globals.css */

.loader {
position: fixed;
top: 70%;
Expand All @@ -91,7 +91,6 @@
z-index: 9999; /* Ensure the loader is on top of other content */
}

/* styles/globals.css */
.spinner {
border: 4px solid rgba(0, 0, 0, 0.1);
border-radius: 50%;
Expand Down
1 change: 0 additions & 1 deletion src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ const SkeletonUI = () => (
const page = () => {
return (
<>
<Navbar />
<div className="flex flex-col">
<HeadSection />
<Separator className="mt-20" />
Expand Down
1 change: 0 additions & 1 deletion src/app/stream/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import SerialCheck from "../../components/SerialCheck";
const Page = () => {
return (
<div className="h-screen">
<Navbar />
<SerialCheck />
</div>
);
Expand Down
125 changes: 75 additions & 50 deletions src/components/Canvas.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"use client";

import React, {
useEffect,
useRef,
Expand All @@ -9,7 +10,6 @@ import React, {
import { SmoothieChart, TimeSeries } from "smoothie";
import { useTheme } from "next-themes";
import { BitSelection } from "./DataPass";
import html2canvas from "html2canvas";

interface CanvasProps {
data: string;
Expand All @@ -35,37 +35,8 @@ const Canvas: React.FC<CanvasProps> = ({
() => [],
[]
);
const [screenshotUrl, setScreenshotUrl] = useState<string | null>(null);
const gridRef = useRef<HTMLDivElement>(null);

const captureScreenshot = useCallback(() => {
if (gridRef.current) {
html2canvas(gridRef.current).then((canvas) => {
const url = canvas.toDataURL();
setScreenshotUrl(url);
});
}
}, []);

useEffect(() => {
setIsGlobalPaused(!isDisplay);

if (!isDisplay) {
captureScreenshot();
} else {
setScreenshotUrl(null);
}

chartRef.current.forEach((chart) => {
if (chart) {
if (isDisplay) {
chart.start();
} else {
chart.stop();
}
}
});
}, [isDisplay, captureScreenshot]);
const gridRef = useRef<HTMLDivElement>(null);

const getChannelColor = useCallback(
(index: number) => {
Expand Down Expand Up @@ -112,20 +83,26 @@ const Canvas: React.FC<CanvasProps> = ({
}, []);

const updateChartColors = useCallback(() => {
// Get the current theme colors
const colors = getThemeColors();

// Iterate through each chart in the chartRef array
chartRef.current.forEach((chart, index) => {
if (chart) {
// Update grid colors based on the theme
chart.options.grid = {
...chart.options.grid,
fillStyle: colors.background,
strokeStyle: colors.grid,
};

// Update label and title colors based on the theme
if (chart.options.labels && chart.options.title) {
chart.options.labels.fillStyle = colors.text;
chart.options.title.fillStyle = colors.text;
}

// Set scaling options for the chart
if (shouldAutoScale(selectedBits)) {
chart.options.maxValue = undefined;
chart.options.minValue = undefined;
Expand All @@ -134,6 +111,7 @@ const Canvas: React.FC<CanvasProps> = ({
chart.options.minValue = 0;
}

// Update the series with new color settings
const series = seriesRef.current[index];
if (series) {
chart.removeTimeSeries(series);
Expand All @@ -143,6 +121,7 @@ const Canvas: React.FC<CanvasProps> = ({
});
}

// Stream chart data to the corresponding canvas element
chart.streamTo(
document.getElementById(
`smoothie-chart-${index + 1}`
Expand All @@ -160,19 +139,25 @@ const Canvas: React.FC<CanvasProps> = ({
]);

const processBatch = useCallback(() => {
// Exit early if the batch buffer is empty or if global pause is active
if (batchBuffer.length === 0 || isGlobalPaused) return;

// Process each batch in the buffer
batchBuffer.forEach((batch) => {
// Iterate through each channel
channels.forEach((channel, index) => {
if (channel) {
// Retrieve the corresponding series for the channel
const series = seriesRef.current[index];
if (series && !isNaN(batch.values[index])) {
// Append the data point to the series if the value is valid
series.append(batch.time, batch.values[index]);
}
}
});
});

// Clear the batch buffer after processing
batchBuffer.length = 0;
}, [channels, batchBuffer, isGlobalPaused]);

Expand All @@ -199,6 +184,13 @@ const Canvas: React.FC<CanvasProps> = ({
}
}, [data, isChartInitialized, handleDataUpdate]);

// Updated to ensure colors are correctly applied when the theme changes
useEffect(() => {
if (isChartInitialized) {
updateChartColors(); // Apply the updated theme colors to the chart
}
}, [theme, isChartInitialized, updateChartColors]);

useEffect(() => {
const intervalId = setInterval(() => {
if (batchBuffer.length > 0 && isDisplay) {
Expand All @@ -213,21 +205,28 @@ const Canvas: React.FC<CanvasProps> = ({
}, [processBatch, batchBuffer, isDisplay]);

useEffect(() => {
// Check if the chart has not been initialized yet
if (!isChartInitialized) {
// Get the current theme colors for the chart
const colors = getThemeColors();

// Iterate over each channel to set up a chart
channels.forEach((channel, index) => {
if (channel) {
// Get the canvas element for the current channel
const canvas = document.getElementById(
`smoothie-chart-${index + 1}`
) as HTMLCanvasElement;

// Adjust canvas dimensions based on its parent element
const parentDiv = canvas.parentElement;
if (parentDiv) {
canvas.height = parentDiv.offsetHeight - 2;
canvas.height = parentDiv.offsetHeight - 2; // Subtracting 2 for margin/padding
canvas.width = parentDiv.offsetWidth;
}

if (canvas) {
// Create a new SmoothieChart instance with the current theme settings
const chart = new SmoothieChart({
responsive: true,
millisPerPixel: 4,
Expand All @@ -247,15 +246,20 @@ const Canvas: React.FC<CanvasProps> = ({
? undefined
: getMaxValue(selectedBits),
});

// Create a new TimeSeries instance for this chart
const series = new TimeSeries();

// Add the TimeSeries to the chart with specific styles
chart.addTimeSeries(series, {
strokeStyle: getChannelColor(index),
lineWidth: 1,
});

// Start streaming data to the canvas with a specified update interval
chart.streamTo(canvas, 500);

// Store references to the chart and series for later use
if (chartRef.current && seriesRef.current) {
chartRef.current[index] = chart;
seriesRef.current[index] = series;
Expand All @@ -264,6 +268,7 @@ const Canvas: React.FC<CanvasProps> = ({
}
});

// Mark the chart as initialized
setIsChartInitialized(true);
}
}, [
Expand All @@ -276,6 +281,28 @@ const Canvas: React.FC<CanvasProps> = ({
getChannelColor,
]);

useEffect(() => {
const resizeCanvas = () => {
channels.forEach((channel, index) => {
const canvas = document.getElementById(
`smoothie-chart-${index + 1}`
) as HTMLCanvasElement;

const parentDiv = canvas.parentElement;
if (parentDiv) {
canvas.height = parentDiv.offsetHeight - 2;
canvas.width = parentDiv.offsetWidth;
}
});
};

window.addEventListener("resize", resizeCanvas);

return () => {
window.removeEventListener("resize", resizeCanvas);
};
}, [channels]);

useEffect(() => {
if (isChartInitialized) {
chartRef.current.forEach((chart) => {
Expand Down Expand Up @@ -312,41 +339,39 @@ const Canvas: React.FC<CanvasProps> = ({
}, [theme, isChartInitialized, updateChartColors]);

return (
<div className="flex flex-col justify-center items-start px-4 m-4 h-[80vh]">
<div className="flex flex-col justify-center items-start px-4 m-2 sm:m-4 md:m-6 lg:m-8 h-[60vh] sm:h-[70vh] md:h-[80vh]">
<div
ref={gridRef}
className={`grid ${
isGridView ? "md:grid-cols-2 grid-cols-1" : "grid-cols-1"
} w-full h-full relative`}
style={{
backgroundColor:
theme === "dark" ? "hsl(222.2, 84%, 4.9%)" : "hsl(0, 0%, 100%)",
color:
theme === "dark" ? "hsl(210, 40%, 98%)" : "hsl(222.2, 84%, 4.9%)",
}}
>
{channels.map((channel, index) => {
if (channel) {
return (
<div
key={index}
className={`flex flex-col w-full relative h-full`}
className={`border border-secondary-foreground w-full ${
isGridView
? "h-[30vh] sm:h-[35vh] md:h-[40vh]"
: "h-[15vh] sm:h-[18vh] md:h-[20vh]"
} relative`}
>
<div
className={`border border-secondary-foreground w-full ${
isGridView ? "h-[40vh]" : "h-[20vh]"
} relative`}
>
<canvas
id={`smoothie-chart-${index + 1}`}
className="w-full h-full"
/>
</div>
<canvas
id={`smoothie-chart-${index + 1}`}
className="w-full h-full"
/>
</div>
);
}
return null;
})}
{screenshotUrl && (
<div
className="absolute top-0 left-0 w-full h-full bg-cover bg-center z-10"
style={{ backgroundImage: `url(${screenshotUrl})` }}
/>
)}
</div>
</div>
);
Expand Down
Loading

0 comments on commit b9d265b

Please sign in to comment.