原文地址:https://segmentfault.com/a/1190000003883095
写在前面
公司的自行车终于接入微信成功,期间经历了无数的大坑,为了同学们不在误入歧途,特地总结,希望对各位有用。你们的收藏与推荐是我继续完善的动力,如果有不明白或者有误的地方,欢迎加qq群讨论,我看到后会在第一时间回复
开发者交流QQ群:390465183
什么是微信硬件JSAPI
微信硬件是微信推出的一项基于公众号的设备服务,依托微信的平台,通过蓝牙或者wifi接入硬件设备,与微信app连接,实现各种服务
两个概念
- 微信js-sdk
- 微信硬件js-api
这里要明确两个概念,微信js-sdk是微信给开发人员使用的通用api,不分使用场景,而微信硬件jsapi是专门用来给微信硬件使用的。虽然这两个东西引入的都是同一个微信JS库,但是发挥的作用不同
前期准备
在老板跟你讲,hi,xx,我们搞了个XX手环,你把这东西给我接到微信里面去。千万不要大腿一拍开始写撸代码,你至少要准备这些东西:
- 一个通过微信认证的服务号
- 服务号开通了设备功能插件
- 具有操作jsapi的权限
注意:这里不要使用开发者测试号,硬件JSAPI目前还未向开发者测试账号开放,请使用正式的服务号,服务号的注册就不说了。通过认证之后,在微信后台添加设备功能插件。添加插件后,发送邮件到wxthings@foxmail.com ,申请微信硬件jsapi的操作权限
连接一个设备
我们想用微信操作一个设备,首先这个设备必须和微信连接在一起,就像下图这样,在你的微信公众号界面上,ios系统会显示已连接,安卓系统会显示已连接1个设备,只有在这个基础上,你才可以进行下一步的操作
注意,如果安卓显示已连接0个设备,那么对不起,你的连接是失败的,没有连接成功
那么如何才能在微信显示已连接呢,作为前端,你需要做好下面这些:
- 在微信后台申请一个设备二维码,
- 问硬件同学拿到你要连接的设备的mac地址,
- 将mac地址和设备的二维码在微信后台授权,这一步很关键
- 打开手机蓝牙,等待和设备的连接
注意,做为前端,你只要把上面这几步做好就可以了,剩下的就是硬件同学的事情了,当你打开微信,进入微信公众号界面,微信app就会主动寻找周围的设备,发送连接数据包,而你的设备,在收到微信数据包的时候应该主动发送回包,类似于TCP协议的三次握手,当微信收到回包之后,连接建立,微信界面就会显示已连接
引入js库
这是微信的js库,使用微信js接口,必须引入这个库,微信设备功能手册里面并没有写要引入这个库,新手在这里就要入坑了
<script type="text/javascript" src='http://res.wx.qq.com/open/js/jweixin-1.0.0.js'></script>
为页面注入配置信息
这个config中几个字符串的生成比较复杂,微信后台提供了完整的demo,可以拿来使用生成自己的配置参数
wx.config({
beta: true, // 开启内测接口调用,注入wx.invoke方法,非常重要!!必须有这个
debug: true,//开启调试接口,alert运行结果
appId: '',//必填,公众号的唯一标识,
timestamp: '',//必填,生成签名的时间戳
nonceStr: '',//必填,生成签名的随机串
signature: '',//必填,签名,见附录1
jsApiList: []//要调用的js函数,必须把函数名字写入数组
});
注意:调用微信硬件jsapi必须在config中配置beta:true这个选项,而公开的开发手册里面没有讲这个,第一次接手的人走到这里绝对入坑,最后一个参数是jsApiList数组,你必须把所有用到的函数名字添加在这个数组里面,比如说初始化库的openWXDeviceLib,发送数据的sendDataToWXDevice等等
通过ready接口处理成功验证
wx.ready(function(){
// 初始化设备库函数
wx.invoke('openWXDeviceLib', {}, function(res){
// alert(res.err_msg);
});
});
注意:你必须在ready中调用openWXDeviceLib来初始化库,getWXDeviceInfos()和sendDataToWXDevice()不用在这里调用,后者在你的业务逻辑里面调用就可以
准备你要发送的数据包
var data={"deviceId": '微信给你的设备id',"base64Data": '你要发送的数据'};
注意:data的第一个参数是设备的id,第二个参数是你要发送的message,message一定要用base64编码,否则设备没有办法解析,在这里我在放一个使用javascript对字符串进行base64编码的函数
js封装的base64编码函数
var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
function base64encode(str) {
var out, i, len;
var c1, c2, c3;
len = str.length;
i = 0;
out = "";
while(i < len) {
c1 = str.charCodeAt(i++) & 0xff;
if(i == len)
{
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt((c1 & 0x3) << 4);
out += "==";
break;
}
c2 = str.charCodeAt(i++);
if(i == len)
{
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
out += base64EncodeChars.charAt((c2 & 0xF) << 2);
out += "=";
break;
}
c3 = str.charCodeAt(i++);
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));
out += base64EncodeChars.charAt(c3 & 0x3F);
}
return out;
}
发送到设备
第二个参数data就是我们在上一步准备的data,当程序执行的到这一步的时候,你的设备就应该收到了你通过蓝牙在微信里面发送的数据,使用WeixinJSBridge.invoke或者wx.invoke都可以,这两者微信都可以识别的
// 发送设置命令
wx.invoke('sendDataToWXDevice', data, function(res){
//回调
});
监听设备返回的数据
在onReceiveDataFromWXDevice函数中,你可以对设备返回的任何数据进行监听,这个函数最大的用处就是初始化的时候,在页面显示设备当前信息
wx.on('onReceiveDataFromWXDevice', function(argv) {
var obj=eval("("+JSON.stringify(argv)+")");
//这里的obj就是你收到的数据对象
//这里你要对数据再做一次解码
})
我遇到的问题
调用jsapi返回access_denied错误
这个一般的原因都是因为公众号还没有获得jsapi的使用权限,或者你的微信公众号后台还没有添加硬件设备功能
开发建议
用什么ui
日前微信同学开源了WeUI,这是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信 Web 开发量身设计,可以令用户的使用感知更加统一。包含button、cell、dialog、 progress、 toast、article、icon等各式元素,建议设计师同学可直接采用这套ui,与微信原生视觉统一
选一个js库
我们开发出来的应用,必须是跑在微信内置浏览器中,这个浏览器还是有很多兼容方面的问题,所以建议选用zepto.js库,避免后期出现的各种问题
本地保存绑定关系表
当设备接入微信成功之后,会有很多业务逻辑需要获取用户名下绑定的设备或者和设备有关的用户,微信有后台api给我们调用来获取这些信息,但是这些api的接口调用都是有次数限制的,所以务必在你的server上用一张表来保存所有的绑定关系