refactor: use calibrated RGB alert flashes

This commit is contained in:
way
2026-09-27 10:00:05 +08:00
parent ac9bc4befd
commit adfa5524b8
4 changed files with 23 additions and 39 deletions
+13 -27
View File
@@ -121,19 +121,6 @@ def rgb_off():
mcu(0x07,0x00) # seller closeRGB(): true OFF
_last_rgb=("off",)
def rgb_mode(mode):
global _last_rgb
match=re.fullmatch(r"(RED|GREEN|BLUE|YELLOW|PURPLE|CYAN|WHITE)_(SLOW|FAST)_BREATHE",mode)
if match is None: raise ValueError(f"unsupported RGB mode: {mode}")
if _last_rgb==(mode,): return
color=RGB_COLOR_VALUES[match.group(1)]
speed=RGB_WARNING_SPEED if match.group(2)=="SLOW" else RGB_CRITICAL_SPEED
# Hardware-calibrated MCU order. The final effect write commits the mode.
mcu(0x05,speed); time.sleep(RGB_WRITE_DELAY_MS/1000.0)
mcu(0x06,color); time.sleep(RGB_WRITE_DELAY_MS/1000.0)
mcu(0x04,0x01)
_last_rgb=(mode,)
def set_pi_led(name,off=True):
base=Path("/sys/class/leds")/name
try:
@@ -261,15 +248,13 @@ FAN_HYST=cf("fan","hysteresis",1.5)
ROW_Y=[cf("display","row1_y",0,int),cf("display","row2_y",8,int),cf("display","row3_y",16,int),cf("display","row4_y",24,int)]
DARK_PWR=cf("dark_mode","pi_pwr_led",True,lambda x: str(x).strip().lower() in ("off","0","false","no"))
DARK_ACT=cf("dark_mode","pi_act_led",True,lambda x: str(x).strip().lower() in ("off","0","false","no"))
EMERGENCY_FLASH_MS=cf("led","emergency_flash_ms",300,int)
POWER_BLINK_MS=cf("led","power_blink_ms",750,int)
RGB_WRITE_DELAY_MS=max(1,cf("led","write_delay_ms",10,int))
RGB_WARNING_SPEED=max(1,min(3,cf("led","warning_speed",1,int)))
RGB_CRITICAL_SPEED=max(1,min(3,cf("led","critical_speed",3,int)))
RGB_COLOR_VALUES={"RED":0,"GREEN":1,"BLUE":2,"YELLOW":3,"PURPLE":4,"CYAN":5,"WHITE":6}
WARNING_FLASH_MS=max(50,cf("led","warning_flash_ms",1500,int))
CRITICAL_FLASH_MS=max(50,cf("led","critical_flash_ms",750,int))
EMERGENCY_FLASH_MS=max(50,cf("led","emergency_flash_ms",300,int))
RGB_STATIC_VALUES={
"RED":(0xff,0x00,0x00),"GREEN":(0x00,0xff,0x00),"BLUE":(0x00,0x00,0xff),
"YELLOW":(0xff,0xff,0x00),"PURPLE":(0xff,0x00,0xff),"CYAN":(0x00,0xff,0xff),
"YELLOW":(0xff,0xff,0x00),"PURPLE":(0xff,0x00,0xff),"CYAN":(0x00,0xff,0x60),
"WHITE":(0xff,0xff,0xff),"ORANGE":(0xff,0x28,0x00),
}
RGB_OBJECT_COLORS={
@@ -428,10 +413,9 @@ def update_active_alerts(cpu,temp,mem,disk,sample_elapsed=0.0):
def rgb_mode_for(request_id,severity):
if severity<=0: return "OFF"
alert_type=request_id.split("|",1)[0]
if alert_type=="POWER_UNDERVOLT": return "ORANGE_CRITICAL_BLINK"
color=RGB_OBJECT_COLORS[alert_type]
if severity>=3: return f"{color}_EMERGENCY_FLASH"
return f"{color}_{'FAST' if severity>=2 else 'SLOW'}_BREATHE"
color="ORANGE" if alert_type=="POWER_UNDERVOLT" else RGB_OBJECT_COLORS[alert_type]
level="EMERGENCY" if severity>=3 else "CRITICAL" if severity>=2 else "WARNING"
return f"{color}_{level}_FLASH"
def rgb_flash(mode,on):
global _last_rgb
@@ -629,18 +613,20 @@ class DisplayController:
while not self.stop_event.is_set():
try:
with self.lock: wanted_mode=self.current_rgb_mode
wanted_flash=wanted_mode.endswith(("_EMERGENCY_FLASH","_CRITICAL_BLINK"))
wanted_flash=wanted_mode.endswith("_FLASH")
if wanted_mode!=applied_mode:
with bus_lock:
if wanted_mode=="OFF": rgb_off()
elif wanted_flash: rgb_flash(wanted_mode,True)
else: rgb_mode(wanted_mode)
else: raise ValueError(f"unsupported RGB mode: {wanted_mode}")
log("INFO","RGB_MODE",old=applied_mode,new=wanted_mode)
applied_mode=wanted_mode; animation_started=time.monotonic()
applied_flash=applied_mode.endswith(("_EMERGENCY_FLASH","_CRITICAL_BLINK"))
applied_flash=applied_mode.endswith("_FLASH")
if applied_flash:
elapsed=time.monotonic()-animation_started
interval=POWER_BLINK_MS if applied_mode=="ORANGE_CRITICAL_BLINK" else EMERGENCY_FLASH_MS
if "_EMERGENCY_" in applied_mode: interval=EMERGENCY_FLASH_MS
elif "_CRITICAL_" in applied_mode: interval=CRITICAL_FLASH_MS
else: interval=WARNING_FLASH_MS
on=int(elapsed*1000/max(50,interval))%2==0
with bus_lock: rgb_flash(applied_mode,on)
if previous_error is not None: log("INFO","RGB_RECOVERED")