更新清洗api链接
This commit is contained in:
@@ -88,35 +88,53 @@ const fetchFromBackend = async (
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const ids = deviceIds.join(",");
|
const device_ids = deviceIds.join(",");
|
||||||
const starttime = dayjs(range.from).format("YYYY-MM-DD HH:mm:ss");
|
const start_time = dayjs(range.from).toISOString();
|
||||||
const endtime = dayjs(range.to).format("YYYY-MM-DD HH:mm:ss");
|
const end_time = dayjs(range.to).toISOString();
|
||||||
// 清洗数据接口
|
// 清洗数据接口
|
||||||
const cleaningSCADAUrl = `${config.BACKEND_URL}/querycleaningscadadatabydeviceidandtimerange/?ids=${ids}&starttime=${starttime}&endtime=${endtime}`;
|
const cleaningDataUrl = `${config.BACKEND_URL}/timescaledb/scada/by-ids-field-time-range?device_ids=${device_ids}&field=cleaned_value&start_time=${start_time}&end_time=${end_time}`;
|
||||||
// 原始数据
|
// 原始数据
|
||||||
const rawSCADAUrl = `${config.BACKEND_URL}/queryscadadatabydeviceidandtimerange/?ids=${ids}&starttime=${starttime}&endtime=${endtime}`;
|
const rawDataUrl = `${config.BACKEND_URL}/timescaledb/scada/by-ids-field-time-range?device_ids=${device_ids}&field=monitored_value&start_time=${start_time}&end_time=${end_time}`;
|
||||||
// 模拟数据接口
|
// 模拟数据接口
|
||||||
const simulationSCADAUrl = `${config.BACKEND_URL}/querysimulationscadadatabydeviceidandtimerange/?ids=${ids}&starttime=${starttime}&endtime=${endtime}`;
|
const simulationDataUrl = `${config.BACKEND_URL}/timescaledb/composite/scada-simulation?device_ids=${device_ids}&start_time=${start_time}&end_time=${end_time}`;
|
||||||
try {
|
|
||||||
let response;
|
|
||||||
response = await fetch(cleaningSCADAUrl);
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
|
||||||
}
|
|
||||||
const data = await response.json();
|
|
||||||
let transformedData = transformBackendData(data, deviceIds);
|
|
||||||
|
|
||||||
// 如果清洗数据接口返回空结果,使用原始数据接口
|
try {
|
||||||
if (transformedData.length === 0) {
|
// 优先查询清洗数据和模拟数据
|
||||||
console.log("[SCADADataPanel] 清洗数据接口无结果,使用原始数据接口");
|
const [cleaningRes, simulationRes] = await Promise.all([
|
||||||
response = await fetch(rawSCADAUrl);
|
fetch(cleaningDataUrl)
|
||||||
if (!response.ok) {
|
.then((r) => (r.ok ? r.json() : null))
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
.catch(() => null),
|
||||||
}
|
fetch(simulationDataUrl)
|
||||||
const data = await response.json();
|
.then((r) => (r.ok ? r.json() : null))
|
||||||
transformedData = transformBackendData(data, deviceIds);
|
.catch(() => null),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const cleaningData = transformBackendData(cleaningRes, deviceIds);
|
||||||
|
const simulationData = transformBackendData(simulationRes, deviceIds);
|
||||||
|
|
||||||
|
// 如果清洗数据有数据,返回清洗和模拟数据
|
||||||
|
if (cleaningData.length > 0) {
|
||||||
|
return mergeTimeSeriesData(
|
||||||
|
cleaningData,
|
||||||
|
simulationData,
|
||||||
|
deviceIds,
|
||||||
|
"clean",
|
||||||
|
"sim"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// 如果清洗数据没有数据,查询原始数据,返回模拟和原始数据
|
||||||
|
const rawRes = await fetch(rawDataUrl)
|
||||||
|
.then((r) => (r.ok ? r.json() : null))
|
||||||
|
.catch(() => null);
|
||||||
|
const rawData = transformBackendData(rawRes, deviceIds);
|
||||||
|
return mergeTimeSeriesData(
|
||||||
|
simulationData,
|
||||||
|
rawData,
|
||||||
|
deviceIds,
|
||||||
|
"sim",
|
||||||
|
"raw"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return transformedData;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[SCADADataPanel] 从后端获取数据失败:", error);
|
console.error("[SCADADataPanel] 从后端获取数据失败:", error);
|
||||||
throw error;
|
throw error;
|
||||||
@@ -178,6 +196,48 @@ const transformBackendData = (
|
|||||||
return [];
|
return [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并两个时间序列数据,为每个设备添加后缀
|
||||||
|
*/
|
||||||
|
const mergeTimeSeriesData = (
|
||||||
|
data1: TimeSeriesPoint[],
|
||||||
|
data2: TimeSeriesPoint[],
|
||||||
|
deviceIds: string[],
|
||||||
|
suffix1: string,
|
||||||
|
suffix2: string
|
||||||
|
): TimeSeriesPoint[] => {
|
||||||
|
const timeMap = new Map<string, Record<string, number | null>>();
|
||||||
|
|
||||||
|
const processData = (data: TimeSeriesPoint[], suffix: string) => {
|
||||||
|
data.forEach((point) => {
|
||||||
|
if (!timeMap.has(point.timestamp)) {
|
||||||
|
timeMap.set(point.timestamp, {});
|
||||||
|
}
|
||||||
|
const values = timeMap.get(point.timestamp)!;
|
||||||
|
deviceIds.forEach((deviceId) => {
|
||||||
|
const value = point.values[deviceId];
|
||||||
|
if (value !== undefined) {
|
||||||
|
values[`${deviceId}_${suffix}`] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
processData(data1, suffix1);
|
||||||
|
processData(data2, suffix2);
|
||||||
|
|
||||||
|
const result = Array.from(timeMap.entries()).map(([timestamp, values]) => ({
|
||||||
|
timestamp,
|
||||||
|
values,
|
||||||
|
}));
|
||||||
|
|
||||||
|
result.sort(
|
||||||
|
(a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
const defaultFetcher = fetchFromBackend;
|
const defaultFetcher = fetchFromBackend;
|
||||||
|
|
||||||
const formatTimestamp = (timestamp: string) =>
|
const formatTimestamp = (timestamp: string) =>
|
||||||
@@ -220,7 +280,11 @@ const buildDataset = (
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
deviceIds.forEach((id) => {
|
deviceIds.forEach((id) => {
|
||||||
const value = point.values[id];
|
const value =
|
||||||
|
point.values[`${id}_clean`] ??
|
||||||
|
point.values[`${id}_raw`] ??
|
||||||
|
point.values[`${id}_sim`] ??
|
||||||
|
point.values[id];
|
||||||
entry[id] =
|
entry[id] =
|
||||||
typeof value === "number"
|
typeof value === "number"
|
||||||
? Number.isFinite(value)
|
? Number.isFinite(value)
|
||||||
@@ -269,23 +333,26 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
|
|||||||
deviceIds: string[],
|
deviceIds: string[],
|
||||||
range: { from: Date; to: Date }
|
range: { from: Date; to: Date }
|
||||||
): Promise<TimeSeriesPoint[]> => {
|
): Promise<TimeSeriesPoint[]> => {
|
||||||
const ids = deviceIds.join(",");
|
const device_ids = deviceIds.join(",");
|
||||||
const starttime = dayjs(range.from).format("YYYY-MM-DD HH:mm:ss");
|
const start_time = dayjs(range.from).toISOString();
|
||||||
const endtime = dayjs(range.to).format("YYYY-MM-DD HH:mm:ss");
|
const end_time = dayjs(range.to).toISOString();
|
||||||
|
|
||||||
const cleaningUrl = `${config.BACKEND_URL}/querycleaningscadadatabydeviceidandtimerange/?ids=${ids}&starttime=${starttime}&endtime=${endtime}`;
|
// 清洗数据接口
|
||||||
const rawUrl = `${config.BACKEND_URL}/queryscadadatabydeviceidandtimerange/?ids=${ids}&starttime=${starttime}&endtime=${endtime}`;
|
const cleaningDataUrl = `${config.BACKEND_URL}/timescaledb/scada/by-ids-field-time-range?device_ids=${device_ids}&field=cleaned_value&start_time=${start_time}&end_time=${end_time}`;
|
||||||
const simUrl = `${config.BACKEND_URL}/querysimulationscadadatabydeviceidandtimerange/?ids=${ids}&starttime=${starttime}&endtime=${endtime}`;
|
// 原始数据
|
||||||
|
const rawDataUrl = `${config.BACKEND_URL}/timescaledb/scada/by-ids-field-time-range?device_ids=${device_ids}&field=monitored_value&start_time=${start_time}&end_time=${end_time}`;
|
||||||
|
// 模拟数据接口
|
||||||
|
const simulationDataUrl = `${config.BACKEND_URL}/timescaledb/composite/scada-simulation?device_ids=${device_ids}&start_time=${start_time}&end_time=${end_time}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const [cleanRes, rawRes, simRes] = await Promise.all([
|
const [cleanRes, rawRes, simRes] = await Promise.all([
|
||||||
fetch(cleaningUrl)
|
fetch(cleaningDataUrl)
|
||||||
.then((r) => (r.ok ? r.json() : null))
|
.then((r) => (r.ok ? r.json() : null))
|
||||||
.catch(() => null),
|
.catch(() => null),
|
||||||
fetch(rawUrl)
|
fetch(rawDataUrl)
|
||||||
.then((r) => (r.ok ? r.json() : null))
|
.then((r) => (r.ok ? r.json() : null))
|
||||||
.catch(() => null),
|
.catch(() => null),
|
||||||
fetch(simUrl)
|
fetch(simulationDataUrl)
|
||||||
.then((r) => (r.ok ? r.json() : null))
|
.then((r) => (r.ok ? r.json() : null))
|
||||||
.catch(() => null),
|
.catch(() => null),
|
||||||
]);
|
]);
|
||||||
@@ -442,21 +509,16 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const { from: rangeFrom, to: rangeTo } = normalizedRange;
|
const { from: rangeFrom, to: rangeTo } = normalizedRange;
|
||||||
const startTime = dayjs(rangeFrom).format("YYYY-MM-DD HH:mm:ss");
|
const startTime = dayjs(rangeFrom).toISOString();
|
||||||
const endTime = dayjs(rangeTo).format("YYYY-MM-DD HH:mm:ss");
|
const endTime = dayjs(rangeTo).toISOString();
|
||||||
|
|
||||||
// 调用后端清洗接口
|
// 调用后端清洗接口
|
||||||
const response = await axios.post(
|
const response = await axios.post(
|
||||||
`${config.BACKEND_URL}/scadadevicedatacleaning/`,
|
`${
|
||||||
null,
|
config.BACKEND_URL
|
||||||
{
|
}/timescaledb/composite/clean-scada?device_ids=${deviceIds.join(
|
||||||
params: {
|
","
|
||||||
ids_list: deviceIds.join(","), // 修改:将数组转为逗号分隔字符串
|
)}&start_time=${startTime}&end_time=${endTime}`
|
||||||
start_time: startTime,
|
|
||||||
end_time: endTime,
|
|
||||||
user_name: user.name,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("[SCADADataPanel] 清洗响应:", response.data);
|
console.log("[SCADADataPanel] 清洗响应:", response.data);
|
||||||
|
|||||||
Reference in New Issue
Block a user