diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6504455..530c651 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: - name: Test with whole-engine and protocol-core coverage gates shell: pwsh - run: .\scripts\test-with-coverage.ps1 -MinimumWholeEngineLineCoverage 5.5 -MinimumLineCoverage 50 -NoRestore + run: .\scripts\test-with-coverage.ps1 -MinimumWholeEngineLineCoverage 10.5 -MinimumLineCoverage 60 -NoRestore - name: Upload test and coverage evidence if: always() diff --git a/CHANGELOG.md b/CHANGELOG.md index 354abd5..57a8cb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,8 @@ All notable ARSVIN changes are documented here using a lightweight Keep a Change - Added recursive validation for all HTML metadata, structured data, canonical uniqueness, local references, search-index targets, sitemap coverage, web-manifest icons, and robots metadata. - Added committed NuGet lock files for Publisher, Subscriber, the shared engine, and Tests. - Added CI evidence upload for the committed dependency lock graph. -- Added a 5.5% whole-engine line-coverage regression floor alongside the existing 50% protocol-core floor. +- Added whole-engine and protocol-core regression floors of 10.5% and 60% respectively. +- Expanded the deterministic test suite from 26 to 54 tests across SCL, COMTRADE, PCAP, MMS, diagnostics, and Sampled Values publisher sessions. ### Changed @@ -23,6 +24,12 @@ All notable ARSVIN changes are documented here using a lightweight Keep a Change - README, build guidance, contributor guidance, repository structure, release examples, and coverage baselines now match the current shared-engine implementation. - CI, CodeQL, and release validation now use the explicit `windows-2025` runner image; Pages and release publication use `ubuntu-24.04`. - GitHub Pages now retriggers when the Python public-site validator changes. +- Moved all shared engine source physically from `src/ARSVIN/Engine` into the owning `src/ARSVIN.Engine` project without duplicating compilation. +- Raised whole-engine line coverage from 5.64% to 10.74% and protocol-core coverage from 57.89% to 64.97%. + +### Fixed + +- Multi-ASDU Publisher sessions now apply the configured `smpCnt` wrap to every ASDU inside a frame, preventing counters such as `4000` and `4001` when a 4,000-sample wrap is configured. ### Security @@ -32,8 +39,7 @@ All notable ARSVIN changes are documented here using a lightweight Keep a Change ### Planned -- Move the engine source directory physically under `src/ARSVIN.Engine` after the shared-assembly transition has proven stable. -- Expand protocol regression tests and raise the whole-engine coverage baseline progressively. +- Continue expanding deterministic regression tests for remaining live capture, MMS service, scheduling, and device-interoperability paths. - Add Windows Authenticode signing when a trusted certificate becomes available. ## 0.3.1 — 2026-07-12 diff --git a/README.md b/README.md index b0de73e..689ba81 100644 --- a/README.md +++ b/README.md @@ -154,13 +154,13 @@ Compatibility wrapper: .\publish-win-x64.ps1 -Version 0.3.1 ``` -Run tests with the repository coverage gate and retain TRX/Cobertura evidence: +Run tests with both repository coverage gates and retain TRX/Cobertura evidence: ```powershell -.\scripts\test-with-coverage.ps1 -MinimumLineCoverage 50 +.\scripts\test-with-coverage.ps1 -MinimumWholeEngineLineCoverage 10.5 -MinimumLineCoverage 60 ``` -The complete shared `ARSVIN.Engine` baseline currently measures 5.64% line coverage across 15,726 instrumented production lines. The established protocol-core regression surface measures 57.89% across 1,534 lines, with 888 covered lines; CI enforces a 50% floor on that tested protocol-core surface while broader engine tests are added. +The current suite contains 54 deterministic tests. The complete shared `ARSVIN.Engine` baseline measures 10.74% line coverage across 15,742 instrumented production lines, with 1,691 covered lines. The protocol-core regression surface measures 64.97% across 1,550 lines, with 1,007 covered lines. CI enforces floors of 10.5% for the whole engine and 60% for protocol core. Generate a CycloneDX SBOM after restoring the solution: @@ -171,19 +171,21 @@ Generate a CycloneDX SBOM after restoring the solution: ## Repository structure ```text -src/ARSVIN.Engine/ Shared IEC 61850 protocol, SCL, capture, transport, and SV engine project -src/ARSVIN/ Publisher application -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 and validation 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 +src/ARSVIN.Engine/ Shared production engine project and source ownership +src/ARSVIN.Engine/AR.Iec61850/ IEC 61850, SCL, SV, MMS, capture, diagnostics, and protocol code +src/ARSVIN.Engine/AR.Iec61850.Transports.Npcap/ Npcap transport implementation +src/ARSVIN/ Publisher application +src/ARSVIN.Subscriber/ ArSubsv subscriber and visualization companion +tests/ARSVIN.Tests/ Deterministic engine and publisher regression tests +installer/ Inno Setup definition for the Windows suite +scripts/ Repeatable release packaging and validation 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 ``` -The shared engine is compiled once as `ARSVIN.Engine`; its source files are still physically located under `src/ARSVIN/Engine` during the staged directory migration. +The shared engine is compiled once as `ARSVIN.Engine`, and its source is physically owned by the same `src/ARSVIN.Engine` project used by Publisher, Subscriber, and Tests. ## Documentation diff --git a/docs/build-and-release.md b/docs/build-and-release.md index 94da99e..c81189a 100644 --- a/docs/build-and-release.md +++ b/docs/build-and-release.md @@ -48,12 +48,14 @@ The script restores the solution in locked mode, then builds and tests: - `src/ARSVIN.Subscriber/ARSVIN.Subscriber.csproj` - `tests/ARSVIN.Tests/ARSVIN.Tests.csproj` +The shared production source is physically owned by `src/ARSVIN.Engine`, including `AR.Iec61850` and the Npcap transport implementation. Publisher, Subscriber, and Tests all reference that same compiled assembly. + External command exit codes are checked, and compiler warnings are treated as errors for the validated build path. ### Coverage evidence ```powershell -.\scripts\test-with-coverage.ps1 -MinimumLineCoverage 50 +.\scripts\test-with-coverage.ps1 -MinimumWholeEngineLineCoverage 10.5 -MinimumLineCoverage 60 ``` The script: @@ -61,22 +63,24 @@ The script: 1. runs the xUnit suite using pinned Coverlet MSBuild instrumentation, 2. instruments the complete shared production `ARSVIN.Engine` assembly, 3. writes TRX, the complete `dotnet test` log, and Cobertura evidence under `artifacts/test-results`, -4. reports whole-engine coverage transparently, -5. calculates the regression gate over the established protocol-core surface, -6. fails when no production lines are instrumented or protocol-core coverage falls below the configured threshold. +4. calculates and enforces the whole-engine regression floor, +5. calculates and enforces the established protocol-core regression floor, +6. fails when no production lines are instrumented or either configured floor is missed. -Current verified baselines: +Current verified baselines from 54 deterministic tests: | Metric | Result | |---|---:| -| Whole `ARSVIN.Engine` instrumented lines | 15,726 | -| Whole-engine line coverage | 5.64% | -| Protocol-core instrumented lines | 1,534 | -| Protocol-core covered lines | 888 | -| Protocol-core line coverage | 57.89% | -| Enforced protocol-core floor | 50% | - -This is not a claim that the complete WPF UI or every live-network path is covered. Whole-engine coverage is intentionally shown as a transparent baseline and must rise as SCL, COMTRADE, capture, diagnostics, MMS, scheduling, and transport tests are expanded. +| Whole `ARSVIN.Engine` instrumented lines | 15,742 | +| Whole-engine covered lines | 1,691 | +| Whole-engine line coverage | 10.74% | +| Enforced whole-engine floor | 10.5% | +| Protocol-core instrumented lines | 1,550 | +| Protocol-core covered lines | 1,007 | +| Protocol-core line coverage | 64.97% | +| Enforced protocol-core floor | 60% | + +The expanded suite covers deterministic behavior across Sampled Values, SCL parsing, COMTRADE parsing and scaling, PCAP read/write handling, MMS data and object references, diagnostics, Ethernet framing, transport helpers, and publisher session behavior. This is not a claim that the complete WPF UI or every live-network path is covered; live Npcap, timing, and device-interoperability behavior still require controlled laboratory validation. ## Validate the public site diff --git a/scripts/test-with-coverage.ps1 b/scripts/test-with-coverage.ps1 index b3608b7..c6db348 100644 --- a/scripts/test-with-coverage.ps1 +++ b/scripts/test-with-coverage.ps1 @@ -1,10 +1,10 @@ [CmdletBinding()] param( [ValidateRange(0, 100)] - [double] $MinimumLineCoverage = 50, + [double] $MinimumLineCoverage = 60, [ValidateRange(0, 100)] - [double] $MinimumWholeEngineLineCoverage = 5.5, + [double] $MinimumWholeEngineLineCoverage = 10.5, [switch] $NoRestore ) @@ -33,7 +33,7 @@ if ($NoRestore) { $arguments += '--no-restore' } -# Instrument the complete production engine. CI now protects both the truthful +# Instrument the complete production engine. CI protects both the truthful # whole-engine baseline and the higher protocol-core regression baseline. $arguments += @( '/p:RestoreLockedMode=true', diff --git a/src/ARSVIN/Engine/AR.Iec61850.Transports.Npcap/NpcapAdapterCatalog.cs b/src/ARSVIN.Engine/AR.Iec61850.Transports.Npcap/NpcapAdapterCatalog.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850.Transports.Npcap/NpcapAdapterCatalog.cs rename to src/ARSVIN.Engine/AR.Iec61850.Transports.Npcap/NpcapAdapterCatalog.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850.Transports.Npcap/NpcapAdapterInfo.cs b/src/ARSVIN.Engine/AR.Iec61850.Transports.Npcap/NpcapAdapterInfo.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850.Transports.Npcap/NpcapAdapterInfo.cs rename to src/ARSVIN.Engine/AR.Iec61850.Transports.Npcap/NpcapAdapterInfo.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850.Transports.Npcap/NpcapProcessBusDuplexTransport.cs b/src/ARSVIN.Engine/AR.Iec61850.Transports.Npcap/NpcapProcessBusDuplexTransport.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850.Transports.Npcap/NpcapProcessBusDuplexTransport.cs rename to src/ARSVIN.Engine/AR.Iec61850.Transports.Npcap/NpcapProcessBusDuplexTransport.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850.Transports.Npcap/NpcapProcessBusFrameSource.cs b/src/ARSVIN.Engine/AR.Iec61850.Transports.Npcap/NpcapProcessBusFrameSource.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850.Transports.Npcap/NpcapProcessBusFrameSource.cs rename to src/ARSVIN.Engine/AR.Iec61850.Transports.Npcap/NpcapProcessBusFrameSource.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850.Transports.Npcap/NpcapProcessBusTransport.cs b/src/ARSVIN.Engine/AR.Iec61850.Transports.Npcap/NpcapProcessBusTransport.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850.Transports.Npcap/NpcapProcessBusTransport.cs rename to src/ARSVIN.Engine/AR.Iec61850.Transports.Npcap/NpcapProcessBusTransport.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Acse/AcseAssociationPayloadInspector.cs b/src/ARSVIN.Engine/AR.Iec61850/Acse/AcseAssociationPayloadInspector.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Acse/AcseAssociationPayloadInspector.cs rename to src/ARSVIN.Engine/AR.Iec61850/Acse/AcseAssociationPayloadInspector.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Acse/AcseMmsAssociateResponse.cs b/src/ARSVIN.Engine/AR.Iec61850/Acse/AcseMmsAssociateResponse.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Acse/AcseMmsAssociateResponse.cs rename to src/ARSVIN.Engine/AR.Iec61850/Acse/AcseMmsAssociateResponse.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Acse/AcseMmsInitiateRequest.cs b/src/ARSVIN.Engine/AR.Iec61850/Acse/AcseMmsInitiateRequest.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Acse/AcseMmsInitiateRequest.cs rename to src/ARSVIN.Engine/AR.Iec61850/Acse/AcseMmsInitiateRequest.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Acse/AcseMmsInitiateResult.cs b/src/ARSVIN.Engine/AR.Iec61850/Acse/AcseMmsInitiateResult.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Acse/AcseMmsInitiateResult.cs rename to src/ARSVIN.Engine/AR.Iec61850/Acse/AcseMmsInitiateResult.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Asn1/BerClass.cs b/src/ARSVIN.Engine/AR.Iec61850/Asn1/BerClass.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Asn1/BerClass.cs rename to src/ARSVIN.Engine/AR.Iec61850/Asn1/BerClass.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Asn1/BerFormatException.cs b/src/ARSVIN.Engine/AR.Iec61850/Asn1/BerFormatException.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Asn1/BerFormatException.cs rename to src/ARSVIN.Engine/AR.Iec61850/Asn1/BerFormatException.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Asn1/BerReader.cs b/src/ARSVIN.Engine/AR.Iec61850/Asn1/BerReader.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Asn1/BerReader.cs rename to src/ARSVIN.Engine/AR.Iec61850/Asn1/BerReader.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Asn1/BerTlv.cs b/src/ARSVIN.Engine/AR.Iec61850/Asn1/BerTlv.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Asn1/BerTlv.cs rename to src/ARSVIN.Engine/AR.Iec61850/Asn1/BerTlv.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Asn1/BerWriter.cs b/src/ARSVIN.Engine/AR.Iec61850/Asn1/BerWriter.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Asn1/BerWriter.cs rename to src/ARSVIN.Engine/AR.Iec61850/Asn1/BerWriter.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Binding/Iec61850SmartValueReading.cs b/src/ARSVIN.Engine/AR.Iec61850/Binding/Iec61850SmartValueReading.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Binding/Iec61850SmartValueReading.cs rename to src/ARSVIN.Engine/AR.Iec61850/Binding/Iec61850SmartValueReading.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Binding/Iec61850ValueBindingEngine.cs b/src/ARSVIN.Engine/AR.Iec61850/Binding/Iec61850ValueBindingEngine.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Binding/Iec61850ValueBindingEngine.cs rename to src/ARSVIN.Engine/AR.Iec61850/Binding/Iec61850ValueBindingEngine.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Binding/Iec61850ValueSchema.cs b/src/ARSVIN.Engine/AR.Iec61850/Binding/Iec61850ValueSchema.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Binding/Iec61850ValueSchema.cs rename to src/ARSVIN.Engine/AR.Iec61850/Binding/Iec61850ValueSchema.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Capture/PcapFormatException.cs b/src/ARSVIN.Engine/AR.Iec61850/Capture/PcapFormatException.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Capture/PcapFormatException.cs rename to src/ARSVIN.Engine/AR.Iec61850/Capture/PcapFormatException.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Capture/PcapPacket.cs b/src/ARSVIN.Engine/AR.Iec61850/Capture/PcapPacket.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Capture/PcapPacket.cs rename to src/ARSVIN.Engine/AR.Iec61850/Capture/PcapPacket.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Capture/PcapReader.cs b/src/ARSVIN.Engine/AR.Iec61850/Capture/PcapReader.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Capture/PcapReader.cs rename to src/ARSVIN.Engine/AR.Iec61850/Capture/PcapReader.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Capture/PcapWriter.cs b/src/ARSVIN.Engine/AR.Iec61850/Capture/PcapWriter.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Capture/PcapWriter.cs rename to src/ARSVIN.Engine/AR.Iec61850/Capture/PcapWriter.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Comtrade/ComtradeAnalogChannel.cs b/src/ARSVIN.Engine/AR.Iec61850/Comtrade/ComtradeAnalogChannel.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Comtrade/ComtradeAnalogChannel.cs rename to src/ARSVIN.Engine/AR.Iec61850/Comtrade/ComtradeAnalogChannel.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Comtrade/ComtradeChannelMapper.cs b/src/ARSVIN.Engine/AR.Iec61850/Comtrade/ComtradeChannelMapper.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Comtrade/ComtradeChannelMapper.cs rename to src/ARSVIN.Engine/AR.Iec61850/Comtrade/ComtradeChannelMapper.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Comtrade/ComtradeConfiguration.cs b/src/ARSVIN.Engine/AR.Iec61850/Comtrade/ComtradeConfiguration.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Comtrade/ComtradeConfiguration.cs rename to src/ARSVIN.Engine/AR.Iec61850/Comtrade/ComtradeConfiguration.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Comtrade/ComtradeDataset.cs b/src/ARSVIN.Engine/AR.Iec61850/Comtrade/ComtradeDataset.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Comtrade/ComtradeDataset.cs rename to src/ARSVIN.Engine/AR.Iec61850/Comtrade/ComtradeDataset.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Comtrade/ComtradeReader.cs b/src/ARSVIN.Engine/AR.Iec61850/Comtrade/ComtradeReader.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Comtrade/ComtradeReader.cs rename to src/ARSVIN.Engine/AR.Iec61850/Comtrade/ComtradeReader.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Comtrade/ComtradeSample.cs b/src/ARSVIN.Engine/AR.Iec61850/Comtrade/ComtradeSample.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Comtrade/ComtradeSample.cs rename to src/ARSVIN.Engine/AR.Iec61850/Comtrade/ComtradeSample.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Comtrade/ComtradeSampleRate.cs b/src/ARSVIN.Engine/AR.Iec61850/Comtrade/ComtradeSampleRate.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Comtrade/ComtradeSampleRate.cs rename to src/ARSVIN.Engine/AR.Iec61850/Comtrade/ComtradeSampleRate.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Diagnostics/Binding/ExpectedObservedBindingProfile.cs b/src/ARSVIN.Engine/AR.Iec61850/Diagnostics/Binding/ExpectedObservedBindingProfile.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Diagnostics/Binding/ExpectedObservedBindingProfile.cs rename to src/ARSVIN.Engine/AR.Iec61850/Diagnostics/Binding/ExpectedObservedBindingProfile.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Diagnostics/Binding/ExpectedObservedBindingProfileBuilder.cs b/src/ARSVIN.Engine/AR.Iec61850/Diagnostics/Binding/ExpectedObservedBindingProfileBuilder.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Diagnostics/Binding/ExpectedObservedBindingProfileBuilder.cs rename to src/ARSVIN.Engine/AR.Iec61850/Diagnostics/Binding/ExpectedObservedBindingProfileBuilder.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Diagnostics/Goose/GooseDiagnosticsProfile.cs b/src/ARSVIN.Engine/AR.Iec61850/Diagnostics/Goose/GooseDiagnosticsProfile.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Diagnostics/Goose/GooseDiagnosticsProfile.cs rename to src/ARSVIN.Engine/AR.Iec61850/Diagnostics/Goose/GooseDiagnosticsProfile.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Diagnostics/Goose/GooseDiagnosticsProfileBuilder.cs b/src/ARSVIN.Engine/AR.Iec61850/Diagnostics/Goose/GooseDiagnosticsProfileBuilder.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Diagnostics/Goose/GooseDiagnosticsProfileBuilder.cs rename to src/ARSVIN.Engine/AR.Iec61850/Diagnostics/Goose/GooseDiagnosticsProfileBuilder.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Diagnostics/HexDump.cs b/src/ARSVIN.Engine/AR.Iec61850/Diagnostics/HexDump.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Diagnostics/HexDump.cs rename to src/ARSVIN.Engine/AR.Iec61850/Diagnostics/HexDump.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Diagnostics/SampledValues/SampledValuesDiagnosticsProfile.cs b/src/ARSVIN.Engine/AR.Iec61850/Diagnostics/SampledValues/SampledValuesDiagnosticsProfile.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Diagnostics/SampledValues/SampledValuesDiagnosticsProfile.cs rename to src/ARSVIN.Engine/AR.Iec61850/Diagnostics/SampledValues/SampledValuesDiagnosticsProfile.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Diagnostics/SampledValues/SampledValuesDiagnosticsProfileBuilder.cs b/src/ARSVIN.Engine/AR.Iec61850/Diagnostics/SampledValues/SampledValuesDiagnosticsProfileBuilder.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Diagnostics/SampledValues/SampledValuesDiagnosticsProfileBuilder.cs rename to src/ARSVIN.Engine/AR.Iec61850/Diagnostics/SampledValues/SampledValuesDiagnosticsProfileBuilder.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Discovery/CdcInferenceEngine.cs b/src/ARSVIN.Engine/AR.Iec61850/Discovery/CdcInferenceEngine.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Discovery/CdcInferenceEngine.cs rename to src/ARSVIN.Engine/AR.Iec61850/Discovery/CdcInferenceEngine.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Discovery/Iec61850ReferenceParts.cs b/src/ARSVIN.Engine/AR.Iec61850/Discovery/Iec61850ReferenceParts.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Discovery/Iec61850ReferenceParts.cs rename to src/ARSVIN.Engine/AR.Iec61850/Discovery/Iec61850ReferenceParts.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Discovery/Iec61850StandardEnumRegistry.cs b/src/ARSVIN.Engine/AR.Iec61850/Discovery/Iec61850StandardEnumRegistry.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Discovery/Iec61850StandardEnumRegistry.cs rename to src/ARSVIN.Engine/AR.Iec61850/Discovery/Iec61850StandardEnumRegistry.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Discovery/Iec61850StandardModelRegistry.cs b/src/ARSVIN.Engine/AR.Iec61850/Discovery/Iec61850StandardModelRegistry.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Discovery/Iec61850StandardModelRegistry.cs rename to src/ARSVIN.Engine/AR.Iec61850/Discovery/Iec61850StandardModelRegistry.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Discovery/LiveIedModelDiscoveryBuilder.cs b/src/ARSVIN.Engine/AR.Iec61850/Discovery/LiveIedModelDiscoveryBuilder.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Discovery/LiveIedModelDiscoveryBuilder.cs rename to src/ARSVIN.Engine/AR.Iec61850/Discovery/LiveIedModelDiscoveryBuilder.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Discovery/LiveIedModelDiscoveryExporter.cs b/src/ARSVIN.Engine/AR.Iec61850/Discovery/LiveIedModelDiscoveryExporter.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Discovery/LiveIedModelDiscoveryExporter.cs rename to src/ARSVIN.Engine/AR.Iec61850/Discovery/LiveIedModelDiscoveryExporter.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Discovery/LiveIedModelDiscoveryModels.cs b/src/ARSVIN.Engine/AR.Iec61850/Discovery/LiveIedModelDiscoveryModels.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Discovery/LiveIedModelDiscoveryModels.cs rename to src/ARSVIN.Engine/AR.Iec61850/Discovery/LiveIedModelDiscoveryModels.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Discovery/LiveIedServiceDiscoveryEvidence.cs b/src/ARSVIN.Engine/AR.Iec61850/Discovery/LiveIedServiceDiscoveryEvidence.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Discovery/LiveIedServiceDiscoveryEvidence.cs rename to src/ARSVIN.Engine/AR.Iec61850/Discovery/LiveIedServiceDiscoveryEvidence.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Discovery/LiveIedServiceDiscoveryReport.cs b/src/ARSVIN.Engine/AR.Iec61850/Discovery/LiveIedServiceDiscoveryReport.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Discovery/LiveIedServiceDiscoveryReport.cs rename to src/ARSVIN.Engine/AR.Iec61850/Discovery/LiveIedServiceDiscoveryReport.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Engineering/Iec61850CapabilityAssessment.cs b/src/ARSVIN.Engine/AR.Iec61850/Engineering/Iec61850CapabilityAssessment.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Engineering/Iec61850CapabilityAssessment.cs rename to src/ARSVIN.Engine/AR.Iec61850/Engineering/Iec61850CapabilityAssessment.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Engineering/Iec61850Client.cs b/src/ARSVIN.Engine/AR.Iec61850/Engineering/Iec61850Client.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Engineering/Iec61850Client.cs rename to src/ARSVIN.Engine/AR.Iec61850/Engineering/Iec61850Client.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Engineering/Iec61850DiagnosticMessage.cs b/src/ARSVIN.Engine/AR.Iec61850/Engineering/Iec61850DiagnosticMessage.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Engineering/Iec61850DiagnosticMessage.cs rename to src/ARSVIN.Engine/AR.Iec61850/Engineering/Iec61850DiagnosticMessage.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Engineering/Iec61850EngineeringProfile.cs b/src/ARSVIN.Engine/AR.Iec61850/Engineering/Iec61850EngineeringProfile.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Engineering/Iec61850EngineeringProfile.cs rename to src/ARSVIN.Engine/AR.Iec61850/Engineering/Iec61850EngineeringProfile.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Engineering/Iec61850EngineeringProfileBuilder.cs b/src/ARSVIN.Engine/AR.Iec61850/Engineering/Iec61850EngineeringProfileBuilder.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Engineering/Iec61850EngineeringProfileBuilder.cs rename to src/ARSVIN.Engine/AR.Iec61850/Engineering/Iec61850EngineeringProfileBuilder.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Engineering/Iec61850ReportReadinessProfile.cs b/src/ARSVIN.Engine/AR.Iec61850/Engineering/Iec61850ReportReadinessProfile.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Engineering/Iec61850ReportReadinessProfile.cs rename to src/ARSVIN.Engine/AR.Iec61850/Engineering/Iec61850ReportReadinessProfile.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Engineering/Iec61850ServiceResult.cs b/src/ARSVIN.Engine/AR.Iec61850/Engineering/Iec61850ServiceResult.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Engineering/Iec61850ServiceResult.cs rename to src/ARSVIN.Engine/AR.Iec61850/Engineering/Iec61850ServiceResult.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Ethernet/EthernetConstants.cs b/src/ARSVIN.Engine/AR.Iec61850/Ethernet/EthernetConstants.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Ethernet/EthernetConstants.cs rename to src/ARSVIN.Engine/AR.Iec61850/Ethernet/EthernetConstants.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Ethernet/EthernetFrame.cs b/src/ARSVIN.Engine/AR.Iec61850/Ethernet/EthernetFrame.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Ethernet/EthernetFrame.cs rename to src/ARSVIN.Engine/AR.Iec61850/Ethernet/EthernetFrame.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Ethernet/EthernetFrameCodec.cs b/src/ARSVIN.Engine/AR.Iec61850/Ethernet/EthernetFrameCodec.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Ethernet/EthernetFrameCodec.cs rename to src/ARSVIN.Engine/AR.Iec61850/Ethernet/EthernetFrameCodec.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Ethernet/MacAddress.cs b/src/ARSVIN.Engine/AR.Iec61850/Ethernet/MacAddress.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Ethernet/MacAddress.cs rename to src/ARSVIN.Engine/AR.Iec61850/Ethernet/MacAddress.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Ethernet/ProcessBusFrame.cs b/src/ARSVIN.Engine/AR.Iec61850/Ethernet/ProcessBusFrame.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Ethernet/ProcessBusFrame.cs rename to src/ARSVIN.Engine/AR.Iec61850/Ethernet/ProcessBusFrame.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Ethernet/ProcessBusFrameCodec.cs b/src/ARSVIN.Engine/AR.Iec61850/Ethernet/ProcessBusFrameCodec.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Ethernet/ProcessBusFrameCodec.cs rename to src/ARSVIN.Engine/AR.Iec61850/Ethernet/ProcessBusFrameCodec.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Ethernet/VlanTag.cs b/src/ARSVIN.Engine/AR.Iec61850/Ethernet/VlanTag.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Ethernet/VlanTag.cs rename to src/ARSVIN.Engine/AR.Iec61850/Ethernet/VlanTag.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Goose/GooseDecodedValue.cs b/src/ARSVIN.Engine/AR.Iec61850/Goose/GooseDecodedValue.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Goose/GooseDecodedValue.cs rename to src/ARSVIN.Engine/AR.Iec61850/Goose/GooseDecodedValue.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Goose/GooseFrame.cs b/src/ARSVIN.Engine/AR.Iec61850/Goose/GooseFrame.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Goose/GooseFrame.cs rename to src/ARSVIN.Engine/AR.Iec61850/Goose/GooseFrame.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Goose/GooseFrameBuilder.cs b/src/ARSVIN.Engine/AR.Iec61850/Goose/GooseFrameBuilder.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Goose/GooseFrameBuilder.cs rename to src/ARSVIN.Engine/AR.Iec61850/Goose/GooseFrameBuilder.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Goose/GooseFrameParser.cs b/src/ARSVIN.Engine/AR.Iec61850/Goose/GooseFrameParser.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Goose/GooseFrameParser.cs rename to src/ARSVIN.Engine/AR.Iec61850/Goose/GooseFrameParser.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Goose/GoosePdu.cs b/src/ARSVIN.Engine/AR.Iec61850/Goose/GoosePdu.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Goose/GoosePdu.cs rename to src/ARSVIN.Engine/AR.Iec61850/Goose/GoosePdu.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Goose/GoosePublisherProfile.cs b/src/ARSVIN.Engine/AR.Iec61850/Goose/GoosePublisherProfile.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Goose/GoosePublisherProfile.cs rename to src/ARSVIN.Engine/AR.Iec61850/Goose/GoosePublisherProfile.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Goose/GoosePublisherSession.cs b/src/ARSVIN.Engine/AR.Iec61850/Goose/GoosePublisherSession.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Goose/GoosePublisherSession.cs rename to src/ARSVIN.Engine/AR.Iec61850/Goose/GoosePublisherSession.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Goose/GooseRetransmissionSchedule.cs b/src/ARSVIN.Engine/AR.Iec61850/Goose/GooseRetransmissionSchedule.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Goose/GooseRetransmissionSchedule.cs rename to src/ARSVIN.Engine/AR.Iec61850/Goose/GooseRetransmissionSchedule.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/Iec61850UtcTime.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/Iec61850UtcTime.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/Iec61850UtcTime.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/Iec61850UtcTime.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsBinaryTime.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsBinaryTime.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsBinaryTime.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsBinaryTime.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsClientSession.VariableAccessAttributes.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsClientSession.VariableAccessAttributes.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsClientSession.VariableAccessAttributes.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsClientSession.VariableAccessAttributes.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsClientSession.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsClientSession.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsClientSession.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsClientSession.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsDataCodec.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsDataCodec.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsDataCodec.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsDataCodec.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsDataKind.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsDataKind.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsDataKind.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsDataKind.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsDataSetDirectory.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsDataSetDirectory.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsDataSetDirectory.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsDataSetDirectory.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsDataValue.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsDataValue.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsDataValue.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsDataValue.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsDataValueRenderer.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsDataValueRenderer.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsDataValueRenderer.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsDataValueRenderer.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsDiscoveryResult.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsDiscoveryResult.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsDiscoveryResult.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsDiscoveryResult.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsDiscoverySnapshot.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsDiscoverySnapshot.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsDiscoverySnapshot.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsDiscoverySnapshot.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsFcResolver.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsFcResolver.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsFcResolver.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsFcResolver.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsFileDirectory.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsFileDirectory.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsFileDirectory.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsFileDirectory.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsFunctionalConstraint.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsFunctionalConstraint.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsFunctionalConstraint.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsFunctionalConstraint.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsGetNameList.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsGetNameList.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsGetNameList.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsGetNameList.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsIedModelDirectory.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsIedModelDirectory.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsIedModelDirectory.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsIedModelDirectory.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsIedModelDirectoryBuilder.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsIedModelDirectoryBuilder.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsIedModelDirectoryBuilder.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsIedModelDirectoryBuilder.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsInformationReport.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsInformationReport.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsInformationReport.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsInformationReport.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsNamedVariableList.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsNamedVariableList.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsNamedVariableList.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsNamedVariableList.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsObjectReference.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsObjectReference.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsObjectReference.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsObjectReference.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsPduEnvelope.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsPduEnvelope.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsPduEnvelope.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsPduEnvelope.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsPersistentReportMonitor.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsPersistentReportMonitor.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsPersistentReportMonitor.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsPersistentReportMonitor.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsPresentation.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsPresentation.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsPresentation.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsPresentation.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsRcbPoolSelector.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsRcbPoolSelector.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsRcbPoolSelector.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsRcbPoolSelector.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsRead.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsRead.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsRead.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsRead.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReceivePump.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReceivePump.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReceivePump.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReceivePump.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReceiveRouter.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReceiveRouter.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReceiveRouter.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReceiveRouter.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportDiscoveryMapper.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportDiscoveryMapper.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportDiscoveryMapper.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportDiscoveryMapper.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportInventory.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportInventory.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportInventory.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportInventory.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportLiveSession.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportLiveSession.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportLiveSession.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportLiveSession.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportPresentation.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportPresentation.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportPresentation.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportPresentation.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportReadiness.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportReadiness.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportReadiness.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportReadiness.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportSessionDiagnostics.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportSessionDiagnostics.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportSessionDiagnostics.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportSessionDiagnostics.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportSessionProfile.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportSessionProfile.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportSessionProfile.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportSessionProfile.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportSubscriptionPlan.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportSubscriptionPlan.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportSubscriptionPlan.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportSubscriptionPlan.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportValueProjector.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportValueProjector.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsReportValueProjector.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsReportValueProjector.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsSmartRead.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsSmartRead.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsSmartRead.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsSmartRead.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsVariableAccessAttributes.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsVariableAccessAttributes.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsVariableAccessAttributes.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsVariableAccessAttributes.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Mms/MmsWrite.cs b/src/ARSVIN.Engine/AR.Iec61850/Mms/MmsWrite.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Mms/MmsWrite.cs rename to src/ARSVIN.Engine/AR.Iec61850/Mms/MmsWrite.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Monitoring/GooseSequenceStatus.cs b/src/ARSVIN.Engine/AR.Iec61850/Monitoring/GooseSequenceStatus.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Monitoring/GooseSequenceStatus.cs rename to src/ARSVIN.Engine/AR.Iec61850/Monitoring/GooseSequenceStatus.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Monitoring/ProcessBusEventKind.cs b/src/ARSVIN.Engine/AR.Iec61850/Monitoring/ProcessBusEventKind.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Monitoring/ProcessBusEventKind.cs rename to src/ARSVIN.Engine/AR.Iec61850/Monitoring/ProcessBusEventKind.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Monitoring/ProcessBusSequenceStatus.cs b/src/ARSVIN.Engine/AR.Iec61850/Monitoring/ProcessBusSequenceStatus.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Monitoring/ProcessBusSequenceStatus.cs rename to src/ARSVIN.Engine/AR.Iec61850/Monitoring/ProcessBusSequenceStatus.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Monitoring/ProcessBusStreamEvent.cs b/src/ARSVIN.Engine/AR.Iec61850/Monitoring/ProcessBusStreamEvent.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Monitoring/ProcessBusStreamEvent.cs rename to src/ARSVIN.Engine/AR.Iec61850/Monitoring/ProcessBusStreamEvent.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Monitoring/ProcessBusStreamMonitor.cs b/src/ARSVIN.Engine/AR.Iec61850/Monitoring/ProcessBusStreamMonitor.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Monitoring/ProcessBusStreamMonitor.cs rename to src/ARSVIN.Engine/AR.Iec61850/Monitoring/ProcessBusStreamMonitor.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Monitoring/ProcessBusStreamSummary.cs b/src/ARSVIN.Engine/AR.Iec61850/Monitoring/ProcessBusStreamSummary.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Monitoring/ProcessBusStreamSummary.cs rename to src/ARSVIN.Engine/AR.Iec61850/Monitoring/ProcessBusStreamSummary.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Osi/CotpClient.cs b/src/ARSVIN.Engine/AR.Iec61850/Osi/CotpClient.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Osi/CotpClient.cs rename to src/ARSVIN.Engine/AR.Iec61850/Osi/CotpClient.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Osi/CotpConnectRequest.cs b/src/ARSVIN.Engine/AR.Iec61850/Osi/CotpConnectRequest.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Osi/CotpConnectRequest.cs rename to src/ARSVIN.Engine/AR.Iec61850/Osi/CotpConnectRequest.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Osi/CotpConnectionConfirm.cs b/src/ARSVIN.Engine/AR.Iec61850/Osi/CotpConnectionConfirm.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Osi/CotpConnectionConfirm.cs rename to src/ARSVIN.Engine/AR.Iec61850/Osi/CotpConnectionConfirm.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Osi/CotpFrameCodec.cs b/src/ARSVIN.Engine/AR.Iec61850/Osi/CotpFrameCodec.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Osi/CotpFrameCodec.cs rename to src/ARSVIN.Engine/AR.Iec61850/Osi/CotpFrameCodec.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Osi/TpktClient.cs b/src/ARSVIN.Engine/AR.Iec61850/Osi/TpktClient.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Osi/TpktClient.cs rename to src/ARSVIN.Engine/AR.Iec61850/Osi/TpktClient.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Osi/TpktFrameCodec.cs b/src/ARSVIN.Engine/AR.Iec61850/Osi/TpktFrameCodec.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Osi/TpktFrameCodec.cs rename to src/ARSVIN.Engine/AR.Iec61850/Osi/TpktFrameCodec.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampleCounterPolicy.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampleCounterPolicy.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampleCounterPolicy.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampleCounterPolicy.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValueAsdu.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValueAsdu.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValueAsdu.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValueAsdu.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValueQuality.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValueQuality.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValueQuality.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValueQuality.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesFrame.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesFrame.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesFrame.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesFrame.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesFrameBuilder.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesFrameBuilder.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesFrameBuilder.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesFrameBuilder.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesFrameParser.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesFrameParser.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesFrameParser.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesFrameParser.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesFramePreview.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesFramePreview.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesFramePreview.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesFramePreview.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPayloadBuilder.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPayloadBuilder.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPayloadBuilder.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPayloadBuilder.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPayloadDecoder.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPayloadDecoder.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPayloadDecoder.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPayloadDecoder.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPayloadLayout.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPayloadLayout.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPayloadLayout.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPayloadLayout.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPcapExporter.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPcapExporter.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPcapExporter.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPcapExporter.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPdu.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPdu.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPdu.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPdu.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPublisherEvidenceReport.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPublisherEvidenceReport.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPublisherEvidenceReport.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPublisherEvidenceReport.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPublisherProfile.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPublisherProfile.cs similarity index 87% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPublisherProfile.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPublisherProfile.cs index 2e08314..964e29e 100644 --- a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPublisherProfile.cs +++ b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPublisherProfile.cs @@ -53,12 +53,19 @@ public SampledValuesFrame CreateFrame( ushort sampleCount, ReadOnlySpan samplePayload, Iec61850UtcTime? referenceTime = null, - byte sampleSynchronization = 2) + byte sampleSynchronization = 2, + ushort? sampleCounterWrap = null) { if (AsduPerFrame != 1) throw new InvalidOperationException($"SV {Stream.ControlBlockReference} declares nofASDU={AsduPerFrame}. Use the multi-ASDU CreateFrame overload."); - return CreateFrame(source, sampleCount, new[] { samplePayload.ToArray() }, referenceTime, sampleSynchronization); + return CreateFrame( + source, + sampleCount, + new[] { samplePayload.ToArray() }, + referenceTime, + sampleSynchronization, + sampleCounterWrap); } public SampledValuesFrame CreateFrame( @@ -66,11 +73,15 @@ public SampledValuesFrame CreateFrame( ushort sampleCount, IReadOnlyList samplePayloads, Iec61850UtcTime? referenceTime = null, - byte sampleSynchronization = 2) + byte sampleSynchronization = 2, + ushort? sampleCounterWrap = null) { ArgumentNullException.ThrowIfNull(samplePayloads); ValidateAsduPayloadBatch(samplePayloads); + if (sampleCounterWrap is 1) + throw new ArgumentOutOfRangeException(nameof(sampleCounterWrap), "SV sample counter wrap must be greater than 1 when supplied."); + var asdus = new List(samplePayloads.Count); for (var i = 0; i < samplePayloads.Count; i++) { @@ -78,7 +89,7 @@ public SampledValuesFrame CreateFrame( { SvId = Stream.SvId, DataSetReference = Stream.DataSetReference, - SampleCount = SampleCounterPolicy.Increment(sampleCount, null, i), + SampleCount = SampleCounterPolicy.Increment(sampleCount, sampleCounterWrap, i), ConfigurationRevision = Stream.ConfigurationRevision, ReferenceTime = referenceTime, SampleSynchronization = sampleSynchronization, @@ -103,9 +114,11 @@ public byte[] BuildEthernetFrame( ushort sampleCount, ReadOnlySpan samplePayload, Iec61850UtcTime? referenceTime = null, - byte sampleSynchronization = 2) + byte sampleSynchronization = 2, + ushort? sampleCounterWrap = null) { - return SampledValuesFrameBuilder.BuildEthernetFrame(CreateFrame(source, sampleCount, samplePayload, referenceTime, sampleSynchronization)); + return SampledValuesFrameBuilder.BuildEthernetFrame( + CreateFrame(source, sampleCount, samplePayload, referenceTime, sampleSynchronization, sampleCounterWrap)); } public byte[] BuildEthernetFrame( @@ -113,9 +126,11 @@ public byte[] BuildEthernetFrame( ushort sampleCount, IReadOnlyList samplePayloads, Iec61850UtcTime? referenceTime = null, - byte sampleSynchronization = 2) + byte sampleSynchronization = 2, + ushort? sampleCounterWrap = null) { - return SampledValuesFrameBuilder.BuildEthernetFrame(CreateFrame(source, sampleCount, samplePayloads, referenceTime, sampleSynchronization)); + return SampledValuesFrameBuilder.BuildEthernetFrame( + CreateFrame(source, sampleCount, samplePayloads, referenceTime, sampleSynchronization, sampleCounterWrap)); } public byte[] BuildPayload(IReadOnlyList values) @@ -182,7 +197,6 @@ public static double ResolvePublicationRate(double sampleRateHz, ushort noAsdu) { if (sampleRateHz <= 0) throw new ArgumentOutOfRangeException(nameof(sampleRateHz), "Sample rate must be greater than 0."); - if (noAsdu == 0) throw new ArgumentOutOfRangeException(nameof(noAsdu), "nofASDU must be greater than 0."); diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPublisherSession.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPublisherSession.cs similarity index 91% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPublisherSession.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPublisherSession.cs index fa9880b..4b4ef6f 100644 --- a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPublisherSession.cs +++ b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPublisherSession.cs @@ -55,7 +55,13 @@ public async ValueTask PublishNextBatchAsync( var sampleCount = NextSampleCount; NextSampleCount = SampleCounterPolicy.Increment(sampleCount, SampleCounterWrap, samplePayloads.Count); - var frame = _profile.BuildEthernetFrame(_source, sampleCount, samplePayloads, referenceTime, sampleSynchronization); + var frame = _profile.BuildEthernetFrame( + _source, + sampleCount, + samplePayloads, + referenceTime, + sampleSynchronization, + SampleCounterWrap); await _transport.SendAsync(frame, cancellationToken).ConfigureAwait(false); return frame; } diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPublisherValidation.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPublisherValidation.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/SampledValuesPublisherValidation.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/SampledValuesPublisherValidation.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/SampledValues/TxTimingHealth.cs b/src/ARSVIN.Engine/AR.Iec61850/SampledValues/TxTimingHealth.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/SampledValues/TxTimingHealth.cs rename to src/ARSVIN.Engine/AR.Iec61850/SampledValues/TxTimingHealth.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Scl/Analysis/SclGoldenDiffAnalyzer.cs b/src/ARSVIN.Engine/AR.Iec61850/Scl/Analysis/SclGoldenDiffAnalyzer.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Scl/Analysis/SclGoldenDiffAnalyzer.cs rename to src/ARSVIN.Engine/AR.Iec61850/Scl/Analysis/SclGoldenDiffAnalyzer.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Scl/Analysis/SclModelSnapshot.cs b/src/ARSVIN.Engine/AR.Iec61850/Scl/Analysis/SclModelSnapshot.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Scl/Analysis/SclModelSnapshot.cs rename to src/ARSVIN.Engine/AR.Iec61850/Scl/Analysis/SclModelSnapshot.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Scl/Analysis/SclModelSnapshotBuilder.cs b/src/ARSVIN.Engine/AR.Iec61850/Scl/Analysis/SclModelSnapshotBuilder.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Scl/Analysis/SclModelSnapshotBuilder.cs rename to src/ARSVIN.Engine/AR.Iec61850/Scl/Analysis/SclModelSnapshotBuilder.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Scl/Engineering/SclEngineeringProfile.cs b/src/ARSVIN.Engine/AR.Iec61850/Scl/Engineering/SclEngineeringProfile.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Scl/Engineering/SclEngineeringProfile.cs rename to src/ARSVIN.Engine/AR.Iec61850/Scl/Engineering/SclEngineeringProfile.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Scl/Engineering/SclEngineeringProfileBuilder.cs b/src/ARSVIN.Engine/AR.Iec61850/Scl/Engineering/SclEngineeringProfileBuilder.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Scl/Engineering/SclEngineeringProfileBuilder.cs rename to src/ARSVIN.Engine/AR.Iec61850/Scl/Engineering/SclEngineeringProfileBuilder.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Scl/Engineering/SclLiveModelProjectionBuilder.cs b/src/ARSVIN.Engine/AR.Iec61850/Scl/Engineering/SclLiveModelProjectionBuilder.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Scl/Engineering/SclLiveModelProjectionBuilder.cs rename to src/ARSVIN.Engine/AR.Iec61850/Scl/Engineering/SclLiveModelProjectionBuilder.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Scl/Export/LiveIedSclExportModels.cs b/src/ARSVIN.Engine/AR.Iec61850/Scl/Export/LiveIedSclExportModels.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Scl/Export/LiveIedSclExportModels.cs rename to src/ARSVIN.Engine/AR.Iec61850/Scl/Export/LiveIedSclExportModels.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Scl/Export/LiveIedSclExporter.cs b/src/ARSVIN.Engine/AR.Iec61850/Scl/Export/LiveIedSclExporter.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Scl/Export/LiveIedSclExporter.cs rename to src/ARSVIN.Engine/AR.Iec61850/Scl/Export/LiveIedSclExporter.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Scl/Export/SclAttributeExportClassifier.cs b/src/ARSVIN.Engine/AR.Iec61850/Scl/Export/SclAttributeExportClassifier.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Scl/Export/SclAttributeExportClassifier.cs rename to src/ARSVIN.Engine/AR.Iec61850/Scl/Export/SclAttributeExportClassifier.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Scl/SclModels.cs b/src/ARSVIN.Engine/AR.Iec61850/Scl/SclModels.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Scl/SclModels.cs rename to src/ARSVIN.Engine/AR.Iec61850/Scl/SclModels.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Scl/SclParser.cs b/src/ARSVIN.Engine/AR.Iec61850/Scl/SclParser.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Scl/SclParser.cs rename to src/ARSVIN.Engine/AR.Iec61850/Scl/SclParser.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Scl/SclProfileException.cs b/src/ARSVIN.Engine/AR.Iec61850/Scl/SclProfileException.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Scl/SclProfileException.cs rename to src/ARSVIN.Engine/AR.Iec61850/Scl/SclProfileException.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Health/PtpHealthCheckResult.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Health/PtpHealthCheckResult.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Health/PtpHealthCheckResult.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Health/PtpHealthCheckResult.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Health/PtpHealthSeverity.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Health/PtpHealthSeverity.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Health/PtpHealthSeverity.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Health/PtpHealthSeverity.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Health/PtpSmpSynchPolicy.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Health/PtpSmpSynchPolicy.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Health/PtpSmpSynchPolicy.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Health/PtpSmpSynchPolicy.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Health/PtpTimingHealthOptions.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Health/PtpTimingHealthOptions.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Health/PtpTimingHealthOptions.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Health/PtpTimingHealthOptions.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Health/PtpTimingHealthReport.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Health/PtpTimingHealthReport.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Health/PtpTimingHealthReport.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Health/PtpTimingHealthReport.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Health/PtpTimingHealthValidator.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Health/PtpTimingHealthValidator.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Health/PtpTimingHealthValidator.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Health/PtpTimingHealthValidator.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Health/SmpSynchValue.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Health/SmpSynchValue.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Health/SmpSynchValue.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Health/SmpSynchValue.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Monitoring/PtpMonitorSnapshot.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Monitoring/PtpMonitorSnapshot.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Monitoring/PtpMonitorSnapshot.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Monitoring/PtpMonitorSnapshot.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Monitoring/PtpObservedMessage.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Monitoring/PtpObservedMessage.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Monitoring/PtpObservedMessage.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Monitoring/PtpObservedMessage.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Monitoring/PtpPassiveMonitor.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Monitoring/PtpPassiveMonitor.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Monitoring/PtpPassiveMonitor.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Monitoring/PtpPassiveMonitor.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Monitoring/PtpSourceClockSnapshot.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Monitoring/PtpSourceClockSnapshot.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Monitoring/PtpSourceClockSnapshot.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Monitoring/PtpSourceClockSnapshot.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/ClockIdentity.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/ClockIdentity.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/ClockIdentity.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/ClockIdentity.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpAnnounceMessage.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpAnnounceMessage.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpAnnounceMessage.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpAnnounceMessage.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpBuildOptions.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpBuildOptions.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpBuildOptions.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpBuildOptions.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpClockAccuracy.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpClockAccuracy.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpClockAccuracy.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpClockAccuracy.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpConstants.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpConstants.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpConstants.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpConstants.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpFrame.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpFrame.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpFrame.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpFrame.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpHeader.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpHeader.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpHeader.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpHeader.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpMessageSerializer.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpMessageSerializer.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpMessageSerializer.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpMessageSerializer.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpMessageType.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpMessageType.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpMessageType.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpMessageType.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpPacketParser.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpPacketParser.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpPacketParser.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpPacketParser.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpPortIdentity.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpPortIdentity.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpPortIdentity.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpPortIdentity.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpTimeSource.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpTimeSource.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpTimeSource.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpTimeSource.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpTimestamp.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpTimestamp.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/Ptp/PtpTimestamp.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/Ptp/PtpTimestamp.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpPublisherOptions.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpPublisherOptions.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpPublisherOptions.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpPublisherOptions.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpPublisherRuntime.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpPublisherRuntime.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpPublisherRuntime.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpPublisherRuntime.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpPublisherStatus.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpPublisherStatus.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpPublisherStatus.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpPublisherStatus.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpSequenceCounters.cs b/src/ARSVIN.Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpSequenceCounters.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpSequenceCounters.cs rename to src/ARSVIN.Engine/AR.Iec61850/TimeSync/PtpRuntime/PtpSequenceCounters.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Transports/IProcessBusFrameSource.cs b/src/ARSVIN.Engine/AR.Iec61850/Transports/IProcessBusFrameSource.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Transports/IProcessBusFrameSource.cs rename to src/ARSVIN.Engine/AR.Iec61850/Transports/IProcessBusFrameSource.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Transports/IProcessBusTransport.cs b/src/ARSVIN.Engine/AR.Iec61850/Transports/IProcessBusTransport.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Transports/IProcessBusTransport.cs rename to src/ARSVIN.Engine/AR.Iec61850/Transports/IProcessBusTransport.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Transports/InMemoryProcessBusFrameSource.cs b/src/ARSVIN.Engine/AR.Iec61850/Transports/InMemoryProcessBusFrameSource.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Transports/InMemoryProcessBusFrameSource.cs rename to src/ARSVIN.Engine/AR.Iec61850/Transports/InMemoryProcessBusFrameSource.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Transports/InMemoryProcessBusTransport.cs b/src/ARSVIN.Engine/AR.Iec61850/Transports/InMemoryProcessBusTransport.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Transports/InMemoryProcessBusTransport.cs rename to src/ARSVIN.Engine/AR.Iec61850/Transports/InMemoryProcessBusTransport.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Transports/ProcessBusCaptureOptions.cs b/src/ARSVIN.Engine/AR.Iec61850/Transports/ProcessBusCaptureOptions.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Transports/ProcessBusCaptureOptions.cs rename to src/ARSVIN.Engine/AR.Iec61850/Transports/ProcessBusCaptureOptions.cs diff --git a/src/ARSVIN/Engine/AR.Iec61850/Transports/ProcessBusCapturedFrame.cs b/src/ARSVIN.Engine/AR.Iec61850/Transports/ProcessBusCapturedFrame.cs similarity index 100% rename from src/ARSVIN/Engine/AR.Iec61850/Transports/ProcessBusCapturedFrame.cs rename to src/ARSVIN.Engine/AR.Iec61850/Transports/ProcessBusCapturedFrame.cs diff --git a/src/ARSVIN.Engine/ARSVIN.Engine.csproj b/src/ARSVIN.Engine/ARSVIN.Engine.csproj index 86ef2fb..aa29138 100644 --- a/src/ARSVIN.Engine/ARSVIN.Engine.csproj +++ b/src/ARSVIN.Engine/ARSVIN.Engine.csproj @@ -13,10 +13,6 @@ - - - - <_Parameter1>ARSVIN diff --git a/src/ARSVIN/ARSVIN.csproj b/src/ARSVIN/ARSVIN.csproj index 7ecc371..a5f0d17 100644 --- a/src/ARSVIN/ARSVIN.csproj +++ b/src/ARSVIN/ARSVIN.csproj @@ -17,7 +17,6 @@ - diff --git a/tests/ARSVIN.Tests/Capture/PcapReaderWriterTests.cs b/tests/ARSVIN.Tests/Capture/PcapReaderWriterTests.cs new file mode 100644 index 0000000..99e819d --- /dev/null +++ b/tests/ARSVIN.Tests/Capture/PcapReaderWriterTests.cs @@ -0,0 +1,66 @@ +using System.Buffers.Binary; +using AR.Iec61850.Capture; +using Xunit; + +namespace ARSVIN.Tests.Capture; + +public sealed class PcapReaderWriterTests +{ + [Fact] + public void RoundTripPreservesTimestampAndEthernetFrame() + { + var timestamp = DateTimeOffset.UnixEpoch.AddSeconds(123).AddTicks(12_340); + var frame = new byte[] { 0x01, 0x0C, 0xCD, 0x04, 0x00, 0x01, 0x88, 0xBA }; + using var stream = new MemoryStream(); + + using (var writer = new PcapWriter(stream, leaveOpen: true)) + writer.WritePacket(timestamp, frame); + + stream.Position = 0; + var packets = PcapReader.ReadAll(stream); + + var packet = Assert.Single(packets); + Assert.Equal(timestamp, packet.Timestamp); + Assert.Equal(frame, packet.Frame); + } + + [Fact] + public void ReaderRejectsUnsupportedLinkType() + { + using var stream = new MemoryStream(); + using (var writer = new PcapWriter(stream, leaveOpen: true)) + { + } + + var bytes = stream.ToArray(); + BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(20, 4), 101); + + var ex = Assert.Throws(() => PcapReader.ReadAll(new MemoryStream(bytes))); + + Assert.Contains("link type", ex.Message, StringComparison.OrdinalIgnoreCase); + } + + [Fact] + public void ReaderRejectsTruncatedPacketPayload() + { + using var stream = new MemoryStream(); + using (var writer = new PcapWriter(stream, leaveOpen: true)) + writer.WritePacket(DateTimeOffset.UnixEpoch, new byte[] { 1, 2, 3, 4 }); + + var truncated = stream.ToArray()[..^1]; + + var ex = Assert.Throws(() => PcapReader.ReadAll(new MemoryStream(truncated))); + + Assert.Contains("payload", ex.Message, StringComparison.OrdinalIgnoreCase); + } + + [Fact] + public void WriterRejectsWritesAfterDispose() + { + var stream = new MemoryStream(); + var writer = new PcapWriter(stream, leaveOpen: true); + writer.Dispose(); + + Assert.Throws(() => writer.WritePacket(DateTimeOffset.UnixEpoch, new byte[] { 1 })); + } +} diff --git a/tests/ARSVIN.Tests/Comtrade/ComtradeReaderTests.cs b/tests/ARSVIN.Tests/Comtrade/ComtradeReaderTests.cs new file mode 100644 index 0000000..5d32207 --- /dev/null +++ b/tests/ARSVIN.Tests/Comtrade/ComtradeReaderTests.cs @@ -0,0 +1,126 @@ +using AR.Iec61850.Comtrade; +using Xunit; + +namespace ARSVIN.Tests.Comtrade; + +public sealed class ComtradeReaderTests +{ + [Fact] + public void LoadAsciiParsesConfigurationScalesChannelsAndPreservesTiming() + { + using var fixture = ComtradeFixture.Create( + dataFileType: "ASCII", + dataLines: + [ + "1,0,10,20", + "2,1000,11,22", + "3,2000,12,24" + ]); + + var dataset = new ComtradeReader().Load(fixture.ConfigurationPath); + + Assert.Equal("ARSVIN-LAB", dataset.Configuration.StationName); + Assert.Equal("MU01", dataset.Configuration.DeviceId); + Assert.Equal(2, dataset.Configuration.AnalogChannelCount); + Assert.Equal(3, dataset.SampleCount); + Assert.Equal(0.002, dataset.DurationSeconds, precision: 9); + Assert.Equal(1000, dataset.NominalSampleRateHz); + Assert.Equal(new double[] { 21, 9 }, dataset.Samples[0].AnalogValues); + Assert.Equal(new double[] { 23, 10 }, dataset.Samples[1].AnalogValues); + Assert.Equal(0.001, dataset.Samples[1].TimestampSeconds, precision: 9); + Assert.Contains("A=2", dataset.Summary); + } + + [Fact] + public void NonIncreasingAsciiTimestampFallsBackToConfiguredSampleRate() + { + using var fixture = ComtradeFixture.Create( + dataFileType: "ASCII", + dataLines: + [ + "1,0,1,2", + "2,0,3,4" + ]); + + var dataset = new ComtradeReader().Load(fixture.ConfigurationPath); + + Assert.Equal(0, dataset.Samples[0].TimestampSeconds); + Assert.Equal(0.001, dataset.Samples[1].TimestampSeconds, precision: 9); + } + + [Fact] + public void DatasetIndexingSupportsLoopingAndClamping() + { + using var fixture = ComtradeFixture.Create( + dataFileType: "ASCII", + dataLines: + [ + "1,0,1,2", + "2,1000,3,4", + "3,2000,5,6" + ]); + + var dataset = new ComtradeReader().Load(fixture.ConfigurationPath); + + Assert.Equal(1, dataset.GetSampleByIndex(3, loop: true).Number); + Assert.Equal(3, dataset.GetSampleByIndex(99, loop: false).Number); + Assert.Equal(3, dataset.GetSampleByIndex(-1, loop: true).Number); + } + + [Fact] + public void UnsupportedDataTypeFailsExplicitly() + { + using var fixture = ComtradeFixture.Create( + dataFileType: "BINARY64", + dataLines: ["1,0,1,2"]); + + var ex = Assert.Throws(() => new ComtradeReader().Load(fixture.ConfigurationPath)); + + Assert.Contains("BINARY64", ex.Message); + Assert.Contains("Supported DAT types", ex.Message); + } + + private sealed class ComtradeFixture : IDisposable + { + private ComtradeFixture(string directory, string configurationPath) + { + Directory = directory; + ConfigurationPath = configurationPath; + } + + public string Directory { get; } + public string ConfigurationPath { get; } + + public static ComtradeFixture Create(string dataFileType, IReadOnlyList dataLines) + { + var directory = Path.Combine(Path.GetTempPath(), $"arsvin-comtrade-{Guid.NewGuid():N}"); + System.IO.Directory.CreateDirectory(directory); + var configurationPath = Path.Combine(directory, "sample.cfg"); + var dataPath = Path.Combine(directory, "sample.dat"); + + File.WriteAllLines(configurationPath, + [ + "ARSVIN-LAB,MU01,1999", + "2,2A,0D", + "1,VA,A,,V,2,1,0,-32768,32767,100,1,P", + "2,IA,A,,A,0.5,-1,0,-32768,32767,100,1,P", + "50", + "1", + "1000,3", + "01/01/2026,00:00:00.000000", + "01/01/2026,00:00:00.000000", + dataFileType, + "1" + ]); + File.WriteAllLines(dataPath, dataLines); + + return new ComtradeFixture(directory, configurationPath); + } + + public void Dispose() + { + if (System.IO.Directory.Exists(Directory)) + System.IO.Directory.Delete(Directory, recursive: true); + } + } +} diff --git a/tests/ARSVIN.Tests/Diagnostics/HexDumpTests.cs b/tests/ARSVIN.Tests/Diagnostics/HexDumpTests.cs new file mode 100644 index 0000000..75d615e --- /dev/null +++ b/tests/ARSVIN.Tests/Diagnostics/HexDumpTests.cs @@ -0,0 +1,39 @@ +using AR.Iec61850.Diagnostics; +using Xunit; + +namespace ARSVIN.Tests.Diagnostics; + +public sealed class HexDumpTests +{ + [Fact] + public void ParseAcceptsMixedWhitespaceAndHexCase() + { + var bytes = HexDump.Parse("01 0a\nFF\t7c"); + + Assert.Equal(new byte[] { 0x01, 0x0A, 0xFF, 0x7C }, bytes); + } + + [Fact] + public void ParseReturnsEmptyForWhitespace() + { + Assert.Empty(HexDump.Parse(" \r\n\t ")); + } + + [Fact] + public void ToCompactStringTruncatesAndReportsRemainingBytes() + { + var text = HexDump.ToCompactString(new byte[] { 0x01, 0x02, 0x03, 0x04 }, maxBytes: 2); + + Assert.Equal("01 02 ... (+2 byte)", text); + } + + [Fact] + public void ContainsFindsOverlappingPatternAndTreatsEmptyPatternAsMatch() + { + var data = new byte[] { 0x10, 0x20, 0x20, 0x30 }; + + Assert.True(HexDump.Contains(data, new byte[] { 0x20, 0x20 })); + Assert.True(HexDump.Contains(data, ReadOnlySpan.Empty)); + Assert.False(HexDump.Contains(data, new byte[] { 0x30, 0x40 })); + } +} diff --git a/tests/ARSVIN.Tests/Mms/MmsDataCodecTests.cs b/tests/ARSVIN.Tests/Mms/MmsDataCodecTests.cs new file mode 100644 index 0000000..4d012e6 --- /dev/null +++ b/tests/ARSVIN.Tests/Mms/MmsDataCodecTests.cs @@ -0,0 +1,61 @@ +using AR.Iec61850.Mms; +using Xunit; + +namespace ARSVIN.Tests.Mms; + +public sealed class MmsDataCodecTests +{ + [Fact] + public void StructureRoundTripPreservesCommonMmsDataKinds() + { + var source = MmsDataValue.Structure(new MmsDataValue[] + { + MmsDataValue.Boolean(true), + MmsDataValue.Integer(-42), + MmsDataValue.Unsigned(42), + MmsDataValue.FloatingPoint(12.5f), + MmsDataValue.VisibleString("MU01"), + MmsDataValue.OctetString(new byte[] { 0xAA, 0x55 }), + MmsDataValue.BitString(3, new byte[] { 0xA0 }) + }); + + var decoded = Assert.Single(MmsDataCodec.DecodeAllData(MmsDataCodec.Encode(source))); + + Assert.Equal(MmsDataKind.Structure, decoded.Kind); + Assert.Equal(7, decoded.Children.Count); + Assert.True((bool)decoded.Children[0].Value!); + Assert.Equal(-42L, decoded.Children[1].Value); + Assert.Equal(42UL, decoded.Children[2].Value); + Assert.Equal(12.5f, Assert.IsType(decoded.Children[3].Value)); + Assert.Equal("MU01", decoded.Children[4].Value); + Assert.Equal(new byte[] { 0xAA, 0x55 }, decoded.Children[5].RawValue); + Assert.Equal(new byte[] { 0x03, 0xA0 }, decoded.Children[6].RawValue); + } + + [Fact] + public void UnknownContextSpecificTagRoundTripsWithoutDataLoss() + { + var source = MmsDataValue.Unknown(22, new byte[] { 0xDE, 0xAD, 0xBE, 0xEF }); + + var decoded = Assert.Single(MmsDataCodec.DecodeAllData(MmsDataCodec.Encode(source))); + + Assert.Equal(MmsDataKind.Unknown, decoded.Kind); + Assert.Equal(22, decoded.UnknownTagNumber); + Assert.Equal(source.RawValue, decoded.RawValue); + } + + [Fact] + public void DecodeAllDataReturnsEmptyForEmptyInput() + { + Assert.Empty(MmsDataCodec.DecodeAllData(ReadOnlyMemory.Empty)); + } + + [Fact] + public void DisplayStringUsesInvariantEngineeringText() + { + Assert.Equal("true", MmsDataCodec.ToDisplayString(MmsDataValue.Boolean(true))); + Assert.Equal("-17", MmsDataCodec.ToDisplayString(MmsDataValue.Integer(-17))); + Assert.Equal("12.5", MmsDataCodec.ToDisplayString(MmsDataValue.FloatingPoint(12.5f))); + Assert.Equal("SV01", MmsDataCodec.ToDisplayString(MmsDataValue.VisibleString("SV01"))); + } +} diff --git a/tests/ARSVIN.Tests/Mms/MmsObjectReferenceTests.cs b/tests/ARSVIN.Tests/Mms/MmsObjectReferenceTests.cs new file mode 100644 index 0000000..ace941f --- /dev/null +++ b/tests/ARSVIN.Tests/Mms/MmsObjectReferenceTests.cs @@ -0,0 +1,48 @@ +using AR.Iec61850.Mms; +using Xunit; + +namespace ARSVIN.Tests.Mms; + +public sealed class MmsObjectReferenceTests +{ + [Fact] + public void FromIec61850ReferenceInsertsFunctionalConstraint() + { + var reference = MmsObjectReference.FromIec61850Reference("LD0/MMXU1.TotW.mag.f", "MX"); + + Assert.Equal("LD0", reference.Domain); + Assert.Equal("MMXU1$MX$TotW$mag$f", reference.Item); + Assert.Equal("MX", reference.FunctionalConstraint); + Assert.Equal("LD0/MMXU1.MX.TotW.mag.f [MX]", reference.ToString()); + } + + [Fact] + public void ExistingFunctionalConstraintIsNotDuplicated() + { + var reference = MmsObjectReference.FromIec61850Reference("LD0/MMXU1$MX$TotW$mag$f", "MX"); + + Assert.Equal("MMXU1$MX$TotW$mag$f", reference.Item); + } + + [Fact] + public void WithoutFunctionalConstraintRemovesOnlyConstraintSegment() + { + var reference = new MmsObjectReference("LD0", "MMXU1$MX$TotW$mag$f", "MX"); + + var withoutFc = reference.WithoutFunctionalConstraint(); + + Assert.Equal("LD0", withoutFc.Domain); + Assert.Equal("MMXU1$TotW$mag$f", withoutFc.Item); + Assert.Equal(string.Empty, withoutFc.FunctionalConstraint); + } + + [Fact] + public void ReferenceWithoutDomainRemainsUsable() + { + var reference = MmsObjectReference.Parse("MMXU1.TotW.mag.f", "MX"); + + Assert.Equal(string.Empty, reference.Domain); + Assert.Equal("MMXU1$TotW$mag$f", reference.Item); + Assert.Equal("MMXU1$TotW$mag$f", reference.ToString()); + } +} diff --git a/tests/ARSVIN.Tests/SampledValues/SampledValuesPublisherSessionTests.cs b/tests/ARSVIN.Tests/SampledValues/SampledValuesPublisherSessionTests.cs new file mode 100644 index 0000000..f1e7709 --- /dev/null +++ b/tests/ARSVIN.Tests/SampledValues/SampledValuesPublisherSessionTests.cs @@ -0,0 +1,120 @@ +using AR.Iec61850.Ethernet; +using AR.Iec61850.SampledValues; +using AR.Iec61850.Scl; +using AR.Iec61850.Transports; +using Xunit; + +namespace ARSVIN.Tests.SampledValues; + +public sealed class SampledValuesPublisherSessionTests +{ + [Fact] + public async Task PublishNextAsyncSendsFrameAndWrapsSampleCounter() + { + var profile = SampledValuesPublisherProfile.Create(CreateStream(noAsdu: 1)); + var transport = new InMemoryProcessBusTransport(); + var session = new SampledValuesPublisherSession( + profile, + MacAddress.Parse("02:00:00:00:20:01"), + transport, + initialSampleCount: 3999, + sampleCounterWrap: 4000); + var payload = new byte[profile.PayloadLayout.PayloadByteLength]; + + var frame = await session.PublishNextAsync(payload); + + Assert.Equal((ushort)0, session.NextSampleCount); + Assert.Equal(frame, Assert.Single(transport.Frames)); + Assert.True(SampledValuesFrameParser.TryParseEthernetFrame(frame, out var parsed)); + Assert.Equal((ushort)3999, Assert.Single(parsed.Pdu.Asdus).SampleCount); + } + + [Fact] + public async Task PublishNextBatchAsyncAdvancesByAsduCountAcrossWrap() + { + var profile = SampledValuesPublisherProfile.Create(CreateStream(noAsdu: 4)); + var transport = new InMemoryProcessBusTransport(); + var session = new SampledValuesPublisherSession( + profile, + MacAddress.Parse("02:00:00:00:20:02"), + transport, + initialSampleCount: 3998, + sampleCounterWrap: 4000); + var payloads = Enumerable.Range(0, 4) + .Select(_ => new byte[profile.PayloadLayout.PayloadByteLength]) + .ToArray(); + + var frame = await session.PublishNextBatchAsync(payloads); + + Assert.Equal((ushort)2, session.NextSampleCount); + Assert.True(SampledValuesFrameParser.TryParseEthernetFrame(frame, out var parsed)); + Assert.Equal(new ushort[] { 3998, 3999, 0, 1 }, parsed.Pdu.Asdus.Select(asdu => asdu.SampleCount).ToArray()); + } + + [Fact] + public async Task SinglePayloadApiRejectsMultiAsduProfile() + { + var profile = SampledValuesPublisherProfile.Create(CreateStream(noAsdu: 4)); + var session = new SampledValuesPublisherSession( + profile, + MacAddress.Parse("02:00:00:00:20:03"), + new InMemoryProcessBusTransport()); + + var ex = await Assert.ThrowsAsync(async () => + await session.PublishNextAsync(new byte[profile.PayloadLayout.PayloadByteLength])); + + Assert.Contains("Use PublishNextBatchAsync", ex.Message); + } + + [Fact] + public void ConstructorRejectsDegenerateSampleCounterWrap() + { + var profile = SampledValuesPublisherProfile.Create(CreateStream(noAsdu: 1)); + + Assert.Throws(() => new SampledValuesPublisherSession( + profile, + MacAddress.Parse("02:00:00:00:20:04"), + new InMemoryProcessBusTransport(), + sampleCounterWrap: 1)); + } + + private static SclSampledValuesStream CreateStream(ushort noAsdu) + => new() + { + Kind = "SV", + IedName = "MU01", + LdInst = "MUnn", + ControlName = "MSVCB01", + ControlBlockReference = "MU01MUnn/LLN0$SV$MSVCB01", + SvId = "MU01SV01", + DataSetName = "PhsMeas", + DataSetReference = "MU01MUnn/LLN0$PhsMeas", + ConfigurationRevision = 1, + SampleRate = 80, + SampleMode = "SmpPerPeriod", + NoAsdu = noAsdu, + Address = new SclStreamAddress + { + AppIdText = "0x4001", + AppId = 0x4001, + DestinationMacText = "01:0C:CD:04:00:01", + DestinationMac = MacAddress.Parse("01:0C:CD:04:00:01"), + VlanId = 100, + VlanPriority = 4 + }, + Entries = new[] + { + new SclDataSetEntry + { + Index = 1, + SignalReference = "MU01/MUnn/TCTR1.Amp.instMag.i [MX]", + LnClass = "TCTR", + LnInst = "1", + DoName = "Amp", + DaName = "instMag.i", + Fc = "MX", + BType = "INT32" + } + } + }; +} diff --git a/tests/ARSVIN.Tests/Scl/SclParserTests.cs b/tests/ARSVIN.Tests/Scl/SclParserTests.cs new file mode 100644 index 0000000..be1150f --- /dev/null +++ b/tests/ARSVIN.Tests/Scl/SclParserTests.cs @@ -0,0 +1,151 @@ +using AR.Iec61850.Scl; +using Xunit; + +namespace ARSVIN.Tests.Scl; + +public sealed class SclParserTests +{ + [Fact] + public void ParseBuildsTypedSampledValuesStreamAddressAndReportControl() + { + var document = new SclParser().Parse(CompleteScl, "demo.scd"); + + Assert.Equal("demo.scd", document.SourceName); + Assert.Equal("DEMO", document.HeaderId); + Assert.Equal(SclEdition.Edition21, document.Edition); + Assert.Equal("MU01", Assert.Single(document.Ieds).Name); + + var dataSet = Assert.Single(document.DataSets); + Assert.Equal("MU01MUnn/LLN0$PhsMeas", dataSet.Reference); + Assert.Equal(2, dataSet.Entries.Count); + Assert.Equal("INT32", dataSet.Entries[0].BType); + Assert.True(dataSet.Entries[1].IsQuality); + + var stream = Assert.Single(document.SampledValuesStreams); + Assert.Equal("MU01SV01", stream.SvId); + Assert.Equal((uint)7, stream.ConfigurationRevision); + Assert.Equal((ushort)80, stream.SampleRate); + Assert.Equal((ushort)4, stream.NoAsdu); + Assert.Equal("0x4001", stream.Address.AppIdText); + Assert.Equal((ushort)0x4001, stream.Address.AppId); + Assert.Equal("01:0C:CD:04:00:01", stream.Address.DestinationMacText); + Assert.Equal((ushort)100, stream.Address.VlanId); + Assert.Equal((byte)4, stream.Address.VlanPriority); + + var report = Assert.Single(document.ReportControls); + Assert.True(report.Buffered); + Assert.Equal("MU01MUnn/LLN0$BR$BRCB01", report.ControlBlockReference); + Assert.Equal((uint)1000, report.IntegrityPeriodMilliseconds); + Assert.Equal(2, report.Entries.Count); + Assert.Empty(document.Conflicts); + } + + [Fact] + public void MissingDatasetProducesExplicitWarningAndSafeNoAsduDefault() + { + const string xml = """ + + + + + + + + + + + + + + """; + + var document = new SclParser().Parse(xml); + + var stream = Assert.Single(document.SampledValuesStreams); + Assert.Equal((ushort)1, stream.NoAsdu); + Assert.Empty(stream.Entries); + Assert.Contains(document.Warnings, warning => warning.Contains("references missing DataSet 'Missing'", StringComparison.Ordinal)); + Assert.Contains(document.Warnings, warning => warning.Contains("No DataSet element", StringComparison.Ordinal)); + } + + [Fact] + public void ParseRejectsNonSclRoot() + { + var ex = Assert.Throws(() => new SclParser().Parse("")); + + Assert.Contains("not an IEC 61850 SCL document", ex.Message); + } + + [Fact] + public void LoadUsesConfigurationFileNameAsSourceName() + { + var directory = Path.Combine(Path.GetTempPath(), $"arsvin-scl-{Guid.NewGuid():N}"); + Directory.CreateDirectory(directory); + var path = Path.Combine(directory, "station.scd"); + + try + { + File.WriteAllText(path, CompleteScl); + + var document = new SclParser().Load(path); + + Assert.Equal("station.scd", document.SourceName); + Assert.Single(document.SampledValuesStreams); + } + finally + { + if (Directory.Exists(directory)) + Directory.Delete(directory, recursive: true); + } + } + + private const string CompleteScl = """ + +
+ + + + +
+

01-0C-CD-04-00-01

+

4001

+

100

+

4

+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """; +}