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  * If you've read through this and still want to use "Secure MQTT" with your
33  * ESP8266 project, we've left the "WiFiClientSecure" lines commented out. To
34  * use them, uncomment the commented out lines within this file and re-compile
35  * the library.
36  */
37 // static const char *fingerprint PROGMEM = "4E C1 52 73 24 A8 36 D6 7A 4C 67
38 // C7 91 0C 0A 22 B9 2D 5B CA";
39 
40 extern Wippersnapper WS;
41 
42 /******************************************************************************/
47 /******************************************************************************/
48 class Wippersnapper_ESP8266 : public Wippersnapper {
49 
50 public:
51  /**************************************************************************/
63  /**************************************************************************/
64  Wippersnapper_ESP8266() : Wippersnapper() {
65  _ssid = 0;
66  _pass = 0;
67  _wifi_client = new WiFiClient;
68  WiFi.persistent(false);
69  WiFi.mode(WIFI_STA);
70  }
71 
72  /**************************************************************************/
76  /**************************************************************************/
77  ~Wippersnapper_ESP8266() {
78  if (_wifi_client)
79  delete _wifi_client;
80  if (_mqtt)
81  delete _mqtt;
82  }
83 
84  /**********************************************************/
92  /**********************************************************/
93  void set_ssid_pass(const char *ssid, const char *ssidPassword) {
94  _ssid = ssid;
95 
96  // set the AP password
97  // check if ssidPassword was "" in secrets.json
98  if ((ssidPassword != NULL) && (strlen(ssidPassword) == 0)) {
99  _pass = NULL; // Set as NULL for open networks
100  } else {
101  _pass = ssidPassword;
102  }
103  }
104 
105  /**********************************************************/
110  /**********************************************************/
111  void set_ssid_pass() {
112  _ssid = WS._config.network.ssid;
113  _pass = WS._config.network.pass;
114  }
115 
116  /***********************************************************/
121  /***********************************************************/
122  bool check_valid_ssid() {
123  // Set WiFi to station mode and disconnect from an AP if it was previously
124  // connected
125  WiFi.mode(WIFI_STA);
126  WiFi.disconnect();
127  delay(100);
128 
129  // Perform a network scan
130  int n = WiFi.scanNetworks();
131  if (n == 0) {
132  WS_DEBUG_PRINTLN("ERROR: No WiFi networks found!");
133  return false;
134  }
135 
136  bool foundNetwork = false;
137 
138  WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks:");
139  for (uint8_t i = 0; i < n; i++) {
140  if (!foundNetwork && strcmp(WiFi.SSID(i).c_str(), _ssid) == 0) {
141  foundNetwork = true;
142  } else if (!foundNetwork && WS._isWiFiMulti) {
143  // multi network mode
144  for (int j = 0; j < WS_MAX_ALT_WIFI_NETWORKS; j++) {
145  if (strcmp(WS._multiNetworks[j].ssid, WiFi.SSID(i).c_str()) == 0) {
146  foundNetwork = true;
147  }
148  }
149  }
150  WS_DEBUG_PRINT(WiFi.SSID(i));
151  WS_DEBUG_PRINT(" (");
152  uint8_t BSSID[WL_MAC_ADDR_LENGTH];
153  memcpy(BSSID, WiFi.BSSID(i), WL_MAC_ADDR_LENGTH);
154  for (int m = 0; m < WL_MAC_ADDR_LENGTH; m++) {
155  if (m != 0)
156  WS_DEBUG_PRINT(":");
157  WS_DEBUG_PRINTHEX(BSSID[m]);
158  }
159  WS_DEBUG_PRINT(") ");
160  WS_DEBUG_PRINT(WiFi.RSSI(i));
161  WS_DEBUG_PRINT("dB (ch");
162  WS_DEBUG_PRINT(WiFi.channel(i))
163  WS_DEBUG_PRINTLN(")");
164  }
165 
166  if (!foundNetwork) {
167  WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!");
168  }
169  return foundNetwork;
170  }
171 
172  /********************************************************/
177  /********************************************************/
178  void getMacAddr() {
179  uint8_t mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
180  WiFi.macAddress(mac);
181  memcpy(WS._macAddr, mac, sizeof(mac));
182  }
183 
184  /********************************************************/
189  /********************************************************/
190  int32_t getRSSI() { return WiFi.RSSI(); }
191 
192  /*******************************************************************/
198  /*******************************************************************/
199  void setupMQTTClient(const char *clientID) {
200  // Uncomment the following lines to use MQTT/SSL. You will need to
201  // re-compile after. _wifi_client->setFingerprint(fingerprint); WS._mqtt =
202  // new Adafruit_MQTT_Client(_wifi_client, WS._config.aio_url,
203  // WS._config.io_port, clientID, WS._config.aio_user, WS._config.aio_key);
204  if (WS._config.io_port == 8883)
205  WS._config.io_port = 1883;
206  WS._mqtt = new Adafruit_MQTT_Client(
207  _wifi_client, WS._config.aio_url, WS._config.io_port, clientID,
208  WS._config.aio_user, WS._config.aio_key);
209  }
210 
211  /********************************************************/
216  /********************************************************/
218  switch (WiFi.status()) {
219  case WL_CONNECTED:
220  return WS_NET_CONNECTED;
221  case WL_CONNECT_FAILED:
222  return WS_NET_CONNECT_FAILED;
223  case WL_IDLE_STATUS:
224  return WS_IDLE;
225  default:
226  return WS_NET_DISCONNECTED;
227  }
228  }
229 
230  /*******************************************************************/
235  /*******************************************************************/
236  const char *connectionType() { return "ESP8266"; }
237 
238 protected:
239  const char *_ssid = NULL;
240  const char *_pass = NULL;
241  WiFiClient *_wifi_client;
242  ESP8266WiFiMulti _wifiMulti;
243 
244  /**************************************************************************/
248  /**************************************************************************/
249  void _connect() {
250 
251  if (WiFi.status() == WL_CONNECTED)
252  return;
253 
254  if (strlen(_ssid) == 0) {
255  _status = WS_SSID_INVALID;
256  } else {
257  WiFi.setAutoReconnect(false);
258  // Attempt connection
259  _disconnect();
260  delay(100);
261  // ESP8266 MUST be in STA mode to avoid device acting as client/server
262  WiFi.mode(WIFI_STA);
263  _status = WS_NET_DISCONNECTED;
264  delay(100);
265 
266  if (WS._isWiFiMulti) {
267  // multi network mode
268  for (int i = 0; i < WS_MAX_ALT_WIFI_NETWORKS; i++) {
269  if (strlen(WS._multiNetworks[i].ssid) > 0 &&
270  (_wifiMulti.existsAP(WS._multiNetworks[i].ssid) == false)) {
271  // doesn't exist, add it
272  _wifiMulti.addAP(WS._multiNetworks[i].ssid,
273  WS._multiNetworks[i].pass);
274  }
275  }
276  }
277 
278  // add default network
279  if (_wifiMulti.existsAP(_ssid) == false) {
280  _wifiMulti.addAP(_ssid, _pass);
281  }
282 
283  long startRetry = millis();
284  WS_DEBUG_PRINTLN("CONNECTING");
285 
286  while (_wifiMulti.run(5000) != WL_CONNECTED &&
287  millis() - startRetry < 10000) {
288  // ESP8266 WDT requires yield() during a busy-loop so it doesn't bite
289  yield();
290  }
291 
292  if (WiFi.status() == WL_CONNECTED) {
293  _status = WS_NET_CONNECTED;
294  } else {
295  _status = WS_NET_DISCONNECTED;
296  }
297 
298  WS.feedWDT();
299  }
300  }
301 
302  /**************************************************************************/
306  /**************************************************************************/
307  void _disconnect() {
308  WiFi.disconnect();
309  delay(500);
310  }
311 };
312 
313 #endif // ARDUINO_ARCH_ESP8266
314 #endif // WIPPERSNAPPER_ESP8266_H
virtual void setupMQTTClient(const char *clientID)
Sets up the MQTT client session.
Definition: Wippersnapper.cpp:203
#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:248
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:162
#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 identifer, typically the MAC address.
Definition: Wippersnapper.cpp:181
virtual void set_ssid_pass()
Sets the device&#39;s wireless network credentials from the secrets.json configuration file...
Definition: Wippersnapper.cpp:238
void feedWDT()
Feeds the WDT to prevent hardware reset.
Definition: Wippersnapper.cpp:2608
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:213
virtual int32_t getRSSI()
Gets the network&#39;s RSSI.
Definition: Wippersnapper.cpp:191
virtual void _disconnect()
Disconnect Wippersnapper MQTT session and network.
Definition: Wippersnapper.cpp:171