推荐另一种配网方式,参见小程序SoftAP配网
下面依然介绍使用sdk的过程
- 引入依赖,在腾讯云注册
- 规划页面
- 开始开发
这里需要注意的是官方demo和我自己在这里集成的,使用真机调试模式都无法配网。
只有点击预览才行,所幸预览可以打开调试,能在这种模式下查看日志及问题。
引入依赖
如果项目中没有用npm,那么先初始化
npm init -y
然后安装airkiss及相关依赖
npm install qcloud-iotexplorer-appdev-sdk
npm install qcloud-iotexplorer-appdev-plugin-wificonf-core
npm install qcloud-iotexplorer-appdev-plugin-wificonf-airkiss
-
初始化sdk
需要在腾讯物联网平台注册账号,添加应用
https://console.cloud.tencent.com/iotexplorer
-
在应用开发中查看相关信息
页面
根据设计,基础页面需求如下:
- 确认配网状态,如指示灯是否在闪烁的提示
- 判断wifi连接状态,填充wifi名称和密码
- 调用配网sdk进行配网操作
- 提示配网成功
{
"path": "pages/configWiFi/tipspage/tipspage",
"style": {
"navigationBarTitleText": "配网提示",
"enablePullDownRefresh": false
}
}, {
"path": "pages/configWiFi/formpage/formpage",
"style": {
"navigationBarTitleText": "获取wifi",
"enablePullDownRefresh": false
}
}, {
"path": "pages/configWiFi/interlinkage/interlinkage",
"style": {
"navigationBarTitleText": "配网",
"enablePullDownRefresh": false
}
}, {
"path": "pages/configWiFi/seccusspage/seccusspage",
"style": {
"navigationBarTitleText": "配网成功",
"enablePullDownRefresh": false
}
}
指示灯提示和成功提示这些基础页面就不在此细说了,都没有繁琐的外部操作。
wifi信息获取页面
先定义在wifi调用过程中的状态码和状态值的对应关系
const errEnum = {
12000: '未先调用 startWifi 接口',
12001: '当前系统不支持相关能力',
12002: '密码错误',
12003: '连接超时, 仅 Android 支持',
12004: '重复连接 Wi-Fi',
12005: 'Android 特有,未打开 Wi-Fi 开关',
12006: 'Android 特有,未打开 GPS 定位开关',
12007: '用户拒绝授权链接 Wi-Fi',
12008: '无效 SSID',
12009: '系统运营商配置拒绝连接 Wi-Fi',
12010: '系统其他错误,需要在 errmsg 打印具体的错误原因',
12011: '应用在后台无法配置 Wi-Fi',
12013: '系统保存的 Wi-Fi 配置过期,建议忘记 Wi-Fi 后重试,仅 Android 支持',
12014: 'iOS 特有,无效的 WEP / WPA 密码'
}
定义要调用的method。
getWifi() {
const $t = this
uni.getConnectedWifi({
success(res) {
$t.form.name = res.wifi.SSID
$t.jinyongs = false
uni.showToast({
title: '已连接wifi网络'
})
},
fail(err) {
let errMsg = ''
if (!err.errCode) {
errMsg = err.errMsg
} else {
errMsg = errEnum[err.errCode]
}
uni.showModal({
content: errMsg,
showCancel: false
});
}
})
},
// 在监听了网络状态变更的同时又监听了`onWifiConnected`,是因为前者在iOS环境下当网络切换为wifi时再调用`uni.getConnectedWifi`会非常慢
onWifiConnected() {
const $t = this
uni.onWifiConnected(res => {
$t.form.name = res.wifi.SSID
uni.showToast({
title: '已连接wifi网络'
})
})
},
onNetworkStatusChange() {
let this_ = this;
uni.onNetworkStatusChange(function(res) {
console.log(res);
if (res.networkType !== 'wifi') {
this_.content = '当前非WiFi网络,请连接2.4G WiFi'
} else {
// this_.getWifi()
}
})
},
在onLoad()
和destroyed()
这两个时机进行环境判断和时间监听的注册
onLoad() {
// 先检查环境,并注册监听
const $t = this
wx.startWifi({
success (res) {
$t.getWifi();
$t.onWifiConnected();
$t.onNetworkStatusChange();
}
})
},
destroyed() {
uni.offNetworkStatusChange()
uni.stopWifi()
},
配网页面
首先引入sdk中相关包,并定义基础函数
const {
AppDevSdk
} = require('qcloud-iotexplorer-appdev-sdk');
const WifiConfConstants = require('qcloud-iotexplorer-appdev-plugin-wificonf-core').constants;
const AirKissPlug = require('qcloud-iotexplorer-appdev-plugin-wificonf-airkiss').default;
const {
// 步骤code
WifiConfStepCode,
// 步骤code的中文描述
WifiConfStepDesp,
// 错误的中文描述
WifiConfErrorMsg,
} = WifiConfConstants;
const onComplete = (deviceInfo) => {
console.log('配网完成(onComplete):', deviceInfo);
uni.showModal({
content: '配网完成',
showCancel: false
});
};
const onError = async ({ code, detail }) => {
const msg = WifiConfErrorMsg[code];
console.log('配网错误(onError)', code, msg, detail);
// uni.showModal({
// content: '配网错误',
// showCancel: false
// });
};
const getAccessToken = async () => {
// 获取小程序登录凭证(code)
const code = await new Promise((resolve, reject) => {
wx.login({
success: (res) => resolve(res.code),
fail: reject
});
});
// 获取小程序用户信息
const userInfo = await new Promise((resolve, reject) => {
wx.getUserInfo({
success: (res) => resolve(res.userInfo),
fail: reject
});
});
// 调用开发者自建的后台服务端获取 AccessToken
// 请根据实际情况调整实现
const resp = await new Promise((resolve, reject) => {
wx.request({
url: '我们自己的后台地址接口',
method: 'POST',
data: {
code: code,
userInfo: userInfo
},
header: {
'content-type': 'application/json'
},
success(res) {
console.log('这里是自己返回的token吧:');
console.log(res, res.data.content);
resolve(res.data.content);
},
fail(err) {
reject(err);
}
});
});
return {
Token: resp,
ExpireAt: 7200,
};
};
基础必要的data定义
targetWifiInfo: {
SSID: '',
password: '',
},
content: '正在配网(请将设备靠近路由器)……',
sdk: {},
回调中
destroyed() {
wx.stopWifi()
},
onLoad(options) {
console.log(options)
const $t = this
// this.wifiName = options.wifiName;
this.targetWifiInfo = {
SSID: options.wifiName,
password: options.pwd
}
// this.setlianjie(options.names)
const sdk = new AppDevSdk({
debug: true,
appKey: 'mZFOqyJJeVCa',
getAccessToken: getAccessToken,
});
sdk.usePlugin(AirKissPlug);
sdk.init()
AirKissPlug.install(sdk);
// sdk.init(options) => Promise<void>
// this.sdk = sdk
// this.airkiss()
wx.startWifi()
sdk.requestApi('AppCreateDeviceBindToken')
.then((data) => {
const bindDeviceToken = data.Token;
this.bindDeviceToken = bindDeviceToken
console.log('wifi设备配网Token=', bindDeviceToken);
sdk.plugins['wifiConfAirKiss'].start({
wifiConfToken: 'bindDeviceToken',
targetWifiInfo: this.targetWifiInfo,
autoRetry: true, // 自动处理故障流程
familyId: 'default',
roomId: '1',
onProgress: $t.onProgress,
onComplete,
onError
});
});
},
method中只定义了onProgress的回调函数,用来更新页面提示
onProgress( val ) {
const msg = WifiConfStepDesp[val.code];
console.log('配网步骤更新_(onProgress)', val.code, msg, val.detail);
switch (val.code) {
case WifiConfStepCode.PROTOCOL_SUCCESS:
this.content = '配网成功'
break;
case WifiConfStepCode.CREATE_UDP_CONNECTION_SUCCESS:
this.content = msg
break;
// case WifiConfStepCode.BUSINESS_QUERY_TOKEN_STATE_SUCCESS:
// this.content = msg
// break;
// case WifiConfStepCode.WIFI_CONF_SUCCESS:
// this.content = msg
// break;
}
},
此处可以判断只要当code为case WifiConfStepCode.PROTOCOL_SUCCESS:
时,即算是配网成功。
虽然后续控制台会进行诸多报错,那是因为sdk中存在一些和腾讯云物联网平台设计的一些验证协议。