• 微信蓝牙设备开发之初步接入微信硬件jsapi接口

    文章来源:http://www.vxzsk.com/145.html 

    已推出最新微 信硬件jsapi学习笔记 地址 http://www.vxzsk.com/282.html

    微信app和蓝牙设备接入通信,通信交互通道有两种,如下图通道路径结构图@V型知识库原创


    黑色箭头 公众号html界面发送命令到设备,设备最终返回数据到厂商服务器,厂商服务器也就是咱们开发者自己工程项目的服务器后端(数据返回到服务器配置url的 servelet的post方法中了)。这也是导致初学者开发者在开发h5界面发送指令后,无论如何在h5前端界面也得不到蓝牙设备返回数据包的原因,这是个坑,大家注意。

    红色箭头 也就是我们接下来介绍的通道路径,公众号html界面发送指令到设备,设备最终返回数据到发送html命令的界面,意思就是H5界面发送指令到设备,设备返回响应数据包到H5界面,而不是服务器端。

    点击公众号菜单或链接跳转到H5界面的java方法(案例用的springMVC),在此方法中获取timestamp,nonceStr,signature三个参数。

    1、spring的controller方法

    //V型知识库 www.vxzsk.com 
    @RequestMapping(value="/goReadCardAnniu")
        public ModelAndView goReadCardAnniu2(HttpServletRequest request,HttpServletResponse response){
             
                 String appId="";//应用id
                 String appsecret="";//应用秘钥
                //1,获取access_token
                AccessToken accessToken = WeixinUtil.getAccessToken(appId, appsecret);
                String access_token=accessToken.getToken();
                //2,获取调用微信jsapi的凭证
                String ticket = WeixinUtil.getJsapiTicket(access_token);
                Map<String,String> map = WeixinUtil.sign(ticket, AppConst.SITE_DOMAIN+"lanya/card/goReadCardAnniu.do");
             
            request.setAttribute("timestamp", map.get("timestamp"));
            request.setAttribute("nonceStr", map.get("nonceStr"));
            request.setAttribute("signature", map.get("signature"));
            request.setAttribute("appId", appId);
             
            return new ModelAndView("/weixin/device/b_chat_s_anniu");
        }

    注意第12行的WeixinUtil.sign方法,第二个参数路径一定是跳转H5界面的路径,否则在H5界面初始化微信硬件jsapi会报错。

    2、获取access_token请参考http://www.vxzsk.com/28.html

    3、获取getJsapiTicket方法

    public static String getJsapiTicket(String access_token){
             String getticket_url="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=";//接口凭据
            String jsonData=HttpUtil.sendGet(getticket_url+access_token+"&type=jsapi", "utf-8", 30000);
            JSONObject jsonObj = JSONObject.fromObject(jsonData);
            String errcode = jsonObj.getString("errcode");
            String ticket = null;
            if(errcode.equals("0")){
                ticket = jsonObj.getString("ticket");
            }
            return ticket;
        }

    HttpUtil.sendGet方法 请参考http://www.vxzsk.com/doc/25.html

    4、WeixinUtil.sign方法获取timestamp,nonceStr,signature三个参数方法

    /***
         * 获取界面调用jsapi的所需参数
         * @param jsapi_ticket 凭据
         * @param url 界面请求地址
         * @return
         V型知识库 www.vxzsk.com
         */
        public static Map<String, String> sign(String jsapi_ticket, String url) {
            Map<String, String> ret = new HashMap<String, String>();
            String nonce_str = create_nonce_str();
            String timestamp = create_timestamp();
            String string1;
            String signature = "";
     
            //注意这里参数名必须全部小写,且必须有序
            string1 = "jsapi_ticket=" + jsapi_ticket +
                      "&noncestr=" + nonce_str +
                      "×tamp=" + timestamp +
                      "&url=" + url;
            System.out.println(string1);
     
            try
            {
                MessageDigest crypt = MessageDigest.getInstance("SHA-1");
                crypt.reset();
                crypt.update(string1.getBytes("UTF-8"));
                signature = byteToHex(crypt.digest());
            }
            catch (NoSuchAlgorithmException e)
            {
                e.printStackTrace();
            }
            catch (UnsupportedEncodingException e)
            {
                e.printStackTrace();
            }
     
            ret.put("url", url);
            ret.put("jsapi_ticket", jsapi_ticket);
            ret.put("nonceStr", nonce_str);
            ret.put("timestamp", timestamp);
            ret.put("signature", signature);
     
            return ret;
        }
         
        private static String byteToHex(final byte[] hash) {
            Formatter formatter = new Formatter();
            for (byte b : hash)
            {
                formatter.format("%02x", b);
            }
            String result = formatter.toString();
            formatter.close();
            return result;
        }
     
        private static String create_nonce_str() {
            return UUID.randomUUID().toString();
        }
     
        private static String create_timestamp() {
            return Long.toString(System.currentTimeMillis() / 1000);
        }
        

    以上便是跳转H5界面的controller方法,跳转到b_chat_s_anniu.jsp界面的代码如下,先来个分割线


    1、jsp界面引入微信硬件jsapi的js库,jquery库

    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script> 
      <script src="http://res.wx.qq.com/open/js/jweixin-1.1.0.js"> </script>

    2、<body></body>之间的html代码

    <!--标题行-->
    <h2 style="color: white;background-color: green;text-align: center;background-position: center;">蓝牙设备</h2>
      <div class="page">
        <div class="bd spacing">
            <div class="weui_cells weui_cells_form">
                    
                <div class="weui_cell">
                    <div class="weui_cell_hd"><label class="weui_label" style="width: auto;">当前设备: </label></div>
                    <div class="weui_cell_bd weui_cell_primary">
                       <label id="lbdeviceid" class="weui_label" style="width: auto;"></label>
                    </div>
                </div>
                <div class="weui_cell">
                    <div class="weui_cell_hd"><label class="weui_label" style="width: auto;">状态信息: </label></div>
                    <div class="weui_cell_bd weui_cell_primary">
                        <label id="lbInfo" class="weui_label" style="width: auto;"></label>
                    </div>
                </div> 
                <div class="weui_cell" >
                    <div class="weui_cell_hd"><label class="weui_label">日志:  </label></div>
                    <div class="weui_cell_bd weui_cell_primary">
                        <textarea id="logtext" class="weui_textarea" placeholder="日志" rows="5"></textarea>
                    </div>
                </div>
      
            </div>
     
            <div class="weui_btn_area weui">
                 
                <button class="weui_btn weui_btn weui_btn_warn" id="CallGetWXrefresh">获取设备</button><br>
      
            </div>
      
        </div>
     
        <div class="weui_dialog_alert" id="Mydialog" style="display: none;">
        <div class="weui_mask"></div>
        <div class="weui_dialog">
            <div class="weui_dialog_hd" id="dialogTitle"><strong class="weui_dialog_title">着急啦</strong></div>
            <div class="weui_dialog_bd" id="dialogContent">亲,使用本功能,请先打开手机蓝牙!</div>
            <div class="weui_dialog_ft">
                <a href="#" class="weui_btn_dialog primary">确定</a>
            </div>
        </div>
        </div>
         
         
        <!--BEGIN toast-->
        <div id="toast" style="display: none;">
            <div class="weui_mask_transparent"></div>
            <div class="weui_toast">
                <i class="weui_icon_toast"></i>
                <p class="weui_toast_content" id="toast_msg">已完成</p>
            </div>
        </div>
        <!--end toast-->
     
        <!-- loading toast -->
        <div id="loadingToast" class="weui_loading_toast" style="display:none;">
            <div class="weui_mask_transparent"></div>
            <div class="weui_toast">
                <div class="weui_loading">
                    <div class="weui_loading_leaf weui_loading_leaf_0"></div>
                    <div class="weui_loading_leaf weui_loading_leaf_1"></div>
                    <div class="weui_loading_leaf weui_loading_leaf_2"></div>
                    <div class="weui_loading_leaf weui_loading_leaf_3"></div>
                    <div class="weui_loading_leaf weui_loading_leaf_4"></div>
                    <div class="weui_loading_leaf weui_loading_leaf_5"></div>
                    <div class="weui_loading_leaf weui_loading_leaf_6"></div>
                    <div class="weui_loading_leaf weui_loading_leaf_7"></div>
                    <div class="weui_loading_leaf weui_loading_leaf_8"></div>
                    <div class="weui_loading_leaf weui_loading_leaf_9"></div>
                    <div class="weui_loading_leaf weui_loading_leaf_10"></div>
                    <div class="weui_loading_leaf weui_loading_leaf_11"></div>
                </div>
                <p class="weui_toast_content" id="loading_toast_msg">数据加载中</p>
            </div>
        </div>
        <!-- End loading toast -->
         
        <!--BEGIN dialog1-->
        <div class="weui_dialog_confirm" id="dialog1" style="display: none;">
            <div class="weui_mask"></div>
            <div class="weui_dialog">
                <div class="weui_dialog_hd"><strong class="weui_dialog_title">弹窗标题</strong></div>
                <div class="weui_dialog_bd">自定义弹窗内容,居左对齐显示,告知需要确认的信息等</div>
                <div class="weui_dialog_ft">
                    <a href="javascript:;" class="weui_btn_dialog default" id="qxBtn">取消</a>
                    <a href="javascript:;" class="weui_btn_dialog primary" id="okBtn">确定</a>
                </div>
            </div>
        </div>
        <!--END dialog1-->
        <!--BEGIN dialog2-->
        <div class="weui_dialog_alert" id="dialog2" style="display: none;">
            <div class="weui_mask"></div>
            <div class="weui_dialog">
                <div class="weui_dialog_hd"><strong class="weui_dialog_title">弹窗标题</strong></div>
                <div class="weui_dialog_bd">弹窗内容,告知当前页面信息等</div>
                <div class="weui_dialog_ft">
                    <a href="javascript:;" class="weui_btn_dialog primary">确定</a>
                </div>
            </div>
        </div>
        <!--END dialog2-->
    </div>
     
    <div id="myparams" style="display: none">
     <span id="timestamp">${timestamp }</span>
     <span id="nonceStr">${nonceStr }</span>
     <span id="signature">${signature }</span>
     <span id="appId">${appId }</span>
      
    </div>

    上述html最后四行代码就是我们在controller中存储在request对象中的四个参数

    3、重点来了,初始化微信硬件jsapi库,代码如下

    jQuery(document).ready(function(){
      //初始化库 
     loadXMLDoc();
     //初始化库结束
     //点击获取设备按钮的函数 开始
     $("#CallGetWXrefresh").on("click",function(e){  
        
         //1. 打开微信设备 
         my_openWXDeviceLib();
         //2. 获取设备信息
         my_getWXDeviceInfos();
     });
     //点击获取设备按钮的函数 结束 
       
     });

    loadXMLDoc();方法是初始化微信硬件jsapi库,后面方法是给"获取设备"按钮绑定一个点击事件

    1)、loadXMLDoc();方法代码

    //初始化 微信硬件jsapi库 V型知识库 www.vxzsk.com
    function loadXMLDoc()
    {
        var appId =jQuery("#appId").text();
        var timestamp=jQuery("#timestamp").text();
        var nonceStr =jQuery("#nonceStr").text();
        var signature=jQuery("#signature").text();
        wx.config({
                 beta: true,
                  debug: true,// 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                  appId: appId, 
                  timestamp: timestamp,
                  nonceStr: nonceStr,
                  signature: signature,
                  jsApiList: [
                    'openWXDeviceLib',
                    'closeWXDeviceLib',
                    'getWXDeviceInfos',
                    'getWXDeviceBindTicket',
                    'getWXDeviceUnbindTicket',
                    'startScanWXDevice',
                    'stopScanWXDevice',
                    'connectWXDevice',
                    'disconnectWXDevice',
                    'sendDataToWXDevice',
                    'onWXDeviceBindStateChange',
                    'onWXDeviceStateChange',
                    'onScanWXDeviceResult',
                    'onReceiveDataFromWXDevice',
                    'onWXDeviceBluetoothStateChange',
                  ]
              });
                 alert("初始化库结束");
    }

    此方法需要四个参数,我们已经在controller中获取并存放到request对象中了。

    2)、打开设备方法my_openWXDeviceLib()代码

    function my_openWXDeviceLib(){
       var x=0; 
       WeixinJSBridge.invoke('openWXDeviceLib', {}, 
       function(res){
           mlog("打开设备返回:"+res.err_msg);
          if(res.err_msg=='openWXDeviceLib:ok')
            {
              if(res.bluetoothState=='off')
                {    
                  showdialog("太着急啦","亲,使用前请先打开手机蓝牙!");  
                  $("#lbInfo").innerHTML="1.请打开手机蓝牙";
                  $("#lbInfo").css({color:"red"});
                  x=1;
                  isOver();
                };
              if(res.bluetoothState=='unauthorized')
                {
                  showdialog("出错啦","亲,请授权微信蓝牙功能并打开蓝牙!");    
                  $("#lbInfo").html("1.请授权蓝牙功能");
                  $("#lbInfo").css({color:"red"});
                  x=1;
                  isOver();
                }; 
              if(res.bluetoothState=='on')
                {
                  //showdialog("太着急啦","亲,请查看您的设备是否打开!");   
                  $("#lbInfo").html("1.蓝牙已打开,未找到设备");
                  $("#lbInfo").css({color:"red"});
                  //$("#lbInfo").attr(("style", "background-color:#000");
                  x=0;
                  //isOver();
                };      
            }
          else
            {
              $("#lbInfo").html("1.微信蓝牙打开失败");
              x=1; 
              showdialog("微信蓝牙状态","亲,请授权微信蓝牙功能并打开蓝牙!");   
            }
        });
       return x;  //0表示成功 1表示失败
    }


    3)、获取设备信息方法my_getWXDeviceInfos代码

    function my_getWXDeviceInfos(){
        
        WeixinJSBridge.invoke('getWXDeviceInfos', {}, function(res){
            var len=res.deviceInfos.length;  //绑定设备总数量
            for(i=0; i<=len-1;i++)
             {
               //alert(i + ' ' + res.deviceInfos[i].deviceId + ' ' +res.deviceInfos[i].state); 
               if(res.deviceInfos[i].state==="connected")
                {
                  $("#lbdeviceid").html(res.deviceInfos[i].deviceId); 
                  C_DEVICEID = res.deviceInfos[i].deviceId;
                  $("#lbInfo").html("2.设备已成功连接");
                  $("#lbInfo").css({color:"green"});
                  
                  break;   
                }  
             }
                
        }); 
      return;    
    }

    4)、日志输出方法

    //打印日志
    function mlog(m){
        var log=$('#logtext').val();
        //log=log+m;
        log = m;
        $('#logtext').val(log);
    }

    好了,至此代码都已经写玩了,咱们来看看效果吧。

    第一、打开手机蓝牙并登录微信,扫描设备的二维码,具体如何生成设备二维码和授权设备请参考左上角菜单中的其它章节。

    第二,绑定设备-进入公众号,然后我们可以看到公众号头部已经有"已连接1个设备或未连接"


    第三、点击我们上面所说的controller方法,进入H5界面


    第四、点击获取设备按钮


    如图所示,当前设备的deviceid已经被输出来了, 并且打开设备的日志也被打印输出。

    第五,完整的jsp页面代码 请前往www.vxzsk.com 微信蓝牙设备开发频道查看




    展开全文
  • 写于:2016-4-15几个基本要用的东西: 1、微信公众平台 ...可以在此申请微信公众号,获取微信测试号。...到时候会引入一个JS文件,是用来调用微信提供的那些接口的3、微信硬件平台说明文档 网址:微

    几个基本要用的东西:
    1、微信公众平台
    网址:https://mp.weixin.qq.com
    申请微信公众号,获取微信测试号。

    2、微信JS-SDK说明文档
    网址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html

    3、微信硬件平台说明文档
    网址(新版):http://iot.weixin.qq.com/wiki/new/index.html
    网址(旧版):http://iot.weixin.qq.com/wiki/index.html

    – 开始开发 –

    1、首先到微信公众平台申请微信公众号,就选个人订阅号。
    2、登录你的公众号,进入公众平台管理页,左边最下面有个“开发者工具”。
    3、点“开发者工具”,进去后找到“公众平台测试帐号”,自己按照步骤申请开通一个。
    4、进入测试号管理页面,就会得到:

    原始ID:gh_xxxxxxxxxx (右上角显示的,这个是微信原始ID,不是微信号)
    (坑:微信原始ID 和 微信帐号不是同一个,微信帐号在之后都不会用到,用到的是原始ID)
    appID:wxxxxxxxxxxxx (appID)
    appsecret:xxxxxxxxxxxxxx (密钥)

    5、测试号管理页面,下面找到“JS接口安全域名”,要配置成你们自己的服务器域名,后面有些微信API会返回数据,它会去匹配这个域名,如果不是指定的域名,会报错。
    6、继续往下看,下面有个“体验接口权限表”,在里面找到“设备功能”,开通它
    7、开通设备功能后,点右边的“设置”,进入设备功能页面
    8、自己”添加产品”,随便搞,连接类型勾选”蓝牙”即可(添加完成后,该产品有个产品编号,后面设备授权时有用)

    ======= 以上是公众平台的配置,下面开始写前端代码 ======

    1、新建HTML,基本结构写好。
    2、引入”http://res.wx.qq.com/open/js/jweixin-1.0.0.js“,这个JS
    3、写JS代码:

    wx.config({
        beta:true,                  //坑:这个很重要,必须配置这个为true,才能调用微信的硬件API
        debug: false,               //是否开启调试模式,会自动弹一些消息框显示微信返回的数据
        appId: 这里填写appID,        //让后台返回appid
        timestamp: 时间戳,          //让后台返回生成证书时用的时间戳
        nonceStr: 随机字符串,        //让后台返回生成证书时用的随机串
        signature: 证书,            //让后台返回以当前URL地址生成的证书
        jsApiList: [                //需要调用的接口,都得在这里面写一遍
            "openWXDeviceLib",//初始化设备库(只支持蓝牙设备)
            "closeWXDeviceLib",//关闭设备库(只支持蓝牙设备)
            "getWXDeviceInfos",//获取设备信息(获取当前用户已绑定的蓝牙设备列表)
            "sendDataToWXDevice",//发送数据给设备
            "startScanWXDevice",//扫描设备(获取周围所有的设备列表,无论绑定还是未被绑定的设备都会扫描到)
            "stopScanWXDevice",//停止扫描设备
            "connectWXDevice",//连接设备
            "disconnectWXDevice",//断开设备连接
            "getWXDeviceTicket",//获取操作凭证
    
            //下面是监听事件:
            "onWXDeviceBindStateChange",//微信客户端设备绑定状态被改变时触发此事件
            "onWXDeviceStateChange",//监听连接状态,可以监听连接中、连接上、连接断开
            "onReceiveDataFromWXDevice",//接收到来自设备的数据时触发
            "onScanWXDeviceResult",//扫描到某个设备时触发
            "onWXDeviceBluetoothStateChange",//手机蓝牙打开或关闭时触发
        ]
    });

    上面这个方法,在进入页面时应该首先被调用,这是初始化微信JS-SDK
    其中:
    beta 这个参数需设为true,才能调用那些微信还没有正式开放的新接口
    appID,timestamp,nonceStr,signature这几个由后台传递到前端。
    生成证书的方法JS-SDK文档中有,此处暂时省略

    4、继续写方法:

    wx.ready(function(){
        //初始化设备库 需填写参数 公众号的原始ID
        wx.invoke('openWXDeviceLib', {'brandUserName':'gh_xxxxxxxxxx'}, function(res){
            //自己把res输出来看一下吧,里面包括了是否初始化成功,当前手机的蓝牙状态等信息
            //这里有个坑,当时研究了好久,跟论坛里的人讨论了半天,就是IOS下正常,
            //安卓下,请带上这个参数:brandUserName:后面是你公众号的原始ID。不然会初始化失败
            //正式的公众号,也有原始ID,是gh_开头的那个,进入公众号,自己找一下吧,有的
            //测试号,就用测试号管理页面右上角的那个gh_开头的那一串数字
        });
    
        //手机蓝牙状态改变时触发 (这是监听事件的调用方法,注意,监听事件都没有参数)
        wx.on('onWXDeviceBluetoothStateChange',function(res){
                //把res输出来看吧
        });
    
        //设备绑定状态改变事件(解绑成功,绑定成功的瞬间,会触发)
        wx.on('onWXDeviceBindStateChange',function(res){
                //把res输出来看吧
        });
    
        //设备连接状态改变
        wx.on('onWXDeviceStateChange',function(res){
            //有3个状态:connecting连接中,connected已连接,unconnected未连接
            //每当手机和设备之间的状态改变的瞬间,会触发一次
        });
    
        //接收到设备传来的数据
        wx.on('onReceiveDataFromWXDevice',function(res){
            //接收到的原始数据:JSON.stringify(res)
            //自己去百度下载一个jbase64.js,可以对字符串进行base64编码解码
            //这里就是用的jbase64.js对原始数据进行解码
            var unicode= BASE64.decoder(res.base64Data);
            var str = '';  
            for(var i = 0 , len =  unicode.length ; i < len ;++i){  
                     str += String.fromCharCode(unicode[i]);  
            }
            //解码后的数据:str
            //坑:你们测试的时候,不要在这里用alert(),页面会卡死。自己把信息输出到页面中查看吧
            //不要在这里alert出来
        });
    });
    

    5、继续写方法:

    wx.error(function(res){
        alert("wx.error错误:"+JSON.stringify(res));
        //如果初始化出错了会调用此方法,没什么特别要注意的
    });

    6、扫描设备:
    (我做的那个项目,是通过手机扫描附近的设备,得到设备的deviceid,然后进行绑定,不是用户扫描二维码进行绑定,所以这里介绍扫描设备的过程)

    //扫描前请先监听设备扫描事件
    wx.on('onScanWXDeviceResult',function(res){
        alert("扫描到1个设备");
        //自己解析一下res,里面会有deviceid,扫描设备的目的就是为了得到这个
        //然后就可以开始绑定了
    }
    
    //开始扫描
    wx.invoke("startScanWXDevice",{"btVersion":"ble"},function(res){});
    //这里填的参数是ble,也可以填bc,bc是经典蓝牙,我们做的这个设备不支持经典蓝牙,所以直接填ble
    //安卓系统不能同时支持ble和bc,这个后面详细说一下
    //执行此方法后,就开始一直不停的扫描,扫描到了设备会触发上面的监听事件
    
    //如果不想扫了,可以停止扫描
    //然而经测试,这个方法并没有什么卵用
    //你发现重新扫描根本什么都扫不出来,即使你现在刷新页面,也扫不出任何东西
    //解决方法:每次扫描前,先调用closeWXDeviceLib关闭设备库,再调用openWXDeviceLib打开设备库
    //这样就相当于重新初始化了一遍设备库,你现在再重新扫描,就可以扫描到设备了。
    wx.invoke("stopScanWXDevice",{},function(res){});

    7、绑定和解除绑定

    //用户绑定设备
    //1、先获取操作凭证(type为1表示绑定,2表示解除绑定)
    wx.invoke('getWXDeviceTicket',{"deviceId":"填写设备的deviceID","type":1},function(res){
        if(res.err_msg !="getWXDeviceTicket:ok"){
                alert("获取操作凭证失败,请重试");  
                return;
        }else{
            //2.将deviceID和操作凭证通过ajax传给后台 进行绑定   
            //后台应该是有当前用户的openId的,其实前端也可以获取到,但比较麻烦
            //我们这边的做法是,后台在数据库里保存了用户的openId,每次要用直接从数据库拿
            //就不用每次还去调微信的接口拿,太麻烦了
            //...此处ajax代码略      
        }
    });
    
    //用户解除绑定
    //与上面的方法基本相同,只有type参数不同
    wx.invoke('getWXDeviceTicket',{"deviceId":"填写设备的deviceID","type":2},function(res){
        if(res.err_msg !="getWXDeviceTicket:ok"){
                alert("获取操作凭证失败,请重试");  
                return;
        }else{
            //2.将deviceID和操作凭证通过ajax传给后台 进行绑定   
            ...代码略      
        }
    });

    8、向设备发送数据

    wx.invoke('sendDataToWXDevice', {'deviceId':dev,"base64Data":BASE64.encoder(str)}, function(res){
        if(res.err_msg =="sendDataToWXDevice:ok"){
                alert("数据已发送");
        }else{
                alert("数据发送失败");
        }
    });
    //发送的数据需要经过base64编码

    以上是前端页面中,基本就这些代码
    当用户绑定了设备后,微信会不停的尝试连接设备,所以其实不用程序员写代码去连接设备。

    下面来说一下遇到的各种坑:(上面内容中提到的就不说了)
    1、开发流程:
    ①、硬件厂商,他们只要得到了设备的mac地址,就可以开始授权了(好像只要有蓝牙板子,就有mac地址了)。
    ②、然后再开始生产设备
    ③、然后才卖给用户
    ④、用户关注公众号,扫描设备(如果用的二维码方式,那就是扫二维码。我们没有用二维码那种方式)
    ⑤、用户绑定设备
    ⑥、微信自动连接设备
    ⑦、连接上后,就可以收发数据了

    2、关于授权:
    我们用的授权新接口,即不需要厂商提供deviceid,由微信分配deviceid
    然后是授权时的那些参数:
    product_id:就是你之前“添加设备”后,就会得到那个编号
    connect_protocol:连接协议
    只能填3,或者只能填1.你别弄成:3|1,
    下面写了,安卓设备不能同时支持ble和经典蓝牙
    IOS一切正常,但是填成3|1,你就发现安卓的ble蓝牙调用“getWXDeviceInfos”(获取设备信息),获取不到!
    如果用户的手机是经典蓝牙,你就写一个html页面,搞个按钮叫“刷成经典蓝牙”,用户可以自己去更新设备属性(就是授权那个地方,不是可以更新设备属性吗,让你们后台工程师写个接口,用户可以自己去把connect_protocol刷成1)

    3、IOS连接设备很快很稳定,安卓连不上设备,显示“已连接0个设备”:
    在微信硬件平台的文档里面的某个地方,有一句话,说安卓设备要先订阅个什么东西,订阅上了,这个时候再连接就OK,因为设备只发了一次Auth和Init包,如果错过这个时机,就错过了…就再也连不上了,除非设备断电重启。
    但IOS估计是订阅那个什么东西非常快,不会过期,所以一下就连上了。
    (2016-9-23更新:听IOS工程师说:IOS连接蓝牙只需要3步,非常快非常稳定。安卓需要5步,其中2步容易失败,就是错过了某个时机就连不上了。貌似微信官方也没有好的解决办法。我们是让硬件开发人员写了个重新连接的机制。但是也不是很好用)

    那句话具体在什么地方,我真的找不到了,微信太坑了。
    目前的解决办法:蓝牙板子是有相关接口的,蓝牙板子可以得到当前手机的连接状态。所以如果当前微信显示的是“正在连接中…”,这个时候,让硬件开发人员再发送Auth和Init包。

    4、关于设备向手机发数据:
    设备发的数据,里面有两个值,一个代表包括包头包尾的总长度,一个代表除去包头包尾的长度,必须与所发数据的实际情况相对应,HTML页面中才能接收到。否则不报错,但也接收不到。

    5、继续补充中

    展开全文
  • 微信硬件蓝牙教程全

    2017-06-14 13:54:19
    微信硬件蓝牙教程: 微信公众号蓝牙开发准备工作(第一课)   java,H5微信蓝牙设备开发教程申请设备和添加设备(第二课)   ...微信蓝牙设备开发教程之...微信蓝牙设备开发微信硬件jsapi接口发送和接收设备数据(第...
    展开全文
  • 微信硬件蓝牙教程: 微信公众号蓝牙开发准备工作(第一课) java,H5微信蓝牙设备开发教程申请设备和添加设备(第二课) 微信蓝牙设备开发教程之...微信蓝牙设备开发微信硬件jsapi接口发送和接收设备数据(第四课续2) 微
    展开全文
  • 微信硬件蓝牙H5开发

    几个基本要用的东西:
    1、微信公众平台
    网址:https://mp.weixin.qq.com
    可以在此申请微信公众号,获取微信测试号。
    微信测试号拥有所有功能权限,如果你有正式的企业服务号,就不必用测试号了。

    2、微信JS-SDK说明文档
    网址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
    到时候会引入一个JS文件,是用来调用微信提供的那些接口的

    3、微信硬件平台说明文档
    网址(新版):http://iot.weixin.qq.com/wiki/new/index.html
    网址(旧版):http://iot.weixin.qq.com/wiki/index.html
    新版和旧版唯一的区别是,新版没有JS硬件API的说明页(但可以在下载中心自己下载)
    开始开发

    1、首先,自己到微信公众平台申请一个微信公众号,就选个人订阅号。
    2、登录你的公众号,进入公众平台管理页,左边最下面有个“开发者工具”。
    3、点“开发者工具”,进去后找到“公众平台测试帐号”,自己按照步骤申请开通一个。
    4、进入测试号管理页面,就会得到:
    原始ID:gh_xxxxxxxxxx (右上角显示的,这个是微信原始ID,不是微信号)
    (坑:微信原始ID 和 微信帐号不是同一个,微信帐号在之后都不会用到,用到的是原始ID)
    appID:wxxxxxxxxxxxx (appID)
    appsecret:xxxxxxxxxxxxxx (密钥)
    5、测试号管理页面,下面找到“JS接口安全域名”,要配置成你们自己的服务器域名,后面有些微信API会返回数据,它会去匹配这个域名,如果不是指定的域名,会报错。
    6、继续往下看,下面有个“体验接口权限表”,在里面找到“设备功能”,开通它
    7、开通设备功能后,点右边的“设置”,进入设备功能页面
    8、自己”添加产品”,随便搞,连接类型勾选”蓝牙”即可(添加完成后,该产品有个产品编号,后面设备授权时有用)

    ======= 以上是公众平台的配置,下面开始写前端代码 ======
    1、新建HTML,基本结构写好。
    2、引入”http://res.wx.qq.com/open/js/jweixin-1.0.0.js“,这个JS

    3、写方法:

    <code class="hljs d">wx.config({
        beta:true,                  //坑:这个很重要,必须配置这个为true,才能调用微信的硬件API
        debug: false,               //是否开启调试模式,会自动弹一些消息框显示微信返回的数据
        appId: 这里填写appID,        //让后台返回appid
        timestamp: 时间戳,          //让后台返回生成证书时用的时间戳
        nonceStr: 随机字符串,        //让后台返回生成证书时用的随机串
        signature: 证书,            //让后台返回已当前URL地址生成的证书
        jsApiList: [                //需要调用的接口,都得在这里面写一遍
            "openWXDeviceLib",//初始化设备库(只支持蓝牙设备)
            "closeWXDeviceLib",//关闭设备库(只支持蓝牙设备)
            "getWXDeviceInfos",//获取设备信息(获取当前用户已绑定的蓝牙设备列表)
            "sendDataToWXDevice",//发送数据给设备
            "startScanWXDevice",//扫描设备(获取周围所有的设备列表,无论绑定还是未被绑定的设备都会扫描到)
            "stopScanWXDevice",//停止扫描设备
            "connectWXDevice",//连接设备
            "disconnectWXDevice",//断开设备连接
            "getWXDeviceTicket",//获取操作凭证
     
            //下面是监听事件:
            "onWXDeviceBindStateChange",//微信客户端设备绑定状态被改变时触发此事件
            "onWXDeviceStateChange",//监听连接状态,可以监听连接中、连接上、连接断开
            "onReceiveDataFromWXDevice",//接收到来自设备的数据时触发
            "onScanWXDeviceResult",//扫描到某个设备时触发
            "onWXDeviceBluetoothStateChange",//手机蓝牙打开或关闭时触发
        ]
    });</code>
    上面这个方法,在进入页面时应该首先被调用,这是初始化微信JS-SDK
    其中:
    beta 这个参数需设为true,才能调用那些微信还没有正式开放的新接口
    appID,timestamp,nonceStr,signature这几个由后台传递到前端。
    生成证书的方法JS-SDK文档中有,此处暂时省略

    4:继续写方法

    <code class="hljs javascript">wx.ready(function(){
        //初始化设备库 需填写参数 公众号的原始ID
        wx.invoke('openWXDeviceLib', {'brandUserName':'gh_xxxxxxxxxx'}, function(res){
            //自己把res输出来看一下吧,里面包括了是否初始化成功,当前手机的蓝牙状态等信息
            //这里有个坑,当时研究了好久,跟论坛里的人讨论了半天,就是IOS下正常,
            //安卓下,请带上这个参数:brandUserName:后面是你公众号的原始ID。不然会初始化失败
            //正式的公众号,也有原始ID,是gh_开头的那个,进入公众号,自己找一下吧,有的
            //测试号,就用测试号管理页面右上角的那个gh_开头的那一串数字
        });
     
            //手机蓝牙状态改变时触发 (这是监听事件的调用方法,注意,监听事件都没有参数)
            wx.on('onWXDeviceBluetoothStateChange',function(res){
                    //把res输出来看吧
            });
     
            //设备绑定状态改变事件(解绑成功,绑定成功的瞬间,会触发)
            wx.on('onWXDeviceBindStateChange',function(res){
                    //把res输出来看吧
            });
     
            //设备连接状态改变
            wx.on('onWXDeviceStateChange',function(res){
                //有3个状态:connecting连接中,connected已连接,unconnected未连接
                //每当手机和设备之间的状态改变的瞬间,会触发一次
            });
     
            //接收到设备传来的数据
            wx.on('onReceiveDataFromWXDevice',function(res){
                    //接收到的原始数据:JSON.stringify(res)
                    //自己去百度下载一个jbase64.js,可以对字符串进行base64编码解码
                    //这里就是用的jbase64.js对原始数据进行解码
                    var unicode= BASE64.decoder(res.base64Data);
                    var str = '';  
                    for(var i = 0 , len =  unicode.length ; i < len ;++i){  
                             str += String.fromCharCode(unicode[i]);  
                    }
                    //解码后的数据:str
                    //坑:你们测试的时候,不要在这里用alert(),页面会卡死。自己把信息输出到页面中查看吧
                    //不要在这里alert出来
                });
            });</code>


    5、继续写方法:

    <code class="hljs javascript">wx.error(function(res){
        alert("wx.error错误:"+JSON.stringify(res));
        //如果初始化出错了会调用此方法,没什么特别要注意的
    });</code>
    6、扫描设备:
    (我做的那个项目,是通过手机扫描附近的设备,得到设备的deviceid,然后进行绑定,不是用户扫描二维码进行绑定,所以这里介绍扫描设备的过程)

    <code class="hljs javascript">//扫描前请先监听设备扫描事件
    wx.on('onScanWXDeviceResult',function(res){
        alert("扫描到1个设备");
        //自己解析一下res,里面会有deviceid,扫描设备的目的就是为了得到这个
        //然后就可以开始绑定了
    }
     
    //开始扫描
    wx.invoke("startScanWXDevice",{"btVersion":"ble"},function(res){});
    //这里填的参数是ble,也可以填bc,bc是经典蓝牙,我们做的这个设备不支持经典蓝牙,所以直接填ble
    //安卓系统不能同时支持bel和bc,这个后面详细说一下
    //执行此方法后,就开始一直不停的扫描,扫描到了设备会触发上面的监听事件
     
    //如果不想扫了,可以停止扫描
    wx.invoke("stopScanWXDevice",{},function(res){});</code>
    

    7、绑定和解除绑定

    <code class="hljs r">//用户绑定设备
    //1、先获取操作凭证(type为1表示绑定,2表示解除绑定)
    wx.invoke('getWXDeviceTicket',{"deviceId":"填写设备的deviceID","type":1},function(res){
        if(res.err_msg !="getWXDeviceTicket:ok"){
                alert("获取操作凭证失败,请重试");  
                return;
        }else{
            //2.将deviceID和操作凭证通过ajax传给后台 进行绑定   
            //后台应该是有当前用户的openId的,其实前端也可以获取到,但比较麻烦
            //我们这边的做法是,后台在数据库里保存了用户的openId,每次要用直接从数据库拿
            //就不用每次还去调微信的接口拿,太麻烦了
            //...此处ajax代码略      
        }
    });
     
    //用户解除绑定
    //与上面的方法基本相同,只有type参数不同
    wx.invoke('getWXDeviceTicket',{"deviceId":"填写设备的deviceID","type":2},function(res){
        if(res.err_msg !="getWXDeviceTicket:ok"){
                alert("获取操作凭证失败,请重试");  
                return;
        }else{
            //2.将deviceID和操作凭证通过ajax传给后台 进行绑定   
            ...代码略      
        }
    });</code>

    8、向设备发送数据

    <code class="hljs javascript">wx.invoke('sendDataToWXDevice', {'deviceId':dev,"base64Data":BASE64.encoder(str)}, function(res){
        if(res.err_msg !="sendDataToWXDevice:ok"){
                alert("数据已发送");
        }else{
                alert("数据发送失败");
        }
    });
    //发送的数据需要经过base64编码</code>

    以上是前端页面中,基本就这些代码
    当用户绑定了设备后,微信会不停的尝试连接设备,所以其实不用程序员写代码去连接设备。

    下面来说一下遇到的各种坑:(上面内容中提到的就不说了)
    1、开发流程:
    ①、硬件厂商,他们只要得到了设备的mac地址,就可以开始授权了(好像只要有蓝牙板子,就有mac地址了)。
    ②、然后再开始生产设备
    ③、然后才卖给用户
    ④、用户关注公众号,扫描设备(如果用的二维码方式,那就是扫二维码。我们没有用二维码那种方式)
    ⑤、用户绑定设备
    ⑥、微信自动连接设备
    ⑦、连接上后,就可以收发数据了

    2、关于授权:
    我们用的授权新接口,即不需要厂商提供deviceid,由微信分配deviceid
    然后是授权时的那些参数:
    product_id:就是你之前“添加设备”后,就会得到那个编号
    connect_protocol:连接协议
    只能填3,或者只能填1.你别弄成:3|1,
    下面写了,安卓设备不能同时支持ble和经典蓝牙
    IOS一切正常,但是填成3|1,你就发现安卓的ble蓝牙调用“getWXDeviceInfos”(获取设备信息),获取不到!
    如果用户的手机是经典蓝牙,你就写一个html页面,搞个按钮叫“刷成经典蓝牙”,用户可以自己去更新设备属性(就是授权那个地方,不是可以更新设备属性吗,让你们后台工程师写个接口,用户可以自己去把connect_protocol刷成1)

    3、IOS连接设备很快很稳定,安卓连不上设备,显示“已连接0个设备”:
    在微信硬件平台的文档里面的某个地方,有一句话,说安卓设备要先订阅个什么东西,订阅上了,这个时候再连接就OK,因为设备只发了一次Auth和Init包,如果错过这个时机,就错过了…就再也连不上了,除非设备断电重启。
    但IOS估计是订阅那个什么东西非常快,不会过期,所以一下就连上了。

    那句话具体在什么地方,我真的找不到了,微信太坑了。
    而且目前我们也没有特别好的解决方法,如果之后有好的解决方法,我再来更新。

    4、关于设备向手机发数据:
    设备发的数据,里面有两个值,一个代表包括包头包尾的总长度,一个代表除去包头包尾的长度,必须与所发数据的实际情况相对应,HTML页面中才能接收到。否则不报错,但也接收不到。

    5、继续补充中



    展开全文
  • 微信公众平台接口调试工具——蓝牙设备调试篇第一步:获取token需要两个参数:appid和appsecret下面将如何获取上面两参数首先进入公众号,点击开发者工具,点击公众平台测试账号,如下图可以看到将上面得到的appid和...
  • 1、蓝牙设备接入微信的基本条件 网上相对于这一块的资料不是特别多,而且有些博主整理的非常好的开发流程也会忽略很多东西,对于一个因为临时需求需要研究硬件设备的人来说太多没说明的坑。 在这里推荐一个链接: ...
  • 微信公众平台蓝牙硬件设备案例
  • 第一章:微信硬件蓝牙接入流程详解第二章:获取微信硬件蓝牙设备二维码和设备id(deviceId)第三章:微信硬件蓝牙设备授权微信硬件jsapi 作者本人以前写过一个系列教程里面已经说的很详细,但是由于作者本人语言组织...
  • 快速入门微信硬件jsapi+微信硬件接入流程+jsapi_ticket的获取+tartScanWXDevice[扫描蓝牙设备]接口实现
  • 微信硬件蓝牙jsapi开发之onWXDeviceStateChange接口实现(12)--监听蓝牙状态变化接口
  • 微信公众号蓝牙开发准备工作(第一课) java,H5微信蓝牙设备开发教程申请设备和添加设备(第二课) ...微信蓝牙设备开发微信硬件jsapi接口发送和接收设备数据(第四课续2) 微信蓝牙设备开发教程之初始化...
  • 微信蓝牙设备开发之初步接入微信硬件jsapi
  • 微信硬件jsapi使用教程说明蓝牙
  • 几个基本要用的东西: 1、微信公众平台 网址:https://mp.weixin.qq.com 申请微信公众号,获取微信測试号。 2、微信JS-SDK说明文档 网址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148...
  • 这篇文章详细描述了微信蓝牙开发连接阶段的具体步骤。 不涉及蓝牙通信内容。 一. 第一阶段(微信后台基本设置) 登录微信公众平台(https://mp.weixin.qq.com/)。 选择:开发者工具->公众平台测试账号,...
  • 微信小程序蓝牙BLE开发(一) 迟来的更新。上半年4月份以来项目中断续在对接好几个产品关于蓝牙BLE设备,通过蓝牙与设备之间通信进行使用产品。开发中也遇到不少问题哈,后面抽时间续篇。写得不好,请各位大神多多...
1 2 3 4 5 ... 20
收藏数 2,839
精华内容 1,135
关键字:

微信开发 蓝牙接口