아두이노 우노 Q 웹 서버

Arduino UNO Q에는 내장 Debian Linux MPU가 있으므로 전체 웹 서버를 실행할 수 있습니다 - 추가 Wi-Fi 쉴드나 클라우드 서비스가 필요하지 않습니다. 이 튜토리얼에서는 세 개의 점진적인 예제를 통해 Arduino UNO Q에서 Python WebUI 웹 서버를 실행하는 방법을 보여줍니다. 가장 간단한 페이지부터 시작하여 깔끔한 API를 구축합니다.

이 튜토리얼에서 배우게 될 내용:

Arduino UNO Q 웹 서버

필요한 하드웨어

1×Arduino UNO Q 아마존
1×USB Cable for Arduino Uno Q 아마존
1×포텐셔미터 쿠팡 | 아마존
1×노브가 있는 포텐셔미터 모듈 쿠팡 | 아마존
1×브레드보드 쿠팡 | 아마존
1×점퍼케이블 쿠팡 | 아마존
1×(추천) 아두이노 우노용 스크루 터미널 블록 쉴드 쿠팡 | 아마존
1×(추천) Sensors/Servo Expansion Shield for Arduino Uno 쿠팡 | 아마존
1×(추천) 아두이노 우노용 브레드보드 쉴드 쿠팡 | 아마존
1×(추천) 아두이노 우노용 케이스 쿠팡 | 아마존
1×(추천) 아두이노 우노용 프로토타이핑 베이스 플레이트 & 브레드보드 키트 아마존
공개: 이 포스팅 에 제공된 일부 링크는 아마존 제휴 링크입니다. 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

Arduino UNO Q 웹 서버 작동 방식

Arduino UNO Q는 두 개의 프로세서를 결합합니다:

  • STM32 MCU — Arduino 스케치(C/C++)를 실시간으로 실행합니다. 센서를 읽고, 릴레이를 제어하며, 모터를 구동하는 등의 작업을 합니다.
  • Qualcomm MPU — 전체 Debian Linux를 실행합니다. Wi-Fi에 연결되고 Python WebUI 웹 서버를 실행할 수 있으므로 네트워크의 모든 브라우저에서 액세스할 수 있습니다.

두 프로세서는 Bridge를 통해 통신합니다. MCU는 Bridge를 통해 하드웨어 함수를 노출하고, MPU의 Python 웹 서버는 이러한 함수를 호출하여 센서 판독값을 얻습니다. 그런 다음 브라우저는 데이터를 가져옵니다 - 순수 HTML 페이지, 스타일이 지정된 웹 페이지 또는 JSON API 응답으로.

※ 주의:

외부 Wi-Fi 쉴드가 필요하지 않습니다. Arduino UNO Q에는 Linux 측에 내장 Wi-Fi가 있습니다.

배선도

Arduino UNO Q 가변저항 연결 배선도

이 이미지는 Fritzing을 사용하여 만들어졌습니다. 이미지를 확대하려면 클릭하세요.

Arduino UNO Q 코드

Arduino UNO Q에는 두 개의 프로세서가 있습니다. 웹 서버의 경우 다음을 작성합니다:

  • 아날로그 핀을 읽고 Bridge를 통해 값을 노출하는 MCU 스케치.
  • Linux MPU에서 HTTP를 통해 값을 제공하는 Python WebUI 스크립트.

아래의 세 예제 모두 동일한 MCU 스케치를 사용합니다. Python 코드(및 선택적 HTML 자산)만 다릅니다.

예제 1 — 간단한 웹 페이지 (CSS, JavaScript 없음)

가장 간단한 웹 서버: 브라우저를 열고, 보드의 IP를 방문하고, 순수 HTML로 원시 아날로그 판독값을 표시합니다. 스타일 없음, 자동 새로고침 없음 — 숫자만 표시됩니다.

MCU 스케치는 핀 A0을 읽고 get_analog라는 Bridge 함수를 통해 값을 노출합니다. Python 서버는 브라우저가 /을 요청할 때 해당 함수를 호출하고 순수 HTML 응답을 반환합니다.

MCU 코드

/* * 이 Arduino UNO Q 코드는 newbiely.kr 에서 개발되었습니다 * 이 Arduino UNO Q 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino-uno-q/arduino-uno-q-web-server */ #include "Arduino_RouterBridge.h" String get_analog(String arg) { int value = analogRead(A0); return String(value); } void setup() { Monitor.begin(); Bridge.begin(); Bridge.provide_safe("get_analog", get_analog); Monitor.println("Bridge ready"); } void loop() { }

Python 코드

/* * 이 Arduino UNO Q 코드는 newbiely.kr 에서 개발되었습니다 * 이 Arduino UNO Q 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino-uno-q/arduino-uno-q-web-server */ from arduino.app_utils import * from arduino.app_bricks.web_ui import WebUI from fastapi.responses import HTMLResponse def index(): value = Bridge.call("get_analog", "") html = "<!DOCTYPE html><html><body><p>Analog A0: " + value + "</p></body></html>" return HTMLResponse(content=html) web_ui = WebUI() web_ui.expose_api("GET", "/", index) App.run()

빠른 단계

  • 연결: Arduino UNO Q를 USB-C 케이블로 컴퓨터에 연결하고 배선도 섹션에 설명된 대로 포텐셔미터를 A0에 배선합니다.
  • Wi-Fi 연결: Arduino UNO Q가 Wi-Fi 네트워크에 연결되어 있는지 확인합니다. Arduino App Lab의 네트워크 아이콘을 사용하여 먼저 연결합니다.
  • Arduino App Lab 열기: Arduino App Lab을 시작하고 Arduino UNO Q가 감지될 때까지 기다립니다.
  • 새 App 만들기: Create New App 버튼을 클릭합니다.
create new app in 아두이노 app lab on Arduino UNO Q
  • App에 이름을 지정합니다(예: WebServerSimple).
  • Create를 클릭하여 확인합니다.
아두이노 app lab app folders and files on Arduino UNO Q
  • MCU 스케치 붙여넣기: 위의 MCU 코드를 복사하여 sketch/sketch.ino에 붙여넣습니다.
  • Python 코드 붙여넣기: App의 python/main.py를 엽니다. 기존 내용을 모두 선택하고 삭제한 다음 위의 Python 웹 서버 코드를 붙여넣습니다.
  • Install the library: Click the Add sketch library button (the open book icon with a + sign) in the left sidebar.
add sketch 라이브러리 in 아두이노 app lab on Arduino UNO Q
  • Search for Arduino_RouterBridge created by Arduino and click the Install button.
My Apps / DIYables Apps
Run
Bricks
No bricks added...
Sketch Libraries
No sketch libra...
Files
python
sketch
.gitignore
README.md
app.yaml
sketch.ino
Add sketch library
Arduino_RouterBridge Arduino

This library provides a simple RPC bridge for Arduino UNO Q boards, allowing communication between the board and other devices using MsgPack serialization.

0.4.1
Install
More Info
  • WebUI Brick 추가: Editor 사이드바의 Add Brick 버튼을 클릭하여 Bricks 카탈로그를 엽니다.
add brick 버튼 in 아두이노 app lab editor sidebar

목록에서 WebUI - HTML을 찾아 선택한 다음 구성 프롬프트를 따릅니다.

webui - html brick selected in 아두이노 app lab bricks catalog

Arduino App Lab이 자동으로 app.yaml 파일에 Brick 항목을 추가합니다 - 그 항목을 수동으로 편집하지 마세요.

※ 주의:

Brick은 Arduino UNO Q Linux 측에서 실행되는 사전 구축된 플러그 앤 플레이 서비스입니다. WebUI - HTML Brick은 HTTP 서버를 처리하므로 Flask 또는 다른 웹 프레임워크를 수동으로 설치할 필요가 없습니다. 자세한 내용은 About Bricks를 참조하세요.

  • 업로드: Arduino App Lab에서 Run 버튼을 클릭합니다.
click run 버튼 in 아두이노 app lab on Arduino UNO Q
  • 휴대폰 또는 PC의 웹 브라우저를 열고 다음으로 이동합니다: http://:7000/

를 Arduino UNO Q의 IP 주소로 바꿉니다.

  • A0의 현재 원시 ADC 값을 표시하는 순수 HTML 페이지가 표시됩니다.
  • 포텐셔미터 노브를 회전하고 브라우저 페이지를 새로고침합니다 - 숫자가 변경됩니다.

App Lab 콘솔 출력

DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
Message (Enter to send a message to "Newbiely" on usb(2820070321))
New Line
9600 baud
[2026-05-08 09:00:01] Bridge ready
DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
[2026-05-08 09:00:02] WebUI started on http://0.0.0.0:7000 [2026-05-08 09:00:02] WebUI started on http://192.168.0.45:7000

브라우저 출력

브라우저에서 http://<ARDUINO_UNO_Q_IP>:7000/을 엽니다. 다음과 같은 순수 HTML 페이지가 표시됩니다:

Analog A0: 512

_RENDER

Arduino UNO Q simple 웹 서버 page

자산 폴더가 있는 웹 서버 (HTML + CSS + JavaScript)

이 예제는 blink-with-ui 예제처럼 프런트 엔드 파일을 assets/ 폴더로 분리합니다. Python 서버는 /api/analog 끝점을 노출합니다. 자산 폴더의 index.html은 JavaScript를 사용하여 매초 해당 끝점을 호출하고 표시된 값을 업데이트합니다 - 페이지 새로고침이 필요하지 않습니다.

MCU 스케치는 예제 1과 동일합니다. 차이점은:

  • Python 코드가 순수 HTML 경로 대신 /api/analog을 노출합니다.
  • assets/index.html 파일에는 HTML, CSS 및 JavaScript가 포함됩니다.
  • WebUI Brick은 assets/ 폴더의 모든 파일을 루트 URL(/)에서 자동으로 제공합니다.

MCU 코드

/* * 이 Arduino UNO Q 코드는 newbiely.kr 에서 개발되었습니다 * 이 Arduino UNO Q 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino-uno-q/arduino-uno-q-web-server */ #include "Arduino_RouterBridge.h" String get_analog(String arg) { int value = analogRead(A0); return String(value); } void setup() { Monitor.begin(); Bridge.begin(); Bridge.provide_safe("get_analog", get_analog); Monitor.println("Bridge ready"); } void loop() { }

Python 코드

/* * 이 Arduino UNO Q 코드는 newbiely.kr 에서 개발되었습니다 * 이 Arduino UNO Q 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino-uno-q/arduino-uno-q-web-server */ from arduino.app_utils import * from arduino.app_bricks.web_ui import WebUI def get_analog(): value = Bridge.call("get_analog", "") return {"pin": "A0", "value": int(value)} web_ui = WebUI() web_ui.expose_api("GET", "/api/analog", get_analog) App.run()

HTML (assets/index.html)

이 파일을 App의 assets/ 폴더에 배치하세요:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Analog Sensor</title> <style> *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'Segoe UI', Arial, sans-serif; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; background: linear-gradient(135deg, #0f2027, #203a43, #2c5364); color: #fff; padding: 24px; } .card { background: rgba(255, 255, 255, 0.07); backdrop-filter: blur(12px); border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 20px; padding: 48px 56px; text-align: center; width: 100%; max-width: 380px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4); } .pin-badge { display: inline-block; background: rgba(0, 188, 212, 0.2); border: 1px solid #00bcd4; color: #00bcd4; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; padding: 4px 12px; border-radius: 999px; margin-bottom: 20px; } h1 { font-size: 1.35rem; font-weight: 600; color: #e0e0e0; margin-bottom: 32px; letter-spacing: 0.02em; } /* Gauge ring */ .gauge-wrap { position: relative; width: 160px; height: 160px; margin: 0 auto 32px; } .gauge-wrap svg { transform: rotate(-90deg); width: 160px; height: 160px; } .gauge-bg { fill: none; stroke: rgba(255,255,255,0.08); stroke-width: 12; } .gauge-fill { fill: none; stroke: url(#gaugeGrad); stroke-width: 12; stroke-linecap: round; stroke-dasharray: 440; stroke-dashoffset: 440; transition: stroke-dashoffset 0.6s ease; } .gauge-center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; } .gauge-value { font-size: 2.4rem; font-weight: 700; color: #fff; line-height: 1; } .gauge-unit { font-size: 0.75rem; color: rgba(255,255,255,0.5); margin-top: 4px; letter-spacing: 0.08em; } /* Progress bar */ .bar-wrap { background: rgba(255,255,255,0.08); border-radius: 999px; height: 8px; overflow: hidden; margin-bottom: 10px; } .bar-fill { height: 100%; width: 0%; border-radius: 999px; background: linear-gradient(90deg, #00bcd4, #7c4dff); transition: width 0.6s ease; } .bar-labels { display: flex; justify-content: space-between; font-size: 0.72rem; color: rgba(255,255,255,0.4); margin-bottom: 28px; } /* Voltage row */ .voltage-row { display: flex; align-items: center; justify-content: center; gap: 8px; font-size: 0.9rem; color: rgba(255,255,255,0.6); } .voltage-val { font-size: 1.05rem; font-weight: 600; color: #80cbc4; } /* Status dot */ .status { display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: 28px; font-size: 0.75rem; color: rgba(255,255,255,0.35); letter-spacing: 0.06em; text-transform: uppercase; } .dot { width: 7px; height: 7px; border-radius: 50%; background: #4caf50; animation: pulse 2s infinite; } .dot.error { background: #f44336; animation: none; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } } </style> </head> <body> <div class="card"> <span class="pin-badge">Pin A0</span> <h1>Analog Sensor</h1> <div class="gauge-wrap"> <svg viewBox="0 0 160 160"> <defs> <linearGradient id="gaugeGrad" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" stop-color="#00bcd4" /> <stop offset="100%" stop-color="#7c4dff" /> </linearGradient> </defs> <circle class="gauge-bg" cx="80" cy="80" r="70" /> <circle class="gauge-fill" id="gaugeFill" cx="80" cy="80" r="70" /> </svg> <div class="gauge-center"> <span class="gauge-value" id="val">--</span> <span class="gauge-unit">/ 1023</span> </div> </div> <div class="bar-wrap"> <div class="bar-fill" id="bar"></div> </div> <div class="bar-labels"><span>0</span><span>1023</span></div> <div class="voltage-row"> Voltage: <span class="voltage-val" id="volt">--</span> V </div> <div class="status"> <div class="dot" id="dot"></div> <span id="statusText">connecting…</span> </div> </div> <script> var CIRCUMFERENCE = 2 * Math.PI * 70; // ~439.8 function refresh() { fetch('/api/analog') .then(function(r) { return r.json(); }) .then(function(d) { var raw = d.value; var pct = raw / 1023; document.getElementById('val').textContent = raw; document.getElementById('bar').style.width = (pct * 100).toFixed(1) + '%'; document.getElementById('gaugeFill').style.strokeDashoffset = (CIRCUMFERENCE * (1 - pct)).toFixed(2); document.getElementById('volt').textContent = (pct * 5).toFixed(2); document.getElementById('dot').className = 'dot'; document.getElementById('statusText').textContent = 'live'; }) .catch(function() { document.getElementById('dot').className = 'dot error'; document.getElementById('statusText').textContent = 'disconnected'; }); } setInterval(refresh, 1000); refresh(); </script> </body> </html>

빠른 단계

  • 예제 1과 동일한 App 생성 단계를 따르되 App 이름을 WebServerAssets로 지정합니다.
  • MCU 코드를 sketch/sketch.ino에 붙여넣습니다.
  • Python 코드를 python/main.py에 붙여넣습니다 (기존 내용 모두 바꾸기).
  • assets/ 폴더에서 index.html을 열고(또는 생성하고) 위의 HTML 코드를 붙여넣습니다.
  • 예제 1처럼 WebUI - HTML Brick을 추가합니다.
  • Run을 클릭하여 업로드합니다.
  • 브라우저에서 http://<ARDUINO_UNO_Q_IP>:7000/을 엽니다.
  • 페이지는 자산 폴더에서 스타일이 지정된 웹 페이지를 로드하고 아날로그 값을 매초 자동으로 업데이트합니다.
  • 포텐셔미터를 회전합니다 — 페이지의 값이 새로고침 없이 변경됩니다.

App Lab 콘솔 출력

DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
Message (Enter to send a message to "Newbiely" on usb(2820070321))
New Line
9600 baud
[2026-05-08 09:00:01] Bridge ready
DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
[2026-05-08 09:00:02] WebUI started on http://0.0.0.0:7000 [2026-05-08 09:00:02] WebUI started on http://192.168.0.45:7000

API 응답

index.html의 JavaScript는 GET /api/analog을 호출합니다. 이 끝점을 직접 테스트할 수도 있습니다:

{"pin": "A0", "value": 512}
Arduino UNO Q 웹 서버 assets page

API로서의 웹 서버 (순수 JSON)

이 예제는 모든 HTML을 제거하고 JSON API 끝점만 제공합니다. 모든 클라이언트(브라우저, 모바일 앱, curl, Postman 또는 다른 마이크로컨트롤러)는 GET /api/analog을 호출하여 현재 아날로그 판독값을 구조화된 데이터로 수신할 수 있습니다.

다음을 수행하려는 경우 이 패턴을 사용하세요:

  • Arduino UNO Q 데이터를 기존 웹 앱 또는 대시보드에 통합
  • 모바일 앱 또는 백엔드 서비스에서 보드 쿼리
  • 명령줄에서 센서 값 테스트 또는 기록

MCU 코드

/* * 이 Arduino UNO Q 코드는 newbiely.kr 에서 개발되었습니다 * 이 Arduino UNO Q 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino-uno-q/arduino-uno-q-web-server */ #include "Arduino_RouterBridge.h" String get_analog(String arg) { int value = analogRead(A0); return String(value); } void setup() { Monitor.begin(); Bridge.begin(); Bridge.provide_safe("get_analog", get_analog); Monitor.println("Bridge ready"); } void loop() { }

Python 코드

/* * 이 Arduino UNO Q 코드는 newbiely.kr 에서 개발되었습니다 * 이 Arduino UNO Q 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino-uno-q/arduino-uno-q-web-server */ from arduino.app_utils import * from arduino.app_bricks.web_ui import WebUI def get_analog(): value = Bridge.call("get_analog", "") return {"pin": "A0", "value": int(value)} web_ui = WebUI() web_ui.expose_api("GET", "/api/analog", get_analog) App.run()

빠른 단계

  • 예제 1과 동일한 App 생성 단계를 따르되 App 이름을 WebServerAPI로 지정합니다.
  • MCU 코드를 sketch/sketch.ino에 붙여넣습니다.
  • Python 코드를 python/main.py에 붙여넣습니다 (기존 내용 모두 바꾸기).
  • 예제 1처럼 WebUI - HTML Brick을 추가합니다.
  • Run을 클릭하여 업로드합니다.
  • 브라우저에서 끝점을 테스트합니다.
Arduino UNO Q 웹 서버 api response
  • 터미널에서 끝점을 테스트합니다:
GET http://ARDUINO_UNO_Q_IP:7000/api/analog
  • 모든 클라이언트에서 끝점을 테스트합니다. 예를 들어 curl 사용:
curl http://:7000/api/analog

API 응답

{"pin": "A0", "value": 512}

App Lab 콘솔 출력

DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
Message (Enter to send a message to "Newbiely" on usb(2820070321))
New Line
9600 baud
[2026-05-08 09:00:01] Bridge ready
DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
[2026-05-08 09:00:02] WebUI started on http://0.0.0.0:7000 [2026-05-08 09:00:02] WebUI started on http://192.168.0.45:7000

Python 코드에서 HTML 분리

WebUI 접근 방식을 사용하면 Python 코드는 API 끝점만 노출합니다 — HTML을 제공하지 않습니다. 이는 설계상 깔끔한 분리입니다:

  • Python WebUI 스크립트 — JSON API 끝점 노출 (예: /api/status, /api/led/on)
  • HTML 파일 — 브라우저에서 열 수 있는 독립 실행형 파일입니다. 내부 JavaScript는 API에서 데이터를 가져옵니다.

Python 스크립트는 다음과 같습니다 (예제 1과 동일 - 변경 필요 없음):

/* * 이 Arduino UNO Q 코드는 newbiely.kr 에서 개발되었습니다 * 이 Arduino UNO Q 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino-uno-q/arduino-uno-q-web-server */ from arduino.app_utils import * from arduino.app_bricks.web_ui import WebUI def get_status(): uptime = Bridge.call("get_uptime", "") led = Bridge.call("get_led_state", "") return {"uptime": uptime, "led": led} web_ui = WebUI() web_ui.expose_api("GET", "/api/status", get_status) App.run()

다음은 API에서 가져오는 독립 실행형 HTML 페이지(index.html)입니다:

/* * 이 Arduino UNO Q 코드는 newbiely.kr 에서 개발되었습니다 * 이 Arduino UNO Q 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino-uno-q/arduino-uno-q-web-server */ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Arduino UNO Q Web Server</title> <style> body { font-family: Arial, sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; margin: 0; background: #1a1a2e; color: #eee; } h1 { font-size: 1.8rem; margin-bottom: 32px; } .card { background: #16213e; border-radius: 12px; padding: 32px 48px; box-shadow: 0 4px 24px rgba(0,0,0,0.4); text-align: center; min-width: 280px; } .label { font-size: 0.9rem; color: #aaa; margin-bottom: 4px; } .value { font-size: 2rem; font-weight: bold; color: #e94560; margin-bottom: 24px; } .led-on { color: #4caf50; } .led-off { color: #aaa; } </style> </head> <body> <h1>Arduino UNO Q Web Server</h1> <div class="card"> <p class="label">MCU Uptime (seconds)</p> <p class="value" id="uptime">--</p> <p class="label">Built-in LED</p> <p class="value" id="ledState">--</p> </div> <script> // Update this IP address to match your Arduino UNO Q const API_BASE = 'http://192.168.0.3:7000'; function update() { fetch(API_BASE + '/api/status') .then(r => r.json()) .then(data => { document.getElementById('uptime').textContent = data.uptime; const ledEl = document.getElementById('ledState'); ledEl.textContent = data.led; ledEl.className = 'value ' + (data.led === 'ON' ? 'led-on' : 'led-off'); }) .catch(e => console.error(e)); } setInterval(update, 2000); update(); </script> </body> </html>

※ 주의:

브라우저에서 index.html을 직접 열거나 (컴퓨터에서) 어디든지 호스팅합니다. 내부 JavaScript는 매 2초마다 http://<ARDUINO_UNO_Q_IP>:7000/api/status를 가져옵니다. HTML 파일의 IP 주소를 보드와 일치하도록 업데이트합니다.

Arduino UNO Q 웹 서버 — 여러 페이지

여러 API 끝점(예: /api/status, /api/led/on, /api/settings)이 있는 웹 서버를 구축하려면 Python WebUI 스크립트에서 끝점당 하나의 expose_api 호출을 추가합니다.

자세한 가이드는 Arduino UNO Q - Web Server Multiple Pages 튜토리얼을 참조하세요.

OpenClaw

You can adapt the OpenClaw to this tutorial by refering the instruction on 아두이노 우노 Q - OpenClaw Tutorial

프로젝트 아이디어

웹 서버는 Arduino UNO Q의 많은 유용한 프로젝트를 위한 빌딩 블록입니다:

  • 센서 대시보드: DHT22 또는 BMP280을 MCU에 연결하고 스타일이 지정된 웹 페이지에 온도, 습도 및 압력을 표시합니다. 매 몇 초마다 자동으로 새로고침됩니다.
  • 릴레이 제어 판넬: 웹 페이지에 버튼을 추가하여 릴레이를 켜고 끕니다 — 집에 있는 동안 휴대폰에서 조명, 선풍기 또는 펌프를 제어하는 데 유용합니다.
  • 데이터 로거 뷰어: 센서 판독값을 Linux 측의 CSV 파일에 기록하고 마지막 100개 판독값을 HTML 표로 반환하는 /history 끝점을 추가합니다.
  • 차고 문 오프너: "trigger" Bridge 함수를 노출하여 1초 동안 릴레이를 펄스합니다 — 웹 페이지에 단일 큰 버튼을 추가하여 휴대폰에서 차고 문을 열거나 닫습니다.
  • 식물 급수 모니터: MCU의 토양 수분 센서를 읽고 웹 페이지의 진행률 표시줄로 수분 수준을 표시하고 토양이 너무 건조할 때 경고 배너를 표시합니다.

스스로 도전해보세요

Arduino UNO Q의 웹 서버로 더 나아가고 싶으신가요? 이러한 도전 과제를 시도해보세요:

  • 쉬움: 컴퓨터에서 http://<ARDUINO_UNO_Q_IP>:7000/api/status에서 가져오는 스타일 지정된 index.html 파일을 생성합니다. Bootstrap 또는 사용자 지정 CSS를 사용하여 깔끔한 레이아웃으로 가동 시간 및 LED 상태를 표시합니다.
  • 중간: Python WebUI 스크립트에 메모리 내 목록에서 마지막 10개 Bridge 값을 읽고 JSON 배열로 반환하는 /api/history 끝점을 추가합니다 — HTML 페이지에 표로 표시합니다.
  • 고급: WebUI 스크립트에 /api/led/toggle POST 끝점을 추가합니다. Bridge를 통해 현재 LED 상태를 읽고 led_on 또는 led_off를 호출하여 LED를 토글합니다 — HTML 페이지에 단일 토글 버튼을 추가합니다.