oscura 0.8.0__py3-none-any.whl → 0.10.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/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/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 +164 -73
- 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/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/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/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/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 +7 -8
- 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.8.0.dist-info → oscura-0.10.0.dist-info}/METADATA +59 -79
- {oscura-0.8.0.dist-info → oscura-0.10.0.dist-info}/RECORD +111 -136
- 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 → oscura-0.10.0.dist-info}/WHEEL +0 -0
- {oscura-0.8.0.dist-info → oscura-0.10.0.dist-info}/entry_points.txt +0 -0
- {oscura-0.8.0.dist-info → oscura-0.10.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,43 +1,35 @@
|
|
|
1
|
-
{% extends "base.html" %}
|
|
2
|
-
|
|
3
|
-
{% block title %}Reports - {{ title }}{% endblock %}
|
|
4
|
-
|
|
5
|
-
{% block content %}
|
|
1
|
+
{% extends "base.html" %} {% block title %}Reports - {{ title }}{% endblock %} {% block content %}
|
|
6
2
|
<div class="row">
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<a href="/api/download/{{ session_id }}/report" class="btn btn-primary">
|
|
21
|
-
<i class="bi bi-download"></i> Download Full Report
|
|
22
|
-
</a>
|
|
23
|
-
</div>
|
|
24
|
-
|
|
25
|
-
<hr>
|
|
3
|
+
<div class="col-12">
|
|
4
|
+
<div class="card">
|
|
5
|
+
<div class="card-body">
|
|
6
|
+
<h2 class="card-title mb-4"><i class="bi bi-file-text"></i> Analysis Reports</h2>
|
|
7
|
+
|
|
8
|
+
{% if report_path %}
|
|
9
|
+
<div class="alert alert-success"><i class="bi bi-check-circle"></i> Report generated successfully</div>
|
|
10
|
+
|
|
11
|
+
<div class="d-grid gap-2">
|
|
12
|
+
<a href="/api/download/{{ session_id }}/report" class="btn btn-primary">
|
|
13
|
+
<i class="bi bi-download"></i> Download Full Report
|
|
14
|
+
</a>
|
|
15
|
+
</div>
|
|
26
16
|
|
|
27
|
-
|
|
28
|
-
<p class="text-muted">Full report available for download above.</p>
|
|
17
|
+
<hr />
|
|
29
18
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<i class="bi bi-exclamation-triangle"></i> No report available yet. Analysis may still be in progress.
|
|
33
|
-
</div>
|
|
19
|
+
<h5>Report Preview</h5>
|
|
20
|
+
<p class="text-muted">Full report available for download above.</p>
|
|
34
21
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
{% endif %}
|
|
39
|
-
</div>
|
|
22
|
+
{% else %}
|
|
23
|
+
<div class="alert alert-warning">
|
|
24
|
+
<i class="bi bi-exclamation-triangle"></i> No report available yet. Analysis may still be in progress.
|
|
40
25
|
</div>
|
|
26
|
+
|
|
27
|
+
<a href="/session/{{ session_id }}" class="btn btn-outline-primary">
|
|
28
|
+
<i class="bi bi-arrow-left"></i> Back to Session
|
|
29
|
+
</a>
|
|
30
|
+
{% endif %}
|
|
31
|
+
</div>
|
|
41
32
|
</div>
|
|
33
|
+
</div>
|
|
42
34
|
</div>
|
|
43
35
|
{% endblock %}
|
|
@@ -1,89 +1,79 @@
|
|
|
1
|
-
{% extends "base.html" %}
|
|
2
|
-
|
|
3
|
-
{% block title %}Session {{ session.id[:8] }} - {{ title }}{% endblock %}
|
|
4
|
-
|
|
5
|
-
{% block content %}
|
|
1
|
+
{% extends "base.html" %} {% block title %}Session {{ session.id[:8] }} - {{ title }}{% endblock %} {% block content %}
|
|
6
2
|
<div class="row">
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
</h2>
|
|
13
|
-
<p class="text-muted">Session ID: <code>{{ session.id }}</code></p>
|
|
3
|
+
<div class="col-lg-8">
|
|
4
|
+
<div class="card mb-4">
|
|
5
|
+
<div class="card-body">
|
|
6
|
+
<h2 class="card-title"><i class="bi bi-file-earmark-code"></i> {{ session.filename }}</h2>
|
|
7
|
+
<p class="text-muted">Session ID: <code>{{ session.id }}</code></p>
|
|
14
8
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
</div>
|
|
9
|
+
<div class="row mt-3">
|
|
10
|
+
<div class="col-md-6">
|
|
11
|
+
<p>
|
|
12
|
+
<strong>Status:</strong>
|
|
13
|
+
<span class="session-status status-{{ session.status }}"> {{ session.status }} </span>
|
|
14
|
+
</p>
|
|
15
|
+
<p><strong>Created:</strong> {{ session.created_at[:19] }}</p>
|
|
16
|
+
<p><strong>Updated:</strong> {{ session.updated_at[:19] }}</p>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="col-md-6">
|
|
19
|
+
<p><strong>File Hash:</strong> <code>{{ session.file_hash[:16] }}...</code></p>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
29
22
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
{% if protocol_spec %}
|
|
24
|
+
<hr />
|
|
25
|
+
<h5>Protocol Specification</h5>
|
|
26
|
+
<p><strong>Protocol:</strong> {{ protocol_spec.protocol_name }}</p>
|
|
27
|
+
<p><strong>Messages:</strong> {{ protocol_spec.message_count }}</p>
|
|
28
|
+
<p><strong>Fields:</strong> {{ protocol_spec.field_count }}</p>
|
|
36
29
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
</div>
|
|
62
|
-
{% endif %}
|
|
63
|
-
{% endif %}
|
|
64
|
-
</div>
|
|
30
|
+
{% if protocol_spec.fields %}
|
|
31
|
+
<div class="table-responsive mt-3">
|
|
32
|
+
<table class="table table-sm">
|
|
33
|
+
<thead>
|
|
34
|
+
<tr>
|
|
35
|
+
<th>Field</th>
|
|
36
|
+
<th>Offset</th>
|
|
37
|
+
<th>Length</th>
|
|
38
|
+
<th>Type</th>
|
|
39
|
+
<th>Confidence</th>
|
|
40
|
+
</tr>
|
|
41
|
+
</thead>
|
|
42
|
+
<tbody>
|
|
43
|
+
{% for field in protocol_spec.fields %}
|
|
44
|
+
<tr>
|
|
45
|
+
<td>{{ field.name }}</td>
|
|
46
|
+
<td>{{ field.offset }}</td>
|
|
47
|
+
<td>{{ field.length }}</td>
|
|
48
|
+
<td>{{ field.type }}</td>
|
|
49
|
+
<td>{{ (field.confidence * 100)|round(1) }}%</td>
|
|
50
|
+
</tr>
|
|
51
|
+
{% endfor %}
|
|
52
|
+
</tbody>
|
|
53
|
+
</table>
|
|
65
54
|
</div>
|
|
55
|
+
{% endif %} {% endif %}
|
|
56
|
+
</div>
|
|
66
57
|
</div>
|
|
58
|
+
</div>
|
|
67
59
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
<i class="bi bi-download"></i> Export/Download
|
|
83
|
-
</a>
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
60
|
+
<div class="col-lg-4">
|
|
61
|
+
<div class="card mb-4">
|
|
62
|
+
<div class="card-body">
|
|
63
|
+
<h5 class="card-title"><i class="bi bi-tools"></i> Actions</h5>
|
|
64
|
+
<div class="d-grid gap-2">
|
|
65
|
+
<a href="/waveforms/{{ session.id }}" class="btn btn-outline-primary">
|
|
66
|
+
<i class="bi bi-graph-up"></i> View Waveforms
|
|
67
|
+
</a>
|
|
68
|
+
<a href="/reports/{{ session.id }}" class="btn btn-outline-primary">
|
|
69
|
+
<i class="bi bi-file-text"></i> View Reports
|
|
70
|
+
</a>
|
|
71
|
+
<a href="/export/{{ session.id }}" class="btn btn-outline-primary">
|
|
72
|
+
<i class="bi bi-download"></i> Export/Download
|
|
73
|
+
</a>
|
|
86
74
|
</div>
|
|
75
|
+
</div>
|
|
87
76
|
</div>
|
|
77
|
+
</div>
|
|
88
78
|
</div>
|
|
89
79
|
{% endblock %}
|
|
@@ -1,83 +1,73 @@
|
|
|
1
|
-
{% extends "base.html" %}
|
|
2
|
-
|
|
3
|
-
{% block title %}Sessions - {{ title }}{% endblock %}
|
|
4
|
-
|
|
5
|
-
{% block content %}
|
|
1
|
+
{% extends "base.html" %} {% block title %}Sessions - {{ title }}{% endblock %} {% block content %}
|
|
6
2
|
<div class="row">
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<i class="bi bi-list-task"></i> Analysis Sessions
|
|
12
|
-
</h1>
|
|
3
|
+
<div class="col-12">
|
|
4
|
+
<div class="card">
|
|
5
|
+
<div class="card-body">
|
|
6
|
+
<h1 class="card-title mb-4"><i class="bi bi-list-task"></i> Analysis Sessions</h1>
|
|
13
7
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<div class="alert alert-info">
|
|
54
|
-
<i class="bi bi-info-circle"></i> No sessions yet. <a href="/">Upload a file</a> to get started.
|
|
55
|
-
</div>
|
|
56
|
-
{% endif %}
|
|
57
|
-
</div>
|
|
8
|
+
{% if sessions %}
|
|
9
|
+
<div class="table-responsive">
|
|
10
|
+
<table class="table table-hover">
|
|
11
|
+
<thead>
|
|
12
|
+
<tr>
|
|
13
|
+
<th>Session ID</th>
|
|
14
|
+
<th>Filename</th>
|
|
15
|
+
<th>Status</th>
|
|
16
|
+
<th>Created</th>
|
|
17
|
+
<th>Updated</th>
|
|
18
|
+
<th>Actions</th>
|
|
19
|
+
</tr>
|
|
20
|
+
</thead>
|
|
21
|
+
<tbody>
|
|
22
|
+
{% for session in sessions %}
|
|
23
|
+
<tr>
|
|
24
|
+
<td><code>{{ session.session_id[:8] }}...</code></td>
|
|
25
|
+
<td>{{ session.filename }}</td>
|
|
26
|
+
<td>
|
|
27
|
+
<span class="session-status status-{{ session.status }}"> {{ session.status }} </span>
|
|
28
|
+
</td>
|
|
29
|
+
<td>{{ session.created_at[:19] }}</td>
|
|
30
|
+
<td>{{ session.updated_at[:19] }}</td>
|
|
31
|
+
<td>
|
|
32
|
+
<a href="/session/{{ session.session_id }}" class="btn btn-sm btn-primary">
|
|
33
|
+
<i class="bi bi-eye"></i> View
|
|
34
|
+
</a>
|
|
35
|
+
<button class="btn btn-sm btn-danger" onclick="deleteSession('{{ session.session_id }}')">
|
|
36
|
+
<i class="bi bi-trash"></i>
|
|
37
|
+
</button>
|
|
38
|
+
</td>
|
|
39
|
+
</tr>
|
|
40
|
+
{% endfor %}
|
|
41
|
+
</tbody>
|
|
42
|
+
</table>
|
|
43
|
+
</div>
|
|
44
|
+
{% else %}
|
|
45
|
+
<div class="alert alert-info">
|
|
46
|
+
<i class="bi bi-info-circle"></i> No sessions yet. <a href="/">Upload a file</a> to get started.
|
|
58
47
|
</div>
|
|
48
|
+
{% endif %}
|
|
49
|
+
</div>
|
|
59
50
|
</div>
|
|
51
|
+
</div>
|
|
60
52
|
</div>
|
|
61
|
-
{% endblock %}
|
|
62
|
-
|
|
63
|
-
{% block extra_scripts %}
|
|
53
|
+
{% endblock %} {% block extra_scripts %}
|
|
64
54
|
<script>
|
|
65
|
-
|
|
66
|
-
|
|
55
|
+
async function deleteSession(sessionId) {
|
|
56
|
+
if (!confirm('Delete this session?')) return;
|
|
67
57
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
58
|
+
try {
|
|
59
|
+
const response = await fetch(`/api/session/${sessionId}`, {
|
|
60
|
+
method: 'DELETE',
|
|
61
|
+
});
|
|
72
62
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
63
|
+
if (response.ok) {
|
|
64
|
+
location.reload();
|
|
65
|
+
} else {
|
|
66
|
+
alert('Failed to delete session');
|
|
67
|
+
}
|
|
68
|
+
} catch (error) {
|
|
69
|
+
alert('Error: ' + error.message);
|
|
81
70
|
}
|
|
71
|
+
}
|
|
82
72
|
</script>
|
|
83
73
|
{% endblock %}
|
|
@@ -1,73 +1,63 @@
|
|
|
1
|
-
{% extends "base.html" %}
|
|
2
|
-
|
|
3
|
-
{% block title %}Waveforms - {{ title }}{% endblock %}
|
|
4
|
-
|
|
5
|
-
{% block content %}
|
|
1
|
+
{% extends "base.html" %} {% block title %}Waveforms - {{ title }}{% endblock %} {% block content %}
|
|
6
2
|
<div class="row">
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
</div>
|
|
15
|
-
</div>
|
|
3
|
+
<div class="col-12">
|
|
4
|
+
<div class="card mb-4">
|
|
5
|
+
<div class="card-body">
|
|
6
|
+
<h2 class="card-title"><i class="bi bi-graph-up"></i> Waveform Viewer</h2>
|
|
7
|
+
<p class="text-muted">{{ filename }}</p>
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
16
10
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
<div class="card">
|
|
12
|
+
<div class="card-body">
|
|
13
|
+
<div id="waveformPlot" style="width: 100%; height: 600px"></div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
22
16
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
<i class="bi bi-arrows-move"></i> Pan
|
|
32
|
-
</button>
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
17
|
+
<div class="card mt-4">
|
|
18
|
+
<div class="card-body">
|
|
19
|
+
<h5 class="card-title">Controls</h5>
|
|
20
|
+
<div class="btn-group" role="group">
|
|
21
|
+
<button class="btn btn-outline-secondary" onclick="resetZoom()">
|
|
22
|
+
<i class="bi bi-zoom-out"></i> Reset Zoom
|
|
23
|
+
</button>
|
|
24
|
+
<button class="btn btn-outline-secondary" onclick="togglePan()"><i class="bi bi-arrows-move"></i> Pan</button>
|
|
35
25
|
</div>
|
|
26
|
+
</div>
|
|
36
27
|
</div>
|
|
28
|
+
</div>
|
|
37
29
|
</div>
|
|
38
|
-
{% endblock %}
|
|
39
|
-
|
|
40
|
-
{% block extra_scripts %}
|
|
30
|
+
{% endblock %} {% block extra_scripts %}
|
|
41
31
|
<script>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
32
|
+
const sessionId = '{{ session_id }}';
|
|
33
|
+
const plotlyConfig = {{ plotly_config|safe }};
|
|
34
|
+
|
|
35
|
+
async function loadWaveform() {
|
|
36
|
+
try {
|
|
37
|
+
const response = await fetch(`/api/session/${sessionId}/waveform`);
|
|
38
|
+
const data = await response.json();
|
|
39
|
+
|
|
40
|
+
Plotly.newPlot('waveformPlot', data.data, data.layout, plotlyConfig);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error('Failed to load waveform:', error);
|
|
43
|
+
document.getElementById('waveformPlot').innerHTML =
|
|
44
|
+
'<div class="alert alert-danger">Failed to load waveform data</div>';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function resetZoom() {
|
|
49
|
+
Plotly.relayout('waveformPlot', {
|
|
50
|
+
'xaxis.autorange': true,
|
|
51
|
+
'yaxis.autorange': true
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function togglePan() {
|
|
56
|
+
const plot = document.getElementById('waveformPlot');
|
|
57
|
+
Plotly.relayout(plot, {dragmode: 'pan'});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Load waveform on page load
|
|
61
|
+
loadWaveform();
|
|
72
62
|
</script>
|
|
73
63
|
{% endblock %}
|
oscura/automotive/__init__.py
CHANGED