팬 정책 데몬 전환과 관측 로그 정리
This commit is contained in:
1 parent
cfd5bb9b94
commit
309c10f1a1
4 files changed
+65
-11
No files matched your search
@@ -6,7 +6,7 @@
|
||||
|
||||
Control은 라즈베리파이/리눅스 호스트의 팬과 시스템 상태를 웹에서 관리하기 위한 내부 운영 도구입니다. 로그인 후 대시보드에서 온도, 팬 RPM, PWM, WiFi client, 저전압/스로틀링, notice를 확인하고 필요한 제어 명령을 실행합니다. 첫 화면은 운영 판단에 필요한 핵심 정보 위주로 구성하고, 상세 차트와 진단성 데이터는 접힘 영역에 둡니다.
|
||||
|
||||
상태 갱신은 WebSocket을 우선 사용하고, 연결 실패 시 HTTP fallback으로 전환합니다. 팬 정책 적용과 센서 수집은 백그라운드 작업과 API 호출을 통해 DB에 기록됩니다.
|
||||
상태 갱신은 WebSocket을 우선 사용하고, 연결 실패 시 HTTP fallback으로 전환합니다. 팬 정책 적용과 센서 수집은 백그라운드 daemon과 API 호출을 통해 DB에 기록됩니다.
|
||||
|
||||
## 주요 기능
|
||||
|
||||
@@ -64,7 +64,7 @@ Control은 라즈베리파이/리눅스 호스트의 팬과 시스템 상태를
|
||||
- `public/assets/app.js`: 대시보드 렌더링, WebSocket, 차트, 조작 이벤트
|
||||
- `public/assets/wakelock.js`: Screen Wake Lock API 제어
|
||||
- `config/config.php`: DB, 인증, CSRF, shell 실행 공통 함수
|
||||
- `apply_policy.php`: CLI/cron 팬 정책 적용
|
||||
- `apply_policy.php`: CLI 1회 실행과 daemon 모드를 지원하는 팬 정책 적용 루프
|
||||
- `bin/control_ws.php`: WebSocket 서버. 핵심 PHP 파일 변경 감지 시 종료되고 systemd가 재시작해 새 코드를 로드
|
||||
- `bin/wifi_observe.php`: 5G WiFi 연결 시간 보정을 위한 시스템단 관측 CLI
|
||||
- `touch_panel/panel.py`: 라즈베리파이 정품 터치 디스플레이용 standalone Qt 대시보드
|
||||
@@ -72,6 +72,7 @@ Control은 라즈베리파이/리눅스 호스트의 팬과 시스템 상태를
|
||||
- `touch_panel/control_touch_bridge.php`: 이전 Qt 패널용 로컬 JSON 브리지. 현재 standalone 패널은 사용하지 않습니다.
|
||||
- `touch_panel/control-touch-panel.desktop`: GUI 로그인 후 Qt 패널을 띄우는 데스크톱 autostart 파일
|
||||
- `systemd/control-rpi-disk-temp.service`: 터치 패널용 SSD 온도 캐시 서비스 예시
|
||||
- `systemd/fanpanel-apply.service`: 팬 정책을 1초 간격으로 계속 실행하는 daemon unit 예시
|
||||
- `systemd/control-wifi-observe.*`: WiFi 관측 CLI를 주기적으로 실행하는 systemd unit 예시
|
||||
- `systemd/control-touch-panel.service`: GUI 세션에서 Qt 관리자 패널을 띄우는 systemd unit 예시
|
||||
|
||||
@@ -168,6 +169,7 @@ systemd 방식이 필요하면 `systemd/control-touch-panel.service`를 `/etc/sy
|
||||
- 탭 복귀: 즉시 1회 상태 갱신
|
||||
- UPS/배터리 잔여 시간: 현재 운영 구성에서는 표시하지 않음
|
||||
- dmesg: 진단 패널에서 열었을 때만 1초마다 갱신, 닫으면 중지
|
||||
- 팬 정책 daemon: `fanpanel-apply.service`가 `apply_policy.php --daemon`을 실행해 1초마다 팬 정책과 센서 로그를 처리
|
||||
- WiFi 관측 보정 timer: 10초마다 `bin/wifi_observe.php` 실행
|
||||
- 외출/귀가 팬 정책: 팬 정책 적용 루프에서 기본 30초마다 서울 HA의 휴대폰 device tracker를 확인
|
||||
- WebSocket 소스 변경 감지: 15초마다 확인 후 재시작
|
||||
@@ -205,7 +207,7 @@ control-wifi-observe.service
|
||||
/usr/bin/php /var/www/control/bin/wifi_observe.php
|
||||
```
|
||||
|
||||
이 작업은 팬 정책, 차트 로그 저장, System Notice 기록과 분리되어 있으며 WiFi/LAN client 목록 확인과 `wifi_observed_sessions` 갱신만 수행합니다.
|
||||
이 작업은 팬 정책, 차트 로그 저장, System Notice 기록과 분리되어 있으며 WiFi/LAN client 목록 확인과 `wifi_observed_sessions` 갱신만 수행합니다. 정상 실행 JSON은 운영 기능에 쓰지 않으므로 systemd unit에서는 stdout을 버리고 실패 stderr만 journal에 남깁니다.
|
||||
|
||||
호스트명은 dnsmasq lease 값을 우선 사용합니다. lease hostname이 `N/A`이면 MAC 주소 끝 6자리 기반 임시명 `기기-XXXXXX`을 표시하고, 표의 호스트명을 클릭해 저장한 수동 이름은 `wifi_client_aliases`에 보관해 이후에도 우선 표시합니다.
|
||||
|
||||
@@ -302,6 +304,7 @@ control-wifi-observe.service
|
||||
- 2.4G 내장 WiFi는 `hostapd-24g.service` 개별 restart 직후 일부 IoT 단말이 WPA/EAPOL 재협상 루프에 들어갈 수 있으므로, 안정화된 상태에서는 개별 restart를 피하고 필요 시 전체 reboot 또는 채널 변경으로 재초기화합니다.
|
||||
- `hostapd-24g.service`, `hostapd-5g.service`는 종료 후 해당 `wlan` 인터페이스를 `br0`에서 떼도록 두어, 모듈이 빠졌다가 돌아온 뒤 hostapd가 다시 붙이는 흐름으로 정리합니다.
|
||||
- 5G WiFi 연결 시간은 외부 모듈이 값을 제공하지 않을 때 서버가 처음 감지한 시각 기준으로 계산합니다. 현재 5G 목록에서 MAC이 사라지면 관측 세션을 즉시 종료하므로 재연결 시 0부터 다시 누적됩니다.
|
||||
- `fanpanel-apply.service`는 `/var/www/control/apply_policy.php --daemon`으로 상주하며, 기존 1초 timer 방식과 같은 팬 정책/센서 로그 처리를 프로세스 재생성 없이 반복합니다.
|
||||
- `control-wifi-observe.timer`는 10초마다 `/var/www/control/bin/wifi_observe.php`를 실행해 사용자가 대시보드에 접속하지 않아도 5G/LAN 연결 시간 카운터를 시작하고 유지합니다.
|
||||
- WebSocket은 장기 실행 프로세스이므로 `public/api.php`, `config/config.php`, `bin/control_ws.php` 변경을 감지하면 15초 안에 종료되고 `control-websocket.service`가 새 프로세스로 재시작합니다.
|
||||
- WebSocket 장기 실행 중 DB 연결이 끊길 수 있으므로 reconnect 로그를 확인합니다.
|
||||
|
||||
+38
-6
@@ -3,6 +3,8 @@ declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/config/config.php';
|
||||
|
||||
const FAN_POLICY_INTERVAL_SECONDS = 1.0;
|
||||
|
||||
function local_fan_paths(): array
|
||||
{
|
||||
$candidates = glob('/sys/devices/platform/cooling_fan/hwmon/hwmon*/pwm1') ?: [];
|
||||
@@ -169,7 +171,8 @@ function dmesg_log_throttled(string $key, string $message, int $seconds = 30): v
|
||||
dmesg_log($message);
|
||||
}
|
||||
|
||||
try {
|
||||
function run_fan_policy_once(): bool
|
||||
{
|
||||
sync_presence_fan_policy();
|
||||
|
||||
$state = get_control_state();
|
||||
@@ -200,15 +203,12 @@ try {
|
||||
usleep(80000);
|
||||
|
||||
$actualPwm = read_int_file($paths['pwm']);
|
||||
|
||||
$rpm = read_int_file($paths['rpm']);
|
||||
|
||||
$load = sys_getloadavg() ?: [0, 0, 0];
|
||||
$mem = local_mem();
|
||||
$disk = local_disk('/');
|
||||
$cpuPower = cpu_power_status();
|
||||
$battery = battery_status();
|
||||
|
||||
$ok = $enableOk && $pwmOk;
|
||||
|
||||
add_sensor_log([
|
||||
@@ -254,8 +254,11 @@ try {
|
||||
);
|
||||
}
|
||||
|
||||
exit($ok ? 0 : 1);
|
||||
} catch (Throwable $e) {
|
||||
return $ok;
|
||||
}
|
||||
|
||||
function report_fan_policy_exception(Throwable $e): void
|
||||
{
|
||||
try {
|
||||
add_fan_action(
|
||||
'apply_policy_exception',
|
||||
@@ -268,5 +271,34 @@ try {
|
||||
}
|
||||
|
||||
fwrite(STDERR, $e->getMessage() . PHP_EOL);
|
||||
}
|
||||
|
||||
function run_fan_policy_daemon(): int
|
||||
{
|
||||
while (true) {
|
||||
$started = microtime(true);
|
||||
|
||||
try {
|
||||
run_fan_policy_once();
|
||||
} catch (Throwable $e) {
|
||||
report_fan_policy_exception($e);
|
||||
}
|
||||
|
||||
$elapsed = microtime(true) - $started;
|
||||
$sleep = max(0.05, FAN_POLICY_INTERVAL_SECONDS - $elapsed);
|
||||
usleep((int)round($sleep * 1000000));
|
||||
}
|
||||
}
|
||||
|
||||
$daemon = in_array('--daemon', $argv ?? [], true);
|
||||
|
||||
if ($daemon) {
|
||||
exit(run_fan_policy_daemon());
|
||||
}
|
||||
|
||||
try {
|
||||
exit(run_fan_policy_once() ? 0 : 1);
|
||||
} catch (Throwable $e) {
|
||||
report_fan_policy_exception($e);
|
||||
exit(1);
|
||||
}
|
||||
@@ -8,5 +8,5 @@ User=root
|
||||
Group=root
|
||||
WorkingDirectory=/var/www/control
|
||||
ExecStart=/usr/bin/php /var/www/control/bin/wifi_observe.php
|
||||
StandardOutput=append:/var/log/control-wifi-observe.log
|
||||
StandardError=append:/var/log/control-wifi-observe.log
|
||||
StandardOutput=null
|
||||
StandardError=journal
|
||||
@@ -0,0 +1,19 @@
|
||||
[Unit]
|
||||
Description=Apply fan panel policy daemon
|
||||
After=network-online.target mariadb.service
|
||||
Wants=network-online.target
|
||||
StartLimitIntervalSec=0
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
Group=root
|
||||
WorkingDirectory=/var/www/control
|
||||
ExecStart=/usr/bin/php /var/www/control/apply_policy.php --daemon
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
StandardOutput=null
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in new issue
Block a user