New value source that monitors host hardware via psutil/pynvml: cpu_load, cpu_temp, gpu_load, gpu_temp, ram_usage, disk_usage, network_rx, network_tx, battery_level, fan_speed. Each metric normalizes to 0.0-1.0 with configurable ranges, poll interval, EMA smoothing, and sensor_label for multi-sensor systems. Conditional editor fields show/hide based on selected metric. Also fixes: WS test crash when raw_value streams lack _min_ha attr, toast timer overlap on rapid calls, SW cache bump to v34.
This commit is contained in:
@@ -25,6 +25,7 @@ from wled_controller.api.schemas.value_sources import (
|
||||
HAEntityValueSourceResponse,
|
||||
StaticColorValueSourceResponse,
|
||||
StaticValueSourceResponse,
|
||||
SystemMetricsValueSourceResponse,
|
||||
ValueSourceCreate,
|
||||
ValueSourceListResponse,
|
||||
ValueSourceResponse,
|
||||
@@ -42,6 +43,7 @@ from wled_controller.storage.value_source import (
|
||||
HAEntityValueSource,
|
||||
StaticColorValueSource,
|
||||
StaticValueSource,
|
||||
SystemMetricsValueSource,
|
||||
ValueSource,
|
||||
)
|
||||
from wled_controller.storage.value_source_store import ValueSourceStore
|
||||
@@ -171,6 +173,22 @@ _RESPONSE_MAP = {
|
||||
led_start=s.led_start,
|
||||
led_end=s.led_end,
|
||||
),
|
||||
SystemMetricsValueSource: lambda s: SystemMetricsValueSourceResponse(
|
||||
id=s.id,
|
||||
name=s.name,
|
||||
description=s.description,
|
||||
tags=s.tags,
|
||||
created_at=s.created_at,
|
||||
updated_at=s.updated_at,
|
||||
metric=s.metric,
|
||||
min_value=s.min_value,
|
||||
max_value=s.max_value,
|
||||
max_rate=s.max_rate,
|
||||
disk_path=s.disk_path,
|
||||
sensor_label=s.sensor_label,
|
||||
poll_interval=s.poll_interval,
|
||||
smoothing=s.smoothing,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@@ -403,7 +421,8 @@ async def test_value_source_ws(
|
||||
raw = stream.get_raw_value()
|
||||
if raw is not None:
|
||||
msg["raw_value"] = round(raw, 4)
|
||||
msg["raw_range"] = [stream._min_ha, stream._max_ha]
|
||||
if hasattr(stream, "_min_ha"):
|
||||
msg["raw_range"] = [stream._min_ha, stream._max_ha]
|
||||
await websocket.send_json(msg)
|
||||
await asyncio.sleep(0.05)
|
||||
except WebSocketDisconnect:
|
||||
|
||||
@@ -124,6 +124,19 @@ class CSSExtractValueSourceResponse(_ValueSourceResponseBase):
|
||||
led_end: int = Field(description="End of LED range (-1 = whole strip)")
|
||||
|
||||
|
||||
class SystemMetricsValueSourceResponse(_ValueSourceResponseBase):
|
||||
source_type: Literal["system_metrics"] = "system_metrics"
|
||||
return_type: Literal["float"] = "float"
|
||||
metric: str = Field(description="System metric to monitor")
|
||||
min_value: float = Field(description="Min value for range-based metrics")
|
||||
max_value: float = Field(description="Max value for range-based metrics")
|
||||
max_rate: float = Field(description="Max rate in bytes/sec for network metrics")
|
||||
disk_path: str = Field(description="Disk path for disk_usage metric")
|
||||
sensor_label: str = Field(description="Sensor label for cpu_temp/fan_speed")
|
||||
poll_interval: float = Field(description="Seconds between reads")
|
||||
smoothing: float = Field(description="EMA smoothing factor (0.0-1.0)")
|
||||
|
||||
|
||||
ValueSourceResponse = Annotated[
|
||||
Union[
|
||||
Annotated[StaticValueSourceResponse, Tag("static")],
|
||||
@@ -138,6 +151,7 @@ ValueSourceResponse = Annotated[
|
||||
Annotated[HAEntityValueSourceResponse, Tag("ha_entity")],
|
||||
Annotated[GradientMapValueSourceResponse, Tag("gradient_map")],
|
||||
Annotated[CSSExtractValueSourceResponse, Tag("css_extract")],
|
||||
Annotated[SystemMetricsValueSourceResponse, Tag("system_metrics")],
|
||||
],
|
||||
Discriminator("source_type"),
|
||||
]
|
||||
@@ -252,6 +266,18 @@ class CSSExtractValueSourceCreate(_ValueSourceCreateBase):
|
||||
led_end: int = Field(-1, description="End of LED range (-1 = whole strip)")
|
||||
|
||||
|
||||
class SystemMetricsValueSourceCreate(_ValueSourceCreateBase):
|
||||
source_type: Literal["system_metrics"] = "system_metrics"
|
||||
metric: str = Field("cpu_load", description="System metric to monitor")
|
||||
min_value: float = Field(0.0, description="Min value for normalization")
|
||||
max_value: float = Field(100.0, description="Max value for normalization")
|
||||
max_rate: float = Field(125_000_000.0, description="Max rate bytes/sec for network")
|
||||
disk_path: str = Field("", description="Disk path for disk_usage")
|
||||
sensor_label: str = Field("", description="Sensor label for cpu_temp/fan_speed")
|
||||
poll_interval: float = Field(1.0, description="Poll interval in seconds", ge=0.1, le=60.0)
|
||||
smoothing: float = Field(0.0, description="EMA smoothing (0.0-1.0)", ge=0.0, le=1.0)
|
||||
|
||||
|
||||
ValueSourceCreate = Annotated[
|
||||
Union[
|
||||
Annotated[StaticValueSourceCreate, Tag("static")],
|
||||
@@ -266,6 +292,7 @@ ValueSourceCreate = Annotated[
|
||||
Annotated[HAEntityValueSourceCreate, Tag("ha_entity")],
|
||||
Annotated[GradientMapValueSourceCreate, Tag("gradient_map")],
|
||||
Annotated[CSSExtractValueSourceCreate, Tag("css_extract")],
|
||||
Annotated[SystemMetricsValueSourceCreate, Tag("system_metrics")],
|
||||
],
|
||||
Discriminator("source_type"),
|
||||
]
|
||||
@@ -374,6 +401,18 @@ class CSSExtractValueSourceUpdate(_ValueSourceUpdateBase):
|
||||
led_end: Optional[int] = Field(None, description="LED range end")
|
||||
|
||||
|
||||
class SystemMetricsValueSourceUpdate(_ValueSourceUpdateBase):
|
||||
source_type: Literal["system_metrics"] = "system_metrics"
|
||||
metric: Optional[str] = Field(None, description="System metric")
|
||||
min_value: Optional[float] = Field(None, description="Min value")
|
||||
max_value: Optional[float] = Field(None, description="Max value")
|
||||
max_rate: Optional[float] = Field(None, description="Max rate bytes/sec")
|
||||
disk_path: Optional[str] = Field(None, description="Disk path")
|
||||
sensor_label: Optional[str] = Field(None, description="Sensor label")
|
||||
poll_interval: Optional[float] = Field(None, description="Poll interval", ge=0.1, le=60.0)
|
||||
smoothing: Optional[float] = Field(None, description="EMA smoothing", ge=0.0, le=1.0)
|
||||
|
||||
|
||||
ValueSourceUpdate = Annotated[
|
||||
Union[
|
||||
Annotated[StaticValueSourceUpdate, Tag("static")],
|
||||
@@ -388,6 +427,7 @@ ValueSourceUpdate = Annotated[
|
||||
Annotated[HAEntityValueSourceUpdate, Tag("ha_entity")],
|
||||
Annotated[GradientMapValueSourceUpdate, Tag("gradient_map")],
|
||||
Annotated[CSSExtractValueSourceUpdate, Tag("css_extract")],
|
||||
Annotated[SystemMetricsValueSourceUpdate, Tag("system_metrics")],
|
||||
],
|
||||
Discriminator("source_type"),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user