Kaynağa Gözat

optimize UI

master
elinkthings 4 yıl önce
ebeveyn
işleme
07f3c5f65c

+ 1
- 1
ailink_demo/app.json Dosyayı Görüntüle

@@ -11,7 +11,7 @@
},
"plugins": {
"sdkPlugin": {
"version": "1.1.1",
"version": "1.1.2",
"provider": "wx17e93aad47cdae1a"
}
},

+ 157
- 57
ailink_demo/pages/index/index.js Dosyayı Görüntüle

@@ -4,16 +4,23 @@ const plugin = requirePlugin("sdkPlugin").AiLink;


function inArray(arr, key, val) {
if (!arr || !arr.length || typeof arr != 'object' || !Array.isArray(arr)) {
return -1
}
for (let i = 0; i < arr.length; i++) {
if (arr[i][key] === val) {
return i;
if (!key) {
if (arr[i] == val) {
return i
}
} else if (arr[i][key] === val) {
return i
}
}
return -1;
}

// ArrayBuffer转16进度字符串示例
function ab2hex(buffer, split = ',') {
function ab2hex(buffer, split) {
var hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
@@ -41,9 +48,17 @@ Page({
],
connected: false,
chs: [],
cmd: '',
name: '',
deviceId: null,
historyList: [],
},
onLoad: function () {

let historyList = []
historyList = wx.getStorageSync('historyList')
this.setData({
historyList,
})
},

// 初始化蓝牙模块
@@ -92,7 +107,7 @@ Page({
allowDuplicatesKey: true,
services: [
"FFE0",
"F0A0",
// "F0A0", // BM30广播模块需加上,如使用连接模块可忽略
],
success: (res) => {
console.log('startBluetoothDevicesDiscovery success', res)
@@ -129,6 +144,9 @@ Page({
} else {
let buff = device.advertisData.slice(-6)
device.mac = new Uint8Array(buff) // 保存广播数据中的mac地址,这是由于iOS不直接返回mac地址
let tempMac = Array.from(device.mac)
tempMac.reverse()
device.macAddr = ab2hex(tempMac, ':').toUpperCase()
}
if (idx === -1) {
data[`devices[${foundDevices.length}]`] = device
@@ -141,6 +159,16 @@ Page({
},
// 连接低功耗蓝牙设备
createBLEConnection(e) {
this._connLoading = true
wx.showLoading({
title: '连接中',
})
setTimeout(() => {
if (this._connLoading) {
this._connLoading = false
wx.hideLoading()
}
}, 6000)
const ds = e.currentTarget.dataset
const index = ds.index
// 保存当前连接的设备,注意不能从wxml的dataset中直接返回该对象,因为ArrarBuffer类型的数据无法保留
@@ -159,13 +187,40 @@ Page({
})
console.log("createBLEConnection:success")
wx.stopBluetoothDevicesDiscovery()
this.onBLEConnectionStateChange()
this.getBLEDeviceServices(deviceId)
},
fail: res => {
this._connLoading = false
wx.hideLoading()
wx.showToast({
title: '连接失败',
icon: 'none'
})
}
})
// 连接上设备就可以停止蓝牙搜索,减少功耗。
this.stopBluetoothDevicesDiscovery()
},

onBLEConnectionStateChange() {
wx.onBLEConnectionStateChange((res) => {
console.log('wx.onBLEConnectionStateChange() ', res.deviceId, res.connected, res.errorCode, res.errorMsg)
// 该方法回调中可以用于处理连接意外断开等异常情况
// console.log(`%c device ${res.deviceId} state has changed, connected: ${res.connected}`, 'color: #F26363')
if (!res.connected) {
wx.showToast({
title: '连接已断开',
icon: 'none'
})
this.setData({
connected: false,
showWriteInput: false,
})
}
})
},

// 断开与低功耗蓝牙设备的连接
closeBLEConnection() {
wx.closeBLEConnection({
@@ -174,6 +229,7 @@ Page({
this.setData({
connected: false,
chs: [],
showWriteInput: false,
})
},

@@ -182,9 +238,8 @@ Page({
wx.getBLEDeviceServices({
deviceId,
success: (res) => {
console.log(res)
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].isPrimary && res.services[i].uuid.indexOf("FFE0")>-1) {
if (res.services[i].isPrimary && res.services[i].uuid.indexOf('FFE0') > -1) {
this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
return
}
@@ -207,44 +262,48 @@ Page({

// 这部分功能在插件的 initPlugin 中已实现,如需用到其中的 uuid 也可取消注释
// // let uuid1, uuid2, uuid3;
// for (let i = 0; i < res.characteristics.length; i++) {
// let item = res.characteristics[i]
// if (item.uuid.indexOf('0000FFE1') != -1) {
// this.uuid1 = item.uuid //下发数据
// } else if (item.uuid.indexOf('0000FFE2') != -1) {
// this.uuid2 = item.uuid //监听数据
// } else if (item.uuid.indexOf('0000FFE3') != -1) {
// this.uuid3 = item.uuid //写入设置
// }
// }
// // 打开监听
// wx.notifyBLECharacteristicValueChange({
// deviceId,
// serviceId,
// characteristicId: this.uuid2,
// state: true,
// })
// wx.notifyBLECharacteristicValueChange({
// deviceId,
// serviceId,
// characteristicId: this.uuid3,
// state: true,
// })
for (let i = 0; i < res.characteristics.length; i++) {
let item = res.characteristics[i]
if (item.uuid.indexOf('0000FFE1') != -1) {
this.uuid1 = item.uuid //下发数据
} else if (item.uuid.indexOf('0000FFE2') != -1) {
this.uuid2 = item.uuid //监听数据
} else if (item.uuid.indexOf('0000FFE3') != -1) {
this.uuid3 = item.uuid //写入设置
}
}
// 打开监听
wx.notifyBLECharacteristicValueChange({
deviceId,
serviceId,
characteristicId: this.uuid2,
state: true,
})
wx.notifyBLECharacteristicValueChange({
deviceId,
serviceId,
characteristicId: this.uuid3,
state: true,
})

// 初始化插件
plugin.initPlugin(res.characteristics, this._device)

wx.onBLECharacteristicValueChange((characteristic) => {
// 解析特征值,返回解密后的数据
console.log("===" + plugin.ab2hex(characteristic.value))
let bleData = plugin.parseBleData(characteristic.value)
console.log(bleData)
if (bleData.status == 0) {
console.log("握手成功")
this._connLoading = false
wx.hideLoading()
wx.showToast({
title: '连接成功',
})
} else if (bleData.status == 1) {
console.log(bleData)
let payload = bleData.data //对应协议中的payload数据,可以自行解析该数据
console.log(ab2hex(payload, ' '))
console.log(ab2hex(bleData.completeData, ' '))
// console.log(ab2hex(payload, ' '))
// console.log(ab2hex(bleData.completeData, ' '))

// 以体脂秤数据解析为例
let weight, adc;
@@ -291,17 +350,17 @@ Page({
if (idx === -1) {
data[`chs[${this.data.chs.length}]`] = {
uuid: characteristic.characteristicId,
value: ab2hex(payload, ' ')
value: ab2hex(bleData.completeData, ' ')
}
} else {
data[`chs[${idx}]`] = {
uuid: characteristic.characteristicId,
value: ab2hex(payload, ' ')
value: ab2hex(bleData.completeData, ' ')
}
}
this.setData(data)
} else {
console.log(bleData)
// console.log(bleData)
}
})
},
@@ -319,7 +378,7 @@ Page({
value: buffer,
success(res) {
console.log('writeBLECharacteristicValue success', res)
console.log(ab2hex(buffer))
console.log('下发指令==> ' + ab2hex(buffer))
}
})
},
@@ -339,23 +398,25 @@ Page({
showWriteInput: false
})
},
// 指令输入
writingCmd(e) {
this._cmd = e.detail.value
},
// 指令下发
submitCmd() {
if (!this._cmd) {
submitCmd(e, cmd) {
let arr = []
let temp = []
if (!cmd) {
cmd = this.data.cmd
}
console.log(cmd)
if(!cmd || !this.data.connected){
return
}
let arr = []
if (this._cmd.indexOf(",") == -1) {
arr = this._cmd.split(" ")
if(cmd.indexOf(",") == -1){
temp = cmd.split(" ")
} else {
arr = this._cmd.split(",")
temp = cmd.split(",")
}
for (let i in arr) {
arr[i] = parseInt(arr[i], 16)
let tempCmd = temp.join(' ')
for(let i = 0; i < temp.length; i++){
arr[i] = parseInt(temp[i],16)
}
// let arr = [
// 0xA6,
@@ -365,15 +426,54 @@ Page({
// 0x6A,
// //A6 01 28 29 6A
// ]
if (arr[0] == 0xA6) {
let payload = arr.slice(2, -2)
if(arr[0] == 0xA6){
let len = arr[1]
let payload = arr.slice(2, 2 + len)
plugin.sendDataOfA6(payload)
} else if (arr[0] == 0xA7) {
let cid = [arr[1], arr[2]] // 001E
let payload = arr.slice(4, -2)
// let buff = new Uint8Array(arr).buffer
// this.writeBLECharacteristicValue(buff, this.uuid3, this._deviceId, this._serviceId)
} else if(arr[0] == 0xA7) {
let len = arr[3]
let payload = arr.slice(4, 4 + len)
plugin.sendDataOfA7(payload)
// this.writeBLECharacteristicValue(buff, this.uuid1, this._deviceId, this._serviceId)
}
return
let historyList = wx.getStorageSync('historyList') || []
let idx = historyList.findIndex(item => item.cmd == tempCmd)
if (idx < 0) {
historyList.push({cmd: tempCmd})
}
this.setData({
historyList
})
wx.setStorage({
data: historyList,
key: 'historyList',
})
wx.showToast({
title: '已发送',
icon: 'none'
})
},
history_delete(e) {
let index = e.currentTarget.dataset.index
this.data.historyList.splice(index, 1)
this.setData({
historyList: this.data.historyList
})
wx.setStorage({
data: this.data.historyList,
key: 'historyList',
})
},
history_copy(e) {
let index = e.currentTarget.dataset.index
wx.setClipboardData({
data: this.data.historyList[index].cmd
})
},
history_send(e) {
let index = e.currentTarget.dataset.index
let cmd = this.data.historyList[index].cmd
this.submitCmd(null, cmd)
},
});

+ 57
- 41
ailink_demo/pages/index/index.wxml Dosyayı Görüntüle

@@ -8,49 +8,65 @@ module.exports.len = function(arr) {
}
</wxs>
<button bindtap="openBluetoothAdapter">开始扫描</button>
<button bindtap="stopBluetoothDevicesDiscovery">停止扫描</button>
<button bindtap="closeBluetoothAdapter">结束流程</button>
<view class="devices_summary">已发现 {{devices.length}} 个外围设备:</view>
<scroll-view class="device_list" scroll-y scroll-with-animation>
<view wx:for="{{devices}}" wx:key="index"
data-device-id="{{item.deviceId}}"
data-name="{{item.name || item.localName}}"
data-mac="{{item.mac}}"
data-index="{{index}}"
bindtap="createBLEConnection"
class="device_item"
hover-class="device_item_hover">
<view style="font-size: 16px; color: #333;">{{item.name}}</view>
<view style="font-size: 10px">信号强度: {{item.RSSI}}dBm ({{utils.max(0, item.RSSI + 100)}}%)</view>
<view style="font-size: 10px">mac地址: {{item.deviceId}}</view>
<!-- <view style="font-size: 10px">Service数量: {{utils.len(item.advertisServiceUUIDs)}}</view> -->
<view style="font-size: 14px">广播数据:{{item.analyzeDataText}}</view>
<view class="container">
<view class="header">
<button bindtap="openBluetoothAdapter" style="font-size: 32rpx;line-height:100rpx;width: 100%;">开始扫描</button>
<button bindtap="stopBluetoothDevicesDiscovery" style="font-size: 32rpx;line-height:100rpx;width: 100%;">停止扫描</button>
<button bindtap="closeBluetoothAdapter" style="font-size: 32rpx;line-height:100rpx;width: 100%;">结束流程</button>
</view>
</scroll-view>
<view class="connected_info" wx:if="{{connected}}">
<view>
<text>已连接到 {{name}}</text>
<view class="operation">
<!-- <button wx:if="{{canWrite}}" size="mini" bindtap="writeBLECharacteristicValue">写数据</button> -->
<button size="mini" bindtap="showWriteInputView">写入指令</button>
<button size="mini" bindtap="closeBLEConnection">断开连接</button>
<view class="devices_summary">已发现 {{devices.length}} 个外围设备:</view>
<scroll-view class="device_list" scroll-y scroll-with-animation>
<view wx:for="{{devices}}" wx:key="index"
data-device-id="{{item.deviceId}}"
data-name="{{item.name || item.localName}}"
data-mac="{{item.mac}}"
data-index="{{index}}"
bindtap="createBLEConnection"
class="device_item"
hover-class="device_item_hover">
<view style="font-size: 32rpx;">
<text style="color:#000;font-weight:bold">{{item.name}}</text>
<text style="font-size:26rpx">(信号强度: {{item.RSSI}}dBm)</text>
</view>
<view style="font-size: 26rpx">mac地址: {{item.macAddr || item.deviceId}}</view>
<!-- <view style="font-size: 10px">Service数量: {{utils.len(item.advertisServiceUUIDs)}}</view> -->
<view style="font-size: 26rpx">广播数据:{{item.analyzeDataText}}</view>
</view>
</scroll-view>
<view class="connected_info" wx:if="{{connected}}">
<view>
<text>已连接到 {{name}}</text>
<view class="operation">
<!-- <button wx:if="{{canWrite}}" size="mini" bindtap="writeBLECharacteristicValue">写数据</button> -->
<button size="mini" bindtap="showWriteInputView" style="line-height:54rpx; font-size:28rpx;padding:0 20rpx;margin-right:10rpx">写入指令</button>
<button size="mini" bindtap="closeBLEConnection" style="line-height:54rpx; font-size:28rpx;padding:0 20rpx;">断开连接</button>
</view>
</view>
<view wx:for="{{chs}}" wx:key="index" style="font-size: 26rpx; margin-top: 20rpx;">
<view>特性值: {{item.value}}</view>
</view>
</view>
<view wx:for="{{chs}}" wx:key="index" style="font-size: 12px; margin-top: 10px;">
<view>特性值: {{item.value}}</view>
</view>
</view>
<view class="writeInputViewBg" wx:if="{{showWriteInput}}"></view>
<view class="writeInputView" wx:if="{{showWriteInput}}">
<view class="writeInput">
<input bindinput="writingCmd"></input>
</view>
<view class="hint">请输入16进制数,Byte之间用空格或英文逗号分隔</view>
<view class="btns">
<button size="mini" bindtap="submitCmd">确定</button>
<button size="mini" bindtap="hideWriteInputView">取消</button>
<view class="writeInputView" wx:if="{{showWriteInput}}">
<view class="writeInput">
<input type="text" model:value="{{cmd}}"></input>
</view>
<view class="hint">请输入16进制数,Byte之间用空格或英文逗号分隔</view>
<view class="btns">
<button bindtap="submitCmd" style="line-height:70rpx; font-size:30rpx;padding:0 50rpx;margin-right:30rpx;">发送</button>
<button bindtap="hideWriteInputView" style="line-height:70rpx; font-size:30rpx;padding:0 50rpx;">取消</button>
</view>
<view class="history">
<view class="history_title">历史记录:</view>
<scroll-view class="history_wrap" scroll-y="true">
<view class="history_item" wx:for="{{historyList}}" wx:key="index">
<view class="history_cmd">{{item.cmd}}</view>
<view class="history_btns">
<button size="mini" bindtap="history_send" data-index="{{index}}" style="line-height:54rpx; font-size:24rpx;padding:0 30rpx;">发送</button>
<button size="mini" bindtap="history_delete" data-index="{{index}}" style="line-height:54rpx; font-size:24rpx;padding:0 30rpx;margin-left:20rpx">删除</button>
</view>
</view>
</scroll-view>
</view>
</view>
</view>

+ 105
- 26
ailink_demo/pages/index/index.wxss Dosyayı Görüntüle

@@ -1,23 +1,60 @@
page {
background: #f0f0f0;
color: #333;
--safe-bottom: env(safe-area-inset-bottom);
}
view,
cover-view,
scroll-view,
swiper,
swiper-item,
movable-area,
movable-view,
button,
input,
textarea,
label,
navigator
{
box-sizing: border-box;
}
.container{
position: relative;
display: flex;
flex-direction: column;
align-items: center;
width: 100vw;
height: 100vh;
padding-bottom: 200rpx;
}
.header{
width: 100%;
}
.container button{
padding-top: 0;
padding-bottom: 0;
border: 1px solid #ddd;
}
.devices_summary {
margin-top: 30px;
padding: 10px;
font-size: 16px;
width: 100%;
line-height: 70rpx;
padding: 0 30rpx;
margin-top: 30rpx;
font-size: 32rpx;
}
.device_list {
height: 300px;
margin: 50px 5px;
flex: 1;
width: 100%;
height: calc(100vh - 600rpx);
margin-top: 0;
border: 1px solid #EEE;
border: 1px solid #fff;
border-radius: 5px;
width: auto;
background: #fff;
}
.device_item {
line-height: 1.5;
padding: 10rpx 30rpx;
border-bottom: 1px solid #EEE;
padding: 10px;
color: #666;
}
.device_item_hover {
background-color: rgba(0, 0, 0, .1);
@@ -26,18 +63,17 @@ page {
position: fixed;
bottom: 0;
width: 100%;
background-color: #F0F0F0;
height: 200rpx;
padding: 10px;
padding-bottom: 20px;
margin-bottom: env(safe-area-inset-bottom);
border-top: 1px solid #ddd;
background-color: #fff;
font-size: 14px;
min-height: 100px;
box-shadow: 0px 0px 3px 0px;
box-shadow: 0px -4rpx 4rpx 0px rgba(0,0,0,.05);
}
.connected_info .operation {
position: absolute;
display: inline-block;
right: 30px;
right: 30rpx;
}
.writeInputViewBg{
position: fixed;
@@ -50,27 +86,69 @@ page {
}
.writeInputView{
position: fixed;
top: 30%;
left: 50%;
bottom: 200rpx;
left: 0;
z-index: 1001;
background-color: #fff;
width: 80vw;
height: 300rpx;
display: flex;
flex-direction: column;
align-items: center;
transform: translateX(-50%);
width: 100%;
height: calc(100vh - 500rpx);
background-color: #fff;
border-top: 1px solid #ddd;
}
.writeInput{
margin-top: 60rpx;
width: 90%;
.history{
position: relative;
flex: 1;
width: 690rpx;
padding-top: 60rpx;
border: 1px solid #ddd;
margin: 30rpx;
}
.history_title{
position: absolute;
top: 0;
left: 0;
padding: 0 30rpx;
line-height: 60rpx;
font-size: 30rpx;
}
.history_wrap{
width: 100%;
height: 100%;
}
.history_item{
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 72rpx;
padding: 0 30rpx;
border-top: 1px solid #ddd;
}
.history_cmd{
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 24rpx;
}
.history_btns{
height: 60rpx;
overflow: hidden;
}
.writeInput{
margin-top: 30rpx;
width: 690rpx;
height: 80rpx;
border: 1rpx solid #ccc;
}
.writeInput input{
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 10rpx;
font-size: 32rpx;
}
.hint{
padding-top: 10rpx;
@@ -82,5 +160,6 @@ page {
align-items: center;
justify-content: space-between;
width: 60%;
margin-top: 50rpx;
padding-bottom: 30rpx;
margin-top: 30rpx;
}

Loading…
İptal
Kaydet