| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520 |
- const regeneratorRuntime = require('./regenerator/runtime.js')
- const logEnable = false
- let isAndroid = false
- let ecBluetoothAdapterStateChangeCallback = () => {}
- let ecBLEConnectionStateChangeCallback = () => {}
- let ecDeviceId = ''
- let ecGattServerUUID = ''
- const ecGattServerUUIDOption1 = '0000A002-0000-1000-8000-00805F9B34FB'
- const ecGattServerUUIDOption2 = 'A002'
- let ecGattCharacteristicWriteUUID = ''
- const ecGattCharacteristicWriteUUIDOption1 = '0000C304-0000-1000-8000-00805F9B34FB'
- const ecGattCharacteristicWriteUUIDOption2 = 'C304'
- const log = data => {
- if (logEnable) {
- console.log('[eciot]:' + JSON.stringify(data))
- }
- }
- const onBluetoothAdapterStateChange = cb => {
- ecBluetoothAdapterStateChangeCallback = cb
- }
- const getSetting = () => {
- return new Promise(function (resolve, reject) {
- wx.getSetting({
- success(res) {
- log(res)
- if (res.authSetting && res.authSetting['scope.bluetooth']) {
- resolve({ ok: true, errCode: 0, errMsg: '' })
- } else {
- resolve({
- ok: false,
- errCode: 30001,
- errMsg: 'getSetting fail',
- })
- }
- },
- fail(res) {
- log(res)
- resolve({
- ok: false,
- errCode: res.errCode ? res.errCode : 30000,
- errMsg: res.errMsg ? res.errMsg : 'getSetting fail',
- })
- },
- })
- })
- }
- const authorize = () => {
- return new Promise(function (resolve, reject) {
- wx.authorize({
- scope: 'scope.bluetooth',
- success(res) {
- log(res)
- resolve({ ok: true, errCode: 0, errMsg: '' })
- },
- fail(res) {
- log(res)
- // {"errMsg":"authorize:fail:auth deny"}
- resolve({ ok: false, errCode: 30000, errMsg: res.errMsg })
- },
- })
- })
- }
- const _openBluetoothAdapter = () => {
- return new Promise(function (resolve, reject) {
- wx.openBluetoothAdapter({
- success(res) {
- log(res)
- // {errno: 0, errMsg: "openBluetoothAdapter:ok"}
- resolve({ ok: true, errCode: 0, errMsg: '' })
- },
- fail(res) {
- log(res)
- resolve({
- ok: false,
- errCode: res.errCode ? res.errCode : 30000,
- errMsg: res.errMsg,
- })
- },
- })
- })
- }
- const openBluetoothAdapter = async () => {
- await _openBluetoothAdapter()
- const systemInfo = wx.getSystemInfoSync()
- log(systemInfo)
- if (systemInfo.platform.toLowerCase() === 'android') {
- isAndroid = true
- }
- if (!systemInfo.bluetoothEnabled) {
- ecBluetoothAdapterStateChangeCallback({
- ok: false,
- errCode: 30001,
- errMsg: '请打开系统蓝牙开关',
- })
- return
- }
- if (isAndroid && !systemInfo.locationEnabled) {
- ecBluetoothAdapterStateChangeCallback({
- ok: false,
- errCode: 30002,
- errMsg: '请打开系统定位开关',
- })
- return
- }
- if (isAndroid && !systemInfo.locationAuthorized) {
- ecBluetoothAdapterStateChangeCallback({
- ok: false,
- errCode: 30003,
- errMsg: '请打开微信定位权限,允许微信使用您的位置信息',
- })
- return
- }
- const setting = await getSetting() //小程序蓝牙权限
- if (!setting.ok) {
- const authRes = await authorize()
- if (!authRes.ok) {
- ecBluetoothAdapterStateChangeCallback({
- ok: false,
- errCode: 30004,
- errMsg: '请打开小程序蓝牙开关,点击右上角三个点,然后点击设置',
- })
- return
- }
- }
- wx.offBluetoothAdapterStateChange()
- wx.onBluetoothAdapterStateChange(res => {
- log(res) // {available: true, discovering: true}
- if (!res.available) {
- ecBluetoothAdapterStateChangeCallback({
- ok: false,
- errCode: 30005,
- errMsg: '蓝牙适配器不可用',
- })
- }
- })
- const openRes = await _openBluetoothAdapter()
- ecBluetoothAdapterStateChangeCallback(openRes)
- }
- const onBluetoothDeviceFound = cb => {
- wx.offBluetoothDeviceFound()
- wx.onBluetoothDeviceFound(res => {
- log(res)
- const device = res.devices[0]
- const name = device.name ? device.name : device.localName
- if (!name) {
- return
- }
- let id = device.deviceId
- let rssi = device.RSSI
- cb({ id, name, rssi })
- })
- }
- const startBluetoothDevicesDiscovery = () => {
- wx.startBluetoothDevicesDiscovery({
- //services: [ecServerId],
- allowDuplicatesKey: true,
- powerLevel: 'high',
- complete(res) {
- log(res)
- },
- })
- }
- const stopBluetoothDevicesDiscovery = () => {
- wx.stopBluetoothDevicesDiscovery({
- complete(res) {
- // {errno: 0, errMsg: "stopBluetoothDevicesDiscovery:ok", isDiscovering: false}
- log(res)
- },
- })
- }
- const onBLEConnectionStateChange = cb => {
- ecBLEConnectionStateChangeCallback = cb
- }
- const _createBLEConnection = () => {
- return new Promise(function (resolve, reject) {
- wx.createBLEConnection({
- deviceId: ecDeviceId,
- success(res) {
- log(res)
- // {"errno":0,"errCode":0,"errMsg":"createBLEConnection:ok"}
- resolve({ ok: true, errCode: 0, errMsg: '' })
- },
- fail(res) {
- log(res)
- // {"errno":1001,"errMsg":"createBLEConnection:fail parameter error: parameter.deviceId should be String instead of Undefined;"}
- resolve({
- ok: false,
- errCode: res.errCode ? res.errCode : res.errno,
- errMsg: res.errMsg,
- })
- },
- })
- })
- }
- const getBLEDeviceServices = () => {
- return new Promise(function (resolve, reject) {
- wx.getBLEDeviceServices({
- deviceId: ecDeviceId,
- success(res) {
- log(res)
- //{"services":[{"uuid":"0000FFF0-0000-1000-8000-00805F9B34FB","isPrimary":true}],"errCode":0,"errno":0,"errMsg":"getBLEDeviceServices:ok"}
- // {"errno":0,"deviceId":"7C7E20F2-CB75-6DA8-F8DF-FFF702B0D63F","services":[{"isPrimary":true,"uuid":"0000FFF0-0000-1000-8000-00805F9B34FB"}],"errMsg":"getBLEDeviceServices:ok","errCode":0}
- resolve({
- ok: true,
- errCode: 0,
- errMsg: '',
- services: res.services,
- })
- },
- fail(res) {
- log(res)
- resolve({ ok: false, errCode: res.errCode, errMsg: res.errMsg })
- },
- })
- })
- }
- const getBLEDeviceCharacteristics = serviceId => {
- return new Promise(function (resolve, reject) {
- wx.getBLEDeviceCharacteristics({
- deviceId: ecDeviceId,
- serviceId,
- success(res) {
- log(res)
- // {"characteristics":[{"uuid":"0000FFF2-0000-1000-8000-00805F9B34FB","handle":3,"properties":{"read":false,"write":true,"notify":false,"indicate":false,"writeNoResponse":true,"writeDefault":true}},{"uuid":"0000FFF1-0000-1000-8000-00805F9B34FB","handle":5,"properties":{"read":true,"write":true,"notify":true,"indicate":false,"writeNoResponse":true,"writeDefault":true}}],"errCode":0,"errno":0,"errMsg":"getBLEDeviceCharacteristics:ok"}
- // {"characteristics":[{"properties":{"writeDefault":true,"notify":false,"write":true,"indicate":false,"read":false,"writeNoResponse":true},"uuid":"0000FFF2-0000-1000-8000-00805F9B34FB"},{"properties":{"writeDefault":true,"notify":true,"write":true,"indicate":false,"read":true,"writeNoResponse":true},"uuid":"0000FFF1-0000-1000-8000-00805F9B34FB"}],"deviceId":"7C7E20F2-CB75-6DA8-F8DF-FFF702B0D63F","serviceId":"0000FFF0-0000-1000-8000-00805F9B34FB","errno":0,"errMsg":"getBLEDeviceCharacteristics:ok","errCode":0}
- resolve({
- ok: true,
- errCode: 0,
- errMsg: '',
- characteristics: res.characteristics,
- })
- },
- fail(res) {
- log(res)
- resolve({ ok: false, errCode: res.errCode, errMsg: res.errMsg })
- },
- })
- })
- }
- const notifyBLECharacteristicValueChange = (serviceId, characteristicId) => {
- return new Promise(function (resolve, reject) {
- wx.notifyBLECharacteristicValueChange({
- state: true,
- deviceId: ecDeviceId,
- serviceId,
- characteristicId,
- success(res) {
- log(res)
- // {"errCode":0,"errno":0,"errMsg":"notifyBLECharacteristicValueChange:ok"}
- resolve({ ok: true, errCode: 0, errMsg: '' })
- },
- fail(res) {
- log(res)
- resolve({ ok: false, errCode: res.errCode, errMsg: res.errMsg })
- },
- })
- })
- }
- const setBLEMTU = mtu => {
- return new Promise(function (resolve, reject) {
- wx.setBLEMTU({
- deviceId: ecDeviceId,
- mtu,
- success(res) {
- log(res)
- // {"errMsg":"setBLEMTU:ok","errno":0,"errCode":0,"mtu":50}
- resolve({ ok: true, errCode: 0, errMsg: '' })
- },
- fail(res) {
- log(res)
- // {"errCode":-1,"errno":1500104,"errMsg":"setBLEMTU:fail:internal error"}
- resolve({ ok: false, errCode: res.errCode, errMsg: res.errMsg })
- },
- })
- })
- }
- //和设备建立连接
- const createBLEConnection = async id => {
- ecDeviceId = id
- wx.offBLEConnectionStateChange()
- wx.onBLEConnectionStateChange(async res => {
- log(res)
- // {"deviceId":"EC:22:05:13:78:49","connected":true}
- if (res.connected) {
- const servicesResult = await getBLEDeviceServices()
- if (!servicesResult.ok) {
- ecBLEConnectionStateChangeCallback(servicesResult)
- closeBLEConnection()
- return
- }
- console.log(servicesResult.services)
- for (const service of servicesResult.services) {
- var isRightService = false;
- if ((service.uuid.toUpperCase() === ecGattServerUUIDOption1) ||
- (service.uuid.toUpperCase() === ecGattServerUUIDOption2)) {
- ecGattServerUUID = service.uuid
- isRightService = true;
- }
- if(!isRightService){
- continue;
- }
- const characteristicsResult = await getBLEDeviceCharacteristics(
- service.uuid
- )
- if (!characteristicsResult.ok) {
- ecBLEConnectionStateChangeCallback(characteristicsResult)
- closeBLEConnection()
- return
- }
- console.log(characteristicsResult.characteristics);
- for (const characteristic of characteristicsResult.characteristics) {
- if (
- characteristic.properties &&
- characteristic.properties.notify
- ) {
- const notifyResult =
- await notifyBLECharacteristicValueChange(
- service.uuid,
- characteristic.uuid
- )
- if (!notifyResult.ok) {
- ecBLEConnectionStateChangeCallback({
- ok: false,
- errCode: 30000,
- errMsg: 'notify error',
- })
- closeBLEConnection()
- return
- }
- }
- if ((characteristic.uuid.toUpperCase() === ecGattCharacteristicWriteUUIDOption1 || characteristic.uuid.toUpperCase() === ecGattCharacteristicWriteUUIDOption2)){
- ecGattCharacteristicWriteUUID = characteristic.uuid
- }
- }
- }
- if (isAndroid) {
- await setBLEMTU(247)
- }
- ecBLEConnectionStateChangeCallback({
- ok: true,
- errCode: 0,
- errMsg: '',
- })
- } else {
- ecBLEConnectionStateChangeCallback({
- ok: false,
- errCode: 0,
- errMsg: 'disconnect',
- })
- }
- })
- const res = await _createBLEConnection()
- if (!res.ok) {
- ecBLEConnectionStateChangeCallback(res)
- }
- }
- //关闭当前连接
- const closeBLEConnection = () => {
- wx.closeBLEConnection({
- deviceId: ecDeviceId,
- complete(res) {
- log(res)
- },
- })
- }
- const onBLECharacteristicValueChange = cb => {
- wx.offBLECharacteristicValueChange()
- wx.onBLECharacteristicValueChange(res => {
- log(res)
- let x = new Uint8Array(res.value)
- log(x)
- let str = utf8BytesToStr(x)
- let strHex = ''
- for (let i = 0; i < x.length; i++) {
- strHex =
- strHex + x[i].toString(16).padStart(2, '0').toUpperCase()
- }
- log(str)
- log(strHex)
- cb(str, strHex)
- })
- }
- const _writeBLECharacteristicValue = buffer => {
- return new Promise(function (resolve, reject) {
- wx.writeBLECharacteristicValue({
- deviceId: ecDeviceId,
- serviceId: ecGattServerUUID,
- characteristicId: ecGattCharacteristicWriteUUID,
- value: buffer,
- writeType: 'write',
- success(res) {
- log(res)
- // {"errno":0,"errCode":0,"errMsg":"writeBLECharacteristicValue:ok"}
- resolve({ ok: true, errCode: 0, errMsg: '' })
- },
- fail(res) {
- log(res)
- resolve({ ok: false, errCode: res.errCode, errMsg: res.errMsg })
- },
- })
- })
- }
- const writeBLECharacteristicValue = async (str, isHex) => {
- if (str.length === 0)
- return { ok: false, errCode: 30000, errMsg: 'data is null' }
- let buffer
- if (isHex) {
- buffer = new ArrayBuffer(str.length / 2)
- let x = new Uint8Array(buffer)
- for (let i = 0; i < x.length; i++) {
- x[i] = parseInt(str.substr(2 * i, 2), 16)
- }
- } else {
- buffer = new Uint8Array(strToUtf8Bytes(str)).buffer
- }
- return await _writeBLECharacteristicValue(buffer)
- }
- const utf8BytesToStr = utf8Bytes => {
- let unicodeStr = ''
- for (let pos = 0; pos < utf8Bytes.length; ) {
- let flag = utf8Bytes[pos]
- let unicode = 0
- if (flag >>> 7 === 0) {
- unicodeStr += String.fromCharCode(utf8Bytes[pos])
- pos += 1
- }
- // else if ((flag & 0xFC) === 0xFC) {
- // unicode = (utf8Bytes[pos] & 0x3) << 30
- // unicode |= (utf8Bytes[pos + 1] & 0x3F) << 24
- // unicode |= (utf8Bytes[pos + 2] & 0x3F) << 18
- // unicode |= (utf8Bytes[pos + 3] & 0x3F) << 12
- // unicode |= (utf8Bytes[pos + 4] & 0x3F) << 6
- // unicode |= (utf8Bytes[pos + 5] & 0x3F)
- // unicodeStr += String.fromCharCode(unicode)
- // pos += 6
- // }
- // else if ((flag & 0xF8) === 0xF8) {
- // unicode = (utf8Bytes[pos] & 0x7) << 24
- // unicode |= (utf8Bytes[pos + 1] & 0x3F) << 18
- // unicode |= (utf8Bytes[pos + 2] & 0x3F) << 12
- // unicode |= (utf8Bytes[pos + 3] & 0x3F) << 6
- // unicode |= (utf8Bytes[pos + 4] & 0x3F)
- // unicodeStr += String.fromCharCode(unicode)
- // pos += 5
- // }
- else if ((flag & 0xf0) === 0xf0) {
- unicode = (utf8Bytes[pos] & 0xf) << 18
- unicode |= (utf8Bytes[pos + 1] & 0x3f) << 12
- unicode |= (utf8Bytes[pos + 2] & 0x3f) << 6
- unicode |= utf8Bytes[pos + 3] & 0x3f
- unicodeStr += String.fromCharCode(unicode)
- pos += 4
- } else if ((flag & 0xe0) === 0xe0) {
- unicode = (utf8Bytes[pos] & 0x1f) << 12
- unicode |= (utf8Bytes[pos + 1] & 0x3f) << 6
- unicode |= utf8Bytes[pos + 2] & 0x3f
- unicodeStr += String.fromCharCode(unicode)
- pos += 3
- } else if ((flag & 0xc0) === 0xc0) {
- //110
- unicode = (utf8Bytes[pos] & 0x3f) << 6
- unicode |= utf8Bytes[pos + 1] & 0x3f
- unicodeStr += String.fromCharCode(unicode)
- pos += 2
- } else {
- unicodeStr += String.fromCharCode(utf8Bytes[pos])
- pos += 1
- }
- }
- return unicodeStr
- }
- const strToUtf8Bytes = str => {
- let bytes = []
- for (let i = 0; i < str.length; ++i) {
- let code = str.charCodeAt(i)
- if (code >= 0x10000 && code <= 0x10ffff) {
- bytes.push((code >> 18) | 0xf0) // 第一个字节
- bytes.push(((code >> 12) & 0x3f) | 0x80)
- bytes.push(((code >> 6) & 0x3f) | 0x80)
- bytes.push((code & 0x3f) | 0x80)
- } else if (code >= 0x800 && code <= 0xffff) {
- bytes.push((code >> 12) | 0xe0)
- bytes.push(((code >> 6) & 0x3f) | 0x80)
- bytes.push((code & 0x3f) | 0x80)
- } else if (code >= 0x80 && code <= 0x7ff) {
- bytes.push((code >> 6) | 0xc0)
- bytes.push((code & 0x3f) | 0x80)
- } else {
- bytes.push(code)
- }
- }
- return bytes
- }
- module.exports = {
- onBluetoothAdapterStateChange,
- openBluetoothAdapter,
- onBluetoothDeviceFound,
- startBluetoothDevicesDiscovery,
- stopBluetoothDevicesDiscovery,
- onBLEConnectionStateChange,
- createBLEConnection,
- closeBLEConnection,
- onBLECharacteristicValueChange,
- writeBLECharacteristicValue,
- }
|