[Console]::OutputEncoding = [Text.Encoding]::UTF8 $ErrorActionPreference = "Stop" $f = "$env:TEMP\opencode\cold2.tsv" $lines = [IO.File]::ReadAllLines($f) 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 } function G16le($b, $o) { if ($b.Length -lt $o+2) { return -1 }; return $b[$o] -bor ($b[$o+1] -shl 8) } function G32le($b, $o) { if ($b.Length -lt $o+4) { return -1 }; return $b[$o] -bor ($b[$o+1] -shl 8) -bor ($b[$o+2] -shl 16) -bor ($b[$o+3] -shl 24) } function Hex($b) { return ($b | ForEach-Object { $_.ToString("x2") }) -join "" } function UidStr($b, $o) { if ($b.Length -lt $o+6) { return "?" }; return ($b[$o..($o+5)] | ForEach-Object { $_.ToString("x2") }) -join "" } # checksum 测试: 先用已知 0002 样本验证公式 Write-Host "=========== [0] checksum 公式自验 (0002 样本) ===========" $sample = H2B "454e65740400000000001c7c00000000000001004600000002004275746c0000a5000000000000001c00cc011a453a7fffffff0899500026c952000000001100020200000729" $msgLen = $sample[0x2C] $sum = 0; for ($i = 0x2A; $i -lt 0x2A + $msgLen; $i++) { $sum += $sample[$i] } $ckOff = 0x2A + $msgLen Write-Host (" msgLen={0} sum=0x{1:x4} field=0x{2:x4} -> {3}" -f $msgLen, ($sum -band 0xFFFF), (($sample[$ckOff] -shl 8) -bor $sample[$ckOff+1]), $(if (($sum -band 0xFFFF) -eq (($sample[$ckOff] -shl 8) -bor $sample[$ckOff+1])) {"OK"} else {"BAD"})) # ============ A) .1->113 全帧型直方图 (type x len) ============ Write-Host "`n=========== [A] .1→113 全帧型 (type×len) 直方图 ===========" $h = @{} 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.1") { continue } $b = H2B $p[4]; if ($b.Length -lt 0x1A) { continue } $t = G32le $b 4 $k = "type=$t len=$($b.Length)" if (-not $h.ContainsKey($k)) { $h[$k] = 0 }; $h[$k]++ } $h.GetEnumerator() | Sort-Object { [int]($_.Value) } -Descending | Select-Object -First 25 | ForEach-Object { Write-Host (" {0} : {1}" -f $_.Key, $_.Value) } # ============ B) type=2 帧时间线 (注册/AECH/AERE/心跳) ============ Write-Host "`n=========== [B] type=2 帧时间线 (全程, 前 40 条) ===========" $shown = 0 foreach ($l in $lines) { $p = $l -split "`t"; if ($p.Count -lt 5 -or -not $p[4]) { continue } $b = H2B $p[4]; if ($b.Length -lt 0x1A) { continue } if ((G32le $b 4) -ne 2) { continue } $sub = G16le $b 0x18 $t = [double]$p[0] Write-Host (" t={0,8:F3} {1,-26} len={2,-4} sub={3}" -f $t, "$($p[1])->$($p[2])", $b.Length, $sub) $shown++; if ($shown -ge 40) { break } } # ============ C) 发现请求/应答: 180B 请求 vs 217B 应答 全文 ============ Write-Host "`n=========== [C] 180B 发现请求 与 217B 应答 样本 ===========" $req180 = $null; $resp217 = $null foreach ($l in $lines) { $p = $l -split "`t"; if ($p.Count -lt 5 -or -not $p[4]) { continue } $b = H2B $p[4] if (-not $req180 -and $p[1] -eq "192.168.123.113" -and $b.Length -eq 180) { $req180 = $b } if (-not $resp217 -and $p[1] -eq "192.168.123.1" -and $b.Length -eq 217) { $resp217 = $b } if ($req180 -and $resp217) { break } } if ($req180) { Write-Host (" 请求180B: " + (Hex $req180)) } if ($resp217) { Write-Host (" 应答217B: " + (Hex $resp217)) } # ============ D) cmd=19 / cmd=1a 查询与应答样本 ============ Write-Host "`n=========== [D] cmd=19 / cmd=1a 样本 (各3条查询+应答) ===========" foreach ($wantCmd in @(0x19, 0x1a)) { $cnt = 0 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 -lt 0x52 -or $b.Length -gt 2000) { continue } if ((G32le $b 4) -ne 4 -or $b[0x3D] -ne $wantCmd -or $b[0x30] -ne 0) { continue } $t = [double]$p[0] Write-Host (" cmd={0:x2} t={1:F3} UID={2} 查询({3}B): {4}" -f $wantCmd, $t, (UidStr $b 0x3E), $b.Length, (Hex ($b[0x20..0x2F] + $b[0x3C..([Math]::Min($b.Length-1, 0x58))]))) $cnt++; if ($cnt -ge 3) { break } } } # ============ E) flag=01 PID=0003 帧样本 (780条是什么) ============ Write-Host "`n=========== [E] flag=01 PID=0003 帧样本 (前3条, 含UID) ===========" $cnt = 0 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 -lt 0x52 -or $b.Length -gt 2000) { continue } if ((G32le $b 4) -ne 4 -or $b[0x3D] -ne 0x18 -or $b[0x30] -ne 1) { continue } if ($b[0x50] -ne 0 -or $b[0x51] -ne 3) { continue } $t = [double]$p[0] Write-Host (" t={0:F3} len={1} flag01 UID={2} hdr: {3}" -f $t, $b.Length, (UidStr $b 0x3E), (Hex $b[0x20..0x33])) $cnt++; if ($cnt -ge 3) { break } } # ============ F) 脉冲时延: cmd=24 查询 → 脉冲 ============ Write-Host "`n=========== [F] cmd=24(flag=00) 查询→脉冲 时延分布 ===========" $discQ = New-Object System.Collections.ArrayList $pulses = New-Object System.Collections.ArrayList foreach ($l in $lines) { $p = $l -split "`t"; if ($p.Count -lt 5 -or -not $p[4]) { continue } $b = H2B $p[4]; if ($b.Length -lt 0x2E) { continue } $t = [double]$p[0] if ($p[1] -eq "192.168.123.113" -and $p[2] -eq "192.168.123.1" -and $b.Length -gt 0x44 -and $b.Length -lt 2000 -and (G32le $b 4) -eq 4 -and $b[0x3D] -eq 0x24 -and $b[0x30] -eq 0) { [void]$discQ.Add(@{ t=$t; lo=($b[0x3E..0x43] | ForEach-Object { $_.ToString("x2") }) -join "" }) } if ($p[1] -eq "192.168.123.1" -and $b.Length -lt 200 -and $b[0x2A] -eq 0xAA) { [void]$pulses.Add(@{ t=$t }) } } Write-Host (" cmd24查询={0} 脉冲={1}" -f $discQ.Count, $pulses.Count) $lats = New-Object System.Collections.ArrayList foreach ($pu in $pulses) { # 找之前最近的查询 $best = $null for ($i = $discQ.Count - 1; $i -ge 0; $i--) { if ($discQ[$i].t -le $pu.t) { $best = $discQ[$i]; break } } if ($best -and ($pu.t - $best.t) -lt 0.5) { [void]$lats.Add([int](($pu.t - $best.t) * 1000)) } } if ($lats.Count -gt 0) { $ls = $lats | Sort-Object Write-Host (" 脉冲时延ms: n={0} min={1} 中位={2} max={3}" -f $ls.Count, $ls[0], $ls[[int]($ls.Count/2)], $ls[-1]) } # ============ G) cmd=24 查询负载: 分支范围 vs 全范围 ============ Write-Host "`n=========== [G] cmd=24 查询的搜索范围分布 (UID 下界@0x3E) ===========" $ranges = @{} foreach ($q in $discQ) { if (-not $ranges.ContainsKey($q.lo)) { $ranges[$q.lo] = 0 }; $ranges[$q.lo]++ } $ranges.GetEnumerator() | Sort-Object Value -Descending | Select-Object -First 10 | ForEach-Object { Write-Host (" 范围下界={0} : {1}" -f $_.Key, $_.Value) } # ============ H) AECH/AERE 帧 (594B) 抓取 ============ Write-Host "`n=========== [H] AECH/AERE (594B type=2) 时间点 ===========" foreach ($l in $lines) { $p = $l -split "`t"; if ($p.Count -lt 5 -or -not $p[4]) { continue } $b = H2B $p[4]; if ($b.Length -lt 500) { continue } if ((G32le $b 4) -ne 2) { continue } $sub = G16le $b 0x18 $t = [double]$p[0] Write-Host (" t={0:F3} {1} len={2} sub={3} hasAECH={4} hasAERE={5}" -f $t, "$($p[1])->$($p[2])", $b.Length, $sub, ((Hex $b) -match "41454348"), ((Hex $b) -match "41455245")) } Write-Host "`n分析完成。"