POSA_LEAKSMS/raspberry_pi4
cw2007 ec78be0bda feat(pms7003): 누수 노드에 미세먼지(PM2.5/PM10) 통합
센서1·3(누수 노드)에 PMS7003 를 온습도와 동일 sensor_id 로 통합하고 metric_type='pms7003'
로 구분해 수집한다. LED 는 스위칭 없이 상시 점등 방식으로 확정.

- raspberry_pi4_pms7003/: PMS7003 노드 풀세트(드라이버·센서·install·systemd·vendor·배선·연결테스트·프레임 단위테스트)
- 서버: evaluate_metric_thresholds() 에 pm25/pm10 선택 인자 추가(온습도 전용 호출 후방호환),
  sensor_data.php 수집 경로에 pms7003 metric 반영, config.php/예시에 PM 임계 추가
- SQL: migration_pms7003.sql · schema_sht30.sql 정합, tools/migration_leak_add_{pms7003,sht30} 마이그레이터
- tests/pm_threshold_test.php + run_tests.sh 러너 등록
- .gitignore: 노드별 config_local.py 커밋 차단
2026-07-19 10:46:33 +09:00
..
systemd i18n(pi): Raspberry Pi 번들 소스 한글 → 영어 (콘솔 mojibake 해소) 2026-07-10 10:44:13 +09:00
.gitignore i18n(pi): Raspberry Pi 번들 소스 한글 → 영어 (콘솔 mojibake 해소) 2026-07-10 10:44:13 +09:00
config.py feat(pms7003): 누수 노드에 미세먼지(PM2.5/PM10) 통합 2026-07-19 10:46:33 +09:00
config_local.example.py i18n(pi): Raspberry Pi 번들 소스 한글 → 영어 (콘솔 mojibake 해소) 2026-07-10 10:44:13 +09:00
install.sh i18n(pi): Raspberry Pi 번들 소스 한글 → 영어 (콘솔 mojibake 해소) 2026-07-10 10:44:13 +09:00
leak_sensor.py feat(pms7003): 누수 노드에 미세먼지(PM2.5/PM10) 통합 2026-07-19 10:46:33 +09:00
README.md feat(pms7003): 누수 노드에 미세먼지(PM2.5/PM10) 통합 2026-07-19 10:46:33 +09:00
requirements.txt i18n(pi): Raspberry Pi 번들 소스 한글 → 영어 (콘솔 mojibake 해소) 2026-07-10 10:44:13 +09:00
test_connection.py i18n(pi): Raspberry Pi 번들 소스 한글 → 영어 (콘솔 mojibake 해소) 2026-07-10 10:44:13 +09:00
vendor.sh i18n(pi): Raspberry Pi 번들 소스 한글 → 영어 (콘솔 mojibake 해소) 2026-07-10 10:44:13 +09:00
WIRING.html feat(pms7003): 누수 노드에 미세먼지(PM2.5/PM10) 통합 2026-07-19 10:46:33 +09:00

Leak Detection Sensor Module — Raspberry Pi 4 Model B Only

A monitoring module that reads the e-con 5C-08 resistive leak detection sensor via the GPIO of a Raspberry Pi 4 Model B. On a leak it immediately reports to the PHP API server (+ triggers an SMS), and captures an on-site photo with the Pi Camera and uploads it.

This folder is a port of a module originally written for the Raspberry Pi Zero 2 W, adapted to be Pi 4 Model B only. The GPIO (BCM) numbering scheme and the rpicam/libcamera camera stack are identical on both boards, so the sensor/capture logic is unchanged; the differences are only in the wiring/power/Ethernet/camera connector and the install environment.


1. Files

File Role
leak_sensor.py Main — GPIO interrupt leak detection, periodic reporting, capture+upload on leak
config.py Non-secret default settings (sensor/threshold/interval/camera). Loads secrets from config_local
config_local.example.py Operational/secret value template → copy to config_local.py before use (not committed)
requirements.txt Python dependencies (pinned)
install.sh Pi 4 install script (air-gapped offline + online fallback)
vendor.sh Pre-download dependencies for air-gapped use (run on build machine)
test_connection.py Server connection/signature check
systemd/leak-sensor.service Auto-start-on-boot service unit

2. Hardware (based on Pi 4 Model B)

  • Raspberry Pi 4 Model B (BCM2711) + Raspberry Pi OS Bookworm 64-bit
  • e-con 5C-08 leak detection sensor (resistive, high-impedance ~1.5MΩ)
  • External 10MΩ pull-down resistor (required — internal pull resistor is off)
  • (Optional) Pi Camera — Pi 4 = 15-pin (1.0mm pitch) standard CSI, Zero 2 W = 22-pin (0.5mm pitch) CSI → Ribbon/camera boards are not compatible (a Pi 4 15-pin ribbon or a 15↔22 adapter is required)
  • Power: USB-C 5V/3A (a power margin is recommended when using the camera)
  • Network: Pi 4 Gigabit Ethernet (wired) or WiFi

2.1 Pinout (default single sensor)

Signal BCM 40-pin header physical pin
Sensor input GPIO17 11
3.3V — 1
GND — 6 (or 9/14/20/25/30/34/39)

To add a sensor, add an entry by BCM number to SENSORS in config.py. (e.g. GPIO27=physical pin 13, GPIO22=physical pin 15)

2.2 Electrical design (important)

  • ACTIVE_LOW = False: when dry GPIO=LOW(0), on leak GPIO=HIGH(1)
  • USE_INTERNAL_PULL = False (keep PUD_OFF): if you turn on the internal 50kΩ pull-down, the 1.5MΩ sensor cannot pull GPIO up to HIGH, causing detection failure. Use only the external 10MΩ pull-down.

3. Server compatibility (must verify)

This module reports to a server that receives the leak_alert / leak_recovery events and photo_upload.php.

✅ The php/ server in this repo is exactly that server (single-server integration complete). Both module 1 (leak + camera) and module 2 (SHT30 temperature/humidity) report to the same cafe24 php/ server with the raw-body signature X-Signature = lowercase_hex(HMAC-SHA256(key=API_KEY, msg=request body bytes)), and leak status, photos, and temperature/humidity are shown together on a single dashboard (dashboard.php).

  • New install: run only sql/schema_sht30.sql — the leak elements (leak_sensor_log.is_leak / leak_sensor_status.is_leak columns, leak_incident, leak_photo, leak_ingest_nonce tables) are already included.

Set API_URL / PHOTO_UPLOAD_URL in config_local.py to this integrated server, and make API_KEY byte-for-byte identical to the API_KEY in the server's config.local.php.


4. Installation

4.1 Prepare configuration values

cp config_local.example.py config_local.py
# Open config_local.py and fill in API_URL / PHOTO_UPLOAD_URL / API_KEY / DEVICE_ID

If config_local.py is missing, execution stops immediately with a clear error (fail closed). Never commit config_local.py or API_KEY (they are handled by .gitignore).

4.2 Online install (environment with internet)

chmod +x install.sh
./install.sh

4.3 Air-gapped offline install

On a machine with internet of the same architecture (aarch64, ideally the same Pi 4 + Bookworm 64-bit), first fetch the dependencies to build a bundle, then move it to the target Pi 4 to install.

# (build machine, internet YES) create wheelhouse/ + debs/
./vendor.sh

# After copying wheelhouse/ and debs/ into this folder on the target Pi 4:
# (target Pi 4, internet NO)
./install.sh        # if debs/ · wheelhouse/ exist, installs offline automatically

If debs/ exists, install.sh installs offline with dpkg; if wheelhouse/ exists, it installs offline with pip --no-index. It falls back to internet apt/pip only when neither is present. wheel/deb are architecture-dependent, so ones fetched on an x86_64 PC will not work on the Pi 4.


5. Running

source venv/bin/activate
python3 leak_sensor.py

In an environment without RPi.GPIO (a development PC, etc.), it automatically runs in simulation mode.

Connection check

source venv/bin/activate
python3 test_connection.py

6. Auto-start on boot (systemd)

# Assumes the folder is placed at /home/pi/raspberry_pi4 (if different, edit the path in .service)
sudo cp systemd/leak-sensor.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable leak-sensor
sudo systemctl start leak-sensor
sudo systemctl status leak-sensor
journalctl -u leak-sensor -f

SupplementaryGroups=video is required for camera access.


7. Security notes

  • Secret values (API_KEY), the server URL, and device info live only in config_local.py (not committed). Committed files contain only placeholders.
  • The report body is protected against tampering with a raw-body HMAC signature: X-Signature = lowercase_hex(HMAC-SHA256(key=API_KEY, msg=request body bytes)) (leak_sensor.sign_raw ↔ server config.php::verify_signature_raw, same scheme as module 2).
    • The canonical string for the photo upload signature is device_id|sensor_id|log_id|timestamp (no spaces) (see config_local.example.py).
    • The old sha256(API_KEY + sorted JSON) body-field signature is deprecated, and the server default rejects it (ALLOW_LEGACY_BODY_SIGNATURE=false, php/config.php).
  • If config_local.py is exposed, immediately rotate API_KEY (change it on the server at the same time).