1
0
forked from dyf/APP

650完成,670完成部分

This commit is contained in:
liub
2025-08-25 17:13:13 +08:00
parent 793fe7132b
commit bbf55c58f0
23 changed files with 16897 additions and 221 deletions

View File

@ -25,18 +25,21 @@
onLoad: function(option) {
const eventChannel = this.getOpenerEventChannel();
var these = this;
eventChannel.on('checkImg', function(data) {
eventChannel.on('checkImg', (data)=> {
console.log("我收到你的消息了,消息内容是:" + JSON.stringify(data));
these.src = data.data;
this.src = data.data;
console.log("我收到你的消息了,消息内容是:",data);
})
},
methods: {
handleCrop(e) {
var these = this;
this.Statu = true;
console.log("裁剪完成");
console.log(e.tempFilePath);
//
const ctx = uni.createCanvasContext('splashCanvas', this);
ctx.drawImage(
e.tempFilePath,
@ -53,11 +56,12 @@
height: 80,
success: (res) => {
// 处理像素数据并发送
const eventChannel = these.getOpenerEventChannel();
console.log("res.data.length="+res.data.length);
// this.processAndSendImageData(res.data).then(
// resolve).catch(reject);
const eventChannel = these.getOpenerEventChannel();
eventChannel.emit('ImgCutOver',res.data);
eventChannel.emit('ImgCutOver_Path',e.tempFilePath);
uni.navigateBack();
},
fail: (err) => {

View File

@ -77,7 +77,7 @@
</view>
<view class="mode marginLeft fleft" :class="formData.cMode=='mode'?'':'active'"
v-on:click.stop="UploadOpenImg()">
v-on:click.stop="ShowUpload()">
<view class="leftImg">
<image class="img" src="/static/images/6155/DeviceDetail/open.png" mode="aspectFit"></image>
</view>
@ -89,19 +89,19 @@
<view class="clear"></view>
</view>
<view class="usrinfo">
<view @click="formData.usrToggle=!formData.usrToggle">
<view @click="Status.usrToggle=!Status.usrToggle">
<text class="usrtitle fleft">人员信息登记</text>
<view class="image fright" :style="{transform:formData.usrToggle?'rotate(0deg)':'rotate(180deg)' }">
<view class="image fright" :style="{transform:Status.usrToggle?'rotate(0deg)':'rotate(180deg)' }">
<image class="img" src="/static/images/6155/DeviceDetail/slideToggle.png" mode="aspectFit"></image>
</view>
<view class="clear"></view>
</view>
<view :class="formData.usrToggle?'':'displayNone'">
<view :class="Status.usrToggle?'':'displayNone'">
<view style="margin: 20rpx 0rpx;">
<view class="btnSend fright" v-on:click.stop="sendUsr">发送</view>
<view class="btnSend fright" v-on:click.stop="sendUsr(null)">发送</view>
<view class="clear"></view>
</view>
<view class="item">
@ -235,7 +235,7 @@
maskBgColor: '#00000066',
showClose: false
},
usrToggle: true,
},
formData: {
img: '/static/images/6155/DeviceDetail/equip.png',
@ -251,17 +251,14 @@
macAddress: '',
cMode: false,
modeCurr: 'low',
usrToggle: true,
company: '黄石消防支队',
name: '菜英俊',
job: '小队长',
id: 'HSXF01061',
iswarn: false
},
rgb565Data: [],
videoHexArray: []
}
},
@ -377,19 +374,41 @@
return className;
},
bleValueNotify: function(receive, device, path) { //订阅消息
let data = recei.ReceiveData(receive, device, pagePath);
console.log("收到设备的数据",data)
if (data) {
console.log("收到订阅消息", receive);
if ("staBlue_picture" in data) {
//重发图片
console.log("收到重新发送图片的命令");
this.checkImgUpload('img', data.staBlue_picture);
return;
} else if ("staBlue_text" in data) {
//重发文本
console.log("收到重新发送文本的命令");
this.sendUsr(data.staBlue_text);
return;
} else if ("staBlue_vidio" in data) {
//重发视频
console.log("收到重新发送视频的命令");
this.checkImgUpload('video', data.staBlue_vidio);
return;
} else if ("staBlue" in data) {
if (data.staBlue == "finish") {
console.log("收到设备回复,全部传输完成");
}
return;
}
let keys = Object.keys(data);
for (var i = 0; i < keys.length; i++) {
let key = keys[i];
these.formData[key] = data[key];
if(key in these.formData){
these.formData[key] = data[key];
}
}
if (these.formData.iswarn) {
these.showPop({
message: "环境存在漏电电源",
@ -398,7 +417,7 @@
buttonBgColor: "#E03434",
});
}
these.setBleFormData();
}
@ -412,8 +431,8 @@
},
getDevice: function() {
console.log("LinkedList=", ble.data.LinkedList);
console.log("formData=", these.formData);
// console.log("LinkedList=", ble.data.LinkedList);
// console.log("formData=", these.formData);
let f = ble.data.LinkedList.find((v) => {
return v.deviceId == these.formData.deviceId;
});
@ -558,33 +577,22 @@
}
});
},
checkImgUpload: function() {
checkImgUpload: function(type, index) {
console.log("123213213213");
// 处理像素数据并发送
var processAndSendImageData = function(pixels) {
return new Promise((resolve, reject) => {
// 创建RGB565格式的像素数据
const rgb565Data = ble.convertToRGB565(pixels);
// 分包发送
sendImagePackets(rgb565Data).then(resolve).catch(reject);
});
}
let f = these.getDevice();
// 分包发送图片数据
var sendImagePackets = function(imageData) {
var sendImagePackets = function(ReSendNo) {
return new Promise((resolve, reject) => {
// 总数据包数
const totalPackets = 52;
let totalPackets = 52;
let currentPacket = 1;
let f = these.getDevice();
if (ReSendNo) {
totalPackets = ReSendNo;
currentPacket = ReSendNo;
}
if (f) {
// 发送单个数据包
@ -597,6 +605,13 @@
message: "上传成功",
iconUrl: "/static/images/6155/DeviceDetail/uploadSuccess.png",
});
if (!ReSendNo) {
setTimeout(()=>{
these.HoldYouHand("transmit complete", 0, f.deviceId, f
.writeServiceId, f.wirteCharactId);
},500);
}
resolve();
return;
@ -604,23 +619,23 @@
// 计算当前包的数据
let packetSize = 250;
if (currentPacket <= 51) {
packetSize = 250; // 前51个包每个500字节
} else {
packetSize = 50; // 最后一个包100字节
}
// if (currentPacket <= 51) {
// packetSize = 250; // 前51个包每个500字节
// } else {
// packetSize = 50; // 最后一个包100字节
// }
// 创建数据包
const startIndex = (currentPacket - 1) * packetSize;
const endIndex = Math.min(startIndex + packetSize, imageData
const endIndex = Math.min(startIndex + packetSize, these.rgb565Data
.length);
if (startIndex > endIndex) {
return;
}
const packetData = imageData.slice(startIndex,
const packetData = these.rgb565Data.slice(startIndex,
endIndex);
// 构建数据包
const bufferSize = 5 + packetData.length * 2; // 头部5字节 + 数据部分
const bufferSize =505;// 5 + packetData.length * 2; // 头部5字节 + 数据部分
const buffer = new ArrayBuffer(bufferSize);
const dataView = new DataView(buffer);
@ -644,6 +659,11 @@
dataView.setUint16(5 + i * 2, packetData[i], false); // 大端字节序
}
if (currentPacket > 51) { //第52包补FF
for (var i = 105; i < bufferSize; i++) {
dataView.setUint8(i, 0xFF);
}
}
@ -681,7 +701,10 @@
});
}
if (ReSendNo) {
sendNextPacket(ReSendNo);
return;
}
// 开始牵手
these.HoldYouHand("picture transmit start", 120, f.deviceId, f.writeServiceId,
f.wirteCharactId).then(() => {
@ -713,8 +736,9 @@
});
these.Status.BottomMenu.show = false;
these.rgb565Data = ble.convertToRGB565(data);
setTimeout(function() {
processAndSendImageData(data).catch(() => {
sendImagePackets().catch(() => {
});
}, 0)
@ -730,6 +754,137 @@
});
}
let sendVideoPackets = (ReSendNo) => {
console.log("开始发送分片数据");
return new Promise((resolve, reject) => {
if (f) {
// 总数据包数
var totalPackets = 1536;
let currentPacket = 1;
console.log("发送数据准备中,总共" + totalPackets);
if (ReSendNo) {
totalPackets = ReSendNo;
currentPacket = ReSendNo;
}
this.totalPackets = totalPackets;
// 发送单个数据包
const sendNextVideoPacket = () => {
console.log("准备发送一段数据");
if (currentPacket > totalPackets) {
if (!ReSendNo) {
setTimeout(()=>{
these.HoldYouHand("transmit complete", 0, f.deviceId, f
.writeServiceId, f.wirteCharactId).then(()=>{
console.log("全部发送完毕")
}).catch((ex)=>{
console.log("出现异常",ex);
});
},500);
}
these.Status.BottomMenu.show = false;
hideLoading(these);
these.showPop({
showPop: true,
message: "上传成功",
iconUrl: "/static/images/6155/DeviceDetail/uploadSuccess.png"
});
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 = 506; // 头部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(6 + i, '0x' + packetData[i]);
}
let inteval = 50;
console.log("开始发送一段视频"); //
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("发送失败了");
if (err.code == '10007') { //遇到这个错误自动重新发送
console.log(err.errMsg + ",发送失败了,正在补偿:" +
currentPacket);
setTimeout(sendNextVideoPacket, inteval);
} else {
these.Status.BottomMenu.show = false;
hideLoading(these);
these.showPop({
showPop: true,
message: err.msg + ",发送失败了",
borderColor: "#e034344d",
buttonBgColor: "#E03434",
buttonText: "确定",
iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png"
});
reject(err);
return;
}
});
};
sendNextVideoPacket();
} else {
console.log("Fail.......")
}
});
}
var sendVideo = (videoPath) => {
let uploadVideo = () => {
@ -740,7 +895,7 @@
}
console.log("开始处理,正在上传");
let f = this.getDevice();
showLoading(these, {
text: "上传中"
});
@ -809,123 +964,13 @@
})
}
let f = these.getDevice();
console.log("f=", f);
let sendVideoPackets = (imageData) => {
console.log("开始发送分片数据");
return new Promise((resolve, reject) => {
if (f) {
// 总数据包数
const totalPackets = 1536;
this.totalPackets = totalPackets;
let currentPacket = 1;
console.log("发送数据准备中,总共" + totalPackets);
// 发送单个数据包
const sendNextVideoPacket = () => {
console.log("准备发送一段数据");
if (currentPacket > totalPackets) {
these.Status.BottomMenu.show = false;
hideLoading(these);
these.showPop({
showPop: true,
message: "上传成功",
iconUrl: "/static/images/6155/DeviceDetail/uploadSuccess.png"
});
these.videoHexArray = [];
resolve();
return;
}
// 计算当前包的数据
let packetSize = 500;
// 创建数据包
const startIndex = (currentPacket - 1) * packetSize;
const endIndex = Math.min(startIndex + packetSize, imageData
.length);
if (startIndex > endIndex) {
resolve();
return;
}
////console.log("111111");
const packetData = imageData.slice(startIndex, endIndex);
// 构建数据包
////console.log("packetData.length"+packetData.length);
const bufferSize = 506; // 头部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(6 + i, '0x' + packetData[i]);
}
let inteval = 50;
console.log("开始发送一段视频"); //
ble.sendData(f.deviceId, buffer, f.writeServiceId, f
.wirteCharactId, 10).then(() => {
updateLoading(these, {
text: "正在发送:" + currentPacket + "/" +
totalPackets
})
currentPacket++;
console.log("发送一段成功,发送下一段");
setTimeout(sendNextVideoPacket, inteval);
}).catch(err => {
if (err.code == '10007') { //遇到这个错误自动重新发送
console.log(err.errMsg + ",发送失败了,正在补偿:" +
currentPacket);
setTimeout(sendNextVideoPacket, inteval);
} else {
these.Status.BottomMenu.show = false;
hideLoading(these);
these.showPop({
showPop: true,
message: err.msg + ",发送失败了",
borderColor: "#e034344d",
buttonBgColor: "#E03434",
buttonText: "确定",
iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png"
});
reject(err);
return;
}
});
};
sendNextVideoPacket();
} else {
console.log("Fail.......")
}
});
}
let shotVideoClick = (array) => {
let shotVideoClick = () => {
console.log("正在开始发送");
sendVideoPackets(array).then(() => {
sendVideoPackets().then(() => {
console.log("发送完成");
}).catch((ex1) => {
@ -940,6 +985,14 @@
}
if (type) {
if (type == 'img') {
sendImagePackets(index);
} else if (type == 'video') {
sendVideoPackets(index);
}
return;
}
uni.chooseMedia({
count: 1,
mediaType: ['image', 'video'],
@ -968,16 +1021,9 @@
}
});
// uni.chooseImage({
// count: 1,
// sizeType: ['original', 'compressed'],
// sourceType: ['album'],
// success: function(res) {
// gotoCutImg(res.tempFiles[0].path);
// }
// });
},
UploadOpenImg: function() {
ShowUpload: function() {
//上传开机画面
this.Status.BottomMenu.menuItems = [];
this.Status.BottomMenu.title = "上传开机画面";
@ -1043,7 +1089,7 @@
}
these.Status.Pop.showPop = true;
},
sendUsr: function() {
sendUsr: function(ReSendNo) {
@ -1052,7 +1098,6 @@
this.formData.name,
this.formData.job,
this.formData.id
];
@ -1070,17 +1115,28 @@
text: "请稍候..."
});
var sendText = function() {
// 总数据包数
const totalPackets = textLines.length;
let totalPackets = textLines.length;
let currentPacket = 1;
// console.log("currentPacket=",currentPacket);
// console.log("ReSendNo=",ReSendNo);
if (ReSendNo) {
totalPackets = ReSendNo;
currentPacket = ReSendNo;
}
// console.log("currentPacket=",currentPacket);
// 发送单个数据包
const sendNextPacket = () => {
if (currentPacket > totalPackets) {
if (!ReSendNo) {
setTimeout(()=>{
these.HoldYouHand("transmit complete", 0, f.deviceId, f.writeServiceId, f
.wirteCharactId);
},500);
}
these.showPop({
showPop: true, //是否显示弹窗
popType: 'custom',
@ -1107,9 +1163,9 @@
let arr = gbk.encode(text)
let gbkData = gbk.arr2hex(arr);
console.log(JSON.stringify(gbkData));
// 构建数据包
const bufferSize = 5 + text.length * 2; // 头部4字节 + 数据部分
const bufferSize = 5 + gbkData.length / 2; // 头部4字节 + 数据部分
const buffer = new ArrayBuffer(bufferSize);
const dataView = new DataView(buffer);
@ -1118,19 +1174,16 @@
dataView.setUint8(1, 0x03); // 帧类型:文字
dataView.setUint8(2, currentPacket.toString(16)); // 包序号
dataView.setUint16(3, (text.length * 2).toString(16)); // 数据长度
console.log("gbkData.length=" + gbkData.length)
// 填充数据
for (let i = 1; i <= text.length * 2; i++) {
const highNibble = gbkData[i * 2 - 2]; // 高4位
const lowNibble = gbkData[i * 2 - 1]; // 低4位如果是奇数长度补0
//console.log("i=" + i + "," + highNibble + lowNibble)
// 组合高低位并转换为字节值
const byteValue = parseInt(highNibble + lowNibble, 16);
dataView.setUint8(5 + i - 1, byteValue);
// 填充数据
let index = 0;
for (var i = 0; i < gbkData.length; i += 2) {
let value = parseInt(gbkData[i] + "" + gbkData[i + 1], 16);
dataView.setUint8(5 + index, value);
index++;
}
console.log("dataView.length=" + dataView.byteLength)
// 发送数据包
@ -1166,7 +1219,10 @@
}
if(ReSendNo){
sendText(ReSendNo);
return;
}
setTimeout(() => {
these.HoldYouHand("word transmit start", 120, f.deviceId, f.writeServiceId, f
.wirteCharactId).then(

1841
pages/670/HBY670.vue Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,472 @@
<template>
<view class="content">
<canvas canvas-id="flashCanvas"
style="width: 160px; height: 80px; z-index: 9999;position: fixed; top:-9999px;left:-9999px;"></canvas>
<f-video ref="compARef" :src="videoPath" :direction="-90" :autoplay="true" @shotVideoClick="shotVideoClick"
:videoWidth="videoWidth" :videoHeight="videoHeight"></f-video>
<view>
<text>发送间隔</text>
<input type="text" v-model="inteval" />
</view>
<view>
<button @click="checkVideo">选择视频</button>
<!-- <button @click="CutImg">发送</button> -->
<button @click="uploadVideo">发送</button>
</view>
<view class="sending-progress" v-if="isSending">
<view class="progress-bar">
<view class="progress-fill" :style="{ width: progress + '%' }"></view>
</view>
<text>正在发送: {{ progress }}% ({{ currentPacket }}/{{ totalPackets }})</text>
</view>
</view>
</template>
<script>
import Common from '@/utils/Common';
export default {
data() {
return {
videoPath: '',
inteval: 0,
progress: 0,
currentPacket: 0,
totalPackets: 100,
connectedDeviceId: '',
serviceId: '0xFFE1',
writeCharacteristicId: '0xFFE1',
notifyCharacteristicId: '0xFFE2',
isSending: "",
textProgress: "",
imgs: [],
videoWidth: 320,
videoHeight: 160,
videoDuration: 2,
hexArray: []
}
},
onLoad() {
const eventChannel = this.getOpenerEventChannel();
eventChannel.on('receiveDevice', (data) => {
this.connectedDeviceId = data.connectedDeviceId;
this.serviceId = data.serviceId;
this.writeCharacteristicId = data.writeCharacteristicId;
this.notifyCharacteristicId = data.notifyCharacteristicId;
})
},
methods: {
checkVideo: function() {
uni.chooseVideo({
sourceType: ['album', 'camera'],
compressed: false,
maxDuration: 2,
camera: 'back',
success: (res) => {
this.videoPath = res.tempFilePath;
this.imgs = [];
this.hexArray = [];
this.$refs.compARef.base64 = [];
this.videoWidth = res.width;
this.videoHeight = res.height;
this.videoDuration = res.duration;
console.log("视频宽:" + res.width + ",视频高:" + res.height + ",视频时长:" + res.duration);
}
})
},
uploadVideo: function() {
if (this.hexArray.length > 0) {
console.log("开始处理,无需上传");
this.shotVideoClick(this.hexArray, 'rgb565');
return;
}
if(!this.videoPath){
uni.showToast({
title: "请选择视频",
icon: 'fail'
})
return;
}
console.log("正在上传视频");
uni.showLoading({
title: "上传中"
});
let p2=new Promise((resolve,reject)=>{
let start = new Date();
console.log("Common.baseURL="+Common.baseURL);
uni.uploadFile({
url:Common.baseURL+'video/upload',
filePath: this.videoPath,
name: 'file',
header: {
"Method": "POST",
"Content-Type": "multipart/form-data"
},
timeout: 600000,
fail: (ex) => {
//console.log("上传视频失败" + JSON.stringify(ex));
uni.showToast({
title: "视频文件上传失败了,请检查网络连接",
icon: 'fail'
})
uni.hideLoading();
reject(ex);
},
success: (res) => {
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff - s) / 60;
console.log("上传完成,耗时:" + m + "分" + s + "秒");
uni.hideLoading();
resolve(res);
}
});
});
let p1=this.HoldYouHand();
Promise.all([p2,p1]).then((arr)=>{
if(arr[1]===true){
let res=arr[0];
res = JSON.parse(res.data);
if (res.data) {
this.hexArray = res.data;
uni.showLoading({
title: "正在发送"
});
setTimeout(() => {
this.shotVideoClick(res.data, 'rgb565');
}, 0)
} else {
console.log("res")
uni.showModal({
content: "服务器未返回RGB565数据",
title: '错误'
})
}
}else{
uni.showModal({
content:"与设备握手失败了",
title:"错误"
})
}
});
},
shotVideoClick: function(array, type) {
//console.log("处理视频完成", array);
//console.log("type=" + type)
//console.log("array=", array);
this.imgs = array;
var sendImagePackets = (imageData) => {
return new Promise((resolve, reject) => {
this.isSending = true;
this.progress = 0;
this.currentPacket = 0;
// 总数据包数
const totalPackets = 1536;
this.totalPackets = totalPackets;
let currentPacket = 1;
// 发送单个数据包
const sendNextPacket = () => {
////console.log("currentPacket="+currentPacket+",imageData.length="+imageData.length);
if (currentPacket > totalPackets) {
this.isSending = false;
resolve();
return;
}
// 计算当前包的数据
let packetSize = 250;
if (type == 'rgb565') {
packetSize = 500;
}
// 创建数据包
const startIndex = (currentPacket - 1) * packetSize;
const endIndex = Math.min(startIndex + packetSize, imageData.length);
if (startIndex > endIndex) {
resolve();
return;
}
////console.log("111111");
const packetData = imageData.slice(startIndex, endIndex);
// 构建数据包
////console.log("packetData.length"+packetData.length);
const bufferSize = 506; // 头部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);
if (type == 'rgb565') {
for (let i = 0; i < packetData.length; i++) {
dataView.setUint8(6 + i, '0x' + packetData[i]);
}
} else {
for (let i = 0; i < packetData.length; i++) {
dataView.setUint16(6 + i * 2, packetData[i], false);
}
}
let inteval = parseInt(this.inteval ? this.inteval : 0);
this.sendData(buffer).then(() => {
// 更新进度
this.currentPacket = currentPacket;
this.progress = Math.round((currentPacket / totalPackets) *
100);
//console.log(`发送数据包完成 ${currentPacket}/${totalPackets}`);
// 发送下一个包(添加延迟避免蓝牙缓冲区溢出)
currentPacket++;
setTimeout(sendNextPacket, inteval);
}).catch(err => {
// console.log(err.errMsg + ",发送失败了,正在补偿:" + currentPacket);
setTimeout(sendNextPacket, inteval);
// uni.showToast({
// title:"发送失败"+JSON.stringify(err)
// })
});
};
sendNextPacket();
});
}
if (type == 'rgb565') {
let start = new Date();
console.log("开始发送");
sendImagePackets(array).then(() => {
console.log("发送完成");
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff-s) / 60;
console.log("发送完成,耗时:" + m + "分" + s + "秒");
uni.showToast({
title: "发送完成,耗时:" + m + "分" + s + "秒",
icon: 'success'
})
}).catch((ex1) => {
//console.log("出现了异常", ex1)
}).finally(() => {
uni.hideLoading();
});
return;
}
},
HoldYouHand() {
var promise=new Promise((resolve,reject)=>{
try{
let start=new Date();
var str = "video transmit start"; //握手的协议字符串
console.log("开始握手:"+str)
// 1. 创建 ArrayBuffer 和 DataView
const buffer = new ArrayBuffer(str.length);
const dataView = new DataView(buffer);
// 2. 将字符串转换为 ASCII 码并写入 DataView
for (let i = 0; i < str.length; i++) {
dataView.setUint8(i, str.charCodeAt(i));
}
//console.log("111111");
this.sendData(buffer).then(() => {
// 开始发送第一个包
setTimeout(()=>{
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff - s) / 60;
console.log("握手成功并完成2200ms等待,耗时"+m+"分"+s+"秒");
resolve(true);
}, 2200);
}).catch(err => {
//console.log("握手没有成功");
reject(err);
});
}catch(ex){
reject(ex);
}
});
return promise;
},
sendData(buffer) {
////console.log("deviceId=" + this.connectedDeviceId);
////console.log("serviceId=" + this.serviceId);
return new Promise(async (resolve, reject) => {
// //console.log("开始发送数据buffer");
var promise = new Promise((succ, err) => {
uni.writeBLECharacteristicValue({
deviceId: this.connectedDeviceId,
serviceId: this.serviceId,
characteristicId: this.writeCharacteristicId,
value: buffer,
writeType: plus.os.name == 'iOS' ? 'write' : 'writeNoResponse',
success: () => {
// //console.log("发送数据成功");
succ();
},
fail: (ex) => {
//console.log("发送数据失败", ex);
err(ex);
},
complete: function() {
// //console.log("123456");
}
});
});
if (plus.os.name == 'iOS') {
function timeout(ms) {
return new Promise((_, err) => {
setTimeout(() => {
err({
code: -1,
errMsg: '超时了'
})
}, ms);
});
}
let inteval = parseInt(this.inteval ? this.inteval : 0);
Promise.race([promise, timeout(inteval)]).then(resolve).catch((ex) => {
//console.log("ex=", ex);
if (ex.code == -1) {
resolve();
} else {
reject();
}
}).finally(() => {
//console.log("完成了")
});
} else {
promise.then(resolve).catch(reject);
}
});
},
CutImg: function() {
if (this.imgs.length == 30) {
this.shotVideoClick(this.imgs, 'img');
return;
}
//console.log("开始处理视频")
uni.showLoading({
title: '开始处理'
});
this.$refs.compARef.shotVideoClick(0);
}
}
}
</script>
<style>
.sending-progress {
margin-top: 30rpx;
width: 100%;
}
.progress-bar {
height: 12rpx;
background-color: #e0e0e0;
border-radius: 6rpx;
overflow: hidden;
}
.progress-fill {
height: 100%;
background-color: #409eff;
transition: width 0.3s;
}
input {
border: 2rpx solid #000000;
}
button {
height: 100rpx;
line-height: 100rpx;
font-size: 28rpx;
float: left;
}
.content {
width: 100vw;
height: 300px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>

View File

@ -0,0 +1,517 @@
<template>
<view class="content">
<canvas canvas-id="flashCanvas"
style="width: 160px; height: 80px; z-index: 9999;position: fixed; top:-9999px;left:-9999px;"></canvas>
<f-video ref="compARef" :src="videoPath" :direction="-90" :autoplay="true" @shotVideoClick="shotVideoClick"
:videoWidth="videoWidth" :videoHeight="videoHeight"></f-video>
<view>
<text>并发包数量</text>
<input type="text" v-model="packgeCnt" />
</view>
<view>
<text>发送间隔</text>
<input type="text" v-model="inteval" />
</view>
<view>
<button @click="checkVideo">选择视频</button>
<!-- <button @click="CutImg">发送</button> -->
<button @click="uploadVideo">发送</button>
</view>
<view class="sending-progress" v-if="isSending">
<view class="progress-bar">
<view class="progress-fill" :style="{ width: progress + '%' }"></view>
</view>
<text>正在发送: {{ progress }}% ({{ currentPacket }}/{{ totalPackets }})</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
videoPath: '',
packgeCnt: 20,
inteval: 0,
progress: 0,
currentPacket: 0,
totalPackets: 100,
connectedDeviceId: '',
serviceId: '0xFFE1',
writeCharacteristicId: '0xFFE1',
notifyCharacteristicId: '0xFFE2',
isSending: "",
textProgress: "",
imgs: [],
videoWidth: 320,
videoHeight: 160,
videoDuration: 2,
hexArray: []
}
},
onLoad() {
const eventChannel = this.getOpenerEventChannel();
eventChannel.on('receiveDevice', (data) => {
this.connectedDeviceId = data.connectedDeviceId;
this.serviceId = data.serviceId;
this.writeCharacteristicId = data.writeCharacteristicId;
this.notifyCharacteristicId = data.notifyCharacteristicId;
})
},
methods: {
checkVideo: function() {
uni.chooseVideo({
sourceType: ['album', 'camera'],
compressed: false,
maxDuration: 2,
camera: 'back',
success: (res) => {
this.videoPath = res.tempFilePath;
this.imgs = [];
this.hexArray = [];
this.$refs.compARef.base64 = [];
this.videoWidth = res.width;
this.videoHeight = res.height;
this.videoDuration = res.duration;
console.log("视频宽:" + res.width + ",视频高:" + res.height + ",视频时长:" + res.duration);
}
})
},
uploadVideo: function() {
if (this.hexArray.length > 0) {
console.log("开始处理,无需上传");
this.shotVideoClick(this.hexArray, 'rgb565');
return;
}
if(!this.videoPath){
uni.showToast({
title: "请选择视频",
icon: 'fail'
})
return;
}
console.log("正在上传视频");
uni.showLoading({
title: "上传中"
});
let p2=new Promise((resolve,reject)=>{
console.log("Common.baseURL="+Common.baseURL);
let start = new Date();
uni.uploadFile({
url: Common.baseURL+'video/upload',
// url: 'http://192.168.110.169:5000/video/upload',
filePath: this.videoPath,
name: 'file',
header: {
"Method": "POST",
"Content-Type": "multipart/form-data"
},
timeout: 600000,
fail: (ex) => {
//console.log("上传视频失败" + JSON.stringify(ex));
uni.showToast({
title: "视频文件上传失败了,请检查网络连接",
icon: 'fail'
})
uni.hideLoading();
reject(ex);
},
success: (res) => {
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff - s) / 60;
console.log("上传完成,耗时:" + m + "分" + s + "秒");
uni.hideLoading();
resolve(res);
}
});
});
let p1=this.HoldYouHand();
Promise.all([p2,p1]).then((arr)=>{
if(arr[1]===true){
let res=arr[0];
res = JSON.parse(res.data);
if (res.data) {
this.hexArray = res.data;
uni.showLoading({
title: "正在发送"
});
setTimeout(() => {
this.shotVideoClick(res.data, 'rgb565');
}, 0)
} else {
console.log("res")
uni.showModal({
content: "服务器未返回RGB565数据",
title: '错误'
})
}
}else{
uni.showModal({
content:"与设备握手失败了",
title:"错误"
})
}
});
},
pause(e) {
////console.log('pause--------------------------', e);
},
shotVideoClick: function(array, type) {
//console.log("处理视频完成", array);
//console.log("type=" + type)
//console.log("array=", array);
this.imgs = array;
var sendImagePackets = (imageData) => {
return new Promise((resolve, reject) => {
this.isSending = true;
this.progress = 0;
this.currentPacket = 0;
// 总数据包数
const totalPackets = 1536;
this.totalPackets = totalPackets;
let currentPacket = 1;
let promises = [];
// 发送单个数据包
const sendNextPacket = () => {
////console.log("currentPacket="+currentPacket+",imageData.length="+imageData.length);
if (currentPacket > totalPackets) {
this.isSending = false;
resolve();
return;
}
// 计算当前包的数据
let packetSize = 250;
if (type == 'rgb565') {
packetSize = 500;
}
// 创建数据包
const startIndex = (currentPacket - 1) * packetSize;
const endIndex = Math.min(startIndex + packetSize, imageData.length);
if (startIndex > endIndex) {
resolve();
return;
}
////console.log("111111");
const packetData = imageData.slice(startIndex, endIndex);
// 构建数据包
////console.log("packetData.length"+packetData.length);
const bufferSize = 506; // 头部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);
if (type == 'rgb565') {
for (let i = 0; i < packetData.length; i++) {
dataView.setUint8(6 + i, '0x' + packetData[i]);
}
} else {
for (let i = 0; i < packetData.length; i++) {
dataView.setUint16(6 + i * 2, packetData[i], false);
}
}
let inteval = parseInt(this.inteval ? this.inteval : 0);
let promise = this.sendData(buffer);
promises.push(promise);
let packgeCnt = parseInt(this.packgeCnt || 20);
if (currentPacket % packgeCnt == 0 || (currentPacket >= totalPackets &&
promises.length > 0)) {
Promise.all(promises).then(() => {
if (currentPacket >= totalPackets) {
this.isSending = false;
resolve();
return;
}
this.currentPacket = currentPacket;
this.progress = Math.round((currentPacket / totalPackets) *
100);
currentPacket++;
setTimeout(sendNextPacket, inteval);
})
} else {
currentPacket++;
sendNextPacket();
}
// .then(() => {
// // 更新进度
// this.currentPacket = currentPacket;
// this.progress = Math.round((currentPacket / totalPackets) *
// 100);
// currentPacket++;
// setTimeout(sendNextPacket, inteval);
// }).catch(err => {
// console.log(err.errMsg+",发送失败了,正在补偿:" + currentPacket);
// setTimeout(sendNextPacket, inteval);
// });
};
//
sendNextPacket();
});
}
if (type == 'rgb565') {
let start = new Date();
console.log("开始发送");
sendImagePackets(array).then(() => {
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff - s) / 60;
console.log("发送完成,耗时:" + m + "分" + s + "秒");
uni.showToast({
title: "发送完成,耗时:" + m + "分" + s + "秒",
icon: 'success',
})
}).catch((ex1) => {
//console.log("出现了异常", ex1)
}).finally(() => {
uni.hideLoading();
});
return;
}
},
HoldYouHand() {
var promise=new Promise((resolve,reject)=>{
try{
let start=new Date();
var str = "video transmit start"; //握手的协议字符串
console.log("开始握手:"+str)
// 1. 创建 ArrayBuffer 和 DataView
const buffer = new ArrayBuffer(str.length);
const dataView = new DataView(buffer);
// 2. 将字符串转换为 ASCII 码并写入 DataView
for (let i = 0; i < str.length; i++) {
dataView.setUint8(i, str.charCodeAt(i));
}
//console.log("111111");
this.sendData(buffer).then(() => {
// 开始发送第一个包
setTimeout(()=>{
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff - s) / 60;
console.log("握手成功并完成2200ms等待,耗时"+m+"分"+s+"秒");
resolve(true);
}, 2200);
}).catch(err => {
//console.log("握手没有成功");
reject(err);
});
}catch(ex){
reject(ex);
}
});
return promise;
},
sendData(buffer) {
let sendBuffer = () => {
return new Promise((resolve, reject) => {
var promise = new Promise((succ, err) => {
uni.writeBLECharacteristicValue({
deviceId: this.connectedDeviceId,
serviceId: this.serviceId,
characteristicId: this.writeCharacteristicId,
value: buffer,
writeType: plus.os.name == 'iOS' ? 'write' : 'writeNoResponse',
success: () => {
// console.log("发送数据成功");
succ();
},
fail: (ex) => {
if (ex.code == '10007') {
// console.log("失败重试");
setTimeout(() => {
sendBuffer().then(succ).catch(err);
}, this.inteval || 0)
// succ()
} else
{
// console.log("发送数据失败",ex);
err(ex);
}
},
complete: function() {
//console.log("123456");
}
});
});
if (plus.os.name == 'iOS') {
function timeout(ms) {
return new Promise((_, err) => {
setTimeout(() => {
err({
code: -1,
errMsg: '超时了'
})
}, ms);
});
}
Promise.race([promise, timeout(this.inteval ? this.inteval : 0)]).then(() => {
// console.log("成功了");
resolve();
})
.catch((ex) => {
if (ex.code == -1) {
// console.log("超时了")
resolve();
} else {
reject(ex);
// console.log("异常了", ex);
//sendBuffer().then(resolve).catch(reject);
}
});
} else {
promise.then(() => {
//console.log("then........")
resolve();
}).catch(() => {
//console.log("catch.........")
reject()
});
}
});
}
return sendBuffer();
},
CutImg: function() {
if (this.imgs.length == 30) {
this.shotVideoClick(this.imgs, 'img');
return;
}
//console.log("开始处理视频")
uni.showLoading({
title: '开始处理'
});
this.$refs.compARef.shotVideoClick(0);
}
}
}
</script>
<style>
.sending-progress {
margin-top: 30rpx;
width: 100%;
}
.progress-bar {
height: 12rpx;
background-color: #e0e0e0;
border-radius: 6rpx;
overflow: hidden;
}
.progress-fill {
height: 100%;
background-color: #409eff;
transition: width 0.3s;
}
input {
border: 2rpx solid #000000;
}
button {
height: 100rpx;
line-height: 100rpx;
font-size: 28rpx;
float: left;
}
.content {
width: 100vw;
height: 300px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>

View File

@ -0,0 +1,537 @@
<template>
<view class="content">
<canvas canvas-id="flashCanvas"
style="width: 160px; height: 80px; z-index: 9999;position: fixed; top:-9999px;left:-9999px;"></canvas>
<view>
<view>
选择的视频:{{videoPath}}</view>
</view>
<view>
重发包序号:{{reSendNumber}}
</view>
<view>
<text>发送间隔</text>
<input type="text" v-model="inteval" />
</view>
<view>
<button @click="checkVideo">选择视频</button>
<button @click="uploadVideo">发送</button>
</view>
<view class="sending-progress" v-if="isSending">
<view class="progress-bar">
<view class="progress-fill" :style="{ width: progress + '%' }"></view>
</view>
<text>正在发送: {{ progress }}% ({{ currentPacket }}/{{ totalPackets }})</text>
</view>
</view>
</template>
<script>
import Common from '../../../utils/Common';
var mqttClient=null;
export default {
data() {
return {
videoPath: '',
inteval: 0,
progress: 0,
currentPacket: 0,
totalPackets: 100,
connectedDeviceId: '',
serviceId: '0xFFE1',
writeCharacteristicId: '0xFFE1',
notifyCharacteristicId: '0xFFE2',
isSending: "",
textProgress: "",
netMode:"ble",
IMEI:"",
imgs: [],
videoWidth: 320,
videoHeight: 160,
videoDuration: 2,
hexArray: [],
reSendNumber:""
}
},
onLoad() {
const eventChannel = this.getOpenerEventChannel();
eventChannel.on('receiveDevice', (data) => {
this.connectedDeviceId = data.connectedDeviceId;
this.serviceId = data.serviceId;
this.writeCharacteristicId = data.writeCharacteristicId;
this.notifyCharacteristicId = data.notifyCharacteristicId;
this.netMode=data.netMode;
mqttClient=data.mqttClient;
this.IMEI=data.IMEI;
});
eventChannel.on('ReSendVideo',(data)=>{
//重新发送某一包
this.reSendNumber=data.videoNo;
setTimeout(()=>{
this.shotVideoClick(this.hexArray,'rgb565',data.videoNo);
},0);
});
},
methods: {
checkVideo: function() {
uni.chooseVideo({
sourceType: ['album', 'camera'],
compressed: false,
maxDuration: 2,
camera: 'back',
success: (res) => {
this.videoPath = res.tempFilePath;
this.imgs = [];
this.hexArray = [];
this.videoWidth = res.width;
this.videoHeight = res.height;
this.videoDuration = res.duration;
console.log("视频宽:" + res.width + ",视频高:" + res.height + ",视频时长:" + res.duration);
}
})
},
uploadVideo: function() {
if (this.hexArray.length > 0) {
console.log("开始处理,无需上传");
this.shotVideoClick(this.hexArray, 'rgb565');
return;
}
if(!this.videoPath){
uni.showToast({
title: "请选择视频",
icon: 'fail'
})
return;
}
console.log("正在上传视频");
uni.showLoading({
title: "上传中"
});
let p2=new Promise((resolve,reject)=>{
let start = new Date();
console.log("Common.baseURL="+Common.baseURL);
uni.uploadFile({
url:Common.baseURL+'video/upload',
filePath: this.videoPath,
name: 'file',
header: {
"Method": "POST",
"Content-Type": "multipart/form-data"
},
timeout: 600000,
fail: (ex) => {
//console.log("上传视频失败" + JSON.stringify(ex));
uni.showToast({
title: "视频文件上传失败了,请检查网络连接",
icon: 'fail'
})
uni.hideLoading();
reject(ex);
},
success: (res) => {
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff - s) / 60;
console.log("上传完成,耗时:" + m + "分" + s + "秒");
uni.hideLoading();
resolve(res);
}
});
});
let p1=this.HoldYouHand();
Promise.all([p2,p1]).then((arr)=>{
if(arr[1]===true){
let res=arr[0];
res = JSON.parse(res.data);
if (res.data) {
this.hexArray = res.data;
uni.showLoading({
title: "正在发送"
});
setTimeout(() => {
this.shotVideoClick(res.data, 'rgb565');
}, 0)
} else {
console.log("res")
uni.showModal({
content: "服务器未返回RGB565数据",
title: '错误'
})
}
}else{
uni.showModal({
content:"与设备握手失败了",
title:"错误"
})
}
});
},
shotVideoClick: function(array, type,ReSendNo) {
//console.log("处理视频完成", array);
//console.log("type=" + type)
//console.log("array=", array);
this.imgs = array;
var sendImagePackets = (imageData) => {
return new Promise((resolve, reject) => {
this.isSending = true;
this.progress = 0;
this.currentPacket = 0;
// 总数据包数
var totalPackets = 1536;
this.totalPackets = totalPackets;
let currentPacket = 1;
if(ReSendNo){
this.progress = ReSendNo-1;
this.currentPacket = ReSendNo-1;
currentPacket=ReSendNo;
totalPackets=ReSendNo;
this.totalPackets=ReSendNo;
}
// 发送单个数据包
const sendNextPacket = () => {
////console.log("currentPacket="+currentPacket+",imageData.length="+imageData.length);
if (currentPacket > totalPackets) {
this.isSending = false;
if(!ReSendNo){
this.bleSendComplete();
}else{
// this.reSendNumber="";
}
resolve();
return;
}
// 计算当前包的数据
let packetSize = 250;
if (type == 'rgb565') {
packetSize = 500;
}
// 创建数据包
const startIndex = (currentPacket - 1) * packetSize;
const endIndex = Math.min(startIndex + packetSize, imageData.length);
if (startIndex > endIndex) {
resolve();
return;
}
////console.log("111111");
const packetData = imageData.slice(startIndex, endIndex);
// 构建数据包
////console.log("packetData.length"+packetData.length);
const bufferSize = 506; // 头部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);
if (type == 'rgb565') {
for (let i = 0; i < packetData.length; i++) {
dataView.setUint8(6 + i, '0x' + packetData[i]);
}
} else {
for (let i = 0; i < packetData.length; i++) {
dataView.setUint16(6 + i * 2, packetData[i], false);
}
}
let inteval = parseInt(this.inteval ? this.inteval : 0);
this.sendData(buffer).then(() => {
// 更新进度
this.currentPacket = currentPacket;
this.progress = Math.round((currentPacket / totalPackets) *
100);
console.log(`发送数据包完成 ${currentPacket}/${totalPackets}`);
// 发送下一个包(添加延迟避免蓝牙缓冲区溢出)
currentPacket++;
setTimeout(sendNextPacket, inteval);
}).catch(err => {
console.log(err.errMsg + ",发送失败了,正在补偿:" + currentPacket);
setTimeout(sendNextPacket, inteval);
// uni.showToast({
// title:"发送失败"+JSON.stringify(err)
// })
});
};
sendNextPacket();
});
}
if (type == 'rgb565') {
let start = new Date();
console.log("开始发送");
sendImagePackets(array).then(() => {
console.log("发送完成");
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff-s) / 60;
console.log("发送完成,耗时:" + m + "分" + s + "秒");
uni.showModal({
content: "发送完成,耗时:" + m + "分" + s + "秒",
title: 'success'
});
}).catch((ex1) => {
console.log("出现了异常", ex1)
}).finally(() => {
uni.hideLoading();
});
return;
}
},
HoldYouHand() {
var promise=new Promise((resolve,reject)=>{
try{
let start=new Date();
var str = "video transmit start"; //握手的协议字符串
console.log("开始握手:"+str)
// 1. 创建 ArrayBuffer 和 DataView
const buffer = new ArrayBuffer(str.length);
const dataView = new DataView(buffer);
// 2. 将字符串转换为 ASCII 码并写入 DataView
for (let i = 0; i < str.length; i++) {
dataView.setUint8(i, str.charCodeAt(i));
}
//console.log("111111");
this.sendData(buffer).then(() => {
// 开始发送第一个包
setTimeout(()=>{
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff - s) / 60;
console.log("握手成功并完成2200ms等待,耗时"+m+"分"+s+"秒");
resolve(true);
}, 2200);
}).catch(err => {
//console.log("握手没有成功");
reject(err);
});
}catch(ex){
reject(ex);
}
});
return promise;
},
bleSendComplete() {
var str = "transmit complete"; //握手的协议字符串
let buffer = new ArrayBuffer(str.length);
let dataView = new DataView(buffer);
for (let i = 0; i < str.length; i++) {
dataView.setUint8(i, str.charCodeAt(i));
}
setTimeout(()=>{
this.sendData(buffer).then(() => {
console.log("完成指令发送成功");
}).catch(err => {
console.log("完成指令发送失败");
});
},500)
},
sendData(buffer) {
if(this.netMode=='ble'){
return this.sendBle(buffer);
}
return this.sendMQ(buffer);
},
sendBle(buffer){
return new Promise(async (resolve, reject) => {
// //console.log("开始发送数据buffer");
var promise = new Promise((succ, err) => {
uni.writeBLECharacteristicValue({
deviceId: this.connectedDeviceId,
serviceId: this.serviceId,
characteristicId: this.writeCharacteristicId,
value: buffer,
writeType: plus.os.name == 'iOS' ? 'write' : 'writeNoResponse',
success: () => {
// //console.log("发送数据成功");
succ();
},
fail: (ex) => {
//console.log("发送数据失败", ex);
err(ex);
},
complete: function() {
// //console.log("123456");
}
});
});
if (plus.os.name == 'iOS') {
function timeout(ms) {
return new Promise((_, err) => {
setTimeout(() => {
err({
code: -1,
errMsg: '超时了'
})
}, ms);
});
}
let inteval = parseInt(this.inteval ? this.inteval : 0);
Promise.race([promise, timeout(inteval)]).then(resolve).catch((ex) => {
//console.log("ex=", ex);
if (ex.code == -1) {
resolve();
} else {
reject();
}
}).finally(() => {
//console.log("完成了")
});
} else {
promise.then(resolve).catch(reject);
}
});
},
sendMQ(message) {
const topic = `B/${this.IMEI}`;
return new Promise((resolve, reject) => {
if(!mqttClient){
reject("MQTT未连接");
return;
}
try {
let flag=mqttClient.publish(topic, message, {
qos: 1
});
if(flag){
resolve();
return;
}
reject("MQTT未连接无法发布消息");
} catch (error) {
reject(error);
}
});
}
}
}
</script>
<style>
.sending-progress {
margin-top: 30rpx;
width: 100%;
}
.progress-bar {
height: 12rpx;
background-color: #e0e0e0;
border-radius: 6rpx;
overflow: hidden;
}
.progress-fill {
height: 100%;
background-color: #409eff;
transition: width 0.3s;
}
input {
border: 2rpx solid #000000;
}
button {
height: 100rpx;
line-height: 100rpx;
font-size: 28rpx;
float: left;
}
.content {
width: 100vw;
height: 300px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>

View File

@ -0,0 +1,115 @@
<template>
<view class="container">
<view class="grid">
<view class="cell" @click="goToDetail(item.name)" v-for="item,index in options">{{item.url}}</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
options: [{
name: '/pages/BlueTooth/ModeSetting/ModeSetting',
url: '7307'
},
{
name: '/pages/BlueTooth/ModeSetting/HBY650',
url: 'HBY650'
},
{
name: '/pages/BlueTooth/ModeSetting/HBY650_1',
url: 'HBY650_V1'
},
{
name: '/pages/BlueTooth/ModeSetting/HBY6155',
url: '6155'
},
{
name: '/pages/BlueTooth/ModeSetting/HBY6155V1',
url: '6155_V1'
},
{
name: "/pages/BlueTooth/ModeSetting/HBY670",
url: 'HBY670'
},
{
name: '/pages/MapTest/MapTest',
url: '地图测试'
},
{
name: '',
url: '更多'
}
]
}
},
onShow: () => {
},
methods: {
goToDetail: function(url) {
console.log("url=" + url)
let qd = () => {
uni.showToast({
title: '敬请期待',
duration: 2000,
icon: "none"
});
};
if (url) {
uni.navigateTo({
url: url,
success: () => {
},
fail: () => {
qd();
}
});
} else {
qd();
}
}
}
}
</script>
<style>
.container {
padding: 15px;
background-color: #f5f5f5;
min-height: 100vh;
}
.grid {
display: flex;
align-content: space-around;
align-items: stretch;
justify-items: center;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
}
.cell {
padding: 0rpx 20rpx;
border: 2rpx solid rgba(0, 0, 0, 0.3);
border-radius: 15rpx;
font-size: 28rpx;
height: 70rpx;
line-height: 70rpx;
margin-left: 30rpx;
margin-top: 20rpx;
}
</style>

View File

@ -0,0 +1,273 @@
<template>
<view class="update-container">
<!-- 进度条 -->
<view v-if="showProgress" class="progress-container">
<view class="progress-title">正在更新 {{ progress }}%</view>
<view class="progress-bar">
<view class="progress" :style="{ width: progress + '%' }"></view>
</view>
</view>
<!-- 更新提示弹窗 -->
<view v-if="showUpdateDialog" class="dialog-mask">
<view class="dialog">
<view class="dialog-title">发现新版本 v{{ newVersion }}</view>
<view class="dialog-content">{{ updateInfo.desc || '有新的功能和优化,建议立即更新' }}</view>
<view class="dialog-buttons">
<button v-if="!updateInfo.force" class="cancel-btn" @click="showUpdateDialog = false">稍后更新</button>
<button class="confirm-btn" @click="startUpdate">立即更新</button>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
// 当前版本
currentVersion: '',
// 最新版本
newVersion: '',
// 更新信息
updateInfo: {},
// 是否显示更新弹窗
showUpdateDialog: false,
// 是否显示进度条
showProgress: false,
// 更新进度
progress: 0
};
},
onLoad() {
// 初始化时检查版本
this.checkVersion();
},
methods: {
/**
* 检查当前版本
*/
async checkVersion() {
try {
// 获取当前应用版本
const versionInfo = plus.runtime.version;
this.currentVersion = versionInfo;
console.log('当前版本:', this.currentVersion);
// 调用后端接口检查最新版本
// 这里替换为你的后端接口地址
const res = await this.$http.get('/api/checkVersion', {
platform: uni.getSystemInfoSync().platform,
version: this.currentVersion
});
if (res.code === 0 && res.data.hasUpdate) {
this.newVersion = res.data.version;
this.updateInfo = res.data;
// 显示更新提示
this.showUpdateDialog = true;
} else {
console.log('当前已是最新版本');
}
} catch (error) {
console.error('版本检查失败:', error);
}
},
/**
* 开始更新
*/
startUpdate() {
if (!this.updateInfo.downloadUrl) {
uni.showToast({
title: '更新地址不存在',
icon: 'none'
});
return;
}
this.showUpdateDialog = false;
this.showProgress = true;
this.downloadWgt(this.updateInfo.downloadUrl);
},
/**
* 下载wgt包
*/
downloadWgt(url) {
const downloadTask = uni.downloadFile({
url: url,
success: (downloadResult) => {
if (downloadResult.statusCode === 200) {
// 下载成功安装wgt包
this.installWgt(downloadResult.tempFilePath);
} else {
this.showProgress = false;
uni.showToast({
title: '下载失败',
icon: 'none'
});
}
},
fail: (err) => {
this.showProgress = false;
console.error('下载失败:', err);
uni.showToast({
title: '下载失败,请稍后重试',
icon: 'none'
});
}
});
// 监听下载进度
downloadTask.onProgressUpdate((res) => {
this.progress = res.progress;
});
},
/**
* 安装wgt包
*/
installWgt(path) {
plus.runtime.install(
path,
{
force: false // 是否强制安装
},
() => {
console.log('安装成功');
this.showProgress = false;
// 安装成功后提示重启
uni.showModal({
title: '更新完成',
content: '应用已更新,是否立即重启?',
showCancel: !this.updateInfo.force,
success: (res) => {
if (res.confirm) {
// 重启应用
plus.runtime.restart();
}
}
});
},
(err) => {
console.error('安装失败:', err);
this.showProgress = false;
uni.showToast({
title: '更新失败: ' + err.message,
icon: 'none',
duration: 3000
});
}
);
}
}
};
</script>
<style scoped>
.update-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 9999;
}
/* 进度条样式 */
.progress-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: #fff;
padding: 10rpx 20rpx;
pointer-events: auto;
}
.progress-title {
font-size: 28rpx;
color: #333;
margin-bottom: 10rpx;
text-align: center;
}
.progress-bar {
height: 8rpx;
background-color: #eee;
border-radius: 4rpx;
overflow: hidden;
}
.progress {
height: 100%;
background-color: #007aff;
transition: width 0.3s ease;
}
/* 弹窗样式 */
.dialog-mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
pointer-events: auto;
}
.dialog {
width: 600rpx;
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
}
.dialog-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
padding: 30rpx;
text-align: center;
border-bottom: 1px solid #eee;
}
.dialog-content {
font-size: 32rpx;
color: #666;
padding: 40rpx 30rpx;
line-height: 1.6;
}
.dialog-buttons {
display: flex;
border-top: 1px solid #eee;
}
.cancel-btn, .confirm-btn {
flex: 1;
height: 100rpx;
line-height: 100rpx;
font-size: 32rpx;
border: none;
background-color: transparent;
}
.cancel-btn {
color: #666;
border-right: 1px solid #eee;
}
.confirm-btn {
color: #007aff;
}
</style>

View File

@ -146,10 +146,31 @@
}
try {
console.log('44444');
if(uni.getStorageSync("token") && uni.getStorageSync("clientID")){//免登陆
let time=uni.getStorageSync("tokenTime");
if(!time){
time=0;
}
let currTime=new Date().getTime();
if(currTime<time){
uni.switchTab({
url: '/pages/common/index/index'
});
return;
}else{
//token过期了
uni.removeStorageSync("token")
uni.removeStorageSync("clientID")
uni.removeStorageSync("tokenTime")
}
}
uni.showLoading({
title: '登录中...'
})
console.log('44444');
// 调用登录接口
const res = await login({
phonenumber: this.phone,
@ -158,16 +179,21 @@
})
if (res.code == 200) {
console.log(res, 'ressss');
uni.hideLoading()
uni.setStorageSync('token', res.data.access_token) // 缓存token
uni.setStorageSync('clientID', res.data.client_id) // 缓存token
uni.hideLoading();
uni.setStorageSync('token', res.data.access_token); // 缓存token
uni.setStorageSync('clientID', res.data.client_id); // 缓存token
uni.setStorageSync('tokenTime',new Date().getTime()+86400000);//过期时间
uni.showToast({
title: '登录成功',
icon: 'success'
})
uni.switchTab({
url: '/pages/common/index/index'
})
});
// uni.navigateTo({
// url:"/pages/BlueTooth/ModeSetting/index"
// });
} else {
uni.showToast({
title: res.msg,