| | |
| | | </view> |
| | | </view> |
| | | <view class="item_btn" v-if="dId == item.id"> |
| | | <!-- <uv-button type="primary" shape="circle" text="已存序列" size="small" :plain="true" |
| | | @click="commandLIST"></uv-button> |
| | | <uv-button type="primary" shape="circle" :text="screenOn ? '关闭屏幕' : '打开屏幕'" size="small" :plain="true" |
| | | @click="toggleScreen()"></uv-button> --> |
| | | <uv-button type="primary" shape="circle" text="调节亮度" size="small" :plain="true" |
| | | @click="this.$refs.popupBRIG.open();"></uv-button> |
| | | <uv-button type="primary" shape="circle" text="发送LED" size="small" :plain="true" |
| | |
| | | baseURL: '', |
| | | dId: '' ,//已连接的设备id, |
| | | devKwh: '', |
| | | platform: '' |
| | | platform: '', |
| | | screenOn: true, |
| | | waitDallThenSend: false // 标记:收到DALL清除所有信息指令回应后,再开始发送INST帧 |
| | | } |
| | | }, |
| | | onLoad() { |
| | |
| | | console.log('--------------', item); |
| | | |
| | | uni.showLoading({ |
| | | title: '发送中...', |
| | | title: '发送中0%', |
| | | mask: true |
| | | }); |
| | | |
| | |
| | | } |
| | | |
| | | if (this.ledData.length > 0) { |
| | | this.commandINST(this.ledData[this.ledCurrent]); |
| | | // 向智能壳发送INST帧前,先发送一次清除所有信息指令(DALL),待智能壳回应后再开始发送 |
| | | this.waitDallThenSend = true; |
| | | this.commandDALL(); |
| | | } else { |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | |
| | | }, |
| | | |
| | | //向低功耗蓝牙设备特征值中写入二进制数据 |
| | | writeBLECharacteristicValue(buffer) { |
| | | //keepLoading: 发送INST帧(含DALL前置指令、结束帧)过程中保持进度loading,发送成功后不关闭 |
| | | writeBLECharacteristicValue(buffer, keepLoading = false) { |
| | | const that = this |
| | | uni.writeBLECharacteristicValue({ |
| | | deviceId: this.deviceId, |
| | |
| | | writeType: 'write', |
| | | success: (res) => { |
| | | //console.log('写入指令发送成功----', res); |
| | | uni.hideLoading(); |
| | | if (!keepLoading) { |
| | | uni.hideLoading(); |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | //console.log('写入指令发送失败----', err); |
| | |
| | | }, 500); |
| | | |
| | | }, |
| | | // 切换屏幕状态 |
| | | toggleScreen() { |
| | | if (this.screenOn) { |
| | | this.commandBLAC() |
| | | } else { |
| | | this.commandOPAC() |
| | | } |
| | | }, |
| | | // 关闭屏幕 |
| | | commandBLAC() { |
| | | console.log('关闭屏幕BLAC----') |
| | | const startBytes = new Array(10).fill(0x55); |
| | | const frameHeader = 0x7E; |
| | | const packageType = 0x41; |
| | | const command = [0x42, 0x4C, 0x41, 0x43]; |
| | | |
| | | const data = [ |
| | | ...startBytes, |
| | | frameHeader, |
| | | packageType, |
| | | ...command |
| | | ]; |
| | | |
| | | const crc = this.calcCRC16(data.slice(11)); |
| | | data.push((crc >> 8) & 0xFF); |
| | | data.push(crc & 0xFF); |
| | | data.push(frameHeader); |
| | | console.log('BLAC data----', this.hexArrayToHexString(data)) |
| | | |
| | | const buffer = new Uint8Array(data).buffer; |
| | | setTimeout(() => { |
| | | this.writeBLECharacteristicValue(buffer) |
| | | }, 500); |
| | | }, |
| | | // 打开屏幕 |
| | | commandOPAC() { |
| | | console.log('打开屏幕OPAC----') |
| | | const startBytes = new Array(10).fill(0x55); |
| | | const frameHeader = 0x7E; |
| | | const packageType = 0x41; |
| | | const command = [0x4F, 0x50, 0x41, 0x43]; |
| | | |
| | | const data = [ |
| | | ...startBytes, |
| | | frameHeader, |
| | | packageType, |
| | | ...command |
| | | ]; |
| | | |
| | | const crc = this.calcCRC16(data.slice(11)); |
| | | data.push((crc >> 8) & 0xFF); |
| | | data.push(crc & 0xFF); |
| | | data.push(frameHeader); |
| | | console.log('OPAC data----', this.hexArrayToHexString(data)) |
| | | |
| | | const buffer = new Uint8Array(data).buffer; |
| | | setTimeout(() => { |
| | | this.writeBLECharacteristicValue(buffer) |
| | | }, 500); |
| | | }, |
| | | // 清除所有信息指令(DALL) |
| | | commandDALL() { |
| | | // 1.手机发指令:启动字节+帧头+包头段(0x43+简易绑定号+屏大小)+DALL+CRC校验码+帧尾。 |
| | | // 2.智能壳回指令:启动字节+帧头+包头段+DALL+返回标志+加密地址+CRC校验码+帧尾。 |
| | | // 构建指令数据 |
| | | const startBytes = new Array(10).fill(0x55); // 10个启动字节 |
| | | const frameHeader = 0x7E; // 帧头 |
| | | const packageType = 0x43; // 包类型 |
| | | // 使用新的简易绑定号生成函数 |
| | | const simpleBindId = this.generateSimpleBindId(); |
| | | |
| | | // 屏大小 (2 bytes) |
| | | const screenSize = [0x0C, 0x18]; |
| | | const packageHeader = [packageType, ...simpleBindId, ...screenSize]; |
| | | const command = [0x44, 0x41, 0x4C, 0x4C]; // "DALL"的ASCII码 |
| | | |
| | | // 组合数据 |
| | | const data = [ |
| | | ...startBytes, |
| | | frameHeader, |
| | | ...packageHeader, |
| | | ...command |
| | | ]; |
| | | // 计算CRC校验码(从包头段开始计算) |
| | | const crc = this.calcCRC16(data.slice(11)); |
| | | // 添加CRC和帧尾 |
| | | data.push((crc >> 8) & 0xFF); // CRC高8位 |
| | | data.push(crc & 0xFF); // CRC低8位 |
| | | data.push(frameHeader); // 帧尾 |
| | | console.log('DALL data----', this.hexArrayToHexString(data)) |
| | | |
| | | const buffer = new Uint8Array(data).buffer; |
| | | setTimeout(() => { |
| | | this.writeBLECharacteristicValue(buffer, true) |
| | | }, 50); |
| | | }, |
| | | //添加信息指令(INST) |
| | | commandINST(hexString) { |
| | | // 1.手机发指令:启动+帧头+包头段(0x43+简易绑定号+屏大小)+INST+信息属性+文件名+总帧数+当前帧*+块描述+块数据+CRC校验码+帧尾 |
| | |
| | | |
| | | // 块数据 |
| | | const blockDescription = this.hexStringToArray(hexString) |
| | | //const blockString = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF0000FF000000000000000000000000000000000000000000000000000000000000FF0000000000000000000000000000000000000000000000FF0000000000000000FF0000FF00000000000000000000000000000000FF0000FF000000000000000000FF0000000000FF0000FF00FF0000FF0000FF000000000000000000FF00FF0000FF000000000000000000FF00000000000000000000FF000000FF0000FF0000FF0000FF0000000000FF0000000000000000000000FF0000000000000000000000FF0000FF0000000000000000FF0000FF0000000000000000000000000000FF00FF000000000000000000000000FF00FF0000FF000000000000000000FF00000000000000FF0000FF0000FF0000FF0000FF0000000000000000FF0000FF000000000000000000000000FF0000000000FF0000000000000000000000000000000000000000FF0000000000000000000000000000000000FF0000000000000000000000000000000000FF00000000000000000000000000FF0000FF000000FF0000FF0000000000000000000000FF00000000000000FF0000FF000000FF00FF0000FF000000000000FF0000000000000000000000000000000000000000000000FF0000000000FF0000000000000000000000FF0000000000000000000000000000000000000000FF0000000000000000FF0000000000000000FF0000000000000000FF00000000000000FF0000FF0000FF0000FF000000000000000000FF00000000000000FF0000FF0000FF0000FF0000FF000000000000000000000000000000000000FF0000FF0000000000000000FF0000000000000000FF0000000000000000FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" |
| | | //const blockDescription = this.hexStringToArray(blockString) |
| | | |
| | | // 组合数据 |
| | | const data = [ |
| | |
| | | //console.log(this.ledCurrent, '----INST data----', this.hexArrayToHexString(data)) |
| | | //const buffer = new Uint8Array(data).buffer; |
| | | console.log('第几帧-------',this.ledCurrent) |
| | | // 根据总帧数和已发送数量更新发送进度(当前帧发送前,已发送ledCurrent帧),范围10%~99% |
| | | const sendPercent = Math.max(10, Math.min(99, Math.round(this.ledCurrent / this.ledTotal * 100))); |
| | | uni.showLoading({ |
| | | title: '发送中' + sendPercent + '%', |
| | | mask: true |
| | | }); |
| | | setTimeout(() => { |
| | | //this.writeBLECharacteristicValue(buffer) |
| | | this.sendBLEDataInChunks( |
| | |
| | | |
| | | const endbuffer = new Uint8Array(endData).buffer; |
| | | setTimeout(() => { |
| | | this.writeBLECharacteristicValue(endbuffer) |
| | | this.writeBLECharacteristicValue(endbuffer, true) |
| | | }, 50); |
| | | }, |
| | | async sendBLEDataInChunks(hexStr) { |
| | |
| | | //that.deviceList[that.listIndex].isLink = true; |
| | | //that.commandPOWR() |
| | | } else if (resName == 'LIST') { |
| | | //that.parseFileList(result) |
| | | that.parseFileList(result) |
| | | } else if (resName == 'BRIG') { |
| | | |
| | | } else if (resName == 'BLAC') { |
| | | console.log('BLAC----', result) |
| | | if (that.screenOn) { |
| | | that.screenOn = false; |
| | | uni.showToast({ |
| | | title: '屏幕已关闭', |
| | | icon: 'none', |
| | | duration: 1500 |
| | | }); |
| | | } else { |
| | | that.screenOn = true; |
| | | uni.showToast({ |
| | | title: '屏幕已打开', |
| | | icon: 'none', |
| | | duration: 1500 |
| | | }); |
| | | } |
| | | } else if (resName == 'PLAY') { |
| | | |
| | | } else if (resName == 'INST') { |
| | |
| | | // }); |
| | | that.commandINST(that.ledData[that.ledCurrent]); |
| | | } else if (that.ledCurrent == that.ledTotal) { |
| | | // uni.showLoading({ |
| | | // title: '发送结束帧', |
| | | // mask: true |
| | | // }); |
| | | // 所有数据帧已发送完成,发送结束帧,进度显示100% |
| | | uni.showLoading({ |
| | | title: '发送中100%', |
| | | mask: true |
| | | }); |
| | | that.commandEnd() |
| | | } else { |
| | | // 结束帧应答(ledCurrent == ledTotal + 1),全部发送完成,隐藏loading |
| | | uni.hideLoading(); |
| | | } |
| | | |
| | | } else if (resName == 'DALL') { |
| | | |
| | | // 清除所有信息指令回应:返回标志0x30工作无异常,0x31工作有异常 |
| | | if (that.waitDallThenSend) { |
| | | that.waitDallThenSend = false; |
| | | // 收到DALL回应后,开始发送第一帧INST |
| | | that.commandINST(that.ledData[that.ledCurrent]); |
| | | } |
| | | } else if (resName == 'POWR') { |
| | | // 查询电量 |
| | | let capacityHex = result.slice(-8, -6); // "0a" |
| | |
| | | } |
| | | }); |
| | | }, |
| | | //查询智能壳已存信息序列(LIST) |
| | | commandLIST() { |
| | | //1.手机发指令:启动字节+帧头+包头段(0x43+简易绑定号+屏大小)+LIST+信息属性+CRC校验码+帧尾。 |
| | | //2.智能壳指令:启动字节+帧头+包头段+LIST+返回标志+加密地址+文件数+[信息名1+信息名2+...+信息名n]+CRC校验码+帧尾。 |
| | | // 构建指令数据 |
| | | const startBytes = new Array(10).fill(0x55); // 10个启动字节 |
| | | const frameHeader = 0x7E; // 帧头 |
| | | const packageType = 0x43; // 包类型 |
| | | // 使用新的简易绑定号生成函数 |
| | | const simpleBindId = this.generateSimpleBindId(); |
| | | |
| | | // 屏大小 (2 bytes): 从ID中获取 |
| | | const screenSize = this.hexStringToArray(this.checId.slice(20, 24)); |
| | | const packageHeader = [packageType, ...simpleBindId, ...screenSize]; |
| | | const command = [0x4C, 0x49, 0x53, 0x54]; // "LIST"的ASCII码 |
| | | const infoAttribute = 0x00; // 信息属性: 0=一般信息 |
| | | // 组合数据 |
| | | const data = [ |
| | | ...startBytes, |
| | | frameHeader, |
| | | ...packageHeader, |
| | | ...command, |
| | | infoAttribute |
| | | ]; |
| | | |
| | | // 计算CRC校验码(从包头段开始计算) |
| | | const crc = this.calcCRC16(data.slice(11)); |
| | | |
| | | // 添加CRC和帧尾 |
| | | data.push((crc >> 8) & 0xFF); // CRC高8位 |
| | | data.push(crc & 0xFF); // CRC低8位 |
| | | data.push(frameHeader); // 帧尾 |
| | | console.log('LIST data----', this.hexArrayToHexString(data)) |
| | | |
| | | const buffer = new Uint8Array(data).buffer; |
| | | setTimeout(() => { |
| | | this.writeBLECharacteristicValue(buffer) |
| | | }, 1000); |
| | | }, |
| | | // 获取文件名称文件数量 |
| | | parseFileList(hexString) { |
| | | // 文件数占1字节(2个十六进制字符 |
| | | const fileCountHex = hexString.slice(32, 34); |
| | | const fileCount = parseInt(fileCountHex, 16); |
| | | console.log('文件数:', fileCount); |
| | | |
| | | // 获取文件名称列表 |
| | | const fileNames = []; |
| | | let nameStartIndex = 34; // 文件数后开始 |
| | | |
| | | for (let i = 0; i < fileCount; i++) { |
| | | // 每个信息名占2个字节(4个十六进制字符) |
| | | const nameHex = hexString.slice(nameStartIndex, nameStartIndex + 4); |
| | | const nameBytes = nameHex.match(/.{2}/g); |
| | | if (nameBytes && nameBytes.length === 2) { |
| | | // 将两个字节转换为ASCII字符 |
| | | const char1 = String.fromCharCode(parseInt(nameBytes[0], 16)); |
| | | const char2 = String.fromCharCode(parseInt(nameBytes[1], 16)); |
| | | const fileName = char1 + char2; |
| | | fileNames.push({ |
| | | fileName: fileName, |
| | | nameHex: nameHex |
| | | }); |
| | | } |
| | | |
| | | nameStartIndex += 4; // 移动到下一个文件名 |
| | | } |
| | | console.log('文件名称列表:', fileNames); |
| | | }, |
| | | // 生成简易绑定号 |
| | | generateSimpleBindId() { |
| | | if (!this.checId || !this.password) { |