上一个项目一直在做智能家居的小程序和后台管理系统,现在整理一下其中最关键的配网步骤。
softAP的配网原理
配网流程图:
softAP配网,即利用设备的无线芯片,将设备进入到softAP模式,开启一个无线局域网,手机(或其它移动设备)通过连入设备开启的无线局域网后,向设备发送路由器的ssid及password等信息,让设备在无屏幕的情况下,获取到路由器的ssid信息,达到联网的目的。 上面的流程图简单的画了一下,下面我大概讲一下具体的配网步骤\
配网步骤总共需要4步
- 智能家居设备需要长按特定的按键进入配网模式,这个时候设备会启动wifi模块释放wifi(不同的设备进入配网的方式不一样)
- 小程序进入配网界面,输入当前家庭连接的wifi密码,记录家庭wifi的名字和密码(可以直接通过小程序的API直接获取到当前手机连接的wifi名字)
- 手机进行网络切换,连接设备释放的wifi,然后进行UDP通信,把wifi名字和密码发送给设备端,设备端通过名字密码连接家庭wifi和服务器进行通信(UDP通信发送名字密码可以做自定义的加密处理降低抓包风险)
4.小程序通过调服务器接口查询智能设备是否配网成功(查询参数加密MD5、设备devId、userId)
softAP实现的代码
// 配网
async getDevice() {
let that = this;
this.setData({
isOnload: false
})
wx.showToast({
title: '配网时长在1-2分钟,请耐心等待!',
icon: 'none',
duration: 2000
})
setTimeout(() => {
wx.showLoading({
title: '配网中',
})
}, 2000)
// 开始配网
let ASCIIStr = `${String.fromCharCode(util.prefixInteger(that.data.SSID.length, 2))}${that.data.SSID}${String.fromCharCode(util.prefixInteger(that.data.password.length, 2))}${that.data.password}`
let ASCIIStrMi = 0;
for (var i = ASCIIStr.length - 1; i >= 0; i--) {
var str = ASCIIStr.charAt(i);
var code = str.charCodeAt();
ASCIIStrMi += code;
}
that.UDPSocketHandler = wx.createUDPSocket(),
that.UDPSocketHandler.bind();
var times = setInterval(() => {
try {
that.UDPSocketHandler.send({
address: "10.10.100.000",
port: 12414,
message: `${ASCIIStr}${String.fromCharCode(ASCIIStrMi % 256)}`,
offset: 0,
// length: message.byteLength
})
} catch (e) { }
}, 1000); //1000:每1秒轮询一次
that.UDPSocketHandler.onListening(function (res) {
console.log(res, '监听中...')
})
that.UDPSocketHandler.onMessage(function (res) {
let str = util.newAb2Str(res.message);
that.setData({
udpCode: str.replace("RECVDONE", "")
});
console.log('str===' + str)
if (str.indexOf("RECVDONE") !== -1) {
clearInterval(times);
that.UDPSocketHandler.close();
that.distributionNetwork();
console.log('RECVDONE !== 1','配网中');
}
})
that.UDPSocketHandler.onError(function (res) {
console.log(res, 'error');
})
},
getuserDev(index) {
let that = this;
if (index > 19) {
wx.hideLoading();
wx.showToast({
title: '配网超时',
icon: 'none',
duration: 2000
});
return;
}
index++;
let md5Str = md5.md5(`${that.data.SSID}${that.data.password}${that.data.udpCode}`)
let data = {
userId: app.globalData.unionId,
wifiMd5: md5Str,
devId: that.data.udpCode,
}
console.log("配网",data)
global.api.devNetwork(data).then(res => {
console.log("res", res);
if (res.code == 200 && res.rows !== null) {
clearInterval(that.data._time);
wx.hideLoading();
wx.showToast({
title: '配网成功',
icon: 'none',
duration: 2000
});
wx.navigateTo({
url: '/xxxx/xxxx/xxxx/xxxx/xxxxxx/index?data=' + JSON.stringify(res.rows) + '&equipment=' + that.data.equipment + '&ps=' + that.data.ps,
});
} else {
setTimeout(() => {
that.getuserDev(index);
}, 5000)
}
})
.catch(err => {
setTimeout(() => {
that.getuserDev(index);
}, 5000)
})
},
distributionNetwork() {
var that = this;
wx.showLoading({
title: '配网中',
});
that.getuserDev(0);
},
上面这部分只是具体的逻辑实现,像调用的小程序获取wifi信息的API就不往上放了。