1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
| <template> <view> <nav-bar navBgColor="#fff" left-text="打印机设置"></nav-bar> <view class="refresh" @click="searchPrint">选择蓝牙设备<image class="icon" src="https://taoliangche.oss-cn-beijing.aliyuncs.com/mini-my/6.30/resh.png"></image> </view> <view class="print-loading">搜索中...</view> <view class="me-list"> <view class="item" v-for="(v,i) in devices" :key="i" @click="setBindDevice(v)"> <view class="name">{{v.name}}</view> <view :class="['status',v.isBind&&'connect']">{{v.isBind?'已连接':'未连接'}} <image class="icon" src="https://taoliangche.oss-cn-beijing.aliyuncs.com/mini-my/6.30/gth.png"></image> </view> </view> </view> </view> </template>
<script setup> import { ref } from 'vue' import { onLoad, onHide, onUnload } from '@dcloudio/uni-app' const devices = ref([]) const bindDevice = ref({}) const platform = ref('')
onLoad(() => { getSystemInfo() searchPrint() }) onHide(() => { stopBluetoothDevicesDiscovery() }) onUnload(() => { stopBluetoothDevicesDiscovery() }) //得到系统信息 const getSystemInfo = () => { uni.getSystemInfo({ success(res) { platform.value = res.platform } }) } //查询蓝牙设备 const searchPrint = () => { uni.closeBluetoothAdapter({ complete: () => { //初始化蓝牙 uni.openBluetoothAdapter({ success: () => { startBluetoothDevicesDiscovery(); }, fail: (res) => { if (res.errCode === 10001) { console.log('蓝牙未开启'); } else { console.log('蓝牙初始化失败'); } } }) } }); } //开始搜寻附近的蓝牙设备 const startBluetoothDevicesDiscovery = () => { //停止蓝牙搜索 stopBluetoothDevicesDiscovery(); //开启蓝牙搜索 uni.startBluetoothDevicesDiscovery({ success: () => { //搜索,监听返回结果 onBluetoothDeviceFound() }, fail: (res) => { console.log(res, "搜索蓝牙失败"); } }); } //停止蓝牙搜索 const stopBluetoothDevicesDiscovery = () => { uni.stopBluetoothDevicesDiscovery({ success() { console.log('停止蓝牙搜索success') }, fail(res) { console.log('停止蓝牙搜索fail', res) } }) } //寻找到新设备的事件的回调函数 const onBluetoothDeviceFound = () => { uni.onBluetoothDeviceFound((res) => { console.log('寻找到新设备的事件的回调函数', res); res.devices.forEach(device => { if (!device.name && !device.localName) { return } // 蓝牙数组 const foundDevices = devices.value; const idx = findArrItem(foundDevices, device.deviceId); if (idx === -1) { foundDevices.push(device); } else { foundDevices[idx] = device; } const device1 = uni.getStorageSync("bindDevice"); if (device1) { foundDevices.map((v) => { if (v.name == device1.name) { v.isBind = true; } return v }) } devices.value = foundDevices }) }) } //重复搜索时,判断设备是否已经存在过滤掉 const findArrItem = (arr, id) => { let index = -1; for (let i in arr) { if (arr[i].deviceId == id) { index = i; } } return index; } //绑定设备 const setBindDevice = (item) => { uni.showLoading({ title: "连接中...", mask: true }) //创建连接,测试设备是否可以读,可写 createBLEConnection1(item); } //低功耗蓝牙设备连接 const createBLEConnection1 = (item, callback) => { uni.createBLEConnection({ deviceId: item.deviceId, timeout: 15000, success: (res) => { console.log('蓝牙连接成功'); bindDevice.value = item //如果蓝牙设备write没定义,说明是新设备需要执行 if (platform.value == 'android') { if (item.write == undefined) { //检查该蓝牙设备是否有写入权限,并保存参数,以便发送数据 setTimeout(() => { getBLEDeviceServices1(item.deviceId, callback); }, 3000) } else { callback ? callback() : '' } } else { getBLEDeviceServices1(item.deviceId, callback); } }, fail: (res) => { uni.hideLoading() console.log("蓝牙连接失败:", res); } }) } const getBLEDeviceServices1 = (deviceId, callback) => { uni.getBLEDeviceServices({ deviceId, success: (res) => { console.log('获取蓝牙设备所有服务', res.services) for (let i = 0; i < res.services.length; i++) { if (res.services[i].isPrimary) { getBLEDeviceCharacteristics1(deviceId, res.services[i].uuid, callback) // return } } }, fail: (res) => { uni.hideLoading() console.log("获取蓝牙服务失败:" + JSON.stringify(res)) } }) }
//获取蓝牙设备某个服务中所有特征值(characteristic) const getBLEDeviceCharacteristics1 = (deviceId, serviceId, callback) => { uni.getBLEDeviceCharacteristics({ deviceId, serviceId, success: (res) => { console.log('获取设备特征值', res.characteristics) for (let i = 0; i < res.characteristics.length; i++) { let item = res.characteristics[i]; let _uuid = item.uuid; let bindDevices = bindDevice.value; // 读取低功耗蓝牙设备的特征值的二进制数据值 注意:必须设备的特征值支持 read 才可以成功调用。 if (item.properties.read) { bindDevices.read = true; } //向低功耗蓝牙设备特征值中写入二进制数据。注意:必须设备的特征值支持 write 才可以成功调用。 if (item.properties.write && !item.properties.notify) { bindDevices.serviceId = serviceId; bindDevices.characteristicId = _uuid; bindDevices.write = true; callback ? callback() : '' } //启用低功耗蓝牙设备特征值变化时的 notify 功能,使用characteristicValueChange事件 if (item.properties.notify || item.properties.indicate) { uni.notifyBLECharacteristicValueChange({ deviceId, serviceId, characteristicId: _uuid, state: true, }) } //设置当前选中的蓝牙设备,包括是否可读写属性采集 bindDevice.value = bindDevices; let oldDevices = devices.value; devices.value = oldDevices.map((v) => { if (v.name == bindDevices.name) { v.isBind = true; } return v }) uni.setStorageSync("bindDevice", bindDevices); } if (uni.getStorageSync("bindDevice").characteristicId) { uni.showToast({ title: "连接成功", icon: "success", complete() { setTimeout(() => { uni.navigateBack() }, 1500) } }) } }, fail(res) { console.error('获取特征值失败:', res) }, complete() { uni.hideLoading() } }) } </script>
<style lang="scss"> .refresh { display: flex; align-items: center; justify-content: space-between; width: 100%; height: 113rpx; background: #FFFFFF; border-radius: 0 0 20rpx 20rpx; font-size: 30rpx; color: #262626; padding: 0 30rpx;
.icon { width: 28rpx; height: 28rpx; } }
.print-loading { width: 100%; text-align: center; font-size: 30rpx; color: #262626; padding: 30rpx 0 0; }
.me-list { width: 690rpx; background: #FFFFFF; border-radius: 20rpx 20rpx 20rpx 20rpx; margin: 30rpx auto; padding: 0 20rpx;
.item { display: flex; align-items: center; justify-content: space-between; width: 100%; height: 112rpx; border-bottom: 1px solid rgba(37, 37, 37, .03);
&:last-child { border-bottom: none; }
.name { width: 500rpx; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; font-size: 36rpx; color: #333333; }
.status { display: flex; align-items: center; font-size: 30rpx; color: #808080;
&.connect { color: #4D4D4D; }
.icon { width: 27rpx; height: 27rpx; margin-left: 20rpx; } } } } </style>
|