# Typed MinerOps miner-control execution. Loaded by MinerOpsAgentService.ps1. function Get-MinerOpsAgentVersion { $versionPath = Join-Path $PSScriptRoot "VERSION" if (Test-Path $versionPath) { return ([string](Get-Content $versionPath -Raw)).Trim() } return "unknown" } function Get-MinerOpsControlCredentials { $config = Read-AgentConfig $account = ([string]$config.api3_account).Trim() $password = [string]$config.api3_password $port = 4433 if ($config.api3_port) { try { $port = [int]$config.api3_port } catch { $port = 4433 } } return @{ available = (-not [string]::IsNullOrWhiteSpace($account)) -and (-not [string]::IsNullOrWhiteSpace($password)) account = $account password = $password port = $port } } function Invoke-MinerOpsControlApi3Command { param( [Parameter(Mandatory=$true)][string]$IpAddress, [Parameter(Mandatory=$true)][string]$Command, [object]$Param = $null ) $credentials = Get-MinerOpsControlCredentials if (-not $credentials.available) { throw "credentials_missing" } $saltInfo = Get-MinerOpsApi3Salt -IpAddress $IpAddress -Port $credentials.port $timestamp = [int64][DateTimeOffset]::UtcNow.ToUnixTimeSeconds() $token = Get-MinerOpsApi3Token -Command $Command -Password $credentials.password ` -Salt ([string]$saltInfo.salt) -Timestamp $timestamp $payload = @{ cmd = $Command ts = $timestamp token = $token account = $credentials.account } if ($null -ne $Param) { $payload["param"] = $Param } $response = Invoke-MinerOpsApi3Payload -IpAddress $IpAddress ` -Port $credentials.port -Payload $payload if ([int]$response.response.code -ne 0) { throw "command_rejected" } return $response } function New-MinerOpsControlResult { param( [bool]$Accepted, [bool]$VerificationAttempted, [string]$VerificationStatus, [string]$ObservedMode = "", [string]$FailureCode = "", [string]$QueueStatus = "completed" ) return [ordered]@{ schema_version = 1 command_accepted = $Accepted verification_attempted = $VerificationAttempted verification_status = $VerificationStatus observed_service_state = $null observed_performance_mode = if ($ObservedMode) { $ObservedMode } else { $null } failure_code = if ($FailureCode) { $FailureCode } else { $null } _queue_status = $QueueStatus } } function Run-MinerControlCommand { param([Parameter(Mandatory=$true)][object]$Payload) try { if ($Payload -is [string]) { $Payload = $Payload | ConvertFrom-Json } $action = ([string]$Payload.action).Trim().ToLower() $ipAddress = ([string]$Payload.ip_address).Trim() $requested = ([string]$Payload.requested_value).Trim().ToLower() if (-not $requested -and $Payload.performance_mode) { $requested = ([string]$Payload.performance_mode).Trim().ToLower() } if ($action -notin @("suspend", "resume", "performance_mode")) { return New-MinerOpsControlResult -Accepted $false ` -VerificationAttempted $false -VerificationStatus "unavailable" ` -FailureCode "invalid_action" -QueueStatus "failed" } if ([string]::IsNullOrWhiteSpace($ipAddress)) { return New-MinerOpsControlResult -Accepted $false ` -VerificationAttempted $false -VerificationStatus "unavailable" ` -FailureCode "target_missing" -QueueStatus "failed" } $credentials = Get-MinerOpsControlCredentials if (-not $credentials.available) { return New-MinerOpsControlResult -Accepted $false ` -VerificationAttempted $false -VerificationStatus "unavailable" ` -FailureCode "credentials_missing" -QueueStatus "failed" } if ($action -eq "performance_mode") { if ($requested -notin @("low", "normal", "high")) { return New-MinerOpsControlResult -Accepted $false ` -VerificationAttempted $false -VerificationStatus "unavailable" ` -FailureCode "invalid_mode" -QueueStatus "failed" } Invoke-MinerOpsControlApi3Command -IpAddress $ipAddress ` -Command "set.miner.power_mode" -Param $requested | Out-Null $observed = "" $readUnavailable = $false for ($attempt = 1; $attempt -le 3; $attempt++) { try { $read = Invoke-MinerOpsControlApi3Command -IpAddress $ipAddress ` -Command "get.miner.setting" $candidate = ([string]$read.response.msg.'power-mode').Trim().ToLower() if ($candidate -in @("low", "normal", "high")) { $observed = $candidate if ($observed -eq $requested) { return New-MinerOpsControlResult -Accepted $true ` -VerificationAttempted $true -VerificationStatus "confirmed" ` -ObservedMode $observed } } } catch { if ($_.Exception.Message -match "unsupported|unknown_command") { $readUnavailable = $true break } } if ($attempt -lt 3) { Start-Sleep -Milliseconds 750 } } if ($readUnavailable) { return New-MinerOpsControlResult -Accepted $true ` -VerificationAttempted $true -VerificationStatus "unavailable" } if ($observed) { return New-MinerOpsControlResult -Accepted $true ` -VerificationAttempted $true ` -VerificationStatus "verification_failed" -ObservedMode $observed } return New-MinerOpsControlResult -Accepted $true ` -VerificationAttempted $true -VerificationStatus "unconfirmed" } $serviceAction = if ($action -eq "suspend") { "stop" } else { "start" } Invoke-MinerOpsControlApi3Command -IpAddress $ipAddress ` -Command "set.miner.service" -Param $serviceAction | Out-Null return New-MinerOpsControlResult -Accepted $true ` -VerificationAttempted $false -VerificationStatus "unconfirmed" } catch { $failure = if ($_.Exception.Message -eq "credentials_missing") { "credentials_missing" } else { "write_rejected" } return New-MinerOpsControlResult -Accepted $false ` -VerificationAttempted $false -VerificationStatus "unavailable" ` -FailureCode $failure -QueueStatus "failed" } } function Send-AgentCommandResult { param( [string]$CommandId, [string]$Status, [object]$ResultPayload = $null, [string]$ErrorMessage = $null ) if ($ResultPayload -and $ResultPayload._queue_status) { $Status = [string]$ResultPayload._queue_status $ResultPayload.Remove("_queue_status") $ErrorMessage = if ($ResultPayload.failure_code) { [string]$ResultPayload.failure_code } else { $null } } $body = [ordered]@{ command_id = $CommandId status = $Status result_payload = $ResultPayload error_message = $ErrorMessage } return Invoke-AgentApi -Method "POST" -Path "/api/agent/commands/result" -Body $body } function Send-AgentCheckin { $config = Read-AgentConfig $credentials = Get-MinerOpsControlCredentials $body = [ordered]@{ agent_id = [string]$config.agent_id site_id = [string]$config.site_id site_name = [string]$config.site_name hostname = $env:COMPUTERNAME version = Get-MinerOpsAgentVersion ip_address = "" control_available = [bool]$credentials.available control_unavailable_reason = if ($credentials.available) { $null } else { "credentials_missing" } local_time = (Get-Date).ToString("o") } return Invoke-AgentApi -Method "POST" -Path "/api/agent/checkin" -Body $body }