前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ESA2GJK1DH1K微信小程序篇: 测试微信小程序APUConfig给WI-Fi模块配网并绑定设备,并通过MQTT控制设备

ESA2GJK1DH1K微信小程序篇: 测试微信小程序APUConfig给WI-Fi模块配网并绑定设备,并通过MQTT控制设备

作者头像
杨奉武
发布2019-11-05 16:56:23
1.1K0
发布2019-11-05 16:56:23
举报
文章被收录于专栏:知识分享知识分享

前言

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

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

  绑定流程详细说明:

实现功能概要

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

测试准备工作

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

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

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

 四,调整波动开关位置,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 控制继电器断开

结语

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

小程序端APUConfig源码:

.js

代码语言:javascript
复制
// 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

代码语言:javascript
复制
{
  "usingComponents": {}
}

.wxml

代码语言:javascript
复制
<!--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

代码语言:javascript
复制
/* 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

代码语言:javascript
复制
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配置流程

代码语言:javascript
复制
/**
  ******************************************************************************
  * @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;
}

绑定成功后跳转

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-11-05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 实现功能概要
  • 测试准备工作
  • 开始测试
  • 结语
相关产品与服务
云开发 CloudBase
云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档