Arduino

[Arduino] ESP32 기본 센서 호출 테스트

이주여이 2025. 4. 1. 22:27
#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);
    });
});