You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

515 lines
12 KiB

const logEnable = false
let isAndroid = false
let ecBluetoothAdapterStateChangeCallback = () => {}
let ecBluetoothDeviceFoundCallback = () => {}
let ecBLEConnectionStateChangeCallback = () => {}
let ecBLECharacteristicValueChangeCallback = () => {}
let ecDeviceId = ''
let ecGattServerUUID = ''
const ecGattServerUUIDOption1 = '0000FFF0-0000-1000-8000-00805F9B34FB'
const ecGattServerUUIDOption2 = 'FFF0'
let ecGattCharacteristicWriteUUID = ''
const ecGattCharacteristicWriteUUIDOption1 = '0000FFF2-0000-1000-8000-00805F9B34FB'
const ecGattCharacteristicWriteUUIDOption2 = 'FFF2'
const log = data => {
if (logEnable) {
console.log('[eciot]:' + JSON.stringify(data))
}
}
const onBluetoothAdapterStateChange = cb => {
ecBluetoothAdapterStateChangeCallback = cb
}
const _openBluetoothAdapter = () => {
return new Promise(function(resolve, reject) {
uni.openBluetoothAdapter({
success(res) {
log(res)
resolve({
ok: true,
errCode: 0,
errMsg: ''
})
},
fail(res) {
log(res)
// {"errMsg":"openBluetoothAdapter:fail not available","code":10001}
resolve({
ok: false,
errCode: res.code,
errMsg: res.errMsg,
})
},
})
})
}
uni.onBluetoothAdapterStateChange(res => {
log(res)
// {"discovering":true,"available":true}
if (!res.available) {
ecBluetoothAdapterStateChangeCallback({
ok: false,
errCode: 30005,
errMsg: '蓝牙适配器不可用',
})
}
})
const openBluetoothAdapter = async () => {
await _openBluetoothAdapter()
const systemInfo = uni.getSystemInfoSync()
log(systemInfo)
if (systemInfo.platform.toLowerCase() === 'android') {
isAndroid = true
}
const systemSetting = uni.getSystemSetting()
log(systemSetting)
const appAuthorizeSetting = uni.getAppAuthorizeSetting()
log(appAuthorizeSetting)
if (!systemSetting.bluetoothEnabled) {
ecBluetoothAdapterStateChangeCallback({
ok: false,
errCode: 30001,
errMsg: '请打开系统蓝牙开关',
})
return
}
if (isAndroid && !systemSetting.locationEnabled) {
ecBluetoothAdapterStateChangeCallback({
ok: false,
errCode: 30002,
errMsg: '请打开系统定位开关',
})
return
}
if (isAndroid && (appAuthorizeSetting.locationAuthorized!=='authorized')) {
ecBluetoothAdapterStateChangeCallback({
ok: false,
errCode: 30003,
errMsg: '请打开应用定位权限,允许应用使用您的位置信息',
})
return
}
const openRes = await _openBluetoothAdapter()
ecBluetoothAdapterStateChangeCallback(openRes)
}
uni.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
ecBluetoothDeviceFoundCallback({
id,
name,
rssi
})
})
const onBluetoothDeviceFound = cb => {
ecBluetoothDeviceFoundCallback = cb
}
const startBluetoothDevicesDiscovery = () => {
uni.startBluetoothDevicesDiscovery({
//services: [ecServerId],
allowDuplicatesKey: true,
// powerLevel: 'high',
complete(res) {
log(res)
},
})
}
const stopBluetoothDevicesDiscovery = () => {
uni.stopBluetoothDevicesDiscovery({
complete(res) {
log(res)
},
})
}
const onBLEConnectionStateChange = cb => {
ecBLEConnectionStateChangeCallback = cb
}
const _createBLEConnection = () => {
return new Promise(function(resolve, reject) {
uni.createBLEConnection({
deviceId: ecDeviceId,
success(res) {
log(res)
resolve({
ok: true,
errCode: 0,
errMsg: ''
})
},
fail(res) {
log(res)
resolve({
ok: false,
errCode: res.code,
errMsg: res.errMsg,
})
},
})
})
}
const getBLEDeviceServices = () => {
return new Promise(function(resolve, reject) {
setTimeout(()=>{
uni.getBLEDeviceServices({
deviceId: ecDeviceId,
success(res) {
log(res)
resolve({
ok: true,
errCode: 0,
errMsg: '',
services: res.services,
})
},
fail(res) {
log(res)
resolve({
ok: false,
errCode: res.code,
errMsg: res.errMsg
})
},
})
},800)
})
}
const getBLEDeviceCharacteristics = serviceId => {
return new Promise(function(resolve, reject) {
uni.getBLEDeviceCharacteristics({
deviceId: ecDeviceId,
serviceId,
success(res) {
log(res)
resolve({
ok: true,
errCode: 0,
errMsg: '',
characteristics: res.characteristics,
})
},
fail(res) {
log(res)
resolve({
ok: false,
errCode: res.code,
errMsg: res.errMsg
})
},
})
})
}
const notifyBLECharacteristicValueChange = (serviceId, characteristicId) => {
return new Promise(function(resolve, reject) {
uni.notifyBLECharacteristicValueChange({
state: true,
deviceId: ecDeviceId,
serviceId,
characteristicId,
success(res) {
log(res)
resolve({
ok: true,
errCode: 0,
errMsg: ''
})
},
fail(res) {
log(res)
resolve({
ok: false,
errCode: res.code,
errMsg: res.errMsg
})
},
})
})
}
const setBLEMTU = mtu => {
return new Promise(function(resolve, reject) {
setTimeout(()=>{
uni.setBLEMTU({
deviceId: ecDeviceId,
mtu,
success(res) {
log(res)
resolve({
ok: true,
errCode: 0,
errMsg: ''
})
},
fail(res) {
log(res)
resolve({
ok: false,
errCode: res.code,
errMsg: res.errMsg
})
},
})
},500)
})
}
uni.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
}
for (const service of servicesResult.services) {
if ((service.uuid.toUpperCase() === ecGattServerUUIDOption1) ||
(service.uuid.toUpperCase() === ecGattServerUUIDOption2)) {
ecGattServerUUID = service.uuid
}
const characteristicsResult = await getBLEDeviceCharacteristics(
service.uuid
)
if (!characteristicsResult.ok) {
ecBLEConnectionStateChangeCallback(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) {
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 createBLEConnection = async id => {
ecDeviceId = id
const res = await _createBLEConnection()
if (!res.ok) {
ecBLEConnectionStateChangeCallback(res)
}
}
const closeBLEConnection = () => {
uni.closeBLEConnection({
deviceId: ecDeviceId,
})
}
uni.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)
ecBLECharacteristicValueChangeCallback(str, strHex)
})
const onBLECharacteristicValueChange = cb => {
ecBLECharacteristicValueChangeCallback = cb
}
const _writeBLECharacteristicValue = buffer => {
return new Promise(function(resolve, reject) {
uni.writeBLECharacteristicValue({
deviceId: ecDeviceId,
serviceId: ecGattServerUUID,
characteristicId: ecGattCharacteristicWriteUUID,
value: buffer,
// writeType: 'writeNoResponse',
success(res) {
log(res)
resolve({
ok: true,
errCode: 0,
errMsg: ''
})
},
fail(res) {
log(res)
resolve({
ok: false,
errCode: res.code,
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
}
export default {
onBluetoothAdapterStateChange,
openBluetoothAdapter,
onBluetoothDeviceFound,
startBluetoothDevicesDiscovery,
stopBluetoothDevicesDiscovery,
onBLEConnectionStateChange,
createBLEConnection,
closeBLEConnection,
onBLECharacteristicValueChange,
writeBLECharacteristicValue,
}