#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <NTPClient.h>
#include "include/wifi.h"
#include "include/mqtt.h"
#include "include/led.h"
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 32400, 60000);
unsigned long lastTime = 0;
const long interval = 5000;
bool ledState = false;
const char* currentTopic = nullptr;
const char* mqttTestTopic = "/mqtt/mqtt_test";
const char* defaultSensorTestTopic = "/mqtt/default_sensor_test";
void setup() {
Serial.begin(115200);
setupWifi();
setupMqtt();
client.setServer(MQTT_SERVER, 1883);
client.setCallback(mqttCallback);
while(!client.connected()) {
if(client.connect("ESP32Client")) {
Serial.println("ESP32 연결 성공");
client.subscribe(mqttTestTopic);
client.subscribe(defaultSensorTestTopic);
Serial.println("mqtt 토픽 발행 성공");
} else {
Serial.println("ESP32 연결 실패");
Serial.println("mqtt 토픽 발행 실패");
delay(2000);
}
}
timeClient.begin();
}
void mqttCallback(char* topic, byte* payload, unsigned int length) {
String message = "";
for (unsigned int i = 0; i < length; i++) {
message += (char)payload[i];
}
}
void loop() {
if(!client.connected()) {
Serial.println("mqtt 연결 실패 & 재연결 시도");
reconnectSetup();
}
unsigned long currentMillis = millis();
if(currentMillis - lastTime >= interval) {
lastTime = currentMillis;
// => mqtt connect test
timeClient.update();
String formattedTime = timeClient.getFormattedTime();
time_t rawTime = timeClient.getEpochTime();
String responseMessage = "mqtt 통신 성공";
StaticJsonDocument<128> doc;
doc["message"] = responseMessage;
doc["timestamp"] = formattedTime.c_str(); // HH:MM:SS
doc["epoch"] = rawTime; // UNIX timestamp
char buffer[128];
serializeJson(doc, buffer);
client.publish(mqttTestTopic, buffer);
// => default sensor test
// 1. CPU 클럭 속도
int voltage = getCpuFrequencyMhz();
// 2. WiFi 신호 강도
long rssi = WiFi.RSSI();
// 3. RAM 메모리
int heapMemory = esp_get_free_heap_size();
StaticJsonDocument<128> doc2;
doc2["voltage"] = voltage;
doc2["rssi"] = rssi;
doc2["timestamp"] = formattedTime.c_str();
doc2["heapMemory"] = heapMemory;
char buffer2[128];
serializeJson(doc2, buffer2);
client.publish(defaultSensorTestTopic, buffer2);
}
client.loop();
}
void reconnectSetup() {
while(!client.connected()) {
if(client.connect("ESP32Client")) {
Serial.println("mqtt 연결 성공");
} else {
Serial.println("mqtt 연결 실패 & 5초 후 재시도");
delay(5000);
}
}
}
① WiFi 연결
② mqtt 연결
③ mqtt topic 발행
④ mqtt topic 구독 시 루프 돌면서 5초마다 센서 값 보내기
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{fragments/layout-admin}" layout:fragment="body">
<style>
th:first-child {width: 30%;}
th:nth-child(2), td:nth-child(2) {width: 30%;}
th:nth-child(3), td:nth-child(3) {width: 30%;}
</style>
<body>
<section>
<div id="home-wrap">
<!-- 현재 시간 표출 -->
<p id="menu-name">기본 센서 테스트</p>
</div>
<div class="data-result-info-box">
<span>마지막 업데이트 시간 : </span>
<span id="response-time"></span>
<p></p>
<span>응답 메세지 값 : </span>
<span id="response-data"></span>
</div>
<div class="data-box-wrap">
<div class="data-box">
<p class="data-box-title">CPU 클럭 속도</p>
<p id="voltage">0</p>
</div>
<div class="data-box">
<p class="data-box-title">RAM 메모리</p>
<p id="heap-memory">0</p>
</div>
<div class="data-box">
<p class="data-box-title">WiFi 강도</p>
<p id="rssi">0</p>
</div>
</div>
</section>
</body>
<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<script th:src="@{/js/admin_default_sensor_test.js}"></script>
</html>
HTML 특정 요소에 mqtt 구독 후 받은 메세지를 표출해야하기 때문에 id로 지정해서 작업을 진행했다.
script는 mqtt 라이브러리 및 아래 js 코드를 import 하는 부분이다.
$(document).ready(() => {
const topic = '/mqtt/default_sensor_test';
const client = mqtt.connect('ws://ljy.myddns.me:8081');
const message = 'MESSAGE';
client.on('connect', () => {
console.log('mqtt 연결 성공');
client.subscribe(topic, (e) => {
if(e) {
console.log(`mqtt 토픽 발행 실패 = ${e}`);
} else {
console.log(`mqtt 토픽 발행 성공 = ${topic}`);
}
});
});
client.publish(topic, message);
client.on('message', (topic, message) => {
const json = JSON.parse(message);
const responseData = message;
const timestamp = json.timestamp;
const voltage = json.voltage;
const battery = json.battery;
const rssi = json.rssi;
const heapMemory = json.heapMemory;
const responseTimeEl = $('#response-time');
const responseDataEl = $('#response-data');
const voltageEl = $('#voltage');
const batteryEl = $('#battery');
const rssiEl = $('#rssi');
const heapMemoryEl = $('#heap-memory');
responseTimeEl.text(timestamp);
responseDataEl.text(responseData);
voltageEl.text(voltage);
batteryEl.text(battery);
rssiEl.text(rssi);
heapMemoryEl.text(heapMemory);
});
});
'Arduino' 카테고리의 다른 글
[Arduino] HTML/Javascript에서 릴레이 모듈 전원 제어하기 (0) | 2025.04.07 |
---|---|
[Arduino] ESP32 4채널 릴레이 모듈 배선 작업 및 테스트 코드 작성 (0) | 2025.04.05 |
[Arduino] MQTT로 JSON 데이터 타입 전송하기(+ JSON, NTPClient 라이브러리 다운로드) (0) | 2025.03.29 |
[Arduino] HTML/Javascript에서 WebSocket, MQTT를 이용한 Arduino 통신 (0) | 2025.03.29 |
[Arduino] CLI에서 테스트 코드 실행하기 (0) | 2025.03.29 |