c-pp

导航

uni-app 小程序蓝牙配网

前言:

本文介绍了uniapp 的蓝牙调用,如搜索蓝牙,连接蓝牙设备

 

蓝牙接口API

一、搜索蓝牙页面代码

HTML

 <view class="container">
  <scroll-view scroll-y :style="'width:690rpx;height:' + list_height + 'rpx'">
    <block v-for="(item, index) in devicesList" :key="index">
      <view class="list-item" :id="item.deviceId" @tap="Connect">
        <view style="display:flex;flex-direction:column;width:80%">
          <text style="font-size:medium;word-break:break-all">设备名称: {{item.name}}</text>
          <text style="font-size:x-small;color:gray;word-break:break-all">设备ID: {{item.deviceId}}</text>
          <text style="font-size:x-small;color:gray;word-break:break-all">信号强度RSSI: {{item.RSSI}}</text>
        </view>
        <image style="width:36px;height:36px" mode="aspectFit" src="/static/images/bluetooth.png"></image>
      </view>
    </block>
  </scroll-view>
  <button type="primary" class="button" :loading="searching" @tap="Search">{{searching?"搜索中...":"搜索蓝牙设备"}}</button>
</view>

CSS

page {
  background-color: #f8f8f8;
}
.container {
  padding: 0 30rpx 0 30rpx;
  align-items: center;
}
.list-item {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  padding: 10px 0 10px 0;
  box-sizing: border-box;
  border: 1px solid #000;
  border-style: none none solid none;
  border-bottom-color: lightgray;
}
.list-item:last-child {
  border-style: none;
}
.button {
  position: fixed;
  width: 690rpx;
  bottom: 30rpx;
}

JS

const app = getApp();
export default {
  data() {
    return {
      searching: false,
      devicesList: [],
      list_height: ""
    };
  },

  components: {},
  props: {},
  onLoad: function (options) {
    var that = this;
    var list_height = (app.globalData.SystemInfo.windowHeight - 50) * (750 / app.globalData.SystemInfo.windowWidth) - 60;
    that.setData({
      list_height: list_height
    });
    uni.onBluetoothAdapterStateChange(function (res) {
      that.setData({
        searching: res.discovering
      });

      if (!res.available) {
        that.setData({
          searching: false
        });
      }
    });
    uni.onBluetoothDeviceFound(function (devices) {
      //剔除重复设备,兼容不同设备API的不同返回值
      var isnotexist = true;
      if (devices.deviceId) {
        if (devices.advertisData) {
          devices.advertisData = app.globalData.buf2hex(devices.advertisData);
        } else {
          devices.advertisData = '';
        }

        console.log(devices);

        for (var i = 0; i < that.devicesList.length; i++) {
          if (devices.deviceId == that.devicesList[i].deviceId) {
            isnotexist = false;
          }
        }

        if (isnotexist) {
          that.devicesList.push(devices);
        }
      } else if (devices.devices) {
        if (devices.devices[0].advertisData) {
          devices.devices[0].advertisData = app.globalData.buf2hex(devices.devices[0].advertisData);
        } else {
          devices.devices[0].advertisData = '';
        }

        console.log(devices.devices[0]);

        for (var i = 0; i < that.devicesList.length; i++) {
          if (devices.devices[0].deviceId == that.devicesList[i].deviceId) {
            isnotexist = false;
          }
        }

        if (isnotexist) {
          that.devicesList.push(devices.devices[0]);
        }
      } else if (devices[0]) {
        if (devices[0].advertisData) {
          devices[0].advertisData = app.globalData.buf2hex(devices[0].advertisData);
        } else {
          devices[0].advertisData = '';
        }

        console.log(devices[0]);

        for (var i = 0; i < devices_list.length; i++) {
          if (devices[0].deviceId == that.devicesList[i].deviceId) {
            isnotexist = false;
          }
        }

        if (isnotexist) {
          that.devicesList.push(devices[0]);
        }
      }

      that.setData({
        devicesList: that.devicesList
      });
    });
  },
  onReady: function () {},
  onShow: function () {},
  onHide: function () {
    var that = this;
    that.setData({
      devicesList: []
    });

    if (this.searching) {
      uni.stopBluetoothDevicesDiscovery({
        success: function (res) {
          console.log(res);
          that.setData({
            searching: false
          });
        }
      });
    }
  },
  methods: {
    Search: function () {
      var that = this;
      if (!that.searching) {
        uni.closeBluetoothAdapter({
          complete: function (res) {
            console.log(res);
            uni.openBluetoothAdapter({
              success: function (res) {
                console.log(res);
                uni.getBluetoothAdapterState({
                  success: function (res) {
                    console.log(res);
                  }
                });
                uni.startBluetoothDevicesDiscovery({
                  allowDuplicatesKey: false,
                  success: function (res) {
                    console.log(res);
                    that.setData({
                      searching: true,
                      devicesList: []
                    });
                  }
                });
              },
              fail: function (res) {
                console.log(res);
                uni.showModal({
                  title: '提示',
                  content: '请检查手机蓝牙是否打开',
                  showCancel: false,
                  success: function (res) {
                    that.setData({
                      searching: false
                    });
                  }
                });
              }
            });
          }
        });
      } else {
        uni.stopBluetoothDevicesDiscovery({
          success: function (res) {
            console.log(res);
            that.setData({
              searching: false
            });
          }
        });
      }
    },
    Connect: function (e) {
      var that = this;
      var advertisData, name;
      console.log(e.currentTarget.id);

      for (var i = 0; i < that.devicesList.length; i++) {
        if (e.currentTarget.id == that.devicesList[i].deviceId) {
          name = that.devicesList[i].name;
          advertisData = that.devicesList[i].advertisData;
        }
      }

      uni.stopBluetoothDevicesDiscovery({
        success: function (res) {
          console.log(res);
          that.setData({
            searching: false
          });
        }
      });
      uni.showLoading({
        title: '连接蓝牙设备中...'
      });
      uni.createBLEConnection({
        deviceId: e.currentTarget.id,
        success: function (res) {
          console.log(res);
          uni.hideLoading();
          uni.showToast({
            title: '连接成功',
            icon: 'success',
            duration: 1000
          });
          uni.navigateTo({
            url: '../device/device?connectedDeviceId=' + e.currentTarget.id + '&name=' + name
          });
        },
        fail: function (res) {
          console.log(res);
          uni.hideLoading();
          uni.showModal({
            title: '提示',
            content: '连接失败',
            showCancel: false
          });
        }
      });
    }
  }
};

效果图

 

二、接收和发送指令给蓝牙设备

HTML

    <view class="container">
        <text style="font-size:medium;word-break:break-all">设备名称:{{name}}</text>
        <text style="font-size:x-small;color:gray;word-break:break-all">设备ID:{{connectedDeviceId}}</text>
        <text style="font-size:x-small;color:gray">状态:{{connected?"已连接":"已断开"}}</text>

        <text style="font-size:medium;margin-top:10px">接收内容:</text>
        <textarea class="res" maxlength="-1" disabled :value="receiveText"></textarea>
        <text> \n </text>

        <text style="font-size:medium;margin-top:10px">发送内容:</text>
        <input class="input" :value="inputText" @input="bindInput" maxlength="20">
        <button type="primary" class="button" @tap="Send">发送</button>
    </view>

CSS

    page {
        background-color: #f8f8f8;
    }

    .container {
        padding: 30rpx;
        align-items: left;
    }

    .input {
        margin-top: 3px;
        width: 100%;
        border: 1px solid lightgray;
        border-radius: 6px;
    }

    .res {
        margin-top: 3px;
        width: 100%;
        border: 3px solid lightgray;
        border-radius: 6px;
    }

    .button {
        position: fixed;
        width: 690rpx;
        bottom: 30rpx;
    }

JS

    const app = getApp();

    export default {
        data() {
            return {
                inputText: 'mootek',
                receiveText: '',
                name: '',
                connectedDeviceId: '',
                services: {},
                characteristics: {},
                connected: true,
                searching: false,
                serviceId: "",
                characteristicId: ""
            };
        },

        components: {},
        props: {},
        onLoad: function(options) {
            console.log(options)
            var that = this;
            that.setData({
                name: options.name,
                connectedDeviceId: options.connectedDeviceId
            });
            uni.getBLEDeviceServices({
                deviceId: that.connectedDeviceId,
                success: function(res) {
                    console.log(res.services);
                    that.setData({
                        services: res.services,
                        serviceId: res.services[0].uuid
                    });
                    uni.getBLEDeviceCharacteristics({
                        deviceId: options.connectedDeviceId,
                        serviceId: that.serviceId,
                        success: function(res) {
                            console.log(res.characteristics);
                            that.setData({
                                characteristics: res.characteristics,
                                characteristicId: res.characteristics[1].uuid
                            });
                            uni.notifyBLECharacteristicValueChange({
                                state: true,
                                deviceId: options.connectedDeviceId,
                                serviceId: that.serviceId,
                                characteristicId: that.characteristicId,
                                success: function(res) {
                                    console.log('启用notify成功:' + that
                                        .characteristicId);
                                    console.log(JSON.stringify(res));
                                    that.onBLECharacteristicValueChange();
                                },
                                fail: function() {
                                    console.log('开启notify失败' + that
                                        .characteristicId);
                                }
                            });
                        }
                    });
                }
            });
            uni.onBLEConnectionStateChange(function(res) {
                console.log(res.connected);
                that.setData({
                    connected: res.connected
                });
            });
        },
        onReady: function() {},
        onShow: function() {},
        onHide: function() {},
        methods: {
            bindInput: function(e) {
                this.setData({
                    inputText: e.detail.value
                });
                console.log(e.detail.value);
            },
            Send: function() {
                var that = this;

                if (that.connected) {
                    var buffer = new ArrayBuffer(that.inputText.length);
                    var dataView = new Uint8Array(buffer);
                    console.log(buffer, dataView)
                    for (var i = 0; i < that.inputText.length; i++) {
                        dataView[i] = that.inputText.charCodeAt(i);
                    }

                    uni.writeBLECharacteristicValue({
                        deviceId: that.connectedDeviceId,
                        serviceId: that.serviceId,
                        characteristicId: that.characteristicId,
                        value: buffer,
                        success: function(res) {
                            console.log('发送指令成功:' + res.errMsg);
                            uni.showModal({
                                title: '数据发送成功',
                                content: ''
                            });
                        },
                        fail: function(res) {
                            // fail
                            //console.log(that.data.services)
                            console.log('message发送失败:' + res.errMsg);
                            uni.showToast({
                                title: '数据发送失败,请稍后重试',
                                icon: 'none'
                            });
                        }
                    });
                } else {
                    uni.showModal({
                        title: '提示',
                        content: '蓝牙已断开',
                        showCancel: false,
                        success: function(res) {
                            that.setData({
                                searching: false
                            });
                        }
                    });
                }
            },
            onBLECharacteristicValueChange: function() {
                console.log('onBLECharacteristicValueChange');
                var that = this;
                console.log(uni.onBLECharacteristicValueChange);
                uni.onBLECharacteristicValueChange(function(res) {
                    console.log('1');
                    console.log('监听低功耗蓝牙设备的特征值变化事件成功', res.value);
                    console.log(app.globalData.buf2string(res.value));
                    if (that.inputText == 'rcd[1]') {
                        var data = app.globalData.Str2Bytes(res.value);
                        console.log(app.globalData.Str2Bytes(res.value))
                        var receiveText = app.globalData.buf2string(data);
                    }else{
                        var receiveText = app.globalData.buf2string(res.value);
                    }
                    that.setData({
                        receiveText: receiveText
                    });
                });
            }
        }
    };

APP.vue 代码

CSS

/**app.wxss**/
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 200rpx 0;
  box-sizing: border-box;
} 

JS

  globalData: {
    buf2hex: function (buffer) {
      return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
    },
    buf2string: function (buffer) {
      var arr = Array.prototype.map.call(new Uint8Array(buffer), x => x);
      var str = '';
        console.log(buffer)
      for (var i = 0; i < arr.length; i++) {
        str += String.fromCharCode(arr[i]);
      }

      return str;
    },
    Str2Bytes(str) {
                    var pos = 0;
                    var len = str.length;
                    if(len %2 != 0) {
                        return null;
                    }
                    len /= 2;
                    var hexA = new Array();
                    for(var i=0; i<len; i++) {
                        var s = str.substr(pos, 2);
                        var v = parseInt(s, 16);
                        hexA.push(v);
                        pos += 2;
                    }
                    return hexA;
                },
                
    SystemInfo: {}
  },
  onLaunch: function () {
    this.globalData.SystemInfo = uni.getSystemInfoSync(); //console.log(this.globalData.SystemInfo)
  },
  methods: {}
};

 

posted on 2024-11-29 16:51  五毛钱咩  阅读(902)  评论(0)    收藏  举报