zoukankan      html  css  js  c++  java
  • ESA2GJK1DH1K微信小程序篇: 微信小程序APUConfig给WI-Fi模块配网并绑定设备,并通过MQTT控制设备(单片机AT指令版 V0.1)

    前言(源码使用介绍在最后)

      

      一,微信小程序篇小程序下载(该源码为这节测试源代码)

      

      二.有多少人一直在期盼着小程序可以实现SmartConfig或者Airkiss的功能? 来吧!我的这种方式包您满意.

        注:APUConfig 是我自己取的名字(哈哈谁让这种方式,我是第一个在微信小程序上实现的),代表着 AP  UDP  Config

        绑定流程详细说明:

        APUConfig小程序端源码

              https://gitee.com/yang456/APUConfig.git

        

    实现功能概要

      1.小程序使用APUConfig给Wi-Fi模块配网,并获取设备MAC等信息,然后通过MQTT控制绑定的Wi-Fi设备.

      2.演示视频:  https://www.bilibili.com/video/av74786875/

    测试准备工作

    一,下载单片机程序(请自行下载)

      

     二,打开微信小程序软件,导入本节工程

      

      

    三,把小程序安装到手机运行

      

     四,调整波动开关位置,STM32和Wi-Fi 串口 通信

      

    五,短接STM32的PB2和Wi-Fi模块的RST引脚(内部程序使用该引脚硬件复位Wi-Fi)

      

    开始测试

    一,点击小程序下方的添加设备按钮 

      

    二,选择添加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 控制继电器断开

          

    结语

    希望能够为在用小程序做物联网开发的大家解决当前最大的烦心事!

    知识是死的,人是活的!

    希望大家不仅要有超强的学习能力,还需要有灵活运用知识的能力.

    现在想想我挺感谢我的高中班主任 (朱兆同老师),是他让我开始了自学生涯,培养了这种能力.

    师者,传道受业解惑者也.   传道:应该是首当其冲的吧!

    绑定部分小程序端源码

    https://gitee.com/yang456/APUConfig.git   (下载最新版本请在git下载)

    小程序端APUConfig源码:

    APUConfig.js

    // pages/APUConfig/APUConfig.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_bind",
            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 () {
    
      }
    })
    View Code

     APUConfig.json

    {
      "usingComponents": {}
    }

    APUConfig.wxml

    <!--pages/APUConfig/APUConfig.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>
    View Code

     APUConfig.WXSS

    /* pages/APUConfig/APUConfig.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; 
      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 { 
      100%; 
     height: 1px; 
     background-color: #cccccc; 
     margin-top: 1px; 
    } 
    /*按钮*/
    .BindClickView { 
      100%; 
     height: auto; 
     background-color: #f2f2f2; 
     margin-top: 0px; 
     margin-bottom: 0px; 
     padding-bottom: 0px; 
    } 
      
    .BindClick { 
      95%; 
     margin-top: 35px; 
    }
    View Code
    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
    }
    View Code

    单片机端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
    ","ready",NULL))//恢复出厂设置
            {
                if(ConfigModuleBlock("AT+CWMODE_DEF=3
    ","OK",NULL))//模式3
                {
                    if(ConfigModuleBlock("AT+CIPSTAMAC_CUR?
    ","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
    ","OK",NULL))//配置发出的无线
                        {
                            if(ConfigModuleBlock("AT+CIPSTART="UDP","192.168.4.2",5555,5556,2
    ","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
    ","OK",NULL))//自动连接路由器
                                {
                                    memset(MainBuffer,0,sizeof(MainBuffer));
                                    sprintf(MainBuffer,"AT+CWJAP_DEF="%s","%s"
    ",ThisSSID,ThisPWD);
                                    if(ConfigModuleBlock(MainBuffer,"WIFI GOT IP",NULL))//设置连接的路由器
                                    {
                                        Flage = 1;//配网成功
                                        SmartConfigSuccess=1;
                                        
                                        if(ConfigModuleBlock("AT+CIPSTA_CUR?
    ","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
    ",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
    ","OK",NULL))//模式1
        {}
        Rst8266();//复位
        SmartConfigFlage = 0;
        return Flage;
    }
    View Code

    1.把文件导入工程

         

    2.请在util.js添加如下代码

      

    使用
    1.跳转到 APUConfig 函数,请在自己需要的地方自行填写

      

    2.绑定完成,跳转到的页面(请根据自己的设置跳转路径)

      

    3.在跳转的页面获取绑定的数据

      

  • 相关阅读:
    EMQTT测试--安装与测试 (windows)
    phpStudy本地搭建wordpress教程
    windows下9款一键快速搭建PHP本地运行环境的好工具(含php7.0环境)
    mysql允许外网访问 和修改mysql 账号密码
    mysql sql常用语句
    Mysql(MyISAM和InnoDB)及Btree和索引优化
    Python 有关网址
    Python 字典(Dictionary)操作详解
    pandas读取xlsx
    Python 学习笔记 (变量与数据类型)
  • 原文地址:https://www.cnblogs.com/yangfengwu/p/11796072.html
Copyright © 2011-2022 走看看