스위치 칩셋인 ESP8266칩셋에서 MQTT를 이용하여 컨트롤하고자 한다. 그러면 어떻게 ESP8266에서 이를 사용할 수 있을까?
아두이노 IDE가 설치되어있다 라는 가정하에 진행하겠습니다.
만약 설치가 안되어있다면 아래 링크에서 받으시면 됩니다
https://docs.arduino.cc/software/ide-v1/tutorials/Windows
1. MQTT 라이브러리 설치하기
우선 MQTT 라이브러리를 설치해야 이 기능을 사용할 수 있으므로 설치를 합니다.
아래 순서대로 진입합니다.
스케치 -> 라이브러리 포함하기 -> 라이브러리
이후 PubSubClient 검색하여
PubSubClient by Nick O'Leary
를 설치하시면 됩니다.
2. 코드 작성(ESP8255)
void mqtt_publish(char* message,const char* message){
if(!client.connected()){
reconnect();
}
client.loop();
client.publish(mqtt_topic, message);
delay(100);
client.loop_stop();
}
void callback(char* topic, byte* payload, unsigned int length) {
String Msg = "";
int i=0;
while (i<length) Msg += (char)payload[i++];
Serial.println(Msg);
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect(mqtt_id)) { //change to ClientID
Serial.println("connected");
// ... and resubscribe
client.subscribe(mqtt_topic_sub);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
각 함수별 설명입니다.
1번. mqtt_publish
Publish를 하는 함수입니다.
- client가 server랑 연결되었는지 확인합니다. 만약 끊겨있을 경우 재접속을 시도합니다.
- 보낼 메세지를 publish의 payload에 담습니다.
2번. 토픽 이름입니다.
Subscribe하는 콜백 함수입니다.
- byte 타입으로 온 메세지를 담을 String 타입 변수 Msg를 선언하고 여기에 메세지를 저장합니다.
- Msg를 출력합니다.
2번. 토픽 이름입니다.
MQTT 서버랑 재접속하는 함수입니다.
- client와 server가 연결되어있는지 확인합니다.
- 연결이 안되어있다면 연결 시도를 합니다.
- 재연결이 실패할 경우 5초후 재시도합니다.
아래는 풀 코드입니다.
#include <Ticker.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266mDNS.h>
#include <PubSubClient.h>
#define APSSID "WIFI 공유기 이름" //AP SSID
#define APPASSWORD "WIFI 공유기 비밀번호" //AP password
#define SERVERPORT 80 //Web server port
#define RELAYPIN 15 // GPIO12 relay pin -> GPIO15
#define LEDPIN 16 // GPIO13 GREEN LED (active low)-> GPIO16 change to wifi connect
#define BUTTONPIN 5 // GPIO0 button pin -> GPIO5
#define BUTTONTIME 0.05 // [s] time between button read
#define BUTTONON "color: green; border: 3px #fff outset;"
#define BUTTONOFF "color: red; border: 3px #fff outset;"
#define BUTTONNOACT "color: black; border: 7px #fff outset;"
#define BUTTONDEBOUNCE 1 //Minimum number of seconds between a valid button press or relay switch.
#define mqtt_server "MQTT 서버 도메인 or IP 주소"
#define mqtt_port 1883
#define mqtt_id "스위치 mqtt id"
#define mqtt_topic "MyHome/Light/Sub/Server"
#define mqtt_topic_sta "MyHome/Light/Sub/Server/State"
#define mqtt_topic_con "MyHome/Light/Sub/Server/Connect"
#define mqtt_topic_sub "MyHome/Light/Pub/bath Room"
bool LEDState = true; // Green LED off
bool RelayState = false; // Relay off
bool ButtonFlag = false; // Does the button need to be handled on this loop
char ButtonCount = 0; // How many cycles/checks the button has been pressed for.
String OnButt;
String OffButt;
//Setup classes needed from libraries.
MDNSResponder mdns;
Ticker buttonTick;
ESP8266WebServer server(SERVERPORT);
ESP8266HTTPUpdateServer httpUpdater;
//mqttclient
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
void setup(void){
// Init
pinMode(BUTTONPIN, INPUT);
pinMode(LEDPIN, OUTPUT);
pinMode(RELAYPIN, OUTPUT);
Serial.begin(115200);
delay(5000);
//Start wifi connection
Serial.println("Connecting to wifi..");
WiFi.begin(APSSID, APPASSWORD);
WiFi.mode(WIFI_STA);
//Print MAC to serial so we can use the address for auth if needed.
printMAC();
// Wait for connection - Slow flash
Serial.print("Waiting on Connection ...");
while (WiFi.status() != WL_CONNECTED) {
digitalWrite(LEDPIN, LOW);
delay(500);
Serial.print(".");
//Serial.println(WiFi.status());
digitalWrite(LEDPIN, HIGH);
delay(500);
}
setLED(false);
client.setServer(mqtt_server,mqtt_port);
client.setCallback(callback);
//Start up blink of LED signaling everything is ready. Fast Flash
for (int i = 0; i < 10; i++) {
setLED(!LEDState);
delay(100);
}
Serial.println("Server is up.");
//Enable periodic watcher for button event handling
buttonTick.attach(BUTTONTIME, buttonFlagSet);
}
//mqtt Start
void mqtt_publish(char* message,const char* message){
if(!client.connected()){
reconnect();
}
client.loop();
client.publish(mqtt_topic, message);
delay(100);
client.loop_stop();
}
void callback(char* topic, byte* payload, unsigned int length) {
String Msg = "";
int i=0;
while (i<length) Msg += (char)payload[i++];
Serial.println(Msg);
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect(mqtt_id)) { //change to ClientID
Serial.println("connected");
// ... and resubscribe
client.subscribe(mqtt_topic_sub);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
// mqtt END
/*
* setRelay
* Sets the state of the Relay
*/
void setRelay(bool SetRelayState) {
//Switch the HTML for the display page
if (SetRelayState == true) {
OnButt = BUTTONON;
OffButt = BUTTONNOACT;
}
if (SetRelayState == false) {
OnButt = BUTTONNOACT;
OffButt = BUTTONOFF;
}
//Set the relay state
RelayState = SetRelayState;
digitalWrite(RELAYPIN, RelayState);
//Set the LED to opposite of the button.
//setLED(!SetRelayState);
}
/*
* setLED
* Sets the state of the LED
*/
void setLED(bool SetLEDState) {
LEDState = SetLEDState; // set green LED
digitalWrite(LEDPIN, LEDState);
}
/*
* ButtonFlagSet
* Sets a variable so that on next loop, the button state is handled.
*/
void buttonFlagSet(void) {
ButtonFlag = true;
}
/* Read and handle button Press*/
void getButton(void) {
// short press butoon to change state of relay
if (digitalRead(BUTTONPIN) == false ) {
++ButtonCount;
}
if (digitalRead(BUTTONPIN) == false && ButtonCount > 1 && ButtonCount < 12 ) {
setRelay(!RelayState); // change relay
ButtonCount = 0;
delay(500);
}
/* long press button restart */
if (ButtonCount > 12) {
setLED(!LEDState);
buttonTick.detach(); // Stop Tickers
/* Wait for release button */
while (!digitalRead(BUTTONPIN)) yield();
delay(100);
ESP.restart();
}
if (digitalRead(BUTTONPIN) == true) ButtonCount = 0;
ButtonFlag = false;
}
/*
* loop
* System Loop
*/
void loop(void){
if (ButtonFlag) getButton();// Handle the button press
if(!client.connected()){
reconnect();
}
client.loop();
}
※ 위 코드는 현재 완성까지 끝낸 코드에서 일부 수정 등을 통한 코드이므로 어색한 부분이 있을수도 있습니다.
※ 버튼 제어 관련 코드는 외부 코드를 많이 참조하였습니다.
'홈 IoT > 기타' 카테고리의 다른 글
EPS8266 MQTT 통신(라이브러리 교체) (2) | 2024.06.15 |
---|---|
ESP8266 스위치 펌웨어 제작 (0) | 2023.05.10 |
DB 테이블 데이터 정리 (0) | 2023.05.09 |
파트 별 JSON 데이터 타입 설정 (0) | 2023.05.02 |