diff --git a/pages/6155/deviceDetail.vue b/pages/6155/deviceDetail.vue index a14f4fa..f9a4375 100644 --- a/pages/6155/deviceDetail.vue +++ b/pages/6155/deviceDetail.vue @@ -77,7 +77,7 @@ 泛光模式 - + + @@ -446,6 +446,35 @@ } }, methods: { + calcTotalPackets(frames) { + if (!Array.isArray(frames) || frames.length === 0) { + return 0; + } + return frames.reduce((frameSum, frame) => { + if (!Array.isArray(frame)) { + return frameSum; + } + const packSum = frame.reduce((packAcc, pack) => { + if (!Array.isArray(pack)) { + return packAcc; + } + return packAcc + pack.length; + }, 0); + return frameSum + packSum; + }, 0); + }, + toByteValue(value) { + if (typeof value === 'number') { + return value; + } + if (typeof value === 'string') { + if (value.startsWith('0x') || value.startsWith('0X')) { + return parseInt(value, 16); + } + return parseInt(`0x${value}`, 16); + } + return 0; + }, deviceRecovry(res) { if (this.Status.pageHide) { return; @@ -545,13 +574,22 @@ if (!json) { return; } + console.log("收到设备数据:", json); let keys = Object.keys(json); keys.forEach((key) => { if (key in these.formData) { - these.formData[key] = json[key]; + // 确保响应式更新 + console.log(`更新字段 ${key}: ${these.formData[key]} -> ${json[key]}`); + these.$set(these.formData, key, json[key]); + } else { + console.log(`字段 ${key} 不在 formData 中,跳过更新`); } }); + // 强制触发视图更新,确保电量显示同步 + these.$forceUpdate(); + console.log("更新后的电量:", these.formData.battary); + if (this.formData.battary <= 20) { this.showPop({ message: "设备电量低", @@ -858,7 +896,7 @@ }, 1500); } //视频上传 - let uplploadVideo = (videoPath) => { + let uplploadVideo = (videoPath, width, height) => { return new Promise((resolve, reject) => { let start = new Date(); @@ -877,7 +915,9 @@ "clientid": clientid }, formData: { - code: 1 + code: 2, + width: width, + height: height }, timeout: 600000, fail: (ex) => { @@ -899,7 +939,7 @@ if (res.statusCode === 200) { if (res.data.code == 200) { - console.log("上传完成,耗时:" + m + "分" + s + "秒,获得数据:"+res.data.length); + console.log("上传完成,耗时:" + m + "分" + s + "秒"); updateLoading(these, { text: "上传完成,耗时:" + m + "分" + s + "秒,正在切片。" }) @@ -923,41 +963,38 @@ } //视频切片 - let videoCutPacket = (array) => { - console.log("开始切片:",array.length); + let videoCutPacket = (data) => { return new Promise((resolve, reject) => { try { - let index=0; - let imgSize = 25600; - let packetSize = 3200; - let tdSize = 500; //只能是400/500 - let childPackLength = (tdSize === 400 ? 8 : 7); + const imgSize = 25600; + const packetSize = 3200; + const chunkSize = 500; + const maxPacketCount = 30; + + let source = Array.isArray(data) ? data.slice() : []; let results = []; - for (let i = 0; i < 30; i++) { //先切出30张,每张25600字节 - let packet = array.slice(0, imgSize); - array.splice(0, imgSize) + for (let i = 0; i < maxPacketCount && source.length >= imgSize; i++) { + let frameBytes = source.splice(0, imgSize); + let framePackets = []; - let secondLevel = []; - for (let j = 0; j < 8; j++) { //每张切8大包,每包3200字节 - let childPacket = packet.slice(0, packetSize); + for (let j = 0; j < 8 && frameBytes.length > 0; j++) { + let majorPacket = frameBytes.splice(0, packetSize); + let childPackets = []; - packet.splice(0, packetSize); - - let thirdLevel = []; - for (let k = 0; k < childPackLength; k++) { - //如果每小包500字节的话,每1个大包切出7个小包,前6包500字节,第7包200字节,共计56小包 - //如果每小包400字节的话,每1个大包切出8个小包,每包400字节,共计64小包 - - let arr = childPacket.slice(0, tdSize); - - childPacket.splice(0, tdSize) - thirdLevel.push(arr); - index++; - console.log("第"+index+"包长度:"+arr.length); + while (majorPacket.length > 0) { + let chunk = majorPacket.splice(0, chunkSize); + if (chunk.length) { + childPackets.push(chunk); + } + } + if (childPackets.length) { + framePackets.push(childPackets); } - secondLevel.push(thirdLevel); } - results.push(secondLevel); + + if (framePackets.length) { + results.push(framePackets); + } } updateLoading(these, { text: '切片完成,正在发送' @@ -970,31 +1007,25 @@ reject(error); } }); - - - - } //发送视频到设备 let shotVideoClick = (array, type, ReSendNo) => { var sendImagePackets = () => { return new Promise((resolve, reject) => { - - - this.currentPacket = 0; - let smallPacketLen = array[0][0][0].length; - // 总数据包数,每包400字节就是1920包,每包500字节时1680包 - var totalPackets = smallPacketLen === 400 ? 1920 : 1680; + let totalPackets = these.calcTotalPackets(array); this.totalPackets = totalPackets; + if (totalPackets === 0) { + reject('没有可发送的数据'); + return; + } let currentPacket = 1; let imgIndex = 0; let imgPackIndex = 0; let childPacketIndex = 0; if (ReSendNo) { - this.currentPacket = ReSendNo - 1; currentPacket = ReSendNo; totalPackets = ReSendNo; @@ -1002,85 +1033,68 @@ } // 发送单个数据包 const sendNextPacket = () => { - // console.log("111111") - if (currentPacket > totalPackets) { + if (imgIndex >= array.length) { resolve(); - return; } - // console.log("111111") - // 计算当前包的数据 - let packetSize = smallPacketLen; - - - if (smallPacketLen === 500) { - if ((currentPacket - 1) % 56 === 0) { - packetSize = 508; - } - - if (childPacketIndex === 6) { - packetSize = 200; - } - - if ((currentPacket - 1) % 56 === 55) { - packetSize = 201; - } - } else if (smallPacketLen === 400) { - if ((currentPacket - 1) % 64 === 0) { - packetSize = 408; - } - if ((currentPacket - 1) % 64 === 63) { - packetSize = 401; - } + if (!array[imgIndex]) { + console.error("没有找到对应的帧数据", imgIndex); + reject(`帧数据缺失,索引 ${imgIndex}`); + return; } + let childPacketsGroup = array[imgIndex][imgPackIndex]; + if (!childPacketsGroup || !childPacketsGroup.length) { + console.error("帧数据结构异常", imgIndex, imgPackIndex); + reject(`帧数据结构异常,帧 ${imgIndex}`); + return; + } - - let packetData = array[imgIndex][imgPackIndex][childPacketIndex]; - console.log("imgIndex=" + imgIndex + ",imgPackIndex=" +imgPackIndex +",childPacketIndex=" + childPacketIndex+',packetData='+packetData.length); + let packetData = childPacketsGroup[childPacketIndex]; + let packetSize = packetData.length; - let buffer = new ArrayBuffer(packetSize); - let dataView = new DataView(buffer); + const isFirstChild = childPacketIndex === 0; + const isLastChild = childPacketIndex === (childPacketsGroup + .length - 1); + + if (isFirstChild) { + packetSize = packetData.length + 8; + } + + if (isLastChild) { + packetSize = packetData.length + (isFirstChild ? 9 : 1); + } + + const buffer = new ArrayBuffer(packetSize); + const dataView = new DataView(buffer); - let sortNo = currentPacket.toString(16).padStart(4, '0'); - // console.log("11111"); let start = 0; - if (((currentPacket - 1) % 56 === 0 && smallPacketLen === 500) - || ((currentPacket - 1) % 64 ===0 && smallPacketLen === 400)) { + if (isFirstChild) { // 填充头部 dataView.setUint8(0, 0xFA); // 帧头 dataView.setUint8(1, 0x09); // 帧类型:开机画面 dataView.setUint8(2, 0x0C); dataView.setUint8(3, 0x84); - - dataView.setUint8(4, 0xFD); dataView.setUint8(5, 0x09); dataView.setUint8(6, imgIndex); dataView.setUint8(7, imgPackIndex + 1); start = 8; } - + for (let i = 0; i < packetData.length; i++) { - dataView.setUint8(start + i, '0x' + packetData[i]); + dataView.setUint8(start + i, these.toByteValue(packetData[i])); } - if (smallPacketLen === 500) { - if ((currentPacket - 1) % 56 === 55) { - dataView.setUint8(200, 0xFF); - } - } else if (smallPacketLen === 400) { - if ((currentPacket - 1) % 64 === 63) { - dataView.setUint8(200, 0xFF); - } + + if (isLastChild) { + dataView.setUint8(packetSize - 1, 0xFF); } - // console.log("444444"); let inteval = parseInt(this.inteval ? this.inteval : 80); - + console.log(inteval, 'intevalinteval'); ble.sendData(f.deviceId, buffer, f.writeServiceId, f - .wirteCharactId,15).then(() => { + .wirteCharactId).then(() => { if (ReSendNo) { - resolve(); return; } @@ -1092,21 +1106,18 @@ totalPackets }); - childPacketIndex++; - if (childPacketIndex == (smallPacketLen === 500?7:8)) { - imgPackIndex++; - if (imgPackIndex == 8) { - imgIndex++; - imgPackIndex = 0; - } + if (childPacketIndex >= childPacketsGroup.length) { childPacketIndex = 0; + imgPackIndex++; + if (imgPackIndex >= array[imgIndex].length) { + imgPackIndex = 0; + imgIndex++; + } } // 发送下一个包(添加延迟避免蓝牙缓冲区溢出) currentPacket++; - - setTimeout(sendNextPacket, inteval); }).catch(err => { if (err.code == 10007) { @@ -1123,38 +1134,53 @@ reject(err); }); }; - - - // console.log("111111") - sendNextPacket(); - }); } - return sendImagePackets(); - - - } uni.chooseVideo({ sourceType: ['album'], - compressed:false, + compressed: false, // 关闭视频压缩,确保上传原始文件 success: function(res) { console.log("res=", res); let path = res.tempFilePath; - let width = res.width; - let height = res.height; + // iOS可能返回浮点数,需要转换为整数进行比较 + let width = Math.round(res.width); + let height = Math.round(res.height); let duration = res.duration; + + // 获取平台信息 + const systemInfo = uni.getSystemInfoSync(); + const platform = systemInfo.platform; + const isIOS = platform === 'ios'; + + console.log("平台:", platform, "uni.chooseVideo返回 - 宽度:", width, "高度:", height, + "时长:", duration); + + // iOS特殊处理:如果返回的是80*40,很可能是160*80的一半(iOS的bug) + if (isIOS && width === 80 && height === 40) { + console.log("检测到iOS特殊情况:返回80*40,实际应该是160*80,进行修正"); + width = 160; + height = 80; + } + + // 检查分辨率是否符合要求 + let checkResolution = (w, h) => { + // 使用容差比较,允许1像素的误差 + return Math.abs(w - 160) <= 1 && Math.abs(h - 80) <= 1; + }; + let err = []; if (duration < 2) { err.push("视频时长至少2秒"); } - // if (width != 160 || height != 80) { - // err.push("视频宽高必须是160*80"); - // } + if (!checkResolution(width, height)) { + err.push("视频宽高必须是160*80,当前分辨率:" + width + "*" + height); + } + if (err.length > 0) { err = err.join(";"); these.showPop({ @@ -1165,13 +1191,32 @@ }); return; } + showLoading(these, { text: '正在上传' }); setTimeout(() => { - uplploadVideo(path).then(result => { + uplploadVideo(path, width, height).then(result => { - videoCutPacket(result.data).then(array => { + let data = result.data; + let convertedData = []; + for (let i = 0; i < data.length; i += 2) { + if (i + 1 < data.length) { + const byte1 = these.toByteValue(data[i]); + const byte2 = these.toByteValue(data[i + 1]); + const rgb565 = (byte1 << 8) | byte2; + const red = (rgb565 & 0xF800) >> 11; + const green = (rgb565 & 0x07E0) >> 5; + const blue = (rgb565 & 0x001F); + const bgr565 = (blue << 11) | (green << 5) | red; + convertedData.push((bgr565 >> 8) & 0xFF); + convertedData.push(bgr565 & 0xFF); + } else { + convertedData.push(these.toByteValue(data[i])); + } + } + + videoCutPacket(convertedData).then(array => { let start = new Date(); console.log("开始发送"); @@ -1460,6 +1505,24 @@ these.showBleUnConnect() return; } + let err = false; + this.formData.textLines.find((txt) => { + if (txt.length === 0 || txt.length > 7) { + console.log("txt=", txt); + err = true; + return true; + } + return false; + }) + if (err) { + this.showPop({ + message: "单位、部门、姓名必须填写且最多7字", + iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png", + borderColor: "#e034344d", + buttonBgColor: "#E03434", + }); + return; + } showLoading(these, { text: "请稍候..." }); @@ -1518,8 +1581,9 @@ dataView.setUint8(bufferSize - 1, 0xFF); - let inteval = parseInt(this.inteval ? this.inteval : 50); - console.log("inteval=", inteval) + let inteval = 100; + //parseInt(this.inteval ? this.inteval : 80); + //console.log("inteval=", inteval) ble.sendData(f.deviceId, buffer, f.writeServiceId, f .wirteCharactId, 30).then(() => { @@ -1566,8 +1630,8 @@ }); console.log("result=", result); - // var str1="FA 06 01 00 FF FF F7 9F EF 6F EC F7 EA 09 CF FF AF FB EF EB EF EB EC 6B EF EB EC 6B EF EB EF FB EE 63 FF FF FF FF F7 9F EF 6F EC F7 EA 09 CF FF AF FB EF EB EF EB EC 6B EF EB EC 6B EF EB EF FB EE 63 FF FF FF FF F7 FF 81 03 ED BB DD B7 CB CF F3 C7 CD 39 BE FF FE FF C0 03 FE FB FD FB F3 F7 8F 87 FF FF FF FF FE FF FE FF FE FF C0 03 FF FB FD FB FD FB FD FB FD FB FB FB FB FF F7 F7 EF F7 9F 8F FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF" - // var str2="FA 07 01 00 FF FF EE DD EE DF EF 5B AB DF AA 03 AE FF AE FF EE 03 EE FF EE FF EE 03 EE FF EE FF EE E3 FF FF FF FF EE DD EE DF EF 5B AB DF AA 03 AE FF AE FF EE 03 EE FF EE FF EE 03 EE FF EE FF EE E3 FF FF FF FF EF 77 EF 73 EF 7F 80 01 EF 7F EF 7F EF 03 E7 3B 8E BB EE D7 EE EF ED E7 ED 9B 8B 7D FF FF FF FF FF FF F7 EF F7 F7 EF F7 DF FB FF FF FF FF FE FF 80 01 FE 7F FD BF FB DF F7 E7 9F F9 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF" + // var str1="FA 06 01 00 FF FF F7 9F EF 6F EC F7 EA 09 CF FF AF FB EF EB EF EB EC 6B EF EB EC 6B EF EB EF FB EE 63 FF FF FF FF F7 9F EF 6F EC F7 EA 09 CF FF AF FB EF EB EF EB EC 6B EF EB EC 6B EF EB EF FB EE 63 FF FF FF FF F7 FF 81 03 ED BB DD B7 CB CF F3 C7 CD 39 BE FF FE FF C0 03 FE FB FD FB F3 F7 8F 87 FF FF FF FF FE FF FE FF FE FF C0 03 FF FB FD FB FD FB FD FB FD FB FB FB FB FF F7 F7 EF F7 9F 8F FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF" + // var str2="FA 07 01 00 FF FF EE DD EE DF EF 5B AB DF AA 03 AE FF AE FF EE 03 EE FF EE FF EE 03 EE FF EE FF EE E3 FF FF FF FF EE DD EE DF EF 5B AB DF AA 03 AE FF AE FF EE 03 EE FF EE FF EE 03 EE FF EE FF EE E3 FF FF FF FF EF 77 EF 73 EF 7F 80 01 EF 7F EF 7F EF 03 E7 3B 8E BB EE D7 EE EF ED E7 ED 9B 8B 7D FF FF FF FF FF FF F7 EF F7 F7 EF F7 DF FB FF FF FF FF FE FF 80 01 FE 7F FD BF FB DF F7 E7 9F F9 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF" // var str3="FA 08 01 00 FF FF EF DF EC 01 EF FF AB FF AA 03 AA FB AE FB EE 03 EF DF EF DF EE DB ED DF ED DD EF 1F FF FF FF FF EF BF EF 87 81 77 EE F7 EC 03 81 7F EF 7F EF 7F EF 03 81 7F EF 7F EF 7D EF 7D EF 03 FF FF FF FF F9 F1 CF BF DF FF DF FF C1 FF DD 81 DD F7 DD F7 C1 F7 DF 77 FF 77 BF 77 BF 77 FF F7 FF FF FF FF FD FF FD FF FB FF FB FF F0 07 E7 F7 EF F7 D8 07 BF F7 FF F7 F8 07 FF F7 FF F7 FF C7 FF FF FF FF FF FF FF FF FF FF FE FF FE 7F FE 7F FE FF FD BF FD FF FB DF F7 EF EF F7 DF FB BF FD FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF" // let arr1=('0x'+(str1.split(' ').join(",0x"))).split(',');