├── .gitignore ├── README.md ├── _config.yml ├── babel.config.js ├── package-lock.json ├── package.json ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── assets │ ├── logo.png │ └── nebula-helper.png ├── background.js ├── components │ └── Main.vue ├── main.js └── plugins │ └── element.js └── vue.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nebula Helper 2 | > 使用 Vue + Electron + node-serialport 实现的现代串行端口调试助手 3 | A modern serial port debugging assistant implemented using Vue + Electron + node-serialport 4 | ## 项目地址 5 | [GitHub](https://github.com/rymcu/nebula-helper) | [Gitee](https://gitee.com/ronger-x/nebula-helper) 6 | ## 功能特性 7 | - [x] 基础串口通信 8 | - [x] 自动发送信息 9 | - [x] 16 进制收发信息 10 | - [x] 停止/恢复显示 11 | - [x] 文件传输 12 | - [x] 保存/加载配置信息 13 | - [x] 刷新串口列表(手动刷新 视图->刷新串口列表) 14 | - [ ] 版本更新(不用每次下载完整的安装包,仅 `app.asar` 文件) 15 | ## 未来计划 16 | - [ ] 单片机程序下载(拷录程序到单片机) 17 | ## 开发指南 18 | > 本项目使用 Electron + Vue + Node-serialport 实现,以下步骤是 windows 操作系统环境配置步骤,1-5 步为安装 node-gyp ,其他操作系统请参考[官方教程](https://github.com/nodejs/node-gyp) 19 | 1. 安装 LTS 版 NodeJS 20 | 2. 安装 Python 2.7 21 | 3. 安装 Visitor Studio 2017 及更高版本(我使用的是 2019) 22 | 4. 执行 `npm install node-gyp -g` 23 | 5. 执行 `node-gyp list` 查看依赖是否全部安装 24 | 6. 执行 `git clone https://github.com/rymcu/nebula-helper.git` 25 | 7. 执行 `npm install` 26 | 8. 执行 `npm run electron:serve` 27 | ## 项目截图 28 | ![nebula-helper](https://github.com/rymcu/nebula-helper/blob/master/src/assets/nebula-helper.png?raw=true) 29 | ## 鸣谢 30 | - [Electron](https://github.com/electron/electron) :electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS 31 | - [Vue](https://github.com/vuejs/vue) 🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web. 32 | - [node-serialport](https://github.com/serialport/node-serialport) Access serial ports with JavaScript. Linux, OSX and Windows. Welcome your robotic JavaScript overlords. Better yet, program them! 33 | - [vue-cli-plugin-electron-builder](https://github.com/nklayman/vue-cli-plugin-electron-builder) Easily Build Your Vue.js App For Desktop With Electron 34 | "# nebula-iot-helper" 35 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nebula-helper", 3 | "version": "0.1.5", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint", 9 | "electron:build": "vue-cli-service electron:build", 10 | "electron:serve": "vue-cli-service electron:serve", 11 | "postinstall": "electron-builder install-app-deps", 12 | "postuninstall": "electron-builder install-app-deps", 13 | "install": "npm rebuild --runtime=electron --target=8.4.0 --disturl=https://npm.taobao.org/mirrors/atom-shell --abi=76" 14 | }, 15 | "author": { 16 | "name": "ronger", 17 | "email": "ronger-x@outlook.com", 18 | "url": "https://rymcu.com" 19 | }, 20 | "main": "background.js", 21 | "dependencies": { 22 | "@serialport/bindings": "^9.0.0", 23 | "core-js": "^3.6.5", 24 | "electron-log": "^4.2.2", 25 | "element-ui": "^2.4.5", 26 | "iconv-lite": "^0.6.2", 27 | "serialport": "^9.0.0", 28 | "vue": "^2.6.11" 29 | }, 30 | "devDependencies": { 31 | "@vue/cli-plugin-babel": "^4.4.0", 32 | "@vue/cli-plugin-eslint": "^4.4.0", 33 | "@vue/cli-service": "^4.4.0", 34 | "babel-eslint": "^10.1.0", 35 | "electron": "^8.4.0", 36 | "electron-devtools-installer": "^3.1.0", 37 | "eslint": "^6.7.2", 38 | "eslint-plugin-vue": "^6.2.2", 39 | "vue-cli-plugin-electron-builder": "^2.0.0-rc.4", 40 | "vue-cli-plugin-element": "^1.0.1", 41 | "vue-template-compiler": "^2.6.11" 42 | }, 43 | "eslintConfig": { 44 | "root": true, 45 | "env": { 46 | "node": true 47 | }, 48 | "extends": [ 49 | "plugin:vue/essential", 50 | "eslint:recommended" 51 | ], 52 | "parserOptions": { 53 | "parser": "babel-eslint" 54 | }, 55 | "rules": {} 56 | }, 57 | "browserslist": [ 58 | "> 1%", 59 | "last 2 versions", 60 | "not dead" 61 | ] 62 | } 63 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rymcu/nebula-helper/80c742bf46b4c0fe9be4ab55014d4e7362c30726/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 12 | 13 | 14 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | 26 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rymcu/nebula-helper/80c742bf46b4c0fe9be4ab55014d4e7362c30726/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/nebula-helper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rymcu/nebula-helper/80c742bf46b4c0fe9be4ab55014d4e7362c30726/src/assets/nebula-helper.png -------------------------------------------------------------------------------- /src/background.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import {app, protocol, BrowserWindow, Menu, shell} from 'electron' 4 | import {createProtocol} from 'vue-cli-plugin-electron-builder/lib' 5 | import installExtension, {VUEJS_DEVTOOLS} from 'electron-devtools-installer' 6 | 7 | const isDevelopment = process.env.NODE_ENV !== 'production' 8 | const serialPort = require('serialport'); 9 | const iconv = require('iconv-lite'); 10 | 11 | const log = require('electron-log') 12 | console.log = log.log 13 | 14 | const fs = require('fs'); 15 | 16 | global.SerialPort = serialPort; 17 | global.iconv = iconv; 18 | global.log = log.log; 19 | global.fs = fs; 20 | 21 | let menuTemplate = [ 22 | { 23 | label: '文件', 24 | role: 'fileMenu', 25 | submenu: [ 26 | { 27 | label: '保存接收数据', 28 | accelerator: 'Ctrl + S', 29 | click: function () { 30 | win.webContents.send('writeFile'); 31 | } 32 | }, 33 | { 34 | label: '读取文件数据', 35 | accelerator: 'Ctrl + L', 36 | click: function () { 37 | win.webContents.send('readFile'); 38 | } 39 | } 40 | , 41 | { 42 | label: '保存配置信息', 43 | accelerator: 'Ctrl + 1', 44 | click: function () { 45 | win.webContents.send('saveOptions'); 46 | } 47 | }, 48 | { 49 | label: '加载配置文件', 50 | accelerator: 'Ctrl + 2', 51 | click: function () { 52 | win.webContents.send('loadOptions'); 53 | } 54 | }, 55 | { 56 | label: '关闭', 57 | accelerator: 'Ctrl + W', 58 | click: function () { 59 | app.quit(); 60 | } 61 | } 62 | ] 63 | }, 64 | { 65 | label: '视图', 66 | role: 'viewMenu', 67 | submenu: [ 68 | { 69 | label: '刷新端口列表', 70 | accelerator: 'Ctrl + R', 71 | click: function () { 72 | win.webContents.send('reloadPorts'); 73 | } 74 | } 75 | ] 76 | }, 77 | { 78 | label: '帮助', 79 | role: 'help', 80 | accelerator: 'Ctrl + H', 81 | submenu: [ 82 | { 83 | label: '问题反馈', 84 | click: function () { 85 | shell.openExternal('https://github.com/rymcu/nebula-helper/issues') 86 | } 87 | }, 88 | { 89 | label: '关于我们', 90 | click: function () { 91 | shell.openExternal('https://rymcu.com') 92 | } 93 | } 94 | ] 95 | } 96 | ] 97 | // Keep a global reference of the window object, if you don't, the window will 98 | // be closed automatically when the JavaScript object is garbage collected. 99 | let win 100 | 101 | // Scheme must be registered before the app is ready 102 | protocol.registerSchemesAsPrivileged([ 103 | {scheme: 'app', privileges: {secure: true, standard: true}} 104 | ]) 105 | 106 | function createWindow() { 107 | // Create the browser window. 108 | win = new BrowserWindow({ 109 | width: 800, 110 | height: 600, 111 | resizable: false, 112 | webPreferences: { 113 | // Use pluginOptions.nodeIntegration, leave this alone 114 | // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info 115 | // nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION 116 | nodeIntegration: true, 117 | nodeIntegrationInWorker: true 118 | }, 119 | show: false 120 | }) 121 | 122 | if (process.env.WEBPACK_DEV_SERVER_URL) { 123 | // Load the url of the dev server if in development mode 124 | win.loadURL(process.env.WEBPACK_DEV_SERVER_URL) 125 | if (!process.env.IS_TEST) win.webContents.openDevTools() 126 | } else { 127 | createProtocol('app') 128 | // Load the index.html when not in development 129 | win.loadURL('app://./index.html') 130 | } 131 | 132 | win.on('closed', () => { 133 | win = null 134 | }) 135 | 136 | win.once('ready-to-show', () => { 137 | win.show() 138 | }) 139 | 140 | const menu = Menu.buildFromTemplate(menuTemplate); 141 | Menu.setApplicationMenu(menu); 142 | } 143 | 144 | // Quit when all windows are closed. 145 | app.on('window-all-closed', () => { 146 | // On macOS it is common for applications and their menu bar 147 | // to stay active until the user quits explicitly with Cmd + Q 148 | if (process.platform !== 'darwin') { 149 | app.quit() 150 | } 151 | }) 152 | 153 | app.on('activate', () => { 154 | // On macOS it's common to re-create a window in the app when the 155 | // dock icon is clicked and there are no other windows open. 156 | if (win === null) { 157 | createWindow() 158 | } 159 | }) 160 | 161 | // This method will be called when Electron has finished 162 | // initialization and is ready to create browser windows. 163 | // Some APIs can only be used after this event occurs. 164 | app.on('ready', async () => { 165 | if (isDevelopment && !process.env.IS_TEST) { 166 | // Install Vue Devtools 167 | try { 168 | await installExtension(VUEJS_DEVTOOLS) 169 | } catch (e) { 170 | console.error('Vue Devtools failed to install:', e.toString()) 171 | } 172 | } 173 | createWindow() 174 | }) 175 | 176 | // Exit cleanly on request from parent process in development mode. 177 | if (isDevelopment) { 178 | if (process.platform === 'win32') { 179 | process.on('message', (data) => { 180 | if (data === 'graceful-exit') { 181 | app.quit() 182 | } 183 | }) 184 | } else { 185 | process.on('SIGTERM', () => { 186 | app.quit() 187 | }) 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/components/Main.vue: -------------------------------------------------------------------------------- 1 | 120 | 121 | 698 | 699 | 701 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import './plugins/element.js' 4 | Vue.config.productionTip = false 5 | 6 | new Vue({ 7 | render: h => h(App), 8 | }).$mount('#app') 9 | -------------------------------------------------------------------------------- /src/plugins/element.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Element from 'element-ui' 3 | import 'element-ui/lib/theme-chalk/index.css' 4 | 5 | Vue.use(Element) 6 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | pluginOptions: { 3 | electronBuilder: { 4 | builderOptions: { 5 | "appId": "com.rymcu.nebula-helper", 6 | "productName": "nebula-helper", 7 | "copyright": "Copyright © rymcu.com", 8 | "win": { 9 | "icon": "./favicon.ico", 10 | "target": [ 11 | { 12 | "target": "nsis", 13 | "arch": [ 14 | "x64", 15 | "ia32" 16 | ] 17 | } 18 | ] 19 | }, 20 | "linux": { 21 | "icon": "./favicon.ico", 22 | "target": [ 23 | "snap" 24 | ] 25 | } 26 | } 27 | } 28 | } 29 | } --------------------------------------------------------------------------------