import request, { baseURL } from '@/utils/request.js'; import { showLoading, hideLoading, updateLoading } from '@/utils/loading.js'; import { MsgSuccess, MsgError, MsgClose, MsgWarning, showPop } from '@/utils/MsgPops.js'; import Common from '@/utils/Common.js'; class SendBatchData{ constructor(_these,_f,_ble){ this.videoHexArray=[]; this.rgb565Data=[]; this.these=_these; this.f=_f; this.ble=_ble; } SendVideo(){ let these=this.these; let f=this.f; let ble=this.ble; let timeDelayCloseLoading = () => { setTimeout(() => { hideLoading(these); }, 1500); } let sendVideoPackets = (ReSendNo) => { console.log("开始发送分片数据"); return new Promise((resolve, reject) => { if (f) { // 总数据包数 var totalPackets = 1536; //36; let currentPacket = 1; console.log("发送数据准备中,总共" + totalPackets); if (ReSendNo) { totalPackets = ReSendNo; currentPacket = ReSendNo; } // 发送单个数据包 const sendNextVideoPacket = () => { // console.log("准备发送一段数据"); if (currentPacket > totalPackets) { if (!ReSendNo) { setTimeout(() => { ble.sendString(f.deviceId, "transmit complete", f .writeServiceId, f.wirteCharactId, 20) .then( () => { console.log("全部发送完毕") }).catch((ex) => { console.log("出现异常", ex); }); }, 500); } hideLoading(these); showPop({ showPop: true, message: "上传成功", iconUrl: "/static/images/common/success.png" }, these); these.videoHexArray = null; resolve(); return; } // 计算当前包的数据 let packetSize = 500; // 创建数据包 const startIndex = (currentPacket - 1) * packetSize; const endIndex = Math.min(startIndex + packetSize, these.videoHexArray .length); if (startIndex > endIndex) { resolve(); return; } ////console.log("111111"); const packetData = these.videoHexArray.slice(startIndex, endIndex); // 构建数据包 ////console.log("packetData.length"+packetData.length); const bufferSize = 504; // 头部5字节 + 数据部分 const buffer = new ArrayBuffer(bufferSize); const dataView = new DataView(buffer); let sortNo = currentPacket.toString(16).padStart(4, '0'); // 填充头部 dataView.setUint8(0, 0x55); // 帧头 dataView.setUint8(1, 0x04); // 帧类型:开机画面 dataView.setUint8(2, '0x' + sortNo.substring(0, 2)); // 包序号 dataView.setUint8(3, '0x' + sortNo.substring(2, 4)); // 包序号 // dataView.setUint8(4, 0x01); // dataView.setUint8(5, 0xF4); for (let i = 0; i < packetData.length; i++) { dataView.setUint8(4 + i, '0x' + packetData[i]); } let inteval = 60; ble.sendData(f.deviceId, buffer, f.writeServiceId, f .wirteCharactId, 10).then(() => { updateLoading(these, { text: "正在发送:" + currentPacket + "/" + totalPackets }); currentPacket++; // console.log("发送一段成功,发送下一段"); setTimeout(sendNextVideoPacket, inteval); }).catch(err => { console.log("发送失败了", err); if (err.code == '10007') { //遇到这个错误自动重新发送 console.log(err.errMsg + ",发送失败了,正在补偿:" + currentPacket); setTimeout(sendNextVideoPacket, 800); } else { hideLoading(these); showPop({ showPop: true, message: err.msg + ",发送失败了", borderColor: "#e034344d", buttonBgColor: "#E03434", buttonText: "确定", iconUrl: "/static/images/common/uploadErr.png" }, these); reject(err); these.videoHexArray = null; return; } }); }; sendNextVideoPacket(); } else { console.log("Fail.......") } }); } var sendVideo = (videoPath) => { let uploadVideo = () => { these.videoHexArray = []; console.log("开始处理,正在上传"); showLoading(these, { text: "上传中" }); let p1 = new Promise((resolve, reject) => { ble.sendString(f.deviceId, "video transmit start", f .writeServiceId, f.wirteCharactId).then(res => { setTimeout(() => { console.log("握手成功了"); resolve(true); }, 2200) }).catch(ex => { reject(ex); }); }); let p2 = new Promise((succ, err) => { const token = uni.getStorageSync('token'); const clientid = uni.getStorageSync('clientID'); if (!token) { err({ code: 401, msg: "请先登陆后再试" }); hideLoading(these); return; } console.log("baseURL=", baseURL); console.log("token", token); console.log("clientID", clientid); uni.uploadFile({ // url: 'http://114.55.111.217/video/upload', url: baseURL + "/app/video/upload", filePath: videoPath, name: 'file', header: { "Method": "POST", "Content-Type": "multipart/form-data", "Authorization": 'Bearer ' + token, "clientid": clientid }, timeout: 600000, fail: (ex) => { console.log("上传视频失败" + JSON.stringify(ex)); err(ex); }, success: (res) => { console.log("上传完成,向蓝牙设备发送"); succ(res); } }); }); Promise.all([p1, p2]).then((arr) => { if (arr[0].status == 'rejected') { MsgError("设备准备未就绪,请重试",'',these); return; } if(arr[1].status== 'rejected'){ MsgError("读取视频失败",'',these); return; } let res = arr[1]; // console.log("11111111111111111111111",res); res = JSON.parse(res.data); // console.log("22222222222222222222"); if (res.data) { these.videoHexArray = res.data; updateLoading(these, { text: "正在发送:0/1536" }); shotVideoClick(res.data); } else { console.log("服务器未返回正确的数据"); showPop({ message: "与服务器连接出现异常,请检查网络设置", iconUrl: "/static/images/common/uploadErr.png", borderColor: "#e034344d", buttonBgColor: "#E03434", }, these); } }).catch((ex) => { console.log("出现异常,", ex) hideLoading(these); showPop({ message: "出现异常," + ex.msg, iconUrl: "/static/images/common/uploadErr.png", borderColor: "#e034344d", buttonBgColor: "#E03434", }, these); }) } let shotVideoClick = () => { console.log("正在开始发送"); sendVideoPackets().then(() => { console.log("发送完成"); }).catch((ex1) => { //console.log("出现了异常", ex1) }).finally(() => { hideLoading(these); }); } uploadVideo(); } uni.chooseVideo({ sourceType: ['album'], compressed: false, // 关闭视频压缩,确保上传原始文件 success: function(res) { console.log("res=", res); let path = res.tempFilePath; // 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 (!checkResolution(width, height)) { err.push("视频宽高必须是160*80,当前分辨率:" + width + "*" + height); } if (err.length > 0) { err = err.join(";"); showPop({ message: err, iconUrl: "/static/images/common/uploadErr.png", borderColor: "#e034344d", buttonBgColor: "#E03434", }, these); return; } showLoading(these, { text: '正在上传' }); setTimeout(() => { sendVideo(path); }, 0); } }); } SendImg(){ let these=this.these; let f=this.f; let ble=this.ble; var sendImagePackets = function(ReSendNo) { return new Promise((resolve, reject) => { // 总数据包数 let totalPackets = 52; let currentPacket = 1; if (ReSendNo) { totalPackets = ReSendNo; currentPacket = ReSendNo; } if (f) { // 发送单个数据包 const sendNextPacket = () => { if (currentPacket > totalPackets) { hideLoading(these); these.closeAction(); showPop({ showPop: true, message: "上传成功", iconUrl: "/static/images/common/success.png", }); setTimeout(() => { ble.sendString(f.deviceId, "transmit complete", f .writeServiceId, f .wirteCharactId); }, 1000); these.rgb565Data = null; resolve(); return; } // 计算当前包的数据 let packetSize = 250; // if (currentPacket <= 51) { // packetSize = 250; // 前51个包每个500字节 // } else { // packetSize = 50; // 最后一个包100字节 // } // 创建数据包 const startIndex = (currentPacket - 1) * packetSize; const endIndex = Math.min(startIndex + packetSize, these.rgb565Data .length); if (startIndex > endIndex) { return; } const packetData = these.rgb565Data.slice(startIndex, endIndex); // 构建数据包 const bufferSize = 505; // 5 + packetData.length * 2; // 头部5字节 + 数据部分 const buffer = new ArrayBuffer(bufferSize); const dataView = new DataView(buffer); // 填充头部 dataView.setUint8(0, 0x55); // 帧头 dataView.setUint8(1, 0x02); // 帧类型:开机画面 dataView.setUint8(2, '0x' + currentPacket.toString(16).padStart(2, '0')); // 包序号 dataView.setUint16(3, packetData.length*2,false); // 包t长度 // 填充数据(每个RGB565值占2字节) for (let i = 0; i < packetData.length; i++) { dataView.setUint16(5 + i * 2, packetData[i], false); // 大端字节序 } //发送数据包 ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, 10) .then(() => { updateLoading(these, { text: "正在发送:" + currentPacket + "/" + totalPackets }) currentPacket++; setTimeout(sendNextPacket, these.inteval); }).catch(err => { console.log("发送数据包失败了" + JSON.stringify(err)); if (err.code == '10007') { setTimeout(sendNextPacket, these.inteval); return; } these.closeAction(); showPop({ message: err.msg, iconUrl: "/static/images/common/uploadErr.png", borderColor: "#e034344d", buttonBgColor: "#E03434", }); hideLoading(these); these.rgb565Data = null; reject(err); }); } if (ReSendNo) { sendNextPacket(ReSendNo); return; } // 开始牵手 ble.sendString(f.deviceId, "picture transmit start", f.writeServiceId, f.wirteCharactId).then(() => { setTimeout(sendNextPacket, 120); }).catch((err) => { console.log("握手没有成功"); showPop({ message: err.msg, iconUrl: "/static/images/common/uploadErr.png", borderColor: "#e034344d", buttonBgColor: "#E03434", }); hideLoading(these); reject(err); }); } }); } uni.chooseImage({ count: 1, sizeType: ['original', 'compressed'], sourceType: ['album','camera'], success: function(res) { uni.navigateTo({ url: "/pages/common/ImgCrop/ImgCrop", events: { ImgCutOver: function(data) { showLoading(these, { text: "正在发送0/52" }); these.rgb565Data = Common.convertToRGB565(data.piexls); setTimeout(function() { sendImagePackets().catch(() => { }); }, 0) } }, success(ev) { ev.eventChannel.emit('checkImg', { data: res.tempFiles[0].path }) }, fail(ex) { console.log("跳转页面失败" + JSON.stringify(ex)); } }); } }); } SendUsr(){ let these=this.these; let f=this.f; let ble=this.ble; these.formData.textLines = [these.formData.company, these.formData.usrname, these.formData.job]; console.log("data=", these.formData.textLines); showLoading(these, { text: "发送中" }); //握手 let holdHand = (hexs, time) => { return new Promise((resolve, reject) => { these.sendData(hexs, 'ble', "string").then(res => { setTimeout(() => { resolve(res) }, time); }).catch(ex => { reject(ex) }); }); } //画图 let drawText = () => { return new Promise((resolve, reject) => { these.$refs.textToHex.drawAndGetPixels().then(allPixels => { if (!allPixels) { reject("文本初始化失败"); return; } console.log("画图成功"); resolve(allPixels); }).catch(compEx => { reject(compEx); }); }); } //发送3个分包的数据 let task = (allPixels) => { try { let combinedData = []; for (let i = 0; i < 4; i++) { let linePixels = (allPixels[i] || []).flat(Infinity).map(item => typeof item === 'string' ? toByteValue(item) : item ); for (var j = linePixels.length; j < 256; j++) { linePixels.push(0x00); } linePixels = [0xFA, 0x06, 0x03, i + 1].concat(linePixels); linePixels.push(0xFF) combinedData.push(linePixels); } let curr = 1; let len = combinedData.length; //分包发送 let sendPacket = () => { if (combinedData.length === curr - 1) { setTimeout(()=>{ holdHand('transmit complete', 200).then(res => { MsgSuccess("人员信息发送成功", "确定", these); hideLoading(these); these.setBleFormData(); }); },300); hideLoading(); return; } let array = combinedData[curr - 1]; console.log("array=", array); ble.sendHexs(f.deviceId, array, null, null, 15).then( res => { curr++; console.log("发送成功", curr); updateLoading(these, { text: '发送中,' + (curr - 1) + '/' + combinedData.length }) setTimeout(sendPacket, 250); }).catch(err => { console.err("发送失败", err); if (err.code == '10007') { setTimeout(sendPacket, 250); } else { console.log("err:", err); MsgError('发送失败' + (err.msg || err.code), '确定', these); hideLoading(); } }); } setTimeout(sendPacket, 0); // 5. 发送成功处理 } catch (ex) { MsgError('发送失败' + (ex.msg || ex.code), '确定', these); } } setTimeout(() => { Promise.allSettled([holdHand('word transmit start', 2200), drawText()]).then(results => { if (results[0].status == 'rejected') { MsgError("与蓝牙设备握手失败,请重试",'',these); setTimeout(() => { hideLoading(these) }, 500); return; } if (results[1].status == 'rejected') { MsgError("读取文字点阵失败,请重试",'',these); return; } task(results[1].value); }) }, 0); } }