打标epoch_finished, event_inner_index,epoch data 走队列

This commit is contained in:
Ivey Song
2026-06-14 19:32:48 +08:00
parent 5d3cd0dba9
commit bfd3fa27b3
2 changed files with 143 additions and 66 deletions

View File

@@ -83,6 +83,10 @@ class zmqServer(threading.Thread):
# 发送队列(双端口分离)
self.cmd_send_queue = queue.Queue() # 8099端口命令结果队列
self.data_send_queue = queue.Queue() # 8100端口滤波数据队列
# epoch完成通知队列生产者(zmqServer)写入, 消费者(Decoder)读取
# 每个元素是一个dict包含完整的epoch数据快照避免裸标志位竞态
self.epoch_queue = queue.Queue(maxsize=10)
# 范式buffer与事件检测参数
self.predict_event = 99
@@ -105,6 +109,12 @@ class zmqServer(threading.Thread):
self.pack_contain_event = False
self.event_inner_idx = -1
self.interval_inited = False
# 清空epoch队列防止残留旧epoch被新阶段消费
while not self.epoch_queue.empty():
try:
self.epoch_queue.get_nowait()
except queue.Empty:
break
def interval_init(self, decoder_class):
if decoder_class == 'ssmvep':
@@ -132,6 +142,12 @@ class zmqServer(threading.Thread):
self.predict_event = 99
self.events = [1, 2, self.predict_event]
self.interval_inited = True
# 清空epoch队列防止旧范式的残留epoch被新阶段消费
while not self.epoch_queue.empty():
try:
self.epoch_queue.get_nowait()
except queue.Empty:
break
# -------------------------- 8099端口命令结果广播 --------------------------
def broadcast_message(self, method, params):
@@ -341,10 +357,60 @@ class zmqServer(threading.Thread):
with self.paradigmBufferLock:
self.paradigmBuffer.appendBuffer(data_np)
if self.interval_inited:
self.pack_contain_event, self.epoch_finished = self.detect_event(data_np)
if self.epoch_finished:
algo_log(f"Epoch采集完成, 当前数据长度{self.paradigmBuffer.GetDataLenCount()}", level="DEBUG")
self.epoch_finished = self.detect_event(data_np)
if self.pack_contain_event:
self.paradigmBuffer.resetAllPara()
self.paradigmBuffer.appendBuffer(data_np)
if self.epoch_finished:
now = datetime.datetime.now()
time_diff_str = ""
# 计算与上一次Epoch完成的时间差
if self.last_epoch_finish_time is not None:
delta_seconds = (now - self.last_epoch_finish_time).total_seconds()
time_diff_str = f" | 与上一次间隔: {delta_seconds:.3f} s"
log_msg = f"Epoch采集完成: {now.strftime('%H:%M:%S.%f')[:-3]}{time_diff_str}"
algo_log(log_msg, level="DEBUG")
self.last_epoch_finish_time = now
# ---- 队列化通知在锁内快照数据原子放入epoch_queue ----
# get_MIData / get_SSMVEPData 内部调用 getData(),返回连续数组副本
# 快照完成后再由 Decoder 线程消费,彻底消除 TOCTOU 竞态
data_length = self.paradigmBuffer.GetDataLenCount()
try:
if self.decoder_class == 'mi':
snapshot = self.paradigmBuffer.get_MIData()
elif self.decoder_class == 'ssmvep':
snapshot = self.paradigmBuffer.get_SSMVEPData()
else:
snapshot = None
except Exception as snap_err:
algo_log(f"epoch快照失败: {snap_err}", level="ERROR")
snapshot = None
epoch_payload = {
'snapshot': snapshot, # 已选通道的数据副本
'currentLabel': self.currentLabel,
'event_inner_idx': self.event_inner_idx,
'data_length': data_length,
'completion_time': now,
'decoder_class': self.decoder_class,
}
try:
self.epoch_queue.put_nowait(epoch_payload)
except queue.Full:
# 队列满时丢弃最旧的epoch保留最新
try:
self.epoch_queue.get_nowait()
except queue.Empty:
pass
try:
self.epoch_queue.put_nowait(epoch_payload)
algo_log("epoch_queue已满已丢弃最旧epoch", level="WARNING")
except queue.Full:
algo_log("epoch_queue放入失败", level="ERROR")
else:
self.paradigmBuffer.appendBuffer(data_np)
except Exception as e:
algo_log(f"数据处理失败: {str(e)}", level="ERROR")