ESP8266 IoT设备自动配置与网络发布

在这篇教程中,将探讨如何为位于森林中央的IoT设备编程,使其能够自动配置并将其传感器数据发布到网络上。这个设备由于其孤立的位置,不适合拥有用户界面,甚至不需要一个按钮。它需要广播传感器的读数给任何监听的设备,并且需要在已知地址上提供一个小型网站。在创建这个设备的过程中,编写了一些代码,用于自动配置ESP8266并将其发布到网络上。本文旨在解释这个过程,并为自己的IoT项目提供实现代码。虽然它是为ESP8266设计的,但这些概念可以转移到其他平台。它应该适用于任何ESP8266模块,甚至是ESP-01。

前提条件: 本文假设已经熟悉ESP8266的编程。 本文假设正在使用Arduino IDE。 本文假设IDE已配置为编程ESP8266基础模块。

概念化: 第一个任务是连接到WiFi。将从内部闪存中读取配置文件。这将包含一个SSID和一个网络密码。 如果在过程中超时,将开始监听WPS信号。如果这也超时,将尝试再次连接到WiFi,并且这个过程会重复。 如果成功使用了WPS,将把SSID和网络密码写入闪存并重置设备。否则,将继续。 最后,将使用多播DNS(mDNS)发布设备,这样其他人就可以使用已知的本地域名找到它。 如果需要推送数据,理想情况下将使用UDP多播,这样任何设备都可以监听一个已知的本地多播地址。UDP通常适合传输传感器读数。否则,如果设备需要监听,它可以这样做,其他设备可以使用其已知的域名找到它。

编码: 确保ESP8266模块处于编程模式。没有对这段代码进行因式分解,因为想让它易于复制和粘贴,而其中包含大量的函数原型会破坏这一点。可能会在某个时候将其制作成库。

#include <ESP8266WiFi.h> #include <ESP8266mDNS.h> #include <EEPROM.h> // Your includes follow // BEGIN only needed if using UDP: #include <WiFiUdp.h> WiFiUDP Udp; #define UDPPORT 11011 #define UDPMULTICASTIP IPAddress(239,0,0,10) // END only needed if using UDP #define HOSTNAME "test" char cfgssid[256]; char cfgpassword[256]; // Your globals follow

上面的代码包含了三个必要的头文件。之后,可以插入自己的包含文件。然后,有一个可选的UDP部分。只需要它如果将使用UDP。 之后,定义了将发布的主机名,并且有缓冲区用于SSID和网络密码。

void setup() { // Initialize the serial port Serial.begin(115200); // commit 512 bytes of ESP8266 flash // this step actually loads the content (512 bytes) of flash into // a 512-byte-array cache in RAM EEPROM.begin(512); int i = 0; // Read the settings for(i = 0; i < 256; ++i) { cfgssid[i] = EEPROM.read(i); if (!cfgssid[i]) break; } cfgssid[i] = 0; i = 0; for(i = 0; i < 256; ++i) { cfgpassword[i] = (char)EEPROM.read(i+256); if (!cfgpassword[i]) break; } cfgpassword[i] = 0; // Initialize the WiFi and connect WiFi.mode(WIFI_STA); bool done = false; while (!done) { WiFi.begin(cfgssid, cfgpassword); Serial.print("\nConnecting to WiFi"); // try this for 10 seconds, then check for WPS for (int i = 0; i < 20 && WL_CONNECTED != WiFi.status(); ++i) { Serial.print("."); delay(500); } Serial.println("\n"); // If we're not connected, wait for a WPS signal if (WL_CONNECTED != WiFi.status()) { Serial.print("\nConnection to "); Serial.print(cfgssid); Serial.println(" failed. Entering auto-config mode"); Serial.println("\nPress the WPS button on your router"); bool ret = WiFi.beginWPSConfig(); if (ret) { String newSSID = WiFi.SSID(); if (0 < newSSID.length()) { Serial.println("\nAuto-configuration successful. Saving."); strcpy(cfgssid, newSSID.c_str()); strcpy(cfgpassword, WiFi.psk().c_str()); int c = strlen(cfgssid); for (int i = 0; i < c; ++i) EEPROM.write(i, cfgssid[i]); EEPROM.write(c, 0); c = strlen(cfgpassword); for (int i = 0; i < c; ++i) EEPROM.write(i+256, cfgpassword[i]); EEPROM.write(c+256, 0); EEPROM.end(); Serial.println("\nRestarting..."); ESP.restart(); } else { ret = false; } } } else done = true; // if we didn't get connected, loop } // Display the status Serial.println("\n"); Serial.print("\nConnected to "); Serial.println(WiFi.SSID()); Serial.print("Host name: "); Serial.print(HOSTNAME); Serial.println(".local"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); // start the multicast DNS publishing if (MDNS.begin(HOSTNAME)) { Serial.println("\nMDNS responder started"); } // initialize the UDP // only needed if using UDP: Udp.begin(UDPPORT); // Your setup code follows }

在上述代码中,初始化了EEPROM库,并分配了512字节的存储空间。然后,读取SSID - 一个少于256个字符的字符串。接下来,在偏移量256处读取密码,但其他方面几乎相同。

现在继续处理WiFi,这有点复杂:

void loop() { // reconnect to the WiFi if we got disconnected if (WL_CONNECTED != WiFi.status()) { // Connect to Wi-Fi WiFi.begin(cfgssid, cfgpassword); Serial.print("\nConnecting to WiFi"); for (int i = 0; i < 20 && WiFi.status() != WL_CONNECTED; ++i) { Serial.print("."); delay(500); } if (WL_CONNECTED != WiFi.status()) { Serial.println("\nCould not reconnect. Restarting."); ESP.restart(); } } // update the DNS information MDNS.update(); // BEGIN only applicable if using UDP: Udp.beginPacketMulticast(UDPMULTICASTIP, UDPPORT, WiFi.localIP()); Udp.print("\nHello World!"); Udp.endPacket(); // END only applicable if using UDP // Your code goes here // we only want to do this every quarter second for the example delay(250); }

逻辑有点笨拙。首先尝试连接。如果在10秒内无法连接,就开始寻找路由器的WPS信号。如果这也超时,回到尝试连接,并且循环重复。如果设法通过WPS连接,那么将新的SSID和密码写入闪存并重新启动设备。重新启动比试图让WiFi设备重新连接更可靠。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485