123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435 |
- <template>
- <view>
- <cu-custom
- ref="custom"
- id="custom"
- bgImage="https://yostest175549.obs.cn-east-2.myhuaweicloud.com:443/202306151686796745663B52544232.png"
- :isBack="true"
- >
- <block slot="backText">返回</block>
- <block slot="content"> 搜索蓝牙设备 </block>
- </cu-custom>
- <view class="head">
- <view class="title">蓝牙设备列表</view>
- <u-loading-icon v-if="beSearching" size="21" />
- <view v-else class="anew" @click="startBluetooth(services)">
- 继续搜索
- </view>
- </view>
- <My_listbox ref="List" :pullDown="false">
- <view class="device" v-for="item in devices" :key="item.deviceId">
- <view class="left">
- <text class="iconfont icon-shuifa" />
- </view>
- <view class="content">
- <view class="name u-line-2">{{ item.name || item.deviceId }}</view>
- <view class="rssi">
- <view class="text">{{ getRSSIText(item.RSSI) }} </view>
- <view class="signal">
- <view
- class="cell"
- v-for="h in [4, 6, 8, 10]"
- :key="h"
- :style="{
- height: h + 'px',
- background:
- h <= getRSSIStyle(item.RSSI).h
- ? getRSSIStyle(item.RSSI).BC
- : '#BBBBBB',
- }"
- />
- </view>
- </view>
- </view>
- <view style="flex: 1" />
- <view
- class="but"
- hover-class="navigator-hover"
- @click="connected ? '' : createBLEConnection(item)"
- >
- <u-loading-icon
- v-if="connected == item.deviceId"
- color="#FFF"
- inactive-color="#999"
- mode="circle"
- size="18"
- />
- <text v-else>连接</text>
- </view>
- </view>
- <view v-if="empty" class="empty">
- <u-empty />
- <view class="title"> 如果长时间未搜索到设备 </view>
- <view class="row"> 1.请检查设备是否开启蓝牙与地理位置 </view>
- <view class="row">
- 2.授权小程序蓝牙和位置想信息授权
- <text style="margin-left: 4px; font-weight: 700" @click="openSetting"
- >去设置</text
- >
- </view>
- <view class="row">
- 3.搜索全部蓝牙设备
- <text style="margin-left: 4px; font-weight: 700" @click="setServices"
- >设置</text
- >
- </view>
- </view>
- </My_listbox>
- </view>
- </template>
- <script>
- export default {
- components: {},
- name: "Bluetooth",
- data() {
- return {
- beSearching: false, //搜索状态
- connected: "", //连接状态
- empty: true,
- services: [],
- devices: [],
- };
- },
- onLoad(options) {
- if (options.services) {
- this.services = JSON.parse(options.services);
- this.startBluetooth(["FW01"]);
- } else {
- this.startBluetooth();
- }
- this.$refs.List.setHeight();
- },
- onUnload() {
- this.stopBluetooth();
- },
- methods: {
- setServices() {
- this.services = [];
- this.stopBluetooth();
- setTimeout(() => {
- this.startBluetooth([]);
- });
- },
- openSetting() {
- uni.openSetting();
- },
- /* 开始搜索 */
- startBluetooth(services = []) {
- let that = this;
- uni.onBluetoothDeviceFound(function ({ devices }) {
- that.devices = that.devices.concat(devices);
- that.empty = that.devices.length == 0;
- });
- uni.startBluetoothDevicesDiscovery({
- // services,
- success(res) {
- that.beSearching = true;
- that.$refs.List.setHeight();
- },
- fail: (fail) => {
- that.beSearching = false;
- that.handleFail(fail);
- if (fail.errno == 10000) uni.openBluetoothAdapter();
- },
- });
- },
- /* 停止搜索 */
- stopBluetooth() {
- let that = this;
- uni.stopBluetoothDevicesDiscovery({
- success: (success) => {
- that.beSearching = false;
- },
- });
- },
- /* 开始连接 */
- createBLEConnection(item) {
- this.stopBluetooth();
- let that = this,
- device = {
- device: item,
- };
- that.connected = item.deviceId;
- uni.createBLEConnection({
- deviceId: item.deviceId,
- success(res) {
- if (res.errCode == 0) {
- uni.getBLEDeviceServices({
- deviceId: item.deviceId,
- success(res) {
- console.log("获取蓝牙服务列表", res);
- if (res.services.length == 0) {
- uni.showModal({
- content: "未获取到蓝牙设备服务列表",
- showCancel: false,
- confirmText: "确认",
- });
- that.closeBLEConnection();
- } else {
- let services = res.services.find(
- (v) => v.uuid.split("-")[0] == "0000FFE0"
- );
- try {
- uni.setBLEMTU({
- deviceId: item.deviceId,
- mtu: 512,
- success: (success) => {
- console.log("设置mtu512", success);
- },
- fail: (fail) => {
- console.log("设置mtu512fail", fail);
- },
- });
- } catch (error) {}
- if (services) {
- device.services = services;
- uni.getBLEDeviceCharacteristics({
- deviceId: item.deviceId,
- serviceId: services.uuid,
- success(res) {
- let write = false,
- notify = false;
- res.characteristics.forEach((v) => {
- if (v.properties.notify) {
- device.Ncharacteristic = v;
- notify = true;
- console.log("获取到notify" + v.uuid.split("-")[0]);
- } else if (res.characteristics[0].properties.write) {
- device.Wcharacteristic = v;
- write = true;
- console.log("获取到write" + v.uuid.split("-")[0]);
- }
- });
- if (write && notify) {
- uni.showModal({
- content: `${
- item.name || item.deviceId
- }连接成功\n是否进入设备操作页`,
- confirmText: "确认",
- cancelText: "重选",
- success: ({ confirm }) => {
- if (confirm) {
- console.log("设备连接完成");
- that.$Http.setBluetooth(device);
- } else {
- that.closeBLEConnection();
- }
- },
- });
- } else {
- uni.showModal({
- content: "设备未开启notify或write权限,已断开连接",
- showCancel: false,
- confirmText: "确认",
- });
- that.closeBLEConnection();
- }
- },
- });
- } else {
- uni.showModal({
- content: "未获取到蓝牙设备指定‘0000FFE0’服务",
- showCancel: false,
- confirmText: "确认",
- });
- }
- }
- },
- fail(err) {
- console.error("获取蓝牙服务失败", err);
- that.handleFail(fail);
- },
- });
- } else {
- console.log("设备连接失败", that.codes[res.errCode]);
- that.handleFail(res);
- }
- },
- fail: (fail) => {
- console.log("连接失败", fail);
- that.handleFail(fail);
- },
- });
- },
- /* 关闭连接 */
- closeBLEConnection() {
- let that = this;
- if (this.connected)
- uni.closeBLEConnection({
- deviceId: that.connected,
- success(res) {},
- });
- this.connected = "";
- },
- handleFail(fail) {
- const codes = {
- 0: "ok",
- "-1": "已连接 ",
- 10000: "未初始化蓝牙适配器",
- 10001: "当前蓝牙适配器不可用",
- 10002: "没有找到指定设备",
- 10003: "连接失败",
- 10004: "没有找到指定服务",
- 10005: "没有找到指定特征值",
- 10006: "当前连接已断开",
- 10007: "当前特征值不支持此操作",
- 10008: "其余所有系统上报的异常",
- 10009: "系统版本低于 4.3 不支持 BLE",
- 10010: "已连接",
- 10011: "配对设备需要配对码",
- 10012: "连接超时",
- 10013: "连接 deviceId 为空或者是格式不正确",
- };
- this.connected = false;
- uni.showModal({
- content: codes[fail.errCode] || fail.errMsg,
- showCancel: false,
- confirmText: "确认",
- });
- this.closeBLEConnection();
- },
- getRSSIText: function (rssi) {
- let text = "";
- if (rssi >= -70) {
- text = "可连接";
- } else if (rssi < -90) {
- text = "不可连接";
- } else {
- text = "信号差";
- }
- return text + `(${rssi})`;
- },
- getRSSIStyle: function (rssi) {
- let obj = {
- h: 10,
- BC: "#5AB73F",
- };
- if (rssi < -60 && rssi >= -69) {
- obj.h = 8;
- } else if (rssi <= -70 && rssi >= -79) {
- obj.h = 6;
- obj.BC = "#F29C37";
- } else if (rssi <= -80 && rssi >= -89) {
- obj.h = 4;
- obj.BC = "#EB4B5C";
- } else if (rssi <= -90) {
- obj.h = 0;
- }
- return obj;
- },
- },
- };
- </script>
- <style lang="scss" scoped>
- .head {
- display: flex;
- justify-content: space-between;
- align-items: center;
- width: 100vw;
- padding: 10px;
- box-sizing: border-box;
- .title {
- font-family: PingFang SC, PingFang SC;
- font-weight: 500;
- font-size: 15px;
- color: #ffffff;
- }
- .anew {
- font-size: 12px;
- color: #ffffff;
- opacity: 0.8;
- }
- }
- .device {
- display: flex;
- align-items: center;
- width: 355px;
- height: 78px;
- background: #ffffff;
- border-radius: 4px;
- margin: 0 auto 10px;
- .left {
- width: 61px;
- text-align: center;
- color: #333333;
- font-size: 18px;
- }
- .content {
- width: 168px;
- .name {
- font-family: PingFang SC, PingFang SC;
- font-weight: bold;
- font-size: 12px;
- color: #333333;
- }
- .rssi {
- display: flex;
- align-items: center;
- height: 17px;
- margin-top: 4px;
- .text {
- font-family: PingFang SC, PingFang SC;
- font-size: 12px;
- color: #666666;
- margin-right: 18px;
- }
- .signal {
- display: flex;
- align-items: flex-end;
- height: 12px;
- .cell {
- width: 3px;
- border-radius: 1px;
- margin-right: 1px;
- }
- }
- }
- }
- .but {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 56px;
- height: 24px;
- background: #0b3f7e;
- border-radius: 4px;
- font-family: PingFang SC, PingFang SC;
- font-weight: 500;
- font-size: 12px;
- color: #ffffff;
- margin-right: 20px;
- }
- }
- .empty {
- text-align: center;
- color: #fff;
- padding-top: 30px;
- .title {
- font-weight: 700;
- margin-top: 40px;
- }
- .row {
- margin-top: 14px;
- font-size: 12px;
- }
- }
- </style>
|