ESA2GJK1DH1K微信小程序篇: 測試微信小程序APUConfig給WI-Fi模塊配網並綁定設備,並經過MQTT控制設備

 

 

 

前言(源碼在最後)

  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次,還沒綁定上
        {
            try { clearInterval(APUConfigSendUDPDataIntervalNumber); } catch (e) { }
          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; 
}

 

 

 

 

 

util.js
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;
}

 

 

綁定成功後跳轉

 

 

 

 

 

 

知識在於靈活的運用!!!!!

相關文章
相關標籤/搜索