Arduino, NodeMCU, MQTT

이도현·2023년 8월 10일
0

아두이노 학습

목록 보기
32/34

  • MQTT: 머신 대 머신에서 사용되는 표준 기반 메시징 프로토콜 또는 규칙 세트
  • 일반적인 IoT 디바이스는 리소스 제약이 있는 네트워크를 통해 제한된 대역폭으로 전송하고 수신해야 합니다.
  • MQTT는 구현이 쉽고 데이터를 효율적으로 전송, 디바이스에서 클라우드로 클라우드에서 디바이스로 데이터 전송
  • MQTT는 브로커(Broker)라는 중앙 서버를 통해 메시지를 전달합니다. 디바이스에서는 MQTT 클라이언트를 실행하여 브로커와 연결하고, 메시지를 보내거나 받을 수 있습니다.

1. NodeMCU에서 MQTT를 사용하는 방법

1) NodeMCU에 MQTT 라이브러리를 설치
2) Wi-Fi 연결
3) MQTT 클라이언트 초기화
4) 브로커에 연결
5) 메시지 발행 또는 구독

2. 예제

#include <WifiMiniCom.h>
#include <PubSubClient.h>
#include <Led.h>

const char *ssid = "TECH2_2G";
const char *password = "tech21234!";

const char *mqtt_server = "172.30.1.127"; // mqtt broker ip address

WifiMiniCom com;

WiFiClient espClient;
PubSubClient client(espClient);
Led led(BUILTIN_LED);

int value = 0;

void callback(char *topic, byte *payload, unsigned int length) {
	char buf[128];
	memcpy(buf, payload, length);
	buf[length] = '\0';

	Serial.print("Message arrived [");
	Serial.print(topic);
	Serial.print("] ");
	Serial.println(buf);

	com.print(0, topic);
	com.print(1, buf);

	if (buf[0] == '1') {
	led.setValue(LOW);
	} else {
	led.setValue(HIGH);
	}
}

void reconnect() {
	while (!client.connected()) {
		Serial.print("Attempting MQTT connection...");
		if (client.connect("ESP8266Client")) { // 클라이언트 ID 중복 주의
		Serial.println("connected");
		client.publish("outTopic", "hello world"); 
		client.subscribe("inTopic"); // subscribe할 토픽 등록
		}
		else { // 연결실패한 경우 5초 후 재시도
			Serial.print("failed, rc=");
			Serial.print(client.state());
			Serial.println(" try again in 5 seconds"); 
			delay(5000);
		}
	}
}

void publish() {
	char msg[50];
	++value;
	sprintf(msg, "hello world #%ld", value);
	Serial.print("Publish message: ");
	Serial.println(msg);
	client.publish("outTopic", msg);
}

void setup() {
	com.init(ssid, password);
	com.setInterval(2000, publish);
	client.setServer(mqtt_server, 1883);
	client.setCallback(callback); // 토픽 수신시 호출할 함수 등록
}

void loop() {
	com.run();
	if (!client.connected()) {
		reconnect();
	}
	client.loop();
}

3. MqttCom

//MqttCom.h
#pragma once

#include <WifiMiniCom.h>
#include <PubSubClient.h>

class MqttCom: public WifiMiniCom {
protected:
	const char *server; // MQTT 브로커 IP 주소
	String client_id; // 클라이언트(NodeMCU의 ID)
	WiFiClient espClient;
	PubSubClient client;

	const char *topic; // subscribe 토픽명
	// void (*callback)(char*, uint8_t*, unsigned int);
	MQTT_CALLBACK_SIGNATURE; // subscribe 콜백 함수 포인터, 변수명은 callback
public :
	MqttCom(int serial_bps=115200, int lcd_addr=0x27);
	void init(const char *ssid, const char *password, int no_lcd=false);
	void setServer(const char *server, const char *topic = NULL, 
							MQTT_CALLBACK_SIGNATURE = NULL);
	void reconnect();
	void run();

	void publish(const char *topic, const char *value);
	void publish(const char *topic, int value);
	void publish(const char *topic, float value);
};
#include "MqttCom.h"

MqttCom::MqttCom(int serial_bps, int lcd_addr) : 
		WifiMiniCom(serial_bps, lcd_addr), client(espClient) {
	topic = NULL;
	callback = NULL;
	server = NULL;

	// 랜덤하게 클라이언트 ID 배정
	randomSeed(analogRead(0));
	int r = random(300);
	client_id = String("ESP8266Client") + r;
}

void MqttCom::init(const char *ssid, const char *password, int no_lcd) {
	WifiMiniCom::init(ssid, password);
	if(no_lcd) {
		WifiMiniCom::setNoLcd();
	}
}

void MqttCom::setServer(const char *server, const char *topic, 
											MQTT_CALLBACK_SIGNATURE) {
	this->server = server;
	this->callback = callback;
	this->topic = topic;
	
	client.setServer(server, 1883);
	if(callback != NULL) {
		client.setCallback(callback);
	}
}

void MqttCom::reconnect() {
	while (!client.connected()) {
		Serial.print("Attempting MQTT connection...");
		print(0, "try MQTT con...");\

		if (client.connect(client_id.c_str())) { // 클라이언트 ID 중복 주의
			Serial.println("connected");
			print(0, "MQTT connected");
				if(topic != NULL) {
				client.subscribe(topic);
				}
		} else {
		char buf[17];
		sprintf(buf, "failed, rc=%d", client.state());
		Serial.print(buf);
		print(0, buf);
		Serial.println(" try again in 5 seconds");
		print(1, "try again in 5 sec");
		delay(5000);
		}
	}
}

void MqttCom::run() {
	MiniCom::run();
	if (!client.connected()) {
		reconnect();
	}
	client.loop();
}
void MqttCom::publish(const char *topic, const char *value) {
	client.publish(topic, value);
}

void MqttCom::publish(const char *topic, int value) {
	char msg[10];
	sprintf(msg, "%d", value);
	client.publish(topic, msg);
}

void MqttCom::publish(const char *topic, float value) {
	String msg = "";
	msg += value;
	client.publish(topic, msg.c_str());
}
//app.ino
#include <MqttCom.h>
#include <Led.h>

const char *ssid = "Campus7_Room4_2.4GHz";
const char *password = NULL;
const char *mqtt_server = "192.168.0.159"; // mqtt broker ip address

MqttCom com;
Led led(BUILTIN_LED);

int value = 0;

void callback(char *topic, byte *payload, unsigned int length) {
	char buf[128];
	memcpy(buf, payload, length);
	buf[length] = '\0';

	com.print(0, topic);
	com.print(1, buf);

	if (buf[0] == '1') {
		led.setValue(LOW);
	} else {
		led.setValue(HIGH);
	}
}

void publish() {
	char msg[50];
	++value;
	sprintf(msg, "hello world #%ld", value);
	com.publish("outTopic", msg);
}

void setup() {
	com.init(ssid, password);
	com.setServer(mqtt_server, "inTopic", callback);
	com.setInterval(2000, publish);
}
void loop() {
	com.run();
}
// mqtt3

#include <MqttCom.h>
#include <Analog.h>
#include <DHT.h>

const char * sside = "TECHBREW_2G";
const char *password = "tech1234";
const char *matt_server = "192.168.0.159"; // mqtt broker ip address

MqttCom com;
Analog cds(A0, 100, 0);
DHT dht11(D7, DHT11);

void publish()
	int illu = cds.read();
	float humi, temp;
	humi = dht11.readnHumidity();
	temp = dht11.readTemperature();

	com.print(0, "T:", temp, "H:", humi);
	com.print(1, "i:", illu);

	// publish
	com.publish("iot/sensor/livingroom/illu", illu);
	com.publish("iot/sensor/bedrooem/temp", temp);
	com.publish("iot/sensor/kitchen/humli", humi);
}

void setup(){
	com.init(ssid, password);
	com.setServer(mqtt_server);  // publish만 수행
	//com.setserver(mqtt_server, "inTopic", callback)
	com.setInterver(3000, publish);
	dht11.begin();
}

void loop() {
}
profile
좋은 지식 나누어요

0개의 댓글