From 42a6ee4bb07dec49485270584a951574d3c2eea1 Mon Sep 17 00:00:00 2001 From: cw2007 Date: Sun, 19 Jul 2026 10:47:00 +0900 Subject: [PATCH] =?UTF-8?q?feat(display):=20Zero=202=20W=20ST7789=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EB=94=94=EC=8A=A4=ED=94=8C=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=20=EB=85=B8=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pi Zero 2 W + ST7789 패널에 노드 상태(누수/온습도/미세먼지·오프라인·정체)를 상시 표시하는 디스플레이 노드 신설. 배포 전 렌더 검증 원칙에 따라 합성 최악 프레임 11종을 패널 실해상도로 render_preview/ 에 PNG 로 선렌더. - st7789_driver.py · display_dashboard.py · render_preview.py(합성 프레임 생성) - install.sh · vendor.sh · systemd/display-dashboard.service · 배선(WIRING)·연결테스트 - render_preview/01~11: 요약/통합/메트릭/오프라인/stale/legacy-무PM 최악 케이스 --- raspberry_pi_zero2w_display/README.md | 48 ++ raspberry_pi_zero2w_display/WIRING.html | 85 ++++ raspberry_pi_zero2w_display/config.py | 50 +++ .../display_dashboard.py | 409 ++++++++++++++++++ raspberry_pi_zero2w_display/install.sh | 114 +++++ raspberry_pi_zero2w_display/render_preview.py | 209 +++++++++ .../render_preview/01_summary_leak.png | Bin 0 -> 9718 bytes .../render_preview/02_summary_pm.png | Bin 0 -> 10282 bytes .../render_preview/03_combined_leak.png | Bin 0 -> 15782 bytes .../render_preview/04_combined_pm25.png | Bin 0 -> 16747 bytes .../render_preview/05_combined_pm10.png | Bin 0 -> 17224 bytes .../render_preview/06_combined_normal.png | Bin 0 -> 16283 bytes .../07_combined_offline_leak.png | Bin 0 -> 10793 bytes .../08_combined_legacy_no_pm.png | Bin 0 -> 15269 bytes .../render_preview/09_metric_normal.png | Bin 0 -> 12056 bytes .../render_preview/10_offline.png | Bin 0 -> 6880 bytes .../render_preview/11_summary_stale.png | Bin 0 -> 10215 bytes raspberry_pi_zero2w_display/requirements.txt | 4 + raspberry_pi_zero2w_display/st7789_driver.py | 159 +++++++ .../systemd/display-dashboard.service | 51 +++ .../test_connection.py | 36 ++ raspberry_pi_zero2w_display/vendor.sh | 40 ++ 22 files changed, 1205 insertions(+) create mode 100644 raspberry_pi_zero2w_display/README.md create mode 100644 raspberry_pi_zero2w_display/WIRING.html create mode 100644 raspberry_pi_zero2w_display/config.py create mode 100644 raspberry_pi_zero2w_display/display_dashboard.py create mode 100644 raspberry_pi_zero2w_display/install.sh create mode 100644 raspberry_pi_zero2w_display/render_preview.py create mode 100644 raspberry_pi_zero2w_display/render_preview/01_summary_leak.png create mode 100644 raspberry_pi_zero2w_display/render_preview/02_summary_pm.png create mode 100644 raspberry_pi_zero2w_display/render_preview/03_combined_leak.png create mode 100644 raspberry_pi_zero2w_display/render_preview/04_combined_pm25.png create mode 100644 raspberry_pi_zero2w_display/render_preview/05_combined_pm10.png create mode 100644 raspberry_pi_zero2w_display/render_preview/06_combined_normal.png create mode 100644 raspberry_pi_zero2w_display/render_preview/07_combined_offline_leak.png create mode 100644 raspberry_pi_zero2w_display/render_preview/08_combined_legacy_no_pm.png create mode 100644 raspberry_pi_zero2w_display/render_preview/09_metric_normal.png create mode 100644 raspberry_pi_zero2w_display/render_preview/10_offline.png create mode 100644 raspberry_pi_zero2w_display/render_preview/11_summary_stale.png create mode 100644 raspberry_pi_zero2w_display/requirements.txt create mode 100644 raspberry_pi_zero2w_display/st7789_driver.py create mode 100644 raspberry_pi_zero2w_display/systemd/display-dashboard.service create mode 100644 raspberry_pi_zero2w_display/test_connection.py create mode 100644 raspberry_pi_zero2w_display/vendor.sh diff --git a/raspberry_pi_zero2w_display/README.md b/raspberry_pi_zero2w_display/README.md new file mode 100644 index 0000000..b61ac14 --- /dev/null +++ b/raspberry_pi_zero2w_display/README.md @@ -0,0 +1,48 @@ +# 미니 상태 표시기 — Pi Zero 2 W + ST7789V (GMT020-02 2.0" 240×320) + +관제 서버의 요약 상태를 2인치 IPS 화면에 상시 표시하는 글랜스 장치. +서버 `api/status_summary.php` 를 30초 폴링(읽기 전용, X-Status-Key HMAC 인증), +페이지 자동 순환: 시스템 요약 → 센서별(누수/온습도) 상세. +배경색 = 시스템 상태(정상 녹색 / 온습도 경보 주황 / 누수 청색 / 오프라인 회색 / +서버 무응답 적색 STALE). + +## 배선 (GMT020-02 7핀 ↔ Zero 2 W 40핀, BCM) + +| LCD 핀 | 기능 | Pi 핀(BCM) | 물리 핀 | +|---|---|---|---| +| VCC | 3.3V | 3V3 | 17 | +| GND | GND | GND | 20 | +| SCL | SPI SCLK | GPIO11 | 23 | +| SDA | SPI MOSI | GPIO10 | 19 | +| RES | Reset | GPIO24 | 18 | +| DC | Data/Cmd | GPIO25 | 22 | +| CS | Chip Select | GPIO8 (CE0) | 24 | + +핀 변경 시 `config.py` 의 PIN_* 수정. 상세 그림: `WIRING.html`. + +## 설치 + +```bash +cp config_local.example.py config_local.py # STATUS_URL / STATUS_KEY 입력(파생키 — API_KEY 아님) +./install.sh # SPI 활성 + apt + venv (번들 있으면 오프라인) +python3 test_connection.py # 서버 연결 검증 +sudo cp systemd/display-dashboard.service /etc/systemd/system/ +sudo systemctl daemon-reload && sudo systemctl enable --now display-dashboard +``` + +폐쇄망: 빌드 PC에서 `bash vendor.sh` → `debs/`+`wheelhouse/` 동봉 후 USB 이송. +하드닝: 센서 노드와 동일 `harden_pi.sh` 사용 가능(아웃바운드 전용 장치). + +## 화면 텍스트 + +기본 폰트 DejaVu → 라벨은 영문 축약(ALL OK / LEAK! / TEMP C …). +한글 표시를 원하면 한글 TTF 를 복사하고 `config.py` FONT_PATH 를 바꾼다 +(폐쇄망이므로 폰트 파일도 USB 로 반입). + +## 문제 해결 + +- 화면 백지: SPI 활성 여부(`ls /dev/spidev0.0`), 배선(DC/RES 스왑 흔함) +- 색 이상: `config.py` INVERT 토글 +- 403: STATUS_KEY 불일치 — `php -r 'echo hash_hmac("sha256","status","<서버 API_KEY>");'` 로 재계산 +- 서비스 로그: `journalctl -u display-dashboard -e` +- 하드웨어 없이 렌더 확인: `FORCE_SIMULATION = True` → `/tmp/display_preview.png` diff --git a/raspberry_pi_zero2w_display/WIRING.html b/raspberry_pi_zero2w_display/WIRING.html new file mode 100644 index 0000000..9988508 --- /dev/null +++ b/raspberry_pi_zero2w_display/WIRING.html @@ -0,0 +1,85 @@ + + + + +배선도 — Pi Zero 2 W + ST7789V (GMT020-02) + + + +

배선도 — Pi Zero 2 W + ST7789V GMT020-02 (2.0" 240×320 IPS)

+ +

⚠️ 반드시 3.3V 사용. 5V 연결 시 패널 손상. 배선은 전원 차단 상태에서.

+ +

연결표 (7핀)

+ + + + + + + + + +
LCD 핀기능Pi GPIO (BCM)물리 핀 번호선색 예시
VCC전원 3.3V3V317빨강
GND접지GND20검정
SCLSPI 클럭(SCLK)GPIO1123주황
SDASPI 데이터(MOSI)GPIO1019노랑
RES리셋 (RST/RESET 과 동일 표기)GPIO2418초록
DC데이터/명령 선택GPIO2522파랑
CS칩 선택(CE0)GPIO824보라
+ +

Zero 2 W 40핀 핀맵 (위에서 본 그림)

+

배선 7가닥 전부 물리 17~24번 블록에 모여 있다 — 헤더 중간 8핀 구간만 쓰면 된다.

+

보드 부품면(위)에서 본 헤더. SD 카드 슬롯이 위, GPIO 헤더가 오른쪽 세로로 오는 방향 기준 +— 핀 1 = 헤더 맨 위 왼쪽(사각 납땜 패드). 왼쪽 열=홀수 핀(보드 안쪽), 오른쪽 열=짝수 핀(보드 가장자리).

+
+ 이번 배선 사용 + 3.3V + 5V + GND +
+ + + + + + + + + + + + + + + + + + + + + +
3V3125V
GPIO2 (SDA1)345V
GPIO3 (SCL1)56GND
GPIO478GPIO14 (TXD)
GND910GPIO15 (RXD)
GPIO171112GPIO18
GPIO271314GND
GPIO221516GPIO23
3V3→ VCC1718GPIO24→ RES
GPIO10 (MOSI)→ SDA1920GND→ GND
GPIO9 (MISO)2122GPIO25→ DC
GPIO11 (SCLK)→ SCL2324GPIO8 (CE0)→ CS
GND2526GPIO7 (CE1)
ID_SD2728ID_SC
GPIO52930GND
GPIO63132GPIO12
GPIO133334GND
GPIO193536GPIO16
GPIO263738GPIO20
GND3940GPIO21
+

방향 확인법: 헤더 납땜면에서 핀 1만 사각 패드(나머지는 원형). 핀 1 은 SD 카드 슬롯과 같은 쪽 모서리다.

+ +

점검

+
    +
  1. SPI 활성 확인: ls /dev/spidev0.0 (install.sh 가 dtparam=spi=on 설정, 재부팅 필요할 수 있음)
  2. +
  3. 화면 백지면 DC/RES 스왑 여부부터 확인(가장 흔한 실수)
  4. +
  5. 색이 반전돼 보이면 config.py 의 INVERT 토글
  6. +
  7. 렌더만 검증: FORCE_SIMULATION = True → /tmp/display_preview.png
  8. +
+ + diff --git a/raspberry_pi_zero2w_display/config.py b/raspberry_pi_zero2w_display/config.py new file mode 100644 index 0000000..d8fe183 --- /dev/null +++ b/raspberry_pi_zero2w_display/config.py @@ -0,0 +1,50 @@ +# ============================================================================= +# config.py — 미니 상태 표시기 (Pi Zero 2 W + ST7789V GMT020-02 2.0" 240x320) +# 비밀값(STATUS_URL/STATUS_KEY)은 config_local.py 에서 로드한다(커밋 금지). +# cp config_local.example.py config_local.py 후 실값 입력. +# ============================================================================= + +# ───────────────────────────────────────────── +# 폴링/화면 주기 +# ───────────────────────────────────────────── +POLL_INTERVAL = 30 # 서버 상태 폴링 주기(초) — 대시보드 자동 새로고침과 동일 +PAGE_INTERVAL = 8 # 페이지 자동 순환 주기(초): 요약 ↔ 센서별 +FETCH_TIMEOUT = 10 # HTTP 타임아웃(초) +STALE_AFTER = 120 # 마지막 성공 수신 후 이 시간(초) 지나면 STALE 표시 + +# ───────────────────────────────────────────── +# ST7789V SPI 배선 (BCM 번호) — README.md 배선표와 일치 +# GMT020-02(7핀): GND / VCC / SCL=SCLK / SDA=MOSI / RES / DC / CS (BLK 없음) +# ───────────────────────────────────────────── +SPI_BUS = 0 # SPI0 +SPI_DEVICE = 0 # CE0 (GPIO8) +SPI_SPEED_HZ = 40_000_000 +PIN_DC = 25 # Data/Command +PIN_RST = 24 # Reset — 물리 18번(SDA 옆). 7핀을 물리 17~24 블록에 집약 +PIN_BL = None # 7핀 모듈은 백라이트 핀 없음(내부 상시 점등). 8핀이면 BCM 번호(예: 18) + +WIDTH = 240 +HEIGHT = 320 +ROTATION = 0 # 0/90/180/270 — 설치 방향에 맞춰 조정 +INVERT = True # GMT020-02(IPS) 는 색반전 ON 이 정색 + +# 하드웨어 없이 개발/검증: True 면 SPI 대신 /tmp/display_preview.png 로 렌더 저장. +# spidev/RPi.GPIO 미설치 환경에서는 자동으로 시뮬레이션 폴백. +FORCE_SIMULATION = False + +# 한글 라벨이 필요하면 한글 TTF 경로 지정(기본은 DejaVu — 영문/숫자만). +FONT_PATH = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf" +FONT_PATH_LIGHT = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf" + +LOG_FILE = "/var/log/display_dashboard.log" + +# ───────────────────────────────────────────── +# 비밀값 로드 (fail closed — config_local.py 없으면 즉시 중단) +# ───────────────────────────────────────────── +try: + from config_local import * # noqa: F401,F403 — STATUS_URL/STATUS_KEY/DEVICE_NAME +except ImportError as e: + raise RuntimeError( + "config_local.py not found. Run `cp config_local.example.py config_local.py`, " + "then fill in STATUS_URL / STATUS_KEY." + ) from e diff --git a/raspberry_pi_zero2w_display/display_dashboard.py b/raspberry_pi_zero2w_display/display_dashboard.py new file mode 100644 index 0000000..a0a50dd --- /dev/null +++ b/raspberry_pi_zero2w_display/display_dashboard.py @@ -0,0 +1,409 @@ +#!/usr/bin/env python3 +# ============================================================================= +# display_dashboard.py — 미니 상태 표시기 메인 루프 (Pi Zero 2 W + ST7789V 2.0") +# +# 서버 api/status_summary.php 를 30초 폴링 → 240x320 화면 렌더(Pillow) → SPI 블릿. +# 페이지 자동 순환: [0] 시스템 요약 → [1..n] 센서별 상세. +# 배경색 = 시스템 상태(정상 녹색 / 온습도 주황 / 미세먼지 마젠타 / 누수 청색 / 오프라인 회색). +# 서버 미응답 시 마지막 데이터 + STALE 배너(경과 시간) 표시. +# +# 글꼴: 기본 DejaVu(영문/숫자) — 2인치 글랜스 화면이라 라벨은 영문 축약. +# 한글 라벨 원하면 config FONT_PATH 에 한글 TTF 지정. +# ============================================================================= +import sys +import time + +import requests +from PIL import Image, ImageDraw, ImageFont + +import config +from st7789_driver import open_display + +W, H = config.WIDTH, config.HEIGHT + +# 상태색 (배경, 강조) — 대시보드 팔레트와 동일 계열 +STATE_COLORS = { + "ok": ((10, 40, 28), (53, 214, 160)), + "alert": ((52, 30, 6), (255, 178, 62)), + "pm": ((42, 12, 48), (208, 120, 236)), # 미세먼지 — 마젠타/바이올렛(온습도 주황과 명확히 구분) + "leak": ((8, 30, 52), (63, 199, 230)), + "offline": ((30, 32, 44), (120, 133, 184)), + "stale": ((40, 12, 20), (255, 84, 112)), +} +INK = (234, 238, 255) # 1차: 값/제목 +INK2 = (150, 160, 200) # 2차: 보조 텍스트 +INK3 = (96, 104, 140) # 3차: eyebrow 라벨·눈금 +HAIR = (42, 48, 72) # 헤어라인 구분선 +TEMP_C = (255, 149, 100) +HUM_C = (74, 194, 224) +PM_C = (208, 120, 236) # 미세먼지 수치 — 마젠타(온습도경보로 오독 방지) + +PAD = 16 # 좌우 여백(8px 그리드) + + +def font(size, bold=True): + path = config.FONT_PATH if bold else config.FONT_PATH_LIGHT + try: + return ImageFont.truetype(path, size) + except OSError: + return ImageFont.load_default() + + +# 타이포 위계: huge(위젯 히어로) > hero(상태) > value(수치) > label > eyebrow +F_HUGE = font(66) +F_HERO = font(44) +F_BIG = font(44) # draw_error 호환 별칭 +F_VALUE = font(30) +F_MED = font(30) # 호환 별칭 +F_LABEL = font(16) +F_SM = font(16) # 호환 별칭 +F_XS = font(13, bold=False) +F_EYE = font(12, bold=False) + + +def _dim(color, f=0.30): + """색을 배경쪽으로 눌러 채움용 저채도 버전 생성.""" + return tuple(int(c * f) for c in color) + + +def _eyebrow(d, xy, text, fill=INK3, ls=2): + """트래킹된 대문자 소형 라벨(Apple eyebrow). 그린 뒤 끝 x 반환.""" + x, y = xy + for ch in text.upper(): + d.text((x, y), ch, font=F_EYE, fill=fill) + x += d.textlength(ch, font=F_EYE) + ls + return x + + +def fetch_status(): + # 최소 권한: config_local 에는 파생 STATUS_KEY 만 있다(API_KEY 비보유). + r = requests.get( + config.STATUS_URL, + headers={ + "X-Status-Key": config.STATUS_KEY, + # 커스텀 UA — 공유호스팅 WAF가 기본 python-requests UA를 403 차단하므로 + "User-Agent": "LeakDisplay/2.0", + }, + timeout=config.FETCH_TIMEOUT, + ) + r.raise_for_status() + return r.json() + + +def state_label(state): + return {"ok": "ALL OK", "alert": "ALERT", "pm": "PM ALERT", + "leak": "LEAK!", "offline": "OFFLINE"}.get(state, state.upper()) + + +def sensor_state(s): + """센서 1개의 표시 상태 — 우선순위 누수 > 미세먼지 > 온습도 > offline > ok. + + (기존 버그: offline 을 leak/미세먼지보다 먼저 판정 → 오프라인이 누수를 가림. + 또한 미세먼지 티어 부재. 이 순서로 재정렬해 실제 경보가 오프라인/온습도에 묻히지 않게.) + 누수·미세먼지는 값이 있으면 오프라인이라도 우선 노출한다. + """ + if s.get("leak") == 1: + return "leak", "LEAK!" + pm_status = s.get("pm_status", "normal") or "normal" + if pm_status != "normal": + return "pm", {"high_pm25": "PM2.5", "high_pm10": "PM10"}.get(pm_status, "DUST") + if s.get("pending"): + return "alert", "CHECK.." + # th_status 신규 키 우선, 없으면 metric_status 별칭(구 API 호환) + th_status = s.get("th_status", s.get("metric_status", "normal")) or "normal" + if th_status != "normal": + return "alert", th_status.replace("_", " ").upper() + if s.get("offline"): + return "offline", "OFFLINE" + return "ok", "OK" + + +def new_frame(state): + bg, accent = STATE_COLORS.get(state, STATE_COLORS["offline"]) + img = Image.new("RGB", (W, H), bg) + d = ImageDraw.Draw(img) + d.rectangle([0, 0, W, 4], fill=accent) # 상단 상태 스트립(얇게) + return img, d, accent + + +def _hairline(d, y): + d.line([(PAD, y), (W - PAD, y)], fill=HAIR, width=1) + + +def draw_summary(data, stale_sec): + sys_ = data["system"] + state = "stale" if stale_sec is not None else sys_["state"] + img, d, accent = new_frame(state) + + # ── 헤더: eyebrow → hero 상태 → 시각 ────────────────────────────── + _eyebrow(d, (PAD, 22), "SYSTEM STATUS") + d.text((PAD, 38), state_label(sys_["state"]), font=F_HERO, fill=accent) + if stale_sec is not None: + d.text((PAD, 90), f"STALE {int(stale_sec // 60)}m · no server", + font=F_XS, fill=(255, 150, 170)) + else: + d.text((PAD, 90), data["ts"][5:16].replace("-", "."), font=F_XS, fill=INK2) + + _hairline(d, 116) + + # ── KPI 목록: 라벨(eyebrow) 좌 / 값 우 ─────────────────────────── + rows = [ + ("ONLINE", f"{sys_['online']}/{sys_['total']}"), + ("LEAK OPEN", str(sys_["unrecovered"])), + ("TODAY ALERTS", str(sys_["today_alerts"])), + ("SMS LEFT", str(sys_["sms_balance"]) if sys_["sms_balance"] is not None else "-"), + ] + y = 130 + for label, val in rows: + _eyebrow(d, (PAD, y + 4), label) + d.text((W - PAD, y), val, font=F_LABEL, fill=INK, anchor="ra") + y += 34 + + # ── 푸터: 센서 상태 점 ─────────────────────────────────────────── + _hairline(d, H - 44) + x = PAD + for s in data["sensors"]: + st, _ = sensor_state(s) + _, dot = STATE_COLORS.get(st, STATE_COLORS["offline"]) + cy = H - 24 + d.ellipse([x, cy - 5, x + 10, cy + 5], fill=dot) + d.text((x + 16, cy - 9), f"S{s['id']}", font=F_LABEL, fill=INK) + x += 68 + return img + + +def _sparkline(d, x, y, w, h, values, color): + """면적 채움 + 추세선 + 현재값 도트. 반환: (lo, hi) 또는 None(데이터부족).""" + pts = [(i, v) for i, v in enumerate(values) if v is not None] + if len(pts) < 2: + d.text((x, y + h // 2 - 7), "no data", font=F_XS, fill=INK3) + return None + vals = [v for _, v in pts] + lo, hi = min(vals), max(vals) + span = (hi - lo) or 1.0 + n = len(values) + coords = [ + (x + w * (i / (n - 1) if n > 1 else 0), y + h - h * ((v - lo) / span)) + for i, v in pts + ] + # 저채도 면적 채움(라인 아래) → 라인 → 현재값 도트 + poly = coords + [(coords[-1][0], y + h), (coords[0][0], y + h)] + d.polygon(poly, fill=_dim(color)) + d.line(coords, fill=color, width=2) + cx, cyy = coords[-1] + d.ellipse([cx - 3, cyy - 3, cx + 3, cyy + 3], fill=color, outline=INK) + return lo, hi + + +def _leak_timeline(d, x, y, w, events, accent): + """24h(0~1440분) 축에 누수 이벤트 시각(HH:MM)을 틱+도트로 표시.""" + base = y + 12 + d.line([(x, base), (x + w, base)], fill=HAIR, width=1) + d.text((x, base + 6), "0h", font=F_XS, fill=INK3) + d.text((x + w, base + 6), "24h", font=F_XS, fill=INK3, anchor="ra") + if not events: + d.text((x + w / 2, base - 18), "no events", font=F_XS, fill=INK3, anchor="ma") + return + for t in events: + try: + hh, mm = t.split(":") + frac = (int(hh) * 60 + int(mm)) / 1440.0 + except (ValueError, AttributeError): + continue + px = x + w * frac + d.line([(px, base - 9), (px, base + 9)], fill=accent, width=2) + d.ellipse([px - 3, base - 13, px + 3, base - 7], fill=accent) + + +def _wide_spark(d, x, y, w, h, values, color): + """넓은 히어로 추세: 면적+라인+도트, min/max 를 우측 상·하단 코너에.""" + rng = _sparkline(d, x, y, w, h, values, color) + if rng is not None: + lo, hi = rng + d.text((x + w, y - 14), f"{hi:.0f}", font=F_XS, fill=INK3, anchor="ra") + d.text((x + w, y + h + 2), f"{lo:.0f}", font=F_XS, fill=INK3, anchor="ra") + + +def _leak_sub(s): + """누수 서브상태 텍스트/색 — 결합 노드 ZONE A용(전체 상태와 독립 표기).""" + if s.get("leak") == 1: + return "LEAK!", STATE_COLORS["leak"][1] + return "DRY", STATE_COLORS["ok"][1] + + +def _pm_fmt(v): + """PM 정수 표기 — 값 없으면 em dash.""" + return "—" if v is None else str(int(round(v))) + + +def _zone_leak(d, s, y0): + """ZONE A(y46~120) — 누수: 큰 DRY/LEAK! + 24h 이벤트 수.""" + _eyebrow(d, (PAD, y0), "LEAK STATUS") + txt, col = _leak_sub(s) + d.text((PAD, y0 + 14), txt, font=F_HERO, fill=col) + d.text((W - PAD, y0 + 2), "24H EVENTS", font=F_EYE, fill=INK3, anchor="ra") + d.text((W - PAD, y0 + 18), str(len(s.get("leak_events") or [])), + font=F_VALUE, fill=INK, anchor="ra") + + +def _zone_pm(d, s, y0): + """ZONE B(y128~198) — 미세먼지: PM2.5 큰 값(마젠타) + PM10 보조. 값 없으면 '—'.""" + _eyebrow(d, (PAD, y0), "FINE DUST · PM2.5") + pm25 = _pm_fmt(s.get("pm25")) + d.text((PAD, y0 + 14), pm25, font=F_HERO, fill=PM_C) + w = d.textlength(pm25, font=F_HERO) + d.text((PAD + w + 8, y0 + 40), "µg/m³", font=F_XS, fill=INK3) + d.text((W - PAD, y0 + 2), "PM10", font=F_EYE, fill=INK3, anchor="ra") + d.text((W - PAD, y0 + 18), _pm_fmt(s.get("pm10")), font=F_VALUE, fill=PM_C, anchor="ra") + + +def _zone_th(d, s, y0): + """ZONE C(y208~300) — 온습도: TEMP / HUM 2단(오직 sht30 행 값).""" + temp_txt = f"{s['temp']:.1f}°" if s.get("temp") is not None else "—" + hum_txt = f"{s['hum']:.0f}%" if s.get("hum") is not None else "—" + _eyebrow(d, (PAD, y0), "TEMP °C") + d.text((PAD, y0 + 16), temp_txt, font=F_HERO, fill=TEMP_C) + xr = W // 2 + 8 + _eyebrow(d, (xr, y0), "HUM %") + d.text((xr, y0 + 16), hum_txt, font=F_HERO, fill=HUM_C) + + +def _draw_combined(d, s): + """결합 노드(sensor 1·3): 240x320 3분할 — LEAK / 미세먼지 / 온습도.""" + _zone_leak(d, s, 48) + _hairline(d, 124) + _zone_pm(d, s, 130) + _hairline(d, 202) + _zone_th(d, s, 210) + + +def _draw_metric(d, s): + """온습도 전용 노드(sensor 2): 온도 히어로 + 습도 보조 (기존 레이아웃).""" + hist = s.get("history") or [] + temps = [p.get("temp") for p in hist] + hums = [p.get("hum") for p in hist] + _eyebrow(d, (PAD, 46), "TEMPERATURE °C") + temp_txt = f"{s['temp']:.1f}°" if s.get("temp") is not None else "—" + # 이상치(예: -999.0)로 240px 를 넘으면 폭에 맞는 작은 폰트로 폴백(무단 클립 방지) + hero_font = F_HUGE if d.textlength(temp_txt, font=F_HUGE) <= W - 2 * PAD else F_HERO + d.text((PAD, 56), temp_txt, font=hero_font, fill=TEMP_C) + _wide_spark(d, PAD, 146, W - 2 * PAD, 58, temps, TEMP_C) + _hairline(d, 226) + _eyebrow(d, (PAD, 238), "HUMIDITY %") + hum_txt = f"{s['hum']:.0f}%" if s.get("hum") is not None else "—" + d.text((PAD, 252), hum_txt, font=F_VALUE, fill=HUM_C) + _sparkline(d, W - PAD - 96, 254, 96, 30, hums, HUM_C) + + +def _draw_leak_only(d, s, st_text, accent): + """누수 전용 노드: 누수 히어로 + 24h 타임라인 (기존 레이아웃).""" + _eyebrow(d, (PAD, 46), "LEAK STATUS") + d.text((PAD, 64), st_text, font=F_HUGE, fill=accent) + _hairline(d, 190) + _eyebrow(d, (PAD, 202), "LEAK · 24H") + _leak_timeline(d, PAD, 224, W - 2 * PAD, s.get("leak_events") or [], accent) + + +def draw_sensor(data, idx, stale_sec): + s = data["sensors"][idx] + st, st_text = sensor_state(s) + frame_state = "stale" if stale_sec is not None else st + img, d, accent = new_frame(frame_state) + + leak_node = bool(s.get("leak_node")) + metric_node = bool(s.get("metric_node")) + pm_node = bool(s.get("pm_node")) # 구 API 는 키 부재 → False + + # ── 헤더 2행: (1) SENSOR id 좌 · 상태 우 (2) 능력 칩 ───────── + # 칩+상태를 한 줄에 몰면 결합 노드(칩 3개)에서 우측 상태와 겹친다 → + # 식별/상태는 위 행, 능력 칩은 아래 행으로 분리(충돌 없음). + chips = [] + if leak_node: + chips.append("LEAK") + if metric_node: + chips.append("T/H") + if pm_node: + chips.append("PM") + _eyebrow(d, (PAD, 12), f"SENSOR {s['id']}") + d.text((W - PAD, 10), st_text, font=F_LABEL, fill=accent, anchor="ra") + _eyebrow(d, (PAD, 30), " · ".join(chips), fill=INK3) + + # ── 본문: 능력 조합으로 분기(우발적 순서 아님) ──────────────── + if leak_node and (metric_node or pm_node): + _draw_combined(d, s) # 결합 노드 3분할 + elif metric_node: + _draw_metric(d, s) # 온습도 전용 + elif leak_node: + _draw_leak_only(d, s, st_text, accent) # 누수 전용 + else: + d.text((PAD, 120), st_text, font=F_HUGE, fill=accent) + + # ── 푸터: 갱신 시각 ────────────────────────────────────────── + if s.get("last_seen"): + d.text((PAD, H - 22), f"upd {s['last_seen'][5:16]}", font=F_XS, fill=INK3) + + return img + + +def draw_error(err_text): + img, d, accent = new_frame("stale") + _eyebrow(d, (PAD, 22), "CONNECTION") + d.text((PAD, 38), "NO DATA", font=F_HERO, fill=accent) + _hairline(d, 116) + d.text((PAD, 130), "Server unreachable", font=F_LABEL, fill=INK) + d.text((PAD, 158), str(err_text)[:64], font=F_XS, fill=INK2) + d.text((PAD, H - 30), time.strftime("%m-%d %H:%M"), font=F_XS, fill=INK3) + return img + + +def main(): + print(f"[INFO] display_dashboard start — {getattr(config, 'DEVICE_NAME', 'display')}") + disp, simulated = open_display(config) + if simulated: + print("[INFO] simulation mode — frames saved to /tmp/display_preview.png") + + data = None + last_ok = 0.0 + last_fetch = 0.0 + last_err = "not fetched yet" + page = 0 + last_page_flip = 0.0 + + while True: + now = time.time() + + if now - last_fetch >= config.POLL_INTERVAL or (data is None and now - last_fetch >= 5): + last_fetch = now + try: + data = fetch_status() + last_ok = now + except Exception as e: + last_err = e + print(f"[WARN] fetch failed: {e}") + + stale_sec = None + if data is not None and (now - last_ok) > config.STALE_AFTER: + stale_sec = now - last_ok + + try: + if data is None: + img = draw_error(last_err) + else: + pages = 1 + len(data["sensors"]) + page = min(page, pages - 1) # 센서 수 감소 시 즉시 클램프(IndexError 방지) + if now - last_page_flip >= config.PAGE_INTERVAL: + page = (page + 1) % pages + last_page_flip = now + img = draw_summary(data, stale_sec) if page == 0 else draw_sensor(data, page - 1, stale_sec) + disp.display(img) + except Exception as e: + print(f"[ERROR] render/display failed: {e}") + + time.sleep(1) + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + sys.exit(0) diff --git a/raspberry_pi_zero2w_display/install.sh b/raspberry_pi_zero2w_display/install.sh new file mode 100644 index 0000000..c581f0c --- /dev/null +++ b/raspberry_pi_zero2w_display/install.sh @@ -0,0 +1,114 @@ +#!/usr/bin/env bash +# ============================================================================= +# 미니 상태 표시기 설치 (Pi Zero 2 W + ST7789V) — SPI 활성 + 패키지 + venv +# 대상 OS: Raspberry Pi OS Bookworm (64-bit) +# +# 폐쇄망: debs/ 또는 wheelhouse/ 가 있으면 자동 오프라인 모드(네트워크 0). +# 번들이 불완전하면 온라인 폴백 없이 명확히 중단(폐쇄망 규칙). OFFLINE=1/0 강제 가능. +# ============================================================================= +set -euo pipefail +cd "$(dirname "$0")" + +SERVICE_USER="${SERVICE_USER:-pi}" + +echo "==========================================" +echo " 미니 상태 표시기 (ST7789V) 설치" +echo "==========================================" + +if [ -r /proc/device-tree/model ]; then + MODEL="$(tr -d '\0' < /proc/device-tree/model)" + echo "[INFO] Board: ${MODEL}" + case "${MODEL}" in + *"Zero 2"*) : ;; + *) echo "[WARN] 이 폴더는 Pi Zero 2 W 용입니다 (다른 보드도 진행은 가능)." ;; + esac +fi + +OFFLINE="${OFFLINE:-}" +if [ -z "${OFFLINE}" ]; then + if compgen -G "debs/*.deb" >/dev/null || [ -d wheelhouse ]; then + OFFLINE=1 + echo "[INFO] 오프라인 번들 감지 → 폐쇄망 설치 모드(네트워크 없음)" + else + OFFLINE=0 + echo "[INFO] 오프라인 번들 없음 → 온라인 설치 모드(인터넷 필요)" + fi +fi + +# 1) 시스템 패키지: requests/Pillow/numpy/GPIO/spidev + 폰트 +echo "[1/4] 시스템 패키지 설치..." +if [ "${OFFLINE}" = "1" ]; then + if ! compgen -G "debs/*.deb" >/dev/null; then + echo "[ERROR] 오프라인 모드인데 debs/ 가 비어 있습니다. vendor.sh 산출물을 넣고 재실행." >&2 + exit 1 + fi + sudo apt-get install -y --no-install-recommends --no-download ./debs/*.deb +else + sudo apt-get update + sudo apt-get install -y python3-requests python3-venv python3-pil python3-numpy \ + python3-rpi.gpio python3-spidev fonts-dejavu-core +fi + +# 2) SPI 활성화 (dtparam + 그룹) +echo "[2/4] SPI 활성화..." +BOOT_CFG="" +for c in /boot/firmware/config.txt /boot/config.txt; do + if [ -f "$c" ]; then BOOT_CFG="$c"; break; fi +done +if [ -n "${BOOT_CFG}" ]; then + if ! grep -q "^dtparam=spi=on" "${BOOT_CFG}"; then + echo " dtparam=spi=on 추가 (${BOOT_CFG}) — 재부팅 후 적용" + echo "dtparam=spi=on" | sudo tee -a "${BOOT_CFG}" >/dev/null + NEED_REBOOT=1 + else + echo " dtparam=spi=on 이미 설정됨" + fi +else + echo "[WARN] config.txt 를 찾지 못함 — raspi-config 로 SPI 수동 활성화 필요" +fi +for grp in spi gpio; do + if getent group "$grp" >/dev/null 2>&1; then + sudo usermod -aG "$grp" "${SERVICE_USER}" || echo "[WARN] usermod $grp 실패" + fi +done + +# 3) venv (+시스템 패키지 상속) + requests +echo "[3/4] Python venv..." +if [ ! -d venv ]; then + python3 -m venv --system-site-packages venv +fi +# shellcheck disable=SC1091 +source venv/bin/activate +if [ "${OFFLINE}" = "1" ]; then + if [ ! -d wheelhouse ]; then + echo "[ERROR] 오프라인 모드인데 wheelhouse/ 가 없습니다. vendor.sh 산출물을 넣고 재실행." >&2 + exit 1 + fi + pip install --no-index --find-links=wheelhouse -r requirements.txt +else + pip install -r requirements.txt +fi + +# 4) 로그 파일 + 설정 잠금 +echo "[4/4] 로그·권한..." +sudo touch /var/log/display_dashboard.log +sudo chown "${SERVICE_USER}:${SERVICE_USER}" /var/log/display_dashboard.log || true +sudo chmod 640 /var/log/display_dashboard.log +if [ -f config_local.py ]; then + chmod 600 config_local.py + sudo chown "${SERVICE_USER}:${SERVICE_USER}" config_local.py 2>/dev/null || true +fi +if [ ! -f config_local.py ]; then + echo "" + echo "[!] config_local.py 가 없습니다: cp config_local.example.py config_local.py 후 실값 입력" +fi + +echo "" +echo "==========================================" +echo " 설치 완료 (OFFLINE=${OFFLINE})" +echo "==========================================" +if [ "${NEED_REBOOT:-0}" = "1" ]; then + echo " ⚠️ SPI 방금 활성화 → 'sudo reboot' 후 화면이 동작합니다." +fi +echo " 단독 실행: source venv/bin/activate && python3 display_dashboard.py" +echo " 서비스 등록: README.md systemd 절 참고" diff --git a/raspberry_pi_zero2w_display/render_preview.py b/raspberry_pi_zero2w_display/render_preview.py new file mode 100644 index 0000000..d5759fb --- /dev/null +++ b/raspberry_pi_zero2w_display/render_preview.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python3 +# ============================================================================= +# render_preview.py — 디스플레이 렌더 검증 하네스 (하드웨어 없이 PNG 로 프레임 생성) +# +# iot-verification 규칙: 디스플레이 변경은 코드 리딩만으로 배포 금지 — +# 합성(worst-case) status JSON 을 실제 draw 코드에 먹여 240x320 PNG 로 렌더하고 눈으로 확인. +# +# ST7789 하드웨어는 건드리지 않는다(draw_summary/draw_sensor 는 순수 Pillow 반환). +# 폰트는 리눅스 DejaVu 경로 대신 로컬(윈도우 Arial 등)로 오버라이드 후 모듈을 임포트. +# +# 실행: python render_preview.py +# 출력: ./render_preview/*.png (정확히 패널 해상도 240x320) +# ============================================================================= +import os +import sys +import types + +HERE = os.path.dirname(os.path.abspath(__file__)) +OUT = os.path.join(HERE, "render_preview") +os.makedirs(OUT, exist_ok=True) +sys.path.insert(0, HERE) + +# ── requests 는 이 하네스에서 불필요 — 미설치 환경에서도 임포트되도록 스텁 ── +if "requests" not in sys.modules: + sys.modules["requests"] = types.ModuleType("requests") + + +def _pick_font(candidates): + for p in candidates: + if os.path.exists(p): + return p + return None + + +# ── 폰트 오버라이드: display_dashboard 임포트 전에 config 에 심어야 +# 모듈 로드 시점의 F_HUGE/F_HERO/... 가 실제 TTF 로 초기화된다 ── +import config # noqa: E402 + +_bold = _pick_font([ + "C:/Windows/Fonts/arialbd.ttf", "C:/Windows/Fonts/segoeuib.ttf", + "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", +]) +_reg = _pick_font([ + "C:/Windows/Fonts/arial.ttf", "C:/Windows/Fonts/segoeui.ttf", + "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", +]) +if _bold: + config.FONT_PATH = _bold +if _reg: + config.FONT_PATH_LIGHT = _reg +config.FORCE_SIMULATION = True +print(f"[harness] fonts: bold={config.FONT_PATH}\n reg ={config.FONT_PATH_LIGHT}") + +import display_dashboard as dd # noqa: E402 + + +# ── 합성 센서 팩토리 — 모든 계약 필드 기본값(누락 필드 graceful 테스트도 가능) ── +def sensor(sid, *, leak_node=False, metric_node=False, pm_node=False, + offline=False, leak=0, pending=False, + metric_status="normal", th_status=None, pm_status="normal", + temp=None, hum=None, pm25=None, pm10=None, pm1_0=None, + leak_events=None, history=None, last_seen="2026-07-19 14:32:07", + include_pm_keys=True): + s = { + "id": sid, "name": f"node{sid}", "location": f"zone-{sid}", + "leak_node": leak_node, "metric_node": metric_node, + "offline": offline, "leak": leak, "pending": pending, + "metric_status": metric_status, + "temp": temp, "hum": hum, + "last_seen": last_seen, + "history": history or [], + "leak_events": leak_events or [], + } + if th_status is not None: + s["th_status"] = th_status + else: + s["th_status"] = metric_status + if include_pm_keys: + s.update({"pm_node": pm_node, "pm_status": pm_status, + "pm25": pm25, "pm10": pm10, "pm1_0": pm1_0}) + return s + + +def hist(n=18, t0=6.0, h0=48.0): + out = [] + for i in range(n): + out.append({"t": f"{(i + 6) % 24:02d}:00", + "temp": round(t0 + i * 0.4, 1), + "hum": round(h0 + (i % 5) * 2.0)}) + return out + + +def wrap(sensors, state, *, unrecovered=0, sms=182, today=3): + online = sum(0 if x["offline"] else 1 for x in sensors) + return { + "ts": "2026-07-19 14:32:07", + "system": {"state": state, "online": online, "total": len(sensors), + "unrecovered": unrecovered, "sms_balance": sms, + "today_alerts": today}, + "sensors": sensors, + } + + +def save(img, name): + p = os.path.join(OUT, name) + assert img.size == (config.WIDTH, config.HEIGHT), f"bad size {img.size}" + img.save(p) + print(f" saved {name} {img.size}") + return p + + +# ── 시나리오 정의 ────────────────────────────────────────────────────────── +# 결합 노드(1·3) = 누수 + 온습도 + 미세먼지 한 sensor_id 아래 +COMBINED_LEAK = sensor(1, leak_node=True, metric_node=True, pm_node=True, + leak=1, temp=22.4, hum=61, pm25=14, pm10=22, + leak_events=["03:12", "03:15", "07:48"], history=hist()) +COMBINED_PM = sensor(3, leak_node=True, metric_node=True, pm_node=True, + leak=0, pm_status="high_pm25", pm25=88, pm10=57, + temp=25.7, hum=54, leak_events=["01:20"], history=hist()) +COMBINED_OK = sensor(1, leak_node=True, metric_node=True, pm_node=True, + leak=0, pm25=11, pm10=19, temp=23.1, hum=49, + leak_events=[], history=hist()) +COMBINED_OFFLINE_LEAK = sensor(3, leak_node=True, metric_node=True, pm_node=True, + offline=True, leak=1, pm25=None, pm10=None, + temp=None, hum=None, leak_events=["22:05"]) +COMBINED_PM10 = sensor(1, leak_node=True, metric_node=True, pm_node=True, + leak=0, pm_status="high_pm10", pm25=41, pm10=173, + temp=24.0, hum=58, history=hist()) +# 온습도 전용 노드(2) +METRIC_OK = sensor(2, metric_node=True, temp=24.8, hum=52, history=hist()) +# 오프라인(누수·미세먼지 없음 → OFFLINE 로 표기) +OFFLINE_NODE = sensor(2, metric_node=True, offline=True, temp=None, hum=None, + last_seen="2026-07-19 11:02:41") +# 구 API(=미세먼지 키 자체 없음) — pm_node 부재 → graceful, zone B '—' +LEGACY_COMBINED = sensor(1, leak_node=True, metric_node=True, leak=0, + temp=23.3, hum=50, history=hist(), include_pm_keys=False) + +print("[harness] rendering frames ->", OUT) +paths = [] + +# 시스템 요약 — 누수 승격(푸터 점: leak/ok/pm/offline 색 자동) +summary_data = wrap([COMBINED_LEAK, METRIC_OK, COMBINED_PM, OFFLINE_NODE], + "leak", unrecovered=1, today=5) +paths.append(save(dd.draw_summary(summary_data, None), "01_summary_leak.png")) + +# 시스템 요약 — 미세먼지 티어가 시스템 상태로 승격된 경우 +summary_pm = wrap([COMBINED_OK, METRIC_OK, COMBINED_PM], "pm", today=4) +paths.append(save(dd.draw_summary(summary_pm, None), "02_summary_pm.png")) + +# 결합 노드 상세 +paths.append(save(dd.draw_sensor(wrap([COMBINED_LEAK], "leak"), 0, None), + "03_combined_leak.png")) +paths.append(save(dd.draw_sensor(wrap([COMBINED_PM], "pm"), 0, None), + "04_combined_pm25.png")) +paths.append(save(dd.draw_sensor(wrap([COMBINED_PM10], "pm"), 0, None), + "05_combined_pm10.png")) +paths.append(save(dd.draw_sensor(wrap([COMBINED_OK], "ok"), 0, None), + "06_combined_normal.png")) +paths.append(save(dd.draw_sensor(wrap([COMBINED_OFFLINE_LEAK], "leak"), 0, None), + "07_combined_offline_leak.png")) +paths.append(save(dd.draw_sensor(wrap([LEGACY_COMBINED], "ok"), 0, None), + "08_combined_legacy_no_pm.png")) + +# 온습도 전용 노드(2) +paths.append(save(dd.draw_sensor(wrap([METRIC_OK], "ok"), 0, None), + "09_metric_normal.png")) + +# 오프라인 노드 +paths.append(save(dd.draw_sensor(wrap([OFFLINE_NODE], "offline"), 0, None), + "10_offline.png")) + +# STALE(서버 미응답) 오버레이 — 요약 페이지 +paths.append(save(dd.draw_summary(summary_data, 372), "11_summary_stale.png")) + +# ── 정밀 검증: 상태/색 precedence 를 코드가 아니라 결과로 단언 ────────────── +def _assert_state(s, expect_st, expect_txt): + st, txt = dd.sensor_state(s) + ok = (st == expect_st and txt == expect_txt) + print(f" [{'OK ' if ok else 'ERR'}] sensor_state -> ({st!r},{txt!r}) " + f"expect ({expect_st!r},{expect_txt!r})") + return ok + + +print("[harness] precedence assertions:") +allok = True +allok &= _assert_state(COMBINED_OFFLINE_LEAK, "leak", "LEAK!") # 누수 > offline +allok &= _assert_state(COMBINED_PM, "pm", "PM2.5") # 미세먼지 > 온습도 +allok &= _assert_state(COMBINED_PM10, "pm", "PM10") +allok &= _assert_state( + sensor(9, leak_node=True, metric_node=True, pm_node=True, leak=1, + pm_status="high_pm25"), "leak", "LEAK!") # 누수 > 미세먼지 +allok &= _assert_state( + sensor(9, metric_node=True, offline=True, th_status="condensation_risk"), + "alert", "CONDENSATION RISK") # 온습도 > offline +allok &= _assert_state(sensor(9, metric_node=True, offline=True), + "offline", "OFFLINE") +allok &= _assert_state(METRIC_OK, "ok", "OK") +# 구 API(th_status 없음, metric_status 별칭 사용) +allok &= _assert_state( + {"id": 9, "leak": 0, "metric_status": "high_humidity", + "leak_node": True, "metric_node": True, "offline": False, "pending": False}, + "alert", "HIGH HUMIDITY") + +print("\n[harness] done.", len(paths), "PNGs") +print("[harness] precedence:", "ALL PASS" if allok else "FAILURES ABOVE") +for p in paths: + print(" ", p) +if not allok: + sys.exit(1) diff --git a/raspberry_pi_zero2w_display/render_preview/01_summary_leak.png b/raspberry_pi_zero2w_display/render_preview/01_summary_leak.png new file mode 100644 index 0000000000000000000000000000000000000000..569c73f828d7a775321e038b3befb39f7662c097 GIT binary patch literal 9718 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%0AkQ7OH&BWaveFHKU;k7i*Z%Fmy1 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 X_^ak=m7u=?#P}euCRZV2@$LTsP{=*c literal 0 HcmV?d00001 diff --git a/raspberry_pi_zero2w_display/render_preview/03_combined_leak.png b/raspberry_pi_zero2w_display/render_preview/03_combined_leak.png new file mode 100644 index 0000000000000000000000000000000000000000..430325ee4a72a054c4111a3169ad657542244856 GIT binary patch literal 15782 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 JmBNMr{}*0%z2^V` literal 0 HcmV?d00001 diff --git a/raspberry_pi_zero2w_display/render_preview/06_combined_normal.png b/raspberry_pi_zero2w_display/render_preview/06_combined_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..ae2d11125bcc4ee1e42561edd9f5b3c3c3f4c7ab GIT binary patch literal 16283 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 literal 0 HcmV?d00001 diff --git a/raspberry_pi_zero2w_display/render_preview/07_combined_offline_leak.png b/raspberry_pi_zero2w_display/render_preview/07_combined_offline_leak.png new file mode 100644 index 0000000000000000000000000000000000000000..281e046614b48bb1b841a393962dbe4687dd0c35 GIT binary patch literal 10793 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%0A>S{FAm3^QVDEfW|1gq-=&3ZwOKz_D>gG;HD5gv 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 Mts+$}VI25B0JM&_CjbBd literal 0 HcmV?d00001 diff --git a/raspberry_pi_zero2w_display/render_preview/08_combined_legacy_no_pm.png b/raspberry_pi_zero2w_display/render_preview/08_combined_legacy_no_pm.png new file mode 100644 index 0000000000000000000000000000000000000000..0508f25660ba9c0df6f8d30165320a9b75122355 GIT binary patch literal 15269 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 Y$)N8PZl3c{#XF3=w2D-<#Mhwz1N1ys$^ZZW literal 0 HcmV?d00001 diff --git a/raspberry_pi_zero2w_display/render_preview/10_offline.png b/raspberry_pi_zero2w_display/render_preview/10_offline.png new file mode 100644 index 0000000000000000000000000000000000000000..2aaf591c36035293e8dfc9ac683e73389a4498d5 GIT binary patch literal 6880 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 adpPr`;tH-y*Z(@hqR`hd(S~Y0diF2BgEn0N literal 0 HcmV?d00001 diff --git a/raspberry_pi_zero2w_display/render_preview/11_summary_stale.png b/raspberry_pi_zero2w_display/render_preview/11_summary_stale.png new file mode 100644 index 0000000000000000000000000000000000000000..6d8d3b397001c5fbe88fe738a094ee5ddffcb803 GIT binary patch literal 10215 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 jed7E7%h$3)McxrKYjT>vKQlg literal 0 HcmV?d00001 diff --git a/raspberry_pi_zero2w_display/requirements.txt b/raspberry_pi_zero2w_display/requirements.txt new file mode 100644 index 0000000..e3dcea3 --- /dev/null +++ b/raspberry_pi_zero2w_display/requirements.txt @@ -0,0 +1,4 @@ +# 미니 표시기 파이썬 의존성 — 무거운 패키지(Pillow/numpy/RPi.GPIO/spidev)는 +# apt(debs/)로 설치하고 venv 는 --system-site-packages 로 물려받는다(sht30 과 동일 전략). +# pip 로는 순수 파이썬 requests 계열만(이미 apt python3-requests 가 있으면 no-op). +requests>=2.28 diff --git a/raspberry_pi_zero2w_display/st7789_driver.py b/raspberry_pi_zero2w_display/st7789_driver.py new file mode 100644 index 0000000..a013958 --- /dev/null +++ b/raspberry_pi_zero2w_display/st7789_driver.py @@ -0,0 +1,159 @@ +# ============================================================================= +# st7789_driver.py — ST7789V(240x320) SPI 드라이버 (GMT020-02 등) +# 외부 디스플레이 라이브러리 의존 없음(폐쇄망 최소 의존): +# spidev + RPi.GPIO + numpy(RGB565 변환) + Pillow(Image 입력)만 사용. +# 하드웨어/모듈 부재 시 SimulationDisplay 로 폴백(PNG 저장) — sht30 드라이버와 동일 철학. +# ============================================================================= +import time + +try: + import numpy as np +except ImportError: # numpy 없으면 순수 파이썬 변환(느리지만 동작) + np = None + + +class SimulationDisplay: + """SPI/GPIO 불가 환경 폴백 — 프레임을 PNG 로 저장해 렌더 결과를 검증한다.""" + + def __init__(self, width=240, height=320, preview_path="/tmp/display_preview.png"): + self.width, self.height = width, height + self.preview_path = preview_path + + def display(self, image): + image.save(self.preview_path) + + def set_backlight(self, on): + pass + + def close(self): + pass + + +class ST7789: + """ST7789V 240x320 — 초기화·전체 프레임 블릿. 부분 갱신은 쓰지 않는다(30초 주기).""" + + def __init__(self, spi_bus=0, spi_device=0, speed_hz=40_000_000, + dc=25, rst=24, bl=None, width=240, height=320, + rotation=0, invert=True): + import spidev + import RPi.GPIO as GPIO + self.GPIO = GPIO + self.width, self.height = width, height + self.rotation = rotation + self.dc, self.rst, self.bl = dc, rst, bl + + GPIO.setwarnings(False) + GPIO.setmode(GPIO.BCM) + GPIO.setup(dc, GPIO.OUT) + GPIO.setup(rst, GPIO.OUT) + if bl is not None: # 7핀 모듈(BLK 없음)은 백라이트 제어 생략 + GPIO.setup(bl, GPIO.OUT) + + self.spi = spidev.SpiDev() + self.spi.open(spi_bus, spi_device) + self.spi.max_speed_hz = speed_hz + self.spi.mode = 0 + + self._reset() + self._init_panel(invert) + self.set_backlight(True) + + # ── 저수준 ────────────────────────────────────────────── + def _cmd(self, cmd, data=None): + self.GPIO.output(self.dc, 0) + self.spi.writebytes([cmd]) + if data: + self.GPIO.output(self.dc, 1) + self.spi.writebytes(list(data)) + + def _reset(self): + self.GPIO.output(self.rst, 1); time.sleep(0.05) + self.GPIO.output(self.rst, 0); time.sleep(0.05) + self.GPIO.output(self.rst, 1); time.sleep(0.15) + + def _init_panel(self, invert): + self._cmd(0x01); time.sleep(0.15) # SWRESET + self._cmd(0x11); time.sleep(0.12) # SLPOUT + self._cmd(0x3A, [0x55]) # COLMOD: 16bit RGB565 + self._cmd(0x36, [self._madctl()]) # MADCTL: 회전 + self._cmd(0xB2, [0x0C, 0x0C, 0x00, 0x33, 0x33]) # PORCTRL + self._cmd(0xB7, [0x35]) # GCTRL + self._cmd(0xBB, [0x19]) # VCOMS + self._cmd(0xC0, [0x2C]) # LCMCTRL + self._cmd(0xC2, [0x01]) # VDVVRHEN + self._cmd(0xC3, [0x12]) # VRHS + self._cmd(0xC4, [0x20]) # VDVS + self._cmd(0xC6, [0x0F]) # FRCTRL2 60Hz + self._cmd(0xD0, [0xA4, 0xA1]) # PWCTRL1 + self._cmd(0xE0, [0xD0, 0x04, 0x0D, 0x11, 0x13, 0x2B, # PVGAMCTRL + 0x3F, 0x54, 0x4C, 0x18, 0x0D, 0x0B, 0x1F, 0x23]) + self._cmd(0xE1, [0xD0, 0x04, 0x0C, 0x11, 0x13, 0x2C, # NVGAMCTRL + 0x3F, 0x44, 0x51, 0x2F, 0x1F, 0x1F, 0x20, 0x23]) + self._cmd(0x21 if invert else 0x20) # INVON/INVOFF + self._cmd(0x13) # NORON + self._cmd(0x29); time.sleep(0.05) # DISPON + + def _madctl(self): + return {0: 0x00, 90: 0x60, 180: 0xC0, 270: 0xA0}.get(self.rotation, 0x00) + + def _set_window(self): + w, h = (self.width, self.height) if self.rotation in (0, 180) else (self.height, self.width) + self._cmd(0x2A, [0, 0, (w - 1) >> 8, (w - 1) & 0xFF]) # CASET + self._cmd(0x2B, [0, 0, (h - 1) >> 8, (h - 1) & 0xFF]) # RASET + self._cmd(0x2C) # RAMWR + + # ── 공개 API ──────────────────────────────────────────── + def display(self, image): + """PIL RGB 이미지를 전체 프레임으로 전송.""" + w, h = (self.width, self.height) if self.rotation in (0, 180) else (self.height, self.width) + if image.size != (w, h): + image = image.resize((w, h)) + if np is not None: + arr = np.asarray(image.convert("RGB"), dtype=np.uint16) + rgb565 = ((arr[..., 0] & 0xF8) << 8) | ((arr[..., 1] & 0xFC) << 3) | (arr[..., 2] >> 3) + buf = rgb565.byteswap().tobytes() # 빅엔디안 + else: + px = image.convert("RGB").load() + buf = bytearray(w * h * 2) + i = 0 + for y in range(h): + for x in range(w): + r, g, b = px[x, y] + v = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3) + buf[i] = v >> 8; buf[i + 1] = v & 0xFF + i += 2 + self._set_window() + self.GPIO.output(self.dc, 1) + if hasattr(self.spi, "writebytes2"): # 버퍼 직접 전송(자동 분할) + self.spi.writebytes2(buf) + else: # 구버전 spidev 폴백: list 로 분할 전송 + for ofs in range(0, len(buf), 4096): + self.spi.writebytes(list(buf[ofs:ofs + 4096])) + + def set_backlight(self, on): + if self.bl is not None: + self.GPIO.output(self.bl, 1 if on else 0) + + def close(self): + try: + self.set_backlight(False) + self.spi.close() + except Exception: + pass + + +def open_display(cfg): + """설정 기반 디스플레이 오픈 — 하드웨어 불가 시 시뮬레이션 폴백.""" + if getattr(cfg, "FORCE_SIMULATION", False): + return SimulationDisplay(cfg.WIDTH, cfg.HEIGHT), True + try: + disp = ST7789( + spi_bus=cfg.SPI_BUS, spi_device=cfg.SPI_DEVICE, speed_hz=cfg.SPI_SPEED_HZ, + dc=cfg.PIN_DC, rst=cfg.PIN_RST, bl=cfg.PIN_BL, + width=cfg.WIDTH, height=cfg.HEIGHT, + rotation=cfg.ROTATION, invert=cfg.INVERT, + ) + return disp, False + except Exception as e: + print(f"[WARN] ST7789 init failed ({e}) — simulation fallback") + return SimulationDisplay(cfg.WIDTH, cfg.HEIGHT), True diff --git a/raspberry_pi_zero2w_display/systemd/display-dashboard.service b/raspberry_pi_zero2w_display/systemd/display-dashboard.service new file mode 100644 index 0000000..492f5aa --- /dev/null +++ b/raspberry_pi_zero2w_display/systemd/display-dashboard.service @@ -0,0 +1,51 @@ +# ============================================================================= +# /etc/systemd/system/display-dashboard.service +# 미니 상태 표시기 (Pi Zero 2 W + ST7789V) 부팅 자동 실행 +# +# 설치: +# sudo cp systemd/display-dashboard.service /etc/systemd/system/ +# sudo systemctl daemon-reload && sudo systemctl enable --now display-dashboard +# 경로가 /home/pi/display 가 아니면 WorkingDirectory/ExecStart 수정. +# ============================================================================= + +[Unit] +Description=Mini Status Display (Pi Zero 2 W, ST7789V) +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=pi +Group=pi +# /dev/spidev0.0 + GPIO 문자장치 접근 +SupplementaryGroups=spi gpio +WorkingDirectory=/home/pi/display +ExecStart=/home/pi/display/venv/bin/python display_dashboard.py +Restart=always +RestartSec=10 +StandardOutput=journal +StandardError=journal +SyslogIdentifier=display-dashboard +Environment=PYTHONUNBUFFERED=1 +PrivateTmp=true + +# ── 샌드박스 (sht30 유닛과 동일 정책) ────────────────────────────────────── +NoNewPrivileges=true +ProtectSystem=strict +ReadWritePaths=/var/log +ProtectHome=read-only +ProtectKernelModules=true +ProtectKernelTunables=true +ProtectControlGroups=true +RestrictSUIDSGID=true +LockPersonality=true +RestrictRealtime=true +# HTTPS 폴링 + 로컬 소켓(DNS/journal). AF_NETLINK 은 getaddrinfo 용. +RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK +# ⚠️ PrivateDevices 금지 — /dev/spidev0.0, /dev/gpiomem 이 가려져 화면 불가. + +StartLimitBurst=5 +StartLimitInterval=600s + +[Install] +WantedBy=multi-user.target diff --git a/raspberry_pi_zero2w_display/test_connection.py b/raspberry_pi_zero2w_display/test_connection.py new file mode 100644 index 0000000..cbd93a8 --- /dev/null +++ b/raspberry_pi_zero2w_display/test_connection.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# ============================================================================= +# test_connection.py — 표시기 → 서버 status_summary 연결 검증 (하드닝 전 필수 통과) +# 성공: 시스템 상태/센서 수 출력 후 exit 0. 실패: 원인 출력 후 exit 1. +# ============================================================================= +import sys + +import requests + +import config + + +def main() -> int: + print(f"[TEST] GET {config.STATUS_URL}") + try: + r = requests.get(config.STATUS_URL, + headers={"X-Status-Key": config.STATUS_KEY, + "User-Agent": "LeakDisplay/2.0"}, + timeout=config.FETCH_TIMEOUT) + except Exception as e: + print(f"[FAIL] 네트워크 오류: {e}") + return 1 + if r.status_code != 200: + print(f"[FAIL] HTTP {r.status_code}: {r.text[:200]}") + if r.status_code == 403: + print(" → STATUS_KEY 불일치: php -r 'echo hash_hmac(\"sha256\",\"status\",\"<서버 API_KEY>\");' 로 재계산.") + return 1 + data = r.json() + sys_ = data.get("system", {}) + print(f"[OK] state={sys_.get('state')} online={sys_.get('online')}/{sys_.get('total')} " + f"sensors={len(data.get('sensors', []))} ts={data.get('ts')}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/raspberry_pi_zero2w_display/vendor.sh b/raspberry_pi_zero2w_display/vendor.sh new file mode 100644 index 0000000..663f4b7 --- /dev/null +++ b/raspberry_pi_zero2w_display/vendor.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# ============================================================================= +# vendor.sh — 폐쇄망 설치용 사전 다운로드 (미니 표시기, Pi Zero 2 W / aarch64) +# 인터넷 되는 빌드 머신에서 실행 → wheelhouse/(pip), debs/(apt) 산출 → USB 로 이송. +# 무거운 바이너리(Pillow/numpy/RPi.GPIO/spidev)는 .deb 로 해결하므로 +# wheel 은 순수 파이썬(requests 계열)만 필요 — 플랫폼 핀 부담이 없다. +# .deb 는 대상과 동일 OS/아키텍처(Bookworm aarch64)에서 받는 것이 가장 안전. +# ============================================================================= +set -euo pipefail +cd "$(dirname "$0")" + +echo "[vendor] (1/2) Python wheel → wheelhouse/" +mkdir -p wheelhouse +python3 -m pip download -r requirements.txt -d wheelhouse \ + || echo "[WARN] 일부 다운로드 실패(순수 파이썬 패키지만 필요 — 아래 개수 확인)" +WHEEL_COUNT="$(ls -A wheelhouse 2>/dev/null | wc -l)" +echo " wheelhouse 파일 수: ${WHEEL_COUNT}" +[ "${WHEEL_COUNT}" -gt 0 ] || { echo "[ERROR] wheelhouse 비어 있음"; exit 1; } + +echo "[vendor] (2/2) apt .deb → debs/" +mkdir -p debs +# nftables/unattended-upgrades 포함 → harden_pi.sh 도 오프라인 실행 가능. +BASE_PKGS="python3-requests python3-venv python3-pil python3-numpy python3-rpi.gpio python3-spidev fonts-dejavu-core nftables unattended-upgrades" +DEPS="$(apt-cache depends --recurse --no-recommends --no-suggests \ + --no-conflicts --no-breaks --no-replaces --no-enhances ${BASE_PKGS} \ + | awk '/^\w/{print $1}' | sort -u)" +( cd debs && apt-get download ${BASE_PKGS} ${DEPS} ) 2>/dev/null \ + || echo "[WARN] 일부 .deb 다운로드 실패(가상/전이 의존일 수 있음 — 필수 패키지는 아래에서 검증)" + +MISS=0 +for p in ${BASE_PKGS}; do + if ! ls debs/"${p}"_*.deb >/dev/null 2>&1; then + echo "[ERROR] 필수 패키지 .deb 누락: ${p}" + MISS=1 + fi +done +[ "${MISS}" = "0" ] || exit 1 + +echo "" +echo "[vendor] 완료 — wheelhouse/ + debs/ 를 이 폴더째 USB 로 옮기면 install.sh 가 자동 오프라인 설치."