feat: HA light output targets — cast LED colors to Home Assistant lights
Lint & Test / test (push) Has been cancelled
Lint & Test / test (push) Has been cancelled
New output target type `ha_light` that sends averaged LED colors to HA light entities via WebSocket service calls (light.turn_on/turn_off): Backend: - HARuntime.call_service(): fire-and-forget WS service calls - HALightOutputTarget: data model with light mappings, update rate, transition - HALightTargetProcessor: processing loop with delta detection, rate limiting - ProcessorManager.add_ha_light_target(): registration - API schemas/routes updated for ha_light target type Frontend: - HA Light Targets section in Targets tab tree nav - Modal editor: HA source picker, CSS source picker, light entity mappings - Target cards with start/stop/clone/edit actions - i18n keys for all new UI strings
This commit is contained in:
@@ -10,6 +10,8 @@ import sys
|
||||
from datetime import datetime, timezone
|
||||
from typing import Optional
|
||||
|
||||
import os
|
||||
|
||||
import psutil
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
|
||||
@@ -52,8 +54,10 @@ from wled_controller.api.routes.system_settings import load_external_url # noqa
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
# Prime psutil CPU counter (first call always returns 0.0)
|
||||
# Prime psutil CPU counters (first call always returns 0.0)
|
||||
psutil.cpu_percent(interval=None)
|
||||
_process = psutil.Process(os.getpid())
|
||||
_process.cpu_percent(interval=None) # prime process-level counter
|
||||
|
||||
# GPU monitoring (initialized once in utils.gpu, shared with metrics_history)
|
||||
from wled_controller.utils.gpu import ( # noqa: E402
|
||||
@@ -264,18 +268,36 @@ def get_system_performance(_: AuthRequired):
|
||||
"""
|
||||
mem = psutil.virtual_memory()
|
||||
|
||||
# App-level metrics
|
||||
proc_mem = _process.memory_info()
|
||||
app_cpu = _process.cpu_percent(interval=None)
|
||||
app_ram_mb = round(proc_mem.rss / 1024 / 1024, 1)
|
||||
|
||||
gpu = None
|
||||
if _nvml_available:
|
||||
try:
|
||||
util = _nvml.nvmlDeviceGetUtilizationRates(_nvml_handle)
|
||||
mem_info = _nvml.nvmlDeviceGetMemoryInfo(_nvml_handle)
|
||||
temp = _nvml.nvmlDeviceGetTemperature(_nvml_handle, _nvml.NVML_TEMPERATURE_GPU)
|
||||
|
||||
# App GPU memory: sum memory used by this process on the GPU
|
||||
app_gpu_mem: float | None = None
|
||||
try:
|
||||
pid = os.getpid()
|
||||
for proc_info in _nvml.nvmlDeviceGetComputeRunningProcesses(_nvml_handle):
|
||||
if proc_info.pid == pid and proc_info.usedGpuMemory:
|
||||
app_gpu_mem = round(proc_info.usedGpuMemory / 1024 / 1024, 1)
|
||||
break
|
||||
except Exception:
|
||||
pass # not all drivers support per-process queries
|
||||
|
||||
gpu = GpuInfo(
|
||||
name=_nvml.nvmlDeviceGetName(_nvml_handle),
|
||||
utilization=float(util.gpu),
|
||||
memory_used_mb=round(mem_info.used / 1024 / 1024, 1),
|
||||
memory_total_mb=round(mem_info.total / 1024 / 1024, 1),
|
||||
temperature_c=float(temp),
|
||||
app_memory_mb=app_gpu_mem,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.debug("NVML query failed: %s", e)
|
||||
@@ -286,6 +308,8 @@ def get_system_performance(_: AuthRequired):
|
||||
ram_used_mb=round(mem.used / 1024 / 1024, 1),
|
||||
ram_total_mb=round(mem.total / 1024 / 1024, 1),
|
||||
ram_percent=mem.percent,
|
||||
app_cpu_percent=app_cpu,
|
||||
app_ram_mb=app_ram_mb,
|
||||
gpu=gpu,
|
||||
timestamp=datetime.now(timezone.utc),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user