elinkthings преди 4 години
ревизия
22d70fc93d

+ 5
- 0
wifi_ble_demo/app.js Целия файл

@@ -0,0 +1,5 @@
//app.js
App({
onLaunch: function () {
}
})

+ 21
- 0
wifi_ble_demo/app.json Целия файл

@@ -0,0 +1,21 @@
{
"pages": [
"pages/index/index",
"pages/wifiList/wifiList"
],
"window": {
"navigationBarBackgroundColor": "#0082FE",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "蓝牙连接Demo",
"backgroundColor": "#eeeeee",
"backgroundTextStyle": "light"
},
"plugins": {
"sdkPlugin": {
"version": "1.1.2",
"provider": "wx17e93aad47cdae1a"
}
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}

+ 72
- 0
wifi_ble_demo/app.wxss Целия файл

@@ -0,0 +1,72 @@
/**app.wxss**/
view,
cover-view,
scroll-view,
swiper,
swiper-item,
movable-area,
movable-view,
button,
input,
textarea,
label,
navigator
{
box-sizing: border-box;
}
page{
--safe-bottom: env(safe-area-inset-bottom);
}
.container{
position: relative;
display: flex;
flex-direction: column;
align-items: center;
width: 100vw;
height: 100vh;
padding-bottom: var(--safe-bottom);
}

.flex{
display: flex;
}
.flex_column{
display: flex;
flex-direction: column;
}
.ai_center{
align-items: center;
}
.ai_start{
align-items: flex-start;
}
.ai_end{
align-items: flex-end;
}
.jc_center{
justify-content: center;
}
.jc_sa{
justify-content: space-around;
}
.jc_sb{
justify-content: space-between;
}
.jc_end{
justify-content: flex-end;
}
.flex_center{
display: flex;
align-items: center;
justify-content: center;
}
.flex_center_sa{
display: flex;
align-items: center;
justify-content: space-around;
}
.flex_center_sb{
display: flex;
align-items: center;
justify-content: space-between;
}

+ 470
- 0
wifi_ble_demo/pages/index/index.js Целия файл

@@ -0,0 +1,470 @@
const util = require("../../utils/util");
const {inArray, ab2hex} = util

const plugin = requirePlugin("sdkPlugin").AiLink;


Page({
data: {
showWriteInput: false,
devices: [
// {
// deviceId: "02:03:04:05:06:07",
// name: "elink",
// localName: "elink",
// mac: "02:03:04:05:06:07",
// RSSI: -69,
// advertisServiceUUIDs:[
// "FFE0","FFC0"
// ],
// analyzeDataText:"0102003241123413"
// }
],
connected: false,
chs: [],
cmd: '',
name: '',
deviceId: null,
historyList: [],
},
onLoad: function () {
let historyList = []
historyList = wx.getStorageSync('historyList')
this.setData({
historyList,
})
},

toConnectWifi() {
this.offBLECharacteristicValueChange()
wx.navigateTo({
url: '../wifiList/wifiList',
})
},

// 初始化蓝牙模块
openBluetoothAdapter() {
wx.openBluetoothAdapter({
success: (res) => {
console.log('openBluetoothAdapter success', res)
this.startBluetoothDevicesDiscovery()
},
fail: (res) => {
if (res.errCode === 10001) {
wx.showToast({
title: '请打开蓝牙',
icon: "none"
})
wx.onBluetoothAdapterStateChange(function (res) {
console.log('onBluetoothAdapterStateChange', res)
if (res.available) {
this.startBluetoothDevicesDiscovery()
}
})
}
}
})
},
// 获取本机蓝牙适配器状态
getBluetoothAdapterState() {
wx.getBluetoothAdapterState({
success: (res) => {
console.log('getBluetoothAdapterState', res)
if (res.discovering) {
this.onBluetoothDeviceFound()
} else if (res.available) {
this.startBluetoothDevicesDiscovery()
}
}
})
},
// 开始搜寻附近的蓝牙外围设备
startBluetoothDevicesDiscovery() {
if (this._discoveryStarted) {
return
}
this._discoveryStarted = true
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
services: [
"FFE0",
// "F0A0", // BM30广播模块需加上,如使用连接模块可忽略
],
success: (res) => {
console.log('startBluetoothDevicesDiscovery success', res)
this.onBluetoothDeviceFound()
},
})
},
// 停止搜寻附近的蓝牙外围设备
stopBluetoothDevicesDiscovery() {
wx.stopBluetoothDevicesDiscovery()
},

// 监听寻找到新设备的事件
onBluetoothDeviceFound() {
wx.onBluetoothDeviceFound((res) => {
res.devices.forEach(device => {
if (!device.name && !device.localName) {
return
}
const foundDevices = this.data.devices
const idx = inArray(foundDevices, 'deviceId', device.deviceId)
const data = {}
// console.log(device)
// console.log(ab2hex(device.advertisData))
// 此处判断是否BM30广播模块,如使用连接模块请删除此 if ,只保留 else 内容
if (device.advertisServiceUUIDs[0].indexOf("F0A0") !== -1) {
let parseDataRes = plugin.parseBroadcastData(device.advertisData)
console.log(parseDataRes)
if (parseDataRes.status == 1) {
let analyzeData = plugin.analyzeBroadcastScaleData(parseDataRes)
console.log(analyzeData)
device.analyzeDataText = analyzeData.text
}
} 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
} else {
data[`devices[${idx}]`] = device
}
this.setData(data)
})
})
},
// 连接低功耗蓝牙设备
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类型的数据无法保留
this._device = this.data.devices[index]
console.log(this._device)
const deviceId = ds.deviceId
const name = ds.name
this.mac = ds.mac
wx.createBLEConnection({
deviceId,
success: (res) => {
this.setData({
connected: true,
name,
deviceId,
})
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) {
setTimeout(()=>{
wx.showToast({
title: '连接已断开',
icon: 'none'
})
},500)
wx.navigateBack()
this.setData({
connected: false,
showWriteInput: false,
})
}
})
},

// 断开与低功耗蓝牙设备的连接
closeBLEConnection() {
wx.closeBLEConnection({
deviceId: this._deviceId
})
this.setData({
connected: false,
chs: [],
showWriteInput: false,
})
},

// 获取蓝牙设备的 serviceId
getBLEDeviceServices(deviceId) {
wx.getBLEDeviceServices({
deviceId,
success: (res) => {
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].isPrimary && res.services[i].uuid.indexOf('FFE0') > -1) {
this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
return
}
}
}
})
},

// 获取蓝牙设备某个服务中所有特征值(characteristic)
getBLEDeviceCharacteristics(deviceId, serviceId) {
this._deviceId = deviceId
this._serviceId = serviceId
this._device.serviceId = serviceId

wx.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: (res) => {
console.log('getBLEDeviceCharacteristics success', res.characteristics)

// 这部分功能在插件的 initPlugin 中已实现,如需用到其中的 uuid 也可取消注释
// 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) => {
// 解析特征值,返回解密后的数据
let bleData = plugin.parseBleData(characteristic.value)
console.log(bleData)
if (bleData.status == 0) {
console.log("握手成功")
this._connLoading = false
wx.hideLoading()
wx.showToast({
title: '连接成功',
})
setTimeout(()=>{
this.toConnectWifi()
},500)
} else if (bleData.status == 1) {
let payload = bleData.data //对应协议中的payload数据,可以自行解析该数据
// console.log(ab2hex(payload, ' '))
// console.log(ab2hex(bleData.completeData, ' '))

// 以体脂秤数据解析为例
switch (payload[0]) {
/*
* 例如: A7 00 0E 05 01 00 01 F4 10 19 7A---------50.0kg
* 其中 01 00 01 F4 10 为 payload
* 具体指令请根据协议解析
*/
case 0x01:
case 0x02:
let weightValue = (payload[1] << 16) | (payload[2] << 8) | payload[3]
let decPoint = (payload[4] & 0xf0) >> 4
let unit = payload[4] & 0x0f
// console.log("体重数值:" + weightValue)
// console.log("小数点:" + decPoint)
// console.log("单位:" + unit)
if (unit == 1) { // 单位为斤
this._weight = weightValue / 2
} else {
// ... 其他单位
}
this._weight = weightValue / (decPoint * 10) // 除去小数点位数
break;
// ...
/*
* 例如: A7 00 0E 03 07 02 30 4A 7A---------阻抗测量成功,阻抗 560Ω
* 其中 07 02 30 为 payload
* 具体指令请根据协议解析
*/
case 0x07:
this._adc = (payload[1] << 8) | payload[2]
break;
case 0x0A:
//测量完成
let bodyData = plugin.getBodyData(1, 20, 170, this._weight, this._adc) // 体脂秤数据解析
console.log("解析后的体脂数据: ", bodyData)
console.log(util.getWeightDisplay(170, this._weight))
break;
}

const idx = inArray(this.data.chs, 'uuid', characteristic.characteristicId)
const data = {}
if (idx === -1) {
data[`chs[${this.data.chs.length}]`] = {
uuid: characteristic.characteristicId,
value: ab2hex(bleData.completeData, ' ')
}
} else {
data[`chs[${idx}]`] = {
uuid: characteristic.characteristicId,
value: ab2hex(bleData.completeData, ' ')
}
}
this.setData(data)
} else if (bleData.status == 2) {
console.log('A6-----^')
}
})
},
fail(res) {
console.error('getBLEDeviceCharacteristics', res)
}
})
},
writeBLECharacteristicValue(buffer, uuid, deviceId, serviceId) {
// 向蓝牙设备发送一个二进制流数据
wx.writeBLECharacteristicValue({
deviceId,
serviceId,
characteristicId: uuid,
value: buffer,
success(res) {
console.log('writeBLECharacteristicValue success', res)
console.log('下发指令==> ' + ab2hex(buffer))
}
})
},

offBLECharacteristicValueChange() {
wx.offBLECharacteristicValueChange((res)=>{
console.log(res)
})
},
closeBluetoothAdapter() {
wx.closeBluetoothAdapter()
this._discoveryStarted = false
},
// 打开指令输入框
showWriteInputView() {
this.setData({
showWriteInput: true
})
},
// 关闭指令输入框
hideWriteInputView() {
this.setData({
showWriteInput: false
})
},
// 指令下发
submitCmd(e, cmd) {
let arr = []
let temp = []
if (!cmd) {
cmd = this.data.cmd
}
console.log(cmd)
if(!cmd || !this.data.connected){
return
}
if(cmd.indexOf(",") == -1){
temp = cmd.split(" ")
} else {
temp = cmd.split(",")
}
let tempCmd = temp.join(' ')
for(let i = 0; i < temp.length; i++){
arr[i] = parseInt(temp[i],16)
}
// let arr = [
// 0xA6,
// 0x01,
// 0x28,
// 0x29,
// 0x6A,
// //A6 01 28 29 6A
// ]
if(arr[0] == 0xA6){
let len = arr[1]
let payload = arr.slice(2, 2 + len)
plugin.sendDataOfA6(payload)
// 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)
}
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)
},
});

+ 4
- 0
wifi_ble_demo/pages/index/index.json Целия файл

@@ -0,0 +1,4 @@
{
"usingComponents": {
}
}

+ 74
- 0
wifi_ble_demo/pages/index/index.wxml Целия файл

@@ -0,0 +1,74 @@
<wxs module="utils">
module.exports.max = function(n1, n2) {
return Math.max(n1, n2)
}
module.exports.len = function(arr) {
arr = arr || []
return arr.length
}
</wxs>
<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>
<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" wx:if="{{0}}">写入指令</button>
<button size="mini" bindtap="toConnectWifi" style="line-height:54rpx; font-size:28rpx;padding:0 20rpx;margin-right:10rpx">连接wifi</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 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>

+ 143
- 0
wifi_ble_demo/pages/index/index.wxss Целия файл

@@ -0,0 +1,143 @@
page {
background: #f0f0f0;
color: #333;
}
.container{
padding-bottom: 200rpx;
}
.header{
width: 100%;
}
.container button{
padding-top: 0;
padding-bottom: 0;
border: 1px solid #ddd;
}
.devices_summary {
width: 100%;
line-height: 70rpx;
padding: 0 30rpx;
margin-top: 30rpx;
font-size: 32rpx;
}
.device_list {
flex: 1;
width: 100%;
height: calc(100vh - 600rpx);
margin-top: 0;
border: 1px solid #fff;
border-radius: 5px;
background: #fff;
}
.device_item {
line-height: 1.5;
padding: 10rpx 30rpx;
border-bottom: 1px solid #EEE;
}
.device_item_hover {
background-color: rgba(0, 0, 0, .1);
}
.connected_info {
position: fixed;
bottom: 0;
width: 100%;
height: 200rpx;
padding: 10px;
border-top: 1px solid #ddd;
background-color: #fff;
font-size: 14px;
box-shadow: 0px -4rpx 4rpx 0px rgba(0,0,0,.05);
}
.connected_info .operation {
position: absolute;
display: inline-block;
right: 30rpx;
}
.writeInputViewBg{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
background-color: rgba(0,0,0,0.5);
}
.writeInputView{
position: fixed;
bottom: 200rpx;
left: 0;
z-index: 1001;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
height: calc(100vh - 500rpx);
background-color: #fff;
border-top: 1px solid #ddd;
}
.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%;
padding: 10rpx;
font-size: 32rpx;
}
.hint{
padding-top: 10rpx;
font-size: 24rpx;
color: #999;
}
.btns{
display: flex;
align-items: center;
justify-content: space-between;
width: 60%;
padding-bottom: 30rpx;
margin-top: 30rpx;
}

+ 328
- 0
wifi_ble_demo/pages/wifiList/wifiList.js Целия файл

@@ -0,0 +1,328 @@
// pages/wifiList/wifiList.js
const util = require("../../utils/util");
const {
ab2hex
} = util;

const plugin = requirePlugin("sdkPlugin").AiLink;

Page({

/**
* 页面的初始数据
*/
data: {
list: [],
wifi_connected: false,
conn_wifi: {},
scanEnd: false,
totalAP: 0,
pwdModal: false,
pwdInput: '',
statusText: '',
statusList: ['', '', '已连接']
},

/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
let pages = getCurrentPages()
this._home = pages[pages.length - 2]

wx.onBLECharacteristicValueChange((characteristic) => {
// 解析特征值,返回解密后的数据
let bleData = plugin.parseBleData(characteristic.value)
// console.log(bleData)
if (bleData.status == 0) {
console.log("握手成功")
} else if (bleData.status == 1) {
console.log('A7-----^')
} else if (bleData.status == 2) {
console.log(bleData)
console.log('A6-----^')
let payload = bleData.data
const result = ['成功', '失败', '不支持']
switch (payload[0]) {
case 0x26: {
console.log('状态改变')
let bleStatus = payload[1] & 0x0f
let wifiStatus = payload[1] >> 4
const bleStatusList = ['无连接', '已连接', '配对完成']
const wifiStatusList = ['未连接', '连接失败', '连接的WiFi信号不好', '连接成功', '正在连接']
console.log('蓝牙状态:' + bleStatusList[bleStatus])
console.log('WiFi状态:' + wifiStatusList[wifiStatus])
this.setData({
statusText: '蓝牙状态:' + bleStatusList[bleStatus] + ' ,WiFi状态:' + wifiStatusList[wifiStatus]
})
break
}
case 0x80: {
wx.hideLoading()
wx.showToast({
title: '扫描AP' + result[payload[1]],
icon: 'none'
})
console.log('扫描AP' + result[payload[1]])
break;
}
case 0x81: {
let id = payload[1]
console.log('上报WiFi名===>')
let nameArr = payload.slice(2)
console.log('原始数据===>' + ab2hex(nameArr, ' '))
let name = nameArr.length ? util.hex2str(nameArr) : ''
if (name) {
console.log('WiFi名===>' + name)
let index = this.data.list.findIndex(item => item.name == name)
if (index < 0) {
this.data.list.push({
id,
name,
})
} else {
this.data.list[index].name = name
}
this.setData({
list: this.data.list
})
}
break;
}
case 0x82: {
console.log('上报WiFi信息-----^')
let id = payload[1]
let index = this.data.list.findIndex(item => item.id == id)
let addr = payload.slice(2, 8)
let signal = payload[8]
let type = payload[9]
let status = payload[10]
if (index < 0) {
// this.data.list.push({
// id,
// addr,
// signal,
// type,
// status,
// })
} else {
this.data.list[index].addr = addr
this.data.list[index].signal = signal
this.data.list[index].type = type
this.data.list[index].status = status
this.setData({
list: this.data.list
})
}
break;
}
case 0x83:
let num = payload[1]
console.log('上报扫描完毕-----^')
this.setData({
totalAP: num,
scanEnd: true
})
break;
case 0x84: {
console.log('设置地址' + result[payload[1]])
wx.showToast({
title: '设置地址' + result[payload[1]],
icon: 'none'
})
// if (this._conn_wifi.status > 0) {
// this.connectWifi()
// }
break;
}
case 0x86: {
console.log('设置密码' + result[payload[1]])
wx.showToast({
title: '设置密码' + result[payload[1]],
icon: 'none'
})
if (payload[1] === 0) {
this.connectWifi()
this.closeModal()
}
break;
}
case 0x88: {
console.log('设置 wifi 状态' + result[payload[1]])
wx.showToast({
title: '设置 wifi 状态' + result[payload[1]],
icon: 'none'
})
if (payload[1] === 0) {
if (this.data.wifi_connected) { // true 建立连接, false 断开连接
this.data.list.forEach(item=>{
if (item.name === this._conn_wifi.name) {
item.status = 2
} else if (item.status == 2) {
item.status = 1
}
})
}
this.setData({
conn_wifi: this._conn_wifi,
wifi_connected: this.data.wifi_connected,
list: this.data.list
})
} else {
this.setData({
wifi_connected: !this.data.wifi_connected
})
}
break;
}

}
}
})
},

doSearch() {
let payload = [0x80, 0x01]
this.setData({
scanEnd: false,
})
wx.showLoading({
title: '开始搜索',
})
this.data.list = []
plugin.sendDataOfA6(payload)
},

tapItem(e) {
let index = e.currentTarget.dataset.index
let item = this.data.list[index]
console.log(item)
// 设置希望连接的 AP 地址
let cmd = [0x84, ...item.addr]
plugin.sendDataOfA6(cmd)
this.showModal()
this._conn_wifi = item
},

confirmPwd() {
if (!this.data.pwdInput || this.data.pwdInput.length < 8) {
wx.showToast({
title: '密码有误',
icon: 'none'
})
return
}
let pwdArr = util.str2hex(this.data.pwdInput)
if (pwdArr.length > 56) {
wx.showToast({
title: '密码有误',
icon: 'none'
})
return
}
if (pwdArr.length > 14) { // 超出14 byte 需分包
console.log('密码超出14位===')
let pwdList = []
let len = parseInt(pwdArr.length / 14) + 1
for (let i = 0; i < len; i++) {
setTimeout(() => {
pwdList[i] = pwdArr.slice(i * 14, (i + 1) * 14)
let isEnd = +(i !== len - 1)
console.log(isEnd)
let cmd = [0x86, isEnd, ...pwdList[i]]
console.log(cmd)
plugin.sendDataOfA6(cmd)
}, 200 * i)
}
console.log(pwdArr)
console.log(pwdList)
} else {
// 设置希望连接的 AP 密码
let cmd = [0x86, 0x00, ...pwdArr]
plugin.sendDataOfA6(cmd)
}
},

connectWifi() {
// 发起 wifi 连接
this.setData({
wifi_connected: true
})
let cmd = [0x88, 0x01]
plugin.sendDataOfA6(cmd)
},

closeWifiConnection() {
// 断开 wifi 连接
this.setData({
wifi_connected: false
})
let cmd = [0x88, 0x00]
plugin.sendDataOfA6(cmd)
},

showModal() {
this.setData({
pwdModal: true
})
},

closeModal() {
this.setData({
pwdModal: false
})
},

stopAction() {
return false
},

/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {

},

/**
* 生命周期函数--监听页面显示
*/
onShow: function () {

},

/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {

},

/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {

},

/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {

},

/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {

},

/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {

}
})

+ 3
- 0
wifi_ble_demo/pages/wifiList/wifiList.json Целия файл

@@ -0,0 +1,3 @@
{
"usingComponents": {}
}

+ 40
- 0
wifi_ble_demo/pages/wifiList/wifiList.wxml Целия файл

@@ -0,0 +1,40 @@
<!--pages/wifiList/wifiList.wxml-->
<view class="container">
<view class="header_button">
<button bindtap="doSearch" style="font-size: 32rpx;line-height:100rpx;width: 100%;background:#fff">开始搜索WiFi</button>
</view>
<view class="wifi_title">
<text>WiFi列表</text>
<text>-WiFi总数:{{list.length}}</text>
<view wx:if="{{0}}">扫描结束,本次扫描到WiFi数:{{totalAP}}</view>
</view>
<scroll-view scroll-y="true" class="wifi_list">
<view class="wifi_item flex_center_sb" wx:for="{{list}}" wx:key='index' bindtap="tapItem" data-index="{{index}}" hover-class="item_hover">
<view>{{item.name}}</view>
<view class="wifi_item_right">{{statusList[item.status]}}</view>
</view>
</scroll-view>
<view class="footer" wx:if="{{conn_wifi.id}}">
<view>
<text>{{conn_wifi.name}} </text>
<text>{{wifi_connected?'已连接':'已断开连接'}}</text>
<view class="operation">
<button size="mini" bindtap="connectWifi" style="line-height:54rpx; font-size:28rpx;padding:0 20rpx;margin-right:10rpx" wx:if="{{!wifi_connected}}">重新连接</button>
<button size="mini" bindtap="closeWifiConnection" style="line-height:54rpx; font-size:28rpx;padding:0 20rpx;">断开连接</button>
</view>
</view>
<view style="font-size: 26rpx; margin-top: 20rpx;" wx:if="{{statusText}}">{{statusText}}</view>
</view>
</view>
<view class="modal_wrapper {{pwdModal ? 'modal_wrapper_show': ''}}" catchtouchmove="stopAction">
<view class="remindModal">
<view class="remindModal_title">密码输入</view>
<view class="modal_input_wrap">
<input model:value='{{pwdInput}}' class="modal_input" placeholder="请输入密码" placeholder-style="font-size:30rpx;color:#b4b4b4" />
</view>
<view class="remindModal_btn">
<view class="confirm_btn" bindtap="confirmPwd">确定</view>
<view class="remindModal_cancel_btn" bindtap="closeModal" hover-class="hover_tap">取消</view>
</view>
</view>
</view>

+ 142
- 0
wifi_ble_demo/pages/wifiList/wifiList.wxss Целия файл

@@ -0,0 +1,142 @@
/* pages/wifiList/wifiList.wxss */
page{
background: #f8f8f8;
}
.container{
padding-bottom: 200rpx;
}
.container button{
padding-top: 0;
padding-bottom: 0;
border: 1px solid #ddd;
}
.header_button{
flex: 0 0 auto;
width: 100%;
}
.wifi_title{
width: 100%;
padding: 40rpx 30rpx 20rpx;
line-height: 1.5;
}
.wifi_list{
width: 100%;
height: calc(100vh - 400rpx);
border: 1px solid #ccc;
}
.wifi_item{
height: 100rpx;
padding: 0 30rpx;
border-bottom: 1px solid #ddd;
background: #fff;
}
.wifi_item_right{
color: #1977ff;
}
.footer {
position: fixed;
bottom: 0;
width: 100%;
height: 200rpx;
padding: 10px;
border-top: 1px solid #ddd;
background-color: #fff;
font-size: 14px;
box-shadow: 0px -4rpx 4rpx 0px rgba(0,0,0,.05);
}
.footer .operation {
position: absolute;
display: inline-block;
right: 30rpx;
}
.modal_wrapper{
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: -1;
background: rgba(0,0,0,0.5);
transition: .4s all;
height: 200vh;
opacity: 0;
}
.modal_wrapper_show{
transform: translateY(-100vh);
opacity: 1;
overflow-x: hidden;
overflow-y: auto;
z-index: 1000;
}
.remindModal{
position: absolute;
bottom: 50vh;
left: 50%;
z-index: 101;
transform: translate(-50%, 50%);
background: #fff;
width: 600rpx;
padding: 40rpx 60rpx;
border-radius: 20rpx;
}
.remindModal_title{
padding: 10rpx 30rpx 50rpx;
text-align: center;
font-size: 32rpx;
}
.remindModal_content{
font-size: 30rpx;
line-height: 1.6;
text-align: center;
padding-top: 30rpx;
min-height: 100rpx;
}
.remindModal_btn{
margin-top: 80rpx;
margin-bottom: 10rpx;
}
.remindModal_cancel_btn{
margin-top: 30rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
color: #FA1111;
font-size: 30rpx;
}
.modal_input_wrap{
width: 100%;
height: 80rpx;
padding: 0 10rpx;
border: 1px solid #dcdcdc;
border-radius: 10rpx;
}
.modal_input{
width: 100%;
height: 100%;
padding: 10rpx;
font-size: 30rpx;
}
.confirm_btn{
display: flex;
align-items: center;
justify-content: center;
width: 480rpx;
height: 100rpx;
border: 1px solid transparent;
margin: auto;
background: #1977FF;
color: #fff;
font-size: 16px;
letter-spacing: 2rpx;
border-radius: 1000rpx;
white-space: nowrap;
}
.item_hover{
background-color: rgba(0, 0, 0, .1);
}

+ 73
- 0
wifi_ble_demo/project.config.json Целия файл

@@ -0,0 +1,73 @@
{
"description": "项目配置文件",
"packOptions": {
"ignore": []
},
"setting": {
"urlCheck": true,
"es6": true,
"enhance": true,
"postcss": true,
"preloadBackgroundData": false,
"minified": true,
"newFeature": false,
"coverView": true,
"nodeModules": false,
"autoAudits": false,
"showShadowRootInWxmlPanel": true,
"scopeDataCheck": false,
"uglifyFileName": false,
"checkInvalidKey": true,
"checkSiteMap": true,
"uploadWithSourceMap": true,
"compileHotReLoad": true,
"useMultiFrameRuntime": true,
"useApiHook": true,
"useApiHostProcess": false,
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
},
"enableEngineNative": false,
"bundle": false,
"useIsolateContext": true,
"useCompilerModule": true,
"userConfirmedUseCompilerModuleSwitch": false,
"userConfirmedBundleSwitch": false,
"packNpmManually": false,
"packNpmRelationList": [],
"minifyWXSS": true
},
"compileType": "miniprogram",
"libVersion": "2.16.0",
"appid": "wx17e93aad47cdae1a",
"projectname": "wifi_ble_demo",
"debugOptions": {
"hidedInDevtools": []
},
"scripts": {},
"isGameTourist": false,
"simulatorType": "wechat",
"simulatorPluginLibVersion": {},
"condition": {
"search": {
"list": []
},
"conversation": {
"list": []
},
"game": {
"list": []
},
"plugin": {
"list": []
},
"gamePlugin": {
"list": []
},
"miniprogram": {
"list": []
}
}
}

+ 7
- 0
wifi_ble_demo/sitemap.json Целия файл

@@ -0,0 +1,7 @@
{
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
"rules": [{
"action": "allow",
"page": "*"
}]
}

+ 3315
- 0
wifi_ble_demo/utils/encoding.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 47
- 0
wifi_ble_demo/utils/util.js Целия файл

@@ -0,0 +1,47 @@
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 (!key) {
if (arr[i] == val) {
return i
}
} else if (arr[i][key] === val) {
return i
}
}
return -1;
}

// ArrayBuffer转16进度字符串示例
function ab2hex(buffer, split) {
var hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join(split);
}

const {TextDecoder, TextEncoder} = require('./encoding')

function hex2str(arr) {
let decoder = new TextDecoder('utf8')
let uint8 = new Uint8Array(arr)
let res = decoder.decode(uint8)
return res
}

function str2hex(str) {
let encoder = new TextEncoder('utf8')
return encoder.encode(str)
}

module.exports = {
inArray,
ab2hex,
hex2str,
str2hex,
}

Loading…
Отказ
Запис