144 lines
4.8 KiB
PowerShell
144 lines
4.8 KiB
PowerShell
# AGV GLB 一键启动
|
||
# 用法:
|
||
# .\start.ps1 启动服务并打开播放页
|
||
# .\start.ps1 -Setup 首次部署:创建 .venv 并安装 requirements.txt
|
||
# .\start.ps1 -NoBrowser 仅启动服务,不打开浏览器
|
||
param(
|
||
[switch]$Setup,
|
||
[switch]$NoBrowser,
|
||
[int]$Port = 8765
|
||
)
|
||
|
||
$ErrorActionPreference = "Stop"
|
||
|
||
$Root = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||
Set-Location $Root
|
||
|
||
function Write-Step([string]$Msg) {
|
||
Write-Host ('>> ' + $Msg) -ForegroundColor Cyan
|
||
}
|
||
|
||
function Find-Python {
|
||
foreach ($cmd in @('py -3', 'python3', 'python')) {
|
||
try {
|
||
$ver = Invoke-Expression ($cmd + ' --version 2>&1') | Out-String
|
||
if ($ver -match 'Python (\d+)\.(\d+)') {
|
||
$major = [int]$Matches[1]
|
||
$minor = [int]$Matches[2]
|
||
if ($major -gt 3 -or ($major -eq 3 -and $minor -ge 10)) {
|
||
return @{ Cmd = $cmd; Version = ($major.ToString() + '.' + $minor.ToString()) }
|
||
}
|
||
}
|
||
} catch { }
|
||
}
|
||
return $null
|
||
}
|
||
|
||
function Get-VenvPython {
|
||
$winPy = Join-Path $Root '.venv\Scripts\python.exe'
|
||
if (Test-Path $winPy) { return $winPy }
|
||
$unixPy = Join-Path $Root '.venv/bin/python'
|
||
if (Test-Path $unixPy) { return $unixPy }
|
||
return $null
|
||
}
|
||
|
||
function Test-PortInUse([int]$P) {
|
||
try {
|
||
$conn = Get-NetTCPConnection -LocalPort $P -State Listen -ErrorAction SilentlyContinue
|
||
return [bool]$conn
|
||
} catch {
|
||
$out = netstat -ano | Select-String (':' + $P + '\s+.*LISTENING')
|
||
return [bool]$out
|
||
}
|
||
}
|
||
|
||
function Wait-ServerReady([string]$BaseUrl, [int]$TimeoutSec = 30) {
|
||
$deadline = (Get-Date).AddSeconds($TimeoutSec)
|
||
while ((Get-Date) -lt $deadline) {
|
||
try {
|
||
$resp = Invoke-WebRequest -Uri ($BaseUrl + '/api/catalog') -UseBasicParsing -TimeoutSec 2
|
||
if ($resp.StatusCode -eq 200) { return $true }
|
||
} catch {
|
||
Start-Sleep -Milliseconds 400
|
||
}
|
||
}
|
||
return $false
|
||
}
|
||
|
||
Write-Host ''
|
||
Write-Host ' AGV GLB 本地服务' -ForegroundColor Green
|
||
Write-Host '==================' -ForegroundColor Green
|
||
Write-Host ''
|
||
|
||
$pyInfo = Find-Python
|
||
if (-not $pyInfo) {
|
||
Write-Host '错误: 未找到 Python 3.10+,请从 https://www.python.org/downloads/ 安装' -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
Write-Step ('Python ' + $pyInfo.Version + ' (' + $pyInfo.Cmd + ')')
|
||
|
||
$venvPy = Get-VenvPython
|
||
if ($Setup) {
|
||
Write-Step '创建虚拟环境 .venv ...'
|
||
if (-not $venvPy) {
|
||
Invoke-Expression ($pyInfo.Cmd + ' -m venv .venv')
|
||
$venvPy = Get-VenvPython
|
||
if (-not $venvPy) {
|
||
Write-Host '错误: 虚拟环境创建失败' -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
}
|
||
Write-Step '安装 Python 依赖 (analyze_agv.py 等工具需要) ...'
|
||
& $venvPy -m pip install --upgrade pip
|
||
& $venvPy -m pip install -r requirements.txt
|
||
Write-Host '依赖安装完成。' -ForegroundColor Green
|
||
}
|
||
|
||
if ($venvPy) {
|
||
Write-Step '使用虚拟环境: .venv'
|
||
} else {
|
||
Write-Step '使用系统 Python(serve.py 无需额外依赖)'
|
||
Write-Host '提示: 运行 .\start.ps1 -Setup 可安装 analyze_agv.py 所需依赖' -ForegroundColor DarkYellow
|
||
}
|
||
|
||
$baseUrl = 'http://127.0.0.1:' + $Port
|
||
|
||
if (Test-PortInUse $Port) {
|
||
Write-Host ('警告: 端口 ' + $Port + ' 已被占用。若 serve.py 已在运行,可直接访问:') -ForegroundColor Yellow
|
||
Write-Host (' 播放页: ' + $baseUrl + '/viewer/play.html') -ForegroundColor White
|
||
Write-Host (' 配置页: ' + $baseUrl + '/viewer/index.html') -ForegroundColor White
|
||
if (-not $NoBrowser) {
|
||
Start-Process ($baseUrl + '/viewer/play.html')
|
||
}
|
||
exit 0
|
||
}
|
||
|
||
$env:PORT = $Port.ToString()
|
||
|
||
Write-Step ('启动 serve.py,端口 ' + $Port + ' ...')
|
||
if ($venvPy) {
|
||
$proc = Start-Process -FilePath $venvPy -ArgumentList 'serve.py' -WorkingDirectory $Root -PassThru -WindowStyle Normal
|
||
} else {
|
||
$arg = '/k ' + $pyInfo.Cmd + ' serve.py'
|
||
$proc = Start-Process -FilePath 'cmd.exe' -ArgumentList $arg -WorkingDirectory $Root -PassThru -WindowStyle Normal
|
||
}
|
||
|
||
Write-Step '等待服务就绪 ...'
|
||
if (-not (Wait-ServerReady $baseUrl)) {
|
||
Write-Host '错误: 服务 30 秒内未响应,请查看 serve.py 窗口中的报错。' -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
|
||
Write-Host ''
|
||
Write-Host ('服务已启动 (PID ' + $proc.Id + ')') -ForegroundColor Green
|
||
Write-Host (' 播放页: ' + $baseUrl + '/viewer/play.html') -ForegroundColor White
|
||
Write-Host (' 配置页: ' + $baseUrl + '/viewer/index.html') -ForegroundColor White
|
||
Write-Host (' API: GET ' + $baseUrl + '/api/catalog | POST ' + $baseUrl + '/api/agv') -ForegroundColor White
|
||
Write-Host ''
|
||
Write-Host ('关闭服务: 在 serve.py 窗口按 Ctrl+C,或结束 PID ' + $proc.Id) -ForegroundColor DarkGray
|
||
Write-Host ''
|
||
|
||
if (-not $NoBrowser) {
|
||
Start-Process ($baseUrl + '/viewer/play.html')
|
||
}
|