From da08fbe15feff5f4e560665e85c056895edffbe1 Mon Sep 17 00:00:00 2001 From: masarray Date: Sat, 11 Jul 2026 02:26:36 +0700 Subject: [PATCH 01/21] Rewrite public README for ARSVIN suite --- README.md | 275 ++++++++++++++++++++++-------------------------------- 1 file changed, 109 insertions(+), 166 deletions(-) diff --git a/README.md b/README.md index ba086ee..5bf6003 100644 --- a/README.md +++ b/README.md @@ -1,132 +1,119 @@ -# ARSVIN — IEC 61850 Sampled Values Publisher for Windows +# ARSVIN — Open-Source IEC 61850 Sampled Values Workbench for Windows [![CI](https://github.com/masarray/arsvin/actions/workflows/ci.yml/badge.svg)](https://github.com/masarray/arsvin/actions/workflows/ci.yml) [![Release](https://github.com/masarray/arsvin/actions/workflows/release.yml/badge.svg)](https://github.com/masarray/arsvin/actions/workflows/release.yml) [![CodeQL](https://github.com/masarray/arsvin/actions/workflows/codeql.yml/badge.svg)](https://github.com/masarray/arsvin/actions/workflows/codeql.yml) [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE) -[![Platform](https://img.shields.io/badge/platform-Windows-0078D4.svg)](#requirements) +[![Platform](https://img.shields.io/badge/platform-Windows%2010%2F11-0078D4.svg)](#system-requirements) [![.NET](https://img.shields.io/badge/.NET-8.0-512BD4.svg)](#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.

- ARSVIN IEC 61850 Sampled Values Publisher preview showing SCL setup, nofASDU, TX timing health, PCAP evidence, and scenario presets + ARSVIN IEC 61850 Sampled Values Publisher interface with SCL stream setup, TX timing health, scenario controls, and evidence export

- 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 +## Two focused applications -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. - -ARSVIN is intentionally narrow: - -```text -SCL-driven SV publishing → TX timing visibility → generated PCAP/report evidence -``` +| 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 +123,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). From 286b25a54a29cffd9e3e7cbc4a2f6579485df11a Mon Sep 17 00:00:00 2001 From: masarray Date: Sat, 11 Jul 2026 02:26:44 +0700 Subject: [PATCH 02/21] Harden build script exit handling --- build.ps1 | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) 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' From 97566f030daf1329bb09a14e209fe14b42fb7529 Mon Sep 17 00:00:00 2001 From: masarray Date: Sat, 11 Jul 2026 02:26:56 +0700 Subject: [PATCH 03/21] Add portable EXE and installer release automation --- .github/workflows/release.yml | 121 +++++++++++++++++++++++++++++++--- 1 file changed, 111 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d491522..193a040 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@v2 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 From 0e9649f9521c3bb22b16e89ad18d4e6c4af8f196 Mon Sep 17 00:00:00 2001 From: masarray Date: Sat, 11 Jul 2026 02:27:17 +0700 Subject: [PATCH 04/21] Add repeatable release packaging script --- scripts/publish-release.ps1 | 168 ++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 scripts/publish-release.ps1 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" From 425ccb8e584e393f02722aece8fef02d14a4fbd7 Mon Sep 17 00:00:00 2001 From: masarray Date: Sat, 11 Jul 2026 02:27:23 +0700 Subject: [PATCH 05/21] Keep portable publish wrapper compatible --- publish-win-x64.ps1 | 65 +++++++++------------------------------------ 1 file changed, 12 insertions(+), 53 deletions(-) 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 +} From 81a81c4a3ba76fa9cdbbcac870085b70a25ec15f Mon Sep 17 00:00:00 2001 From: masarray Date: Sat, 11 Jul 2026 02:27:37 +0700 Subject: [PATCH 06/21] Add ARSVIN Suite Inno Setup installer --- installer/ARSVIN.iss | 97 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 installer/ARSVIN.iss 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; From 9c37f542fa8863fc9ecac9a809f0eeb8e45e47d9 Mon Sep 17 00:00:00 2001 From: masarray Date: Sat, 11 Jul 2026 02:27:54 +0700 Subject: [PATCH 07/21] Document portable and installer release process --- docs/build-and-release.md | 147 +++++++++++++++++++++++++++++++------- 1 file changed, 122 insertions(+), 25 deletions(-) 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). From acf880a6ebd73c7122cc739f227755a79218c54c Mon Sep 17 00:00:00 2001 From: masarray Date: Sat, 11 Jul 2026 02:28:28 +0700 Subject: [PATCH 08/21] Redesign public landing page for ARSVIN suite --- site/index.html | 303 +++++++++++++++++++++++++++++++----------------- 1 file changed, 196 insertions(+), 107 deletions(-) diff --git a/site/index.html b/site/index.html index 38c2614..113be91 100644 --- a/site/index.html +++ b/site/index.html @@ -3,23 +3,26 @@ - ARSVIN — IEC 61850 Sampled Values Publisher for Windows - + ARSVIN — Open-Source IEC 61850 Sampled Values Publisher & Subscriber + + - - + + + + - - + + @@ -32,19 +35,25 @@ "@context": "https://schema.org", "@type": "SoftwareApplication", "name": "ARSVIN", - "alternateName": "ARSVIN IEC 61850 Sampled Values Publisher", + "alternateName": "ARSVIN IEC 61850 Sampled Values Workbench", "applicationCategory": "EngineeringApplication", - "operatingSystem": "Windows 10/11 x64", - "softwareRequirements": "Npcap, .NET 8 SDK for source builds", + "applicationSubCategory": "Substation automation and process bus engineering", + "operatingSystem": "Windows 10, Windows 11", "license": "https://www.apache.org/licenses/LICENSE-2.0", + "isAccessibleForFree": true, "codeRepository": "https://github.com/masarray/arsvin", "url": "https://masarray.github.io/arsvin/", - "downloadUrl": "https://github.com/masarray/arsvin/releases", + "downloadUrl": "https://github.com/masarray/arsvin/releases/latest", "image": "https://masarray.github.io/arsvin/assets/arsvin-social-preview.png", - "author": { "@type": "Person", "name": "Ari Sulistiono", "url": "https://github.com/masarray" }, - "description": "Apache-2.0 IEC 61850 Sampled Values Publisher for Windows with SCL setup, nofASDU support, COMTRADE replay, TX timing health, per-phase scenario presets, and PCAP evidence export for isolated lab use." + "author": { + "@type": "Person", + "name": "Ari Sulistiono", + "url": "https://github.com/masarray" + }, + "description": "Apache-2.0 IEC 61850 Sampled Values Publisher and Subscriber suite for Windows with SCL-driven stream setup, COMTRADE replay, live and PCAP analysis, waveform, phasor, RMS, timing health, and evidence export." } +