1
0
forked from dyf/APP
Files
APP/pages/650/HBY650.vue
2025-08-05 13:14:22 +08:00

1823 lines
43 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="content contentBg">
<view class="eq">
<view class="leftImg">
<image class="img" src="/static/images/6155/DeviceDetail/Hby650.png" mode="aspectFit"></image>
</view>
<view class="rightTxt">
<view class="row">
<image class="img" src="/static/images/6155/DeviceDetail/battry.png" mode="aspectFit"></image>
<view class="txt">
<view class="bigTxt">{{formData.battary}}%</view>
<view class="smallTxt">电量</view>
</view>
</view>
<view class="row">
<image class="img" src="/static/images/6155/DeviceDetail/time.png" mode="aspectFit"></image>
<view class="txt">
<view class="bigTxt">{{formData.xuhang}}</view>
<view class="smallTxt">续航时间</view>
</view>
</view>
</view>
</view>
<view class="eqinfo">
<!-- <view class="item">
<text class="lbl">蓝牙名称</text>
<text class="value">{{formData.name}}</text>
</view> -->
<view class="item">
<text class="lbl">照明档位</text>
<text class="value">{{formData.RSSI}}</text>
</view>
<view class="item">
<text class="lbl">探测档位</text>
<text class="value">{{formData.statu}}</text>
</view>
<view class="item">
<text class="lbl">预警级别</text>
<text class="value">{{formData.warnLevel}}</text>
</view>
</view>
<!-- <view class="lamp">
<view class="title">
<text>灯光亮度</text>
<text>{{formData.liangDu}}%</text>
</view>
<view class="slider-container">
<slider min="1" max="100" step="1" :disabled="false" :value="formData.liangDu" activeColor="#bbe600"
backgroundColor="#00000000" block-size="20" block-color="#ffffffde" @change="sliderChange"
@changing="sliderChange" class="custom-slider" />
</view>
</view> -->
<view class="modeSetting">
<view class="item" :class="Status.modeCurr=='low'?'active':''"
@click="MainModeSetting('low','staticBattery')">
<view class="p100 center">低档</view>
</view>
<view class="item " :class="Status.modeCurr=='center'?'active':''"
@click="MainModeSetting('center','staticBattery')">
<view class="p100 center">中档</view>
</view>
<view class="item " :class="Status.modeCurr=='hight'?'active':''"
@click="MainModeSetting('hight','staticBattery')">
<view class="p100 center">高档</view>
</view>
<view class="item " :class="Status.modeCurr=='close'?'active':''"
@click="MainModeSetting('close','staticBattery')">
<view class="p100 center">关闭</view>
</view>
</view>
<view class="lampMode">
<view class="mode fleft" :class="Status.cMode?'active':''" v-on:click.stop="LampToggle()">
<view class="leftImg">
<image class="img" src="/static/images/6155/DeviceDetail/mainLamp.png" mode="aspectFit"></image>
</view>
<view class="rightTxt">
<text class="bigTxt">照明模式</text>
</view>
</view>
<view class="mode marginLeft fleft" :class="Status.cMode=='mode'?'':'active'"
v-on:click.stop="UploadOpenImg()">
<view class="leftImg">
<image class="img" src="/static/images/6155/DeviceDetail/open.png" mode="aspectFit"></image>
</view>
<view class="rightTxt">
<text class="bigTxt">开机画面</text>
<text class="smallTxt">上传</text>
</view>
</view>
<view class="clear"></view>
</view>
<view class="usrinfo">
<view @click="Status.usrToggle=!Status.usrToggle">
<text class="usrtitle fleft">人员信息登记</text>
<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="Status.usrToggle?'':'displayNone'">
<view style="margin: 20rpx 0rpx;">
<view class="btnSend fright" v-on:click.stop="sendUsr">发送</view>
<view class="clear"></view>
</view>
<view class="item">
<text class="lbl">单位</text>
<input class="value" v-model="user.company" placeholder="请输入单位" placeholder-class="usrplace" />
</view>
<view class="item">
<text class="lbl">姓名</text>
<input class="value" v-model="user.name" placeholder="请输入姓名" placeholder-class="usrplace" />
</view>
<view class="item">
<text class="lbl">职位</text>
<input class="value" v-model="user.job" placeholder="请输入职位" placeholder-class="usrplace" />
</view>
<view class="item">
<text class="lbl">ID号</text>
<input class="value" v-model="user.id" placeholder="请输入ID" placeholder-class="usrplace" />
</view>
</view>
</view>
<view class="proinfo lamp">
<text class="title">产品信息</text>
<view class="itemcontent">
<view class="item" @click="proParam()">
<image class="img" src="/static/images/6155/DeviceDetail/param.png" mode="aspectFit"></image>
<text class="txt">产品参数</text>
</view>
<view class="item" @click="handRemark()">
<image class="img" src="/static/images/6155/DeviceDetail/remark.png" mode="aspectFit"></image>
<text class="txt">操作说明</text>
</view>
<view class="item" @click="handVideo()">
<image class="img" src="/static/images/6155/DeviceDetail/video.png" mode="aspectFit"></image>
<text class="txt">操作视频</text>
</view>
</view>
</view>
<!-- 弹窗通知 -->
<MessagePopup :visible="Status.Pop.showPop" :type="Status.Pop.popType" :bgColor="Status.Pop.bgColor"
:borderColor="Status.Pop.borderColor" :textColor="Status.Pop.textColor"
:buttonBgColor="Status.Pop.buttonBgColor" :buttonTextColor="Status.Pop.buttonTextColor"
:iconUrl="Status.Pop.iconUrl" :message="Status.Pop.message" :buttonText="Status.Pop.buttonText"
@buttonClick="HidePop" :visiblePrompt="Status.Pop.visiblePrompt" :promptTitle="Status.Pop.promptTitle"
v-model="Status.Pop.modelValue" />
<!-- 下方菜单 -->
<BottomSlideMenuPlus :config="Status.BottomMenu" @close="closeMenu" @itemClick="handleItemClick"
@btnClick="btnClick">
<view class="addIco">
<view class="icoContent center" v-on:click.stop="checkImgUpload()">
<image mode="aspectFit" class="img" src="/static/images/6155/DeviceDetail/add.png"></image>
</view>
</view>
</BottomSlideMenuPlus>
<Progress :config="Status.Progress"></Progress>
</view>
</template>
<script>
import gbk from '@/utils/gbk.js'
import BleTool from '@/utils/BleHelper.js'
var ble = null;
export default {
data() {
return {
Status: {
cMode: false,
modeCurr: 'low',
usrToggle: true,
Pop: {
showPop: false, //是否显示弹窗
popType: 'custom',
bgColor: '#383934bd',
borderColor: '#BBE600',
textColor: '#ffffffde',
buttonBgColor: '#BBE600',
buttonTextColor: '#232323DE',
iconUrl: '',
message: '您确定要这样做吗?',
buttonText: '确定',
clickEvt: '',
visiblePrompt: false,
promptTitle: '设备名称',
modelValue: '',
visibleClose: false
},
BottomMenu: {
show: false,
showHeader: true,
menuItems: [{
text: '强光',
icon: '/static/images/6155/DeviceDetail/qiang.png'
},
{
text: '弱光',
icon: '/static/images/6155/DeviceDetail/ruo.png'
},
{
text: '爆闪',
icon: '/static/images/6155/DeviceDetail/shan.png'
}
],
activeIndex: -1,
bgColor: '#2a2a2a',
itemBgColor: '#3a3a3a',
textColor: '#ffffffde',
textAlign: 'flex-start',
title: '主灯模式',
showDivider: false,
dividerColor: '#00000000',
dividerThickness: '0rpx',
dividerMargin: '10rpx',
itemHeight: '80rpx',
type: '',
showBtn: true,
btnBgColor: "#bbe600",
btnText: "确定",
btnTextColor: "#232323de",
showMask: true,
maskBgColor: '#00000066',
showClose: false
},
Progress: {
show: false, //是否显示
height: '20rpx',
showMask: true, //是否显示mask
maskBgColor: '#00000000', //mask背景颜色
contentBgColor: '#121212', //总背景颜色
showText: true, //是否显示当前进度的文字
txtColor: '#ffffffde', //文字的颜色
curr: 20, //当前进度
total: 100, //总进度
proBgColor: '#2a2a2a', //进度条底色,
proBorder: '', //进度条border
currBgColor: '#bbe600', //当前进度底色
currBorder: '', //当前进度border
borderRadius: '10rpx'
}
},
formData: {
img: '/static/images/6155/DeviceDetail/equip.png',
battary: '',
xuhang: '1',
name: 'JQZM-EF4651',
RSSI: '-30',
statu: '运行中',
liangDu: '50',
warnLevel: '',
macAddress: ''
},
cEdit: {
mode: ''
},
user: {
company: '黄石消防支队',
name: '菜英俊',
job: '小队长',
id: 'HSXF01061'
},
device: {
deviceId: '',
writeServiceId: '',
wirteCharactId: '',
notifyServiceid: '',
notifyCharactId: ''
},
videoHexArray: []
}
},
onLoad: function() {
var these = this;
ble = BleTool.getBleTool();
let eventChannel = this.getOpenerEventChannel();
//eventChannel.on('receivdata', function(data) {
let data = {
data: {
deviceMac: '35:06:00:EF:46:51',
bluetoothName: 'JQZM-EF4651',
deviceName: 'JQZM-EF4651',
devicePic: '',
id: '35:06:00:EF:46:51'
}
};
console.log("收到父页面的参数:" + JSON.stringify(data));
var device = data.data;
these.device.deviceId = device.deviceMac;
these.formData.name = device.bluetoothName ? device.bluetoothName : device.deviceName;
these.formData.img = device.devicePic;
these.formData.id = device.id;
//});
ble.addReceiveCallback(these.bleValueNotify);
let startLink=()=>{
ble.addDeviceFound((res) => {
console.log("发现新设备,",res);
let f = res.devices.find((v) => {
return v.name == device.deviceName;
});
if (f) {
console.log("找到了目标设备,正在连接:"+f.deviceId)
these.device.deviceId = f.deviceId;
these.formData.id = f.deviceId;
ble.LinkBlue(f.deviceId);
}
});
ble.StartSearch();
}
if(ble.data.LinkedList && ble.data.LinkedList.length>0){
let f=ble.data.LinkedList.find((v)=>{
return v.name==device.deviceName;
});
if(!f){
startLink();
}else{
these.device.deviceId = f.deviceId;
these.formData.id = f.deviceId;
}
}else{
startLink();
}
},
onHide: function() {
},
onBackPress(e) {
var these = this;
console.log("these.device=" + JSON.stringify(these.device));
if (these.device.deviceId) {
if (e.from === 'backbutton') {
these.getLinkBlue((res) => {
if (res.devices.length == 0) {
console.log("没有已连接的蓝牙设备")
uni.navigateBack();
return;
}
let f = res.devices.find(function(v) {
return v.deviceId == these.device.deviceId;
});
if (!f) {
console.log("该设备没有连接")
uni.navigateBack();
return;
}
uni.showModal({
title: '提示',
content: '是否断开与设备的蓝牙连接?',
success: function(res) {
if (res.confirm) {
ble.disconnectDevice(these.device.deviceId);
}
uni.navigateBack();
}
});
});
return true;
}
}
return false;
},
computed: {
RSSIRemark: function() {
let remark = '极弱';
if (this.formData.RSSI <= 0 && this.formData.RSSI >= -30) {
remark = '强';
}
if (this.formData.RSSI < -30 && this.formData.RSSI >= -60) {
remark = '一般';
}
if (this.formData.RSSI < -60 && this.formData.RSSI >= -85) {
remark = '弱';
}
if (this.formData.RSSI < -85 && this.formData.RSSI >= -100) {
remark = '微弱';
}
}
},
methods: {
bleValueNotify: function(receive) { //订阅消息
console.log("收到订阅消息", receive);
var these = this;
var parseData = (
bytes) => {
if (bytes[0] == 0x55) {
try {
let staticLevelByte = bytes[1];
let staticLevelText = '未知';
let modeCurr = "";
switch (staticLevelByte) {
case 0x65:
staticLevelText = '高档';
modeCurr = "hight";
break;
case 0x66:
staticLevelText = '中档';
modeCurr = "center";
break;
case 0x67:
staticLevelText = '低档';
modeCurr = "low";
break;
case 0x68:
staticLevelText = '关闭';
modeCurr = "close";
break;
}
// 解析照明档位
let lightingLevelByte = bytes[2];
let lightingLevelText = lightingLevelByte === 0x6e ? '开启' : '关闭';
// 解析剩余照明时间(第三和第四字节,大端序)
let lightingTime =(bytes[3] <<8) | bytes[4];
let hours = Math.floor(lightingTime / 60);
let remainingMinutes = lightingTime % 60;
let xuhang = '0分';
// 处理不同情况的显示
if (hours === 0) {
xuhang = `${remainingMinutes}`;
} else if (remainingMinutes === 0) {
xuhang = `${hours}小时`;
} else {
xuhang = `${hours}小时${remainingMinutes}`;
}
// 解析剩余电量
let batteryLevelByte = bytes[5];
// 电量百分比范围检查
let batteryLevel = Math.max(0, Math.min(100, batteryLevelByte));
let warn = bytes[6];
if (warn == 0x00) {
warn = '无预警';
} else if (warn == 0x01) {
warn = '弱预警';
} else if (warn == 0x02) {
warn = '中预警';
} else if (warn == 0x03) {
warn = '强预警';
} else if (warn == 0x04) {
warn = '非常强预警';
}
these.formData.battary = batteryLevel;
these.formData.xuhang = xuhang;
these.Status.cMode = lightingLevelByte === 0x6e;
these.Status.modeCurr = modeCurr;
these.formData.warnLevel = warn;
} catch (error) {
console.error('数据解析错误:', error);
}
} else {
try {
let uint8Array = new Uint8Array(receive.value);
let str = '';
for (let i = 0; i < uint8Array.length; i++) {
// 将每个字节转换为对应的字符
str += String.fromCharCode(uint8Array[i]);
}
if (str.indexOf('mac address:') == 0) {
these.formData.macAddress = str.split(':')[1];
console.log("收到mac地址:", )
} else {
console.log("收到无法解析的字符串:", str)
}
} catch (ex) {
console.log("将数据转文本失败", ex);
}
}
}
// 转换为字节数组
const bytes = receive.bytes;
parseData(bytes);
},
getDevice: function() {
var these = this;
let f = ble.data.LinkedList.find((v) => {
return v.deviceId == these.device.deviceId;
});
return f;
},
MainModeSetting: function(type, byteType) {
if (this.Status.modeCurr == type) {
return;
}
this.Status.modeCurr = type;
let dataValue = 0x00;
let btype = 0x00;
switch (type) {
case "low": //低档
dataValue = 0x67;
break;
case "center": //中档
dataValue = 0x66;
break;
case "hight": //高档
dataValue = 0x65;
break;
case "close": //关闭
dataValue = 0x68;
break;
case true: //开灯
dataValue = 0x6E;
break;
case false: //关灯
dataValue = 0x6F;
break;
default: //未知
dataValue = 0x00;
break;
}
switch (byteType) {
case "staticBattery":
btype = 0x00;
break;
case "lamp":
btype = 0x01;
break;
default:
break;
}
let buffer = new ArrayBuffer(6);
let dataView = new DataView(buffer);
dataView.setUint8(0, 0x55); // 帧头
dataView.setUint8(1, btype); // 帧类型
dataView.setUint8(2, 0x01); // 包序号
dataView.setUint8(3, 0x00); // 数据长度
dataView.setUint8(4, 0x01); // 数据长度
dataView.setUint8(5, dataValue); // 数据
let f = this.getDevice();
if (f) {
// 发送数据
ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, 50).then(()=>{
console.log("发送成功了");
}).catch((ex)=>{
uni.showModal({
title:'提示',
content:ex.msg
})
});
} else {
console.log("333333");
}
},
LampToggle: function() {
this.Status.cMode = !this.Status.cMode;
this.MainModeSetting(this.Status.cMode, "lamp");
},
proParam: function() {
uni.navigateTo({
url: '/pages/common/productDes/index?id=' + this.device.deviceId,
success(ev) {
},
fail() {
uni.showToast({
title: '敬请期待'
})
}
});
},
handRemark: function() {
uni.navigateTo({
url: '/pages/common/operatingInstruct/index?id=' + this.device.deviceId,
success(ev) {
},
fail() {
uni.showToast({
title: '敬请期待'
})
}
});
},
handVideo: function() {
uni.navigateTo({
url: '/pages/common/operationVideo/index?id=' + this.device.deviceId,
success(ev) {
},
fail() {
uni.showToast({
title: '敬请期待'
})
}
});
},
checkImgUpload: function() {
console.log("123213213213");
var these = this;
// 处理像素数据并发送
var processAndSendImageData = function(pixels) {
return new Promise((resolve, reject) => {
// 创建RGB565格式的像素数据
const rgb565Data = convertToRGB565(pixels);
// 分包发送
sendImagePackets(rgb565Data).then(resolve).catch(reject);
});
}
// 将RGBA转换为RGB565
var convertToRGB565 = function(pixels) {
var rgbaToRgb565 = function(r, g, b, a = 255) {
// 忽略透明度(如果需要考虑透明度,请根据需求处理)
// 将8位颜色值压缩到RGB565对应的位数
const r5 = Math.round((r / 255) * 31); // 5位0-31
const g6 = Math.round((g / 255) * 63); // 6位0-63
const b5 = Math.round((b / 255) * 31); // 5位0-31
// 合并为16位整数
return (r5 << 11) | (g6 << 5) | b5;
}
const result = new Uint16Array(160 * 80);
let index = 0;
console.log("pixels.length=" + pixels.length);
for (let i = 0; i < pixels.length; i += 4) {
const r = pixels[i];
const g = pixels[i + 1];
const b = pixels[i + 2];
// 转换为RGB565 (R:5bit, G:6bit, B:5bit)
const rgb565 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
//let rgb565=rgbaToRgb565(r,g,b);
result[index++] = rgb565;
}
return result;
}
// 分包发送图片数据
var sendImagePackets = function(imageData) {
return new Promise((resolve, reject) => {
// this.isSending = true;
// this.progress = 0;
// this.currentPacket = 0;
// 总数据包数
const totalPackets = 52;
let currentPacket = 1;
let f = these.getDevice();
if (f) {
// 发送单个数据包
const sendNextPacket = () => {
if (currentPacket > totalPackets) {
uni.hideLoading();
these.Status.BottomMenu.show = false;
these.Status.Progress.show = false;
these.Status.Pop.showPop = true;
these.Status.Pop.message = "上传成功";
these.Status.Pop.iconUrl =
"/static/images/6155/DeviceDetail/uploadSuccess.png";
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, imageData
.length);
if (startIndex > endIndex) {
return;
}
const packetData = imageData.slice(startIndex,
endIndex); // imageData.subarray(startIndex, endIndex);
// console.log("imageData.length=" + imageData.length +
// ",startIndex=" +
// startIndex +
// ",endIndex=" + endIndex + ",数据包长度" + (endIndex -
// startIndex) +
// ',packetData.length=' + packetData.length);
// 构建数据包
const bufferSize = 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')); // 包序号
// if(packetData.length==250)
// {
// dataView.setUint8(3, 0x01);
// dataView.setUint8(4, 0xFF);
// }
if (packetData.length == 250) {
dataView.setUint8(3, 0x01);
dataView.setUint8(4, 0xF4);
} else {
dataView.setUint8(3, 0x00);
dataView.setUint8(4, 0x64);
}
// 填充数据每个RGB565值占2字节
for (let i = 0; i < packetData.length; i++) {
dataView.setUint16(5 + i * 2, packetData[i], false); // 大端字节序
}
console.log(
`发送数据包${currentPacket}/${totalPackets},${dataView.getUint8(0)} ${dataView.getUint8(1)} ${dataView.getUint8(2)}`
)
//发送数据包
ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, 50)
.then(() => {
these.Status.Progress.curr = currentPacket;
currentPacket++;
setTimeout(sendNextPacket, 0);
}).catch(err => {
console.log("发送数据包失败了" + JSON.stringify(err));
if (err.code == '10007') {
setTimeout(sendNextPacket, 0);
return;
}
these.Status.BottomMenu.show = false;
these.Status.Progress.show = false;
uni.showModal({
title:'提示',
content:err.msg
})
uni.hideLoading();
reject(err);
});
}
// 开始牵手
these.HoldYouHand("picture transmit start", 120, f.deviceId, f.writeServiceId,
f.wirteCharactId).then(() => {
sendNextPacket();
}).catch((err) => {
console.log("握手没有成功");
reject(err);
});
}
});
}
//去图片裁剪
var gotoCutImg = (imgPath) => {
uni.navigateTo({
url: "/pages/6155/ImgCrop",
events: {
ImgCutOver: function(data) {
console.log("我收到裁剪后的图片了,感谢老铁," + data)
uni.showLoading({
title: "正在发送..."
});
these.Status.Progress.show = true;
these.Status.Progress.curr = 0;
these.Status.Progress.total = 52;
these.Status.BottomMenu.show = false;
setTimeout(function() {
processAndSendImageData(data).catch(() => {
});
}, 0)
}
},
success(ev) {
ev.eventChannel.emit('checkImg', {
data: imgPath
});
}
});
}
var sendVideo = (videoPath) => {
let uploadVideo = () => {
if (these.videoHexArray.length > 0) {
console.log("开始处理,无需上传");
shotVideoClick(these.videoHexArray);
return;
}
console.log("开始处理,正在上传");
let f = this.getDevice();
uni.showLoading({
title: "上传中"
});
let p1 = these.HoldYouHand("video transmit start", 2200, f.deviceId, f.writeServiceId,
f.wirteCharactId);
let p2 = new Promise((succ, err) => {
uni.uploadFile({
url: 'http://114.55.111.217/video/upload',
filePath: 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();
err(ex);
},
success: (res) => {
uni.hideLoading();
console.log("上传完成,向蓝牙设备发送");
succ(res);
}
});
});
Promise.all([p1, p2]).then((arr) => {
let res = arr[1];
res = JSON.parse(res.data);
if (res.data) {
these.videoHexArray = res.data;
these.Status.Progress.show = true;
these.Status.Progress.curr = 0;
these.Status.Progress.total = 1536;
these.Status.BottomMenu.show = false;
setTimeout(() => {
shotVideoClick(res.data);
}, 0)
} else {
console.log("服务器未返回正确的数据");
uni.showToast({
title: "与服务器连接出现异常",
icon: 'fail'
})
}
}).catch((ex) => {
uni.showModal({
title: "提示",
content: "出现异常"
});
})
}
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;
these.Status.Progress.show = false;
these.Status.Pop.showPop = true;
these.Status.Pop.message = "上传成功";
these.videoHexArray = [];
these.Status.Pop.iconUrl =
"/static/images/6155/DeviceDetail/uploadSuccess.png";
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, inteval).then(() => {
these.Status.Progress.curr = currentPacket;
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;
these.Status.Progress.show = false;
these.Status.Pop.showPop = true;
these.Status.Pop.message = err.msg+",发送失败了";
these.Status.Pop.borderColor="#e034344d";
these.Status.Pop.buttonBgColor="#E03434";
these.Status.Pop.buttonText="确定";
these.Status.Pop.iconUrl =
"/static/images/6155/DeviceDetail/uploadErr.png";
reject(err);
return;
}
});
};
sendNextVideoPacket();
} else {
console.log("Fail.......")
}
});
}
let shotVideoClick = (array) => {
console.log("正在开始发送");
sendVideoPackets(array).then(() => {
console.log("发送完成");
}).catch((ex1) => {
//console.log("出现了异常", ex1)
}).finally(() => {
uni.hideLoading();
});
}
uploadVideo();
}
uni.chooseMedia({
count: 1,
mediaType: ['image', 'video'],
sourceType: ['album'],
maxDuration: 3,
sizeType: ['original'],
success: (res) => {
let file = res.tempFiles[0];
if (file.fileType == 'image') {
gotoCutImg(file.tempFilePath);
return;
}
if (file.fileType == 'video') {
if (file.duration < 2) {
this.alert('提示', "请选择2S及以上的视频");
return;
}
these.videoHexArray = [];
sendVideo(file.tempFilePath);
return;
}
}
});
// uni.chooseImage({
// count: 1,
// sizeType: ['original', 'compressed'],
// sourceType: ['album'],
// success: function(res) {
// gotoCutImg(res.tempFiles[0].path);
// }
// });
},
UploadOpenImg: function() {
//上传开机画面
this.Status.BottomMenu.menuItems = [];
this.Status.BottomMenu.title = "上传开机画面";
this.Status.BottomMenu.type = "checkImg";
this.Status.BottomMenu.show = true;
this.Status.cMode = "img";
},
showMenu(flag) {
this.Status.BottomMenu.show = true;
},
closeMenu() {
this.Status.BottomMenu.show = false;
},
btnClick(item, index) {
},
setMode(mode) {
},
handleItemClick(item, index) {
switch (this.Status.BottomMenu.type) {
case "main":
break;
case "fu":
break;
}
this.Status.BottomMenu.activeIndex = index;
},
HidePop: function() {
if (this.Status.Pop.clickEvt == 'SendUsr') {
}
this.Status.Pop.showPop = false;
},
sendUsr: function() {
var these = this;
var textLines = [
this.user.company,
this.user.name,
this.user.job,
this.user.id
];
let f = this.getDevice();
var sendText = function() {
// 总数据包数
const totalPackets = textLines.length;
let currentPacket = 1;
// 发送单个数据包
const sendNextPacket = () => {
if (currentPacket > totalPackets) {
these.Status.Pop = {
showPop: true, //是否显示弹窗
popType: 'custom',
bgColor: '#383934bd',
borderColor: '#BBE600',
textColor: '#ffffffde',
buttonBgColor: '#BBE600',
buttonTextColor: '#232323DE',
iconUrl: '/static/images/6155/DeviceDetail/sendSucc.png',
message: '人员信息发送成功',
buttonText: '确定',
clickEvt: 'SendUsr',
visiblePrompt: false,
promptTitle: '',
modelValue: '',
visibleClose: true
}
return;
}
// 获取当前行文字
const text = textLines[currentPacket - 1] || '';
let arr = gbk.encode(text)
let gbkData = gbk.arr2hex(arr);
console.log(JSON.stringify(gbkData));
// 构建数据包
const bufferSize = 5 + text.length * 2; // 头部4字节 + 数据部分
const buffer = new ArrayBuffer(bufferSize);
const dataView = new DataView(buffer);
// 填充头部
dataView.setUint8(0, 0x55); // 帧头
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);
}
console.log("dataView.length=" + dataView.byteLength)
// 发送数据包
ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, 50).then(() => {
// 更新进度
console.log(
`发送文字数据包 ${currentPacket}/${totalPackets}: ${text}`
);
// 发送下一个包
currentPacket++;
setTimeout(sendNextPacket, 0);
}).catch(err => {
// this.isSendingText = false;
uni.showToast({
title: '文字发送失败',
icon: 'none'
});
});
};
// 开始发送第一个包
sendNextPacket();
}
these.HoldYouHand("word transmit start", 120, f.deviceId, f.writeServiceId, f.wirteCharactId).then(
() => {
setTimeout(sendText, 200);
}).catch((ex) => {
console.log("握手没有成功", ex);
uni.showToast({
title: '握手没有成功',
icon: 'none'
});
});
},
HoldYouHand(str, pauseTime, deviceid, serviceid, characid) {
if (!pauseTime) {
pauseTime = 0;
}
var promise = new Promise((resolve, reject) => {
// 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("开始握手");
ble.sendData(deviceid, buffer, serviceid, characid, 50).then(
() => {
setTimeout(() => {
console.log("握手成功并完成了等待");
resolve(true);
}, pauseTime);
}).catch(err => {
console.log("握手没有成功",)
reject(err);
});
});
return promise;
},
ack: function() {
var these = this;
let eventChannel = this.getOpenerEventChannel();
eventChannel.emit('ack', {
data: '我已收到了您的消息,谢谢。'
});
}
}
}
</script>
<style>
.content {
padding: 30rpx;
box-sizing: border-box;
}
.eq {
width: 100%;
height: 250rpx;
border-radius: 8px;
background: rgba(26, 26, 26, 1);
box-sizing: border-box;
padding: 24rpx 28rpx;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: center;
align-items: center;
margin-bottom: 24rpx;
}
.eq .leftImg {
box-sizing: border-box;
padding: 36rpx;
border-radius: 16rpx;
background: rgba(42, 42, 42, 0.5);
}
.eq .leftImg,
.eq .rightTxt {
width: 50%;
height: 100%;
}
.eq .rightTxt {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
align-content: flex-start;
justify-content: space-evenly;
align-items: flex-start;
}
.eq .leftImg .img {
width: 100%;
height: 100%;
}
.eq .rightTxt .img {
width: 52rpx;
height: 52rpx;
}
.eq .rightTxt .row {
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: flex-start;
align-items: center;
box-sizing: border-box;
padding-left: 50rpx;
}
.eq .rightTxt .row .txt {
padding-left: 20rpx;
}
.eq .bigTxt {
color: rgba(255, 255, 255, 0.87);
font-family: PingFang SC;
font-size: 28rpx;
font-weight: 400;
}
.eq .smallTxt {
color: rgba(255, 255, 255, 0.6);
font-family: PingFang SC;
font-size: 24rpx;
font-weight: 400;
}
.eqinfo {
border-radius: 16rpx;
background: rgba(26, 26, 26, 1);
box-sizing: border-box;
padding: 14rpx 0rpx;
}
.eqinfo .item {
width: 100%;
height: 60rpx;
line-height: 60rpx;
padding: 0rpx 28rpx;
box-sizing: border-box;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: space-between;
align-items: center;
}
.eqinfo .lbl {
color: rgba(255, 255, 255, 0.87);
font-family: PingFang SC;
font-size: 28rpx;
font-weight: 400;
letter-spacing: 0.07px;
text-align: left;
}
.eqinfo .value {
color: rgba(255, 255, 255, 0.6);
font-family: PingFang SC;
font-size: 28rpx;
font-weight: 400;
letter-spacing: 0.07px;
text-align: left;
}
.lamp {
margin-top: 24rpx;
}
.lamp .title {
width: 100%;
height: 60rpx;
line-height: 60rpx;
padding: 0rpx 28rpx;
box-sizing: border-box;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: space-between;
align-items: center;
font-size: 28rpx;
}
.lampMode {
padding: 30rpx 0rpx;
width: 100%;
box-sizing: border-box;
}
.lampMode .mode {
width: calc(calc(100% - 34rpx) / 2);
border-radius: 8px;
margin-top: 20rpx;
background: rgba(26, 26, 26, 1);
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
align-items: center;
justify-content: flex-start;
padding: 30rpx;
box-sizing: border-box;
}
.lampMode .mode.active {
border: 1px solid rgba(174, 214, 0, 1);
}
.lampMode .mode.active .bigTxt {
color: rgba(174, 214, 0, 1) !important;
}
.mode.marginLeft {
margin-left: 34rpx !important;
}
.mode .leftImg .img {
width: 70rpx;
height: 70rpx;
}
.mode .rightTxt {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
align-content: flex-start;
justify-content: center;
align-items: flex-start;
padding-left: 20rpx;
}
.mode .bigTxt {
color: rgba(255, 255, 255, 0.87);
font-family: PingFang SC;
font-size: 28rpx;
font-weight: 400;
letter-spacing: 0.07px;
}
.mode .smallTxt {
color: rgba(255, 255, 255, 0.6);
font-family: PingFang SC;
font-size: 24rpx;
font-weight: 400;
letter-spacing: 0.07px;
}
.usrinfo {
border-radius: 8px;
width: 100%;
box-sizing: border-box;
padding: 24rpx 28rpx;
background: rgba(26, 26, 26, 1);
}
.usrtitle {
color: rgba(255, 255, 255, 0.87);
font-family: PingFang SC;
font-size: 28rpx;
font-weight: 400;
height: 40rpx;
line-height: 40rpx;
letter-spacing: 0.07px;
}
.usrinfo .btnSend {
line-height: 44rpx;
border-radius: 8px;
width: 82rpx;
height: 44rpx;
color: rgba(35, 35, 35, 0.87);
font-family: PingFang SC;
font-size: 24rpx;
font-weight: 400;
letter-spacing: 0.07px;
text-align: center;
background-color: #BBE600;
}
.usrinfo .item {
border-radius: 8px;
width: 100%;
box-sizing: border-box;
line-height: 90rpx;
height: 90rpx;
background: rgba(42, 42, 42, 1);
margin-top: 24rpx;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: flex-start;
align-items: center;
}
.usrinfo .lbl {
width: 120rpx;
height: 100%;
padding-left: 24rpx;
box-sizing: border-box;
text-align: right;
color: rgba(255, 255, 255, 0.87);
font-family: PingFang SC;
font-size: 28rpx;
font-weight: 400;
letter-spacing: 0.07px;
}
.usrinfo .value {
width: calc(100% - 120rpx);
height: 100%;
font-size: 28rpx;
font-weight: 400;
letter-spacing: 0.07px;
text-align: left;
}
.usrinfo .value .uni-input-input {
color: rgba(255, 255, 255, 0.87);
font-family: PingFang SC;
}
.usrplace {
color: rgba(255, 255, 255, 0.4);
font-family: PingFang SC;
font-size: 28rpx;
font-weight: 400;
letter-spacing: 0.07px;
text-align: left;
}
.proinfo .itemcontent {
display: flex;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: space-evenly;
}
.proinfo .item {
width: 180rpx;
height: 180rpx;
box-sizing: border-box;
padding: 40rpx;
border-radius: 16rpx;
background: rgba(26, 26, 26, 1);
display: flex;
flex-direction: column;
flex-wrap: nowrap;
align-content: center;
justify-content: center;
align-items: center;
}
.proinfo .item .img {
width: 50rpx;
height: 50rpx;
}
.proinfo .item .txt {
color: rgba(255, 255, 255, 0.6);
font-family: PingFang SC;
font-size: 24rpx;
font-weight: 400;
margin-top: 20rpx;
letter-spacing: 0.07px;
text-align: left;
}
.slider-container {
padding: 0px;
}
/* .custom-slider .uni-slider-handle-wrapper {
height: 60rpx !important;
border-radius: 3px;
}
.custom-slider .uni-slider-active {
background-color: #FF6B6B !important;
}
.custom-slider .uni-slider-handle {
width: 60rpx !important;
height: 60rpx !important;
border-radius: 16rpx !important;
background-color: #FFFFFFde !important;
margin-top: -15px !important;
border: none !important;
}
.custom-slider .uni-slider-thumb {
width: 60rpx !important;
height: 60rpx !important;
border-radius: 16rpx !important;
background-color: #00000000 !important;
border: none !important;
} */
.addIco {
width: 100%;
height: 360rpx;
display: flex;
flex-wrap: nowrap;
flex-direction: row;
align-content: center;
justify-content: center;
align-items: center;
}
.icoContent {
width: 240rpx;
height: 240rpx;
border-radius: 8rpx;
background: rgba(58, 58, 58, 1);
}
.icoContent .img {
width: 70rpx;
height: 70rpx;
}
.modeSetting {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: space-around;
align-items: center;
}
.modeSetting .item {
width: 150rpx;
height: 150rpx;
background: rgba(26, 26, 26, 1);
border-radius: 50%;
color: rgba(255, 255, 255, 0.87);
margin-top: 40rpx;
font-family: PingFang SC;
font-size: 28rpx;
font-weight: 400;
line-height: 0px;
box-sizing: border-box;
}
.modeSetting .item.active {
border: 4rpx solid rgba(174, 214, 0, 1);
background: rgba(26, 26, 26, 1);
padding: 6rpx;
color: rgba(26, 26, 26, 0.87);
}
.modeSetting .item.active .p100 {
background: rgba(174, 214, 0, 1);
border-radius: 50%;
}
.usrinfo .image {
width: 30rpx;
height: 40rpx;
}
.usrinfo .img {
width: 30rpx;
height: 40rpx;
}
.content {
box-sizing: border-box;
width: 100%;
min-height: 100vh;
height: auto;
}
.contentBg {
background-color: #121212;
color: #ffffffde;
}
.fleft {
float: left;
}
.fright {
float: right;
}
.clear {
clear: both;
}
.displayNone {
display: none !important;
}
.p100 {
width: 100%;
height: 100%;
}
.center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: center;
align-items: center;
}
.centerLeft {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: flex-start;
align-items: center;
}
</style>