POSA_LEAKSMS/raspberry_pi4/README.md
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

168 lines
6.5 KiB
Markdown

# 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
```bash
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)
```bash
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.
```bash
# (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
```bash
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
```bash
source venv/bin/activate
python3 test_connection.py
```
---
## 6. Auto-start on boot (systemd)
```bash
# 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).