@@ -152,14 +152,39 @@ def summarize_legacy_export(export_path: Path) -> dict[str, object]:
152152 return summary
153153
154154
155- def find_simulation_device (manager : automation .Manager ) -> automation .DeviceDesc :
156- devices = manager .get_devices (include_simulation_devices = True )
155+ def format_device_type (device : automation .DeviceDesc ) -> str :
156+ return getattr (device .device_type , "name" , str (device .device_type ))
157+
158+
159+ def find_requested_simulation_device (
160+ manager : automation .Manager , requested_device : str , sample_rate : int
161+ ) -> automation .DeviceDesc :
162+ devices = [device for device in manager .get_devices (include_simulation_devices = True ) if device .is_simulation ]
163+
164+ if not devices :
165+ raise RuntimeError ("No Logic 2 simulation device was reported by the automation API." )
166+
167+ if requested_device == "auto" :
168+ if sample_rate > 100_000_000 :
169+ for preferred_type in ("LOGIC_PRO_8" , "LOGIC_PRO_16" ):
170+ for device in devices :
171+ if format_device_type (device ) == preferred_type :
172+ return device
173+
174+ return devices [0 ]
175+
176+ requested_type = {
177+ "logic8" : "LOGIC_8" ,
178+ "pro8" : "LOGIC_PRO_8" ,
179+ "pro16" : "LOGIC_PRO_16" ,
180+ }[requested_device ]
157181
158182 for device in devices :
159- if device . is_simulation :
183+ if format_device_type ( device ) == requested_type :
160184 return device
161185
162- raise RuntimeError ("No Logic 2 simulation device was reported by the automation API." )
186+ available = ", " .join (format_device_type (device ) for device in devices )
187+ raise RuntimeError (f"Requested simulation device { requested_type } was not available. Found: { available } " )
163188
164189
165190def validate_demo_summary (summary : dict [str , object ]) -> None :
@@ -180,7 +205,7 @@ def run_demo_capture(
180205 output_dir : Path ,
181206 manual_rerun_capture_path : Path ,
182207) -> tuple [automation .Capture , automation .AnalyzerHandle , str ]:
183- device = find_simulation_device (manager )
208+ device = find_requested_simulation_device (manager , args . simulation_device , args . sample_rate )
184209 capture = manager .start_capture (
185210 device_id = device .device_id ,
186211 device_configuration = automation .LogicDeviceConfiguration (
@@ -204,29 +229,19 @@ def run_demo_capture(
204229 print ("You can inspect Logic 2 now, and press Run manually during this pause if needed." )
205230 time .sleep (args .demo_pause_seconds )
206231
207- if args .manual_rerun :
208- prepared_capture_path = manual_rerun_capture_path
209- print (f"Analyzer added to the demo capture at { args .bitrate } bit/s." )
210- print (f"Rerun the capture in the Logic 2 GUI, save it to { prepared_capture_path } , then press Enter here." )
232+ prepared_capture_path = manual_rerun_capture_path
233+ print (f"Analyzer added to the demo capture at { args .bitrate } bit/s." )
234+ print ("Logic 2's automation API does not expose a rerun helper for analyzer demo data." )
235+ print (f"Rerun the capture in the Logic 2 GUI, save it to { prepared_capture_path } , then press Enter here." )
236+ try :
211237 input ()
238+ except EOFError as exc :
239+ raise RuntimeError (
240+ "Demo mode requires an interactive terminal so you can rerun the capture in Logic 2 and save the resulting .sal file."
241+ ) from exc
212242
213- if prepared_capture_path .exists () is False :
214- raise FileNotFoundError (f"Manual rerun capture not found: { prepared_capture_path } " )
215- else :
216- prepared_capture_path = output_dir / "flexray_demo_auto.sal"
217- try :
218- capture .save_capture (str (prepared_capture_path ))
219- except automation .errors .InvalidRequestError as exc :
220- if 'does not exist' not in str (exc ):
221- raise
222-
223- prepared_capture_path = manual_rerun_capture_path
224- print ("The demo capture was rerun in the GUI during the pause, so the original automation capture no longer exists." )
225- print (f"Save the current Logic 2 capture to { prepared_capture_path } , then press Enter here." )
226- input ()
227-
228- if prepared_capture_path .exists () is False :
229- raise FileNotFoundError (f"Fallback demo capture not found: { prepared_capture_path } " ) from exc
243+ if prepared_capture_path .exists () is False :
244+ raise FileNotFoundError (f"Manual rerun capture not found: { prepared_capture_path } " )
230245
231246 prepared_capture_for_api = create_capture_without_saved_analyzers (
232247 prepared_capture_path ,
@@ -238,14 +253,14 @@ def run_demo_capture(
238253 analyzer = add_flexray_analyzer (capture , args )
239254
240255 source_description = (
256+ f"Simulation: { format_device_type (device )} ({ device .device_id } )\n "
241257 f"Demo capture: { prepared_capture_path } \n "
242258 f"API capture: { prepared_capture_for_api } \n "
243259 f"Sample rate: { args .sample_rate } \n "
244260 f"Bit rate: { args .bitrate } "
245261 )
246262
247- if args .manual_rerun is False :
248- source_description += "\n Flow: automated two-pass demo setup"
263+ source_description += "\n Flow: manual rerun after analyzer add"
249264
250265 return capture , analyzer , source_description
251266
@@ -255,12 +270,23 @@ def main() -> int:
255270
256271 parser = argparse .ArgumentParser (description = "Validate the FlexRay analyzer against a Logic 2 capture or demo simulation." )
257272 parser .add_argument ("--logic2" , help = "Path to the Logic 2 executable, .app bundle, or AppImage." )
258- parser .add_argument ("--mode" , choices = ["capture" , "demo" ], default = "capture" , help = "Load a .sal capture or record from the Logic 2 simulation device." )
273+ parser .add_argument (
274+ "--mode" ,
275+ choices = ["capture" , "demo" ],
276+ default = "capture" ,
277+ help = "Load a .sal capture or use the Logic 2 simulation device, then manually rerun the demo after adding the analyzer." ,
278+ )
259279 parser .add_argument ("--capture" , default = str (root / "assets" / "SP2018_FlexRay.sal" ), help = "Path to the .sal capture." )
260280 parser .add_argument ("--output-dir" , default = str (root / "build" / "automation" ), help = "Directory for exported CSV files." )
261281 parser .add_argument ("--analyzers-dir" , default = str (root / "build" / "Analyzers" ), help = "Directory containing libFlexRayAnalyzer.so." )
262282 parser .add_argument ("--channel" , type = int , default = 0 , help = "Digital channel index for the FlexRay signal." )
263283 parser .add_argument ("--bitrate" , type = int , default = 10_000_000 , choices = [2_500_000 , 5_000_000 , 10_000_000 ], help = "FlexRay bit rate." )
284+ parser .add_argument (
285+ "--simulation-device" ,
286+ choices = ["auto" , "logic8" , "pro8" , "pro16" ],
287+ default = "auto" ,
288+ help = "Simulation device to use in demo mode. Auto prefers Pro devices when the requested sample rate exceeds 100 MS/s." ,
289+ )
264290 parser .add_argument (
265291 "--sample-rate" ,
266292 type = int ,
@@ -279,7 +305,7 @@ def main() -> int:
279305 parser .add_argument (
280306 "--manual-rerun" ,
281307 action = "store_true" ,
282- help = "For demo mode: pause after adding the analyzer so you can rerun the capture in the GUI, save it, and then export that saved capture ." ,
308+ help = "Deprecated compatibility flag. Demo mode now always requires a manual rerun after adding the analyzer ." ,
283309 )
284310 parser .add_argument (
285311 "--manual-rerun-capture" ,
@@ -357,4 +383,8 @@ def main() -> int:
357383
358384
359385if __name__ == "__main__" :
360- raise SystemExit (main ())
386+ try :
387+ raise SystemExit (main ())
388+ except Exception as exc :
389+ print (f"Error: { exc } " , file = sys .stderr )
390+ raise SystemExit (1 )
0 commit comments