快應用 使用藍牙

2020-08-08 15:26 更新
了解如何使用低功耗藍牙

通過本節(jié),你將學會:

使用方法

初始化藍牙模塊

為了使用藍牙功能,你需要先初始化藍牙模塊。除了設置狀態(tài)監(jiān)聽以外,所有的藍牙接口都需要在初始化完成以后才能正常使用。

//初始化藍牙模塊
bluetooth.openAdapter({
  //是否打開系統(tǒng)藍牙開關(guān),默認false
  operateAdapter: true,
  success: function() {
    console.log('success')
  },
  fail: function(data, code) {
    console.log(`handling fail, code = ${code}`)
    if (code === 10001) {
      //藍牙未打開,提示用戶打開藍牙
    }
  },
  complete: function() {
    console.log('complete')
  }
})

搜索周圍設備

你可以通過搜索操作,發(fā)現(xiàn)周圍的低功耗藍牙設備。在進行掃描前,你需要注冊設備發(fā)現(xiàn)回調(diào)以及時接收搜索結(jié)果

//在掃描之前先注冊設備發(fā)現(xiàn)回調(diào)
bluetooth.ondevicefound = function (data) {
  console.log("new device list has founded");
  data.devices.forEach(device => {
    //發(fā)現(xiàn)所需設備后停止掃描
    bluetooth.stopDevicesDiscovery();
    _this.deviceId = device.deviceId;

    console.log(`handling find new devive:${JSON.stringify(device)}`);
    console.log(`handling advertisData = ${_this.ab2hex(device.advertisData)}`);
    for (let key in device.serviceData) {
      console.log(
        `handling serviceData: uuid = ${key}, serviceData = ${_this.ab2hex(device.serviceData[key])}`
      );
    }
  });
};
//開始掃描
bluetooth.startDevicesDiscovery({
  //指定設備uuid,支持16-bit,32-bit,128-bit uuid,不填則掃描周圍所有設備
  services: ["1105"],
  //是否允許重復設備上報,如果不需要監(jiān)聽廣播包數(shù)據(jù),建議不設置此項,默認值為false
  allowDuplicatesKey: false,
  //上報間隔,單位毫秒,為0則立即上報,默認值為0
  interval: 1000,
  success: function () {
    console.log("success");
  }
});

連接設備

在操作設備前,你需要先連接設備,連接操作可以通過deviceId直接進行,掃描并不是必要的操作。在連接前,你可以注冊設備連接狀態(tài)接口來監(jiān)聽設備斷連狀態(tài)

//注冊設備連接狀態(tài)監(jiān)聽
bluetooth.onbleconnectionstatechange = function (data) {
  console.log(`handling device state change: deviceId = ${data.deviceId}, connected = ${data.connected}`)
  //更新設備連接狀態(tài)
  _this.connected = data.connected
  if (data.connected) {
    //目標設備連接后,獲取服務列表
    _this.getServices()
  } else {
    //做斷開連接的相關(guān)操作,比如重新連接,或者重新掃描等
  }
}
//連接設備
bluetooth.createBLEConnection({
  deviceId: _this.deviceId,
  success: function () {
    console.log("success")
  },
  fail: function (data, code) {
    console.log(`handling fail, code = ${code}`)
  },
  complete: function () {
    console.log("complete")
  }
})

獲取設備服務信息

每個設備都會定義若干個服務,你可以從中獲取需要操作的服務信息

bluetooth.getBLEDeviceServices({
  deviceId: _this.deviceId,
  success: function (data) {
    data.services.forEach(service => {
      console.log(`handling device services: uuid = ${service.uuid}, isPrimary = ${service.isPrimary}`)
      //獲取需要的服務,可以根據(jù)設備定義的uuid篩選
      if (service.isPrimary) {
        _this.serviceId = service.uuid
        //獲取特征值列表
        _this.getCharacteristics()
      }
    })
  },
  fail: function (data, code) {
    console.log(`handling fail, code = ${code}`)
  },
  complete: function () {
    console.log("complete")
  }
})

獲取設備特征值信息

每個服務內(nèi)會定義若干個特征值,你可以從中獲取需要操作的特征值信息

bluetooth.getBLEDeviceCharacteristics({
  deviceId: _this.deviceId,
  serviceId: _this.serviceId,
  success: function (data) {
    data.characteristics.forEach(characteristic => {
      console.log(`handling device characteristic : ${JSON.stringify(characteristic)}`)
      //獲取需要的特征值,可以根據(jù)設備定義的uuid篩選
      if (characteristic.properties.write) {
        _this.writeCharacteristicId = characteristic.uuid
      } else if (characteristic.properties.read) {
        _this.readCharacteristicId = characteristic.uuid
      } else if (characteristic.properties.notify || characteristic.properties.indicate) {
        _this.notifyCharacteristicId = characteristic.uuid
      }
    })
  },
  fail: function (data, code) {
    console.log(`handling fail, code = ${code}`)
  },
  complete: function () {
    console.log("complete")
  }
})

向設備寫入數(shù)據(jù)

通過獲取到的服務與特征值信息,可以向設備對應的特征值寫入數(shù)據(jù),需要該特征值支持 write

let buffer = new ArrayBuffer(2)
let dataView = new DataView(buffer)
dataView.setUint8(0, 0)
dataView.setUint8(1, 0xf)
bluetooth.writeBLECharacteristicValue({
  // 這里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound接口中獲取
  deviceId: _this.deviceId,
  // 這里的 serviceId 需要在 getBLEDeviceServices 接口中獲取
  serviceId: _this.serviceId,
  // 這里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中獲取
  characteristicId: _this.writeCharacteristicId,
  // 這里的value是ArrayBuffer類型
  value: buffer,
  success: function () {
    console.log("success")
  },
  fail: function (data, code) {
    console.log(`handling fail, code = ${code}`)
  },
  complete: function () {
    console.log("complete")
  }
})

讀取設備數(shù)據(jù)

通過獲取到的服務與特征值信息,可以讀取設備對應特征值數(shù)據(jù),需要該特征值支持 read,讀取到的設備信息會通過onblecharacteristicvaluechange監(jiān)聽接口上報,此接口藍牙模塊通用,無需重復注冊

//注冊特征值改變監(jiān)聽
bluetooth.onblecharacteristicvaluechange = function (data) {
  console.log(`handling characteristic value change: deviceId = ${data.deviceId}, serviceId = ${data.serviceId}, characteristicId = ${data.characteristicId}, value = ${_this.ab2hex(data.value)}`)
}
bluetooth.readBLECharacteristicValue({
  // 這里的 deviceId 需要已經(jīng)通過 createBLEConnection 與對應設備建立鏈接
  deviceId: _this.deviceId,
  // 這里的 serviceId 需要在 getBLEDeviceServices 接口中獲取
  serviceId: _this.serviceId,
  // 這里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中獲取
  characteristicId: _this.readCharacteristicId,
  success: function () {
    // 執(zhí)行操作成功,讀取的值會在onblecharacteristicvaluechange 接口中上報
    console.log("success")
  }
})

監(jiān)聽設備數(shù)據(jù)變化

通過獲取到的服務與特征值信息,可以開啟或者關(guān)閉設備相應的特征值變化時的通知功能,需要該特征值支持 notify 或者 indicate,讀取到的設備信息會通過onblecharacteristicvaluechange監(jiān)聽接口上報,此接口藍牙模塊通用,無需重復注冊

//注冊特征值改變監(jiān)聽
bluetooth.onblecharacteristicvaluechange = function (data) {
  console.log(`handling characteristic value change: deviceId = ${data.deviceId}, serviceId = ${data.serviceId}, characteristicId = ${data.characteristicId}, value = ${_this.ab2hex(data.value)}`)
}
bluetooth.notifyBLECharacteristicValueChange({
  // 啟用 notify 功能,為true則開啟通知
  state: enable,
  // 這里的 deviceId 需要已經(jīng)通過 createBLEConnection 與對應設備建立鏈接
  deviceId: _this.deviceId,
  // 這里的 serviceId 需要在 getBLEDeviceServices 接口中獲取
  serviceId: _this.serviceId,
  // 這里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中獲取
  characteristicId: _this.notifyCharacteristicId,
  success: function () {
    // 執(zhí)行操作成功,讀取的值會在onblecharacteristicvaluechange 接口中上報
    _this.notifyEnabled = enable
    console.log("success")
  },
  fail: function (data, code) {
    console.log(`handling fail, code = ${code}`)
  },
  complete: function () {
    console.log("complete")
  }
})

注銷藍牙模塊

在不需要使用藍牙時,需要注銷藍牙模塊,以釋放系統(tǒng)資源

//取消不需要的狀態(tài)監(jiān)聽
bluetooth.onadapterstatechange = null
bluetooth.onbleconnectionstatechange = null
bluetooth.onblecharacteristicvaluechange = null
bluetooth.ondevicefound = null

//注銷藍牙模塊
bluetooth.closeAdapter({
  //是否關(guān)閉系統(tǒng)藍牙開關(guān),默認false,此操作會直接關(guān)閉系統(tǒng)藍牙,為了不影響用戶其他藍牙設備的體驗,不建議設置為true
  operateAdapter: false,
  success: function () {
    console.log("success");
  },
  fail: function (data, code) {
    console.log(`handling fail, code = ${code}`);
  },
  complete: function () {
    console.log("complete");
  }
});

示例代碼如下:

<template>
  <div class="doc-page">
    <div class="item-container">
      <text></text>
      <input type="button" class="btn" onclick="startDiscovery" value="掃描設備" />
      <input type="button" class="btn" onclick="createConnection" value="連接設備" />
      <input type="button" class="btn" onclick="closeConnection" value="斷開設備" />
    </div>
    <div class="item-container" if=false>
      <input type="button" class="btn" onclick="write" value="寫入數(shù)據(jù)" />
      <input type="button" class="btn" onclick="read" value="讀取數(shù)據(jù)" />

    </div>
  </div>
</template>

<style>
  .doc-page {
    flex: 1;
    flex-direction: column;
  }

  .item-container {
    flex - direction: column;
    margin-bottom: 50px;
    margin-right: 60px;
    margin-left: 60px;
  }

  .text {
    width: 100%;
    margin-top: 5px;
    background-color: white;
    padding: 3px;
    margin-top: 1px;
    font-size: 28px;
    color: black;
  }

  .btn {
    height: 80px;
    text-align: center;
    border-radius: 5px;
    margin-right: 60px;
    margin-left: 60px;
    margin-bottom: 50px;
    color: #ffffff;
    font-size: 30px;
    background-color: #0faeff;
    line-height: 80px;
  }
</style>

<script>
  import bluetooth from "@system.bluetooth";

  export default {
    private: {
      connected: false,
      notifyEnabled: false,
      deviceId: '',
      readCharacteristicId: '',
      writeCharacteristicId: '',
      notifyCharacteristicId: ''
    },
    //arrayBuffer轉(zhuǎn)String
    ab2hex(buffer) {
      var hexArr = Array.prototype.map.call(
        new Uint8Array(buffer),
        function (bit) {
          return ("00" + bit.toString(16)).slice(-2);
        });
      return hexArr.join("");
    },
    //在頁面初始化時進行藍牙模塊初始化操作
    onInit() {
      let _this = this
      //注冊藍牙適配器監(jiān)聽
      bluetooth.onadapterstatechange = function (data) {
        console.log("adapterState changed, now is", data.available);
      };

      //注冊設備連接狀態(tài)監(jiān)聽
      bluetooth.onbleconnectionstatechange = function (data) {
        console.log(`handling device state change: deviceId = ${data.deviceId}, connected = ${data.connected}`)
        //更新設備連接狀態(tài)
        _this.connected = data.connected
        if (data.connected) {
          //目標設備連接后,獲取服務列表
          _this.getServices()
        } else {
          //做斷開連接的相關(guān)操作,比如重新連接,或者重新掃描等
        }
      }

      //注冊特征值改變監(jiān)聽
      bluetooth.onblecharacteristicvaluechange = function (data) {
        console.log(`handling characteristic value change: deviceId = ${data.deviceId}, serviceId = ${data.serviceId}, characteristicId = ${data.characteristicId}, value = ${_this.ab2hex(data.value)}`)
      }

      //初始化藍牙模塊
      bluetooth.openAdapter({
        //是否打開系統(tǒng)藍牙開關(guān),默認false
        operateAdapter: true,
        success: function () {
          console.log("success");
        },
        fail: function (data, code) {
          console.log(`handling fail, code = ${code}`);
          if (code === 10001) {
            //藍牙未打開,提示用戶打開藍牙
          }
        },
        complete: function () {
          console.log("complete");
        }
      });
    },
    //在結(jié)束時注銷藍牙模塊
    onDestroy() {
      //取消不需要的狀態(tài)監(jiān)聽
      bluetooth.onadapterstatechange = null
      bluetooth.onbleconnectionstatechange = null
      bluetooth.onblecharacteristicvaluechange = null
      bluetooth.ondevicefound = null

      //注銷藍牙模塊
      bluetooth.closeAdapter({
        //是否關(guān)閉系統(tǒng)藍牙開關(guān),默認false,此操作會直接關(guān)閉系統(tǒng)藍牙,為了不影響用戶其他藍牙設備的體驗,不建議設置為true
        operateAdapter: false,
        success: function () {
          console.log("success");
        },
        fail: function (data, code) {
          console.log(`handling fail, code = ${code}`);
        },
        complete: function () {
          console.log("complete");
        }
      });
    },
    startDiscovery() {
      let _this = this
      //在掃描之前先注冊設備發(fā)現(xiàn)回調(diào)
      bluetooth.ondevicefound = function (data) {
        console.log("new device list has founded");
        data.devices.forEach(device => {
          //發(fā)現(xiàn)所需設備后停止掃描
          bluetooth.stopDevicesDiscovery();
          _this.deviceId = device.deviceId;

          console.log(`handling find new devive:${JSON.stringify(device)}`);
          console.log(`handling advertisData = ${_this.ab2hex(device.advertisData)}`);
          for (let key in device.serviceData) {
            console.log(
              `handling serviceData: uuid = ${key}, serviceData = ${_this.ab2hex(device.serviceData[key])}`
            );
          }
        });
      };
      //開始掃描
      bluetooth.startDevicesDiscovery({
        //指定設備uuid,支持16-bit,32-bit,128-bit uuid,不填則掃描周圍所有設備
        services: ["1105"],
        //是否允許重復設備上報,如果不需要監(jiān)聽廣播包數(shù)據(jù),建議不設置此項,默認值為false
        allowDuplicatesKey: false,
        success: function () {
          console.log("success");
        }
      });
    },
    createConnection() {
      let _this = this
      //連接設備
      bluetooth.createBLEConnection({
        deviceId: _this.deviceId,
        success: function () {
          console.log("success")
        },
        fail: function (data, code) {
          console.log(`handling fail, code = ${code}`)
        },
        complete: function () {
          console.log("complete")
        }
      })
    },
    closeConnection() {
      let _this = this
      bluetooth.closeBLEConnection({
        deviceId: _this.deviceId,
        success: function () {
          console.log("success")
        },
        fail: function (data, code) {
          console.log(`handling fail, code = ${code}`)
        },
        complete: function () {
          console.log("complete")
        }
      })
    },
    getServices() {
      let _this = this
      bluetooth.getBLEDeviceServices({
        deviceId: _this.deviceId,
        success: function (data) {
          data.services.forEach(service => {
            console.log(`handling device services: uuid = ${service.uuid}, isPrimary = ${service.isPrimary}`)
            //獲取需要的服務,可以根據(jù)設備定義的uuid篩選
            if (service.isPrimary) {
              _this.serviceId = service.uuid
              //獲取特征列表
              _this.getCharacteristics()
            }
          })
        },
        fail: function (data, code) {
          console.log(`handling fail, code = ${code}`)
        },
        complete: function () {
          console.log("complete")
        }
      })
    },
    getCharacteristics() {
      let _this = this
      bluetooth.getBLEDeviceCharacteristics({
        deviceId: _this.deviceId,
        serviceId: _this.serviceId,
        success: function (data) {
          data.characteristics.forEach(characteristic => {
            console.log(`handling device characteristic : ${JSON.stringify(characteristic)}`)
            //獲取需要的特征,可以根據(jù)設備定義的uuid篩選
            if (characteristic.properties.write) {
              _this.writeCharacteristicId = characteristic.uuid
            } else if (characteristic.properties.read) {
              _this.readCharacteristicId = characteristic.uuid
            } else if (characteristic.properties.notify || characteristic.properties.indicate) {
              _this.notifyCharacteristicId = characteristic.uuid
            }
          })
        },
        fail: function (data, code) {
          console.log(`handling fail, code = ${code}`)
        },
        complete: function () {
          console.log("complete")
        }
      })
    },
    write() {
      let _this = this
      let buffer = new ArrayBuffer(2)
      let dataView = new DataView(buffer)
      dataView.setUint8(0, 0)
      dataView.setUint8(1, 0xf)
      bluetooth.writeBLECharacteristicValue({
        // 這里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound接口中獲取
        deviceId: _this.deviceId,
        // 這里的 serviceId 需要在 getBLEDeviceServices 接口中獲取
        serviceId: _this.serviceId,
        // 這里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中獲取
        characteristicId: _this.writeCharacteristicId,
        // 這里的value是ArrayBuffer類型
        value: buffer,
        success: function () {
          console.log("success")
        },
        fail: function (data, code) {
          console.log(`handling fail, code = ${code}`)
        },
        complete: function () {
          console.log("complete")
        }
      })
    },
    read() {
      let _this = this
      bluetooth.readBLECharacteristicValue({
        // 這里的 deviceId 需要已經(jīng)通過 createBLEConnection 與對應設備建立鏈接
        deviceId: _this.deviceId,
        // 這里的 serviceId 需要在 getBLEDeviceServices 接口中獲取
        serviceId: _this.serviceId,
        // 這里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中獲取
        characteristicId: _this.readCharacteristicId,
        success: function () {
          // 執(zhí)行操作成功,讀取的值會在onblecharacteristicvaluechange 接口中上報
          console.log("success")
        }
      })
    },
    notifyDevice(enable) {
      let _this = this
      bluetooth.notifyBLECharacteristicValueChange({
        // 啟用 notify 功能
        state: enable,
        // 這里的 deviceId 需要已經(jīng)通過 createBLEConnection 與對應設備建立鏈接
        deviceId: _this.deviceId,
        // 這里的 serviceId 需要在 getBLEDeviceServices 接口中獲取
        serviceId: _this.serviceId,
        // 這里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中獲取
        characteristicId: _this.notifyCharacteristicId,
        success: function () {
          // 執(zhí)行操作成功,讀取的值會在onblecharacteristicvaluechange 接口中上報
          _this.notifyEnabled = enable
          console.log("success")
        },
        fail: function (data, code) {
          console.log(`handling fail, code = ${code}`)
        },
        complete: function () {
          console.log("complete")
        }
      })
    }
  };
</script>


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號