chronaxis.execution.legacy_frame_samples
源码基线:8904c2f744951857659abd40aaa3535d57faf53c
1"""把同次BLF原帧仓与稀疏解码仓按原序连接,供新增报文重建使用。23不重新扫描BLF、不重新解码;新DBC上下文只提供编码布局和复用选择器。4原帧与解码记录的序号、时间和公开帧字段逐项相符,结束时两仓均完整核验。5"""67from ..results.frame_exports import as_export_frame8from ..results.frame_rebuild import FrameSample9from ..results.budget import _reserve_owned_ram,_release_owned_ram,_cleanup_owner10from ..results.errors import ResultClosedError,ResultFormatError111213class LegacyFrameSamples:14 """最多保留一条原帧与一条解码记录,拥有两游标而借用原仓和DBC。"""1516 def __init__(self,raw_store,message_store,context,budget,*,read_identity,session_id,channel,trace=True):17 """核同次仓身份后开有限游标。参数: 原帧/解码仓/DBC上下文/预算、原scan的read身份/会话/声明通道。返回: owner。异常: 合同/IO错。18 """19 self._budget=budget; self.context=context; self._held_cost=self._fixed_cost=020 self.channel=channel;self.trace=trace21 self.raw=self.messages=self.pending=None; self._closed=False; self._ended=False22 try:23 context.require_open()24 if raw_store._budget is not budget or raw_store.state!='sealed':25 raise ValueError('重建需要同预算已封口原帧仓')26 if message_store is not None and (message_store._budget is not budget or message_store.state!='sealed'27 or message_store.source_name!=raw_store.source_name or message_store.session_id!=session_id28 or message_store.read_identity!=read_identity):29 raise ValueError('原帧与解码仓不是同次读取')30 _reserve_owned_ram(self,262144,'_fixed_cost')31 self.raw=raw_store.iter_frames()32 if message_store is not None:33 self.messages=message_store.iter_records(); self.pending=next(self.messages,None)34 except BaseException as error:35 _cleanup_owner(self,error,'legacy_frame_samples_cleanup_owner','原帧解码连接构造'); raise3637 @property38 def closed(self):39 """返回真实关闭状态。参数: 无。返回: bool。异常: 无。40 """41 return self._closed4243 def __iter__(self):44 """返回独立游标。参数: 无。返回: self。异常: 无。45 """46 return self4748 def __next__(self):49 """连接同原序记录,不跳过完整仓核验。参数: 无。返回: FrameSample。异常: EOF/来源不符/IO错。50 """51 if self._closed or self._ended:52 raise StopIteration53 self.context.require_open()54 try:55 raw=next(self.raw)56 except StopIteration:57 if self.pending is not None or not self.raw.verified_eof or self.messages is not None and not self.messages.verified_eof:58 raise ResultFormatError('原帧和解码仓没有共同完整结束')59 self._ended=True; raise60 decoded=None61 if self.pending is not None:62 item=self.pending63 if item.decoded.sequence<raw.sequence:64 raise ResultFormatError('解码仓出现无对应原帧记录')65 if item.decoded.sequence==raw.sequence:66 if item.time_ns!=raw.time_ns or item.decoded.frame!=raw.frame:67 raise ResultFormatError('重建原帧与解码记录内容不符')68 decoded=item.decoded; self.pending=next(self.messages,None)69 # 与同次读取使用相同候选选择,不把标准与扩展帧的同数值ID混为一条。70 message=self.context.observe(raw.frame)71 known=raw.frame.channel==self.channel and self.context.is_known_frame(raw.frame)72 values=(); layout=(); valid=True73 rule=next((rule for rule in self.context.rules if rule.matches(raw.frame)),None)74 if rule is not None and not raw.frame.is_error_frame and not raw.frame.is_remote_frame:75 if decoded is None or message is None:76 raise ResultFormatError('已请求重建报文缺同次解码记录')77 values=tuple((name,decoded.values.get(name)) for name in rule.continuous)78 selectors=tuple(signal for signal in message.signals if signal.is_multiplexer)79 # 未激活分支的复用选择器可以缺席;实际布局只包含本次解码已有的选择器。80 layout=tuple((signal.name,int(signal.conversion.numeric_scaled_to_raw(decoded.values[signal.name])))81 for signal in selectors if signal.name in decoded.values)82 return FrameSample(as_export_frame(raw,compact=not self.trace),values,layout,known,valid)8384 def close(self):85 """关闭真实两个游标后释放自己的费用。参数: 无。返回: None。异常: 原close错可重试。86 """87 if self._closed:88 return89 for slot in ('raw','messages'):90 owner=getattr(self,slot)91 if owner is not None:92 owner.close(); setattr(self,slot,None)93 self.pending=self.context=None94 _release_owned_ram(self,self._fixed_cost,'_fixed_cost'); self._closed=True95