Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 0 additions & 68 deletions .github/workflows/arstack-winget-manifest.yml

This file was deleted.

166 changes: 166 additions & 0 deletions .github/workflows/m3h1-cross-platform-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
name: Publish M3.H.1 Cross-Platform Packaging Release

on:
pull_request:
paths:
- '.github/workflows/m3h1-cross-platform-release.yml'
- 'docs/releases/M3H1_CROSS_PLATFORM_RELEASE.md'
push:
branches: [main]
paths:
- '.github/workflows/m3h1-cross-platform-release.yml'
- 'docs/releases/M3H1_CROSS_PLATFORM_RELEASE.md'
workflow_dispatch:

permissions:
contents: read
actions: read

concurrency:
group: m3h1-once-release
cancel-in-progress: false

jobs:
validate:
name: Validate immutable cross-platform packaging plan
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- name: Verify release notes and pinned Linux acceptance
run: |
set -euo pipefail
grep -Fq 'same verified M3.H SV/PTP core' docs/releases/M3H1_CROSS_PLATFORM_RELEASE.md
grep -Fq 'Linux x86_64' docs/releases/M3H1_CROSS_PLATFORM_RELEASE.md
test -s docs/INSTALL.md
test ! -e scripts/generate_winget_manifest.py
test ! -e .github/workflows/arstack-winget-manifest.yml
echo 'PASS: packaging-only plan and direct downloads'

publish:
name: Publish Windows + verified Linux with exact SHA provenance
needs: validate
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: write
actions: read
env:
GH_TOKEN: ${{ github.token }}
ORIGINAL_TAG: processbus-sim-m3h-20261024
CROSS_PLATFORM_TAG: processbus-sim-m3h1-20261024
ORIGINAL_SOURCE_TAG_SHA: a4b6e53d0dbbcababc55ba8a4ff97ade6f2a6200
LINUX_ACCEPTANCE_RUN: '40089029880'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Confirm original release and accepted Linux run
run: |
set -euo pipefail
test "$(git rev-parse "$ORIGINAL_TAG^{commit}")" = "$ORIGINAL_SOURCE_TAG_SHA"
gh api "repos/$GITHUB_REPOSITORY/releases/latest" > /tmp/release-latest.json
gh api "repos/$GITHUB_REPOSITORY/releases/tags/$ORIGINAL_TAG" > /tmp/release-original.json
gh api "repos/$GITHUB_REPOSITORY/actions/runs/$LINUX_ACCEPTANCE_RUN" > /tmp/linux-run.json
python3 - <<'PY'
import json
original=json.load(open('/tmp/release-original.json'))
latest=json.load(open('/tmp/release-latest.json'))
linux=json.load(open('/tmp/linux-run.json'))
assert original['id']==422544367 and not original['prerelease'] and not original['draft']
assert latest['id']==original['id'], 'A newer stable release already exists; do not supersede'
assert linux['conclusion']=='success' and linux['path'].endswith('m3h-exact-tag-linux-artifact.yml'), 'Linux candidate not accepted'
assert linux['head_sha']=='95d846e7c2ca06878f4a301c5e477002c4e00f77', 'Unexpected acceptance head'
expected={
'ARStack-ProcessBus-M3H-win-x64-setup.exe':'4902e8bf44e78fc55a139ce84a1273f0768ef6fe10000f5d0f85d75d2f6c736e',
'ARStack-ProcessBus-M3H-win-x64-portable.zip':'ca01424e4102aa65e353737024ebf3258b4d2f614fa60d932c95c353ee228d8f',
'ARStack-ESP32P4-ProcessBus-M3H-firmware.bin':'61c508e9bf1357eb964d2b817b260b6a0e985446ddd68de1d45d9467e25c4607',
'firmware-manifest.json':'b2878148a1cda30f11a4c93a200bcba07bb63548aa571de8d05260c2ef630f9a',
'SHA256SUMS.txt':'c7674d1a97b77b66adda12216f7d5e460f86da5cb07fd1d1f02bf3011b99c876',
}
assets={x['name']:(x.get('digest') or '').removeprefix('sha256:') for x in original['assets']}
assert assets==expected, 'Original five release artifacts do not match accepted hashes'
print('PASS: original stable release untouched and exact Linux acceptance validated')
PY
if gh release view "$CROSS_PLATFORM_TAG" >/dev/null 2>&1; then
echo 'Cross-platform release tag already exists; refusing overwrite' >&2
exit 1
fi

- name: Download five original verified release assets
run: |
set -euo pipefail
mkdir -p staging
gh release download "$ORIGINAL_TAG" --dir staging

- name: Fetch independently accepted M3.H Linux CI package
uses: actions/download-artifact@v4
with:
name: m3h-exact-tag-linux-candidate
run-id: 40089029880
github-token: ${{ github.token }}
path: linux-candidate

- name: Verify Linux artifact and build cross-platform checksum manifest
run: |
set -euo pipefail
(cd linux-candidate && sha256sum -c ARStack-Studio-M3H-exact-tag-linux-x86_64.sha256)
cp linux-candidate/ARStack-Studio-M3H-exact-tag-linux-x86_64.AppImage staging/ARStack-Studio-linux-x86_64.AppImage
python3 - <<'PY'
from pathlib import Path
import hashlib,json
root=Path('staging')
expected={
'ARStack-ProcessBus-M3H-win-x64-setup.exe':'4902e8bf44e78fc55a139ce84a1273f0768ef6fe10000f5d0f85d75d2f6c736e',
'ARStack-ProcessBus-M3H-win-x64-portable.zip':'ca01424e4102aa65e353737024ebf3258b4d2f614fa60d932c95c353ee228d8f',
'ARStack-ESP32P4-ProcessBus-M3H-firmware.bin':'61c508e9bf1357eb964d2b817b260b6a0e985446ddd68de1d45d9467e25c4607',
'firmware-manifest.json':'b2878148a1cda30f11a4c93a200bcba07bb63548aa571de8d05260c2ef630f9a'
}
for n,d in expected.items():
assert hashlib.sha256((root/n).read_bytes()).hexdigest()==d, f'Immutable original bytes changed: {n}'
assert json.loads((root/'firmware-manifest.json').read_text())['buildId']=='a922e9bdba4e57a4'
# Old original checksum file is retained in the source M3.H release;
# replace it ONLY in this new cross-platform release to include Linux.
(root/'SHA256SUMS.txt').unlink()
names=sorted(x.name for x in root.iterdir() if x.is_file() and x.name!='SHA256SUMS.txt')
(root/'SHA256SUMS.txt').write_text(''.join(
hashlib.sha256((root/n).read_bytes()).hexdigest()+' '+n+'\n' for n in names))
linux='ARStack-Studio-linux-x86_64.AppImage'
(root/'ARStack-Studio-linux-x86_64.sha256').write_text(
hashlib.sha256((root/linux).read_bytes()).hexdigest()+' '+linux+'\n')
print('PASS: same Windows/firmware bytes, verified Linux, new checksums')
PY
(cd staging && sha256sum -c SHA256SUMS.txt && sha256sum -c ARStack-Studio-linux-x86_64.sha256)
test "$(find staging -maxdepth 1 -type f | wc -l)" = 7

- name: Publish new stable packaging-only release
run: |
set -euo pipefail
gh release create "$CROSS_PLATFORM_TAG" staging/* \
--repo "$GITHUB_REPOSITORY" \
--target "$ORIGINAL_SOURCE_TAG_SHA" \
--title "ARStack Process Bus Simulator M3.H.1 — Cross-Platform Edition" \
--notes-file docs/releases/M3H1_CROSS_PLATFORM_RELEASE.md \
--latest

- name: Verify published release is complete without mutating original
run: |
set -euo pipefail
gh api "repos/$GITHUB_REPOSITORY/releases/tags/$CROSS_PLATFORM_TAG" > /tmp/release-cross-platform.json
gh api "repos/$GITHUB_REPOSITORY/releases/tags/$ORIGINAL_TAG" > /tmp/release-original-after.json
python3 - <<'PY'
import json,hashlib
before=json.load(open('/tmp/release-original.json'))
old=json.load(open('/tmp/release-original-after.json'))
new=json.load(open('/tmp/release-cross-platform.json'))
assert not new['draft'] and not new['prerelease'] and new['tag_name']=='processbus-sim-m3h1-20261024'
def records(r):
return sorted((a['id'],a['name'],a['size'],a.get('digest')) for a in r['assets'])
assert records(before)==records(old), 'Original M3.H assets changed'
assert len(new['assets'])==7
for a in new['assets']:
actual=hashlib.sha256(open('staging/'+a['name'],'rb').read()).hexdigest()
assert a.get('digest')=='sha256:'+actual, 'New release hash mismatch: '+a['name']
print('PASS: new stable Windows+Linux release verified; original M3.H assets and identity preserved')
PY
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ For active SV/PTP transmission, use an **isolated laboratory Ethernet network**,
| Windows Portable ZIP | **Available** in the [latest release](https://github.com/masarray/arstack61850/releases/latest) |
| Matched ESP32-P4 firmware | **Available** with the same release |
| Linux AppImage | Shown in the [latest release](https://github.com/masarray/arstack61850/releases/latest) when a tested package is published |
| Windows package manager | [WinGet preparation and status](docs/INSTALL.md#windows-package-manager--winget) |

Every published Windows release includes the application dependencies and a matched firmware package; no C++ build environment is required for ordinary installation.

Expand All @@ -53,7 +52,8 @@ Every published Windows release includes the application dependencies and a matc
ARStack is built to make IEC 61850 experiments more accessible to engineers, students and automation enthusiasts around the world.

- **[Ask a question or report a problem](SUPPORT.md)** — share what you tried and what happened.
- **[Share an interoperability experiment](docs/COMMUNITY_TESTING.md)** — feedback from independent laboratory setups helps improve the project.
- **[Share an interoperability experiment](docs/COMMUNITY_TESTING.md)** — independent lab experiences help improve the project; [browse community reports](docs/community/README.md).
- **[SCL import help](docs/SCL_TROUBLESHOOTING.md)** — a practical path when imported SV fields do not appear.
- **[Contribute](CONTRIBUTING.md)** — improvements to documentation, software, tests and examples are welcome.

ARStack uses the [GPL-3.0 license](LICENSE). It is a laboratory simulation and engineering tool, not a certified primary measurement or UTC reference device.
Expand Down
2 changes: 1 addition & 1 deletion SUPPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Use the [simple bug-report form](https://github.com/masarray/arstack61850/issues

Useful details include the Studio release, Windows version, ESP32-P4 firmware build if connected, the exact error shown and the last action you tried.

**SCL import issue?** Share a screenshot of the validation result and, if permissible, a sanitized SCL/CID/SCD/IID file that reproduces it. Never share confidential installation data.
**SCL import issue?** Follow the [SCL import troubleshooting steps](docs/SCL_TROUBLESHOOTING.md). Share the Studio version, stream selection and a sanitized sample if possible. Never share confidential installation data.

**Can't find the board?** Check the USB data cable and serial device selection; use **Configuration → Firmware** to verify the ESP32-P4 and install matching firmware.

Expand Down
2 changes: 1 addition & 1 deletion docs/COMMUNITY_TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Have you tried ARStack with a simulator, analyzer, protection relay or bay controller in your own lab? Your results can help the international IEC 61850 community discover useful configurations and improve ARStack.

**[Share an interoperability report](https://github.com/masarray/arstack61850/issues/new?template=interoperability.yml)** · [Ask for help](../SUPPORT.md)
**[Share an interoperability report](https://github.com/masarray/arstack61850/issues/new?template=interoperability.yml)** · [Browse community reports](community/README.md) · [Ask for help](../SUPPORT.md)

## What is helpful to share?

Expand Down
2 changes: 1 addition & 1 deletion docs/GETTING_STARTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Adjust a voltage or current setpoint and observe the generated waveform. Open a

## Need help?

Check the [installation guide](INSTALL.md) or [support guide](../SUPPORT.md). If a file does not import or a device will not connect, share the Studio version, the error message and a sanitized example file if possible.
Check the [installation guide](INSTALL.md) or [support guide](../SUPPORT.md). For an SCL import where SV ID or MAC address does not appear, follow the [SCL troubleshooting guide](SCL_TROUBLESHOOTING.md). If a device will not connect, share the Studio version and the displayed error.

Want to publish observations from another IEC 61850 tool or device? See the [community testing guide](COMMUNITY_TESTING.md).

Expand Down
14 changes: 1 addition & 13 deletions docs/INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ To download a verified copy without starting the installer, run `& $script -Down

## Linux (x86_64)

When the latest GitHub release offers `ARStack-Studio-linux-x86_64.AppImage`, download it, mark it executable (`chmod +x`) and open it. You can also install it into your home folder with:
For Linux x86_64, download `ARStack-Studio-linux-x86_64.AppImage` from the [latest stable release](https://github.com/masarray/arstack61850/releases/latest) when listed. Mark it executable (`chmod +x`) and open it. You can also install it into your home folder with:

```bash
curl -fLsS https://raw.githubusercontent.com/masarray/arstack61850/main/scripts/install-linux.sh -o /tmp/arstack-install-linux.sh
Expand All @@ -27,18 +27,6 @@ bash /tmp/arstack-install-linux.sh

The install script checks the matching published SHA-256. It will explain when the current release does not yet contain a Linux build rather than downloading an older or unverified binary. The AppImage build is only published after Linux CI succeeds.

## Windows Package Manager / WinGet

WinGet uses an indexed, versioned package manifest. The release tooling prepares a manifest from the actual installer and SHA-256 once a release is final. The Microsoft community repository must accept the package **before** a public `winget install MasArray.ARStackStudio` command works; until then, use the Windows command above. A script or README alone does not register a WinGet package.

Maintainer command (requires a tagged release with a unique Windows package version):

```bash
python3 scripts/generate_winget_manifest.py --version X.Y.Z --installer-type inno
```

Review the generated YAML, validate with WinGet tooling, and submit it to [microsoft/winget-pkgs](https://github.com/microsoft/winget-pkgs). Use `--installer-type nullsoft` for the earlier NSIS installer format.

## First lab experiment

1. Open **ARStack Studio** and start from the built-in 4I+4V profile.
Expand Down
35 changes: 35 additions & 0 deletions docs/SCL_TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# SCL import troubleshooting — find your SV stream

If ARStack Studio opens an SCL file but does not show the SV ID, multicast MAC or publisher configuration you expected, these steps help narrow down what happened.

## 1. Start with the latest Studio

Download the [latest stable release](https://github.com/masarray/arstack61850/releases/latest). Check the installed version in Studio before comparing behavior with other engineering tools.

## 2. Open the actual engineering file

Use **Open SCL** with your `.scd`, `.cid`, `.icd` or `.iid` file. Successful XML import tells you the file was read; it does not automatically select an SV publisher or deploy it to the board.

Look for the file's IED, AccessPoint, logical device, SV control block and DataSet. If the file contains several publishers, select the intended SV stream before evaluating its fields.

## 3. Check the publisher address mapping

For a stream configured in SCL, `svID` is commonly associated with `SampledValueControl`, while multicast MAC address and APPID appear in the relevant `Communication/ConnectedAP/SMV/Address` mapping. A valid file can have more than one candidate stream.

If the SV ID or MAC is blank, inspect the Studio stream selection and validation messages. A file that opens successfully might still lack a selectable deployment profile in the current reference workflow.

## 4. Try the 4I+4V Quick Start

Choose **4I+4V Quick Start** and verify that the supported SV publisher profile appears. This is a useful comparison against the imported SCL. For real network output, firmware on the ESP32-P4 must match the Studio release.

## 5. Share a reproducer

If the SV fields still do not appear:

- Note the **ARStack Studio version** and which SCL IED / stream you selected.
- Capture a screenshot of the import result and any validation messages.
- Share the smallest **sanitized SCL** file that reproduces the behavior, either through the [bug report form](https://github.com/masarray/arstack61850/issues/new?template=bug_report.yml) or a private message/link to the maintainer when you are already in contact.

Remove project names, substation identifiers and other confidential engineering data before sharing files. We welcome files generated by different IEC 61850 engineering environments because they help make import workflows easier for everyone.

[Back to Getting Started](GETTING_STARTED.md) · [Support](../SUPPORT.md)
Loading
Loading