diff --git a/App.vue b/App.vue index 4d86eee..35e20f9 100644 --- a/App.vue +++ b/App.vue @@ -53,6 +53,9 @@ }, onHide: function() { console.log('App Hide'); + }, + onError(ex) { + console.error("出现了未知的异常",ex); } } diff --git a/components/TextToHex/TextToHexV1.vue b/components/TextToHex/TextToHexV1.vue index 36bfc99..d3237ad 100644 --- a/components/TextToHex/TextToHexV1.vue +++ b/components/TextToHex/TextToHexV1.vue @@ -229,12 +229,12 @@ let linePixls = []; let item = this.validTxts[i]; - console.log("item=",item); + for (var j = 0; j < item.length; j++) { let result = await drawTxt(item[j]); linePixls.push(convertCharToMatrix(result.pixelData)); } - console.log("hexs=",linePixls.join(",")); + // console.log("hexs=",linePixls.join(",")); arr.push(linePixls); } diff --git a/manifest.json b/manifest.json index 5eef456..6dadd96 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "name" : "星汉物联", "appid" : "__UNI__A21EF43", "description" : "设备管控", - "versionName" : "1.0.11", + "versionName" : "1.0.12", "versionCode" : "100", "transformPx" : false, /* 5+App特有相关 */ @@ -99,23 +99,7 @@ }, "push" : { "unipush" : { - "version" : "2", - "offline" : true, - "hms" : {}, - "oppo" : {}, - "vivo" : {}, - "mi" : {}, - "meizu" : {}, - "honor" : {}, - "icons" : { - "small" : { - "xxhdpi" : "unpackage/res/icons/72x72.png", - "xhdpi" : "unpackage/res/icons/48x48.png", - "hdpi" : "unpackage/res/icons/36x36.png", - "mdpi" : "unpackage/res/icons/24x24.png", - "ldpi" : "unpackage/res/icons/18x18.png" - } - } + "offline" : false } } }, diff --git a/pages.json b/pages.json index 75ce43f..acfd99c 100644 --- a/pages.json +++ b/pages.json @@ -339,6 +339,7 @@ "path" : "pages/102/HBY102", "style" : { + "navigationStyle": "custom", "navigationBarTitleText" : "HBY102" } }, @@ -376,6 +377,13 @@ { "navigationBarTitleText" : "BJQ6155" } + }, + { + "path" : "pages/102/HBY102_History", + "style" : + { + "navigationStyle": "custom" + } } diff --git a/pages/102/HBY102.vue b/pages/102/HBY102.vue index ff9220c..4379aef 100644 --- a/pages/102/HBY102.vue +++ b/pages/102/HBY102.vue @@ -1,5 +1,26 @@ @@ -223,30 +245,30 @@ show: false, showHeader: true, menuItems: [{ - text: '2M', - value:'status_2M', - icon: '' - }, - { - text: '4M', - value:'status_4M', - icon: '' - }, - { - text: '7M', - value:'status_7M', - icon: '' - }, - { - text: '10M', - value:'status_10M', - icon: '' - }, - { - text: '关闭', - value:'status_off', - icon: '' - } + text: '2M', + value: 'status_2M', + icon: '' + }, + { + text: '4M', + value: 'status_4M', + icon: '' + }, + { + text: '7M', + value: 'status_7M', + icon: '' + }, + { + text: '10M', + value: 'status_10M', + icon: '' + }, + { + text: '关闭', + value: 'status_off', + icon: '' + } ], activeIndex: -1, bgColor: '#2a2a2a', @@ -269,6 +291,21 @@ showClose: false }, usrToggle: false, + navbar: { + icons: [{ + src: '/static/images/common/history.png', + callback: this.gotoHistory, + math: 0 + }, + { + src: '/static/images/common/shape.png', + callback: this.gotoShare + } + ], + title: 'HBY102' + + }, + apiType: '' }, formData: { img: '/static/images/common/HBY102.png', @@ -281,13 +318,13 @@ statu: '', sta_address: '', bleStatu: false, - sta_charge:'', + sta_charge: '', sta_LedType: '', sta_RadarType: '', sta_Online: '', warnTime: '', sta_sosadd: "", - sta_sosName:'', + sta_sosName: '', sta_IntrusTime: '' }, @@ -300,7 +337,8 @@ show: true, img: '/static/images/100/light.png', activeImg: '/static/images/100/lightActive.png', - group: 'sta_LedType' + group: 'sta_LedType', + permission: '1' }, { key: 'led_low_flash', @@ -308,7 +346,8 @@ show: true, img: '/static/images/102/lowFlash.png', activeImg: '/static/images/102/lowFlashActive.png', - group: 'sta_LedType' + group: 'sta_LedType', + permission: '1' }, { key: 'led_steady', @@ -316,7 +355,8 @@ show: true, img: '/static/images/102/liting.png', activeImg: '/static/images/102/litingActive.png', - group: 'sta_LedType' + group: 'sta_LedType', + permission: '1' }, { key: 'status_on', @@ -324,7 +364,8 @@ show: true, img: '/static/images/102/redar.png', activeImg: '/static/images/102/redarActive.png', - group: 'sta_RadarType' + group: 'sta_RadarType', + permission: '48' }, { key: 'E49_on', @@ -332,7 +373,8 @@ show: true, img: '/static/images/102/line.png', activeImg: '/static/images/102/lineActive.png', - group: 'sta_Online' + group: 'sta_Online', + permission: '49' }, { key: 'led_off', @@ -377,7 +419,8 @@ showConfirm: false }, groupDevices: [], - warnDevices:[] + warnDevices: [], + permissions: [] } }, @@ -404,9 +447,20 @@ eventChannel.on('detailData', function(data) { - // console.log("收到父页面的参数:" + JSON.stringify(data)); + console.log("收到父页面的参数:" + JSON.stringify(data)); var device = data.data; + these.Status.apiType = data.apiType; + if (data.apiType !== 'listA') { + Common.getdeviceShareId(data.data.id).then(res => { + if (res.code == 200) { + if (res.data.permission) { + these.permissions = res.data.permission.split(','); + } + } + }); + } these.device = device; + these.getWarns(); let f = ble.data.LinkedList.find((v) => { if (v.macAddress == device.deviceMac) { // console.log("找到设备了", v); @@ -452,34 +506,181 @@ }, onShow() { this.Status.pageHide = false; + this.getLinkedCnt(); }, computed: { - Distance:function(){ - let f=this.Status.BottomMenu.menuItems.find((item,index)=>{ - - return item.value===this.formData.sta_RadarType; - - + Distance: function() { + let f = this.Status.BottomMenu.menuItems.find((item, index) => { + + return item.value === this.formData.sta_RadarType; + + }); - if(f){ + if (f) { return f.text; } return '关闭'; }, - activeIndex:function(){ - let active=4; - let f=this.Status.BottomMenu.menuItems.find((item,index)=>{ - - if(item.value===this.formData.sta_RadarType){ - active=index; + activeIndex: function() { + let active = 4; + let f = this.Status.BottomMenu.menuItems.find((item, index) => { + + if (item.value === this.formData.sta_RadarType) { + active = index; } }); return active; } }, methods: { + getLinkedCnt() {//获取在线设备的数量 + let f = this.getDevice(); + // #ifdef APP-PLUS + if (!f) { + return; + } + // #endif + // #ifdef H5 + f = { + deviceId: '12345' + } + // #endif + + + if (ble) { + let buffer = { + ins_Quantity: "query" + }; + ble.sendString(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, 30).then(res=>{ + setTimeout(()=>{ + this.getWarns(); + },1500); + }).catch(()=>{ + this.getWarns(); + }) + } + + + }, + getWarns() { + return new Promise((resolve, reject) => { + if (!these.device.id) { + return; + } + + let warnKey = "102_" + these.device.id + "_warning"; + let linkKey = "102_" + these.device.id + "_linked"; + let p1 = new Promise((succ, err) => { + uni.getStorage({ + key: warnKey, + success(res) { + let data = res.data; + let fs = data.filter(v => { + return !v.read + }); + succ(fs); + }, + fail(ex) { + err(null); + } + }); + }); + + let p2 = new Promise((succ, err) => { + uni.getStorage({ + key: linkKey, + success(res) { + console.error("获取到联机数据",res); + let data = res.data; + let fs = data.filter(v => { + return !v.read + }); + console.error("未读联机数据",fs); + succ(fs); + }, + fail(ex) { + err(null); + } + }); + }); + + Promise.allSettled([p1, p2]).then(results => { + let fs = []; + + if (results[0].status == 'fulfilled') { + fs=fs.concat(results[0].value); + } + if (results[1].status == 'fulfilled') { + fs=fs.concat(results[1].value); + } +console.error("获取到未读消息",fs); + these.$set(these.Status.navbar.icons[0], "math", fs.length); + }); + + + }); + + }, + + gotoHistory(item, s) { + + uni.navigateTo({ + url: '/pages/102/HBY102_History', + success: (res) => { + res.eventChannel.emit('detailData', { + data: these.device + }); + } + }); + + }, + gotoShare(item, s) { + uni.navigateTo({ + url: '/pages/common/share/index', + events: { + ack: function(data) {} + }, + success: (res) => { + let json = { + persissonType: '102' + }; + Object.assign(json, this.device); + res.eventChannel.emit('share', { + data: json + }); + } + }) + }, + handleRightClick(item, s) { + if (item && item.callback) { + item.callback(item, s); + } else { + uni.showModal({ + content: '敬请期待' + }) + + } + }, + navigatorBack() { + uni.navigateBack(); + }, actionSett(item, index) { + + if (!this.permissions.includes(item.permission) && this.Status.apiType !== 'listA') { + + this.showPop({ + message: '无操作权限', + iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png", + borderColor: "#e034344d", + buttonBgColor: "#E03434", + okCallback: null, + buttonText: "确定" + }) + return; + } + + if (item.group == 'sta_LedType') { this.sosSetting(item, index); return; @@ -488,7 +689,7 @@ if (item.group == 'sta_RadarType') { // this.toggleRedar(item, index); - this.showRedarSetting(item,index); + this.showRedarSetting(item, index); return; } @@ -555,24 +756,24 @@ }, - showRedarSetting(){ - this.Status.BottomMenu.show=true; - this.Status.BottomMenu.showBtn=false; - - this.Status.BottomMenu.title="感应距离设置"; - - this.Status.BottomMenu.textAlign="center"; - - this.Status.BottomMenu.showMask=true; - this.Status.BottomMenu.activeIndex=this.activeIndex; + showRedarSetting() { + this.Status.BottomMenu.show = true; + this.Status.BottomMenu.showBtn = false; + + this.Status.BottomMenu.title = "感应距离设置"; + + this.Status.BottomMenu.textAlign = "center"; + + this.Status.BottomMenu.showMask = true; + this.Status.BottomMenu.activeIndex = this.activeIndex; }, - btnClick(item,index){ - this.Status.BottomMenu.show=false; - console.log("选中的项:"+index+",值:"+JSON.stringify(item)); - this.toggleRedar(item,index); + btnClick(item, index) { + this.Status.BottomMenu.show = false; + console.log("选中的项:" + index + ",值:" + JSON.stringify(item)); + this.toggleRedar(item, index); }, - closeActionSheet(){ - this.Status.BottomMenu.show=false; + closeActionSheet() { + this.Status.BottomMenu.show = false; }, toggleRedar(item, index) { //雷达启停 let f = this.getDevice(); @@ -601,7 +802,7 @@ .then(res => { debugger; this.formData.sta_RadarType = val; - this.Status.BottomMenu.activeIndex=index; + this.Status.BottomMenu.activeIndex = index; these.setBleFormData(); resolve(); }) @@ -642,6 +843,19 @@ sosSetting(item, isOk) { + if (!this.permissions.includes('46') && this.Status.apiType !== 'listA') { + + this.showPop({ + message: '无操作权限', + iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png", + borderColor: "#e034344d", + buttonBgColor: "#E03434", + okCallback: null, + buttonText: "确定" + }) + return; + } + if (item.key == 'led_alarm' && this.formData.sta_LedType == 'led_alarm') { return; } @@ -817,59 +1031,66 @@ let json = recei.ReceiveData(receive, device, pagePath, recArr); console.log("json=", json) + setTimeout(()=>{ + this.getWarns(); + },500); - - - let active=-1; - let f=this.Status.BottomMenu.menuItems.find((item,index)=>{ - - if(item.value===json.sta_RadarType){ - active=index; + + let active = -1; + let f = this.Status.BottomMenu.menuItems.find((item, index) => { + + if (item.value === json.sta_RadarType) { + active = index; } }); - this.Status.BottomMenu.activeIndex=active; + this.Status.BottomMenu.activeIndex = active; let msg = []; - if (json.sta_PowerPercent <= 20 && (json.sta_charge===0 || json.sta_charge==='0')) { + if (json.sta_PowerPercent <= 20 && (json.sta_charge === 0 || json.sta_charge === '0')) { msg.push("设备电量低"); } - - if(json.sta_sosadd_off){//某个设备解除报警 - this.warnDevices.filter((d,index)=>{ - if(d.mac===json.sta_sosadd_off){ - this.warnDevices.splice(index,1); + + if (json.sta_sosadd_off) { //某个设备解除报警 + this.warnDevices.filter((d, index) => { + if (d.mac === json.sta_sosadd_off) { + this.warnDevices.splice(index, 1); } }); } - - + + let keys = Object.keys(json); - + keys.forEach(key => { if (key in this.formData) { // console.log("key=",key+",value=",json[key]); this.formData[key] = json[key]; } }); - - if (json.sta_sosadd) {//某个设备闯入报警 - console.log("查询设备中",json.sta_sosadd); + + if (json.sta_sosadd) { //某个设备闯入报警 + console.log("查询设备中", json.sta_sosadd); this.searchDevice(json.sta_sosadd).catch(ex => {}).then(dev => { console.log("dev=", dev); - let d=this.warnDevices.find(v=>{return v.mac===json.sta_sosadd}); - let deviceName=""; + let d = this.warnDevices.find(v => { + return v.mac === json.sta_sosadd + }); + let deviceName = ""; if (dev) { // this.formData.sta_sosName=dev.deviceName; msg.push('"' + dev.deviceName + '"闯入报警中'); - deviceName=dev.deviceName; - + deviceName = dev.deviceName; + } else { msg.push('闯入报警中'); // this.formData.sta_sosName=""; } - if(!d){ - this.warnDevices.push({mac:json.sta_sosadd,name:deviceName}); + if (!d) { + this.warnDevices.push({ + mac: json.sta_sosadd, + name: deviceName + }); } this.showMsg(msg.join(',')); }); @@ -898,7 +1119,7 @@ }, getWarDevice(macStr) { - console.log("macStr=",macStr); + console.log("macStr=", macStr); if (macStr) { if (!macStr.includes(':')) { @@ -1158,6 +1379,11 @@ \ No newline at end of file diff --git a/pages/102/HBY102_History.vue b/pages/102/HBY102_History.vue new file mode 100644 index 0000000..fc8fd88 --- /dev/null +++ b/pages/102/HBY102_History.vue @@ -0,0 +1,1327 @@ + + + + + + \ No newline at end of file diff --git a/pages/6155/BJQ6155.vue b/pages/6155/BJQ6155.vue index 235d947..b4ad2a2 100644 --- a/pages/6155/BJQ6155.vue +++ b/pages/6155/BJQ6155.vue @@ -103,7 +103,7 @@ 发送 + :color="'#000000'" :fontSize="16" /> @@ -178,7 +178,7 @@ baseURL } from '@/utils/request.js'; - var pagePath = "/pages/6155/deviceDetail"; + var pagePath = "/pages/6155/BJQ6155"; var ble = null; var these = null; @@ -192,6 +192,9 @@ data() { return { Status: { + lightMode: { + + }, pageHide: false, Pop: { showPop: false, //是否显示弹窗 @@ -214,19 +217,7 @@ 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' - } - ], + menuItems: [], activeIndex: -1, bgColor: '#2a2a2a', itemBgColor: '#3a3a3a', @@ -260,7 +251,7 @@ deviceId: '', textLines: ['', '', ''], mode: '', - light:null, + light: null, bleStatu: '' }, inteval: 80, @@ -282,8 +273,49 @@ alarmStatus: null, detailPageUrl: "/pages/6155/deviceDetail", showConfirm: false - } + }, + videoHexArray: [], + rgb565Data: [], + dic: { + menuItems: [{ + text: '强光', + icon: '/static/images/6155/DeviceDetail/qiang.png', + math: 100, + type: 'main' + }, + { + text: '弱光', + icon: '/static/images/6155/DeviceDetail/ruo.png', + math: 50, + type: 'main' + }, + { + text: '爆闪', + icon: '/static/images/6155/DeviceDetail/shan.png', + math: 30, + type: 'main' + }, + { + text: '关闭', + icon: '/static/images/6155/DeviceDetail/close.png', + math: 0, + type: 'main' + }, + { + text: '泛光', + icon: '/static/images/6155/DeviceDetail/fan.png', + math: 100, + type: 'fu' + }, + { + text: '强+泛光', + icon: '/static/images/6155/DeviceDetail/fan.png', + math: 70, + type: 'fu' + } + ] + } } }, onUnload() { @@ -403,22 +435,9 @@ }, computed: { - RSSIRemark: function() { - let remark = '极弱'; - if (this.formData.RSSI <= 0 && this.formData.RSSI >= -30) { - remark = '强'; - } + cModeItems: function() { - 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: { @@ -441,16 +460,16 @@ } break; case 2: - if (type == 'main' && this.formData.mode == 'main') { - txt = "爆闪"; - } - + if (type == 'main' && this.formData.mode == 'main') { + txt = "爆闪"; + } + break; case 3: - if (type == 'main' && this.formData.mode == 'main') { - txt = "关闭"; - } - + if (type == 'main' && this.formData.mode == 'main') { + txt = "关闭"; + } + break; default: txt = "关闭"; @@ -478,18 +497,7 @@ return frameSum + packSum; }, 0); }, - toByteValue(value) { - if (typeof value === 'number') { - return value; - } - if (typeof value === 'string') { - if (value.startsWith('0x') || value.startsWith('0X')) { - return parseInt(value, 16); - } - return parseInt(`0x${value}`, 16); - } - return 0; - }, + deviceRecovry(res) { if (this.Status.pageHide) { return; @@ -602,6 +610,7 @@ } }); + // 强制触发视图更新,确保电量显示同步 these.$forceUpdate(); // console.log("更新后的电量:", these.formData.battary); @@ -680,182 +689,142 @@ return; } - // 处理像素数据并发送 - var processAndSendImageData = function(pixels) { + // 分包发送图片数据 + var sendImagePackets = function(ReSendNo) { + return new Promise((resolve, reject) => { - // 创建RGB565格式的像素数据 - // console.log("pixels=",pixels); - const arr = ble.convertToRGB565(pixels, 'bgr'); - var list = []; - let index = 0; // 用于追踪arr的当前位置 - let packetSize = 3200; - let cSize = 200; - // 外层循环:7个主要元素(i从1到7) - for (let i = 1; i < 9; i++) { - let secondLevel = []; - let secondCnt = 0; - // 中层循环:每个主要元素包含9个子数组(j从1到9) - for (let j = 1; j < 9; j++) { - // 确定当前子数组的长度:前8个是254,第9个是64 + // 总数据包数 + let totalPackets = 52; + let currentPacket = 1; - let thirdLevel = []; + if (ReSendNo) { + totalPackets = ReSendNo; + currentPacket = ReSendNo; + } - // 从arr中提取相应数量的元素 - for (let k = 0; k < cSize && index < arr.length; k++) { + if (f) { + // 发送单个数据包 + const sendNextPacket = () => { + if (currentPacket > totalPackets) { + hideLoading(these); + these.Status.BottomMenu.show = false; + these.showPop({ + showPop: true, + message: "上传成功", + iconUrl: "/static/images/common/success.png", + }); - if (secondCnt == packetSize) { - break; - } - thirdLevel.push(arr[index]); - secondCnt++; - index++; + ble.sendString(f.deviceId, "transmit complete", f.writeServiceId, f + .wirteCharactId); + these.rgb565Data = null; + resolve(); + return; } - secondLevel.push(thirdLevel); - } - list.push(secondLevel); - } + // 计算当前包的数据 + let packetSize = 250; + // if (currentPacket <= 51) { + // packetSize = 250; // 前51个包每个500字节 + // } else { + // packetSize = 50; // 最后一个包100字节 + // } - console.log("list=", list); + // 创建数据包 + const startIndex = (currentPacket - 1) * packetSize; + const endIndex = Math.min(startIndex + packetSize, these.rgb565Data + .length); + if (startIndex > endIndex) { + return; + } + const packetData = these.rgb565Data.slice(startIndex, + endIndex); + // 构建数据包 + const bufferSize = 505; // 5 + packetData.length * 2; // 头部5字节 + 数据部分 + const buffer = new ArrayBuffer(bufferSize); + const dataView = new DataView(buffer); - let length = 0; - for (let i = 0; i < list.length; i++) { - const item = list[i]; - let clength = 0; - for (let j = 0; j < item.length; j++) { - const element = item[j]; - console.log("第" + i + "包,第" + j + "小包,长度:" + element.length) - length += element.length; - clength += element.length; + // 填充头部 + dataView.setUint8(0, 0x55); // 帧头 + dataView.setUint8(1, 0x02); // 帧类型:开机画面 + dataView.setUint8(2, '0x' + currentPacket.toString(16).padStart(2, + '0')); // 包序号 - } - } - // 分包发送 - sendImagePackets(list).then(resolve).catch(reject); - }); - } + 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); // 大端字节序 + } + + if (currentPacket > 51) { //第52包补FF + for (var i = 105; i < bufferSize; i++) { + dataView.setUint8(i, 0xFF); + } + } - // 分包发送图片数据 - var sendImagePackets = function(imageData) { - return new Promise((resolve, reject) => { - // 总数据包数 - const totalPackets = 8; - let currentPacket = 1; - let childPacket = 1; - let totalChildPacket = 8; + //发送数据包 + ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, + 10) + .then(() => { - // 发送单个数据包 - const sendNextPacket = () => { - if (currentPacket > totalPackets) { - updateLoading(these, { - text: '发送完成,等待设备30秒' - }); - setTimeout(() => { - hideLoading(these); - these.Status.BottomMenu.show = false; + updateLoading(these, { + text: "正在发送:" + currentPacket + "/" + + totalPackets + }) + currentPacket++; - these.showPop({ - message: "上传成功", - iconUrl: "/static/images/6155/DeviceDetail/uploadSuccess.png", - borderColor: '#BBE600', - buttonBgColor: '#BBE600' + setTimeout(sendNextPacket, these.inteval); + }).catch(err => { + console.log("发送数据包失败了" + JSON.stringify(err)); + if (err.code == '10007') { + setTimeout(sendNextPacket, these.inteval); + return; + } + these.Status.BottomMenu.show = false; + these.showPop({ + message: err.msg, + iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png", + borderColor: "#e034344d", + buttonBgColor: "#E03434", + }); + hideLoading(these); + these.rgb565Data = null; + reject(err); }); + } - resolve(); - }, 0) - + if (ReSendNo) { + sendNextPacket(ReSendNo); return; } + // 开始牵手 + ble.sendString(f.deviceId, "picture transmit start", f.writeServiceId, + f.wirteCharactId).then(() => { + setTimeout(sendNextPacket, 120); - var packetData = imageData[currentPacket - 1][childPacket - 1]; - console.log("childPacket=", childPacket); - console.log("packetData=", packetData); - let start = 0; - let bufferSize = packetData.length * 2; - - - - if (childPacket == 1) { - bufferSize = bufferSize + 8 - start = 8; - } - if (childPacket == 8) { //|| (currentPacket==7 && childPacket==3 - bufferSize = bufferSize + 1 - } - - - //FA 09 0C 84 FE 09 00 [01~08] + 3200字节 +FF 数据格式 - var buffer = new ArrayBuffer(bufferSize); - var dataView = new DataView(buffer); - if (childPacket == 1) { - dataView.setUint8(0, 0xFA); // 帧头 - dataView.setUint8(1, 0x09); // 帧头 - dataView.setUint8(2, 0x0C); // 帧头 - dataView.setUint8(3, 0x84); // 帧头 - dataView.setUint8(4, 0xFE); // 帧头 - dataView.setUint8(5, 0x09); - dataView.setUint8(6, 0x00); // 帧头 - dataView.setUint8(7, currentPacket); //包序号 - } - - for (let i = 0; i < packetData.length; i++) { - dataView.setUint16(start + i * 2, packetData[i], false); //本包数据,大端字节序 - } - console.log("packetData.length=", packetData.length); - console.log("bufferSize=", bufferSize) - if (childPacket == 8) { // || (currentPacket==7 && childPacket==3 - dataView.setUint8(bufferSize - 1, 0xFF); - } - - //发送数据包 - ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, - 30) - .then(() => { - - let curr = childPacket + (currentPacket - 1) * - totalChildPacket; - console.log("第" + currentPacket + "大包,第" + childPacket + - "小包发送完成,总计:" + curr); - updateLoading(these, { - text: "正在发送" + curr + "/64" - - }) - if (childPacket == 8) { - currentPacket++; - childPacket = 1; - } else { - childPacket++; - } - - setTimeout(sendNextPacket, 100); - }).catch(err => { - if (err.code == 10007) { - setTimeout(sendNextPacket, 100); - return; - } - - console.log("发送数据包失败了", err); - - these.Status.BottomMenu.show = false; - these.showPop({ - message: "发送数据包失败了" + err.msg, - iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png", - borderColor: "#e034344d", - buttonBgColor: "#E03434", - }); - - hideLoading(these); - reject(err); + }).catch((err) => { + console.log("握手没有成功"); + these.showPop({ + message: err.msg, + iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png", + borderColor: "#e034344d", + buttonBgColor: "#E03434", }); + hideLoading(these); + reject(err); + }); } - // 开始发送数据 - sendNextPacket(); - }); } @@ -871,14 +840,15 @@ ImgCutOver: function(data) { showLoading(these, { - text: "正在发送0/64" + text: "正在发送0/52" }); - + console.log("data=", data); these.Status.BottomMenu.show = false; + these.rgb565Data = ble.convertToRGB565(data.piexls); + setTimeout(function() { - processAndSendImageData(data.piexls).catch(( - ex) => { - console.log("出现异常", ex); + sendImagePackets().catch(() => { + }); }, 0) @@ -911,251 +881,273 @@ hideLoading(these); }, 1500); } - //视频上传 - let uplploadVideo = (videoPath, width, height) => { + + let sendVideoPackets = (ReSendNo) => { + console.log("开始发送分片数据"); return new Promise((resolve, reject) => { - let start = new Date(); + if (f) { + // 总数据包数 + var totalPackets = 1536; //36; - let token = uni.getStorageSync('token'); - let clientid = uni.getStorageSync('clientID'); - uni.uploadFile({ + 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(() => { - url: baseURL + "/app/video/upload", - filePath: videoPath, - name: 'file', - header: { - "Method": "POST", - "Content-Type": "multipart/form-data", - "Authorization": 'Bearer ' + token, - "clientid": clientid - }, - formData: { - code: 1, - width: width, - height: height - }, - timeout: 600000, - fail: (ex) => { + ble.sendString(f.deviceId, "transmit complete", f + .writeServiceId, f.wirteCharactId, 20) + .then( + () => { + console.log("全部发送完毕") + }).catch((ex) => { + console.log("出现异常", ex); + }); + }, 500); - updateLoading(these, { - text: '视频文件上传失败了,请检查网络连接' - }); + } + these.Status.BottomMenu.show = false; + hideLoading(these); + these.showPop({ + showPop: true, + message: "上传成功", + iconUrl: "/static/images/common/success.png" + }); + these.videoHexArray = null; + resolve(); - reject(ex); - }, - success: (res) => { - // console.error(res); - let end = new Date(); - var diff = (end.getTime() - start.getTime()) / 1000; - let s = diff % 60; - let m = parseInt((diff - s) / 60); - console.log("res.statusCode==", res.statusCode); - res.data = JSON.parse(res.data); + return; + } - if (res.statusCode === 200) { - if (res.data.code == 200) { - console.log("上传完成,耗时:" + m + "分" + s + "秒"); - updateLoading(these, { - text: "上传完成,耗时:" + m + "分" + s + "秒,正在切片。" - }) - resolve(res.data); + // 计算当前包的数据 + let packetSize = 500; - return; + + // 创建数据包 + const startIndex = (currentPacket - 1) * packetSize; + const endIndex = Math.min(startIndex + packetSize, these.videoHexArray + .length); + if (startIndex > endIndex) { + resolve(); + return; + } + ////console.log("111111"); + const packetData = these.videoHexArray.slice(startIndex, endIndex); + + // 构建数据包 + ////console.log("packetData.length"+packetData.length); + const bufferSize = 504; // 头部5字节 + 数据部分 + const buffer = new ArrayBuffer(bufferSize); + const dataView = new DataView(buffer); + + let sortNo = currentPacket.toString(16).padStart(4, '0'); + + // 填充头部 + dataView.setUint8(0, 0x55); // 帧头 + dataView.setUint8(1, 0x04); // 帧类型:开机画面 + dataView.setUint8(2, '0x' + sortNo.substring(0, 2)); // 包序号 + dataView.setUint8(3, '0x' + sortNo.substring(2, 4)); // 包序号 + + // dataView.setUint8(4, 0x01); + // dataView.setUint8(5, 0xF4); + + for (let i = 0; i < packetData.length; i++) { + dataView.setUint8(4 + i, '0x' + packetData[i]); + } + + let inteval = 40; + + ble.sendData(f.deviceId, buffer, f.writeServiceId, f + .wirteCharactId, 10).then(() => { + + updateLoading(these, { + text: "正在发送:" + currentPacket + "/" + + totalPackets + }) + + currentPacket++; + + // console.log("发送一段成功,发送下一段"); + setTimeout(sendNextVideoPacket, inteval); + }).catch(err => { + console.log("发送失败了", err); + if (err.code == '10007') { //遇到这个错误自动重新发送 + console.log(err.errMsg + ",发送失败了,正在补偿:" + + currentPacket); + setTimeout(sendNextVideoPacket, inteval); } else { - console.log("res.data=", res.data); + 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); + these.videoHexArray = null; + return; } - } - console.error("上传完成,耗时:" + m + "分" + s + "秒"); - reject(res); - - } - - }); - - }); + }); + }; + sendNextVideoPacket(); - } - //视频切片 - let videoCutPacket = (data) => { - return new Promise((resolve, reject) => { - try { - const imgSize = 25600; - const packetSize = 3200; - const chunkSize = 500; - const maxPacketCount = 30; - - let source = Array.isArray(data) ? data.slice() : []; - let results = []; - for (let i = 0; i < maxPacketCount && source.length >= imgSize; i++) { - let frameBytes = source.splice(0, imgSize); - let framePackets = []; - - for (let j = 0; j < 8 && frameBytes.length > 0; j++) { - let majorPacket = frameBytes.splice(0, packetSize); - let childPackets = []; - - while (majorPacket.length > 0) { - let chunk = majorPacket.splice(0, chunkSize); - if (chunk.length) { - childPackets.push(chunk); - } - } - if (childPackets.length) { - framePackets.push(childPackets); - } - } - - if (framePackets.length) { - results.push(framePackets); - } - } - updateLoading(these, { - text: '切片完成,正在发送' - }); - resolve(results); - } catch (error) { - updateLoading(these, { - text: '视频切片发生异常' - }); - reject(error); + } else { + console.log("Fail.......") } }); } - //发送视频到设备 - let shotVideoClick = (array, type, ReSendNo) => { - var sendImagePackets = () => { - return new Promise((resolve, reject) => { - this.currentPacket = 0; - let totalPackets = these.calcTotalPackets(array); - this.totalPackets = totalPackets; - if (totalPackets === 0) { - reject('没有可发送的数据'); + var sendVideo = (videoPath) => { + let uploadVideo = () => { + + these.videoHexArray = []; + console.log("开始处理,正在上传"); + + showLoading(these, { + text: "上传中" + }); + let p1 = new Promise((resolve, reject) => { + + ble.sendString(f.deviceId, "video transmit start", f + .writeServiceId, f.wirteCharactId).then(res => { + + setTimeout(() => { + console.log("握手成功了"); + resolve(true); + }, 2200) + }).catch(ex => { + reject(ex); + }); + }); + + + let p2 = new Promise((succ, err) => { + + const token = uni.getStorageSync('token'); + const clientid = uni.getStorageSync('clientID'); + if (!token) { + err({ + code: 401, + msg: "请先登陆后再试" + }); + hideLoading(these); return; } - let currentPacket = 1; + console.log("baseURL=", baseURL); + console.log("token", token); + console.log("clientID", clientid); + uni.uploadFile({ + // url: 'http://114.55.111.217/video/upload', + url: baseURL + "/app/video/upload", + filePath: videoPath, + name: 'file', + header: { + "Method": "POST", + "Content-Type": "multipart/form-data", + "Authorization": 'Bearer ' + token, + "clientid": clientid + }, + timeout: 600000, + fail: (ex) => { + console.log("上传视频失败" + JSON.stringify(ex)); - let imgIndex = 0; - let imgPackIndex = 0; - let childPacketIndex = 0; - if (ReSendNo) { - this.currentPacket = ReSendNo - 1; - currentPacket = ReSendNo; - totalPackets = ReSendNo; - this.totalPackets = ReSendNo; - } - // 发送单个数据包 - const sendNextPacket = () => { - if (imgIndex >= array.length) { - resolve(); - return; + err(ex); + }, + success: (res) => { + + console.log("上传完成,向蓝牙设备发送"); + succ(res); } - if (!array[imgIndex]) { - console.error("没有找到对应的帧数据", imgIndex); - reject(`帧数据缺失,索引 ${imgIndex}`); - return; - } + }); + }); - let childPacketsGroup = array[imgIndex][imgPackIndex]; - if (!childPacketsGroup || !childPacketsGroup.length) { - console.error("帧数据结构异常", imgIndex, imgPackIndex); - reject(`帧数据结构异常,帧 ${imgIndex}`); - return; - } + Promise.all([p1, p2]).then((arr) => { - let packetData = childPacketsGroup[childPacketIndex]; - let packetSize = packetData.length; - - const isFirstChild = childPacketIndex === 0; - const isLastChild = childPacketIndex === (childPacketsGroup - .length - 1); - - if (isFirstChild) { - packetSize = packetData.length + 8; - } - - if (isLastChild) { - packetSize = packetData.length + (isFirstChild ? 9 : 1); - } - - const buffer = new ArrayBuffer(packetSize); - const dataView = new DataView(buffer); - - let start = 0; - if (isFirstChild) { - // 填充头部 - dataView.setUint8(0, 0xFA); // 帧头 - dataView.setUint8(1, 0x09); // 帧类型:开机画面 - dataView.setUint8(2, 0x0C); - dataView.setUint8(3, 0x84); - dataView.setUint8(4, 0xFD); - dataView.setUint8(5, 0x09); - dataView.setUint8(6, imgIndex); - dataView.setUint8(7, imgPackIndex + 1); - start = 8; - } - - for (let i = 0; i < packetData.length; i++) { - dataView.setUint8(start + i, these.toByteValue(packetData[i])); - } - - if (isLastChild) { - dataView.setUint8(packetSize - 1, 0xFF); - } - let inteval = parseInt(this.inteval ? this.inteval : 80); - // console.log(inteval, 'intevalinteval'); - ble.sendData(f.deviceId, buffer, f.writeServiceId, f - .wirteCharactId).then(() => { - if (ReSendNo) { - resolve(); - return; - } - // 更新进度 - this.currentPacket = currentPacket; - - updateLoading(these, { - text: '正在发送:' + currentPacket + "/" + - totalPackets - }); - - childPacketIndex++; - if (childPacketIndex >= childPacketsGroup.length) { - childPacketIndex = 0; - imgPackIndex++; - if (imgPackIndex >= array[imgIndex].length) { - imgPackIndex = 0; - imgIndex++; - } - } - // 发送下一个包(添加延迟避免蓝牙缓冲区溢出) - currentPacket++; - - setTimeout(sendNextPacket, inteval); - }).catch(err => { - if (err.code == 10007) { - console.error(err.errMsg + ",发送失败了,正在补偿:" + - currentPacket); - setTimeout(sendNextPacket, 100); - return; - } - - console.error(err.errMsg + ",发送失败了" + currentPacket); - updateLoading(these, { - text: "发送失败," + err.errMsg - }); - reject(err); + if (arr[0].status == 'rejected') { + these.showPop({ + message: "设备准备未就绪", + iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png", + borderColor: "#e034344d", + buttonBgColor: "#E03434", }); - }; - sendNextPacket(); + return; + } + let res = arr[1]; + // console.log("11111111111111111111111",res); + res = JSON.parse(res.data); + // console.log("22222222222222222222"); + if (res.data) { + these.videoHexArray = res.data; + updateLoading(these, { + text: "正在发送:0/1536" + }); + + these.Status.BottomMenu.show = false; + + shotVideoClick(res.data); + + + } else { + console.log("服务器未返回正确的数据"); + + + these.showPop({ + message: "与服务器连接出现异常,请检查网络设置", + iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png", + borderColor: "#e034344d", + buttonBgColor: "#E03434", + }); + } + + }).catch((ex) => { + console.log("出现异常,", ex) + hideLoading(these); + these.showPop({ + message: "出现异常," + ex.msg, + iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png", + borderColor: "#e034344d", + buttonBgColor: "#E03434", + }); + }) + } + let f = these.getDevice(); + + + + + let shotVideoClick = () => { + console.log("正在开始发送"); + sendVideoPackets().then(() => { + console.log("发送完成"); + + }).catch((ex1) => { + //console.log("出现了异常", ex1) + }).finally(() => { + hideLoading(these); }); } - return sendImagePackets(); + + + uploadVideo(); + } uni.chooseVideo({ @@ -1214,60 +1206,7 @@ text: '正在上传' }); setTimeout(() => { - uplploadVideo(path, width, height).then(result => { - - let data = result.data; - let convertedData = []; - for (let i = 0; i < data.length; i += 2) { - if (i + 1 < data.length) { - const byte1 = these.toByteValue(data[i]); - const byte2 = these.toByteValue(data[i + 1]); - const rgb565 = (byte1 << 8) | byte2; - const red = (rgb565 & 0xF800) >> 11; - const green = (rgb565 & 0x07E0) >> 5; - const blue = (rgb565 & 0x001F); - const bgr565 = (blue << 11) | (green << 5) | red; - convertedData.push((bgr565 >> 8) & 0xFF); - convertedData.push(bgr565 & 0xFF); - } else { - convertedData.push(these.toByteValue(data[i])); - } - } - - videoCutPacket(convertedData).then(array => { - - let start = new Date(); - console.log("开始发送"); - shotVideoClick(array).then(() => { - console.log("发送完成"); - let end = new Date(); - var diff = (end.getTime() - start - .getTime()) / 1000; - let s = parseInt(diff % 60); - let m = parseInt((diff - s) / 60); - console.log("发送完成,耗时:" + m + "分" + - s + "秒"); - updateLoading(these, { - text: "发送完成,耗时:" + m + - "分" + s + "秒", - }); - - }).catch((ex1) => { - console.log("出现了异常", ex1) - }).finally(() => { - timeDelayCloseLoading(); - }); - - - - - }).catch(err => { - timeDelayCloseLoading(); - }); - - }).catch(ex => { - timeDelayCloseLoading(); - }); + sendVideo(path); }, 0); } @@ -1284,58 +1223,34 @@ }, ModeSetting: function(type) { - - let items = []; - let title = ''; + this.Status.lightMode = type; + let title = ''; + let items = this.dic.menuItems.filter((v => { + return v.type == type; + })); switch (type) { case "main": title = '主灯模式'; - items = [{ - text: '强光', - icon: '/static/images/6155/DeviceDetail/qiang.png' - }, - // { - // text: '工作光', - // icon: '/static/images/6155/DeviceDetail/fan.png' - // }, - { - text: '弱光', - icon: '/static/images/6155/DeviceDetail/ruo.png' - }, - { - text: '爆闪', - icon: '/static/images/6155/DeviceDetail/shan.png' - }, - { - text: '关闭', - icon: '/static/images/6155/DeviceDetail/close.png' - } - ]; + break; case "fu": title = '辅灯模式'; - items = [{ - text: '泛光', - icon: '/static/images/6155/DeviceDetail/fan.png' - }, - { - text: '强+泛光', - icon: '/static/images/6155/DeviceDetail/fan.png' - }, - ]; + break; } - + this.Status.BottomMenu.menuItems = items; this.Status.BottomMenu.title = title; this.Status.BottomMenu.type = type; this.Status.BottomMenu.show = true; - if(this.formData.mode != type){ - - this.Status.BottomMenu.activeIndex =null; - } - + if (this.formData.mode != type) { + + this.Status.BottomMenu.activeIndex = null; + } else { + this.Status.BottomMenu.activeIndex = this.formData.light; + } + }, showMenu(flag) { this.Status.BottomMenu.show = true; @@ -1363,26 +1278,28 @@ setMode(mode, type) { let dataValue = 0; + console.log("mode=", mode); + switch (mode) { case 0: if (type == 'main') { - dataValue = 0x01; + dataValue = 0x6D; } else if (type == 'fu') { - dataValue = 0x04; + dataValue = 0x71; } break; case 1: if (type == 'main') { - dataValue = 0x02; + dataValue = 0x6E; } else if (type == 'fu') { - dataValue = 0x0A; //强泛光 + dataValue = 0x72; //强泛光 } break; case 2: - dataValue = 0x03; + dataValue = 0x70; break; case 3: - dataValue = 0x0B; + dataValue = 0x6F; break; } @@ -1391,12 +1308,12 @@ var buffer = new ArrayBuffer(6); var dataView = new DataView(buffer); - dataView.setUint8(0, 0xFA); // 帧头 - dataView.setUint8(1, dataValue); // 帧类型 - dataView.setUint8(2, 0x00); // 数据 - dataView.setUint8(3, 0x01); // 数据 - dataView.setUint8(4, 0x00); // 数据 - dataView.setUint8(5, 0xFF); // 数据 + dataView.setUint8(0, 0x55); // 帧头 + dataView.setUint8(1, 0x00); // 帧类型 + dataView.setUint8(2, 0x01); // 数据 + dataView.setUint8(3, 0x00); // 数据 + dataView.setUint8(4, 0x01); // 数据 + dataView.setUint8(5, dataValue); // 数据 let f = this.getDevice(); // 发送数据 @@ -1413,6 +1330,7 @@ ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, 30).then(() => { this.formData.light = mode; this.formData.mode = type + this.formData.liangDu = 100; this.setBleFormData(); }).catch((ex) => { these.showPop({ @@ -1527,6 +1445,20 @@ these.showBleUnConnect() return; } + + let toByteValue = (value) => { + if (typeof value === 'number') { + return value; + } + if (typeof value === 'string') { + if (value.startsWith('0x') || value.startsWith('0X')) { + return parseInt(value, 16); + } + return parseInt(`0x${value}`, 16); + } + return 0; + } + let err = false; this.formData.textLines.find((txt) => { if (txt.length === 0 || txt.length > 7) { @@ -1548,90 +1480,129 @@ showLoading(these, { text: "请稍候..." }); - this.setBleFormData(); - let task = async () => { + //握手 + let holdHand = () => { + return new Promise((resolve, reject) => { + updateLoading(these, { + text: '设备准备中...' + }) + let hexs = 'word transmit start'; + ble.sendString(f.deviceId, hexs, f.writeServiceId, f.wirteCharactId, 10).then(res => { + setTimeout(() => { + resolve(res) + }, 2200); + + }).catch(ex => { + reject(ex) + }); + + }); + } + //画图 + let drawText = () => { + return new Promise((resolve, reject) => { + this.$refs.textToHex.drawAndGetPixels().then(allPixels => { + if (!allPixels) { + reject("文本初始化失败"); + return; + } + resolve(allPixels); + }).catch(compEx => { + reject(compEx); + }); + + }); + } + //发送3个分包的数据 + let task = (allPixels) => { try { - // 预热画布,确保画布和字体完全准备好(解决APP重新打开后第一次获取数据不完整的问题) - console.log("预热画布..."); - await this.$refs.textToHex.drawAndGetPixels(); - await new Promise(resolve => setTimeout(resolve, 200)); // 等待预热完成 - - // 1. 获取所有文本行的像素数据 - const allPixels = await this.$refs.textToHex.drawAndGetPixels(); - if (!allPixels) { - throw new Error("无法生成像素数据"); - } - - // 2. 将所有像素数据合并到一个大数组中 let combinedData = []; for (let i = 0; i < 3; i++) { - const linePixels = (allPixels[i] || []).flat(Infinity).map(item => - typeof item === 'string' ? these.toByteValue(item) : item + let linePixels = (allPixels[i] || []).flat(Infinity).map(item => + typeof item === 'string' ? toByteValue(item) : item ); - // 补齐到256字节 - while (linePixels.length < 256) { + for (var j = linePixels.length; j < 256; j++) { linePixels.push(0x00); + } - combinedData = combinedData.concat(linePixels.slice(0, 256)); + linePixels = [0xFA, 0x06, 0x03, i + 1].concat(linePixels); + + linePixels.push(0xFF) + + combinedData.push(linePixels); } + combinedData.push([0x74, 0x72, 0x61, 0x6E, 0x73, 0x6D, 0x69, 0x74, 0x20, 0x63, 0x6F, 0x6D, + 0x70, 0x6C, 0x65, 0x74, 0x65 + ]); - // 3. 构建完整的逻辑大包 - const logicalPacketSize = 4 + combinedData.length + 1; // Header + Data + Footer - const logicalBuffer = new ArrayBuffer(logicalPacketSize); - const logicalDataView = new DataView(logicalBuffer); - // 写入头部 - logicalDataView.setUint8(0, 0xFA); - logicalDataView.setUint8(1, 0x06); - logicalDataView.setUint8(2, 0x03); - logicalDataView.setUint8(3, 0x00); - // 写入数据 - for (let i = 0; i < combinedData.length; i++) { - logicalDataView.setUint8(4 + i, combinedData[i]); - } - - // 写入尾部 - logicalDataView.setUint8(logicalPacketSize - 1, 0xFF); - - // 4. 将逻辑大包分包发送 - const CHUNK_SIZE = 500; // 每个物理包的大小 - const totalChunks = Math.ceil(logicalPacketSize / CHUNK_SIZE); - - updateLoading(these, { - text: `准备发送,共 ${totalChunks} 个数据包...` + let curr = 1; + let len = combinedData.length; + console.log(combinedData); + showLoading(these, { + text: '正在发送' + (curr - 1) + '/' + len }); - for (let i = 0; i < totalChunks; i++) { - const start = i * CHUNK_SIZE; - const end = Math.min(start + CHUNK_SIZE, logicalPacketSize); - const chunk = logicalBuffer.slice(start, end); + //分包发送 + let sendPacket = () => { + + if (combinedData.length === curr - 1) { + + these.setBleFormData(); + these.showPop({ + message: "发送成功", + iconUrl: "/static/images/common/success.png", + borderColor: '#BBE600', + buttonBgColor: '#BBE600' + }); + + let json = { + deviceId: these.device.id, + name: these.formData.textLines[1], + position: these.formData.textLines[0], + unitName: these.formData.textLines[2], + code: "" + }; + usrApi.sendUsr(json); + + hideLoading(these); + return; + } + + let array = combinedData[curr - 1]; + + + ble.sendHexs(f.deviceId, array, f.writeServiceId, f.wirteCharactId, 10).then( + res => { + + + updateLoading(these, { + text: '正在发送' + curr + '/' + len + }); + curr++; + setTimeout(sendPacket, 150); + }).catch(err => { + if (err.code == '10007') { + + setTimeout(sendPacket, 150); + } else { + console.log("err:", err); + hideLoading(these); + these.showPop({ + message: "发送失败: " + (err.msg || err.message), + iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png", + borderColor: "#e034344d", + buttonBgColor: "#E03434", + }); + } - updateLoading(these, { - text: `正在发送 ${i + 1} / ${totalChunks}` }); - - await ble.sendData(f.deviceId, chunk, f.writeServiceId, f.wirteCharactId, 50); - await new Promise(resolve => setTimeout(resolve, 50)); // 包之间延迟 } + setTimeout(sendPacket, 0); // 5. 发送成功处理 - hideLoading(these); - this.showPop({ - message: "发送成功", - iconUrl: "/static/images/6155/DeviceDetail/uploadSuccess.png", - borderColor: '#BBE600', - buttonBgColor: '#BBE600' - }); - let json = { - deviceId: these.device.id, - name: these.formData.textLines[1], - position: these.formData.textLines[0], - unitName: these.formData.textLines[2], - code: "" - }; - usrApi.sendUsr(json); } catch (ex) { hideLoading(these); @@ -1642,11 +1613,38 @@ buttonBgColor: "#E03434", }); } - }; - setTimeout(task, 0); + + + } + + setTimeout(() => { + Promise.allSettled([holdHand(), drawText()]).then(results => { + if (results[0].status == 'rejected') { + updateLoading(these, { + text: results[0].reason + }); + setTimeout(() => { + hideLoading(these) + }, 500); + return; + } + if (results[1].status == 'rejected') { + updateLoading(these, { + text: results[1].reason + }) + setTimeout(() => { + hideLoading(these) + }, 500); + return; + } + + task(results[1].value); + }) + + }, 0); }, getDetail() { - var that = this; + var these = this; usrApi.getDetail(this.device.id).then(res => { if (res && res.code == 200) { @@ -1671,76 +1669,63 @@ }, sliderChange: function(evt) { + let f = this.getDevice(); + if (!f) { + these.showBleUnConnect() + return; + } this.formData.liangDu = evt.detail.value; clearTimeout(BrighInteval) //给蓝牙设备发送信号更新亮度 BrighInteval = setTimeout(() => { + this.sendBrightness(); - this.setBleFormData(); + }, 100); }, sendBrightness: function() { - const buffer = new ArrayBuffer(6); - const dataView = new DataView(buffer); - let data = '0x' + parseInt(this.formData.liangDu).toString(16); - console.log("亮度:" + this.formData.liangDu + ',16进制:' + data); - dataView.setUint8(0, 0xFA); // 帧头 - dataView.setUint8(1, 0x05); // 帧类型:亮度调节 - dataView.setUint8(2, 0x00); // 包序号 - dataView.setUint8(3, 0x01); // 包序号 - dataView.setUint8(4, data); // 数据长度 - dataView.setUint8(5, 0xFF); // 数据长度 + try { + let liangDu = this.formData.liangDu + let fs = this.dic.menuItems.filter((v => { + return v.type == this.formData.mode; + })); + if (fs.length > 0) { + if (this.formData.light < fs.length) { + let f = fs[this.formData.light]; - let f = this.getDevice(); - if (f) { - // 发送数据 + liangDu = Math.floor(liangDu / 100 * f.math); + console.error("当前模式", this.formData.mode); + console.error("当前灯光", this.formData.light); + console.error("当前亮度", liangDu); + } + } + const buffer = new ArrayBuffer(6); + const dataView = new DataView(buffer); - ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, 30); + dataView.setUint8(0, 0x55); // 帧头 + dataView.setUint8(1, 0x07); // 帧类型:亮度调节 + dataView.setUint8(2, 0x01); // 包序号 + dataView.setUint8(3, 0x00); // 包序号 + dataView.setUint8(4, 0x01); // 数据长度 + dataView.setUint8(5, liangDu); // 数据长度 + + let f = this.getDevice(); + if (f) { + // 发送数据 + + ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, 30).then(res => { + this.setBleFormData(); + }).catch(err=>{ + + }); + + } + } catch (ex) { + console.error("出现错误", ex); } - }, - //获取当前设备状态 - GetDeviceStatu: function() { - //数据头 命令码 数据 校验码 - //JQOC 0B 00 9C41 - //硬件响应 - //数据头 命令码 主灯模式 副灯模式 亮度(%) 电量(%) 充电状态 校验码 - //JQOC 0B 01 01 64 85 01 9C41 - this.sendCmd('0x0B'); - }, - //设备重启 - DeviceReStart: function() { - //数据头 命令码 数据 校验码 - //JQOC 0C 01 9C412 - this.sendCmd('0x0C'); - }, - //恢复出厂设置 - DeviceReSet: function() { - //数据头 命令码 数据 校验码 - //JQOC 0D 01 9C412 - this.sendCmd('0x0D'); - }, - sendCmd: function(type, callback) { - //数据头 命令码 数据 校验码 - - const buffer = new ArrayBuffer(7); - const dataView = new DataView(buffer); - let data = '0x' + parseInt(this.formData.liangDu).toString(16); - console.log("亮度:" + this.formData.liangDu + ',16进制:' + data); - dataView.setUint8(0, 'JQOC'); // 帧头 - dataView.setUint8(1, type); // 帧类型:亮度调节 - dataView.setUint8(2, '0x01'); // 包序号 - dataView.setUint8(3, '9C41'); // 数据长度 - let f = this.getDevice(); - if (f) { - // 发送数据 - - ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, 30); - - - } } diff --git a/pages/670/HBY670.vue b/pages/670/HBY670.vue index 345debe..0142f06 100644 --- a/pages/670/HBY670.vue +++ b/pages/670/HBY670.vue @@ -9,7 +9,7 @@ - + diff --git a/pages/common/addBLE/addEquip.vue b/pages/common/addBLE/addEquip.vue index 4b00e7c..c9b31ee 100644 --- a/pages/common/addBLE/addEquip.vue +++ b/pages/common/addBLE/addEquip.vue @@ -422,8 +422,11 @@ if (these.Status.isPageHidden) { return; } + if(receivData.bytes[0]===0xFC && receivData.hexs.length>=7){ + console.log("22222222"); + } if(receivData.str.indexOf('mac address:')>-1 || receivData.str.indexOf('sta_address')>-1 - || (receivData.hexs[0]===0xFC && receivData.hexs.length>=7)) + || (receivData.bytes[0]===0xFC && receivData.bytes.length>=7)) { console.log("1111111"); if (f.macAddress && these.device) { @@ -716,8 +719,8 @@ }); return; } - console.log("验证设备") - these.DeviceVerdict(item.deviceId); + // console.log("验证设备") + // these.DeviceVerdict(item.deviceId); } let execLink = () => { return new Promise((resolve, reject) => { diff --git a/pages/common/index/index.vue b/pages/common/index/index.vue index d4ad9ab..a848ff5 100644 --- a/pages/common/index/index.vue +++ b/pages/common/index/index.vue @@ -25,7 +25,7 @@ 发送信息 - @@ -147,11 +147,12 @@ } from '@/api/common/index.js' import bleTool from '@/utils/BleHelper.js'; import MescrollUni from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-uni.vue' - +import BleReceive from '@/utils/BleReceive'; var pagePath = 'pages/common/index'; var ble = null; var timeout = null; + var recei=null; export default { components: { MescrollUni @@ -498,6 +499,9 @@ case 'scan': // 扫一扫 uni.scanCode({ + autoDecodeCharset:true, + autoZoom:true, + barCodeInput:true, success: (res) => { console.log('条码内容:', res); // 清除之前的数据 @@ -512,14 +516,19 @@ if ('imei' in json) { url = `/pages/common/qrcode/qrcode?deviceId=${encodeURIComponent(json.imei)}`; - } else if ('blue' in json) { - if (!json.blue.includes(':')) { - json.blue = json.blue.replace( - /(.{2})/g, '$1:') - .slice(0, -1) + } else if ('blue' in json || 'ble' in json) { + if(json.ble){ + json.blue=json.ble; } - url = - `/pages/common/addBLE/LinkBle?mac=${encodeURIComponent(json.blue)}`; + if(json.blue){ + if (!json.blue.includes(':')) { + json.blue = json.blue.replace( + /(.{2})/g, '$1:') + .slice(0, -1) + } + } + + url =`/pages/common/addBLE/LinkBle?mac=${encodeURIComponent(json.blue)}`; } } catch (ex) { @@ -771,7 +780,7 @@ this.downCallback(); }); ble = bleTool.getBleTool(); - + recei = BleReceive.getBleReceive(); //蓝牙连接成功的回调 ble.addRecoveryCallback((res) => { console.log("蓝牙连接成功的回调"); @@ -797,7 +806,9 @@ }, pagePath); //接收到消息的回调 - ble.addReceiveCallback((rec, f, path, arr) => { + ble.addReceiveCallback((receive, device, path, recArr) => { + console.error("首页收到消息了"); + recei.ReceiveData(receive, device, path, recArr); this.updateBleStatu(); }, pagePath); @@ -809,7 +820,7 @@ uni.$off('refreshDeviceList'); }, onUnload() { - + console.log("onUnload..."); uni.$off('deviceStatusUpdate'); ble && ble.removeAllCallback(pagePath); } diff --git a/static/images/common/filter.png b/static/images/common/filter.png new file mode 100644 index 0000000..53386f1 Binary files /dev/null and b/static/images/common/filter.png differ diff --git a/static/images/common/history.png b/static/images/common/history.png new file mode 100644 index 0000000..c940047 Binary files /dev/null and b/static/images/common/history.png differ diff --git a/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue b/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue index 5a300bf..c627d86 100644 --- a/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue +++ b/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue @@ -74,7 +74,7 @@ props: { dark: { type: Boolean, - default: false + default: true }, title: { type: String, @@ -98,7 +98,7 @@ }, fixed: { type: [Boolean, String], - default: false + default: true }, color: { type: String, @@ -110,7 +110,7 @@ }, statusBar: { type: [Boolean, String], - default: false + default: true }, shadow: { type: [Boolean, String], @@ -118,7 +118,7 @@ }, border: { type: [Boolean, String], - default: true + default: false }, height: { type: [Number, String], @@ -126,11 +126,11 @@ }, leftWidth: { type: [Number, String], - default: 60 + default: 90 }, rightWidth: { type: [Number, String], - default: 60 + default: 90 }, showMenuButtonWidth: { type: Boolean, @@ -153,7 +153,7 @@ if (this.backgroundColor) { return this.backgroundColor } else { - return this.dark ? '#333' : '#FFF' + return this.dark ? '#121212' : '#FFF' } } return this.backgroundColor || '#FFF' diff --git a/utils/BleHelper.js b/utils/BleHelper.js index 5602171..ea7f675 100644 --- a/utils/BleHelper.js +++ b/utils/BleHelper.js @@ -780,7 +780,6 @@ class BleHelper { if (this.cfg.receivDataCallback.length > 0) { - let path = this.getCurrentPagePath(); // console.log("有人订阅消息") this.cfg.receivDataCallback.forEach(( rec) => { @@ -789,7 +788,7 @@ class BleHelper { try { // console.log("正在处理订阅消息",rec); rec.callback(recData, f, - path, this.cfg + rec.key, this.cfg .receivDataCallback ); // console.log("处理订阅消息完毕"); @@ -1601,12 +1600,23 @@ class BleHelper { timeout: 30000, success: (info) => { //释放连接锁 + delete this.data.connectingDevices[deviceId]; console.log("新连接成功", this.data.LinkedList); + + // 处理 MTU 设置 + if (plus.os.name === 'Android') { + this.setMtu(deviceId).catch(ex => { + console.error("mtu设置失败=", ex); + }); + } + this.getLinkBlue().then((arr) => { + let linkId=new Date().getTime();//本次连接的id let cr = arr.devices.find(c => { if (c.deviceId == deviceId) { c.Linked = true; + c.linkId=linkId return true; } return false; @@ -1614,6 +1624,7 @@ class BleHelper { if (fIndex > -1) { this.data.LinkedList[fIndex].Linked = true; + this.data.LinkedList[fIndex].linkId=linkId; } else { this.data.LinkedList.push(cr); } @@ -1647,12 +1658,7 @@ class BleHelper { }); } - // 处理 MTU 设置 - if (plus.os.name === 'Android') { - this.setMtu(deviceId).catch(ex => { - console.error("mtu设置失败=", ex); - }); - } + resolve(true); }).catch((ex) => { diff --git a/utils/BleReceive.js b/utils/BleReceive.js index f64bbc3..b31a44b 100644 --- a/utils/BleReceive.js +++ b/utils/BleReceive.js @@ -1,8 +1,11 @@ +import Common from '@/utils/Common.js' + class BleReceive { constructor() { this.StorageKey = "linkedDevices"; this.HandlerMap = { '/pages/6155/deviceDetail': this.Receive_6155.bind(this), + '/pages/6155/BJQ6155': this.Receive_6155_XH.bind(this), '/pages/7305/BJQ7305': this.Receive_6155.bind(this), '/pages/650/HBY650': this.Receive_650.bind(this), '/pages/670/HBY670': this.Receive_670.bind(this), @@ -423,6 +426,94 @@ class BleReceive { return data; } + Receive_6155_XH(receive, f, path, recArr) { + let bytes = receive.bytes; + if (bytes[0] == 0xFB && bytes[1] == 0x64 && bytes.length >= 8) { + try { + + let light = null; + let mode = null; + + if (bytes[2] === 0x01 && bytes[3] === 0x00) { + light = 0; + mode = 'main'; + } else if (bytes[2] === 0x02 && bytes[3] === 0x00) { + light = 1; + mode = 'main'; + } else if (bytes[2] === 0x00 && bytes[3] === 0x01) { + light = 2; + mode = 'main'; + } else if (bytes[2] === 0x03 && bytes[3] === 0x00) { + light = 0; + mode = 'fu'; + } else if (bytes[2] === 0x04 && bytes[3] === 0x00) { + light = 1; + mode = 'fu'; + } + if (bytes[2] === 0x05 && bytes[3] === 0x00) { + light = 3; + } + + + // 解析剩余电量 + let batteryLevelByte = bytes[4]; + // 电量百分比范围检查 + let batteryLevel = Math.max(0, Math.min(100, batteryLevelByte)); + + + + + //充电状态 + let warn = bytes[5]; + if (warn == 0x00) { + warn = '未充电'; + } else if (warn == 0x01) { + warn = '充电中'; + } + + // 解析剩余照明时间(第三和第四字节,小端序) + let lightingTime = ""; + let HH = Math.max(0, Math.min(100, bytes[6])); + let mm = Math.max(0, Math.min(100, bytes[7])); + lightingTime = HH + "小时" + mm + "分钟"; + let formData = {}; + formData.mode = mode; + formData.light = light; + + formData.battary = batteryLevel; + formData.statu = warn; + formData.xuhang = lightingTime; + + + let recCnt = recArr.find(v => { + + return v.key.replace(/\//g, "").toLowerCase() === f.device.detailPageUrl.replace(/\//g, + '').toLowerCase(); + + + + }); + if (!recCnt) { + if (batteryLevel <= 20) { + // 会弹出两个框,暂且注释掉这段代码 + uni.showModal({ + content: "设备'" + f.device.deviceName + "'电量低", + title: "提示" + }); + } + } + + + this.setBleFormData(formData, f); + return formData; + } catch (error) { + console.log('7305数据解析错误:', error); + return null; + } + } + return null; + } + Receive_6155(receive, f, path, recArr) { let bytes = receive.bytes; if (bytes[0] == 0xFB && bytes[1] == 0x64 && bytes.length >= 8) { @@ -588,8 +679,9 @@ class BleReceive { let receiveData = {}; try { - - // console.log("str=",receive.str); + console.log("订阅消息者:", path); + console.log("设备收到消息:", f); + console.log("消息内容:", receive); receiveData = JSON.parse(receive.str); let recCnt = recArr.find(v => { @@ -613,6 +705,134 @@ class BleReceive { } } + + + + if (f.device && path === "pages/common/index") { //仅在首页订阅此操作 + console.error("1111111111"); + let linkKey = "102_" + f.device.id + "_linked"; + let warnKey = "102_" + f.device.id + "_warning"; + let time = new Date(); //Common.DateFormat(new Date(),'yyyy-MM-dd HH:mmss'); + + if (receiveData.sta_tomac) { //某个设备上线了 + + if (receiveData.sta_tomac.indexOf(':') == -1) { + receiveData.sta_tomac = receiveData.sta_tomac.replace(/(.{2})/g, '$1:').slice(0, - + 1); //mac地址自动补: + } + uni.getStorageInfo({ + success: function(res) { + + let arr = []; + let linked = { + linkId: f.linkId, + read: false, + linkEqs: [{ + linkTime: time, + linkMac: f.macAddress + }, { + linkTime: time, + linkMac: receiveData.sta_tomac + }] + }; + if (res.keys.includes(linkKey)) { + arr = uni.getStorageSync(linkKey); + } + if (arr.length == 0) { + arr.unshift(linked); + + } else { + let dev = arr.find(v => { + if (v.linkId == f.linkId) { + let vl = v.linkEqs.find(cvl => { + if(cvl.linkMac === receiveData.sta_tomac){ + v.read=false; + cvl.linkTime=time; + return true; + } + return false; + }); + if (!vl) { + v.linkEqs.push({ + linkTime: time, + linkMac: receiveData.sta_tomac + }); + } + return vl; + } + return false; + }); + if (!dev) { + arr.unshift(linked); + } + + } + console.error("某个设备上线了", arr) + uni.setStorage({ + key: linkKey, + data: arr + }); + + + } + }); + } + + let warnArrs = []; + let guid = Common.guid(); + if (receiveData.sta_sosadd) { //某个设备闯入报警 + console.error("某个设备闯入报警"); + if (receiveData.sta_sosadd.indexOf(':') == -1) { + receiveData.sta_sosadd = receiveData.sta_sosadd.replace(/(.{2})/g, '$1:').slice(0, - + 1); //mac地址自动补: + } + warnArrs.push({ + linkId: f.linkId, + read: false, + key: guid, + warnType: "闯入报警", + warnMac: receiveData.sta_sosadd, + warnTime: time, + warnName: "" + }); + + } + + if (receiveData.sta_LedType === 'led_alarm' || receiveData.ins_LedType === 'led_alarm') { //强制报警 + console.error("强制报警了", f); + warnArrs.push({ + linkId: f.linkId, + read: false, + key: guid, + warnType: "强制报警", + warnMac: f.macAddress, + warnTime: time, + warnName: "" + }); + } + + if (warnArrs.length > 0) { + uni.getStorageInfo({ + success: function(res) { + let arr = []; + if (res.keys.includes(warnKey)) { + arr = uni.getStorageSync(warnKey); + arr = warnArrs.concat(arr); + } else { + arr = warnArrs + } + uni.setStorage({ + key: warnKey, + data: arr + }); + + } + }); + + } + } + + } catch (error) { receiveData = {}; console.log("文本解析失败", error) diff --git a/utils/Common.js b/utils/Common.js index 76d313b..6fab65e 100644 --- a/utils/Common.js +++ b/utils/Common.js @@ -218,7 +218,7 @@ export default { value: "1", label: "灯光模式", checked: false, - type: ['6170', '670'] + type: ['6170', '670','102'] }, { value: "2", @@ -282,7 +282,7 @@ export default { value: "46", label: "手动报警", checked: false, - type: ['210'] + type: ['210','102'] }, { value: "47", @@ -290,6 +290,18 @@ export default { checked: false, type: ['210'] }, + { + value: "48", + label: "物体感应", + checked: false, + type: ['102'] + }, + { + value: "49", + label: "联机模式", + checked: false, + type: ['102'] + }, ] let arr = [];