| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- <template>
- <view class="wrap">
- <button type="primary" :disabled="scanning" @tap="scan">{{scanning?'扫描中':'1. 扫描'}}</button>
- <radio-group v-if="list.length" @change="e=>deviceId=e.detail.value">
- <label v-for="d in list" :key="d.deviceId">
- <radio :value="d.deviceId" />{{d.name||d.localName||'未知设备'}}
- </label>
- </radio-group>
- <button type="warn" :disabled="!deviceId||connecting" @tap="connect">2. 连接</button>
- <view class="log">
- <text v-for="(l,i) in logs" :key="i">{{l}}</text>
- </view>
- </view>
- </template>
- <script>
- // Promise 化
- const $p = (api, opts = {}) => new Promise((res, rej) => {
- opts.success = res;
- opts.fail = rej;
- uni[api](opts)
- })
- export default {
- data() {
- return {
- scanning: false,
- list: [], // 扫描列表
- deviceId: '', // 选中设备
- connecting: false,
- logs: []
- }
- },
- onUnload() {
- this.close()
- },
- methods: {
- log(msg) {
- this.logs.unshift(`${new Date().toLocaleTimeString()} ${msg}`)
- },
- /* 1. 扫描 */
- async scan() {
- this.log('打开蓝牙...')
- try {
- await $p('openBluetoothAdapter')
- await $p('startBluetoothDevicesDiscovery', {
- allowDuplicatesKey: false
- })
- this.scanning = true
- this.log('扫描中...')
- uni.onBluetoothDeviceFound(res => this.list = [...this.list, ...res.devices])
- setTimeout(() => this.stopScan(), 8000)
- } catch (e) {
- this.log('扫描失败:' + e.errMsg)
- }
- },
- async stopScan() {
- this.scanning = false
- await $p('stopBluetoothDevicesDiscovery')
- this.log('扫描已停止')
- },
- /* 2. 连接并发现服务/特征 */
- async connect() {
- if (!this.deviceId) return
- this.connecting = true
- this.log('正在连接...')
- try {
- await $p('createBLEConnection', {
- deviceId: this.deviceId
- })
- // 部分机型必须延时
- await new Promise(r => setTimeout(r, 800))
- const {
- services
- } = await $p('getBLEDeviceServices', {
- deviceId: this.deviceId
- })
- if (!services.length) throw new Error('无服务')
- const service = services[0]
- const {
- characteristics
- } = await $p('getBLEDeviceCharacteristics', {
- deviceId: this.deviceId,
- serviceId: service.uuid
- })
- const char = characteristics.find(c => c.properties.notify || c.properties.indicate)
- if (char) {
- await $p('notifyBLECharacteristicValueChange', {
- deviceId: this.deviceId,
- serviceId: service.uuid,
- characteristicId: char.uuid,
- state: true
- })
- // 监听数据
- uni.onBLECharacteristicValueChange(res => {
- const hex = Array.prototype.map.call(new Uint8Array(res.value), b => ('0' + b
- .toString(16)).slice(-2)).join('')
- this.log(`收到 notify:${hex}`)
- })
- }
- this.log('连接成功,已启用 notify!')
- } catch (e) {
- this.log('连接失败:' + e.errMsg || e)
- }
- this.connecting = false
- },
- /* 3. 断开 & 释放 */
- async close() {
- if (this.deviceId) {
- await $p('closeBLEConnection', {
- deviceId: this.deviceId
- }).catch(() => {})
- }
- await $p('closeBluetoothAdapter').catch(() => {})
- }
- }
- }
- </script>
- <style scoped>
- .wrap {
- padding: 30rpx
- }
- .log {
- margin-top: 30rpx;
- font-size: 24rpx;
- color: #555;
- background: #f5f5f5;
- padding: 20rpx;
- max-height: 400rpx;
- overflow-y: auto;
- }
- </style>
|