init commit
parent
09fd8d57c4
commit
c1fc36b44c
|
@ -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)
|
||||||
|
// }
|
|
@ -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)
|
|
@ -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)
|
||||||
|
}
|
||||||
|
})
|
|
@ -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() {}
|
||||||
|
}
|
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { BaseWindow } from './BaseWindow'
|
||||||
|
|
||||||
|
export class OnlineSoftwareWindow extends BaseWindow {
|
||||||
|
constructor (url: string, options = {}) {
|
||||||
|
super(options)
|
||||||
|
|
||||||
|
this.loadURL(url)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class BDAndTimeWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('BD&time.html', options )
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class BDCommunicationAssistantWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('BD-communication-assistant.html', options)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class BDComprehensiveExperimentalPlatformWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('BD-comprehensive-experimental-platform.html', options)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class BDDataAnalysisPlatformWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('BD-data-analysis-platform.html', options)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class BDMeteorologicalDataDisplayPlatformWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('BD-meteorological-data-display-platform.html', options )
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class BDMeteorologicalDataProtocolWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('BD-meteorological-data-protocol.html', options )
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class BDSatellite3DPostureDisplayWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('BD-satellite-3D-posture-display.html', options)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class BDSatelliteAttitudeControlWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('BD-satellite-attitude-control.html', options)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class BDSatelliteParameterMonitoringPlatformWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('BD-satellite-parameter-monitoring-platform.html', options)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class BDSatelliteTimeConfigurationWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('BD-satellite-time-configuration.html', options)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class ClockConfigWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('clock-config.html', options )
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class DistanceCalculationToolWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('distance-calculation-tool.html', options )
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class ElectronicScreenDesignWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('electronic-screen-design.html', options )
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class GeneratingConstellationChartWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('generating-constellation-chart.html', options )
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class GestureRecognitionWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('gesture-recognition.html', options )
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class NixieTubeConfigurationWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('nixie-tube-configuration.html', options )
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class VoltageMonitoringWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('voltage-monitoring.html', options)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { LocalSoftwareWindow } from '../LocalSoftwareWindow'
|
||||||
|
|
||||||
|
export class WirelessCommunicationModuleConfigurationWindow extends LocalSoftwareWindow {
|
||||||
|
constructor (options = {}) {
|
||||||
|
super('wireless-communication-module-configuration.html', options)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue