From c1fc36b44cb71ff9585fee648eed6f0d40116547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B6=E5=BF=97=E8=B6=85?= Date: Fri, 13 Oct 2023 16:39:27 +0800 Subject: [PATCH] init commit --- src/main/app.ts | 81 ++++ src/main/index.ts | 27 ++ src/main/preload.js | 31 ++ src/main/window/BaseWindow.ts | 30 ++ src/main/window/LocalSoftwareWindow.ts | 13 + src/main/window/ModelWindow.ts | 24 ++ src/main/window/OnlineSoftwareWindow.ts | 9 + .../window/localSoftware/BDAndTimeWindow.ts | 7 + .../BDCommunicationAssistantWindow.ts | 7 + ...ComprehensiveExperimentalPlatformWindow.ts | 7 + .../BDDataAnalysisPlatformWindow.ts | 7 + ...MeteorologicalDataDisplayPlatformWindow.ts | 7 + .../BDMeteorologicalDataProtocolWindow.ts | 7 + .../BDPositionTrackRetracingWindow.ts | 35 ++ .../BDSatellite3DPostureDisplayWindow.ts | 7 + .../BDSatelliteAttitudeControlWindow.ts | 7 + ...elliteParameterMonitoringPlatformWindow.ts | 7 + .../BDSatelliteTimeConfigurationWindow.ts | 7 + .../window/localSoftware/ClockConfigWindow.ts | 7 + .../DistanceCalculationToolWindow.ts | 7 + .../ElectronicScreenDesignWindow.ts | 7 + .../window/localSoftware/FontDesignWindow.ts | 46 +++ .../GeneratingConstellationChartWindow.ts | 7 + .../localSoftware/GestureRecognitionWindow.ts | 7 + src/main/window/localSoftware/MainWindow.ts | 364 ++++++++++++++++++ .../NixieTubeConfigurationWindow.ts | 7 + .../localSoftware/VoltageMonitoringWindow.ts | 7 + ...sCommunicationModuleConfigurationWindow.ts | 7 + 28 files changed, 786 insertions(+) create mode 100644 src/main/app.ts create mode 100644 src/main/index.ts create mode 100644 src/main/preload.js create mode 100644 src/main/window/BaseWindow.ts create mode 100644 src/main/window/LocalSoftwareWindow.ts create mode 100644 src/main/window/ModelWindow.ts create mode 100644 src/main/window/OnlineSoftwareWindow.ts create mode 100644 src/main/window/localSoftware/BDAndTimeWindow.ts create mode 100644 src/main/window/localSoftware/BDCommunicationAssistantWindow.ts create mode 100644 src/main/window/localSoftware/BDComprehensiveExperimentalPlatformWindow.ts create mode 100644 src/main/window/localSoftware/BDDataAnalysisPlatformWindow.ts create mode 100644 src/main/window/localSoftware/BDMeteorologicalDataDisplayPlatformWindow.ts create mode 100644 src/main/window/localSoftware/BDMeteorologicalDataProtocolWindow.ts create mode 100644 src/main/window/localSoftware/BDPositionTrackRetracingWindow.ts create mode 100644 src/main/window/localSoftware/BDSatellite3DPostureDisplayWindow.ts create mode 100644 src/main/window/localSoftware/BDSatelliteAttitudeControlWindow.ts create mode 100644 src/main/window/localSoftware/BDSatelliteParameterMonitoringPlatformWindow.ts create mode 100644 src/main/window/localSoftware/BDSatelliteTimeConfigurationWindow.ts create mode 100644 src/main/window/localSoftware/ClockConfigWindow.ts create mode 100644 src/main/window/localSoftware/DistanceCalculationToolWindow.ts create mode 100644 src/main/window/localSoftware/ElectronicScreenDesignWindow.ts create mode 100644 src/main/window/localSoftware/FontDesignWindow.ts create mode 100644 src/main/window/localSoftware/GeneratingConstellationChartWindow.ts create mode 100644 src/main/window/localSoftware/GestureRecognitionWindow.ts create mode 100644 src/main/window/localSoftware/MainWindow.ts create mode 100644 src/main/window/localSoftware/NixieTubeConfigurationWindow.ts create mode 100644 src/main/window/localSoftware/VoltageMonitoringWindow.ts create mode 100644 src/main/window/localSoftware/WirelessCommunicationModuleConfigurationWindow.ts diff --git a/src/main/app.ts b/src/main/app.ts new file mode 100644 index 0000000..a3951c6 --- /dev/null +++ b/src/main/app.ts @@ -0,0 +1,81 @@ +import { app, BrowserWindow } from 'electron' +import { MainWindow } from './window/localSoftware/MainWindow' + +app.commandLine.appendSwitch('enable-features', 'ElectronSerialChooser') + +let mainWindow: MainWindow | null = null +const createMainWindow = () => { + mainWindow = new MainWindow() + + + + mainWindow.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => { + //Add listeners to handle ports being added or removed before the callback for `select-serial-port` + //is called. + // mainWindow.webContents.session.on('serial-port-added', (event, port) => { + // console.log('serial-port-added FIRED WITH', port) + // //Optionally update portList to add the new port + // }) + + // mainWindow.webContents.session.on('serial-port-removed', (event, port) => { + // console.log('serial-port-removed FIRED WITH', port) + // //Optionally update portList to remove the port + // }) + + + event.preventDefault() + if (portList && portList.length > 0) { + mainWindow?.setSelectedPort(portList[0]) + callback(portList[0].portId) + } else { + callback('') //Could not find any matching devices + } + }) + + mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => { + if (permission === 'serial') { + return true + } + + return false + }) + + mainWindow.webContents.session.setDevicePermissionHandler((details) => { + if (details.deviceType === 'serial') { + return true + } + + return false + }) +} + +const gotTheLock = app.requestSingleInstanceLock() + +if (!gotTheLock) { + app.quit() +} else { + app.on('second-instance', () => { + // 有人试图运行第二个实例,我们应该关注我们的窗口 + if (mainWindow) { + if (mainWindow.isMinimized()) mainWindow.restore() + mainWindow.focus() + } + }) + + // 创建 mainWindow, 加载应用的其余部分, etc... + app.once('ready', createMainWindow) + + app.on('window-all-closed', () => { + if (process.platform !== 'darwin') app.quit() + }) + + app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) createMainWindow() + }) +} + +export const quit = () => app.quit() + +// if (process.env.NODE_ENV != 'development') { +// app.once('browser-window-created', enableAutoLaunch) +// } \ No newline at end of file diff --git a/src/main/index.ts b/src/main/index.ts new file mode 100644 index 0000000..b3bd8b6 --- /dev/null +++ b/src/main/index.ts @@ -0,0 +1,27 @@ +import { join } from 'path' +import { app, ipcMain, BrowserWindow } from 'electron' + +const IS_DEV_ENV = process.env.NODE_ENV === 'development' +const ROOT_PATH = IS_DEV_ENV ? 'http://localhost:5173' : `file://${__dirname}/../render` +const preload = IS_DEV_ENV ? join(__dirname, './preload.ts') : join(__dirname, './preload.js') + +let mainWindow : BrowserWindow; + +const createMainWindow = () => { + mainWindow = new BrowserWindow({ + width: 900, + height: 600, + webPreferences: { + nodeIntegration: true, + preload: join(__dirname, './preload.js'), + }, + }) + + mainWindow.loadURL(join(ROOT_PATH, 'page/index.html')) +} + +ipcMain.on("CLOSE_MAIN_WINDOW", () => { + app.quit() +}) + +app.on('ready', createMainWindow) diff --git a/src/main/preload.js b/src/main/preload.js new file mode 100644 index 0000000..8d2ae02 --- /dev/null +++ b/src/main/preload.js @@ -0,0 +1,31 @@ +const { ipcRenderer, contextBridge } = require('electron') + +contextBridge.exposeInMainWorld('ipcRenderer', { + send: (channel, data) => { + // whitelist channels + let validChannels = ['toMain'] + if (validChannels.includes(channel)) { + ipcRenderer.send(channel, data) + } + ipcRenderer.send(channel, data) + }, + sendSync: (channel, data) => { + // whitelist channels + let validChannels = ['toMain'] + if (validChannels.includes(channel)) { + return ipcRenderer.sendSync(channel, data) + } + return ipcRenderer.sendSync(channel, data) + }, + receive: (channel, func) => { + let validChannels = ['fromMain'] + if (validChannels.includes(channel)) { + // Deliberately strip event as it includes `sender` + ipcRenderer.on(channel, (event, ...args) => func(...args)) + } + ipcRenderer.on(channel, (event, ...args) => func(...args)) + }, + unreceive: (channel) => { + ipcRenderer.removeAllListeners(channel) + } +}) diff --git a/src/main/window/BaseWindow.ts b/src/main/window/BaseWindow.ts new file mode 100644 index 0000000..f5a2438 --- /dev/null +++ b/src/main/window/BaseWindow.ts @@ -0,0 +1,30 @@ +import { join } from 'path' +import { Menu, BrowserWindow } from 'electron' + +Menu.setApplicationMenu(null) + +// TODO: 修改标题栏ico图标 +const BASE_WINDOW_OPTIONS = { + icon: join(__dirname, '../../../public/favicon.ico'), + webPreferences : { + nodeIntegration : true, + enableBlinkFeatures: 'Serial', + experimentalFeatures: true, + preload : join(__dirname, '../preload.js') + }, +} + +export abstract class BaseWindow extends BrowserWindow { + constructor (options = {}) { + Object.assign(options, BASE_WINDOW_OPTIONS) + super(options) + + this.bindIpcEvent() + + if (process.env.NODE_ENV === 'development') { + this.webContents.openDevTools() + } + } + + bindIpcEvent() {} +} diff --git a/src/main/window/LocalSoftwareWindow.ts b/src/main/window/LocalSoftwareWindow.ts new file mode 100644 index 0000000..01ba05f --- /dev/null +++ b/src/main/window/LocalSoftwareWindow.ts @@ -0,0 +1,13 @@ +import { join } from 'path' +import { BaseWindow } from './BaseWindow' + +const IS_DEV_ENV = process.env.NODE_ENV === 'development' +const ROOT_PATH = IS_DEV_ENV ? 'http://localhost:5173/page' : `file://${__dirname}/../../render/page` + +export abstract class LocalSoftwareWindow extends BaseWindow { + constructor (localFileName: string, options = {}) { + super(options) + + this.loadURL(join(ROOT_PATH, localFileName)) + } +} diff --git a/src/main/window/ModelWindow.ts b/src/main/window/ModelWindow.ts new file mode 100644 index 0000000..e2ea2d8 --- /dev/null +++ b/src/main/window/ModelWindow.ts @@ -0,0 +1,24 @@ +import { BaseWindow } from './BaseWindow' +import { BrowserWindow } from 'electron' + +// TODO: 禁止双击标题栏改变窗口大小 +const MODEL_WINDOW_OPTIONS = { + modal : true, + show : false, + movable : false, + resizable : false, + minimizable : false, + maximizable : false, +} + +export abstract class ModelWindow extends BaseWindow { + constructor (parent: BrowserWindow | null, options = {}) { + Object.assign(options, { parent }, MODEL_WINDOW_OPTIONS) + super(options) + + this.maximize() + this.once('ready-to-show', () => { + this.show() + }) + } +} diff --git a/src/main/window/OnlineSoftwareWindow.ts b/src/main/window/OnlineSoftwareWindow.ts new file mode 100644 index 0000000..a33c22f --- /dev/null +++ b/src/main/window/OnlineSoftwareWindow.ts @@ -0,0 +1,9 @@ +import { BaseWindow } from './BaseWindow' + +export class OnlineSoftwareWindow extends BaseWindow { + constructor (url: string, options = {}) { + super(options) + + this.loadURL(url) + } +} diff --git a/src/main/window/localSoftware/BDAndTimeWindow.ts b/src/main/window/localSoftware/BDAndTimeWindow.ts new file mode 100644 index 0000000..06d6938 --- /dev/null +++ b/src/main/window/localSoftware/BDAndTimeWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class BDAndTimeWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('BD&time.html', options ) + } +} diff --git a/src/main/window/localSoftware/BDCommunicationAssistantWindow.ts b/src/main/window/localSoftware/BDCommunicationAssistantWindow.ts new file mode 100644 index 0000000..ba4b7b4 --- /dev/null +++ b/src/main/window/localSoftware/BDCommunicationAssistantWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class BDCommunicationAssistantWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('BD-communication-assistant.html', options) + } +} diff --git a/src/main/window/localSoftware/BDComprehensiveExperimentalPlatformWindow.ts b/src/main/window/localSoftware/BDComprehensiveExperimentalPlatformWindow.ts new file mode 100644 index 0000000..e270e45 --- /dev/null +++ b/src/main/window/localSoftware/BDComprehensiveExperimentalPlatformWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class BDComprehensiveExperimentalPlatformWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('BD-comprehensive-experimental-platform.html', options) + } +} diff --git a/src/main/window/localSoftware/BDDataAnalysisPlatformWindow.ts b/src/main/window/localSoftware/BDDataAnalysisPlatformWindow.ts new file mode 100644 index 0000000..a075370 --- /dev/null +++ b/src/main/window/localSoftware/BDDataAnalysisPlatformWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class BDDataAnalysisPlatformWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('BD-data-analysis-platform.html', options) + } +} diff --git a/src/main/window/localSoftware/BDMeteorologicalDataDisplayPlatformWindow.ts b/src/main/window/localSoftware/BDMeteorologicalDataDisplayPlatformWindow.ts new file mode 100644 index 0000000..34609dd --- /dev/null +++ b/src/main/window/localSoftware/BDMeteorologicalDataDisplayPlatformWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class BDMeteorologicalDataDisplayPlatformWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('BD-meteorological-data-display-platform.html', options ) + } +} diff --git a/src/main/window/localSoftware/BDMeteorologicalDataProtocolWindow.ts b/src/main/window/localSoftware/BDMeteorologicalDataProtocolWindow.ts new file mode 100644 index 0000000..18e8ef2 --- /dev/null +++ b/src/main/window/localSoftware/BDMeteorologicalDataProtocolWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class BDMeteorologicalDataProtocolWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('BD-meteorological-data-protocol.html', options ) + } +} diff --git a/src/main/window/localSoftware/BDPositionTrackRetracingWindow.ts b/src/main/window/localSoftware/BDPositionTrackRetracingWindow.ts new file mode 100644 index 0000000..40e54e7 --- /dev/null +++ b/src/main/window/localSoftware/BDPositionTrackRetracingWindow.ts @@ -0,0 +1,35 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' +import { IpcMainEvent } from 'electron' +import { readFile } from 'fs' +import { usedSync } from 'windows-drive-letters' + +export class BDPositionTrackRetracingWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('BD-position-track-retracing.html', options) + } + + bindIpcEvent() { + this.webContents.ipc.on('GET_DATA', this.getData ) + } + + getData(event: IpcMainEvent) { + const letters = usedSync() + const filePath = letters[letters.length - 1] + ':/BDLOG.TXT' + + readFile(filePath, 'utf8', (err, data) => { + if (err) { + if (err.code === 'ENOENT') { + console.error('file not exist') + event.returnValue = { err: new Error('文件不存在') } + return + } + + console.error(err, 'open') + event.returnValue = { err } + return + } + + event.returnValue = { data } + }) + } +} diff --git a/src/main/window/localSoftware/BDSatellite3DPostureDisplayWindow.ts b/src/main/window/localSoftware/BDSatellite3DPostureDisplayWindow.ts new file mode 100644 index 0000000..9782da1 --- /dev/null +++ b/src/main/window/localSoftware/BDSatellite3DPostureDisplayWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class BDSatellite3DPostureDisplayWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('BD-satellite-3D-posture-display.html', options) + } +} diff --git a/src/main/window/localSoftware/BDSatelliteAttitudeControlWindow.ts b/src/main/window/localSoftware/BDSatelliteAttitudeControlWindow.ts new file mode 100644 index 0000000..630cd58 --- /dev/null +++ b/src/main/window/localSoftware/BDSatelliteAttitudeControlWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class BDSatelliteAttitudeControlWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('BD-satellite-attitude-control.html', options) + } +} diff --git a/src/main/window/localSoftware/BDSatelliteParameterMonitoringPlatformWindow.ts b/src/main/window/localSoftware/BDSatelliteParameterMonitoringPlatformWindow.ts new file mode 100644 index 0000000..f2835d9 --- /dev/null +++ b/src/main/window/localSoftware/BDSatelliteParameterMonitoringPlatformWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class BDSatelliteParameterMonitoringPlatformWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('BD-satellite-parameter-monitoring-platform.html', options) + } +} diff --git a/src/main/window/localSoftware/BDSatelliteTimeConfigurationWindow.ts b/src/main/window/localSoftware/BDSatelliteTimeConfigurationWindow.ts new file mode 100644 index 0000000..b4885d0 --- /dev/null +++ b/src/main/window/localSoftware/BDSatelliteTimeConfigurationWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class BDSatelliteTimeConfigurationWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('BD-satellite-time-configuration.html', options) + } +} diff --git a/src/main/window/localSoftware/ClockConfigWindow.ts b/src/main/window/localSoftware/ClockConfigWindow.ts new file mode 100644 index 0000000..520e242 --- /dev/null +++ b/src/main/window/localSoftware/ClockConfigWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class ClockConfigWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('clock-config.html', options ) + } +} diff --git a/src/main/window/localSoftware/DistanceCalculationToolWindow.ts b/src/main/window/localSoftware/DistanceCalculationToolWindow.ts new file mode 100644 index 0000000..4734746 --- /dev/null +++ b/src/main/window/localSoftware/DistanceCalculationToolWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class DistanceCalculationToolWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('distance-calculation-tool.html', options ) + } +} diff --git a/src/main/window/localSoftware/ElectronicScreenDesignWindow.ts b/src/main/window/localSoftware/ElectronicScreenDesignWindow.ts new file mode 100644 index 0000000..00bfb55 --- /dev/null +++ b/src/main/window/localSoftware/ElectronicScreenDesignWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class ElectronicScreenDesignWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('electronic-screen-design.html', options ) + } +} diff --git a/src/main/window/localSoftware/FontDesignWindow.ts b/src/main/window/localSoftware/FontDesignWindow.ts new file mode 100644 index 0000000..fffd563 --- /dev/null +++ b/src/main/window/localSoftware/FontDesignWindow.ts @@ -0,0 +1,46 @@ +import { readFile, writeFile, existsSync } from 'fs' +import { IpcMainEvent } from 'electron' +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +const FONT_LIBRARY_FILE_PATH = './fontLibrary.json' + +export class FontDesignWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('font-design.html', options ) + } + + bindIpcEvent(): void { + this.webContents.ipc.on('LOAD_FONT_LIBRARY', this.load ) + this.webContents.ipc.on('SAVE_FONT_LIBRARY', this.save ) + } + + load(event: IpcMainEvent) { + if (!existsSync(FONT_LIBRARY_FILE_PATH)) { + event.returnValue = {} + return + } + + readFile(FONT_LIBRARY_FILE_PATH, 'utf8', (err, data) => { + if (err) { + console.error(err); + + event.returnValue = {} + } else { + event.returnValue = { data } + } + }) + } + + save(event: IpcMainEvent, fontLibrary: string) { + if (!fontLibrary) { + event.returnValue = { err: new Error('字库为空') } + return + } + + try { + writeFile( FONT_LIBRARY_FILE_PATH, fontLibrary, 'utf8', () => event.returnValue = 'OK') + } catch (err) { + event.returnValue = { err } + } + } +} diff --git a/src/main/window/localSoftware/GeneratingConstellationChartWindow.ts b/src/main/window/localSoftware/GeneratingConstellationChartWindow.ts new file mode 100644 index 0000000..c576be4 --- /dev/null +++ b/src/main/window/localSoftware/GeneratingConstellationChartWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class GeneratingConstellationChartWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('generating-constellation-chart.html', options ) + } +} diff --git a/src/main/window/localSoftware/GestureRecognitionWindow.ts b/src/main/window/localSoftware/GestureRecognitionWindow.ts new file mode 100644 index 0000000..c1d0104 --- /dev/null +++ b/src/main/window/localSoftware/GestureRecognitionWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class GestureRecognitionWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('gesture-recognition.html', options ) + } +} diff --git a/src/main/window/localSoftware/MainWindow.ts b/src/main/window/localSoftware/MainWindow.ts new file mode 100644 index 0000000..5c38e01 --- /dev/null +++ b/src/main/window/localSoftware/MainWindow.ts @@ -0,0 +1,364 @@ +import { BrowserWindow, IpcMainEvent, SerialPort } from 'electron' +import { exec, execFile, spawn } from 'child_process' +import { join } from 'path' +import { existsSync } from 'fs' + +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' +import { OnlineSoftwareWindow } from '../OnlineSoftwareWindow' +import { BDAndTimeWindow } from './BDAndTimeWindow' +import { BDCommunicationAssistantWindow } from './BDCommunicationAssistantWindow' +import { BDComprehensiveExperimentalPlatformWindow } from './BDComprehensiveExperimentalPlatformWindow' +import { BDDataAnalysisPlatformWindow } from './BDDataAnalysisPlatformWindow' +import { BDPositionTrackRetracingWindow } from './BDPositionTrackRetracingWindow' +import { BDSatellite3DPostureDisplayWindow } from './BDSatellite3DPostureDisplayWindow' +import { BDSatelliteAttitudeControlWindow } from './BDSatelliteAttitudeControlWindow' +import { BDSatelliteParameterMonitoringPlatformWindow } from './BDSatelliteParameterMonitoringPlatformWindow' +import { BDSatelliteTimeConfigurationWindow } from './BDSatelliteTimeConfigurationWindow' +import { VoltageMonitoringWindow } from './VoltageMonitoringWindow' +import { WirelessCommunicationModuleConfigurationWindow } from './WirelessCommunicationModuleConfigurationWindow' +import { BDMeteorologicalDataDisplayPlatformWindow } from './BDMeteorologicalDataDisplayPlatformWindow' +import { BDMeteorologicalDataProtocolWindow } from './BDMeteorologicalDataProtocolWindow' +import { ElectronicScreenDesignWindow } from './ElectronicScreenDesignWindow' +import { GestureRecognitionWindow } from './GestureRecognitionWindow' +import { ClockConfigWindow } from './ClockConfigWindow' +import { FontDesignWindow } from './FontDesignWindow' +import { NixieTubeConfigurationWindow } from './NixieTubeConfigurationWindow' +import { DistanceCalculationToolWindow } from './DistanceCalculationToolWindow' +import { GeneratingConstellationChartWindow } from './GeneratingConstellationChartWindow' + +import { init, scan, connect, disconnect, getCurrentConnections, WiFiNetwork, ConnectionOpts } from 'node-wifi' +import { blockDevices } from 'systeminformation' +init({}) + +const is_development_env = process.env.NODE_ENV === 'development' + +// TODO: 尝试使用import.meta.globEager遍历所有子窗口类 +// const modules = import.meta.globEager('./modal/**/*.ts'); +// console.log(modules, '---------------------'); +// Object.keys(modules).forEach((key) => { +// const mod = modules[key].default || {}; +// console.log(key, '---------------------'); +// console.log(mod, '---------------------'); +// // const modList = Array.isArray(mod) ? [...mod] : [mod]; +// // routeModuleList.push(...modList); +// }); + + +const MAIN_WINDOW_OPTIONS = { + alwaysOnTop : is_development_env ? false : true, + kiosk : is_development_env ? false : true, + frame : false, + fullscreen : true, +} + +const MODAL_WINDOW_OPTIONS = { + modal : true, + show : false, + movable : false, + resizable : false, + minimizable : false, + maximizable : false, +} + +const ESP32_ROOT_PATH = 'C:\\esp32\\' +const ESP_TOOL_PATH = ESP32_ROOT_PATH + 'esptool.exe' +const BOOT_APP0_BIN_PATH = ESP32_ROOT_PATH + 'boot_app0.bin' +const BOOT_LOADER_BIN_PATH = ESP32_ROOT_PATH + 'bootloader.bin' +const PARTITIONS_BIN_PATH = ESP32_ROOT_PATH + 'partitions.bin' + +const BIN_FILE_ROOT_PATH = process.env.LOCALAPPDATA + '\\Arduino\\' + + + +const SYSTEM_CONFIG_BAT_PATH = 'C:\\SystemConfig\\SystemConfig.bat' + +export class MainWindow extends LocalSoftwareWindow { + subWindow : BrowserWindow | undefined + subWindowOptions: Object + selectedPort : SerialPort | undefined + + constructor (options = {}) { + Object.assign(options, MAIN_WINDOW_OPTIONS) + super('index.html', options) + + this.subWindowOptions = Object.assign({}, { parent: this }, MODAL_WINDOW_OPTIONS) + } + + setSelectedPort(port: SerialPort): void { + if (!port) return + + this.selectedPort = port + } + + bindIpcEvent(): void { + this.webContents.ipc.on('QUIT' , this.quit.bind(this) ) + this.webContents.ipc.on('REBOOT' , this.reboot ) + this.webContents.ipc.on('SHUTDOWN' , this.shutdown ) + this.webContents.ipc.on('SYSTEM_REPAIR' , this.systemRepair ) + this.webContents.ipc.on('SOFTWARE_UPGRADE' , this.softwareUpgrade.bind(this) ) + this.webContents.ipc.on('NETWORK_QUERY' , this.networkQuery ) + this.webContents.ipc.on('NETWORK_CONNECT' , this.networkConnect ) + this.webContents.ipc.on('NETWORK_DISCONNECT' , this.networkDisconnect ) + this.webContents.ipc.on('BURN_PROGRAM' , this.burnProgram ) + this.webContents.ipc.on('LAUNCH_ONLINE_SOFTWARE', this.launchOnlineSoftware.bind(this) ) + this.webContents.ipc.on('LAUNCH_LOCAL_SOFTWARE' , this.launchLocalSoftware.bind(this) ) + } + + quit() { + this.close() + } + + reboot() { + const command = exec('shutdown -r -t 00', function (err, stdout, stderr) { + if (err || stderr) { + console.error("shutdown failed" + err + stderr); + } + }); + + if (!command || !command.stdin) return + + command.stdin.end(); + + command.on("close", function (code) { + console.log("shutdown", code); + }); + } + + shutdown() { + const command = exec('shutdown -s -t 00', function (err, stdout, stderr) { + if (err || stderr) { + console.error("shutdown failed" + err + stderr); + } + }); + + if (!command || !command.stdin) return + + command.stdin.end(); + + command.on("close", function (code) { + console.log("shutdown", code); + }); + } + + async getLastestDriveIdentifier() { + const devices = await blockDevices() + return devices[devices.length - 1]?.identifier + } + + async softwareUpgrade(event: IpcMainEvent) { + const identifier = await this.getLastestDriveIdentifier() + + if (!identifier) { + event.returnValue = new Error('系统出错,请联系售后技术支持') + return + } + + const software_upgrade_file_path = identifier + '\\SoftwareUpgrade\\SoftwareUpgrade.bat' + if (!existsSync(software_upgrade_file_path)) { + event.returnValue = new Error('软件升级文件缺失,请联系售后技术支持') + return + } + + spawn('cmd.exe', ['/c', software_upgrade_file_path], { detached: true, shell: true }) + event.returnValue = 'OK' + } + + systemRepair(event: IpcMainEvent) { + if (!existsSync(SYSTEM_CONFIG_BAT_PATH)) { + event.returnValue = new Error('系统修复文件缺失,请联系售后技术支持') + return + } + + spawn('cmd.exe', ['/c', SYSTEM_CONFIG_BAT_PATH], { detached: true, shell: true }) + } + + async networkQuery(event: IpcMainEvent) { + try { + const current: WiFiNetwork[] = await getCurrentConnections() + let networks: WiFiNetwork[] = await scan() + networks = networks.filter(network => network.ssid.trim().length > 0) + + networks.sort( (a, b) => { return b.signal_level - a.signal_level }) + + if (current.length > 0) { + for (let index = 0; index < networks.length; index++) { + const network = networks[index] + + if (network.ssid === current[0].ssid) { + networks.unshift(networks.splice(index, 1)[0]) + break + } + } + } + + event.returnValue = { current, networks } + } catch (error) { + event.returnValue = 'ERROR' + } + } + + async networkConnect(event: IpcMainEvent, network: ConnectionOpts) { + try { + await connect(network) + + event.returnValue = 'OK' + } catch (error) { + event.returnValue = error + } + } + + async networkDisconnect(event: IpcMainEvent) { + try { + await disconnect() + + event.returnValue = 'OK' + } catch (error) { + event.returnValue = 'ERROR' + } + } + + burnProgram(event: IpcMainEvent, binFileName: string) { + if (!existsSync(ESP_TOOL_PATH) || + !existsSync(BOOT_APP0_BIN_PATH) || + !existsSync(BOOT_LOADER_BIN_PATH) || + !existsSync(PARTITIONS_BIN_PATH)) { + event.sender.send('BURN_PROGRAM_FEEDBACK', { err: new Error('烧录工具缺失,请联系售后技术支持') } ) + return + } + + const bin_file_path = join(BIN_FILE_ROOT_PATH, binFileName) + if (!existsSync(bin_file_path)) { + event.sender.send('BURN_PROGRAM_FEEDBACK', { err: new Error('程序文件缺失,请联系售后技术支持') } ) + return + } + + const mainWindow: MainWindow = BrowserWindow.fromWebContents(event.sender) as MainWindow + if (!mainWindow) { + event.sender.send('BURN_PROGRAM_FEEDBACK', { err: new Error('请先连接核心处理模块') } ) + return + } + // 参考1:https://docs.espressif.com/projects/esptool/en/latest/esp32/ + // 参考2:https://blog.csdn.net/espressif/article/details/105028809 + execFile(ESP_TOOL_PATH, + ['--chip', 'esp32', '--port', mainWindow.selectedPort ? mainWindow.selectedPort.portName : '', '--baud', '921600', '--before', 'default_reset', '--after', 'hard_reset', 'write_flash', '-z', '--flash_mode', 'dio', '--flash_freq', '80m', '--flash_size', 'detect', + '0xe000' , BOOT_APP0_BIN_PATH, + '0x1000' , BOOT_LOADER_BIN_PATH, + '0x10000', bin_file_path, + '0x8000' , PARTITIONS_BIN_PATH], (err, stdout) => { + if (err) { + event.sender.send('BURN_PROGRAM_FEEDBACK', { err } ) + } else { + event.sender.send('BURN_PROGRAM_FEEDBACK', { stdout }) + } + }); + } + + launchOnlineSoftware(_: IpcMainEvent, param: any) { + // TODO: 添加http网址正则表达式验证 + const { url } = param + + this.subWindow = new OnlineSoftwareWindow(url, this.subWindowOptions) + + this.showSubWindow() + } + + launchLocalSoftware(_: IpcMainEvent, param: any) { + const { subWindowName } = param + + switch (subWindowName) { + case 'BDAndTimeWindow': + this.subWindow = new BDAndTimeWindow(this.subWindowOptions) + break; + + case 'BDCommunicationAssistantWindow': + this.subWindow = new BDCommunicationAssistantWindow(this.subWindowOptions) + break; + + case 'BDComprehensiveExperimentalPlatformWindow': + this.subWindow = new BDComprehensiveExperimentalPlatformWindow(this.subWindowOptions) + break; + + case 'BDDataAnalysisPlatformWindow': + this.subWindow = new BDDataAnalysisPlatformWindow(this.subWindowOptions) + break; + + case 'BDPositionTrackRetracingWindow': + this.subWindow = new BDPositionTrackRetracingWindow(this.subWindowOptions) + break; + + case 'BDSatellite3DPostureDisplayWindow': + this.subWindow = new BDSatellite3DPostureDisplayWindow(this.subWindowOptions) + break; + + case 'BDSatelliteAttitudeControlWindow': + this.subWindow = new BDSatelliteAttitudeControlWindow(this.subWindowOptions) + break; + + case 'BDSatelliteParameterMonitoringPlatformWindow': + this.subWindow = new BDSatelliteParameterMonitoringPlatformWindow(this.subWindowOptions) + break; + + case 'BDSatelliteTimeConfigurationWindow': + this.subWindow = new BDSatelliteTimeConfigurationWindow(this.subWindowOptions) + break; + + case 'VoltageMonitoringWindow': + this.subWindow = new VoltageMonitoringWindow(this.subWindowOptions) + break; + + case 'WirelessCommunicationModuleConfigurationWindow': + this.subWindow = new WirelessCommunicationModuleConfigurationWindow(this.subWindowOptions) + break; + + case 'BDMeteorologicalDataDisplayPlatformWindow': + this.subWindow = new BDMeteorologicalDataDisplayPlatformWindow(this.subWindowOptions) + break; + + case 'BDMeteorologicalDataProtocolWindow': + this.subWindow = new BDMeteorologicalDataProtocolWindow(this.subWindowOptions) + break; + + case 'ElectronicScreenDesignWindow': + this.subWindow = new ElectronicScreenDesignWindow(this.subWindowOptions) + break; + + case 'GestureRecognitionWindow': + this.subWindow = new GestureRecognitionWindow(this.subWindowOptions) + break; + + case 'ClockConfigWindow': + this.subWindow = new ClockConfigWindow(this.subWindowOptions) + break; + + case 'FontDesignWindow': + this.subWindow = new FontDesignWindow(this.subWindowOptions) + break; + + case 'NixieTubeConfigurationWindow': + this.subWindow = new NixieTubeConfigurationWindow(this.subWindowOptions) + break; + + case 'DistanceCalculationToolWindow': + this.subWindow = new DistanceCalculationToolWindow(this.subWindowOptions) + break; + + case 'GeneratingConstellationChartWindow': + this.subWindow = new GeneratingConstellationChartWindow(this.subWindowOptions) + break; + + default: + break; + } + + this.showSubWindow() + } + + showSubWindow(): void { + if (!this.subWindow) return + + this.subWindow.maximize() + this.subWindow.once('ready-to-show', () => { + this.subWindow?.show() + }) + } +} diff --git a/src/main/window/localSoftware/NixieTubeConfigurationWindow.ts b/src/main/window/localSoftware/NixieTubeConfigurationWindow.ts new file mode 100644 index 0000000..3669b22 --- /dev/null +++ b/src/main/window/localSoftware/NixieTubeConfigurationWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class NixieTubeConfigurationWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('nixie-tube-configuration.html', options ) + } +} diff --git a/src/main/window/localSoftware/VoltageMonitoringWindow.ts b/src/main/window/localSoftware/VoltageMonitoringWindow.ts new file mode 100644 index 0000000..5bda4c8 --- /dev/null +++ b/src/main/window/localSoftware/VoltageMonitoringWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class VoltageMonitoringWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('voltage-monitoring.html', options) + } +} diff --git a/src/main/window/localSoftware/WirelessCommunicationModuleConfigurationWindow.ts b/src/main/window/localSoftware/WirelessCommunicationModuleConfigurationWindow.ts new file mode 100644 index 0000000..f0da7bf --- /dev/null +++ b/src/main/window/localSoftware/WirelessCommunicationModuleConfigurationWindow.ts @@ -0,0 +1,7 @@ +import { LocalSoftwareWindow } from '../LocalSoftwareWindow' + +export class WirelessCommunicationModuleConfigurationWindow extends LocalSoftwareWindow { + constructor (options = {}) { + super('wireless-communication-module-configuration.html', options) + } +}