文章目录

前言

本文介绍了uni-app蓝牙的基本调用,如搜索蓝牙设备,链接蓝牙设备,给蓝牙设备发送值,接收蓝牙设备传值。

一、搜索蓝牙页面代码

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: {}
};

总结

如果需要接收蓝牙设备的传回来的值和发送过去的值,需要找到该设备的特定的特征值,才能完成接收和发送,发送的指令需要蓝牙设备厂家给你提供。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐