Skip to content

Commit a42e6e4

Browse files
committed
new example mqtt_airlift_subscribe_time_keepalive.ino
This approach stabilizes long-running MQTT connections on AirLift boards and prevents the “No socket available” disconnect condition that users are encountering.
1 parent 7f01eab commit a42e6e4

File tree

1 file changed

+243
-0
lines changed

1 file changed

+243
-0
lines changed
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
/***************************************************
2+
mqtt_airlift_subscribe_time_keepalive
3+
4+
Example demonstrating MQTT subscription and manual
5+
KeepAlive handling for AirLift (ESP32 / NINA-FW)
6+
devices using the Adafruit_MQTT_Library.
7+
8+
This example:
9+
* Connects an AirLift device to WiFi
10+
* Subscribes to io.adafruit.com/time/ISO-8601
11+
* Manually manages MQTT KeepAlive intervals
12+
* Sends periodic MQTT PINGs to maintain the
13+
MQTT session (workaround for NINA-FW behavior)
14+
15+
Written by Bruce Conrad.
16+
MIT license, all text above must be included in
17+
any redistribution.
18+
****************************************************/
19+
20+
#include <SPI.h>
21+
#include <WiFiNINA.h>
22+
#include "Adafruit_MQTT.h"
23+
#include "Adafruit_MQTT_Client.h"
24+
25+
/************************* WiFi Setup *********************************/
26+
// Update for your WiFi network.
27+
#define WIFI_SSID "YOUR_WIFI_SSID"
28+
#define WIFI_PASS "YOUR_WIFI_PASSWORD"
29+
30+
/************************* Adafruit IO Setup ***************************/
31+
#define AIO_SERVER "io.adafruit.com"
32+
#define AIO_SERVERPORT 1883 // use 8883 for MQTTS
33+
#define AIO_USERNAME "YOUR_ADAFRUIT_IO_USERNAME"
34+
#define AIO_KEY "YOUR_ADAFRUIT_IO_KEY"
35+
36+
/************************* AirLift Pin Setup ***************************/
37+
// These are the pins you provided and known-good.
38+
#define SPIWIFI SPI
39+
#define SPIWIFI_SS 13
40+
#define SPIWIFI_IRQ 11
41+
#define SPIWIFI_RESET 12
42+
#define ESP32_GPIO0 -1
43+
44+
/*************************** Timing / Params ***************************/
45+
#define AIRLIFT_KEEPALIVE 30
46+
#define MAX_MQTT_RETRIES 5
47+
#define SUBSCRIBE_WAIT_MS 1500
48+
#define PING_PERIOD_MS ((AIRLIFT_KEEPALIVE - 10) * 1000)
49+
50+
/*************************** MQTT Objects ******************************/
51+
WiFiClient client;
52+
53+
Adafruit_MQTT_Client mqtt(
54+
&client,
55+
AIO_SERVER,
56+
AIO_SERVERPORT,
57+
AIO_USERNAME,
58+
AIO_KEY
59+
);
60+
61+
Adafruit_MQTT_Subscribe time_subscription =
62+
Adafruit_MQTT_Subscribe(&mqtt, "time/ISO-8601");
63+
64+
/*************************** State Vars *******************************/
65+
unsigned long ping_clk = 0;
66+
long ping_cnt = 0;
67+
68+
/*************************** Function Prototypes ***********************/
69+
void initWiFi();
70+
void MQTT_connect();
71+
void MQTT_ping();
72+
void printCurrentNet();
73+
void printWiFiData();
74+
void printMacAddress(byte mac[]);
75+
76+
/*************************** Setup *************************************/
77+
void setup() {
78+
Serial.begin(115200);
79+
while (!Serial) delay(10);
80+
81+
Serial.println("MQTT AirLift Subscribe + KeepAlive Example");
82+
83+
initWiFi();
84+
85+
mqtt.setKeepAliveInterval(AIRLIFT_KEEPALIVE);
86+
mqtt.subscribe(&time_subscription);
87+
88+
MQTT_connect();
89+
}
90+
91+
/*************************** Main Loop *********************************/
92+
void loop() {
93+
94+
MQTT_ping();
95+
96+
Adafruit_MQTT_Subscribe *subscription =
97+
mqtt.readSubscription(SUBSCRIBE_WAIT_MS);
98+
99+
if (subscription == &time_subscription) {
100+
Serial.print("TIME FEED: ");
101+
Serial.println((char *)time_subscription.lastread);
102+
}
103+
}
104+
105+
/*************************** MQTT Connect ******************************/
106+
void MQTT_connect() {
107+
108+
unsigned long start = millis();
109+
long attempts = 0;
110+
111+
while (attempts < MAX_MQTT_RETRIES) {
112+
attempts++;
113+
114+
Serial.print("MQTT Connect Attempt #");
115+
Serial.print(attempts);
116+
Serial.print(" ... ");
117+
118+
int8_t ret = mqtt.connect();
119+
120+
if (ret == 0) {
121+
Serial.print("Connected in ");
122+
Serial.print(millis() - start);
123+
Serial.println(" ms");
124+
ping_clk = millis();
125+
return;
126+
}
127+
128+
Serial.println(mqtt.connectErrorString(ret));
129+
Serial.println("Retrying in 5 seconds...");
130+
mqtt.disconnect();
131+
delay(5000);
132+
}
133+
134+
Serial.println("ERROR: Maximum MQTT connect attempts exceeded.");
135+
while (1) delay(10);
136+
}
137+
138+
/*************************** MQTT PING Logic ***************************/
139+
void MQTT_ping() {
140+
if ((millis() - ping_clk) < PING_PERIOD_MS) return;
141+
142+
ping_cnt++;
143+
unsigned long start = millis();
144+
145+
Serial.print("PING #");
146+
Serial.print(ping_cnt);
147+
Serial.print(" ... ");
148+
149+
for (int i = 0; i < MAX_MQTT_RETRIES; i++) {
150+
151+
if (mqtt.ping()) {
152+
Serial.print("OK (");
153+
Serial.print(millis() - start);
154+
Serial.println(" ms)");
155+
ping_clk = millis();
156+
return;
157+
}
158+
159+
Serial.print("fail ");
160+
delay(1000);
161+
}
162+
163+
Serial.println("\nERROR: No MQTT PING response. Halting.");
164+
while (1) delay(10);
165+
}
166+
167+
/*************************** WiFi Init *********************************/
168+
void initWiFi() {
169+
170+
// IMPORTANT: passes the *SPI object* (SPIWIFI), not a pin
171+
WiFi.setPins(SPIWIFI_SS, SPIWIFI_IRQ, SPIWIFI_RESET, ESP32_GPIO0, &SPIWIFI);
172+
173+
Serial.println("Starting AirLift WiFi...");
174+
175+
if (WiFi.status() == WL_NO_SHIELD) {
176+
Serial.println("ERROR: Communication with AirLift failed.");
177+
while (1) delay(10);
178+
}
179+
180+
Serial.print("NINA-FW Version: ");
181+
Serial.println(WiFi.firmwareVersion());
182+
183+
int status = WL_IDLE_STATUS;
184+
185+
while (status != WL_CONNECTED) {
186+
Serial.print("Connecting to SSID: ");
187+
Serial.println(WIFI_SSID);
188+
189+
status = WiFi.begin(WIFI_SSID, WIFI_PASS);
190+
191+
while (WiFi.localIP()[0] == 0) {
192+
delay(50);
193+
}
194+
}
195+
196+
Serial.println("WiFi connected.");
197+
printCurrentNet();
198+
printWiFiData();
199+
}
200+
201+
/*************************** Helpers ***********************************/
202+
void printCurrentNet() {
203+
Serial.print("SSID: ");
204+
Serial.print(WiFi.SSID());
205+
206+
byte bssid[6];
207+
WiFi.BSSID(bssid);
208+
209+
Serial.print(" BSSID: ");
210+
printMacAddress(bssid);
211+
212+
Serial.print(" RSSI: ");
213+
Serial.print(WiFi.RSSI());
214+
215+
Serial.print(" Encryption: ");
216+
Serial.println(WiFi.encryptionType(), HEX);
217+
}
218+
219+
void printWiFiData() {
220+
Serial.print("IP: ");
221+
Serial.print(WiFi.localIP());
222+
223+
Serial.print(" Gateway: ");
224+
Serial.print(WiFi.gatewayIP());
225+
226+
Serial.print(" Subnet: ");
227+
Serial.print(WiFi.subnetMask());
228+
229+
byte mac[6];
230+
WiFi.macAddress(mac);
231+
232+
Serial.print(" MAC: ");
233+
printMacAddress(mac);
234+
}
235+
236+
void printMacAddress(byte mac[]) {
237+
for (int i = 5; i >= 0; i--) {
238+
if (mac[i] < 16) Serial.print("0");
239+
Serial.print(mac[i], HEX);
240+
if (i > 0) Serial.print(":");
241+
}
242+
Serial.print(" ");
243+
}

0 commit comments

Comments
 (0)