Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
07d0160
fix(studio): reject legacy bare START without 4I4V scenario
masarray Oct 19, 2026
a1d157c
fix(studio): reject legacy bare START without 4I4V scenario
masarray Oct 19, 2026
df19e47
test(studio): guard legacy bare START against stale firmware state
masarray Oct 19, 2026
73a0338
test(studio): use public device error readback
masarray Oct 19, 2026
b3582a8
feat(core): fixed-capacity staged SV scenario transaction and canonic…
masarray Oct 19, 2026
908eeb0
feat(firmware): add fail-closed CFG transaction begin/commit/readback…
masarray Oct 19, 2026
ffc76e3
feat(firmware): route existing FREQ SET ENABLE SHAPE parsing into iso…
masarray Oct 19, 2026
40148d2
feat(studio): own one generation-bound scenario ACK/readback state in…
masarray Oct 19, 2026
9f543ec
feat(studio): canonical normalized 8-channel hash and stage CFG batch…
masarray Oct 19, 2026
2f25758
feat(studio): gate START on transaction ACK and applied generation/ha…
masarray Oct 19, 2026
6621348
test(core): positive, partial, corrupt, stale, timeout, validation an…
masarray Oct 19, 2026
4fc43e0
build: register portable atomic SV scenario transaction regression suite
masarray Oct 19, 2026
d7a8f74
feat(firmware): declare verified SV config transaction capability
masarray Oct 19, 2026
c972322
fix(firmware): forbid publisher START without a current control heart…
masarray Oct 19, 2026
2cd75a2
fix(firmware): make malformed staged commands permanently reject tran…
masarray Oct 19, 2026
3dbd29f
test(studio): exercise commit/readback/START sequence and reject stal…
masarray Oct 19, 2026
203ddb4
feat(studio): expose read-only scenario transaction lifecycle to coal…
masarray Oct 19, 2026
3fff6a4
feat(studio): announce verified CFG terminal state without extra supe…
masarray Oct 19, 2026
8301039
fix(studio): preserve rapid GUI live edits during exclusive CFG apply…
masarray Oct 19, 2026
863247a
fix(studio): STOP cancels pending ACK/readback-to-START transaction
masarray Oct 19, 2026
913a286
test(studio): regression STOP while config ACK pending rejects late S…
masarray Oct 19, 2026
c380bbd
fix(studio): tolerate asynchronous RUNNING telemetry before token ACK…
masarray Oct 19, 2026
ea1f0e6
test(studio): replace obsolete queued-START assertion with stricter f…
masarray Oct 19, 2026
8039d9d
fix(qt): forward-declare live channel type to avoid Qt slots macro co…
masarray Oct 19, 2026
a02ce14
fix Qt and IEC core include macro isolation
masarray Oct 19, 2026
fd72815
Add reserved SV cancellation function declaration
masarray Oct 19, 2026
0316064
Add bounded SV cancellation marker
masarray Oct 19, 2026
6095986
fix(serial): preempt normal command queue with reserved SV cancellati…
masarray Oct 19, 2026
3c49bc5
fix(serial): terminate priority SV STOP with real LF byte
masarray Oct 19, 2026
91d9774
fix(serial): clear pending reserved SV STOP on port retire and reopen
masarray Oct 19, 2026
2bd0eed
test: register bounded SV STOP queue test
masarray Oct 19, 2026
ca04172
test: queue capacity 64 SV cancellation stays bounded
masarray Oct 19, 2026
1acb2c6
fix(core): require explicit successful firmware readback before START…
masarray Oct 19, 2026
91fcbfd
fix(firmware): only arm transaction ticket after verified bank readba…
masarray Oct 19, 2026
3093df9
test(core): prove no START before firmware readback even after valid …
masarray Oct 19, 2026
609a8a6
fix(studio): permit visible Stop and F6 cancellation while firmware C…
masarray Oct 19, 2026
5e39b96
fix(studio): permit visible Stop and F6 cancellation while firmware C…
masarray Oct 19, 2026
8206f88
fix(studio): permit visible Stop and F6 cancellation while firmware C…
masarray Oct 19, 2026
3ba385e
test(studio): guard Stop action availability during pending ACK sequence
masarray Oct 19, 2026
d6f2a13
Correct deterministic bare START regression target
masarray Oct 19, 2026
1efacd3
test(studio): avoid unbound local in pending-START cancellation QML g…
masarray Oct 19, 2026
546bc29
feat(evidence): independent read-only 9-2LE PCAP frame, 8-channel, sm…
masarray Oct 19, 2026
c935a54
perf(evidence): stream 14.4M SV frames/hour with constant-memory chan…
masarray Oct 19, 2026
a54eaff
test(evidence): synthetic 8-channel SV PCAP decode, sequence wrap, lo…
masarray Oct 19, 2026
9c6f1c8
ci(evidence): gate Studio smoke on independent streaming PCAP parser …
masarray Oct 19, 2026
cec2cc1
fix(evidence): encode synthetic ASDU fields and default sync byte as …
masarray Oct 19, 2026
e198e6e
fix(evidence): encode synthetic ASDU fields and default sync byte as …
masarray Oct 19, 2026
85b193e
feat(evidence): streaming fundamental RMS and phase equivalence again…
masarray Oct 19, 2026
2447f42
test(evidence): prove signed -30/-150 phase and RMS equivalence, reje…
masarray Oct 19, 2026
420edc2
docs(evidence): reproducible independent 120s and 3600s SMV PCAP acce…
masarray Oct 19, 2026
36b7e27
feat(evidence): compare all eight captured quality words to optional …
masarray Oct 19, 2026
3e68e96
test(evidence): reject PCAP quality mismatch even with correct RMS an…
masarray Oct 19, 2026
d061821
feat(studio): define independent capture controller with asynchronous…
masarray Oct 19, 2026
dfa8326
feat(studio): nonblocking Npcap/dumpcap SV-only one-click capture, sa…
masarray Oct 19, 2026
f0adc93
feat(studio): constant-memory PCAP SV/BER decoder, 4I+4V quality CSV,…
masarray Oct 19, 2026
2f2d380
build(studio): link QtConcurrent for worker-thread CSV export, packag…
masarray Oct 19, 2026
0412eb7
feat(ux): one-click SV capture in Device Advanced with adapter, durat…
masarray Oct 19, 2026
99bdf0f
feat(ux): embed evidence capture card in Advanced Device tab
masarray Oct 19, 2026
9def3a8
feat(studio): register single native SV capture controller in QML engine
masarray Oct 19, 2026
73fe8ec
feat(evidence): preserve labeled GUI snapshot as nonauthoritative PCA…
masarray Oct 19, 2026
7aecae0
feat(evidence): bind firmware identity, PTP and session telemetry pro…
masarray Oct 19, 2026
ed45cc2
feat(studio): export identity and PTP snapshot automatically with one…
masarray Oct 19, 2026
3bb3fed
feat(studio): export identity and PTP snapshot automatically with one…
masarray Oct 19, 2026
69dbfad
test(studio): permit deterministic native fixture to validate exact p…
masarray Oct 19, 2026
ed15a34
test(studio): deterministic native Ethernet SV fixture proves PCAP 8-…
masarray Oct 19, 2026
25fa3cf
test(build): add headless native PCAP to CSV/JSON decoder regression …
masarray Oct 19, 2026
0b6f010
ci(studio): compile and gate native SV capture evidence regression on…
masarray Oct 19, 2026
cbe7648
fix(studio): QML registrable QObject cannot be final; resolve exact Q…
masarray Oct 19, 2026
ce2bdd7
fix(evidence): 120s+5s PCAP acceptance margin and independent sample …
masarray Oct 19, 2026
81388ab
fix(ux): scroll Advanced Device contents at minimum window size witho…
masarray Oct 19, 2026
f66d15c
perf(ux): lazily discover capture interfaces only on first Device tab…
masarray Oct 19, 2026
8270b74
fix(transport): define bounded inter-command UART pacing independent …
masarray Oct 19, 2026
52e75fc
fix(transport): pace host UART lines 15ms; preserve immediate reserve…
masarray Oct 19, 2026
8176b1d
fix(studio): suspend 1Hz PTP/PROFILE SHOW chatter during binary profi…
masarray Oct 19, 2026
7aac562
fix(session): bounded 4.5s per-profile-ACK deadline for USB console l…
masarray Oct 19, 2026
ecd1852
test(studio): keep P0 policy self-check consistent with bounded USB p…
masarray Oct 19, 2026
dd6992c
feat(diagnostics): expose exact binary profile transfer phase for act…
masarray Oct 19, 2026
aed45ae
feat(diagnostics): show actual BINSTATUS/BINCHUNK/BINCOMMIT stage and…
masarray Oct 19, 2026
52a8432
fix(diagnostics): report exact firmware binary profile transfer stage…
masarray Oct 19, 2026
f9f8746
fix(profile): fail fast with corrupt-console evidence rather than sil…
masarray Oct 19, 2026
a10b07d
test(P0): reproduce field PROFW corruption, protect START, suspend PT…
masarray Oct 19, 2026
881c22d
fix(transport): retire UART inter-line timer on USB disconnect/sessio…
masarray Oct 19, 2026
2523f48
fix(profile): coalesce and defer all GUI live 4I+4V edits until binar…
masarray Oct 19, 2026
8003c70
fix(profile): reserve firmware binary-profile console transaction, fo…
masarray Oct 19, 2026
fc7243c
test(P0): guarantee atomic PROFILE BIN stage rejects concurrent PTP/S…
masarray Oct 19, 2026
35e64be
feat(profile): shared fixed-memory canonical binary record identity f…
masarray Oct 19, 2026
e092184
feat(firmware): cache validated active binary profile identity alongs…
masarray Oct 19, 2026
538548f
feat(firmware): advertise only verified committed profile binary iden…
masarray Oct 19, 2026
f801781
feat(firmware): capability-gate boot-local matching profile reuse wit…
masarray Oct 19, 2026
311009e
feat(studio): add boot-bound verified profile reuse state and explici…
masarray Oct 19, 2026
64e5d89
feat(profile): avoid duplicate binary uploads only after matched acti…
masarray Oct 19, 2026
a07ee14
fix(firmware): always report no-committed-record sentinel so Studio c…
masarray Oct 19, 2026
c2f9cc9
fix(session): accept unchanged generation only when device proved can…
masarray Oct 19, 2026
b51328f
build(studio): explicit uint64 type dependency for canonical profile …
masarray Oct 19, 2026
6ce5572
fix(session): clear active profile reuse proof on every COM disconnec…
masarray Oct 19, 2026
36b22a3
test(P0): canonical profile idempotent READY only after hash, full 4I…
masarray Oct 19, 2026
3da476d
feat(safety): pin canonical profile identity proof to verified device…
masarray Oct 19, 2026
4fe1906
feat(safety): bind binary upload and profile reuse to observed firmwa…
masarray Oct 19, 2026
e141574
fix(safety): reject delayed profile ACK/readback if ESP32-P4 boot ide…
masarray Oct 19, 2026
97a0980
feat(session): three bounded profile attempts with explicit backoff a…
masarray Oct 19, 2026
2b32cb1
feat(studio): visible context-aware bounded profile recovery, 650/145…
masarray Oct 19, 2026
0f4b830
test(P0): reflect bounded 3-attempt profile recovery policy in native…
masarray Oct 19, 2026
faa8a1a
test(P0): prove visible profile cool-down and hard 30-second timeout …
masarray Oct 19, 2026
11d6ca3
fix(ux): show meaningful profile/recovery states instead of generic A…
masarray Oct 19, 2026
b0e8d57
fix(ux): expose bounded profile cooldown reason and disable START exp…
masarray Oct 19, 2026
e8c6999
fix(safety): detect ESP32-P4 reboot on unchanged COM and revoke stale…
masarray Oct 19, 2026
e4a1bba
fix(session): auto-reconcile profile on live firmware boot-ID rollove…
masarray Oct 19, 2026
f0830c4
test(P0): live CH343 COM reboot revokes RUNNING, old profile reuse pr…
masarray Oct 19, 2026
83b4389
test(qt): invoke QTimer private-signal timeout through metaobject in …
masarray Oct 19, 2026
be50743
test(policy): align native P0 self-check with exactly three bounded p…
masarray Oct 19, 2026
5c4323b
fix(safety): reject stale/rolled-back profile generation as proof of …
masarray Oct 19, 2026
260237f
test(policy): ensure same-boot profile generation cannot regress
masarray Oct 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion .github/workflows/arstack-studio-qt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ jobs:
shell: bash
run: python3 apps/arstack_studio/tests/check_operator_workspace.py

- name: Independent SV PCAP decoder deterministic regressions
shell: bash
run: python3 -m unittest discover -s tests -p test_smv_wire_capture_audit.py -v

- name: Native binary profile authority regression
shell: bash
run: |
Expand Down Expand Up @@ -212,7 +216,7 @@ jobs:
run: |
set -o pipefail
cmake --build build-arstack-studio \
--target arstack_studio arstack_session_harness --parallel 2 \
--target arstack_studio arstack_session_harness arstack_capture_harness --parallel 2 \
2>&1 | tee /tmp/arstack-studio-build.log

- name: 4I+4V reference template regression
Expand All @@ -236,6 +240,13 @@ jobs:
timeout 20s ./build-arstack-studio/arstack_session_harness \
2>&1 | tee /tmp/arstack-studio-session-harness.log

- name: Native SV PCAP capture and CSV decoder regression
shell: bash
run: |
set -o pipefail
timeout 20s ./build-arstack-studio/arstack_capture_harness \
2>&1 | tee /tmp/arstack-studio-capture-harness.log

- name: Firmware bundle contract regression
shell: bash
run: |
Expand Down
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,13 @@ if(ARIEC61850_BUILD_TESTS)
ariec61850_apply_warnings(ariec61850_live_signal_tests)
ariec61850_apply_sanitizers(ariec61850_live_signal_tests)
add_test(NAME ariec61850_live_signal_tests COMMAND ariec61850_live_signal_tests)
add_executable(ariec61850_sv_scenario_transaction_tests tests/test_sv_scenario_transaction.cpp)
target_link_libraries(ariec61850_sv_scenario_transaction_tests PRIVATE ARIEC61850::core)
target_compile_features(ariec61850_sv_scenario_transaction_tests PRIVATE cxx_std_20)
ariec61850_apply_warnings(ariec61850_sv_scenario_transaction_tests)
ariec61850_apply_sanitizers(ariec61850_sv_scenario_transaction_tests)
add_test(NAME ariec61850_sv_scenario_transaction_tests
COMMAND ariec61850_sv_scenario_transaction_tests)

add_executable(ariec61850_goose_runtime_tests tests/test_goose_runtime.cpp)
target_link_libraries(ariec61850_goose_runtime_tests PRIVATE ARIEC61850::core)
Expand Down
17 changes: 16 additions & 1 deletion apps/arstack_studio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

find_package(Qt6 6.5 REQUIRED COMPONENTS Core Gui Qml Quick QuickControls2 SerialPort)
find_package(Qt6 6.5 REQUIRED COMPONENTS Core Gui Qml Quick QuickControls2 SerialPort Concurrent)
qt_standard_project_setup(REQUIRES 6.5)

# Reuse the repository's IEC 61850/SCL implementation directly. The desktop UI
Expand Down Expand Up @@ -38,6 +38,8 @@ qt_add_executable(arstack_studio
src/main.cpp
src/StudioClipboard.cpp
src/StudioClipboard.hpp
src/SvCaptureController.cpp
src/SvCaptureController.hpp
${ARSTACK_STUDIO_CORE_SOURCES}
)

Expand All @@ -52,6 +54,17 @@ qt_add_executable(arstack_session_harness
${ARSTACK_STUDIO_CORE_SOURCES}
)

# Offline production wire decoder regression (no Npcap or hardware required).
qt_add_executable(arstack_capture_harness
src/SvCaptureHarness.cpp
src/SvCaptureController.cpp
src/SvCaptureController.hpp
)
target_link_libraries(arstack_capture_harness PRIVATE
Qt6::Core Qt6::Gui Qt6::Concurrent
)
target_compile_features(arstack_capture_harness PRIVATE cxx_std_20)

# RC2 is a fail-closed evidence evaluator, not a hardware simulator. CI self-tests
# its acceptance policy; a physical run feeds the same executable a machine-readable
# evidence JSON collected from Studio telemetry and an independent SV capture.
Expand Down Expand Up @@ -104,6 +117,7 @@ qt_add_qml_module(arstack_studio
qml/StudioPtpSwitch.qml
qml/StudioTimingTray.qml
qml/DeviceExpertPanel.qml
qml/SvCapturePanel.qml
qml/FirmwarePanel.qml
qml/WaveformExpertPanel.qml
qml/SignalMatrix.qml
Expand Down Expand Up @@ -166,6 +180,7 @@ target_link_libraries(arstack_studio PRIVATE
Qt6::Quick
Qt6::QuickControls2
Qt6::SerialPort
Qt6::Concurrent
ARIEC61850::core
)

Expand Down
20 changes: 14 additions & 6 deletions apps/arstack_studio/qml/ConfigurationHub.qml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Item {
property var session
property string uiFont: "Inter"
property string monoFont: "Inter"
property bool captureTabVisited: false

function openEngineeringFile() { profileInspector.openEngineeringFile() }
function showRecovery() { expertTabs.currentIndex = 1 }
Expand Down Expand Up @@ -116,6 +117,7 @@ Item {

TabBar {
id: expertTabs
onCurrentIndexChanged: if (currentIndex === 4) hub.captureTabVisited = true
Layout.fillWidth: true
implicitHeight: 42
spacing: 4
Expand Down Expand Up @@ -171,12 +173,18 @@ Item {
uiFont: hub.uiFont
monoFont: hub.monoFont
}
DeviceExpertPanel {
theme: hub.theme
device: hub.device
session: hub.session
uiFont: hub.uiFont
monoFont: hub.monoFont
Loader {
// Never invoke Npcap interface discovery on the main Studio startup.
// Once opened, keep this item alive across tab switches so a running
// 120s/3600s capture cannot be aborted by merely browsing Advanced.
active: hub.captureTabVisited
sourceComponent: DeviceExpertPanel {
theme: hub.theme
device: hub.device
session: hub.session
uiFont: hub.uiFont
monoFont: hub.monoFont
}
}
}
}
Expand Down
24 changes: 20 additions & 4 deletions apps/arstack_studio/qml/DeviceExpertPanel.qml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,17 @@ SurfacePanel {
property string uiFont: "Inter"
property string monoFont: "Inter"

ColumnLayout {
ScrollView {
id: deviceScroll
anchors.fill: parent
anchors.margins: 16
spacing: 12
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff

ColumnLayout {
x: 16
y: 16
width: Math.max(0, deviceScroll.availableWidth - 32)
spacing: 12

Label { text: "Device protocol"; color: panel.theme.text; font.family: panel.uiFont; font.pixelSize: 18; font.weight: Font.DemiBold }
Label {
Expand Down Expand Up @@ -93,6 +100,15 @@ SurfacePanel {
font.pixelSize: 9
wrapMode: Text.WordWrap
}
Item { Layout.fillHeight: true }
SvCapturePanel {
Layout.fillWidth: true
Layout.preferredHeight: 268
theme: panel.theme
device: panel.device
uiFont: panel.uiFont
monoFont: panel.monoFont
}
Item { Layout.fillHeight: true; implicitHeight: 16 }
}
}
}
2 changes: 1 addition & 1 deletion apps/arstack_studio/qml/Main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ ApplicationWindow {
Shortcut { sequence: "Ctrl+B"; enabled: !workflowBar.startQueued; onActivated: root.balanced() }
Shortcut { sequence: "Ctrl+0"; enabled: !workflowBar.startQueued; onActivated: root.zeroAll() }
Shortcut { sequence: "F5"; enabled: workflowBar.session && workflowBar.session.state !== "RUNNING"; onActivated: workflowBar.requestStart() }
Shortcut { sequence: "F6"; enabled: workflowBar.session && workflowBar.session.state === "RUNNING"; onActivated: workflowBar.requestStop() }
Shortcut { sequence: "F6"; enabled: workflowBar.session && (workflowBar.session.state === "RUNNING" || workflowBar.startQueued); onActivated: workflowBar.requestStop() }

Dialog {
id: diagnosticsDialog
Expand Down
7 changes: 5 additions & 2 deletions apps/arstack_studio/qml/ModernRibbon.qml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ Rectangle {
if (session.state === "UPDATING FIRMWARE") return "Updating"
if (session.state === "UPDATE NEEDS BOOT") return "Bootloader"
if (session.state === "PREPARING 4I+4V") return "Preparing"
if (session.state === "PROFILE BLOCKED" || session.state === "PROFILE SYNC ERROR" || session.state === "SETUP ERROR") return "Attention"
if (session.state === "RECOVERING PROFILE") return "Retrying"
if (session.state === "PROFILE SYNC ERROR") return "Profile failed"
if (session.state === "PROFILE BLOCKED") return "Bad profile"
if (session.state === "SETUP ERROR") return "Setup failed"
return workflow.displayState
}

Expand Down Expand Up @@ -108,7 +111,7 @@ Rectangle {
text: "Stop"
tone: bar.workflow.injectionRunning ? "danger" : "neutral"
iconSource: Qt.resolvedUrl("../assets/material/stop.svg")
enabled: (bar.workflow.injectionRunning || bar.controller.offlinePreviewRunning)
enabled: (bar.workflow.injectionRunning || bar.workflow.startQueued || bar.controller.offlinePreviewRunning)
&& !bar.session.updatingFirmware
toolTipText: ""
onClicked: {
Expand Down
175 changes: 175 additions & 0 deletions apps/arstack_studio/qml/SvCapturePanel.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import ARStack.Studio 1.0

Rectangle {
id: panel
property var theme
property var device
property string uiFont: "Inter"
property string monoFont: "Inter"
color: theme.surface2
radius: 8
border.width: 1
border.color: theme.lineSoft
implicitHeight: 258

SvCaptureController { id: capture }

ColumnLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 9

RowLayout {
Layout.fillWidth: true
Label {
text: "SV WIRE CAPTURE"
color: panel.theme.text
font.family: panel.uiFont
font.pixelSize: 12
font.weight: Font.DemiBold
}
Item { Layout.fillWidth: true }
Label {
text: capture.capturing ? "RECORDING" : capture.processing ? "EXPORTING" : "READ-ONLY"
color: capture.capturing ? panel.theme.amber : panel.theme.green
font.family: panel.uiFont
font.pixelSize: 9
font.weight: Font.DemiBold
}
}
Label {
Layout.fillWidth: true
text: "Capture genuine IEC 61850 SV Ethernet frames. No injector commands are sent. Requires Wireshark dumpcap + Npcap and a TAP/SPAN receiving the injector traffic."
wrapMode: Text.WordWrap
color: panel.theme.textSoft
font.family: panel.uiFont
font.pixelSize: 9
lineHeight: 1.15
}
RowLayout {
Layout.fillWidth: true
spacing: 8
Label {
text: "Ethernet"
color: panel.theme.muted
font.family: panel.uiFont
font.pixelSize: 9
}
StudioDarkComboBox {
id: adapter
theme: panel.theme
uiFont: panel.uiFont
Layout.fillWidth: true
model: capture.interfaces
font.pixelSize: 9
enabled: !capture.capturing && !capture.processing
Connections {
target: capture
function onInterfacesChanged() {
adapter.currentIndex = capture.suggestedInterface >= 0
? capture.suggestedInterface : -1
}
}
}
CalmButton {
theme: panel.theme
uiFont: panel.uiFont
text: "Refresh"
enabled: !capture.capturing && !capture.processing
onClicked: capture.refreshInterfaces()
}
}
RowLayout {
Layout.fillWidth: true
spacing: 8
Label {
text: "Duration"
color: panel.theme.muted
font.family: panel.uiFont
font.pixelSize: 9
}
StudioDarkComboBox {
id: captureDuration
theme: panel.theme
uiFont: panel.uiFont
Layout.preferredWidth: 170
model: ["30 s · quick check", "120 s · acceptance", "3600 s · endurance"]
currentIndex: 1
enabled: !capture.capturing && !capture.processing
font.pixelSize: 9
}
CalmButton {
theme: panel.theme
uiFont: panel.uiFont
text: capture.capturing ? "Capturing…" :
capture.processing ? "Exporting…" : "Capture SV + CSV"
tone: "accent"
enabled: !capture.capturing && !capture.processing && adapter.currentIndex >= 0
onClicked: {
var seconds = captureDuration.currentIndex === 2 ? 3600
: captureDuration.currentIndex === 0 ? 30 : 120
capture.startCapture(adapter.currentIndex, seconds, {
"captured_utc": new Date().toISOString(),
"firmware_version": panel.device ? panel.device.firmwareVersion : "",
"firmware_build_id": panel.device ? panel.device.firmwareBuildId : "",
"boot_id": panel.device ? panel.device.bootId : "",
"device_id": panel.device ? panel.device.deviceId : "",
"serial_port": panel.device ? panel.device.portName : "",
"running": panel.device ? panel.device.running : false,
"profile_generation": panel.device ? panel.device.profileGeneration : "",
"signal_generation": panel.device ? panel.device.signalGeneration : "",
"smpSynch_value": panel.device ? panel.device.smpSynchValue : "",
"smpSynch_source": panel.device ? panel.device.smpSynchSource : "",
"ptp_role": panel.device ? panel.device.ptpRole : "",
"ptp_running": panel.device ? panel.device.ptpRunning : false,
"ptp_discipline": panel.device ? panel.device.ptpDiscipline : "",
"ptp_source": panel.device ? panel.device.ptpSource : "",
"ptp_offset_ns": panel.device ? panel.device.ptpOffsetNs : "",
"device_fps": panel.device ? panel.device.fps : "",
"device_missed": panel.device ? panel.device.missed : "",
"device_tx_failures": panel.device ? panel.device.txFailures : ""
})
}
}
CalmButton {
theme: panel.theme
uiFont: panel.uiFont
text: "Abort"
tone: "danger"
visible: capture.capturing
onClicked: capture.abortCapture()
}
Item { Layout.fillWidth: true }
CalmButton {
theme: panel.theme
uiFont: panel.uiFont
text: "Open files"
enabled: !capture.capturing
onClicked: capture.openOutputFolder()
}
}
Label {
Layout.fillWidth: true
text: capture.status
wrapMode: Text.WordWrap
color: capture.capturing ? panel.theme.amber : panel.theme.textSoft
font.family: panel.uiFont
font.pixelSize: 9
maximumLineCount: 3
elide: Text.ElideRight
}
Label {
Layout.fillWidth: true
text: "Exports: filtered .pcap + 8-channel samples.csv + seconds.csv + report.json. CSV is 1:20 sampled only for 3600 s; the PCAP always retains all packets. A capture is not a physical PASS."
wrapMode: Text.WordWrap
color: panel.theme.muted
font.family: panel.uiFont
font.pixelSize: 8
}
Item { Layout.fillHeight: true }
}
}
Loading
Loading