- tools/make_deploy_bundles.py: PMS7003·Zero2W 디스플레이 노드 번들 생성 반영(폐쇄망 동봉) - tools/harden_pi.sh: 하드닝 스크립트 갱신 - docs/superpowers: 노드 센서 통합·스모크 파일럿·대시보드 다크 설계/계획 문서 - docs/claude-config: IoT 납품·검증 스킬/룰 참조본 - review/: 프로젝트 리뷰·UI v2 목업
6.6 KiB
6.6 KiB
설계: 누수 노드 다중센서 통합 (누수 + 온습도 + 미세먼지) · 상시 카메라 조명
날짜: 2026-07-19
브랜치: feat/pi-c-sensor3-leak-node
상태: 설계 확정, 구현 진행
대체: 2026-07-18-smoke-node-pilot-design.md (연기 개조/불꽃/CO 경로 폐기)
참조 계획: ../plans/2026-07-18-smoke-node-pilot.md (연기 시범 → PMS7003 metric 통합으로 전환)
목표
기존 누수 노드(Pi-A = sensor_id 1, Pi-C = sensor_id 3)를 한 노드에 3종 센서를 얹은 통합 노드로 확장한다:
- 누수 — 기존 leak GPIO(GPIO17, active-high). 변경 없음.
- 온습도(SHT30) — I2C metric(
metric_type=sht30). 이미 통합됨(2026-07-15 설계). - 미세먼지(PMS7003) — UART metric(
metric_type=pms7003). 이번 신규. 연기(화재)의 대리 지표(smoke proxy) — 입자 유입 시 PM 농도가 급등한다.
세 센서 모두 그 노드의 같은 sensor_id(1 또는 3)로 보고하고, metric_type 문자열로만
구분한다. SHT30 동일-id 통합 방식을 그대로 미러(새 id·재번호 없음).
추가로, 누수 확인 카메라(NoIR)용 상시점등 백색 LED를 배선한다(스위칭·코드 없음).
핵심 결정 (확정)
- 동일 sensor_id · metric_type 구분.
leak_sensor_metric(sensor_id + 측정시각 키)이 온습도·미세먼지를 한 테이블에서metric_type으로 구분 → 한 sensor_id가 누수 상태 + 온습도 측정 + 미세먼지 측정을 동시에 가진다. PM 행은pm1_0/pm2_5/pm10만 채우고temperature_c/humidity_percent는 NULL(반대도 동일) — additive 컬럼. - 노드: 별도 서비스. 불안정한 누수 코드는 건드리지 않는다. PMS7003 는 SHT30 처럼
독립 systemd 서비스(
pms7003-sensor)로 얹는다. config 의SENSOR_ID만 노드별(1/3). - event_type: 첫 성공 판독 =
startup, 이후periodic(SHT30 와 동일). PMS 는 누수/알람 이벤트를 절대 방출하지 않는다 — 임계 판정·SMS 는 전적으로 서버 몫. - Pi metric_status = 물리 타당성만(
normal|out_of_range). 서버가 운영 임계를 재평가 하므로 Pi 의 status 를 경보 근거로 신뢰하지 않는다. - 경보/수신자: 전역
METRIC_PM25_HIGH(75)·METRIC_PM10_HIGH(150) 초과 시 서버가 판정 →[미세먼지경보]SMS. 수신자는 기존 sensor_id 1·3 그룹 그대로(추가 매핑 불필요). - 카메라 조명: 상시점등. 스위칭·GPIO 제어 없음. 백색 LED 모듈을 Pi 5V 에 직결해 항상 켠다.
데이터 흐름 / 페이로드
Pi-A (한 대) Pi-C: 동일, sensor_id=3
├ leak-sensor.service → POST(sensor_id=1) leak_alert/recovery/periodic (누수)
├ sht30-sensor.service → POST(sensor_id=1) startup/periodic (metric_type=sht30, 온·습도)
└ pms7003-sensor.service → POST(sensor_id=1) startup/periodic (metric_type=pms7003, PM)
서버 sensor_data.php: sensor_id=1 metric 저장(metric_type 구분) + 임계 재평가
→ high_pm25/high_pm10 breach → [미세먼지경보] SMS (SENSOR_RECIPIENTS[1])
→ is_leak 보존(비-누수 이벤트는 누수 상태를 덮지 않음)
대시보드: sensor_id=1 → 누수 칩 + 온습도 칩 + 미세먼지 칩
PMS7003 보고 바디 (Pi 가 이 바이트 순서 그대로 만들어 HMAC 서명; KEY 이름 서버와 일치):
{"device_id":"..","device_location":"..","sensor_id":1,"sensor_name":"..","event_type":"periodic",
"timestamp":<int>,"metric_type":"pms7003","pm1_0":<int>,"pm2_5":<int>,"pm10":<int>,
"metric_status":"normal","app_version":".."}
pm1_0/pm2_5/pm10= 맨 정수 µg/m³(대기환산), 범위 0..1000.- HTTP User-Agent:
PMS7003Sensor/2.0(WAF 우회용 커스텀 UA).
서버 (이미 반영됨 — 참고)
- 스키마
leak_sensor_metric:pm1_0/pm2_5/pm10 SMALLINT UNSIGNED NULLadditive. config.php:METRIC_PM25_HIGH(75) ·METRIC_PM10_HIGH(150) ·METRIC_PM_HYSTERESIS(10), 쿨다운은METRIC_ALERT_COOLDOWN_SEC재사용.- 새 breach kind
high_pm25·high_pm10→ 둘 다SMS_TAG_HIGH_PM = '[미세먼지경보]'매핑.
하드웨어 배선
PMS7003 (UART, 5V) — TXD 만 읽으면 됨
| 신호 | PMS7003 | Pi 4 | 비고 |
|---|---|---|---|
| 전원 | VCC | 5V (물리 pin2) | 레이저 팬 구동, 5V 필수 |
| 접지 | GND | GND (물리 pin6) | |
| 데이터 | TXD | RXD = GPIO15 (물리 pin10) | PMS → Pi 단방향(읽기) |
- UART 활성화 필수:
enable_uart=1+ 직렬 로그인 콘솔 분리(포트 점유 해제).install.sh가 자동 처리, 첫 활성화면 재부팅 필요(migrate.sh 가 안내). 포트 =/dev/serial0. - 버스 무충돌: UART(GPIO14/15)는 누수 GPIO17·SHT30 I2C(GPIO2/3)와 겹치지 않는다 → 세 센서 병행 가능.
카메라 조명 (상시점등 백색 LED)
| 신호 | LED 모듈 | Pi 4 | 비고 |
|---|---|---|---|
| 전원 | VCC | 5V | |
| 접지 | GND | GND |
- 상시 켜짐 · 스위칭/코드 없음. 저전력 모듈이라 발열 무해, 상시점등해도 문제 없음.
- NoIR + 백색광 주의: NoIR 카메라 + 백색 LED 는 화면 색이 분홍빛으로 나온다(누수 여부 식별에는 지장 없음). 색을 정상으로 원하면 **일반 카메라(IR-cut 필터 내장)**를 쓴다.
- 자세한 배선/주의는
raspberry_pi4/WIRING.html"Camera Lighting (Always-On)" 절 참조.
배포 (기존 절차 재사용)
- 소스 트리: PMS7003 Pi 코드는
raspberry_pi4_pms7003/(SHT30 소스 미러 —pms7003_sensor.py/pms7003_driver.py/install.sh/vendor.sh/systemd/pms7003-sensor.service). - 기존 하드닝 노드(SSH off) 대상 USB 원샷 마이그레이션:
tools/migration_leak_add_pms7003/→ 생성물deploy/07_migration_leak_add_pms7003/.migrate.sh가 노드의 기존config_local.py에서 API_URL/API_KEY/위치/sensor_id 를 자동 추출해 같은 id 로 통합(시크릿 미포함 번들). - 폐쇄망: 빌드 PC 에서
cd pms7003 && bash vendor.sh→debs/·wheelhouse/동봉. - 서버:
config.local.php의METRIC_SENSOR_IDS에 1·3 포함 확인(온습도와 동일 목록).
비목표 (YAGNI)
- Pi-B(sensor_id 2, 온습도 전용) 변경 없음.
- 연기 개조/불꽃/CO/릴레이 감지 경로 — 전면 폐기(smoke proxy = PM 농도로 대체).
- PM 기반 자동 카메라 캡처 트리거 — 별개 이슈(이번 범위 밖).
- 카메라 조명 밝기 제어/스위칭 — 상시점등이라 불필요.