const event = require('./event'); const penDataHandle = require('./penDataHandle'); const utils = require('./utils'); let is130 = false let battreySuccess = null let batteryFail = null let lowPower = null let getBatteryFlag = false let isOid4B = false let listenFlag = null let serviceFlag = null let initFlag = null class AllSDK { /** * * @param {number} platForm */ constructor(platForm) { // 离线接收进行量 this.gofflineDataProgress = 0 // 离线数据量 this.offlineDataNum = 0 // 进度 this.gefflineCounter = 0 // 已连接蓝牙deviceId this.connectDeviceId = null // 已连接serviceid this.connectServiceId = null // 已连接characteristicId this.connectCharacteristicId = null this.finishFlag = false this.allDevices = {} this.allDevices.foundDevices = [] this.blueToothOn = false // 日志文件储存flag this.saveDataFlag = false // 不同的平台将平台全局变量传入 switch (platForm) { // 微信小程序 case 0: this.platForm = wx // 此处储存日志,储存日志功能现在仅限于微信小程序 this.fs = wx.getFileSystemManager() this.fileName = `${wx.env.USER_DATA_PATH}/tqlData-${Date.now()}.txt` this.fs.writeFile({ filePath: this.fileName, encoding: "utf-8", success: () => { console.log('writeFileSuccess'); }, fail: () => { console.log('writeFileFail'); } }) break; // 钉钉小程序 case 1: this.platForm = dd break; // 飞书小程序 case 2: this.platForm = tt break; // uniApp case 3: this.platForm = uni break; default: break; } this.platFormFlag = platForm // 读取本地文件flag this.readLocalTxtFlag = false // 获取离线数据flag this.getOfflineDataFlag = false event.on('130', this, data => { console.log('130', data); is130 = data }) event.on('getBatteryFlag', this, data => { console.log('getBatteryFlag', data); getBatteryFlag = data }) event.on('penBattery', this, data => { console.log(data, 'penBattery'); if (data) { this.startGetOfflineData(battreySuccess, batteryFail) } else { getBatteryFlag = false // 低电量方法 if (lowPower) { lowPower(); } } }) // 2022-7-14 chende 笔类型OID this.penType = null this.penOID = null } // 监听本地蓝牙状态改变 /** * * @param {Function} blueToothON */ listenBlueState(blueToothON) { this.platForm.onBluetoothAdapterStateChange((res) => { if (res.available) { // 在本地蓝牙开启之后 关闭本地蓝牙状态监听 if (this.platForm.offBluetoothAdapterStateChange) { this.platForm.offBluetoothAdapterStateChange() } if (blueToothON) { blueToothON() } } }) } // 蓝牙错误码 static BLUETOOTH_ERRORCODE = new Map([ [0, '正常'], [-1, '已连接'], [10000, '未初始化蓝牙适配器'], [10001, '当前蓝牙适配器不可用'], [10002, '没有找到指定设备'], [10003, '连接失败'], [10004, '没有找到指定服务'], [10005, '没有找到指定特征'], [10006, '当前连接已断开'], [10007, '当前特征不支持此操作'], [10008, '其余所有系统上报的异常正常'], [10009, 'Android 系统特有,系统版本低于 4.3 不支持 BLE'], [10012, '连接超时'], [10013, '连接 deviceId 为空或者是格式不正确'], ]) // iOS下提示 static IOS_FAIL_STATE = new Map([ [0, '未知'], [1, '重置中'], [2, '不支持'], [3, '未授权'], [4, '未开启'], ]) /** * @param {Function} success * @param {Function} fail * @returns {void} */ // 初始化蓝牙模块 initBlueTooth(success, fail) { this.platForm.openBluetoothAdapter({ success: () => { if (success) { success(); } }, fail: (e) => { console.log(e) if (fail) { const { state, errCode, errMsg } = e let msg = errMsg if (state === 3) { msg = '系统蓝牙未授权' } fail({ msg }); } } }) } // 读取本地蓝牙适配器状态信息 getLocalBlueToothState() { } // 监听蓝牙连接设备断开 listenBlueConnection() { // 监听之前先移除已有的监听事件 防止同一事件多次监听 if (this.platForm.offBLEConnectionStateChange) { this.platForm.offBLEConnectionStateChange(); } this.platForm.onBLEConnectionStateChange(res => { if (this.connectDeviceId === res.deviceId && !res.connected) { event.emit('unConnect', true) } }); } // 搜索附近的蓝牙设备 /** * @param {Function} success * @param {Function} fail * @returns {void } */ searchBlueTooth(success, fail) { // console.log(success) this.platForm.startBluetoothDevicesDiscovery({ allowDuplicatesKey: true, success: (res) => { if (success) { success() } }, fail: (res) => { if (fail) { fail() } }, complete: (res) => { console.log(res) } }) } // 停止搜索附近蓝牙设备 stopBlueToothSearch(success, fail) { this.platForm.stopBluetoothDevicesDiscovery({ success: () => { if (success) { this.showBlueToothList() success() } }, fail: () => { if (fail) { fail() } } }) } // 查找到的设备列表 showBlueToothList() { let flag = true this.platForm.onBluetoothDeviceFound(res => { if (res) { res.devices.forEach(device => { // 此处钉钉advertisData为hexstring 飞书 uni 微信为arrayBuffer let penCheck = null if (this.platFormFlag === 1) { if (!device.advertisData) { return } let arrayData = hexToArray(device.advertisData) penCheck = ab2hex(arrayData) } else { penCheck = ab2hex(device.advertisData) } if (penCheck.length < 10) { return } if (penCheck.slice(0, 4).join(":").toUpperCase() !== '31:32:33:34') { return } device.macAddress = penCheck.slice(4, 10).reverse().join(':').toUpperCase(); if (this.allDevices.foundDevices.length !== 0) { flag = this.allDevices.foundDevices.every((item, index) => { return item.deviceId !== device.deviceId }) } if (flag) { this.allDevices.foundDevices.push(device) } }) } // 此处做出修改 不同平台之间的赋值方式不同 统一为event发送 event.emit('foundDevices', this.allDevices) }) } // 释放蓝牙 closeBlueTooth(success, fail) { this.platForm.closeBluetoothAdapter({ success: () => { if (success) { success(); } }, fail: () => { if (fail) { fail(); } } }) } // 创建蓝牙连接 createBlueToothConnection(deviceId, success, fail) { this.stopBlueToothSearch(() => { console.log('stopSearch'); }) switch (this.platFormFlag) { // uniapp case 3: // 微信小程序创建连接 case 0: this.platForm.createBLEConnection({ deviceId, success: () => { // 连接成功默认关闭蓝牙搜索 // this.stopBlueToothSearch(() => { // console.log('stopBlueToothDiscovery'); // }) // 此处监听蓝牙断开 setTimeout(() => { this.listenBlueConnection() }, 500); if (success) { success(); } }, fail: () => { if (fail) { fail(); } } }) break // 钉钉小程序 case 1: // 飞书小程序 case 2: this.platForm.connectBLEDevice({ deviceId, success: () => { // 连接成功默认关闭蓝牙搜索 this.stopBlueToothSearch(() => { console.log('stopBlueToothDiscovery'); }) // 此处监听蓝牙断开 setTimeout(() => { this.listenBlueConnection() }, 500) if (success) { success(); } }, fail: () => { if (fail) { fail(); } } }) break default: break; } } // 断开蓝牙连接 unConnectBlueTooth(deviceId, success, fail) { switch (this.platFormFlag) { // uniapp case 3: // 微信小程序 case 0: this.platForm.closeBLEConnection({ deviceId, success: () => { if (success) { success(); } setTimeout(() => { if (this.platForm.offBLECharacteristicValueChange) { this.platForm.offBLECharacteristicValueChange(res => { console.log(res); }) } }, 500) }, fail: () => { if (fail) { fail(); } } }) break // 钉钉小程序 case 1: // 飞书小程序 case 2: this.platForm.disconnectBLEDevice({ deviceId, success: () => { if (success) { success() } }, fail: () => { if (fail) { fail() } } }) break default: break } } // chende add 2022-8-8 // 0-微信 / 1-钉钉 / 2-飞书 / 3-uniapp static SERVICE_ID = ['0000F100-0000-1000-8000-00805F9B34FB', '0000FFF0-0000-1000-8000-00805F9B34FB', '0000F200-0000-1000-8000-00805F9B34FB'] static SERVICE_ID_KEY = (platForm) => ['uuid', 'serviceId', 'serviceId', 'uuid'][platForm] // 获取蓝牙设备服务 getBlueToothService(deviceId, success, fail) { this.platForm.getBLEDeviceServices({ deviceId, success: async (res) => { // console.log(res) // 获取主服务的所有特征值 // 获取蓝牙设备服务不同平台属性不一样 // 飞书 钉钉为serviceId 而微信小程序 uniapp为 uuid // 并且此处因为不用平台的底层实现不一样 必须有sleep才能进行 if (serviceFlag) { clearTimeout(serviceFlag) } serviceFlag = setTimeout(async () => { // chende fix 2022-8-8 const serviceIdKey = AllSDK.SERVICE_ID_KEY(this.platFormFlag) let length = res.services.length for (let i = 0; i < length; i++) { const serviceId = res.services[i][serviceIdKey] if (AllSDK.SERVICE_ID.includes(serviceId)) { this.getBlueToothCharaceristics(deviceId, serviceId) await sleep(100) } } // switch (this.platFormFlag) { // // 微信小程序 // case 0: // // uniapp // case 3: // let length = res.services.length // for (let i = 0; i < length; i++) { // console.log('getService'); // this.getBlueToothCharaceristics(deviceId, res.services[i].uuid) // await sleep(100) // } // break // // 钉钉小程序 // case 1: // // 飞书小程序 // case 2: // let serviceLength = res.services.length // for (let i = 0; i < serviceLength; i++) { // this.getBlueToothCharaceristics(deviceId, res.services[i].serviceId) // await sleep(100) // } // break // default: // break // } }, 500) if (success) { success() } }, fail: (error) => { console.error('getBlueToothService', error) if (fail) { fail() } } }) } // chende add 2022-8-8 // 0-微信 / 1-钉钉 / 2-飞书 / 3-uniapp static UUID_KEY = (platForm) => ['uuid', 'characteristicId', 'characteristicId', 'uuid'][platForm] // 获取蓝牙设备的某个服务的所有特征值 // 此处不同平台的属性值不一样 微信小程序 uniapp 为uuid 而飞书 钉钉为 characteristicId // 服务特征值不同平台不一样 微信为 uuid 飞书为characteristicsId // 防抖 getBlueToothCharaceristics(deviceId, serviceId) { this.platForm.getBLEDeviceCharacteristics({ deviceId, serviceId, success: (res) => { // chende fix 2022-8-8 const uuidKey = AllSDK.UUID_KEY(this.platFormFlag) res.characteristics.forEach((item) => { const uuid = item[uuidKey] if (item.properties.notify || item.properties.indicate) { this.platForm.notifyBLECharacteristicValueChange({ state: true, deviceId, serviceId, characteristicId: uuid, success: (res) => console.log(`监听特征值:${uuid}`) }) } //向蓝牙写数据 //此处不同的平台有不同的属性值 需要区别处理 if (item.properties.write && item.uuid.toUpperCase() == '0000F102-0000-1000-8000-00805F9B34FB') { this.connectDeviceId = deviceId this.connectServiceId = serviceId this.connectCharacteristicId = uuid } }) // 此处开始监听数据 if (listenFlag) { clearTimeout(listenFlag) } listenFlag = setTimeout(() => { this.listenValueChange() event.emit('blueToothConnect', true) }, 2000) if (initFlag) { clearTimeout(initFlag) } initFlag = setTimeout(() => { // 此处获取笔的类型 this.getPenModal(); this.getValue() // 初始化笔的时间 this.setRTCTime(new Date().getTime()) }, 2100); // switch (this.platFormFlag) { // // 微信小程序 // case 0: // // uniapp // case 3: // res.characteristics.forEach(item => { // if (item.properties.notify || item.properties.indicate) { // this.platForm.notifyBLECharacteristicValueChange({ // state: true, // deviceId, // serviceId, // characteristicId: item.uuid, // success: (res) => { // console.log('notifyBLECharacteristicValueChange success------: ' + res.errMsg) // } // }) // } // //向蓝牙写数据 // //此处不同的平台有不同的属性值 需要区别处理 // if (item.properties.write && item.uuid.toUpperCase() == '0000F102-0000-1000-8000-00805F9B34FB') { // this.connectDeviceId = deviceId // this.connectServiceId = serviceId // this.connectCharacteristicId = item.uuid // } // // 此处开始监听数据 // if (listenFlag) { // clearTimeout(listenFlag) // } // listenFlag = setTimeout(() => { // this.listenValueChange() // event.emit('blueToothConnect', true) // }, 1000) // }) // break // // 钉钉小程序 // case 1: // // 飞书小程序 // case 2: // res.characteristics.forEach((item) => { // if (item.properties.notify || item.properties.indicate) { // this.platForm.notifyBLECharacteristicValueChange({ // state: true, // deviceId, // serviceId, // characteristicId: item.characteristicId, // success: (res) => { // console.log('notifyBLECharacteristicValueChange success------: ' + res) // } // }) // } // // 向蓝牙写数据 // if (item.properties.write && item.characteristicId.toUpperCase() === '0000F102-0000-1000-8000-00805F9B34FB') { // console.log('向蓝牙写数据') // this.connectDeviceId = deviceId // this.connectServiceId = serviceId // this.connectCharacteristicId = item.characteristicId // // console.log(deviceId,serviceId,item.characteristicId) // } // // 此处开始监听数据 // if (listenFlag) { // clearTimeout(listenFlag) // } // listenFlag = setTimeout(() => { // this.listenValueChange() // event.emit('blueToothConnect', true) // }, 1000) // }) // break // default: // break // } // if (initFlag) { // clearTimeout(initFlag) // } // initFlag = setTimeout(() => { // // 此处获取笔的类型 // this.getPenModal(); // this.getValue() // // 初始化笔的时间 // this.setRTCTime(new Date().getTime()) // }, 1000); }, fail: (error) => { console.error('getBlueToothCharaceristics', error) } }) } // 监听 第一时间处理数据 listenValueChange() { // 有些平台可能会没有这个api if (this.platForm.offBLECharacteristicValueChange) { this.platForm.offBLECharacteristicValueChange() } this.platForm.onBLECharacteristicValueChange(characteristic => { switch (characteristic.characteristicId.toUpperCase()) { // 实时数据 // 此处飞书 格式为hexstring uniapp为arrayBuffer 钉钉也是hexstring 微信小程序为arraybuffer case '0000FFF1-0000-1000-8000-00805F9B34FB': // 接收离线数据或者读取本地文件时停止接收实时数据 if (this.readLocalTxtFlag) { return } // 微信与uniapp if (this.platFormFlag === 0 || this.platFormFlag === 3) { let dataArr = ab2hex(characteristic.value) let dataLength = dataArr.length / 10 // console.log(dataArr); for (let i = 0; i < dataLength; i++) { penDataHandle.splitData(hex2Bytes(dataArr.slice(i * 10, (i + 1) * 10))) // 微信存日志 if (this.saveDataFlag && this.platFormFlag === 0) { this.fs.appendFileSync(this.fileName, (dataArr.slice(i * 10, (i + 1) * 10)).join(" ") + '\n', 'utf-8') } } // 飞书与钉钉 } else { let buffer = hexToArray(characteristic.value) let dataArr1 = ab2hex(buffer) let dataLength = dataArr1.length / 10 for (let i = 0; i < dataLength; i++) { penDataHandle.splitData(hex2Bytes(dataArr1.slice(i * 10, (i + 1) * 10))) } } break // 离线数据 case '0000F202-0000-1000-8000-00805F9B34FB': //微信与uniapp if (this.platFormFlag === 0 || this.platFormFlag === 3) { let dataArray = ab2hex(characteristic.value) //此处转换后的数据格式为['e1','08',....] // console.log(dataArray); let dataLength1 = dataArray.length / 10 for (let i = 0; i < dataLength1; i++) { let newArr = dataArray.slice(i * 10, (i + 1) * 10); // 离线数据 if (newArr[0] === 'e1' && newArr[1] === '08') { const oid4CodeValue = parseInt(newArr.slice(2).join(""), 16) const index = oid4CodeValue >> 10 const newIndex = index % 65536 let SA = Math.floor((index / 65536 / 256 / 256 / 256) % 256) let SB = Math.floor((index / 65536 / 256 / 256) % 256) let SC = Math.floor((index / 65536 / 256) % 256) let SD = Math.floor((index / 65536) % 256) emitData({ cmd: 'offlineOID4codeValue', data: `${SA}-${SB}-${SC}-${SD}-${newIndex}` }) console.log(`sa:${SA},sb:${SB}sc:${SC}sd:${SD}index:${newIndex}`) // 此处计数 this.gofflineDataProgress += 1 if (!(this.gofflineDataProgress % 50)) { event.emit('offlineGross', this.gofflineDataProgress) } // console.log(this.offlineDataNum,this.gofflineDataProgress); // if (this.offlineDataNum === this.gofflineDataProgress) { // setTimeout(() => { // this.gofflineDataProgress = 0 // this.getOfflineDataFlag = false // event.emit('offlineDataFinish', true) // }, 2000) // } } else { let arr = hex2Bytes(newArr) penDataHandle.splitData(arr, false) // 此处计数 this.gofflineDataProgress += 1 if (!(this.gofflineDataProgress % 50)) { event.emit('offlineGross', this.gofflineDataProgress) } // console.log(this.offlineDataNum,this.gofflineDataProgress); // if (this.offlineDataNum === this.gofflineDataProgress) { // setTimeout(() => { // this.gofflineDataProgress = 0 // this.getOfflineDataFlag = false // event.emit('offlineDataFinish', true) // }, 2000) // } } // console.log(this.offlineDataNum, this.gofflineDataProgress); } } else { // 飞书与钉钉 let buffer1 = hexToArray(characteristic.value); let dataArray1 = ab2hex(buffer1) let dataLength2 = dataArray1.length / 10 for (let i = 0; i < dataLength2; i++) { let newArr = dataArray1.slice(i * 10, (i + 1) * 10) let arr1 = hex2Bytes(newArr) penDataHandle.splitData(arr1, false) } } break // 属性列表 case "0000F101-0000-1000-8000-00805F9B34FB": // 微信与uniapp if (this.platFormFlag === 0 || this.platFormFlag === 3) { let dataArr1 = ab2hex(characteristic.value) let arr1 = hex2Bytes(dataArr1) getDataInfo(arr1, this) } else { // 钉钉与飞书 let buffer2 = hexToArray(characteristic.value) let dataArray2 = ab2hex(buffer2) let arr2 = hex2Bytes(dataArray2) getDataInfo(arr2, this) } break default: break } }) } // 发送指令封装 dealData(index, arrData, success, fail) { let buffer = new ArrayBuffer(index) let bufferView = new DataView(buffer) for (let i = 0; i < index; i++) { bufferView.setUint8(i, arrData[i]) } // 发送指令是不同的平台有不同的格式 // 微信小程序与uniapp为buffer 飞书和钉钉为hexstring switch (this.platFormFlag) { // 微信小程序 case 0: // uniapp case 3: this.platForm.writeBLECharacteristicValue({ characteristicId: this.connectCharacteristicId, serviceId: this.connectServiceId, deviceId: this.connectDeviceId, value: buffer, success: (res) => { if (success) { success(); } }, fail: (err) => { if (fail) { fail(); } } }) break; // 钉钉 case 1: // 飞书 case 2: // console.log(buffer) let dataHex = buf2hex(buffer) this.platForm.writeBLECharacteristicValue({ characteristicId: this.connectCharacteristicId, serviceId: this.connectServiceId, deviceId: this.connectDeviceId, value: dataHex, success: () => { if (success) { success() } }, fail: () => { if (fail) { fail(); } } }) break; default: break; } // let dataHex = buf2hex(buffer) // this.platForm.writeBLECharacteristicValue({ // characteristicId: this.connectCharacteristicId, // serviceId: this.connectServiceId, // deviceId: this.connectDeviceId, // value: dataHex, // success: () => { // success(); // }, // fail: () => { // fail(); // } // }) } // 写入笔名 /** * * @param {string} penName * @param {Function} success * @param {Function} fail */ setPenName(penName, success, fail) { let strBytesArr = strToUtf8(penName); let byteLength = strBytesArr.length; let offLineBuffer = new ArrayBuffer(byteLength + 2); let DataViews = new DataView(offLineBuffer); DataViews.setUint8(0, 0xA2); DataViews.setUint8(1, byteLength); for (let i = 0; i < byteLength; i++) { DataViews.setUint8(i + 2, strBytesArr[i]) } if (this.platFormFlag === 0 || this.platFormFlag === 3) { this.platForm.writeBLECharacteristicValue({ characteristicId: this.connectCharacteristicId, serviceId: this.connectServiceId, deviceId: this.connectDeviceId, value: offLineBuffer, success: () => { if (success) { success(); } }, fail: () => { if (fail) { fail(); } } }) } else { let hexStr = buf2hex(offLineBuffer) this.platForm.writeBLECharacteristicValue({ characteristicId: this.connectCharacteristicId, serviceId: this.connectServiceId, deviceId: this.connectDeviceId, value: hexStr, success: () => { if (success) { success(); } }, fail: () => { if (fail) { fail(); } } }) } } // 请求笔名 getPenName(success, fail) { this.dealData(3, [0xa0, 0x01, 0xff], success, fail) } // 获取MAC地址 getMACAddress(success, fail) { this.dealData(3, [164, 1, 255], success, fail) } // 获取蓝牙固件版本 getPenFirmWare(success, fail) { this.dealData(3, [0xa6, 0x01, 0xff], success, fail) } // 获取剩余电量 getPenBattery(success, fail) { this.dealData(3, [0xa8, 0x01, 0xff], success, fail) } // 写入rtc时间 // 传入时间为想改写时间的时间戳 /** * * @param {number} RTCTime * @param {Function} success * @param {Function} fail */ setRTCTime(RTCTime, success, fail) { let timeStamp = (RTCTime - 1262275200000) / 1000; // console.log(timeStamp, 'timestamp') this.dealData(6, [0xac, 0x04, timeStamp & 0xff, (timeStamp >> 8) & 0xff, (timeStamp >> 16) & 0xff, (timeStamp >> 24) & 0xff], success, fail); } // 请求rtc时间 getRTCTime(success, fail) { this.dealData(3, [0xaa, 0x01, 0xff], success, fail) } // 写入自动关机时间 /** * * @param {number} offTime * @param {Function} success * @param {Function} fail */ setPenAutoOff(offTime, success, fail) { if (offTime > 120 || offTime < 0) { return console.error('自动关机时间的范围为0~120') } this.dealData(4, [0xb2, 0x02, offTime % 256, offTime / 256], success, fail) } // 请求自动关机时间 getPenAutoOff(success, fail) { this.dealData(3, [0xb0, 0x01, 0xff], success, fail) } // 获取已使用内存 getPenMemory(success, fail) { this.dealData(3, [0xb6, 0x01, 0xff], success, fail) } // 获取是否点笔开机 getPenClickMode(success, fail) { this.dealData(3, [0xb8, 0x01, 0xff], success, fail) } // 设置点笔开机 /** * * @param {boolean} isClick * @param {Function} success * @param {Function} fail */ setPenClickMode(isClick, success, fail) { this.dealData(3, [0xba, 0x01, isClick ? 0x01 : 0x00], success, fail) } // 设置是否蜂鸣 /** * * @param {boolean} isOn * @param {Function} success * @param {Function} fail */ setPenBeep(isOn, success, fail) { this.dealData(3, [0xbe, 0x01, isOn ? 0x01 : 0x00], success, fail) } // 获取是否蜂鸣 getPenBeep(success, fail) { this.dealData(3, [0xbc, 0x01, 0xff], success, fail) } // 恢复出厂设置 restoreFactory(success, fail) { this.dealData(3, [0xb4, 0x01, 0xff, success, fail]) } // 写入压力敏感度 /** * * @param {number} level * @param {Function} success * @param {Function} fail */ setPenSensor(level, success, fail) { this.dealData(3, [0xd2, 0x01, level], success, fail) } // 获取压力敏感度 getPenSensor(success, fail) { this.dealData(3, [0xd0, 0x01, 0xff], success, fail) } // 设置LED灯颜色 setPenLedColor(color, success, fail) { this.dealData(3, [0xd6, 0x01, color], success, fail) } // 获取led颜色 getPenLedColor(success, fail) { this.dealData(3, [0xd4, 0x01, 0xff], success, fail) } // 获取压力校正值 getPenSensorRegulate(success, fail) { this.dealData(3, [0xd8, 0x01, 0xff], success, fail) } // 获取mcu固件版本 getMCUVersion(success, fail) { this.dealData(3, [0xda, 0x01, 0xff], success, fail) } // 获取笔的类型 getPenModal(success, fail) { this.dealData(3, [0xe4, 0x01, 0xff], success, fail) } // 获取点码类型 getPenPointType(success, fail) { this.dealData(3, [0xe6, 0x01, 0xff], success, fail) } // led设置开关 /** * * @param {boolean} isOn * @param {Function} success * @param {Function} fail */ setLedConfig(isOn, success, fail) { this.dealData(3, [0xee, 0x01, isOn ? 0x01 : 0x00], success, fail) } // 获取led是够可以设置的结果 getLedConfig(success, fail) { this.dealData(3, [0xec, 0x01, 0xff], success, fail) } // 获取离线数据量大小 getPenOfflineDataSize(success, fail) { this.dealData(3, [0xc0, 0x01, 0xff], success, fail) } // 开始获得离线数据 /** * * @param {Function} success * @param {Function} fail * @param {Function} lowPower */ startGetOfflineData(success, fail, lowPower) { battreySuccess = success batteryFail = fail lowPower = lowPower if (is130 && !getBatteryFlag) { event.emit('getBatteryFlag', true) this.getPenBattery(); return } event.emit('getBatteryFlag', false) this.dealData(3, [0xc2, 0x01, 0x00], success, fail) } // 停止获得离线数据 stopGetOfflineData(success, fail) { this.dealData(3, [0xc2, 0x01, 0x01], success, fail) } // 暂停获得离线数据 pauseGetOfflineData(success, fail) { this.dealData(3, [0xcb, 0x01, 0x00], success, fail) } // 继续获得离线数据 continueGetOfflineData(success, fail) { this.dealData(3, [0xcb, 0x01, 0x01], success, fail) } // 删除离线数据 deleteOfflineData(success, fail) { this.dealData(3, [0xc8, 0x01, 0xff], success, fail) } // 确认离线数据已经接受完毕 confirmOfflineDataDone(success, fail) { this.dealData(3, [0xc6, 0x01, this.finishFlag ? 0x00 : 0x01], success, fail) } // 获取客户id getCustomerId(success, fail) { this.dealData(3, [0xDC, 0x01, 0xff], success, fail) } // // 设置客户id // setCustomerId(success,fail){ // } // 获取oid值 getOIDValue(success, fail) { // console.log(0xe0); this.dealData(3, [0xE0, 0x01, 0xff], success, fail) } // 获取笔的镜头值 getValue(suceess, fail) { this.dealData(3, [0xe6, 0x01, 0xff], suceess, fail) } // ota升级 otaUpdate(success, fail) { this.dealData(3, [0xf4, 0x01, 0xff], success, fail) } // 给蓝牙装置发送升级文件 // otaUpdateFile() { // } // 双指令集合 // 读取本厂家参数 getMCUsetting(success, fail) { this.dealData(6, [0x00, 0x08, 0x06, 0x05, 0x01, 0xff], success, fail) } // 设置厂家参数 setMCUsetting(data, success, fail) { console.log(data); let numA = Number(data) >> 8 let numB = Number(data) & 0xff this.dealData(13, [0x00, 0x08, 0x06, 0x04, 8, 0, 0, 0, 0, 0, 0, numA, numB], success, fail) } // 获取压感设置 getPenPressure(success, fail) { this.dealData(6, [0x00, 0x08, 0x06, 0x03, 0x01, 0xff], success, fail) } // 写入压感 setPenPressure() { } // 主动响蜂鸣器 triggerPenBeep(num, interval) { let intervalH = Number(interval) >> 8 let intervalL = Number(interval) & 0xff this.dealData(8, [0x00, 0x08, 0x04, 0x00, 3, Number(num), intervalH, intervalL]) } } // arrayBuffer转16进制字符串数组 /** * * @param {ArrayBufferTypes} buffer */ const ab2hex = (buffer) => { return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)) } // hex to bytes /** * * @param {Array} arr */ const hex2Bytes = (arr) => { return arr.map((item) => { return parseInt(item, 16) }) } /** * @param {Array} lpData * @param {object} doneFlag */ const getDataInfo = (lpData, doneFlag) => { // console.log('笔数据-', lpData, lpData.map(i => i.toString(16))) const data = {}; let len = 0; let val = lpData.slice(2, len + 2); // 双指令接收 if (lpData[0] === 0x00 && lpData[1] === 0x08) { // 接收通知蜂鸣器鸣叫 if (lpData[2] === 0x04 && lpData[3] === 0x00) { emitData({ data: lpData[5] ? false : true, cmd: 'penBeepSuccess' }) } // 读取无效码设置 if (lpData[2] === 0x06 && lpData[3] === 0x05) { let newArray = lpData.slice(-2) console.log(newArray); let num = (newArray[0] << 8) + newArray[1] console.log(num); emitData({ data: num, cmd: 'getInvalidSetting' }) } //设置无效码返回值 if (lpData[2] === 0x06 && lpData[3] === 0x04) { console.log(lpData); emitData({ data: lpData[5] ? false : true, cmd: "setInvalidSetting" }) } // 读取MCU配置 if (lpData[2] === 0x06 && lpData[3] === 0x03) { } // 设置MCU配置返回值 if (lpData[2] === 0x06 && lpData[3] === 0x02) { } // 读取是否开启偏移 if (lpData[2] === 0x06 && lpData[3] === 0x01) { } // 偏移开启成功失败 if (lpData[2] === 0x06 && lpData[3] === 0x00) { emitData({ data: lpData[5] ? false : true, cmd: 'penDeviation' }) } // 监听无效码上报 if (lpData[2] === 0x05 && lpData[3] === 0x00) { emitData({ cmd: 'invalidCode', data: true }) } } switch (lpData[0]) { case 0xE7: { doneFlag.penOID = lpData[2] switch (lpData[2]) { case 0x00: //OID3 event.emit('isOffset', { offset: true, codeType: 12 }) break; case 0x01: //OID4 event.emit('isOffset', { offset: true, codeType: 12 }) break; case 0x02: //2021.05.18 增加新的点类型 用来确定角度修正值 //OID_A event.emit('isOffset', { offset: true, codeType: 12 }) break; case 0x12: //2021.09.08 增加009镜头是否做了偏移判断 //OID_B //009 down去掉 第一个move点变成down点 event.emit('isOffset', { offset: false, codeType: 12 }) break; case 0x03: //12x12 需要SDK内部修偏移 event.emit('isOffset', { offset: true, codeType: 12 }) //OID4_A break; case 0x13: //12x12 不需要内部修偏移 event.emit('isOffset', { offset: false, codeType: 12 }) //OID4_B break; case 0x23: //16x16 需要SDK内部修偏移 //OID4_A event.emit('isOffset', { offset: true, codeType: 12 }) break; case 0x33: //16x16 不需要SDK内部修偏移 //OID4_B event.emit('isOffset', { offset: false, codeType: 16 }) break; default: break; } break; } case 0xa1: len = lpData[1] & 0xff; val = byteToString(lpData.slice(2, len + 2)); emitData({ data: val, cmd: 'getPenName' }) break; case 0xa3: if (lpData[2] === 0x00) { emitData({ cmd: 'setPenName', data: true }) } else { emitData({ cmd: 'setPenName', data: false }) } break case 0xa5: let macAddress = lpData.slice(2, lpData.length).map((item) => { return MAC(item) }).join(':') emitData({ cmd: 'getMacAddress', data: macAddress }) break; case 0xa7: let res = byteToString(lpData.slice(2, lpData.length)) emitData({ cmd: 'getBlueToothVersion', data: res }) break; // 2021 05 19 添加电量低于10%禁止获取离线数据 case 0xa9: let penBattery = lpData[2] & 0xff; let penIsCharging = lpData[3] === 0x01; if (is130 && getBatteryFlag) { event.emit('penBattery', penBattery > 10) } emitData({ cmd: 'getPenBattery', data: { penBattery: `${penBattery}%`, penIsCharging } }) break; // 获取笔的rtc时间 case 0xab: console.log(lpData); const startTime = 1262275200000; //2010.01.01开始时间戳 let currentTime = (new Date()).getTime(); let mPen_time = (lpData[2] & 0xff) | ((lpData[3] << 8) & 0xff00) | ((lpData[4] << 16) & 0xff0000) | ((lpData[5] << 24) & 0xff000000); console.log(mPen_time * 1000); let timeOffset = (currentTime - startTime) / 1000 let offTimeoff = timeOffset - mPen_time console.log(offTimeoff, '时间差') penDataHandle.changeOffset(offTimeoff); emitData({ cmd: "getRTCtime", data: (mPen_time * 1000 + startTime) }) break; case 0xad: emitData({ cmd: 'setRTCtime', data: lpData[2] === 0x00 }) break; case 0xb1: val = lpData.slice(2, 4); let penAutoShutDown = (val[0] & 0xff) | ((val[1] << 8) & 0xff00) emitData({ cmd: 'getPenAutoShutDownTime', data: penAutoShutDown }) break; case 0xb3: emitData({ cmd: 'setPenAutoOff', data: lpData[2] === 0x00 }) break case 0xb5: emitData({ cmd: 'RestoreFactorySettings', data: lpData[2] === 0x00 }) break case 0xb7: // console.log(lpData[2] & 0xff) emitData({ cmd: 'getUsedMemory', data: lpData[2] & 0xff + '%' }) break; case 0xb9: emitData({ cmd: 'getPenClickMode', data: lpData[2] === 0x01 }) break case 0xbb: emitData({ cmd: 'setPenClickMode', data: lpData[2] === 0x00 }) break case 0xbd: emitData({ cmd: 'getPenBeep', data: lpData[2] === 0x01 }) break case 0xbf: emitData({ cmd: 'setPenBeep', data: lpData[2] === 0x00 }) break case 0xd1: emitData({ cmd: 'getPenSensor', data: lpData[2] & 0xff }) break case 0xd3: emitData({ cmd: "setPenSensor", data: lpData[2] === 0x00 }) break case 0xd5: emitData({ cmd: 'getLEDColor', data: lpData[2] & 0xff }) break; // case 0xd7: // emitData({ // cmd: "setPenSensor", // data: lpData[2] === 0x00 // }) // break case 0xd9: // 压力校正值 // console.log(lpData); let lowSensor = (((lpData[3] << 8) & 0xff00) + (lpData[2] & 0xff)) let highSensor = (((lpData[5] << 8) & 0xff00) + (lpData[4] & 0xff)) // var sensitivityCorrection = "20g:" + (((lpData[3] << 8) & 0xff00) + (lpData[2] & 0xff)) + "300g:" + (((lpData[5] << 8) & 0xff00) + (lpData[4] & 0xff)); // console.log(sensitivityCorrection); emitData({ cmd: "getSensitivityCorrection", data: `${lowSensor}-${highSensor}` }) break; case 0xdb: console.log(lpData, 'MCU'); len = lpData[1] & 0xff; val = lpData.slice(2, len + 2); var isR = lpData[2] & 0xff; var mcu_firmware = ""; if (isR) { mcu_firmware = "MCUF_" + "R" + (lpData[4] & 0xff * 10) + (lpData[5] & 0xff) + (data[6] & 0xff); } else { mcu_firmware = "MCUF_" + "B" + (lpData[4] & 0xff) + (lpData[5] & 0xff) + (lpData[6] & 0xff); } if (lpData[9] === 7 || lpData[9] === 8 || lpData[9] === 9 || lpData[9] === 10) { if (lpData[2] === 1) { mcu_firmware = "V" + (lpData[4] * 10 + lpData[5]) + '.' + (lpData[6] * 10 + lpData[7]) } else { mcu_firmware = 'B' + (lpData[4] * 10 + lpData[5]) + '.' + (lpData[6] * 10 + lpData[7]) } console.log(mcu_firmware); } emitData({ cmd: 'getMCUVersion', data: mcu_firmware }) break; case 0xe1: // console.log(lpData, '点读码值'); let oid4CodeValue = 0 // 离线点读码 if (lpData[1] === 8) { // let arrayData = lpData.slice(8);//[0x18,0x69] // console.log(arrayData); // let value = arrayData[0] >> 2 console.log(lpData); if (lpData.length > 10) { for (let i = 0; i < lpData.length / 10; i++) { let newArr = lpData.slice(i * 10, (i + 1) * 10) let oid4CodeValue = ((newArr[3] * Math.pow(2, 40)) & 0xFF0000000000) | ((newArr[4] * Math.pow(2, 32)) & 0xFF00000000) | ((newArr[5] * Math.pow(2, 24)) & 0xFF000000) | ((newArr[6] * Math.pow(2, 16)) & 0xFF0000) | ((newArr[7] * Math.pow(2, 8)) & 0xFF00) | (newArr[9] & 0xFC) // console.log(oid4CodeValue); oid4CodeValue = oid4CodeValue >> 2 // console.log(oid4CodeValue); let index = oid4CodeValue % 65536 // console.log(index, 'index'); let SA = Math.floor((oid4CodeValue / 65536 / 256 / 256 / 256) % 256) let SB = Math.floor((oid4CodeValue / 65536 / 256 / 256) % 256) let SC = Math.floor((oid4CodeValue / 65536 / 256) % 256) let SD = Math.floor((oid4CodeValue / 65536) % 256) emitData({ cmd: 'offlineOID4codeValue', data: `${SA}-${SB}-${SC}-${SD}-${index}` }) } } } else { // console.log(lpData) let oidFlag = (lpData[2] >> 7 & 0x01); // let index =undefined if (oidFlag == 1) { // oid4 high-coder let n9 = (lpData[2] & 0xf0) >> 4 console.log(n9, 'n9'); if (n9 === 9) { //009 let startPoint = lpData[2] & 0x03 let newArray = [] let dataArray = lpData.slice(3, 9) for (let i = 0; i < dataArray.length; i++) { newArray.push(numToHex(dataArray[i])) } let dataString = startPoint + newArray.join('') // console.log(dataString); dataString = dataString.slice(0, dataString.length - 1) oid4CodeValue = (parseInt(dataString, 16)) // console.log(oid4CodeValue) } else { //005 // console.log(lpData); let oid_a = (lpData[8] << 40); oid_a = numToHex(lpData[8] & 0x3f) // console.log(oid_a, 'oidA'); let oid_b = (lpData[9] << 32); oid_b = numToHex(lpData[9]) let dataArray = lpData.slice(9, 14) let stringArray = [] // console.log(oid_b, 'oidB'); for (let i = 0; i < dataArray.length; i++) { stringArray.push(numToHex(dataArray[i])) } let hexNum = oid_a + stringArray.join('') // console.log(hexNum); oid4CodeValue = parseInt(hexNum, 16) console.log(oid4CodeValue); } } else if (oidFlag == 0) { // oid3 high-coder oid4CodeValue = ((lpData[10] & 0xff) << 24) | (lpData[11] << 16) | (lpData[12] << 8) | (lpData[13]); } else { // console.log("The oidFlag state is : " + oidFlag); } if (oid4CodeValue == 0) { return; } // if ((lpData[2] & 0x10) != 0) { // return;22222222222 // } console.log(oid4CodeValue, 'oidValue'); let index = oid4CodeValue % 65536 console.log(index, 'index'); let SA = Math.floor((oid4CodeValue / 65536 / 256 / 256 / 256) % 256) let SB = Math.floor((oid4CodeValue / 65536 / 256 / 256) % 256) let SC = Math.floor((oid4CodeValue / 65536 / 256) % 256) let SD = Math.floor((oid4CodeValue / 65536) % 256) // console.log(`SA:${SA}/SB:${SB}/SC:${SC}/SD:${SD}/index:${index}`); emitData({ cmd: 'getOID4CodeValue', data: `${SA}-${SB}-${SC}-${SD}-${index}` }) console.log(SA, SB, SC, SD, index) } break; case 0xf0: let penColor = lpData.slice(2, lpData.length); emitData({ cmd: 'penColor', data: penColor }) break; // 读取笔的类型 case 0xe5: doneFlag.penType = lpData[2] switch (lpData[2]) { case 0x00: event.emit('130', false) utils.changeDistanceAndAngle(3.3641, 17) break case 0x01: event.emit('130', false) utils.changeDistanceAndAngle(2.9431, 180); break; case 0x02: event.emit('130', false) utils.changeDistanceAndAngle(2.9431, 180); break case 0x03: event.emit('130', false) utils.changeDistanceAndAngle(4.3841, 17); break; case 0x08: // 此处为只有130的笔才有的输出三个up点 event.emit('130', true) isOid4B ? utils.changeDistanceAndAngle(0.0, 180) : utils.changeDistanceAndAngle(2.8, 180); break; case 0x09: // 此处为只有130的笔才有的输出三个up点 event.emit('130', true) isOid4B ? utils.changeDistanceAndAngle(0.0, 180) : utils.changeDistanceAndAngle(2.8, 180); // utils.changeDistanceAndAngle(2.8, 180) break case 0x10: // 此处为只有130的笔才有的输出三个up点 event.emit('130', true) utils.changeDistanceAndAngle(2.5, 180); break default: break } break // case 0xe7: // switch (lpData[2]) { // case 0: // isOid4B = false // break; // case 1: // isOid4B = false // break // case 2: // isOid4B = false // break // case 18: // isOid4B = true // break // default: // break; // } // // console.log(lpData[2], '笔的标识位'); // break case 0xeb: var mPen_CurrentCodePointType = ""; switch (lpData[2]) { case 0: mPen_CurrentCodePointType = "OID3"; break; case 1: mPen_CurrentCodePointType = "OID4"; break; default: break; } emitData({ cmd: 'getCodePointType', data: mPen_CurrentCodePointType }) break; // 获取离线数据量 case 0xc1: // console.log(0xc1); let offlineDataSize = lpData.slice(2, lpData.length); // console.log(lpData, 'lpdata') let offlineDataNum = parseInt((((offlineDataSize[3] << 24) & 0xff000000) | ((offlineDataSize[2] << 16) & 0xff0000) | ((offlineDataSize[1] << 8) & 0xff00) | (offlineDataSize[0] & 0xff)) / 10); doneFlag.offlineDataNum = offlineDataNum emitData({ cmd: "getOfflineDataNum", data: offlineDataNum }) break; // 开始获取离线数据 case 0xc3: if (lpData[2] === 0x00) { emitData({ cmd: 'startGetOffline', data: true }) } else { emitData({ cmd: "startGetOffline", data: false }) } break case 0xc4: doneFlag.gofflineDataProgress = 0 console.log(doneFlag) emitData({ cmd: 'offLineProgressStop', data: lpData[2] === 0x00 }) break case 0xc5: doneFlag.gofflineDataProgress = 0 doneFlag.getOfflineDataFlag = false event.emit('offlineDataFinish', true) break case 0xcc: emitData({ cmd: "offLineProgressPause", data: lpData[2] === 0x00 }) break case 0xcd: emitData({ cmd: 'offLineProgressContinue', data: lpData[2] === 0x00 }) break case 0xc5: doneFlag.finishFlag = lpData[2] === 0x00 // console.log(doneFlag) setTimeout(() => { emitData({ cmd: 'offLineProgressFinish', data: lpData[2] === 0x00 ? '100%' : false }) // event.emit('finish', true) doneFlag.gofflineDataProgress = 0 }, 1000) break case 0xc7: emitData({ cmd: 'offLineDataConfirm', data: lpData[2] === 0x00 }) break case 0xc9: emitData({ cmd: 'offLineDataDelete', data: lpData[2] === 0x00 }) break case 0xdd: let id1 = (lpData[2] & 0xff) | ((data[3] << 8) & 0xff00) let id2 = (lpData[4] & 0xff) | ((data[5] << 8) & 0xff00) emitData({ cmd: 'customerId', data: `${id1}-${id2}` }) break // ota升级返回值 case 0xf5: break } } // byte数组转字符串 /** * * @param {Array} arr * @returns {string} */ const byteToString = (arr) => { if (typeof arr === 'string') { return arr; } var str = '', _arr = arr; for (var i = 0; i < _arr.length; i++) { var one = _arr[i].toString(2), v = one.match(/^1+?(?=0)/); if (v && one.length == 8) { var bytesLength = v[0].length; var store = _arr[i].toString(2).slice(7 - bytesLength); for (var st = 1; st < bytesLength; st++) { store += _arr[st + i].toString(2).slice(2); } str += String.fromCharCode(parseInt(store, 2)); i += bytesLength - 1; } else { str += String.fromCharCode(_arr[i]); } } return str; } /** * * @param {object} val */ const emitData = (val) => { event.emit('penData', val); } // 字符串转utf-8 /** * * @param {string} str * @returns {Array} */ const strToUtf8 = (str) => { const utf8 = []; for (let ii = 0; ii < str.length; ii++) { let charCode = str.charCodeAt(ii); if (charCode < 0x80) utf8.push(charCode); else if (charCode < 0x800) { utf8.push(0xc0 | (charCode >> 6), 0x80 | (charCode & 0x3f)); } else if (charCode < 0xd800 || charCode >= 0xe000) { utf8.push(0xe0 | (charCode >> 12), 0x80 | ((charCode >> 6) & 0x3f), 0x80 | (charCode & 0x3f)); } else { ii++; charCode = 0x10000 + (((charCode & 0x3ff) << 10) | (str.charCodeAt(ii) & 0x3ff)); utf8.push( 0xf0 | (charCode >> 18), 0x80 | ((charCode >> 12) & 0x3f), 0x80 | ((charCode >> 6) & 0x3f), 0x80 | (charCode & 0x3f), ); } } //兼容汉字,ASCII码表最大的值为127,大于127的值为特殊字符 for (let jj = 0; jj < utf8.length; jj++) { var code = utf8[jj]; if (code > 127) { utf8[jj] = code - 256; } } return utf8; } /** * * @param {number} num * @returns {string} */ const MAC = (num) => { let num1 = changeData(Math.floor(num / 16)); let num2 = changeData(num % 16); return num1 + num2 } /** * * @param {number} num * @returns {string} */ function changeData(num) { let nums = null if (num >= 10) { switch (num) { case 10: nums = 'A'; break; case 11: nums = 'B' break; case 12: nums = 'C'; break; case 13: nums = 'D' break case 14: nums = 'E'; break case 15: nums = 'F' break default: break } } else { nums = num + '' } return nums; } class Queue { constructor() { this.dataStore = [] } enqueue(item) { this.dataStore.push(item) } dequeue() { return this.dataStore.shift() } front() { return this.dataStore[0] } back() { return this.dataStore[this.dataStore.length - 1] } getLength() { return this.dataStore.length } empty() { return this.dataStore.length === 0 } toString() { let retStr = '' this.dataStore.forEach((item) => { retStr += item + '\n' }) return retStr } } // hexstring转arraybuffer /** * * @param {string} hexStr * @returns {ArrayBuffer} */ function hexToArray(hexStr) { return new Uint8Array(hexStr.match(/[\da-f]{2}/gi).map(function (h) { return parseInt(h, 16) })).buffer } // arraybuffer转hexString /** * * @param {ArrayBuffer} buffer * @returns {string} */ const buf2hex = buffer => { // buffer is an ArrayBuffer return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('') } /** * * @param {number} ms * @returns {Promise} */ function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)) } //数字转16进制字符串补0 function numToHex(num) { let str = num.toString(16) if (str.length === 1) { return '0' + str } else { return str } } export { AllSDK }