POSA_LEAKSMS/php/config.local.example.php
cw2007 0b1e86c84a feat(sht30): 누수 노드에 온습도 동일-id 통합 (소스·서버예시·테스트·문서)
누수 노드(Pi-A=sensor_id 1, Pi-C=sensor_id 3)에 SHT30 온습도를 "같은
sensor_id"로 보고하는 구성을 반영. 노드는 기존 sht30_sensor.py를 별도
systemd 서비스로 얹고(불안정한 누수 코드 무변경), config_local로 SENSOR_ID만 지정.

- raspberry_pi4_sht30/config.py: config_local로 SENSOR_ID/SENSOR_NAME 오버라이드
  지원(미지정 시 기본 2 유지 — Pi-B 하위호환)
- php/config.local.example.php: METRIC_SENSOR_IDS=[1,2,3] 예시 +
  SENSOR_HEARTBEAT_TIMEOUT_SEC[1,3]=1800(1·3이 온습도 목록에 들어가도 누수
  오프라인 감지 속도 유지)
- tests/heartbeat_timeout_test.php: 동일-id 통합 시 1·3 누수 타임아웃 유지 검증
- docs/superpowers/{specs,plans}: 설계 문서 + 구현 계획

설치 패키지(deploy/* — gitignored)는 온디스크 산출물로 별도 반영(sht30 서브폴더,
install.sh 체이닝, WIRING/SETUP/README, 서버 SETUP 절차).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nd7QvbgEWCjSQtUYnGNvvV
2026-07-15 10:16:49 +09:00

106 lines
6.3 KiB
PHP

<?php
// =============================================================================
// config.local.example.php - v2606 (SHT30 온습도) 운영 설정 예시
//
// 1. 이 파일을 config.local.php로 복사합니다.
// 2. 실제 운영 값으로 교체합니다.
// 3. config.local.php는 서버에만 보관하고 공유하지 않습니다.
// =============================================================================
return [
'DB_HOST' => 'localhost',
'DB_PORT' => 3306,
'DB_NAME' => 'your_db_name',
'DB_USER' => 'your_db_user',
'DB_PASS' => 'your_db_password',
'API_KEY' => 'replace-with-long-random-secret',
// 요청 서명은 HMAC-SHA256(키=API_KEY, 메시지=요청본문 바이트)이며 X-Signature 헤더로
// 전송된다. 레거시 키-접두 sha256 폴백은 기본 비활성이고, 운영(STM32 HMAC 전용)에서는
// 반드시 false 로 둔다. 과거 RPi(레거시) 클라이언트가 아직 남아 있을 때만 true 로 켠다.
'ALLOW_LEGACY_BODY_SIGNATURE' => false,
'SMS_USER_ID' => 'your-cafe24-sms-user-id',
'SMS_SECURE' => 'your-cafe24-sms-secure-key',
'SMS_SENDER' => '01000000000',
'SMS_RECIPIENTS' => [
'01000000000',
],
// 센서별 수신자 그룹 — 지정한 센서의 경보 SMS 는 그 그룹으로만 발송된다. 지정 없는
// 센서는 위 전역 SMS_RECIPIENTS 로 폴백한다(헬스/잔액 등 시스템 통지도 전역 사용).
// 예: 누수(1번)는 시설팀, 3번은 고객센터로. 비우면(기본) 전역만 사용.
'SENSOR_RECIPIENTS' => [
// 1 => ['010-1111-1111', '010-2222-2222'],
// 3 => ['010-3333-3333'],
],
'ADMIN_USER' => 'admin',
'ADMIN_PASSWORD_HASH' => '$2y$10$replace.with.password_hash.output',
// Base32 TOTP secret. MUST be left EMPTY here and set to a UNIQUE generated value in
// config.local.php. Empty '' => admin_mfa_configured() is false => login is DISABLED
// (fail-closed) until a real secret is set. NEVER put a literal Base32 string in this
// example file: any non-empty Base32-ish value (even "REPLACE_WITH_...") decodes to a
// usable, publicly-known TOTP secret and silently enables MFA on a known seed.
// Generate a unique secret on the server only:
// php -r "require 'php/admin_security.php'; echo admin_totp_secret().PHP_EOL;"
'ADMIN_TOTP_SECRET' => '',
// Temporary bootstrap token for setup_mfa.php. Remove or empty after MFA enrollment.
'MFA_SETUP_TOKEN' => 'replace-with-temporary-random-token',
// 누수 모듈 sensor_id 목록 — 대시보드 누수 상태 카드 표시 대상 (기본 [1]).
// 신규 누수 지점(예: Pi-C, sensor_id 3) 투입 시: [1, 3]
'LEAK_SENSOR_IDS' => [1],
// 온습도(SHT30) sensor_id 목록 — 대시보드 온습도 카드 표시 대상 (기본 [2]).
// 누수 노드(1·3)에 SHT30 을 얹어 "같은 sensor_id" 로 온습도를 보고하는 구성에서는
// 1·3 도 포함한다: [1, 2, 3]. (같은 지점에 누수 카드 + 온습도 카드가 함께 표시됨)
'METRIC_SENSOR_IDS' => [1, 2, 3],
// 누수 감지/복구 디바운스(감지↔복구 플래핑 SMS 폭탄 방지). 상태가 확인창 동안 지속돼야
// 확정하고 확정 엣지에서만 SMS 1회. 아래는 기본값(필요 시 조정). sql/migration_leak_debounce.sql
// 적용 필요(컬럼 없으면 레거시 즉시 발송으로 자동 폴백).
// 'LEAK_DEBOUNCE_ENABLED' => true,
// 'LEAK_ALERT_CONFIRM_SEC' => 60, // 감지 확인창(초)
// 'LEAK_RECOVERY_CONFIRM_SEC' => 180, // 복구 확인창(초)
// 센서별 오프라인 판정 타임아웃(무수신 초). 온습도(SHT30)는 1시간 주기라 전역 20분으론
// 매시간 오탐 → 온습도 센서는 METRIC_HEARTBEAT_TIMEOUT_SEC(기본 7500s≈125분) 자동 적용.
// 특정 센서만 다르게 하려면 SENSOR_HEARTBEAT_TIMEOUT_SEC 로 명시 오버라이드.
// 'METRIC_HEARTBEAT_TIMEOUT_SEC' => 7500,
// ★ 동일-id 온습도 통합: 1·3 은 위 METRIC_SENSOR_IDS 에도 들어가지만 누수 노드이므로
// metric 기본(7500s)으로 느슨해지면 안 됨 → 누수 타임아웃(30분) 유지하도록 명시 오버라이드.
'SENSOR_HEARTBEAT_TIMEOUT_SEC' => [1 => 1800, 3 => 1800],
// 온습도 임계 경보 (서버 판정 → SMS). 운영 환경에 맞게 조정.
'METRIC_TEMP_HIGH_C' => 27, // 고온 임계(℃)
'METRIC_TEMP_LOW_C' => 10, // 저온 임계(℃)
'METRIC_RH_HIGH' => 60, // 고습 임계(%)
'METRIC_RH_LOW' => -1, // 저습 경보 비활성(RH 는 항상 ≥0 → 절대 발화 안 함)
'METRIC_DEWPOINT_MARGIN_C' => 0, // 결로(이슬점) 경보 비활성(0 이면 판정 분기 스킵)
'METRIC_ALERT_COOLDOWN_SEC' => 1800, // 동일 종류 경보 재발송 억제(초, 기본 30분)
// 예보·대응(대시보드 예방 신호 + 조치 가이드). 전부 기본값으로 동작 — 필요 시만 override.
// FORECAST_ENABLED(true), FORECAST_WARN_MARGIN_TEMP_C(2.0), FORECAST_WARN_MARGIN_RH(8.0),
// FORECAST_HORIZON_MIN(180), FORECAST_RATE_TEMP_C_PER_10MIN(3.0) 등. config.php 참고.
// 대응 담당자(대시보드 '대응 필요' 섹션에 표시). 비우면 담당자 블록 생략.
'RESPONSE_CONTACTS' => [
// ['role' => '시설담당', 'name' => '홍길동', 'phone' => '010-0000-0000'],
// ['role' => '야간당직', 'name' => '김철수', 'phone' => '010-0000-0000'],
],
// 상태별 대응 체크리스트는 config.php 의 기본 플레이북을 사용. 현장 절차로 바꾸려면
// 'RESPONSE_PLAYBOOKS' => ['high_temp' => ['title'=>'고온 대응','steps'=>['...']], ...] 로 통째 override.
// 미복귀 경보 2차(야간) 에스컬레이션 수신자. 비우면 비활성(opt-in).
'SMS_RECIPIENTS_TIER2' => [],
'ESCALATE_AFTER_SEC' => 1800, // 경보 미복귀 30분 후 2차 통지
// 아래는 기본값으로 동작(필요 시에만 override):
// SMS_BALANCE_WARN_THRESHOLD(30건), HEALTH_SMS_HOUR(9시),
// STUCK_DETECT_SAMPLES(3 = 온습도 1시간 주기 기준 ≈3시간), SMS_RETRY_OFFLINE(true)
'SMS_LOG_RETENTION_DAYS' => 365,
'SENSOR_LOG_RETENTION_DAYS' => 365,
'SENSOR_METRIC_RETENTION_DAYS' => 365,
'ADMIN_AUDIT_RETENTION_DAYS' => 365,
];