1
0
forked from dyf/APP

Compare commits

...

3 Commits

2 changed files with 142 additions and 82 deletions

View File

@ -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)

View File

@ -77,7 +77,7 @@
<text class="smallTxt">泛光模式</text> <text class="smallTxt">泛光模式</text>
</view> </view>
</view> </view>
<!-- <view class="mode fleft" v-on:click.stop="UploadOpenImg()"> <view class="mode fleft" v-on:click.stop="UploadOpenImg()">
<view class="leftImg"> <view class="leftImg">
<image class="img" src="/static/images/6155/DeviceDetail/open.png" mode="aspectFit"></image> <image class="img" src="/static/images/6155/DeviceDetail/open.png" mode="aspectFit"></image>
</view> </view>
@ -85,8 +85,8 @@
<text class="bigTxt">开机画面</text> <text class="bigTxt">开机画面</text>
<text class="smallTxt">上传</text> <text class="smallTxt">上传</text>
</view> </view>
</view> --> </view>
<view class="mode fleft" 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;
@ -773,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) {
@ -781,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); //包序号
@ -1532,78 +1528,58 @@
var promise = new Promise((resolve, reject) => { var promise = new Promise((resolve, reject) => {
try { try {
// 设备协议FA 06/07/08 01 00 + 256字节数据 + FF
let packetSize = rgbdata.length; //每包均分的数量 // 每个文本行只需要一个261字节的包
let mode = rgbdata.length % packetSize; //最后一包的数量 const bufferSize = 261;
let cnt = const dataSize = 256; // 数据部分固定256字节
1; // parseInt(rgbdata.length / packetSize) + (mode > 0 ? 1 :0); //总包数量
let curr = 1; //当前包序号
let sendNext = () => {
if (curr > cnt) {
resolve();
return;
}
let bufferSize = 261;
console.log("bufferSize=", bufferSize)
let buffer = new ArrayBuffer(bufferSize); let buffer = new ArrayBuffer(bufferSize);
let dataView = new DataView(buffer); let dataView = new DataView(buffer);
let startIndex = (curr - 1) * packetSize;
let endIndex = Math.min(startIndex + packetSize, rgbdata // 写入头部FA 06/07/08 01 00
.length);
if (startIndex > endIndex) {
return;
}
let packetData = rgbdata.slice(startIndex,
endIndex); //取一片数据发送
console.log("packetData.length=", packetData.length);
let start = 0;
if (curr == 1) {
dataView.setUint8(0, 0xFA); dataView.setUint8(0, 0xFA);
dataView.setUint8(1, type); dataView.setUint8(1, type);
dataView.setUint8(2, 0x01); dataView.setUint8(2, 0x01);
dataView.setUint8(3, 0x00); dataView.setUint8(3, 0x00);
// 写入数据最多256字节确保数据是数字格式
start = 4; let actualDataSize = Math.min(rgbdata.length, dataSize);
for (let i = 0; i < actualDataSize; i++) {
// 确保数据是数字格式,如果是字符串则转换
let byteValue = typeof rgbdata[i] === 'string' ? these.toByteValue(rgbdata[i]) : rgbdata[i];
dataView.setUint8(4 + i, byteValue);
} }
for (let i = 0; i < packetData.length; i++) { // 用0填充剩余数据部分如果数据不足256字节
dataView.setUint8(start + i, packetData[i]); for (let i = 4 + actualDataSize; i < bufferSize - 1; i++) {
dataView.setUint8(i, 0x00);
} }
// 写入尾部FF
dataView.setUint8(bufferSize - 1, 0xFF); dataView.setUint8(bufferSize - 1, 0xFF);
let inteval = 100; console.log(`发送文本数据包: type=0x${type.toString(16)}, 数据长度=${actualDataSize}, 总长度=${bufferSize}`);
//parseInt(this.inteval ? this.inteval : 80);
//console.log("inteval=", inteval) // 发送数据包
ble.sendData(f.deviceId, buffer, f.writeServiceId, f ble.sendData(f.deviceId, buffer, f.writeServiceId, f
.wirteCharactId, 30).then(() => { .wirteCharactId, 100).then(() => {
resolve();
curr++;
setTimeout(sendNext, inteval);
}).catch(err => { }).catch(err => {
if (err.code == '10007') { if (err.code == '10007') {
setTimeout(sendNext, inteval); // 重试
setTimeout(() => {
ble.sendData(f.deviceId, buffer, f.writeServiceId, f
.wirteCharactId, 100).then(() => {
resolve();
}).catch(reject);
}, 100);
} else { } else {
reject(err); reject(err);
} }
}); });
}
sendNext();
} catch (ex) { } catch (ex) {
console.log("ex=", ex); console.log("构建数据包异常:", ex);
reject(ex); reject(ex);
} }
}); });
@ -1616,9 +1592,10 @@
var result = null; var result = null;
try { try {
console.log("this.$refs.textToHex=", this.$refs.textToHex); console.log("this.$refs.textToHex=", this.$refs.textToHex);
// 获取像素数据(组件内部会自动预热画布)
result = await this.$refs.textToHex.drawAndGetPixels(); result = await this.$refs.textToHex.drawAndGetPixels();
} catch (ex) { } catch (ex) {
console.log("ex=", ex); console.log("获取画布数据异常:", ex);
} }
if (!result) { if (!result) {
hideLoading(this); hideLoading(this);
@ -1626,7 +1603,10 @@
} }
console.log("result=", result); console.log("result=", result);
result = result.map(level1 => { result = result.map(level1 => {
return level1.flat(Infinity); return level1.flat(Infinity).map(item => {
// 确保数据转换为数字格式,避免字符串格式导致的问题
return typeof item === 'string' ? these.toByteValue(item) : item;
});
}); });
console.log("result=", result); console.log("result=", result);
@ -1647,6 +1627,9 @@
let h3dic = [0x06, 0x07, 0x08]; let h3dic = [0x06, 0x07, 0x08];
let pros = []; let pros = [];
let flag = true; let flag = true;
// 在开始发送前添加延迟,确保数据完全准备好(解决第一次发送第一个字缺失的问题)
await new Promise(resolve => setTimeout(resolve, 500));
for (var i = 0; i < result.length; i++) { for (var i = 0; i < result.length; i++) {
let str = this.formData.textLines[i]; let str = this.formData.textLines[i];
@ -1656,13 +1639,31 @@
let width = str.length * 16; let width = str.length * 16;
var rgb = result[i]; var rgb = result[i];
// 确保数据是数组且已转换
if (!Array.isArray(rgb)) {
console.error(`${i+1}行数据格式错误:`, rgb);
flag = false;
break;
}
// 第一次发送前额外延迟,确保设备完全准备好
if (i === 0) {
console.log("准备发送第一个文本行,等待设备准备好...");
await new Promise(resolve => setTimeout(resolve, 500));
}
try { try {
// console.log("1111"); console.log(`开始发送第${i+1}个文本行 (type=0x${h3dic[i].toString(16)})`);
await sendTxtPackge(rgb, h3dic[i], str); await sendTxtPackge(rgb, h3dic[i], str);
// console.log("222222"); console.log(`${i+1}个文本行发送完成`);
// 每个文本行发送完成后,添加延迟确保设备处理完成
if (i < result.length - 1) {
await new Promise(resolve => setTimeout(resolve, 300));
}
} catch (ex) { } catch (ex) {
flag = false; flag = false;
console.log("33333"); console.error(`发送第${i+1}个文本行出现异常:`, ex);
break; break;
} }
} }