339 lines
8.8 KiB
Vue
Raw Permalink Normal View History

2025-07-07 09:21:15 +08:00
<template>
<page-meta>
<navigation-bar :title="$tt('navBar.connectResult')" title-align="center" background-color="#F1F3F9"
front-color="#000000" />
</page-meta>
<view class="set-wifi">
<view class="img-wrap">
<u-loading-icon size="70"></u-loading-icon>
</view>
<view class="progress">
<view>
<text class="num">{{progress}}</text>
<text class="unit">%</text>
</view>
<view class="dec">{{infoText}}</view>
<view class="tip">{{$tt('bleConnect.sureMobileCloseDevAndNetworkUnobstructed')}}</view>
</view>
<view class="btn-wrap">
<button class="back" @click="handleGoBack">{{$tt('bleConnect.goBack')}}</button>
<button class="restart" @click="handleRelocation">{{$tt('bleConnect.reconfigNetwork')}}</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
progress: 0,
deviceId: '',
ssid: '',
pass: '',
infoText: this.$tt('bleConnect.devRegistering'),
interval: null, // 定时器
};
},
onLoad(option) {
const { deviceId, ssid, pass } = option;
this.deviceId = deviceId;
this.ssid = ssid;
this.pass = pass;
},
mounted() {
this.simulateLoading();
this.connectBlueTooth(this.deviceId);
},
methods: {
// 模拟进度条
simulateLoading() {
let currentProgress = 0;
this.interval = setInterval(() => {
currentProgress += 10;
this.progress = currentProgress;
if (currentProgress >= 100) {
clearInterval(this.interval);
}
}, 1300); // 每500毫秒更新一次进度
},
// 连接蓝牙设备
connectBlueTooth(deviceId) {
this.infoText = this.$tt('bleConnect.devBeginsToConnect');
this.closeBlueTooth(deviceId, () => {
setTimeout(() => {
uni.createBLEConnection({
deviceId: deviceId,
success: (res) => {
this.infoText = this.$tt('bleConnect.devConnectSuccess');
this.getBlueToothService(deviceId);
},
fail: (res) => {
clearInterval(this.interval);
this.infoText = this.$tt('bleConnect.devConnectFailed') +
`${res.errMsg}`;
},
});
}, 2000);
});
},
// 关闭蓝牙设备手机端可以同时连接多个蓝牙设备但是同一个蓝牙设备不能被多次连接所以需要在每次连接前关闭BLE连接
closeBlueTooth(deviceId, callback) {
uni.closeBLEConnection({
deviceId: deviceId,
success: (res) => {
console.log('closeBLEConnection', res);
},
fail: (res) => {
console.log('closeBLEConnection', res);
},
complete: callback,
});
},
// 获取蓝牙设备服务uuid
getBlueToothService(deviceId) {
this.infoText = this.$tt('bleConnect.discoveryService');
setTimeout(() => {
uni.getBLEDeviceServices({
deviceId: deviceId,
success: (res) => {
const services = res.services;
if (services.length <= 0) {
this.infoText = this.$tt('bleConnect.mainServiceNoFound');
return;
}
this.infoText = this.$tt('bleConnect.findServiceLists') +
`${services.length}`;
for (let i = 0; i < services.length; i++) {
if (services[i].isPrimary) {
this.infoText = this.$tt('bleConnect.uuid') +
`${services[i].uuid}`;
this.getBlueToothCharacteristics(deviceId, services[i].uuid);
}
}
},
fail: (res) => {
clearInterval(this.interval);
this.infoText = this.$tt('bleConnect.obtainServiceFailed') +
`${res.errMsg}`;
},
});
}, 5000)
},
// 获取设备特征值
getBlueToothCharacteristics(deviceId, uuid) {
this.infoText = this.$tt('bleConnect.keyExchange');
uni.getBLEDeviceCharacteristics({
deviceId: deviceId,
serviceId: uuid,
success: (res) => {
// 这里会获取到两个特征值,一个用来写,一个用来读
const chars = res.characteristics;
if (chars.length <= 0) {
this.infoText = this.$tt('bleConnect.signatureCodeNoFound');
return;
}
this.infoText = this.$tt('bleConnect.findFeatureCode') +
`${chars.length}`;
if (chars.length >= 1) {
chars.forEach((item) => {
const prop = item.properties;
if (prop.notify === true || prop.notify === true) {
this.receiveData(deviceId, uuid, item.uuid);
} else if (prop.write === true) {
this.sendData(deviceId, uuid, item.uuid);
}
});
}
},
fail: (res) => {
clearInterval(this.interval);
this.infoText = this.$tt('bleConnect.findFeatureCodeFailed') +
`${res.errMsg}`;
}
});
},
// 接受蓝牙设备发送过来的数据
receiveData(deviceId, serviceId, charId) {
const timeOut = setTimeout(() => {
this.infoText = this.$tt('bleConnect.acceptDataTimeout');
this.closeBlueTooth(this.deviceId);
}, 13000);
uni.notifyBLECharacteristicValueChange({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: charId,
state: true,
success: (res) => {
uni.onBLECharacteristicValueChange((data) => {
const resHex = this.ab2hex(data.value);
let result = this.hexCharCodeToStr(resHex)
result = JSON.parse(result);
if (result) {
this.infoText = this.$tt('bleConnect.configurationSuccess');
} else {
this.infoText = this.$tt('bleConnect.configurationFailed');
}
this.progress = 100;
clearInterval(this.interval);
clearTimeout(timeOut);
});
},
fail: (res) => {
clearInterval(this.interval);
this.infoText = this.$tt('bleConnect.receiveDataFailed') + `${res.errMsg}`;
}
});
},
// 向蓝牙设备发送数据
sendData(deviceId, serviceId, charId) {
this.infoText = this.$tt('bleConnect.sendConfigurationData');
const data = {
ssid: this.ssid,
password: this.pass
};
const buffer = this.toBuffer(data);
setTimeout(() => {
uni.writeBLECharacteristicValue({
value: buffer,
deviceId: deviceId,
serviceId: serviceId,
characteristicId: charId,
success: (res) => {
this.infoText = this.$tt('bleConnect.sendSuccess');
},
fail: (res) => {
clearInterval(this.interval);
this.infoText = this.$tt('bleConnect.sendFailed') + `${res.errMsg}`;
},
});
}, 1000);
},
toBuffer(data) {
const dataStr = JSON.stringify(data);
const buffer = new ArrayBuffer(dataStr.length);
let bufView = new Uint8Array(buffer);
for (var i = 0; i < dataStr.length; i++) {
bufView[i] = dataStr.charCodeAt(i);
}
return buffer;
},
// ArrayBuffer转16进度字符串
ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('')
},
// 将16进制的内容转成我们看得懂的字符串内容
hexCharCodeToStr(hexCharCodeStr) {
var trimedStr = hexCharCodeStr.trim();
var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
var len = rawStr.length;
if (len % 2 !== 0) {
return "";
}
var curCharCode;
var resultStr = [];
for (var i = 0; i < len; i = i + 2) {
curCharCode = parseInt(rawStr.substr(i, 2), 16);
resultStr.push(String.fromCharCode(curCharCode));
}
return resultStr.join("");
},
// 返回
handleGoBack() {
this.closeBlueTooth(this.deviceId);
uni.switchTab({
url: '/pages/tabBar/home/index'
});
},
// 重新配网
handleRelocation() {
this.closeBlueTooth(this.deviceId);
uni.reLaunch({
url: `/pagesB/home/device/add/bleConnect/index`
});
}
},
}
</script>
<style lang="scss">
page {
height: 100%;
background: $uni-bg-color-grey;
}
</style>
<style lang="scss" scoped>
.set-wifi {
.img-wrap {
padding: 160rpx 0;
text-align: center;
}
.progress {
text-align: center;
padding: 0 20rpx;
.num {
font-size: 80rpx;
line-height: 100rpx;
}
.unit {
margin-left: 10rpx;
}
.dec {
font-size: 28rpx;
line-height: 48rpx;
color: #7e7e7e;
}
.tip {
margin-top: 20rpx;
font-size: 32rpx;
line-height: 52rpx;
}
}
.btn-wrap {
position: fixed;
left: 80rpx;
right: 80rpx;
bottom: 160rpx;
.restart {
display: flex;
justify-content: center;
align-items: center;
height: 98rpx;
border-radius: 18rpx;
color: #486FF2;
background-color: #fff;
font-weight: 400;
font-size: 32rpx;
letter-spacing: 0.6rpx;
border: 2rpx solid #486FF2;
margin-top: 36rpx;
}
.back {
display: flex;
justify-content: center;
align-items: center;
height: 98rpx;
border-radius: 18rpx;
color: #fff;
background-color: #486FF2;
font-weight: 400;
font-size: 32rpx;
letter-spacing: 0.6rpx;
}
}
}
</style>