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() {
let that = this;
that.$ble.openBluetoothAdapter(
(res) => {
that.$ble.getBluetoothAdapterState((res) => {
if (res.available) {
if (res.discovering) {
that.$ble.stopBluetoothDevicesDiscovery();
} else {
that.getBluetoothDevices();
}
that.checkPemission();
} else {
that.$tip.toast("本机蓝牙不可用");
}
});
},
(err) => {
that.openSetting();
}
);
},
openSetting() {
let params = {
title: "检测到您没打开蓝牙权限,是否去设置打开?",
showCancel: true,
};
this.$tip.showModal(params, (res) => {
if (res.confirm) {
this.$ble.openSetting();
}
});
},
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() {
that.$tip.loading("蓝牙搜索中");
this.$ble.getBluetoothDevices((res) => {
this.bluetoohList = res;
this.$tip.loaded();
});
},
// 连接蓝牙 跳转到连接页面
openControl(item) {
let params = {
list: this.bluetoohList,
info: item,
};
this.$tip.redirectTo("/pagesA/bleDevice/bleWifiSuccess", 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
<script>
export default {
data() {
return {
bluInfo: {},
services: [],
bleServiceId: "",
serviceId: 0,
writeCharacter: false,
readCharacter: false,
notifyCharacter: false,
BLEInformation: {
serveiceId: "",
config_write_char_id: "",
cmd_write_char_id: "",
config_read_char_id: "",
cmd_read_char_id: "",
},
};
},
onLoad(option) {
// 接收页面传递的数据
this.bluInfo = JSON.parse(decodeURIComponent(option.info));
this.bluetooh(this.bluInfo.info.deviceId);
},
methods: {
bluetooh(deviceId) {
var that = this;
that.$ble.stopBluetoothDevicesDiscovery();
that.$ble.createBLEConnection(
deviceId,
(res) => {
that.getSeviceId(deviceId);
},
(err) => {
console.log(err, "11111111");
that.bluetoothFail();
}
);
},
// 连接成功后保存连接状态
getSeviceId(deviceId) {
var that = this;
that.$ble.getBLEDeviceServices(
deviceId,
(res) => {
that.services = res.services;
that.bleServiceId = res.services[0].uuid;
this.BLEInformation.serveiceId = res.services[0].uuid;
that.getCharacteristics(deviceId);
},
(err) => {
console.log(err, "2222222");
that.bluetoothFail();
}
);
},
getCharacteristics(deviceId) {
var that = this;
var list = that.services;
var num = that.serviceId;
var write = that.writeCharacter;
var read = that.readCharacter;
var notify = that.notifyCharacter;
that.$ble.getBLEDeviceCharacteristics(
deviceId,
that.bleServiceId,
(res) => {
for (var i = 0; i < res.characteristics.length; ++i) {
var properties = res.characteristics[i].properties;
if (!notify) {
if (properties.notify) {
notify = true;
}
}
if (!write) {
if (properties.write) {
this.BLEInformation.config_write_char_id =
res.characteristics[2].uuid;
this.BLEInformation.cmd_write_char_id =
res.characteristics[0].uuid;
write = true;
}
}
if (!read) {
if (properties.read) {
this.BLEInformation.config_read_char_id =
res.characteristics[3].uuid;
this.BLEInformation.cmd_read_char_id =
res.characteristics[1].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(deviceId);
}
} else {
that.bluetoothSuccess(res);
}
},
(err) => {
console.log(err, "4444444");
that.bluetoothFail();
}
);
},
// 蓝牙连接打印机
bluetoothSuccess(res) {
uni.setStorageSync("blefiInfo", this.BLEInformation);
let params = {
title: "连接成功",
confirmText: "继续",
showCancel: false,
};
this.$tip.showModal(params, (res) => {
if (res.confirm) {
// 蓝牙连接成功
this.$tip.redirectTo("/pages/ble/bleWifi");
}
});
},
bluetoothFail() {
// 蓝牙连接失败
this.$tip.redirectTo("/pages/ble/bleFail");
},
},
};
</script>
<style scoped>
.zai-box {
padding: 0;
margin: 0;
height: 100%;
background-color: #fff;
}
.container {
padding: 30rpx;
margin: 0;
font-size: 28rpx;
color: #20212b;
background-color: #fff;
text-align: left;
font-weight: 400;
}
image {
width: 362rpx;
height: 362rpx;
margin-top: 30rpx;
}
.textTitle {
display: block;
font-size: 36rpx;
font-weight: bold;
color: #20212b;
display: block;
margin-bottom: 30rpx;
}
.textItem {
display: block;
font-size: 24rpx;
font-weight: 400;
color: #999999;
line-height: 36rpx;
}
</style>
3. 低功耗蓝牙连接WiFi blefiWifi.vue
<template>
<view>
<text>{{ SSID }}</text>
<input type="text" placeholder="请输入密码" v-model="password" />
<button @click="settiing">连接</button>
</view>
</template>
<script>
import APToast from "@/util/APToast.js";
export default {
data() {
return {
SSID: "your SSID",
password: "",
connected: true,
wifiCountDown: 0,
wifiCountInterval: null, // 定时器
blefiInfo: {},
};
},
// 二级页面清除
onUnload() {
this.$ble.offBLEConnectionStateChange();
this.clearIntervalWifi();
},
onLoad(options) {
this.blefiInfo = uni.getStorageSync("blefiInfo");
let sys = uni.getStorageSync("phoneInfo");
if (sys.platform == "android") {
// this.$ble.onBLEMTUChange((res) => {
// console.log(res, "androidMTU");
// });
// this.$ble.getBLEMTU(this.blefiInfo.deviceId, (res) => {
// console.log(res, "mtu");
// });
const mtu = 512;
this.$ble.setBLEMTU(
this.blefiInfo.deviceId,
mtu,
(res) => {
console.log(res, "512");
},
(err) => {
console.log(err, "000");
}
);
}
this.$ble.getBLEDeviceServices(this.blefiInfo.deviceId, (res) => {
this.$ble.getBLEDeviceCharacteristics(
this.blefiInfo.deviceId,
this.blefiInfo.serveiceId,
(res) => {
this.$ble.notifyBLECharacteristicValueChange(
true,
this.blefiInfo.deviceId,
this.blefiInfo.serveiceId,
this.blefiInfo.readCharId,
(res) => {
console.log("启用notify成功");
}
);
}
);
});
this.$ble.onBLEConnectionStateChange((res) => {
this.connected = res.connected;
if (!res.connected) {
this.$tip.loaded();
// 蓝牙连接失败,跳转到失败页面
this.$tip.redirectTo("/pages/ble/bleFail");
}
});
// 接收配网打印机回传的数据
this.$ble.onBLECharacteristicValueChange((res) => {
if (!res || res.value.byteLength == 0) return;
this.clearIntervalWifi();
this.$tip.loaded();
let num = new Int32Array(res.value)[0];
console.log(num, "NUM");
let tip = APToast.find((item) => item.id == num);
if (num == 0) {
// 连接wifi成功
this.$tip.redirectTo("/pages/ble/WifiSuccess");
} else {
// 连接WiFi失败
this.$tip.redirectTo("/pages/ble/WifiFile");
}
});
},
methods: {
settiing() {
this.startSMSTimer("60");
this.$tip.loading("连接中");
if (this.connected) {
this.sendWifi();
} else {
this.$tip.loaded();
// 蓝牙连接失败,跳转到失败页面
this.$tip.redirectTo("/pages/ble/bleFail");
}
},
// 转UTF-8
sendWifi() {
let msg = {
event: "network",
data: { ssid: this.SSID, password: this.password, authmode: 4 },
};
let buffer = this.stringToUint8Array(JSON.stringify(msg));
this.bleSendWifi(buffer);
},
// json字符串数据转Uint8Array
stringToUint8Array(str) {
// 方法一
// var arr = [];
// for (var i = 0, j = str.length; i < j; ++i) {
// arr.push(str.charCodeAt(i));
// }
// var tmpUint8Array = new Uint8Array(arr);
// return tmpUint8Array.buffer;
// 方法二
let buffer = new ArrayBuffer(str.length);
let dataView = new DataView(buffer);
for (var i = 0; i < str.length; i++) {
dataView.setUint8(i, str.charCodeAt(i));
}
return buffer;
},
bleSendWifi(payload) {
if (this.connected) {
this.$ble.writeBLECharacteristicValueOnce(
this.blefiInfo.deviceId,
this.blefiInfo.serveiceId,
this.blefiInfo.writecharId,
payload
);
if (this.blefiInfo.readCharId) {
this.$ble.readBLECharacteristicValue(
this.blefiInfo.deviceId,
this.blefiInfo.serveiceId,
this.blefiInfo.readCharId
);
}
}
},
startSMSTimer(val) {
this.wifiCountDown = val;
this.wifiCountInterval = setInterval(() => {
this.wifiCountDown--;
// console.log(this.wifiCountDown);
if (this.wifiCountDown <= 0) {
clearInterval(this.wifiCountInterval);
this.wifiCountInterval = null;
this.$tip.loaded();
// 连接WiFi失败
this.$tip.redirectTo("/pages/ble/WifiFile");
}
}, 1000);
},
clearIntervalWifi() {
this.wifiCountDown = 0;
if (this.wifiCountInterval) {
clearInterval(this.wifiCountInterval);
this.wifiCountInterval = null;
}
},
},
};
</script>
4. 手机连接蓝牙失败、蓝牙连接WiFi成功/失败(关闭蓝牙连接)
<script>
export default {
onLoad() {
// 使用完成后在合适的时机断开连接和关闭蓝牙适配器
this.$ble.closeBLEConnection(this.deviceId);
this.$ble.closeBluetoothAdapter();
},
};
</script>
5.ble.js
let data = {
devices: [],
log: [],
connected: true, //原本是false
chs: [],
deviceId: "",
writeDeviceId: "",
writeServiceId: "",
writeCharacteristicId: "",
packData: [], // 分包数据
cmd: null, // 命令码
statusCode: null, // 状态码
datalength: null, // 数据长度
checkSums: null, // 校验和
req_key_id: "",
};
class ble {
openBluetoothAdapter(success, failure) {
uni.openBluetoothAdapter({
success: (res) => {
success(res);
},
fail: (err) => {
failure(err);
},
});
}
getBluetoothAdapterState(success) {
uni.getBluetoothAdapterState({
success: (res) => {
success(res);
},
});
}
//停止搜寻附近的蓝牙外围设备
stopBluetoothDevicesDiscovery() {
uni.stopBluetoothDevicesDiscovery();
}
//获取蓝牙设备信息
getBluetoothDevices(success) {
// 开始搜寻附近的蓝牙外围设备
uni.startBluetoothDevicesDiscovery({
success: (res) => {
setTimeout(() => {
// 获取搜索到的设备信息
uni.getBluetoothDevices({
success: (res) => {
let bluetoohList = [];
var num = 0;
for (var i = 0; i < res.devices.length; ++i) {
if (res.devices[i].name != "未知设备") {
bluetoohList[num] = res.devices[i];
num++;
}
}
this.stopBluetoothDevicesDiscovery();
success(bluetoohList);
},
});
}, 5000);
// that.onBluetoothDeviceFound();
},
});
}
openSetting() {
uni.openSetting({
//opensetting是调起设置页面的
success: (res) => {
if (res.authSetting == true) {
//判断res.authsetting的值是true还是false
uni.openBluetoothAdapter();
}
},
});
}
//断开与低功耗蓝牙设备的连接
closeBLEConnection(deviceId) {
uni.closeBLEConnection({
deviceId: deviceId,
});
}
offBLEConnectionStateChange() {
wx.offBLEConnectionStateChange();
}
//连接低功耗蓝牙设备
createBLEConnection(deviceId, success, failure) {
uni.createBLEConnection({
deviceId: deviceId,
success: (res) => {
success(res);
},
fail: (err) => {
failure(err);
},
});
}
//获取蓝牙设备所有服务
getBLEDeviceServices(deviceId, success, failure) {
wx.getBLEDeviceServices({
deviceId: deviceId,
success: (res) => {
success(res);
},
fail(err) {
failure(err);
},
});
}
//获取蓝牙设备某个服务中所有特征值
getBLEDeviceCharacteristics(deviceId, serviceId, success, failure) {
wx.getBLEDeviceCharacteristics({
deviceId: deviceId,
serviceId: serviceId,
success: (res) => {
success(res);
},
fail(err) {
failure(err);
},
});
}
notifyBLECharacteristicValueChange(
state,
deviceId,
serviceId,
characteristicId,
success
) {
wx.notifyBLECharacteristicValueChange({
state: state,
deviceId: deviceId,
serviceId: serviceId,
characteristicId: characteristicId,
success: function (res) {
success(res);
},
});
}
onBLEConnectionStateChange(success) {
wx.onBLEConnectionStateChange((res) => {
success(res);
});
}
// 接收配网打印机回传的数据
onBLECharacteristicValueChange(success) {
wx.onBLECharacteristicValueChange((res) => {
success(res);
});
}
//关闭蓝牙模块
closeBluetoothAdapter() {
wx.closeBluetoothAdapter();
}
// 不分包写入蓝牙
writeBLECharacteristicValueOnce(
deviceId,
serviceId,
characteristicId,
value
) {
wx.writeBLECharacteristicValue({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: characteristicId,
value: value,
});
}
readBLECharacteristicValue(deviceId, serviceId, characteristicId) {
wx.readBLECharacteristicValue({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: characteristicId,
});
}
getBLEMTU(deviceId, success) {
wx.getBLEMTU({
deviceId: deviceId,
writeType: "write",
success(res) {
success(res.mtu);
},
});
}
onBLEMTUChange(success) {
wx.onBLEMTUChange(function (res) {
success(res.mtu);
});
}
setBLEMTU(deviceId, mtu, success, failure) {
wx.setBLEMTU({
deviceId: deviceId,
mtu: mtu,
success: (res) => {
success(res);
},
fail: (res) => {
failure(res);
},
});
}
}
const bleDevice = new ble();
export default bleDevice;
6.APToast.js
const message = [
{
id:0,
type:"WIFI_REASON_SUCCESS",
message:"打印机连接成功"
},
{
id:2,
type:"WIFI_REASON_AUTH_EXPIRE",
message:"身份验证超时"
},
{
id:3,
type:"WIFI_REASON_AUTH_LEAVE",
message:"连接中断"
},
{
id:8,
type:"WIFI_REASON_ASSOC_LEAVE",
message:"连接中断"
},
{
id:15,
type:"WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT",
message:"密码错误"
},
{
id:201,
type:"WIFI_REASON_NO_AP_FOUND",
message:"未找到可用的网络"
},
{
id:202,
type:"WIFI_REASON_AUTH_FAIL",
message:"密码错误或身份验证超时"
},
{
id:203,
type:"WIFI_REASON_ASSOC_FAIL",
message:"设备无法与WiFi成功关联"
},
{
id:204,
type:"WIFI_REASON_HANDSHAKE_TIMEOUT",
message:"密码错误"
},
{
id:205,
type:"WIFI_REASON_CONNECTION_FAIL",
message:"连接失败"
},
]
export default message;
7.tip.js
export default class Tips {
/**
* 弹出提示框
*/
static success(title, duration = 1000) {
setTimeout(() => {
uni.showToast({
title: title,
icon: "success",
mask: true,
duration: duration,
});
}, 300);
if (duration > 0) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, duration);
});
}
}
/**
* 弹出加载提示
*/
static loading(title = "加载中") {
if (Tips.isLoading) {
return;
}
Tips.isLoading = true;
uni.showLoading({
title: title,
mask: true,
});
}
/**
* 加载完毕
*/
static loaded() {
if (Tips.isLoading) {
Tips.isLoading = false;
uni.hideLoading();
}
}
/**
* 关闭当前页面,跳转到新页面
*/
static redirectTo(urls, item) {
uni.redirectTo({
url: item
? urls + "?info=" + encodeURIComponent(JSON.stringify(item))
: urls, // JSON.parse(decodeURIComponent(option.info));
});
}
/**
* 弹出确认窗口
*/
static showModal(val, success) {
uni.showModal({
title: val.title ? val.title : "",
content: val.content ? val.content : "",
showCancel: val.showCancel,
confirmText: val.confirmText ? val.confirmText : "确定",
cancelText: val.cancelText ? val.cancelText : "取消",
cancelColor: "#999999", //取消按钮颜色
confirmColor: "#00A0E9", //确定按钮颜色
success: (res) => {
success(res);
},
});
}
}
/**
* 静态变量,是否加载中
*/
Tips.isLoading = false;
8.main.js
import ble from "./common/util/ble.js";
import tip from "./common/util/tip.js";
// ble
Vue.prototype.$ble = ble;
// tip
Vue.prototype.$tip = tip;