ESP32 쿼리 문자열 웹 서버 동적 URL 매개변수
WebServerQueryStrings 예제 - 동적 다중 페이지 서버
개요
이 예제는 URL 쿼리 매개변수를 사용하여 대화형 콘텐츠를 제공하고 매끄러운 페이지 탐색으로 제어 기능을 구현하는 동적 다중 페이지 웹 서버를 만드는 방법을 보여줍니다.
주요 기능
- 다중 페이지 내비게이션 URL 매개변수에 따라 동적으로 콘텐츠가 제공됩니다
- 온도 단위 변환(섭씨/화씨)을 쿼리 매개변수를 통해 수행합니다
- LED 제어를 쿼리 문자열 매개변수를 사용하여 구현합니다
- 동적 콘텐츠 생성은 사용자 입력에 따라 수행됩니다
- 전문적인 다중 페이지 레이아웃은 일관된 내비게이션과 함께 제공됩니다
- URL 매개변수 파싱 및 검증을 수행합니다
준비물
| 1 | × | ESP32 ESP-WROOM-32 개발 모듈 | 쿠팡 | 아마존 | |
| 1 | × | USB 케이블 타입-A to 타입-C (USB-A PC용) | 쿠팡 | 아마존 | |
| 1 | × | USB 케이블 타입-C to 타입-C (USB-C PC용) | 아마존 | |
| 1 | × | (추천) ESP32용 스크루 터미널 확장 보드 | 쿠팡 | 아마존 | |
| 1 | × | (추천) Breakout Expansion Board for ESP32 | 쿠팡 | 아마존 | |
| 1 | × | (추천) ESP32용 전원 분배기 | 쿠팡 | 아마존 |
공개: 이 포스팅 에 제공된 일부 링크는 아마존 제휴 링크입니다. 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
라이브러리 설치
다음 지침을 단계별로 따라가세요:
- 이것이 ESP32를 처음 사용하는 경우에는 Arduino IDE에서 ESP32를 위한 환경 설정 튜토리얼을 참고하세요 Arduino IDE에서 ESP32를 위한 환경 설정 튜토리얼.
- ESP32 보드를 USB 케이블로 컴퓨터에 연결하세요.
- 컴퓨터에서 Arduino IDE를 실행하세요.
- 적절한 ESP32 보드(예: ESP32)와 COM 포트를 선택하세요.
- Arduino IDE의 왼쪽에 있는 Library Manager 아이콘을 클릭하여 라이브러리 매니저를 여세요.
- Web Server for ESP32를 검색하고 DIYables의 mWebSockets를 찾아보세요.
- Install 버튼을 클릭하여 mWebSockets 라이브러리를 추가하세요.

웹 서버 쿼리 문자열 예시
- Arduino IDE에서 File 예제 ESP32용 웹 서버 WebServerQueryStrings 예제 코드를 열려면
코드 구조
- home.h: 홈 페이지 HTML 템플릿
- temperature.h: 온도 모니터링 페이지 템플릿
- led.h: LED 제어 페이지 템플릿
- WebServerQueryStrings.ino: 메인 서버 로직
회로 연결
외부 부품이 필요하지 않습니다. 이 예제는 핀 13에 내장된 LED를 사용합니다.
쿼리 매개변수 기능
온도 페이지 매개변수
- unit=c or unit=celsius - 섭씨로 온도를 표시
- unit=f or unit=fahrenheit - 화씨로 온도를 표시
- 매개변수가 없으면 기본값은 섭씨
LED 제어 매개변수
- state=on - LED를 켭니다
- state=off - LED를 끕니다
설정 지침
1. 네트워크 구성
WebServerQueryStrings.ino 파일에서 WiFi 자격 증명을 직접 편집하세요:
const char WIFI_SSID[] = "YOUR_WIFI_SSID";
const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
2. 코드 업로드 및 출력 모니터링
- ESP32를 컴퓨터에 연결하세요
- Arduino IDE에서 올바른 보드와 포트를 선택하세요
- WebServerQueryStrings.ino 스케치를 업로드하세요
- 시리얼 모니터를 여세요(9600bps)
- WiFi 연결을 기다리세요
- 표시된 IP 주소를 확인하세요
- 시리얼 모니터에 IP 주소가 보이지 않으면 ESP32 보드의 리셋 버튼을 누르세요
사용 예시
웹 브라우저를 열고 시리얼 모니터에 표시된 IP 주소를 입력하여 웹 서버에 접속하십시오.

온도 모니터링 기능 테스트:
- "온도" 메뉴를 클릭하세요.
- 온도 표시를 확인하세요. 각 버튼을 클릭하여 온도 단위를 변경하세요.

LED 제어 기능을 테스트:
- LED 제어 메뉴를 클릭하세요. 아래와 같이 웹 인터페이스가 표시됩니다:

- 제공된 버튼을 사용하여 LED를 켜고 끄세요.
- ESP32 보드의 내장 LED 상태가 즉시 업데이트되는 것을 관찰하십시오.
다른 페이지에 접속하기
홈 페이지
- 웹 주소: http://your-esp32-ip/
- 주요 기능: 네비게이션 메뉴가 있는 환영 페이지
온도 페이지 (기본값 - 섭씨)
- URL: http://your-esp32-ip/temperature
- 표시: 단위 선택이 가능한 섭씨 온도
화씨 온도
- 주소: http://your-esp32-ip/temperature?unit=f
- 주소: http://your-esp32-ip/temperature?unit=fahrenheit
- 표시: 화씨로 변환된 온도
LED 제어
- 전원 켜기: http://your-esp32-ip/led?state=on
- 전원 끄기: http://your-esp32-ip/led?state=off
코드 설명
쿼리 파라미터 처리
void handleTemperature(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) {
// Check for query parameter "unit"
String unit = "C";
for (int i = 0; i < params.count; i++) {
if (String(params.params[i].key) == "unit") {
unit = params.params[i].value;
}
}
// Generate temperature display based on unit
String temperatureDisplay = "Simulated temperature: 25°" + unit;
// Use the TEMPERATURE_PAGE template and replace placeholder
String response = TEMPERATURE_PAGE;
response.replace("%TEMPERATURE_VALUE%", temperatureDisplay);
server.sendResponse(client, response.c_str());
}
쿼리 매개변수를 사용한 LED 제어
void handleLed(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) {
// Check for query parameter "state"
String state = "";
for (int i = 0; i < params.count; i++) {
if (String(params.params[i].key) == "state") {
state = params.params[i].value;
break;
}
}
// Control LED based on state
if (state == "on") {
ledState = HIGH;
digitalWrite(LED_PIN, ledState);
} else if (state == "off") {
ledState = LOW;
digitalWrite(LED_PIN, ledState);
} else if (state == "") {
// No state parameter provided, just show current status
} else {
// Invalid state parameter
client.println("HTTP/1.1 400 Bad Request");
client.println("Connection: close");
client.println();
client.print("Invalid state parameter. Use ?state=on or ?state=off");
return;
}
// Get current LED state
String ledStatus = (ledState == HIGH) ? "ON" : "OFF";
// Use the LED_PAGE template and replace placeholders
String response = LED_PAGE;
response.replace("%LED_STATUS%", ledStatus);
server.sendResponse(client, response.c_str());
}
매개변수 검증
// Helper function to find query parameter value
String getQueryParam(const QueryParams& params, const String& key) {
for (int i = 0; i < params.count; i++) {
if (String(params.params[i].key) == key) {
return params.params[i].value;
}
}
return "";
}
// Validation functions
bool isValidTemperatureUnit(String unit) {
unit.toLowerCase();
return (unit == "c" || unit == "celsius" ||
unit == "f" || unit == "fahrenheit" ||
unit == "");
}
bool isValidLedState(String state) {
return (state == "on" || state == "off" || state == "");
}
동적 콘텐츠가 포함된 HTML 템플릿
온도 페이지 템플릿
<div class="temperature-display">
<h2>Current Temperature</h2>
<div class="temp-value">%TEMPERATURE% %UNIT%</div>
<div class="unit-selector">
<p>Display in:</p>
<a href="/temperature?unit=c" class="unit-btn">Celsius</a>
<a href="/temperature?unit=f" class="unit-btn">Fahrenheit</a>
</div>
</div>
LED 제어 템플릿
<div class="led-control">
<h2>LED Control</h2>
<div class="status">Status: <span>%LED_STATUS%</span></div>
<div class="controls">
<a href="/led?state=on" class="btn btn-on">Turn ON</a>
<a href="/led?state=off" class="btn btn-off">Turn OFF</a>
</div>
</div>
고급 기능
라우트 구성
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
ledState = LOW;
digitalWrite(LED_PIN, ledState);
// Initialize web server with credentials
server.begin(WIFI_SSID, WIFI_PASSWORD);
server.printWifiStatus();
// Add routes
server.addRoute("/", handleHome);
server.addRoute("/temperature", handleTemperature);
server.addRoute("/led", handleLed);
// Set custom 404 handler
server.setNotFoundHandler(handleNotFound);
}
쿼리 매개변수 헬퍼 함수들
// Extract parameter from QueryParams structure
String getParam(const QueryParams& params, const String& key, const String& defaultValue = "") {
for (int i = 0; i < params.count; i++) {
if (String(params.params[i].key) == key) {
return params.params[i].value;
}
}
return defaultValue;
}
// Check if parameter exists
bool hasParam(const QueryParams& params, const String& key) {
for (int i = 0; i < params.count; i++) {
if (String(params.params[i].key) == key) {
return true;
}
}
return false;
}
URL 구성 도우미
// Helper to build URLs with parameters
String buildLedUrl(String state) {
return "/led?state=" + state;
}
String buildTempUrl(String unit) {
return "/temperature?unit=" + unit;
}
실제 구현 참고 사항
현재의 한계
실제 구현은 기능이 풍부한 웹 서버에 비해 단순화되어 있습니다:
- 핸들러당 단일 매개변수 추출만 지원합니다.
- 문자열 기반의 간단한 온도 시뮬레이션(단위 변환 없음)
- 켜짐/꺼짐 상태만 지원하는 기본 LED 제어
- 표준 핀 13 대신 핀 9를 사용합니다.
문제 해결
일반적인 문제
매개변수 작동하지 않음
- URL 형식 확인: page?param=value
- 매개변수 이름이 정확히 일치하는지 확인합니다 (대소문자 구분)
- 현재 구현은 LED에 대해 state를 사용하고 있으며, action은 사용하지 않습니다.
LED 핀 이슈
- 이 예제는 핀 9를 사용하며 핀 13은 사용하지 않습니다
- LED_PIN 상수가 하드웨어와 일치하는지 확인하세요
쿼리 매개변수 접근
- QueryParams 구조를 사용하고, server.arg()를 사용하지 마세요.
- 특정 매개변수를 찾기 위해 params.params[i]를 순회합니다.
디버그 출력
void debugParameters(const QueryParams& params) {
Serial.println("=== Request Parameters ===");
Serial.println("Params count: " + String(params.count));
for (int i = 0; i < params.count; i++) {
Serial.print(" ");
Serial.print(params.params[i].key);
Serial.print(" = ");
Serial.println(params.params[i].value);
}
Serial.println("========================");
}
맞춤화
매개변수가 있는 새 핸들러 추가
void handleCustomPage(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) {
String theme = getParam(params, "theme", "light");
String lang = getParam(params, "lang", "en");
// Process parameters and generate response
String response = "<html><body>";
response += "<h1>Custom Page</h1>";
response += "<p>Theme: " + theme + "</p>";
response += "<p>Language: " + lang + "</p>";
response += "</body></html>";
server.sendResponse(client, response.c_str());
}
// Register the new route in setup()
server.addRoute("/custom", handleCustomPage);
템플릿 시스템 개선
실제 구현은 간단한 자리 표시자 교체를 사용합니다:
String response = TEMPERATURE_PAGE;
response.replace("%TEMPERATURE_VALUE%", temperatureDisplay);
// Add more replacements as needed
response.replace("%UNIT%", unit);
response.replace("%TIMESTAMP%", String(millis()));
다음 단계
- REST API 개발을 위해 WebServerJson.ino를 탐색하기
- 실시간 통신을 위해 WebServerWithWebSocket.ino를 사용하기
- POST 매개변수를 사용하여 폼 핸들링을 구현하기