oscura 0.5.1__py3-none-any.whl → 0.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (497) hide show
  1. oscura/__init__.py +169 -167
  2. oscura/analyzers/__init__.py +3 -0
  3. oscura/analyzers/classification.py +659 -0
  4. oscura/analyzers/digital/edges.py +325 -65
  5. oscura/analyzers/digital/quality.py +293 -166
  6. oscura/analyzers/digital/timing.py +260 -115
  7. oscura/analyzers/digital/timing_numba.py +334 -0
  8. oscura/analyzers/entropy.py +605 -0
  9. oscura/analyzers/eye/diagram.py +176 -109
  10. oscura/analyzers/eye/metrics.py +5 -5
  11. oscura/analyzers/jitter/__init__.py +6 -4
  12. oscura/analyzers/jitter/ber.py +52 -52
  13. oscura/analyzers/jitter/classification.py +156 -0
  14. oscura/analyzers/jitter/decomposition.py +163 -113
  15. oscura/analyzers/jitter/spectrum.py +80 -64
  16. oscura/analyzers/ml/__init__.py +39 -0
  17. oscura/analyzers/ml/features.py +600 -0
  18. oscura/analyzers/ml/signal_classifier.py +604 -0
  19. oscura/analyzers/packet/daq.py +246 -158
  20. oscura/analyzers/packet/parser.py +12 -1
  21. oscura/analyzers/packet/payload.py +50 -2110
  22. oscura/analyzers/packet/payload_analysis.py +361 -181
  23. oscura/analyzers/packet/payload_patterns.py +133 -70
  24. oscura/analyzers/packet/stream.py +84 -23
  25. oscura/analyzers/patterns/__init__.py +26 -5
  26. oscura/analyzers/patterns/anomaly_detection.py +908 -0
  27. oscura/analyzers/patterns/clustering.py +169 -108
  28. oscura/analyzers/patterns/clustering_optimized.py +227 -0
  29. oscura/analyzers/patterns/discovery.py +1 -1
  30. oscura/analyzers/patterns/matching.py +581 -197
  31. oscura/analyzers/patterns/pattern_mining.py +778 -0
  32. oscura/analyzers/patterns/periodic.py +121 -38
  33. oscura/analyzers/patterns/sequences.py +175 -78
  34. oscura/analyzers/power/conduction.py +1 -1
  35. oscura/analyzers/power/soa.py +6 -6
  36. oscura/analyzers/power/switching.py +250 -110
  37. oscura/analyzers/protocol/__init__.py +17 -1
  38. oscura/analyzers/protocols/base.py +6 -6
  39. oscura/analyzers/protocols/ble/__init__.py +38 -0
  40. oscura/analyzers/protocols/ble/analyzer.py +809 -0
  41. oscura/analyzers/protocols/ble/uuids.py +288 -0
  42. oscura/analyzers/protocols/can.py +257 -127
  43. oscura/analyzers/protocols/can_fd.py +107 -80
  44. oscura/analyzers/protocols/flexray.py +139 -80
  45. oscura/analyzers/protocols/hdlc.py +93 -58
  46. oscura/analyzers/protocols/i2c.py +247 -106
  47. oscura/analyzers/protocols/i2s.py +138 -86
  48. oscura/analyzers/protocols/industrial/__init__.py +40 -0
  49. oscura/analyzers/protocols/industrial/bacnet/__init__.py +33 -0
  50. oscura/analyzers/protocols/industrial/bacnet/analyzer.py +708 -0
  51. oscura/analyzers/protocols/industrial/bacnet/encoding.py +412 -0
  52. oscura/analyzers/protocols/industrial/bacnet/services.py +622 -0
  53. oscura/analyzers/protocols/industrial/ethercat/__init__.py +30 -0
  54. oscura/analyzers/protocols/industrial/ethercat/analyzer.py +474 -0
  55. oscura/analyzers/protocols/industrial/ethercat/mailbox.py +339 -0
  56. oscura/analyzers/protocols/industrial/ethercat/topology.py +166 -0
  57. oscura/analyzers/protocols/industrial/modbus/__init__.py +31 -0
  58. oscura/analyzers/protocols/industrial/modbus/analyzer.py +525 -0
  59. oscura/analyzers/protocols/industrial/modbus/crc.py +79 -0
  60. oscura/analyzers/protocols/industrial/modbus/functions.py +436 -0
  61. oscura/analyzers/protocols/industrial/opcua/__init__.py +21 -0
  62. oscura/analyzers/protocols/industrial/opcua/analyzer.py +552 -0
  63. oscura/analyzers/protocols/industrial/opcua/datatypes.py +446 -0
  64. oscura/analyzers/protocols/industrial/opcua/services.py +264 -0
  65. oscura/analyzers/protocols/industrial/profinet/__init__.py +23 -0
  66. oscura/analyzers/protocols/industrial/profinet/analyzer.py +441 -0
  67. oscura/analyzers/protocols/industrial/profinet/dcp.py +263 -0
  68. oscura/analyzers/protocols/industrial/profinet/ptcp.py +200 -0
  69. oscura/analyzers/protocols/jtag.py +180 -98
  70. oscura/analyzers/protocols/lin.py +219 -114
  71. oscura/analyzers/protocols/manchester.py +4 -4
  72. oscura/analyzers/protocols/onewire.py +253 -149
  73. oscura/analyzers/protocols/parallel_bus/__init__.py +20 -0
  74. oscura/analyzers/protocols/parallel_bus/centronics.py +92 -0
  75. oscura/analyzers/protocols/parallel_bus/gpib.py +137 -0
  76. oscura/analyzers/protocols/spi.py +192 -95
  77. oscura/analyzers/protocols/swd.py +321 -167
  78. oscura/analyzers/protocols/uart.py +267 -125
  79. oscura/analyzers/protocols/usb.py +235 -131
  80. oscura/analyzers/side_channel/power.py +17 -12
  81. oscura/analyzers/signal/__init__.py +15 -0
  82. oscura/analyzers/signal/timing_analysis.py +1086 -0
  83. oscura/analyzers/signal_integrity/__init__.py +4 -1
  84. oscura/analyzers/signal_integrity/sparams.py +2 -19
  85. oscura/analyzers/spectral/chunked.py +129 -60
  86. oscura/analyzers/spectral/chunked_fft.py +300 -94
  87. oscura/analyzers/spectral/chunked_wavelet.py +100 -80
  88. oscura/analyzers/statistical/checksum.py +376 -217
  89. oscura/analyzers/statistical/classification.py +229 -107
  90. oscura/analyzers/statistical/entropy.py +78 -53
  91. oscura/analyzers/statistics/correlation.py +407 -211
  92. oscura/analyzers/statistics/outliers.py +2 -2
  93. oscura/analyzers/statistics/streaming.py +30 -5
  94. oscura/analyzers/validation.py +216 -101
  95. oscura/analyzers/waveform/measurements.py +9 -0
  96. oscura/analyzers/waveform/measurements_with_uncertainty.py +31 -15
  97. oscura/analyzers/waveform/spectral.py +500 -228
  98. oscura/api/__init__.py +31 -5
  99. oscura/api/dsl/__init__.py +582 -0
  100. oscura/{dsl → api/dsl}/commands.py +43 -76
  101. oscura/{dsl → api/dsl}/interpreter.py +26 -51
  102. oscura/{dsl → api/dsl}/parser.py +107 -77
  103. oscura/{dsl → api/dsl}/repl.py +2 -2
  104. oscura/api/dsl.py +1 -1
  105. oscura/{integrations → api/integrations}/__init__.py +1 -1
  106. oscura/{integrations → api/integrations}/llm.py +201 -102
  107. oscura/api/operators.py +3 -3
  108. oscura/api/optimization.py +144 -30
  109. oscura/api/rest_server.py +921 -0
  110. oscura/api/server/__init__.py +17 -0
  111. oscura/api/server/dashboard.py +850 -0
  112. oscura/api/server/static/README.md +34 -0
  113. oscura/api/server/templates/base.html +181 -0
  114. oscura/api/server/templates/export.html +120 -0
  115. oscura/api/server/templates/home.html +284 -0
  116. oscura/api/server/templates/protocols.html +58 -0
  117. oscura/api/server/templates/reports.html +43 -0
  118. oscura/api/server/templates/session_detail.html +89 -0
  119. oscura/api/server/templates/sessions.html +83 -0
  120. oscura/api/server/templates/waveforms.html +73 -0
  121. oscura/automotive/__init__.py +8 -1
  122. oscura/automotive/can/__init__.py +10 -0
  123. oscura/automotive/can/checksum.py +3 -1
  124. oscura/automotive/can/dbc_generator.py +590 -0
  125. oscura/automotive/can/message_wrapper.py +121 -74
  126. oscura/automotive/can/patterns.py +98 -21
  127. oscura/automotive/can/session.py +292 -56
  128. oscura/automotive/can/state_machine.py +6 -3
  129. oscura/automotive/can/stimulus_response.py +97 -75
  130. oscura/automotive/dbc/__init__.py +10 -2
  131. oscura/automotive/dbc/generator.py +84 -56
  132. oscura/automotive/dbc/parser.py +6 -6
  133. oscura/automotive/dtc/data.json +17 -102
  134. oscura/automotive/dtc/database.py +2 -2
  135. oscura/automotive/flexray/__init__.py +31 -0
  136. oscura/automotive/flexray/analyzer.py +504 -0
  137. oscura/automotive/flexray/crc.py +185 -0
  138. oscura/automotive/flexray/fibex.py +449 -0
  139. oscura/automotive/j1939/__init__.py +45 -8
  140. oscura/automotive/j1939/analyzer.py +605 -0
  141. oscura/automotive/j1939/spns.py +326 -0
  142. oscura/automotive/j1939/transport.py +306 -0
  143. oscura/automotive/lin/__init__.py +47 -0
  144. oscura/automotive/lin/analyzer.py +612 -0
  145. oscura/automotive/loaders/blf.py +13 -2
  146. oscura/automotive/loaders/csv_can.py +143 -72
  147. oscura/automotive/loaders/dispatcher.py +50 -2
  148. oscura/automotive/loaders/mdf.py +86 -45
  149. oscura/automotive/loaders/pcap.py +111 -61
  150. oscura/automotive/uds/__init__.py +4 -0
  151. oscura/automotive/uds/analyzer.py +725 -0
  152. oscura/automotive/uds/decoder.py +140 -58
  153. oscura/automotive/uds/models.py +7 -1
  154. oscura/automotive/visualization.py +1 -1
  155. oscura/cli/analyze.py +348 -0
  156. oscura/cli/batch.py +142 -122
  157. oscura/cli/benchmark.py +275 -0
  158. oscura/cli/characterize.py +137 -82
  159. oscura/cli/compare.py +224 -131
  160. oscura/cli/completion.py +250 -0
  161. oscura/cli/config_cmd.py +361 -0
  162. oscura/cli/decode.py +164 -87
  163. oscura/cli/export.py +286 -0
  164. oscura/cli/main.py +115 -31
  165. oscura/{onboarding → cli/onboarding}/__init__.py +3 -3
  166. oscura/{onboarding → cli/onboarding}/help.py +80 -58
  167. oscura/{onboarding → cli/onboarding}/tutorials.py +97 -72
  168. oscura/{onboarding → cli/onboarding}/wizard.py +55 -36
  169. oscura/cli/progress.py +147 -0
  170. oscura/cli/shell.py +157 -135
  171. oscura/cli/validate_cmd.py +204 -0
  172. oscura/cli/visualize.py +158 -0
  173. oscura/convenience.py +125 -79
  174. oscura/core/__init__.py +4 -2
  175. oscura/core/backend_selector.py +3 -3
  176. oscura/core/cache.py +126 -15
  177. oscura/core/cancellation.py +1 -1
  178. oscura/{config → core/config}/__init__.py +20 -11
  179. oscura/{config → core/config}/defaults.py +1 -1
  180. oscura/{config → core/config}/loader.py +7 -5
  181. oscura/{config → core/config}/memory.py +5 -5
  182. oscura/{config → core/config}/migration.py +1 -1
  183. oscura/{config → core/config}/pipeline.py +99 -23
  184. oscura/{config → core/config}/preferences.py +1 -1
  185. oscura/{config → core/config}/protocol.py +3 -3
  186. oscura/{config → core/config}/schema.py +426 -272
  187. oscura/{config → core/config}/settings.py +1 -1
  188. oscura/{config → core/config}/thresholds.py +195 -153
  189. oscura/core/correlation.py +5 -6
  190. oscura/core/cross_domain.py +0 -2
  191. oscura/core/debug.py +9 -5
  192. oscura/{extensibility → core/extensibility}/docs.py +158 -70
  193. oscura/{extensibility → core/extensibility}/extensions.py +160 -76
  194. oscura/{extensibility → core/extensibility}/logging.py +1 -1
  195. oscura/{extensibility → core/extensibility}/measurements.py +1 -1
  196. oscura/{extensibility → core/extensibility}/plugins.py +1 -1
  197. oscura/{extensibility → core/extensibility}/templates.py +73 -3
  198. oscura/{extensibility → core/extensibility}/validation.py +1 -1
  199. oscura/core/gpu_backend.py +11 -7
  200. oscura/core/log_query.py +101 -11
  201. oscura/core/logging.py +126 -54
  202. oscura/core/logging_advanced.py +5 -5
  203. oscura/core/memory_limits.py +108 -70
  204. oscura/core/memory_monitor.py +2 -2
  205. oscura/core/memory_progress.py +7 -7
  206. oscura/core/memory_warnings.py +1 -1
  207. oscura/core/numba_backend.py +13 -13
  208. oscura/{plugins → core/plugins}/__init__.py +9 -9
  209. oscura/{plugins → core/plugins}/base.py +7 -7
  210. oscura/{plugins → core/plugins}/cli.py +3 -3
  211. oscura/{plugins → core/plugins}/discovery.py +186 -106
  212. oscura/{plugins → core/plugins}/lifecycle.py +1 -1
  213. oscura/{plugins → core/plugins}/manager.py +7 -7
  214. oscura/{plugins → core/plugins}/registry.py +3 -3
  215. oscura/{plugins → core/plugins}/versioning.py +1 -1
  216. oscura/core/progress.py +16 -1
  217. oscura/core/provenance.py +8 -2
  218. oscura/{schemas → core/schemas}/__init__.py +2 -2
  219. oscura/{schemas → core/schemas}/device_mapping.json +2 -8
  220. oscura/{schemas → core/schemas}/packet_format.json +4 -24
  221. oscura/{schemas → core/schemas}/protocol_definition.json +2 -12
  222. oscura/core/types.py +4 -0
  223. oscura/core/uncertainty.py +3 -3
  224. oscura/correlation/__init__.py +52 -0
  225. oscura/correlation/multi_protocol.py +811 -0
  226. oscura/discovery/auto_decoder.py +117 -35
  227. oscura/discovery/comparison.py +191 -86
  228. oscura/discovery/quality_validator.py +155 -68
  229. oscura/discovery/signal_detector.py +196 -79
  230. oscura/export/__init__.py +18 -8
  231. oscura/export/kaitai_struct.py +513 -0
  232. oscura/export/scapy_layer.py +801 -0
  233. oscura/export/wireshark/generator.py +1 -1
  234. oscura/export/wireshark/templates/dissector.lua.j2 +2 -2
  235. oscura/export/wireshark_dissector.py +746 -0
  236. oscura/guidance/wizard.py +207 -111
  237. oscura/hardware/__init__.py +19 -0
  238. oscura/{acquisition → hardware/acquisition}/__init__.py +4 -4
  239. oscura/{acquisition → hardware/acquisition}/file.py +2 -2
  240. oscura/{acquisition → hardware/acquisition}/hardware.py +7 -7
  241. oscura/{acquisition → hardware/acquisition}/saleae.py +15 -12
  242. oscura/{acquisition → hardware/acquisition}/socketcan.py +1 -1
  243. oscura/{acquisition → hardware/acquisition}/streaming.py +2 -2
  244. oscura/{acquisition → hardware/acquisition}/synthetic.py +3 -3
  245. oscura/{acquisition → hardware/acquisition}/visa.py +33 -11
  246. oscura/hardware/firmware/__init__.py +29 -0
  247. oscura/hardware/firmware/pattern_recognition.py +874 -0
  248. oscura/hardware/hal_detector.py +736 -0
  249. oscura/hardware/security/__init__.py +37 -0
  250. oscura/hardware/security/side_channel_detector.py +1126 -0
  251. oscura/inference/__init__.py +4 -0
  252. oscura/inference/active_learning/observation_table.py +4 -1
  253. oscura/inference/alignment.py +216 -123
  254. oscura/inference/bayesian.py +113 -33
  255. oscura/inference/crc_reverse.py +101 -55
  256. oscura/inference/logic.py +6 -2
  257. oscura/inference/message_format.py +342 -183
  258. oscura/inference/protocol.py +95 -44
  259. oscura/inference/protocol_dsl.py +180 -82
  260. oscura/inference/signal_intelligence.py +1439 -706
  261. oscura/inference/spectral.py +99 -57
  262. oscura/inference/state_machine.py +810 -158
  263. oscura/inference/stream.py +270 -110
  264. oscura/iot/__init__.py +34 -0
  265. oscura/iot/coap/__init__.py +32 -0
  266. oscura/iot/coap/analyzer.py +668 -0
  267. oscura/iot/coap/options.py +212 -0
  268. oscura/iot/lorawan/__init__.py +21 -0
  269. oscura/iot/lorawan/crypto.py +206 -0
  270. oscura/iot/lorawan/decoder.py +801 -0
  271. oscura/iot/lorawan/mac_commands.py +341 -0
  272. oscura/iot/mqtt/__init__.py +27 -0
  273. oscura/iot/mqtt/analyzer.py +999 -0
  274. oscura/iot/mqtt/properties.py +315 -0
  275. oscura/iot/zigbee/__init__.py +31 -0
  276. oscura/iot/zigbee/analyzer.py +615 -0
  277. oscura/iot/zigbee/security.py +153 -0
  278. oscura/iot/zigbee/zcl.py +349 -0
  279. oscura/jupyter/display.py +125 -45
  280. oscura/{exploratory → jupyter/exploratory}/__init__.py +8 -8
  281. oscura/{exploratory → jupyter/exploratory}/error_recovery.py +298 -141
  282. oscura/jupyter/exploratory/fuzzy.py +746 -0
  283. oscura/{exploratory → jupyter/exploratory}/fuzzy_advanced.py +258 -100
  284. oscura/{exploratory → jupyter/exploratory}/legacy.py +464 -242
  285. oscura/{exploratory → jupyter/exploratory}/parse.py +167 -145
  286. oscura/{exploratory → jupyter/exploratory}/recovery.py +119 -87
  287. oscura/jupyter/exploratory/sync.py +612 -0
  288. oscura/{exploratory → jupyter/exploratory}/unknown.py +299 -176
  289. oscura/jupyter/magic.py +4 -4
  290. oscura/{ui → jupyter/ui}/__init__.py +2 -2
  291. oscura/{ui → jupyter/ui}/formatters.py +3 -3
  292. oscura/{ui → jupyter/ui}/progressive_display.py +153 -82
  293. oscura/loaders/__init__.py +183 -67
  294. oscura/loaders/binary.py +88 -1
  295. oscura/loaders/chipwhisperer.py +153 -137
  296. oscura/loaders/configurable.py +208 -86
  297. oscura/loaders/csv_loader.py +458 -215
  298. oscura/loaders/hdf5_loader.py +278 -119
  299. oscura/loaders/lazy.py +87 -54
  300. oscura/loaders/mmap_loader.py +1 -1
  301. oscura/loaders/numpy_loader.py +253 -116
  302. oscura/loaders/pcap.py +226 -151
  303. oscura/loaders/rigol.py +110 -49
  304. oscura/loaders/sigrok.py +201 -78
  305. oscura/loaders/tdms.py +81 -58
  306. oscura/loaders/tektronix.py +291 -174
  307. oscura/loaders/touchstone.py +182 -87
  308. oscura/loaders/tss.py +456 -0
  309. oscura/loaders/vcd.py +215 -117
  310. oscura/loaders/wav.py +155 -68
  311. oscura/reporting/__init__.py +9 -0
  312. oscura/reporting/analyze.py +352 -146
  313. oscura/reporting/argument_preparer.py +69 -14
  314. oscura/reporting/auto_report.py +97 -61
  315. oscura/reporting/batch.py +131 -58
  316. oscura/reporting/chart_selection.py +57 -45
  317. oscura/reporting/comparison.py +63 -17
  318. oscura/reporting/content/executive.py +76 -24
  319. oscura/reporting/core_formats/multi_format.py +11 -8
  320. oscura/reporting/engine.py +312 -158
  321. oscura/reporting/enhanced_reports.py +949 -0
  322. oscura/reporting/export.py +86 -43
  323. oscura/reporting/formatting/numbers.py +69 -42
  324. oscura/reporting/html.py +139 -58
  325. oscura/reporting/index.py +137 -65
  326. oscura/reporting/output.py +158 -67
  327. oscura/reporting/pdf.py +67 -102
  328. oscura/reporting/plots.py +191 -112
  329. oscura/reporting/sections.py +88 -47
  330. oscura/reporting/standards.py +104 -61
  331. oscura/reporting/summary_generator.py +75 -55
  332. oscura/reporting/tables.py +138 -54
  333. oscura/reporting/templates/enhanced/protocol_re.html +525 -0
  334. oscura/sessions/__init__.py +14 -23
  335. oscura/sessions/base.py +3 -3
  336. oscura/sessions/blackbox.py +106 -10
  337. oscura/sessions/generic.py +2 -2
  338. oscura/sessions/legacy.py +783 -0
  339. oscura/side_channel/__init__.py +63 -0
  340. oscura/side_channel/dpa.py +1025 -0
  341. oscura/utils/__init__.py +15 -1
  342. oscura/utils/bitwise.py +118 -0
  343. oscura/{builders → utils/builders}/__init__.py +1 -1
  344. oscura/{comparison → utils/comparison}/__init__.py +6 -6
  345. oscura/{comparison → utils/comparison}/compare.py +202 -101
  346. oscura/{comparison → utils/comparison}/golden.py +83 -63
  347. oscura/{comparison → utils/comparison}/limits.py +313 -89
  348. oscura/{comparison → utils/comparison}/mask.py +151 -45
  349. oscura/{comparison → utils/comparison}/trace_diff.py +1 -1
  350. oscura/{comparison → utils/comparison}/visualization.py +147 -89
  351. oscura/{component → utils/component}/__init__.py +3 -3
  352. oscura/{component → utils/component}/impedance.py +122 -58
  353. oscura/{component → utils/component}/reactive.py +165 -168
  354. oscura/{component → utils/component}/transmission_line.py +3 -3
  355. oscura/{filtering → utils/filtering}/__init__.py +6 -6
  356. oscura/{filtering → utils/filtering}/base.py +1 -1
  357. oscura/{filtering → utils/filtering}/convenience.py +2 -2
  358. oscura/{filtering → utils/filtering}/design.py +169 -93
  359. oscura/{filtering → utils/filtering}/filters.py +2 -2
  360. oscura/{filtering → utils/filtering}/introspection.py +2 -2
  361. oscura/utils/geometry.py +31 -0
  362. oscura/utils/imports.py +184 -0
  363. oscura/utils/lazy.py +1 -1
  364. oscura/{math → utils/math}/__init__.py +2 -2
  365. oscura/{math → utils/math}/arithmetic.py +114 -48
  366. oscura/{math → utils/math}/interpolation.py +139 -106
  367. oscura/utils/memory.py +129 -66
  368. oscura/utils/memory_advanced.py +92 -9
  369. oscura/utils/memory_extensions.py +10 -8
  370. oscura/{optimization → utils/optimization}/__init__.py +1 -1
  371. oscura/{optimization → utils/optimization}/search.py +2 -2
  372. oscura/utils/performance/__init__.py +58 -0
  373. oscura/utils/performance/caching.py +889 -0
  374. oscura/utils/performance/lsh_clustering.py +333 -0
  375. oscura/utils/performance/memory_optimizer.py +699 -0
  376. oscura/utils/performance/optimizations.py +675 -0
  377. oscura/utils/performance/parallel.py +654 -0
  378. oscura/utils/performance/profiling.py +661 -0
  379. oscura/{pipeline → utils/pipeline}/base.py +1 -1
  380. oscura/{pipeline → utils/pipeline}/composition.py +1 -1
  381. oscura/{pipeline → utils/pipeline}/parallel.py +3 -2
  382. oscura/{pipeline → utils/pipeline}/pipeline.py +1 -1
  383. oscura/{pipeline → utils/pipeline}/reverse_engineering.py +412 -221
  384. oscura/{search → utils/search}/__init__.py +3 -3
  385. oscura/{search → utils/search}/anomaly.py +188 -58
  386. oscura/utils/search/context.py +294 -0
  387. oscura/{search → utils/search}/pattern.py +138 -10
  388. oscura/utils/serial.py +51 -0
  389. oscura/utils/storage/__init__.py +61 -0
  390. oscura/utils/storage/database.py +1166 -0
  391. oscura/{streaming → utils/streaming}/chunked.py +302 -143
  392. oscura/{streaming → utils/streaming}/progressive.py +1 -1
  393. oscura/{streaming → utils/streaming}/realtime.py +3 -2
  394. oscura/{triggering → utils/triggering}/__init__.py +6 -6
  395. oscura/{triggering → utils/triggering}/base.py +6 -6
  396. oscura/{triggering → utils/triggering}/edge.py +2 -2
  397. oscura/{triggering → utils/triggering}/pattern.py +2 -2
  398. oscura/{triggering → utils/triggering}/pulse.py +115 -74
  399. oscura/{triggering → utils/triggering}/window.py +2 -2
  400. oscura/utils/validation.py +32 -0
  401. oscura/validation/__init__.py +121 -0
  402. oscura/{compliance → validation/compliance}/__init__.py +5 -5
  403. oscura/{compliance → validation/compliance}/advanced.py +5 -5
  404. oscura/{compliance → validation/compliance}/masks.py +1 -1
  405. oscura/{compliance → validation/compliance}/reporting.py +127 -53
  406. oscura/{compliance → validation/compliance}/testing.py +114 -52
  407. oscura/validation/compliance_tests.py +915 -0
  408. oscura/validation/fuzzer.py +990 -0
  409. oscura/validation/grammar_tests.py +596 -0
  410. oscura/validation/grammar_validator.py +904 -0
  411. oscura/validation/hil_testing.py +977 -0
  412. oscura/{quality → validation/quality}/__init__.py +4 -4
  413. oscura/{quality → validation/quality}/ensemble.py +251 -171
  414. oscura/{quality → validation/quality}/explainer.py +3 -3
  415. oscura/{quality → validation/quality}/scoring.py +1 -1
  416. oscura/{quality → validation/quality}/warnings.py +4 -4
  417. oscura/validation/regression_suite.py +808 -0
  418. oscura/validation/replay.py +788 -0
  419. oscura/{testing → validation/testing}/__init__.py +2 -2
  420. oscura/{testing → validation/testing}/synthetic.py +5 -5
  421. oscura/visualization/__init__.py +9 -0
  422. oscura/visualization/accessibility.py +1 -1
  423. oscura/visualization/annotations.py +64 -67
  424. oscura/visualization/colors.py +7 -7
  425. oscura/visualization/digital.py +180 -81
  426. oscura/visualization/eye.py +236 -85
  427. oscura/visualization/interactive.py +320 -143
  428. oscura/visualization/jitter.py +587 -247
  429. oscura/visualization/layout.py +169 -134
  430. oscura/visualization/optimization.py +103 -52
  431. oscura/visualization/palettes.py +1 -1
  432. oscura/visualization/power.py +427 -211
  433. oscura/visualization/power_extended.py +626 -297
  434. oscura/visualization/presets.py +2 -0
  435. oscura/visualization/protocols.py +495 -181
  436. oscura/visualization/render.py +79 -63
  437. oscura/visualization/reverse_engineering.py +171 -124
  438. oscura/visualization/signal_integrity.py +460 -279
  439. oscura/visualization/specialized.py +190 -100
  440. oscura/visualization/spectral.py +670 -255
  441. oscura/visualization/thumbnails.py +166 -137
  442. oscura/visualization/waveform.py +150 -63
  443. oscura/workflows/__init__.py +3 -0
  444. oscura/{batch → workflows/batch}/__init__.py +5 -5
  445. oscura/{batch → workflows/batch}/advanced.py +150 -75
  446. oscura/workflows/batch/aggregate.py +531 -0
  447. oscura/workflows/batch/analyze.py +236 -0
  448. oscura/{batch → workflows/batch}/logging.py +2 -2
  449. oscura/{batch → workflows/batch}/metrics.py +1 -1
  450. oscura/workflows/complete_re.py +1144 -0
  451. oscura/workflows/compliance.py +44 -54
  452. oscura/workflows/digital.py +197 -51
  453. oscura/workflows/legacy/__init__.py +12 -0
  454. oscura/{workflow → workflows/legacy}/dag.py +4 -1
  455. oscura/workflows/multi_trace.py +9 -9
  456. oscura/workflows/power.py +42 -62
  457. oscura/workflows/protocol.py +82 -49
  458. oscura/workflows/reverse_engineering.py +351 -150
  459. oscura/workflows/signal_integrity.py +157 -82
  460. oscura-0.7.0.dist-info/METADATA +661 -0
  461. oscura-0.7.0.dist-info/RECORD +591 -0
  462. oscura/batch/aggregate.py +0 -300
  463. oscura/batch/analyze.py +0 -139
  464. oscura/dsl/__init__.py +0 -73
  465. oscura/exceptions.py +0 -59
  466. oscura/exploratory/fuzzy.py +0 -513
  467. oscura/exploratory/sync.py +0 -384
  468. oscura/exporters/__init__.py +0 -94
  469. oscura/exporters/csv.py +0 -303
  470. oscura/exporters/exporters.py +0 -44
  471. oscura/exporters/hdf5.py +0 -217
  472. oscura/exporters/html_export.py +0 -701
  473. oscura/exporters/json_export.py +0 -291
  474. oscura/exporters/markdown_export.py +0 -367
  475. oscura/exporters/matlab_export.py +0 -354
  476. oscura/exporters/npz_export.py +0 -219
  477. oscura/exporters/spice_export.py +0 -210
  478. oscura/search/context.py +0 -149
  479. oscura/session/__init__.py +0 -34
  480. oscura/session/annotations.py +0 -289
  481. oscura/session/history.py +0 -313
  482. oscura/session/session.py +0 -520
  483. oscura/workflow/__init__.py +0 -13
  484. oscura-0.5.1.dist-info/METADATA +0 -583
  485. oscura-0.5.1.dist-info/RECORD +0 -481
  486. /oscura/core/{config.py → config/legacy.py} +0 -0
  487. /oscura/{extensibility → core/extensibility}/__init__.py +0 -0
  488. /oscura/{extensibility → core/extensibility}/registry.py +0 -0
  489. /oscura/{plugins → core/plugins}/isolation.py +0 -0
  490. /oscura/{schemas → core/schemas}/bus_configuration.json +0 -0
  491. /oscura/{builders → utils/builders}/signal_builder.py +0 -0
  492. /oscura/{optimization → utils/optimization}/parallel.py +0 -0
  493. /oscura/{pipeline → utils/pipeline}/__init__.py +0 -0
  494. /oscura/{streaming → utils/streaming}/__init__.py +0 -0
  495. {oscura-0.5.1.dist-info → oscura-0.7.0.dist-info}/WHEEL +0 -0
  496. {oscura-0.5.1.dist-info → oscura-0.7.0.dist-info}/entry_points.txt +0 -0
  497. {oscura-0.5.1.dist-info → oscura-0.7.0.dist-info}/licenses/LICENSE +0 -0
@@ -3,10 +3,18 @@
3
3
  This module provides DBC file parsing and generation capabilities.
4
4
  """
5
5
 
6
- __all__ = ["DBCGenerator", "DBCParser", "load_dbc"]
6
+ __all__ = ["DBCGenerator", "DBCMessage", "DBCNode", "DBCParser", "DBCSignal", "load_dbc"]
7
7
 
8
8
  try:
9
- from oscura.automotive.dbc.generator import DBCGenerator
9
+ # Import comprehensive DBC generator from new location
10
+ from oscura.automotive.can.dbc_generator import (
11
+ DBCGenerator,
12
+ DBCMessage,
13
+ DBCNode,
14
+ DBCSignal,
15
+ )
16
+
17
+ # Parser stays in dbc module
10
18
  from oscura.automotive.dbc.parser import DBCParser, load_dbc
11
19
  except ImportError:
12
20
  # Optional dependencies not installed
@@ -1,7 +1,10 @@
1
- """DBC file generator from discovery documents.
1
+ """DBC file generator wrapper for backward compatibility.
2
2
 
3
- This module generates standard DBC files from Oscura discovery documents,
4
- enabling export of reverse-engineered protocols to industry-standard format.
3
+ This module provides a backward-compatible wrapper around the comprehensive
4
+ DBC generator in oscura.automotive.can.dbc_generator, supporting the legacy
5
+ static method API used by existing code.
6
+
7
+ For new code, import directly from oscura.automotive.can.dbc_generator instead.
5
8
  """
6
9
 
7
10
  from __future__ import annotations
@@ -10,16 +13,29 @@ from pathlib import Path
10
13
  from typing import TYPE_CHECKING
11
14
 
12
15
  if TYPE_CHECKING:
13
- from oscura.automotive.can.discovery import (
14
- DiscoveryDocument,
15
- )
16
+ from oscura.automotive.can.discovery import DiscoveryDocument
16
17
  from oscura.automotive.can.session import CANSession
17
18
 
19
+ from oscura.automotive.can.dbc_generator import (
20
+ DBCGenerator as _DBCGeneratorImpl,
21
+ )
22
+ from oscura.automotive.can.dbc_generator import (
23
+ DBCMessage,
24
+ DBCSignal,
25
+ )
26
+
18
27
  __all__ = ["DBCGenerator"]
19
28
 
20
29
 
21
30
  class DBCGenerator:
22
- """Generate DBC files from discovery documents."""
31
+ """Backward-compatible DBC generator wrapper.
32
+
33
+ This class provides static methods for generating DBC files from
34
+ DiscoveryDocument and CANSession objects, maintaining API compatibility
35
+ with the original implementation.
36
+
37
+ For new code, use oscura.automotive.can.dbc_generator.DBCGenerator directly.
38
+ """
23
39
 
24
40
  @staticmethod
25
41
  def generate(
@@ -35,70 +51,76 @@ class DBCGenerator:
35
51
  output_path: Output DBC file path.
36
52
  min_confidence: Minimum confidence threshold for including signals.
37
53
  include_comments: Include evidence as comments in DBC.
54
+
55
+ Example:
56
+ >>> from oscura.automotive.can.discovery import DiscoveryDocument
57
+ >>> doc = DiscoveryDocument()
58
+ >>> # ... add messages and signals ...
59
+ >>> DBCGenerator.generate(doc, "output.dbc")
38
60
  """
39
- path = Path(output_path)
40
61
 
41
- lines = []
62
+ path = Path(output_path)
42
63
 
43
- # DBC header
44
- lines.append('VERSION ""')
45
- lines.append("")
46
- lines.append("NS_ :")
47
- lines.append("")
48
- lines.append("BS_:")
49
- lines.append("")
50
- lines.append("BU_:") # No nodes defined
51
- lines.append("")
64
+ # Create instance of new generator
65
+ gen = _DBCGeneratorImpl()
52
66
 
53
- # Generate messages
54
- for msg in sorted(discovery.messages.values(), key=lambda m: m.id):
67
+ # Convert discovery document to DBC format
68
+ for msg_id, msg_discovery in sorted(discovery.messages.items()):
55
69
  # Filter signals by confidence
56
- signals = [s for s in msg.signals if s.confidence >= min_confidence]
70
+ signals = [s for s in msg_discovery.signals if s.confidence >= min_confidence]
57
71
 
58
72
  if not signals:
59
73
  continue # Skip messages with no high-confidence signals
60
74
 
61
- # Message definition
62
- # Format: BO_ <ID> <Name>: <DLC> <Transmitter>
63
- transmitter = msg.transmitter if msg.transmitter else "Vector__XXX"
64
- lines.append(f"BO_ {msg.id} {msg.name}: {msg.length} {transmitter}")
65
-
66
- # Signals
75
+ # Convert signals to DBC format
76
+ dbc_signals = []
67
77
  for sig in signals:
68
- # Format: SG_ <Name> : <StartBit>|<Length>@<ByteOrder><ValueType> (<Scale>,<Offset>) [<Min>|<Max>] "<Unit>" <Receiver>
69
- byte_order = "0" if sig.byte_order == "big_endian" else "1"
70
- value_type = "+" if sig.value_type == "unsigned" else "-"
71
-
72
- min_val = sig.min_value if sig.min_value is not None else 0
73
- max_val = sig.max_value if sig.max_value is not None else 0
74
-
75
- signal_line = (
76
- f" SG_ {sig.name} : {sig.start_bit}|{sig.length}@{byte_order}{value_type} "
77
- f"({sig.scale},{sig.offset}) [{min_val}|{max_val}] "
78
- f'"{sig.unit}" Vector__XXX'
78
+ # Convert value_type: DBC only supports unsigned/signed, not float
79
+ # Floats are typically represented as unsigned in DBC
80
+ value_type: str = sig.value_type
81
+ if value_type not in ("unsigned", "signed"):
82
+ value_type = "unsigned"
83
+
84
+ dbc_sig = DBCSignal(
85
+ name=sig.name,
86
+ start_bit=sig.start_bit,
87
+ bit_length=sig.length,
88
+ byte_order=sig.byte_order,
89
+ value_type=value_type, # type: ignore[arg-type]
90
+ factor=sig.scale,
91
+ offset=sig.offset,
92
+ min_value=sig.min_value if sig.min_value is not None else 0.0,
93
+ max_value=sig.max_value if sig.max_value is not None else 0.0,
94
+ unit=sig.unit,
95
+ receivers=["Vector__XXX"],
96
+ comment="; ".join(sig.evidence) if include_comments and sig.evidence else "",
79
97
  )
80
-
81
- lines.append(signal_line)
82
-
83
- # Add comment if evidence exists
84
- if include_comments and sig.evidence:
85
- evidence_str = "; ".join(sig.evidence)
86
- # DBC comments format: CM_ SG_ <ID> <SignalName> "<Comment>";
87
- comment_line = f'CM_ SG_ {msg.id} {sig.name} "{evidence_str}";'
88
- lines.append("")
89
- lines.append(comment_line)
90
-
91
- lines.append("")
92
-
93
- # Write file with latin-1 encoding (DBC standard)
94
- with open(path, "w", encoding="latin-1") as f:
95
- f.write("\n".join(lines))
98
+ dbc_signals.append(dbc_sig)
99
+
100
+ # Create DBC message
101
+ dbc_msg = DBCMessage(
102
+ message_id=msg_id,
103
+ name=msg_discovery.name,
104
+ dlc=msg_discovery.length,
105
+ sender=msg_discovery.transmitter if msg_discovery.transmitter else "Vector__XXX",
106
+ signals=dbc_signals,
107
+ comment=msg_discovery.comment if msg_discovery.comment else "",
108
+ cycle_time=int(msg_discovery.cycle_time_ms)
109
+ if msg_discovery.cycle_time_ms is not None
110
+ else None,
111
+ send_type="Cyclic",
112
+ )
113
+
114
+ gen.add_message(dbc_msg)
115
+
116
+ # Generate DBC file
117
+ gen.generate(path)
96
118
 
97
119
  @staticmethod
98
120
  def generate_from_session(
99
121
  session: CANSession,
100
122
  output_path: Path | str,
101
- min_confidence: float = 0.8, # noqa: ARG004 - API compatibility parameter
123
+ min_confidence: float = 0.8, # Reserved for future use
102
124
  ) -> None:
103
125
  """Generate DBC file from CANSession with documented signals.
104
126
 
@@ -106,6 +128,12 @@ class DBCGenerator:
106
128
  session: CANSession with documented signals.
107
129
  output_path: Output DBC file path.
108
130
  min_confidence: Minimum confidence threshold (reserved for future use).
131
+
132
+ Example:
133
+ >>> from oscura.automotive.can.session import CANSession
134
+ >>> session = CANSession.from_file("capture.blf")
135
+ >>> # ... document signals ...
136
+ >>> DBCGenerator.generate_from_session(session, "output.dbc")
109
137
  """
110
138
  from oscura.automotive.can.discovery import (
111
139
  DiscoveryDocument,
@@ -152,5 +180,5 @@ class DBCGenerator:
152
180
  # Skip messages without documented signals
153
181
  pass
154
182
 
155
- # Generate DBC
183
+ # Generate DBC using main method
156
184
  DBCGenerator.generate(doc, output_path, min_confidence=0.0)
@@ -30,7 +30,7 @@ class DBCParser:
30
30
  FileNotFoundError: If DBC file doesn't exist.
31
31
  """
32
32
  try:
33
- import cantools # type: ignore[import-untyped]
33
+ import cantools
34
34
  except ImportError as e:
35
35
  raise ImportError(
36
36
  "cantools is required for DBC file support. "
@@ -58,7 +58,7 @@ class DBCParser:
58
58
  """
59
59
  # Get message definition from DBC
60
60
  try:
61
- msg_def = self.db.get_message_by_frame_id(message.arbitration_id) # type: ignore[union-attr]
61
+ msg_def = self.db.get_message_by_frame_id(message.arbitration_id)
62
62
  except KeyError as e:
63
63
  raise KeyError(f"Message ID 0x{message.arbitration_id:03X} not found in DBC") from e
64
64
 
@@ -70,7 +70,7 @@ class DBCParser:
70
70
 
71
71
  # Convert to DecodedSignal objects
72
72
  signals = {}
73
- for signal_name, value in decoded_data.items(): # type: ignore[union-attr]
73
+ for signal_name, value in decoded_data.items():
74
74
  # Get signal definition from DBC
75
75
  signal_def = msg_def.get_signal_by_name(signal_name)
76
76
 
@@ -94,7 +94,7 @@ class DBCParser:
94
94
  # Create DecodedSignal
95
95
  decoded_sig = DecodedSignal(
96
96
  name=signal_name,
97
- value=float(value), # type: ignore[arg-type]
97
+ value=float(value),
98
98
  unit=sig_def.unit,
99
99
  timestamp=message.timestamp,
100
100
  definition=sig_def,
@@ -110,7 +110,7 @@ class DBCParser:
110
110
  Returns:
111
111
  Set of CAN arbitration IDs.
112
112
  """
113
- return {msg.frame_id for msg in self.db.messages} # type: ignore[union-attr]
113
+ return {msg.frame_id for msg in self.db.messages}
114
114
 
115
115
  def get_message_name(self, arbitration_id: int) -> str | None:
116
116
  """Get message name from DBC.
@@ -122,7 +122,7 @@ class DBCParser:
122
122
  Message name or None if not found.
123
123
  """
124
124
  try:
125
- msg = self.db.get_message_by_frame_id(arbitration_id) # type: ignore[union-attr]
125
+ msg = self.db.get_message_by_frame_id(arbitration_id)
126
126
  return str(msg.name) # Explicit cast to str
127
127
  except KeyError:
128
128
  return None
@@ -266,12 +266,7 @@
266
266
  "category": "Powertrain",
267
267
  "severity": "High",
268
268
  "system": "Throttle Control",
269
- "possible_causes": [
270
- "TPS circuit shorted to voltage",
271
- "Faulty TPS sensor",
272
- "Wiring harness open",
273
- "ECM problem"
274
- ]
269
+ "possible_causes": ["TPS circuit shorted to voltage", "Faulty TPS sensor", "Wiring harness open", "ECM problem"]
275
270
  },
276
271
  "P0125": {
277
272
  "code": "P0125",
@@ -865,12 +860,7 @@
865
860
  "category": "Powertrain",
866
861
  "severity": "Medium",
867
862
  "system": "Emissions Control",
868
- "possible_causes": [
869
- "EGR valve stuck closed",
870
- "EGR passages clogged",
871
- "Faulty EGR valve",
872
- "Vacuum leak"
873
- ]
863
+ "possible_causes": ["EGR valve stuck closed", "EGR passages clogged", "Faulty EGR valve", "Vacuum leak"]
874
864
  },
875
865
  "P0401": {
876
866
  "code": "P0401",
@@ -891,12 +881,7 @@
891
881
  "category": "Powertrain",
892
882
  "severity": "Medium",
893
883
  "system": "Emissions Control",
894
- "possible_causes": [
895
- "EGR valve stuck open",
896
- "Faulty EGR valve",
897
- "EGR vacuum solenoid fault",
898
- "ECM problem"
899
- ]
884
+ "possible_causes": ["EGR valve stuck open", "Faulty EGR valve", "EGR vacuum solenoid fault", "ECM problem"]
900
885
  },
901
886
  "P0403": {
902
887
  "code": "P0403",
@@ -958,12 +943,7 @@
958
943
  "category": "Powertrain",
959
944
  "severity": "Low",
960
945
  "system": "Emissions Control",
961
- "possible_causes": [
962
- "Loose or missing fuel cap",
963
- "EVAP system leak",
964
- "Faulty purge valve",
965
- "Faulty vent valve"
966
- ]
946
+ "possible_causes": ["Loose or missing fuel cap", "EVAP system leak", "Faulty purge valve", "Faulty vent valve"]
967
947
  },
968
948
  "P0441": {
969
949
  "code": "P0441",
@@ -1075,12 +1055,7 @@
1075
1055
  "category": "Powertrain",
1076
1056
  "severity": "Low",
1077
1057
  "system": "Idle Control",
1078
- "possible_causes": [
1079
- "Vacuum leak",
1080
- "IAC valve fault",
1081
- "Dirty throttle body",
1082
- "PCV valve problem"
1083
- ]
1058
+ "possible_causes": ["Vacuum leak", "IAC valve fault", "Dirty throttle body", "PCV valve problem"]
1084
1059
  },
1085
1060
  "P0507": {
1086
1061
  "code": "P0507",
@@ -1088,12 +1063,7 @@
1088
1063
  "category": "Powertrain",
1089
1064
  "severity": "Low",
1090
1065
  "system": "Idle Control",
1091
- "possible_causes": [
1092
- "Vacuum leak",
1093
- "IAC valve stuck open",
1094
- "PCV valve stuck open",
1095
- "EVAP purge valve leaking"
1096
- ]
1066
+ "possible_causes": ["Vacuum leak", "IAC valve stuck open", "PCV valve stuck open", "EVAP purge valve leaking"]
1097
1067
  },
1098
1068
  "P0600": {
1099
1069
  "code": "P0600",
@@ -1127,12 +1097,7 @@
1127
1097
  "category": "Powertrain",
1128
1098
  "severity": "Critical",
1129
1099
  "system": "Engine Control Module",
1130
- "possible_causes": [
1131
- "ECM not programmed",
1132
- "ECM programming incomplete",
1133
- "Wrong software version",
1134
- "ECM fault"
1135
- ]
1100
+ "possible_causes": ["ECM not programmed", "ECM programming incomplete", "Wrong software version", "ECM fault"]
1136
1101
  },
1137
1102
  "P0603": {
1138
1103
  "code": "P0603",
@@ -1205,12 +1170,7 @@
1205
1170
  "category": "Powertrain",
1206
1171
  "severity": "Medium",
1207
1172
  "system": "Charging System",
1208
- "possible_causes": [
1209
- "Faulty alternator",
1210
- "Wiring harness problem",
1211
- "Poor electrical connection",
1212
- "ECM fault"
1213
- ]
1173
+ "possible_causes": ["Faulty alternator", "Wiring harness problem", "Poor electrical connection", "ECM fault"]
1214
1174
  },
1215
1175
  "P0625": {
1216
1176
  "code": "P0625",
@@ -1283,12 +1243,7 @@
1283
1243
  "category": "Powertrain",
1284
1244
  "severity": "High",
1285
1245
  "system": "Transmission",
1286
- "possible_causes": [
1287
- "Faulty input speed sensor",
1288
- "Wiring harness problem",
1289
- "Sensor reluctor damaged",
1290
- "TCM fault"
1291
- ]
1246
+ "possible_causes": ["Faulty input speed sensor", "Wiring harness problem", "Sensor reluctor damaged", "TCM fault"]
1292
1247
  },
1293
1248
  "P0720": {
1294
1249
  "code": "P0720",
@@ -1491,12 +1446,7 @@
1491
1446
  "category": "Chassis",
1492
1447
  "severity": "High",
1493
1448
  "system": "ABS",
1494
- "possible_causes": [
1495
- "Faulty valve relay",
1496
- "Relay circuit problem",
1497
- "ABS module fault",
1498
- "Wiring harness issue"
1499
- ]
1449
+ "possible_causes": ["Faulty valve relay", "Relay circuit problem", "ABS module fault", "Wiring harness issue"]
1500
1450
  },
1501
1451
  "C0161": {
1502
1452
  "code": "C0161",
@@ -2206,12 +2156,7 @@
2206
2156
  "category": "Body",
2207
2157
  "severity": "Low",
2208
2158
  "system": "Lighting System",
2209
- "possible_causes": [
2210
- "Burned out bulb",
2211
- "Wiring harness problem",
2212
- "Lamp socket corrosion",
2213
- "BCM fault"
2214
- ]
2159
+ "possible_causes": ["Burned out bulb", "Wiring harness problem", "Lamp socket corrosion", "BCM fault"]
2215
2160
  },
2216
2161
  "B0601": {
2217
2162
  "code": "B0601",
@@ -2232,12 +2177,7 @@
2232
2177
  "category": "Body",
2233
2178
  "severity": "Low",
2234
2179
  "system": "Lighting System",
2235
- "possible_causes": [
2236
- "Burned out turn signal bulb",
2237
- "Wiring harness problem",
2238
- "Flasher relay fault",
2239
- "BCM fault"
2240
- ]
2180
+ "possible_causes": ["Burned out turn signal bulb", "Wiring harness problem", "Flasher relay fault", "BCM fault"]
2241
2181
  },
2242
2182
  "B0603": {
2243
2183
  "code": "B0603",
@@ -2245,12 +2185,7 @@
2245
2185
  "category": "Body",
2246
2186
  "severity": "Low",
2247
2187
  "system": "Lighting System",
2248
- "possible_causes": [
2249
- "Burned out turn signal bulb",
2250
- "Wiring harness problem",
2251
- "Flasher relay fault",
2252
- "BCM fault"
2253
- ]
2188
+ "possible_causes": ["Burned out turn signal bulb", "Wiring harness problem", "Flasher relay fault", "BCM fault"]
2254
2189
  },
2255
2190
  "B0604": {
2256
2191
  "code": "B0604",
@@ -2362,12 +2297,7 @@
2362
2297
  "category": "Body",
2363
2298
  "severity": "Low",
2364
2299
  "system": "Keyless Entry",
2365
- "possible_causes": [
2366
- "Key fob battery weak",
2367
- "Key fob not synchronized",
2368
- "BCM fault",
2369
- "Receiver antenna fault"
2370
- ]
2300
+ "possible_causes": ["Key fob battery weak", "Key fob not synchronized", "BCM fault", "Receiver antenna fault"]
2371
2301
  },
2372
2302
  "B1300": {
2373
2303
  "code": "B1300",
@@ -2466,12 +2396,7 @@
2466
2396
  "category": "Network",
2467
2397
  "severity": "Critical",
2468
2398
  "system": "CAN Bus",
2469
- "possible_causes": [
2470
- "TCM not powered",
2471
- "CAN bus wiring problem",
2472
- "TCM internal fault",
2473
- "CAN bus short circuit"
2474
- ]
2399
+ "possible_causes": ["TCM not powered", "CAN bus wiring problem", "TCM internal fault", "CAN bus short circuit"]
2475
2400
  },
2476
2401
  "U0102": {
2477
2402
  "code": "U0102",
@@ -2544,12 +2469,7 @@
2544
2469
  "category": "Network",
2545
2470
  "severity": "High",
2546
2471
  "system": "CAN Bus",
2547
- "possible_causes": [
2548
- "BCM not powered",
2549
- "CAN bus wiring problem",
2550
- "BCM internal fault",
2551
- "Ground connection issue"
2552
- ]
2472
+ "possible_causes": ["BCM not powered", "CAN bus wiring problem", "BCM internal fault", "Ground connection issue"]
2553
2473
  },
2554
2474
  "U0141": {
2555
2475
  "code": "U0141",
@@ -2557,12 +2477,7 @@
2557
2477
  "category": "Network",
2558
2478
  "severity": "High",
2559
2479
  "system": "CAN Bus",
2560
- "possible_causes": [
2561
- "BCM not powered",
2562
- "CAN bus wiring problem",
2563
- "Module internal fault",
2564
- "Connector problem"
2565
- ]
2480
+ "possible_causes": ["BCM not powered", "CAN bus wiring problem", "Module internal fault", "Connector problem"]
2566
2481
  },
2567
2482
  "U0151": {
2568
2483
  "code": "U0151",
@@ -106,7 +106,7 @@ class DTCDatabase:
106
106
 
107
107
  Args:
108
108
  code: DTC code to look up (e.g., "P0420", "p0420")
109
- Case-insensitive
109
+ Case-insensitive, whitespace is stripped
110
110
 
111
111
  Returns:
112
112
  DTCInfo object if found, None if code not in database
@@ -117,7 +117,7 @@ class DTCDatabase:
117
117
  ... print(f"{info.code}: {info.description}")
118
118
  P0420: Catalyst System Efficiency Below Threshold (Bank 1)
119
119
  """
120
- return DTCS.get(code.upper())
120
+ return DTCS.get(code.strip().upper())
121
121
 
122
122
  @staticmethod
123
123
  def search(keyword: str) -> list[DTCInfo]:
@@ -0,0 +1,31 @@
1
+ """FlexRay automotive protocol analysis.
2
+
3
+ This module provides FlexRay-specific analysis tools including frame parsing,
4
+ CRC validation, signal decoding, and FIBEX format support.
5
+
6
+ Example:
7
+ >>> from oscura.automotive.flexray import FlexRayAnalyzer, FlexRaySignal
8
+ >>> analyzer = FlexRayAnalyzer()
9
+ >>> frame = analyzer.parse_frame(data, timestamp=0.0, channel="A")
10
+ >>> print(f"Slot {frame.header.frame_id}, CRC valid: {frame.crc_valid}")
11
+ """
12
+
13
+ from oscura.automotive.flexray.analyzer import (
14
+ FlexRayAnalyzer,
15
+ FlexRayFrame,
16
+ FlexRayHeader,
17
+ FlexRaySignal,
18
+ )
19
+ from oscura.automotive.flexray.crc import calculate_frame_crc, calculate_header_crc
20
+ from oscura.automotive.flexray.fibex import FIBEXExporter, FIBEXImporter
21
+
22
+ __all__ = [
23
+ "FIBEXExporter",
24
+ "FIBEXImporter",
25
+ "FlexRayAnalyzer",
26
+ "FlexRayFrame",
27
+ "FlexRayHeader",
28
+ "FlexRaySignal",
29
+ "calculate_frame_crc",
30
+ "calculate_header_crc",
31
+ ]