MQTT③创建两个客户端交换信息

此篇教程的内容是跟随【零知ESP32教程】MQTT②创建客户端发送温度数据

在上一个教程MQTT②中,我们创建了一个客户端发送温度数据,然后输出到显示屏上,同时也在等待接收数据来控制LED。 因此我们还需要创建一个客户端先接收温度数据并显示出来,然后再给第一个客户端发送消息控制LED。

一、软件和硬件

LCD1602引脚说明:

ESP32 #2 连线:

安装运行程序运行时必备的库:

1、安装运行必备的库文件,AsyncMqttClient 和 AsyncTCP,如果在上个教程中已安装,则直接使用就行,没有安装可以看从上一个教程里下载库。

2、安装LCD1602驱动,将下面的LiquidCrystal_I2C解压后放到工程目录下即可。

LiquidCrystal_I2C.zip(点击下载)

在导入代码之后,要在第10,11行替换自己的WiFi名称和密码。 在第15行替换自己的MQTT服务器IP地址。


							
	#include <WiFi.h>
	extern "C" {
	        #include "freertos/FreeRTOS.h"
	        #include "freertos/timers.h"
	}
	#include <AsyncMqttClient.h>
	#include "LiquidCrystal_I2C.h"
	 
	// Change the credentials below, so your ESP32 connects to your router
	#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
	#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"
	 
	// Change the MQTT_HOST variable to your IP address,
	// so it connects to your Mosquitto MQTT broker
	#define MQTT_HOST IPAddress(192, 168, X, XXX)
	#define MQTT_PORT 1883
	 
	// Create objects to handle MQTT client
	AsyncMqttClient mqttClient;
	TimerHandle_t mqttReconnectTimer;
	TimerHandle_t wifiReconnectTimer;
	 
	// Set the LCD number of columns and rows
	const int lcdColumns = 16;
	const int lcdRows = 2;
	 
	// Set LCD address, number of columns and rows
	// if you don't know your display address, run an I2C scanner sketch
	LiquidCrystal_I2C lcd(0x3f, lcdColumns, lcdRows);
	 
	// Thermometer icon
	byte thermometerIcon[8] = {
	        B00100,
	        B01010,
	        B01010,
	        B01010,
	        B01010,
	        B10001,
	        B11111,
	        B01110
	};
	 
	// Define GPIO where the pushbutton is connected to
	const int buttonPin = 32;
	int buttonState;                      // current reading from the input pin (pushbutton)
	int lastButtonState = LOW;            // previous reading from the input pin (pushbutton)
	unsigned long lastDebounceTime = 0;   // the last time the output pin was toggled
	unsigned long debounceDelay = 50;     // the debounce time; increase if the output flickers
	 
	void connectToWifi() {
	        Serial.println("Connecting to Wi-Fi...");
	        WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
	}
	 
	void connectToMqtt() {
	        Serial.println("Connecting to MQTT...");
	        mqttClient.connect();
	}
	 
	void WiFiEvent(WiFiEvent_t event) {
	        Serial.printf("[WiFi-event] event: %d\n", event);
	        switch(event) {
	                case SYSTEM_EVENT_STA_GOT_IP:
	                Serial.println("WiFi connected");
	                Serial.println("IP address: ");
	                Serial.println(WiFi.localIP());
	                connectToMqtt();
	                break;
	                case SYSTEM_EVENT_STA_DISCONNECTED:
	                Serial.println("WiFi lost connection");
	                xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
	                xTimerStart(wifiReconnectTimer, 0);
	                break;
	        }
	}
	 
	// Add more topics that want your ESP32 to be subscribed to
	void onMqttConnect(bool sessionPresent) {
	        Serial.println("Connected to MQTT.");
	        Serial.print("Session present: ");
	        Serial.println(sessionPresent);
	        uint16_t packetIdSub = mqttClient.subscribe("esp32/temperature", 0);
	        Serial.print("Subscribing at QoS 0, packetId: ");
	        Serial.println(packetIdSub);
	}
	 
	void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
	        Serial.println("Disconnected from MQTT.");
	        if (WiFi.isConnected()) {
	                xTimerStart(mqttReconnectTimer, 0);
	        }
	}
	 
	void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
	        Serial.println("Subscribe acknowledged.");
	        Serial.print("  packetId: ");
	        Serial.println(packetId);
	        Serial.print("  qos: ");
	        Serial.println(qos);
	}
	 
	void onMqttUnsubscribe(uint16_t packetId) {
	        Serial.println("Unsubscribe acknowledged.");
	        Serial.print("  packetId: ");
	        Serial.println(packetId);
	}
	 
	void onMqttPublish(uint16_t packetId) {
	        Serial.println("Publish acknowledged.");
	        Serial.print("  packetId: ");
	        Serial.println(packetId);
	}
	 
	// You can modify this function to handle what happens when you receive a certain message in a specific topic
	void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
	        String messageTemp;
	        for (int i = 0; i < len; i++) {
	                //Serial.print((char)payload[i]);
	                messageTemp += (char)payload[i];
	        }
	        if (strcmp(topic, "esp32/temperature") == 0) {
	                lcd.clear();
	                lcd.setCursor(1, 0);
	                lcd.write(0);
	                lcd.print(" Temperature");
	                lcd.setCursor(0, 1);
	                lcd.print(messageTemp);
	        }
	         
	        Serial.println("Publish received.");
	        Serial.print("  message: ");
	        Serial.println(messageTemp);
	        Serial.print("  topic: ");
	        Serial.println(topic);
	        Serial.print("  qos: ");
	        Serial.println(properties.qos);
	        Serial.print("  dup: ");
	        Serial.println(properties.dup);
	        Serial.print("  retain: ");
	        Serial.println(properties.retain);
	        Serial.print("  len: ");
	        Serial.println(len);
	        Serial.print("  index: ");
	        Serial.println(index);
	        Serial.print("  total: ");
	        Serial.println(total);
	}
	 
	void setup() {
	        // Initialize LCD
	        lcd.init();
	        // Turn on LCD backlight
	        lcd.backlight();
	        // Create thermometer icon
	        lcd.createChar(0, thermometerIcon);
	         
	        // Define buttonPin as an INPUT
	        pinMode(buttonPin, INPUT);
	         
	        Serial.begin(115200);
	         
	        mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
	        wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToWifi));
	         
	        WiFi.onEvent(WiFiEvent);
	         
	        mqttClient.onConnect(onMqttConnect);
	        mqttClient.onDisconnect(onMqttDisconnect);
	        mqttClient.onSubscribe(onMqttSubscribe);
	        mqttClient.onUnsubscribe(onMqttUnsubscribe);
	        mqttClient.onMessage(onMqttMessage);
	        mqttClient.onPublish(onMqttPublish);
	        mqttClient.setServer(MQTT_HOST, MQTT_PORT);
	         
	        connectToWifi();
	}
	 
	void loop() {
	        // Read the state of the pushbutton and save it in a local variable
	        int reading = digitalRead(buttonPin);
	         
	        // If the pushbutton state changed (due to noise or pressing it), reset the timer
	        if (reading != lastButtonState) {
	                // Reset the debouncing timer
	                lastDebounceTime = millis();
	        }
	         
	        // If the button state has changed, after the debounce time
	        if ((millis() - lastDebounceTime) > debounceDelay) {
	                // And if the current reading is different than the current buttonState
	                if (reading != buttonState) {
	                        buttonState = reading;
	                        // Publish an MQTT message on topic esp32/led to toggle the LED (turn the LED on or off)P
	                        if (buttonState == HIGH) {
	                                mqttClient.publish("esp32/led", 0, true, "toggle");
	                                Serial.println("Publishing on topic esp32/led topic at QoS 0");
	                        }
	                }
	        }
	        // Save the reading. Next time through the loop, it'll be the lastButtonState
	        lastButtonState = reading;
	}
							
						

验证程序后并上传到ESP32,打开调试窗口,可以看到已经成功连入MQTT服务器,并且成功接收到主题为 esp32/temperature 的消息: