ESP32/ESP32-WROOM-32

ESP-WROOM-32 보드 사용하기 3편(MQTT)

원원 2024. 5. 26. 13:01

안녕하세요. 오늘은 MQTT에 대해 알아보겠습니다.
MQTT(Message Queuing Telemetry Transport)는 IoT(Internet Of Things)에서 주로 사용하는 프로토콜입니다. 


MQTT구조
MQTT는 브로커(Broker)를 통해서 클라이언트(Client)끼리 통신을 하는 구조입니다.
브로커가 서버역할이라고 보면됩니다.

1. A클라이언트가 브로커에게 발행(Publish)합니다. (발행: 브로커에게 데이터전송)
2. B클라이언트가 브로커에게 구독(Subscribe)합니다. (구독: 브로커에게 데이터를 받기위한 행동)
3. 브로커는 발행과 구독내용을 보고 일치하면 데이터를 보내줍니다.

발행과 구독을 할때는 토픽(Topic)과 페이로드(Payload)를 사용합니다. 토픽은 메세지의 ID이고 페이로드는 메세지의 내용입니다.

MQTT특징
1. 발행/구독 모델 
2. 낮은 전력 소비
3. 패킷 크기가 작아서 제한된 환경에서도 효율적으로 동작 가능
4. QoS(Quality of Service)지원 : 메시지의 신뢰성을 보장하기위해 세 가지 레벨 지원(QoS1,QoS2, Qos3)
1) Qos1 : 최소한의 전달(메세지가 전달안될수도 있음)
2) Qos2 : 최소 한 번 전달(메시지가 중복될수도 있음)
3) Qos3 : 정확히 한 번 전달(메시지가 중복되거나 손실되지 않음)


MQTT 아두이노에서 사용하기
1. MQTT를 사용하기위해서 pubsubclient를 검색해서 라이브러리를 설치합니다

2. 브로커는 "https://broker.mqtt-dashboard.com/"를 사용합니다. 무료서버이고 토픽과 메세지가 모두 공개됩니다(포트1883)
3. 클라이언트로는 ESP32, 스마트폰을 사용하겠습니다. 스마트폰은 플레이스토어에있는 MyMQTT앱을 이용하겠습니다. 만약 MyMQTT앱이 없다면 MQTT를 지원하는 다른 앱을 사용해도 상관없습니다.

4. ESP32에는 LED를 연결하고 스마트폰에서 on/off를 통해서 LED를 제어하겠습니다. ESP32에 조도센서(빛의 세기 감지)를 연결하고 스마트폰에게 ADC값을 전달하겠습니다.
(ESP32)
1) 구독 : LED제어를위한 "wowon/led"구독, Payload가 0이면 LED를 OFF하고 1이면 LED를 ON함
2) 발행 : 조도센서 ADC값 발행. Topic은 "wowon/cds", Payload는 ADC값 
(스마트폰)
1) 구독 : 조도센서 ADC값 수신을위한 "wowon/cds" 구독
2) 발행 : LED제어를위해 0,1 발행. Topic은 "wowon/led", Payload는 "0" or "1"

선연결

ESP32코드

#include <WiFi.h>
#include <PubSubClient.h>

const char* ssid = "my_wifi";
const char* password = "12345678";
const char* mqtt_server = "broker.mqtt-dashboard.com";

WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE	(50)
char msg[MSG_BUFFER_SIZE];


void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  randomSeed(micros());
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  if ((char)payload[0] == '1') {
    digitalWrite(15, HIGH);
  } else {
    digitalWrite(15, LOW);
  }
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    String clientId = "ESP32-";
    clientId += String(random(0xffff), HEX);
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      client.subscribe("wowon/led"); // subscribe
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void setup() {
  pinMode(15, OUTPUT); // LED OUTPUT
  Serial.begin(115200); // Setting the baudrate for debugging
  setup_wifi(); // wifi setting
  client.setServer(mqtt_server, 1883); // MQTT broker setting
  client.setCallback(callback); // When I received your subscription
}

void loop() {
   //Maintain connection with the server
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  unsigned long now = millis();
  // Publish the CDS ADC value once every second
  if (now - lastMsg > 1000) {
    lastMsg = now;

    snprintf (msg, MSG_BUFFER_SIZE, "CDS ADC : %d", analogRead(34));
    Serial.print("Publish message: ");
    Serial.println(msg);
    client.publish("wowon/cds", msg);
  }
}

1초마다 CDS ADC를 Publish 해줍니다. 그리고 "wowon/led"가 들어오면 callback 함수를 호출해서 payload를 읽고 led를 on/off합니다. (스마트폰 설정 이후의 사진)


스마트폰 (MyMQTT설정)