PowerShell Script Content
This script waits for the local PWI4 API, connects the mount if needed, enables RA/Azimuth first, enables DEC/Altitude second, uses up to three total attempts through disconnect/connect recovery if an axis does not become enabled and optionally starts homing.
param(
[string]$BaseUrl = "http://localhost:8220",
[int]$TimeoutSeconds = 90,
[int]$HomeSettleSeconds = 3,
[int]$AxisTimeoutSeconds = 20,
[int]$AxisRetryCount = 2,
[int]$AxisEnableSettleSeconds = 5,
[int]$AxisRetryDelaySeconds = 10,
[int]$ReconnectSettleSeconds = 8,
[int]$StatusLogIntervalSeconds = 5,
[bool]$DetailedLog = $true,
[string]$LogDirectory = "",
[switch]$SkipHome,
[switch]$DryRun
)
$ScriptVersion = "2026-05-26.1"
$ErrorActionPreference = "Stop"
$script:RunStartedAt = Get-Date
$script:RunId = "{0}_pid{1}" -f $script:RunStartedAt.ToString("yyyyMMdd_HHmmss_fff"), $PID
$script:ScriptRoot = if ([string]::IsNullOrWhiteSpace($PSScriptRoot)) { (Get-Location).Path } else { $PSScriptRoot }
if ([string]::IsNullOrWhiteSpace($LogDirectory)) {
$LogDirectory = Join-Path $script:ScriptRoot "logs"
}
elseif (-not [System.IO.Path]::IsPathRooted($LogDirectory)) {
$LogDirectory = Join-Path $script:ScriptRoot $LogDirectory
}
$script:LogDirectory = $LogDirectory
$script:LatestLogPath = Join-Path $script:ScriptRoot "pwi4_connect_enable_home.log"
$script:DetailLogPath = Join-Path $script:LogDirectory ("pwi4_connect_enable_home_{0}.log" -f $script:RunId)
$script:LogTargets = @()
function Add-AsciiLogLines {
param(
[string]$Path,
[string[]]$Lines,
[switch]$Overwrite
)
$fileMode = if ($Overwrite) { [System.IO.FileMode]::Create } else { [System.IO.FileMode]::Append }
$stream = $null
$writer = $null
try {
$stream = New-Object System.IO.FileStream($Path, $fileMode, [System.IO.FileAccess]::Write, [System.IO.FileShare]::ReadWrite)
$writer = New-Object System.IO.StreamWriter($stream, [System.Text.Encoding]::ASCII)
foreach ($line in $Lines) {
$writer.WriteLine($line)
}
$writer.Flush()
}
finally {
if ($null -ne $writer) {
$writer.Dispose()
}
elseif ($null -ne $stream) {
$stream.Dispose()
}
}
}
function Initialize-LogFiles {
$usableTargets = @()
$latestHeader = @(
"------------------------------------------------------------",
"PWI4 Connect Helper diagnostic log",
("RunId={0}" -f $script:RunId),
("Started={0}" -f $script:RunStartedAt.ToString("yyyy-MM-dd HH:mm:ss.fff zzz")),
("ScriptVersion={0}" -f $ScriptVersion),
""
)
try {
Add-AsciiLogLines -Path $script:LatestLogPath -Lines $latestHeader
$usableTargets += $script:LatestLogPath
}
catch {
Write-Host ("Log file could not be initialized at {0}: {1}" -f $script:LatestLogPath, $_.Exception.Message)
}
try {
if (-not (Test-Path -LiteralPath $script:LogDirectory)) {
New-Item -ItemType Directory -Path $script:LogDirectory -Force | Out-Null
}
$detailHeader = @(
"PWI4 Connect Helper diagnostic log",
("RunId={0}" -f $script:RunId),
("Started={0}" -f $script:RunStartedAt.ToString("yyyy-MM-dd HH:mm:ss.fff zzz")),
("ScriptVersion={0}" -f $ScriptVersion),
""
)
Add-AsciiLogLines -Path $script:DetailLogPath -Lines $detailHeader -Overwrite
$usableTargets += $script:DetailLogPath
}
catch {
Write-Host ("Log file could not be initialized at {0}: {1}" -f $script:DetailLogPath, $_.Exception.Message)
}
if ($usableTargets.Count -eq 0) {
$fallbackDir = Join-Path ([System.IO.Path]::GetTempPath()) "PWI4ConnectLogs"
$fallbackPath = Join-Path $fallbackDir ("pwi4_connect_enable_home_{0}.log" -f $script:RunId)
try {
New-Item -ItemType Directory -Path $fallbackDir -Force | Out-Null
Add-AsciiLogLines -Path $fallbackPath -Lines @(
"PWI4 Connect Helper diagnostic log",
("RunId={0}" -f $script:RunId),
("Started={0}" -f $script:RunStartedAt.ToString("yyyy-MM-dd HH:mm:ss.fff zzz")),
""
) -Overwrite
$usableTargets += $fallbackPath
$script:DetailLogPath = $fallbackPath
}
catch {
Write-Host ("Fallback log file could not be initialized at {0}: {1}" -f $fallbackPath, $_.Exception.Message)
}
}
$script:LogTargets = $usableTargets
}
function Write-Log {
param(
[string]$Message,
[string]$Level = "INFO"
)
$line = "[{0}] [{1}] [PID:{2}] {3}" -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss.fff"), $Level, $PID, $Message
Write-Host $line
foreach ($target in $script:LogTargets) {
for ($attempt = 1; $attempt -le 5; $attempt++) {
try {
Add-AsciiLogLines -Path $target -Lines @($line)
break
}
catch {
if ($attempt -ge 5) {
Write-Host ("Log write failed for {0}: {1}" -f $target, $_.Exception.Message)
}
else {
Start-Sleep -Milliseconds 200
}
}
}
}
}
function Write-DiagnosticHeader {
param([string]$Mode)
Write-Log ("Start PWI4 {0}, Version={1}, BaseUrl={2}, Timeout={3}s, AxisTimeout={4}s, AxisRetries={5}, AxisAttempts={6}" -f $Mode, $ScriptVersion, $BaseUrl, $TimeoutSeconds, $AxisTimeoutSeconds, $AxisRetryCount, ([Math]::Max(1, $AxisRetryCount + 1)))
Write-Log ("RunId={0}" -f $script:RunId)
Write-Log ("LatestLog={0}" -f $script:LatestLogPath)
Write-Log ("DetailLog={0}" -f $script:DetailLogPath)
Write-Log ("DetailedLog={0}; StatusLogIntervalSeconds={1}" -f $DetailedLog, $StatusLogIntervalSeconds)
Write-Log ("ScriptRoot={0}" -f $script:ScriptRoot)
Write-Log ("ScriptPath={0}" -f $PSCommandPath)
Write-Log ("WorkingDirectory={0}" -f (Get-Location).Path)
Write-Log ("CommandLine={0}" -f [Environment]::CommandLine)
Write-Log ("User={0}\{1}; Computer={2}" -f $env:USERDOMAIN, $env:USERNAME, $env:COMPUTERNAME)
Write-Log ("OS={0}; 64BitOS={1}; 64BitProcess={2}" -f [Environment]::OSVersion.VersionString, [Environment]::Is64BitOperatingSystem, [Environment]::Is64BitProcess)
Write-Log ("PowerShellVersion={0}; CLRVersion={1}" -f $PSVersionTable.PSVersion, $PSVersionTable.CLRVersion)
Write-Log ("EffectiveParameters: SkipHome={0}; DryRun={1}; HomeSettleSeconds={2}; AxisEnableSettleSeconds={3}; AxisRetryDelaySeconds={4}; ReconnectSettleSeconds={5}" -f $SkipHome, $DryRun, $HomeSettleSeconds, $AxisEnableSettleSeconds, $AxisRetryDelaySeconds, $ReconnectSettleSeconds)
}
function Write-RawResponseLog {
param(
[string]$Label,
[string]$Content
)
if (-not $DetailedLog) {
return
}
if ($null -eq $Content) {
Write-Log ("RAW {0}: <null>" -f $Label) "DEBUG"
return
}
Write-Log ("RAW {0}: begin" -f $Label) "DEBUG"
$lines = $Content -split "`r?`n"
if ($lines.Count -eq 0) {
Write-Log ("RAW {0}: <empty>" -f $Label) "DEBUG"
}
else {
for ($index = 0; $index -lt $lines.Count; $index++) {
Write-Log ("RAW {0}: {1:D3}: {2}" -f $Label, ($index + 1), $lines[$index]) "DEBUG"
}
}
Write-Log ("RAW {0}: end" -f $Label) "DEBUG"
}
function Write-ExceptionDetail {
param([System.Management.Automation.ErrorRecord]$ErrorRecord)
if ($null -eq $ErrorRecord) {
return
}
Write-Log ("ERROR_DETAIL Category={0}; FullyQualifiedErrorId={1}" -f $ErrorRecord.CategoryInfo, $ErrorRecord.FullyQualifiedErrorId) "ERROR"
if (-not [string]::IsNullOrWhiteSpace($ErrorRecord.ScriptStackTrace)) {
Write-Log ("ERROR_DETAIL ScriptStackTrace={0}" -f ($ErrorRecord.ScriptStackTrace -replace "`r?`n", " | ")) "ERROR"
}
$exception = $ErrorRecord.Exception
$depth = 0
while ($null -ne $exception) {
Write-Log ("ERROR_DETAIL Exception[{0}] Type={1}; Message={2}" -f $depth, $exception.GetType().FullName, $exception.Message) "ERROR"
$exception = $exception.InnerException
$depth++
}
}
function Convert-PwiStatus {
param([string]$Content)
$status = @{}
foreach ($line in ($Content -split "`r?`n")) {
if ($line -match "^([^=]+)=(.*)$") {
$status[$matches[1]] = $matches[2]
}
}
return $status
}
function Get-PwiBool {
param(
[hashtable]$Status,
[string]$Key
)
if (-not $Status.ContainsKey($Key)) {
return $false
}
$value = [string]$Status[$Key]
return (
$value.Equals("true", [System.StringComparison]::OrdinalIgnoreCase) -or
$value.Equals("yes", [System.StringComparison]::OrdinalIgnoreCase) -or
$value.Equals("enabled", [System.StringComparison]::OrdinalIgnoreCase) -or
$value.Equals("1", [System.StringComparison]::OrdinalIgnoreCase)
)
}
function Get-PwiAnyBool {
param(
[hashtable]$Status,
[string[]]$Keys
)
foreach ($key in $Keys) {
if (Get-PwiBool -Status $Status -Key $key) {
return $true
}
}
return $false
}
function Test-PwiHasAnyKey {
param(
[hashtable]$Status,
[string[]]$Keys
)
foreach ($key in $Keys) {
if ($Status.ContainsKey($key)) {
return $true
}
}
return $false
}
function Format-PwiStatusValues {
param(
[hashtable]$Status,
[string[]]$Keys
)
if ($null -eq $Status) {
return "<no status>"
}
$parts = @()
foreach ($key in $Keys) {
if ($Status.ContainsKey($key)) {
$parts += ("{0}={1}" -f $key, $Status[$key])
}
else {
$parts += ("{0}=<missing>" -f $key)
}
}
return ($parts -join "; ")
}
function Write-PwiStatusSummary {
param(
[string]$Label,
[hashtable]$Status,
[string[]]$Keys = @()
)
if ($null -eq $Status) {
Write-Log ("STATUS {0}: <no status>" -f $Label) "DEBUG"
return
}
Write-Log ("STATUS {0}: parsed_key_count={1}" -f $Label, $Status.Count) "DEBUG"
if ($Keys.Count -gt 0) {
Write-Log ("STATUS {0}: selected={1}" -f $Label, (Format-PwiStatusValues -Status $Status -Keys $Keys)) "DEBUG"
}
if ($DetailedLog) {
foreach ($key in ($Status.Keys | Sort-Object)) {
Write-Log ("STATUS {0}: {1}={2}" -f $Label, $key, $Status[$key]) "DEBUG"
}
}
}
function Read-ErrorResponseBody {
param($Response)
if ($null -eq $Response) {
return ""
}
try {
$stream = $Response.GetResponseStream()
if ($null -eq $stream) {
return ""
}
$reader = New-Object System.IO.StreamReader($stream)
try {
return $reader.ReadToEnd()
}
finally {
$reader.Dispose()
}
}
catch {
Write-Log ("Could not read error response body: {0}" -f $_.Exception.Message) "WARN"
return ""
}
}
function Invoke-Pwi {
param(
[string]$Path,
[switch]$Quiet,
[switch]$TransientFailure,
[int]$RequestTimeoutSeconds = 10
)
$uri = $BaseUrl.TrimEnd("/") + $Path
if ((-not $Quiet) -or $DetailedLog) {
Write-Log ("PWI4 API request: path={0}; uri={1}" -f $Path, $uri)
}
if ($DryRun) {
Write-Log ("DryRun: skipped PWI4 API request path={0}" -f $Path) "DEBUG"
return @{}
}
$started = Get-Date
$effectiveRequestTimeout = [Math]::Max(1, $RequestTimeoutSeconds)
try {
$response = Invoke-WebRequest -UseBasicParsing -Uri $uri -TimeoutSec $effectiveRequestTimeout
}
catch {
$failureLevel = if ($TransientFailure) { "WARN" } else { "ERROR" }
$elapsedMs = [Math]::Round(((Get-Date) - $started).TotalMilliseconds)
Write-Log ("PWI4 API failed: path={0}; uri={1}; elapsed_ms={2}; message={3}" -f $Path, $uri, $elapsedMs, $_.Exception.Message) $failureLevel
$errorResponse = $_.Exception.Response
if ($null -ne $errorResponse) {
$statusCode = ""
$statusDescription = ""
try {
$statusCode = [int]$errorResponse.StatusCode
$statusDescription = $errorResponse.StatusDescription
}
catch {
$statusCode = "<unknown>"
$statusDescription = "<unknown>"
}
Write-Log ("PWI4 API error response: status={0}; description={1}; content_type={2}" -f $statusCode, $statusDescription, $errorResponse.ContentType) $failureLevel
$body = Read-ErrorResponseBody -Response $errorResponse
if (-not [string]::IsNullOrEmpty($body)) {
Write-RawResponseLog -Label ("ERROR {0}" -f $Path) -Content $body
}
}
throw ("PWI4 API is not reachable or returned an error at {0}: {1}" -f $uri, $_.Exception.Message)
}
$elapsed = (Get-Date) - $started
$content = [string]$response.Content
$byteCount = [System.Text.Encoding]::UTF8.GetByteCount($content)
Write-Log ("PWI4 API result: path={0}; status={1} {2}; elapsed_ms={3}; chars={4}; utf8_bytes={5}" -f $Path, $response.StatusCode, $response.StatusDescription, [Math]::Round($elapsed.TotalMilliseconds), $content.Length, $byteCount) "DEBUG"
Write-RawResponseLog -Label $Path -Content $content
$status = Convert-PwiStatus -Content $content
if ($Path -eq "/status") {
Write-PwiStatusSummary -Label $Path -Status $status -Keys @("mount.is_connected", "mount.is_slewing", "mount.axis0.is_enabled", "mount.axis1.is_enabled", "mount.ra.is_enabled", "mount.dec.is_enabled")
}
elseif ($DetailedLog -and $status.Count -gt 0) {
Write-PwiStatusSummary -Label $Path -Status $status
}
return $status
}
function Get-PwiStatus {
param(
[switch]$Quiet,
[switch]$TransientFailure,
[int]$RequestTimeoutSeconds = 10
)
return (Invoke-Pwi -Path "/status" -Quiet:$Quiet -TransientFailure:$TransientFailure -RequestTimeoutSeconds $RequestTimeoutSeconds)
}
function Wait-PwiApiReady {
param([int]$WaitSeconds = 0)
if ($WaitSeconds -le 0) {
$WaitSeconds = $TimeoutSeconds
}
$statusUri = $BaseUrl.TrimEnd("/") + "/status"
$progressInterval = [Math]::Max(1, $StatusLogIntervalSeconds)
$deadline = (Get-Date).AddSeconds($WaitSeconds)
$nextProgressLog = Get-Date
$lastError = $null
$requestTimeout = [Math]::Min(5, [Math]::Max(1, $WaitSeconds))
Write-Log ("Waiting for PWI4 API readiness at {0}. Timeout up to {1}s." -f $statusUri, $WaitSeconds)
do {
try {
$status = Get-PwiStatus -Quiet -TransientFailure -RequestTimeoutSeconds $requestTimeout
Write-Log ("OK: PWI4 API is reachable at {0}." -f $statusUri)
return $status
}
catch {
$lastError = $_
$now = Get-Date
if ($now -ge $nextProgressLog) {
$remaining = [Math]::Max(0, [Math]::Round(($deadline - $now).TotalSeconds))
Write-Log ("PWI4 API is not reachable yet. Remaining up to {0}s. Last error: {1}" -f $remaining, $_.Exception.Message) "WARN"
$nextProgressLog = $now.AddSeconds($progressInterval)
}
if ((Get-Date) -lt $deadline) {
Start-Sleep -Seconds 1
}
}
} while ((Get-Date) -lt $deadline)
$lastMessage = if ($null -eq $lastError) { "no response received" } else { $lastError.Exception.Message }
throw ("Timeout while waiting for PWI4 API at {0}. Last error: {1}" -f $statusUri, $lastMessage)
}
function Wait-PwiStatus {
param(
[string]$Description,
[scriptblock]$Predicate,
[string[]]$DiagnosticKeys = @(),
[int]$WaitSeconds = 0
)
if ($WaitSeconds -le 0) {
$WaitSeconds = $TimeoutSeconds
}
$progressInterval = [Math]::Max(1, $StatusLogIntervalSeconds)
$deadline = (Get-Date).AddSeconds($WaitSeconds)
$nextProgressLog = Get-Date
$status = $null
$lastError = $null
$requestTimeout = [Math]::Min(5, [Math]::Max(1, $WaitSeconds))
do {
try {
$status = Get-PwiStatus -Quiet -TransientFailure -RequestTimeoutSeconds $requestTimeout
$lastError = $null
}
catch {
$lastError = $_
$now = Get-Date
if ($now -ge $nextProgressLog) {
$remaining = [Math]::Max(0, [Math]::Round(($deadline - $now).TotalSeconds))
Write-Log ("Waiting for {0}. PWI4 status API is temporarily not reachable. Remaining up to {1}s. Last error: {2}" -f $Description, $remaining, $_.Exception.Message) "WARN"
$nextProgressLog = $now.AddSeconds($progressInterval)
}
if ((Get-Date) -lt $deadline) {
Start-Sleep -Seconds 1
}
continue
}
if (& $Predicate $status) {
Write-Log ("OK: {0}" -f $Description)
if ($DiagnosticKeys.Count -gt 0) {
Write-Log ("OK status: {0}" -f (Format-PwiStatusValues -Status $status -Keys $DiagnosticKeys)) "DEBUG"
}
return $status
}
$now = Get-Date
if ($now -ge $nextProgressLog) {
$remaining = [Math]::Max(0, [Math]::Round(($deadline - $now).TotalSeconds))
Write-Log ("Waiting for {0}. Remaining up to {1}s." -f $Description, $remaining)
if ($DiagnosticKeys.Count -gt 0) {
Write-Log ("Current status: {0}" -f (Format-PwiStatusValues -Status $status -Keys $DiagnosticKeys)) "DEBUG"
}
$nextProgressLog = $now.AddSeconds($progressInterval)
}
Start-Sleep -Seconds 1
} while ((Get-Date) -lt $deadline)
if ($DiagnosticKeys.Count -gt 0) {
Write-Log ("Last status: {0}" -f (Format-PwiStatusValues -Status $status -Keys $DiagnosticKeys)) "ERROR"
}
if ($null -ne $lastError) {
Write-Log ("Last PWI4 status API error while waiting for {0}: {1}" -f $Description, $lastError.Exception.Message) "ERROR"
throw ("Timeout while waiting for: {0}. Last PWI4 API error: {1}" -f $Description, $lastError.Exception.Message)
}
throw ("Timeout while waiting for: {0}" -f $Description)
}
function Connect-PwiMount {
param([string]$Description = "mount.is_connected=true")
Invoke-Pwi -Path "/mount/connect" | Out-Null
return (Wait-PwiStatus -Description $Description -DiagnosticKeys @("mount.is_connected") -Predicate {
param($s)
Get-PwiBool -Status $s -Key "mount.is_connected"
})
}
function Reconnect-PwiMount {
param([string]$Reason)
Write-Log ("Recovery: {0}" -f $Reason)
Write-Log "Recovery: disconnecting mount."
Invoke-Pwi -Path "/mount/disconnect" | Out-Null
Write-Log ("Recovery: waiting {0}s after disconnect." -f $ReconnectSettleSeconds)
Start-Sleep -Seconds $ReconnectSettleSeconds
Write-Log "Recovery: reconnecting mount."
$status = Connect-PwiMount -Description "mount.is_connected=true after recovery reconnect"
Write-Log ("Recovery: waiting {0}s before retrying axis enable sequence." -f $AxisRetryDelaySeconds)
Start-Sleep -Seconds $AxisRetryDelaySeconds
return $status
}
function Enable-PwiAxis {
param(
[int]$Axis,
[string]$Name,
[string[]]$Keys
)
Write-Log ("Enable {0} axis {1}." -f $Name, $Axis)
Invoke-Pwi -Path ("/mount/enable?axis={0}" -f $Axis) | Out-Null
Write-Log ("Waiting {0}s after enabling {1} axis {2}." -f $AxisEnableSettleSeconds, $Name, $Axis)
Start-Sleep -Seconds $AxisEnableSettleSeconds
$status = Get-PwiStatus -Quiet
if (-not (Test-PwiHasAnyKey -Status $status -Keys $Keys)) {
Write-Log ("Axis status keys missing after enabling {0}. Expected one of: {1}" -f $Name, ($Keys -join ", ")) "ERROR"
throw ("PWI4 /status does not expose enabled state for {0}. Cannot safely continue. Expected one of: {1}" -f $Name, ($Keys -join ", "))
}
$axisKeys = $Keys
return (Wait-PwiStatus -Description ("{0} axis {1} enabled" -f $Name, $Axis) -DiagnosticKeys $axisKeys -WaitSeconds $AxisTimeoutSeconds -Predicate {
param($s)
Get-PwiAnyBool -Status $s -Keys $axisKeys
}.GetNewClosure())
}
function Enable-PwiAxesWithRecovery {
param(
[string[]]$Axis0Keys,
[string[]]$Axis1Keys
)
$maxAttempts = [Math]::Max(1, $AxisRetryCount + 1)
for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) {
if ($attempt -gt 1) {
Write-Log ("Axis enable retry attempt {0}/{1}." -f $attempt, $maxAttempts)
}
try {
$status = Enable-PwiAxis -Axis 0 -Name "RA/Azimuth" -Keys $Axis0Keys
$status = Enable-PwiAxis -Axis 1 -Name "DEC/Altitude" -Keys $Axis1Keys
return $status
}
catch {
$message = $_.Exception.Message
if ($attempt -ge $maxAttempts) {
throw ("Axes did not become enabled after {0} attempt(s). Last error: {1}" -f $maxAttempts, $message)
}
Write-Log ("Axis enable attempt {0}/{1} failed: {2}" -f $attempt, $maxAttempts, $message)
Reconnect-PwiMount -Reason "axis did not become enabled; repeating complete RA/DEC enable sequence" | Out-Null
}
}
}
function Test-PwiAxesEnabled {
param(
[hashtable]$Status,
[string[]]$Axis0Keys,
[string[]]$Axis1Keys
)
return (
(Get-PwiAnyBool -Status $Status -Keys $Axis0Keys) -and
(Get-PwiAnyBool -Status $Status -Keys $Axis1Keys)
)
}
Initialize-LogFiles
try {
$mode = if ($SkipHome) { "connect/enable" } else { "connect/enable/home" }
Write-DiagnosticHeader -Mode $mode
if ($DryRun) {
Write-Log "DryRun: no PWI4 commands are executed."
Write-Log ("Startup script completed successfully. DetailLog={0}" -f $script:DetailLogPath)
exit 0
}
$axis0Keys = @("mount.axis0.is_enabled", "mount.axis0.enabled", "mount.axis0.is_initialized", "mount.axis0.is_servo_on", "mount.axis0.is_servo_enabled", "mount.ra.is_enabled", "mount.ra.enabled")
$axis1Keys = @("mount.axis1.is_enabled", "mount.axis1.enabled", "mount.axis1.is_initialized", "mount.axis1.is_servo_on", "mount.axis1.is_servo_enabled", "mount.dec.is_enabled", "mount.dec.enabled")
Write-Log ("Axis0Keys={0}" -f ($axis0Keys -join ", ")) "DEBUG"
Write-Log ("Axis1Keys={0}" -f ($axis1Keys -join ", ")) "DEBUG"
$status = Wait-PwiApiReady
if (Get-PwiBool -Status $status -Key "mount.is_connected") {
$hasAxisStatus = (
(Test-PwiHasAnyKey -Status $status -Keys $axis0Keys) -and
(Test-PwiHasAnyKey -Status $status -Keys $axis1Keys)
)
if ($hasAxisStatus -and (Test-PwiAxesEnabled -Status $status -Axis0Keys $axis0Keys -Axis1Keys $axis1Keys)) {
Write-Log "PWI4 mount is already connected and both axes are enabled. No action, no home."
Write-Log ("Startup script completed successfully. DetailLog={0}" -f $script:DetailLogPath)
exit 0
}
if (-not $hasAxisStatus) {
Write-Log "PWI4 mount is already connected, but expected axis status fields are not available. Running axis enable sequence so the diagnostic log can capture the PWI4 response."
}
else {
Write-Log "PWI4 mount is already connected, but axes are not both enabled. Running axis enable recovery sequence."
}
}
else {
Write-Log "PWI4 mount is not connected. Connecting mount."
$status = Connect-PwiMount
}
$status = Enable-PwiAxesWithRecovery -Axis0Keys $axis0Keys -Axis1Keys $axis1Keys
if ($SkipHome) {
Write-Log "SkipHome is set. Homing was not started."
Write-Log ("Startup script completed successfully. DetailLog={0}" -f $script:DetailLogPath)
exit 0
}
Write-Log "Starting mount home."
Invoke-Pwi -Path "/mount/find_home" | Out-Null
Start-Sleep -Seconds $HomeSettleSeconds
$status = Wait-PwiStatus -Description "home finished / mount is not slewing" -DiagnosticKeys @("mount.is_slewing") -Predicate {
param($s)
if (-not $s.ContainsKey("mount.is_slewing")) {
return $true
}
return (-not (Get-PwiBool -Status $s -Key "mount.is_slewing"))
}
Write-Log ("Startup script completed successfully. DetailLog={0}" -f $script:DetailLogPath)
exit 0
}
catch {
Write-Log ("ERROR: {0}" -f $_.Exception.Message) "ERROR"
Write-ExceptionDetail -ErrorRecord $_
Write-Log ("Startup script failed. LatestLog={0}; DetailLog={1}" -f $script:LatestLogPath, $script:DetailLogPath) "ERROR"
exit 1
}