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
@@ -0,0 +1,449 @@
1
+ """FIBEX (FlexRay Interface Bus Exchange) format support.
2
+
3
+ This module implements FIBEX XML import and export for FlexRay network
4
+ configuration, frame definitions, and signal definitions.
5
+
6
+ References:
7
+ ASAM FIBEX 4.0.0 Specification
8
+ FlexRay Communications System Protocol Specification Version 3.0.1
9
+
10
+ Example:
11
+ >>> from oscura.automotive.flexray import FIBEXExporter, FlexRayAnalyzer
12
+ >>> analyzer = FlexRayAnalyzer()
13
+ >>> # ... parse frames and add signals ...
14
+ >>> exporter = FIBEXExporter(analyzer)
15
+ >>> exporter.export(Path("network.xml"))
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import xml.etree.ElementTree as ET
21
+ from pathlib import Path
22
+ from typing import TYPE_CHECKING, Any
23
+
24
+ if TYPE_CHECKING:
25
+ from oscura.automotive.flexray.analyzer import FlexRayAnalyzer, FlexRaySignal
26
+
27
+
28
+ class FIBEXExporter:
29
+ """FIBEX XML exporter for FlexRay networks.
30
+
31
+ Exports FlexRay network configuration as FIBEX 4.0 XML format.
32
+
33
+ Attributes:
34
+ analyzer: FlexRay analyzer with frames and signals.
35
+
36
+ Example:
37
+ >>> exporter = FIBEXExporter(analyzer)
38
+ >>> exporter.export(Path("flexray_network.xml"))
39
+ """
40
+
41
+ FIBEX_NAMESPACE = "http://www.asam.net/xml/fbx"
42
+ FIBEX_VERSION = "4.0.0"
43
+
44
+ def __init__(self, analyzer: FlexRayAnalyzer) -> None:
45
+ """Initialize FIBEX exporter.
46
+
47
+ Args:
48
+ analyzer: FlexRay analyzer containing parsed frames and signals.
49
+ """
50
+ self.analyzer = analyzer
51
+
52
+ def export(self, output_path: Path) -> None:
53
+ """Export FIBEX XML file.
54
+
55
+ Creates a FIBEX XML file containing:
56
+ - Project information
57
+ - Cluster configuration
58
+ - Frame definitions
59
+ - Signal definitions
60
+ - Coding information
61
+
62
+ Args:
63
+ output_path: Output file path for FIBEX XML.
64
+
65
+ Example:
66
+ >>> exporter.export(Path("output/flexray_network.xml"))
67
+ """
68
+ # Create root element
69
+ root = ET.Element("FIBEX")
70
+ root.set("xmlns", self.FIBEX_NAMESPACE)
71
+ root.set("VERSION", self.FIBEX_VERSION)
72
+
73
+ # Add project
74
+ project = ET.SubElement(root, "PROJECT")
75
+ project.set("ID", "FlexRay_Network")
76
+
77
+ project_name = ET.SubElement(project, "SHORT-NAME")
78
+ project_name.text = "FlexRay Network"
79
+
80
+ # Add cluster
81
+ clusters = ET.SubElement(project, "CLUSTERS")
82
+ cluster = ET.SubElement(clusters, "CLUSTER")
83
+ cluster.set("ID", "FlexRay_Cluster_1")
84
+
85
+ cluster_name = ET.SubElement(cluster, "SHORT-NAME")
86
+ cluster_name.text = "FlexRay_Cluster"
87
+
88
+ # Add cluster parameters
89
+ self._add_cluster_parameters(cluster)
90
+
91
+ # Add channels
92
+ self._add_channels(cluster)
93
+
94
+ # Add frames
95
+ self._add_frames(cluster)
96
+
97
+ # Add signals
98
+ self._add_signals(project)
99
+
100
+ # Write XML with pretty formatting
101
+ self._indent(root)
102
+ tree = ET.ElementTree(root)
103
+ tree.write(output_path, encoding="utf-8", xml_declaration=True)
104
+
105
+ def _add_cluster_parameters(self, cluster: ET.Element) -> None:
106
+ """Add cluster parameters to FIBEX.
107
+
108
+ Args:
109
+ cluster: Cluster XML element.
110
+ """
111
+ params = ET.SubElement(cluster, "CLUSTER-PARAMS")
112
+
113
+ # Get configuration
114
+ config = self.analyzer.cluster_config
115
+
116
+ # Speed
117
+ speed = ET.SubElement(params, "SPEED")
118
+ speed.text = "10000" # 10 Mbps
119
+
120
+ # Static slots
121
+ static_slots = ET.SubElement(params, "NUMBER-OF-STATIC-SLOTS")
122
+ static_slots.text = str(config.get("static_slot_count", 100))
123
+
124
+ # Dynamic slots
125
+ dynamic_slots = ET.SubElement(params, "NUMBER-OF-DYNAMIC-SLOTS")
126
+ dynamic_slots.text = str(config.get("dynamic_slot_count", 50))
127
+
128
+ # Cycle length
129
+ cycle_length = ET.SubElement(params, "CYCLE-LENGTH-IN-MACROTICKS")
130
+ cycle_length.text = str(config.get("cycle_length", 5000))
131
+
132
+ def _add_channels(self, cluster: ET.Element) -> None:
133
+ """Add channel definitions to FIBEX.
134
+
135
+ Args:
136
+ cluster: Cluster XML element.
137
+ """
138
+ channels = ET.SubElement(cluster, "CHANNELS")
139
+
140
+ # Get unique channels from frames
141
+ unique_channels = {frame.channel for frame in self.analyzer.frames}
142
+
143
+ for channel_id in sorted(unique_channels):
144
+ channel = ET.SubElement(channels, "CHANNEL")
145
+ channel.set("ID", f"Channel_{channel_id}")
146
+
147
+ channel_name = ET.SubElement(channel, "SHORT-NAME")
148
+ channel_name.text = f"Channel_{channel_id}"
149
+
150
+ def _add_frames(self, cluster: ET.Element) -> None:
151
+ """Add frame definitions to FIBEX.
152
+
153
+ Args:
154
+ cluster: Cluster XML element.
155
+ """
156
+ frames_elem = ET.SubElement(cluster, "FRAMES")
157
+
158
+ # Get unique frame IDs
159
+ unique_frame_ids = sorted({frame.header.frame_id for frame in self.analyzer.frames})
160
+
161
+ for frame_id in unique_frame_ids:
162
+ # Get representative frame for this ID
163
+ frame_example = next(f for f in self.analyzer.frames if f.header.frame_id == frame_id)
164
+
165
+ frame_elem = ET.SubElement(frames_elem, "FRAME")
166
+ frame_elem.set("ID", f"Frame_{frame_id}")
167
+
168
+ # Frame name
169
+ frame_name = ET.SubElement(frame_elem, "SHORT-NAME")
170
+ frame_name.text = f"Frame_{frame_id}"
171
+
172
+ # Slot ID
173
+ slot_id_elem = ET.SubElement(frame_elem, "SLOT-ID")
174
+ slot_id_elem.text = str(frame_id)
175
+
176
+ # Frame length
177
+ frame_length = ET.SubElement(frame_elem, "FRAME-LENGTH")
178
+ frame_length.text = str(frame_example.header.payload_length)
179
+
180
+ # Segment type
181
+ segment_type = ET.SubElement(frame_elem, "SEGMENT-TYPE")
182
+ segment_type.text = frame_example.segment_type.upper()
183
+
184
+ # Add signals in this frame
185
+ frame_signals = [s for s in self.analyzer.signals if s.frame_id == frame_id]
186
+ if frame_signals:
187
+ signals_elem = ET.SubElement(frame_elem, "SIGNALS")
188
+ for signal in frame_signals:
189
+ signal_ref = ET.SubElement(signals_elem, "SIGNAL-REF")
190
+ signal_ref.set("ID-REF", signal.name)
191
+
192
+ def _add_signals(self, project: ET.Element) -> None:
193
+ """Add signal definitions to FIBEX.
194
+
195
+ Args:
196
+ project: Project XML element.
197
+ """
198
+ if not self.analyzer.signals:
199
+ return
200
+
201
+ signals_elem = ET.SubElement(project, "SIGNALS")
202
+
203
+ for signal in self.analyzer.signals:
204
+ signal_elem = ET.SubElement(signals_elem, "SIGNAL")
205
+ signal_elem.set("ID", signal.name)
206
+
207
+ # Signal name
208
+ signal_name = ET.SubElement(signal_elem, "SHORT-NAME")
209
+ signal_name.text = signal.name
210
+
211
+ # Bit position
212
+ bit_position = ET.SubElement(signal_elem, "BIT-POSITION")
213
+ bit_position.text = str(signal.start_bit)
214
+
215
+ # Bit length
216
+ bit_length = ET.SubElement(signal_elem, "BIT-LENGTH")
217
+ bit_length.text = str(signal.bit_length)
218
+
219
+ # Byte order
220
+ byte_order = ET.SubElement(signal_elem, "BYTE-ORDER")
221
+ byte_order.text = "BIG-ENDIAN" if signal.byte_order == "big_endian" else "LITTLE-ENDIAN"
222
+
223
+ # Coding
224
+ coding = ET.SubElement(signal_elem, "CODING")
225
+
226
+ # Factor
227
+ factor_elem = ET.SubElement(coding, "FACTOR")
228
+ factor_elem.text = str(signal.factor)
229
+
230
+ # Offset
231
+ offset_elem = ET.SubElement(coding, "OFFSET")
232
+ offset_elem.text = str(signal.offset)
233
+
234
+ # Unit
235
+ if signal.unit:
236
+ unit_elem = ET.SubElement(coding, "UNIT")
237
+ unit_elem.text = signal.unit
238
+
239
+ def _indent(self, elem: ET.Element, level: int = 0) -> None:
240
+ """Add pretty-printing indentation to XML tree.
241
+
242
+ Args:
243
+ elem: XML element to indent.
244
+ level: Current indentation level.
245
+ """
246
+ indent = " "
247
+ i = "\n" + level * indent
248
+ if len(elem):
249
+ if not elem.text or not elem.text.strip():
250
+ elem.text = i + indent
251
+ if not elem.tail or not elem.tail.strip():
252
+ elem.tail = i
253
+ for child in elem:
254
+ self._indent(child, level + 1)
255
+ if elem and (not elem[-1].tail or not elem[-1].tail.strip()):
256
+ elem[-1].tail = i
257
+ else:
258
+ if level and (not elem.tail or not elem.tail.strip()):
259
+ elem.tail = i
260
+
261
+
262
+ class FIBEXImporter:
263
+ """FIBEX XML importer for FlexRay networks.
264
+
265
+ Imports FlexRay network configuration from FIBEX 4.0 XML format.
266
+
267
+ Example:
268
+ >>> importer = FIBEXImporter()
269
+ >>> cluster_config, signals = importer.load(Path("network.xml"))
270
+ >>> analyzer = FlexRayAnalyzer(cluster_config=cluster_config)
271
+ >>> for signal in signals:
272
+ ... analyzer.add_signal(signal)
273
+ """
274
+
275
+ def __init__(self) -> None:
276
+ """Initialize FIBEX importer."""
277
+
278
+ def load(self, fibex_path: Path) -> tuple[dict[str, Any], list[FlexRaySignal]]:
279
+ """Load FIBEX XML file.
280
+
281
+ Args:
282
+ fibex_path: Path to FIBEX XML file.
283
+
284
+ Returns:
285
+ Tuple of (cluster_config, signals) where:
286
+ - cluster_config: Dictionary with cluster parameters
287
+ - signals: List of FlexRaySignal definitions
288
+
289
+ Raises:
290
+ FileNotFoundError: If FIBEX file not found.
291
+ ValueError: If FIBEX file is invalid.
292
+
293
+ Example:
294
+ >>> config, signals = importer.load(Path("flexray_network.xml"))
295
+ >>> print(f"Loaded {len(signals)} signals")
296
+ """
297
+ # Import here to avoid circular dependency
298
+
299
+ if not fibex_path.exists():
300
+ raise FileNotFoundError(f"FIBEX file not found: {fibex_path}")
301
+
302
+ tree = ET.parse(fibex_path)
303
+ root = tree.getroot()
304
+
305
+ # Extract cluster configuration
306
+ cluster_config = self._parse_cluster_config(root)
307
+
308
+ # Extract signal definitions
309
+ signals = self._parse_signals(root)
310
+
311
+ return cluster_config, signals
312
+
313
+ def _parse_cluster_config(self, root: ET.Element) -> dict[str, Any]:
314
+ """Parse cluster configuration from FIBEX.
315
+
316
+ Args:
317
+ root: FIBEX root element.
318
+
319
+ Returns:
320
+ Cluster configuration dictionary.
321
+ """
322
+ config: dict[str, Any] = {}
323
+
324
+ # Find cluster parameters
325
+ cluster_params = root.find(".//{*}CLUSTER-PARAMS")
326
+ if cluster_params is not None:
327
+ # Static slots
328
+ static_slots = cluster_params.find("{*}NUMBER-OF-STATIC-SLOTS")
329
+ if static_slots is not None and static_slots.text:
330
+ config["static_slot_count"] = int(static_slots.text)
331
+
332
+ # Dynamic slots
333
+ dynamic_slots = cluster_params.find("{*}NUMBER-OF-DYNAMIC-SLOTS")
334
+ if dynamic_slots is not None and dynamic_slots.text:
335
+ config["dynamic_slot_count"] = int(dynamic_slots.text)
336
+
337
+ # Cycle length
338
+ cycle_length = cluster_params.find("{*}CYCLE-LENGTH-IN-MACROTICKS")
339
+ if cycle_length is not None and cycle_length.text:
340
+ config["cycle_length"] = int(cycle_length.text)
341
+
342
+ return config
343
+
344
+ def _parse_signals(self, root: ET.Element) -> list[FlexRaySignal]:
345
+ """Parse signal definitions from FIBEX.
346
+
347
+ Args:
348
+ root: FIBEX root element.
349
+
350
+ Returns:
351
+ List of FlexRay signal definitions.
352
+ """
353
+ # Import here to avoid circular dependency
354
+ from oscura.automotive.flexray.analyzer import FlexRaySignal
355
+
356
+ signals: list[FlexRaySignal] = []
357
+
358
+ # Find all signal elements
359
+ for signal_elem in root.findall(".//{*}SIGNAL"):
360
+ signal_id = signal_elem.get("ID", "")
361
+
362
+ # Signal name
363
+ name_elem = signal_elem.find("{*}SHORT-NAME")
364
+ name = name_elem.text if name_elem is not None and name_elem.text else signal_id
365
+
366
+ # Bit position
367
+ bit_pos_elem = signal_elem.find("{*}BIT-POSITION")
368
+ start_bit = (
369
+ int(bit_pos_elem.text) if bit_pos_elem is not None and bit_pos_elem.text else 0
370
+ )
371
+
372
+ # Bit length
373
+ bit_len_elem = signal_elem.find("{*}BIT-LENGTH")
374
+ bit_length = (
375
+ int(bit_len_elem.text) if bit_len_elem is not None and bit_len_elem.text else 8
376
+ )
377
+
378
+ # Byte order
379
+ byte_order_elem = signal_elem.find("{*}BYTE-ORDER")
380
+ byte_order = "big_endian"
381
+ if byte_order_elem is not None and byte_order_elem.text:
382
+ byte_order = (
383
+ "big_endian" if byte_order_elem.text == "BIG-ENDIAN" else "little_endian"
384
+ )
385
+
386
+ # Coding
387
+ coding_elem = signal_elem.find("{*}CODING")
388
+ factor = 1.0
389
+ offset = 0.0
390
+ unit = ""
391
+
392
+ if coding_elem is not None:
393
+ factor_elem = coding_elem.find("{*}FACTOR")
394
+ if factor_elem is not None and factor_elem.text:
395
+ factor = float(factor_elem.text)
396
+
397
+ offset_elem = coding_elem.find("{*}OFFSET")
398
+ if offset_elem is not None and offset_elem.text:
399
+ offset = float(offset_elem.text)
400
+
401
+ unit_elem = coding_elem.find("{*}UNIT")
402
+ if unit_elem is not None and unit_elem.text:
403
+ unit = unit_elem.text
404
+
405
+ # Find frame ID (need to search for frame containing this signal)
406
+ frame_id = self._find_frame_id_for_signal(root, signal_id)
407
+
408
+ signal = FlexRaySignal(
409
+ name=name,
410
+ frame_id=frame_id,
411
+ start_bit=start_bit,
412
+ bit_length=bit_length,
413
+ byte_order=byte_order,
414
+ factor=factor,
415
+ offset=offset,
416
+ unit=unit,
417
+ )
418
+
419
+ signals.append(signal)
420
+
421
+ return signals
422
+
423
+ def _find_frame_id_for_signal(self, root: ET.Element, signal_id: str) -> int:
424
+ """Find frame ID containing a signal.
425
+
426
+ Args:
427
+ root: FIBEX root element.
428
+ signal_id: Signal ID to find.
429
+
430
+ Returns:
431
+ Frame ID (slot ID) containing the signal, or 0 if not found.
432
+ """
433
+ # Find frame containing this signal reference
434
+ for frame_elem in root.findall(".//{*}FRAME"):
435
+ signal_refs = frame_elem.findall(".//{*}SIGNAL-REF")
436
+ for sig_ref in signal_refs:
437
+ if sig_ref.get("ID-REF") == signal_id:
438
+ # Found frame, get slot ID
439
+ slot_id_elem = frame_elem.find("{*}SLOT-ID")
440
+ if slot_id_elem is not None and slot_id_elem.text:
441
+ return int(slot_id_elem.text)
442
+
443
+ return 0 # Default if not found
444
+
445
+
446
+ __all__ = [
447
+ "FIBEXExporter",
448
+ "FIBEXImporter",
449
+ ]
@@ -1,12 +1,49 @@
1
- """J1939 heavy-duty vehicle protocol support.
1
+ """J1939 (SAE J1939) protocol support for heavy-duty vehicles.
2
2
 
3
- This module provides J1939 protocol decoding for heavy-duty vehicles
4
- (trucks, buses, agriculture, marine).
3
+ This module provides comprehensive J1939 protocol analysis including:
4
+ - Message decoding and PGN extraction
5
+ - Transport protocol (TP.CM, TP.DT, BAM) multi-packet reassembly
6
+ - Suspect Parameter Number (SPN) decoding
7
+ - Standard SPN definitions
8
+
9
+ Example:
10
+ >>> from oscura.automotive.j1939 import J1939Analyzer, J1939SPN
11
+ >>> analyzer = J1939Analyzer()
12
+ >>> msg = analyzer.parse_message(0x0CF00400, b'\\xff' * 8)
13
+ >>> print(msg.identifier.pgn)
14
+ 61444
5
15
  """
6
16
 
7
- __all__ = ["J1939Decoder", "J1939Message", "extract_pgn"]
17
+ from oscura.automotive.j1939.analyzer import (
18
+ J1939SPN,
19
+ J1939Analyzer,
20
+ J1939Identifier,
21
+ J1939Message,
22
+ )
23
+ from oscura.automotive.j1939.decoder import (
24
+ J1939Decoder,
25
+ extract_pgn,
26
+ )
27
+ from oscura.automotive.j1939.decoder import (
28
+ J1939Message as DecoderMessage,
29
+ )
30
+ from oscura.automotive.j1939.spns import STANDARD_SPNS, get_standard_spns
31
+ from oscura.automotive.j1939.transport import TransportProtocol, TransportSession
8
32
 
9
- try:
10
- from oscura.automotive.j1939.decoder import J1939Decoder, J1939Message, extract_pgn
11
- except ImportError:
12
- pass
33
+ __all__ = [
34
+ "J1939SPN",
35
+ # SPN definitions
36
+ "STANDARD_SPNS",
37
+ "DecoderMessage",
38
+ # Analyzer (new comprehensive analyzer)
39
+ "J1939Analyzer",
40
+ # Decoder (legacy decoder)
41
+ "J1939Decoder",
42
+ "J1939Identifier",
43
+ "J1939Message",
44
+ # Transport protocol
45
+ "TransportProtocol",
46
+ "TransportSession",
47
+ "extract_pgn",
48
+ "get_standard_spns",
49
+ ]