<template>
|
|
<view >
|
|
|
|
<view class="content" v-if="!connected">
|
|
<u-icon class="logo" size="300" color="#808080" @click="scanDevice" name="scan"></u-icon>
|
|
<view class="text-area">
|
|
<text class="title">{{title}}</text>
|
|
</view>
|
|
</view>
|
|
|
|
|
|
<view v-else style="margin-top: 300rpx;padding-left: 10px;">
|
|
<u-row gutter="16">
|
|
<u-col span="7">
|
|
<view ><u-slider :height="20" @end="kiTovalue" v-model="valueki" step="10"></u-slider></view>
|
|
</u-col>
|
|
<u-col span="4" offset="1">
|
|
<u-number-box v-model="value" :min="0" :max="10" @change="valueToki"/>
|
|
</u-col>
|
|
</u-row>
|
|
<u-row gutter="16" >
|
|
<u-col span="3">
|
|
<u-button plain size="mini" type="success" @click="sendValue">确认发送</u-button>
|
|
</u-col>
|
|
<u-col span="3">
|
|
<u-button plain size="mini" type="error" @click="closeBLEConnection">断开连接</u-button>
|
|
</u-col>
|
|
<u-col span="3">
|
|
<u-button plain size="mini" type="warning" @click="writeBLECharacteristicValueString('getd')">获取开合度</u-button>
|
|
</u-col>
|
|
</u-row>
|
|
|
|
</view>
|
|
<u-modal @cancel='stopBluetoothDevicesDiscovery,show=false' title="提示" content="未搜索到设备,是否继续搜索" :show-cancel-button="true" @confirm="continueSearch()" v-model="searchLoad" >
|
|
</u-modal>
|
|
<u-toast ref="uToast" />
|
|
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
data() {
|
|
return {
|
|
searchLoad:false,
|
|
valueki:0,
|
|
value: 0,
|
|
title: '扫描设备二维码',
|
|
equipment: {},
|
|
connected: false,
|
|
isStop: true,
|
|
list: [],
|
|
imei: '',
|
|
item: [],
|
|
idObject:{
|
|
serviceId:'',
|
|
writeId:'',
|
|
notifyId:'',
|
|
},
|
|
timeSearch:null,
|
|
|
|
};
|
|
},
|
|
onLoad() {
|
|
this.onBLEConnectionStateChange();
|
|
},
|
|
onUnload:function(){
|
|
if(this.timeSearch) {
|
|
clearTimeout(this.timeSearch)
|
|
this.timeSearch = null
|
|
}
|
|
},
|
|
methods: {
|
|
kiTovalue(){
|
|
this.value=this.valueki/10
|
|
},
|
|
valueToki(){
|
|
this.valueki=this.value*10
|
|
},
|
|
sendValue() {
|
|
this.writeBLECharacteristicValueString('vals'+this.value)
|
|
},
|
|
continueSearch(){
|
|
clearTimeout(this.timeSearch)
|
|
this.timeSearch=setTimeout(() => {
|
|
if(!this.searchLoad&&!this.connected){
|
|
this.searchLoad=true
|
|
}
|
|
}, 8000);
|
|
uni.showToast({
|
|
title: '搜索设备中...',
|
|
icon: 'loading',
|
|
duration: 8000
|
|
});
|
|
this.startBluetoothDevicesDiscovery();
|
|
},
|
|
scanDevice() {
|
|
uni.openBluetoothAdapter({
|
|
success: e => {
|
|
var that = this
|
|
uni.scanCode({
|
|
success: function(res) {
|
|
|
|
let str1 = res.result.replace(';', '');
|
|
that.imei = str1
|
|
uni.showToast({
|
|
title: '搜索设备中...',
|
|
icon: 'loading',
|
|
duration: 8000
|
|
});
|
|
that.timeSearch=setTimeout(() => {
|
|
if(!that.searchLoad&&!that.connected){
|
|
that.searchLoad=true
|
|
}
|
|
}, 8000);
|
|
that.startBluetoothDevicesDiscovery();
|
|
},
|
|
fail: (res) => {
|
|
/* this.$refs.uToast.show({
|
|
title: '已取消',
|
|
type: 'error',
|
|
}) */
|
|
}
|
|
});
|
|
this.getBluetoothAdapterState();
|
|
},
|
|
fail: e => {
|
|
console.log(e)
|
|
console.log('初始化蓝牙失败,错误码:' + (e.errCode || e.errMsg));
|
|
if (e.errCode !== 0) {
|
|
initTypes(e.errCode, e.errMsg);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
},
|
|
|
|
/**
|
|
* 初始化蓝牙设备
|
|
*/
|
|
openBluetoothAdapter() {
|
|
uni.openBluetoothAdapter({
|
|
success: e => {
|
|
console.log('初始化蓝牙成功:' + e.errMsg);
|
|
console.log(JSON.stringify(e));
|
|
this.isStop = false;
|
|
this.getBluetoothAdapterState();
|
|
},
|
|
fail: e => {
|
|
console.log(e)
|
|
console.log('初始化蓝牙失败,错误码:' + (e.errCode || e.errMsg));
|
|
if (e.errCode !== 0) {
|
|
initTypes(e.errCode, e.errMsg);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
/**
|
|
* 开始搜索蓝牙设备
|
|
*/
|
|
startBluetoothDevicesDiscovery() {
|
|
uni.startBluetoothDevicesDiscovery({
|
|
success: e => {
|
|
this.onBluetoothDeviceFound();
|
|
},
|
|
fail: e => {
|
|
console.log('搜索蓝牙设备失败,错误码:' + e.errCode);
|
|
if (e.errCode !== 0) {
|
|
initTypes(e.errCode);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
/**
|
|
* 停止搜索蓝牙设备
|
|
*/
|
|
stopBluetoothDevicesDiscovery(types) {
|
|
clearTimeout(this.timeSearch)
|
|
uni.stopBluetoothDevicesDiscovery({
|
|
success: e => {
|
|
console.log('停止搜索蓝牙设备:' + e.errMsg);
|
|
},
|
|
fail: e => {
|
|
console.log('停止搜索蓝牙设备失败,错误码:' + e.errCode);
|
|
if (e.errCode !== 0) {
|
|
initTypes(e.errCode);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
/**
|
|
* 发现外围设备
|
|
*/
|
|
onBluetoothDeviceFound() {
|
|
uni.onBluetoothDeviceFound(devices => {
|
|
// this.$set(this.disabled, 3, false);
|
|
this.getBluetoothDevices();
|
|
});
|
|
},
|
|
/**
|
|
* 获取在蓝牙模块生效期间所有已发现的蓝牙设备。包括已经和本机处于连接状态的设备。
|
|
*/
|
|
getBluetoothDevices() {
|
|
// this.list=[]
|
|
let that = this
|
|
let imei = that.imei
|
|
|
|
uni.getBluetoothDevices({
|
|
success: res => {
|
|
res.devices.forEach(device => {
|
|
|
|
if (!device.name.indexOf('tpsl04v-' + imei.substr(imei.length - 6))) {
|
|
|
|
uni.hideToast();
|
|
that.stopBluetoothDevicesDiscovery()
|
|
that.equipment = device;
|
|
that.createBLEConnection()
|
|
return
|
|
} else {
|
|
//that.list.push(device)
|
|
}
|
|
})
|
|
},
|
|
fail: e => {
|
|
console.log('获取蓝牙设备错误,错误码:' + e.errCode);
|
|
if (e.errCode !== 0) {
|
|
initTypes(e.errCode);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
},
|
|
/**
|
|
* 获取本机蓝牙适配器状态
|
|
*/
|
|
getBluetoothAdapterState() {
|
|
console.log('--->');
|
|
uni.getBluetoothAdapterState({
|
|
success: res => {
|
|
console.log(JSON.stringify(res));
|
|
},
|
|
fail: e => {
|
|
console.log('获取本机蓝牙适配器状态失败,错误码:' + e.errCode);
|
|
if (e.errCode !== 0) {
|
|
initTypes(e.errCode);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
/**
|
|
* 连接低功耗蓝牙
|
|
*/
|
|
createBLEConnection() {
|
|
|
|
let deviceId = this.equipment.deviceId;
|
|
uni.showToast({
|
|
title: '连接蓝牙...',
|
|
icon: 'loading',
|
|
duration: 99999
|
|
});
|
|
|
|
if (!this.connected) {
|
|
uni.createBLEConnection({
|
|
deviceId,
|
|
success: res => {
|
|
this.connected = true;
|
|
clearTimeout(this.timeSearch)
|
|
console.log(res);
|
|
console.log('连接蓝牙成功:' + res.errMsg);
|
|
// 连接设备后断开搜索 并且不能搜索设备
|
|
|
|
uni.hideToast();
|
|
|
|
uni.showToast({
|
|
title: '连接成功',
|
|
icon: 'success',
|
|
duration: 2000
|
|
});
|
|
// this.closeBLEConnection()
|
|
|
|
this.getBLEDeviceServices()
|
|
},
|
|
fail: e => {
|
|
uni.hideToast();
|
|
/* uni.showToast({
|
|
title: '连接错误',
|
|
icon: 'error',
|
|
duration: 2000
|
|
}); */
|
|
console.log('连接低功耗蓝牙失败,错误码:' + e.errCode);
|
|
if (e.errCode !== 0) {
|
|
initTypes(e.errCode);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
},
|
|
/**
|
|
* 断开与低功耗蓝牙设备的连接
|
|
*/
|
|
closeBLEConnection() {
|
|
let deviceId = this.equipment.deviceId;
|
|
this.connected = false
|
|
uni.closeBLEConnection({
|
|
deviceId,
|
|
success: res => {
|
|
console.log(res);
|
|
console.log('断开低功耗蓝牙成功:' + res.errMsg);
|
|
this.equipment = {};
|
|
this.idObject={}
|
|
},
|
|
fail: e => {
|
|
console.log('断开低功耗蓝牙成功,错误码:' + e.errCode);
|
|
if (e.errCode !== 0) {
|
|
initTypes(e.errCode);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
/**
|
|
* 获取所有服务
|
|
*/
|
|
getBLEDeviceServices() {
|
|
let deviceId = this.equipment.deviceId;
|
|
uni.getBLEDeviceServices({
|
|
deviceId,
|
|
success: res => {
|
|
|
|
this.list = res.services;
|
|
this.idObject = {};
|
|
if (this.list.length <= 0) {
|
|
toast('获取服务失败,请重试!');
|
|
return;
|
|
}
|
|
|
|
this.list.forEach(item => {
|
|
this.getBLEDeviceCharacteristics(item)
|
|
})
|
|
this.maskShow = true;
|
|
},
|
|
fail: e => {
|
|
console.log('获取设备服务失败,错误码:' + e.errCode);
|
|
if (e.errCode !== 0) {
|
|
initTypes(e.errCode);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
/**
|
|
* 获取某个服务下的所有特征值
|
|
*/
|
|
getBLEDeviceCharacteristics(item) {
|
|
let deviceId = this.equipment.deviceId;
|
|
let serviceId = item.uuid;
|
|
let that = this
|
|
let write=''
|
|
let notify=''
|
|
uni.getBLEDeviceCharacteristics({
|
|
deviceId,
|
|
serviceId,
|
|
success: res => {
|
|
this.list = res.characteristics;
|
|
if (this.list.length <= 0) {
|
|
// toast('获取特征值失败,请重试!');
|
|
return;
|
|
}
|
|
|
|
this.list.forEach(characteristic => {
|
|
/* if (characteristic.properties.read) {
|
|
|
|
|
|
uni.readBLECharacteristicValue({
|
|
deviceId,
|
|
serviceId,
|
|
characteristicId: characteristic.uuid,
|
|
success: res => {
|
|
console.log('读取设备数据值成功read');
|
|
console.log(JSON.stringify(res));
|
|
|
|
},
|
|
fail(e) {
|
|
console.log('读取设备数据值失败,错误码:' + e.errCode);
|
|
if (e.errCode !== 0) {
|
|
initTypes(e.errCode);
|
|
}
|
|
}
|
|
});
|
|
|
|
} */
|
|
if (characteristic.properties.write ) {
|
|
|
|
write=characteristic.uuid
|
|
|
|
}
|
|
if (characteristic.properties.notify || characteristic.properties.indicate) {
|
|
notify=characteristic.uuid
|
|
|
|
|
|
}
|
|
})
|
|
if(write!==''&¬ify!==''){
|
|
this.idObject={
|
|
serviceId:serviceId,
|
|
writeId:write,
|
|
notifyId:notify,
|
|
}
|
|
console.log(this.idObject)
|
|
uni.notifyBLECharacteristicValueChange({
|
|
state: true, // 启用 notify 功能
|
|
deviceId,
|
|
serviceId,
|
|
characteristicId: this.idObject.notifyId,
|
|
success(res) {
|
|
that.onBLECharacteristicValueChange()
|
|
setTimeout(() => {
|
|
that.writeBLECharacteristicValueString('getd')
|
|
}, 1000);
|
|
},
|
|
fail(e) {
|
|
console.log('失败,错误码:' + e.errCode);
|
|
if (e.errCode !== 0) {
|
|
initTypes(e.errCode);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
},
|
|
fail: e => {
|
|
console.log('获取特征值失败,错误码:' + e.errCode);
|
|
if (e.errCode !== 0) {
|
|
initTypes(e.errCode);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
/**
|
|
* 监听低功耗蓝牙连接状态的改变事件。包括开发者主动连接或断开连接,设备丢失,连接异常断开等等
|
|
*/
|
|
onBLEConnectionStateChange() {
|
|
uni.onBLEConnectionStateChange(res => {
|
|
// 该方法回调中可以用于处理连接意外断开等异常情况
|
|
console.log(`蓝牙连接状态 -------------------------->`);
|
|
console.log(JSON.stringify(res));
|
|
if (!res.connected) {
|
|
this.connected=false
|
|
console.log('断开低功耗蓝牙成功:');
|
|
this.equipment = {};
|
|
this.idObject={}
|
|
toast('已经断开当前蓝牙连接');
|
|
}
|
|
});
|
|
},
|
|
writeBLECharacteristicValueString(str) {
|
|
console.log(str)
|
|
let deviceId = this.equipment.deviceId;
|
|
let serviceId = this.idObject.serviceId;
|
|
let characteristicId = this.idObject.writeId;
|
|
// 向蓝牙设备发送16进制数据
|
|
let buffer = new ArrayBuffer(str.length);
|
|
let dataView = new DataView(buffer);
|
|
|
|
for (let i in str) {
|
|
dataView.setUint8(i, str[i].charCodeAt() | 0);
|
|
}
|
|
uni.writeBLECharacteristicValue({
|
|
deviceId,
|
|
|
|
serviceId,
|
|
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
|
|
characteristicId,
|
|
value: buffer,
|
|
success: function(res) {
|
|
console.log(res);
|
|
},
|
|
fail: function(res) {
|
|
console.log(res);
|
|
}
|
|
})
|
|
},
|
|
// 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('')
|
|
},
|
|
/**
|
|
* 监听低功耗蓝牙设备的特征值变化事件。必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification。
|
|
*/
|
|
onBLECharacteristicValueChange() {
|
|
// 必须在这里的回调才能获取
|
|
let that = this
|
|
uni.onBLECharacteristicValueChange(function(res) {
|
|
console.log(`characteristic ${res.characteristicId} has changed, now is ${res.value}`)
|
|
// console.log(that.ab2hex(res.value))
|
|
console.log(res)
|
|
let hex = new Uint8Array(res.value);
|
|
hex = String.fromCharCode.apply(null, hex);
|
|
that.value= parseInt(hex.replace('valve status: ', ''));
|
|
that.valueki=parseInt(hex.replace('valve status: ', ''))*10;
|
|
console.log(that.value)
|
|
})
|
|
},
|
|
|
|
/**
|
|
* 断开蓝牙模块
|
|
*/
|
|
closeBluetoothAdapter(OBJECT) {
|
|
uni.closeBluetoothAdapter({
|
|
success: res => {
|
|
console.log('断开蓝牙模块成功');
|
|
this.equipment = {};
|
|
this.idObject={}
|
|
toast('断开蓝牙模块');
|
|
}
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 判断初始化蓝牙状态
|
|
*/
|
|
function initTypes(code, errMsg) {
|
|
switch (code) {
|
|
case 10000:
|
|
console.log('未初始化蓝牙适配器');
|
|
break;
|
|
case 10001:
|
|
toast('未检测到蓝牙,请打开蓝牙重试!');
|
|
break;
|
|
case 10002:
|
|
console.log('没有找到指定设备');
|
|
break;
|
|
case 10003:
|
|
console.log('连接失败');
|
|
break;
|
|
case 10004:
|
|
console.log('没有找到指定服务');
|
|
break;
|
|
case 10005:
|
|
console.log('没有找到指定特征值');
|
|
break;
|
|
case 10006:
|
|
console.log('当前连接已断开');
|
|
break;
|
|
case 10007:
|
|
console.log('当前特征值不支持此操作');
|
|
break;
|
|
case 10008:
|
|
console.log('其余所有系统上报的异常');
|
|
break;
|
|
case 10009:
|
|
console.log('Android 系统特有,系统版本低于 4.3 不支持 BLE');
|
|
break;
|
|
default:
|
|
console.log(errMsg);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 弹出框封装
|
|
*/
|
|
function toast(content, showCancel = false) {
|
|
uni.showModal({
|
|
title: '提示',
|
|
content,
|
|
showCancel
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
page {
|
|
height: 100%;
|
|
width: 100%;
|
|
}
|
|
|
|
.content {
|
|
display: flex;
|
|
width: 100%;
|
|
height: 100%;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.logo {
|
|
|
|
margin: 0;
|
|
padding: 0;
|
|
margin-top: 300rpx;
|
|
}
|
|
|
|
.text-area {
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
|
|
.title {
|
|
font-size: 36rpx;
|
|
color: #8f8f94;
|
|
}
|
|
.u-row {
|
|
margin: 40rpx 0;
|
|
}
|
|
</style>
|