sync: Add Yealink tools and session log for 2026-02-24/25
Session covering YMCS setup, Yealink phone scanner tool development, and Peaceful Spirit UCG Ultra speed diagnostics (ECM crash-loop, Cox plant issue). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
183
tools/test-yealink.ps1
Normal file
183
tools/test-yealink.ps1
Normal file
@@ -0,0 +1,183 @@
|
||||
# Test SSDP/UPnP discovery for Yealink phones
|
||||
param(
|
||||
[string]$IP = "172.16.1.29",
|
||||
[int]$DiscoveryTimeout = 5
|
||||
)
|
||||
|
||||
# --- Test 1: SSDP M-SEARCH broadcast ---
|
||||
Write-Host "=== Test 1: SSDP M-SEARCH (broadcast) ===" -ForegroundColor Yellow
|
||||
Write-Host " Sending M-SEARCH to 239.255.255.250:1900..." -ForegroundColor DarkGray
|
||||
|
||||
$ssdpMessage = @"
|
||||
M-SEARCH * HTTP/1.1
|
||||
HOST: 239.255.255.250:1900
|
||||
MAN: "ssdp:discover"
|
||||
MX: 3
|
||||
ST: ssdp:all
|
||||
|
||||
"@
|
||||
|
||||
$ssdpBytes = [System.Text.Encoding]::ASCII.GetBytes($ssdpMessage.Replace("`n", "`r`n"))
|
||||
$udpClient = New-Object System.Net.Sockets.UdpClient
|
||||
$udpClient.Client.ReceiveTimeout = ($DiscoveryTimeout * 1000)
|
||||
$udpClient.Client.SetSocketOption([System.Net.Sockets.SocketOptionLevel]::Socket,
|
||||
[System.Net.Sockets.SocketOptionName]::ReuseAddress, $true)
|
||||
|
||||
$multicastEp = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Parse("239.255.255.250"), 1900)
|
||||
$udpClient.Send($ssdpBytes, $ssdpBytes.Length, $multicastEp) | Out-Null
|
||||
|
||||
$responses = @()
|
||||
$sw = [System.Diagnostics.Stopwatch]::StartNew()
|
||||
while ($sw.Elapsed.TotalSeconds -lt $DiscoveryTimeout) {
|
||||
try {
|
||||
$remoteEp = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 0)
|
||||
$data = $udpClient.Receive([ref]$remoteEp)
|
||||
$response = [System.Text.Encoding]::ASCII.GetString($data)
|
||||
$sourceIp = $remoteEp.Address.ToString()
|
||||
|
||||
if ($response -match 'yealink|Yealink|YEALINK|SIP-T') {
|
||||
Write-Host " [YEALINK] Response from $sourceIp" -ForegroundColor Green
|
||||
Write-Host $response -ForegroundColor Cyan
|
||||
$responses += @{ IP = $sourceIp; Response = $response }
|
||||
}
|
||||
elseif ($sourceIp -eq $IP) {
|
||||
Write-Host " Response from TARGET $sourceIp" -ForegroundColor Green
|
||||
Write-Host $response -ForegroundColor Cyan
|
||||
$responses += @{ IP = $sourceIp; Response = $response }
|
||||
}
|
||||
}
|
||||
catch [System.Net.Sockets.SocketException] {
|
||||
break # Timeout
|
||||
}
|
||||
}
|
||||
$udpClient.Close()
|
||||
Write-Host " Received $($responses.Count) Yealink/target responses" -ForegroundColor DarkGray
|
||||
|
||||
# --- Test 2: Direct SSDP to the phone's IP ---
|
||||
Write-Host ""
|
||||
Write-Host "=== Test 2: Direct SSDP M-SEARCH to $IP ===" -ForegroundColor Yellow
|
||||
|
||||
$udpClient2 = New-Object System.Net.Sockets.UdpClient
|
||||
$udpClient2.Client.ReceiveTimeout = 3000
|
||||
|
||||
$directEp = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Parse($IP), 1900)
|
||||
$udpClient2.Send($ssdpBytes, $ssdpBytes.Length, $directEp) | Out-Null
|
||||
|
||||
try {
|
||||
$remoteEp2 = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 0)
|
||||
$data2 = $udpClient2.Receive([ref]$remoteEp2)
|
||||
$response2 = [System.Text.Encoding]::ASCII.GetString($data2)
|
||||
Write-Host " Response from $($remoteEp2.Address):" -ForegroundColor Green
|
||||
Write-Host $response2 -ForegroundColor Cyan
|
||||
}
|
||||
catch {
|
||||
Write-Host " No response (timeout)" -ForegroundColor DarkYellow
|
||||
}
|
||||
$udpClient2.Close()
|
||||
|
||||
# --- Test 3: Try fetching UPnP device description if we got a LOCATION header ---
|
||||
Write-Host ""
|
||||
Write-Host "=== Test 3: UPnP device description URLs ===" -ForegroundColor Yellow
|
||||
|
||||
# Try common UPnP description URLs
|
||||
$descUrls = @(
|
||||
"http://${IP}:1900/description.xml",
|
||||
"http://${IP}/description.xml",
|
||||
"http://${IP}:49152/description.xml",
|
||||
"http://${IP}:5060/description.xml",
|
||||
"http://${IP}/DeviceDescription.xml",
|
||||
"http://${IP}/upnp/description.xml"
|
||||
)
|
||||
|
||||
# Also extract LOCATION from any SSDP responses
|
||||
foreach ($r in $responses) {
|
||||
if ($r.Response -match 'LOCATION:\s*(http[^\s\r\n]+)') {
|
||||
$loc = $Matches[1].Trim()
|
||||
if ($descUrls -notcontains $loc) { $descUrls = @($loc) + $descUrls }
|
||||
}
|
||||
}
|
||||
|
||||
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
|
||||
[System.Net.ServicePointManager]::Expect100Continue = $false
|
||||
|
||||
# Enable unsafe header parsing
|
||||
$netAssembly = [System.Reflection.Assembly]::GetAssembly([System.Net.Configuration.SettingsSection])
|
||||
if ($netAssembly) {
|
||||
$settingsType = $netAssembly.GetType("System.Net.Configuration.SettingsSectionInternal")
|
||||
if ($settingsType) {
|
||||
$bf = [System.Reflection.BindingFlags]::Static -bor [System.Reflection.BindingFlags]::GetProperty -bor [System.Reflection.BindingFlags]::NonPublic
|
||||
$instance = $settingsType.InvokeMember("Section", $bf, $null, $null, @())
|
||||
if ($instance) {
|
||||
$field = $settingsType.GetField("useUnsafeHeaderParsing", [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance)
|
||||
if ($field) { $field.SetValue($instance, $true) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($url in $descUrls) {
|
||||
Write-Host " Trying: $url" -ForegroundColor DarkGray -NoNewline
|
||||
try {
|
||||
$req = [System.Net.HttpWebRequest]::Create($url)
|
||||
$req.Timeout = 3000
|
||||
$req.UserAgent = "UPnP/1.0"
|
||||
$resp = $req.GetResponse()
|
||||
$reader = New-Object System.IO.StreamReader($resp.GetResponseStream())
|
||||
$body = $reader.ReadToEnd()
|
||||
$reader.Close()
|
||||
$resp.Close()
|
||||
Write-Host " -> OK ($($body.Length) chars)" -ForegroundColor Green
|
||||
Write-Host $body -ForegroundColor Cyan
|
||||
|
||||
# Save if it looks like XML device description
|
||||
if ($body -match 'serialNumber|modelName|manufacturer') {
|
||||
Write-Host ""
|
||||
Write-Host " [FOUND] Device description with useful fields!" -ForegroundColor Green
|
||||
$body | Out-File "C:\temp\yealink_upnp.xml" -Encoding UTF8
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Host " -> FAIL" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
# --- Test 4: Try SNMP if available ---
|
||||
Write-Host ""
|
||||
Write-Host "=== Test 4: SNMP probe (community: public) ===" -ForegroundColor Yellow
|
||||
Write-Host " Trying SNMPv2c GET on common OIDs..." -ForegroundColor DarkGray
|
||||
|
||||
# Build a simple SNMPv2c GET request for sysDescr (1.3.6.1.2.1.1.1.0)
|
||||
# This is a minimal hand-crafted SNMP packet
|
||||
$snmpGet = [byte[]]@(
|
||||
0x30, 0x29, # SEQUENCE, length 41
|
||||
0x02, 0x01, 0x01, # INTEGER: version = 1 (SNMPv2c)
|
||||
0x04, 0x06, # OCTET STRING: community
|
||||
0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, # "public"
|
||||
0xA0, 0x1C, # GET-REQUEST, length 28
|
||||
0x02, 0x04, 0x01, 0x02, 0x03, 0x04, # request-id
|
||||
0x02, 0x01, 0x00, # error-status: 0
|
||||
0x02, 0x01, 0x00, # error-index: 0
|
||||
0x30, 0x0E, # varbind list
|
||||
0x30, 0x0C, # varbind
|
||||
0x06, 0x08, # OID
|
||||
0x2B, 0x06, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00, # 1.3.6.1.2.1.1.1.0 (sysDescr)
|
||||
0x05, 0x00 # NULL
|
||||
)
|
||||
|
||||
try {
|
||||
$snmpClient = New-Object System.Net.Sockets.UdpClient
|
||||
$snmpClient.Client.ReceiveTimeout = 3000
|
||||
$snmpEp = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Parse($IP), 161)
|
||||
$snmpClient.Send($snmpGet, $snmpGet.Length, $snmpEp) | Out-Null
|
||||
|
||||
$snmpRemote = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 0)
|
||||
$snmpData = $snmpClient.Receive([ref]$snmpRemote)
|
||||
$snmpResponse = [System.Text.Encoding]::ASCII.GetString($snmpData)
|
||||
Write-Host " SNMP response received ($($snmpData.Length) bytes)" -ForegroundColor Green
|
||||
# Try to extract readable text from the response
|
||||
$readable = ($snmpData | ForEach-Object { if ($_ -ge 32 -and $_ -le 126) { [char]$_ } else { "." } }) -join ""
|
||||
Write-Host " Readable: $readable" -ForegroundColor Cyan
|
||||
$snmpClient.Close()
|
||||
}
|
||||
catch {
|
||||
Write-Host " No SNMP response (timeout or blocked)" -ForegroundColor DarkYellow
|
||||
}
|
||||
Reference in New Issue
Block a user