2-5 在ESP8266中接收 MQTT 消息

ESP8266 家庭自动化项目中文版目录​​​​​​​

现在让我们使用 mosquitto_pub 发布消息并在 ESP8266 中接收它。
为此,ESP8266 需要订阅 mosquitto_pub 将发布消息的相同主题。我们将主题称为 outdoor/light,它将发布 01 值。如果 ESP8266 的值为 1,它将打开连接到 GPIO 12 的 LED,如果它接收到 0,它将关闭该 LED:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

使用适合您网络的值更新这些值:

const char* wifi_network= "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
const char* mqtt_serv_address = "YOUR_MQTT_SERVER_IP";
const int mqtt_port_number = 1883;
#define OUTDOOR LIGHT 12
WiFiClient espClient;
PubsubClient client(espClient);
long lastMsg = 0;

启动与Wi-Fi网络的连接,并设置从MQTT代理接收消息时将调用的函数的名称,如下所示:

void setup() {
  pinMode(OUTDOOR_LIGHT, OUTPUT);
  //Initialize the BUILTIN LED pin as an output
  // 初始化BUILTIN LED引脚作为输出
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_serv_address, mqtt_port_number);
  client.setCallback(callback);
}

连接到Wi-Fi网络:

void setup_wifi() {
  delay(10);
  //我们首先连接到WiFi网络
  Serial.println();
  Serial.print("Connecting to");
  Serial.println(wifi_network);
  WiFi.begin(wifi_network, password);
  while(WiFi.status() != WL_CONNECTED) {
    WiFi.begin(wifi_network, password);
    Serial.print(".");
    delay(5000);
  }
  Serial.println("");
  Serial.println( "WiFi connected");
  Serial.println("IP address:");
  Serial.println(WiFi.localIP());
}

当消息到达 ESP8266 MQTT 客户端时,将带着 包含到达消息中的主题名称(模块可能订阅了多个主题) 的 topic 参数 ,消息的实际内容 payload 和 消息的长度 msg_length

void callback(char* topic, byte* payload, unsigned int msg_length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("]");
  for(inti=O;i<msg_length;i++){
    Serial.print((char)payload[i]);
  }
  Serial.println();
  // 如果收到第一个字符为 1 ,则打开LED
  if ((char)payload[0] == '0') {
    digitalWrite(OUTDOOR_LIGHT, LOW); //关闭 LED 
  } else {
    digitalWrite(OUTDOOR_LIGHT, HIGH); //打开 LED
  }
}

在 reconnect()函数中,它也将订阅 outdoor/light 主题并从中获取消息 ,如果与代理的连接丢失,它将每五秒尝试连接一次:

void reconnect( ) {
  //循环直到我们重新连接
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection. . .");
    //尝试连接
    if (client.connect("ESP8266Client")){
      Serial.println("connected");
      client.subscribe("outdoor/light");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println("try again in 5 seconds");
      //等待5秒再重试
      delay(5000);
    }
  }
}

loop()函数将发布 GPIO 12 的值,它实际上是室外灯的状态:

void loop() {
  if(!client.connected()){
    reconnect();
  }
  client.loop();
  long now = millis();
  if (now - lastMsg > 2000) {
    lastMsg = now;
    String light_state;
    if (digitalRead (OUTDOOR_LIGHT) == HIGH)
      light state = "ON";
    else
      light_state = "OFF";
    Serial.print("Publish message: ");
    Serial.println(light_state);
    client.publish ("outdoor/light/status", light_state.c_str());
   }
}

在终端窗口中,您将看到 ONOFF,具体取决于在 outdoor/light  主题上传输的最后一条消息的值。请注意,该模块正在订阅 outdoor/light 主题,并在 outdoor/light 主题上发布GPIO的状态:

发送和接收消息

猜你喜欢

转载自blog.csdn.net/countofdane/article/details/86713466