最近被支付宝的蓝牙和IOS的蓝牙整破防了,太多兼容性问题,磕磕绊绊终于把支付宝小程序和微信小程序的蓝牙问题给解决了。该方案完美解决
因为支付宝和微信的api不同,收到消息后解析也有所差别,所以对支付宝和微信编写两份APIJS文件,如果业务只涉及单边的蓝牙连接,就只需要引入所需的js即可。
另外IOS和安卓也略有不同,不通型号的手机可发送字节也不同,这都是踩坑才出来的,一把辛酸泪。
新建BLEWX.js文件
/**
* 微信连接蓝牙API
* @author RedEric
* @date 2023年9月6日
*/
const logEnable = false
let isAndroid = false
let BluetoothAdapterStateChangeCallback = () => {}
let BLEConnectionStateChangeCallback = () => {}
let DeviceId = ''
let GattServerUUID = ''
const GattServerUUIDOption1 = '0000FFF0-0000-1000-8000-00805F9B34FB'
const GattServerUUIDOption2 = 'FFF0'
let GattCharacteristicWriteUUID = ''
const GattCharacteristicWriteUUIDOption1 = '0000FFF2-0000-1000-8000-00805F9B34FB'
const GattCharacteristicWriteUUIDOption2 = 'FFF2'
const log = data => {
if (logEnable) {
console.log('[eciot]:' + JSON.stringify(data))
}
}
const onBluetoothAdapterStateChange = cb => {
BluetoothAdapterStateChangeCallback = 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) {
BluetoothAdapterStateChangeCallback({
ok: false,
errCode: 30001,
errMsg: '请打开系统蓝牙开关',
})
return
}
if (isAndroid && !systemInfo.locationEnabled) {
BluetoothAdapterStateChangeCallback({
ok: false,
errCode: 30002,
errMsg: '请打开系统定位开关',
})
return
}
if (isAndroid && !systemInfo.locationAuthorized) {
BluetoothAdapterStateChangeCallback({
ok: false,
errCode: 30003,
errMsg: '请打开微信定位权限,允许微信使用您的位置信息',
})
return
}
const setting = await getSetting() //小程序蓝牙权限
if (!setting.ok) {
const authRes = await authorize()
if (!authRes.ok) {
BluetoothAdapterStateChangeCallback({
ok: false,
errCode: 30004,
errMsg: '请打开小程序蓝牙开关,点击右上角三个点,然后点击设置',
})
return
}
}
wx.offBluetoothAdapterStateChange()
wx.onBluetoothAdapterStateChange(res => {
log(res) // {available: true, discovering: true}
if (!res.available) {
BluetoothAdapterStateChangeCallback({
ok: false,
errCode: 30005,
errMsg: '蓝牙适配器不可用',
})
}
})
const openRes = await _openBluetoothAdapter()
BluetoothAdapterStateChangeCallback(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 => {
BLEConnectionStateChangeCallback = cb
}
const _createBLEConnection = () => {
return new Promise(function (resolve, reject) {
wx.createBLEConnection({
deviceId: DeviceId,
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: DeviceId,
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: DeviceId,
serviceId,
success(res) {
log(res)
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: DeviceId,
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: DeviceId,
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 => {
DeviceId = 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) {
BLEConnectionStateChangeCallback(servicesResult)
closeBLEConnection()
return
}
for (const service of servicesResult.services) {
if ((service.uuid.toUpperCase() === GattServerUUIDOption1) ||
(service.uuid.toUpperCase() === GattServerUUIDOption2)) {
GattServerUUID = service.uuid
}
const characteristicsResult = await getBLEDeviceCharacteristics(
service.uuid
)
if (!characteristicsResult.ok) {
BLEConnectionStateChangeCallback(characteristicsResult)
closeBLEConnection()
return
}
for (const characteristic of characteristicsResult.characteristics) {
if (
characteristic.properties &&
characteristic.properties.notify
) {
const notifyResult =
await notifyBLECharacteristicValueChange(
service.uuid,
characteristic.uuid
)
if (!notifyResult.ok) {
BLEConnectionStateChangeCallback({
ok: false,
errCode: 30000,
errMsg: 'notify error',
})
closeBLEConnection()
return
}
}
if ((characteristic.uuid.toUpperCase() === GattCharacteristicWriteUUIDOption1) ||
(characteristic.uuid.toUpperCase() === GattCharacteristicWriteUUIDOption2)) {
GattCharacteristicWriteUUID = characteristic.uuid
}
}
}
if (isAndroid) {
await setBLEMTU(247)
}
BLEConnectionStateChangeCallback({
ok: true,
errCode: 0,
errMsg: '',
})
} else {
BLEConnectionStateChangeCallback({
ok: false,
errCode: 0,
errMsg: 'disconnect',
})
}
})
const res = await _createBLEConnection()
if (!res.ok) {
BLEConnectionStateChangeCallback(res)
}
}
//关闭当前连接
const closeBLEConnection = () => {
wx.closeBLEConnection({
deviceId: DeviceId,
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: DeviceId,
serviceId: GattServerUUID,
characteristicId: GattCharacteristicWriteUUID,
value: buffer,
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 & 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,
}
新建BLEWX.js文件
/**
* 微信连接蓝牙API
* @author RedEric
* @date 2023年9月6日
*/
const logEnable = false
let isAndroid = false
let BluetoothAdapterStateChangeCallback = () => { }
let BLEConnectionStateChangeCallback = () => { }
let DeviceId = ''
let GattServerUUID = ''
const GattServerUUIDOption1 = '0000FFF0-0000-1000-8000-00805F9B34FB'
const GattServerUUIDOption2 = 'FFF0'
let GattCharacteristicWriteUUID = ''
const GattCharacteristicWriteUUIDOption1 = '0000FFF2-0000-1000-8000-00805F9B34FB'
const GattCharacteristicWriteUUIDOption2 = 'FFF2'
const log = data => {
if (logEnable) {
console.log('[eciot]:' + JSON.stringify(data))
}
}
const onBluetoothAdapterStateChange = cb => {
BluetoothAdapterStateChangeCallback = cb
}
const getSetting = () => {
return new Promise(function (resolve, reject) {
my.getSetting({
success(res) {
log(res)
if (res.authSetting && res.authSetting.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.error ? res.error : 30000,
errMsg: res.errorMessage ? res.errorMessage : 'getSetting fail',
})
},
})
})
}
const authorize = async () => {
return await _openBluetoothAdapter()
}
const _openBluetoothAdapter = () => {
return new Promise(function (resolve, reject) {
my.openBluetoothAdapter({
success(res) {
log(res)
if (res.isSupportBLE) {
resolve({ ok: true, errCode: 0, errMsg: '' })
} else {
resolve({ ok: false, errCode: 30001, errMsg: 'isSupportBLE is false' })
}
},
fail(res) {
log(res)
resolve({
ok: false,
errCode: res.error ? res.error : 30000,
errMsg: res.errorMessage,
})
},
})
})
}
const openBluetoothAdapter = async () => {
await _openBluetoothAdapter()
const systemInfo = my.getSystemInfoSync()
log(systemInfo)
if (systemInfo.platform.toLowerCase() === 'android') {
isAndroid = true
}
if (isAndroid && !systemInfo.bluetoothEnabled) {
BluetoothAdapterStateChangeCallback({
ok: false,
errCode: 30001,
errMsg: '请打开系统蓝牙开关',
})
return
}
if (isAndroid && !systemInfo.locationEnabled) {
BluetoothAdapterStateChangeCallback({
ok: false,
errCode: 30002,
errMsg: '请打开系统定位开关',
})
return
}
if (isAndroid && !systemInfo.locationAuthorized) {
BluetoothAdapterStateChangeCallback({
ok: false,
errCode: 30003,
errMsg: '请打开支付宝定位权限,允许支付宝使用您的位置信息',
})
return
}
const setting = await getSetting() //小程序蓝牙权限
if (!setting.ok) {
const authRes = await authorize()
if (!authRes.ok) {
BluetoothAdapterStateChangeCallback({
ok: false,
errCode: 30004,
errMsg: '请打开小程序蓝牙开关,点击右上角三个点,然后点击设置',
})
return
}
}
my.offBluetoothAdapterStateChange()
my.onBluetoothAdapterStateChange(res => {
log(res)
// {"available":false,"discovering":false,"NBPageUrl":"https://2021002131657266.hybrid.alipay-eco.com/index.html#pages/index/index"}
if (!res.available) {
BluetoothAdapterStateChangeCallback({
ok: false,
errCode: 30005,
errMsg: '蓝牙适配器不可用',
})
}
})
const openRes = await _openBluetoothAdapter()
BluetoothAdapterStateChangeCallback(openRes)
}
const onBluetoothDeviceFound = cb => {
my.offBluetoothDeviceFound()
my.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 = () => {
my.startBluetoothDevicesDiscovery({
//services: [ecServerId],
allowDuplicatesKey: true,
// powerLevel: 'high',
complete(res) {
log(res)
},
})
}
const stopBluetoothDevicesDiscovery = () => {
my.stopBluetoothDevicesDiscovery({
complete(res) {
log(res)
},
})
}
const onBLEConnectionStateChange = cb => {
BLEConnectionStateChangeCallback = cb
}
const _createBLEConnection = () => {
return new Promise(function (resolve, reject) {
my.connectBLEDevice({
deviceId: DeviceId,
success(res) {
log(res)
resolve({ ok: true, errCode: 0, errMsg: '' })
},
fail(res) {
log(res)
resolve({
ok: false,
errCode: res.error,
errMsg: res.errorMessage,
})
},
})
})
}
const getBLEDeviceServices = () => {
return new Promise(function (resolve, reject) {
my.getBLEDeviceServices({
deviceId: DeviceId,
success(res) {
log(res)
resolve({
ok: true,
errCode: 0,
errMsg: '',
services: res.services,
})
},
fail(res) {
log(res)
resolve({ ok: false, errCode: res.error, errMsg: res.errorMessage })
},
})
})
}
const getBLEDeviceCharacteristics = serviceId => {
return new Promise(function (resolve, reject) {
my.getBLEDeviceCharacteristics({
deviceId: DeviceId,
serviceId,
success(res) {
log(res)
resolve({
ok: true,
errCode: 0,
errMsg: '',
characteristics: res.characteristics,
})
},
fail(res) {
log(res)
resolve({ ok: false, errCode: res.error, errMsg: res.errorMessage })
},
})
})
}
const notifyBLECharacteristicValueChange = (serviceId, characteristicId) => {
return new Promise(function (resolve, reject) {
my.notifyBLECharacteristicValueChange({
state: true,
deviceId: DeviceId,
serviceId,
characteristicId,
success(res) {
log(res)
resolve({ ok: true, errCode: 0, errMsg: '' })
},
fail(res) {
log(res)
resolve({ ok: false, errCode: res.error, errMsg: res.errorMessage })
},
})
})
}
const setBLEMTU = mtu => {
return new Promise(function (resolve, reject) {
my.setBLEMTU({
deviceId: DeviceId,
mtu,
success(res) {
log(res)
resolve({ ok: true, errCode: 0, errMsg: '' })
},
fail(res) {
log(res)
resolve({ ok: false, errCode: res.error, errMsg: res.errorMessage })
},
})
})
}
const createBLEConnection = async id => {
console.log('创建连接')
DeviceId = id
my.offBLEConnectionStateChanged()
my.onBLEConnectionStateChanged(async res => {
log(res)
// {"deviceId":"EC:22:05:13:78:49","connected":true}
if (res.connected) {
const servicesResult = await getBLEDeviceServices()
if (!servicesResult.ok) {
BLEConnectionStateChangeCallback(servicesResult)
closeBLEConnection()
return
}
for (const service of servicesResult.services) {
if ((service.serviceId.toUpperCase() === GattServerUUIDOption1) ||
(service.serviceId.toUpperCase() === GattServerUUIDOption2)) {
GattServerUUID = service.serviceId
}
const characteristicsResult = await getBLEDeviceCharacteristics(
service.serviceId
)
if (!characteristicsResult.ok) {
BLEConnectionStateChangeCallback(characteristicsResult)
closeBLEConnection()
return
}
for (const characteristic of characteristicsResult.characteristics) {
if (
characteristic.properties &&
characteristic.properties.notify
) {
const notifyResult =
await notifyBLECharacteristicValueChange(
service.serviceId,
characteristic.characteristicId
)
if (!notifyResult.ok) {
BLEConnectionStateChangeCallback({
ok: false,
errCode: 30000,
errMsg: 'notify error',
})
closeBLEConnection()
return
}
}
if ((characteristic.characteristicId.toUpperCase() === GattCharacteristicWriteUUIDOption1) ||
(characteristic.characteristicId.toUpperCase() === GattCharacteristicWriteUUIDOption2)) {
GattCharacteristicWriteUUID = characteristic.characteristicId
}
}
}
if (isAndroid) {
await setBLEMTU(247)
}
BLEConnectionStateChangeCallback({
ok: true,
errCode: 0,
errMsg: '',
})
} else {
BLEConnectionStateChangeCallback({
ok: false,
errCode: 0,
errMsg: 'disconnect',
})
}
})
const res = await _createBLEConnection()
if (!res.ok) {
BLEConnectionStateChangeCallback(res)
}
}
const closeBLEConnection = () => {
my.disconnectBLEDevice({
deviceId: DeviceId,
complete(res) {
log(res)
},
})
}
const onBLECharacteristicValueChange = cb => {
my.offBLECharacteristicValueChange()
my.onBLECharacteristicValueChange(res => {
log(res)
let bytes = []
for (let i = 0; i < (res.value.length / 2); i++) {
bytes.push(parseInt(res.value.substr(i * 2, 2), 16))
}
let str = utf8BytesToStr(bytes)
let strHex = res.value
log(str)
log(strHex)
cb(str, strHex)
})
}
const _writeBLECharacteristicValue = buffer => {
return new Promise(function (resolve, reject) {
my.writeBLECharacteristicValue({
deviceId: DeviceId,
serviceId: GattServerUUID,
characteristicId: GattCharacteristicWriteUUID,
value: buffer,
// writeType: 'writeNoResponse',
success(res) {
log(res)
resolve({ ok: true, errCode: 0, errMsg: '' })
},
fail(res) {
log(res)
resolve({ ok: false, errCode: res.error, errMsg: res.errorMessage })
},
})
})
}
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 & 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,
}
页面引入对应的API文件,然后调用API的方法即可
const BLEApi = require('../../common/utils/BLEUtil/BLEAPI.js')
let _this;
let deviceListData = []
export default {
data() {
return {
deviceListDataShow: []
}
},
onLoad() {
_this = this
setInterval(() => {
_this.deviceListDataShow = JSON.parse(JSON.stringify(deviceListData))
}, 800)
},
onShow() {
setTimeout(() => {
_this.openBluetoothAdapter()
}, 100)
},
methods: {
listViewTap(id){
uni.showLoading('设备连接中')
BLEApi.onBLEConnectionStateChange(res => {
uni.hideLoading()
if (res.ok) {
BLEApi.stopBluetoothDevicesDiscovery()
uni.navigateTo({ url: '../device/device' })
} else {
uni.showModal({
title: '提示',
content: '连接失败,errCode=' + res.errCode + ',errMsg=' + res.errMsg
})
}
})
BLEApi.createBLEConnection(id)
},
openBluetoothAdapter() {
BLEApi.onBluetoothAdapterStateChange(res => {
if (res.ok) {
console.log('Bluetooth adapter ok')
_this.startBluetoothDevicesDiscovery()
} else {
uni.showModal({
title: '提示',
content: `Bluetooth adapter error | ${res.errCode} | ${res.errMsg}`
})
}
})
BLEApi.openBluetoothAdapter()
},
startBluetoothDevicesDiscovery() {
console.log('start search')
BLEApi.onBluetoothDeviceFound(res => {
// if(res.id==="EC:22:05:13:78:49")
// console.log(`id:${res.id},name:${res.name},rssi:${res.rssi}`)
for (const item of deviceListData) {
if (item.id === res.id) {
item.name = res.name
item.rssi = res.rssi
return
}
}
let manufacturer = ''
if (res.name.length === 11 && res.name.startsWith('@')) {
manufacturer = 'eciot'
}
if (res.name.length === 15 && res.name.startsWith('BT_')) {
manufacturer = 'eciot'
}
deviceListData.push({
id: res.id,
name: res.name,
rssi: res.rssi,
manufacturer,
})
})
BLEApi.startBluetoothDevicesDiscovery()
},
}
}
安卓、支付宝、IOS、安卓都可以使用
未开启蓝牙 | 开启蓝牙,蓝牙列表 | 连接蓝牙,收发消息 |
---|---|---|
源码地址:
https://download.csdn.net/download/qq_35921773/88306318