<# .SYNOPSIS 启动支持网页命令输入的串口实时控制台。 .DESCRIPTION 使用单一进程独占串口,同时提供串口读取、原始日志、时间戳文本日志和本机网页命令接口。 网页仅监听 127.0.0.1;普通命令支持 None、CR、LF、CRLF 四种结尾。 .EXAMPLE .\serial_web_console.ps1 -Port COM56 -LogPath F:\tmp\serial.log .EXAMPLE .\serial_web_console.ps1 -Port COM56 -LogPath .\serial.log -WebPort 8766 .PARAMETER ValidateOnly 只编译并验证程序和页面资源,不打开串口,也不监听网页端口。 #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$Port, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$LogPath, [ValidateRange(1, 4000000)] [int]$BaudRate = 115200, [ValidateRange(5, 8)] [int]$DataBits = 8, [ValidateSet('None', 'Odd', 'Even', 'Mark', 'Space')] [string]$Parity = 'None', [ValidateSet('One', 'OnePointFive', 'Two')] [string]$StopBits = 'One', [ValidateSet('None', 'XOnXOff', 'RequestToSend', 'RequestToSendXOnXOff')] [string]$Handshake = 'None', [string]$EncodingName = 'utf-8', [ValidateRange(1, 5000)] [int]$PollMilliseconds = 100, [ValidateRange(64, 1048576)] [int]$BufferSize = 4096, [string]$RawPath, [ValidateRange(1024, 65535)] [int]$WebPort = 8766, [string]$HtmlPath, [ValidateRange(0, 2147483647)] [int]$DurationSeconds = 0, [switch]$DtrEnable, [switch]$RtsEnable, [switch]$ValidateOnly ) $ErrorActionPreference = 'Stop' $broker = $null try { if ($PSVersionTable.PSEdition -ne 'Desktop') { throw '该脚本需要由 Windows PowerShell 5.1 运行。请使用 powershell.exe,而不是 pwsh.exe。' } $sourcePath = Join-Path $PSScriptRoot 'SerialWebConsoleHost.cs' if (-not (Test-Path -LiteralPath $sourcePath -PathType Leaf)) { throw "找不到串口服务源文件:$sourcePath" } if ([string]::IsNullOrWhiteSpace($HtmlPath)) { $HtmlPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'assets\serial-console.html' } $resolvedHtmlPath = [System.IO.Path]::GetFullPath($HtmlPath) if (-not (Test-Path -LiteralPath $resolvedHtmlPath -PathType Leaf)) { throw "找不到串口控制台页面:$resolvedHtmlPath" } # Windows PowerShell 5.1 自带完整 .NET Framework,可直接编译 SerialPort 和 HttpListener。 Add-Type -Path $sourcePath -ErrorAction Stop if ($ValidateOnly.IsPresent) { Write-Output "验证通过:串口服务代码已编译,网页资源存在。" Write-Output "源文件:$sourcePath" Write-Output "页面:$resolvedHtmlPath" return } $resolvedLogPath = [System.IO.Path]::GetFullPath($LogPath) if ([string]::IsNullOrWhiteSpace($RawPath)) { $resolvedRawPath = $resolvedLogPath + '.raw.bin' } else { $resolvedRawPath = [System.IO.Path]::GetFullPath($RawPath) } $broker = [EmbeddedAppPcDebug.SerialWebConsoleHost]::new( $Port, $BaudRate, $DataBits, $Parity, $StopBits, $Handshake, $EncodingName, $PollMilliseconds, $BufferSize, $DtrEnable.IsPresent, $RtsEnable.IsPresent, $resolvedLogPath, $resolvedRawPath, $WebPort, $resolvedHtmlPath ) $broker.Start() $startTime = Get-Date Write-Output "串口网页控制台已启动:$($broker.Url)" Write-Output "按 Ctrl+C 可停止串口采集和网页服务。" while (-not $broker.IsStopping) { if ($DurationSeconds -gt 0 -and ((Get-Date) - $startTime).TotalSeconds -ge $DurationSeconds) { break } Start-Sleep -Milliseconds 200 } } catch { $message = '[' + (Get-Date -Format 'yyyy-MM-dd HH:mm:ss.fff') + '] 串口网页控制台失败:' + [string]$_.Exception.Message [Console]::Error.WriteLine($message) exit 1 } finally { if ($null -ne $broker) { $broker.Dispose() } }