Skip to content

Commit d29e3e4

Browse files
committed
[SD] Start to support pico2
1 parent e076710 commit d29e3e4

File tree

2 files changed

+370
-4
lines changed

2 files changed

+370
-4
lines changed
Lines changed: 366 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,366 @@
1+
/*!
2+
* @file ws_networking_pico_v2.h
3+
*
4+
* This is a driver for using the Raspberry Pi Pico (RP2040)
5+
* network interface with Adafruit IO Wippersnapper.
6+
*
7+
* Adafruit invests time and resources providing this open source code,
8+
* please support Adafruit and open-source hardware by purchasing
9+
* products from Adafruit!
10+
*
11+
* Copyright (c) Brent Rubell 2023 for Adafruit Industries.
12+
*
13+
* MIT license, all text here must be included in any redistribution.
14+
*
15+
*/
16+
17+
#ifndef WS_NETWORKING_PICO_V2_H
18+
#define WS_NETWORKING_PICO_V2_H
19+
20+
#ifdef ARDUINO_ARCH_RP2040
21+
22+
#define PICO_CONNECT_TIMEOUT_MS 20000 /*!< Connection timeout (in ms) */
23+
#define PICO_CONNECT_RETRY_DELAY_MS 200 /*!< delay time between retries. */
24+
25+
#include "Wippersnapper_V2.h"
26+
27+
#include "Adafruit_MQTT.h"
28+
#include "Adafruit_MQTT_Client.h"
29+
#include "Arduino.h"
30+
#include <WiFiClient.h>
31+
#include <WiFiClientSecure.h>
32+
extern Wippersnapper_V2 WsV2;
33+
34+
/****************************************************************************/
35+
/*!
36+
@brief Class for using the Raspberry Pi Pico network interface.
37+
*/
38+
/****************************************************************************/
39+
class ws_networking_pico_v2 : public Wippersnapper_V2 {
40+
41+
public:
42+
/**************************************************************************/
43+
/*!
44+
@brief Initializes the WipperSnapper class for RPi Pico.
45+
*/
46+
/**************************************************************************/
47+
ws_networking_pico_v2() : Wippersnapper_V2() {
48+
_ssid = 0;
49+
_pass = 0;
50+
}
51+
52+
/**************************************************************************/
53+
/*!
54+
@brief Destructor
55+
*/
56+
/**************************************************************************/
57+
~ws_networking_pico_v2() {
58+
if (_mqtt_client_secure)
59+
delete _mqtt_client_secure;
60+
if (_mqtt_client_secure)
61+
delete _mqtt_client_secure;
62+
}
63+
64+
/********************************************************/
65+
/*!
66+
@brief Sets the WiFi client's ssid and password.
67+
@param ssid
68+
WiFi network's SSID.
69+
@param ssidPassword
70+
WiFi network's password.
71+
*/
72+
/********************************************************/
73+
void set_ssid_pass(const char *ssid, const char *ssidPassword) {
74+
_ssid = ssid;
75+
76+
// set the AP password
77+
// check if ssidPassword was "" in secrets.json
78+
if ((ssidPassword != NULL) && (strlen(ssidPassword) == 0)) {
79+
_pass = NULL; // Set as NULL for open networks
80+
} else {
81+
_pass = ssidPassword;
82+
}
83+
}
84+
85+
/**********************************************************/
86+
/*!
87+
@brief Sets the WiFi client's ssid and password.
88+
*/
89+
/**********************************************************/
90+
void set_ssid_pass() {
91+
_ssid = WsV2._configV2.network.ssid;
92+
_pass = WsV2._configV2.network.pass;
93+
}
94+
95+
/***********************************************************/
96+
/*!
97+
@brief Performs a scan of local WiFi networks.
98+
@returns True if `_network_ssid` is found, False otherwise.
99+
*/
100+
/***********************************************************/
101+
bool check_valid_ssid() {
102+
// Set WiFi to station mode and disconnect from an AP if it was previously
103+
// connected
104+
WiFi.mode(WIFI_STA);
105+
WiFi.disconnect();
106+
delay(100);
107+
108+
// Perform a network scan
109+
int n = WiFi.scanNetworks();
110+
if (n == 0) {
111+
WS_DEBUG_PRINTLN("ERROR: No WiFi networks found!");
112+
return false;
113+
}
114+
115+
// Was the network within secrets.json found?
116+
for (int i = 0; i < n; ++i) {
117+
if (strcmp(_ssid, WiFi.SSID(i)) == 0) {
118+
WS_DEBUG_PRINT("SSID (");
119+
WS_DEBUG_PRINT(_ssid);
120+
WS_DEBUG_PRINT(") found! RSSI: ");
121+
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
122+
return true;
123+
}
124+
if (WsV2._isWiFiMultiV2) {
125+
// multi network mode
126+
for (int j = 0; j < WS_MAX_ALT_WIFI_NETWORKS; j++) {
127+
if (strcmp(WsV2._multiNetworksV2[j].ssid, WiFi.SSID(i)) == 0) {
128+
WS_DEBUG_PRINT("SSID (");
129+
WS_DEBUG_PRINT(WsV2._multiNetworksV2[j].ssid);
130+
WS_DEBUG_PRINT(") found! RSSI: ");
131+
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
132+
return true;
133+
}
134+
}
135+
}
136+
}
137+
138+
// User-set network not found, print scan results to serial console
139+
WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!");
140+
WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: ");
141+
for (int i = 0; i < n; ++i) {
142+
WS_DEBUG_PRINT(WiFi.SSID(i));
143+
WS_DEBUG_PRINT(" ");
144+
WS_DEBUG_PRINT(WiFi.RSSI(i));
145+
WS_DEBUG_PRINTLN("dB");
146+
}
147+
148+
return false;
149+
}
150+
151+
/********************************************************/
152+
/*!
153+
@brief Sets the RPi Pico's unique client identifier
154+
@note On RPi Pico, the UID is the MAC address.
155+
*/
156+
/********************************************************/
157+
void getMacAddr() {
158+
uint8_t mac[6] = {0};
159+
WiFi.macAddress(mac);
160+
memcpy(WsV2._macAddrV2, mac, sizeof(mac));
161+
}
162+
163+
/********************************************************/
164+
/*!
165+
@brief Gets the current network RSSI value
166+
@return int32_t RSSI value
167+
*/
168+
/********************************************************/
169+
int32_t getRSSI() { return WiFi.RSSI(); }
170+
171+
/********************************************************/
172+
/*!
173+
@brief Initializes the MQTT client
174+
@param clientID
175+
MQTT client identifier
176+
*/
177+
/********************************************************/
178+
void setupMQTTClient(const char *clientID) {
179+
if (strcmp(WsV2._configV2.aio_url, "io.adafruit.com") == 0 ||
180+
strcmp(WsV2._configV2.aio_url, "io.adafruit.us") == 0) {
181+
_mqtt_client_secure = new WiFiClientSecure();
182+
_mqtt_client_secure->setCACert(
183+
strcmp(WsV2._configV2.aio_url, "io.adafruit.com") == 0
184+
? _aio_root_ca_prod
185+
: _aio_root_ca_staging);
186+
WsV2._mqttV2 = new Adafruit_MQTT_Client(
187+
_mqtt_client_secure, WsV2._configV2.aio_url, WsV2._configV2.io_port, clientID,
188+
WsV2._configV2.aio_user, WsV2._configV2.aio_key);
189+
} else {
190+
_mqtt_client_insecure = new WiFiClient();
191+
WsV2._mqttV2 = new Adafruit_MQTT_Client(
192+
_mqtt_client_insecure, WsV2._configV2.aio_url, WsV2._configV2.io_port,
193+
clientID, WsV2._configV2.aio_user, WsV2._configV2.aio_key);
194+
}
195+
}
196+
197+
/********************************************************/
198+
/*!
199+
@brief Returns the network status of an RPi Pico.
200+
@return ws_status_t
201+
*/
202+
/********************************************************/
203+
ws_status_t networkStatus() {
204+
switch (WiFi.status()) {
205+
case WL_CONNECTED:
206+
return WS_NET_CONNECTED;
207+
case WL_CONNECT_FAILED:
208+
return WS_NET_CONNECT_FAILED;
209+
case WL_IDLE_STATUS:
210+
return WS_IDLE;
211+
default:
212+
return WS_NET_DISCONNECTED;
213+
}
214+
}
215+
216+
/*******************************************************************/
217+
/*!
218+
@brief Returns the type of network connection used by Wippersnapper
219+
@return Pico
220+
*/
221+
/*******************************************************************/
222+
const char *connectionType() { return "Pico"; }
223+
224+
protected:
225+
const char *_ssid; ///< WiFi SSID
226+
const char *_pass; ///< WiFi password
227+
WiFiClient
228+
*_mqtt_client_insecure; ///< Pointer to an insecure WiFi client object
229+
WiFiClientSecure
230+
*_mqtt_client_secure; ///< Pointer to a secure WiFi client object
231+
WiFiMulti _wifiMulti; ///< WiFiMulti object for multi-network mode
232+
233+
const char *_aio_root_ca_staging =
234+
"-----BEGIN CERTIFICATE-----\n"
235+
"MIIEVzCCAj+gAwIBAgIRALBXPpFzlydw27SHyzpFKzgwDQYJKoZIhvcNAQELBQAw\n"
236+
"TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n"
237+
"cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw\n"
238+
"WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg\n"
239+
"RW5jcnlwdDELMAkGA1UEAxMCRTYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATZ8Z5G\n"
240+
"h/ghcWCoJuuj+rnq2h25EqfUJtlRFLFhfHWWvyILOR/VvtEKRqotPEoJhC6+QJVV\n"
241+
"6RlAN2Z17TJOdwRJ+HB7wxjnzvdxEP6sdNgA1O1tHHMWMxCcOrLqbGL0vbijgfgw\n"
242+
"gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD\n"
243+
"ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSTJ0aYA6lRaI6Y1sRCSNsj\n"
244+
"v1iU0jAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB\n"
245+
"AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g\n"
246+
"BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu\n"
247+
"Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAfYt7SiA1sgWGCIpunk46r4AExIRc\n"
248+
"MxkKgUhNlrrv1B21hOaXN/5miE+LOTbrcmU/M9yvC6MVY730GNFoL8IhJ8j8vrOL\n"
249+
"pMY22OP6baS1k9YMrtDTlwJHoGby04ThTUeBDksS9RiuHvicZqBedQdIF65pZuhp\n"
250+
"eDcGBcLiYasQr/EO5gxxtLyTmgsHSOVSBcFOn9lgv7LECPq9i7mfH3mpxgrRKSxH\n"
251+
"pOoZ0KXMcB+hHuvlklHntvcI0mMMQ0mhYj6qtMFStkF1RpCG3IPdIwpVCQqu8GV7\n"
252+
"s8ubknRzs+3C/Bm19RFOoiPpDkwvyNfvmQ14XkyqqKK5oZ8zhD32kFRQkxa8uZSu\n"
253+
"h4aTImFxknu39waBxIRXE4jKxlAmQc4QjFZoq1KmQqQg0J/1JF8RlFvJas1VcjLv\n"
254+
"YlvUB2t6npO6oQjB3l+PNf0DpQH7iUx3Wz5AjQCi6L25FjyE06q6BZ/QlmtYdl/8\n"
255+
"ZYao4SRqPEs/6cAiF+Qf5zg2UkaWtDphl1LKMuTNLotvsX99HP69V2faNyegodQ0\n"
256+
"LyTApr/vT01YPE46vNsDLgK+4cL6TrzC/a4WcmF5SRJ938zrv/duJHLXQIku5v0+\n"
257+
"EwOy59Hdm0PT/Er/84dDV0CSjdR/2XuZM3kpysSKLgD1cKiDA+IRguODCxfO9cyY\n"
258+
"Ig46v9mFmBvyH04=\n"
259+
"-----END CERTIFICATE-----\n"; ///< Root certificate for io.adafruit.us
260+
261+
const char *_aio_root_ca_prod =
262+
"-----BEGIN CERTIFICATE-----\n"
263+
"MIIEjTCCA3WgAwIBAgIQDQd4KhM/xvmlcpbhMf/ReTANBgkqhkiG9w0BAQsFADBh\n"
264+
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
265+
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n"
266+
"MjAeFw0xNzExMDIxMjIzMzdaFw0yNzExMDIxMjIzMzdaMGAxCzAJBgNVBAYTAlVT\n"
267+
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
268+
"b20xHzAdBgNVBAMTFkdlb1RydXN0IFRMUyBSU0EgQ0EgRzEwggEiMA0GCSqGSIb3\n"
269+
"DQEBAQUAA4IBDwAwggEKAoIBAQC+F+jsvikKy/65LWEx/TMkCDIuWegh1Ngwvm4Q\n"
270+
"yISgP7oU5d79eoySG3vOhC3w/3jEMuipoH1fBtp7m0tTpsYbAhch4XA7rfuD6whU\n"
271+
"gajeErLVxoiWMPkC/DnUvbgi74BJmdBiuGHQSd7LwsuXpTEGG9fYXcbTVN5SATYq\n"
272+
"DfbexbYxTMwVJWoVb6lrBEgM3gBBqiiAiy800xu1Nq07JdCIQkBsNpFtZbIZhsDS\n"
273+
"fzlGWP4wEmBQ3O67c+ZXkFr2DcrXBEtHam80Gp2SNhou2U5U7UesDL/xgLK6/0d7\n"
274+
"6TnEVMSUVJkZ8VeZr+IUIlvoLrtjLbqugb0T3OYXW+CQU0kBAgMBAAGjggFAMIIB\n"
275+
"PDAdBgNVHQ4EFgQUlE/UXYvkpOKmgP792PkA76O+AlcwHwYDVR0jBBgwFoAUTiJU\n"
276+
"IBiV5uNu5g/6+rkS7QYXjzkwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsG\n"
277+
"AQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMDQGCCsGAQUFBwEB\n"
278+
"BCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEIGA1Ud\n"
279+
"HwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEds\n"
280+
"b2JhbFJvb3RHMi5jcmwwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEW\n"
281+
"HGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwDQYJKoZIhvcNAQELBQADggEB\n"
282+
"AIIcBDqC6cWpyGUSXAjjAcYwsK4iiGF7KweG97i1RJz1kwZhRoo6orU1JtBYnjzB\n"
283+
"c4+/sXmnHJk3mlPyL1xuIAt9sMeC7+vreRIF5wFBC0MCN5sbHwhNN1JzKbifNeP5\n"
284+
"ozpZdQFmkCo+neBiKR6HqIA+LMTMCMMuv2khGGuPHmtDze4GmEGZtYLyF8EQpa5Y\n"
285+
"jPuV6k2Cr/N3XxFpT3hRpt/3usU/Zb9wfKPtWpoznZ4/44c1p9rzFcZYrWkj3A+7\n"
286+
"TNBJE0GmP2fhXhP1D/XVfIW/h0yCJGEiV9Glm/uGOa3DXHlmbAcxSyCRraG+ZBkA\n"
287+
"7h4SeM6Y8l/7MBRpPCz6l8Y=\n"
288+
"-----END CERTIFICATE-----\n"; ///< Root certificate for io.adafruit.com
289+
290+
/**************************************************************************/
291+
/*!
292+
@brief Establishes a connection with the wireless network.
293+
*/
294+
/**************************************************************************/
295+
void _connect() {
296+
297+
if (WiFi.status() == WL_CONNECTED)
298+
return;
299+
300+
WiFi.mode(WIFI_STA);
301+
WsV2.feedWDTV2();
302+
WiFi.setTimeout(20000);
303+
WsV2.feedWDTV2();
304+
305+
if (strlen(_ssid) == 0) {
306+
_statusV2 = WS_SSID_INVALID;
307+
} else {
308+
_disconnect();
309+
delay(5000);
310+
WsV2.feedWDTV2();
311+
if (WsV2._isWiFiMultiV2) {
312+
// multi network mode
313+
_wifiMulti.clearAPList();
314+
// add default network
315+
_wifiMulti.addAP(_ssid, _pass);
316+
// add array of alternative networks
317+
for (int i = 0; i < WS_MAX_ALT_WIFI_NETWORKS; i++) {
318+
_wifiMulti.addAP(WsV2._multiNetworksV2[i].ssid,
319+
WsV2._multiNetworksV2[i].pass);
320+
}
321+
WsV2.feedWDTV2();
322+
if (_wifiMulti.run(10000) == WL_CONNECTED) {
323+
WsV2.feedWDTV2();
324+
_statusV2 = WS_NET_CONNECTED;
325+
return;
326+
}
327+
WsV2.feedWDTV2();
328+
} else {
329+
WiFi.begin(_ssid, _pass);
330+
331+
// Use the macro to retry the status check until connected / timed out
332+
int lastResult;
333+
/* RETRY_FUNCTION_UNTIL_TIMEOUT(
334+
[]() -> int { return WiFi.status(); }, // Function call each cycle
335+
int, // return type
336+
lastResult, // return variable (unused here)
337+
[](int status) { return status == WL_CONNECTED; }, // check
338+
PICO_CONNECT_TIMEOUT_MS, // timeout interval (ms)
339+
PICO_CONNECT_RETRY_DELAY_MS); // interval between retries */
340+
341+
if (lastResult == WL_CONNECTED) {
342+
_statusV2 = WS_NET_CONNECTED;
343+
// wait 2seconds for connection to stabilize
344+
// WS_DELAY_WITH_WDT(2000);
345+
return;
346+
}
347+
}
348+
_statusV2 = WS_NET_DISCONNECTED;
349+
}
350+
}
351+
352+
/**************************************************************************/
353+
/*!
354+
@brief Disconnects from the wireless network.
355+
*/
356+
/**************************************************************************/
357+
void _disconnect() {
358+
WsV2.feedWDTV2();
359+
WiFi.disconnect();
360+
delay(5000);
361+
WsV2.feedWDTV2();
362+
}
363+
};
364+
365+
#endif // ARDUINO_ARCH_RP2040
366+
#endif // WS_NETWORKING_PICO_V2_H

src/ws_manager.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#ifndef WIPPERSNAPPER_MANAGER_H
22
#define WIPPERSNAPPER_MANAGER_H
33

4-
#include "network_interfaces/Wippersnapper_ESP32.h"
5-
typedef Wippersnapper_ESP32 Wippersnapper_WiFi;
6-
#include "network_interfaces/Wippersnapper_ESP32_V2.h"
7-
typedef Wippersnapper_ESP32V2 Wippersnapper_WiFiV2;
4+
#include "network_interfaces/ws_networking_pico.h"
5+
typedef ws_networking_pico Wippersnapper_WiFi;
6+
#include "network_interfaces/ws_networking_pico_v2.h"
7+
typedef ws_networking_pico_v2 Wippersnapper_WiFiV2;
88

99
/****************************************************************************/
1010
/*!

0 commit comments

Comments
 (0)