配网原理
配网需求
在前面我们写Blinker设备时,都是把WIFI信息写到程序中,烧录到模块中,因此当网络信息发生改变时,涉笔就无法连接到网络。此时需要重新修改代码,重新烧录。对于用户来说,修改程序比较繁琐,怎样做才能让设备去适应不同的场景呢?这就需要配网功能了。
配网模式
常见的配网模式有:
- 直接配网 -> SSID(Wi-Fi名称)和PWD(Wi-Fi密码)保存在设备中(每次修改都要重新烧录代码)
- ap配网 -> 设备处于路由模式下等待客户端发送来SSID和PWD(可以随时修改,不易于操作)
- web配置 -> 设备内做了个小web服务器通过网页交换SSID和PWD(界面化操作,流程繁琐)
- SmartConfig -> 手机通过软件发送UDP广播包(包含SSID和PWD,界面化操作,操作简单)
- Airkiss -> 类似与SmartConfig,可以使用微信公众号直接配置(界面化操作,不需要装APP)
- 零配 -> 以配网设备为未配网设备配网,两个设备间数据交互(AliOS-Things中有涉及)
- 蓝牙配网 -> 利用蓝牙设备配网,蓝牙模块跟ESP8266串口数据交互(未使用过,不做评价)
我们此次采用的时Airkiss,其实和SmartConfig是差不多的,两者可以一样用。
Airkiss模式
此模式配网过程:
- 手机连接带目标WIFI
- 设备进入配网模式,等待接收SSID和密码
- 手机按照协议向周围广播SSID和密码信息(微信公众号:安信可科技,官方配网APP也可以)
- 设备接收到SSID和密码后,连接到WIFI
代码讲解
代码功能
新建设备为小米插座类型设备,开机尝试连接到8266记录的WIFI,如果连接不上,则进入配网模式,等待手机配网,配网完成后连接到指定WIFI,并利用设备秘钥连接到Blinker云,与米家云通讯,小爱同学即可操作对应设备。
代码基于Blinker的MIOT_OUTLET例程。
整体代码展示
/* *****************************************************************
*
* Download latest Blinker library here:
* https://github.com/blinker-iot/blinker-library/archive/master.zip
*
*
* Blinker is a cross-hardware, cross-platform solution for the IoT.
* It provides APP, device and server support,
* and uses public cloud services for data transmission and storage.
* It can be used in smart home, data monitoring and other fields
* to help users build Internet of Things projects better and faster.
*
* Make sure installed 2.5.0 or later ESP8266/Arduino package,
* if use ESP8266 with Blinker.
* https://github.com/esp8266/Arduino/releases
*
* Make sure installed 1.0.2 or later ESP32/Arduino package,
* if use ESP32 with Blinker.
* https://github.com/espressif/arduino-esp32/releases
*
* Docs: https://doc.blinker.app/
* https://github.com/blinker-iot/blinker-doc/wiki
*
* *****************************************************************
*
* Blinker 库下载地址:
* https://github.com/blinker-iot/blinker-library/archive/master.zip
*
* Blinker 是一套跨硬件、跨平台的物联网解决方案,提供APP端、设备端、
* 服务器端支持,使用公有云服务进行数据传输存储。可用于智能家居、
* 数据监测等领域,可以帮助用户更好更快地搭建物联网项目。
*
* 如果使用 ESP8266 接入 Blinker,
* 请确保安装了 2.5.0 或更新的 ESP8266/Arduino 支持包。
* https://github.com/esp8266/Arduino/releases
*
* 如果使用 ESP32 接入 Blinker,
* 请确保安装了 1.0.2 或更新的 ESP32/Arduino 支持包。
* https://github.com/espressif/arduino-esp32/releases
*
* 文档: https://doc.blinker.app/
* https://github.com/blinker-iot/blinker-doc/wiki
*
* *****************************************************************/
#define BLINKER_WIFI //配置为WIFI接入模式
#define BLINKER_MIOT_OUTLET //配置为小米插座类设备
#include <Blinker.h> //Blinker库
#include <ESP8266WiFi.h> //WIFI库,配网必需
int count = 0; //时间计数
bool WIFI_Status = true; //WIFI状态标志位
#define pin D1 //要操作的IO
char auth[] = "xxxxxxxx"; //设备秘钥
bool oState = false;
/* 配网函数 */
void smartConfig()
{
WiFi.mode(WIFI_STA);//设置STA模式
Serial.println("\r\nWait for Smartconfig...");//打印log信息
WiFi.beginSmartConfig();//开始SmartConfig,等待手机端发出用户名和密码
while(1)
{
Serial.println(".");
digitalWrite(LED_BUILTIN,HIGH);//指示灯闪烁
delay(1000);
digitalWrite(LED_BUILTIN,LOW);//指示灯闪烁
delay(1000);
if(WiFi.smartConfigDone())//配网成功,接收到SSID和密码
{
Serial.println("SmartConfig Success");
Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
break;
}
}
}
/* 小米电源类设备回调函数 */
void miotPowerState(const String & state)
{
BLINKER_LOG("need set power state: ", state);
if (state == BLINKER_CMD_ON) { //指令打开设备
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(pin, HIGH);
BlinkerMIOT.powerState("on");
BlinkerMIOT.print();
oState = true;
}
else if (state == BLINKER_CMD_OFF) { //指令关闭设备
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(pin, LOW);
BlinkerMIOT.powerState("off");
BlinkerMIOT.print();
oState = false;
}
}
/* 小米设备状态查询回调函数 */
void miotQuery(int32_t queryCode)
{
BLINKER_LOG("MIOT Query codes: ", queryCode);
switch (queryCode)
{
case BLINKER_CMD_QUERY_ALL_NUMBER :
BLINKER_LOG("MIOT Query All");
BlinkerMIOT.powerState(oState ? "on" : "off");
BlinkerMIOT.print();
break;
case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
BLINKER_LOG("MIOT Query Power State");
BlinkerMIOT.powerState(oState ? "on" : "off");
BlinkerMIOT.print();
break;
default :
BlinkerMIOT.powerState(oState ? "on" : "off");
BlinkerMIOT.print();
break;
}
}
void dataRead(const String & data)
{
BLINKER_LOG("Blinker readString: ", data);
Blinker.vibrate();
uint32_t BlinkerTime = millis();
Blinker.print("millis", BlinkerTime);
}
void setup()
{
Serial.begin(115200);
BLINKER_DEBUG.stream(Serial);
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
Serial.println("\r\n正在连接WIFI...");
while(WiFi.status()!=WL_CONNECTED)//判断是否连接WIFI成功
{
if(WIFI_Status)
{
Serial.print(".");
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
count++;
if(count>=5)//5s
{
WIFI_Status = false;
Serial.println("WiFi连接失败,请用手机进行配网");
}
}
else
{
smartConfig(); //微信智能配网
}
}
Serial.println("连接成功");
Serial.print("IP:");
Serial.println(WiFi.localIP());
Blinker.begin(auth,WiFi.SSID().c_str(),WiFi.psk().c_str()); //根据配网得到的WIFI信息和设备秘钥,连接到Blinker云
Blinker.attachData(dataRead);
BlinkerMIOT.attachPowerState(miotPowerState);//注册回调函数
BlinkerMIOT.attachQuery(miotQuery);
}
void loop()
{
Blinker.run();
}