SHT30 온습도 모니터링 시스템 전체 소스(서버 PHP, STM32 펌웨어, SQL, 테스트). 전체 코드리뷰에서 도출된 보안 하드닝 10건 반영: - 요청 서명 HMAC-SHA256 전환(펌웨어 sig.c/서버 config.php/호스트 패리티 동시) - 재전송 방어 + 기본 API_KEY fail-closed + 디바이스 문자열 정제(api/sensor_data.php) - 오프라인 SMS 중복 발송 경합 제거(cron_heartbeat.php, 원자적 선점) - CSV 수식 주입 방지(monthly_report.php), 감사로그 회전 락(retention_cleanup.php) - 브루트포스 카운터 원자화(login.php), 예시 TOTP 비밀키 무효화, 마이그레이션 멱등화 _backup/(하드코딩 실 비밀값 포함)·config.local.php·런타임 상태는 .gitignore 제외.
119 lines
4.4 KiB
Markdown
119 lines
4.4 KiB
Markdown
# SHT30 온습도 센서 설치 가이드
|
|
|
|
서버실 온습도 모니터링을 위해 Sensirion SHT30(한진데이터 P4422-3, I2C) 센서를 설치하고 서버에 연동하는 가이드입니다. 기본 구성은 STM32F407VGT6 펌웨어(`sht30_fw`, `sensor_id=2`, `device_id=stm32-sht30-01`)이며, 폐쇄망의 다른 환경을 위한 Raspberry Pi I2C 대안도 함께 설명합니다.
|
|
|
|
## 1. 서버 준비
|
|
|
|
1. 웹 서버 DB에 통합 스키마를 적용합니다(신규 설치).
|
|
|
|
```sql
|
|
SOURCE sql/schema_sht30.sql;
|
|
```
|
|
|
|
기존 누수 설치를 온습도 전용으로 전환하는 경우에는 전환 마이그레이션을 적용합니다.
|
|
|
|
```sql
|
|
SOURCE sql/migration_drop_leak.sql;
|
|
```
|
|
|
|
2. 서버 파일을 배포합니다.
|
|
|
|
```text
|
|
php/api/sensor_data.php
|
|
php/dashboard.php
|
|
php/ops_checks.php
|
|
php/config.php
|
|
sql/schema_sht30.sql
|
|
```
|
|
|
|
API는 `sht30` 측정을 수신하면 `sensor_status`를 갱신하고 측정값을 `sensor_metric`에 저장합니다. 서버가 `METRIC_*` 임계로 고온/저온/고습/저습을 판정하고, 초과 시 종류별 30분 쿨다운으로 SMS를 발송합니다.
|
|
|
|
## 2. 기본 구성 — STM32F407VGT6 (`sht30_fw`)
|
|
|
|
### 2.1 I2C 배선
|
|
|
|
SHT30을 STM32 I2C1 버스에 연결합니다(상세는 [wiring_diagram.md](./wiring_diagram.md), [firmware/docs/HARDWARE.md](../firmware/docs/HARDWARE.md) §3).
|
|
|
|
```text
|
|
SHT30 VDD -> STM32 3.3V
|
|
SHT30 GND -> STM32 GND
|
|
SHT30 SCL -> STM32 PB6 (I2C1_SCL, AF4) + 4.7kΩ 풀업 -> 3.3V
|
|
SHT30 SDA -> STM32 PB7 (I2C1_SDA, AF4) + 4.7kΩ 풀업 -> 3.3V
|
|
SHT30 ADDR -> GND (주소 0x44; VDD 면 0x45)
|
|
```
|
|
|
|
- 7-bit 주소 `0x44`(`APP_SHT30_I2C_ADDR`), I2C 100kHz 권장.
|
|
- 명령 `0x2C06`(high-repeatability) → 약 20ms 대기 → 6바이트 read.
|
|
|
|
### 2.2 펌웨어 설정·빌드 (폐쇄망)
|
|
|
|
```bash
|
|
cp firmware/common/secrets.h.example firmware/common/secrets.h
|
|
# secrets.h 의 APP_API_KEY 를 서버 config.local.php 의 API_KEY 와 동일하게 채운다.
|
|
```
|
|
|
|
| 위치 | 설정 |
|
|
|---|---|
|
|
| `firmware/common/secrets.h` | `APP_API_KEY` = 서버 `API_KEY` |
|
|
| `firmware/common/app_config.h` | `APP_API_HOST`, `APP_API_PATH`(`/raspi_leck_detecter/api/sensor_data.php`), 네트워크 |
|
|
| `firmware/common/app_config.h` | `APP_SHT30_REPORT_INTERVAL_SEC`(기본 300초), `APP_SHT30_I2C_ADDR`(0x44) |
|
|
| `firmware/certs/server_ca.c` | 자리표시자 CA → 실제 Cafe24 루트 CA |
|
|
|
|
벤더링·빌드·플래시 절차는 [firmware/docs/BUILD_OFFLINE.md](../firmware/docs/BUILD_OFFLINE.md)를 따릅니다. `sht30_fw` 타깃을 빌드해 보드에 플래시합니다.
|
|
|
|
### 2.3 동작 확인
|
|
|
|
USART3(PD8/PD9, 115200) 콘솔 로그에서 확인합니다.
|
|
|
|
- I2C1 초기화 및 SHT30 0x44 응답, 첫 측정값
|
|
- 네트워크/SNTP/TLS 핸드셰이크 → 서버 200 응답 → `startup` 보고
|
|
- 이후 5분 주기 `periodic` 측정 보고
|
|
|
|
## 3. 대안 구성 — Raspberry Pi I2C (STM32 외 대안)
|
|
|
|
STM32 보드를 쓸 수 없는 환경에서는 Raspberry Pi 40핀 헤더 I2C 버스 1을 사용할 수 있습니다.
|
|
|
|
```text
|
|
SHT30 VCC -> Raspberry Pi 3.3V (pin 1)
|
|
SHT30 GND -> Raspberry Pi GND
|
|
SHT30 SDA -> Raspberry Pi GPIO2 / SDA1 / pin 3
|
|
SHT30 SCL -> Raspberry Pi GPIO3 / SCL1 / pin 5
|
|
SHT30 ADDR -> GND (주소 0x44; 점퍼 변경 시 0x45)
|
|
```
|
|
|
|
I2C를 먼저 활성화합니다.
|
|
|
|
```bash
|
|
sudo raspi-config # Interface Options -> I2C -> enable
|
|
sudo apt-get update
|
|
sudo apt-get install -y python3-venv python3-smbus i2c-tools
|
|
```
|
|
|
|
센서가 보이는지 확인합니다.
|
|
|
|
```bash
|
|
i2cdetect -y 1 # 44 또는 45 가 보여야 함
|
|
```
|
|
|
|
환경 파일 `/etc/sht30-sensor.env`를 생성하고 다음 값을 채웁니다.
|
|
|
|
```text
|
|
API_URL=https://your-domain.example/raspi_leck_detecter/api/sensor_data.php
|
|
API_KEY=서버와 동일한 API_KEY
|
|
DEVICE_ID=rpi-sht30-01
|
|
DEVICE_LOCATION=온습도 측정 위치
|
|
SHT30_SENSOR_ID=2
|
|
SHT30_I2C_ADDR=0x44
|
|
```
|
|
|
|
> 대안 구성에서도 `sensor_id=2`, raw-body 서명(`X-Signature = sha256(API_KEY + body)`), 5분 측정 주기는 동일합니다. 임계 판정과 SMS는 모두 서버에서 수행하므로 측정 송신부만 환경에 맞게 구성하면 됩니다.
|
|
|
|
## 4. 대시보드 결과
|
|
|
|
첫 정상 보고 후:
|
|
|
|
- `sensor_status`에 `sensor_id=2` 항목이 생성됩니다.
|
|
- `sensor_metric`에 온도/습도 이력이 누적됩니다.
|
|
- `dashboard.php`가 센서 카드에 최신 온도/습도와 임계 상태를 표시합니다.
|
|
|
|
장비가 `HEARTBEAT_TIMEOUT_SEC`(기본 1200초=20분)을 초과해 보고를 멈추면 서버가 오프라인으로 판정하고 SMS를 발송합니다.
|