1.获取蓝牙列表 bleList.vue
<template>
<view>
<button @touchstart="startSearch">获取蓝牙列表</button>
<scroll-view :scroll-top="scrollTop" scroll-y class="content-pop">
<view
class="bluetoothItem"
v-for="(item, index) in bluetoohList"
:key="index"
@click="openControl(item)"
>
<view class="textItem">蓝牙:{{ item.name }}</view>
<view>{{ item.deviceId }}</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
bluetoohList: [],
};
},
onLoad: function (options) {
this.startSearch();
},
methods: {
// 连接蓝牙
startSearch() {
var that = this;
uni.openBluetoothAdapter({
success: (res) => {
uni.getBluetoothAdapterState({
success: (res) => {
if (res.available) {
if (res.discovering) {
uni.stopBluetoothDevicesDiscovery({
success: (res) => {},
});
} else {
that.getBluetoothDevices();
}
that.checkPemission();
} else {
uni.showToast({
title: "本机蓝牙不可用",
mask: true,
});
}
},
});
},
fail: (err) => {
that.openSetting();
},
});
},
openSetting() {
uni.showModal({
title: "检测到您没打开蓝牙权限,是否去设置打开?",
confirmText: "确认",
cancelText: "取消",
cancelColor: "#999999", //取消按钮颜色
confirmColor: "#00A0E9", //确定按钮颜色
success: (res) => {
if (res.confirm) {
uni.openSetting({
//opensetting是调起设置页面的
success: (res) => {
if (res.authSetting == true) {
//判断res.authsetting的值是true还是false
uni.openBluetoothAdapter({
success: (res) => {
this.startSearch();
},
});
}
},
});
} else {
// 取消
return false;
}
},
});
},
checkPemission() {
//android 6.0以上需授权地理位置权限
var that = this;
const sys = uni.getSystemInfoSync();
if (sys.platform == "ios") {
that.getBluetoothDevices();
} else if (sys.platform == "android") {
console.log(
app
.getSystem()
.substring(
app.getSystem().length - (app.getSystem().length - 8),
app.getSystem().length - (app.getSystem().length - 8) + 1
)
);
if (
app.globalData
.getSystem()
.substring(
app.globalData.getSystem().length -
(app.globalData.getSystem().length - 8),
app.globalData.getSystem().length -
(app.globalData.getSystem().length - 8) +
1
) > 5
) {
uni.getSetting({
success: (res) => {
console.log(res);
if (!res.authSetting["scope.userLocation"]) {
uni.authorize({
scope: "scope.userLocation",
complete: (res) => {
that.getBluetoothDevices();
},
});
} else {
that.getBluetoothDevices();
}
},
});
}
}
},
//获取蓝牙设备信息
getBluetoothDevices() {
var that = this;
uni.showLoading({
title: "蓝牙搜索中",
mask: true,
});
// 开始搜寻附近的蓝牙外围设备
uni.startBluetoothDevicesDiscovery({
success: (res) => {
setTimeout(() => {
// 获取搜索到的设备信息
uni.getBluetoothDevices({
success: (res) => {
that.bluetoohList = [];
var num = 0;
for (var i = 0; i < res.devices.length; ++i) {
if (res.devices[i].name != "未知设备") {
that.bluetoohList[num] = res.devices[i];
num++;
}
}
uni.stopPullDownRefresh(); // 停止当前页面下拉刷新
uni.stopBluetoothDevicesDiscovery({
// 停止搜索蓝牙设备
success: (res) => {
uni.hideLoading();
},
});
},
});
}, 5000);
},
});
},
// 连接蓝牙 跳转到连接页面
openControl(item) {
let params = {
list: this.bluetoohList,
info: item,
};
uni.redirectTo({
url:
"/pages/blefi/blefi?info=" +
encodeURIComponent(JSON.stringify(params)),
});
},
},
};
</script>
<style scoped>
.content-pop {
width: 100vw;
max-height: 55vh;
padding: 0 30rpx;
}
.bluetoothItem {
padding: 20rpx 0;
font-weight: 400;
font-size: 28rpx;
border-bottom: 1rpx solid #f4f4f4;
text-align: left;
}
.textItem {
display: block;
margin-bottom: 10rpx;
}
</style>
2.选择蓝牙进行连接 blefi.vue
<template>
<text>打印机正在连接中...</text>
</template>
<script>
export default {
data() {
return {
bluInfo: {},
services: [],
serviceId: 0,
writeCharacter: false,
readCharacter: false,
notifyCharacter: false,
deviceId: "",
notifyCharaterId: "",
notifyServiceId: "",
writeCharaterId: "",
writeServiceId: "",
readCharaterId: "",
readServiceId: "",
};
},
onLoad(option) {
// 接收页面传递的数据
this.bluInfo = JSON.parse(decodeURIComponent(option.info));
this.bluetooh(this.bluInfo.info.deviceId);
this.deviceId = this.bluInfo.info.deviceId;
},
methods: {
bluetooh(deviceId) {
var that = this;
uni.stopBluetoothDevicesDiscovery({
success: (res) => {},
});
uni.createBLEConnection({
deviceId: deviceId,
success: (res) => {
that.getSeviceId();
},
fail: (e) => {
that.bluetoothFail();
},
complete: (e) => {},
});
},
// 连接成功后保存连接状态
getSeviceId() {
var that = this;
uni.getBLEDeviceServices({
deviceId: this.deviceId,
success: (res) => {
that.services = res.services;
that.getCharacteristics();
},
fail: (e) => {
that.bluetoothFail();
},
complete: (e) => {},
});
},
getCharacteristics() {
var that = this;
var list = that.services;
var num = that.serviceId;
var write = that.writeCharacter;
var read = that.readCharacter;
var notify = that.notifyCharacter;
uni.getBLEDeviceCharacteristics({
deviceId: this.deviceId,
serviceId: list[num].uuid,
success: (res) => {
for (var i = 0; i < res.characteristics.length; ++i) {
var properties = res.characteristics[i].properties;
var item = res.characteristics[i].uuid;
if (!notify) {
if (properties.notify) {
this.notifyCharaterId = item;
this.notifyServiceId = list[num].uuid;
notify = true;
}
}
if (!write) {
if (properties.write) {
this.writeCharaterId = item;
this.writeServiceId = list[num].uuid;
write = true;
}
}
if (!read) {
if (properties.read) {
readServiceId.readCharaterId = item;
readServiceId.readServiceId = list[num].uuid;
read = true;
}
}
}
if (!write || !notify || !read) {
num++;
(that.writeCharacter = write),
(that.readCharacter = read),
(that.notifyCharacter = notify),
(that.serviceId = num);
if (num == list.length) {
// console.log("找不到该读写的特征值")
that.bluetoothFail();
} else {
that.getCharacteristics();
}
} else {
that.bluetoothSuccess(res);
}
},
fail: (e) => {
that.bluetoothFail();
},
});
},
// 蓝牙连接打印机
bluetoothSuccess(res) {
let info = {
deviceId: this.deviceId,
notifyCharaterId: thid.notifyCharaterId,
notifyServiceId: thid.notifyServiceId,
writeCharaterId: thid.writeCharaterId,
writeServiceId: thid.writeServiceId,
readCharaterId: thid.readCharaterId,
readServiceId: thid.readServiceId,
};
uni.setStorageSync("blefiInfo", info);
uni.showModal({
title: "连接成功",
confirmText: "继续",
confirmColor: "#00A0E9", //确定按钮颜色
showCancel: false, //没有取消按钮的弹框
success: (res) => {
if (res.confirm) {
// 蓝牙连接成功,跳转到下一页面
uni.redirectTo({
url: "/pages/blefi/blefiWifi",
});
}
},
});
},
bluetoothFail() {
// 蓝牙连接失败,跳转到失败页面
uni.redirectTo({
url: "/pages/blefi/blefiFail",
});
},
},
};
</script>
3. 低功耗蓝牙连接WiFi blefiWifi.vue
<template>
<view>
<text>{{ wifiSSID }}</text>
<input type="text" placeholder="请输入WLAN密码" v-model="password" />
<button @click="settiing">连接</button>
</view>
</template>
<script>
export default {
data() {
return {
bleInfo: {},
wifiSSID: "your SSID",
password: "",
bleSendSequence: 0,
connected: true,
wifiCountDown: 0,
wifiCountInterval: null, // 定时器
dataEnum: {
PACKAGE_VALUE: 0x01,
SUBTYPE_NEG: 0x00,
SUBTYPE_STA_WIFI_BSSID: 0x01,
SUBTYPE_STA_WIFI_SSID: 0x02,
SUBTYPE_STA_WIFI_PASSWORD: 0x03,
SUBTYPE_SOFTAP_WIFI_SSID: 0x04,
SUBTYPE_SOFTAP_WIFI_PASSWORD: 0x05,
SUBTYPE_SOFTAP_MAX_CONNECTION_COUNT: 0x06,
SUBTYPE_SOFTAP_AUTH_MODE: 0x07,
SUBTYPE_SOFTAP_CHANNEL: 0x08,
SUBTYPE_USERNAME: 0x09,
SUBTYPE_CA_CERTIFICATION: 0x0a,
SUBTYPE_CLIENT_CERTIFICATION: 0x0b,
SUBTYPE_SERVER_CERTIFICATION: 0x0c,
SUBTYPE_CLIENT_PRIVATE_KEY: 0x0d,
SUBTYPE_SERVER_PRIVATE_KEY: 0x0e,
SUBTYPE_WIFI_CONNECTION_STATE: 0x0f,
SUBTYPE_VERSION: 0x10,
SUBTYPE_WIFI_LIST: 0x11,
SUBTYPE_ERROR: 0x12,
SUBTYPE_CUSTOM_DATA: 0x13,
},
controllEnum: {
PACKAGE_VALUE: 0x00,
SUBTYPE_ACK: 0x00,
SUBTYPE_SET_SEC_MODE: 0x01,
SUBTYPE_SET_OP_MODE: 0x02,
SUBTYPE_CONNECT_WIFI: 0x03,
SUBTYPE_DISCONNECT_WIFI: 0x04,
SUBTYPE_GET_WIFI_STATUS: 0x05,
SUBTYPE_DEAUTHENTICATE: 0x06,
SUBTYPE_GET_VERSION: 0x07,
SUBTYPE_CLOSE_CONNECTION: 0x08,
SUBTYPE_GET_WIFI_LIST: 0x09,
},
};
},
// 二级页面清除
onUnload() {
wx.offBLEConnectionStateChange();
if (this.wifiCountInterval) {
clearInterval(this.wifiCountInterval);
this.wifiCountInterval = null;
}
},
onLoad(options) {
this.bleInfo = uni.getStorageSync("blefiInfo");
var that = this;
wx.getBLEDeviceServices({
deviceId: this.bleInfo.deviceId,
success: function (res) {
wx.getBLEDeviceCharacteristics({
deviceId: this.bleInfo.deviceId,
serviceId: this.bleInfo.notifyServiceId,
success: function (res) {
wx.notifyBLECharacteristicValueChange({
state: true,
deviceId: this.bleInfo.deviceId,
serviceId: this.bleInfo.notifyServiceId,
characteristicId: this.bleInfo.notifyCharaterId,
success: function (res) {
console.log("启用notify成功");
},
});
},
});
},
});
wx.onBLEConnectionStateChange((res) => {
that.connected = res.connected;
if (!res.connected) {
uni.hideLoading();
// 蓝牙连接失败,跳转到失败页面
uni.redirectTo({
url: "/pages/blefi/blefiFail",
});
}
});
// 接收配网打印机回传的数据
wx.onBLECharacteristicValueChange(function (res) {
uni.hideLoading();
var receive = that.ab2strt(res.value);
console.log("接收到数据 receive : " + receive);
// 处理接收的数据........
});
},
methods: {
// 将 ArrayBuffer 转换为16进度字符串
ab2strt(buff) {
var hexArr = Array.prototype.map.call(
new Uint8Array(buff),
function (bit) {
return ("00" + bit.toString(16)).slice(-2);
}
);
return hexArr.join(" ");
},
settiing() {
// 取消wifi连接成功/失败页面
this.wifiCountDown = 30;
this.startSMSTimer();
uni.showLoading({
title: "连接中",
mask: true,
});
if (this.connected) {
this.sendSSID();
this.sendPASSWORD();
this.notifyConnect();
} else {
uni.hideLoading();
// 蓝牙连接失败,跳转到失败页面
uni.redirectTo({
url: "/pages/blefi/blefiFail",
});
}
},
startSMSTimer() {
this.wifiCountInterval = setInterval(() => {
this.wifiCountDown--;
if (this.wifiCountDown <= 0) {
clearInterval(this.wifiCountInterval);
this.wifiCountInterval = null;
uni.hideLoading();
// 蓝牙连接wifi失败
uni.redirectTo({
url: "/pages/blefi/wifiFile",
});
}
}, 1000);
},
sendSSID() {
// SSID转UTF-8
let password = this.utf16to8(this.wifiSSID);
let u8buffer = new Uint8Array(password.length);
for (var i = 0; i < password.length; i++) {
u8buffer[i] = password.charCodeAt(i);
}
this.bleSendCMD(
this.dataEnum.PACKAGE_VALUE,
this.dataEnum.SUBTYPE_STA_WIFI_SSID,
0,
u8buffer
);
},
utf16to8(str) {
var out, i, len, c;
out = "";
len = str.length;
for (i = 0; i < len; i++) {
c = str.charCodeAt(i);
if (c >= 0x0001 && c <= 0x007f) {
out += str.charAt(i);
} else if (c > 0x07ff) {
out += String.fromCharCode(0xe0 | ((c >> 12) & 0x0f));
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3f));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3f));
} else {
out += String.fromCharCode(0xc0 | ((c >> 6) & 0x1f));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3f));
}
}
return out;
},
sendPASSWORD() {
let password = this.password;
let u8buffer = new Uint8Array(password.length);
for (var i = 0; i < password.length; i++) {
u8buffer[i] = password.charCodeAt(i);
}
this.bleSendCMD(
this.dataEnum.PACKAGE_VALUE,
this.dataEnum.SUBTYPE_STA_WIFI_PASSWORD,
0,
u8buffer
);
},
notifyConnect() {
let password = this.password;
let u8buffer = new Uint8Array(password.length);
for (var i = 0; i < password.length; i++) {
u8buffer[i] = password.charCodeAt(i);
}
this.bleSendCMD(
this.controllEnum.PACKAGE_VALUE,
this.controllEnum.SUBTYPE_CONNECT_WIFI,
0,
u8buffer
);
},
//ESP32的蓝牙配网命令接口
bleSendCMD(CMD, subCMD, frameControl, payload) {
var newValue = new ArrayBuffer(payload.length + 6);
var u8array = new Uint8Array(newValue);
var LSB_Type = ((subCMD & 0x3f) << 2) | (CMD & 0x03);
u8array[0] = LSB_Type;
u8array[1] = frameControl;
u8array[2] = this.bleSendSequence;
u8array[3] = payload.length;
for (let i = 0; i < payload.length; i++) {
u8array[4 + i] = payload[i];
}
this.bleSendSequence++;
if (this.connected) {
wx.writeBLECharacteristicValue({
deviceId: this.bleInfo.deviceId,
serviceId: this.bleInfo.writeServiceId,
characteristicId: this.bleInfo.writeCharaterId,
value: newValue,
});
}
},
},
};
</script>
4. 手机连接蓝牙失败、蓝牙连接WiFi成功/失败(关闭蓝牙连接)
<script>
export default {
onLoad() {
let deviceId = uni.getStorageSync("blefiInfo").deviceId
uni.closeBLEConnection({
deviceId: deviceId,
});
},
};
</script>