From a72ea18130dd3b82afabda3e7f8657f46a26b783 Mon Sep 17 00:00:00 2001 From: cw2007 Date: Fri, 10 Jul 2026 10:44:13 +0900 Subject: [PATCH] =?UTF-8?q?i18n(pi):=20Raspberry=20Pi=20=EB=B2=88=EB=93=A4?= =?UTF-8?q?=20=EC=86=8C=EC=8A=A4=20=ED=95=9C=EA=B8=80=20=E2=86=92=20?= =?UTF-8?q?=EC=98=81=EC=96=B4=20(=EC=BD=98=EC=86=94=20mojibake=20=ED=95=B4?= =?UTF-8?q?=EC=86=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 헤드리스 Pi 콘솔/journalctl에서 한글이 깨져 보이는 문제로, Pi 번들(02/03/04)에 들어가는 모든 소스의 사람-대상 텍스트를 영어로 전환. 코드·식별자·설정키·경로·숫자·hex·서명 스킴·f-string 플레이스홀더는 불변. - raspberry_pi4/, raspberry_pi4_sht30/: 로그·주석·문서·센서명·위치 영어화 - tools/make_deploy_bundles.py: 생성 템플릿(config_local.py/setup.sh/SETUP.md/PI_META 위치) 영어화 - tools/harden_pi.sh, tools/set_network.sh: echo/주석 영어화 - WIRING.html: 영어화 + SHT30 전압 경고 정정 반영 - 서버 번들(01, php/)은 한글 유지(브라우저 대시보드, Pi에서 안 깨짐) - 전 파이썬/셸 문법검사 통과, JSON 본문 서명 무영향 --- raspberry_pi4/.gitignore | 8 +- raspberry_pi4/README.md | 166 ++++++----- raspberry_pi4/WIRING.html | 184 ++++++------ raspberry_pi4/config.py | 108 +++---- raspberry_pi4/config_local.example.py | 54 ++-- raspberry_pi4/install.sh | 83 +++--- raspberry_pi4/leak_sensor.py | 229 +++++++-------- raspberry_pi4/requirements.txt | 4 +- raspberry_pi4/systemd/leak-sensor.service | 46 +-- raspberry_pi4/test_connection.py | 67 ++--- raspberry_pi4/vendor.sh | 50 ++-- raspberry_pi4_sht30/.gitignore | 8 +- raspberry_pi4_sht30/README.md | 152 +++++----- raspberry_pi4_sht30/WIRING.html | 135 ++++----- raspberry_pi4_sht30/config.py | 68 ++--- raspberry_pi4_sht30/config_local.example.py | 30 +- raspberry_pi4_sht30/install.sh | 108 +++---- raspberry_pi4_sht30/requirements.txt | 8 +- raspberry_pi4_sht30/sht30_sensor.py | 106 +++---- .../systemd/sht30-sensor.service | 32 +- raspberry_pi4_sht30/test_connection.py | 50 ++-- raspberry_pi4_sht30/test_sensor.py | 50 ++-- raspberry_pi4_sht30/vendor.sh | 52 ++-- raspberry_pi4_sht30/wire.py | 46 +-- tools/harden_pi.sh | 106 +++---- tools/make_deploy_bundles.py | 274 +++++++++--------- tools/set_network.sh | 158 +++++----- 27 files changed, 1200 insertions(+), 1182 deletions(-) diff --git a/raspberry_pi4/.gitignore b/raspberry_pi4/.gitignore index 0680897..1e182b6 100644 --- a/raspberry_pi4/.gitignore +++ b/raspberry_pi4/.gitignore @@ -1,14 +1,14 @@ -# 운영·비밀값 (절대 커밋 금지) +# Operational secrets (never commit) config_local.py -# Python venv / 캐시 +# Python venv / cache venv/ __pycache__/ *.pyc -# 오프라인 설치 번들 (vendor.sh 산출물 — 용량이 큼, 전송은 별도) +# Offline install bundle (vendor.sh output - large; transferred separately) wheelhouse/ debs/ -# 런타임 로그 +# Runtime logs *.log diff --git a/raspberry_pi4/README.md b/raspberry_pi4/README.md index e47226c..48bc845 100644 --- a/raspberry_pi4/README.md +++ b/raspberry_pi4/README.md @@ -1,127 +1,135 @@ -# 누수감지 센서 모듈 — Raspberry Pi 4 Model B 전용 +# Leak Detection Sensor Module — Raspberry Pi 4 Model B Only -e-con **5C-08 저항형 누수감지센서**를 Raspberry Pi 4 Model B 의 GPIO 로 읽어, -누수 발생 시 즉시 PHP API 서버에 보고(+SMS 발송 트리거)하고 **Pi Camera 로 현장 사진을 -촬영해 업로드**하는 모니터링 모듈입니다. +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**. -> 원래 **Raspberry Pi Zero 2 W** 용으로 작성된 모듈을 **Pi 4 Model B 전용**으로 이식한 -> 폴더입니다. GPIO(BCM) 번호 체계와 `rpicam`/`libcamera` 카메라 스택은 두 보드가 동일해 -> 센서·촬영 로직은 그대로이며, 차이는 **배선/전원/이더넷/카메라 커넥터**와 설치 환경뿐입니다. +> 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. 구성 파일 +## 1. Files -| 파일 | 역할 | +| File | Role | |---|---| -| `leak_sensor.py` | 메인 — GPIO 인터럽트 누수 감지, 주기 보고, 누수 시 촬영+업로드 | -| `config.py` | 비밀이 아닌 기본 설정(센서/임계/간격/카메라). `config_local` 에서 비밀값 로드 | -| `config_local.example.py` | 운영·비밀값 템플릿 → `config_local.py` 로 복사해 사용(미커밋) | -| `requirements.txt` | Python 의존성(핀 고정) | -| `install.sh` | Pi 4 설치 스크립트(폐쇄망 오프라인 + 온라인 폴백) | -| `vendor.sh` | 폐쇄망용 의존성 사전 다운로드(빌드 머신에서 실행) | -| `test_connection.py` | 서버 연결/서명 점검 | -| `systemd/leak-sensor.service` | 부팅 자동 실행 서비스 유닛 | +| `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. 하드웨어 (Pi 4 Model B 기준) +## 2. Hardware (based on Pi 4 Model B) - **Raspberry Pi 4 Model B** (BCM2711) + Raspberry Pi OS **Bookworm 64-bit** -- e-con **5C-08** 누수감지센서(저항형, 고임피던스 ~1.5MΩ) -- **외부 4.7MΩ 풀다운 저항** (필수 — 내부 풀저항은 끔) -- (선택) **Pi Camera** — Pi 4 = **15핀(1.0mm 피치) 표준 CSI**, Zero 2 W = **22핀(0.5mm 피치) CSI** - → 리본/카메라 보드 호환 안 됨 (Pi 4용 15핀 리본 또는 15↔22 변환 어댑터 필요) -- 전원: **USB-C 5V/3A** (카메라 사용 시 여유 전원 권장) -- 네트워크: Pi 4 **Gigabit Ethernet**(유선) 또는 WiFi +- e-con **5C-08** leak detection sensor (resistive, high-impedance ~1.5MΩ) +- **External 4.7MΩ 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 핀 배치 (기본 센서 1개) +### 2.1 Pinout (default single sensor) -| 신호 | BCM | 40핀 헤더 물리 핀 | +| Signal | BCM | 40-pin header physical pin | |---|---|---| -| 센서 입력 | GPIO17 | 11 | +| Sensor input | GPIO17 | 11 | | 3.3V | — | 1 | -| GND | — | 6 (또는 9/14/20/25/30/34/39) | +| GND | — | 6 (or 9/14/20/25/30/34/39) | -> 센서를 추가하려면 `config.py` 의 `SENSORS` 에 BCM 번호로 항목을 추가합니다. -> (예: GPIO27=물리 13번, GPIO22=물리 15번) +> 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 전기 설계 (중요) +### 2.2 Electrical design (important) -- `ACTIVE_LOW = False`: 건조 시 GPIO=LOW(0), 누수 시 GPIO=HIGH(1) -- `USE_INTERNAL_PULL = False`(**PUD_OFF 유지**): 내부 50kΩ 풀다운을 켜면 1.5MΩ 센서가 - GPIO 를 HIGH 로 끌어올리지 못해 **감지 실패**합니다. 외부 4.7MΩ 풀다운만 사용하세요. +- `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 4.7MΩ pull-down. --- -## 3. 서버 호환성 (반드시 확인) +## 3. Server compatibility (must verify) -이 모듈은 `leak_alert` / `leak_recovery` 이벤트와 `photo_upload.php` 를 **수신하는 서버**에 -보고합니다. +This module reports to a **server that receives** the `leak_alert` / `leak_recovery` events +and `photo_upload.php`. -> ✅ **이 repo 의 `php/` 서버가 바로 그 서버입니다(단일 서버 통합 완료).** -> 1번(누수+카메라)·2번(SHT30 온습도) 두 모듈 모두 **동일한 cafe24 `php/` 서버**에 -> raw-body 서명 `X-Signature = lowercase_hex(HMAC-SHA256(key=API_KEY, msg=요청본문 바이트))` -> 로 보고하며, 누수 상태·사진·온습도가 하나의 대시보드(`dashboard.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`). > -> - **신규 설치:** `sql/schema_sht30.sql` 하나만 실행 — 누수 요소 -> (`leak_sensor_log.is_leak` / `leak_sensor_status.is_leak` 컬럼, `leak_incident`, `leak_photo`, -> `leak_ingest_nonce` 테이블)가 이미 포함되어 있습니다. +> - **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. > -> `config_local.py` 의 `API_URL` / `PHOTO_UPLOAD_URL` 을 이 통합 서버로 설정하고, -> `API_KEY` 는 서버 `config.local.php` 의 `API_KEY` 와 **바이트 단위로 동일**하게 맞춥니다. +> 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. 설치 +## 4. Installation -### 4.1 설정값 준비 +### 4.1 Prepare configuration values ```bash cp config_local.example.py config_local.py -# config_local.py 를 열어 API_URL / PHOTO_UPLOAD_URL / API_KEY / DEVICE_ID 채움 +# Open config_local.py and fill in API_URL / PHOTO_UPLOAD_URL / API_KEY / DEVICE_ID ``` -`config_local.py` 가 없으면 실행 시 **명확한 오류로 즉시 중단**됩니다(fail closed). -`config_local.py` 와 `API_KEY` 는 **절대 커밋하지 마세요**(`.gitignore` 처리됨). +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 온라인 설치 (인터넷 가능 환경) +### 4.2 Online install (environment with internet) ```bash chmod +x install.sh ./install.sh ``` -### 4.3 폐쇄망(air-gapped) 오프라인 설치 +### 4.3 Air-gapped offline install -인터넷이 되는 **동일 아키텍처(aarch64, 가급적 동일 Pi 4 + Bookworm 64-bit)** 머신에서 -의존성을 먼저 받아 번들을 만든 뒤, 타깃 Pi 4 로 옮겨 설치합니다. +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 -# (빌드 머신, 인터넷 O) wheelhouse/ + debs/ 생성 +# (build machine, internet YES) create wheelhouse/ + debs/ ./vendor.sh -# wheelhouse/ 와 debs/ 를 타깃 Pi 4 의 이 폴더로 복사한 뒤: -# (타깃 Pi 4, 인터넷 X) -./install.sh # debs/ · wheelhouse/ 가 있으면 자동으로 오프라인 설치 +# 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 ``` -> `install.sh` 는 `debs/` 가 있으면 `dpkg` 오프라인, `wheelhouse/` 가 있으면 -> `pip --no-index` 오프라인으로 설치합니다. 둘 다 없을 때만 인터넷 apt/pip 로 폴백합니다. -> wheel/deb 는 아키텍처 종속이므로 x86_64 PC 에서 받은 것은 Pi 4 에서 동작하지 않습니다. +> 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. 실행 +## 5. Running ```bash source venv/bin/activate python3 leak_sensor.py ``` -`RPi.GPIO` 가 없는 환경(개발 PC 등)에서는 자동으로 **시뮬레이션 모드**로 동작합니다. +In an environment without `RPi.GPIO` (a development PC, etc.), it automatically runs in +**simulation mode**. -### 연결 점검 +### Connection check ```bash source venv/bin/activate @@ -130,10 +138,10 @@ python3 test_connection.py --- -## 6. 부팅 자동 실행 (systemd) +## 6. Auto-start on boot (systemd) ```bash -# 폴더를 /home/pi/raspberry_pi4 에 배치했다고 가정 (다르면 .service 의 경로 수정) +# 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 @@ -142,19 +150,19 @@ sudo systemctl status leak-sensor journalctl -u leak-sensor -f ``` -`SupplementaryGroups=video` 가 카메라 접근에 필요합니다. +`SupplementaryGroups=video` is required for camera access. --- -## 7. 보안 메모 +## 7. Security notes -- 비밀값(`API_KEY`)·서버 URL·기기 정보는 `config_local.py`(미커밋)에만 둡니다. - 커밋되는 파일에는 placeholder 만 존재합니다. -- 보고 본문은 **raw-body HMAC 서명**으로 위변조를 방지합니다: - `X-Signature = lowercase_hex(HMAC-SHA256(key=API_KEY, msg=요청본문 바이트))` - (`leak_sensor.sign_raw` ↔ 서버 `config.php::verify_signature_raw`, 2번 모듈과 동일 스킴). - - 사진 업로드 서명의 canonical 문자열은 `device_id|sensor_id|log_id|timestamp` - (공백 없음)입니다 (`config_local.example.py` 참고). - - 구버전의 `sha256(API_KEY + 정렬 JSON)` body-field 서명은 **폐기**되었고, 서버 기본 - 설정이 거부합니다(`ALLOW_LEGACY_BODY_SIGNATURE=false`, `php/config.php`). -- `config_local.py` 노출 시 즉시 `API_KEY` 를 교체(서버 동시 변경)하세요. +- 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). diff --git a/raspberry_pi4/WIRING.html b/raspberry_pi4/WIRING.html index fb1eef7..b935474 100644 --- a/raspberry_pi4/WIRING.html +++ b/raspberry_pi4/WIRING.html @@ -1,9 +1,9 @@ - + -누수 감지 노드 · 배선 & 핀맵 (Raspberry Pi 4) +Leak Detection Node · Wiring & Pinmap (Raspberry Pi 4)