added dynamic input based on graph
This commit is contained in:
parent
813f620b4d
commit
49af0ea3c9
3
app/.env
3
app/.env
|
@ -9,3 +9,6 @@ REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000
|
||||||
|
|
||||||
# Base URL for the server marketplace API.
|
# Base URL for the server marketplace API.
|
||||||
REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011
|
REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011
|
||||||
|
|
||||||
|
# base url for IoT socket server
|
||||||
|
REACT_APP_IOT_SOCKET_SERVER_URL =185.100.212.76:5010
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,6 +9,7 @@
|
||||||
"@react-three/drei": "^9.113.0",
|
"@react-three/drei": "^9.113.0",
|
||||||
"@react-three/fiber": "^8.17.7",
|
"@react-three/fiber": "^8.17.7",
|
||||||
"@react-three/postprocessing": "^2.16.3",
|
"@react-three/postprocessing": "^2.16.3",
|
||||||
|
"@recast-navigation/core": "^0.39.0",
|
||||||
"@recast-navigation/three": "^0.39.0",
|
"@recast-navigation/three": "^0.39.0",
|
||||||
"@testing-library/jest-dom": "^5.17.0",
|
"@testing-library/jest-dom": "^5.17.0",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
|
|
|
@ -18,7 +18,7 @@ const sampleData = {
|
||||||
{
|
{
|
||||||
data: [65, 59, 80, 81, 56, 55, 40],
|
data: [65, 59, 80, 81, 56, 55, 40],
|
||||||
backgroundColor: "#6f42c1",
|
backgroundColor: "#6f42c1",
|
||||||
borderColor: "#ffffff",
|
borderColor: "#b392f0",
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,115 +1,215 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
// import React, { useEffect, useState } from 'react'
|
||||||
import MultiLevelDropdown from '../../../../ui/inputs/MultiLevelDropDown'
|
// import MultiLevelDropdown from '../../../../ui/inputs/MultiLevelDropDown'
|
||||||
import { AddIcon } from '../../../../icons/ExportCommonIcons'
|
// import { AddIcon } from '../../../../icons/ExportCommonIcons'
|
||||||
import RegularDropDown from '../../../../ui/inputs/RegularDropDown'
|
// import RegularDropDown from '../../../../ui/inputs/RegularDropDown'
|
||||||
import useChartStore from '../../../../../store/useChartStore'
|
// import useChartStore from '../../../../../store/useChartStore'
|
||||||
import axios from 'axios'
|
// import axios from 'axios'
|
||||||
|
|
||||||
type Props = {}
|
// type Props = {}
|
||||||
|
|
||||||
const LineGrapInput = (props: Props) => {
|
// const LineGrapInput = (props: Props) => {
|
||||||
const [dropDowndata, setDropDownData] = useState({})
|
// const [dropDowndata, setDropDownData] = useState({})
|
||||||
const [selections, setSelections] = useState<Record<string, { name: string, fields: string }>>({})
|
// const [selections, setSelections] = useState<Record<string, { name: string, fields: string }>>({})
|
||||||
const [selectedOption, setSelectedOption] = useState('1h')
|
// const [selectedOption, setSelectedOption] = useState('1h')
|
||||||
const { measurements, setMeasurements, updateDuration, duration } = useChartStore();
|
// const { measurements, setMeasurements, updateDuration, duration } = useChartStore();
|
||||||
|
// const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
|
||||||
const handleSelectDuration = (option: string) => {
|
// const handleSelectDuration = (option: string) => {
|
||||||
updateDuration(option); // Normalize for key matching
|
// updateDuration(option); // Normalize for key matching
|
||||||
};
|
// };
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
const fetchZoneData = async () => {
|
// const fetchZoneData = async () => {
|
||||||
try {
|
// try {
|
||||||
const response = await axios.get('http://192.168.0.192:5010/getinput');
|
// const response = await axios.get(`http://${iotApiUrl}/getinput`);
|
||||||
if (response.status === 200) {
|
// if (response.status === 200) {
|
||||||
console.log('dropdown data:', response.data);
|
// console.log('dropdown data:', response.data);
|
||||||
setDropDownData(response.data)
|
// setDropDownData(response.data)
|
||||||
} else {
|
// } else {
|
||||||
console.log('Unexpected response:', response);
|
// console.log('Unexpected response:', response);
|
||||||
}
|
// }
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
console.error('There was an error!', error);
|
// console.error('There was an error!', error);
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
fetchZoneData();
|
// fetchZoneData();
|
||||||
}, []);
|
// }, []);
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
console.log(selections);
|
// console.log(selections);
|
||||||
}, [selections])
|
// }, [selections])
|
||||||
|
|
||||||
const handleSelect = (inputKey: string, selectedData: { name: string, fields: string } | null) => {
|
// const handleSelect = (inputKey: string, selectedData: { name: string, fields: string } | null) => {
|
||||||
setSelections(prev => {
|
// setSelections(prev => {
|
||||||
if (selectedData === null) {
|
// if (selectedData === null) {
|
||||||
const newSelections = { ...prev };
|
// const newSelections = { ...prev };
|
||||||
delete newSelections[inputKey];
|
// delete newSelections[inputKey];
|
||||||
return newSelections;
|
// return newSelections;
|
||||||
} else {
|
// } else {
|
||||||
return {
|
// return {
|
||||||
...prev,
|
// ...prev,
|
||||||
[inputKey]: selectedData
|
// [inputKey]: selectedData
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
};
|
// };
|
||||||
|
|
||||||
interface Measurement {
|
// interface Measurement {
|
||||||
name: string;
|
// name: string;
|
||||||
fields: string;
|
// fields: string;
|
||||||
}
|
// }
|
||||||
|
|
||||||
interface InputData {
|
// interface InputData {
|
||||||
[key: string]: Measurement;
|
// [key: string]: Measurement;
|
||||||
}
|
// }
|
||||||
|
|
||||||
const extractMeasurements = (input: InputData): Measurement[] => {
|
// const extractMeasurements = (input: InputData): Measurement[] => {
|
||||||
return Object.values(input);
|
// return Object.values(input);
|
||||||
};
|
// };
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
const measurementsData = extractMeasurements(selections);
|
// const measurementsData = extractMeasurements(selections);
|
||||||
setMeasurements(measurementsData);
|
// setMeasurements(measurementsData);
|
||||||
}, [selections]);
|
// }, [selections]);
|
||||||
|
|
||||||
|
|
||||||
return (
|
// return (
|
||||||
<>
|
// <>
|
||||||
<div className="inputs-wrapper">
|
// <div className="inputs-wrapper">
|
||||||
{[...Array(6)].map((_, index) => {
|
// {[...Array(6)].map((_, index) => {
|
||||||
const inputKey = `input${index + 1}`;
|
// const inputKey = `input${index + 1}`;
|
||||||
return (
|
// return (
|
||||||
<div key={index} className="datas">
|
// <div key={index} className="datas">
|
||||||
<div className="datas__label">Input {index + 1}</div>
|
// <div className="datas__label">Input {index + 1}</div>
|
||||||
<div className="datas__class">
|
// <div className="datas__class">
|
||||||
<MultiLevelDropdown
|
// <MultiLevelDropdown
|
||||||
data={dropDowndata}
|
// data={dropDowndata}
|
||||||
onSelect={(selectedData) => handleSelect(inputKey, selectedData)}
|
// onSelect={(selectedData) => handleSelect(inputKey, selectedData)}
|
||||||
onUnselect={() => handleSelect(inputKey, null)}
|
// onUnselect={() => handleSelect(inputKey, null)}
|
||||||
selectedValue={selections[inputKey]}
|
// selectedValue={selections[inputKey]}
|
||||||
/>
|
// />
|
||||||
<div className="icon">
|
// <div className="icon">
|
||||||
<AddIcon />
|
// <AddIcon />
|
||||||
</div>
|
// </div>
|
||||||
</div>
|
// </div>
|
||||||
</div>
|
// </div>
|
||||||
);
|
// );
|
||||||
})}
|
// })}
|
||||||
</div>
|
// </div>
|
||||||
<div>
|
// <div>
|
||||||
<div className="datas">
|
// <div className="datas">
|
||||||
<div className="datas__label">duration</div>
|
// <div className="datas__label">duration</div>
|
||||||
<div className="datas__class">
|
// <div className="datas__class">
|
||||||
<RegularDropDown
|
// <RegularDropDown
|
||||||
header={duration}
|
// header={duration}
|
||||||
options={["1h", "2h", "12h"]}
|
// options={["1h", "2h", "12h"]}
|
||||||
onSelect={handleSelectDuration}
|
// onSelect={handleSelectDuration}
|
||||||
search={false}
|
// search={false}
|
||||||
/>
|
// />
|
||||||
</div>
|
// </div>
|
||||||
</div>
|
// </div>
|
||||||
</div>
|
// </div>
|
||||||
</>
|
// </>
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
|
|
||||||
export default LineGrapInput
|
// export default LineGrapInput
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
|
import useChartStore from "../../../../../store/useChartStore";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
type Props = {};
|
||||||
|
|
||||||
|
const LineGrapInput = (props: Props) => {
|
||||||
|
const { measurements, setMeasurements, updateDuration, duration } = useChartStore();
|
||||||
|
|
||||||
|
const [dropDowndata, setDropDownData] = useState({});
|
||||||
|
const [selections, setSelections] = useState<Record<string, { name: string; fields: string }>>(measurements);
|
||||||
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchZoneData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`http://${iotApiUrl}/getinput`);
|
||||||
|
if (response.status === 200) {
|
||||||
|
console.log("dropdown data:", response.data);
|
||||||
|
setDropDownData(response.data);
|
||||||
|
} else {
|
||||||
|
console.log("Unexpected response:", response);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error!", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchZoneData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Sync Zustand state when component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
setSelections(measurements);
|
||||||
|
}, [measurements]);
|
||||||
|
|
||||||
|
const handleSelect = (inputKey: string, selectedData: { name: string; fields: string } | null) => {
|
||||||
|
setSelections((prev) => {
|
||||||
|
const newSelections = { ...prev };
|
||||||
|
if (selectedData === null) {
|
||||||
|
delete newSelections[inputKey];
|
||||||
|
} else {
|
||||||
|
newSelections[inputKey] = selectedData;
|
||||||
|
}
|
||||||
|
setMeasurements(newSelections); // Update Zustand store
|
||||||
|
return newSelections;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectDuration = (option: string) => {
|
||||||
|
updateDuration(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="inputs-wrapper">
|
||||||
|
{[...Array(6)].map((_, index) => {
|
||||||
|
const inputKey = `input${index + 1}`;
|
||||||
|
return (
|
||||||
|
<div key={index} className="datas">
|
||||||
|
<div className="datas__label">Input {index + 1}</div>
|
||||||
|
<div className="datas__class">
|
||||||
|
<MultiLevelDropdown
|
||||||
|
data={dropDowndata}
|
||||||
|
onSelect={(selectedData) => handleSelect(inputKey, selectedData)}
|
||||||
|
onUnselect={() => handleSelect(inputKey, null)}
|
||||||
|
selectedValue={selections[inputKey]} // Load from Zustand
|
||||||
|
/>
|
||||||
|
<div className="icon">
|
||||||
|
<AddIcon />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="datas">
|
||||||
|
<div className="datas__label">Duration</div>
|
||||||
|
<div className="datas__class">
|
||||||
|
<RegularDropDown
|
||||||
|
header={duration}
|
||||||
|
options={["1h", "2h", "12h"]}
|
||||||
|
onSelect={handleSelectDuration}
|
||||||
|
search={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LineGrapInput;
|
||||||
|
|
|
@ -8,11 +8,12 @@ type Props = {}
|
||||||
const PieChartInput = (props: Props) => {
|
const PieChartInput = (props: Props) => {
|
||||||
const [dropDowndata, setDropDownData] = useState({})
|
const [dropDowndata, setDropDownData] = useState({})
|
||||||
const [selections, setSelections] = useState<Record<string, {name: string, fields: string}>>({})
|
const [selections, setSelections] = useState<Record<string, {name: string, fields: string}>>({})
|
||||||
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchZoneData = async () => {
|
const fetchZoneData = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get('http://192.168.0.192:5010/getinput');
|
const response = await axios.get(`http://${iotApiUrl}/getinput`);
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
console.log('dropdown data:', response.data);
|
console.log('dropdown data:', response.data);
|
||||||
setDropDownData(response.data)
|
setDropDownData(response.data)
|
||||||
|
|
|
@ -237,14 +237,14 @@ export const DraggableWidget = ({
|
||||||
title={widget.title}
|
title={widget.title}
|
||||||
fontSize={widget.fontSize}
|
fontSize={widget.fontSize}
|
||||||
fontWeight={widget.fontWeight}
|
fontWeight={widget.fontWeight}
|
||||||
data={{
|
// data={{
|
||||||
measurements: [
|
// measurements: [
|
||||||
{ name: "testDevice", fields: "powerConsumption" },
|
// { name: "testDevice", fields: "powerConsumption" },
|
||||||
{ name: "furnace", fields: "powerConsumption" },
|
// { name: "furnace", fields: "powerConsumption" },
|
||||||
],
|
// ],
|
||||||
interval: 1000,
|
// interval: 1000,
|
||||||
duration: "1h",
|
// duration: "1h",
|
||||||
}}
|
// }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{widget.type === "bar" && (
|
{widget.type === "bar" && (
|
||||||
|
@ -253,14 +253,14 @@ export const DraggableWidget = ({
|
||||||
title={widget.title}
|
title={widget.title}
|
||||||
fontSize={widget.fontSize}
|
fontSize={widget.fontSize}
|
||||||
fontWeight={widget.fontWeight}
|
fontWeight={widget.fontWeight}
|
||||||
data={{
|
// data={{
|
||||||
measurements: [
|
// measurements: [
|
||||||
{ name: "testDevice", fields: "powerConsumption" },
|
// { name: "testDevice", fields: "powerConsumption" },
|
||||||
{ name: "furnace", fields: "powerConsumption" },
|
// { name: "furnace", fields: "powerConsumption" },
|
||||||
],
|
// ],
|
||||||
interval: 1000,
|
// interval: 1000,
|
||||||
duration: "1h",
|
// duration: "1h",
|
||||||
}}
|
// }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{widget.type === "pie" && (
|
{widget.type === "pie" && (
|
||||||
|
@ -269,14 +269,14 @@ export const DraggableWidget = ({
|
||||||
title={widget.title}
|
title={widget.title}
|
||||||
fontSize={widget.fontSize}
|
fontSize={widget.fontSize}
|
||||||
fontWeight={widget.fontWeight}
|
fontWeight={widget.fontWeight}
|
||||||
data={{
|
// data={{
|
||||||
measurements: [
|
// measurements: [
|
||||||
{ name: "testDevice", fields: "powerConsumption" },
|
// { name: "testDevice", fields: "powerConsumption" },
|
||||||
{ name: "furnace", fields: "powerConsumption" },
|
// { name: "furnace", fields: "powerConsumption" },
|
||||||
],
|
// ],
|
||||||
interval: 1000,
|
// interval: 1000,
|
||||||
duration: "1h",
|
// duration: "1h",
|
||||||
}}
|
// }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{widget.type === "doughnut" && (
|
{widget.type === "doughnut" && (
|
||||||
|
|
|
@ -1,6 +1,195 @@
|
||||||
import { useMemo } from "react";
|
// import React, { useEffect, useRef, useMemo, useState } from "react";
|
||||||
|
// import { Chart } from "chart.js/auto";
|
||||||
|
// import { useThemeStore } from "../../../../store/useThemeStore";
|
||||||
|
// import io from "socket.io-client";
|
||||||
|
// import { Bar } from 'react-chartjs-2';
|
||||||
|
// import useChartStore from "../../../../store/useChartStore";
|
||||||
|
|
||||||
|
// // WebSocket Connection
|
||||||
|
// // const socket = io("http://localhost:5000"); // Adjust to your backend URL
|
||||||
|
|
||||||
|
// interface ChartComponentProps {
|
||||||
|
// type: any;
|
||||||
|
// title: string;
|
||||||
|
// fontFamily?: string;
|
||||||
|
// fontSize?: string;
|
||||||
|
// fontWeight?: "Light" | "Regular" | "Bold";
|
||||||
|
// data: any;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const LineGraphComponent = ({
|
||||||
|
// type,
|
||||||
|
// title,
|
||||||
|
// fontFamily,
|
||||||
|
// fontSize,
|
||||||
|
// fontWeight = "Regular",
|
||||||
|
// data,
|
||||||
|
// }: ChartComponentProps) => {
|
||||||
|
// const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
// const { themeColor } = useThemeStore();
|
||||||
|
// const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
||||||
|
// labels: [],
|
||||||
|
// datasets: [],
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
|
||||||
|
// const defaultData = {
|
||||||
|
// labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
|
||||||
|
// datasets: [
|
||||||
|
// {
|
||||||
|
// label: "Dataset",
|
||||||
|
// data: [12, 19, 3, 5, 2, 3],
|
||||||
|
// backgroundColor: ["#6f42c1"],
|
||||||
|
// borderColor: "#ffffff",
|
||||||
|
// borderWidth: 2,
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // Memoize Theme Colors to Prevent Unnecessary Recalculations
|
||||||
|
// const buttonActionColor = useMemo(
|
||||||
|
// () => themeColor[0] || "#5c87df",
|
||||||
|
// [themeColor]
|
||||||
|
// );
|
||||||
|
// const buttonAbortColor = useMemo(
|
||||||
|
// () => themeColor[1] || "#ffffff",
|
||||||
|
// [themeColor]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Memoize Font Weight Mapping
|
||||||
|
// const chartFontWeightMap = useMemo(
|
||||||
|
// () => ({
|
||||||
|
// Light: "lighter" as const,
|
||||||
|
// Regular: "normal" as const,
|
||||||
|
// Bold: "bold" as const,
|
||||||
|
// }),
|
||||||
|
// []
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Parse and Memoize Font Size
|
||||||
|
// const fontSizeValue = useMemo(
|
||||||
|
// () => (fontSize ? parseInt(fontSize) : 12),
|
||||||
|
// [fontSize]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Determine and Memoize Font Weight
|
||||||
|
// const fontWeightValue = useMemo(
|
||||||
|
// () => chartFontWeightMap[fontWeight],
|
||||||
|
// [fontWeight, chartFontWeightMap]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Memoize Chart Font Style
|
||||||
|
// const chartFontStyle = useMemo(
|
||||||
|
// () => ({
|
||||||
|
// family: fontFamily || "Arial",
|
||||||
|
// size: fontSizeValue,
|
||||||
|
// weight: fontWeightValue,
|
||||||
|
// }),
|
||||||
|
// [fontFamily, fontSizeValue, fontWeightValue]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Memoize Chart Data
|
||||||
|
// // const data = useMemo(() => propsData, [propsData]);
|
||||||
|
|
||||||
|
// // Memoize Chart Options
|
||||||
|
// const options = useMemo(
|
||||||
|
// () => ({
|
||||||
|
// responsive: true,
|
||||||
|
// maintainAspectRatio: false,
|
||||||
|
// plugins: {
|
||||||
|
// title: {
|
||||||
|
// display: true,
|
||||||
|
// text: title,
|
||||||
|
// font: chartFontStyle,
|
||||||
|
// },
|
||||||
|
// legend: {
|
||||||
|
// display: false,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// scales: {
|
||||||
|
// x: {
|
||||||
|
// ticks: {
|
||||||
|
// display: true, // This hides the x-axis labels
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// }),
|
||||||
|
// [title, chartFontStyle]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const { measurements, setMeasurements, updateDuration, duration } = useChartStore();
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
|
||||||
|
// const socket = io(`http://${iotApiUrl}`);
|
||||||
|
|
||||||
|
// if ( measurements.length > 0 ) {
|
||||||
|
// var inputes = {
|
||||||
|
// measurements: measurements,
|
||||||
|
// duration: duration,
|
||||||
|
// interval: 1000,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Start stream
|
||||||
|
// const startStream = () => {
|
||||||
|
// socket.emit("lineInput", inputes);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// socket.on('connect', startStream);
|
||||||
|
|
||||||
|
// socket.on("lineOutput", (response) => {
|
||||||
|
// const responceData = response.data;
|
||||||
|
// console.log("Received data:", responceData);
|
||||||
|
|
||||||
|
// // Extract timestamps and values
|
||||||
|
// const labels = responceData.time;
|
||||||
|
// const datasets = measurements.map((measurement: any) => {
|
||||||
|
// const key = `${measurement.name}.${measurement.fields}`;
|
||||||
|
// return {
|
||||||
|
// label: key,
|
||||||
|
// data: responceData[key]?.values ?? [], // Ensure it exists
|
||||||
|
// backgroundColor: "#6f42c1",
|
||||||
|
// borderColor: "#ffffff",
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
|
// setChartData({ labels, datasets });
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return () => {
|
||||||
|
// socket.off("lineOutput");
|
||||||
|
// socket.emit("stop_stream"); // Stop streaming when component unmounts
|
||||||
|
// };
|
||||||
|
// }, [measurements, duration]);
|
||||||
|
|
||||||
|
// // useEffect(() => {
|
||||||
|
// // if (!canvasRef.current) return;
|
||||||
|
// // const ctx = canvasRef.current.getContext("2d");
|
||||||
|
// // if (!ctx) return;
|
||||||
|
|
||||||
|
// // const chart = new Chart(ctx, {
|
||||||
|
// // type,
|
||||||
|
// // data: chartData,
|
||||||
|
// // options: options,
|
||||||
|
// // });
|
||||||
|
|
||||||
|
// // return () => chart.destroy();
|
||||||
|
// // }, [chartData, type, title]);
|
||||||
|
|
||||||
|
// return <Bar data={measurements && measurements.length > 0 ? chartData : defaultData} options={options} />;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export default LineGraphComponent;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
import { Bar } from "react-chartjs-2";
|
import { Bar } from "react-chartjs-2";
|
||||||
|
import io from "socket.io-client";
|
||||||
|
import { useThemeStore } from "../../../../store/useThemeStore";
|
||||||
|
import useChartStore from "../../../../store/useChartStore";
|
||||||
|
|
||||||
interface ChartComponentProps {
|
interface ChartComponentProps {
|
||||||
type: any;
|
type: any;
|
||||||
|
@ -8,16 +197,42 @@ interface ChartComponentProps {
|
||||||
fontFamily?: string;
|
fontFamily?: string;
|
||||||
fontSize?: string;
|
fontSize?: string;
|
||||||
fontWeight?: "Light" | "Regular" | "Bold";
|
fontWeight?: "Light" | "Regular" | "Bold";
|
||||||
data: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const LineGraphComponent = ({
|
const BarGraphComponent = ({
|
||||||
|
type,
|
||||||
title,
|
title,
|
||||||
fontFamily,
|
fontFamily,
|
||||||
fontSize,
|
fontSize,
|
||||||
fontWeight = "Regular",
|
fontWeight = "Regular",
|
||||||
}: ChartComponentProps) => {
|
}: ChartComponentProps) => {
|
||||||
// Memoize Font Weight Mapping
|
const { themeColor } = useThemeStore();
|
||||||
|
const { measurements, duration } = useChartStore(); // Zustand Store
|
||||||
|
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
||||||
|
labels: [],
|
||||||
|
datasets: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
|
||||||
|
const defaultData = {
|
||||||
|
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Dataset",
|
||||||
|
data: [12, 19, 3, 5, 2, 3],
|
||||||
|
backgroundColor: ["#6f42c1"],
|
||||||
|
borderColor: "#b392f0",
|
||||||
|
borderWidth: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Memoize Theme Colors
|
||||||
|
const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]);
|
||||||
|
const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]);
|
||||||
|
|
||||||
|
// Memoize Font Styling
|
||||||
const chartFontWeightMap = useMemo(
|
const chartFontWeightMap = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
Light: "lighter" as const,
|
Light: "lighter" as const,
|
||||||
|
@ -27,19 +242,9 @@ const LineGraphComponent = ({
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Parse and Memoize Font Size
|
const fontSizeValue = useMemo(() => (fontSize ? parseInt(fontSize) : 12), [fontSize]);
|
||||||
const fontSizeValue = useMemo(
|
const fontWeightValue = useMemo(() => chartFontWeightMap[fontWeight], [fontWeight, chartFontWeightMap]);
|
||||||
() => (fontSize ? parseInt(fontSize) : 12),
|
|
||||||
[fontSize]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Determine and Memoize Font Weight
|
|
||||||
const fontWeightValue = useMemo(
|
|
||||||
() => chartFontWeightMap[fontWeight],
|
|
||||||
[fontWeight, chartFontWeightMap]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Memoize Chart Font Style
|
|
||||||
const chartFontStyle = useMemo(
|
const chartFontStyle = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
family: fontFamily || "Arial",
|
family: fontFamily || "Arial",
|
||||||
|
@ -49,6 +254,7 @@ const LineGraphComponent = ({
|
||||||
[fontFamily, fontSizeValue, fontWeightValue]
|
[fontFamily, fontSizeValue, fontWeightValue]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Memoized Chart Options
|
||||||
const options = useMemo(
|
const options = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
responsive: true,
|
responsive: true,
|
||||||
|
@ -66,7 +272,7 @@ const LineGraphComponent = ({
|
||||||
scales: {
|
scales: {
|
||||||
x: {
|
x: {
|
||||||
ticks: {
|
ticks: {
|
||||||
display: false, // This hides the x-axis labels
|
display: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -74,21 +280,53 @@ const LineGraphComponent = ({
|
||||||
[title, chartFontStyle]
|
[title, chartFontStyle]
|
||||||
);
|
);
|
||||||
|
|
||||||
const chartData = {
|
useEffect(() => {
|
||||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
label: "My First Dataset",
|
|
||||||
data: [65, 59, 80, 81, 56, 55, 40],
|
|
||||||
backgroundColor: "#6f42c1",
|
|
||||||
borderColor: "#ffffff",
|
|
||||||
borderWidth: 2,
|
|
||||||
fill: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
return <Bar data={chartData} options={options} />;
|
const socket = io(`http://${iotApiUrl}`);
|
||||||
|
|
||||||
|
const inputData = {
|
||||||
|
measurements,
|
||||||
|
duration,
|
||||||
|
interval: 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
const startStream = () => {
|
||||||
|
socket.emit("lineInput", inputData);
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.on("connect", startStream);
|
||||||
|
|
||||||
|
socket.on("lineOutput", (response) => {
|
||||||
|
const responseData = response.data;
|
||||||
|
console.log("Received data:", responseData);
|
||||||
|
|
||||||
|
// Extract timestamps and values
|
||||||
|
const labels = responseData.time;
|
||||||
|
const datasets = Object.keys(measurements).map((key) => {
|
||||||
|
const measurement = measurements[key];
|
||||||
|
const datasetKey = `${measurement.name}.${measurement.fields}`;
|
||||||
|
return {
|
||||||
|
label: datasetKey,
|
||||||
|
data: responseData[datasetKey]?.values ?? [],
|
||||||
|
backgroundColor: "#6f42c1",
|
||||||
|
borderColor: "#b392f0",
|
||||||
|
borderWidth: 1,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
setChartData({ labels, datasets });
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
socket.off("lineOutput");
|
||||||
|
socket.emit("stop_stream"); // Stop streaming when component unmounts
|
||||||
|
socket.disconnect();
|
||||||
|
};
|
||||||
|
}, [measurements, duration, iotApiUrl]);
|
||||||
|
|
||||||
|
return <Bar data={Object.keys(measurements).length > 0 ? chartData : defaultData} options={options} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LineGraphComponent;
|
export default BarGraphComponent;
|
||||||
|
|
||||||
|
|
|
@ -1,115 +1,15 @@
|
||||||
// import { useMemo } from "react";
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
// import { Line } from "react-chartjs-2";
|
import { Line } from "react-chartjs-2";
|
||||||
|
|
||||||
// interface ChartComponentProps {
|
|
||||||
// type: any;
|
|
||||||
// title: string;
|
|
||||||
// fontFamily?: string;
|
|
||||||
// fontSize?: string;
|
|
||||||
// fontWeight?: "Light" | "Regular" | "Bold";
|
|
||||||
// data: any;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const LineGraphComponent = ({
|
|
||||||
// title,
|
|
||||||
// fontFamily,
|
|
||||||
// fontSize,
|
|
||||||
// fontWeight = "Regular",
|
|
||||||
// }: ChartComponentProps) => {
|
|
||||||
// // Memoize Font Weight Mapping
|
|
||||||
// const chartFontWeightMap = useMemo(
|
|
||||||
// () => ({
|
|
||||||
// Light: "lighter" as const,
|
|
||||||
// Regular: "normal" as const,
|
|
||||||
// Bold: "bold" as const,
|
|
||||||
// }),
|
|
||||||
// []
|
|
||||||
// );
|
|
||||||
|
|
||||||
// // Parse and Memoize Font Size
|
|
||||||
// const fontSizeValue = useMemo(
|
|
||||||
// () => (fontSize ? parseInt(fontSize) : 12),
|
|
||||||
// [fontSize]
|
|
||||||
// );
|
|
||||||
|
|
||||||
// // Determine and Memoize Font Weight
|
|
||||||
// const fontWeightValue = useMemo(
|
|
||||||
// () => chartFontWeightMap[fontWeight],
|
|
||||||
// [fontWeight, chartFontWeightMap]
|
|
||||||
// );
|
|
||||||
|
|
||||||
// // Memoize Chart Font Style
|
|
||||||
// const chartFontStyle = useMemo(
|
|
||||||
// () => ({
|
|
||||||
// family: fontFamily || "Arial",
|
|
||||||
// size: fontSizeValue,
|
|
||||||
// weight: fontWeightValue,
|
|
||||||
// }),
|
|
||||||
// [fontFamily, fontSizeValue, fontWeightValue]
|
|
||||||
// );
|
|
||||||
|
|
||||||
// const options = useMemo(
|
|
||||||
// () => ({
|
|
||||||
// responsive: true,
|
|
||||||
// maintainAspectRatio: false,
|
|
||||||
// plugins: {
|
|
||||||
// title: {
|
|
||||||
// display: true,
|
|
||||||
// text: title,
|
|
||||||
// font: chartFontStyle,
|
|
||||||
// },
|
|
||||||
// legend: {
|
|
||||||
// display: false,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// scales: {
|
|
||||||
// x: {
|
|
||||||
// ticks: {
|
|
||||||
// display: true, // This hides the x-axis labels
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// }),
|
|
||||||
// [title, chartFontStyle]
|
|
||||||
// );
|
|
||||||
|
|
||||||
// const chartData = {
|
|
||||||
// labels: ["January", "February", "March", "April", "May", "June", "July"],
|
|
||||||
// datasets: [
|
|
||||||
// {
|
|
||||||
// label: "My First Dataset",
|
|
||||||
// data: [65, 59, 80, 81, 56, 55, 40],
|
|
||||||
// backgroundColor: "#6f42c1", // Updated to #6f42c1 (Purple)
|
|
||||||
// borderColor: "#ffffff", // Keeping border color white
|
|
||||||
// borderWidth: 2,
|
|
||||||
// fill: false,
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// };
|
|
||||||
|
|
||||||
// return <Line data={chartData} options={options} />;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// export default LineGraphComponent;
|
|
||||||
|
|
||||||
|
|
||||||
import React, { useEffect, useRef, useMemo, useState } from "react";
|
|
||||||
import { Chart } from "chart.js/auto";
|
|
||||||
import { useThemeStore } from "../../../../store/useThemeStore";
|
|
||||||
import io from "socket.io-client";
|
import io from "socket.io-client";
|
||||||
import { Line } from 'react-chartjs-2';
|
import { useThemeStore } from "../../../../store/useThemeStore";
|
||||||
import useChartStore from "../../../../store/useChartStore";
|
import useChartStore from "../../../../store/useChartStore";
|
||||||
|
|
||||||
// WebSocket Connection
|
|
||||||
// const socket = io("http://localhost:5000"); // Adjust to your backend URL
|
|
||||||
|
|
||||||
interface ChartComponentProps {
|
interface ChartComponentProps {
|
||||||
type: any;
|
type: any;
|
||||||
title: string;
|
title: string;
|
||||||
fontFamily?: string;
|
fontFamily?: string;
|
||||||
fontSize?: string;
|
fontSize?: string;
|
||||||
fontWeight?: "Light" | "Regular" | "Bold";
|
fontWeight?: "Light" | "Regular" | "Bold";
|
||||||
data: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const LineGraphComponent = ({
|
const LineGraphComponent = ({
|
||||||
|
@ -118,60 +18,55 @@ const LineGraphComponent = ({
|
||||||
fontFamily,
|
fontFamily,
|
||||||
fontSize,
|
fontSize,
|
||||||
fontWeight = "Regular",
|
fontWeight = "Regular",
|
||||||
data,
|
|
||||||
}: ChartComponentProps) => {
|
}: ChartComponentProps) => {
|
||||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
||||||
const { themeColor } = useThemeStore();
|
const { themeColor } = useThemeStore();
|
||||||
|
const { measurements, duration } = useChartStore(); // Zustand Store
|
||||||
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
||||||
labels: [],
|
labels: [],
|
||||||
datasets: [],
|
datasets: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Memoize Theme Colors to Prevent Unnecessary Recalculations
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
const buttonActionColor = useMemo(
|
|
||||||
() => themeColor[0] || "#5c87df",
|
const defaultData = {
|
||||||
[themeColor]
|
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
|
||||||
);
|
datasets: [
|
||||||
const buttonAbortColor = useMemo(
|
{
|
||||||
() => themeColor[1] || "#ffffff",
|
label: "Dataset",
|
||||||
[themeColor]
|
data: [12, 19, 3, 5, 2, 3],
|
||||||
);
|
backgroundColor: ["#6f42c1"],
|
||||||
|
borderColor: "#b392f0",
|
||||||
// Memoize Font Weight Mapping
|
borderWidth: 1,
|
||||||
const chartFontWeightMap = useMemo(
|
},
|
||||||
() => ({
|
],
|
||||||
Light: "lighter" as const,
|
};
|
||||||
Regular: "normal" as const,
|
|
||||||
Bold: "bold" as const,
|
// Memoize Theme Colors
|
||||||
}),
|
const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]);
|
||||||
[]
|
const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]);
|
||||||
);
|
|
||||||
|
// Memoize Font Styling
|
||||||
// Parse and Memoize Font Size
|
const chartFontWeightMap = useMemo(
|
||||||
const fontSizeValue = useMemo(
|
() => ({
|
||||||
() => (fontSize ? parseInt(fontSize) : 12),
|
Light: "lighter" as const,
|
||||||
[fontSize]
|
Regular: "normal" as const,
|
||||||
);
|
Bold: "bold" as const,
|
||||||
|
}),
|
||||||
// Determine and Memoize Font Weight
|
[]
|
||||||
const fontWeightValue = useMemo(
|
);
|
||||||
() => chartFontWeightMap[fontWeight],
|
|
||||||
[fontWeight, chartFontWeightMap]
|
const fontSizeValue = useMemo(() => (fontSize ? parseInt(fontSize) : 12), [fontSize]);
|
||||||
);
|
const fontWeightValue = useMemo(() => chartFontWeightMap[fontWeight], [fontWeight, chartFontWeightMap]);
|
||||||
|
|
||||||
// Memoize Chart Font Style
|
const chartFontStyle = useMemo(
|
||||||
const chartFontStyle = useMemo(
|
() => ({
|
||||||
() => ({
|
family: fontFamily || "Arial",
|
||||||
family: fontFamily || "Arial",
|
size: fontSizeValue,
|
||||||
size: fontSizeValue,
|
weight: fontWeightValue,
|
||||||
weight: fontWeightValue,
|
}),
|
||||||
}),
|
[fontFamily, fontSizeValue, fontWeightValue]
|
||||||
[fontFamily, fontSizeValue, fontWeightValue]
|
);
|
||||||
);
|
|
||||||
|
|
||||||
// Memoize Chart Data
|
|
||||||
// const data = useMemo(() => propsData, [propsData]);
|
|
||||||
|
|
||||||
// Memoize Chart Options
|
// Memoize Chart Options
|
||||||
const options = useMemo(
|
const options = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
@ -198,67 +93,54 @@ const LineGraphComponent = ({
|
||||||
[title, chartFontStyle]
|
[title, chartFontStyle]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { measurements, setMeasurements, updateDuration, duration } = useChartStore();
|
useEffect(() => {console.log(measurements);
|
||||||
|
},[measurements])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
|
||||||
|
|
||||||
const socket = io("http://192.168.0.192:5010");
|
const socket = io(`http://${iotApiUrl}`);
|
||||||
|
|
||||||
if ( measurements.length > 0 ) {
|
const inputData = {
|
||||||
var inputes = {
|
measurements,
|
||||||
measurements: measurements,
|
duration,
|
||||||
duration: duration,
|
interval: 1000,
|
||||||
interval: 1000,
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// Start stream
|
|
||||||
const startStream = () => {
|
const startStream = () => {
|
||||||
socket.emit("lineInput", inputes);
|
socket.emit("lineInput", inputData);
|
||||||
}
|
};
|
||||||
|
|
||||||
socket.on('connect', startStream);
|
socket.on("connect", startStream);
|
||||||
|
|
||||||
socket.on("lineOutput", (response) => {
|
socket.on("lineOutput", (response) => {
|
||||||
const responceData = response.data;
|
const responseData = response.data;
|
||||||
console.log("Received data:", responceData);
|
|
||||||
|
|
||||||
// Extract timestamps and values
|
// Extract timestamps and values
|
||||||
const labels = responceData.time;
|
const labels = responseData.time;
|
||||||
const datasets = measurements.map((measurement: any) => {
|
const datasets = Object.keys(measurements).map((key) => {
|
||||||
const key = `${measurement.name}.${measurement.fields}`;
|
const measurement = measurements[key];
|
||||||
|
const datasetKey = `${measurement.name}.${measurement.fields}`;
|
||||||
return {
|
return {
|
||||||
label: key,
|
label: datasetKey,
|
||||||
data: responceData[key]?.values ?? [], // Ensure it exists
|
data: responseData[datasetKey]?.values ?? [],
|
||||||
backgroundColor: themeColor[0] || "#5c87df",
|
backgroundColor: "#6f42c1",
|
||||||
borderColor: themeColor[1] || "#ffffff",
|
borderColor: "#b392f0",
|
||||||
|
borderWidth: 1,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
setChartData({ labels, datasets });
|
setChartData({ labels, datasets });
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
socket.off("lineOutput");
|
socket.off("lineOutput");
|
||||||
socket.emit("stop_stream"); // Stop streaming when component unmounts
|
socket.emit("stop_stream"); // Stop streaming when component unmounts
|
||||||
|
socket.disconnect();
|
||||||
};
|
};
|
||||||
}, [measurements, duration]);
|
}, [measurements, duration, iotApiUrl]);
|
||||||
|
|
||||||
// useEffect(() => {
|
return <Line data={Object.keys(measurements).length > 0 ? chartData : defaultData} options={options} />;
|
||||||
// if (!canvasRef.current) return;
|
|
||||||
// const ctx = canvasRef.current.getContext("2d");
|
|
||||||
// if (!ctx) return;
|
|
||||||
|
|
||||||
// const chart = new Chart(ctx, {
|
|
||||||
// type,
|
|
||||||
// data: chartData,
|
|
||||||
// options: options,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return () => chart.destroy();
|
|
||||||
// }, [chartData, type, title]);
|
|
||||||
|
|
||||||
return <Line data={chartData} options={options} />;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LineGraphComponent;
|
export default LineGraphComponent;
|
||||||
|
|
|
@ -1,5 +1,195 @@
|
||||||
import { useMemo } from "react";
|
// import React, { useEffect, useRef, useMemo, useState } from "react";
|
||||||
|
// import { Chart } from "chart.js/auto";
|
||||||
|
// import { useThemeStore } from "../../../../store/useThemeStore";
|
||||||
|
// import io from "socket.io-client";
|
||||||
|
// import { Pie } from 'react-chartjs-2';
|
||||||
|
// import useChartStore from "../../../../store/useChartStore";
|
||||||
|
|
||||||
|
// // WebSocket Connection
|
||||||
|
// // const socket = io("http://localhost:5000"); // Adjust to your backend URL
|
||||||
|
|
||||||
|
// interface ChartComponentProps {
|
||||||
|
// type: any;
|
||||||
|
// title: string;
|
||||||
|
// fontFamily?: string;
|
||||||
|
// fontSize?: string;
|
||||||
|
// fontWeight?: "Light" | "Regular" | "Bold";
|
||||||
|
// data: any;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const PieChartComponent = ({
|
||||||
|
// type,
|
||||||
|
// title,
|
||||||
|
// fontFamily,
|
||||||
|
// fontSize,
|
||||||
|
// fontWeight = "Regular",
|
||||||
|
// data,
|
||||||
|
// }: ChartComponentProps) => {
|
||||||
|
// const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
// const { themeColor } = useThemeStore();
|
||||||
|
// const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
||||||
|
// labels: [],
|
||||||
|
// datasets: [],
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
|
||||||
|
// const defaultData = {
|
||||||
|
// labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
|
||||||
|
// datasets: [
|
||||||
|
// {
|
||||||
|
// label: "Dataset",
|
||||||
|
// data: [12, 19, 3, 5, 2, 3],
|
||||||
|
// backgroundColor: ["#6f42c1"],
|
||||||
|
// borderColor: "#ffffff",
|
||||||
|
// borderWidth: 2,
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // Memoize Theme Colors to Prevent Unnecessary Recalculations
|
||||||
|
// const buttonActionColor = useMemo(
|
||||||
|
// () => themeColor[0] || "#6f42c1",
|
||||||
|
// [themeColor]
|
||||||
|
// );
|
||||||
|
// const buttonAbortColor = useMemo(
|
||||||
|
// () => themeColor[1] || "#ffffff",
|
||||||
|
// [themeColor]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Memoize Font Weight Mapping
|
||||||
|
// const chartFontWeightMap = useMemo(
|
||||||
|
// () => ({
|
||||||
|
// Light: "lighter" as const,
|
||||||
|
// Regular: "normal" as const,
|
||||||
|
// Bold: "bold" as const,
|
||||||
|
// }),
|
||||||
|
// []
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Parse and Memoize Font Size
|
||||||
|
// const fontSizeValue = useMemo(
|
||||||
|
// () => (fontSize ? parseInt(fontSize) : 12),
|
||||||
|
// [fontSize]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Determine and Memoize Font Weight
|
||||||
|
// const fontWeightValue = useMemo(
|
||||||
|
// () => chartFontWeightMap[fontWeight],
|
||||||
|
// [fontWeight, chartFontWeightMap]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Memoize Chart Font Style
|
||||||
|
// const chartFontStyle = useMemo(
|
||||||
|
// () => ({
|
||||||
|
// family: fontFamily || "Arial",
|
||||||
|
// size: fontSizeValue,
|
||||||
|
// weight: fontWeightValue,
|
||||||
|
// }),
|
||||||
|
// [fontFamily, fontSizeValue, fontWeightValue]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Memoize Chart Data
|
||||||
|
// // const data = useMemo(() => propsData, [propsData]);
|
||||||
|
|
||||||
|
// // Memoize Chart Options
|
||||||
|
// const options = useMemo(
|
||||||
|
// () => ({
|
||||||
|
// responsive: true,
|
||||||
|
// maintainAspectRatio: false,
|
||||||
|
// plugins: {
|
||||||
|
// title: {
|
||||||
|
// display: true,
|
||||||
|
// text: title,
|
||||||
|
// font: chartFontStyle,
|
||||||
|
// },
|
||||||
|
// legend: {
|
||||||
|
// display: false,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// scales: {
|
||||||
|
// // x: {
|
||||||
|
// // ticks: {
|
||||||
|
// // display: true, // This hides the x-axis labels
|
||||||
|
// // },
|
||||||
|
// // },
|
||||||
|
// },
|
||||||
|
// }),
|
||||||
|
// [title, chartFontStyle]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const { measurements, setMeasurements, updateDuration, duration } = useChartStore();
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
|
||||||
|
// const socket = io(`http://${iotApiUrl}`);
|
||||||
|
|
||||||
|
// if ( measurements.length > 0 ) {
|
||||||
|
// var inputes = {
|
||||||
|
// measurements: measurements,
|
||||||
|
// duration: duration,
|
||||||
|
// interval: 1000,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Start stream
|
||||||
|
// const startStream = () => {
|
||||||
|
// socket.emit("lineInput", inputes);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// socket.on('connect', startStream);
|
||||||
|
|
||||||
|
// socket.on("lineOutput", (response) => {
|
||||||
|
// const responceData = response.data;
|
||||||
|
// console.log("Received data:", responceData);
|
||||||
|
|
||||||
|
// // Extract timestamps and values
|
||||||
|
// const labels = responceData.time;
|
||||||
|
// const datasets = measurements.map((measurement: any) => {
|
||||||
|
// const key = `${measurement.name}.${measurement.fields}`;
|
||||||
|
// return {
|
||||||
|
// label: key,
|
||||||
|
// data: responceData[key]?.values ?? [], // Ensure it exists
|
||||||
|
// backgroundColor: "#6f42c1",
|
||||||
|
// borderColor: "#ffffff",
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
|
// setChartData({ labels, datasets });
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return () => {
|
||||||
|
// socket.off("lineOutput");
|
||||||
|
// socket.emit("stop_stream"); // Stop streaming when component unmounts
|
||||||
|
// };
|
||||||
|
// }, [measurements, duration]);
|
||||||
|
|
||||||
|
// // useEffect(() => {
|
||||||
|
// // if (!canvasRef.current) return;
|
||||||
|
// // const ctx = canvasRef.current.getContext("2d");
|
||||||
|
// // if (!ctx) return;
|
||||||
|
|
||||||
|
// // const chart = new Chart(ctx, {
|
||||||
|
// // type,
|
||||||
|
// // data: chartData,
|
||||||
|
// // options: options,
|
||||||
|
// // });
|
||||||
|
|
||||||
|
// // return () => chart.destroy();
|
||||||
|
// // }, [chartData, type, title]);
|
||||||
|
|
||||||
|
// return <Pie data={measurements && measurements.length > 0 ? chartData : defaultData} options={options} />;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export default PieChartComponent;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
import { Pie } from "react-chartjs-2";
|
import { Pie } from "react-chartjs-2";
|
||||||
|
import io from "socket.io-client";
|
||||||
|
import { useThemeStore } from "../../../../store/useThemeStore";
|
||||||
|
import useChartStore from "../../../../store/useChartStore";
|
||||||
|
|
||||||
interface ChartComponentProps {
|
interface ChartComponentProps {
|
||||||
type: any;
|
type: any;
|
||||||
|
@ -7,16 +197,42 @@ interface ChartComponentProps {
|
||||||
fontFamily?: string;
|
fontFamily?: string;
|
||||||
fontSize?: string;
|
fontSize?: string;
|
||||||
fontWeight?: "Light" | "Regular" | "Bold";
|
fontWeight?: "Light" | "Regular" | "Bold";
|
||||||
data: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PieChartComponent = ({
|
const PieChartComponent = ({
|
||||||
|
type,
|
||||||
title,
|
title,
|
||||||
fontFamily,
|
fontFamily,
|
||||||
fontSize,
|
fontSize,
|
||||||
fontWeight = "Regular",
|
fontWeight = "Regular",
|
||||||
}: ChartComponentProps) => {
|
}: ChartComponentProps) => {
|
||||||
// Memoize Font Weight Mapping
|
const { themeColor } = useThemeStore();
|
||||||
|
const { measurements, duration } = useChartStore(); // Zustand Store
|
||||||
|
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
||||||
|
labels: [],
|
||||||
|
datasets: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
|
||||||
|
const defaultData = {
|
||||||
|
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Dataset",
|
||||||
|
data: [12, 19, 3, 5, 2, 3],
|
||||||
|
backgroundColor: ["#6f42c1"],
|
||||||
|
borderColor: "#b392f0",
|
||||||
|
borderWidth: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Memoize Theme Colors
|
||||||
|
const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]);
|
||||||
|
const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]);
|
||||||
|
|
||||||
|
// Memoize Font Styling
|
||||||
const chartFontWeightMap = useMemo(
|
const chartFontWeightMap = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
Light: "lighter" as const,
|
Light: "lighter" as const,
|
||||||
|
@ -26,19 +242,9 @@ const PieChartComponent = ({
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Parse and Memoize Font Size
|
const fontSizeValue = useMemo(() => (fontSize ? parseInt(fontSize) : 12), [fontSize]);
|
||||||
const fontSizeValue = useMemo(
|
const fontWeightValue = useMemo(() => chartFontWeightMap[fontWeight], [fontWeight, chartFontWeightMap]);
|
||||||
() => (fontSize ? parseInt(fontSize) : 12),
|
|
||||||
[fontSize]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Determine and Memoize Font Weight
|
|
||||||
const fontWeightValue = useMemo(
|
|
||||||
() => chartFontWeightMap[fontWeight],
|
|
||||||
[fontWeight, chartFontWeightMap]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Memoize Chart Font Style
|
|
||||||
const chartFontStyle = useMemo(
|
const chartFontStyle = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
family: fontFamily || "Arial",
|
family: fontFamily || "Arial",
|
||||||
|
@ -48,12 +254,7 @@ const PieChartComponent = ({
|
||||||
[fontFamily, fontSizeValue, fontWeightValue]
|
[fontFamily, fontSizeValue, fontWeightValue]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Access the CSS variable for the primary accent color
|
// Memoized Chart Options
|
||||||
const accentColor = getComputedStyle(document.documentElement)
|
|
||||||
.getPropertyValue("--accent-color")
|
|
||||||
.trim();
|
|
||||||
|
|
||||||
console.log("accentColor: ", accentColor);
|
|
||||||
const options = useMemo(
|
const options = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
responsive: true,
|
responsive: true,
|
||||||
|
@ -68,24 +269,64 @@ const PieChartComponent = ({
|
||||||
display: false,
|
display: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
scales: {
|
||||||
|
// x: {
|
||||||
|
// ticks: {
|
||||||
|
// display: true,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
[title, chartFontStyle]
|
[title, chartFontStyle]
|
||||||
);
|
);
|
||||||
|
|
||||||
const chartData = {
|
useEffect(() => {
|
||||||
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
|
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
label: "Dataset",
|
|
||||||
data: [12, 19, 3, 5, 2, 3],
|
|
||||||
backgroundColor: ["#6f42c1"],
|
|
||||||
borderColor: "#ffffff",
|
|
||||||
borderWidth: 2,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
return <Pie data={chartData} options={options} />;
|
const socket = io(`http://${iotApiUrl}`);
|
||||||
|
|
||||||
|
const inputData = {
|
||||||
|
measurements,
|
||||||
|
duration,
|
||||||
|
interval: 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
const startStream = () => {
|
||||||
|
socket.emit("lineInput", inputData);
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.on("connect", startStream);
|
||||||
|
|
||||||
|
socket.on("lineOutput", (response) => {
|
||||||
|
const responseData = response.data;
|
||||||
|
console.log("Received data:", responseData);
|
||||||
|
|
||||||
|
// Extract timestamps and values
|
||||||
|
const labels = responseData.time;
|
||||||
|
const datasets = Object.keys(measurements).map((key) => {
|
||||||
|
const measurement = measurements[key];
|
||||||
|
const datasetKey = `${measurement.name}.${measurement.fields}`;
|
||||||
|
return {
|
||||||
|
label: datasetKey,
|
||||||
|
data: responseData[datasetKey]?.values ?? [],
|
||||||
|
backgroundColor: "#6f42c1",
|
||||||
|
borderColor: "#b392f0",
|
||||||
|
borderWidth: 1,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
setChartData({ labels, datasets });
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
socket.off("lineOutput");
|
||||||
|
socket.emit("stop_stream"); // Stop streaming when component unmounts
|
||||||
|
socket.disconnect();
|
||||||
|
};
|
||||||
|
}, [measurements, duration, iotApiUrl]);
|
||||||
|
|
||||||
|
return <Pie data={Object.keys(measurements).length > 0 ? chartData : defaultData} options={options} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PieChartComponent;
|
export default PieChartComponent;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ const MqttEvents = () => {
|
||||||
const { setTouch, setTemperature, setHumidity } = useDrieUIValue();
|
const { setTouch, setTemperature, setHumidity } = useDrieUIValue();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
const client = mqtt.connect("ws://192.168.0.192:1884", {
|
const client = mqtt.connect("ws://192.168.0.193:1884", {
|
||||||
username: "gabby",
|
username: "gabby",
|
||||||
password: "gabby"
|
password: "gabby"
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,15 +6,15 @@ interface Measurement {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MeasurementStore {
|
interface MeasurementStore {
|
||||||
measurements: Measurement[];
|
measurements: Record<string, Measurement>; // Change array to Record<string, Measurement>
|
||||||
interval: number;
|
interval: number;
|
||||||
duration: string;
|
duration: string;
|
||||||
setMeasurements: (newMeasurements: Measurement[]) => void;
|
setMeasurements: (newMeasurements: Record<string, Measurement>) => void;
|
||||||
updateDuration: (newDuration: string) => void;
|
updateDuration: (newDuration: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useChartStore = create<MeasurementStore>((set) => ({
|
const useChartStore = create<MeasurementStore>((set) => ({
|
||||||
measurements: [],
|
measurements: {}, // Initialize as an empty object
|
||||||
interval: 1000,
|
interval: 1000,
|
||||||
duration: "1h",
|
duration: "1h",
|
||||||
|
|
||||||
|
@ -26,3 +26,4 @@ const useChartStore = create<MeasurementStore>((set) => ({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export default useChartStore;
|
export default useChartStore;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue