/* * @Author: 李皓 hao_li_work@163.com * @Date: 2026-07-28 16:31:45 * @LastEditors: 李皓 hao_li_work@163.com * @LastEditTime: 2026-07-28 16:44:07 * @FilePath: \pc\preload.js * @Description: * @Version: 1.0.0 */ const { contextBridge, ipcRenderer } = require('electron') const nodeNet = require('net') const dns = require('dns') function tryConnect(host, port, timeout) { return new Promise((resolve) => { const socket = new nodeNet.Socket() socket.setTimeout(timeout) socket.on('connect', () => { socket.destroy(); resolve(true) }) socket.on('error', () => { socket.destroy(); resolve(false) }) socket.on('timeout', () => { socket.destroy(); resolve(false) }) socket.connect(port, host) }) } const net = { async ping(host, timeout) { try { await dns.promises.resolve(host) } catch { return false } for (const port of [443, 80]) { if (await tryConnect(host, port, timeout)) return true } return false } } const appCallbacks = { onFileWrite: null, onFileRead: null, onFileDelete: null, onPageModeChanged: null } ipcRenderer.on('app-file-write-callback', (_event, token, filePath, success, err) => { if (typeof appCallbacks.onFileWrite === 'function') appCallbacks.onFileWrite(token, filePath, success, err) }) ipcRenderer.on('app-file-read-callback', (_event, token, filePath, content) => { if (typeof appCallbacks.onFileRead === 'function') appCallbacks.onFileRead(token, filePath, content) }) ipcRenderer.on('app-file-delete-callback', (_event, token, filePath, success) => { if (typeof appCallbacks.onFileDelete === 'function') appCallbacks.onFileDelete(token, filePath, success) }) ipcRenderer.on('app-page-mode', (_event, mode) => { if (typeof appCallbacks.onPageModeChanged === 'function') appCallbacks.onPageModeChanged(mode) }) const app = { clearCache() { return ipcRenderer.sendSync('app-clear-cache-sync') }, versionCode() { return ipcRenderer.sendSync('app-version-code-sync') }, setCache(key, value) { return ipcRenderer.sendSync('set-cache-sync', key, value) }, getCache(key) { return ipcRenderer.sendSync('get-cache-sync', key) }, offlinePage() { ipcRenderer.send('app-offline-page') }, onlinePage() { ipcRenderer.send('app-online-page') }, fileList(dir) { return ipcRenderer.sendSync('app-file-list-sync', dir) }, fileWriteString(filePath, content, token) { ipcRenderer.send('app-file-write-string', filePath, content, token) }, fileReadString(filePath, token) { ipcRenderer.send('app-file-read-string', filePath, token) }, fileDelete(filePath, token) { ipcRenderer.send('app-file-delete', filePath, token) }, get onFileWrite() { return appCallbacks.onFileWrite }, set onFileWrite(fn) { appCallbacks.onFileWrite = fn }, get onFileRead() { return appCallbacks.onFileRead }, set onFileRead(fn) { appCallbacks.onFileRead = fn }, get onFileDelete() { return appCallbacks.onFileDelete }, set onFileDelete(fn) { appCallbacks.onFileDelete = fn }, get onPageModeChanged() { return appCallbacks.onPageModeChanged }, set onPageModeChanged(fn) { appCallbacks.onPageModeChanged = fn } } const sensorCallbacks = { onSensorAttached: null, onSensorDetached: null, onOperationCallback: null } ipcRenderer.on('sensor-attached', (_event, data) => { if (typeof sensorCallbacks.onSensorAttached === 'function') sensorCallbacks.onSensorAttached(data.id, data.name) }) ipcRenderer.on('sensor-detached', (_event, data) => { if (typeof sensorCallbacks.onSensorDetached === 'function') sensorCallbacks.onSensorDetached(data.id, data.name) }) ipcRenderer.on('sensor-operation-callback', (_event, id, opId, result) => { if (typeof sensorCallbacks.onOperationCallback === 'function') sensorCallbacks.onOperationCallback(id, opId, result) }) const sensor = { initAll() { return ipcRenderer.sendSync('sensor-init-all-sync') }, flush() { return ipcRenderer.sendSync('sensor-flush-sync') }, sensorList() { return ipcRenderer.sendSync('sensor-list-sync') }, init(id) { return ipcRenderer.sendSync('sensor-init-sync', id) }, open(id) { return ipcRenderer.sendSync('sensor-open-sync', id) }, close(id) { return ipcRenderer.sendSync('sensor-close-sync', id) }, operation(id, opId, args) { return ipcRenderer.sendSync('sensor-operation-sync', id, opId, args) }, operationAsync(id, opId, args) { ipcRenderer.send('sensor-operation-async', id, opId, args) }, get onSensorAttached() { return sensorCallbacks.onSensorAttached }, set onSensorAttached(fn) { sensorCallbacks.onSensorAttached = fn }, get onSensorDetached() { return sensorCallbacks.onSensorDetached }, set onSensorDetached(fn) { sensorCallbacks.onSensorDetached = fn }, get onOperationCallback() { return sensorCallbacks.onOperationCallback }, set onOperationCallback(fn) { sensorCallbacks.onOperationCallback = fn } } const appSensorCallbacks = { onValueCallback: null } const appSensor = { version: '1.0.0', name: 'appSensor', open() { return ipcRenderer.sendSync('app-sensor-open-sync') }, close() { return ipcRenderer.sendSync('app-sensor-close-sync') }, isOpen() { return ipcRenderer.sendSync('app-sensor-is-open-sync') }, get onValueCallback() { return appSensorCallbacks.onValueCallback }, set onValueCallback(fn) { appSensorCallbacks.onValueCallback = fn } } ipcRenderer.on('sensor-data', (_event, data) => { if (typeof appSensorCallbacks.onValueCallback === 'function') appSensorCallbacks.onValueCallback(data) }) const appLocationCallbacks = { onOpened: null, onLocationChanged: null } ipcRenderer.on('app-location-opened', (_event, status) => { if (typeof appLocationCallbacks.onOpened === 'function') appLocationCallbacks.onOpened(status) }) ipcRenderer.on('app-location-changed', (_event, location) => { if (typeof appLocationCallbacks.onLocationChanged === 'function') appLocationCallbacks.onLocationChanged(location) }) const appLocation = { isSupport() { return ipcRenderer.sendSync('app-location-is-support-sync') }, isOpen() { return ipcRenderer.sendSync('app-location-is-open-sync') }, open() { ipcRenderer.send('app-location-open') }, close() { ipcRenderer.send('app-location-close') }, get onOpened() { return appLocationCallbacks.onOpened }, set onOpened(fn) { appLocationCallbacks.onOpened = fn }, get onLocationChanged() { return appLocationCallbacks.onLocationChanged }, set onLocationChanged(fn) { appLocationCallbacks.onLocationChanged = fn } } const usbSerialCallbacks = { onDeviceAttached: null, onDeviceDetached: null, onDeviceDiscovered: null, onDeviceProbeResult: null, onDeviceOpened: null, onDeviceState: null, onDeviceData: null } for (const [eventName, cbName] of [ ['usb-callback-device-attached', 'onDeviceAttached'], ['usb-callback-device-detached', 'onDeviceDetached'], ['usb-callback-device-discovered', 'onDeviceDiscovered'], ['usb-callback-device-probe-result', 'onDeviceProbeResult'], ['usb-callback-device-opened', 'onDeviceOpened'], ['usb-callback-device-state', 'onDeviceState'], ['usb-callback-device-data', 'onDeviceData'] ]) { ipcRenderer.on(eventName, (_event, jsonStr) => { const cb = usbSerialCallbacks[cbName] if (typeof cb === 'function') cb(jsonStr) }) } const usbSerial = { get onDeviceAttached() { return usbSerialCallbacks.onDeviceAttached }, set onDeviceAttached(fn) { usbSerialCallbacks.onDeviceAttached = fn }, get onDeviceDetached() { return usbSerialCallbacks.onDeviceDetached }, set onDeviceDetached(fn) { usbSerialCallbacks.onDeviceDetached = fn }, get onDeviceDiscovered() { return usbSerialCallbacks.onDeviceDiscovered }, set onDeviceDiscovered(fn) { usbSerialCallbacks.onDeviceDiscovered = fn }, get onDeviceProbeResult() { return usbSerialCallbacks.onDeviceProbeResult }, set onDeviceProbeResult(fn) { usbSerialCallbacks.onDeviceProbeResult = fn }, get onDeviceOpened() { return usbSerialCallbacks.onDeviceOpened }, set onDeviceOpened(fn) { usbSerialCallbacks.onDeviceOpened = fn }, get onDeviceState() { return usbSerialCallbacks.onDeviceState }, set onDeviceState(fn) { usbSerialCallbacks.onDeviceState = fn }, get onDeviceData() { return usbSerialCallbacks.onDeviceData }, set onDeviceData(fn) { usbSerialCallbacks.onDeviceData = fn }, startDiscovery() { ipcRenderer.send('usb-start-discovery') }, stopDiscovery() { ipcRenderer.send('usb-stop-discovery') }, getDiscoveredDevices() { return ipcRenderer.invoke('usb-get-discovered') }, deviceProbe(deviceName, portNumber, baudRate, hexCmd, timeoutMs) { ipcRenderer.send('usb-device-probe', { deviceName, portNumber, baudRate, hexCmd, timeoutMs }) }, deviceOpen(deviceName, portNumber, baudRate) { ipcRenderer.send('usb-device-open', { deviceName, portNumber, baudRate }) }, deviceClose(deviceName, portNumber) { ipcRenderer.send('usb-device-close', { deviceName, portNumber }) }, deviceWrite(deviceName, portNumber, hexData) { ipcRenderer.send('usb-device-write', { deviceName, portNumber, hexData }) } } contextBridge.exposeInMainWorld('app', app) contextBridge.exposeInMainWorld('net', net) contextBridge.exposeInMainWorld('sensor', sensor) contextBridge.exposeInMainWorld('appSensor', appSensor) contextBridge.exposeInMainWorld('appLocation', appLocation) contextBridge.exposeInMainWorld('usbSerial', usbSerial)