Adafruit Library
Wippersnapper_ESP8266.h
Go to the documentation of this file.
1 
17 #ifndef WIPPERSNAPPER_ESP8266_H
18 #define WIPPERSNAPPER_ESP8266_H
19 
20 #ifdef ARDUINO_ARCH_ESP8266
21 #include "Adafruit_MQTT.h"
22 #include "Adafruit_MQTT_Client.h"
23 #include "ESP8266WiFi.h"
24 #include "ESP8266WiFiMulti.h"
25 #include "Wippersnapper.h"
26 
27 /* NOTE - Projects that require "Secure MQTT" (TLS/SSL) also require a new
28  * SSL certificate every year. If adding Secure MQTT to your ESP8266 project is
29  * important - please switch to using the modern ESP32 (and related models)
30  * instead of the ESP8266 to avoid updating the SSL fingerprint every year.
31  *
32  * The commented-out fingerprint below was last updated on 07/14/2025.
33  *
34  * If you've read through this and still want to use "Secure MQTT" with your
35  * ESP8266 project, we've left the "WiFiClientSecure" lines commented out. To
36  * use them, uncomment the commented out lines within this file and re-compile
37  * the library.
38  */
39 // static const char *fingerprint PROGMEM = "47 D2 CB 14 DF 38 97 59 C6 65 1A
40 // 1F 3E 00 1E 53 CC A5 17 E0";
41 
42 extern Wippersnapper WS;
43 
44 /******************************************************************************/
49 /******************************************************************************/
50 class Wippersnapper_ESP8266 : public Wippersnapper {
51 
52 public:
53  /**************************************************************************/
65  /**************************************************************************/
66  Wippersnapper_ESP8266() : Wippersnapper() {
67  _ssid = 0;
68  _pass = 0;
69  _wifi_client = new WiFiClient;
70  WiFi.persistent(false);
71  WiFi.mode(WIFI_STA);
72  }
73 
74  /**************************************************************************/
78  /**************************************************************************/
79  ~Wippersnapper_ESP8266() {
80  if (_wifi_client)
81  delete _wifi_client;
82  if (_mqtt)
83  delete _mqtt;
84  }
85 
86  /**********************************************************/
94  /**********************************************************/
95  void set_ssid_pass(const char *ssid, const char *ssidPassword) {
96  _ssid = ssid;
97 
98  // set the AP password
99  // check if ssidPassword was "" in secrets.json
100  if ((ssidPassword != NULL) && (strlen(ssidPassword) == 0)) {
101  _pass = NULL; // Set as NULL for open networks
102  } else {
103  _pass = ssidPassword;
104  }
105  }
106 
107  /**********************************************************/
112  /**********************************************************/
113  void set_ssid_pass() {
114  _ssid = WS._config.network.ssid;
115  _pass = WS._config.network.pass;
116  }
117 
118  /***********************************************************/
123  /***********************************************************/
124  bool check_valid_ssid() {
125  // Set WiFi to station mode and disconnect from an AP if it was previously
126  // connected
127  WiFi.mode(WIFI_STA);
128  WiFi.disconnect();
129  delay(100);
130 
131  // Perform a network scan
132  int n = WiFi.scanNetworks();
133  if (n == 0) {
134  WS_DEBUG_PRINTLN("ERROR: No WiFi networks found!");
135  return false;
136  }
137 
138  bool foundNetwork = false;
139 
140  WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks:");
141  for (uint8_t i = 0; i < n; i++) {
142  if (!foundNetwork && strcmp(WiFi.SSID(i).c_str(), _ssid) == 0) {
143  foundNetwork = true;
144  } else if (!foundNetwork && WS._isWiFiMulti) {
145  // multi network mode
146  for (int j = 0; j < WS_MAX_ALT_WIFI_NETWORKS; j++) {
147  if (strcmp(WS._multiNetworks[j].ssid, WiFi.SSID(i).c_str()) == 0) {
148  foundNetwork = true;
149  }
150  }
151  }
152  WS_DEBUG_PRINT(WiFi.SSID(i));
153  WS_DEBUG_PRINT(" (");
154  uint8_t BSSID[WL_MAC_ADDR_LENGTH];
155  memcpy(BSSID, WiFi.BSSID(i), WL_MAC_ADDR_LENGTH);
156  for (int m = 0; m < WL_MAC_ADDR_LENGTH; m++) {
157  if (m != 0)
158  WS_DEBUG_PRINT(":");
159  WS_DEBUG_PRINTHEX(BSSID[m]);
160  }
161  WS_DEBUG_PRINT(") ");
162  WS_DEBUG_PRINT(WiFi.RSSI(i));
163  WS_DEBUG_PRINT("dB (ch");
164  WS_DEBUG_PRINT(WiFi.channel(i))
165  WS_DEBUG_PRINTLN(")");
166  }
167 
168  if (!foundNetwork) {
169  WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!");
170  }
171  return foundNetwork;
172  }
173 
174  /********************************************************/
179  /********************************************************/
180  void getMacAddr() {
181  uint8_t mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
182  WiFi.macAddress(mac);
183  memcpy(WS._macAddr, mac, sizeof(mac));
184  }
185 
186  /********************************************************/
191  /********************************************************/
192  int32_t getRSSI() { return WiFi.RSSI(); }
193 
194  /*******************************************************************/
200  /*******************************************************************/
201  void setupMQTTClient(const char *clientID) {
202  // Uncomment the following lines to use MQTT/SSL. You will need to
203  // re-compile after. _wifi_client->setFingerprint(fingerprint); WS._mqtt =
204  // new Adafruit_MQTT_Client(_wifi_client, WS._config.aio_url,
205  // WS._config.io_port, clientID, WS._config.aio_user, WS._config.aio_key);
206  if (WS._config.io_port == 8883)
207  WS._config.io_port = 1883;
208  WS._mqtt = new Adafruit_MQTT_Client(
209  _wifi_client, WS._config.aio_url, WS._config.io_port, clientID,
210  WS._config.aio_user, WS._config.aio_key);
211  }
212 
213  /********************************************************/
218  /********************************************************/
220  switch (WiFi.status()) {
221  case WL_CONNECTED:
222  return WS_NET_CONNECTED;
223  case WL_CONNECT_FAILED:
224  return WS_NET_CONNECT_FAILED;
225  case WL_IDLE_STATUS:
226  return WS_IDLE;
227  default:
228  return WS_NET_DISCONNECTED;
229  }
230  }
231 
232  /*******************************************************************/
237  /*******************************************************************/
238  const char *connectionType() { return "ESP8266"; }
239 
240 protected:
241  const char *_ssid = NULL;
242  const char *_pass = NULL;
243  WiFiClient *_wifi_client;
244  ESP8266WiFiMulti _wifiMulti;
245 
246  /**************************************************************************/
250  /**************************************************************************/
251  void _connect() {
252 
253  if (WiFi.status() == WL_CONNECTED)
254  return;
255 
256  if (strlen(_ssid) == 0) {
257  _status = WS_SSID_INVALID;
258  } else {
259  WiFi.setAutoReconnect(false);
260  // Attempt connection
261  _disconnect();
262  delay(100);
263  // ESP8266 MUST be in STA mode to avoid device acting as client/server
264  WiFi.mode(WIFI_STA);
265  _status = WS_NET_DISCONNECTED;
266  delay(100);
267 
268  if (WS._isWiFiMulti) {
269  // multi network mode
270  for (int i = 0; i < WS_MAX_ALT_WIFI_NETWORKS; i++) {
271  if (strlen(WS._multiNetworks[i].ssid) > 0 &&
272  (_wifiMulti.existsAP(WS._multiNetworks[i].ssid) == false)) {
273  // doesn't exist, add it
274  _wifiMulti.addAP(WS._multiNetworks[i].ssid,
275  WS._multiNetworks[i].pass);
276  }
277  }
278  }
279 
280  // add default network
281  if (_wifiMulti.existsAP(_ssid) == false) {
282  _wifiMulti.addAP(_ssid, _pass);
283  }
284 
285  long startRetry = millis();
286  WS_DEBUG_PRINTLN("CONNECTING");
287 
288  while (_wifiMulti.run(5000) != WL_CONNECTED &&
289  millis() - startRetry < 10000) {
290  // ESP8266 WDT requires yield() during a busy-loop so it doesn't bite
291  yield();
292  }
293 
294  if (WiFi.status() == WL_CONNECTED) {
295  _status = WS_NET_CONNECTED;
296  } else {
297  _status = WS_NET_DISCONNECTED;
298  }
299 
300  WS.feedWDT();
301  }
302  }
303 
304  /**************************************************************************/
308  /**************************************************************************/
309  void _disconnect() {
310  WiFi.disconnect();
311  delay(500);
312  }
313 };
314 
315 #endif // ARDUINO_ARCH_ESP8266
316 #endif // WIPPERSNAPPER_ESP8266_H
virtual void setupMQTTClient(const char *clientID)
Sets up the MQTT client session.
Definition: Wippersnapper.cpp:205
#define WS_DEBUG_PRINT(...)
Prints debug output.
Definition: Wippersnapper.h:49
#define WS_DEBUG_PRINTHEX(...)
Prints debug output.
Definition: Wippersnapper.h:55
secretsConfig _config
Definition: Wippersnapper.h:406
#define WL_MAC_ADDR_LENGTH
MAC address length - from RP2040 BSP.
Definition: Wippersnapper_Networking.h:20
ws_status_t
Definition: Wippersnapper.h:190
virtual bool check_valid_ssid()
Performs a scan of local WiFi networks.
Definition: Wippersnapper.cpp:250
Class that provides storage and functions for the Adafruit IO Wippersnapper interface.
Definition: Wippersnapper.h:283
virtual void _connect()
Connects to wireless network.
Definition: Wippersnapper.cpp:164
#define WS_MAX_ALT_WIFI_NETWORKS
Maximum number of alternative networks.
Definition: Wippersnapper.h:251
virtual void getMacAddr()
Sets the network interface&#39;s unique identifier, typically the MAC address.
Definition: Wippersnapper.cpp:183
virtual void set_ssid_pass()
Sets the device&#39;s wireless network credentials from the secrets.json configuration file...
Definition: Wippersnapper.cpp:240
void feedWDT()
Feeds the WDT to prevent hardware reset.
Definition: Wippersnapper.cpp:2632
bool _isWiFiMulti
Definition: Wippersnapper.h:408
networkConfig _multiNetworks[3]
Definition: Wippersnapper.h:407
#define WS_DEBUG_PRINTLN(...)
Prints line from debug output.
Definition: Wippersnapper.h:52
Wippersnapper WS
Definition: Wippersnapper.cpp:36
uint8_t _macAddr[6]
Definition: Wippersnapper.h:401
Adafruit_MQTT * _mqtt
Definition: Wippersnapper.h:404
virtual ws_status_t networkStatus()
Returns the network&#39;s connection status.
Definition: Wippersnapper.cpp:215
virtual int32_t getRSSI()
Gets the network&#39;s RSSI.
Definition: Wippersnapper.cpp:193
virtual void _disconnect()
Disconnect Wippersnapper MQTT session and network.
Definition: Wippersnapper.cpp:173