@@ -30,6 +30,15 @@
|
||||
|
||||
.PARAMETER BridgeNodeId
|
||||
NodeId at which the server publishes the TagPath.
|
||||
|
||||
.PARAMETER FastBridgeNodeId
|
||||
Optional NodeId for a Tag declared with ScanRateMs <= 100. When supplied
|
||||
alongside SlowBridgeNodeId the script runs the per-tag scan-rate assertion
|
||||
(PR abcip-4.1).
|
||||
|
||||
.PARAMETER SlowBridgeNodeId
|
||||
Optional NodeId for a Tag declared with ScanRateMs >= 1000. Pair with
|
||||
FastBridgeNodeId to enable the scan-rate assertion.
|
||||
#>
|
||||
|
||||
param(
|
||||
@@ -37,7 +46,9 @@ param(
|
||||
[string]$Family = "ControlLogix",
|
||||
[string]$TagPath = "TestDINT",
|
||||
[string]$OpcUaUrl = "opc.tcp://localhost:4840",
|
||||
[Parameter(Mandatory)] [string]$BridgeNodeId
|
||||
[Parameter(Mandatory)] [string]$BridgeNodeId,
|
||||
[string]$FastBridgeNodeId,
|
||||
[string]$SlowBridgeNodeId
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
@@ -119,5 +130,57 @@ if ($Family -ne "Micro800") {
|
||||
}
|
||||
}
|
||||
|
||||
# PR abcip-4.1 — per-tag scan-rate divergence assertion. Runs only when both fast + slow
|
||||
# NodeIds are wired; otherwise this knob is skipped on the existing single-NodeId fixture.
|
||||
# The assertion is "fast bucket sees > 5x as many notifications as slow bucket" — the
|
||||
# unit + integration tests cover the bucketing math, this just proves the multi-rate split
|
||||
# survives end-to-end through the OPC UA server's Subscription / MonitoredItem path.
|
||||
if ($FastBridgeNodeId -and $SlowBridgeNodeId) {
|
||||
Write-Header "Per-tag scan rate (FastBridge=$FastBridgeNodeId, SlowBridge=$SlowBridgeNodeId)"
|
||||
$duration = 8
|
||||
$fastOut = New-TemporaryFile
|
||||
$slowOut = New-TemporaryFile
|
||||
$fastErr = New-TemporaryFile
|
||||
$slowErr = New-TemporaryFile
|
||||
$fastArgs = @($opcUaCli.PrefixArgs) + @("subscribe", "-u", $OpcUaUrl, "-n", $FastBridgeNodeId, "-i", "100", "--duration", "$duration")
|
||||
$slowArgs = @($opcUaCli.PrefixArgs) + @("subscribe", "-u", $OpcUaUrl, "-n", $SlowBridgeNodeId, "-i", "1000", "--duration", "$duration")
|
||||
$fastProc = Start-Process -FilePath $opcUaCli.File -ArgumentList $fastArgs `
|
||||
-NoNewWindow -PassThru `
|
||||
-RedirectStandardOutput $fastOut.FullName `
|
||||
-RedirectStandardError $fastErr.FullName
|
||||
$slowProc = Start-Process -FilePath $opcUaCli.File -ArgumentList $slowArgs `
|
||||
-NoNewWindow -PassThru `
|
||||
-RedirectStandardOutput $slowOut.FullName `
|
||||
-RedirectStandardError $slowErr.FullName
|
||||
Start-Sleep -Seconds 2
|
||||
|
||||
# Drive a single PLC change so even stable tags get *one* notification during the window
|
||||
# (initial-data push + 1 change). The cadence assertion below relies on the fast tag
|
||||
# accumulating sampling-interval-driven events even between explicit changes.
|
||||
$tickValue = Get-Random -Minimum 50000 -Maximum 59999
|
||||
$writeArgs = @("write") + $commonAbCip + @("-t", $TagPath, "--type", "DInt", "-v", $tickValue)
|
||||
& $abcipCli.Exe @($abcipCli.Args + $writeArgs) | Out-Null
|
||||
|
||||
$fastProc.WaitForExit(($duration + 5) * 1000) | Out-Null
|
||||
$slowProc.WaitForExit(($duration + 5) * 1000) | Out-Null
|
||||
if (-not $fastProc.HasExited) { Stop-Process -Id $fastProc.Id -Force }
|
||||
if (-not $slowProc.HasExited) { Stop-Process -Id $slowProc.Id -Force }
|
||||
|
||||
$fastText = (Get-Content $fastOut.FullName -Raw) + (Get-Content $fastErr.FullName -Raw)
|
||||
$slowText = (Get-Content $slowOut.FullName -Raw) + (Get-Content $slowErr.FullName -Raw)
|
||||
Remove-Item $fastOut.FullName, $slowOut.FullName, $fastErr.FullName, $slowErr.FullName -ErrorAction SilentlyContinue
|
||||
|
||||
# Each data-change line matches `=\s*<value>\s*(<status>)` per Test-SubscribeSeesChange.
|
||||
$fastMatches = ([regex]::Matches($fastText, "=\s*\S+\s*\(")).Count
|
||||
$slowMatches = ([regex]::Matches($slowText, "=\s*\S+\s*\(")).Count
|
||||
$passed = ($fastMatches -ge 5) -and ($fastMatches -gt ($slowMatches * 5))
|
||||
$detail = if ($passed) {
|
||||
"fast=$fastMatches notifications vs slow=$slowMatches (>5x ratio achieved)"
|
||||
} else {
|
||||
"fast=$fastMatches slow=$slowMatches — expected fast > slow*5"
|
||||
}
|
||||
$results += [PSCustomObject]@{ Name = "PerTagScanRate"; Passed = $passed; Detail = $detail }
|
||||
}
|
||||
|
||||
Write-Summary -Title "AB CIP e2e" -Results $results
|
||||
if ($results | Where-Object { -not $_.Passed }) { exit 1 }
|
||||
|
||||
Reference in New Issue
Block a user