modify: IN2 DI 输入监听

This commit is contained in:
2026-09-13 20:34:10 +08:00
parent d7636c4c3b
commit 293254c61a
9 changed files with 272 additions and 704 deletions
+21 -15
View File
@@ -14,7 +14,6 @@
import errno
import glob
import os
import select # noqa: F401 (留给上层使用)
import struct
import time
@@ -42,9 +41,11 @@ class Backend:
raise NotImplementedError
def read(self):
"""非阻塞读一次,返回 (level, ts) 或 None。
"""非阻塞读一次,返回本批事件列表 [(level, ts), ...];无事件返回 []。
level 是原始电平 0/1,尚未做 active_low 翻转。
同一批数据里的多个事件必须全部返回,不能只留最后一个,
否则快速抖动(一次 read 里按下+释放)会丢失中间跳变。
"""
raise NotImplementedError
@@ -125,15 +126,15 @@ class EventBackend(Backend):
# ---- 读取 ----
def read(self):
"""返回 (level, ts) 或 None;只汇报关心的 key。"""
"""返回 [(level, ts), ...];只汇报关心的 key,批内事件按序全部返回。"""
if self.fd is None:
return None
return []
try:
data = os.read(self.fd, EVENT_STRUCT.size * 64)
except OSError:
return None
return []
self.buf += data
result = None
events = []
while len(self.buf) >= EVENT_STRUCT.size:
chunk = self.buf[:EVENT_STRUCT.size]
self.buf = self.buf[EVENT_STRUCT.size:]
@@ -147,8 +148,8 @@ class EventBackend(Backend):
if value not in (VALUE_RELEASE, VALUE_PRESS):
continue
ts = sec + usec / 1e6
result = (value, ts)
return result
events.append((value, ts))
return events
# ---------------------------------------------------------------------------
@@ -165,6 +166,7 @@ class SysfsBackend(Backend):
self.interval = interval
self._cand = None
self._cand_n = 0
self._reported = None # 上次上报的稳定值(跳变只报一次)
@property
def name(self):
@@ -193,13 +195,14 @@ class SysfsBackend(Backend):
# ---- 带抗抖的读取 ----
def read(self):
"""返回 (level, ts) 或 None。
"""返回 [(level, ts)];抗抖未确认或电平未变化时返回 []。
level 为抗抖确认后的稳定值;None 表示还没确认跳变。
连续 debounce 次采样一致才确认稳定值;确认值与上次上报不同
(真实跳变)才上报一次,避免稳态期间每个抗抖周期重复产出事件。
"""
v = self.read_raw()
if v is None:
return None
return []
ts = time.time()
if self._cand is None or v == self._cand:
@@ -209,10 +212,13 @@ class SysfsBackend(Backend):
self._cand = v
self._cand_n = 1
if self._cand_n >= self.debounce:
self._cand_n = 0 # 复位,避免重复上报
return (int(v), ts)
return None
if self._cand_n < self.debounce:
return []
confirmed = int(v)
if self._reported == confirmed:
return []
self._reported = confirmed
return [(confirmed, ts)]
# ---------------------------------------------------------------------------
+4 -8
View File
@@ -161,9 +161,8 @@ class DIChannel:
break
timeout = int(min(remain, 0.5) * 1000)
poller.poll(timeout)
got = self.backend.read()
if got:
raw, ts = got
# read() 返回本批全部事件,按序处理,快速抖动不丢中间跳变
for raw, ts in self.backend.read():
if self.on_event:
self.on_event(ts, raw)
self._emit(self._to_level(raw), ts)
@@ -173,13 +172,10 @@ class DIChannel:
while not self._stop:
if deadline and time.time() >= deadline:
break
got = self.backend.read()
if got:
raw, ts = got
lvl = self._to_level(raw)
for raw, ts in self.backend.read():
if self.on_event:
self.on_event(ts, raw)
self._emit(lvl, ts)
self._emit(self._to_level(raw), ts)
time.sleep(interval)
def request_stop(self):