光电挠度仪上位机
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

133 lines
3.9 KiB

import { ipcMain } from 'electron'
import dgram from 'dgram'
import net from 'net'
import { IPC_EVENT } from '../renderer/src/common/ipcEvents.js'
import fs from 'fs'
// 全局保存所有TCP连接
const tcpClients = new Map()
export function registerIpRouter() {
ipcMain.on(IPC_EVENT.DEVICE_SEARCH, searchDevice) // 设备搜索
ipcMain.on(IPC_EVENT.DEVICE_CONNECT, connectDevice) // 设备连接
ipcMain.on(IPC_EVENT.DEVICE_DISCONNECT, disconnectDevice) // 设备断开
}
const searchDevice = (event) => {
const message = Buffer.from(JSON.stringify({ command: 'name', type: 'get' }))
const PORT = 2230
const BROADCAST_ADDR = '255.255.255.255'
const udpClient = dgram.createSocket('udp4')
let timer = null
const resultMap = new Map()
udpClient.bind(() => {
udpClient.setBroadcast(true)
udpClient.send(message, 0, message.length, PORT, BROADCAST_ADDR, (err) => {
if (err) {
console.error('UDP send failed', err)
udpClient.close()
} else {
console.log('UDP send successful')
}
})
})
udpClient.on('message', (msg, rinfo) => {
try {
// 以 IP 为 key,自动去重
resultMap.set(rinfo.address, {
from: rinfo.address,
data: msg.toString()
})
} catch (e) {
console.error('parse UDP message failed:', e)
}
// 每收到一条消息就重置定时器
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
udpClient.close()
console.log('UDP socket closed after timeout')
// 关闭后统一回复所有结果(已去重)
event.reply && event.reply(IPC_EVENT.DEVICE_SEARCH_REPLY, Array.from(resultMap.values()))
}, 1000) // 1秒内没有新消息就关闭
})
udpClient.on('error', (err) => {
console.error('UDP error:', err)
udpClient.close()
// 出错时也可以回复已收到的内容
event.reply && event.reply(IPC_EVENT.DEVICE_SEARCH_REPLY, Array.from(resultMap.values()))
})
}
const connectDevice = (event, { ip, port }) => {
if (!ip || !port) {
event.reply(IPC_EVENT.DEVICE_CONNECT_REPLY, { success: false, error: '参数缺失' })
return
}
if (tcpClients.has(ip)) {
event.reply(IPC_EVENT.DEVICE_CONNECT_REPLY, { success: false, error: '已连接' })
return
}
const client = new net.Socket()
client.connect(Number(port), ip, () => {
event.reply(IPC_EVENT.DEVICE_CONNECT_REPLY, { success: true, ip })
tcpClients.set(ip, client)
})
let buffer = ''
client.on('data', (data) => {
buffer += data.toString()
let index
while ((index = buffer.indexOf('\n')) !== -1) {
const line = buffer.slice(0, index)
buffer = buffer.slice(index + 1)
if (!line.trim()) continue
let msg
try {
msg = JSON.parse(line)
console.log(msg.command)
} catch (e) {
console.error('TCP data parse error:', e)
fs.appendFileSync('error_log.txt', line + '\n')
continue
}
if (!msg || !msg.command) {
console.log('invalid msg format:', msg)
continue
}
switch (msg.command) {
case 'result':
event.sender.send(IPC_EVENT.SENSOR_DATA, { ip, ...msg })
break
case 'image':
event.sender.send(IPC_EVENT.IMAGE_DATA, { ip, ...msg })
break
case 'heartbeat':
break
default:
console.warn('unknow command type:', msg.command)
}
}
})
client.on('error', (err) => {
event.reply(IPC_EVENT.DEVICE_CONNECT_REPLY, { success: false, error: err.message })
client.destroy()
tcpClients.delete(ip)
})
client.on('close', () => {
tcpClients.delete(ip)
})
}
const disconnectDevice = (event, { ip }) => {
const client = tcpClients.get(ip)
if (client) {
client.destroy()
tcpClients.delete(ip)
event.reply(IPC_EVENT.DEVICE_DISCONNECT_REPLY, { success: true })
} else {
event.reply(IPC_EVENT.DEVICE_DISCONNECT_REPLY, { success: false, error: '未连接' })
}
}