2025-07-07 09:21:15 +08:00

339 lines
8.8 KiB
Vue
Raw Permalink 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>
<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>