node环境下使用serialport对串口设备进行轮询

上一节我们学习了node的SerialPort如何配置,本节我们从底层到前端完成一个简易串口轮询功能

底层逻辑

定义持续扫描函数scanInfinite, 启动时每隔500ms扫描所有连接的串口设备 , 得到一个串口队列ports , 扫描到ports之后 , 由于不同的系统串口驱动的名称是不一样的 , 区分mac和windows系统做好处理 , 然后把当前ports 和之前缓存的posts(即scannedSP)作比对 , 若一致 , 说明没有新连接串口 , 不管他 ; 不一致 , 说明新连接了串口 , 通过回调函数返回port信息,然后停止扫描

停止扫描的意义 : SerialPort在底层开了C++扫描进程 , 由于我们的扫描间隔是500ms , 当快速插拔时 , 可能会造成端口扫描超时 , 虽然我们设置了超时看门狗 , 但是当热插拔十分频繁 , 大量的扫描超时事件会造成栈溢出 , 使scanInfinite崩溃 . 避免崩溃的方法就是停止扫描 , 然后在前端接受的回调函数的时候强制重启scanInfinite函数

底层伪代码

const SerialPort = require('serialport')
// 扫描队列
this.scanTask = null
 // 扫描超时看门狗
this.scanWatchDog = null

scanInfinite(callback) {
    //扫描到的串口放在这里
    const scannedSP = []
    const _this = this
    // 开始轮询
    this.scanTask = setInterval(function() {
        //SerialPort.list是SerialPort内置方法,会返回连接的串口设备数组ports
      SerialPort.list(function(err, ports) {
        // 查询串口
        for (var i = 0; i < ports.length; i++) {
          var port = ports[i]
          // 就是这个串口
          let validPort = false
          // mac 平台 ,字符串是什么要自己去查串口驱动,这里我用的是wch公司开发的驱动
          if (process.platform === 'darwin') {
            //mac串口分为数据接口和管理接口和其他扩展接口,可能会有多个字符串,随便找一个就行
            validPort = port.comName.search('wchusbserial') !== -1
          } else {
            // windows平台
            validPort = port.manufacturer === 'wch.cn'
          }
          if (validPort) {
            // 将串口加到已扫描列表中,并回调通知
            const found = scannedSP.findIndex((e) => {
              return e.comName === port.comName
            })
            if (found === -1) {
              scannedSP.push(port)
              if (callback) {
                callback(null, port)
                _this.stopScan()
              }
            }
          }
        }
      })
    }, 500)
  }

  /** 停止扫描
   */
  stopScan() {
    if (this.scanWatchDog) {
      clearTimeout(this.scanWatchDog)
      this.scanWatchDog = null
    }
    if (this.scanTask) {
      clearInterval(this.scanTask)
      this.scanTask = null
    }
  }

前端Native逻辑

有了串口实例之后 , 就可以连接了,连接成功之后就是通信层面的socket业务函数了,结合上一节node环境下使用serialport对硬件指令进行封装 , 我们就可以与硬件进行通信了 , 这里是伪代码 , 在项目中其实是多个文件

注意SerialPort即使在没有反复插拔的的情况下长时间运行也会有一定的几率造成扫描跑飞(原因不明 , 可能是我写的程序有溢出,也可能是时这个包没有开多线程守护) , 这里我们可以自己写一个守护 , 在前端设置一个定时器来守护这个connected , 这里port的open方法中我们回调了onSuccess函数,这个函数会为前端层返回一个connected属性 , 然后使用testSp函数进行长轮询 , 在open的状态下 , 如果7次检查不到connected属性 , 那么直接重启扫描进程 , 如果open状态下打不开串口 , 我们就可以进行变砖检测了

前端Native伪代码

scanInfinite((err , comPort)=>{
     // 9600是波特率 , 如果使用232协议的话 , 衰减很低 , 可以直接上最大值230400波特率
     const port = new SerialPort(comPort.comName, { baudRate: 9600 })
     //在全局保存port变量
     SP._port=port
     port.on('error', (err) => {})
     port.on('close', () => {})
     port.on('data', (data) => {})
     port.on('open', () => {
        if(this.callback.onSuccess) {
            this.callback.onSuccess((connected=true)=>{
                  ....
            })
      }else{
            this.testBlock()
      }   
    })
})


  testSp = () => {
        let wachDog = 0
        _connTimer = setInterval(() => {
            let {connected} = this.state
            if (!connected) {
            // 7次长轮询失败,说明底层串口扫描已经崩了
                if (!SP._port) {
                    wachDog++;
                    console.log('watchDog is sleep')
                    if (wachDog > 7) {
                        wachDog = 0
                        console.log('watchDog  is raking')
                        SP.stopScan()
                        SP. scanInfinite(callback)
                    }
                } else {
                    console.log('已经插拔过', SP._port)
                }
            }
        },500)
  }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354