蓝牙模块Noble不兼容最新的macOS系统(10.15.4)的解决方法

2020年3月底,macOS新版本的系统:catalina 10.15.4发布了,测试和产品提出问题:当更新了最新的系统后,electron的项目中的蓝牙功能不能用了。

看了一下目前正在使用的蓝牙模块的底层代码:
蓝牙模块Noble不兼容最新的macOS系统(10.15.4)的解决方法
发现以前的同事也遇过macOS版本更新后,noble模块不能兼容的问题,解决方法主要是去把noble模块的发起蓝牙连接和写入指令等js代码改写,关键点是改写通信id。如上图,noble模块很多接口都有一个msgId,而这个msgId在不同的系统版本上是不一样的。

那我怎么知道在新的macOS系统是,对应的很多个接口(startScan接口、discover接口、stateChange、stopScan、connent、disconnect、updateRssi等很多接口),他们的msgId 是什么呢?

方法是通过循环**的方法去找,代码如下:
蓝牙模块Noble不兼容最新的macOS系统(10.15.4)的解决方法
蓝牙模块Noble不兼容最新的macOS系统(10.15.4)的解决方法
思路是,在需要寻找msgId的地方,直接写代码循环,一次性提交很多个msgId的请求,监听的时候也是,直接监听很多个kCBMsgId,这样子总有一个提交的msgId会对应命中到监听的on方法上的kCBMsgId,以此类推,一个一个方法去找,就能找到对应的id,改写过来。

我用这种方法确实也能找出很多msgId在macOs系统的catalina 10.15.4版本上的兼容的id,如下:
stateChange: 6
startScanning: 53
response to startScanning: 60
scanStop: 52
connect: 56
response to connect: 63
response to disconnect: 61
discoverServices: 102
response to discover service: 107
但是当我找到response to discoverservice 这个方法的时候,107的on监听方法能够接收到硬件返回的数据,但是参数内容相比以前的版本,变了:
蓝牙模块Noble不兼容最新的macOS系统(10.15.4)的解决方法
具体改变的内容是:
旧版本上,response to discoverservice方法返回的参数是:
蓝牙模块Noble不兼容最新的macOS系统(10.15.4)的解决方法
macOS catalina 10.15.4上,response to discoverservice方法返回的参数是:
蓝牙模块Noble不兼容最新的macOS系统(10.15.4)的解决方法
少了servicesUuid,而这个参数的确是导致后面连接不上蓝牙。经过调试,发现修复不了,此问题似乎是noble模块在最新的macOS10.15.4上的一个bug,然后去github上相关issue上提了问题。得到的回复是:请使用这个蓝牙模块:@abandonware/noble
蓝牙模块Noble不兼容最新的macOS系统(10.15.4)的解决方法
看了一下,该库的底层不是js了,而是c++写的。

然后就在当前项目中引入当前@abandonware/noble模块,发现很多报错,其中就有无法编译binding.node模块的问题。这应该是在我的项目中,electron版本过低,1.4.5,在编译底层c++模块以及其引用的其他c++和node原生的模块的时候,报错了。

然后就打算升级electron版本,但是因为整个项目包括node、npm、以及其他依赖包,很多版本都是相互匹配的,升级过程中依然遇到很多版本不匹配,或者can’t resolve一些模块的问题,导致无法引入并跑起@abandonware/noble

继续寻找方法。。。

在github上找了一个新的项目demo,electron-vue,https://github.com/SimulatedGREG/electron-vue ,发现在此项目上可以引入@abandonware/noble,并且编译通过,能够被调用。

然后就在此项目框架上,改写自己的项目底层,原本自己的项目,是用electron+cooking做的,打包的cooking早就没有维护了,electron版本1.4.5也太低了。

然后就是项目迁移,electron版本也升级到2.0.4,cooking改为webpack,解决了很多模块依赖的报错,打包和编译的报错,然后终于能运行起来了,@abandonware/noble也能正常连接到蓝牙。

@abandonware/noble遇到一个小坑:
蓝牙模块Noble不兼容最新的macOS系统(10.15.4)的解决方法
它的write方法,不能接收undefined数据了,估计跟底层语言有关,需要加个判断才行,如上图。否则write方法不能用,写入蓝牙指令功能就不能用了。