<template>
  <view>
    <button @click="getList">获取设备列表</button>
    <view v-if="showList">
      <button class="device" v-for="item in list"
              :key="item.deviceId" @click="connect(item)">{{item.name}}
        - {{item.pair ? '已配对' : '未配对'}}-{{item.sleep ? '休眠中' :
            '已唤醒'}}</button>
    </view>
    <view v-else>
      <button @click="getPublicKey">获取锁公钥</button>
      <button @click="getCommKey">获取锁私钥</button>
      <button @click="getLockStatus">获取锁状态</button>
      <button @click="addUser">添加用户</button>
      <button @click="openDoor">开门</button>
    </view>
  </view>
</template>

<script>
import crc from 'crc'
import { md5 } from 'js-md5'
import { sm4 } from 'sm-crypto'

export default {
  data() {
    return {
      list: [],
      getting: false,
      deviceId: '',
      serviceId: '',
      characteristicId1: '',
      characteristicId2: '',
      lockId: '',
      publicKey: new Uint8Array(16),
      commKey: new Uint8Array(16),
      signKey: new Uint8Array(16),
      showList: true,
      number: 1,
      lockStatus: new Uint8Array(1),
      token: new Uint8Array([0,0,0,0]),
      keyId: '0',
      uid: '294',
      userId: '294',
      // userId: '336',
      password: '',
      config: {},
      notify: false
    }
  },
  onLoad() {
    uni.openBluetoothAdapter({
      success(res) {
        console.log('初始化成功')
        console.log(res)
      },
      fail(res) {
        console.log('初始化失败')
        console.log(res)
      }
    })
  },
  onUnload() {
    uni.closeBluetoothAdapter({
      success(res) {
        console.log('关闭蓝牙成功')
        console.log(res)
      },
      fail(res) {
        console.log('关闭蓝牙失败')
        console.log(res)
      }
    })
  },
  methods: {
    // 添加超级管理员
    addUser() {
      // 头部数据
      let headArray = new Uint8Array(12)

      // 固定包头
      headArray[0] = 0xEF
      headArray[1] = 0x01
      headArray[2] = 0xEE
      headArray[3] = 0x02

      // 包类型 发送
      headArray[4] = 0x01

      // 包序号
      headArray[5] = this.number / 256
      headArray[6] = this.number % 256
      this.number++

      // 包标识
      headArray[7] = 0x23

      // 数据长度
      headArray[8] = 192 / 256
      headArray[9] = 192 % 256
      headArray[10] = 182 / 256
      headArray[11] = 182 % 256

      // 入参
      let paramsArray = new Uint8Array(182)

      // 命令
      paramsArray[0] = 0x3001 / 256
      paramsArray[1] = 0x3001 % 256

      // 锁ID
      for (let i = 0; i < this.lockId.length; i++) {
        paramsArray[2 + i] = this.lockId.charCodeAt(i)
      }

      // 用户ID
      for (let i = 0; i < this.uid.length; i++) {
        paramsArray[42 + i] = this.uid.charCodeAt(i)
      }

      // keyId
      for (let i = 0; i < this.keyId.length; i++) {
        paramsArray[62 + i] = this.keyId.charCodeAt(i)
      }

      // userId
      for (let i = 0; i < this.userId.length; i++) {
        paramsArray[102 + i] = this.userId.charCodeAt(i)
      }

      // 开锁方式
      paramsArray[122] = 0x01

      // 钥匙类型
      paramsArray[123] = 0x01

      // 启用日期
      const nowTime = parseInt(new Date().getTime() / 1000)

      paramsArray[124] = (nowTime & 0xff000000) >> 24
      paramsArray[125] = (nowTime & 0xff0000) >> 16
      paramsArray[126] = (nowTime & 0xff00) >> 8
      paramsArray[127] = (nowTime & 0xff)

      // 结束日期
      const endTime = 0x11223344

      paramsArray[128] = (endTime & 0xff000000) >> 24
      paramsArray[129] = (endTime & 0xff0000) >> 16
      paramsArray[130] = (endTime & 0xff00) >> 8
      paramsArray[131] = (endTime & 0xff)

      // 有效次数
      paramsArray[132] = 0xffff / 256
      paramsArray[133] = 0xffff % 256

      // 是否循环
      paramsArray[134] = 0
      // 循环周期
      paramsArray[135] = 0
      // 开始小时
      paramsArray[136] = 0
      // 开始分钟
      paramsArray[137] = 0
      // 结束小时
      paramsArray[138] = 0
      // 结束分钟
      paramsArray[139] = 0
      // 用户角色
      paramsArray[140] = 0xff

      // 随机密码
      const password = this.password == '' ? (Math.floor(Math.random() * 900000) + 100000).toString() : this.password.toString()
      console.log('随机密码', password)
      for(let i = 0; i < password.length; i++){
        paramsArray[141 + i] = password.charCodeAt(i)
      }

      for(let i = 0; i < this.token.length; i++){
        paramsArray[161 + i] = this.token[i]
      }
      // MD5长度
      paramsArray[165] = 16

      const originAuthCodeLen = this.keyId.length + this.uid.length + 4 + 16
      let authCodeBinaryData = new Uint8Array(originAuthCodeLen)

      for(let i=0; i < this.uid.length; i++){
        authCodeBinaryData[i] = this.uid.charCodeAt(i)
      }

      for(let i=0; i < this.keyId.length; i++){
        authCodeBinaryData[this.uid.length + i] = this.keyId.charCodeAt(i)
      }

      const number = this.keyId.length + this.uid.length

      if(this.token[0] === 0 && this.token[1] === 0 && this.token[2] === 0 && this.token[3] === 0){
        authCodeBinaryData[number + 0] = (nowTime & 0xff000000) >> 24
        authCodeBinaryData[number + 1] = (nowTime & 0xff0000) >> 16
        authCodeBinaryData[number + 2] = (nowTime & 0xff00) >> 8
        authCodeBinaryData[number + 3] = (nowTime & 0xff)
      } else {
        authCodeBinaryData[number + 0] = this.token[0]
        authCodeBinaryData[number + 1] = this.token[1]
        authCodeBinaryData[number + 2] = this.token[2]
        authCodeBinaryData[number + 3] = this.token[3]
      }

      for(let i=0; i < 16; i++){
        authCodeBinaryData[number + 4 + i] = this.publicKey[i]
      }

      console.log('md5前的数据', Array.from(authCodeBinaryData))
      const md5Hex = md5(authCodeBinaryData)
      const md5Array = new Uint8Array(md5Hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16)))
      console.log('md5后的数据', Array.from(md5Array))

      for(let i = 0; i < md5Array.length; i++) {
        paramsArray[166 + i] = md5Array[i]
      }

      console.log('未加密的数据', Array.from(paramsArray))
      const encryptArray = sm4.encrypt(paramsArray, this.commKey, { mode: 'ecb', output: 'array' })
      console.log('加密后的数据', Array.from(encryptArray))

      // 合并头部数据和加密数据
      let mergeBuffer = new ArrayBuffer(204)
      let mergeArray = new Uint8Array(mergeBuffer)
      for(let i = 0; i < 12; i++){
        mergeArray[i] = headArray[i]
      }
      for(let i = 0; i < 192; i++){
        mergeArray[i + 12] = encryptArray[i]
      }

      console.log('crc前的数据', Array.from(mergeArray))
      let resultBuffer = new ArrayBuffer(206)
      let resultArray = new Uint8Array(resultBuffer)
      for(let i = 0; i < 204; i++){
        resultArray[i] = mergeArray[i]
      }
      resultArray[204] = crc.crc16kermit(mergeBuffer) / 256
      resultArray[205] = crc.crc16kermit(mergeBuffer) % 256
      this.writeBLECharacteristicValue(resultBuffer)
    },
    reconnect() {
      return new Promise(resolve => setTimeout(resolve, 2000))
    },
    // 开门
    async openDoor() {
      const that = this

      that.connect(that.config)
      // 重连
      const result = await that.reconnect()

      // 头部数据
      let headArray = new Uint8Array(12)

      // 固定包头
      headArray[0] = 0xEF
      headArray[1] = 0x01
      headArray[2] = 0xEE
      headArray[3] = 0x02

      // 包类型 发送
      headArray[4] = 0x01

      // 包序号
      headArray[5] = this.number / 256
      headArray[6] = this.number % 256
      this.number++

      // 包标识
      headArray[7] = 0x23

      // 数据长度
      headArray[8] = 112 / 256
      headArray[9] = 112 % 256
      headArray[10] = 104 / 256
      headArray[11] = 104 % 256

      // 入参
      let paramsArray = new Uint8Array(104)

      // 命令
      paramsArray[0] = 0x3005 / 256
      paramsArray[1] = 0x3005 % 256

      // 锁ID
      for (let i = 0; i < this.lockId.length; i++) {
        paramsArray[2 + i] = this.lockId.charCodeAt(i)
      }

      // 用户ID
      for (let i = 0; i < this.uid.length; i++) {
        paramsArray[42 + i] = this.uid.charCodeAt(i)
      }

      // 开锁方式
      paramsArray[62] = 0

      // 启用日期
      const nowTime = parseInt(new Date().getTime() / 1000)

      paramsArray[63] = (nowTime & 0xff000000) >> 24
      paramsArray[64] = (nowTime & 0xff0000) >> 16
      paramsArray[65] = (nowTime & 0xff00) >> 8
      paramsArray[66] = (nowTime & 0xff)

      // token
      for (let i = 0; i < this.token.length; i++) {
        paramsArray[67 + i] = this.token[i]
      }

      // authCode长度
      paramsArray[71] = 16

      const originAuthCodeLen = this.keyId.length + this.uid.length + 4 + 16
      let authCodeBinaryData = new Uint8Array(originAuthCodeLen)

      for (let i = 0; i < this.keyId.length; i++) {
        authCodeBinaryData[i] = this.keyId.charCodeAt(i)
      }

      for (let i = 0; i < this.uid.length; i++) {
        authCodeBinaryData[this.keyId.length + i] = this.uid.charCodeAt(i)
      }

      const number = this.keyId.length + this.uid.length

      authCodeBinaryData[number + 0] = this.token[0]
      authCodeBinaryData[number + 1] = this.token[1]
      authCodeBinaryData[number + 2] = this.token[2]
      authCodeBinaryData[number + 3] = this.token[3]

      for (let i = 0; i < 16; i++) {
        authCodeBinaryData[number + 4 + i] = this.signKey[i]
      }

      console.log('md5前的数据', Array.from(authCodeBinaryData))
      const md5Hex = md5(authCodeBinaryData)
      const md5Array = new Uint8Array(md5Hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16)))
      console.log('md5后的数据', Array.from(md5Array))

      for (let i = 0; i < md5Array.length; i++) {
        paramsArray[72 + i] = md5Array[i]
      }

      const onlineToken = '0'
      for (let i = 0; i < onlineToken.length; i++) {
        paramsArray[88 + i] = onlineToken.charCodeAt(i)
      }

      console.log('未加密的数据', Array.from(paramsArray))
      const encryptArray = sm4.encrypt(paramsArray, this.commKey, { mode: 'ecb', output: 'array' })
      console.log('加密后的数据', Array.from(encryptArray))

      // 合并头部数据和加密数据
      let mergeBuffer = new ArrayBuffer(124)
      let mergeArray = new Uint8Array(mergeBuffer)
      for (let i = 0; i < 12; i++) {
        mergeArray[i] = headArray[i]
      }
      for (let i = 0; i < 112; i++) {
        mergeArray[i + 12] = encryptArray[i]
      }

      console.log('crc前的数据', Array.from(mergeArray))
      let resultBuffer = new ArrayBuffer(126)
      let resultArray = new Uint8Array(resultBuffer)
      for (let i = 0; i < 124; i++) {
        resultArray[i] = mergeArray[i]
      }
      resultArray[124] = crc.crc16kermit(mergeBuffer) / 256
      resultArray[125] = crc.crc16kermit(mergeBuffer) % 256
      this.writeBLECharacteristicValue(resultBuffer)
    },
    // 获取锁状态
    getLockStatus() {
      // 头部数据
      let binaryData = new Uint8Array(12)

      // 固定包头
      binaryData[0] = 0xEF
      binaryData[1] = 0x01
      binaryData[2] = 0xEE
      binaryData[3] = 0x02

      // 包类型 发送
      binaryData[4] = 0x01

      // 包序号
      binaryData[5] = this.number / 256
      binaryData[6] = this.number % 256
      this.number++

      // 包标识
      binaryData[7] = 0x23

      // 数据长度
      binaryData[8] = 80 / 256
      binaryData[9] = 80 % 256
      binaryData[10] = 70 / 256
      binaryData[11] = 70 % 256

      console.log('请求头', Array.from(binaryData))

      // 入参
      let paramsBuffer = new ArrayBuffer(70)
      let paramsBinaryData = new Uint8Array(paramsBuffer)

      // 命令
      paramsBinaryData[0] = 0x3040 / 256
      paramsBinaryData[1] = 0x3040 % 256

      // 设备ID
      for(let i=0; i < this.lockId.length; i++){
        paramsBinaryData[2 + i] = this.lockId.charCodeAt(i)
      }

      // userId
      const authUserId = '294'
      for(let i=0; i < authUserId.length; i++){
        paramsBinaryData[42 + i] = authUserId.charCodeAt(i)
      }

      const nowTime = parseInt(new Date().getTime() / 1000)

      paramsBinaryData[62] = (nowTime & 0xff000000) >> 24
      paramsBinaryData[62 + 1] = (nowTime & 0xff0000) >> 16
      paramsBinaryData[62 + 2] = (nowTime & 0xff00) >> 8
      paramsBinaryData[62 + 3] = (nowTime & 0xff)

      paramsBinaryData[66] = (nowTime & 0xff000000) >> 24
      paramsBinaryData[66 + 1] = (nowTime & 0xff0000) >> 16
      paramsBinaryData[66 + 2] = (nowTime & 0xff00) >> 8
      paramsBinaryData[66 + 3] = (nowTime & 0xff)

      console.log('ecb加密前入参', Array.from(paramsBinaryData))
      console.log('密钥', Array.from(this.commKey))
      const encrypted = sm4.encrypt(paramsBinaryData, this.commKey, { mode: 'ecb', output: 'array' })
      console.log('ecb加密后的数据', Array.from(encrypted))

      let newBuffer = new ArrayBuffer(92)
      let newBinaryData = new Uint8Array(newBuffer)
      for(let i = 0; i < 12; i++){
        newBinaryData[i] = binaryData[i]
      }
      for(let i = 0; i < 80; i++){
        newBinaryData[i + 12] = encrypted[i]
      }
      console.log('crc前的数据', Array.from(newBinaryData))
      let resultBuffer = new ArrayBuffer(94)
      let resultBinaryData = new Uint8Array(resultBuffer)
      for(let i = 0; i < 92; i++){
        resultBinaryData[i] = newBinaryData[i]
      }

      resultBinaryData[92] = crc.crc16kermit(newBuffer) / 256
      resultBinaryData[93] = crc.crc16kermit(newBuffer) % 256
      this.writeBLECharacteristicValue(resultBuffer)
    },
    // 十六进制字符串转Uint8Array
    hexToUint8Array(hex) {
      if (hex.length % 2 !== 0) {
        throw new Error('Invalid hex string')
      }
      const array = new Uint8Array(hex.length / 2)
      for (let i = 0; i < hex.length; i += 2) {
        array[i / 2] = parseInt(hex.substr(i, 2), 16)
      }
      return array
    },
    // 获取私钥
    getCommKey() {
      const keyId = '0'
      const authUserId = '294'
      const nowTime = parseInt(new Date().getTime() / 1000)

      const originAuthCodeLen = keyId.length + authUserId.length + 4 + 16

      let authCodeBuffer = new ArrayBuffer(originAuthCodeLen)
      let authCodeBinaryData = new Uint8Array(authCodeBuffer)

      for(let i=0; i < authUserId.length; i++){
        authCodeBinaryData[i] = authUserId.charCodeAt(i)
      }

      for(let i=0; i < keyId.length; i++){
        authCodeBinaryData[authUserId.length + i] = keyId.charCodeAt(i)
      }

      const number = keyId.length + authUserId.length
      authCodeBinaryData[number + 0] = (nowTime & 0xff000000) >> 24
      authCodeBinaryData[number + 1] = (nowTime & 0xff0000) >> 16
      authCodeBinaryData[number + 2] = (nowTime & 0xff00) >> 8
      authCodeBinaryData[number + 3] = (nowTime & 0xff)

      for(let i=0; i < 16; i++){
        authCodeBinaryData[number + 4 + i] = this.publicKey[i]
      }

      console.log('钥ID', keyId, '用户ID', authUserId, '时间戳', nowTime,'公钥', Array.from(this.publicKey))
      console.log('md5前的数据', Array.from(authCodeBinaryData, byte =>
          byte.toString(10)).join(','))
      const md5Hex = md5(authCodeBinaryData)
      const codeMd5 = new Uint8Array(md5Hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16)))
      console.log('md5后的数据', codeMd5, codeMd5.length)

      const bufferLength = codeMd5.length + 12 + 107

      let buffer = new ArrayBuffer(bufferLength)
      let binaryData = new Uint8Array(buffer)

      // 固定包头
      binaryData[0] = 0xEF
      binaryData[1] = 0x01
      binaryData[2] = 0xEE
      binaryData[3] = 0x02

      // 包类型 发送
      binaryData[4] = 0x01

      // 包序号
      binaryData[5] = this.number / 256
      binaryData[6] = this.number % 256
      this.number++

      // 包标识
      binaryData[7] = 0x22

      // 数据长度
      binaryData[10] = (codeMd5.length + 107) / 256
      binaryData[11] = (codeMd5.length + 107) % 256

      // 命令
      binaryData[12] = 0x3091 / 256
      binaryData[13] = 0x3091 % 256

      for(let i=0; i < this.lockId.length; i++){
        binaryData[14 + i] = this.lockId.charCodeAt(i)
      }
      let flagNumber = 14 + 40
      for (let i = 0; i < keyId.length; i++) {
        binaryData[flagNumber + i] = keyId.charCodeAt(i)
      }
      flagNumber += 40
      for (let i = 0; i < authUserId.length; i++) {
        binaryData[flagNumber + i] = authUserId.charCodeAt(i)
      }

      flagNumber += 20
      binaryData[flagNumber + 0] = (nowTime & 0xff000000) >> 24
      binaryData[flagNumber + 1] = (nowTime & 0xff0000) >> 16
      binaryData[flagNumber + 2] = (nowTime & 0xff00) >> 8
      binaryData[flagNumber + 3] = (nowTime & 0xff)

      flagNumber += 4
      binaryData[flagNumber] = codeMd5.length
      flagNumber += 1
      for (let i = 0; i < codeMd5.length; i++) {
        binaryData[flagNumber + i] = codeMd5[i]
      }

      binaryData[8] = Math.ceil((bufferLength - 12)/16) * 16 / 256
      binaryData[9] = Math.ceil((bufferLength - 12)/16) * 16 % 256

      let cebBuffer = new ArrayBuffer(bufferLength - 12)
      let cebBinaryData = new Uint8Array(cebBuffer)

      for(let i = 0; i < bufferLength - 12; i++){
        cebBinaryData[i] = binaryData[i + 12]
      }

      const key = new Uint8Array(16)
      for (let i = 0; i < this.lockId.length; i++) {
        key[i] = this.lockId.charCodeAt(i)
      }

      console.log('未加密的数据', Array.from(cebBinaryData))
      const encrypted = sm4.encrypt(cebBinaryData, key, { mode: 'ecb' })
      const newBinaryData = this.hexToUint8Array(encrypted)
      console.log('ecb加密后的数据', Array.from(newBinaryData))

      const encrypteBuffer = new ArrayBuffer(12 + newBinaryData.length)
      const encrypteBinaryData = new Uint8Array(encrypteBuffer)
      for(let i = 0; i< 12; i++){
        encrypteBinaryData[i] = binaryData[i]
      }
      for(let i = 12; i < encrypteBinaryData.length; i++){
        encrypteBinaryData[i] = newBinaryData[i - 12]
      }
      console.log('crc前的数据', Array.from(encrypteBinaryData))

      const resultBuffer = new ArrayBuffer(encrypteBinaryData.length + 2)
      const resultBinaryData = new Uint8Array(resultBuffer)
      for(let i = 0; i< encrypteBinaryData.length; i++){
        resultBinaryData[i] = encrypteBinaryData[i]
      }
      resultBinaryData[encrypteBinaryData.length] = crc.crc16kermit(encrypteBuffer) / 256
      resultBinaryData[1 + encrypteBinaryData.length] = crc.crc16kermit(encrypteBuffer) % 256

      this.writeBLECharacteristicValue(resultBuffer)
    },
    // 获取公钥
    getPublicKey() {
      let buffer = new ArrayBuffer(54)
      let binaryData = new Uint8Array(buffer)

      // 固定包头
      binaryData[0] = 0xEF
      binaryData[1] = 0x01
      binaryData[2] = 0xEE
      binaryData[3] = 0x02

      // 包类型 发送
      binaryData[4] = 0x01

      // 包序号
      binaryData[5] = this.number / 256
      binaryData[6] = this.number % 256
      this.number++

      // 包标识
      binaryData[7] = 0x20

      // 数据长度
      binaryData[8] = 42 / 256
      binaryData[9] = 42 % 256
      binaryData[10] = 42 / 256
      binaryData[11] = 42 % 256

      // 命令
      binaryData[12] = 0x3090 / 256
      binaryData[13] = 0x3090 % 256

      // // 设备ID
      for(let i=0; i < this.lockId.length; i++){
        binaryData[14 + i] = this.lockId.charCodeAt(i);
      }

      // crc

      let newBuffer = new ArrayBuffer(56)
      let newBinaryData = new Uint8Array(newBuffer)
      for(let i = 0; i < 54; i++){
        newBinaryData[i] = binaryData[i]
      }
      newBinaryData[54] = crc.crc16kermit(buffer) / 256
      newBinaryData[55] = crc.crc16kermit(buffer) % 256
      this.writeBLECharacteristicValue(newBuffer)
    },
    // 写入输入
    writeBLECharacteristicValue(data) {
      const that = this
      console.log('写入设备的设备 ID',that.deviceId)
      console.log('写入设备的serviceId',that.serviceId)
      console.log('写入设备的characteristicId',that.characteristicId2)
      console.log('写入设备的lockID',that.lockId)

      let Uint8ArrayData = new Uint8Array(data)

      console.log('未加工的数据', Array.from(Uint8ArrayData))

      for(let i = 0; i < Math.ceil(data.byteLength / 20); i++){
        let length = i === (Math.ceil(data.byteLength / 20)-1)?data.byteLength%20:20
        let buffer = new ArrayBuffer(length)
        let binaryData = new Uint8Array(buffer)
        for(let j = 0; j < 20; j++){
          if(i * 20 + j < data.byteLength){
            binaryData[j] = Uint8ArrayData[i * 20 + j]
          }
        }
        uni.writeBLECharacteristicValue({
          deviceId: that.deviceId,
          serviceId: that.serviceId,
          characteristicId: that.characteristicId2,
          value: buffer,
          success() {
            const hexString = Array.from(binaryData, byte =>
                byte.toString(10)).join(',')
            console.log('写入的数据', hexString)
            console.log('写入成功')
          },
          fail(res) {
            console.log('写入失败')
            console.log(res)
          }
        })
      }
    },
    // 解析特征值返回数据
    parsingdata(binaryData) {
      const that = this
      // 明文 0x20 SM4事先约定密钥 0x22
      if(binaryData[7] === 0x20) {
        if(binaryData[12] === 48 && binaryData[13] === 144){
          const publicKey = binaryData.slice(15, 31)
          console.log('公钥', Array.from(publicKey))
          that.publicKey = publicKey
        }
      } else if(binaryData[7] === 0x22) {
        const cebBinaryData = binaryData.slice(12, binaryData.length - 2)
        console.log('sm4返回参数', Array.from(cebBinaryData))
        const key = new Uint8Array(16)
        for (let i = 0; i < that.lockId.length; i++) {
          key[i] = that.lockId.charCodeAt(i)
        }
        const decrypted = sm4.decrypt(cebBinaryData, key, { mode: 'ecb', output: 'array' })
        console.log('ecb解密后的数据', decrypted)
        if(decrypted[0] === 48 && decrypted[1] === 145) {
          that.commKey = decrypted.slice(3, 19)
          that.signKey = decrypted.slice(19, 35)
          console.log('commKey', Array.from(that.commKey))
          console.log('signKey', Array.from(that.signKey))
        }
      } else if(binaryData[7] === 0x23) {
        const cebBinaryData = binaryData.slice(12, binaryData.length - 2)
        console.log('sm4返回参数', Array.from(cebBinaryData))
        const decrypted = sm4.decrypt(cebBinaryData, that.commKey, { mode: 'ecb', output: 'array' })
        console.log('ecb解密后的数据', decrypted)
        if(decrypted[0] === 48 && decrypted[1] === 64) {
          that.lockStatus = decrypted
          console.log('锁状态', that.lockStatus)
        } else {
          that.token = decrypted.slice(42,46)
          console.log('token', Array.from(that.token))
          if(decrypted[0] === 48 && decrypted[1] === 1) {
            if(decrypted[46] === 6) {
              that.addUser()
            }
          } else if(decrypted[0] === 48 && decrypted[1] === 5) {
            if(decrypted[46] === 6) {
              that.openDoor()
            }
          }
        }
      }
    },
    // 监听特征值变化
    notifyBLECharacteristicValueChange() {
      const that = this
      let completeData
      let length
      uni.notifyBLECharacteristicValueChange({
        state: true,
        deviceId: that.deviceId,
        serviceId: that.serviceId,
        characteristicId: that.characteristicId1,
        type: 'notification',
        success(res) {
          console.log(res)
          if(that.notify) return
          uni.onBLECharacteristicValueChange(function (res) {
            that.notify = true
            let binaryData = new Uint8Array(res.value)
            console.log('设备返回的数据', Array.from(binaryData), Array.from(binaryData, byte =>
                byte.toString(16)).join(','))
            if(binaryData[0] === 239 && binaryData[1] === 1 && binaryData[2] === 238 && binaryData[3] === 2) {
              length = binaryData[8] * 256 + binaryData[9]
              if(length + 14 > binaryData.length) {
                completeData = binaryData
              } else {
                that.parsingdata(binaryData)
              }
            } else {
              if(completeData.length > 0) {
                const combinedArray = new Uint8Array(completeData.length + binaryData.length)
                combinedArray.set(completeData, 0);
                combinedArray.set(binaryData, completeData.length)
                completeData = combinedArray
                if(length + 14 === completeData.length) {
                  that.parsingdata(completeData)
                  completeData = new Uint8Array(0)
                }
              }
            }
          })
        }
      })
    },

    // 连接蓝牙设备
    connect(item) {
      this.config = item
      const that = this
      if(item.pair) {
        return
      }
      uni.createBLEConnection({
        deviceId: item.deviceId,
        success(res) {
          console.log('连接成功')
          console.log(res)
          uni.getBLEDeviceServices({
            deviceId: item.deviceId,
            success(res) {
              console.log('获取服务成功')
              console.log(res.services)
              const uuid = res.services[0].uuid
              that.lockId = item.name
              console.log('锁ID', that.lockId)
              uni.getBLEDeviceCharacteristics({
                deviceId: item.deviceId,
                serviceId: uuid,
                success(res) {
                  console.log('获取特征值成功')
                  console.log(res)
                  that.deviceId = item.deviceId
                  that.serviceId = uuid
                  for (let i = 0; i < res.characteristics.length; i++) {
                    if (res.characteristics[i].uuid.indexOf("FFF1") !== -1) {
                      that.characteristicId1 = res.characteristics[i].uuid
                    }
                    if (res.characteristics[i].uuid.indexOf("FFF2") !== -1) {
                      that.characteristicId2 = res.characteristics[i].uuid
                    }
                  }
                  that.showList = false
                  that.notifyBLECharacteristicValueChange()
                  uni.showToast({
                    title: '数据获取成功',
                    icon: 'none',
                    duration: 2000
                  })
                },
                fail(res) {
                  console.log('获取特征值失败')
                  console.log(res)
                }
              })
            },
            fail(res) {
              console.log('获取服务失败')
              console.log(res)
            }
          })
        },
        fail(res) {
          console.log('连接失败')
          console.log(res)
        }
      })
    },
    // 监听蓝牙设备列表变化
    startGetList() {
      const that = this
      this.getting = true
      console.log('开始监听蓝牙列表更新')
      uni.startBluetoothDevicesDiscovery({
        allowDuplicatesKey: false,
        powerLevel: 'high',
        success: function (res) {
          // 更新列表
          console.log('列表发生变化', res)
          that.getList()
        }
      })
    },
    // 获取蓝牙设备列表
    getList() {
      const that = this
      uni.getBluetoothDevices({
        success(res) {
          console.log('获取设备列表成功')
          console.log(res)
          that.list = []
          for(let i =0; i < res.devices.length; i++){
            if(res.devices[i]?.advertisServiceUUIDs) {
              const advertisServiceUUIDs =
                  res.devices[i]?.advertisServiceUUIDs[0]
              if(advertisServiceUUIDs &&
                  advertisServiceUUIDs.slice(2,8)==='758824'){
                res.devices[i].pair =
                    advertisServiceUUIDs.slice(30,32) === '01'
                res.devices[i].sleep =
                    advertisServiceUUIDs.slice(32,34) === '00'
                that.list.push(res.devices[i])
              }
            }
          }
          console.log(that.list)
          if(!that.getting) {
            that.startGetList()
          }
        },
        fail(res) {
          console.log('获取设备列表失败')
          console.log(res)
        }
      })
    }
  }
}
</script>

<style>
.device {
  text-align: center;
}
</style>
