POSA_LEAKSMS/raspberry_pi4_sht30
cw2007 73e49fd528 feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝
2번 모듈 신규(raspberry_pi4_sht30/): SHT30 온습도 → cafe24, raw-body X-Signature HMAC, 폐쇄망 오프라인 설치(vendor/install), systemd, CRC/포맷 자가점검. firmware sht30_fw wire 포맷과 byte-parity 검증.

1번 모듈 통합(raspberry_pi4/): 누수+카메라를 동일 서버로. 레거시 sha256(key+json) body-sig → X-Signature HMAC 전환, 사진 canonical=device_id|sensor_id|log_id|timestamp.

서버 통합(php/): api/sensor_data.php 누수 이벤트 수신, api/photo_upload.php 신규(HMAC·finfo·서버생성 파일명·nonce 멱등·sensor 결속), photo.php 인증 사진서빙, dashboard.php 누수 패널+사진, sms_send.php 누수 SMS, config.php 태그/요약.

DB: sql/migration_add_leak.sql(가산·멱등), schema_sht30.sql 통합 스키마.

보안 하드닝(외부 펜테스트 대비, 확정 CRITICAL/HIGH 0): cron_heartbeat api_key fail-closed, setup_mfa 부트스트랩 토큰 post-enrollment 잠금, var/ PHP 실행차단, HSTS.

문서/테스트: SYSTEM_OVERVIEW.md, security_hardening_test.php 갱신. 참고: 사용자 요청으로 세션 외 기존 미커밋 변경도 함께 포함.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:21:11 +09:00
..
systemd feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝 2026-06-23 16:21:11 +09:00
.gitignore feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝 2026-06-23 16:21:11 +09:00
config.py feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝 2026-06-23 16:21:11 +09:00
config_local.example.py feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝 2026-06-23 16:21:11 +09:00
install.sh feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝 2026-06-23 16:21:11 +09:00
README.md feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝 2026-06-23 16:21:11 +09:00
requirements.txt feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝 2026-06-23 16:21:11 +09:00
sht30_driver.py feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝 2026-06-23 16:21:11 +09:00
sht30_sensor.py feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝 2026-06-23 16:21:11 +09:00
test_connection.py feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝 2026-06-23 16:21:11 +09:00
test_sensor.py feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝 2026-06-23 16:21:11 +09:00
vendor.sh feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝 2026-06-23 16:21:11 +09:00
wire.py feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝 2026-06-23 16:21:11 +09:00

온습도(SHT30) 센서 모듈 — Raspberry Pi 4 Model B 전용 (2번 모듈)

Sensirion SHT30(한진데이터 P4422-3, I2C) 온습도 센서를 Raspberry Pi 4 Model B 의 I2C 버스로 읽어, 주기적으로 cafe24 서버(php/api/sensor_data.php)에 보고하는 모듈입니다. 서버가 측정값을 저장하고, 고온/저온/고습/저습 임계 판정과 SMS, 대시보드 표시를 모두 수행합니다.

이 폴더는 STM32F407 펌웨어(sht30_fw)의 동작을 Raspberry Pi 4 + Python 으로 이식한 "2번 모듈"입니다. wire 포맷(본문/서명)·CRC·변환식은 펌웨어와 바이트 단위로 동일합니다. "1번 모듈"(누수+카메라)은 ../raspberry_pi4/ 폴더입니다. 전체 구성은 루트의 SYSTEM_OVERVIEW.md를 보세요.


1. 구성 파일

파일 역할
sht30_sensor.py 메인 — 주기 측정 → 본문 생성/서명 → POST(재시도), startup→periodic
sht30_driver.py SHT30 I2C 측정 + CRC-8 검증 + 물리값 변환 (smbus2, 시뮬레이션 폴백)
wire.py 본문 JSON + raw-body HMAC 서명 (펌웨어 jsonbody.c/sig.c와 바이트 동일)
config.py 비밀 아닌 기본 설정(센서 id/주기/범위/ I2C). config_local 에서 비밀값 로드
config_local.example.py 운영·비밀값 템플릿 → config_local.py 로 복사해 사용(미커밋)
requirements.txt Python 의존성(requests, smbus2, 핀 고정)
install.sh Pi 4 설치(폐쇄망 오프라인 + 온라인 폴백, I2C 활성화 포함)
vendor.sh 폐쇄망용 의존성 사전 다운로드(빌드 머신에서 실행)
test_connection.py 서버 연결/서명 POST 점검
test_sensor.py CRC/포맷 자가점검 + 측정 1회(하드웨어 없이도 포맷 점검 통과)
systemd/sht30-sensor.service 부팅 자동 실행 서비스 유닛

2. 하드웨어 (Pi 4 Model B 기준)

  • Raspberry Pi 4 Model B (BCM2711) + Raspberry Pi OS Bookworm 64-bit
  • SHT30 온습도 센서 모듈 (I2C, 한진데이터 P4422-3)
  • I2C 풀업 저항 4.7kΩ × 2 (모듈에 내장된 경우 생략)
  • 전원: USB-C 5V/3A, 네트워크: Pi 4 Gigabit Ethernet(유선) 또는 WiFi

2.1 핀 배치 (I2C 버스 1)

신호 Pi 4 핀 비고
SHT30 VCC 3.3V (물리 1) 5V 금지
SHT30 GND GND (물리 6/9/14/…)
SHT30 SDA GPIO2 / SDA1 (물리 3) + 4.7kΩ 풀업 → 3.3V
SHT30 SCL GPIO3 / SCL1 (물리 5) + 4.7kΩ 풀업 → 3.3V
SHT30 ADDR GND → 주소 0x44 VDD 면 0x45 (config.py I2C_ADDR)

3. 서버 호환성 (반드시 확인)

이 모듈은 **현재 repo 의 php/ 서버(=cafe24 SHT30 대시보드 서버)**로 보고합니다. 서버는 raw-body HMAC 서명을 요구합니다.

X-Signature = lowercase_hex( HMAC-SHA256( key=API_KEY, msg=요청본문 바이트 ) )
  • config_local.py 의 API_KEY 는 서버 config.local.php 의 API_KEY 와 정확히 동일해야 합니다.
  • 서버는 timestamp 신선도(±600초)로 재전송을 막으므로 Pi 시각이 NTP 로 동기되어 있어야 합니다(Raspberry Pi OS 기본 활성).
  • sensor_id=2 로 보고하며, 서버 대시보드(dashboard.php)는 기본 차트로 sensor 2 를 표시합니다.
  • 임계 경보(고온/저온/고습/저습)·SMS·복구 판정은 모두 서버가 수행합니다. 이 모듈은 측정값만 보고합니다.

서버 측 스키마/배포는 ../sql/schema_sht30.sql, ../docs/INSTALL_PI_SERVER.md, ../docs/SHT30_SENSOR2_SETUP.md 참고.


4. 설치

4.1 설정값 준비

cp config_local.example.py config_local.py
# config_local.py 를 열어 API_URL / API_KEY / DEVICE_ID / DEVICE_LOCATION 채움

config_local.py 가 없으면 실행 시 명확한 오류로 즉시 중단됩니다(fail closed). config_local.py 와 API_KEY 는 절대 커밋하지 마세요(.gitignore 처리됨).

4.2 온라인 설치 (인터넷 가능 환경)

chmod +x install.sh
./install.sh
sudo reboot      # I2C 를 새로 켠 경우 1회 재부팅

4.3 폐쇄망(air-gapped) 오프라인 설치

인터넷이 되는 동일 아키텍처(aarch64, 가급적 동일 Pi 4 + Bookworm 64-bit) 머신에서 의존성을 먼저 받아 번들을 만든 뒤, 타깃 Pi 4 로 옮겨 설치합니다.

# (빌드 머신, 인터넷 O) wheelhouse/ + debs/ 생성
./vendor.sh

# wheelhouse/ 와 debs/ 를 타깃 Pi 4 의 이 폴더로 복사한 뒤:
# (타깃 Pi 4, 인터넷 X)
./install.sh        # debs/ · wheelhouse/ 가 있으면 자동으로 오프라인 설치

smbus2 는 순수 파이썬(arch 무관)이라 x86 빌드 머신에서 받아도 됩니다. requests 등 다른 wheel/deb 는 aarch64 용을 받아야 합니다(타깃 arch 에서 vendor.sh 권장).


5. 실행 / 점검

# 센서가 보이는지 (0x44)
i2cdetect -y 1

# 포맷/CRC 자가점검 + 측정 1회 (하드웨어 없으면 시뮬레이션)
source venv/bin/activate
python3 test_sensor.py

# 서버 연결/서명 점검
python3 test_connection.py

# 실제 실행
python3 sht30_sensor.py

smbus2 미설치 또는 I2C 미활성 환경(개발 PC 등)에서는 자동으로 시뮬레이션 모드로 동작합니다.


6. 부팅 자동 실행 (systemd)

# 폴더를 /home/pi/raspberry_pi4_sht30 에 배치했다고 가정 (다르면 .service 의 경로 수정)
sudo cp systemd/sht30-sensor.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable sht30-sensor
sudo systemctl start sht30-sensor
sudo systemctl status sht30-sensor
journalctl -u sht30-sensor -f

SupplementaryGroups=i2c 가 /dev/i2c-1 접근에 필요합니다.


7. 보안 메모

  • 비밀값(API_KEY)·서버 URL·기기 정보는 config_local.py(미커밋)에만 둡니다. 커밋되는 파일에는 placeholder 만 존재합니다.
  • 보고 본문은 HMAC-SHA256(API_KEY, raw_body) 서명(X-Signature 헤더)으로 위변조를 방지합니다 (길이확장 공격에 면역). 레거시 body-field sha256 폴백은 서버에서 기본 비활성입니다.
  • 서명하는 바이트와 전송하는 바이트는 항상 동일합니다(wire.py 가 본문을 직접 만들어 그 바이트에 서명 후 raw POST). 펌웨어 sig.c / reference.py / 서버 verify_signature_raw 와 바이트 단위로 일치합니다.
  • config_local.py 노출 시 즉시 API_KEY 를 교체(서버 동시 변경)하세요.