Add adaptive brightness value source with time-of-day and scene modes
New "adaptive" value source type that automatically adjusts brightness based on external conditions. Two sub-modes: time-of-day (schedule-based interpolation with midnight wrap) and scene brightness (frame luminance analysis via numpy BT.601 subsampling with EMA smoothing). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,15 +1,16 @@
|
||||
"""Value source data model with inheritance-based source types.
|
||||
|
||||
A ValueSource produces a scalar float (0.0–1.0) that can drive target
|
||||
parameters like brightness. Three types:
|
||||
parameters like brightness. Four types:
|
||||
StaticValueSource — constant float value
|
||||
AnimatedValueSource — periodic waveform (sine, triangle, square, sawtooth)
|
||||
AudioValueSource — audio-reactive scalar (RMS, peak, beat detection)
|
||||
AdaptiveValueSource — adapts to external conditions (time of day, scene brightness)
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from typing import List, Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -42,6 +43,10 @@ class ValueSource:
|
||||
"mode": None,
|
||||
"sensitivity": None,
|
||||
"smoothing": None,
|
||||
"adaptive_mode": None,
|
||||
"schedule": None,
|
||||
"picture_source_id": None,
|
||||
"scene_behavior": None,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
@@ -87,6 +92,20 @@ class ValueSource:
|
||||
smoothing=float(data.get("smoothing") or 0.3),
|
||||
)
|
||||
|
||||
if source_type == "adaptive":
|
||||
return AdaptiveValueSource(
|
||||
id=sid, name=name, source_type="adaptive",
|
||||
created_at=created_at, updated_at=updated_at, description=description,
|
||||
adaptive_mode=data.get("adaptive_mode") or "time_of_day",
|
||||
schedule=data.get("schedule") or [],
|
||||
picture_source_id=data.get("picture_source_id") or "",
|
||||
scene_behavior=data.get("scene_behavior") or "complement",
|
||||
sensitivity=float(data.get("sensitivity") or 1.0),
|
||||
smoothing=float(data.get("smoothing") or 0.3),
|
||||
min_value=float(data.get("min_value") or 0.0),
|
||||
max_value=float(data["max_value"]) if data.get("max_value") is not None else 1.0,
|
||||
)
|
||||
|
||||
# Default: "static" type
|
||||
return StaticValueSource(
|
||||
id=sid, name=name, source_type="static",
|
||||
@@ -152,3 +171,34 @@ class AudioValueSource(ValueSource):
|
||||
d["sensitivity"] = self.sensitivity
|
||||
d["smoothing"] = self.smoothing
|
||||
return d
|
||||
|
||||
|
||||
@dataclass
|
||||
class AdaptiveValueSource(ValueSource):
|
||||
"""Value source that adapts to external conditions.
|
||||
|
||||
Two sub-modes:
|
||||
time_of_day — interpolates brightness along a 24-hour schedule
|
||||
scene — derives brightness from a picture source's frame luminance
|
||||
"""
|
||||
|
||||
adaptive_mode: str = "time_of_day" # "time_of_day" | "scene"
|
||||
schedule: List[dict] = field(default_factory=list) # [{time: "HH:MM", value: 0.0-1.0}]
|
||||
picture_source_id: str = "" # for scene mode
|
||||
scene_behavior: str = "complement" # "complement" | "match"
|
||||
sensitivity: float = 1.0 # gain multiplier (0.1-5.0)
|
||||
smoothing: float = 0.3 # temporal smoothing (0.0-1.0)
|
||||
min_value: float = 0.0 # output range min
|
||||
max_value: float = 1.0 # output range max
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
d = super().to_dict()
|
||||
d["adaptive_mode"] = self.adaptive_mode
|
||||
d["schedule"] = self.schedule
|
||||
d["picture_source_id"] = self.picture_source_id
|
||||
d["scene_behavior"] = self.scene_behavior
|
||||
d["sensitivity"] = self.sensitivity
|
||||
d["smoothing"] = self.smoothing
|
||||
d["min_value"] = self.min_value
|
||||
d["max_value"] = self.max_value
|
||||
return d
|
||||
|
||||
Reference in New Issue
Block a user