Skip to content

Commit

Permalink
Merge pull request #47 from akadeepesh/main
Browse files Browse the repository at this point in the history
Fixing #45 #46
  • Loading branch information
lorforlinux authored Sep 24, 2024
2 parents 4c582ab + ff7995f commit c11cb57
Show file tree
Hide file tree
Showing 10 changed files with 329 additions and 298 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ Chords is an application based on Web Serial connection, you can connect boards
- [TypeScript](https://www.typescriptlang.org/): Statically typed superset of JavaScript.
- [Tailwind CSS](https://tailwindcss.com/): Utility-first CSS framework.
- [Shadcn UI](https://tailwindcss.com/): Provides Reusable and customizable components, built with radix UI.
- [Lodash](https://lodash.com/): Utility library for data manipulation, used for data throttling.
- [Smoothie Js](http://smoothiecharts.org/): Real time charting library.
- [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) Browser-based database for storing recorded data.

Expand Down
1 change: 0 additions & 1 deletion public/CNAME

This file was deleted.

163 changes: 107 additions & 56 deletions src/components/Canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,22 @@ const Canvas: React.FC<CanvasProps> = ({

const getChannelColor = useCallback(
(index: number) => {
const colorsDark = ["#FF4985", "#79E6F3", "#00FFC1", "#ccc"];
const colorsLight = ["#D10054", "#007A8C", "#008060", "#555555"];
const colorsDark = [
"#FF4985",
"#79E6F3",
"#00FFC1",
"#6EC207",
"#AD49E1",
"#E85C0D",
];
const colorsLight = [
"#D10054",
"#007A8C",
"#0A6847",
"#674188",
"#E65C19",
"#2E073F",
];
return theme === "dark"
? colorsDark[index] || colorsDark[colorsDark.length - 1]
: colorsLight[index] || colorsLight[colorsLight.length - 1];
Expand Down Expand Up @@ -83,6 +97,7 @@ const Canvas: React.FC<CanvasProps> = ({
const canvas = document.getElementById(
`smoothie-chart-${index + 1}`
) as HTMLCanvasElement;

const parentDiv = canvas?.parentElement;
if (parentDiv) {
canvas.height = parentDiv.offsetHeight - 2;
Expand All @@ -91,6 +106,7 @@ const Canvas: React.FC<CanvasProps> = ({
});
};

// Update chart options (colors and scaling)
const updateChartColors = useCallback(() => {
const colors = getThemeColors();
chartRef.current.forEach((chart, index) => {
Expand All @@ -105,12 +121,15 @@ const Canvas: React.FC<CanvasProps> = ({
chart.options.labels.fillStyle = colors.text;
}

// Set scaling options for the chart
if (shouldAutoScale(selectedBits)) {
chart.options.maxValue = undefined;
chart.options.minValue = undefined;
} else {
chart.options.maxValue = getMaxValue(selectedBits);
chart.options.minValue = 0;
chart.options.minValue = shouldAutoScale(selectedBits)
? undefined
: 0;
}

const series = seriesRef.current[index];
Expand Down Expand Up @@ -158,29 +177,21 @@ const Canvas: React.FC<CanvasProps> = ({
batchBuffer.length = 0;
}, [channels, batchBuffer, isGlobalPaused]);

// Improve the data update to handle data flow more consistently
const handleDataUpdate = useCallback(
(line: string) => {
if (line.trim() !== "" && isDisplay) {
const sensorValues = line.split(",").map(Number).slice(0);
const timestamp = Date.now();
batchBuffer.push({ time: timestamp, values: sensorValues });

// Process the batch buffer periodically or based on certain conditions
if (batchBuffer.length >= 10) {
// Example condition
processBatch();
if (batchBuffer.length >= 5) {
processBatch(); // Process batches more frequently
}
}
},
[batchBuffer, isDisplay, processBatch]
);
useEffect(() => {
const intervalId = setInterval(() => {
processBatch();
}, 1000); // Adjust the interval as needed

return () => clearInterval(intervalId);
}, [processBatch]);

useEffect(() => {
if (isChartInitialized) {
Expand All @@ -190,68 +201,78 @@ const Canvas: React.FC<CanvasProps> = ({
}, [data, isChartInitialized, handleDataUpdate]); // Check these dependencies

useEffect(() => {
// Initialize charts only when the number of channels (canvasCount) changes
const initializeCharts = () => {
const colors = getThemeColors();

// Clean up existing charts before initializing new ones
chartRef.current.forEach((chart, index) => {
if (chart) {
chart.stop(); // Stop the chart streaming
const series = seriesRef.current[index];
if (series) {
chart.removeTimeSeries(series);
}
}
});

// Re-initialize all channels
channels.forEach((_, index) => {
const canvas = document.getElementById(
`smoothie-chart-${index + 1}`
) as HTMLCanvasElement;

if (canvas) {
const chart =
chartRef.current[index] ||
new SmoothieChart({
responsive: true,
millisPerPixel: 4,
interpolation: "linear",
grid: {
fillStyle: colors.background,
strokeStyle: colors.grid,
borderVisible: true,
millisPerLine: 1000,
lineWidth: 1,
},
labels: {
fillStyle: colors.text,
},
minValue: shouldAutoScale(selectedBits) ? undefined : 0,
maxValue: shouldAutoScale(selectedBits)
? undefined
: getMaxValue(selectedBits),
});
const series = seriesRef.current[index] || new TimeSeries();
const chart = new SmoothieChart({
responsive: true,
millisPerPixel: 4,
interpolation: "bezier",
limitFPS: 100,
grid: {
fillStyle: colors.background,
strokeStyle: colors.grid,
borderVisible: true,
millisPerLine: 1000,
lineWidth: 1,
},
labels: {
fillStyle: colors.text,
},
minValue: shouldAutoScale(selectedBits) ? undefined : 0,
maxValue: shouldAutoScale(selectedBits)
? undefined
: getMaxValue(selectedBits),
});

if (!chartRef.current[index]) {
chartRef.current[index] = chart;
seriesRef.current[index] = series;
}
const series = new TimeSeries();
chartRef.current[index] = chart; // Store the chart
seriesRef.current[index] = series; // Store the series

chart.addTimeSeries(series, {
strokeStyle: getChannelColor(index),
lineWidth: 1,
});

chart.streamTo(canvas, 500);
chart.streamTo(canvas, 100); // Stream data to the canvas
}
});

setIsChartInitialized(true);
};

initializeCharts();
}, [
canvasCount,
getThemeColors,
getMaxValue,
shouldAutoScale,
getChannelColor,
channels,
]);
initializeCharts(); // Initialize when canvasCount changes
}, [canvasCount]); // Initialize charts only when canvasCount changes

// Update chart properties (theme, selectedBits) without reinitializing the charts
useEffect(() => {
updateChartColors();
}, [theme, updateChartColors]);
if (isChartInitialized) {
updateChartColors(); // Update chart properties (colors, max/min values, etc.)
}
}, [theme, selectedBits, isChartInitialized, updateChartColors]);

useEffect(() => {
if (isChartInitialized) {
updateChartColors();
}
}, [theme, isChartInitialized, updateChartColors]);

useEffect(() => {
setIsGlobalPaused(!isDisplay);
Expand All @@ -268,17 +289,47 @@ const Canvas: React.FC<CanvasProps> = ({
}, [isDisplay]);

useEffect(() => {
resizeCanvas(); // Force resize on channel changes

const handleResize = () => {
resizeCanvas();
};

// Add resize event listener
window.addEventListener("resize", handleResize);
resizeCanvas(); // Initial resize

// Cleanup the event listener when component unmounts or when dependencies change
return () => {
window.removeEventListener("resize", handleResize);
};
}, [channels]);
}, [canvasCount, channels]); // Dependencies include canvasCount and channels

useEffect(() => {
const updateChannels = () => {
channels.forEach((_, index) => {
if (chartRef.current[index]) {
const chart = chartRef.current[index];
chart.options.maxValue = shouldAutoScale(selectedBits)
? undefined
: getMaxValue(selectedBits);
chart.options.minValue = shouldAutoScale(selectedBits)
? undefined
: 0;

const series = seriesRef.current[index];
if (series) {
chart.removeTimeSeries(series);
chart.addTimeSeries(series, {
strokeStyle: getChannelColor(index),
lineWidth: 1,
});
}
}
});
};

updateChannels();
}, [canvasCount, selectedBits]);

const getHeightClass = (count: number) => {
switch (count) {
Expand Down
Loading

0 comments on commit c11cb57

Please sign in to comment.