oscura 0.8.0__py3-none-any.whl → 0.11.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.
- oscura/__init__.py +19 -19
- oscura/__main__.py +4 -0
- oscura/analyzers/__init__.py +2 -0
- oscura/analyzers/digital/extraction.py +2 -3
- oscura/analyzers/digital/quality.py +1 -1
- oscura/analyzers/digital/timing.py +1 -1
- oscura/analyzers/ml/signal_classifier.py +6 -0
- oscura/analyzers/patterns/__init__.py +66 -0
- oscura/analyzers/power/basic.py +3 -3
- oscura/analyzers/power/soa.py +1 -1
- oscura/analyzers/power/switching.py +3 -3
- oscura/analyzers/signal_classification.py +529 -0
- oscura/analyzers/signal_integrity/sparams.py +3 -3
- oscura/analyzers/statistics/basic.py +10 -7
- oscura/analyzers/validation.py +1 -1
- oscura/analyzers/waveform/measurements.py +200 -156
- oscura/analyzers/waveform/measurements_with_uncertainty.py +91 -35
- oscura/analyzers/waveform/spectral.py +182 -84
- oscura/api/dsl/commands.py +15 -6
- oscura/api/server/templates/base.html +137 -146
- oscura/api/server/templates/export.html +84 -110
- oscura/api/server/templates/home.html +248 -267
- oscura/api/server/templates/protocols.html +44 -48
- oscura/api/server/templates/reports.html +27 -35
- oscura/api/server/templates/session_detail.html +68 -78
- oscura/api/server/templates/sessions.html +62 -72
- oscura/api/server/templates/waveforms.html +54 -64
- oscura/automotive/__init__.py +1 -1
- oscura/automotive/can/session.py +1 -1
- oscura/automotive/dbc/generator.py +638 -23
- oscura/automotive/dtc/data.json +17 -102
- oscura/automotive/flexray/fibex.py +9 -1
- oscura/automotive/uds/decoder.py +99 -6
- oscura/cli/analyze.py +8 -2
- oscura/cli/batch.py +36 -5
- oscura/cli/characterize.py +18 -4
- oscura/cli/export.py +47 -5
- oscura/cli/main.py +2 -0
- oscura/cli/onboarding/wizard.py +10 -6
- oscura/cli/pipeline.py +585 -0
- oscura/cli/visualize.py +6 -4
- oscura/convenience.py +400 -32
- oscura/core/measurement_result.py +286 -0
- oscura/core/progress.py +1 -1
- oscura/core/schemas/device_mapping.json +2 -8
- oscura/core/schemas/packet_format.json +4 -24
- oscura/core/schemas/protocol_definition.json +2 -12
- oscura/core/types.py +232 -239
- oscura/correlation/multi_protocol.py +1 -1
- oscura/export/legacy/__init__.py +11 -0
- oscura/export/legacy/wav.py +75 -0
- oscura/exporters/__init__.py +19 -0
- oscura/exporters/wireshark.py +809 -0
- oscura/hardware/acquisition/file.py +5 -19
- oscura/hardware/acquisition/saleae.py +10 -10
- oscura/hardware/acquisition/socketcan.py +4 -6
- oscura/hardware/acquisition/synthetic.py +1 -5
- oscura/hardware/acquisition/visa.py +6 -6
- oscura/hardware/security/side_channel_detector.py +5 -508
- oscura/inference/message_format.py +686 -1
- oscura/jupyter/display.py +2 -2
- oscura/jupyter/magic.py +3 -3
- oscura/loaders/__init__.py +17 -12
- oscura/loaders/binary.py +1 -1
- oscura/loaders/chipwhisperer.py +1 -2
- oscura/loaders/configurable.py +1 -1
- oscura/loaders/csv_loader.py +2 -2
- oscura/loaders/hdf5_loader.py +1 -1
- oscura/loaders/lazy.py +6 -1
- oscura/loaders/mmap_loader.py +0 -1
- oscura/loaders/numpy_loader.py +8 -7
- oscura/loaders/preprocessing.py +3 -5
- oscura/loaders/rigol.py +21 -7
- oscura/loaders/sigrok.py +2 -5
- oscura/loaders/tdms.py +3 -2
- oscura/loaders/tektronix.py +38 -32
- oscura/loaders/tss.py +20 -27
- oscura/loaders/validation.py +17 -10
- oscura/loaders/vcd.py +13 -8
- oscura/loaders/wav.py +1 -6
- oscura/pipeline/__init__.py +76 -0
- oscura/pipeline/handlers/__init__.py +165 -0
- oscura/pipeline/handlers/analyzers.py +1045 -0
- oscura/pipeline/handlers/decoders.py +899 -0
- oscura/pipeline/handlers/exporters.py +1103 -0
- oscura/pipeline/handlers/filters.py +891 -0
- oscura/pipeline/handlers/loaders.py +640 -0
- oscura/pipeline/handlers/transforms.py +768 -0
- oscura/reporting/formatting/measurements.py +55 -14
- oscura/reporting/templates/enhanced/protocol_re.html +504 -503
- oscura/sessions/legacy.py +49 -1
- oscura/side_channel/__init__.py +38 -57
- oscura/utils/builders/signal_builder.py +5 -5
- oscura/utils/comparison/compare.py +7 -9
- oscura/utils/comparison/golden.py +1 -1
- oscura/utils/filtering/convenience.py +2 -2
- oscura/utils/math/arithmetic.py +38 -62
- oscura/utils/math/interpolation.py +20 -20
- oscura/utils/pipeline/__init__.py +4 -17
- oscura/utils/progressive.py +1 -4
- oscura/utils/triggering/edge.py +1 -1
- oscura/utils/triggering/pattern.py +2 -2
- oscura/utils/triggering/pulse.py +2 -2
- oscura/utils/triggering/window.py +3 -3
- oscura/validation/hil_testing.py +11 -11
- oscura/visualization/__init__.py +46 -284
- oscura/visualization/batch.py +72 -433
- oscura/visualization/plot.py +542 -53
- oscura/visualization/styles.py +184 -318
- oscura/workflows/batch/advanced.py +1 -1
- oscura/workflows/batch/aggregate.py +12 -9
- oscura/workflows/complete_re.py +251 -23
- oscura/workflows/digital.py +27 -4
- oscura/workflows/multi_trace.py +136 -17
- oscura/workflows/waveform.py +11 -6
- oscura-0.11.0.dist-info/METADATA +460 -0
- {oscura-0.8.0.dist-info → oscura-0.11.0.dist-info}/RECORD +120 -145
- oscura/side_channel/dpa.py +0 -1025
- oscura/utils/optimization/__init__.py +0 -19
- oscura/utils/optimization/parallel.py +0 -443
- oscura/utils/optimization/search.py +0 -532
- oscura/utils/pipeline/base.py +0 -338
- oscura/utils/pipeline/composition.py +0 -248
- oscura/utils/pipeline/parallel.py +0 -449
- oscura/utils/pipeline/pipeline.py +0 -375
- oscura/utils/search/__init__.py +0 -16
- oscura/utils/search/anomaly.py +0 -424
- oscura/utils/search/context.py +0 -294
- oscura/utils/search/pattern.py +0 -288
- oscura/utils/storage/__init__.py +0 -61
- oscura/utils/storage/database.py +0 -1166
- oscura/visualization/accessibility.py +0 -526
- oscura/visualization/annotations.py +0 -371
- oscura/visualization/axis_scaling.py +0 -305
- oscura/visualization/colors.py +0 -451
- oscura/visualization/digital.py +0 -436
- oscura/visualization/eye.py +0 -571
- oscura/visualization/histogram.py +0 -281
- oscura/visualization/interactive.py +0 -1035
- oscura/visualization/jitter.py +0 -1042
- oscura/visualization/keyboard.py +0 -394
- oscura/visualization/layout.py +0 -400
- oscura/visualization/optimization.py +0 -1079
- oscura/visualization/palettes.py +0 -446
- oscura/visualization/power.py +0 -508
- oscura/visualization/power_extended.py +0 -955
- oscura/visualization/presets.py +0 -469
- oscura/visualization/protocols.py +0 -1246
- oscura/visualization/render.py +0 -223
- oscura/visualization/rendering.py +0 -444
- oscura/visualization/reverse_engineering.py +0 -838
- oscura/visualization/signal_integrity.py +0 -989
- oscura/visualization/specialized.py +0 -643
- oscura/visualization/spectral.py +0 -1226
- oscura/visualization/thumbnails.py +0 -340
- oscura/visualization/time_axis.py +0 -351
- oscura/visualization/waveform.py +0 -454
- oscura-0.8.0.dist-info/METADATA +0 -661
- {oscura-0.8.0.dist-info → oscura-0.11.0.dist-info}/WHEEL +0 -0
- {oscura-0.8.0.dist-info → oscura-0.11.0.dist-info}/entry_points.txt +0 -0
- {oscura-0.8.0.dist-info → oscura-0.11.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -35,7 +35,7 @@ def interpolate(
|
|
|
35
35
|
*,
|
|
36
36
|
method: Literal["linear", "cubic", "nearest", "zero"] = "linear",
|
|
37
37
|
fill_value: float | tuple[float, float] = np.nan,
|
|
38
|
-
|
|
38
|
+
channel: str | None = None,
|
|
39
39
|
) -> WaveformTrace:
|
|
40
40
|
"""Interpolate trace to new time points.
|
|
41
41
|
|
|
@@ -47,7 +47,7 @@ def interpolate(
|
|
|
47
47
|
new_time: New time points in seconds.
|
|
48
48
|
method: Interpolation method ("linear", "cubic", "nearest", "zero").
|
|
49
49
|
fill_value: Value for points outside original range.
|
|
50
|
-
|
|
50
|
+
channel: Name for the result trace (optional).
|
|
51
51
|
|
|
52
52
|
Returns:
|
|
53
53
|
Interpolated WaveformTrace at new time points.
|
|
@@ -70,13 +70,13 @@ def interpolate(
|
|
|
70
70
|
|
|
71
71
|
# Create interpolator and interpolate
|
|
72
72
|
interp_func = _create_interpolator(
|
|
73
|
-
trace.
|
|
73
|
+
trace.time, trace.data.astype(np.float64), method, fill_value
|
|
74
74
|
)
|
|
75
75
|
result_data = interp_func(new_time)
|
|
76
76
|
|
|
77
77
|
# Build result trace
|
|
78
78
|
new_sample_rate = _calculate_new_sample_rate(new_time, trace.metadata.sample_rate)
|
|
79
|
-
new_metadata = _create_interpolated_metadata(trace, new_sample_rate,
|
|
79
|
+
new_metadata = _create_interpolated_metadata(trace, new_sample_rate, channel)
|
|
80
80
|
|
|
81
81
|
return WaveformTrace(data=result_data.astype(np.float64), metadata=new_metadata)
|
|
82
82
|
|
|
@@ -107,7 +107,7 @@ def _calculate_new_sample_rate(new_time: NDArray[np.float64], original_sample_ra
|
|
|
107
107
|
|
|
108
108
|
|
|
109
109
|
def _create_interpolated_metadata(
|
|
110
|
-
trace: WaveformTrace, new_sample_rate: float,
|
|
110
|
+
trace: WaveformTrace, new_sample_rate: float, channel: str | None
|
|
111
111
|
) -> TraceMetadata:
|
|
112
112
|
"""Create metadata for interpolated trace."""
|
|
113
113
|
return TraceMetadata(
|
|
@@ -117,7 +117,7 @@ def _create_interpolated_metadata(
|
|
|
117
117
|
acquisition_time=trace.metadata.acquisition_time,
|
|
118
118
|
trigger_info=trace.metadata.trigger_info,
|
|
119
119
|
source_file=trace.metadata.source_file,
|
|
120
|
-
|
|
120
|
+
channel=channel or f"{trace.metadata.channel or 'trace'}_interp",
|
|
121
121
|
)
|
|
122
122
|
|
|
123
123
|
|
|
@@ -214,7 +214,7 @@ def resample(
|
|
|
214
214
|
num_samples: int | None = None,
|
|
215
215
|
method: Literal["fft", "polyphase", "interp"] = "fft",
|
|
216
216
|
anti_alias: bool = True,
|
|
217
|
-
|
|
217
|
+
channel: str | None = None,
|
|
218
218
|
) -> WaveformTrace:
|
|
219
219
|
"""Resample trace to new sample rate or number of samples.
|
|
220
220
|
|
|
@@ -232,7 +232,7 @@ def resample(
|
|
|
232
232
|
- "polyphase": Polyphase filter resampling (efficient)
|
|
233
233
|
- "interp": Linear interpolation (fastest)
|
|
234
234
|
anti_alias: Apply anti-aliasing filter before downsampling.
|
|
235
|
-
|
|
235
|
+
channel: Name for the result trace (optional).
|
|
236
236
|
|
|
237
237
|
Returns:
|
|
238
238
|
Resampled WaveformTrace.
|
|
@@ -293,7 +293,7 @@ def resample(
|
|
|
293
293
|
acquisition_time=trace.metadata.acquisition_time,
|
|
294
294
|
trigger_info=trace.metadata.trigger_info,
|
|
295
295
|
source_file=trace.metadata.source_file,
|
|
296
|
-
|
|
296
|
+
channel=channel or f"{trace.metadata.channel or 'trace'}_resampled",
|
|
297
297
|
)
|
|
298
298
|
|
|
299
299
|
return WaveformTrace(data=result_data.astype(np.float64), metadata=new_metadata)
|
|
@@ -305,7 +305,7 @@ def align_traces(
|
|
|
305
305
|
*,
|
|
306
306
|
method: Literal["interpolate", "resample"] = "interpolate",
|
|
307
307
|
reference: Literal["first", "second", "higher"] = "higher",
|
|
308
|
-
|
|
308
|
+
channels: tuple[str | None, str | None] | None = None,
|
|
309
309
|
) -> tuple[WaveformTrace, WaveformTrace]:
|
|
310
310
|
"""Align two traces to have the same sample rate and length.
|
|
311
311
|
|
|
@@ -322,7 +322,7 @@ def align_traces(
|
|
|
322
322
|
- "first": Use trace1's sample rate
|
|
323
323
|
- "second": Use trace2's sample rate
|
|
324
324
|
- "higher": Use the higher sample rate (default)
|
|
325
|
-
|
|
325
|
+
channels: Optional names for the aligned traces.
|
|
326
326
|
|
|
327
327
|
Returns:
|
|
328
328
|
Tuple of (aligned_trace1, aligned_trace2) with matching parameters.
|
|
@@ -353,17 +353,17 @@ def align_traces(
|
|
|
353
353
|
# Create common time vector
|
|
354
354
|
common_time = np.arange(num_samples) / target_rate
|
|
355
355
|
|
|
356
|
-
name1 =
|
|
357
|
-
name2 =
|
|
356
|
+
name1 = channels[0] if channels else None
|
|
357
|
+
name2 = channels[1] if channels else None
|
|
358
358
|
|
|
359
359
|
if method == "interpolate":
|
|
360
360
|
# Interpolate both traces to common time points
|
|
361
|
-
aligned1 = interpolate(trace1, common_time,
|
|
362
|
-
aligned2 = interpolate(trace2, common_time,
|
|
361
|
+
aligned1 = interpolate(trace1, common_time, channel=name1)
|
|
362
|
+
aligned2 = interpolate(trace2, common_time, channel=name2)
|
|
363
363
|
else: # "resample"
|
|
364
364
|
# Resample both to common rate
|
|
365
|
-
aligned1 = resample(trace1, num_samples=num_samples,
|
|
366
|
-
aligned2 = resample(trace2, num_samples=num_samples,
|
|
365
|
+
aligned1 = resample(trace1, num_samples=num_samples, channel=name1)
|
|
366
|
+
aligned2 = resample(trace2, num_samples=num_samples, channel=name2)
|
|
367
367
|
|
|
368
368
|
return aligned1, aligned2
|
|
369
369
|
|
|
@@ -374,7 +374,7 @@ def downsample(
|
|
|
374
374
|
*,
|
|
375
375
|
anti_alias: bool = True,
|
|
376
376
|
method: Literal["decimate", "average", "max", "min"] = "decimate",
|
|
377
|
-
|
|
377
|
+
channel: str | None = None,
|
|
378
378
|
) -> WaveformTrace:
|
|
379
379
|
"""Downsample trace by an integer factor.
|
|
380
380
|
|
|
@@ -390,7 +390,7 @@ def downsample(
|
|
|
390
390
|
- "average": Average every N samples
|
|
391
391
|
- "max": Maximum of every N samples
|
|
392
392
|
- "min": Minimum of every N samples
|
|
393
|
-
|
|
393
|
+
channel: Name for the result trace (optional).
|
|
394
394
|
|
|
395
395
|
Returns:
|
|
396
396
|
Downsampled WaveformTrace.
|
|
@@ -440,7 +440,7 @@ def downsample(
|
|
|
440
440
|
acquisition_time=trace.metadata.acquisition_time,
|
|
441
441
|
trigger_info=trace.metadata.trigger_info,
|
|
442
442
|
source_file=trace.metadata.source_file,
|
|
443
|
-
|
|
443
|
+
channel=channel or f"{trace.metadata.channel or 'trace'}_ds{factor}",
|
|
444
444
|
)
|
|
445
445
|
|
|
446
446
|
return WaveformTrace(data=result_data, metadata=new_metadata)
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Reverse engineering pipeline for protocol analysis.
|
|
2
2
|
|
|
3
|
-
This package provides
|
|
4
|
-
|
|
3
|
+
This package provides the REPipeline for automated protocol reverse engineering
|
|
4
|
+
from captured traces, including flow extraction, payload analysis, field inference,
|
|
5
|
+
and protocol structure discovery.
|
|
5
6
|
|
|
6
7
|
- RE-INT-001: RE Pipeline Integration
|
|
7
8
|
"""
|
|
8
9
|
|
|
9
|
-
from .base import TraceTransformer
|
|
10
|
-
from .composition import Composable, compose, curry, make_composable, pipe
|
|
11
|
-
from .pipeline import Pipeline
|
|
12
|
-
|
|
13
10
|
# RE-INT-001: Reverse Engineering Pipeline
|
|
14
11
|
from .reverse_engineering import (
|
|
15
12
|
FlowInfo,
|
|
@@ -22,22 +19,12 @@ from .reverse_engineering import (
|
|
|
22
19
|
)
|
|
23
20
|
|
|
24
21
|
__all__ = [
|
|
25
|
-
"Composable",
|
|
26
22
|
# RE-INT-001: Reverse Engineering Pipeline
|
|
27
23
|
"FlowInfo",
|
|
28
24
|
"MessageTypeInfo",
|
|
29
|
-
# Pipeline
|
|
30
|
-
"Pipeline",
|
|
31
25
|
"ProtocolCandidate",
|
|
32
26
|
"REAnalysisResult",
|
|
33
27
|
"REPipeline",
|
|
34
28
|
"StageResult",
|
|
35
|
-
# Base classes
|
|
36
|
-
"TraceTransformer",
|
|
37
29
|
"analyze",
|
|
38
|
-
# Composition
|
|
39
|
-
"compose",
|
|
40
|
-
"curry",
|
|
41
|
-
"make_composable",
|
|
42
|
-
"pipe",
|
|
43
30
|
]
|
oscura/utils/progressive.py
CHANGED
|
@@ -242,10 +242,7 @@ def analyze_roi(
|
|
|
242
242
|
sample_rate=trace.metadata.sample_rate,
|
|
243
243
|
vertical_scale=trace.metadata.vertical_scale,
|
|
244
244
|
vertical_offset=trace.metadata.vertical_offset,
|
|
245
|
-
|
|
246
|
-
trigger_info=trace.metadata.trigger_info,
|
|
247
|
-
source_file=trace.metadata.source_file,
|
|
248
|
-
channel_name=getattr(trace.metadata, "channel_name", None),
|
|
245
|
+
channel=trace.metadata.channel,
|
|
249
246
|
),
|
|
250
247
|
)
|
|
251
248
|
|
oscura/utils/triggering/edge.py
CHANGED
|
@@ -91,7 +91,7 @@ class PatternTrigger(Trigger):
|
|
|
91
91
|
level = self._get_level(trace)
|
|
92
92
|
digital = trace.data >= level
|
|
93
93
|
|
|
94
|
-
sample_period = trace.metadata.
|
|
94
|
+
sample_period = 1.0 / trace.metadata.sample_rate
|
|
95
95
|
events: list[TriggerEvent] = []
|
|
96
96
|
|
|
97
97
|
if self.match_type == "sequence":
|
|
@@ -240,7 +240,7 @@ class MultiChannelPatternTrigger(Trigger):
|
|
|
240
240
|
digitals.append(trace.data >= level)
|
|
241
241
|
|
|
242
242
|
# Find samples where all channels match pattern
|
|
243
|
-
sample_period = traces[0].metadata.
|
|
243
|
+
sample_period = 1.0 / traces[0].metadata.sample_rate
|
|
244
244
|
n_samples = min(len(d) for d in digitals)
|
|
245
245
|
events: list[TriggerEvent] = []
|
|
246
246
|
|
oscura/utils/triggering/pulse.py
CHANGED
|
@@ -142,7 +142,7 @@ class PulseWidthTrigger(Trigger):
|
|
|
142
142
|
data = trace.data
|
|
143
143
|
level = self.level
|
|
144
144
|
|
|
145
|
-
sample_period = trace.metadata.
|
|
145
|
+
sample_period = 1.0 / trace.metadata.sample_rate
|
|
146
146
|
pulses: list[PulseInfo] = []
|
|
147
147
|
|
|
148
148
|
# Find all threshold crossings
|
|
@@ -419,7 +419,7 @@ class RuntTrigger(Trigger):
|
|
|
419
419
|
return []
|
|
420
420
|
|
|
421
421
|
data = trace.data
|
|
422
|
-
sample_period = trace.metadata.
|
|
422
|
+
sample_period = 1.0 / trace.metadata.sample_rate
|
|
423
423
|
events: list[TriggerEvent] = []
|
|
424
424
|
|
|
425
425
|
zones = np.array([self._get_zone(v) for v in data])
|
|
@@ -97,7 +97,7 @@ class WindowTrigger(Trigger):
|
|
|
97
97
|
List of trigger events for window crossings.
|
|
98
98
|
"""
|
|
99
99
|
data = trace.data
|
|
100
|
-
sample_period = trace.metadata.
|
|
100
|
+
sample_period = 1.0 / trace.metadata.sample_rate
|
|
101
101
|
events: list[TriggerEvent] = []
|
|
102
102
|
|
|
103
103
|
# Determine if each sample is inside the window
|
|
@@ -182,7 +182,7 @@ class ZoneTrigger(Trigger):
|
|
|
182
182
|
List of trigger events.
|
|
183
183
|
"""
|
|
184
184
|
data = trace.data
|
|
185
|
-
sample_period = trace.metadata.
|
|
185
|
+
sample_period = 1.0 / trace.metadata.sample_rate
|
|
186
186
|
time_vector = np.arange(len(data)) * sample_period
|
|
187
187
|
events: list[TriggerEvent] = []
|
|
188
188
|
|
|
@@ -396,7 +396,7 @@ class MaskTrigger(Trigger):
|
|
|
396
396
|
mask_path = Path(self.mask_points)
|
|
397
397
|
|
|
398
398
|
data = trace.data
|
|
399
|
-
sample_period = trace.metadata.
|
|
399
|
+
sample_period = 1.0 / trace.metadata.sample_rate
|
|
400
400
|
time_vector = np.arange(len(data)) * sample_period
|
|
401
401
|
|
|
402
402
|
# Create points array for containment test
|
oscura/validation/hil_testing.py
CHANGED
|
@@ -35,7 +35,7 @@ from enum import Enum
|
|
|
35
35
|
from typing import Any, Protocol
|
|
36
36
|
|
|
37
37
|
try:
|
|
38
|
-
import can
|
|
38
|
+
import can
|
|
39
39
|
except ImportError:
|
|
40
40
|
can = None # type: ignore[assignment]
|
|
41
41
|
|
|
@@ -46,18 +46,18 @@ except ImportError:
|
|
|
46
46
|
# Create module structure for test patching even when pyusb unavailable
|
|
47
47
|
import types
|
|
48
48
|
|
|
49
|
-
usb = types.ModuleType("usb")
|
|
49
|
+
usb = types.ModuleType("usb")
|
|
50
50
|
usb.core = None # type: ignore[attr-defined]
|
|
51
51
|
|
|
52
52
|
try:
|
|
53
53
|
import spidev # type: ignore[import-not-found]
|
|
54
54
|
except ImportError:
|
|
55
|
-
spidev = None
|
|
55
|
+
spidev = None
|
|
56
56
|
|
|
57
57
|
try:
|
|
58
58
|
from smbus2 import SMBus # type: ignore[import-not-found]
|
|
59
59
|
except ImportError:
|
|
60
|
-
SMBus = None
|
|
60
|
+
SMBus = None
|
|
61
61
|
|
|
62
62
|
try:
|
|
63
63
|
import RPi.GPIO as GPIO # type: ignore[import-untyped]
|
|
@@ -65,23 +65,23 @@ except ImportError:
|
|
|
65
65
|
try:
|
|
66
66
|
import gpiod # type: ignore[import-not-found]
|
|
67
67
|
|
|
68
|
-
GPIO = None
|
|
68
|
+
GPIO = None
|
|
69
69
|
except ImportError:
|
|
70
|
-
GPIO = None
|
|
71
|
-
gpiod = None
|
|
70
|
+
GPIO = None
|
|
71
|
+
gpiod = None
|
|
72
72
|
|
|
73
73
|
try:
|
|
74
74
|
from scapy.all import IP, UDP, Packet, wrpcap # type: ignore[attr-defined]
|
|
75
75
|
except ImportError:
|
|
76
|
-
IP = None
|
|
77
|
-
UDP = None
|
|
76
|
+
IP = None
|
|
77
|
+
UDP = None
|
|
78
78
|
Packet = None # type: ignore[assignment,misc]
|
|
79
79
|
wrpcap = None # type: ignore[assignment]
|
|
80
80
|
|
|
81
81
|
try:
|
|
82
82
|
import serial # type: ignore[import-untyped]
|
|
83
83
|
except ImportError:
|
|
84
|
-
serial = None
|
|
84
|
+
serial = None
|
|
85
85
|
|
|
86
86
|
from oscura.utils.serial import connect_serial_port
|
|
87
87
|
|
|
@@ -960,7 +960,7 @@ class HILTester:
|
|
|
960
960
|
# Create UDP packet for received data if present
|
|
961
961
|
if recv_data:
|
|
962
962
|
pkt = IP(src="192.168.1.1") / UDP(sport=12345) / bytes(recv_data)
|
|
963
|
-
pkt.time = timestamp + 0.001
|
|
963
|
+
pkt.time = timestamp + 0.001
|
|
964
964
|
packets.append(pkt)
|
|
965
965
|
|
|
966
966
|
if packets:
|