<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 &lt;= 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 }) {
        let index = that.devices.findIndex(
          (v) => v.deviceId == devices[0].deviceId
        );
        if (index == -1) {
          that.devices = that.devices.concat(devices);
        } else {
          that.devices[index] = devices[0];
        }
        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.connected = "";
                  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();
                                that.connected = "";
                              }
                            },
                          });
                        } else {
                          uni.showModal({
                            content: "设备未开启notify或write权限,已断开连接",
                            showCancel: false,
                            confirmText: "确认",
                          });
                          that.closeBLEConnection();
                          that.connected = "";
                        }
                      },
                    });
                  } else {
                    uni.showModal({
                      content: "未获取到蓝牙设备指定‘0000FFE0’服务",
                      showCancel: false,
                      confirmText: "确认",
                    });
                    that.connected = "";
                  }
                }
              },
              fail(err) {
                console.error("获取蓝牙服务失败", err);
                that.handleFail(fail);
                that.connected = "";
              },
            });
          } else {
            console.log("设备连接失败", that.codes[res.errCode]);
            that.handleFail(res);
            that.connected = "";
          }
        },
        fail: (fail) => {
          console.log("连接失败", fail);
          that.handleFail(fail);
          that.connected = "";
        },
      });
    },
    /* 关闭连接 */
    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>
