Add comprehensive documentation and update deployment paths
Documentation: - Add ShopDB-API.md with full API reference (all GET/POST endpoints) - Add detailed docs for Update-ShopfloorPCs-Remote, Invoke-RemoteMaintenance, Update-PC-CompleteAsset - Add DATA_COLLECTION_PARITY.md comparing local vs remote data collection - Add HTML versions of all documentation with styled code blocks - Document software deployment mechanism and how to add new apps - Document deprecated scripts (Invoke-RemoteAssetCollection, Install-KioskApp) Script Updates: - Update deployment source paths to network share (tsgwp00525.wjs.geaerospace.net) - InstallDashboard: \\...\scripts\Dashboard\GEAerospaceDashboardSetup.exe - InstallLobbyDisplay: \\...\scripts\LobbyDisplay\GEAerospaceLobbyDisplaySetup.exe - UpdateEMxAuthToken: \\...\scripts\eMx\eMxInfo.txt - DeployUDCWebServerConfig: \\...\scripts\UDC\udc_webserver_settings.json - Update machine network detection to include 100.0.0.* for CMM cases - Rename PC Type #9 from "Part Marker" to "Inspection" Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
.PARAMETER PcType
|
||||
Target PCs by type (e.g., Dashboard, Lobby Display, CMM, Shopfloor).
|
||||
Valid values: Standard, Engineer, Shopfloor, CMM, Wax / Trace, Keyence,
|
||||
Genspect, Heat Treat, Part Marker, Dashboard, Lobby Display, Uncategorized
|
||||
Genspect, Heat Treat, Inspection, Dashboard, Lobby Display, Uncategorized
|
||||
|
||||
.PARAMETER BusinessUnit
|
||||
Target PCs by business unit (e.g., Blisk, HPT, Spools).
|
||||
@@ -128,7 +128,7 @@ param(
|
||||
|
||||
[Parameter(ParameterSetName='ByPcType')]
|
||||
[ValidateSet('Standard', 'Engineer', 'Shopfloor', 'CMM', 'Wax / Trace', 'Keyence',
|
||||
'Genspect', 'Heat Treat', 'Part Marker', 'Dashboard', 'Lobby Display', 'Uncategorized')]
|
||||
'Genspect', 'Heat Treat', 'Inspection', 'Dashboard', 'Lobby Display', 'Uncategorized')]
|
||||
[string]$PcType,
|
||||
|
||||
[Parameter(ParameterSetName='ByBusinessUnit')]
|
||||
@@ -222,7 +222,7 @@ function Get-ShopfloorPCsFromApi {
|
||||
$PcTypeLookup = @{
|
||||
'Standard' = 1; 'Engineer' = 2; 'Shopfloor' = 3; 'Uncategorized' = 4;
|
||||
'CMM' = 5; 'Wax / Trace' = 6; 'Keyence' = 7; 'Genspect' = 8;
|
||||
'Heat Treat' = 9; 'Part Marker' = 10; 'Dashboard' = 11; 'Lobby Display' = 12
|
||||
'Heat Treat' = 9; 'Inspection' = 10; 'Dashboard' = 11; 'Lobby Display' = 12
|
||||
}
|
||||
|
||||
$BusinessUnitLookup = @{
|
||||
@@ -778,7 +778,7 @@ $TaskScripts = @{
|
||||
}
|
||||
|
||||
$destFile = "eMxInfo.txt"
|
||||
$tempPath = "C:\Windows\Temp\eMxInfo-2026.txt"
|
||||
$tempPath = "C:\Windows\Temp\eMxInfo.txt"
|
||||
|
||||
# Check both possible DNC installation paths
|
||||
$destDirs = @(
|
||||
@@ -1234,8 +1234,8 @@ $sessionOption = New-PSSessionOption -OpenTimeout 30000 -OperationTimeout 600000
|
||||
|
||||
# Special handling for UpdateEMxAuthToken - requires pushing file first
|
||||
if ($Task -eq 'UpdateEMxAuthToken') {
|
||||
$sourcePath = "\\tsgwp00525.rd.ds.ge.com\shared\cameron\eMxInfo-2026.txt"
|
||||
$remoteTempPath = "C:\Windows\Temp\eMxInfo-2026.txt"
|
||||
$sourcePath = "\\tsgwp00525.wjs.geaerospace.net\dt\shopfloor\scripts\eMx\eMxInfo.txt"
|
||||
$remoteTempPath = "C:\Windows\Temp\eMxInfo.txt"
|
||||
|
||||
Write-Log "UpdateEMxAuthToken: Checking source file..." -Level "INFO"
|
||||
|
||||
@@ -1307,7 +1307,7 @@ if ($Task -eq 'UpdateEMxAuthToken') {
|
||||
|
||||
# Special handling for DeployUDCWebServerConfig - check for UDC installation, then push config file
|
||||
if ($Task -eq 'DeployUDCWebServerConfig') {
|
||||
$sourcePath = Join-Path $PSScriptRoot "udc_webserver_settings.json"
|
||||
$sourcePath = "\\tsgwp00525.wjs.geaerospace.net\dt\shopfloor\scripts\UDC\udc_webserver_settings.json"
|
||||
$remoteTempPath = "C:\Windows\Temp\udc_webserver_settings.json"
|
||||
|
||||
Write-Log "DeployUDCWebServerConfig: Checking source file..." -Level "INFO"
|
||||
@@ -1388,12 +1388,14 @@ if ($Task -eq 'DeployUDCWebServerConfig') {
|
||||
$KioskAppConfig = @{
|
||||
'InstallDashboard' = @{
|
||||
Action = 'Install'
|
||||
InstallerPath = '\\tsgwp00525.wjs.geaerospace.net\dt\shopfloor\scripts\Dashboard\GEAerospaceDashboardSetup.exe'
|
||||
InstallerName = 'GEAerospaceDashboardSetup.exe'
|
||||
AppName = 'GE Aerospace Dashboard'
|
||||
UninstallGuid = '{9D9EEE25-4D24-422D-98AF-2ADEDA4745ED}'
|
||||
}
|
||||
'InstallLobbyDisplay' = @{
|
||||
Action = 'Install'
|
||||
InstallerPath = '\\tsgwp00525.wjs.geaerospace.net\dt\shopfloor\scripts\LobbyDisplay\GEAerospaceLobbyDisplaySetup.exe'
|
||||
InstallerName = 'GEAerospaceLobbyDisplaySetup.exe'
|
||||
AppName = 'GE Aerospace Lobby Display'
|
||||
UninstallGuid = '{42FFB952-0B72-493F-8869-D957344CA305}'
|
||||
@@ -1414,14 +1416,13 @@ $KioskAppConfig = @{
|
||||
|
||||
if ($KioskAppConfig.ContainsKey($Task)) {
|
||||
$appConfig = $KioskAppConfig[$Task]
|
||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
|
||||
if ($appConfig.Action -eq 'Install') {
|
||||
# Find installer
|
||||
$installerPath = Join-Path $scriptDir $appConfig.InstallerName
|
||||
# Find installer from network share
|
||||
$installerPath = $appConfig.InstallerPath
|
||||
if (-not (Test-Path $installerPath)) {
|
||||
Write-Log "Installer not found: $installerPath" -Level "ERROR"
|
||||
Write-Log "Place $($appConfig.InstallerName) in the script directory" -Level "ERROR"
|
||||
Write-Log "Ensure the installer exists on the network share" -Level "ERROR"
|
||||
exit 1
|
||||
}
|
||||
Write-Log "$($appConfig.Action): $($appConfig.AppName)" -Level "INFO"
|
||||
|
||||
@@ -482,11 +482,15 @@ function Get-RemotePCInfo {
|
||||
$os = Get-CimInstance -ClassName Win32_OperatingSystem
|
||||
|
||||
$result.SerialNumber = $bios.SerialNumber
|
||||
$result.ServiceTag = $bios.SerialNumber # Same as serial for Dell
|
||||
$result.Manufacturer = $computerSystem.Manufacturer
|
||||
$result.Model = $computerSystem.Model
|
||||
$result.LoggedInUser = $computerSystem.UserName
|
||||
$result.OSVersion = $os.Caption
|
||||
$result.LastBootUpTime = if ($os.LastBootUpTime) { $os.LastBootUpTime.ToString("yyyy-MM-dd HH:mm:ss") } else { $null }
|
||||
$result.TotalPhysicalMemory = [Math]::Round($computerSystem.TotalPhysicalMemory / 1GB, 2)
|
||||
$result.DomainRole = $computerSystem.DomainRole
|
||||
$result.CurrentTimeZone = (Get-TimeZone).Id
|
||||
|
||||
# Get network interfaces
|
||||
$networkAdapters = Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration |
|
||||
@@ -564,10 +568,10 @@ function Get-RemotePCInfo {
|
||||
"^WJCMM" = "CMM" # Generic CMM
|
||||
"^WJMEAS" = "Measuring" # Generic measuring
|
||||
"^0600$" = "Wax Trace" # Wax trace machines
|
||||
"^0612$" = "Part Marker" # Part markers
|
||||
"^0613$" = "Part Marker" # Part markers
|
||||
"^0615" = "Part Marker" # Part markers
|
||||
"^8003$" = "Part Marker" # Part markers
|
||||
"^0612$" = "Inspection" # Part markers
|
||||
"^0613$" = "Inspection" # Part markers
|
||||
"^0615" = "Inspection" # Part markers
|
||||
"^8003$" = "Inspection" # Part markers
|
||||
"^TEST" = $null # Test machines
|
||||
"^TEMP" = $null # Temporary
|
||||
"^DEFAULT"= $null # Default value
|
||||
@@ -586,6 +590,41 @@ function Get-RemotePCInfo {
|
||||
}
|
||||
$result.MachineNo = $machineNo
|
||||
|
||||
# Get GE Aircraft Engines registry info (DualPath configuration)
|
||||
$geInfo = @{
|
||||
Registry32Bit = $false
|
||||
Registry64Bit = $false
|
||||
DualPathEnabled = $null
|
||||
Path1Name = $null
|
||||
Path2Name = $null
|
||||
}
|
||||
$gePaths = @{
|
||||
'32bit' = 'HKLM:\SOFTWARE\GE Aircraft Engines'
|
||||
'64bit' = 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines'
|
||||
}
|
||||
foreach ($pathType in $gePaths.Keys) {
|
||||
$basePath = $gePaths[$pathType]
|
||||
if (Test-Path $basePath) {
|
||||
if ($pathType -eq '32bit') { $geInfo.Registry32Bit = $true }
|
||||
else { $geInfo.Registry64Bit = $true }
|
||||
|
||||
$efocasPath = "$basePath\DNC\eFocas"
|
||||
if (Test-Path $efocasPath) {
|
||||
$efocasValues = Get-ItemProperty -Path $efocasPath -ErrorAction SilentlyContinue
|
||||
if ($efocasValues.DualPath -and $geInfo.DualPathEnabled -eq $null) {
|
||||
$geInfo.DualPathEnabled = ($efocasValues.DualPath -eq 'YES')
|
||||
}
|
||||
if (-not $geInfo.Path1Name -and $efocasValues.Path1Name) {
|
||||
$geInfo.Path1Name = $efocasValues.Path1Name
|
||||
}
|
||||
if (-not $geInfo.Path2Name -and $efocasValues.Path2Name) {
|
||||
$geInfo.Path2Name = $efocasValues.Path2Name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$result.GERegistryInfo = $geInfo
|
||||
|
||||
# Get serial port configuration
|
||||
$comPorts = @()
|
||||
$serialPorts = Get-CimInstance -ClassName Win32_SerialPort -ErrorAction SilentlyContinue
|
||||
@@ -620,6 +659,26 @@ function Get-RemotePCInfo {
|
||||
}
|
||||
$result.HasVnc = $hasVnc
|
||||
|
||||
# Get default printer FQDN (network printers only)
|
||||
$defaultPrinterFQDN = $null
|
||||
try {
|
||||
$defaultPrinter = Get-WmiObject -Query "SELECT * FROM Win32_Printer WHERE Default=$true" -ErrorAction SilentlyContinue
|
||||
if ($defaultPrinter -and $defaultPrinter.PortName) {
|
||||
$portName = $defaultPrinter.PortName
|
||||
# Skip local/virtual printers
|
||||
$localPorts = @('USB', 'LPT', 'COM', 'PORTPROMPT:', 'FILE:', 'NUL:', 'XPS', 'PDF', 'FOXIT', 'Microsoft')
|
||||
$isLocalPrinter = $false
|
||||
foreach ($localPort in $localPorts) {
|
||||
if ($portName -like "$localPort*") { $isLocalPrinter = $true; break }
|
||||
}
|
||||
if (-not $isLocalPrinter) {
|
||||
# Strip anything after underscore (e.g., 10.80.92.53_2 -> 10.80.92.53)
|
||||
$defaultPrinterFQDN = $portName -replace '_.*$', ''
|
||||
}
|
||||
}
|
||||
} catch { }
|
||||
$result.DefaultPrinterFQDN = $defaultPrinterFQDN
|
||||
|
||||
# ================================================================
|
||||
# Detect installed applications for PC type classification
|
||||
# ================================================================
|
||||
@@ -955,6 +1014,40 @@ function Send-PCDataToApi {
|
||||
$postData.hasVnc = "0"
|
||||
}
|
||||
|
||||
# Add new parity fields
|
||||
if ($PCData.ServiceTag) {
|
||||
$postData.serviceTag = $PCData.ServiceTag
|
||||
}
|
||||
if ($PCData.TotalPhysicalMemory) {
|
||||
$postData.totalPhysicalMemory = $PCData.TotalPhysicalMemory
|
||||
}
|
||||
if ($PCData.DomainRole -ne $null) {
|
||||
$postData.domainRole = $PCData.DomainRole
|
||||
}
|
||||
if ($PCData.CurrentTimeZone) {
|
||||
$postData.currentTimeZone = $PCData.CurrentTimeZone
|
||||
}
|
||||
|
||||
# Add GE Registry info (DualPath configuration)
|
||||
if ($PCData.GERegistryInfo) {
|
||||
$postData.dncGeRegistry32Bit = if ($PCData.GERegistryInfo.Registry32Bit) { "1" } else { "0" }
|
||||
$postData.dncGeRegistry64Bit = if ($PCData.GERegistryInfo.Registry64Bit) { "1" } else { "0" }
|
||||
if ($PCData.GERegistryInfo.DualPathEnabled -ne $null) {
|
||||
$postData.dncDualPathEnabled = if ($PCData.GERegistryInfo.DualPathEnabled) { "1" } else { "0" }
|
||||
}
|
||||
if ($PCData.GERegistryInfo.Path1Name) {
|
||||
$postData.dncPath1Name = $PCData.GERegistryInfo.Path1Name
|
||||
}
|
||||
if ($PCData.GERegistryInfo.Path2Name) {
|
||||
$postData.dncPath2Name = $PCData.GERegistryInfo.Path2Name
|
||||
}
|
||||
}
|
||||
|
||||
# Add default printer FQDN
|
||||
if ($PCData.DefaultPrinterFQDN) {
|
||||
$postData.defaultPrinterFQDN = $PCData.DefaultPrinterFQDN
|
||||
}
|
||||
|
||||
# Add network interfaces as JSON
|
||||
if ($PCData.NetworkInterfaces -and $PCData.NetworkInterfaces.Count -gt 0) {
|
||||
$postData.networkInterfaces = ($PCData.NetworkInterfaces | ConvertTo-Json -Compress)
|
||||
@@ -988,10 +1081,14 @@ function Send-PCDataToApi {
|
||||
# Send to API
|
||||
$response = Invoke-RestMethod @restParams
|
||||
|
||||
# Debug: log full API response for relationship troubleshooting
|
||||
Write-Log " API Response: $($response | ConvertTo-Json -Compress)" -Level "INFO"
|
||||
|
||||
return @{
|
||||
Success = $response.success
|
||||
Message = $response.message
|
||||
MachineId = $response.machineid
|
||||
RelationshipCreated = $response.relationshipCreated
|
||||
}
|
||||
} catch {
|
||||
$errMsg = $_.Exception.Message
|
||||
@@ -1016,6 +1113,7 @@ function Send-PCDataToApi {
|
||||
Success = $response.success
|
||||
Message = $response.message
|
||||
MachineId = $response.machineid
|
||||
RelationshipCreated = $response.relationshipCreated
|
||||
}
|
||||
} catch {
|
||||
# WebClient also failed
|
||||
@@ -1317,6 +1415,12 @@ foreach ($result in $results) {
|
||||
Write-Log " IPs: $ips" -Level "INFO"
|
||||
}
|
||||
|
||||
if ($result.LoggedInUser) {
|
||||
Write-Log " Logged In: $($result.LoggedInUser)" -Level "INFO"
|
||||
} else {
|
||||
Write-Log " Logged In: (none)" -Level "INFO"
|
||||
}
|
||||
|
||||
if ($result.MachineNo) {
|
||||
Write-Log " Machine #: $($result.MachineNo)" -Level "INFO"
|
||||
} elseif ($result.IsGenericMachineNo) {
|
||||
@@ -1358,6 +1462,11 @@ foreach ($result in $results) {
|
||||
|
||||
if ($apiResult.Success) {
|
||||
Write-Log " -> Updated in ShopDB (MachineID: $($apiResult.MachineId))" -Level "SUCCESS"
|
||||
if ($apiResult.RelationshipCreated) {
|
||||
Write-Log " -> Machine Relationship: Created" -Level "SUCCESS"
|
||||
} elseif ($result.MachineNo) {
|
||||
Write-Log " -> Machine Relationship: FAILED (machineNo=$($result.MachineNo))" -Level "ERROR"
|
||||
}
|
||||
|
||||
# Update WinRM status - since we successfully connected via WinRM, mark it as enabled
|
||||
try {
|
||||
@@ -1492,6 +1601,11 @@ if ($connectionFailures.Count -gt 0) {
|
||||
|
||||
if ($apiResult.Success) {
|
||||
Write-Log " -> Updated in ShopDB (MachineID: $($apiResult.MachineId))" -Level "SUCCESS"
|
||||
if ($apiResult.RelationshipCreated) {
|
||||
Write-Log " -> Machine Relationship: Created" -Level "SUCCESS"
|
||||
} elseif ($ipResult.MachineNo) {
|
||||
Write-Log " -> Machine Relationship: FAILED (machineNo=$($ipResult.MachineNo))" -Level "ERROR"
|
||||
}
|
||||
$successCount++
|
||||
$successPCs += @{
|
||||
Hostname = $ipResult.Hostname
|
||||
|
||||
Reference in New Issue
Block a user