1
0
mirror of https://github.com/adafruit/Adafruit_MQTT_Library.git synced 2025-12-19 20:02:29 +03:00

Merge pull request #235 from mikeysklar/mqtt-keep-alive

new example mqtt_airlift_subscribe_time_keepalive.ino
This commit is contained in:
Brent Rubell
2025-11-24 11:12:23 -05:00
committed by GitHub
2 changed files with 250 additions and 2 deletions

View File

@@ -0,0 +1,248 @@
/***************************************************
mqtt_airlift_subscribe_time_keepalive
Example demonstrating MQTT subscription and manual
KeepAlive handling for AirLift (ESP32 / NINA-FW)
devices using the Adafruit_MQTT_Library.
This example:
* Connects an AirLift device to WiFi
* Subscribes to io.adafruit.com/time/ISO-8601
* Manually manages MQTT KeepAlive intervals
* Sends periodic MQTT PINGs to maintain the
MQTT session (workaround for NINA-FW behavior)
Written by Bruce Conrad.
MIT license, all text above must be included in
any redistribution.
****************************************************/
#include <SPI.h>
#include <WiFiNINA.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
/************************* WiFi Setup *********************************/
// Update for your WiFi network.
#define WIFI_SSID "YOUR_WIFI_SSID"
#define WIFI_PASS "YOUR_WIFI_PASSWORD"
/************************* Adafruit IO Setup ***************************/
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 1883 // use 8883 for MQTTS
#define AIO_USERNAME "YOUR_ADAFRUIT_IO_USERNAME"
#define AIO_KEY "YOUR_ADAFRUIT_IO_KEY"
/************************* AirLift Pin Setup ***************************/
// These are the pins you provided and known-good.
#define SPIWIFI SPI
#define SPIWIFI_SS 13
#define SPIWIFI_IRQ 11
#define SPIWIFI_RESET 12
#define ESP32_GPIO0 -1
/*************************** Timing / Params ***************************/
// MQTT KeepAlive interval (seconds). The client must send at least one
// packet (e.g., PINGREQ) within this interval or the MQTT server will
// disconnect the session.
#define AIRLIFT_KEEPALIVE 30
// Safety margin (seconds) to subtract before sending a manual PING.
// AirLift/NINA-FW firmware does not reliably handle automatic MQTT
// KeepAlive packets, and real-world testing shows a 10 second margin
// prevents premature disconnects (“No socket available”).
#define KEEPALIVE_SAFETY_MARGIN 10
#define MAX_MQTT_RETRIES 5
#define SUBSCRIBE_WAIT_MS 1500
// Time (milliseconds) between manual MQTT PING operations.
#define PING_PERIOD_MS \
((AIRLIFT_KEEPALIVE - KEEPALIVE_SAFETY_MARGIN) * 1000)
/*************************** MQTT Objects ******************************/
WiFiClient client;
Adafruit_MQTT_Client mqtt(
&client,
AIO_SERVER,
AIO_SERVERPORT,
AIO_USERNAME,
AIO_KEY
);
Adafruit_MQTT_Subscribe time_subscription =
Adafruit_MQTT_Subscribe(&mqtt, "time/ISO-8601");
/*************************** State Vars *******************************/
unsigned long ping_clk = 0;
long ping_cnt = 0;
/*************************** MQTT Connect ******************************/
void MQTT_connect() {
unsigned long start = millis();
long attempts = 0;
while (attempts < MAX_MQTT_RETRIES) {
attempts++;
Serial.print("MQTT Connect Attempt #");
Serial.print(attempts);
Serial.print(" ... ");
int8_t ret = mqtt.connect();
if (ret == 0) {
Serial.print("Connected in ");
Serial.print(millis() - start);
Serial.println(" ms");
ping_clk = millis();
return;
}
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying in 5 seconds...");
mqtt.disconnect();
delay(5000);
}
Serial.println("ERROR: Maximum MQTT connect attempts exceeded.");
while (1) delay(10);
}
/*************************** MQTT PING Logic ***************************/
void MQTT_ping() {
if ((millis() - ping_clk) < PING_PERIOD_MS) return;
ping_cnt++;
unsigned long start = millis();
Serial.print("PING #");
Serial.print(ping_cnt);
Serial.print(" ... ");
for (int i = 0; i < MAX_MQTT_RETRIES; i++) {
if (mqtt.ping()) {
Serial.print("OK (");
Serial.print(millis() - start);
Serial.println(" ms)");
ping_clk = millis();
return;
}
Serial.print("fail ");
delay(1000);
}
Serial.println("\nERROR: No MQTT PING response. Halting.");
while (1) delay(10);
}
/*************************** WiFi Init *********************************/
void initWiFi() {
// IMPORTANT: passes the *SPI object* (SPIWIFI), not a pin
WiFi.setPins(SPIWIFI_SS, SPIWIFI_IRQ, SPIWIFI_RESET, ESP32_GPIO0, &SPIWIFI);
Serial.println("Starting AirLift WiFi...");
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("ERROR: Communication with AirLift failed.");
while (1) delay(10);
}
Serial.print("NINA-FW Version: ");
Serial.println(WiFi.firmwareVersion());
int status = WL_IDLE_STATUS;
while (status != WL_CONNECTED) {
Serial.print("Connecting to SSID: ");
Serial.println(WIFI_SSID);
status = WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.localIP()[0] == 0) {
delay(50);
}
}
Serial.println("WiFi connected.");
printCurrentNet();
printWiFiData();
}
/*************************** Helpers ***********************************/
void printCurrentNet() {
Serial.print("SSID: ");
Serial.print(WiFi.SSID());
byte bssid[6];
WiFi.BSSID(bssid);
Serial.print(" BSSID: ");
printMacAddress(bssid);
Serial.print(" RSSI: ");
Serial.print(WiFi.RSSI());
Serial.print(" Encryption: ");
Serial.println(WiFi.encryptionType(), HEX);
}
void printWiFiData() {
Serial.print("IP: ");
Serial.print(WiFi.localIP());
Serial.print(" Gateway: ");
Serial.print(WiFi.gatewayIP());
Serial.print(" Subnet: ");
Serial.print(WiFi.subnetMask());
byte mac[6];
WiFi.macAddress(mac);
Serial.print(" MAC: ");
printMacAddress(mac);
}
void printMacAddress(byte mac[]) {
for (int i = 5; i >= 0; i--) {
if (mac[i] < 16) Serial.print("0");
Serial.print(mac[i], HEX);
if (i > 0) Serial.print(":");
}
Serial.print(" ");
}
/*************************** Setup *************************************/
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("MQTT AirLift Subscribe + KeepAlive Example");
initWiFi();
mqtt.setKeepAliveInterval(AIRLIFT_KEEPALIVE);
mqtt.subscribe(&time_subscription);
MQTT_connect();
}
/*************************** Main Loop *********************************/
void loop() {
MQTT_ping();
Adafruit_MQTT_Subscribe *subscription =
mqtt.readSubscription(SUBSCRIBE_WAIT_MS);
if (subscription == &time_subscription) {
Serial.print("TIME FEED: ");
Serial.println((char *)time_subscription.lastread);
}
}

View File

@@ -1,5 +1,5 @@
name=Adafruit MQTT Library
version=2.6.1
version=2.6.2
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=MQTT library that supports the FONA, ESP8266, ESP32, Yun, and generic Arduino Client hardware.
@@ -7,4 +7,4 @@ paragraph=Simple MQTT library that supports the bare minimum to publish and subs
category=Communication
url=https://github.com/adafruit/Adafruit_MQTT_Library
architectures=*
depends=Adafruit SleepyDog Library, Adafruit FONA Library, WiFi101
depends=Adafruit SleepyDog Library, Adafruit FONA Library, WiFi101, WiFiNINA_-_Adafruit_Fork