1.有多少人一直在期盼着小程序能夠實現SmartConfig或者Airkiss的功能? 來吧!個人這種方式包您滿意.html
注:APUConfig 是我本身取的名字(哈哈誰讓這種方式,我是第一個在微信小程序上實現的),表明着 AP UDP Configjson
綁定流程詳細說明:小程序
小程序使用APUConfig給Wi-Fi模塊配網,並獲取設備MAC等信息,而後經過MQTT控制綁定的Wi-Fi設備.微信小程序
一,下載單片機程序(請自行下載)微信
二,打開微信小程序軟件,導入本節工程網絡
三,把小程序安裝到手機運行app
四,調整波動開關位置,STM32和Wi-Fi 串口 通訊xss
五,短接STM32的PB2和Wi-Fi模塊的RST引腳(內部程序使用該引腳硬件復位Wi-Fi)ide
一,點擊小程序下方的添加設備按鈕 函數
二,選擇添加Wi-Fi設備
三,輸入路由器密碼(注:Wi-Fi名稱自動獲取,也可本身填寫)
四.長按PB5大約4S,等待指示燈快閃,鬆開PB5,Wi-Fi模塊進入配網狀態
五.點擊小程序上的 "綁定設備"按鈕,開始搜索設備,綁定成功,將自動跳轉到主頁面,顯示綁定的Wi-Fi設備
5.1 正在嘗試鏈接Wi-Fi模塊的熱點
5.2 鏈接上熱點,正在和模塊通訊
5.3 成功綁定設備
六.點擊設備,進入控制頁面,控制設備
6.1 點擊設備
6.2 控制繼電器吸合
6.2 控制繼電器斷開
但願可以爲用小程序作物聯網開發的你們解決當前最大的煩心事!
小程序端APUConfig源碼:
.js
// pages/BindWiFiDevice/BindWiFiDevice.js var util = require("../../utils/util.js"); var APUConfigStart = false;//是否在配網 var APUConfigconnectAPCount = 0;//鏈接熱點的次數 var APUConfigSendUDPDataIntervalNumber = 0;//發送UDP數據的定時器編號 var APUConfigSendUDPDataCount = 0;//發送UDP數據的次數 var udp; Page({ /** * 頁面的初始數據 */ data: { ssid: '', password: '' }, // 獲取路由器名稱 ssidInput: function (e) { this.data.ssid = e.detail.value; }, // 獲取輸入密碼 passwordInput: function (e) { this.data.password = e.detail.value; }, /** * 成功鏈接熱點 */ connectWifiSuccess: function(res) { var _this = this; udp = wx.createUDPSocket()//啓用UDP udp.bind() wx.hideLoading(); wx.showLoading({ title: '正在綁定' }) udp.onListening(function (res) { console.log('監聽中...') console.log(res) }) //定時1S發送一次UDP數據 try { clearInterval(APUConfigSendUDPDataIntervalNumber); } catch (e) { } APUConfigSendUDPDataIntervalNumber = setInterval( function () { udp.send ({ address: '192.168.4.1', port: 5556, message: "{\"ssid\":" + "\"" + _this.data.ssid + "\"" + "\"pwd\":" + "\"" + _this.data.password + "\"" + "}" }) APUConfigSendUDPDataCount = APUConfigSendUDPDataCount + 1; console.log('發送數據: ' + "{\"ssid\":" + "\"" + _this.data.ssid + "\"" + "\"pwd\":" + "\"" + _this.data.password + "\"" + "}"); if (APUConfigSendUDPDataCount>20)//發送了20次,還沒綁定上 {
APUConfigSendUDPDataCount = 0; APUConfigconnectAPCount = 0; APUConfigStart = false;// udp.close(); wx.hideLoading(); wx.showModal({//彈出對話框 title: '綁定失敗', content: '請從新嘗試' }) } }, 1000, "null");//啓動定時器 //UDP接收到消息 udp.onMessage(function (res) { console.log(res) let str = util.newAb2Str(res.message);//接收消息 console.log('str===' + str) //{ "mac": "dc:4f:22:10:b0:ce", "ip": "192.168.0.101" } try { clearInterval(APUConfigSendUDPDataIntervalNumber); } catch (e) { } try { udp.close(); } catch (e) { }//關閉UDP APUConfigSendUDPDataCount = 0; APUConfigconnectAPCount = 0; APUConfigStart = false;//復位全部變量 wx.hideLoading();//關閉提示框 if (str!=null) { let json = JSON.parse(str);//解析JSON數據 if (json != null) { let mac = json.mac; let ip = json.ip; if (mac != null) { wx.reLaunch({ url: '../index/index?ClientID=' + mac + "&" + "IP=" + ip }) } } } }) }, /** * 鏈接無線失敗 */ connectWifiFail: function (res) { var _this = this; if (APUConfigconnectAPCount<6)//嘗試鏈接熱點的次數 { APUConfigconnectAPCount = APUConfigconnectAPCount + 1; console.log('鏈接Wi-Fi: wifi_8266_bind'); wx.connectWifi//控制鏈接Wi-Fi無線信號 ({ SSID: "wifi_8266_bind", password: "11223344", success: _this.connectWifiSuccess, fail: _this.connectWifiFail }) } else { APUConfigconnectAPCount = 0; APUConfigStart = false;// wx.hideLoading(); wx.showModal({//彈出對話框 title: '綁定失敗', content: '請從新嘗試' }) } }, //點擊綁定按鈕 BindClick: function () { var _this = this; if (_this.data.ssid.length == 0 || _this.data.password.length == 0) { wx.showModal({//彈出對話框 title: '提示', content: 'Wi-Fi名稱和密碼不能爲空' }) } else { APUConfigStart = true;//開始配網 //控制鏈接Wi-Fi無線信號 wx.connectWifi ({ SSID: "wifi_8266_qqqqq_binding", password: "11223344", success: _this.connectWifiSuccess, fail: _this.connectWifiFail }) } }, /** * 生命週期函數--監聽頁面加載 */ onLoad: function (options) { var _this = this; _this.GetWiFiSSID();//顯示當前鏈接的Wi-Fi名稱 //啓動網絡狀態監聽 wx.onNetworkStatusChange(function (res) { console.log("綁定設備:網絡改變" + res.isConnected + " " + res.networkType); if (res.networkType == "wifi")//當前鏈接的網絡類型是WIFI { console.log("綁定設備:當前鏈接的網絡類型是WIFI"); if (!APUConfigStart)//沒在配網狀態 { _this.GetWiFiSSID(); } } else//其它網絡 { if (!APUConfigStart)//沒在配網狀態 { _this.setData({//清空顯示的wifi名稱 ssidValue: "" }) } } }) }, /** * 獲取連接的WIFI名稱 */ GetWiFiSSID: function () { var _this = this; wx.startWifi({//啓用WIFI功能 success(res) { wx.getConnectedWifi//獲取連接的Wi-Fi信息 ({ success(res) //獲取到信息 { _this.data.ssid = res.wifi.SSID; console.log("綁定設備:鏈接的Wi-Fi名稱 " + _this.data.ssid); _this.setData({ ssidValue: _this.data.ssid }) }, fail(res) { } }) } }) }, /** * 生命週期函數--監聽頁面顯示 */ onShow: function () { this.GetWiFiSSID();//顯示當前鏈接的Wi-Fi名稱 }, /** * 生命週期函數--監聽頁面卸載 */ onUnload: function () { try { clearInterval(APUConfigSendUDPDataIntervalNumber); } catch (e) { } try { udp.close(); } catch (e) { } APUConfigSendUDPDataCount = 0; APUConfigconnectAPCount = 0; APUConfigStart = false;// wx.hideLoading(); }, /** * 生命週期函數--監聽頁面隱藏 */ onHide: function () { }, /** * 頁面相關事件處理函數--監聽用戶下拉動做 */ onPullDownRefresh: function () { }, /** * 頁面上拉觸底事件的處理函數 */ onReachBottom: function () { }, /** * 用戶點擊右上角分享 */ onShareAppMessage: function () { } })
.json
{ "usingComponents": {} }
.wxml
<!--pages/BindWiFiDevice/BindWiFiDevice.wxml--> <view class="container"> <!--提示--> <view class="hint"> <text style="color: #545454; font-size:35rpx;">綁定設備前請肯定完成如下步驟</text> <view> <text style="color:#09bb07; font-size:35rpx;">①</text> <text style="font-size:35rpx;" space='nbsp'> 請先鏈接自家路由器熱點</text> </view> <view> <text style="color:#09bb07; font-size:35rpx;">②</text> <text style="font-size:35rpx;" space='nbsp'> 給設備上電</text> </view> <view> <text style="color:#09bb07; font-size:35rpx;">③</text> <text style="font-size:35rpx;" space='nbsp'> 長按"配置按鍵"大約3S,直至指示燈快閃</text> </view> <view> <text style="color:#09bb07; font-size:35rpx;">④</text> <text style="font-size:35rpx;" space='nbsp'> 輸入路由器密碼,點擊「添加設備」按鈕</text> </view> <view> <text style="color:#09bb07; font-size:35rpx;" >⑥</text> <text style="font-size:35rpx;" space='nbsp'> 綁定成功後,軟件自動跳轉到設備頁面</text> </view> </view> <view class="login-from"> <!--WiFi名稱--> <view class="inputView"> <label class="loginLab">WiFi名稱:</label> <input class="inputText" placeholder="請輸入路由器熱點" bindinput="ssidInput" value="{{ssidValue}}"/> </view> <view class="line"></view> <!--WiFi密碼--> <view class="inputView"> <label class="loginLab">WiFi密碼:</label> <input class="inputText" placeholder="請輸入密碼" bindinput="passwordInput"/> </view> <!--按鈕--> <view class="BindClickView"> <button class="BindClick" type="primary" bindtap="BindClick">綁定設備</button> </view> </view> </view>
.WXSS
/* pages/BindWiFiDevice/BindWiFiDevice.wxss */ page{ height: 100%; } .container { height: 100%; display: flex; flex-direction: column; padding: 0; box-sizing: border-box; background-color: #f2f2f2 } /*提示信息*/ .hint { display: flex; flex-direction: column; margin-top: 10rpx } /*表單內容*/ .login-from { margin-top: 50px; width: 90%; flex: auto; height:100%; } .inputView { display: flex; flex-direction: row; background-color: #fff; } /*Wi-Fi名稱和密碼兩個字*/ .loginLab { margin-left: 10px; margin-top: 15px; margin-bottom: 15px; color: #545454; font-size: 16px } .inputText { margin-left: 10px; text-align: left; margin-top: 15px; color: black; font-size: 16px } .line { width: 100%; height: 1px; background-color: #cccccc; margin-top: 1px; } /*按鈕*/ .BindClickView { width: 100%; height: auto; background-color: #f2f2f2; margin-top: 0px; margin-bottom: 0px; padding-bottom: 0px; } .BindClick { width: 95%; margin-top: 35px; }
const formatTime = date => { const year = date.getFullYear() const month = date.getMonth() + 1 const day = date.getDate() const hour = date.getHours() const minute = date.getMinutes() const second = date.getSeconds() return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') } const formatNumber = n => { n = n.toString() return n[1] ? n : '0' + n } // util.newAb2Str代碼 var newAb2Str = function newAb2Str(arrayBuffer) { let unit8Arr = new Uint8Array(arrayBuffer); let encodedString = String.fromCharCode.apply(null, unit8Arr), decodedString = decodeURIComponent(escape((encodedString)));//沒有這一步中文會亂碼 return decodedString; } module.exports = { formatTime: formatTime, newAb2Str: newAb2Str }
單片機端APUConfig,Wi-Fi配置流程
/** ****************************************************************************** * @author yang feng wu * @version V1.0.0 * @date 2019/10/12 * @brief 配置8266 ****************************************************************************** 一,使用說明:指示燈(PC13) 1,把如下程序放在1ms定時器中斷中 SmartConfigCnt++; if(SmartConfigFlage)//配網狀態,指示燈閃耀 { Config8266LedDelay++; if(Config8266LedDelay>100) { Config8266LedDelay=0; SmartConfigPinOut = ~SmartConfigPinOut; } } else { Config8266LedDelay=0; } 2,調用使用,建議使用一個按鈕控制 if(SmartConfig())//配網成功 { //執行操做 } ****************************************************************************** APUConfig配網綁定流程 設備端 1.獲取設備MAC XX:XX:XX:XX:XX:XX 2.控制WIFI發出固定無線網 名稱:wifi_8266_bind 密碼:11223344 3.UDP 監聽固定端口5556 4.等待接收客戶端的消息. 消息格式{"ssid":"qqqqq","pwd":"11223344"} 5.提取路由器名稱和密碼,鏈接路由器 6.獲取連接路由器後分的的IP. 假設是192.168.10.2 以防後期實現局域網通訊備用 7.UDP發送數據,{"mac":"XX:XX:XX:XX:XX:XX","ip":"192.168.10.2"} APP/小程序/上位機 1.提示用戶鏈接本身的路由器,長按設備按鈕使得設備進入UDP監聽狀態,提示用戶輸入路由器密碼 2.用戶點擊綁定設備 , 控制手機嘗試鏈接 名稱爲 wifi_8266_bind 的無線 (內部控制) 3.成功鏈接無線,往192.168.4.1:5556 UDP發送路由器信息,1S 1次 4.接收到 {"mac":"XX:XX:XX:XX:XX:XX","ip":"192.168.10.2"} 5.綁定成功 8.完 */ #define CONFIG8266_C_ #include "include.h" char SmartConfigFlage = 0;//是否是在配網 u32 SmartConfigCnt = 0;//配網鏈接路由器延時使用 char SmartConfigSuccess = 0;//是否配網成功 u32 Config8266Delay=0;//執行Config8266函數內部所需延時 u32 Config8266LedDelay=0;//配置8266指示燈閃耀 char ThisSSID[32]="";//記錄路由器名稱 char ThisPWD[64]="";//記錄密碼 char ThisMAC[18]="";//記錄設備MAC char ThisIP[21]="";//記錄設備鏈接路由器分得的IP /** * @brief 啓用APUConfig 給WIFI配網 * @ warn None * @param None * @param None * @param None * @param None * @retval 1:成功 * @example **/ char APUConfig(void) { u32 delay=0,Flage=0; SmartConfigPinOut = 1; SmartConfigSuccess = 0; Rst8266(); if(ConfigModuleBlock("+++","+++",NULL))//退出透傳 { if(ConfigModuleBlock("AT+RESTORE\r\n","ready",NULL))//恢復出廠設置 { if(ConfigModuleBlock("AT+CWMODE_DEF=3\r\n","OK",NULL))//模式3 { if(ConfigModuleBlock("AT+CIPSTAMAC_CUR?\r\n","MAC_CUR",NULL))//MAC { MainString = StrBetwString(Usart1ReadBuff,"MAC_CUR:\"","\"");//獲得MAC if(strlen(MainString) ==17) { memset(ThisMAC,0,sizeof(ThisMAC)); memcpy(ThisMAC,MainString,17); } else {goto end;} cStringRestore(); if(ConfigModuleBlock("AT+CWSAP_DEF=\"wifi_8266_bind\",\"11223344\",11,4,4\r\n","OK",NULL))//配置發出的無線 { if(ConfigModuleBlock("AT+CIPSTART=\"UDP\",\"192.168.4.2\",5555,5556,2\r\n","OK",NULL))//配置UDP { SmartConfigCnt = 0; while(1) { //{"ssid":"qqqqq","pwd":"11223344"} //{"mac":"XX:XX:XX:XX:XX:XX","ip":"192.168.10.2"} //*StrBetwString(char *Str,char *StrBegin,char *StrEnd) IWDG_Feed();//喂狗 if(Usart1ReadFlage==1) { Usart1ReadFlage=0; MainString = StrBetwString(Usart1ReadBuff,"\"ssid\":\"","\"");//獲取ssid if(MainString!=NULL) { memset(ThisSSID,0,sizeof(ThisSSID)); sprintf(ThisSSID,"%s",MainString); cStringRestore(); MainString = StrBetwString(Usart1ReadBuff,"\"pwd\":\"","\"");//獲取pwd if(MainString!=NULL) { memset(ThisPWD,0,sizeof(ThisPWD)); sprintf(ThisPWD,"%s",MainString); cStringRestore(); break; } else {goto end;} } else {goto end;} } if(SmartConfigCnt>60000) {goto end;}//60S超時 } if(ConfigModuleBlock("AT+CWAUTOCONN=1\r\n","OK",NULL))//自動鏈接路由器 { memset(MainBuffer,0,sizeof(MainBuffer)); sprintf(MainBuffer,"AT+CWJAP_DEF=\"%s\",\"%s\"\r\n",ThisSSID,ThisPWD); if(ConfigModuleBlock(MainBuffer,"WIFI GOT IP",NULL))//設置鏈接的路由器 { Flage = 1;//配網成功 SmartConfigSuccess=1; if(ConfigModuleBlock("AT+CIPSTA_CUR?\r\n","CIPSTA_CUR:ip",NULL))//獲取路由器分得的IP { MainString = StrBetwString(Usart1ReadBuff,"CUR:ip:\"","\"");//獲得路由器分得的IP if(MainString != NULL) { memset(ThisIP,0,sizeof(ThisIP)); memcpy(ThisIP,MainString,strlen(MainString)); split(MainString,".",NULL,&MainLen);//XXX.XXX.XXX.XXX if(MainLen == 4) { MainLen = sprintf(MainBuffer,"{\"mac\":\"%s\",\"ip\":\"%s\"}",ThisMAC,ThisIP); MainLen = sprintf(MainBuffer,"AT+CIPSEND=%d\r\n",MainLen); if(ConfigModuleBlock(MainBuffer,">",NULL))//準備向UDP客戶端發送消息 { memset(MainBuffer,0,sizeof(MainBuffer)); MainLen = sprintf(MainBuffer,"{\"mac\":\"%s\",\"ip\":\"%s\"}",ThisMAC,ThisIP); printf("%s",MainBuffer); SmartConfigCnt = 0; while(SmartConfigCnt<3000) { IWDG_Feed();//喂狗 } }else {goto end;} }else {goto end;} }else {goto end;} cStringRestore(); } } } } } } } } } end: if(ConfigModuleBlock("AT+CWMODE_DEF=1\r\n","OK",NULL))//模式1 {} Rst8266();//復位 SmartConfigFlage = 0; return Flage; }
綁定成功後跳轉
知識在於靈活的運用!!!!!