智能家居小程序softAP配网和BLE配网功能实现
上一个项目一直在做智能家居的小程序和后台管理系统,现在整理一下其中最关键的配网步骤。
softAP的配网原理
配网流程图:
softAP配网,即利用设备的无线芯片,将设备进入到softAP模式,开启一个无线局域网,手机(或其它移动设备)通过连入设备开启的无线局域网后,向设备发送路由器的ssid及password等信息,让设备在无屏幕的情况下,获取到路由器的ssid信息,达到联网的目的。
上面的流程图简单的画了一下,下面我大概讲一下具体的配网步骤\
配网步骤总共需要4步
智能家居设备需要长按特定的按键进入配网模式,这个时候设备会启动wifi模块释放wifi(不同的设备进入配网的方式不一样)
2. 小程序进入配网界面,输入当前家庭连接的wifi密码,记录家庭wifi的名字和密码(可以直接通过小程序的API直接获取到当前手机连接的wifi名字) 3. 手机进行网络切换,连接设备释放的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就不往上放了。
BLE配网功能
BLE配网就是低功耗蓝牙配网
// 获取当前设备信息 getSystemInfo() { var that = this; wx.getSystemInfo({ success: function (res) { console.log(res, "获取当前设备信息"); that.setData({ windowHeight: res.windowHeight, }); }, }); }, // 初始化蓝牙模块 openBluetooth() { var that = this; wx.openBluetoothAdapter({ success: function (res) { console.log("初始化蓝牙适配器成功" + JSON.stringify(res)); that.setData({ msg: "初始化蓝牙适配器成功", }); wx.showModal({ title: "蓝牙适配情况", content: "初始化蓝牙适配器成功", }); }, fail() { that.setData({ msg: "初始化蓝牙适配器失败", }); wx.showModal({ title: "蓝牙适配情况", content: "蓝牙适配失败,请检查手机蓝牙和定位功能是否打开", }); }, complete() { console.log("初始化蓝牙适配器完成"); }, }); }, // 开启蓝牙设备搜索 switchChange() { var that = this; if (!that.data.searchDevice) { that.setData({ searchDevice: !that.data.searchDevice, }); console.log("打开蓝牙设备搜索"); wx.getBluetoothAdapterState({ success(res) { console.log("getBluetoothAdapterState", res); }, }); wx.onBluetoothAdapterStateChange(function (res) { console.log("onBluetoothAdapterStateChange", res.available); }); wx.startBluetoothDevicesDiscovery({ success(res) { console.log("startBluetoothDevicesDiscovery", res); }, }); wx.onBluetoothDeviceFound(function (devices) { console.error(devices, "devices"); if (!devices.devices[0]) return; let result = that.data.deviceList.some((item) => { console.log(item, "item"); if (item.deviceId === devices.devices[0].deviceId) return true; }); if (!result) { that.setData({ deviceList: [...that.data.deviceList, devices.devices[0]], }); } // console.log('onBluetoothDeviceFound', that.data.deviceList) }); wx.getBluetoothDevices({ success(res) { console.log("getBluetoothDevices", res); }, }); } else { // that.deviceList = [] // that.currentDevice = {} wx.stopBluetoothDevicesDiscovery({ success(res) { that.setData({ searchDevice: !that.data.searchDevice, }); console.log("关闭蓝牙设备搜索", res); }, }); } }, // 点击蓝牙设备 chooseDevice(event) { console.log(event.currentTarget.dataset.item, "item"); var that = this; that.setData({ currentDevice: event.currentTarget.dataset.item, nowDevice: true, }); wx.pageScrollTo({ scrollTop: that.data.windowHeight, duration: 100, }); }, // confirmConnect(event) { console.log(event.currentTarget, "aaaaaa"); var that = this; wx.showModal({ title: "连接当前蓝牙设备", success(res) { if (res.confirm) { that.connectTo(event.currentTarget.dataset.deviceid); } else if (res.cancel) { console.log("用户点击取消"); } }, }); }, // connectTo(deviceId) { var that = this; console.log("连接蓝牙设备搜索", deviceId); wx.stopBluetoothDevicesDiscovery({ success(res) { console.log("关闭蓝牙设备搜索", res); that.setData({ searchDevice: !that.data.searchDevice, }); }, }); wx.showLoading({ title: "连接蓝牙设备中...", }); wx.createBLEConnection({ deviceId: deviceId, success(res) { console.log("蓝牙设备连接成功", res); wx.hideLoading(); wx.getBLEDeviceServices({ deviceId: deviceId, success(res) { that.setData({ deviceService: res.services, }); for (var t = 0; t < that.data.deviceService.length; t++) { var service = that.data.deviceService[t]; var serviceId = service.uuid.substring(4, 8); console.log(service.uuid, "serviceId1111111"); if (serviceId === "FFE0") { that.setData({ serviceId: service.uuid, }); } } that.setData({ nowDevice: !that.nowDevice, nowService: !that.nowService, }); console.log("获取蓝牙设备Service" + res.errMsg); }, fail(res) { wx.showModal({ title: "设备Service信息", content: "蓝牙设备连接成功" + "\n" + "设备信息获取错误" + res.errMsg, }); }, }); }, fail(res) { console.log("蓝牙设备连接失败,请稍后重试"); wx.hideLoading(); wx.showModal({ title: "提示", content: "蓝牙设备连接失败,请稍后重试", duration: 2000, }); }, complete() { console.log("蓝牙设备连接完成"); wx.hideLoading(); }, }); }, // 发送数据 sendMessage() { let that = this; console.log(that.data.sendData); let data = that.data.sendData.split(","); let dataBuffer = new ArrayBuffer(data.length); let dataView = new DataView(dataBuffer); for (let j = 0; j < data.length; j++) { dataView.setUint8(j, "0x" + data[j]); } that.setData({ deviceId: that.data.currentDevice.deviceId, }); console.log(that.data.serviceId, "serviceId"); console.log(that.data.deviceId, "deviceId"); wx.getBLEDeviceCharacteristics({ deviceId: that.data.deviceId, serviceId: that.data.serviceId, success(res) { console.log(res.characteristics); that.deviceCharacteristics = res.characteristics; for (var i = 0; i < that.deviceCharacteristics.length; i++) { that.characteristic = that.deviceCharacteristics[i]; that.characteristicProperties = that.characteristic.properties; if (that.characteristicProperties.notify === true) { that.characteristicId = that.characteristic.uuid; wx.notifyBLECharacteristicValueChange({ state: true, // 启用 notify 功能 deviceId: that.deviceId, serviceId: that.serviceId, characteristicId: that.characteristicId, success(res) { console.log("开启notify成功" + that.characteristic.uuid); for (let i = 0; i < dataView.byteLength; i++) { var writeData = "0x" + dataView.getUint8(i).toString(16); that.writeDatas = that.writeDatas + "\n" + writeData; } wx.writeBLECharacteristicValue({ deviceId: that.deviceId, serviceId: that.serviceId, characteristicId: that.characteristicId, value: dataBuffer, success(res) { console.log("发送的数据:" + that.writeDatas); console.log("message发送成功"); wx.showModal({ title: "数据发送成功", content: that.writeDatas, }); wx.readBLECharacteristicValue({ deviceId: that.deviceId, serviceId: that.serviceId, characteristicId: that.characteristicId, success(res) { console.log("读取数据成功"); }, }); }, fail(res) { // fail console.log("message发送失败" + that.characteristicIdw); wx.showToast({ title: "数据发送失败,请稍后重试", icon: "none", }); }, complete(res) { // fail console.log("message发送完成"); }, }); }, fail() { console.log("开启notify失败" + that.characteristicId); }, }); // that.writeMessage(that.deviceId, that.serviceId, that.characteristicIdw, that.characteristicIdr, that.characteristicIdn) } } }, fail() { console.log("获取characteristic失败"); }, }); that.writeDatas = []; }, receiveMessage() { let that = this; that.deviceId = this.currentDevice.deviceId; that.serviceId = that.serviceId; wx.getBLEDeviceCharacteristics({ deviceId: that.deviceId, serviceId: that.serviceId, success(res) { console.log(res.characteristics); that.deviceCharacteristics = res.characteristics; for (var i = 0; i < that.deviceCharacteristics.length; i++) { that.characteristic = that.deviceCharacteristics[i]; that.characteristicProperties = that.characteristic.properties; if (that.characteristicProperties.notify === true) { that.characteristicId = that.characteristic.uuid; wx.notifyBLECharacteristicValueChange({ state: true, // 启用 notify 功能 deviceId: that.deviceId, serviceId: that.serviceId, characteristicId: that.characteristicId, success(res) { console.log("开启notify成功" + that.characteristic.uuid); console.log(that.characteristicProperties.write); console.log(that.characteristicProperties.read); wx.readBLECharacteristicValue({ deviceId: that.deviceId, serviceId: that.serviceId, characteristicId: that.characteristicId, success(res) { console.log("接收数据成功"); }, }); wx.onBLECharacteristicValueChange(function (res) { console.log("接收数据:", that.ab2hex(res.value)); var recMessage = that.ab2hex(res.value); that.reMessage.push(recMessage); }); }, fail() { console.log("开启notify失败" + that.characteristicId); console.log(that.characteristicProperties.write); console.log(that.characteristicProperties.read); }, complete() { console.log("开启完成"); }, }); } } }, fail() { console.log("获取characteristic失败"); }, }); }, disconnect() { var that = this; that.setData({ deviceId: that.data.currentDevice.deviceId, }); wx.closeBLEConnection({ deviceId: that.data.deviceId, success(res) { wx.showModal({ title: "设备连接情况", content: "蓝牙设备已经断开", }); that.setData({ nowDevice: false, currentDevice: {}, nowService: false, deviceService: {}, }); }, }); }, ab2hex(buffer) { var hexArr = Array.prototype.map.call( new Uint8Array(buffer), function (bit) { return ("00" + bit.toString(16)).slice(-2); } ); return hexArr.join(""); }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { console.log(this.data.deviceList, "deviceList"); this.getSystemInfo(); this.openBluetooth(); }, /** * 生命周期函数--监听页面显示 */ onShow: function () { var that = this; // 监听蓝牙适配器状态变化事件 wx.onBluetoothAdapterStateChange(function (res) { console.log(`蓝牙设备状态更改`, res.available); that.openBluetooth(); }); },
作者:王小辉
链接:https://juejin.cn/post/7020596289146454047