Electron+serialport串口开发

7,769 阅读3分钟

前端开发利用Electron + node-serialpost实现串口通信,最近有需求尽可能直接读取地磅数据,现有项目是vue写的网页项目,为了最大化的减少工作量,调研后发现用electron+serialport满足需求,通过iframe加载已经写好的页面,再通过与iframe通信传输串口数据即可。但折腾来折腾去,踩了各种坑也花了接近两周的时间,刚好遇到疫情,就研究了一波,特此记录一下配置过程,主要是整合资源,将全过程记录。

安装 electron serialport electron-rebuild

安装electron受网络环境影响可能需要科学上网,不能科学上网就用cnpm。

mkdir my-electron-app && cd my-electron-app\
npm init
cnpm i electron --save-dev
cnpm i serialport
cnpm i electron-rebuild --save-dev

安装依赖

node-serialport是一个让node可以访问电脑串口设备的原生模块,需要编译,也是出问题最多的一个环节。编译需要做一些准备工作。

  • 安装node-gyp、VS2017和python
npm install -g node-gyp 
npm install --global --production windows-build-tools
npm config set python python2.7 
npm config set msvs_version 2017
  • 编译
.\node_modules\.bin\electron-rebuild.cmd

可能出现的问题

  1. 安装windows-build-tools时卡顿,此时一大神发现了解决方案,我按照此步骤,成功解决问题。
  2. NODE_MOUDLE_VERSION不一致,这个错误有可能在软件运行时抛出。
  3. 其他各种问题,只能百度,实在不行就google,多次尝试,我花了一周多的时间才搞好... 成功一次就别在瞎折腾了,放过在下也放过自己,我重新搞了一次,结果又遇到各种问题...

测试serialport

若当前无硬件设备,需要下载虚拟串口工具(VSPD虚拟串口)和串口调试工具

package.json中将入口文件设置为main.js

// package.json
...
"main": "main.js"
...

添加main.js和html文件

在main.js添加测试代码,若控制台输出端口信息,则证明已经成功了95.8%了。

const serialport = require("serialport");
  serialport.list().then((ports) => {
    console.log(ports);
  });

image.png

在html中使用serialport

上一步成功后,我们尝试将serialport用在html页面中,发现控制台会报错,经过查找各种资料,发现Electron 9.0开始,官方推荐在渲染进程中不使用原生nodejs模块,哦吼,所以我们该怎么办。 image.png

想到我们在main.js主线程上能用,那我们可以研究研究主线程和渲染线程的通信。Electron提供了ipcMain和ipcRenderer API,网上文章页讲的很详细,找了一份带有示例的与大家分享:Electron笔记之进程间通信(ipc)

  1. html页面设置串口参数:串口名称、波特率、校验位和停止位等参数,设置完将参数发送至主线程。
  2. 主线程接收参数,打开串口,接收数据(利用串口调试工具发送数据)。
  3. npm start启动项目,发现得到数据,成功!
const { ipcMain } = require("electron");

ipcMain.on("open-serialport", (event, args) => {
    const port = new serialport(path, options, errorCallback);
    port.on('data', data => {
        // 将串口接收的数据返回渲染进程,用于显示
        event.sender.send("send-data", `${data}`);
    });
});

vscode对electron主线程调试

程序员怎么能不会调试呢!参照此篇文章进行调试。

打包

上面的都行的通之后,通过与iframe的通信便满足需求了。接下来研究怎么打包成安装包,因为还涉及到客户端的更新升级,在下用的electron-builder,安装完之后,在package.json添加打包命令,执行命令 npm run build 发现大量报错,一看都是网络原因,怎么办,不要怕,大神多的很,请参照electron-builder打包采坑问题汇总配置,一个字:好使!打包完后dist文件夹长这样,exe就是我们的安装程序了。

image.png

npm i electron-builder
// package.json
"build": {
    "appId": "com.xxx.app",
    "productName": "marco-test-app",
    "publish": [
      {
        "provider": "generic",
        "url": "http://localhost:7777/download",
        "channel": "latest"
      }
    ],
    "mac": {
      "target": [
        "dmg",
        "zip"
      ]
    },
    "win": {
      "target": [
        "nsis",
        "zip"
      ]
    },
    "nsis": {
      "oneClick": false,
      "allowToChangeInstallationDirectory": true, 
      "allowElevation": true,
      "createDesktopShortcut": true,
      "createStartMenuShortcut": true,
      "shortcutName": "marco-app"
    }
  },
 "scripts": {
    "start": "electron --inspect=8888 .",
    "build": "electron-builder --win --x64"
  },

自动更新 electron-updater

给了用户安装包,那必须得支持版本更新啊,我们怎么搞?

不要怕,electron也提供了更新策略,安装electron-updater,然后在main.js中检测更新,在package.json -> build -> publish中配置更新地址,为方便本地测试,我们用node在本地配置更新地址,可参考Electron应用实现自动更新 配置本地环境,打包的更新文件一定要放对位置,一定要有latest.yml文件,若不存在,需要在package.json -> build -> publish添加 "channel":"latest",配置完,安装软件后,如有高版本就会自动下载安装。

本地运行npm start测试更新时,可能会报错:dev-app-update.yml文件不存在或者Update for version X.X.X is not available (latest version: x.x.x, downgrade is disallowed),测试在本地建立此文件,将打包的文件夹win-unpacked\resources中app-update.yml内容复制过来即可,更多错误参考electron-updater更新electron应用程序

npm i electron-updater
// main.js
app.whenReady().then(() => {
  createWindow();
  checkForUpdates();
});

function checkForUpdates() {
  // 更新地址,即新版本存放地址
  autoUpdater.setFeedURL("http://localhost:7777/download");
  autoUpdater.checkForUpdates();

  autoUpdater.on("update-available", function (info) {
    dialog.showMessageBox({title: '更新', message: '有更新可用'});
  });

  autoUpdater.on('update-not-available', function (info) {
    dialog.showMessageBox({title: '无更新', message: '无更新可用'});
  })

  autoUpdater.on("update-downloaded", (info) => {
    dialog.showMessageBox(
      {
        // icon: __static + "/favicon.png",
        type: "info",
        title: "软件更新",
        message: `已更新到最新版本(${info.version})请重启应用。`,
        // detail: detail,
        buttons: ["确定"],
      },
      (idx) => {
        // 点击确定的时候执行更新
        if (idx === 0) {
          autoUpdater.quitAndInstall();
        }
      }
    );
  });
}
"build": {
    "appId": "com.xxx.app",
    "productName": "marco-test-app",
    "publish": [
      {
        "provider": "generic",
        "url": "http://localhost:7777/download",
        "channel": "latest"
      }
    ],
    "mac": {
      "target": [
        "dmg",
        "zip"
      ]
    },
    "win": {
      "target": [
        "nsis",
        "zip"
      ]
    },
    "nsis": {
      "oneClick": false,
      "allowToChangeInstallationDirectory": true, 
      "allowElevation": true,
      "createDesktopShortcut": true,
      "createStartMenuShortcut": true,
      "shortcutName": "marco-app"
    }
  }

总结

这一套流程下来,都要哭了,会遇到各种各样的问题,我一共花了接近两周时间(一天不到两小时)才搞好,太难了,中途想过放弃不搞了,但他越出错我越想搞,幸运的是最终成功了,不能保证按照这个流程一定成功,仅记录过程。

参考文章:

实战Electron使用SerialPort与串口交互详细全过程

npm安装windows-build-tools时卡在Successfully installed Python 2.7

electron使用serialport报错NODE_MOUDLE_VERSION不一致

Electron笔记之进程间通信(ipc)

Electron怎样进行渲染进程调试和使用浏览器和VSCode进行调试

Electron应用实现自动更新

electron-updater更新electron应用程序