[Console]::OutputEncoding = [Text.Encoding]::UTF8 $ErrorActionPreference = "Stop" function H2B($hex) { if (-not $hex) { return $null } $n = $hex.Length / 2 $b = New-Object byte[] $n for ($i = 0; $i -lt $n; $i++) { $b[$i] = [Convert]::ToByte($hex.Substring(2*$i, 2), 16) } return $b } $lines = [IO.File]::ReadAllLines("$env:TEMP\opencode\ss123.tsv") $dmx = New-Object System.Collections.ArrayList foreach ($l in $lines) { $p = $l -split "`t"; if ($p.Count -lt 5 -or -not $p[4]) { continue } if ($p[1] -ne "192.168.123.113" -or $p[2] -ne "192.168.123.1") { continue } $b = H2B $p[4]; if ($b.Length -ne 1084) { continue } if ([int]$b[4] -ne 4) { continue } if (-not ($b[0x20] -eq 1 -and $b[0x21] -eq 1)) { continue } [void]$dmx.Add(@{ t=[double]$p[0]; b=$b }) } Write-Host ("DMX-A 帧数: {0}" -f $dmx.Count) # --- 0x22-0x29 作为 LE u64 检验 --- function GU64($b, $off) { $v = [uint64]0 for ($i = 7; $i -ge 0; $i--) { $v = $v * 256 + [uint64]$b[$off+$i] } return $v } $inc64 = 0; $dec64 = 0; $eq = 0 $deltas = New-Object System.Collections.ArrayList for ($i = 1; $i -lt $dmx.Count; $i++) { $v0 = GU64 $dmx[$i-1].b 0x22; $v1 = GU64 $dmx[$i].b 0x22 if ($v1 -gt $v0) { $inc64++; [void]$deltas.Add($v1 - $v0) } elseif ($v1 -lt $v0) { $dec64++ } else { $eq++ } } Write-Host ("u64@0x22: 增={0} 减={1} 等={2}" -f $inc64, $dec64, $eq) if ($deltas.Count -gt 0) { $ds = $deltas | Sort-Object Write-Host (" 增量: min={0} p50={1} p90={2} max={3}" -f $ds[0], $ds[[int]($ds.Count/2)], $ds[[int]($ds.Count*0.9)], $ds[-1]) $top = $deltas | Group-Object | Sort-Object { [int]$_.Name } | Select-Object -First 8 Write-Host (" 常见增量: " + (($top | ForEach-Object { "{0}×{1}" -f $_.Name, $_.Count }) -join ", ")) } Write-Host (" 首帧 u64={0} (0x{0:x}) 尾帧 u64={1} (0x{1:x})" -f (GU64 $dmx[0].b 0x22), (GU64 $dmx[-1].b 0x22)) # --- u64 增量 vs 实际时间差: 是否微秒时间戳 --- Write-Host "`n=== u64 增量 vs 时间差相关性 (前 12 帧) ===" for ($i = 1; $i -lt 13; $i++) { $dt = ($dmx[$i].t - $dmx[$i-1].t) * 1000000 # us $dv = [int64]((GU64 $dmx[$i].b 0x22) - (GU64 $dmx[$i-1].b 0x22)) Write-Host (" dt={0,8:N0}us du64={1,8}" -f $dt, $dv) } # --- 0x1A-0x1B: 与通道数据的校验和关系? --- Write-Host "`n=== 0x1A-0x1B 检验 (是否通道数据校验) ===" $matchSum = 0; $matchCrc = 0 foreach ($f in ($dmx | Select-Object -First 200)) { $stored = [int]$f.b[0x1A] + [int]$f.b[0x1B]*256 # 简单和 (0x3C 起 1024B) $sum = 0; foreach ($v in $f.b[0x3C..0x43B]) { $sum += $v } if (($sum -band 0xFFFF) -eq $stored) { $matchSum++ } # CRC16-IBM $crc = 0 foreach ($v in $f.b[0x3C..0x43B]) { $crc = $crc -bxor $v for ($j = 0; $j -lt 8; $j++) { if ($crc -band 1) { $crc = ($crc -shr 1) -bxor 0xA001 } else { $crc = $crc -shr 1 } } } if ($crc -eq $stored) { $matchCrc++ } } Write-Host (" 简单和匹配: {0}/200 CRC16-IBM匹配: {1}/200" -f $matchSum, $matchCrc) # 打印几个 stored 值与帧序关系 Write-Host (" 0x1A-1B 前 10 帧: " + ((($dmx | Select-Object -First 10) | ForEach-Object { "{0:x2}{1:x2}" -f $_.b[0x1B], $_.b[0x1A] }) -join " ")) # --- 0x22-0x29 是否某种位打包 seq? 试 u32@0x22 / u32@0x26 --- foreach ($off in @(0x22, 0x24, 0x26)) { $v0 = (GU64 $dmx[0].b $off) -band 0xFFFFFFFF $vN = (GU64 $dmx[-1].b $off) -band 0xFFFFFFFF $inc = 0; $dec = 0 for ($i = 1; $i -lt $dmx.Count; $i++) { $a = (GU64 $dmx[$i-1].b $off) -band 0xFFFFFFFF $b2 = (GU64 $dmx[$i].b $off) -band 0xFFFFFFFF if ($b2 -gt $a) { $inc++ } elseif ($b2 -lt $a) { $dec++ } } Write-Host ("u32@0x{0:x2}: 首={1} 尾={2} 增={3} 减={4}" -f $off, $v0, $vN, $inc, $dec) }