Compare commits
9 Commits
ec6deab32a
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| e247acdd5e | |||
| 2ba53fcf92 | |||
| 97b6825420 | |||
| 14d6fa7ccb | |||
| 8270cc77d7 | |||
| 27308e0ed1 | |||
| 76d40bc096 | |||
| 31b189dd72 | |||
| fc1fad0579 |
@ -34,7 +34,9 @@
|
|||||||
currentCanvasWidth: 0,
|
currentCanvasWidth: 0,
|
||||||
currentCanvasHeight: 0,
|
currentCanvasHeight: 0,
|
||||||
// Canvas上下文(复用)
|
// Canvas上下文(复用)
|
||||||
ctx: null
|
ctx: null,
|
||||||
|
// 标记是否已经预热过画布
|
||||||
|
canvasWarmed: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -62,10 +64,67 @@
|
|||||||
this.ctx.fillRect(0, 0, this.currentCanvasWidth, this.currentCanvasHeight);
|
this.ctx.fillRect(0, 0, this.currentCanvasWidth, this.currentCanvasHeight);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预热画布,确保画布和字体完全准备好(解决APP重新打开后第一次获取数据不完整的问题)
|
||||||
|
*/
|
||||||
|
async warmupCanvas() {
|
||||||
|
if (this.canvasWarmed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 设置画布尺寸
|
||||||
|
this.currentCanvasWidth = 16;
|
||||||
|
this.currentCanvasHeight = 16;
|
||||||
|
|
||||||
|
// 清空画布
|
||||||
|
this.clearCanvas();
|
||||||
|
|
||||||
|
// 绘制一个测试字符来预热字体和画布
|
||||||
|
this.ctx.setFillStyle(this.color);
|
||||||
|
this.ctx.setFontSize(this.fontSize);
|
||||||
|
this.ctx.font = `${this.fontSize}px "PingFangBold", "PingFang SC", Arial, sans-serif`;
|
||||||
|
this.ctx.setTextBaseline('middle');
|
||||||
|
this.ctx.fillText('测', 0, 8);
|
||||||
|
|
||||||
|
// 等待画布绘制完成
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
this.ctx.draw(false, () => {
|
||||||
|
// 获取一次测试数据,确保canvasGetImageData API已准备好
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.canvasGetImageData({
|
||||||
|
canvasId: 'reusableCanvas',
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
success: () => {
|
||||||
|
this.canvasWarmed = true;
|
||||||
|
resolve();
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
this.canvasWarmed = true;
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 额外等待确保字体完全加载
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 200));
|
||||||
|
} catch (ex) {
|
||||||
|
console.log("画布预热异常:", ex);
|
||||||
|
this.canvasWarmed = true; // 即使失败也标记为已预热,避免重复尝试
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 复用单个Canvas处理所有文本行
|
* 复用单个Canvas处理所有文本行
|
||||||
*/
|
*/
|
||||||
async drawAndGetPixels() {
|
async drawAndGetPixels() {
|
||||||
|
// 第一次调用时先预热画布(解决APP重新打开后第一次获取数据不完整的问题)
|
||||||
|
await this.warmupCanvas();
|
||||||
|
|
||||||
let convertCharToMatrix=function(imageData) {
|
let convertCharToMatrix=function(imageData) {
|
||||||
// console.log("imgData=",imageData)
|
// console.log("imgData=",imageData)
|
||||||
|
|||||||
@ -86,7 +86,7 @@
|
|||||||
<text class="smallTxt">上传</text>
|
<text class="smallTxt">上传</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="mode fleft marginLeft" v-on:click.stop="UploadOpenVideo()">
|
<view class="mode marginLeft fleft" v-on:click.stop="UploadOpenVideo()">
|
||||||
<view class="leftImg">
|
<view class="leftImg">
|
||||||
<image class="img" src="/static/images/common/video.png" mode="aspectFit"></image>
|
<image class="img" src="/static/images/common/video.png" mode="aspectFit"></image>
|
||||||
</view>
|
</view>
|
||||||
@ -422,15 +422,11 @@
|
|||||||
}
|
}
|
||||||
switch (this.formData.mode) {
|
switch (this.formData.mode) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
||||||
|
|
||||||
txt = "强光模式";
|
txt = "强光模式";
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
txt = "弱光模式";
|
txt = "弱光模式";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
txt = "爆闪模式";
|
txt = "爆闪模式";
|
||||||
break;
|
break;
|
||||||
@ -446,6 +442,35 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
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) {
|
deviceRecovry(res) {
|
||||||
if (this.Status.pageHide) {
|
if (this.Status.pageHide) {
|
||||||
return;
|
return;
|
||||||
@ -545,13 +570,22 @@
|
|||||||
if (!json) {
|
if (!json) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
console.log("收到设备数据:", json);
|
||||||
let keys = Object.keys(json);
|
let keys = Object.keys(json);
|
||||||
keys.forEach((key) => {
|
keys.forEach((key) => {
|
||||||
if (key in these.formData) {
|
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) {
|
if (this.formData.battary <= 20) {
|
||||||
this.showPop({
|
this.showPop({
|
||||||
message: "设备电量低",
|
message: "设备电量低",
|
||||||
@ -735,7 +769,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//FA 09 0C 84 FB 09 00 [01~08] + 3200字节 +FF 数据格式
|
//FA 09 0C 84 FE 09 00 [01~08] + 3200字节 +FF 数据格式
|
||||||
var buffer = new ArrayBuffer(bufferSize);
|
var buffer = new ArrayBuffer(bufferSize);
|
||||||
var dataView = new DataView(buffer);
|
var dataView = new DataView(buffer);
|
||||||
if (childPacket == 1) {
|
if (childPacket == 1) {
|
||||||
@ -743,7 +777,7 @@
|
|||||||
dataView.setUint8(1, 0x09); // 帧头
|
dataView.setUint8(1, 0x09); // 帧头
|
||||||
dataView.setUint8(2, 0x0C); // 帧头
|
dataView.setUint8(2, 0x0C); // 帧头
|
||||||
dataView.setUint8(3, 0x84); // 帧头
|
dataView.setUint8(3, 0x84); // 帧头
|
||||||
dataView.setUint8(4, 0xFD); // 帧头
|
dataView.setUint8(4, 0xFE); // 帧头
|
||||||
dataView.setUint8(5, 0x09);
|
dataView.setUint8(5, 0x09);
|
||||||
dataView.setUint8(6, 0x00); // 帧头
|
dataView.setUint8(6, 0x00); // 帧头
|
||||||
dataView.setUint8(7, currentPacket); //包序号
|
dataView.setUint8(7, currentPacket); //包序号
|
||||||
@ -858,7 +892,7 @@
|
|||||||
}, 1500);
|
}, 1500);
|
||||||
}
|
}
|
||||||
//视频上传
|
//视频上传
|
||||||
let uplploadVideo = (videoPath) => {
|
let uplploadVideo = (videoPath, width, height) => {
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let start = new Date();
|
let start = new Date();
|
||||||
@ -877,7 +911,9 @@
|
|||||||
"clientid": clientid
|
"clientid": clientid
|
||||||
},
|
},
|
||||||
formData: {
|
formData: {
|
||||||
code: 1
|
code: 2,
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
},
|
},
|
||||||
timeout: 600000,
|
timeout: 600000,
|
||||||
fail: (ex) => {
|
fail: (ex) => {
|
||||||
@ -899,7 +935,7 @@
|
|||||||
|
|
||||||
if (res.statusCode === 200) {
|
if (res.statusCode === 200) {
|
||||||
if (res.data.code == 200) {
|
if (res.data.code == 200) {
|
||||||
console.log("上传完成,耗时:" + m + "分" + s + "秒,获得数据:"+res.data.length);
|
console.log("上传完成,耗时:" + m + "分" + s + "秒");
|
||||||
updateLoading(these, {
|
updateLoading(these, {
|
||||||
text: "上传完成,耗时:" + m + "分" + s + "秒,正在切片。"
|
text: "上传完成,耗时:" + m + "分" + s + "秒,正在切片。"
|
||||||
})
|
})
|
||||||
@ -923,41 +959,38 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//视频切片
|
//视频切片
|
||||||
let videoCutPacket = (array) => {
|
let videoCutPacket = (data) => {
|
||||||
console.log("开始切片:",array.length);
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
let index=0;
|
const imgSize = 25600;
|
||||||
let imgSize = 25600;
|
const packetSize = 3200;
|
||||||
let packetSize = 3200;
|
const chunkSize = 500;
|
||||||
let tdSize = 500; //只能是400/500
|
const maxPacketCount = 30;
|
||||||
let childPackLength = (tdSize === 400 ? 8 : 7);
|
|
||||||
|
let source = Array.isArray(data) ? data.slice() : [];
|
||||||
let results = [];
|
let results = [];
|
||||||
for (let i = 0; i < 30; i++) { //先切出30张,每张25600字节
|
for (let i = 0; i < maxPacketCount && source.length >= imgSize; i++) {
|
||||||
let packet = array.slice(0, imgSize);
|
let frameBytes = source.splice(0, imgSize);
|
||||||
array.splice(0, imgSize)
|
let framePackets = [];
|
||||||
|
|
||||||
let secondLevel = [];
|
for (let j = 0; j < 8 && frameBytes.length > 0; j++) {
|
||||||
for (let j = 0; j < 8; j++) { //每张切8大包,每包3200字节
|
let majorPacket = frameBytes.splice(0, packetSize);
|
||||||
let childPacket = packet.slice(0, packetSize);
|
let childPackets = [];
|
||||||
|
|
||||||
packet.splice(0, packetSize);
|
while (majorPacket.length > 0) {
|
||||||
|
let chunk = majorPacket.splice(0, chunkSize);
|
||||||
let thirdLevel = [];
|
if (chunk.length) {
|
||||||
for (let k = 0; k < childPackLength; k++) {
|
childPackets.push(chunk);
|
||||||
//如果每小包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);
|
|
||||||
}
|
}
|
||||||
secondLevel.push(thirdLevel);
|
|
||||||
}
|
}
|
||||||
results.push(secondLevel);
|
if (childPackets.length) {
|
||||||
|
framePackets.push(childPackets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (framePackets.length) {
|
||||||
|
results.push(framePackets);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
updateLoading(these, {
|
updateLoading(these, {
|
||||||
text: '切片完成,正在发送'
|
text: '切片完成,正在发送'
|
||||||
@ -970,31 +1003,25 @@
|
|||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//发送视频到设备
|
//发送视频到设备
|
||||||
let shotVideoClick = (array, type, ReSendNo) => {
|
let shotVideoClick = (array, type, ReSendNo) => {
|
||||||
var sendImagePackets = () => {
|
var sendImagePackets = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.currentPacket = 0;
|
this.currentPacket = 0;
|
||||||
let smallPacketLen = array[0][0][0].length;
|
let totalPackets = these.calcTotalPackets(array);
|
||||||
// 总数据包数,每包400字节就是1920包,每包500字节时1680包
|
|
||||||
var totalPackets = smallPacketLen === 400 ? 1920 : 1680;
|
|
||||||
this.totalPackets = totalPackets;
|
this.totalPackets = totalPackets;
|
||||||
|
if (totalPackets === 0) {
|
||||||
|
reject('没有可发送的数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
let currentPacket = 1;
|
let currentPacket = 1;
|
||||||
|
|
||||||
let imgIndex = 0;
|
let imgIndex = 0;
|
||||||
let imgPackIndex = 0;
|
let imgPackIndex = 0;
|
||||||
let childPacketIndex = 0;
|
let childPacketIndex = 0;
|
||||||
if (ReSendNo) {
|
if (ReSendNo) {
|
||||||
|
|
||||||
this.currentPacket = ReSendNo - 1;
|
this.currentPacket = ReSendNo - 1;
|
||||||
currentPacket = ReSendNo;
|
currentPacket = ReSendNo;
|
||||||
totalPackets = ReSendNo;
|
totalPackets = ReSendNo;
|
||||||
@ -1002,59 +1029,49 @@
|
|||||||
}
|
}
|
||||||
// 发送单个数据包
|
// 发送单个数据包
|
||||||
const sendNextPacket = () => {
|
const sendNextPacket = () => {
|
||||||
// console.log("111111")
|
if (imgIndex >= array.length) {
|
||||||
if (currentPacket > totalPackets) {
|
|
||||||
resolve();
|
resolve();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// console.log("111111")
|
|
||||||
// 计算当前包的数据
|
|
||||||
let packetSize = smallPacketLen;
|
|
||||||
|
|
||||||
|
if (!array[imgIndex]) {
|
||||||
|
console.error("没有找到对应的帧数据", imgIndex);
|
||||||
if (smallPacketLen === 500) {
|
reject(`帧数据缺失,索引 ${imgIndex}`);
|
||||||
if ((currentPacket - 1) % 56 === 0) {
|
return;
|
||||||
packetSize = 508;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (childPacketIndex === 6) {
|
let childPacketsGroup = array[imgIndex][imgPackIndex];
|
||||||
packetSize = 200;
|
if (!childPacketsGroup || !childPacketsGroup.length) {
|
||||||
|
console.error("帧数据结构异常", imgIndex, imgPackIndex);
|
||||||
|
reject(`帧数据结构异常,帧 ${imgIndex}`);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((currentPacket - 1) % 56 === 55) {
|
let packetData = childPacketsGroup[childPacketIndex];
|
||||||
packetSize = 201;
|
let packetSize = packetData.length;
|
||||||
}
|
|
||||||
} else if (smallPacketLen === 400) {
|
const isFirstChild = childPacketIndex === 0;
|
||||||
if ((currentPacket - 1) % 64 === 0) {
|
const isLastChild = childPacketIndex === (childPacketsGroup
|
||||||
packetSize = 408;
|
.length - 1);
|
||||||
}
|
|
||||||
if ((currentPacket - 1) % 64 === 63) {
|
if (isFirstChild) {
|
||||||
packetSize = 401;
|
packetSize = packetData.length + 8;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isLastChild) {
|
||||||
|
packetSize = packetData.length + (isFirstChild ? 9 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const buffer = new ArrayBuffer(packetSize);
|
||||||
|
const dataView = new DataView(buffer);
|
||||||
|
|
||||||
let packetData = array[imgIndex][imgPackIndex][childPacketIndex];
|
|
||||||
console.log("imgIndex=" + imgIndex + ",imgPackIndex=" +imgPackIndex +",childPacketIndex=" + childPacketIndex+',packetData='+packetData.length);
|
|
||||||
|
|
||||||
let buffer = new ArrayBuffer(packetSize);
|
|
||||||
let dataView = new DataView(buffer);
|
|
||||||
|
|
||||||
let sortNo = currentPacket.toString(16).padStart(4, '0');
|
|
||||||
// console.log("11111");
|
|
||||||
let start = 0;
|
let start = 0;
|
||||||
if (((currentPacket - 1) % 56 === 0 && smallPacketLen === 500)
|
if (isFirstChild) {
|
||||||
|| ((currentPacket - 1) % 64 ===0 && smallPacketLen === 400)) {
|
|
||||||
// 填充头部
|
// 填充头部
|
||||||
dataView.setUint8(0, 0xFA); // 帧头
|
dataView.setUint8(0, 0xFA); // 帧头
|
||||||
dataView.setUint8(1, 0x09); // 帧类型:开机画面
|
dataView.setUint8(1, 0x09); // 帧类型:开机画面
|
||||||
dataView.setUint8(2, 0x0C);
|
dataView.setUint8(2, 0x0C);
|
||||||
dataView.setUint8(3, 0x84);
|
dataView.setUint8(3, 0x84);
|
||||||
|
|
||||||
|
|
||||||
dataView.setUint8(4, 0xFD);
|
dataView.setUint8(4, 0xFD);
|
||||||
dataView.setUint8(5, 0x09);
|
dataView.setUint8(5, 0x09);
|
||||||
dataView.setUint8(6, imgIndex);
|
dataView.setUint8(6, imgIndex);
|
||||||
@ -1063,24 +1080,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < packetData.length; i++) {
|
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) {
|
if (isLastChild) {
|
||||||
dataView.setUint8(200, 0xFF);
|
dataView.setUint8(packetSize - 1, 0xFF);
|
||||||
}
|
}
|
||||||
} else if (smallPacketLen === 400) {
|
|
||||||
if ((currentPacket - 1) % 64 === 63) {
|
|
||||||
dataView.setUint8(200, 0xFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// console.log("444444");
|
|
||||||
let inteval = parseInt(this.inteval ? this.inteval : 80);
|
let inteval = parseInt(this.inteval ? this.inteval : 80);
|
||||||
|
console.log(inteval, 'intevalinteval');
|
||||||
ble.sendData(f.deviceId, buffer, f.writeServiceId, f
|
ble.sendData(f.deviceId, buffer, f.writeServiceId, f
|
||||||
.wirteCharactId,15).then(() => {
|
.wirteCharactId).then(() => {
|
||||||
if (ReSendNo) {
|
if (ReSendNo) {
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1092,21 +1102,18 @@
|
|||||||
totalPackets
|
totalPackets
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
childPacketIndex++;
|
childPacketIndex++;
|
||||||
if (childPacketIndex == (smallPacketLen === 500?7:8)) {
|
if (childPacketIndex >= childPacketsGroup.length) {
|
||||||
imgPackIndex++;
|
|
||||||
if (imgPackIndex == 8) {
|
|
||||||
imgIndex++;
|
|
||||||
imgPackIndex = 0;
|
|
||||||
}
|
|
||||||
childPacketIndex = 0;
|
childPacketIndex = 0;
|
||||||
|
imgPackIndex++;
|
||||||
|
if (imgPackIndex >= array[imgIndex].length) {
|
||||||
|
imgPackIndex = 0;
|
||||||
|
imgIndex++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 发送下一个包(添加延迟避免蓝牙缓冲区溢出)
|
// 发送下一个包(添加延迟避免蓝牙缓冲区溢出)
|
||||||
currentPacket++;
|
currentPacket++;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setTimeout(sendNextPacket, inteval);
|
setTimeout(sendNextPacket, inteval);
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
if (err.code == 10007) {
|
if (err.code == 10007) {
|
||||||
@ -1123,38 +1130,53 @@
|
|||||||
reject(err);
|
reject(err);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// console.log("111111")
|
|
||||||
|
|
||||||
sendNextPacket();
|
sendNextPacket();
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return sendImagePackets();
|
return sendImagePackets();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uni.chooseVideo({
|
uni.chooseVideo({
|
||||||
sourceType: ['album'],
|
sourceType: ['album'],
|
||||||
compressed:false,
|
compressed: false, // 关闭视频压缩,确保上传原始文件
|
||||||
success: function(res) {
|
success: function(res) {
|
||||||
console.log("res=", res);
|
console.log("res=", res);
|
||||||
let path = res.tempFilePath;
|
let path = res.tempFilePath;
|
||||||
let width = res.width;
|
// iOS可能返回浮点数,需要转换为整数进行比较
|
||||||
let height = res.height;
|
let width = Math.round(res.width);
|
||||||
|
let height = Math.round(res.height);
|
||||||
let duration = res.duration;
|
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 = [];
|
let err = [];
|
||||||
if (duration < 2) {
|
if (duration < 2) {
|
||||||
err.push("视频时长至少2秒");
|
err.push("视频时长至少2秒");
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (width != 160 || height != 80) {
|
if (!checkResolution(width, height)) {
|
||||||
// err.push("视频宽高必须是160*80");
|
err.push("视频宽高必须是160*80,当前分辨率:" + width + "*" + height);
|
||||||
// }
|
}
|
||||||
|
|
||||||
if (err.length > 0) {
|
if (err.length > 0) {
|
||||||
err = err.join(";");
|
err = err.join(";");
|
||||||
these.showPop({
|
these.showPop({
|
||||||
@ -1165,13 +1187,32 @@
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
showLoading(these, {
|
showLoading(these, {
|
||||||
text: '正在上传'
|
text: '正在上传'
|
||||||
});
|
});
|
||||||
setTimeout(() => {
|
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();
|
let start = new Date();
|
||||||
console.log("开始发送");
|
console.log("开始发送");
|
||||||
@ -1460,155 +1501,96 @@
|
|||||||
these.showBleUnConnect()
|
these.showBleUnConnect()
|
||||||
return;
|
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, {
|
showLoading(these, {
|
||||||
text: "请稍候..."
|
text: "请稍候..."
|
||||||
});
|
});
|
||||||
this.setBleFormData();
|
this.setBleFormData();
|
||||||
let task = async () => {
|
let task = async () => {
|
||||||
var sendTxtPackge = (rgbdata, type, str) => {
|
|
||||||
|
|
||||||
var promise = new Promise((resolve, reject) => {
|
|
||||||
try {
|
try {
|
||||||
|
// 预热画布,确保画布和字体完全准备好(解决APP重新打开后第一次获取数据不完整的问题)
|
||||||
|
console.log("预热画布...");
|
||||||
|
await this.$refs.textToHex.drawAndGetPixels();
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 200)); // 等待预热完成
|
||||||
|
|
||||||
let packetSize = rgbdata.length; //每包均分的数量
|
// 1. 获取所有文本行的像素数据
|
||||||
let mode = rgbdata.length % packetSize; //最后一包的数量
|
const allPixels = await this.$refs.textToHex.drawAndGetPixels();
|
||||||
let cnt =
|
if (!allPixels) {
|
||||||
1; // parseInt(rgbdata.length / packetSize) + (mode > 0 ? 1 :0); //总包数量
|
throw new Error("无法生成像素数据");
|
||||||
let curr = 1; //当前包序号
|
|
||||||
|
|
||||||
let sendNext = () => {
|
|
||||||
|
|
||||||
if (curr > cnt) {
|
|
||||||
resolve();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let bufferSize = 261;
|
// 2. 将所有像素数据合并到一个大数组中
|
||||||
|
let combinedData = [];
|
||||||
console.log("bufferSize=", bufferSize)
|
for (let i = 0; i < 3; i++) {
|
||||||
|
const linePixels = (allPixels[i] || []).flat(Infinity).map(item =>
|
||||||
let buffer = new ArrayBuffer(bufferSize);
|
typeof item === 'string' ? these.toByteValue(item) : item
|
||||||
let dataView = new DataView(buffer);
|
);
|
||||||
let startIndex = (curr - 1) * packetSize;
|
// 补齐到256字节
|
||||||
|
while (linePixels.length < 256) {
|
||||||
let endIndex = Math.min(startIndex + packetSize, rgbdata
|
linePixels.push(0x00);
|
||||||
.length);
|
}
|
||||||
if (startIndex > endIndex) {
|
combinedData = combinedData.concat(linePixels.slice(0, 256));
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let packetData = rgbdata.slice(startIndex,
|
// 3. 构建完整的逻辑大包
|
||||||
endIndex); //取一片数据发送
|
const logicalPacketSize = 4 + combinedData.length + 1; // Header + Data + Footer
|
||||||
console.log("packetData.length=", packetData.length);
|
const logicalBuffer = new ArrayBuffer(logicalPacketSize);
|
||||||
let start = 0;
|
const logicalDataView = new DataView(logicalBuffer);
|
||||||
if (curr == 1) {
|
|
||||||
dataView.setUint8(0, 0xFA);
|
|
||||||
dataView.setUint8(1, type);
|
|
||||||
dataView.setUint8(2, 0x01);
|
|
||||||
dataView.setUint8(3, 0x00);
|
|
||||||
|
|
||||||
|
// 写入头部
|
||||||
|
logicalDataView.setUint8(0, 0xFA);
|
||||||
|
logicalDataView.setUint8(1, 0x06);
|
||||||
|
logicalDataView.setUint8(2, 0x03);
|
||||||
|
logicalDataView.setUint8(3, 0x00);
|
||||||
|
|
||||||
start = 4;
|
// 写入数据
|
||||||
|
for (let i = 0; i < combinedData.length; i++) {
|
||||||
|
logicalDataView.setUint8(4 + i, combinedData[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < packetData.length; i++) {
|
// 写入尾部
|
||||||
dataView.setUint8(start + i, packetData[i]);
|
logicalDataView.setUint8(logicalPacketSize - 1, 0xFF);
|
||||||
}
|
|
||||||
|
|
||||||
dataView.setUint8(bufferSize - 1, 0xFF);
|
// 4. 将逻辑大包分包发送
|
||||||
|
const CHUNK_SIZE = 20; // 每个物理包的大小
|
||||||
|
const totalChunks = Math.ceil(logicalPacketSize / CHUNK_SIZE);
|
||||||
|
|
||||||
let inteval = parseInt(this.inteval ? this.inteval : 50);
|
updateLoading(these, {
|
||||||
console.log("inteval=", inteval)
|
text: `准备发送,共 ${totalChunks} 个数据包...`
|
||||||
ble.sendData(f.deviceId, buffer, f.writeServiceId, f
|
|
||||||
.wirteCharactId, 30).then(() => {
|
|
||||||
|
|
||||||
curr++;
|
|
||||||
setTimeout(sendNext, inteval);
|
|
||||||
}).catch(err => {
|
|
||||||
|
|
||||||
if (err.code == '10007') {
|
|
||||||
setTimeout(sendNext, inteval);
|
|
||||||
} else {
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
for (let i = 0; i < totalChunks; i++) {
|
||||||
|
const start = i * CHUNK_SIZE;
|
||||||
|
const end = Math.min(start + CHUNK_SIZE, logicalPacketSize);
|
||||||
|
const chunk = logicalBuffer.slice(start, end);
|
||||||
|
|
||||||
sendNext();
|
updateLoading(these, {
|
||||||
} catch (ex) {
|
text: `正在发送 ${i + 1} / ${totalChunks}`
|
||||||
console.log("ex=", ex);
|
|
||||||
|
|
||||||
reject(ex);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return promise;
|
await ble.sendData(f.deviceId, chunk, f.writeServiceId, f.wirteCharactId, 50);
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 50)); // 包之间延迟
|
||||||
}
|
|
||||||
|
|
||||||
console.log("11111");
|
|
||||||
var result = null;
|
|
||||||
try {
|
|
||||||
console.log("this.$refs.textToHex=", this.$refs.textToHex);
|
|
||||||
result = await this.$refs.textToHex.drawAndGetPixels();
|
|
||||||
} catch (ex) {
|
|
||||||
console.log("ex=", ex);
|
|
||||||
}
|
|
||||||
if (!result) {
|
|
||||||
hideLoading(this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log("result=", result);
|
|
||||||
result = result.map(level1 => {
|
|
||||||
return level1.flat(Infinity);
|
|
||||||
});
|
|
||||||
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 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(',');
|
|
||||||
// let arr2=('0x'+(str2.split(' ').join(",0x"))).split(',');
|
|
||||||
// let arr3=('0x'+(str3.split(' ').join(",0x"))).split(',');
|
|
||||||
|
|
||||||
// result=[arr1,arr2,arr3];
|
|
||||||
|
|
||||||
|
|
||||||
// console.log("result=",result);
|
|
||||||
|
|
||||||
|
|
||||||
let h3dic = [0x06, 0x07, 0x08];
|
|
||||||
let pros = [];
|
|
||||||
let flag = true;
|
|
||||||
for (var i = 0; i < result.length; i++) {
|
|
||||||
|
|
||||||
let str = this.formData.textLines[i];
|
|
||||||
|
|
||||||
if (str.length > 0) {
|
|
||||||
|
|
||||||
let width = str.length * 16;
|
|
||||||
var rgb = result[i];
|
|
||||||
|
|
||||||
try {
|
|
||||||
// console.log("1111");
|
|
||||||
await sendTxtPackge(rgb, h3dic[i], str);
|
|
||||||
// console.log("222222");
|
|
||||||
} catch (ex) {
|
|
||||||
flag = false;
|
|
||||||
console.log("33333");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 5. 发送成功处理
|
||||||
hideLoading(these);
|
hideLoading(these);
|
||||||
if (flag) {
|
|
||||||
console.log("发送成功");
|
|
||||||
this.showPop({
|
this.showPop({
|
||||||
message: "发送成功",
|
message: "发送成功",
|
||||||
iconUrl: "/static/images/6155/DeviceDetail/uploadSuccess.png",
|
iconUrl: "/static/images/6155/DeviceDetail/uploadSuccess.png",
|
||||||
@ -1616,9 +1598,6 @@
|
|||||||
buttonBgColor: '#BBE600'
|
buttonBgColor: '#BBE600'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let json = {
|
let json = {
|
||||||
deviceId: these.device.id,
|
deviceId: these.device.id,
|
||||||
name: these.formData.textLines[1],
|
name: these.formData.textLines[1],
|
||||||
@ -1626,17 +1605,18 @@
|
|||||||
unitName: these.formData.textLines[2],
|
unitName: these.formData.textLines[2],
|
||||||
code: ""
|
code: ""
|
||||||
};
|
};
|
||||||
usrApi.sendUsr(json)
|
usrApi.sendUsr(json);
|
||||||
} else {
|
|
||||||
|
} catch (ex) {
|
||||||
|
hideLoading(these);
|
||||||
this.showPop({
|
this.showPop({
|
||||||
message: "出现异常发送失败",
|
message: "发送失败: " + (ex.msg || ex.message),
|
||||||
iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png",
|
iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png",
|
||||||
borderColor: "#e034344d",
|
borderColor: "#e034344d",
|
||||||
buttonBgColor: "#E03434",
|
buttonBgColor: "#E03434",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
setTimeout(task, 0);
|
setTimeout(task, 0);
|
||||||
},
|
},
|
||||||
getDetail() {
|
getDetail() {
|
||||||
|
|||||||
Reference in New Issue
Block a user