打标epoch_finished, event_inner_index,epoch data 走队列
This commit is contained in:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user