fix: arbitrate display requests atomically
This commit is contained in:
@@ -69,7 +69,7 @@ CHECK STORAGE
|
||||
|
||||
### 4. DisplayController、OLED 与 RGB
|
||||
|
||||
每个当前故障都是 DisplayController 中的一个 active request,包含稳定 ID、priority、severity、OLED 显示数据、首次发现时间、最后变化时间和元数据。监控只提交或清除 request。DisplayController 始终只选一个 owner,OLED 和 RGB 同步表达该 owner;`NORMAL_HOME` 是 priority 0 的常驻 request,有任何故障 owner 时不会抢回显示权。同优先级新 request 排队而不抢占,owner 恢复后按 priority、first_seen、ID 重新仲裁。历史 power flags 只进入 diagnose 和一次性 Journal 记录。
|
||||
每个当前故障都是 DisplayController 中的一个 active request,包含稳定 ID、priority、severity、OLED 显示数据、首次发现时间、最后变化时间和元数据。监控只提交或清除 request,同一轮采样作为一个原子批次,全部更新后只仲裁一次。DisplayController 始终只选一个 owner,OLED 和 RGB 同步表达该 owner;`NORMAL_HOME` 是 priority 0 的常驻 request,有任何故障 owner 时不会抢回显示权。同优先级新 request 排队而不抢占,owner 恢复后按 priority、first_seen、ID 重新仲裁。历史 power flags 只进入 diagnose 和一次性 Journal 记录。
|
||||
|
||||
### 5. RGB 告警引擎
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
162b3c8dee7576d0cd81ac9b4cd5c7f1051f8d1dc7f35fd8b3eeb2a932662d95 README.md
|
||||
72e5eabe3093fde436d9bbef417660ada81a52164f9697486dcbd73f5322c205 README.md
|
||||
72c46162c33f9587c6ccb01ad53fbaaf4ecec8cd21014b909e87e8707e253e36 app/oled_font_5x7.bin
|
||||
f750ec8189c14fb8a4cdadc691752ce757b9ab4e26784197ba09883aaa630b4c app/pigway_pi_control.py
|
||||
319ee4dbeed007df5ff3ce60f5a4b24b950f797f595848917542862bcbcbbd7d app/pigway_pi_control.py
|
||||
dfb1d083c9d64a5e0d6ccfa60a4ef5f71e83ea137ebc53b169a69f6b1458883f config/pigway-pi-control.conf
|
||||
4c2816da08378f2927c746b70ecfa7d5312e1730c08727cd89e8c2801e707054 install.sh
|
||||
81aea0a89b298b2512fcb9bf6418618ba7a66474d425390cf95a0128c4093474 systemd/pigway-pi-control.service
|
||||
|
||||
@@ -488,6 +488,7 @@ class DisplayController:
|
||||
self.current_priority=0
|
||||
self.current_rgb_mode="OFF"
|
||||
self.owner_since=now
|
||||
self.batch_depth=0
|
||||
self.stop_event=threading.Event()
|
||||
self.rgb_thread=threading.Thread(target=self._rgb_worker,name="rgb",daemon=True)
|
||||
|
||||
@@ -518,14 +519,23 @@ class DisplayController:
|
||||
("priority","severity","rgb_mode","title","l2","l3","l4","metadata"))
|
||||
if not changed: request["last_changed"]=current["last_changed"]
|
||||
self.requests[request_id]=request
|
||||
self._arbitrate_locked()
|
||||
if self.batch_depth==0: self._arbitrate_locked()
|
||||
|
||||
def clear(self,request_id):
|
||||
if request_id=="NORMAL_HOME": return
|
||||
with self.lock:
|
||||
if self.requests.pop(request_id,None) is not None:
|
||||
log("INFO","ALERT_RECOVERED",alert=request_id)
|
||||
self._arbitrate_locked()
|
||||
if self.batch_depth==0: self._arbitrate_locked()
|
||||
|
||||
def begin_update(self):
|
||||
with self.lock: self.batch_depth+=1
|
||||
|
||||
def end_update(self):
|
||||
with self.lock:
|
||||
if self.batch_depth<=0: raise RuntimeError("display update batch imbalance")
|
||||
self.batch_depth-=1
|
||||
if self.batch_depth==0: self._arbitrate_locked()
|
||||
|
||||
def _arbitrate_locked(self):
|
||||
current=self.requests.get(self.current_owner_id)
|
||||
@@ -654,7 +664,9 @@ try:
|
||||
|
||||
c,t,m,d=latest
|
||||
display.update_home(c,t,m,d)
|
||||
update_active_alerts(c,t,m,d,sample_elapsed)
|
||||
display.begin_update()
|
||||
try: update_active_alerts(c,t,m,d,sample_elapsed)
|
||||
finally: display.end_update()
|
||||
if now-last_render >= OLED_REFRESH:
|
||||
display.refresh()
|
||||
last_render=now
|
||||
|
||||
Reference in New Issue
Block a user