78 lines
3.7 KiB
PowerShell
78 lines
3.7 KiB
PowerShell
# Verify-Rs485.ps1 — 验证 rs485_verification_plan.md §2 离线项 S1~S4(-Hardware 时附 COM 口探测)
|
||
param(
|
||
[switch]$Hardware
|
||
)
|
||
$ErrorActionPreference = 'Stop'
|
||
$script:pass = 0; $script:fail = 0
|
||
function Check($name, $cond, $detail) {
|
||
if ($cond) { $script:pass++; Write-Host (" [PASS] {0} {1}" -f $name, $detail) }
|
||
else { $script:fail++; Write-Host (" [FAIL] {0} {1}" -f $name, $detail) }
|
||
}
|
||
$dir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||
|
||
Write-Host "== S1 帧编码 =="
|
||
$expected = [byte[]](0x42, 0x52, 0x54, 0x3D, 0x38, 0x30, 0x0A)
|
||
$payload = "BRT=80\n" -replace '\\n', "`n" -replace '\\r', "`r"
|
||
$bytes = [System.Text.Encoding]::ASCII.GetBytes($payload)
|
||
$same = ($bytes.Count -eq $expected.Count) -and (-not (Compare-Object $bytes $expected -SyncWindow 0))
|
||
Check "S1a BRT=80\n字节序列" $same ("| " + (($bytes | ForEach-Object { $_.ToString('X2') }) -join ' '))
|
||
|
||
$p1 = "A\r\nB" -replace '\\r', "`r" -replace '\\n', "`n"
|
||
$CR = $p1.Contains([char]0x0D); $LF = $p1.Contains([char]0x0A)
|
||
Check "S1b \r\n 转义还原" ($CR -and $LF) ("| CR={0} LF={1}" -f $CR, $LF)
|
||
|
||
Write-Host "== S2 行帧解析 =="
|
||
$buf = "BRT=0`nBRT=25`r`nBRT=50`nBRT="
|
||
$parts = $buf -split "`n"
|
||
$complete = $parts[0..($parts.Count - 2)]
|
||
$rest = $parts[-1]
|
||
$clean = @($complete | ForEach-Object { $_.TrimEnd("`r") })
|
||
Check "S2a 完整行数" ($clean.Count -eq 3) ("| " + ($clean -join ' / '))
|
||
Check "S2b 半包留缓冲" ($rest -eq 'BRT=') ("| tail='$rest'")
|
||
Check "S2c 行内容无损" (($clean -join ',') -eq 'BRT=0,BRT=25,BRT=50') "| 无CR残留且顺序正确"
|
||
|
||
Write-Host "== S3 Lua 脚本结构 =="
|
||
$luaPath = Join-Path $dir 'lpc_serial_brt.lua'
|
||
Check "S3a 脚本文件存在" (Test-Path $luaPath) "| $luaPath"
|
||
if (Test-Path $luaPath) {
|
||
$lua = Get-Content $luaPath -Raw
|
||
Check "S3b 读取通配符变量" ($lua -match 'get_trigger_variable\(1\)') "| get_trigger_variable(1).integer(Designer 2 语法)"
|
||
Check "S3c 边界钳位" ($lua -match 'if v < 0' -and $lua -match 'if v > 100') "| 0..100"
|
||
Check "S3d 强度换算" ($lua -match 'v / 100') "| 百分比→0..1"
|
||
Check "S3e 组主亮度调光" ($lua -match 'get_group' -and $lua -match 'set_master_intensity') "| get_group(n):set_master_intensity"
|
||
$balance = ([regex]::Matches($lua, '\(')).Count -eq ([regex]::Matches($lua, '\)')).Count
|
||
Check "S3f 括号配平" $balance "| 粗略语法完整性"
|
||
}
|
||
|
||
Write-Host "== S4 工具模式 =="
|
||
$tool = Join-Path $dir 'Test-Rs485.ps1'
|
||
$errs = $null
|
||
$null = [System.Management.Automation.Language.Parser]::ParseFile($tool, [ref]$null, [ref]$errs)
|
||
Check "S4a Test-Rs485.ps1 语法" ($errs.Count -eq 0) ("| 语法错误 {0} 个" -f $errs.Count)
|
||
$raw = Get-Content $tool -Raw
|
||
foreach ($mode in 'ListPorts', 'Send', 'Listen', 'Interactive') {
|
||
Check "S4b 模式 -$mode" ($raw -match "\`$$mode|\[$mode\]|-$mode") "| 参数存在"
|
||
}
|
||
|
||
if ($Hardware) {
|
||
Write-Host "== 硬件探测(只开/关端口,不写数据)=="
|
||
foreach ($p in ([System.IO.Ports.SerialPort]::GetPortNames() | Sort-Object)) {
|
||
$sp = $null
|
||
try {
|
||
$sp = New-Object System.IO.Ports.SerialPort($p, 9600, 'None', 8, 'One')
|
||
$sp.ReadTimeout = 200
|
||
$sp.Open(); $sp.Close()
|
||
Write-Host (" [OPEN] {0} 可用(候选 USB-485,拔插对比确认)" -f $p)
|
||
} catch {
|
||
Write-Host (" [BUSY] {0} 被占用或不可开:{1}" -f $p, $_.Exception.Message.Trim())
|
||
} finally {
|
||
if ($sp -and $sp.IsOpen) { $sp.Close() }
|
||
}
|
||
}
|
||
}
|
||
|
||
Write-Host ""
|
||
Write-Host "========================================"
|
||
Write-Host ("RS485 链路离线验证结果: PASS={0} FAIL={1}" -f $script:pass, $script:fail)
|
||
if ($script:fail -eq 0) { Write-Host ">>> 离线验证全部通过,可进入阶段1(H1 单机自发自收)<<<" }
|