확장 제작 가이드

ESP8266 + DHT22 값을 웹서버로 전송하기

시리얼 모니터에서 온습도 값이 안정적으로 보였다면, 다음 단계는 장치를 현장에 두고 웹서버로 값을 보내는 것입니다. 이 글에서는 Wi-Fi 이름과 암호를 코드에 직접 넣고, ESP8266이 HTTP POST로 값을 전송하며, PHP 웹서버가 그 값을 받아 CSV로 저장하는 흐름까지 만듭니다.

여러 원격지 온습도 센서 장치가 웹서버로 데이터를 전송하는 구조 이미지

현실적인 사용 상황

자주 방문하기 어려운 장비실, 통신함, 창고, 옥상 장비함은 에어컨이나 환기 장치가 멈췄을 때 온도가 빠르게 올라갑니다. 서버, 네트워크 장비, CCTV 녹화기, 전원 장치가 들어 있는 공간이라면 온도 상승이 곧 장애로 이어질 수 있습니다.

이 예제의 목표는 ESP8266과 DHT22를 장비실 한쪽에 설치하고, 5분 또는 10분마다 온습도 값을 웹서버에 보내는 것입니다. 서버는 값을 기록하고, 이후에는 임계 온도 초과 시 알림을 보내는 구조로 확장할 수 있습니다.

전체 흐름

  1. ESP8266이 DHT22에서 온도와 습도를 읽습니다.
  2. 코드에 직접 입력한 Wi-Fi SSID와 암호로 공유기에 접속합니다.
  3. HTTP POST 방식으로 웹서버의 PHP 수신 주소에 값을 보냅니다.
  4. PHP는 API 키와 값을 확인한 뒤 CSV 파일에 시간, 장치명, 온도, 습도를 저장합니다.
  5. 배터리 장치는 전송이 끝나면 딥슬립으로 들어가 대기 전류를 줄입니다.

이 글에서는 먼저 가장 단순하고 확실한 방식으로 Wi-Fi 정보를 코드에 직접 넣습니다. 휴대폰으로 장치명과 Wi-Fi 암호를 설정하는 AP 모드, OTA 업데이트는 다음 단계에서 다루는 것이 좋습니다.

웹서버 수신 PHP

웹서버에는 값을 받을 PHP 파일을 하나 둡니다. 예를 들어 /iot-lab/examples/dht22-receive.php 같은 경로를 만들고 아래 코드를 넣을 수 있습니다. 실제 운영에서는 로그 파일을 웹에서 바로 내려받을 수 없도록 웹루트 밖이나 데이터베이스에 저장하는 구성이 더 안전합니다.

PHP 수신 예제
<?php
// ESP8266 코드에 넣은 값과 같아야 합니다.
$apiKey = 'CHANGE_THIS_KEY';

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
  http_response_code(405);
  exit('POST only');
}

if (($_POST['key'] ?? '') !== $apiKey) {
  http_response_code(403);
  exit('bad key');
}

$device = preg_replace('/[^a-zA-Z0-9_-]/', '', $_POST['device'] ?? 'unknown');
$temp = filter_var($_POST['temp'] ?? null, FILTER_VALIDATE_FLOAT);
$hum = filter_var($_POST['hum'] ?? null, FILTER_VALIDATE_FLOAT);

if ($temp === false || $hum === false) {
  http_response_code(400);
  exit('bad value');
}

$line = date('c') . ',' . $device . ',' . $temp . ',' . $hum . PHP_EOL;
$file = __DIR__ . '/dht22-log.csv';

if (!file_exists($file)) {
  file_put_contents($file, "time,device,temp_c,humidity\n");
}

file_put_contents($file, $line, FILE_APPEND | LOCK_EX);
echo 'ok';

ESP8266 전송 코드

아래 코드는 DHT22 값을 읽은 뒤 Wi-Fi에 접속하고, 서버로 HTTP POST를 보냅니다. WIFI_SSID, WIFI_PASS, DEVICE_ID, API_KEY, SERVER_URL을 현장에 맞게 바꿉니다.

Arduino IDE - HTTP POST + Deep Sleep
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecure.h>
#include <DHT.h>

#define DHTPIN 2        // ESP-01 GPIO2 기준
#define DHTTYPE DHT22

const char* WIFI_SSID = "YOUR_WIFI_NAME";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* DEVICE_ID = "remote-room-01";
const char* API_KEY = "CHANGE_THIS_KEY";
const char* SERVER_URL = "https://iothub.co.kr/iot-lab/examples/dht22-receive.php";

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(115200);
  delay(1000);
  dht.begin();

  float humidity = dht.readHumidity();
  float temperature = dht.readTemperature();

  if (isnan(humidity) || isnan(temperature)) {
    Serial.println("DHT22 read failed");
    sleepNow();
  }

  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);

  unsigned long start = millis();
  while (WiFi.status() != WL_CONNECTED && millis() - start < 15000) {
    delay(500);
    Serial.print(".");
  }

  if (WiFi.status() == WL_CONNECTED) {
    WiFiClientSecure client;
    client.setInsecure(); // 첫 테스트용. 운영 시 인증서 검증을 권장합니다.

    HTTPClient http;
    http.begin(client, SERVER_URL);
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");

    String body = "key=" + String(API_KEY) +
                  "&device=" + String(DEVICE_ID) +
                  "&temp=" + String(temperature, 1) +
                  "&hum=" + String(humidity, 1);

    int code = http.POST(body);
    Serial.printf("HTTP %d\n", code);
    Serial.println(http.getString());
    http.end();
  } else {
    Serial.println("Wi-Fi connection failed");
  }

  sleepNow();
}

void loop() {}

void sleepNow() {
  Serial.println("sleep");
  ESP.deepSleep(10 * 60 * 1000000ULL); // 10분 후 재시작
}

전송 확인

업로드 후 시리얼 모니터를 115200 baud로 열면 Wi-Fi 접속 진행 표시와 HTTP 응답 코드가 보입니다. 서버가 정상 수신하면 HTTP 200ok가 표시됩니다.

시리얼 출력 예시
.....
HTTP 200
ok
sleep

ESP-01과 배터리 운용

ESP-01처럼 작은 모듈은 장비실 구석이나 통신함에 넣기 좋지만, 배터리로 오래 쓰려면 계속 켜두면 안 됩니다. Wi-Fi 연결 상태를 유지하면 전류 소모가 커지므로, 측정하고 전송한 뒤 바로 딥슬립에 들어가는 방식이 기본입니다.

  • 딥슬립 배선: ESP8266은 GPIO16을 RST에 연결해야 딥슬립에서 깨어날 수 있습니다. ESP-01은 GPIO16이 핀헤더로 나오지 않는 제품이 많아 납땜이 필요하거나, 딥슬립이 쉬운 ESP-12F/ESP-07 계열 보드를 선택하는 편이 낫습니다.
  • 측정 주기: 장비실 온도 감시는 10초마다 보낼 필요가 거의 없습니다. 5분 또는 10분 간격으로 보내면 배터리 시간이 크게 늘어납니다.
  • 전원 회로: 저전류 레귤레이터를 쓰고, 보드의 전원 LED나 USB-시리얼 칩처럼 계속 전류를 쓰는 부품을 줄여야 합니다.
  • 센서 전원: DHT22도 계속 켜두면 전류를 씁니다. 더 길게 운용하려면 센서 VCC를 GPIO나 MOSFET으로 제어해 측정할 때만 켜는 방법을 검토합니다.
  • 통풍: 케이스를 완전히 밀폐하면 내부 발열 때문에 실제 장비실 온도보다 높게 나올 수 있습니다. 센서 주변에 공기가 흐를 수 있게 해야 합니다.

배터리 운용은 코드보다 하드웨어 선택이 더 중요합니다. ESP-01은 작지만 딥슬립 배선이 까다롭고, 개발과 유지보수까지 생각하면 처음에는 Wemos D1 mini 또는 ESP-12F 기반 보드로 검증한 뒤 소형화하는 흐름이 안정적입니다.

다음 글 예고

이번 글은 Wi-Fi 이름과 암호를 코드에 직접 넣는 방식입니다. 실제 납품형 장치나 여러 장소에 설치하는 장치라면 매번 펌웨어를 다시 올리는 방식은 불편합니다. 다음 단계에서는 장치가 처음 켜질 때 AP 모드로 열리고, 휴대폰에서 Wi-Fi 이름, 암호, 장치명을 입력한 뒤 저장하는 구조와 OTA 업데이트 흐름을 다루는 것이 좋습니다.