diff --git a/src/main/ipcRouter.js b/src/main/ipcRouter.js index cc73f9d..ccc965e 100644 --- a/src/main/ipcRouter.js +++ b/src/main/ipcRouter.js @@ -3,7 +3,8 @@ import dgram from 'dgram' import net from 'net' import { IPC_EVENT } from '../renderer/src/common/ipcEvents.js' import fs from 'fs' - +const TIMEOUT = 10000 // 10秒超时 +const END_SEQUENCE = '\n\n' // 消息结束标志 // 全局保存所有TCP连接和相关信息 const tcpClients = new Map() // 保存待处理的请求,用于关联响应 @@ -13,7 +14,24 @@ export function registerIpRouter() { ipcMain.on(IPC_EVENT.DEVICE_SEARCH, searchDevice) ipcMain.on(IPC_EVENT.DEVICE_CONNECT, connectDevice) ipcMain.on(IPC_EVENT.DEVICE_DISCONNECT, disconnectDevice) - ipcMain.handle(IPC_EVENT.SENSORS_GET, sensorLoad) // 改为handle,支持异步返回 + ipcMain.handle(IPC_EVENT.SENSORS_GET, sensorLoad) // 获取传感器 + ipcMain.handle(IPC_EVENT.SENSORS_SET, sensorSet) // 传感器设置处理 + ipcMain.handle(IPC_EVENT.IMAGE_SEND_TIME_GET, imageSendTimeGet) + ipcMain.handle(IPC_EVENT.IMAGE_SEND_TIME_SET, imageSendTimeSet) + // 其他基本参数GET处理 + ipcMain.handle(IPC_EVENT.ZERO_COUNT_GET, zeroCountGet) + ipcMain.handle(IPC_EVENT.RESULT_COUNT_GET, resultCountGet) + ipcMain.handle(IPC_EVENT.DATA_FPS_GET, dataFpsGet) + ipcMain.handle(IPC_EVENT.VIDEO_FPS_GET, videoFpsGet) + ipcMain.handle(IPC_EVENT.THRESHOLD_GET, thresholdGet) + ipcMain.handle(IPC_EVENT.INVALID_DATA_COUNT_GET, invalidDataCountGet) + // 其他基本参数SET处理 + ipcMain.handle(IPC_EVENT.ZERO_COUNT_SET, zeroCountSet) + ipcMain.handle(IPC_EVENT.RESULT_COUNT_SET, resultCountSet) + ipcMain.handle(IPC_EVENT.DATA_FPS_SET, dataFpsSet) + ipcMain.handle(IPC_EVENT.VIDEO_FPS_SET, videoFpsSet) + ipcMain.handle(IPC_EVENT.THRESHOLD_SET, thresholdSet) + ipcMain.handle(IPC_EVENT.INVALID_DATA_COUNT_SET, invalidDataCountSet) } const searchDevice = (event) => { @@ -143,7 +161,7 @@ const disconnectDevice = (event, { ip }) => { } // 处理TCP响应 -const handleTcpResponse = (ip, msg) => { +const handleTcpResponse = async (ip, msg) => { const connectionInfo = tcpClients.get(ip) if (!connectionInfo) return @@ -159,11 +177,182 @@ const handleTcpResponse = (ip, msg) => { const sensorRequest = pendingRequests.get(`${ip}${IPC_EVENT.SENSORS_GET}`) if (sensorRequest) { // 响应传感器加载请求 + await delay() sensorRequest.resolve({ success: true, data: msg }) pendingRequests.delete(`${ip}${IPC_EVENT.SENSORS_GET}`) } } break + case IPC_EVENT.SENSORS_SET: + { + const sensorSetRequest = pendingRequests.get(`${ip}${IPC_EVENT.SENSORS_SET}`) + if (sensorSetRequest) { + // 响应传感器设置请求 + await delay() + sensorSetRequest.resolve({ success: true, data: msg }) + pendingRequests.delete(`${ip}${IPC_EVENT.SENSORS_SET}`) + } + } + break + case IPC_EVENT.IMAGE_SEND_TIME_GET: + { + const imageTimeRequest = pendingRequests.get(`${ip}${IPC_EVENT.IMAGE_SEND_TIME_GET}`) + if (imageTimeRequest) { + // 响应图像发送间隔获取请求 + await delay() + console.log(msg) + imageTimeRequest.resolve({ success: true, data: msg }) + + pendingRequests.delete(`${ip}${IPC_EVENT.IMAGE_SEND_TIME_GET}`) + } + } + break + case IPC_EVENT.IMAGE_SEND_TIME_SET: + { + const imageTimeRequest = pendingRequests.get(`${ip}${IPC_EVENT.IMAGE_SEND_TIME_SET}`) + if (imageTimeRequest) { + // 响应图像发送间隔设置请求 + await delay() + console.log(msg) + imageTimeRequest.resolve({ success: true, data: msg }) + pendingRequests.delete(`${ip}${IPC_EVENT.IMAGE_SEND_TIME_SET}`) + } + } + break + // 其他基本参数GET响应处理 + case IPC_EVENT.ZERO_COUNT_GET: + { + const paramRequest = pendingRequests.get(`${ip}${IPC_EVENT.ZERO_COUNT_GET}`) + if (paramRequest) { + await delay() + console.log(msg) + paramRequest.resolve({ success: true, data: msg }) + pendingRequests.delete(`${ip}${IPC_EVENT.ZERO_COUNT_GET}`) + } + } + break + case IPC_EVENT.RESULT_COUNT_GET: + { + const paramRequest = pendingRequests.get(`${ip}${IPC_EVENT.RESULT_COUNT_GET}`) + if (paramRequest) { + await delay() + console.log(msg) + paramRequest.resolve({ success: true, data: msg }) + pendingRequests.delete(`${ip}${IPC_EVENT.RESULT_COUNT_GET}`) + } + } + break + case IPC_EVENT.DATA_FPS_GET: + { + const paramRequest = pendingRequests.get(`${ip}${IPC_EVENT.DATA_FPS_GET}`) + if (paramRequest) { + await delay() + console.log(msg) + paramRequest.resolve({ success: true, data: msg }) + pendingRequests.delete(`${ip}${IPC_EVENT.DATA_FPS_GET}`) + } + } + break + case IPC_EVENT.VIDEO_FPS_GET: + { + const paramRequest = pendingRequests.get(`${ip}${IPC_EVENT.VIDEO_FPS_GET}`) + if (paramRequest) { + await delay() + console.log(msg) + paramRequest.resolve({ success: true, data: msg }) + pendingRequests.delete(`${ip}${IPC_EVENT.VIDEO_FPS_GET}`) + } + } + break + case IPC_EVENT.THRESHOLD_GET: + { + const paramRequest = pendingRequests.get(`${ip}${IPC_EVENT.THRESHOLD_GET}`) + if (paramRequest) { + await delay() + console.log(msg) + paramRequest.resolve({ success: true, data: msg }) + pendingRequests.delete(`${ip}${IPC_EVENT.THRESHOLD_GET}`) + } + } + break + case IPC_EVENT.INVALID_DATA_COUNT_GET: + { + const paramRequest = pendingRequests.get(`${ip}${IPC_EVENT.INVALID_DATA_COUNT_GET}`) + if (paramRequest) { + await delay() + console.log(msg) + paramRequest.resolve({ success: true, data: msg }) + pendingRequests.delete(`${ip}${IPC_EVENT.INVALID_DATA_COUNT_GET}`) + } + } + break + // 其他基本参数SET响应处理 + case IPC_EVENT.ZERO_COUNT_SET: + { + const paramRequest = pendingRequests.get(`${ip}${IPC_EVENT.ZERO_COUNT_SET}`) + if (paramRequest) { + await delay() + console.log(msg) + paramRequest.resolve({ success: true, data: msg }) + pendingRequests.delete(`${ip}${IPC_EVENT.ZERO_COUNT_SET}`) + } + } + break + case IPC_EVENT.RESULT_COUNT_SET: + { + const paramRequest = pendingRequests.get(`${ip}${IPC_EVENT.RESULT_COUNT_SET}`) + if (paramRequest) { + await delay() + console.log(msg) + paramRequest.resolve({ success: true, data: msg }) + pendingRequests.delete(`${ip}${IPC_EVENT.RESULT_COUNT_SET}`) + } + } + break + case IPC_EVENT.DATA_FPS_SET: + { + const paramRequest = pendingRequests.get(`${ip}${IPC_EVENT.DATA_FPS_SET}`) + if (paramRequest) { + await delay() + console.log(msg) + paramRequest.resolve({ success: true, data: msg }) + pendingRequests.delete(`${ip}${IPC_EVENT.DATA_FPS_SET}`) + } + } + break + case IPC_EVENT.VIDEO_FPS_SET: + { + const paramRequest = pendingRequests.get(`${ip}${IPC_EVENT.VIDEO_FPS_SET}`) + if (paramRequest) { + await delay() + console.log(msg) + paramRequest.resolve({ success: true, data: msg }) + pendingRequests.delete(`${ip}${IPC_EVENT.VIDEO_FPS_SET}`) + } + } + break + case IPC_EVENT.THRESHOLD_SET: + { + const paramRequest = pendingRequests.get(`${ip}${IPC_EVENT.THRESHOLD_SET}`) + if (paramRequest) { + await delay() + console.log(msg) + paramRequest.resolve({ success: true, data: msg }) + pendingRequests.delete(`${ip}${IPC_EVENT.THRESHOLD_SET}`) + } + } + break + case IPC_EVENT.INVALID_DATA_COUNT_SET: + { + const paramRequest = pendingRequests.get(`${ip}${IPC_EVENT.INVALID_DATA_COUNT_SET}`) + if (paramRequest) { + await delay() + console.log(msg) + paramRequest.resolve({ success: true, data: msg }) + pendingRequests.delete(`${ip}${IPC_EVENT.INVALID_DATA_COUNT_SET}`) + } + } + break case IPC_EVENT.HEARTBEAT_REPLY: // 心跳处理 break @@ -173,7 +362,7 @@ const handleTcpResponse = (ip, msg) => { } } -// 传感器加载 - 改为异步处理 +// 传感器加载 const sensorLoad = async (event, { ip }) => { return new Promise((resolve, reject) => { const connectionInfo = tcpClients.get(ip) @@ -189,7 +378,7 @@ const sensorLoad = async (event, { ip }) => { const timeout = setTimeout(() => { pendingRequests.delete(requestKey) resolve({ success: false, error: '请求超时' }) - }, 10000) // 10秒超时 + }, TIMEOUT) // 10秒超时 // 保存请求信息 pendingRequests.set(requestKey, { @@ -206,7 +395,7 @@ const sensorLoad = async (event, { ip }) => { // 发送传感器加载命令 const command = { command: 'sensors', type: 'get', values: '' } - const message = JSON.stringify(command) + '\n\n' + const message = JSON.stringify(command) + END_SEQUENCE connectionInfo.client.write(message, (err) => { if (err) { @@ -217,15 +406,632 @@ const sensorLoad = async (event, { ip }) => { }) }) } +// 传感器设置 +const sensorSet = async (event, { ip, sensors }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return + } -// 清理指定IP的所有待处理请求 -const clearPendingRequestsByIp = (ip) => { - const keysToDelete = [] - for (const [key, request] of pendingRequests) { - if (key.startsWith(`${ip}_`)) { - request.resolve({ success: false, error: '连接已断开' }) - keysToDelete.push(key) + // 生成请求ID并保存待处理请求 + const requestKey = `${ip}${IPC_EVENT.SENSORS_SET}` + + // 设置超时 + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) // 10秒超时 + + // 保存请求信息 + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + // 发送传感器设置命令 + const command = { command: 'sensors', type: 'set', values: sensors } + const message = JSON.stringify(command) + END_SEQUENCE + + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} +// 图像发送间隔获取 +const imageSendTimeGet = async (event, { ip }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return } - } - keysToDelete.forEach((key) => pendingRequests.delete(key)) + + // 生成请求ID并保存待处理请求 + const requestKey = `${ip}${IPC_EVENT.IMAGE_SEND_TIME_GET}` + + // 设置超时 + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) // 10秒超时 + + // 保存请求信息 + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + // 发送图像发送间隔获取命令 + const command = { command: 'imageSendTime', type: 'get', values: '' } + const message = JSON.stringify(command) + END_SEQUENCE + + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} +// 图像发送间隔设置 +const imageSendTimeSet = async (event, { ip, value }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return + } + + // 生成请求ID并保存待处理请求 + const requestKey = `${ip}${IPC_EVENT.IMAGE_SEND_TIME_SET}` + + // 设置超时 + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) // 10秒超时 + + // 保存请求信息 + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + // 发送图像发送间隔设置命令 + const command = { command: 'imageSendTime', type: 'set', values: value } + const message = JSON.stringify(command) + END_SEQUENCE + + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} + +// zeroCount获取 +const zeroCountGet = async (event, { ip }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return + } + + const requestKey = `${ip}${IPC_EVENT.ZERO_COUNT_GET}` + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) + + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + const command = { command: 'zeroCount', type: 'get', values: '' } + const message = JSON.stringify(command) + END_SEQUENCE + + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} + +// zeroCount设置 +const zeroCountSet = async (event, { ip, value }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return + } + + const requestKey = `${ip}${IPC_EVENT.ZERO_COUNT_SET}` + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) + + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + const command = { command: 'zeroCount', type: 'set', values: value } + const message = JSON.stringify(command) + END_SEQUENCE + + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} + +// resultCount获取 +const resultCountGet = async (event, { ip }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return + } + + const requestKey = `${ip}${IPC_EVENT.RESULT_COUNT_GET}` + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) + + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + const command = { command: 'resultCount', type: 'get', values: '' } + const message = JSON.stringify(command) + END_SEQUENCE + + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} + +// resultCount设置 +const resultCountSet = async (event, { ip, value }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return + } + + const requestKey = `${ip}${IPC_EVENT.RESULT_COUNT_SET}` + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) + + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + const command = { command: 'resultCount', type: 'set', values: value } + const message = JSON.stringify(command) + END_SEQUENCE + + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} + +// dataFps获取 +const dataFpsGet = async (event, { ip }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return + } + + const requestKey = `${ip}${IPC_EVENT.DATA_FPS_GET}` + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) + + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + const command = { command: 'dataFps', type: 'get', values: '' } + const message = JSON.stringify(command) + END_SEQUENCE + + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} + +// dataFps设置 +const dataFpsSet = async (event, { ip, value }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return + } + + const requestKey = `${ip}${IPC_EVENT.DATA_FPS_SET}` + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) + + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + const command = { command: 'dataFps', type: 'set', values: value } + const message = JSON.stringify(command) + END_SEQUENCE + console.log('Sending command:', message) + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} + +// videoFps获取 +const videoFpsGet = async (event, { ip }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return + } + + const requestKey = `${ip}${IPC_EVENT.VIDEO_FPS_GET}` + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) + + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + const command = { command: 'videoFps', type: 'get', values: '' } + const message = JSON.stringify(command) + END_SEQUENCE + + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} + +// videoFps设置 +const videoFpsSet = async (event, { ip, value }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return + } + + const requestKey = `${ip}${IPC_EVENT.VIDEO_FPS_SET}` + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) + + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + const command = { command: 'videoFps', type: 'set', values: value } + const message = JSON.stringify(command) + END_SEQUENCE + + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} + +// threshold获取 +const thresholdGet = async (event, { ip }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return + } + + const requestKey = `${ip}${IPC_EVENT.THRESHOLD_GET}` + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) + + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + const command = { command: 'threshold', type: 'get', values: '' } + const message = JSON.stringify(command) + END_SEQUENCE + + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} + +// threshold设置 +const thresholdSet = async (event, { ip, value }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return + } + + const requestKey = `${ip}${IPC_EVENT.THRESHOLD_SET}` + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) + + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + const command = { command: 'threshold', type: 'set', values: value } + const message = JSON.stringify(command) + END_SEQUENCE + + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} + +// invalidDataCount获取 +const invalidDataCountGet = async (event, { ip }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return + } + + const requestKey = `${ip}${IPC_EVENT.INVALID_DATA_COUNT_GET}` + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) + + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + const command = { command: 'invalidDataCount', type: 'get', values: '' } + const message = JSON.stringify(command) + END_SEQUENCE + + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} + +// invalidDataCount设置 +const invalidDataCountSet = async (event, { ip, value }) => { + return new Promise((resolve, reject) => { + const connectionInfo = tcpClients.get(ip) + if (!connectionInfo) { + resolve({ success: false, error: '设备未连接' }) + return + } + + const requestKey = `${ip}${IPC_EVENT.INVALID_DATA_COUNT_SET}` + const timeout = setTimeout(() => { + pendingRequests.delete(requestKey) + resolve({ success: false, error: '请求超时' }) + }, TIMEOUT) + + pendingRequests.set(requestKey, { + resolve: (result) => { + clearTimeout(timeout) + resolve(result) + }, + reject: (error) => { + clearTimeout(timeout) + reject(error) + }, + timestamp: Date.now() + }) + + const command = { command: 'invalidDataCount', type: 'set', values: value } + const message = JSON.stringify(command) + END_SEQUENCE + + connectionInfo.client.write(message, (err) => { + if (err) { + pendingRequests.delete(requestKey) + clearTimeout(timeout) + resolve({ success: false, error: err.message }) + } + }) + }) +} + +// 清理指定IP的所有待处理请求 +const clearPendingRequestsByIp = (ip) => { + const keysToDelete = [] + for (const [key, request] of pendingRequests) { + if (key.startsWith(`${ip}_`)) { + request.resolve({ success: false, error: '连接已断开' }) + keysToDelete.push(key) + } + } + keysToDelete.forEach((key) => pendingRequests.delete(key)) +} + +//模拟延迟函数 +const delay = () => { + return new Promise((resolve) => setTimeout(resolve, 1000)) } diff --git a/src/renderer/src/common/ipcEvents.js b/src/renderer/src/common/ipcEvents.js index 2e51b1a..dc7d460 100644 --- a/src/renderer/src/common/ipcEvents.js +++ b/src/renderer/src/common/ipcEvents.js @@ -10,5 +10,24 @@ export const IPC_EVENT = { RESULT_REPLY: 'result:reply', // 传感器数据 IMAGE_REPLY: 'image:reply', // 图像数据 HEARTBEAT_REPLY: 'heartbeat:reply', // 心跳包 - SENSORS_GET: 'sensors:get' // 加载传感器配置 + SENSORS_GET: 'sensors:get', // 加载传感器配置 + SENSORS_SET: 'sensors:set', // 加载传感器配置 + + // 基本参数相关,GET + IMAGE_SEND_TIME_GET: 'imageSendTime:get', + ZERO_COUNT_GET: 'zeroCount:get', + RESULT_COUNT_GET: 'resultCount:get', + DATA_FPS_GET: 'dataFps:get', + VIDEO_FPS_GET: 'videoFps:get', + THRESHOLD_GET: 'threshold:get', + INVALID_DATA_COUNT_GET: 'invalidDataCount:get', + + // 基本参数相关,SET + IMAGE_SEND_TIME_SET: 'imageSendTime:set', + ZERO_COUNT_SET: 'zeroCount:set', + RESULT_COUNT_SET: 'resultCount:set', + DATA_FPS_SET: 'dataFps:set', + VIDEO_FPS_SET: 'videoFps:set', + THRESHOLD_SET: 'threshold:set', + INVALID_DATA_COUNT_SET: 'invalidDataCount:set' } diff --git a/src/renderer/src/components/DeflectionCollection/DeflectionCollection.jsx b/src/renderer/src/components/DeflectionCollection/DeflectionCollection.jsx index 036b0fa..17caeb2 100644 --- a/src/renderer/src/components/DeflectionCollection/DeflectionCollection.jsx +++ b/src/renderer/src/components/DeflectionCollection/DeflectionCollection.jsx @@ -1,3 +1,6 @@ +import { useEffect, useState } from 'react' +import { IPC_EVENT } from '../../common/ipcEvents' +import useDeviceStore from '../../stores/deviceStore' import { Line } from 'react-chartjs-2' import { Chart as ChartJS, @@ -13,65 +16,111 @@ import { FileTextOutlined, ClockCircleOutlined, EyeOutlined } from '@ant-design/ ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend) -function randomAround(base, delta) { - return base + Math.round((Math.random() * 2 - 1) * delta) -} - -function getTimeLabels(count) { - const now = new Date() - return Array.from({ length: count }).map((_, i) => { - const d = new Date(now.getTime() - (count - 1 - i) * 2 * 1000) - return d.toTimeString().slice(0, 8) - }) -} - function DeflectionCollection() { - const count = 10 - const targetCount = 5 // 支持多个target + // 传感器数据状态 - 最多保存10个时间点的数据 + const [sensorDataHistory, setSensorDataHistory] = useState([]) + + // 获取设备连接状态 + const connectedDevice = useDeviceStore((state) => state.connectedDevice) - // 为每个target生成颜色 + // 为每个传感器生成颜色 const targetColors = [ 'rgba(75,192,192,1)', // 青色 'rgba(255,99,132,1)', // 红色 'rgba(54,162,235,1)', // 蓝色 'rgba(255,206,86,1)', // 黄色 - 'rgba(153,102,255,1)' // 紫色 + 'rgba(153,102,255,1)', // 紫色 + 'rgba(255,159,64,1)', // 橙色 + 'rgba(199,199,199,1)', // 灰色 + 'rgba(83,102,255,1)' // 靛色 ] - // 生成多个target的数据 - const targetsData = Array.from({ length: targetCount }).map((_, targetIndex) => ({ - name: `Target ${targetIndex + 1}`, - color: targetColors[targetIndex % targetColors.length], - data: Array.from({ length: count }).map((_, i) => ({ - x: 350 + targetIndex * 50 + Math.sin(i * 0.5 + targetIndex) * 20 + randomAround(0, 3), - y: 50 + targetIndex * 20 + Math.cos(i * 0.3 + targetIndex) * 15 + randomAround(0, 2), - w: randomAround(125, 5), - h: randomAround(115, 5) - })) - })) + // 监听设备连接状态变化,设备连接时清空历史数据 + useEffect(() => { + if (connectedDevice) { + console.log('设备连接,清空历史数据:', connectedDevice) + setSensorDataHistory([]) + } + }, [connectedDevice]) + + useEffect(() => { + if (window?.electron?.ipcRenderer?.on && IPC_EVENT?.RESULT_REPLY) { + const handler = (event, data) => { + console.log('收到主进程RESULT_REPLY:', data) + + // 检查数据格式 + if (data && data.values && data.values.sensors && Array.isArray(data.values.sensors)) { + const newDataPoint = { + timestamp: data.values.timestamp || new Date().toISOString(), + sensors: data.values.sensors + } + + setSensorDataHistory((prev) => { + const newHistory = [...prev, newDataPoint] + // 保持最多10个数据点 + return newHistory.slice(-10) + }) + } + } + window.electron.ipcRenderer.on(IPC_EVENT.RESULT_REPLY, handler) + return () => { + window.electron.ipcRenderer.removeListener(IPC_EVENT.RESULT_REPLY, handler) + } + } + }, []) - const timeLabels = getTimeLabels(count) + // 生成时间标签 - 包含毫秒级精度 + const timeLabels = sensorDataHistory.map((dataPoint) => { + const timestamp = new Date(dataPoint.timestamp) + // 格式化为 HH:MM:SS.mmm 显示毫秒 + const hours = timestamp.getHours().toString().padStart(2, '0') + const minutes = timestamp.getMinutes().toString().padStart(2, '0') + const seconds = timestamp.getSeconds().toString().padStart(2, '0') + const milliseconds = timestamp.getMilliseconds().toString().padStart(3, '0') + return `${hours}:${minutes}:${seconds}.${milliseconds}` + }) + // 获取所有唯一的传感器位置 + const allSensors = sensorDataHistory.reduce((acc, dataPoint) => { + dataPoint.sensors.forEach((sensor) => { + if (!acc.some((s) => s.pos === sensor.pos)) { + acc.push({ + pos: sensor.pos, + des: sensor.des, + color: targetColors[acc.length % targetColors.length] + }) + } + }) + return acc + }, []) + // 生成Y方向数据 const dataY = { labels: timeLabels, - datasets: targetsData.map((target) => ({ - label: `${target.name}`, - data: target.data.map((d) => d.y), - borderColor: target.color, - backgroundColor: target.color.replace('1)', '0.2)'), + datasets: allSensors.map((sensor) => ({ + label: `测点${sensor.pos}`, + data: sensorDataHistory.map((dataPoint) => { + const sensorData = dataPoint.sensors.find((s) => s.pos === sensor.pos) + return sensorData ? Number(sensorData.yReal) : null + }), + borderColor: sensor.color, + backgroundColor: sensor.color.replace('1)', '0.2)'), tension: 0.3, pointRadius: 3, pointHoverRadius: 5 })) } + // 生成X方向数据 const dataX = { labels: timeLabels, - datasets: targetsData.map((target) => ({ - label: `${target.name}`, - data: target.data.map((d) => d.x), - borderColor: target.color, - backgroundColor: target.color.replace('1)', '0.2)'), + datasets: allSensors.map((sensor) => ({ + label: `测点${sensor.pos}`, + data: sensorDataHistory.map((dataPoint) => { + const sensorData = dataPoint.sensors.find((s) => s.pos === sensor.pos) + return sensorData ? Number(sensorData.xReal) : null + }), + borderColor: sensor.color, + backgroundColor: sensor.color.replace('1)', '0.2)'), tension: 0.3, pointRadius: 3, pointHoverRadius: 5 @@ -108,6 +157,10 @@ function DeflectionCollection() { } } + // 获取最新数据用于右侧实时显示 + const latestData = + sensorDataHistory.length > 0 ? sensorDataHistory[sensorDataHistory.length - 1] : null + return (