<template> <view class="page"> <u-navbar title="添加设备" :border-bottom="false" :background="bgc" title-color='#262B37' title-size='38' :custom-back="btnzhuce" height='50'></u-navbar> <view class="iptbox" @click="backpage()"> <input type="text" class="ips" v-model="mac" placeholder=" " style="margin-left: 32rpx;" placeholder-class="my-placeholder" /> <view class="iconfont icon-xiangyou1 "> </view> </view> <view class="iptbox"> <view class="qrcode" @click="qrcode()"> <image src="https://api.ccttiot.com/smartmeter/img/static/uy7BNwAMIKwvstqFnRhs" mode="aspectFit"></image> </view> <input type="text" class="ips" v-model="storeId" placeholder="请扫描设备上的二维码" style="margin-left: 32rpx;" placeholder-class="my-placeholder" /> </view> <view class="iptbox" @click="show=true"> <!-- <view class="" v-if="hardwareInfo.version"> 版本:{{hardwareInfo.version}} 版本id:{{hardwareInfo.id}} </view> --> <view class=""> {{banben}} </view> </view> <view class="tips" v-if="hardwareInfo.version"> 版本介绍:{{hardwareInfo.instructions}} </view> <u-select v-model="show" :list="list" title='选择型号' @confirm="confirm"></u-select> <view class="imgs" style="margin-top: 330rpx;"> <image src="https://lxnapi.ccttiot.com/bike/img/static/u9wFJhLZGm7rboSDySV4" mode="aspectFit" @click="qrcode()"> </image> </view> <view class="btn" @click="bind()"> 确认录入 </view> <view class="bot_btn"> <view class="btn1" @click="Binddevice()"> 蓝牙连接 </view> <!-- <view class="btn1" @click="ring()" v-if="carstause"> 响铃寻车 </view> --> <view class="btn1" @click="open()" v-if="carstause"> 蓝牙开启 </view> <view class="btn1" @click="close()" v-if="carstause"> 蓝牙关闭 </view> <!-- <view class="btn1" @click="reboot()" v-if="carstause"> 设备重启 </view> <view class="btn1" @click="Binddevice()" v-if="isbands"> 接口响铃 </view> --> </view> <u-mask :show="showbind" :z-index='100' /> <view class="tip_box" v-if="showbind"> <view class="top" v-if="showbind"> <view class="tip"> 操作提示 </view> <view class="ipt_box" style="justify-content: center;"> <view class="text" style="width: 80%;text-align: center;"> 该mac号已有绑定sn码是否修改为当前sn码 </view> </view> </view> <view class="bots"> <view class="bot_left" @click="showbind=false "> 取消 </view> <view class="bot_right" @click="changeBind()"> 确定 </view> </view> </view> <!-- <view class="bot"> <view class="btn"> 退款 </view> </view> --> </view> </template> <script> const app = getApp(); var xBlufi = require("@/components/blufi/xBlufi.js"); let _this = null; export default { data() { return { devicesList: [ // {name:'110000', // mac:'11111'} ], searching: false, texts: '正在扫描蓝牙设备...', btnflag: true, tishiflag: false, option: '', bluthlist: [], //蓝牙数组 // status: 'loading', statusflag: false, Bluetoothmac: '', mac: '', ishave: false, ver_data: null, deviceInfoss: {}, gps: {}, isband: false, // status: false, deviceIds: '', name: '', orderinfo: {}, dl: 0, czmoney: true, iscz: true, banben: '请点击选择版本', modelId: '', bgc: { backgroundColor: "#F7FAFE", }, sn: '', carstause: false, isbands: false, show: false, list: [], hardwareInfo: {}, showbind: false, storeId:'', deviceId:'' } }, onLoad(e) { console.log(e); this.mac = e.mac this.Binddevice() this.isbands = false this.carstause = false // if(uni.getStorageSync('banben') || uni.getStorageSync('banbenid')){ // this.banben = uni.getStorageSync('banben') // this.modelId = uni.getStorageSync('banbenid') // } }, onShow() { this.getlist() }, onUnload: function() { xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent); wx.closeBLEConnection({ deviceId: this.deviceId, }) }, onHide() { xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent); xBlufi.notifyStartDiscoverBle({ 'isStart': false }); }, onBeforeUnmount() { xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent); xBlufi.notifyStartDiscoverBle({ 'isStart': false }); }, watch: { }, methods: { btnzhuce(){ uni.reLaunch({ url:'/page_user/luru' }) }, confirm(e) { // console.log(e); this.banben = e[0].label this.modelId = e[0].value uni.setStorageSync('banben', this.banben) uni.setStorageSync('banbenid', this.modelId) // uni.setStorageSync('hardwareVersionId', e[0].value); // this.hardwareVersionId = e[0].value // const hardwareVersionId =this.hardwareVersionId // if (hardwareVersionId) { // const matchedVersion = this.Versionlist.find(version => version.id === // hardwareVersionId); // if (matchedVersion) { // this.hardwareInfo = matchedVersion; // } // } }, getlist() { this.$u.get('/app/model/all').then((res) => { if (res.code === 200) { this.Versionlist = res.data const hardwareVersionId = uni.getStorageSync('hardwareVersionId'); if (hardwareVersionId) { this.hardwareVersionId = hardwareVersionId const matchedVersion = this.Versionlist.find(version => version.id === hardwareVersionId); if (matchedVersion) { this.hardwareInfo = matchedVersion; } } this.list = res.data.map(item => ({ value: item.modelId, label: item.modelName })); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }) }, send() { this.$u.post('/app/device/ring?sn=' + this.sn).then((res) => { if (res.code === 200) { } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }) }, changeBind() { this.$u.post(`/appVerify/updateSn?sn=` + this.sn + '&mac=' + this.mac + '&hardwareVersionId=' + this .hardwareVersionId).then((res) => { if (res.code === 200) { uni.showToast({ title: '绑定成功', icon: 'none', duration: 2000 }); setTimeout(() => { uni.reLaunch({ url:'/page_user/luru' }) }, 2000) } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }) }, // backpage() { // uni.navigateBack({ // delta: 1 // delta值为1时表示返回的页面层数 // }); // }, // 新增and替换设备 gettihuan(){ let data = { sn: this.storeId, mac: this.mac, modelId: this.modelId } this.$u.post('/app/device', data).then((res) => { if (res.code == 200) { uni.showToast({ title: res.msg, icon: 'success', duration: 2000 }) wx.closeBLEConnection({ deviceId: this.deviceId, }) setTimeout(()=>{ uni.reLaunch({ url:'/page_user/lurukz?sn=' + this.storeId }) },1500) } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }) }, bind() { this.$u.get(`/app/device/admin/byMac?mac=${this.mac}`).then(res =>{ if(res.code == 200){ if(res.data == '' || res.data == null){ this.gettihuan() }else{ let that = this uni.showModal({ title: '温馨提示', content: '该设备已绑定SN,您确定修改该设备的SN吗?', success: (resModal) => { if (resModal.confirm) { that.gettihuan() } else if (resModal.cancel) { // 用户点击了取消按钮 uni.showToast({ title: '已取消', icon: 'none', duration: 1000 }) } } }) } }else{ uni.showToast({ title: res.msg, icon: 'success', duration: 2000 }) } }) }, qrcode() { uni.scanCode({ onlyFromCamera: true, scanType: ['qrCode'], success: res => { function getQueryParam(url, paramName) { let regex = new RegExp(`[?&]${paramName}=([^&]*)`) let results = regex.exec(url); return results ? decodeURIComponent(results[1].replace(/\+/g, ' ')) : null } let sceneValue = res.result let decodedValue = decodeURIComponent(sceneValue) let id = getQueryParam(decodedValue, 'sn') this.storeId = id // 找到与目标字符串最相似的元素并打印其ID let closestItemId = null; let closestItemname = null let smallestDistance = Infinity; console.log( this.storeId,'idididididi'); this.Versionlist.forEach(item => { if(item.snPrefix != null && item.snPrefix.length != 0){ const distance = this.levenshtein(item.snPrefix, this.storeId); if (distance < smallestDistance) { smallestDistance = distance closestItemId = item.modelId closestItemname = item.modelName } } }) this.modelId = closestItemId this.banben = closestItemname console.log("与目标字符串最相似的元素的是:",this.modelId,this.banben); }, fail: err => { console.error('扫描失败:', err) uni.showToast({ title: '扫描失败', icon: 'none' }) } }) }, // 匹配最相似的 levenshtein(a, b) { console.log(a,b,'ababababab'); const matrix = []; // 增量地构建矩阵 for (let i = 0; i <= b.length; i++) { matrix[i] = [i]; } for (let j = 0; j <= a.length; j++) { matrix[0][j] = j; } // 填充矩阵的其余部分 for (let i = 1; i <= b.length; i++) { for (let j = 1; j <= a.length; j++) { if (b.charAt(i - 1) === a.charAt(j - 1)) { matrix[i][j] = matrix[i - 1][j - 1]; } else { matrix[i][j] = Math.min( matrix[i - 1][j - 1] + 1, // 替换 Math.min(matrix[i][j - 1] + 1, // 插入 matrix[i - 1][j] + 1) // 删除 ); } } } // 返回矩阵右下角的值,即两个字符串之间的Levenshtein距离 return matrix[b.length][a.length]; }, Binddevice() { uni.showLoading({ title: '连接中..' }) xBlufi.initXBlufi(1); xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent); xBlufi.notifyStartDiscoverBle({ 'isStart': true }) // 两秒后停止蓝牙搜索 setTimeout(() => { xBlufi.notifyStartDiscoverBle({ 'isStart': false }); setTimeout(() => { uni.hideLoading() if (this.devicesList.length == 0) { uni.showToast({ title: '暂无发现对应设备,请重试', icon: 'none' }); } else { let uniqueDevicesList = Array.from(new Set(this.devicesList)); // 将去重后的数组重新赋值给 this.devicesList this.devicesList = uniqueDevicesList; // console.log(this.devicesList,'this.devicesListthis.devicesList'); this.devicesList.forEach(device => { // 从设备名称中提取 MAC 地址(假设 MAC 地址是设备名称的后6个字符) let macFromName = device.name.substring(device.name.length - 12); console.log(macFromName, 'macFromNamemacFromName'); // 与 this.mac 进行比较 if (macFromName == this.mac) { // 如果相同,则将 this.ishave 设置为 true console.log(device); this.deviceInfoss = device // this.ishave = true; this.createBLEConnection(device) console.log('对比正确1111111111'); } else { console.log('对比错误'); } }); } }, 200) // 判断是否存在浇花器设备 // this.status = true }, 2000) }, reboot() { let vm = this; // 将外部的 this 绑定到 vm 上 uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { console.log('已连接的蓝牙设备信息:', res); // vm.dl = (vm.orderinfo.deviceAmount / vm.orderinfo.unitPrice).toFixed(2); // 使用 vm 访问 Vue 实例的属性 xBlufi.notifySendCustomData({ customData: "11reboot" }); // uni.hideLoading() // vm.remakr() }, fail(err) { uni.hideLoading() console.error('获取已连接蓝牙设备信息失败:', err); } }); } else { console.log('手机未连接网络'); } } }); }, open() { let vm = this; // 将外部的 this 绑定到 vm 上 uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { console.log('已连接的蓝牙设备信息:', res); // vm.dl = (vm.orderinfo.deviceAmount / vm.orderinfo.unitPrice).toFixed(2); // 使用 vm 访问 Vue 实例的属性 xBlufi.notifySendCustomData({ customData: "open" }); xBlufi.notifySendCustomData({ customData: "11open" }); let datas = { mac:vm.mac, reason:'添加设备操作', command:'11open', result:'成功' } console.log(datas,'111'); vm.$u.post(`/app/commandLog/bluetooth`,datas).then(res => {}) // uni.hideLoading() // vm.remakr() }, fail(err) { uni.hideLoading() console.error('获取已连接蓝牙设备信息失败:', err); } }); } else { console.log('手机未连接网络'); } } }); }, close() { let vm = this; // 将外部的 this 绑定到 vm 上 uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { console.log('已连接的蓝牙设备信息:', res); // vm.dl = (vm.orderinfo.deviceAmount / vm.orderinfo.unitPrice).toFixed(2); // 使用 vm 访问 Vue 实例的属性 xBlufi.notifySendCustomData({ customData: "close" }); xBlufi.notifySendCustomData({ customData: "11close" }); let datas = { mac:vm.mac, reason:'添加设备操作', command:'11open', result:'成功' } console.log(datas,'111'); vm.$u.post(`/app/commandLog/bluetooth`,datas).then(res => {}) // uni.hideLoading() // vm.remakr() }, fail(err) { uni.hideLoading() console.error('获取已连接蓝牙设备信息失败:', err); } }); } else { console.log('手机未连接网络'); } } }); }, ring() { let vm = this; // 将外部的 this 绑定到 vm 上 uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { console.log('已连接的蓝牙设备信息:', res); // vm.dl = (vm.orderinfo.deviceAmount / vm.orderinfo.unitPrice).toFixed(2); // 使用 vm 访问 Vue 实例的属性 xBlufi.notifySendCustomData({ customData: "11play1@" }); // uni.hideLoading() // vm.remakr() }, fail(err) { uni.hideLoading() console.error('获取已连接蓝牙设备信息失败:', err); } }); } else { console.log('手机未连接网络'); } } }); }, btnyc() { this.titleflag = false }, // 解析自定义数据 funListenDeviceMsgEvent: function(options) { switch (options.type) { case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS: if (options.result) { let devicesarr = options.data // this.devicesList = options.data devicesarr.forEach(device => { // this.$u.get(`/app/device/${mac}/isBind`, data).then((res) => { // if (res.data == false) { this.devicesList.push(device); let uniqueDevicesList = Array.from(new Set(this.devicesList)); // 将去重后的数组重新赋值给 this.devicesList this.devicesList = uniqueDevicesList; }); } break; case xBlufi.XBLUFI_TYPE.TYPE_CONNECTED: console.log("连接回调:" + JSON.stringify(options)); if (options.result) { uni.hideLoading(); uni.showToast({ title: '连接成功', icon: 'none' }); { xBlufi.notifyInitBleEsp32({ deviceId: options.data.deviceId }); xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvents); this.deviceIds = options.data.deviceId this.name = options.data.name // 连接成功绑定设备 // let params = { // mac: this.Bluetoothmac, // userId: this.$store.state.user.userId // } let systemInfo = uni.getSystemInfoSync(); if (systemInfo.platform === 'android') { // 当前设备是 Android } else if (systemInfo.platform === 'ios') { // 当前设备是 iOS // uni.navigateTo({ // url: '/pages/wifilist/index?deviceId=' + options // .data.deviceId + '&name=' + options.data.name // }) } } } break; case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA: // this.ver_data = this.parseCustomData(options.data) if (options.data) { this.carstause = true } // console.log("1收到设备发来的自定义数据结果:", this.ver_data); break; case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_STOP: if (options.result) { // let uniqueDevicesList = Array.from(new Set(this.devicesList)); // 过滤出名称字段的前五个字母为 "CTPOW" 的项 // let filteredDevices = uniqueDevicesList.filter(device => device.name.substring(0, 4) === "BBLE"); // 将过滤后的数组重新赋值给 this.devicesList // this.devicesList = filteredDevices; // console.log('蓝牙停止搜索ok',this.devicesList); } else { //蓝牙停止搜索失败 // console.log('蓝牙停止搜索失败'); } this.searching = false // _this.setData({ // searching: false // }); break; } }, //4、建立连接 createBLEConnection(e) { console.log('调用了'); xBlufi.notifyStartDiscoverBle({ 'isStart': false }); console.log(e, '蓝牙信息') const deviceId = e.deviceId this.deviceId = e.deviceId this.Bluetoothmac = e.localName.substring(5) //从第七位开始截取 只取后面的mac号 console.log(this.Bluetoothmac, '11111'); let name = e.name; console.log('点击了,蓝牙准备连接的deviceId:' + e.deviceId); xBlufi.notifyConnectBle({ isStart: true, deviceId: e.deviceId, name }); // for (var i = 0; i < this.devicesList.length; i++) { // if (e.deviceId === this.devicesList[i].deviceId) { // uni.showLoading({ // title: '连接蓝牙设备中...' // }); // } // } }, // 点击重新搜索 Search() { if (this.status) { xBlufi.notifyStartDiscoverBle({ 'isStart': true }); // 重新搜索清空蓝牙数组 this.bluthlist = [] this.devicesList = [] // 重新搜索 // this.startBluetoothDevicesDiscovery() this.statusflag = true this.status = false this.texts = '正在扫描蓝牙设备...' setTimeout(() => { this.statusflag = false this.status = true if (this.searching) { xBlufi.notifyStartDiscoverBle({ 'isStart': false }); // 判断是否存在浇花器设备 if (this.devicesList.length == 0) { uni.showToast({ title: '暂无发现对应设备,请重试', icon: 'none' }); } else { this.texts = '扫描到以下设备,请点击连接!' } } else { xBlufi.notifyStartDiscoverBle({ 'isStart': true }); } }, 2000) } }, funListenDeviceMsgEvents: function(options) { let that = this; switch (options.type) { case xBlufi.XBLUFI_TYPE.TYPE_STATUS_CONNECTED: { console.log('状态', options.result) if (options.result == false) { this.carstause = false uni.showToast({ title: '设备断开链接,请重新点击蓝牙链接', icon: 'none' }); // uni.showModal({ // title: '很抱歉提醒你!', // content: '小程序与设备异常断开', // showCancel: false, // success: function(res) { // // uni.navigateBack({ // // url: '../search/search' // // }); // } // }); // this.statusflag = false uni.hideLoading(); } } break; case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_MY_DATA: this.loadPercent = options.data; this.loadText = '文件读取中' console.log("文件读取中", options.data); break; case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA: // this.isband = true // this.ver_data = this.parseCustomData(options.data) console.log("1收到设备发来的自定义数据结果:", options.data); if (options.data) { this.carstause = true } break; case xBlufi.XBLUFI_TYPE.TYPE_INIT_ESP32_RESULT: uni.hideLoading(); if (options.result) { console.log('初始化成功'); } else { console.log('初始化失败'); } break; } }, // 点击隐藏没有设备提示 btnhd() { this.tishiflag = false }, } } </script> <style lang="scss"> page { overflow-x: hidden; background-color: #F3F3F3; } .page { padding-bottom: 250rpx; width: 750rpx; height: 100%; .tip_box { position: fixed; left: 72rpx; top: 628rpx; width: 610rpx; // height: 282rpx; background: #FFFFFF; border-radius: 30rpx 30rpx 30rpx 30rpx; z-index: 110; padding-bottom: 100rpx; .top { padding: 52rpx 38rpx 42rpx 36rpx; .ipt_box { margin-top: 22rpx; display: flex; flex-wrap: nowrap; align-items: center; .text { width: 350rpx; font-weight: 400; font-size: 32rpx; color: #3D3D3D; } .ipt { padding: 10rpx 18rpx; display: flex; align-items: center; justify-content: space-between; margin-left: 26rpx; width: 420rpx; height: 64rpx; border-radius: 0rpx 0rpx 0rpx 0rpx; border: 2rpx solid #979797; .input { width: 80%; } } } .tip { width: 100%; text-align: center; font-weight: 700; font-size: 32rpx; color: #3D3D3D; } .txt { margin-top: 32rpx; width: 100%; text-align: center; font-weight: 500; font-size: 32rpx; color: #3D3D3D; } } .bots { position: absolute; width: 610rpx; // border-top: 2rpx solid #D8D8D8; display: flex; flex-wrap: nowrap; // height: 100%; bottom: -20rpx; .bot_left { border-radius: 0rpx 0rpx 0rpx 30rpx; width: 50%; height: 86rpx; display: flex; align-items: center; justify-content: center; font-weight: 500; font-size: 32rpx; color: #3D3D3D; background: #EEEEEE; } .bot_right { border-radius: 0rpx 0rpx 30rpx 0rpx; width: 50%; height: 86rpx; background: #4C97E7; display: flex; align-items: center; justify-content: center; color: #FFFFFF; // border-left: 2rpx solid #D8D8D8; font-weight: 500; font-size: 32rpx; // color: #4C97E7; } } } .imgs { margin-top: 50rpx; width: 100%; display: flex; justify-content: center; image { width: 400rpx; height: 400rpx; } } .btn { margin: 160rpx auto; margin-top: 30rpx; // position: fixed; display: flex; align-items: center; justify-content: center; // bottom: 100rpx; // left: 46rpx; width: 658rpx; height: 88rpx; background: #48893B; border-radius: 20rpx 20rpx 20rpx 20rpx; font-weight: 500; font-size: 32rpx; color: #FFFFFF; } .tips { margin: 28rpx auto 0; width: 658rpx; } .iptbox { display: flex; align-items: center; flex-wrap: nowrap; padding: 22rpx; margin: 28rpx auto 0; width: 658rpx; height: 88rpx; background: #FFFFFF; box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0, 0, 0, 0.15); border-radius: 20rpx 20rpx 20rpx 20rpx; .qrcode { padding-right: 20rpx; border-right: 2rpx solid #D8D8D8; image { width: 54rpx; height: 54rpx; } } .ips { width: 630rpx; } image { width: 18rpx; height: 32rpx; } .my-placeholder { font-weight: 400; font-size: 32rpx; color: #808080; } } .bot_btn { position: fixed; bottom: 0; display: flex; flex-wrap: wrap; padding: 40rpx 18rpx; width: 750rpx; // height: 330rpx; background: #fff; // background: linear-gradient( 180deg, #FFFFFF 0%, rgba(255,255,255,0) 100%); box-shadow: 0rpx 10rpx 64rpx 0rpx rgba(0, 0, 0, 0.08); border-radius: 0rpx 0rpx 0rpx 0rpx; .btn:nth-child(4n) { margin-right: 0; } .btn1 { margin-top: 10rpx; margin-right: 12rpx; display: flex; align-items: center; justify-content: center; width: 164rpx; height: 66rpx; background: #E2F2FF; border-radius: 0rpx 0rpx 0rpx 0rpx; border: 2rpx solid #48893B; font-weight: 400; font-size: 28rpx; color: #3D3D3D; } } } </style>