diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3250c0..7028891 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,17 +23,26 @@ jobs: with: dotnet-version: 8.0.x - - name: Restore app + - name: Restore Publisher run: dotnet restore src/ARSVIN/ARSVIN.csproj + - name: Restore Subscriber + run: dotnet restore src/ARSVIN.Subscriber/ARSVIN.Subscriber.csproj + - name: Restore tests run: dotnet restore tests/ARSVIN.Tests/ARSVIN.Tests.csproj - - name: Build app + - name: Build Publisher run: dotnet build src/ARSVIN/ARSVIN.csproj -c Release --no-restore + - name: Build Subscriber + run: dotnet build src/ARSVIN.Subscriber/ARSVIN.Subscriber.csproj -c Release --no-restore + - name: Test run: dotnet test tests/ARSVIN.Tests/ARSVIN.Tests.csproj -c Release --no-restore --logger trx - - name: Dependency vulnerability report + - name: Publisher dependency vulnerability report run: dotnet list src/ARSVIN/ARSVIN.csproj package --vulnerable --include-transitive + + - name: Subscriber dependency vulnerability report + run: dotnet list src/ARSVIN.Subscriber/ARSVIN.Subscriber.csproj package --vulnerable --include-transitive diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 21b8cc8..79558ff 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,18 +1,32 @@ -name: Release Portable Windows EXE +name: Build Windows Release on: push: tags: - 'v*.*.*' workflow_dispatch: + inputs: + version: + description: 'Version used for manual artifact builds (for example 0.3.0)' + required: false + default: '0.0.0-dev' permissions: contents: write +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: false + +env: + DOTNET_CLI_TELEMETRY_OPTOUT: '1' + DOTNET_NOLOGO: '1' + jobs: - publish: - name: Publish win-x64 portable package + release: + name: Portable EXEs and installer runs-on: windows-latest + steps: - name: Checkout uses: actions/checkout@v4 @@ -21,24 +35,111 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x + cache: true + cache-dependency-path: | + **/*.csproj + Directory.Packages.props + + - name: Resolve version + id: version + shell: pwsh + run: | + if ('${{ github.ref_type }}' -eq 'tag') { + $version = '${{ github.ref_name }}' -replace '^[vV]', '' + } + else { + $version = '${{ inputs.version }}' + if ([string]::IsNullOrWhiteSpace($version)) { + $version = '0.0.0-dev' + } + $version = $version -replace '^[vV]', '' + } + + if ($version -notmatch '^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$') { + throw "Unsupported release version: $version" + } + + "value=$version" >> $env:GITHUB_OUTPUT + Write-Host "Release version: $version" - name: Build and test shell: pwsh run: .\build.ps1 - - name: Publish portable ZIP + - name: Publish single-file portable applications shell: pwsh - run: .\publish-win-x64.ps1 + run: .\scripts\publish-release.ps1 -Version '${{ steps.version.outputs.value }}' -SkipTests + + - name: Install Inno Setup + shell: pwsh + run: choco install innosetup --no-progress -y + + - name: Build Windows installer + shell: pwsh + run: | + $iscc = @( + "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe", + "${env:ProgramFiles}\Inno Setup 6\ISCC.exe" + ) | Where-Object { Test-Path $_ } | Select-Object -First 1 + + if (-not $iscc) { + throw 'Inno Setup compiler (ISCC.exe) was not found.' + } + + $sourceDir = (Resolve-Path '.\artifacts\installer-input').Path + $outputDir = (Resolve-Path '.\artifacts\release').Path + $version = '${{ steps.version.outputs.value }}' + + & $iscc ` + "/DMyAppVersion=$version" ` + "/DSourceDir=$sourceDir" ` + "/DOutputDir=$outputDir" ` + '.\installer\ARSVIN.iss' + + if ($LASTEXITCODE -ne 0) { + throw "Inno Setup failed with exit code $LASTEXITCODE." + } + + - name: Generate SHA-256 checksums + shell: pwsh + run: | + $releaseRoot = Resolve-Path '.\artifacts\release' + $lines = Get-ChildItem $releaseRoot -File | + Where-Object { $_.Name -ne 'SHA256SUMS.txt' } | + Sort-Object Name | + ForEach-Object { + $hash = (Get-FileHash $_.FullName -Algorithm SHA256).Hash.ToLowerInvariant() + "$hash $($_.Name)" + } + + [System.IO.File]::WriteAllLines( + (Join-Path $releaseRoot 'SHA256SUMS.txt'), + $lines, + [System.Text.UTF8Encoding]::new($false) + ) + + Get-Content (Join-Path $releaseRoot 'SHA256SUMS.txt') - - name: Upload workflow artifact + - name: Upload release workflow artifact uses: actions/upload-artifact@v4 with: - name: ARSVIN-win-x64-portable - path: artifacts/ARSVIN-win-x64-portable.zip + name: ARSVIN-${{ steps.version.outputs.value }}-windows-x64 + path: | + artifacts/release/*.exe + artifacts/release/*.zip + artifacts/release/SHA256SUMS.txt + if-no-files-found: error + retention-days: 30 - name: Create GitHub Release - if: startsWith(github.ref, 'refs/tags/') + if: github.ref_type == 'tag' uses: softprops/action-gh-release@v3 with: - files: artifacts/ARSVIN-win-x64-portable.zip generate_release_notes: true + fail_on_unmatched_files: true + files: | + artifacts/release/ARSVIN-Publisher-win-x64.exe + artifacts/release/ArSubsv-Subscriber-win-x64.exe + artifacts/release/ARSVIN-Suite-Setup-win-x64.exe + artifacts/release/ARSVIN-win-x64-portable.zip + artifacts/release/SHA256SUMS.txt diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9b60785..2e5ad2b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,13 +2,13 @@ Thank you for considering a contribution to ARSVIN. -ARSVIN is an engineering tool for IEC 61850 Sampled Values lab publishing. The project values clear code, cautious live-network behavior, reproducible test notes, and documentation that an engineer can use in the field. +ARSVIN is an engineering suite for IEC 61850 Sampled Values laboratory workflows. The project values clear code, cautious live-network behavior, reproducible test notes, and documentation that an engineer can use in the field. ## Project principles -- Keep the product focused on SV publishing and relay readability checks. -- Do not turn ARSVIN into a general protocol analyzer unless the feature directly improves publishing safety or setup correctness. -- Keep live packet injection guarded, visible, and clearly labelled. +- Keep Publisher and Subscriber responsibilities explicit and independently testable. +- Add analysis features only when they improve Sampled Values visibility, interoperability, troubleshooting, or evidence quality. +- Keep live packet capture and injection guarded, visible, and clearly labelled. - Preserve Apache-2.0 compatibility. - Prefer explicit engineering wording over marketing claims. - Update documentation when behavior, UI, safety assumptions, or release packaging changes. @@ -20,7 +20,7 @@ Recommended environment: - Windows 10/11 x64 - .NET 8 SDK - PowerShell 7+ -- Npcap for live packet publishing tests +- Npcap for live packet capture/publishing tests - Wireshark for packet inspection Build: @@ -35,10 +35,10 @@ Run tests: dotnet test tests/ARSVIN.Tests/ARSVIN.Tests.csproj -c Release ``` -Create a portable package: +Create portable release artifacts: ```powershell -.\publish-win-x64.ps1 +.\scripts\publish-release.ps1 -Version 0.1.0 ``` ## Pull request checklist @@ -46,7 +46,7 @@ Create a portable package: Before opening a PR, please check: - The change has a narrow engineering purpose. -- The app builds in Release mode. +- Both affected applications build in Release mode. - Relevant unit tests were added or updated where practical. - Safety behavior is not weakened. - Docs are updated for user-visible changes. @@ -68,12 +68,13 @@ Document smpSynch compatibility mode Use GitHub Issues and include: - ARSVIN version or commit +- Application: Publisher or ArSubsv Subscriber - Windows version - Npcap version -- SCL/COMTRADE sample if shareable +- SCL/COMTRADE/PCAP sample if shareable - Steps to reproduce - Expected behavior - Actual behavior - Screenshots or Wireshark capture notes when relevant -Do not upload confidential station SCL files, relay IP plans, or production network captures. +Do not upload confidential station SCL files, relay IP plans, credentials, or production network captures. diff --git a/NOTICE b/NOTICE index 93f6c74..1c4c2b6 100644 --- a/NOTICE +++ b/NOTICE @@ -1,9 +1,12 @@ -ARSVIN - IEC 61850 Sampled Values Publisher & Process Bus Traffic Tester +ARSVIN - IEC 61850 Sampled Values Engineering Suite Copyright 2026 Ari Sulistiono Licensed under the Apache License, Version 2.0. Author: Ari Sulistiono GitHub: https://github.com/masarray +Project: https://github.com/masarray/arsvin -ARSVIN can transmit raw Ethernet frames and is intended only for isolated lab networks, point-to-point engineering tests, and educational use. +ARSVIN includes a Sampled Values Publisher and the ArSubsv Subscriber companion. The software can capture and transmit raw Ethernet frames and is intended only for isolated laboratory networks, authorized point-to-point engineering tests, development, troubleshooting support, and education. + +ARSVIN is not a certified IEC 61850 conformance tool, calibrated merging unit, protection test set, deterministic real-time platform, or production process-bus monitoring system. diff --git a/README.md b/README.md index ba086ee..4212361 100644 --- a/README.md +++ b/README.md @@ -1,132 +1,127 @@ -# ARSVIN — IEC 61850 Sampled Values Publisher for Windows +# ARSVIN — Open-Source IEC 61850 Sampled Values Workbench for Windows [](https://github.com/masarray/arsvin/actions/workflows/ci.yml) [](https://github.com/masarray/arsvin/actions/workflows/release.yml) [](https://github.com/masarray/arsvin/actions/workflows/codeql.yml) [](LICENSE) -[](#requirements) +[](#system-requirements) [](#build-from-source) -**ARSVIN** is an Apache-2.0 IEC 61850 **Sampled Values Publisher** for Windows. It helps substation automation engineers publish SV streams from SCL settings, replay COMTRADE records, run repeatable publisher scenarios, and export TX-side evidence for controlled lab work. +**ARSVIN** is a focused, Apache-2.0 engineering suite for IEC 61850 Sampled Values on Windows. It combines an SCL-driven **SV Publisher** with **ArSubsv**, a live/PCAP **SV Subscriber and analysis companion** for transparent, repeatable laboratory workflows.
-
+
- Download latest release · - Landing page · + Download · + Product site · Quick start · - Documentation + Documentation · + Contribute
-> [!WARNING] -> ARSVIN transmits raw Ethernet frames. Use it only on isolated lab networks, point-to-point test links, or networks where you have explicit authorization. ARSVIN is **not** a certified relay test set, calibrated current/voltage source, calibrated merging unit, production process-bus tool, or certified IEC 61850-9-3 PTP grandmaster. +> [!CAUTION] +> ARSVIN can capture and transmit raw Ethernet traffic. Use it only on isolated laboratory networks, point-to-point test links, or networks where you have explicit authorization. It is not a certified relay test set, calibrated merging unit, protection trip-time platform, production process-bus monitor, or IEC 61850 conformance tool. -## Why ARSVIN exists +## Real application views -IEC 61850 Sampled Values testing often needs transparent tooling: a way to inspect stream settings, publish repeatable SV frames, replay simple analog records, and preserve evidence without hiding the implementation behind a black box. ARSVIN focuses on that workflow. +| ArSubsv stream monitor | ArSubsv live analysis | +|---|---| +|
|
|
-ARSVIN is intentionally narrow:
+The screenshots above are captured from the actual Windows applications. They show the Publisher setup workflow and the Subscriber waveform, phasor, channel, RMS, and stream-analysis views.
-```text
-SCL-driven SV publishing → TX timing visibility → generated PCAP/report evidence
-```
+## Two focused applications
+
+| Application | Purpose | Typical workflow |
+|---|---|---|
+| **ARSVIN Publisher** | Generate IEC 61850 Sampled Values from SCL settings, manual values, scenarios, or COMTRADE records. | Configure → preflight → dry run/live TX → export PCAP and report. |
+| **ArSubsv Subscriber** | Discover, receive, decode, visualize, and assess SV streams from a live Npcap adapter or PCAP file. | Capture/import → bind to SCL → inspect values, waveform, phasor, RMS, and stream health → export report. |
-It does **not** try to replace StationScout, Wireshark, IEDScout, Omicron-class test sets, RTDS/HIL platforms, or certified conformance tools.
+The tools are intentionally separated. Publisher evidence proves what the PC generated; Subscriber evidence proves what the selected PC/NIC received and decoded. Neither alone proves that a protection IED consumed the multicast stream.
## Key capabilities
-| Capability | What it does |
-|---|---|
-| IEC 61850 SV publisher | Publishes Ethernet Sampled Values frames from a Windows workstation using Npcap. |
-| SCL-driven setup | Reads APPID, destination MAC, VLAN, `svID`, dataset, `confRev`, `smpRate`, `smpMod`, and `nofASDU` from SCL/SCD. |
-| Multi-ASDU packing | Supports `nofASDU=1/2/4/8` for lab-oriented SV frame packing. |
-| Multi-stream publishing | Runs up to three independent publisher slots for repeatable lab streams. |
-| COMTRADE replay | Replays ASCII, BINARY, BINARY32, and FLOAT32 analog COMTRADE records as SV values. |
-| Publisher scenarios | Generates balanced and per-phase state sequencer presets: 3P fault, A-G fault, B-C fault, negative/zero sequence, CT saturation stress, VT fuse fail, harmonic injection, DC offset, frequency steps, phase jump, and load reversal. |
-| TX Timing Health | Reports target FPS, actual FPS, jitter, late frames, missed schedule count, send duration, and overall TX health. |
-| PCAP evidence export | Exports generated SV frames to PCAP for offline inspection in Wireshark or other packet tools. |
-| Markdown evidence report | Exports TX-side publisher evidence with stream settings, preflight findings, timing health, and scenario metadata. |
-| Safety-first UX | Preflight warnings and explicit boundaries keep live publishing decisions visible. |
-
-## Supported publishing profiles
-
-| Area | Current support | Notes |
-|---|---|---|
-| IEC 61850 Sampled Values APDU | Lab publisher implementation | Focused on generated SV streams, not certified conformance. |
-| IEC 61850-9-2LE style 4I+4V | Supported as lab profile | Includes sample SCL and common 4 current + 4 voltage payload shape. |
-| `nofASDU` | `1`, `2`, `4`, `8` | Sample counter advances per ASDU. |
-| Quality bits | Good, invalid, questionable, oldData, test, operatorBlocked | Used for intentional relay behavior tests. |
-| PTP / `smpSynch` | Compatibility/lab behavior only | Not a certified IEC 61850-9-3 timing implementation. |
-| IEC 61869-9 generic datasets | Partial/future | See [SV profile support](docs/sv-profile-support.md). |
+### Publisher
-## Common workflows
+- SCL/SCD stream setup for APPID, destination MAC, VLAN, `svID`, dataset, `confRev`, `smpRate`, `smpMod`, and `nofASDU`.
+- Lab-oriented IEC 61850-9-2LE-style 4I+4V publishing.
+- Multi-ASDU frame packing with `nofASDU=1/2/4/8`.
+- Up to three independent publisher slots.
+- Manual values, ramps, state sequences, per-phase scenarios, waveform shaping, and COMTRADE replay.
+- Intentional quality-bit modes for controlled behavior checks.
+- TX timing health: target/actual FPS, jitter, late frames, missed schedules, and send duration.
+- Generated PCAP and Markdown evidence reports.
-### Publish from SCL
+### Subscriber / ArSubsv
-1. Open an SCL/SCD file.
-2. Select Publisher 1, 2, or 3.
-3. Choose an SV stream.
-4. Review APPID, MAC, VLAN, `svID`, dataset, `smpRate`, `smpMod`, and `nofASDU`.
-5. Run dry mode first.
-6. Publish live only on an isolated lab link.
+- Live SV capture through Npcap and offline classic-PCAP import.
+- Stream discovery and SCL-assisted binding.
+- APPID, VLAN, `svID`, `confRev`, `nofASDU`, sample-rate, and payload-layout checks.
+- `smpCnt` continuity and stream-health diagnostics.
+- Decoded instantaneous values, oscilloscope waveform, phasor, and RMS views.
+- Receiver-side Markdown evidence reports.
-### Replay COMTRADE as SV
+## Release downloads
-1. Load a COMTRADE `.cfg` and matching `.dat`.
-2. Map analog channels to current/voltage fields.
-3. Select the SV stream profile.
-4. Publish or export generated evidence.
+Every tagged release builds reproducible Windows x64 artifacts:
-### Preserve TX-side evidence
+| Artifact | Use |
+|---|---|
+| `ARSVIN-Publisher-win-x64.exe` | Self-contained, single-file portable Publisher. |
+| `ArSubsv-Subscriber-win-x64.exe` | Self-contained, single-file portable Subscriber. |
+| `ARSVIN-Suite-Setup-win-x64.exe` | Installer containing both applications, Start Menu shortcuts, documentation, and uninstaller. |
+| `ARSVIN-win-x64-portable.zip` | Portable suite folder containing both applications and essential documentation. |
+| `SHA256SUMS.txt` | SHA-256 checksums for release verification. |
-1. Run preflight.
-2. Start a dry run or live publisher session.
-3. Check TX Timing Health.
-4. Export generated PCAP.
-5. Export Markdown evidence report.
+The binaries are currently **unsigned**. Windows SmartScreen may show an unknown-publisher warning. Releases do not silently install Npcap; download Npcap from its official website when live capture or transmission is required.
-## Companion app: ARSVIN Subscriber
+## Quick start
-This repository now includes **ARSVIN Subscriber**, a separate WPF receiver-side verification companion for ARSVIN Publisher. It listens to IEC 61850 Sampled Values on an Npcap adapter, binds received streams to SCL when available, verifies APPID/VLAN/svID/confRev/nofASDU/sample-rate/payload layout, tracks `smpCnt` health, decodes values, and exports a receiver-side evidence report.
+### Installer
-Build it with:
+1. Download `ARSVIN-Suite-Setup-win-x64.exe` from the latest release.
+2. Install the suite.
+3. Install Npcap separately for live Ethernet capture/transmission.
+4. Open **ARSVIN Publisher** or **ArSubsv Subscriber** from the Start Menu.
+5. Start with a dry run, sample file, PCAP import, or isolated point-to-point link.
-```powershell
-dotnet build .\src\ARSVIN.Subscriber\ARSVIN.Subscriber.csproj -c Release
-```
-
-The subscriber proves that **this PC/NIC** receives and decodes the stream. It does not prove that a relay or IED consumed the multicast SV stream. See [`docs/subscriber-verification-app.md`](docs/subscriber-verification-app.md).
+### Portable
-## Quick start
+1. Download the Publisher or Subscriber portable `.exe`.
+2. Run the selected application directly.
+3. Run as Administrator only when the selected Npcap/live-network workflow requires it.
-### Download portable release
+See [Quick Start](docs/quick-start.md) and [Build and Release](docs/build-and-release.md).
-1. Install [Npcap](https://npcap.com/) on Windows.
-2. Download `ARSVIN-win-x64-portable.zip` from [Releases](https://github.com/masarray/arsvin/releases).
-3. Extract the ZIP.
-4. Run `ARSVIN.exe` as Administrator when live publishing raw Ethernet frames.
-5. Open a sample SCL from `samples/scl` or your lab SCD.
-6. Start with dry mode before live TX.
+## Supported scope
-See [Quick Start](docs/quick-start.md) for the full flow.
+| Area | Current status | Boundary |
+|---|---|---|
+| IEC 61850 Sampled Values APDU | Publisher and subscriber implementation for engineering/lab use | Not certified conformance testing. |
+| IEC 61850-9-2LE-style 4I+4V | Supported lab profile | Validate formal requirements independently. |
+| `nofASDU` | `1`, `2`, `4`, `8` | Publisher and receiver behavior is software/PC timing dependent. |
+| COMTRADE | ASCII, BINARY, BINARY32, FLOAT32 analog replay | Verify scaling and channel mapping before live TX. |
+| PTP / `smpSynch` | Compatibility and lab behavior | Not an IEC 61850-9-3 certified clock. |
+| Windows timing | Best-effort scheduling with visible health metrics | Not deterministic real-time execution. |
+| IED subscription proof | Not provided | SV multicast has no application-layer acknowledgement. |
-## Requirements
+## System requirements
For users:
-- Windows 10/11 x64
-- Npcap for live Ethernet publishing
-- Administrator rights for live packet transmission
-- Wireshark or equivalent tool for independent packet inspection
+- Windows 10 or Windows 11, x64.
+- Npcap for live capture or transmission.
+- Administrator permission when required by the local Npcap/network configuration.
+- Wireshark or another independent packet tool is recommended for verification.
For developers:
-- Windows 10/11 x64
-- .NET 8 SDK
-- PowerShell 7+ recommended
-- Visual Studio 2022, Rider, or VS Code with C# tooling
+- .NET 8 SDK.
+- PowerShell 7+ recommended.
+- Visual Studio 2022, JetBrains Rider, or VS Code with C# tooling.
+- Inno Setup 6 only when building the installer locally.
## Build from source
@@ -136,107 +131,63 @@ cd arsvin
.\build.ps1
```
-Create a portable Windows package:
+Build all release artifacts except the installer:
```powershell
-.\publish-win-x64.ps1
+.\scripts\publish-release.ps1 -Version 0.1.0
```
-Run tests:
+Compatibility wrapper:
```powershell
-dotnet test tests/ARSVIN.Tests/ARSVIN.Tests.csproj -c Release
+.\publish-win-x64.ps1 -Version 0.1.0
```
-## Repository structure
+Run tests directly:
-```text
-src/ARSVIN/ WPF desktop application and IEC 61850 publisher engine
-tests/ARSVIN.Tests/ Unit tests for protocol primitives and publisher helpers
-docs/ Engineering documentation, safety notes, and public launch docs
-samples/ SCL, COMTRADE, scenario, and evidence samples
-site/ Static GitHub Pages landing page
-.github/workflows/ CI, CodeQL, Pages, and release automation
+```powershell
+dotnet test .\tests\ARSVIN.Tests\ARSVIN.Tests.csproj -c Release
```
-## Documentation
-
-Start with [Documentation Index](docs/index.md), or jump directly to:
-
-- [Quick Start](docs/quick-start.md)
-- [SV Profile Support](docs/sv-profile-support.md)
-- [P0 Publisher Protocol Roadmap](docs/p0-publisher-protocol-roadmap.md)
-- [P1 Publisher Evidence Workflow](docs/p1-publisher-evidence-workflow.md)
-- [P2 Full Publisher Scenario Engine](docs/p2-full-publisher-scenarios.md)
-- [Waveform Shape Panel](docs/waveform-shape-panel.md)
-- [Multi-Stream SV Publishing](docs/multi-stream.md)
-- [COMTRADE Replay](docs/comtrade-replay.md)
-- [TX Safety Boundaries](docs/safety-boundaries.md)
-- [PTP and smpSynch Compatibility](docs/ptp-and-smpsynch.md)
-- [Build and Release](docs/build-and-release.md)
-- [SEO and Public Launch Checklist](docs/seo-public-launch-checklist.md)
-
-## What ARSVIN is not
-
-ARSVIN is not:
-
-- a live SV subscriber/analyzer,
-- a certified IEC 61850 conformance test tool,
-- a calibrated merging unit,
-- a protection trip-time validation platform,
-- a production process-bus diagnostic suite,
-- a replacement for relay vendor tools, StationScout, Wireshark, or Omicron-class test sets.
-
-SV is multicast and unacknowledged. A publisher cannot know which IEDs are live subscribers unless that information is derived from complete SCL/SCD engineering data or from external tooling.
-
-## SEO topics for GitHub
-
-Set these in the GitHub repository **About → Topics** panel:
+## Repository structure
```text
-iec61850
-iec-61850
-sampled-values
-sampled-values-publisher
-sv-publisher
-sv-injector
-merging-unit
-merging-unit-simulator
-process-bus
-digital-substation
-substation-automation
-comtrade
-ptp
-wpf
-dotnet
-windows
+src/ARSVIN/ Publisher application and SV generation engine
+src/ARSVIN.Subscriber/ ArSubsv subscriber and visualization companion
+tests/ARSVIN.Tests/ Protocol and publisher helper tests
+installer/ Inno Setup definition for the Windows suite
+scripts/ Repeatable release packaging scripts
+docs/ Engineering, safety, and contributor documentation
+samples/ SCL, COMTRADE, scenario, and evidence samples
+site/ Static, SEO-ready GitHub Pages product site
+.github/workflows/ CI, CodeQL, Pages, and release automation
```
-Suggested GitHub About description:
-
-```text
-Apache-2.0 IEC 61850 Sampled Values Publisher for Windows — SCL-driven SV publishing, COMTRADE replay, nofASDU support, TX timing health, per-phase scenario presets, and PCAP evidence export.
-```
+## Documentation
-## Contributing
+- [Documentation index](docs/index.md)
+- [Quick start](docs/quick-start.md)
+- [Subscriber verification app](docs/subscriber-verification-app.md)
+- [ArSubsv SV scout companion](docs/arsubsv-sv-scout-companion.md)
+- [SV profile support](docs/sv-profile-support.md)
+- [COMTRADE replay](docs/comtrade-replay.md)
+- [Multi-stream publishing](docs/multi-stream.md)
+- [Publisher evidence workflow](docs/p1-publisher-evidence-workflow.md)
+- [Full publisher scenarios](docs/p2-full-publisher-scenarios.md)
+- [Safety boundaries](docs/safety-boundaries.md)
+- [PTP and `smpSynch` compatibility](docs/ptp-and-smpsynch.md)
+- [Build and release](docs/build-and-release.md)
-Practical engineering contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md), keep pull requests focused, include test notes, and keep safety wording honest.
+## Security and responsible use
-## Author
+Do not attach confidential station SCL/SCD files, relay credentials, production packet captures, or internal network plans to public issues. Report vulnerabilities through GitHub Security Advisories as described in [SECURITY.md](SECURITY.md).
-Created and maintained by **Ari Sulistiono**.
+## Contributing
-GitHub: [github.com/masarray](https://github.com/masarray)
+Focused engineering contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md), keep changes reviewable, include test evidence where practical, and preserve explicit safety boundaries.
## License
-Apache License 2.0. See [LICENSE](LICENSE).
-
-Third-party dependency notes are listed in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
-
-
-## ArSubsv — Sampled Values Scout Companion
-
-The repository now includes **ArSubsv**, a separate WPF receiver-side SV scout app. It provides live stream discovery, SCL-bound decoding, oscilloscope waveform visualization, phasor/RMS indicators, classic PCAP import, stream health checks, and Markdown evidence reports. It is not an OMICRON product and does not copy OMICRON branding; it targets the same engineering class of Sampled Values visualization while keeping the ARSVIN visual identity.
+Copyright © 2026 Ari Sulistiono.
-See [`docs/arsubsv-sv-scout-companion.md`](docs/arsubsv-sv-scout-companion.md).
+Licensed under the [Apache License 2.0](LICENSE). Third-party dependency notices are documented in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md
index a2a67ac..3a61b09 100644
--- a/THIRD_PARTY_NOTICES.md
+++ b/THIRD_PARTY_NOTICES.md
@@ -1,11 +1,11 @@
# Third-Party Notices
-This file summarizes third-party components that ARSVIN depends on directly or expects users to install for live packet publishing.
+This file summarizes third-party components that ARSVIN depends on directly or expects users to install for live packet capture and transmission.
## SharpPcap
- Package: `SharpPcap`
-- Purpose: Packet capture and injection API used for live Ethernet publishing support
+- Purpose: Packet capture and injection API used by ARSVIN Publisher and ArSubsv Subscriber
- License: MIT
- Project: https://github.com/dotpcap/sharppcap
- Package: https://www.nuget.org/packages/SharpPcap
@@ -14,11 +14,11 @@ SharpPcap is consumed as a NuGet package and is not authored by the ARSVIN maint
## Npcap
-- Purpose: Windows packet capture/transmission driver required for live packet publishing
+- Purpose: Windows packet capture/transmission driver required for live Ethernet workflows
- Project: https://npcap.com/
-Npcap is not bundled in this repository. Users install it separately and are responsible for following its license and usage terms.
+Npcap is not bundled in this repository or silently installed by the ARSVIN installer. Users install it separately and are responsible for following its license and usage terms.
## .NET and WPF
-ARSVIN is built with .NET and WPF. See Microsoft documentation and license terms for the installed SDK/runtime components.
+ARSVIN is built with .NET and WPF. Self-contained release binaries include applicable .NET runtime components. See Microsoft documentation and license terms for those components.
diff --git a/build.ps1 b/build.ps1
index a9ce19d..9a020ba 100644
--- a/build.ps1
+++ b/build.ps1
@@ -1,24 +1,35 @@
$ErrorActionPreference = 'Stop'
+Set-StrictMode -Version Latest
$root = $PSScriptRoot
$appProject = Join-Path $root 'src\ARSVIN\ARSVIN.csproj'
$subscriberProject = Join-Path $root 'src\ARSVIN.Subscriber\ARSVIN.Subscriber.csproj'
$testProject = Join-Path $root 'tests\ARSVIN.Tests\ARSVIN.Tests.csproj'
-Write-Host '==> Restoring ARSVIN Publisher'
-dotnet restore $appProject
+function Invoke-DotNet {
+ param(
+ [Parameter(Mandatory)]
+ [string[]] $Arguments
+ )
-Write-Host '==> Restoring ARSVIN Subscriber'
-dotnet restore $subscriberProject
+ & dotnet @Arguments
+ if ($LASTEXITCODE -ne 0) {
+ throw "dotnet $($Arguments -join ' ') failed with exit code $LASTEXITCODE."
+ }
+}
-Write-Host '==> Restoring ARSVIN tests'
-dotnet restore $testProject
+Write-Host '==> Restoring solution projects'
+Invoke-DotNet -Arguments @('restore', $appProject)
+Invoke-DotNet -Arguments @('restore', $subscriberProject)
+Invoke-DotNet -Arguments @('restore', $testProject)
Write-Host '==> Building ARSVIN Publisher'
-dotnet build $appProject -c Release --no-restore
+Invoke-DotNet -Arguments @('build', $appProject, '-c', 'Release', '--no-restore')
-Write-Host '==> Building ARSVIN Subscriber'
-dotnet build $subscriberProject -c Release --no-restore
+Write-Host '==> Building ArSubsv Subscriber'
+Invoke-DotNet -Arguments @('build', $subscriberProject, '-c', 'Release', '--no-restore')
Write-Host '==> Running tests'
-dotnet test $testProject -c Release --no-restore
+Invoke-DotNet -Arguments @('test', $testProject, '-c', 'Release', '--no-restore')
+
+Write-Host '==> Build completed successfully'
diff --git a/docs/build-and-release.md b/docs/build-and-release.md
index eb90e53..8a51d6e 100644
--- a/docs/build-and-release.md
+++ b/docs/build-and-release.md
@@ -1,66 +1,163 @@
# Build and Release
-## Build
+ARSVIN uses a tag-driven GitHub Actions workflow to build two self-contained portable applications, one suite installer, one portable ZIP, and SHA-256 checksums.
-Requirements:
+## Prerequisites
+
+For local source builds:
- Windows 10/11 x64
- .NET 8 SDK
- PowerShell 7+ recommended
+For local installer builds:
+
+- All requirements above
+- Inno Setup 6
+
+Npcap is required only for live capture/transmission testing. It is not silently bundled or installed by the ARSVIN release process.
+
+## Build and test
+
```powershell
.\build.ps1
```
-The build script restores the WPF application and test project, builds Release configuration, and runs the unit tests.
+The script restores, builds, and tests:
+
+- `src/ARSVIN/ARSVIN.csproj`
+- `src/ARSVIN.Subscriber/ARSVIN.Subscriber.csproj`
+- `tests/ARSVIN.Tests/ARSVIN.Tests.csproj`
+
+External command exit codes are checked, so CI and local builds stop immediately when a `dotnet` command fails.
+
+## Build portable release artifacts
+
+```powershell
+.\scripts\publish-release.ps1 -Version 0.3.0
+```
-## Test
+Compatibility wrapper:
```powershell
-dotnet test tests/ARSVIN.Tests/ARSVIN.Tests.csproj -c Release
+.\publish-win-x64.ps1 -Version 0.3.0
+```
+
+Generated files:
+
+```text
+artifacts/release/
+├── ARSVIN-Publisher-win-x64.exe
+├── ArSubsv-Subscriber-win-x64.exe
+└── ARSVIN-win-x64-portable.zip
+```
+
+Staging files for the installer are generated under:
+
+```text
+artifacts/installer-input/
```
-The current test project focuses on stable protocol primitives. More SCL, COMTRADE, SV, and PTP tests should be added as public APIs stabilize.
+The two direct `.exe` files are self-contained .NET 8 single-file applications. The ZIP includes both applications, essential documentation, license notices, and sample files.
+
+## Build the installer locally
-## Publish portable Windows package
+After running the publish script:
```powershell
-.\publish-win-x64.ps1
+$version = '0.3.0'
+$sourceDir = (Resolve-Path '.\artifacts\installer-input').Path
+$outputDir = (Resolve-Path '.\artifacts\release').Path
+$iscc = "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe"
+
+& $iscc `
+ "/DMyAppVersion=$version" `
+ "/DSourceDir=$sourceDir" `
+ "/DOutputDir=$outputDir" `
+ '.\installer\ARSVIN.iss'
```
Output:
```text
-artifacts/ARSVIN-win-x64-portable.zip
+artifacts/release/ARSVIN-Suite-Setup-win-x64.exe
```
-The ZIP should include:
+The installer:
+
+- installs per-user under `%LOCALAPPDATA%\Programs\ARSVIN`,
+- includes Publisher and Subscriber,
+- creates Start Menu shortcuts,
+- offers an optional Publisher desktop shortcut,
+- includes an uninstaller,
+- preserves Apache-2.0 and third-party notices,
+- warns when Npcap is not detected.
-- `ARSVIN.exe`
-- README
-- LICENSE
-- NOTICE
-- THIRD_PARTY_NOTICES
-- documentation files needed for safe use
+## GitHub Actions release flow
-## GitHub release
+Workflow: `.github/workflows/release.yml`
+
+### Tagged release
Create and push a semantic version tag:
```powershell
-git tag v0.1.0
-git push origin v0.1.0
+git tag v0.3.0
+git push origin v0.3.0
+```
+
+The workflow then:
+
+1. restores, builds, and tests the solution,
+2. publishes both self-contained single-file applications,
+3. creates the portable suite ZIP,
+4. installs Inno Setup on the Windows runner,
+5. compiles the suite installer,
+6. generates `SHA256SUMS.txt`,
+7. uploads the files as a workflow artifact,
+8. creates a GitHub Release and attaches all public artifacts.
+
+### Manual artifact build
+
+Run **Build Windows Release** from the Actions tab and provide a version such as `0.3.0-dev.1`.
+
+Manual runs upload workflow artifacts but do not create a GitHub Release because no tag is present.
+
+## Release assets
+
+| File | Description |
+|---|---|
+| `ARSVIN-Publisher-win-x64.exe` | Portable Publisher. |
+| `ArSubsv-Subscriber-win-x64.exe` | Portable Subscriber/analysis companion. |
+| `ARSVIN-Suite-Setup-win-x64.exe` | Installer for both applications. |
+| `ARSVIN-win-x64-portable.zip` | Portable suite package. |
+| `SHA256SUMS.txt` | Integrity hashes for all release assets. |
+
+## Verify a download
+
+```powershell
+Get-FileHash .\ARSVIN-Suite-Setup-win-x64.exe -Algorithm SHA256
```
-The release workflow builds a self-contained win-x64 package and attaches it to the GitHub Release.
+Compare the result with `SHA256SUMS.txt` from the same GitHub Release.
+
+## Code signing status
+
+Release binaries are currently unsigned. Windows SmartScreen may display an unknown-publisher warning. The workflow intentionally does not contain placeholder signing steps or require paid signing secrets.
+
+When a trusted code-signing certificate becomes available, sign the portable executables before compiling the installer, then sign the completed installer before checksum generation.
-## Manual release checklist
+## Release checklist
-Before publishing:
+Before tagging a public release:
-- Run the build script on Windows.
-- Test dry run mode.
+- Confirm `main` CI and CodeQL are green.
+- Test Publisher dry run.
- Test live publishing only on an isolated lab link.
-- Verify packet behavior in Wireshark.
+- Test Subscriber live capture and PCAP import.
+- Verify generated SV traffic independently in Wireshark.
+- Verify portable executables on a clean Windows 10/11 x64 machine.
+- Verify install, upgrade, shortcuts, launch, and uninstall behavior.
- Review [Known Limitations](known-limitations.md).
+- Review [Safety Boundaries](safety-boundaries.md).
- Review [Public Release Checklist](public-release-checklist.md).
diff --git a/docs/github-repository-settings.md b/docs/github-repository-settings.md
index 483b3be..1a0f923 100644
--- a/docs/github-repository-settings.md
+++ b/docs/github-repository-settings.md
@@ -1,13 +1,17 @@
# GitHub Repository Settings
-These settings cannot be applied from the source tree, but they should be configured manually after pushing the repository.
+These settings are stored in GitHub rather than the source tree. Apply them manually after the pull request is merged.
+
+## Repository visibility
+
+Set the repository to **Public**. The repository is already public as of July 11, 2026.
## About panel
Description:
```text
-Apache-2.0 IEC 61850 Sampled Values Publisher for Windows — SCL-driven SV publishing, COMTRADE replay, nofASDU support, TX timing health, scenario presets, and PCAP evidence export.
+Apache-2.0 IEC 61850 Sampled Values workbench for Windows — SCL-driven SV publishing, COMTRADE replay, live/PCAP subscriber analysis, waveform, phasor, RMS, timing health, and evidence export.
```
Website:
@@ -16,6 +20,13 @@ Website:
https://masarray.github.io/arsvin/
```
+Enable:
+
+- Releases
+- Packages only when a package feed is introduced
+- Issues
+- Discussions only when there is enough maintainer capacity
+
Topics:
```text
@@ -23,20 +34,23 @@ iec61850
iec-61850
sampled-values
sampled-values-publisher
+sampled-values-subscriber
sv-publisher
+sv-subscriber
sv-injector
-merging-unit
-merging-unit-simulator
process-bus
digital-substation
substation-automation
comtrade
-ptp
+pcap
+phasor
wpf
dotnet
windows
```
+Avoid topics that imply certification, calibration, deterministic real-time performance, or affiliation with another vendor.
+
## Social preview
Upload:
@@ -48,13 +62,13 @@ site/assets/arsvin-social-preview.png
Recommended preview message:
```text
-ARSVIN — IEC 61850 Sampled Values Publisher
-SCL • COMTRADE • nofASDU • TX Timing • PCAP Evidence
+ARSVIN — IEC 61850 Sampled Values Workbench
+Publisher • Subscriber • SCL • COMTRADE • PCAP • Engineering Evidence
```
## Pages
-Use the existing workflow:
+Use **GitHub Actions** as the Pages source. The existing workflow is:
```text
.github/workflows/pages.yml
@@ -66,19 +80,40 @@ Expected public URL:
https://masarray.github.io/arsvin/
```
+After deployment, verify:
+
+- canonical URL,
+- responsive layout,
+- Open Graph preview,
+- direct latest-release links,
+- `robots.txt`,
+- `sitemap.xml`.
+
## Releases
-Use release assets for portable downloads. Recommended asset naming:
+The release workflow publishes stable asset names:
```text
+ARSVIN-Publisher-win-x64.exe
+ArSubsv-Subscriber-win-x64.exe
+ARSVIN-Suite-Setup-win-x64.exe
ARSVIN-win-x64-portable.zip
+SHA256SUMS.txt
```
Release notes should include:
-- capability summary,
-- installation steps,
-- Npcap/admin requirement,
+- Publisher and Subscriber capability summary,
+- installer and portable usage,
+- Npcap requirement for live workflows,
+- unsigned-binary/SmartScreen note,
- safety warning,
- known limitations,
- link to documentation.
+
+## Recommended merge settings
+
+- Enable squash merge.
+- Automatically delete head branches after merge.
+- Require the CI and CodeQL checks before merging into `main` when branch protection is enabled.
+- Require pull requests for changes to `main` when the project begins accepting external contributors.
diff --git a/docs/index.md b/docs/index.md
index b46ac3f..50d7af7 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,11 +1,11 @@
# ARSVIN Documentation
-ARSVIN is a focused IEC 61850 Sampled Values Publisher for Windows. This index groups the documentation by workflow so users can find the right page quickly.
+ARSVIN is a focused IEC 61850 Sampled Values engineering suite for Windows. It includes ARSVIN Publisher for stream generation and ArSubsv Subscriber for live/PCAP reception, decoding, visualization, and receiver-side evidence.
## Start here
-- [Quick Start](quick-start.md) — install, open SCL, choose a stream, and publish safely.
-- [Safety Boundaries](safety-boundaries.md) — lab-only assumptions and responsible use.
+- [Quick Start](quick-start.md) — install the suite, choose Publisher or Subscriber, and begin with a safe workflow.
+- [Safety Boundaries](safety-boundaries.md) — laboratory assumptions and responsible use.
- [Known Limitations](known-limitations.md) — current protocol and runtime boundaries.
## Publisher workflows
@@ -16,14 +16,19 @@ ARSVIN is a focused IEC 61850 Sampled Values Publisher for Windows. This index g
- [Live Preflight Diagnostics](live-preflight-diagnostics.md) — preflight checks before live TX.
- [P0 Publisher Protocol Roadmap](p0-publisher-protocol-roadmap.md) — nofASDU, quality, timing, and PCAP foundation.
- [P1 Publisher Evidence Workflow](p1-publisher-evidence-workflow.md) — generated PCAP and Markdown evidence export.
-- [P2 Full Publisher Scenario Engine](p2-full-publisher-scenarios.md)
-- [Waveform Shape Panel](waveform-shape-panel.md) — per-phase and waveform-shaped publisher scenario presets.
+- [P2 Full Publisher Scenario Engine](p2-full-publisher-scenarios.md) — repeatable protection and process-bus scenarios.
+- [Waveform Shape Panel](waveform-shape-panel.md) — per-phase and waveform-shaped publisher scenarios.
+
+## Subscriber workflows
+
+- [Subscriber Verification App](subscriber-verification-app.md) — receiver-side stream binding, validation, health, and evidence.
+- [ArSubsv SV Scout Companion](arsubsv-sv-scout-companion.md) — discovery, waveform, phasor, RMS, and PCAP analysis.
## Data sources and timing
- [COMTRADE Replay](comtrade-replay.md) — replaying analog records as Sampled Values.
-- [PTP and smpSynch Compatibility](ptp-and-smpsynch.md) — timing and synchronization boundaries.
-- [Sync Compatibility Mode](sync-compatibility-mode.md) — lab smpSynch behavior.
+- [PTP and `smpSynch` Compatibility](ptp-and-smpsynch.md) — timing and synchronization boundaries.
+- [Sync Compatibility Mode](sync-compatibility-mode.md) — laboratory `smpSynch` behavior.
## Build, release, and public repository
@@ -36,12 +41,7 @@ ARSVIN is a focused IEC 61850 Sampled Values Publisher for Windows. This index g
## Samples
-- `samples/scl` — minimal and nofASDU sample SCL files.
-- `samples/comtrade` — simple COMTRADE replay files.
-- `samples/evidence` — sample Markdown evidence report.
-- `samples/scenarios` — P2 full scenario preset notes and scenario matrix.
-
-- [ARSVIN Subscriber verification app](subscriber-verification-app.md)
-
-
-- [ArSubsv — IEC 61850 Sampled Values Scout Companion](arsubsv-sv-scout-companion.md)
+- `samples/scl` — minimal and `nofASDU` sample SCL files.
+- `samples/comtrade` — COMTRADE replay files.
+- `samples/evidence` — sample Markdown evidence reports.
+- `samples/scenarios` — publisher scenario notes and matrices.
diff --git a/docs/quick-start.md b/docs/quick-start.md
index 754c84c..de6cf2a 100644
--- a/docs/quick-start.md
+++ b/docs/quick-start.md
@@ -1,86 +1,124 @@
# Quick Start
-## 1. Install prerequisites
+ARSVIN contains two focused Windows applications:
-- Windows 10/11
-- Npcap for live Ethernet publishing
-- Administrator rights for live packet transmission
-- A lab network or isolated point-to-point setup when using live publish mode
+- **ARSVIN Publisher** for generating IEC 61850 Sampled Values.
+- **ArSubsv Subscriber** for live/PCAP capture, decoding, visualization, and receiver-side evidence.
-## 2. Start ARSVIN
+## 1. Install or run portable
-Run `ARSVIN.exe`.
+### Installer
-For live packet publishing, launch it as **Administrator**.
+Download `ARSVIN-Suite-Setup-win-x64.exe` from the latest GitHub Release and install the suite. Start Menu shortcuts are created for Publisher and Subscriber.
-## 3. Open SCL
+### Portable
-Use **Config** to open an SCL file and select an SV stream.
+Download either:
-The imported stream can provide APPID, VLAN, destination MAC, `svID`, dataset reference, and other network details.
+- `ARSVIN-Publisher-win-x64.exe`
+- `ArSubsv-Subscriber-win-x64.exe`
-## 4. Select a publisher slot
+The applications are self-contained single-file Windows x64 executables.
-Use the Publisher selector to switch between:
+## 2. Install live-network prerequisite
-- Publisher 1
-- Publisher 2
-- Publisher 3
+Install Npcap separately from its official website when live Ethernet capture or transmission is required.
-Each publisher can have its own stream, APPID, MAC, VLAN, sample rate, and values.
+Npcap is not bundled or silently installed by ARSVIN. Offline PCAP import, configuration, documentation, and Publisher dry-run workflows do not require live network access.
-## 5. Choose a publishing workflow
+## 3. Use an authorized test environment
-ARSVIN supports several practical lab workflows:
+For live traffic, use only:
-- **Manual Continue** — continuous steady-state publishing until stopped
-- **Ramp** — state-based magnitude / angle changes using the configured ramp timing
-- **Sequencer** — timed state sequence publishing using the configured state durations
-- **COMTRADE Replay** — replay analog records as Sampled Values
+- an isolated laboratory network,
+- a point-to-point engineering link, or
+- another network where you have explicit authorization.
-## 6. Review network settings
+Administrator rights may be required by the local Npcap/network configuration.
-Before using live mode, confirm:
+# Publisher workflow
-- selected adapter
-- destination MAC
-- source MAC
-- APPID
-- VLAN ID and priority
-- sample rate / `smpCnt` progression expectation
-- selected `smpSynch` behavior / compatibility mode
+## 4. Open SCL
-## 7. Publish
+Open **ARSVIN Publisher**, then use **Config** to load an SCL/SCD file and select an SV stream.
-Use **Check** for optional live diagnostics, then **Start** for live publishing. ARSVIN uses a KM Looptest friendly preflight model: warnings do not block live publish, but fatal errors still stop invalid traffic.
+Imported engineering data can provide APPID, VLAN, destination MAC, `svID`, dataset reference, `confRev`, sample rate, `smpMod`, and `nofASDU`.
-You can also run a dry test for validation without transmitting on the network.
+## 5. Select a publisher slot
-## 8. Verify
+Switch between Publisher 1, Publisher 2, and Publisher 3. Each slot can use its own stream, APPID, MAC, VLAN, sample rate, source mode, and values.
-Use Wireshark and the relay / subscriber status to confirm the stream is visible and readable.
+## 6. Choose a source mode
-Useful checks include:
+Available workflows include:
-- Ethernet type `0x88BA`
-- correct destination multicast MAC
-- correct APPID
-- correct VLAN tag
-- expected `svID`
-- expected `smpSynch` behavior, especially whether the relay requires global compatibility mode
+- **Manual Continue** — continuous steady-state publishing.
+- **Ramp** — magnitude/angle changes using configured timing.
+- **Sequencer** — timed states and repeatable per-phase scenarios.
+- **COMTRADE Replay** — analog record replay as Sampled Values.
+- **Waveform shaping** — harmonic, DC-offset, clipping, and related laboratory scenarios.
-## Sync compatibility note
+## 7. Review and preflight
+
+Before live transmission, confirm:
+
+- selected adapter,
+- destination and source MAC,
+- APPID,
+- VLAN ID and priority,
+- `svID`, dataset, and `confRev`,
+- sample rate and `nofASDU`,
+- expected `smpCnt` progression,
+- selected quality mode,
+- `smpSynch` compatibility behavior.
+
+Run a dry test first. Warnings remain visible but do not block valid laboratory traffic; fatal configuration errors do.
+
+## 8. Publish and preserve evidence
+
+Start live publishing only after preflight and network authorization.
+
+Use TX Timing Health to inspect target/actual FPS, jitter, late frames, missed schedules, and send duration. Export generated PCAP and the Markdown publisher report when evidence is needed.
+
+# Subscriber workflow
+
+## 9. Select live capture or PCAP import
-For point-to-point relay readability checks, **Global compatibility — smpSynch=2** is usually the most practical starting point. It helps strict subscribers accept the SV stream, but it does not prove real PTP timing accuracy.
+Open **ArSubsv Subscriber** and choose:
+- a live Npcap adapter, or
+- a classic PCAP file for offline analysis.
-## 9. Use the modern SV setup workflow
+When SCL is available, load it to assist stream binding and expected-configuration checks.
-The **SV Setup** window is organized for quick looptest work:
+## 10. Inspect the stream
-- use the left **SV streams** navigator to select SV1, SV2, or SV3
-- edit the selected stream in the main panel
-- choose **Manual**, **Ramp**, **Sequence**, or **COMTRADE** source mode
-- press **Check** to open the Preflight Results window when you need details
+Review:
+
+- discovered streams,
+- APPID, VLAN, `svID`, and `confRev`,
+- `nofASDU`, sample rate, and payload layout,
+- `smpCnt` continuity and stream health,
+- decoded values,
+- waveform,
+- phasor and RMS views.
+
+Export the receiver-side Markdown report when a repeatable record is required.
+
+## 11. Verify independently
+
+Use Wireshark, relay diagnostics, vendor tools, or certified equipment when independent verification is required.
+
+Useful packet checks include:
+
+- Ethernet type `0x88BA`,
+- correct multicast destination MAC,
+- correct APPID and VLAN tag,
+- expected `svID`, dataset, and `confRev`,
+- expected ASDU packing and sample counter behavior.
+
+Publisher evidence shows what the PC generated. Subscriber evidence shows what the selected PC/NIC received and decoded. Neither alone proves that a protection IED consumed the multicast stream.
+
+## Sync compatibility note
-Warnings are shown in the Preflight Results window and event log. They do not block live publishing. Only fatal configuration errors block live publishing.
+For point-to-point relay readability checks, **Global compatibility — `smpSynch=2`** can be a practical starting point for strict subscribers. It does not prove IEC 61850-9-3 timing accuracy or make the Windows PC a certified PTP grandmaster.
diff --git a/installer/ARSVIN.iss b/installer/ARSVIN.iss
new file mode 100644
index 0000000..b20e7b3
--- /dev/null
+++ b/installer/ARSVIN.iss
@@ -0,0 +1,97 @@
+; ARSVIN Suite installer
+; Built by .github/workflows/release.yml with Inno Setup 6.
+
+#ifndef MyAppVersion
+ #define MyAppVersion "0.0.0-dev"
+#endif
+
+#ifndef SourceDir
+ #define SourceDir "..\artifacts\installer-input"
+#endif
+
+#ifndef OutputDir
+ #define OutputDir "..\artifacts\release"
+#endif
+
+#define MyAppName "ARSVIN Suite"
+#define MyAppPublisher "Ari Sulistiono"
+#define MyAppUrl "https://github.com/masarray/arsvin"
+
+[Setup]
+AppId={{A76AC909-93A0-4EA3-A6EE-DA3B64595F52}
+AppName={#MyAppName}
+AppVersion={#MyAppVersion}
+AppVerName={#MyAppName} {#MyAppVersion}
+AppPublisher={#MyAppPublisher}
+AppPublisherURL={#MyAppUrl}
+AppSupportURL={#MyAppUrl}/issues
+AppUpdatesURL={#MyAppUrl}/releases
+DefaultDirName={localappdata}\Programs\ARSVIN
+DefaultGroupName=ARSVIN
+DisableProgramGroupPage=yes
+OutputDir={#OutputDir}
+OutputBaseFilename=ARSVIN-Suite-Setup-win-x64
+SetupIconFile=..\src\ARSVIN\Assets\arsvin.ico
+UninstallDisplayIcon={app}\ARSVIN.exe
+Compression=lzma2/ultra64
+SolidCompression=yes
+WizardStyle=modern
+PrivilegesRequired=lowest
+ArchitecturesAllowed=x64compatible
+MinVersion=10.0
+CloseApplications=yes
+RestartApplications=no
+VersionInfoCompany={#MyAppPublisher}
+VersionInfoDescription=ARSVIN IEC 61850 Sampled Values engineering suite
+VersionInfoProductName={#MyAppName}
+LicenseFile=..\LICENSE
+
+[Languages]
+Name: "english"; MessagesFile: "compiler:Default.isl"
+
+[Tasks]
+Name: "desktopicon"; Description: "Create a desktop shortcut for ARSVIN Publisher"; GroupDescription: "Additional shortcuts:"; Flags: unchecked
+
+[Files]
+Source: "{#SourceDir}\ARSVIN.exe"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#SourceDir}\ArSubsv.exe"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#SourceDir}\README.md"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#SourceDir}\LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#SourceDir}\NOTICE.txt"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#SourceDir}\THIRD_PARTY_NOTICES.md"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#SourceDir}\VERSION.txt"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#SourceDir}\docs\*"; DestDir: "{app}\docs"; Flags: ignoreversion recursesubdirs createallsubdirs
+Source: "{#SourceDir}\samples\*"; DestDir: "{app}\samples"; Flags: ignoreversion recursesubdirs createallsubdirs
+
+[Icons]
+Name: "{group}\ARSVIN Publisher"; Filename: "{app}\ARSVIN.exe"; WorkingDir: "{app}"
+Name: "{group}\ArSubsv Subscriber"; Filename: "{app}\ArSubsv.exe"; WorkingDir: "{app}"
+Name: "{group}\Documentation"; Filename: "{app}\README.md"
+Name: "{group}\Project website"; Filename: "{#MyAppUrl}"
+Name: "{group}\Uninstall ARSVIN Suite"; Filename: "{uninstallexe}"
+Name: "{autodesktop}\ARSVIN Publisher"; Filename: "{app}\ARSVIN.exe"; WorkingDir: "{app}"; Tasks: desktopicon
+
+[Run]
+Filename: "{app}\ARSVIN.exe"; Description: "Launch ARSVIN Publisher"; WorkingDir: "{app}"; Flags: nowait postinstall skipifsilent
+
+[Code]
+function NpcapInstalled(): Boolean;
+begin
+ Result :=
+ FileExists(ExpandConstant('{sys}\Npcap\wpcap.dll')) or
+ FileExists(ExpandConstant('{sys}\wpcap.dll'));
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+begin
+ if (CurStep = ssPostInstall) and (not NpcapInstalled()) then
+ begin
+ MsgBox(
+ 'ARSVIN was installed successfully.' + #13#10 + #13#10 +
+ 'Live IEC 61850 Sampled Values capture and transmission require Npcap. ' +
+ 'Install Npcap separately from its official website before using live network features.',
+ mbInformation,
+ MB_OK
+ );
+ end;
+end;
diff --git a/publish-win-x64.ps1 b/publish-win-x64.ps1
index 7847f26..31a3bc4 100644
--- a/publish-win-x64.ps1
+++ b/publish-win-x64.ps1
@@ -1,56 +1,15 @@
-$ErrorActionPreference = 'Stop'
-
-$root = $PSScriptRoot
-$artifactRoot = Join-Path $root 'artifacts'
-$out = Join-Path $artifactRoot 'ARSVIN-win-x64'
-$publisherOut = Join-Path $out 'Publisher'
-$subscriberOut = Join-Path $out 'Subscriber'
-$publisherProject = Join-Path $root 'src\ARSVIN\ARSVIN.csproj'
-$subscriberProject = Join-Path $root 'src\ARSVIN.Subscriber\ARSVIN.Subscriber.csproj'
-$zipPath = Join-Path $artifactRoot 'ARSVIN-win-x64-portable.zip'
-
-if (Test-Path $out) { Remove-Item $out -Recurse -Force }
-New-Item -ItemType Directory -Path $publisherOut -Force | Out-Null
-New-Item -ItemType Directory -Path $subscriberOut -Force | Out-Null
-
-if (Test-Path $zipPath) { Remove-Item $zipPath -Force }
+param(
+ [string] $Version = '0.0.0-dev',
+ [string] $Runtime = 'win-x64',
+ [switch] $SkipTests
+)
-Write-Host '==> Publishing ARSVIN Publisher win-x64 portable package'
-dotnet publish $publisherProject `
- -c Release `
- -r win-x64 `
- --self-contained true `
- -p:PublishSingleFile=true `
- -p:IncludeNativeLibrariesForSelfExtract=true `
- -p:EnableCompressionInSingleFile=true `
- -p:DebugType=None `
- -p:DebugSymbols=false `
- -o $publisherOut
-
-Write-Host '==> Publishing ARSVIN Subscriber win-x64 portable package'
-dotnet publish $subscriberProject `
- -c Release `
- -r win-x64 `
- --self-contained true `
- -p:PublishSingleFile=true `
- -p:IncludeNativeLibrariesForSelfExtract=true `
- -p:EnableCompressionInSingleFile=true `
- -p:DebugType=None `
- -p:DebugSymbols=false `
- -o $subscriberOut
-
-Copy-Item (Join-Path $root 'README.md') (Join-Path $out 'README.md') -Force
-Copy-Item (Join-Path $root 'LICENSE') (Join-Path $out 'LICENSE.txt') -Force
-Copy-Item (Join-Path $root 'NOTICE') (Join-Path $out 'NOTICE.txt') -Force
-Copy-Item (Join-Path $root 'THIRD_PARTY_NOTICES.md') (Join-Path $out 'THIRD_PARTY_NOTICES.md') -Force
+$ErrorActionPreference = 'Stop'
+Set-StrictMode -Version Latest
-$docsOut = Join-Path $out 'docs'
-New-Item -ItemType Directory -Path $docsOut -Force | Out-Null
-Copy-Item (Join-Path $root 'docs\quick-start.md') $docsOut -Force
-Copy-Item (Join-Path $root 'docs\live-mode-safety.md') $docsOut -Force
-Copy-Item (Join-Path $root 'docs\known-limitations.md') $docsOut -Force
-Copy-Item (Join-Path $root 'docs\safety-boundaries.md') $docsOut -Force
-Copy-Item (Join-Path $root 'docs\subscriber-verification-app.md') $docsOut -Force
+$script = Join-Path $PSScriptRoot 'scripts\publish-release.ps1'
+& $script -Version $Version -Runtime $Runtime -SkipTests:$SkipTests
-Compress-Archive -Path (Join-Path $out '*') -DestinationPath $zipPath -Force
-Write-Host "Created $zipPath"
+if ($LASTEXITCODE -ne 0) {
+ exit $LASTEXITCODE
+}
diff --git a/scripts/publish-release.ps1 b/scripts/publish-release.ps1
new file mode 100644
index 0000000..0d9b52e
--- /dev/null
+++ b/scripts/publish-release.ps1
@@ -0,0 +1,168 @@
+param(
+ [string] $Version = '0.0.0-dev',
+ [string] $Runtime = 'win-x64',
+ [switch] $SkipTests
+)
+
+$ErrorActionPreference = 'Stop'
+Set-StrictMode -Version Latest
+
+$root = Split-Path -Parent $PSScriptRoot
+$artifactRoot = Join-Path $root 'artifacts'
+$releaseRoot = Join-Path $artifactRoot 'release'
+$tempRoot = Join-Path $artifactRoot 'publish-temp'
+$portableRoot = Join-Path $artifactRoot 'ARSVIN-win-x64'
+$installerInput = Join-Path $artifactRoot 'installer-input'
+
+$publisherProject = Join-Path $root 'src\ARSVIN\ARSVIN.csproj'
+$subscriberProject = Join-Path $root 'src\ARSVIN.Subscriber\ARSVIN.Subscriber.csproj'
+$testProject = Join-Path $root 'tests\ARSVIN.Tests\ARSVIN.Tests.csproj'
+
+$normalizedVersion = ($Version.Trim() -replace '^[vV]', '')
+if ($normalizedVersion -notmatch '^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$') {
+ throw "Version '$Version' is not a supported semantic version. Example: 1.2.3 or 1.2.3-beta.1."
+}
+
+$coreVersion = ($normalizedVersion -split '[-+]')[0]
+$fileVersion = "$coreVersion.0"
+$informationalVersion = $normalizedVersion
+
+function Invoke-DotNet {
+ param(
+ [Parameter(Mandatory)]
+ [string[]] $Arguments
+ )
+
+ & dotnet @Arguments
+ if ($LASTEXITCODE -ne 0) {
+ throw "dotnet $($Arguments -join ' ') failed with exit code $LASTEXITCODE."
+ }
+}
+
+function Reset-Directory {
+ param([Parameter(Mandatory)][string] $Path)
+
+ if (Test-Path $Path) {
+ Remove-Item $Path -Recurse -Force
+ }
+ New-Item -ItemType Directory -Path $Path -Force | Out-Null
+}
+
+function Copy-ReleaseDocumentation {
+ param([Parameter(Mandatory)][string] $Destination)
+
+ New-Item -ItemType Directory -Path $Destination -Force | Out-Null
+
+ Copy-Item (Join-Path $root 'README.md') (Join-Path $Destination 'README.md') -Force
+ Copy-Item (Join-Path $root 'LICENSE') (Join-Path $Destination 'LICENSE.txt') -Force
+ Copy-Item (Join-Path $root 'NOTICE') (Join-Path $Destination 'NOTICE.txt') -Force
+ Copy-Item (Join-Path $root 'THIRD_PARTY_NOTICES.md') (Join-Path $Destination 'THIRD_PARTY_NOTICES.md') -Force
+
+ $docsOut = Join-Path $Destination 'docs'
+ New-Item -ItemType Directory -Path $docsOut -Force | Out-Null
+
+ $documents = @(
+ 'quick-start.md',
+ 'live-mode-safety.md',
+ 'known-limitations.md',
+ 'safety-boundaries.md',
+ 'subscriber-verification-app.md',
+ 'arsubsv-sv-scout-companion.md'
+ )
+
+ foreach ($document in $documents) {
+ $source = Join-Path $root "docs\$document"
+ if (Test-Path $source) {
+ Copy-Item $source $docsOut -Force
+ }
+ }
+
+ $samplesSource = Join-Path $root 'samples'
+ if (Test-Path $samplesSource) {
+ Copy-Item $samplesSource (Join-Path $Destination 'samples') -Recurse -Force
+ }
+}
+
+Reset-Directory $releaseRoot
+Reset-Directory $tempRoot
+Reset-Directory $portableRoot
+Reset-Directory $installerInput
+
+if (-not $SkipTests) {
+ Write-Host '==> Restoring and testing'
+ Invoke-DotNet -Arguments @('restore', $publisherProject)
+ Invoke-DotNet -Arguments @('restore', $subscriberProject)
+ Invoke-DotNet -Arguments @('restore', $testProject)
+ Invoke-DotNet -Arguments @('test', $testProject, '-c', 'Release', '--no-restore')
+}
+
+$commonPublishArguments = @(
+ '-c', 'Release',
+ '-r', $Runtime,
+ '--self-contained', 'true',
+ '-p:PublishSingleFile=true',
+ '-p:IncludeNativeLibrariesForSelfExtract=true',
+ '-p:EnableCompressionInSingleFile=true',
+ '-p:PublishReadyToRun=false',
+ '-p:DebugType=None',
+ '-p:DebugSymbols=false',
+ "-p:Version=$normalizedVersion",
+ "-p:FileVersion=$fileVersion",
+ "-p:AssemblyVersion=$fileVersion",
+ "-p:InformationalVersion=$informationalVersion"
+)
+
+$publisherOut = Join-Path $tempRoot 'publisher'
+$subscriberOut = Join-Path $tempRoot 'subscriber'
+
+Write-Host "==> Publishing ARSVIN Publisher $normalizedVersion"
+Invoke-DotNet -Arguments (@('publish', $publisherProject) + $commonPublishArguments + @('-o', $publisherOut))
+
+Write-Host "==> Publishing ArSubsv Subscriber $normalizedVersion"
+Invoke-DotNet -Arguments (@('publish', $subscriberProject) + $commonPublishArguments + @('-o', $subscriberOut))
+
+$publisherExe = Join-Path $publisherOut 'ARSVIN.exe'
+$subscriberExe = Join-Path $subscriberOut 'ARSVIN.Subscriber.exe'
+
+if (-not (Test-Path $publisherExe)) {
+ throw "Publisher executable was not found: $publisherExe"
+}
+if (-not (Test-Path $subscriberExe)) {
+ throw "Subscriber executable was not found: $subscriberExe"
+}
+
+$publisherPortable = Join-Path $releaseRoot 'ARSVIN-Publisher-win-x64.exe'
+$subscriberPortable = Join-Path $releaseRoot 'ArSubsv-Subscriber-win-x64.exe'
+
+Copy-Item $publisherExe $publisherPortable -Force
+Copy-Item $subscriberExe $subscriberPortable -Force
+
+Copy-Item $publisherExe (Join-Path $portableRoot 'ARSVIN.exe') -Force
+Copy-Item $subscriberExe (Join-Path $portableRoot 'ArSubsv.exe') -Force
+Copy-ReleaseDocumentation -Destination $portableRoot
+
+Copy-Item $publisherExe (Join-Path $installerInput 'ARSVIN.exe') -Force
+Copy-Item $subscriberExe (Join-Path $installerInput 'ArSubsv.exe') -Force
+Copy-ReleaseDocumentation -Destination $installerInput
+
+$versionFile = @"
+ARSVIN Suite
+Version: $normalizedVersion
+Runtime: $Runtime
+Publisher: ARSVIN.exe
+Subscriber: ArSubsv.exe
+"@
+Set-Content -Path (Join-Path $portableRoot 'VERSION.txt') -Value $versionFile -Encoding utf8
+Set-Content -Path (Join-Path $installerInput 'VERSION.txt') -Value $versionFile -Encoding utf8
+
+$portableZip = Join-Path $releaseRoot 'ARSVIN-win-x64-portable.zip'
+if (Test-Path $portableZip) {
+ Remove-Item $portableZip -Force
+}
+Compress-Archive -Path (Join-Path $portableRoot '*') -DestinationPath $portableZip -CompressionLevel Optimal -Force
+
+Write-Host '==> Portable release artifacts'
+Get-ChildItem $releaseRoot -File | Select-Object Name, Length | Format-Table -AutoSize
+
+Write-Host "Release output: $releaseRoot"
+Write-Host "Installer input: $installerInput"
diff --git a/site/assets/arsvin-publisher-sv-setup.webp b/site/assets/arsvin-publisher-sv-setup.webp
new file mode 100644
index 0000000..6e3cc10
Binary files /dev/null and b/site/assets/arsvin-publisher-sv-setup.webp differ
diff --git a/site/assets/arsvin-subscriber-live-analysis.webp b/site/assets/arsvin-subscriber-live-analysis.webp
new file mode 100644
index 0000000..774ca0b
Binary files /dev/null and b/site/assets/arsvin-subscriber-live-analysis.webp differ
diff --git a/site/assets/arsvin-subscriber-waveform-phasor.webp b/site/assets/arsvin-subscriber-waveform-phasor.webp
new file mode 100644
index 0000000..8277a78
Binary files /dev/null and b/site/assets/arsvin-subscriber-waveform-phasor.webp differ
diff --git a/site/index.html b/site/index.html
index 38c2614..95f5d08 100644
--- a/site/index.html
+++ b/site/index.html
@@ -3,23 +3,26 @@
-