Arduino

[Arduino] HTML/Javascript에서 릴레이 모듈 전원 제어하기

이주여이 2025. 4. 7. 23:07

1. ino

#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <NTPClient.h>
#include "include/wifi.h"
#include "include/mqtt.h"

WiFiUDP      ntpUDP;

unsigned long lastTime             = 0;
const long interval                = 5000;
const char* relayOnTopic           = "/relay/on";
const char* relayOffTopic          = "/relay/off";
int relayPin                       = 26;

void setup() {
    Serial.begin(115200);

    setupWifi();
    setupMqtt();

    client.setServer(MQTT_SERVER, 1883);
    client.setCallback(callback);

    while(!client.connected()) {
        if(client.connect("ESP32Client")) {
            Serial.println("ESP32 연결 성공");

            client.subscribe(relayOnTopic);
            client.subscribe(relayOffTopic);

            Serial.println("mqtt 토픽 발행 성공");
        } else {
            Serial.println("ESP32 연결 실패");
            Serial.println("mqtt 토픽 발행 실패");

            delay(2000);
        }
    }

    timeClient.begin();

    pinMode(relayPin, OUTPUT);
    digitalWrite(relayPin, HIGH);
}

void callback(char* topic, byte* payload, unsigned int length) {
    String message = "";

    Serial.print("topic = ");
    Serial.println(topic);

    for (unsigned int i = 0; i < length; i++) {
        message += (char)payload[i];
    }

    Serial.print("message = ");
    Serial.println(message);

     if(strcmp(topic, relayOnTopic) == 0) {
         digitalWrite(relayPin, LOW);
     } else if(strcmp(topic, relayOffTopic) == 0) {
         digitalWrite(relayPin, HIGH);
     }
}

void loop() {
    // ... 관련없는 코드이므로 생략
}

void reconnectSetup() {
    while(!client.connected()) {
        if(client.connect("ESP32Client")) {
            Serial.println("mqtt 연결 성공");
        } else {
            Serial.println("mqtt 연결 실패 & 5초 후 재시도");

            delay(5000);
        }
    }
}

2. HTML

<!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">
<body>
    <section>
        <div id="control-wrap" style="display: block">
            <p class=l>Relay Module OFF</p>
                <div class="round">
                <input type=checkbox id="relay-module" name="relay-module" />
                <div class="back">
                    <label class=but for="relay-module">
                        <span class="on">I</span>
                        <span class="off">0</span>
                    </label>
                </div>
            </div>
            <p class=r>Relay Module ON</p>
        </div>
    </section>
</body>

<script src="https://cdn.jsdelivr.net/npm/mqtt@4.3.7/dist/mqtt.min.js"></script>
<script th:src="@{/js/admin_relay_test.js}"></script>
</html>

3. Javascript

let client;
const brokerUrl     = '';
const relayOnTopic  = '/relay/on';
const relayOffTopic = '/relay/off';

$(document).ready(() => {
    client = mqtt.connect(brokerUrl);

    client.on('connect', () => {
        console.log('mqtt 연결 성공');
    });

    $('#relay-module').change(function() {
        if($(this).is(':checked')) {
            client.publish(relayOnTopic, 'ON');
        } else {
            client.publish(relayOffTopic, 'OFF');
        }
    });
});

 

 

 

버튼 클릭할 때 마다 모니터링 화면에 토픽이랑 메세지가 표출되고 해당 토픽에 따라 릴레이 모듈을 제어한다.

 

참고로 스위치 CSS는 여기서 가져왔다.

 

 

Toggle switch with checkbox:checked

Round switch button in css with animation cleaned up. Inspired on the design of Paul Flavius, see: http://psd.tutsplus.com/tutorials/interface-tutoria...

codepen.io