feat(sensor): 센서별 표시 라벨(위치·관리주체) 서버측 오버라이드
SENSOR_LABELS(config.local.php) 로 센서별 위치·관리주체를 서버에서 지정하고, sensor_label() 헬퍼로 SMS·대시보드 표시를 통일한다(Pi 재배포 불필요). SMS 본문 라벨을 '센서'→'관리주체'로 변경. 배포 번들에 3개 센서(서버실 안/문서고/밖) 예시 SENSOR_LABELS 를 주입.
This commit is contained in:
parent
a72ea18130
commit
0966f6d32b
3 changed files with 68 additions and 25 deletions
|
|
@ -264,6 +264,50 @@ $metric_sensor_ids = array_values(array_filter(
|
|||
));
|
||||
define('METRIC_SENSOR_IDS', $metric_sensor_ids !== [] ? $metric_sensor_ids : [2]);
|
||||
|
||||
// ─── 센서별 표시 라벨 오버라이드 (서버측) ────────────────────
|
||||
// SMS·대시보드에 표시할 센서별 "위치"와 "관리주체(표시명)"를 서버에서 지정한다
|
||||
// (Pi 재배포 없이 config.local.php 만 바꾸면 됨). 지정이 없으면 Pi 가 보고한
|
||||
// device_location / sensor_name 을 그대로 쓴다. 예:
|
||||
// 'SENSOR_LABELS' => [
|
||||
// 1 => ['location' => '서버실(안)', 'name' => '정보기반'],
|
||||
// 2 => ['location' => '문서고', 'name' => '조직혁신'],
|
||||
// 3 => ['location' => '서버실(밖)', 'name' => '고객센터'],
|
||||
// ]
|
||||
$sensor_labels_raw = cfg('SENSOR_LABELS', []);
|
||||
$sensor_labels = [];
|
||||
if (is_array($sensor_labels_raw)) {
|
||||
foreach ($sensor_labels_raw as $sid => $lbl) {
|
||||
$sid = (int)$sid;
|
||||
if ($sid < 1 || $sid > 255 || !is_array($lbl)) {
|
||||
continue;
|
||||
}
|
||||
$entry = [];
|
||||
if (isset($lbl['location']) && is_string($lbl['location']) && $lbl['location'] !== '') {
|
||||
$entry['location'] = $lbl['location'];
|
||||
}
|
||||
if (isset($lbl['name']) && is_string($lbl['name']) && $lbl['name'] !== '') {
|
||||
$entry['name'] = $lbl['name'];
|
||||
}
|
||||
if ($entry !== []) {
|
||||
$sensor_labels[$sid] = $entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
define('SENSOR_LABELS', $sensor_labels);
|
||||
|
||||
/**
|
||||
* 센서 표시 라벨 결정: SENSOR_LABELS(서버 오버라이드) 우선, 없으면 보고값(Pi) 폴백.
|
||||
* SMS·대시보드 등 사람이 보는 모든 곳에서 센서의 위치/관리주체를 이 헬퍼로 얻는다.
|
||||
*
|
||||
* @return array{0:string,1:string} [위치, 관리주체(표시명)]
|
||||
*/
|
||||
function sensor_label(int $sensor_id, ?string $reported_location, ?string $reported_name): array {
|
||||
$ov = SENSOR_LABELS[$sensor_id] ?? [];
|
||||
$loc = $ov['location'] ?? ((($reported_location ?? '') !== '') ? $reported_location : '알 수 없음');
|
||||
$name = $ov['name'] ?? ((($reported_name ?? '') !== '') ? $reported_name : "센서{$sensor_id}");
|
||||
return [$loc, $name];
|
||||
}
|
||||
|
||||
// ─── 대시보드 세션 인증 ──────────────────────────────────
|
||||
define('ADMIN_USER', cfg('ADMIN_USER', 'admin'));
|
||||
define('ADMIN_PASSWORD_HASH', cfg('ADMIN_PASSWORD_HASH', '')); // bcrypt 해시
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ function send_sms_cafe24(string $receiver, string $message): array {
|
|||
* @return bool 전원 발송 성공 여부
|
||||
*/
|
||||
function sms_dispatch_to_recipients(PDO $db, array $sensor_data, string $message, string $logLabel, ?array $recipients = null): bool {
|
||||
$name = $sensor_data['sensor_name'] ?? "센서{$sensor_data['sensor_id']}";
|
||||
[, $name] = sensor_label((int)($sensor_data['sensor_id'] ?? 0), null, $sensor_data['sensor_name'] ?? null);
|
||||
$allSuccess = true;
|
||||
$lastRemaining = null; // 게이트웨이가 알려준 최신 잔여 건수(잔액 사전경보용)
|
||||
$targets = $recipients ?? SMS_RECIPIENTS; // 기본 1차, 에스컬레이션은 TIER2 전달
|
||||
|
|
@ -520,14 +520,13 @@ function send_metric_alert_sms(array $sensor_data, string $kind, float $value):
|
|||
|
||||
// ── 메시지 구성 ──────────────────────────────────────────
|
||||
$dt = date('Y-m-d H:i:s');
|
||||
$name = $sensor_data['sensor_name'] ?? "센서{$sensor_id}";
|
||||
$loc = $sensor_data['device_location'] ?? '알 수 없음';
|
||||
[$loc, $name] = sensor_label((int)$sensor_data['sensor_id'], $sensor_data['device_location'] ?? null, $sensor_data['sensor_name'] ?? null);
|
||||
$valStr = metric_value_str($value);
|
||||
$thrStr = metric_value_str((float)$threshold);
|
||||
|
||||
$message = "{$tag}\n"
|
||||
. "위치: {$loc}\n"
|
||||
. "센서: {$name}\n"
|
||||
. "관리주체: {$name}\n"
|
||||
. "{$metricName}: {$valStr}{$unit} (임계 {$thrStr}{$unit} {$dir})\n"
|
||||
. "시각: {$dt}";
|
||||
|
||||
|
|
@ -555,12 +554,11 @@ function send_metric_recovery_sms(array $sensor_data, float $temp_c, float $rh):
|
|||
$db = get_db();
|
||||
|
||||
$dt = date('Y-m-d H:i:s');
|
||||
$name = $sensor_data['sensor_name'] ?? "센서{$sensor_data['sensor_id']}";
|
||||
$loc = $sensor_data['device_location'] ?? '알 수 없음';
|
||||
[$loc, $name] = sensor_label((int)$sensor_data['sensor_id'], $sensor_data['device_location'] ?? null, $sensor_data['sensor_name'] ?? null);
|
||||
|
||||
$message = SMS_TAG_RECOVERY . "\n"
|
||||
. "위치: {$loc}\n"
|
||||
. "센서: {$name}\n"
|
||||
. "관리주체: {$name}\n"
|
||||
. "온도 " . metric_value_str($temp_c) . "℃ / 습도 " . metric_value_str($rh) . "%\n"
|
||||
. "시각: {$dt}\n"
|
||||
. "온습도가 정상 범위로 복귀했습니다.";
|
||||
|
|
@ -632,12 +630,11 @@ function send_leak_alert_sms(array $sensor_data): bool {
|
|||
|
||||
// ── 메시지 구성 ──
|
||||
$dt = date('Y-m-d H:i:s');
|
||||
$name = $sensor_data['sensor_name'] ?? "센서{$sensor_id}";
|
||||
$loc = $sensor_data['device_location'] ?? '알 수 없음';
|
||||
[$loc, $name] = sensor_label((int)$sensor_data['sensor_id'], $sensor_data['device_location'] ?? null, $sensor_data['sensor_name'] ?? null);
|
||||
|
||||
$message = SMS_TAG_LEAK_ALERT . "\n"
|
||||
. "위치: {$loc}\n"
|
||||
. "센서: {$name}\n"
|
||||
. "관리주체: {$name}\n"
|
||||
. "누수가 감지되었습니다. 즉시 확인하세요!\n"
|
||||
. "시각: {$dt}";
|
||||
|
||||
|
|
@ -685,12 +682,11 @@ function send_leak_recovery_sms(array $sensor_data): bool {
|
|||
}
|
||||
|
||||
$dt = date('Y-m-d H:i:s');
|
||||
$name = $sensor_data['sensor_name'] ?? "센서{$sensor_id}";
|
||||
$loc = $sensor_data['device_location'] ?? '알 수 없음';
|
||||
[$loc, $name] = sensor_label((int)$sensor_data['sensor_id'], $sensor_data['device_location'] ?? null, $sensor_data['sensor_name'] ?? null);
|
||||
|
||||
$message = SMS_TAG_LEAK_RECOVERY . "\n"
|
||||
. "위치: {$loc}\n"
|
||||
. "센서: {$name}\n"
|
||||
. "관리주체: {$name}\n"
|
||||
. "누수가 해소(복구)되었습니다.\n"
|
||||
. "시각: {$dt}";
|
||||
|
||||
|
|
@ -707,13 +703,12 @@ function send_device_offline_sms(array $sensor_data): bool {
|
|||
$db = get_db();
|
||||
|
||||
$dt = date('Y-m-d H:i:s');
|
||||
$name = $sensor_data['sensor_name'] ?? "센서{$sensor_data['sensor_id']}";
|
||||
$loc = $sensor_data['device_location'] ?? '알 수 없음';
|
||||
[$loc, $name] = sensor_label((int)$sensor_data['sensor_id'], $sensor_data['device_location'] ?? null, $sensor_data['sensor_name'] ?? null);
|
||||
$last = $sensor_data['last_seen'] ?? '알 수 없음';
|
||||
|
||||
$message = SMS_TAG_DEVICE_OFFLINE . "\n"
|
||||
. "위치: {$loc}\n"
|
||||
. "센서: {$name}\n"
|
||||
. "관리주체: {$name}\n"
|
||||
. "마지막 통신: {$last}\n"
|
||||
. "감지 시각: {$dt}\n"
|
||||
. "장비 상태를 확인하세요!";
|
||||
|
|
@ -731,12 +726,11 @@ function send_device_online_sms(array $sensor_data): bool {
|
|||
$db = get_db();
|
||||
|
||||
$dt = date('Y-m-d H:i:s');
|
||||
$name = $sensor_data['sensor_name'] ?? "센서{$sensor_data['sensor_id']}";
|
||||
$loc = $sensor_data['device_location'] ?? '알 수 없음';
|
||||
[$loc, $name] = sensor_label((int)$sensor_data['sensor_id'], $sensor_data['device_location'] ?? null, $sensor_data['sensor_name'] ?? null);
|
||||
|
||||
$message = SMS_TAG_DEVICE_ONLINE . "\n"
|
||||
. "위치: {$loc}\n"
|
||||
. "센서: {$name}\n"
|
||||
. "관리주체: {$name}\n"
|
||||
. "복구 시각: {$dt}\n"
|
||||
. "통신이 정상 복구되었습니다.";
|
||||
|
||||
|
|
@ -920,11 +914,10 @@ function maybe_escalate_alerts(PDO $db): void {
|
|||
continue;
|
||||
}
|
||||
$firstLine = strtok($msg, "\n");
|
||||
$name = $s['sensor_name'] ?: "센서{$sid}";
|
||||
$loc = $s['device_location'] ?: '알 수 없음';
|
||||
[$loc, $name] = sensor_label($sid, $s['device_location'] ?? null, $s['sensor_name'] ?? null);
|
||||
$mins = (int)floor((time() - strtotime((string)$row['sent_at'])) / 60);
|
||||
$message = SMS_TAG_ESCALATION . "\n"
|
||||
. "위치: {$loc}\n센서: {$name}\n"
|
||||
. "위치: {$loc}\n관리주체: {$name}\n"
|
||||
. "{$firstLine} 미복귀 {$mins}분 경과\n"
|
||||
. "1차 미대응 — 확인 바랍니다.\n시각: " . date('Y-m-d H:i:s');
|
||||
$info = ['sensor_id' => $sid, 'sensor_name' => $name, 'device_id' => $s['device_id'], 'device_location' => $loc];
|
||||
|
|
@ -969,11 +962,10 @@ function maybe_detect_stuck_sensors(PDO $db): void {
|
|||
if (recent_tag_within($db, $sid, SMS_TAG_SENSOR_STUCK, STUCK_ALERT_COOLDOWN_SEC)) {
|
||||
continue; // 쿨다운
|
||||
}
|
||||
$name = $s['sensor_name'] ?: "센서{$sid}";
|
||||
$loc = $s['device_location'] ?: '알 수 없음';
|
||||
[$loc, $name] = sensor_label($sid, $s['device_location'] ?? null, $s['sensor_name'] ?? null);
|
||||
$tval = number_format((float)$rows[0]['temperature_c'], 2);
|
||||
$hval = number_format((float)$rows[0]['humidity_percent'], 2);
|
||||
$message = SMS_TAG_SENSOR_STUCK . "\n위치: {$loc}\n센서: {$name}\n"
|
||||
$message = SMS_TAG_SENSOR_STUCK . "\n위치: {$loc}\n관리주체: {$name}\n"
|
||||
. "최근 {$n}회 측정값 고착(온도 {$tval}℃ / 습도 {$hval}%)\n"
|
||||
. "센서/배선 점검 필요\n시각: " . date('Y-m-d H:i:s');
|
||||
$info = ['sensor_id' => $sid, 'sensor_name' => $name, 'device_id' => $s['device_id'], 'device_location' => $loc];
|
||||
|
|
|
|||
|
|
@ -309,6 +309,13 @@ return [
|
|||
// -- leak module sensor_id (Site 1 + new Site 3) --
|
||||
'LEAK_SENSOR_IDS' => [1, 3],
|
||||
|
||||
// -- per-sensor display labels (location + managing entity) shown in SMS/dashboard --
|
||||
'SENSOR_LABELS' => [
|
||||
1 => ['location' => '서버실(안)', 'name' => '정보기반'],
|
||||
2 => ['location' => '문서고', 'name' => '조직혁신'],
|
||||
3 => ['location' => '서버실(밖)', 'name' => '고객센터'],
|
||||
],
|
||||
|
||||
// -- temperature/humidity thresholds (recommended operational values) --
|
||||
'METRIC_TEMP_HIGH_C' => 27,
|
||||
'METRIC_TEMP_LOW_C' => 10,
|
||||
|
|
|
|||
Loading…
Reference in a new issue