Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ba0d31f
Add native Qt ARStack Studio build scaffold
masarray Aug 11, 2026
f2a10bb
Add Qt SCL profile model interface
masarray Aug 11, 2026
f05116d
Implement direct C++ SCL compilation for Qt
masarray Aug 11, 2026
73795a1
Add Qt application entry point
masarray Aug 11, 2026
25fb843
Add premium Qt Quick SMV injection workspace
masarray Aug 11, 2026
ec547ff
Simplify native Qt premium injection workspace
masarray Aug 11, 2026
36204cf
Align Qt build scaffold with Qt 6 CMake guidance
masarray Aug 11, 2026
98fef69
Share ESP32-P4 SV profile support classification
masarray Aug 11, 2026
32be3e3
Add native Qt serial device controller
masarray Aug 11, 2026
ec3ee6b
Implement native Qt serial SMV control transport
masarray Aug 11, 2026
720d1af
Use shared ESP32 profile gate in Qt SCL model
masarray Aug 11, 2026
dada745
Link native Qt serial transport
masarray Aug 11, 2026
681d8f3
Expose native serial controller to QML
masarray Aug 11, 2026
f581827
Wire latest SMV profile and live controls into Qt UX
masarray Aug 11, 2026
ca6b9e9
Add native Qt Studio build and launch smoke CI
masarray Aug 11, 2026
22ab078
Reuse shared ESP32 profile support gate in inspector
masarray Aug 11, 2026
24d3273
Retain native Qt build logs on CI failures
masarray Aug 11, 2026
ceca8cd
Fix Qt QML syntax and streamline native injector workspace
masarray Aug 11, 2026
fd64c67
Document native Qt SMV Injector scope and workflow
masarray Aug 11, 2026
b2d2337
Allow Qt QML wrapper for SCL profile model
masarray Aug 11, 2026
387308e
Allow Qt QML wrapper for native device controller
masarray Aug 11, 2026
a77758a
Polish Qt injector P0 live workflow
masarray Aug 11, 2026
b3940d9
Fix Qt P0 state badge color
masarray Aug 11, 2026
655d9d5
Polish Qt SMV Injector P1 UX
masarray Aug 11, 2026
d041391
Merge remote-tracking branch 'origin/main' into main-qt-premium-phase2
masarray Aug 11, 2026
ab7704a
Add premium Qt workflow and dock shell
masarray Aug 11, 2026
97227a8
Add smart live injection and resizable Qt dock shell
masarray Aug 11, 2026
ec7daef
Fix CT waveform int64 portability
masarray Aug 11, 2026
472b3fc
Harden Qt live injection safety gates
masarray Aug 11, 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
80 changes: 80 additions & 0 deletions .github/workflows/arstack-studio-qt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: ARStack Studio Qt

on:
push:
paths:
- 'apps/arstack_studio/**'
- 'include/ariec61850/sampled_values/**'
- 'src/scl/**'
- 'include/ariec61850/scl/**'
- '.github/workflows/arstack-studio-qt.yml'
pull_request:
paths:
- 'apps/arstack_studio/**'
- 'include/ariec61850/sampled_values/**'
- 'src/scl/**'
- 'include/ariec61850/scl/**'
- '.github/workflows/arstack-studio-qt.yml'

permissions:
contents: read

jobs:
qt-build-smoke:
runs-on: ubuntu-latest
container: ubuntu:26.04
steps:
- name: Install build and Qt dependencies
shell: bash
run: |
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
ca-certificates git cmake ninja-build g++ \
qt6-base-dev qt6-declarative-dev qt6-serialport-dev \
qml6-module-qtquick qml6-module-qtquick-controls \
qml6-module-qtquick-layouts qml6-module-qtquick-dialogs \
qml6-module-qtquick-window

- name: Checkout
uses: actions/checkout@v4

- name: Configure
shell: bash
run: |
set -o pipefail
cmake -S apps/arstack_studio -B build-arstack-studio -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DARIEC61850_WARNINGS_AS_ERRORS=ON 2>&1 | tee /tmp/arstack-studio-configure.log

- name: Build
shell: bash
run: |
set -o pipefail
cmake --build build-arstack-studio --target arstack_studio --parallel 2 \
2>&1 | tee /tmp/arstack-studio-build.log

- name: Headless QML launch smoke
shell: bash
run: |
set +e
timeout 6s env QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software \
./build-arstack-studio/arstack_studio > /tmp/arstack-studio-launch.log 2>&1
status=$?
set -e
cat /tmp/arstack-studio-launch.log
if [ "$status" -ne 124 ]; then
echo "ARStack Studio exited before smoke timeout (status=$status)."
exit "$status"
fi

- name: Retain Qt smoke logs
if: always()
uses: actions/upload-artifact@v4
with:
name: arstack-studio-qt-logs
path: |
/tmp/arstack-studio-configure.log
/tmp/arstack-studio-build.log
/tmp/arstack-studio-launch.log
if-no-files-found: ignore
retention-days: 7
88 changes: 88 additions & 0 deletions apps/arstack_studio/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
cmake_minimum_required(VERSION 3.24)

project(ARStackStudio VERSION 0.1.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
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)
qt_standard_project_setup(REQUIRES 6.5)

# Reuse the repository's IEC 61850/SCL implementation directly. The desktop UI
# is a presentation/control plane; it must not grow a second SCL semantic engine.
set(ARIEC61850_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(ARIEC61850_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
set(ARIEC61850_BUILD_FUZZERS OFF CACHE BOOL "" FORCE)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../.. ${CMAKE_BINARY_DIR}/ariec61850-core EXCLUDE_FROM_ALL)

qt_add_executable(arstack_studio
src/main.cpp
src/SclProfileModel.cpp
src/SclProfileModel.hpp
src/DeviceController.cpp
src/DeviceController.hpp
)

qt_add_qml_module(arstack_studio
URI ARStack.Studio
VERSION 1.0
QML_FILES
qml/Main.qml
qml/StudioTheme.qml
qml/SurfacePanel.qml
qml/DockFrame.qml
qml/DarkToolButton.qml
qml/TelemetryDock.qml
qml/WorkflowBar.qml
qml/CalmButton.qml
qml/NumericField.qml
qml/StateBadge.qml
qml/ProfileInspector.qml
qml/ConfigurationHub.qml
qml/PtpExpertPanel.qml
qml/DeviceExpertPanel.qml
qml/WaveformExpertPanel.qml
qml/SignalMatrix.qml
qml/QualityEditor.qml
qml/SignalPreview.qml
qml/StatusToast.qml
RESOURCES
assets/InterVariable.ttf
assets/INTER_LICENSE.txt
assets/LUCIDE_LICENSE.txt
assets/lucide/x.svg
assets/lucide/external-link.svg
assets/lucide/chevron-up.svg
assets/lucide/chevron-down.svg
assets/lucide/radio-tower.svg
assets/lucide/scale.svg
assets/lucide/circle-off.svg
assets/lucide/activity.svg
assets/lucide/circle-check.svg
assets/lucide/settings-2.svg
assets/lucide/upload.svg
assets/lucide/square.svg
assets/lucide/play.svg
assets/lucide/panels-top-left.svg
assets/lucide/folder-open.svg
assets/lucide/scan-search.svg
assets/lucide/clock-3.svg
)

target_link_libraries(arstack_studio PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Qml
Qt6::Quick
Qt6::QuickControls2
Qt6::SerialPort
ARIEC61850::core
)

target_compile_features(arstack_studio PRIVATE cxx_std_20)

if(WIN32)
set_target_properties(arstack_studio PROPERTIES WIN32_EXECUTABLE TRUE)
endif()
179 changes: 179 additions & 0 deletions apps/arstack_studio/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
# ARStack Studio — native Qt SMV Injector

`apps/arstack_studio` is the native Qt 6 / C++ / QML operator surface for the ESP32-P4 Sampled Values injector.

This branch is intentionally stacked on `feature/smv-scl-profile-bridge` so the desktop application follows the latest SCL/profile and embedded-runtime behavior instead of freezing an older web-GUI snapshot.

## Architecture

```text
SCL / CID / SCD / IID
-> ARIEC61850 SclParser
-> SvPublisherProfileCompiler
-> shared ESP32-P4 deployment support classifier
-> Qt SclProfileModel
-> operator selects / validates stream
-> Qt DeviceController (QSerialPort)
-> current ESP32-P4 PROFILE + live-control protocol
-> deterministic publisher on ESP32-P4
```

The Qt application is a presentation and control plane. The PC is not the 4000/4800 fps realtime clock and does not replace the ESP32-P4 publisher.

## Latest workflow carried into Qt

- direct native SCL/CID/SCD/IID import using the repository C++ parser;
- resolved SampledValueControl stream selection;
- compatibility Class A / B / C;
- fail-closed ESP32-P4 device-support classification;
- explicit sample-counter-modulus confirmation for Class-B candidate profiles;
- explicit current counts/A and voltage counts/V test scaling;
- immutable profile deployment while STOPPED;
- profile identity: svID, data set, destination MAC, APPID, VLAN/PCP, confRev, publisher rate and counter modulus;
- optional DataSet / SampleRate ASDU-field flags already supported by the current device bridge;
- native serial 115200 8N1 control using Qt SerialPort;
- smart USB discovery with firmware-handshake verification and sequential
read-only fallback probing when Windows exposes only generic COM metadata;
- explicit `IDENTIFY` device identity backed by the ESP32-P4 factory MAC, so
the normal workflow never asks the operator to choose a COM port;
- live magnitude, phase, editable AC frequency, DC, enable and quality controls;
- mandatory live apply after verified connection; no mode switch can leave the
operator editing a stale local copy while output is running;
- an ARSVIN-compatible CT-saturation test shape with bounded DC offset,
harmonic, order, and clip controls in Expert mode;
- START / STOP / ZERO / SHOW and runtime telemetry;
- keyboard-first 4I + 4V matrix navigation;
- 3-phase linkage;
- persistent generated phasor and waveform preview;
- PTP Lab TX status, bounded runtime configuration, start/stop, and counters;
- serial diagnostics surface.

The current deployment gate intentionally accepts only the embedded layout already supported by the ESP32-P4 runtime. Broader SCL structures may parse correctly while remaining `unsupported-layout`; the GUI does not guess them into the firmware profile.

## Truthfulness boundary

The phasor and waveform are **generated setpoint previews**. They visualize the configured engineering state. They are not independent Ethernet on-wire evidence.

CT Saturation is a deterministic test-waveform approximation, not a calibrated
electromagnetic CT model. Its preview and parameters are labeled accordingly.

A later Process Bus monitor can add an observed trace and generated-vs-observed comparison without changing this distinction.

`smpSynch` remains an embedded timing/synchronization truth. The GUI must not claim synchronized output until the runtime has measured synchronization evidence.

## Build

Qt 6.5+ is required with:

- Qt Core / Gui / Qml / Quick / QuickControls2
- Qt SerialPort
- a C++20 compiler
- CMake 3.24+

### Windows example

From the repository root with a Qt-enabled developer shell:

```powershell
cmake -S apps/arstack_studio -B build-arstack-studio -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build-arstack-studio --target arstack_studio --parallel
.\build-arstack-studio\arstack_studio.exe
```

On the Windows development workstation used for this phase, Qt is installed at
`D:\Qt\6.8.3\msvc2022_64`. Build and launch with one command:

```powershell
.\apps\arstack_studio\run-windows.ps1
```

Use `-NoLaunch` for a build-only verification. The launcher discovers the
installed Visual Studio C++ toolchain with `vswhere`, reuses its bundled Ninja,
and does not modify the user's global `PATH`.

## P2 fast-workflow ribbon

The compact Home / View / Engineering ribbon carries ARSVIN's short operator
loop into the native Qt surface without copying its visual styling. Home keeps
Balanced, Zero, Check, Configure, Deploy, Start, and Stop one action away. View
owns dock visibility and detachment; Engineering owns SCL, smart discovery,
PTP refresh, and diagnostics. Device and output state stay in the header/footer
instead of being repeated as large workflow cards.

Keyboard operators can use `Ctrl+O`, `Ctrl+B`, `Ctrl+0`, `Ctrl+K`, `Ctrl+D`,
`F5`, and `F6`. Check reports readiness through the existing non-modal status
surface; it does not bypass the deployment gate.

## P2 dock shell

The main window now behaves as a compact engineering shell rather than a fixed
form. Engineering source, profile, scaling, quick setup, and runtime details
live in a dedicated Smart / Expert Configuration window instead of consuming
permanent space beside the injector. Phasor View and Waveform View are separate
right-side docks; each can be hidden or detached into its own real Qt window.
Status History and Output Monitor share a bottom dock that starts collapsed.
The View ribbon restores closed panels, detaches either plot, and expands the
bottom monitor.

The shell uses nested draggable splitters: editor vs preview docks, Phasor vs
Waveform, and workspace vs bottom monitor. Every pane keeps a protective
minimum size, while its split can be resized directly like an engineering MDI
shell. The complete monitor header is clickable for smooth expand/collapse.

Smart mode is the default and guides device recognition, PTP inspection, and SV
profile selection. Expert mode exposes the detailed SV profile compiler plus
bounded PTP domain, transportSpecific, VLAN, interval, and peer-delay controls.
Deploy and Start remain disabled until the serial response proves the connected
port is the ARStack ESP32-P4 injector.

PTP remains explicitly labeled as a laboratory timing companion. The firmware
serial surface now supports `PTP SHOW`, `PTP START`, `PTP STOP`, and bounded
`PTP CONFIG`; none of these claims external grandmaster lock or changes the
truthful `smpSynch` boundary.

The safety-critical editor remains the stable center pane. Split sizes are
operator-adjustable, while arbitrary drag-reordering and layout persistence
remain follow-up work; detaching a view must never move or duplicate the output
controls.

For redistribution, package the required dynamically linked Qt runtime libraries with the normal Qt deployment tooling and review the applicable Qt/LGPL distribution obligations for the chosen module set.

## CI

`.github/workflows/arstack-studio-qt.yml` performs:

1. standalone Qt configure;
2. native C++ / QML build;
3. headless QML launch smoke test;
4. retained configure/build/launch logs on every run.

A green desktop CI proves that the application builds and QML instantiates in the hosted environment. It does **not** replace physical ESP32-P4 / Ethernet validation.

## Physical acceptance still required

Before this desktop GUI is treated as a proven replacement for the current bench surface, retain hardware evidence for at least:

1. native serial `IDENTIFY`, SHOW, and PROFILE SHOW using updated firmware;
2. development 4000 fps START/STOP and live SET/FREQ/ENABLE/QUALITY updates;
3. SCL Class-A profile deployment followed by PROFILE committed/armed confirmation;
4. 4800 fps profile deployment and observed ~4800 fps with the expected smpCnt cycle;
5. live magnitude/phase changes without unintended counter restart;
6. DC and CT-saturation SHAPE commands with observed on-wire sample values;
7. PTP Lab TX configuration/counters and explicit non-lock truth labeling;
8. generated-vs-on-wire identity comparison using a trusted capture path.

## UI direction

The desktop visual target is a calm premium engineering instrument:

- Inter Variable is bundled under the SIL Open Font License and used for all
interface, numeric, status, and plot-label text; no monospace family is used;
- compact Lucide SVG icons are bundled with upstream license notices for the
ribbon and dock controls;
- Current and Voltage are the primary working matrices;
- SCL/profile information stays available without dominating the work surface;
- phasor and waveform remain persistent;
- Start/Stop remain fixed and obvious;
- values are optimized for keyboard operation;
- no browser/local-web-server dependency is required by the desktop application;
- visualization remains intentionally lightweight before any future custom `QQuickItem`/scene-graph optimization.
Loading
Loading