누수 노드(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
61 lines
2.7 KiB
PHP
61 lines
2.7 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
// 센서별 히트비트(오프라인 판정) 타임아웃 해소 순수 로직 테스트 (DB/네트워크 없음).
|
|
// resolve_heartbeat_timeout(): 명시 오버라이드 > 온습도(METRIC) 기본 > 전역 기본.
|
|
|
|
$root = dirname(__DIR__);
|
|
require_once $root . '/php/config.php'; // resolve_heartbeat_timeout() 포함
|
|
|
|
$failures = [];
|
|
function check(bool $cond, string $msg): void {
|
|
global $failures;
|
|
if (!$cond) { $failures[] = $msg; }
|
|
}
|
|
|
|
check(function_exists('resolve_heartbeat_timeout'), 'resolve_heartbeat_timeout() should exist.');
|
|
|
|
$overrides = [3 => 900]; // 3번만 명시 오버라이드
|
|
$metricIds = [2, 4]; // 온습도 센서
|
|
$metricDef = 7500;
|
|
$globalDef = 1200;
|
|
|
|
// ── 1) 명시 오버라이드 최우선(온습도여도) ──
|
|
check(resolve_heartbeat_timeout(3, $overrides, $metricIds, $metricDef, $globalDef) === 900,
|
|
'explicit override wins');
|
|
|
|
// ── 2) 온습도 센서 → METRIC 기본 ──
|
|
check(resolve_heartbeat_timeout(2, $overrides, $metricIds, $metricDef, $globalDef) === 7500,
|
|
'metric sensor -> metric default');
|
|
check(resolve_heartbeat_timeout(4, $overrides, $metricIds, $metricDef, $globalDef) === 7500,
|
|
'metric sensor 4 -> metric default');
|
|
|
|
// ── 3) 그 외(누수 등) → 전역 기본 ──
|
|
check(resolve_heartbeat_timeout(1, $overrides, $metricIds, $metricDef, $globalDef) === 1200,
|
|
'leak/other sensor -> global default');
|
|
|
|
// ── 4) 명시 오버라이드가 온습도 기본을 이긴다 ──
|
|
$ov2 = [2 => 4000];
|
|
check(resolve_heartbeat_timeout(2, $ov2, $metricIds, $metricDef, $globalDef) === 4000,
|
|
'explicit override beats metric default for a metric sensor');
|
|
|
|
// ── 5) 동일-id 온습도 통합: 누수 노드(1·3)가 METRIC_SENSOR_IDS 에도 포함돼도,
|
|
// 명시 오버라이드가 metric 기본(7500)을 이겨 누수 타임아웃(1800)을 유지해야 한다. ──
|
|
$sameIdOverride = [1 => 1800, 3 => 1800];
|
|
$sameIdMetric = [1, 2, 3]; // 1·3 은 온습도도 같은 id 로 보고 → 목록에 포함
|
|
check(resolve_heartbeat_timeout(1, $sameIdOverride, $sameIdMetric, 7500, 1200) === 1800,
|
|
'same-id leak(1) keeps leak timeout despite metric membership');
|
|
check(resolve_heartbeat_timeout(3, $sameIdOverride, $sameIdMetric, 7500, 1200) === 1800,
|
|
'same-id leak(3) keeps leak timeout despite metric membership');
|
|
check(resolve_heartbeat_timeout(2, $sameIdOverride, $sameIdMetric, 7500, 1200) === 7500,
|
|
'pure metric(2) still uses metric default');
|
|
|
|
if ($failures) {
|
|
fwrite(STDERR, "Heartbeat timeout test failures:\n");
|
|
foreach ($failures as $f) {
|
|
fwrite(STDERR, "- {$f}\n");
|
|
}
|
|
exit(1);
|
|
}
|
|
|
|
echo "Heartbeat timeout resolution checks passed.\n";
|