diff --git a/README.md b/README.md index f619660..b1c39eb 100644 --- a/README.md +++ b/README.md @@ -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 告警引擎 diff --git a/SHA256SUMS b/SHA256SUMS index de90aa8..0cb430c 100644 --- a/SHA256SUMS +++ b/SHA256SUMS @@ -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 diff --git a/app/pigway_pi_control.py b/app/pigway_pi_control.py index 114f281..e9a5b07 100755 --- a/app/pigway_pi_control.py +++ b/app/pigway_pi_control.py @@ -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