POSA_LEAKSMS/php/config.local.example.php
cw2007 031a0c0fdf feat: 대시보드 예보·대응 정보 (예방 신호 + 조치 가이드)
기존 측정 데이터만으로 "경보가 터지기 전"을 보여주고, 위험 시 무엇을 할지
안내한다. 새 센서·ML·DB 스키마 변경 없음(폐쇄망 정합).

신규 php/forecast.php — 순수 계산 함수(DB·출력 없음, 단위테스트 용이):
- dew_point_c(Magnus 이슬점), linear_trend(최소자승 회귀), threshold_eta_min
  (임계 도달 예상 분), headroom_state(여유 3단계), forecast_metric/freshness,
  risk_items(대응 섹션용 정규화 위험 목록).
tests/forecast_test.php — 31 검사(이슬점 알려진값·회귀·ETA·여유·신선도·위험 엣지).

config.php — FORECAST_*(지평/최소점/근접여유/급변 기준) + RESPONSE_PLAYBOOKS
(상태별 대응 체크리스트) + RESPONSE_CONTACTS. 전부 config.local.php 오버라이드.

dashboard.php — 센서별 최근점으로 예보 계산 →
- 카드 예보줄(상시): 임계 여유·추세 ETA·이슬점 결로·변화율(근접/초과만 강조).
- 대응 필요 섹션(위험 시만): 조건·ETA + 상태별 권장 조치 체크리스트 + 담당자.
기존 offline 판정을 단일 진실원으로 사용, 누수 노드 중복 없음.

app.css — .forecast-chip(near/over 상태 3중 인코딩)·.response-panel·.playbook·
.contact (토큰 기반, 라이트/다크 자동). run_tests.sh 에 forecast_test 등록.

검증: forecast_test 31/0, php -l clean(7페이지+forecast), 헤드리스 렌더 확인.
2026-07-05 14:02:48 +09:00

78 lines
4.2 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',
],
'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],
// 온습도 임계 경보 (서버 판정 → 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(6), SMS_RETRY_OFFLINE(true)
'SMS_LOG_RETENTION_DAYS' => 365,
'SENSOR_LOG_RETENTION_DAYS' => 365,
'SENSOR_METRIC_RETENTION_DAYS' => 365,
'ADMIN_AUDIT_RETENTION_DAYS' => 365,
];