<%@ Language=VBScript %> <% ' ============================================================================ ' DATABASE CONNECTION - Created directly in api.asp to avoid scoping issues ' ============================================================================ Dim objConn, rs, DB_CONN_STRING ' Use direct MySQL ODBC driver connection (same as sql.asp) instead of DSN DB_CONN_STRING = "Driver={MySQL ODBC 9.4 Unicode Driver};" & _ "Server=192.168.122.1;" & _ "Port=3306;" & _ "Database=shopdb;" & _ "User=570005354;" & _ "Password=570005354;" & _ "Option=3;" & _ "Pooling=True;Max Pool Size=100;" Session.Timeout = 15 Set objConn = Server.CreateObject("ADODB.Connection") objConn.ConnectionString = DB_CONN_STRING objConn.Open Set rs = Server.CreateObject("ADODB.Recordset") Response.Buffer = True Response.ContentType = "application/json" ' ============================================================================ ' ShopDB API - PowerShell Data Collection Endpoint ' ============================================================================ ' Purpose: Receive PC asset data from PowerShell scripts and store in Phase 2 schema ' Created: 2025-11-13 ' Modified: 2025-11-21 - Use sql.asp include for database connection ' Schema: Phase 2 (machines table, pctypeid IS NOT NULL for PCs) ' ============================================================================ ' Error handling wrapper On Error Resume Next ' Get action from POST or GET Dim action action = Request.Form("action") If action = "" Then action = Request.QueryString("action") ' Route to appropriate handler Select Case action Case "updateCompleteAsset" UpdateCompleteAsset() Case "updatePrinterMapping" UpdatePrinterMapping() Case "updateInstalledApps" UpdateInstalledApps() Case "updateWinRMStatus" UpdateWinRMStatus() Case "getDashboardData" GetDashboardData() Case "getShopfloorPCs" GetShopfloorPCs() Case "getRecordedIP" GetRecordedIP() Case "updateMachinePositions" UpdateMachinePositions() Case Else SendError "Invalid action: " & action End Select ' Clean up If Not objConn Is Nothing Then If objConn.State = 1 Then objConn.Close Set objConn = Nothing End If ' ============================================================================ ' MAIN HANDLERS ' ============================================================================ Sub UpdateCompleteAsset() On Error Resume Next ' Log request LogToFile "=== NEW updateCompleteAsset REQUEST ===" LogToFile "Hostname: " & Request.Form("hostname") LogToFile "Serial: " & Request.Form("serialNumber") LogToFile "PC Type: " & Request.Form("pcType") ' Get all POST parameters Dim hostname, serialnumber, manufacturer, model, pcType Dim loggedinuser, machinenumber, osVersion, osid, pcstatusid Dim warrantyEndDate, warrantyStatus, warrantyServiceLevel, warrantyDaysRemaining Dim networkInterfaces, commConfigs, dncConfig Dim dncDualPathEnabled, dncPath1Name, dncPath2Name Dim dncGeRegistry32Bit, dncGeRegistry64Bit, dncGeRegistryNotes ' Basic PC info hostname = Trim(Request.Form("hostname") & "") serialnumber = Trim(Request.Form("serialNumber") & "") manufacturer = Trim(Request.Form("manufacturer") & "") model = Trim(Request.Form("model") & "") pcType = Trim(Request.Form("pcType") & "") loggedinuser = Trim(Request.Form("loggedInUser") & "") machinenumber = Trim(Request.Form("machineNo") & "") osVersion = Trim(Request.Form("osVersion") & "") ' Warranty data (optional) warrantyEndDate = Request.Form("warrantyEndDate") warrantyStatus = Trim(Request.Form("warrantyStatus") & "") warrantyServiceLevel = Trim(Request.Form("warrantyServiceLevel") & "") warrantyDaysRemaining = Request.Form("warrantyDaysRemaining") ' Shopfloor data (optional) networkInterfaces = Request.Form("networkInterfaces") commConfigs = Request.Form("commConfigs") dncConfig = Request.Form("dncConfig") ' VNC detection (optional) Dim hasVnc hasVnc = Trim(Request.Form("hasVnc") & "") ' WinRM detection (optional) Dim hasWinRM hasWinRM = Trim(Request.Form("hasWinRM") & "") ' Last boot time (optional) - accepts both lastBootUpTime and lastBootTime Dim lastBootTime lastBootTime = Trim(Request.Form("lastBootUpTime") & "") If lastBootTime = "" Then lastBootTime = Trim(Request.Form("lastBootTime") & "") End If ' Installed apps (optional) - JSON array of tracked apps Dim installedApps installedApps = Request.Form("installedApps") ' DNC/GE registry data dncDualPathEnabled = Request.Form("dncDualPathEnabled") dncPath1Name = Trim(Request.Form("dncPath1Name") & "") dncPath2Name = Trim(Request.Form("dncPath2Name") & "") dncGeRegistry32Bit = Request.Form("dncGeRegistry32Bit") dncGeRegistry64Bit = Request.Form("dncGeRegistry64Bit") dncGeRegistryNotes = Trim(Request.Form("dncGeRegistryNotes") & "") ' Validate required fields If hostname = "" Or serialnumber = "" Then SendError "hostname and serialNumber are required" Exit Sub End If ' Get OS ID (inlined to avoid VBScript scoping issues) osid = 0 If osVersion <> "" Then Dim safeOsVersion, rsOS safeOsVersion = Replace(osVersion, "'", "''") Set rsOS = objConn.Execute("SELECT osid FROM operatingsystems WHERE operatingsystem = '" & safeOsVersion & "'") If Not rsOS.EOF Then osid = CLng(rsOS("osid")) Else objConn.Execute "INSERT INTO operatingsystems (operatingsystem) VALUES ('" & safeOsVersion & "')" Set rsOS = objConn.Execute("SELECT LAST_INSERT_ID() AS newid") osid = CLng(rsOS("newid")) End If rsOS.Close Set rsOS = Nothing End If pcstatusid = 3 ' Default to "In Use" ' Clear existing shopfloor data if this is a shopfloor PC Dim machineid If pcType = "Shopfloor" Then ClearShopfloorData hostname If Err.Number <> 0 Then Err.Clear End If End If ' Clear any previous errors before InsertOrUpdatePC Err.Clear ' Inline PC insert/update logic (avoids function scoping issues on production IIS) Dim debugMsg debugMsg = "" ' Check objConn If objConn Is Nothing Then SendError debugMsg & "1-objConn is Nothing" Exit Sub End If debugMsg = debugMsg & "1-OK," If objConn.State <> 1 Then SendError debugMsg & "2-objConn not open state=" & objConn.State Exit Sub End If debugMsg = debugMsg & "2-OK," ' Get vendor ID inline Dim vendorId, modelId, machineTypeId Dim safeManufacturer, safeModel, rsVendor, rsModel vendorId = 0 modelId = 1 If manufacturer <> "" Then safeManufacturer = Replace(manufacturer, "'", "''") Set rsVendor = objConn.Execute("SELECT vendorid FROM vendors WHERE vendor = '" & safeManufacturer & "'") If Err.Number <> 0 Then SendError debugMsg & "3-vendor query failed: " & Err.Description Exit Sub End If debugMsg = debugMsg & "3-OK," If Not rsVendor.EOF Then vendorId = CLng(rsVendor("vendorid")) debugMsg = debugMsg & "3a-found " & vendorId & "," Else objConn.Execute "INSERT INTO vendors (vendor) VALUES ('" & safeManufacturer & "')" If Err.Number <> 0 Then SendError debugMsg & "3b-vendor insert failed: " & Err.Description Exit Sub End If Set rsVendor = objConn.Execute("SELECT LAST_INSERT_ID() AS newid") vendorId = CLng(rsVendor("newid")) debugMsg = debugMsg & "3b-created " & vendorId & "," End If rsVendor.Close Set rsVendor = Nothing End If debugMsg = debugMsg & "4-vendorId=" & vendorId & "," ' Get model ID inline If model <> "" And vendorId > 0 Then safeModel = Replace(model, "'", "''") Set rsModel = objConn.Execute("SELECT modelnumberid FROM models WHERE modelnumber = '" & safeModel & "' AND vendorid = " & vendorId) If Err.Number <> 0 Then SendError debugMsg & "5-model query failed: " & Err.Description Exit Sub End If debugMsg = debugMsg & "5-OK," If Not rsModel.EOF Then modelId = CLng(rsModel("modelnumberid")) Else objConn.Execute "INSERT INTO models (modelnumber, vendorid, notes, isactive) VALUES ('" & safeModel & "', " & vendorId & ", 'Auto-imported', 1)" If Err.Number <> 0 Then SendError debugMsg & "5b-model insert failed: " & Err.Description Exit Sub End If Set rsModel = objConn.Execute("SELECT LAST_INSERT_ID() AS newid") modelId = CLng(rsModel("newid")) End If rsModel.Close Set rsModel = Nothing End If debugMsg = debugMsg & "6-modelId=" & modelId & "," ' Get machine type ID (all PCs use 33) machineTypeId = 33 debugMsg = debugMsg & "7-machineTypeId=" & machineTypeId & "," ' Get PC type ID from pcType string (inlined to avoid function call issues) Dim pctypeId, pcTypeClean pcTypeClean = Trim(UCase(pcType)) Select Case pcTypeClean Case "ENGINEER", "ENGINEERING" pctypeId = 2 Case "SHOPFLOOR", "SHOP FLOOR" pctypeId = 3 Case "CMM" pctypeId = 5 Case "WAX TRACE", "WAXTRACE", "WAX", "WAX / TRACE" pctypeId = 6 Case "KEYENCE" pctypeId = 7 Case "GENSPECT", "EAS1000" pctypeId = 8 Case "HEAT TREAT", "HEATTTREAT", "HEATTEAT", "HEAT_TREAT", "HEATTREAT" pctypeId = 9 Case "PART MARKER", "PARTMARKER" pctypeId = 10 Case "MEASURING", "MEASURING TOOL" pctypeId = 7 Case Else pctypeId = 1 End Select debugMsg = debugMsg & "7b-pctypeId=" & pctypeId & "," ' Check if PC exists Dim strSQL, rsResult, safeHostname, safeSerial safeHostname = Replace(hostname, "'", "''") strSQL = "SELECT machineid FROM machines WHERE hostname = '" & safeHostname & "' AND pctypeid IS NOT NULL" Set rsResult = objConn.Execute(strSQL) If Err.Number <> 0 Then SendError debugMsg & "8-PC check failed: " & Err.Description Exit Sub End If debugMsg = debugMsg & "8-OK," If Not rsResult.EOF Then ' PC exists - UPDATE machineid = rsResult("machineid") rsResult.Close Set rsResult = Nothing debugMsg = debugMsg & "9-UPDATE id=" & machineid & "," safeSerial = Replace(serialnumber, "'", "''") ' Determine VNC value (1 or 0) Dim vncValue If hasVnc = "1" Then vncValue = 1 Else vncValue = 0 End If ' Determine WinRM value (1 or 0) Dim winrmValue If hasWinRM = "1" Then winrmValue = 1 Else winrmValue = 0 End If ' Build UPDATE with optional lastboottime Dim lastBootPart If lastBootTime <> "" Then lastBootPart = ", lastboottime='" & Replace(lastBootTime, "'", "''") & "'" Else lastBootPart = "" End If strSQL = "UPDATE machines SET serialnumber='" & safeSerial & "', modelnumberid=" & modelId & ", machinetypeid=" & machineTypeId & ", pctypeid=" & pctypeId & ", osid=" & osid & ", isvnc=" & vncValue & ", iswinrm=" & winrmValue & lastBootPart & ", lastupdated=NOW() WHERE machineid=" & machineid objConn.Execute strSQL If Err.Number <> 0 Then SendError debugMsg & "10-UPDATE failed: " & Err.Description Exit Sub End If debugMsg = debugMsg & "10-OK," Else ' PC doesn't exist - INSERT rsResult.Close Set rsResult = Nothing debugMsg = debugMsg & "9-INSERT," safeSerial = Replace(serialnumber, "'", "''") ' Determine VNC value for insert (reuse logic from update branch) Dim vncValueInsert If hasVnc = "1" Then vncValueInsert = 1 Else vncValueInsert = 0 End If ' Determine WinRM value for insert Dim winrmValueInsert If hasWinRM = "1" Then winrmValueInsert = 1 Else winrmValueInsert = 0 End If ' Build INSERT with optional lastboottime Dim lastBootColInsert, lastBootValInsert If lastBootTime <> "" Then lastBootColInsert = ", lastboottime" lastBootValInsert = ", '" & Replace(lastBootTime, "'", "''") & "'" Else lastBootColInsert = "" lastBootValInsert = "" End If strSQL = "INSERT INTO machines (hostname, serialnumber, modelnumberid, machinetypeid, pctypeid, osid, machinestatusid, isvnc, iswinrm, lastupdated" & lastBootColInsert & ") VALUES ('" & safeHostname & "', '" & safeSerial & "', " & modelId & ", " & machineTypeId & ", " & pctypeId & ", " & osid & ", " & pcstatusid & ", " & vncValueInsert & ", " & winrmValueInsert & ", NOW()" & lastBootValInsert & ")" objConn.Execute strSQL If Err.Number <> 0 Then SendError debugMsg & "10-INSERT failed: " & Err.Description Exit Sub End If Set rsResult = objConn.Execute("SELECT LAST_INSERT_ID() AS newid") machineid = CLng(rsResult("newid")) rsResult.Close Set rsResult = Nothing debugMsg = debugMsg & "10-OK id=" & machineid & "," End If If Err.Number <> 0 Then SendError "Failed to insert/update PC: " & Err.Description Exit Sub End If If machineid = 0 Then SendError "Failed to get machineid after insert/update" Exit Sub End If LogToFile "PC record created/updated. machineid: " & machineid ' Clear existing network interfaces before inserting new ones (prevents duplicates on re-scan) If networkInterfaces <> "" Then Dim cmdClearInterfaces Set cmdClearInterfaces = Server.CreateObject("ADODB.Command") cmdClearInterfaces.ActiveConnection = objConn cmdClearInterfaces.CommandText = "DELETE FROM communications WHERE machineid = ? AND comstypeid = 1" cmdClearInterfaces.Parameters.Append cmdClearInterfaces.CreateParameter("@machineid", 3, 1, , CLng(machineid)) cmdClearInterfaces.Execute LogToFile "Cleared " & cmdClearInterfaces.RecordsAffected & " existing network interfaces" Set cmdClearInterfaces = Nothing End If ' Insert network interfaces Dim interfaceCount interfaceCount = 0 If networkInterfaces <> "" Then interfaceCount = InsertNetworkInterfaces(machineid, networkInterfaces) LogToFile "Network interfaces inserted: " & interfaceCount End If ' Insert communication configs (serial ports) Dim commConfigCount commConfigCount = 0 If commConfigs <> "" Then commConfigCount = InsertCommConfigs(machineid, commConfigs) LogToFile "Comm configs inserted: " & commConfigCount End If ' Insert DNC config Dim dncSuccess dncSuccess = False If dncConfig <> "" Then dncSuccess = InsertDNCConfig(machineid, dncConfig, dncDualPathEnabled, dncPath1Name, dncPath2Name, _ dncGeRegistry32Bit, dncGeRegistry64Bit, dncGeRegistryNotes) LogToFile "DNC config inserted: " & dncSuccess End If ' Create PC-to-machine relationship if machine number provided Dim relationshipCreated relationshipCreated = False If machinenumber <> "" Then relationshipCreated = CreatePCMachineRelationship(machineid, machinenumber) LogToFile "PC-Machine relationship created: " & relationshipCreated End If ' Update warranty data in separate table If warrantyEndDate <> "" Then UpdateWarrantyData machineid, warrantyEndDate, warrantyStatus, warrantyServiceLevel, warrantyDaysRemaining End If ' Update installed apps if provided Dim installedAppsCount installedAppsCount = 0 If installedApps <> "" Then installedAppsCount = SaveInstalledApps(machineid, installedApps) LogToFile "Installed apps saved: " & installedAppsCount End If ' Send success response (flattened to avoid nested dictionary issues) Dim responseObj Set responseObj = Server.CreateObject("Scripting.Dictionary") responseObj.Add "success", True responseObj.Add "message", "PC asset data updated successfully" responseObj.Add "machineid", machineid responseObj.Add "hostname", hostname responseObj.Add "operation", "complete" responseObj.Add "networkInterfacesCount", interfaceCount responseObj.Add "commConfigsCount", commConfigCount responseObj.Add "dncConfigSuccess", dncSuccess responseObj.Add "relationshipCreated", relationshipCreated responseObj.Add "installedAppsCount", installedAppsCount SendResponse responseObj End Sub Sub UpdatePrinterMapping() On Error Resume Next Dim hostname, printerFQDN hostname = Trim(Request.Form("hostname") & "") printerFQDN = Trim(Request.Form("printerFQDN") & "") If hostname = "" Or printerFQDN = "" Then SendError "hostname and printerFQDN are required" Exit Sub End If LogToFile "UpdatePrinterMapping: hostname=" & hostname & ", printerFQDN=" & printerFQDN ' Get machineid for this hostname Dim machineid machineid = GetMachineidByHostname(hostname) If machineid = 0 Then SendError "PC not found: " & hostname Exit Sub End If ' Find printer by FQDN (try name match, IP match, or alias match) Dim printerid, matchMethod printerid = 0 matchMethod = "" Dim safePrinterFQDN safePrinterFQDN = Replace(printerFQDN, "'", "''") ' Try exact FQDN match first Dim strSQL, rsResult strSQL = "SELECT printerid FROM printers WHERE fqdn = '" & safePrinterFQDN & "'" Set rsResult = objConn.Execute(strSQL) If Not rsResult.EOF Then printerid = rsResult("printerid") matchMethod = "fqdn" End If rsResult.Close Set rsResult = Nothing ' Try printer windows name match If printerid = 0 Then strSQL = "SELECT printerid FROM printers WHERE printerwindowsname = '" & safePrinterFQDN & "'" Set rsResult = objConn.Execute(strSQL) If Not rsResult.EOF Then printerid = rsResult("printerid") matchMethod = "windowsname" End If rsResult.Close Set rsResult = Nothing End If ' Try IP address match If printerid = 0 And IsIPAddress(printerFQDN) Then strSQL = "SELECT printerid FROM printers WHERE ipaddress = '" & safePrinterFQDN & "'" Set rsResult = objConn.Execute(strSQL) If Not rsResult.EOF Then printerid = rsResult("printerid") matchMethod = "ip" End If rsResult.Close Set rsResult = Nothing End If If printerid = 0 Then SendError "Printer not found: " & printerFQDN Exit Sub End If ' Update machine record to link to this printer Dim cmdUpdate Set cmdUpdate = Server.CreateObject("ADODB.Command") cmdUpdate.ActiveConnection = objConn cmdUpdate.CommandText = "UPDATE machines SET printerid = ? WHERE machineid = ?" cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@printerid", 3, 1, , CLng(printerid)) cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@machineid", 3, 1, , CLng(machineid)) cmdUpdate.Execute If Err.Number <> 0 Then SendError "Failed to update printer mapping: " & Err.Description Exit Sub End If ' Send success response (flattened to avoid nested dictionary issues) Dim responseObj Set responseObj = Server.CreateObject("Scripting.Dictionary") responseObj.Add "success", True responseObj.Add "message", "Printer mapping updated" responseObj.Add "printerId", printerid responseObj.Add "machinesUpdated", 1 responseObj.Add "matchMethod", matchMethod SendResponse responseObj End Sub Sub UpdateInstalledApps() On Error Resume Next Dim hostname, installedApps hostname = Trim(Request.Form("hostname") & "") installedApps = Request.Form("installedApps") If hostname = "" Or installedApps = "" Then SendError "hostname and installedApps are required" Exit Sub End If LogToFile "UpdateInstalledApps: hostname=" & hostname ' Get machineid for this hostname Dim machineid machineid = GetMachineidByHostname(hostname) If machineid = 0 Then SendError "PC not found: " & hostname Exit Sub End If ' Parse JSON array of apps (simple parsing) LogToFile "Raw installedApps: " & installedApps Dim appsArray appsArray = ParseJSONArray(installedApps) LogToFile "Parsed apps array, count: " & (UBound(appsArray) + 1) ' Debug: show first parsed item If UBound(appsArray) >= 0 Then LogToFile "First item after parse: " & appsArray(0) End If ' Clear existing app mappings for this PC using direct SQL Dim deleteSQL deleteSQL = "DELETE FROM installedapps WHERE machineid = " & CLng(machineid) LogToFile "DELETE SQL: " & deleteSQL objConn.Execute deleteSQL If Err.Number <> 0 Then LogToFile "ERROR on DELETE: " & Err.Number & " - " & Err.Description Err.Clear Else LogToFile "DELETE completed successfully" End If ' Insert new app mappings Dim appCount, i, appName, appVersion, appid, appversionid, cmdInsert, appidStr, insertSQL Dim debugLoopError, safeVer, verSQL, rsVer, isActiveStr, isActive debugLoopError = "" appCount = 0 Err.Clear For i = 0 To UBound(appsArray) ' Get appid directly (pre-mapped from CSV) appid = 0 appidStr = Trim(GetJSONValue(appsArray(i), "appid") & "") If appidStr <> "" And IsNumeric(appidStr) Then appid = CLng(appidStr) ' Get version and app name for logging appVersion = Trim(GetJSONValue(appsArray(i), "version") & "") appName = Trim(GetJSONValue(appsArray(i), "appname") & "") ' Get isactive status (for UDC/CLM process detection) isActive = 1 ' Default to active isActiveStr = Trim(GetJSONValue(appsArray(i), "isactive") & "") If isActiveStr <> "" And IsNumeric(isActiveStr) Then isActive = CLng(isActiveStr) LogToFile "App " & i & ": appid=" & appid & ", appname='" & appName & "', version='" & appVersion & "', isactive=" & isActive If appid > 0 Then appversionid = 0 Err.Clear ' Version lookup and creation using global rs recordset If appVersion <> "" And Not IsNull(appVersion) Then safeVer = Replace(appVersion, "'", "''") verSQL = "SELECT appversionid FROM appversions WHERE appid = " & CLng(appid) & " AND version = '" & safeVer & "'" rs.Open verSQL, objConn, 0, 1 If Err.Number <> 0 Then debugLoopError = debugLoopError & " | rs.Open err:" & Err.Number Err.Clear ElseIf Not rs.EOF Then appversionid = CLng(rs("appversionid")) Else ' Version not found - create it If rs.State = 1 Then rs.Close verSQL = "INSERT INTO appversions (appid, version) VALUES (" & CLng(appid) & ", '" & safeVer & "')" objConn.Execute verSQL If Err.Number = 0 Then ' Get the new ID rs.Open "SELECT LAST_INSERT_ID() AS newid", objConn, 0, 1 If Err.Number = 0 And Not rs.EOF Then appversionid = CLng(rs("newid")) End If If Err.Number <> 0 Then Err.Clear Else Err.Clear End If End If If rs.State = 1 Then rs.Close End If ' Insert app with isactive status If appversionid > 0 Then insertSQL = "INSERT INTO installedapps (machineid, appid, appversionid, isactive) VALUES (" & CLng(machineid) & ", " & CLng(appid) & ", " & CLng(appversionid) & ", " & isActive & ")" Else insertSQL = "INSERT INTO installedapps (machineid, appid, isactive) VALUES (" & CLng(machineid) & ", " & CLng(appid) & ", " & isActive & ")" End If objConn.Execute insertSQL If Err.Number = 0 Then appCount = appCount + 1 Else debugLoopError = debugLoopError & " | INSERT error: " & Err.Number & " - " & Err.Description Err.Clear End If End If Next LogToFile "Installed apps inserted: " & appCount ' Send success response with debug info Dim responseObj Set responseObj = Server.CreateObject("Scripting.Dictionary") responseObj.Add "success", True responseObj.Add "message", "Installed applications updated" responseObj.Add "appsProcessed", appCount responseObj.Add "machineid", machineid responseObj.Add "debugError", debugLoopError SendResponse responseObj End Sub ' ============================================================================ ' SaveInstalledApps - Save installed apps for a PC (callable from UpdateCompleteAsset) ' Returns: count of apps saved ' ============================================================================ Function SaveInstalledApps(machineid, installedAppsJson) On Error Resume Next SaveInstalledApps = 0 If machineid = 0 Or installedAppsJson = "" Then Exit Function End If LogToFile "SaveInstalledApps: machineid=" & machineid & ", raw JSON length=" & Len(installedAppsJson) ' Parse JSON array of apps Dim appsArray appsArray = ParseJSONArray(installedAppsJson) If Not IsArray(appsArray) Then LogToFile "SaveInstalledApps: Failed to parse JSON array" Exit Function End If LogToFile "SaveInstalledApps: Parsed " & (UBound(appsArray) + 1) & " apps" ' Clear existing app mappings for this PC Dim deleteSQL deleteSQL = "DELETE FROM installedapps WHERE machineid = " & CLng(machineid) objConn.Execute deleteSQL If Err.Number <> 0 Then LogToFile "SaveInstalledApps: DELETE error: " & Err.Description Err.Clear End If ' Insert new app mappings Dim appCount, i, appName, appVersion, appid, appversionid, appidStr, insertSQL Dim safeVer, verSQL, rsVer, isActiveStr, isActive appCount = 0 Err.Clear For i = 0 To UBound(appsArray) ' Get appid directly (pre-mapped from PowerShell) appid = 0 appidStr = Trim(GetJSONValue(appsArray(i), "appid") & "") If appidStr <> "" And IsNumeric(appidStr) Then appid = CLng(appidStr) ' Get version and app name for logging appVersion = Trim(GetJSONValue(appsArray(i), "version") & "") appName = Trim(GetJSONValue(appsArray(i), "appname") & "") ' Get isactive status (for UDC/CLM process detection) isActive = 1 ' Default to active isActiveStr = Trim(GetJSONValue(appsArray(i), "isactive") & "") If isActiveStr <> "" And IsNumeric(isActiveStr) Then isActive = CLng(isActiveStr) If appid > 0 Then appversionid = 0 Err.Clear ' Version lookup and creation If appVersion <> "" And Not IsNull(appVersion) Then safeVer = Replace(appVersion, "'", "''") verSQL = "SELECT appversionid FROM appversions WHERE appid = " & CLng(appid) & " AND version = '" & safeVer & "'" rs.Open verSQL, objConn, 0, 1 If Err.Number <> 0 Then Err.Clear ElseIf Not rs.EOF Then appversionid = CLng(rs("appversionid")) Else ' Version not found - create it If rs.State = 1 Then rs.Close verSQL = "INSERT INTO appversions (appid, version) VALUES (" & CLng(appid) & ", '" & safeVer & "')" objConn.Execute verSQL If Err.Number = 0 Then rs.Open "SELECT LAST_INSERT_ID() AS newid", objConn, 0, 1 If Err.Number = 0 And Not rs.EOF Then appversionid = CLng(rs("newid")) End If If Err.Number <> 0 Then Err.Clear Else Err.Clear End If End If If rs.State = 1 Then rs.Close End If ' Insert app with isactive status If appversionid > 0 Then insertSQL = "INSERT INTO installedapps (machineid, appid, appversionid, isactive) VALUES (" & CLng(machineid) & ", " & CLng(appid) & ", " & CLng(appversionid) & ", " & isActive & ")" Else insertSQL = "INSERT INTO installedapps (machineid, appid, isactive) VALUES (" & CLng(machineid) & ", " & CLng(appid) & ", " & isActive & ")" End If objConn.Execute insertSQL If Err.Number = 0 Then appCount = appCount + 1 Else LogToFile "SaveInstalledApps: INSERT error for appid " & appid & ": " & Err.Description Err.Clear End If End If Next LogToFile "SaveInstalledApps: Saved " & appCount & " apps" SaveInstalledApps = appCount End Function Sub GetDashboardData() ' Simple health check endpoint Dim responseObj, connStatus Set responseObj = Server.CreateObject("Scripting.Dictionary") responseObj.Add "success", True responseObj.Add "message", "ShopDB API is online - v13 (inlined all queries)" responseObj.Add "version", "1.0" responseObj.Add "schema", "Phase 2" ' Debug: check objConn status If objConn Is Nothing Then connStatus = "objConn is Nothing" ElseIf objConn.State = 1 Then connStatus = "objConn is Open" Else connStatus = "objConn state=" & objConn.State End If responseObj.Add "connStatus", connStatus SendResponse responseObj End Sub Sub GetShopfloorPCs() ' Returns list of all active shopfloor PCs for remote management On Error Resume Next Dim rsPC, strSQL, pcList, pcCount, pcData ' Query active shopfloor PCs only (pctype = 'Shopfloor') ' Include hostname, machineid, machinenumber (equipment), IP address, last updated strSQL = "SELECT m.machineid, m.hostname, m.machinenumber, m.serialnumber, " & _ "m.loggedinuser, m.lastupdated, " & _ "c.address AS ipaddress, " & _ "pt.typename AS pctype " & _ "FROM machines m " & _ "LEFT JOIN communications c ON m.machineid = c.machineid AND c.isprimary = 1 AND c.comstypeid = 1 " & _ "INNER JOIN pctype pt ON m.pctypeid = pt.pctypeid " & _ "WHERE m.isactive = 1 " & _ "AND pt.typename = 'Shopfloor' " & _ "ORDER BY m.hostname ASC" Set rsPC = objConn.Execute(strSQL) If Err.Number <> 0 Then SendError "Database error: " & Err.Description Exit Sub End If ' Build JSON array of PCs pcList = "" pcCount = 0 Do While Not rsPC.EOF If pcList <> "" Then pcList = pcList & "," ' Build individual PC object pcData = "{" pcData = pcData & """machineid"":" & rsPC("machineid") & "," pcData = pcData & """hostname"":""" & EscapeJSON(rsPC("hostname") & "") & """," pcData = pcData & """machinenumber"":""" & EscapeJSON(rsPC("machinenumber") & "") & """," pcData = pcData & """serialnumber"":""" & EscapeJSON(rsPC("serialnumber") & "") & """," pcData = pcData & """ipaddress"":""" & EscapeJSON(rsPC("ipaddress") & "") & """," pcData = pcData & """loggedinuser"":""" & EscapeJSON(rsPC("loggedinuser") & "") & """," pcData = pcData & """pctype"":""" & EscapeJSON(rsPC("pctype") & "") & """," ' Handle lastupdated date If Not IsNull(rsPC("lastupdated")) Then pcData = pcData & """lastupdated"":""" & FormatDateTime(rsPC("lastupdated"), 2) & " " & FormatDateTime(rsPC("lastupdated"), 4) & """" Else pcData = pcData & """lastupdated"":null" End If pcData = pcData & "}" pcList = pcList & pcData pcCount = pcCount + 1 rsPC.MoveNext Loop rsPC.Close Set rsPC = Nothing ' Send response Response.Write "{""success"":true,""count"":" & pcCount & ",""data"":[" & pcList & "]}" End Sub Sub GetRecordedIP() On Error Resume Next Err.Clear Dim hostname, ipaddress hostname = Trim(Request.Form("hostname")) If hostname = "" Then SendError "Missing hostname parameter" Exit Sub End If ' Look up primary IP (10.134.*.*) from communications table for this hostname Dim cmd, rs Set cmd = Server.CreateObject("ADODB.Command") cmd.ActiveConnection = objConn cmd.CommandText = "SELECT c.address FROM communications c " & _ "INNER JOIN machines m ON c.machineid = m.machineid " & _ "WHERE m.hostname = ? AND c.address LIKE '10.134.%' " & _ "ORDER BY c.isprimary DESC, c.communicationid ASC LIMIT 1" cmd.Parameters.Append cmd.CreateParameter("@hostname", 200, 1, 50, hostname) Set rs = cmd.Execute() If Err.Number <> 0 Then SendError "Database error: " & Err.Description Exit Sub End If If Not rs.EOF Then ipaddress = rs("address") & "" Response.Write "{""success"":true,""hostname"":""" & hostname & """,""ipaddress"":""" & ipaddress & """}" Else Response.Write "{""success"":false,""hostname"":""" & hostname & """,""ipaddress"":null,""message"":""No 10.134.*.* IP found""}" End If rs.Close Set rs = Nothing Set cmd = Nothing End Sub ' ============================================================================ ' HELPER FUNCTIONS - PC MANAGEMENT ' ============================================================================ Function InsertOrUpdatePC(conn, hostname, serialnumber, manufacturer, model, pcType, _ loggedinuser, machinenumber, osid, pcstatusid, _ warrantyEndDate, warrantyStatus, warrantyServiceLevel, warrantyDaysRemaining) On Error Resume Next Err.Clear ' Step 1: Check conn (passed as parameter) If conn Is Nothing Then Err.Raise 1001, "InsertOrUpdatePC", "conn is Nothing" InsertOrUpdatePC = 0 Exit Function End If If conn.State <> 1 Then Err.Raise 1002, "InsertOrUpdatePC", "conn not open, state=" & conn.State InsertOrUpdatePC = 0 Exit Function End If ' Step 2: Get vendor ID (inlined to avoid VBScript scoping issues) Dim vendorId, modelId, machineTypeId Dim safeManufacturer, safeModel, rsVendor, rsModel vendorId = 0 modelId = 1 If manufacturer <> "" Then safeManufacturer = Replace(manufacturer, "'", "''") Set rsVendor = objConn.Execute("SELECT vendorid FROM vendors WHERE vendor = '" & safeManufacturer & "'") If Not rsVendor.EOF Then vendorId = CLng(rsVendor("vendorid")) Else ' Create new vendor objConn.Execute "INSERT INTO vendors (vendor) VALUES ('" & safeManufacturer & "')" Set rsVendor = objConn.Execute("SELECT LAST_INSERT_ID() AS newid") vendorId = CLng(rsVendor("newid")) End If rsVendor.Close Set rsVendor = Nothing End If ' Step 3: Get model ID (inlined) If model <> "" And vendorId > 0 Then safeModel = Replace(model, "'", "''") Set rsModel = objConn.Execute("SELECT modelnumberid FROM models WHERE modelnumber = '" & safeModel & "' AND vendorid = " & vendorId) If Not rsModel.EOF Then modelId = CLng(rsModel("modelnumberid")) Else ' Create new model objConn.Execute "INSERT INTO models (modelnumber, vendorid, notes, isactive) VALUES ('" & safeModel & "', " & vendorId & ", 'Auto-imported via PowerShell', 1)" Set rsModel = objConn.Execute("SELECT LAST_INSERT_ID() AS newid") modelId = CLng(rsModel("newid")) End If rsModel.Close Set rsModel = Nothing End If ' Step 4: Get machine type ID and PC type ID machineTypeId = GetMachineTypeIdFromPCType(pcType) Dim pctypeId pctypeId = GetPCTypeIdFromPCType(pcType) ' Override pctypeid based on machinenumber pattern ' WJPRT* = Wax Trace PC (pctypeid 6) If machinenumber <> "" Then If UCase(Left(machinenumber, 5)) = "WJPRT" Then pctypeId = 6 ' Wax / Trace LogToFile "Detected WJPRT pattern in machinenumber, setting pctypeid to 6 (Wax/Trace)" End If End If ' Ensure all IDs are numeric (fallback to safe defaults if empty) If Not IsNumeric(vendorId) Or vendorId = "" Then vendorId = 0 If Not IsNumeric(modelId) Or modelId = "" Then modelId = 1 ' TBD model If Not IsNumeric(machineTypeId) Or machineTypeId = "" Then machineTypeId = 33 ' PC If Not IsNumeric(pctypeId) Or pctypeId = "" Then pctypeId = 1 ' Standard LogToFile "Vendor ID: " & vendorId & ", Model ID: " & modelId & ", Machine Type ID: " & machineTypeId & ", PC Type ID: " & pctypeId ' Check if PC already exists (Phase 2: identify PCs by pctypeid IS NOT NULL) Dim strSQL, rsResult, safeHostname safeHostname = Replace(hostname, "'", "''") strSQL = "SELECT machineid FROM machines WHERE hostname = '" & safeHostname & "' AND pctypeid IS NOT NULL" Set rsResult = objConn.Execute(strSQL) Dim machineid machineid = 0 If Err.Number <> 0 Then LogToFile "ERROR checking for existing PC: " & Err.Description InsertOrUpdatePC = 0 Exit Function End If ' Declare string sanitization variables for both UPDATE and INSERT paths Dim safeSerial, safeUser, safeMachineNum If Not rsResult.EOF Then ' PC exists - UPDATE machineid = rsResult("machineid") rsResult.Close Set rsResult = Nothing LogToFile "Updating existing PC, machineid: " & machineid ' Build UPDATE with direct values safeSerial = Replace(serialnumber, "'", "''") If loggedinuser <> "" Then safeUser = Replace(loggedinuser, "'", "''") Else safeUser = "" End If If machinenumber <> "" Then safeMachineNum = Replace(machinenumber, "'", "''") Else safeMachineNum = "" End If ' Build UPDATE SQL with proper conditional logic (VBScript doesn't have IIf) Dim sqlModelId, sqlUserId, sqlMachineNum, sqlOsId, sqlStatusId If modelId > 0 Then sqlModelId = CLng(modelId) Else sqlModelId = "NULL" End If If safeUser <> "" Then sqlUserId = "'" & safeUser & "'" Else sqlUserId = "NULL" End If If safeMachineNum <> "" Then sqlMachineNum = "'" & safeMachineNum & "'" Else sqlMachineNum = "NULL" End If If osid > 0 Then sqlOsId = CLng(osid) Else sqlOsId = "NULL" End If If pcstatusid > 0 Then sqlStatusId = CLng(pcstatusid) Else sqlStatusId = "NULL" End If ' Build lastboottime part for UPDATE Dim sqlLastBoot If lastBootTime <> "" Then sqlLastBoot = "lastboottime = '" & Replace(lastBootTime, "'", "''") & "', " Else sqlLastBoot = "" End If strSQL = "UPDATE machines SET " & _ "serialnumber = '" & safeSerial & "', " & _ "modelnumberid = " & sqlModelId & ", " & _ "machinetypeid = " & CLng(machineTypeId) & ", " & _ "pctypeid = " & CLng(pctypeId) & ", " & _ "loggedinuser = " & sqlUserId & ", " & _ "machinenumber = " & sqlMachineNum & ", " & _ "osid = " & sqlOsId & ", " & _ "machinestatusid = " & sqlStatusId & ", " & _ sqlLastBoot & _ "lastupdated = NOW() " & _ "WHERE machineid = " & CLng(machineid) & " AND pctypeid IS NOT NULL" LogToFile "UPDATE SQL built: " & Left(strSQL, 200) & "..." objConn.Execute strSQL If Err.Number <> 0 Then LogToFile "ERROR updating PC: " & Err.Description InsertOrUpdatePC = 0 Exit Function End If Else ' PC doesn't exist - INSERT rsResult.Close Set rsResult = Nothing LogToFile "Inserting new PC" ' Build INSERT with direct values (sanitize strings) safeSerial = Replace(serialnumber, "'", "''") If loggedinuser <> "" Then safeUser = Replace(loggedinuser, "'", "''") Else safeUser = "" End If If machinenumber <> "" Then safeMachineNum = Replace(machinenumber, "'", "''") Else safeMachineNum = "" End If LogToFile "Building INSERT SQL..." LogToFile "Values: hostname=" & safeHostname & ", serial=" & safeSerial ' Build SQL in parts to isolate error Dim sqlPart1, sqlPart2, sqlPart3 ' Add lastboottime column if provided Dim sqlLastBootCol, sqlLastBootVal If lastBootTime <> "" Then sqlLastBootCol = ", lastboottime" sqlLastBootVal = ", '" & Replace(lastBootTime, "'", "''") & "'" Else sqlLastBootCol = "" sqlLastBootVal = "" End If sqlPart1 = "INSERT INTO machines (hostname, serialnumber, modelnumberid, machinetypeid, pctypeid, loggedinuser, machinenumber, osid, machinestatusid, isactive, lastupdated" & sqlLastBootCol & ") VALUES (" sqlPart2 = "'" & safeHostname & "', '" & safeSerial & "', " If modelId > 0 Then sqlPart2 = sqlPart2 & CLng(modelId) & ", " Else sqlPart2 = sqlPart2 & "NULL, " End If ' machinetypeid and pctypeid are required for PCs sqlPart2 = sqlPart2 & CLng(machineTypeId) & ", " & CLng(pctypeId) & ", " If safeUser <> "" Then sqlPart2 = sqlPart2 & "'" & safeUser & "', " Else sqlPart2 = sqlPart2 & "NULL, " End If If safeMachineNum <> "" Then sqlPart2 = sqlPart2 & "'" & safeMachineNum & "', " Else sqlPart2 = sqlPart2 & "NULL, " End If If osid > 0 Then sqlPart3 = CLng(osid) & ", " Else sqlPart3 = "NULL, " End If If pcstatusid > 0 Then sqlPart3 = sqlPart3 & CLng(pcstatusid) & ", 1, NOW()" & sqlLastBootVal & ")" Else sqlPart3 = sqlPart3 & "NULL, 1, NOW()" & sqlLastBootVal & ")" End If strSQL = sqlPart1 & sqlPart2 & sqlPart3 LogToFile "SQL built successfully, executing..." objConn.Execute strSQL If Err.Number <> 0 Then LogToFile "ERROR inserting PC: " & Err.Description InsertOrUpdatePC = 0 Exit Function End If ' Get the new machineid strSQL = "SELECT LAST_INSERT_ID() AS newid" Set rsResult = objConn.Execute(strSQL) If Not rsResult.EOF Then machineid = CLng(rsResult("newid")) LogToFile "Retrieved new machineid from LAST_INSERT_ID: " & machineid Else machineid = 0 LogToFile "ERROR: LAST_INSERT_ID returned no rows" End If rsResult.Close Set rsResult = Nothing End If LogToFile "InsertOrUpdatePC returning machineid: " & machineid InsertOrUpdatePC = machineid End Function Function GetMachineidByHostname(hostname) On Error Resume Next Dim strSQL, rsResult, safeHostname safeHostname = Replace(hostname, "'", "''") strSQL = "SELECT machineid FROM machines WHERE hostname = '" & safeHostname & "' AND pctypeid IS NOT NULL" Set rsResult = objConn.Execute(strSQL) If Not rsResult.EOF Then GetMachineidByHostname = CLng(rsResult("machineid")) Else GetMachineidByHostname = 0 End If rsResult.Close Set rsResult = Nothing End Function Sub ClearShopfloorData(hostname) On Error Resume Next Dim machineid machineid = GetMachineidByHostname(hostname) If machineid = 0 Then LogToFile "ClearShopfloorData: Cannot find machineid for hostname: " & hostname Exit Sub End If LogToFile "ClearShopfloorData: Clearing data for machineid " & machineid ' Delete from communications table Dim cmdDelete Set cmdDelete = Server.CreateObject("ADODB.Command") cmdDelete.ActiveConnection = objConn cmdDelete.CommandText = "DELETE FROM communications WHERE machineid = ?" cmdDelete.Parameters.Append cmdDelete.CreateParameter("@machineid", 3, 1, , CLng(machineid)) cmdDelete.Execute LogToFile "Deleted " & cmdDelete.RecordsAffected & " communications records" ' Delete from commconfig Set cmdDelete = Server.CreateObject("ADODB.Command") cmdDelete.ActiveConnection = objConn cmdDelete.CommandText = "DELETE FROM commconfig WHERE machineid = ?" cmdDelete.Parameters.Append cmdDelete.CreateParameter("@machineid", 3, 1, , CLng(machineid)) cmdDelete.Execute LogToFile "Deleted " & cmdDelete.RecordsAffected & " comm config records" ' Delete from dncconfig Set cmdDelete = Server.CreateObject("ADODB.Command") cmdDelete.ActiveConnection = objConn cmdDelete.CommandText = "DELETE FROM dncconfig WHERE machineid = ?" cmdDelete.Parameters.Append cmdDelete.CreateParameter("@machineid", 3, 1, , CLng(machineid)) cmdDelete.Execute LogToFile "Deleted " & cmdDelete.RecordsAffected & " DNC config records" End Sub ' ============================================================================ ' HELPER FUNCTIONS - NETWORK & COMMUNICATION ' ============================================================================ Function InsertNetworkInterfaces(machineid, networkInterfacesJSON) On Error Resume Next Dim interfacesArray interfacesArray = ParseJSONArray(networkInterfacesJSON) Dim count, i count = 0 For i = 0 To UBound(interfacesArray) Dim ipAddress, macAddress, subnetMask, gateway, interfaceName, isMachineNetwork ipAddress = Trim(GetJSONValue(interfacesArray(i), "IPAddress") & "") macAddress = Trim(GetJSONValue(interfacesArray(i), "MACAddress") & "") subnetMask = Trim(GetJSONValue(interfacesArray(i), "SubnetMask") & "") gateway = Trim(GetJSONValue(interfacesArray(i), "DefaultGateway") & "") interfaceName = Trim(GetJSONValue(interfacesArray(i), "InterfaceName") & "") isMachineNetwork = GetJSONValue(interfacesArray(i), "IsMachineNetwork") If interfaceName = "" Then interfaceName = "Interface " & (i + 1) ' Determine if primary - 10.134.*.* is always primary for shopfloor PCs Dim isPrimary, isPrimaryFromJson isPrimary = 0 isPrimaryFromJson = GetJSONValue(interfacesArray(i), "IsPrimary") If isPrimaryFromJson = True Or isPrimaryFromJson = "true" Or isPrimaryFromJson = "True" Then isPrimary = 1 ElseIf Left(ipAddress, 7) = "10.134." Then ' Fallback: 10.134.*.* is always primary isPrimary = 1 End If ' Insert into communications table Dim cmdInsert Set cmdInsert = Server.CreateObject("ADODB.Command") cmdInsert.ActiveConnection = objConn cmdInsert.CommandText = "INSERT INTO communications (" & _ "machineid, comstypeid, address, macaddress, " & _ "subnetmask, defaultgateway, interfacename, isprimary, isactive" & _ ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" ' Prepare parameter values (VBScript doesn't have IIf) Dim paramAddress, paramMacAddress, paramSubnet, paramGateway If ipAddress <> "" Then paramAddress = ipAddress Else paramAddress = Null If macAddress <> "" Then paramMacAddress = macAddress Else paramMacAddress = Null If subnetMask <> "" Then paramSubnet = subnetMask Else paramSubnet = Null If gateway <> "" Then paramGateway = gateway Else paramGateway = Null cmdInsert.Parameters.Append cmdInsert.CreateParameter("@machineid", 3, 1, , CLng(machineid)) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@comstypeid", 3, 1, , 1) ' 1 = Network Interface cmdInsert.Parameters.Append cmdInsert.CreateParameter("@address", 200, 1, 45, paramAddress) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@macaddress", 200, 1, 17, paramMacAddress) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@subnetmask", 200, 1, 45, paramSubnet) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@gateway", 200, 1, 45, paramGateway) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@interfacename", 200, 1, 50, interfaceName) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@isprimary", 3, 1, , isPrimary) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@isactive", 3, 1, , 1) cmdInsert.Execute If Err.Number = 0 Then count = count + 1 Else LogToFile "ERROR inserting network interface: " & Err.Description End If Next InsertNetworkInterfaces = count End Function Function InsertCommConfigs(machineid, commConfigsJSON) On Error Resume Next Dim configsArray configsArray = ParseJSONArray(commConfigsJSON) Dim count, i count = 0 For i = 0 To UBound(configsArray) Dim portName, baudRate, dataBits, parity, stopBits, flowControl portName = Trim(GetJSONValue(configsArray(i), "PortName") & "") baudRate = GetJSONValue(configsArray(i), "BaudRate") dataBits = GetJSONValue(configsArray(i), "DataBits") parity = Trim(GetJSONValue(configsArray(i), "Parity") & "") stopBits = Trim(GetJSONValue(configsArray(i), "StopBits") & "") flowControl = Trim(GetJSONValue(configsArray(i), "FlowControl") & "") If portName <> "" Then Dim cmdInsert Set cmdInsert = Server.CreateObject("ADODB.Command") cmdInsert.ActiveConnection = objConn cmdInsert.CommandText = "INSERT INTO commconfig (" & _ "machineid, portname, baudrate, databits, parity, stopbits, flowcontrol" & _ ") VALUES (?, ?, ?, ?, ?, ?, ?)" ' Prepare parameter values (VBScript doesn't have IIf) Dim paramBaud, paramDataBits, paramParity, paramStopBits, paramFlowControl If IsNumeric(baudRate) Then paramBaud = CLng(baudRate) Else paramBaud = Null If IsNumeric(dataBits) Then paramDataBits = CLng(dataBits) Else paramDataBits = Null If parity <> "" Then paramParity = parity Else paramParity = Null If stopBits <> "" Then paramStopBits = stopBits Else paramStopBits = Null If flowControl <> "" Then paramFlowControl = flowControl Else paramFlowControl = Null cmdInsert.Parameters.Append cmdInsert.CreateParameter("@machineid", 3, 1, , CLng(machineid)) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@portname", 200, 1, 50, portName) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@baudrate", 3, 1, , paramBaud) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@databits", 3, 1, , paramDataBits) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@parity", 200, 1, 20, paramParity) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@stopbits", 200, 1, 20, paramStopBits) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@flowcontrol", 200, 1, 50, paramFlowControl) cmdInsert.Execute If Err.Number = 0 Then count = count + 1 Else LogToFile "ERROR inserting comm config: " & Err.Description End If End If Next InsertCommConfigs = count End Function Function InsertDNCConfig(machineid, dncConfigJSON, dualPathEnabled, path1Name, path2Name, _ geRegistry32Bit, geRegistry64Bit, geRegistryNotes) On Error Resume Next ' Parse DNC config JSON Dim dncObj Set dncObj = ParseJSONObject(dncConfigJSON) If dncObj Is Nothing Then InsertDNCConfig = False Exit Function End If ' Extract DNC values Dim site, cnc, ncif, machineNumber, hostType Dim ftpHostPrimary, ftpHostSecondary, ftpAccount Dim debug, uploads, scanner, dripFeed, additionalSettings site = Trim(GetDictValue(dncObj, "Site") & "") cnc = Trim(GetDictValue(dncObj, "CNC") & "") ncif = Trim(GetDictValue(dncObj, "NCIF") & "") machineNumber = Trim(GetDictValue(dncObj, "MachineNumber") & "") hostType = Trim(GetDictValue(dncObj, "HostType") & "") ftpHostPrimary = Trim(GetDictValue(dncObj, "FTPHostPrimary") & "") ftpHostSecondary = Trim(GetDictValue(dncObj, "FTPHostSecondary") & "") ftpAccount = Trim(GetDictValue(dncObj, "FTPAccount") & "") debug = Trim(GetDictValue(dncObj, "Debug") & "") uploads = Trim(GetDictValue(dncObj, "Uploads") & "") scanner = Trim(GetDictValue(dncObj, "Scanner") & "") dripFeed = Trim(GetDictValue(dncObj, "DripFeed") & "") additionalSettings = Trim(GetDictValue(dncObj, "AdditionalSettings") & "") ' Convert boolean strings to integers Dim dualPathInt, geRegistry32Int, geRegistry64Int dualPathInt = ConvertBoolToInt(dualPathEnabled) geRegistry32Int = ConvertBoolToInt(geRegistry32Bit) geRegistry64Int = ConvertBoolToInt(geRegistry64Bit) ' Insert DNC config Dim cmdInsert Set cmdInsert = Server.CreateObject("ADODB.Command") cmdInsert.ActiveConnection = objConn cmdInsert.CommandText = "INSERT INTO dncconfig (" & _ "machineid, site, cnc, ncif, machinenumber, hosttype, " & _ "ftphostprimary, ftphostsecondary, ftpaccount, " & _ "debug, uploads, scanner, dripfeed, additionalsettings, " & _ "dualpath_enabled, path1_name, path2_name, " & _ "ge_registry_32bit, ge_registry_64bit, ge_registry_notes, " & _ "lastupdated" & _ ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())" ' Prepare parameter values (VBScript doesn't have IIf) Dim pSite, pCnc, pNcif, pMachineNum, pHostType, pFtpPri, pFtpSec, pFtpAcct Dim pDebug, pUploads, pScanner, pDripFeed, pAddSet, pDualPath, pPath1, pPath2, pGe32, pGe64, pGeNotes If site <> "" Then pSite = site Else pSite = Null If cnc <> "" Then pCnc = cnc Else pCnc = Null If ncif <> "" Then pNcif = ncif Else pNcif = Null If machineNumber <> "" Then pMachineNum = machineNumber Else pMachineNum = Null If hostType <> "" Then pHostType = hostType Else pHostType = Null If ftpHostPrimary <> "" Then pFtpPri = ftpHostPrimary Else pFtpPri = Null If ftpHostSecondary <> "" Then pFtpSec = ftpHostSecondary Else pFtpSec = Null If ftpAccount <> "" Then pFtpAcct = ftpAccount Else pFtpAcct = Null If debug <> "" Then pDebug = debug Else pDebug = Null If uploads <> "" Then pUploads = uploads Else pUploads = Null If scanner <> "" Then pScanner = scanner Else pScanner = Null If dripFeed <> "" Then pDripFeed = dripFeed Else pDripFeed = Null If additionalSettings <> "" Then pAddSet = additionalSettings Else pAddSet = Null If dualPathInt >= 0 Then pDualPath = dualPathInt Else pDualPath = Null If path1Name <> "" Then pPath1 = path1Name Else pPath1 = Null If path2Name <> "" Then pPath2 = path2Name Else pPath2 = Null If geRegistry32Int >= 0 Then pGe32 = geRegistry32Int Else pGe32 = Null If geRegistry64Int >= 0 Then pGe64 = geRegistry64Int Else pGe64 = Null If geRegistryNotes <> "" Then pGeNotes = geRegistryNotes Else pGeNotes = Null cmdInsert.Parameters.Append cmdInsert.CreateParameter("@machineid", 3, 1, , CLng(machineid)) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@site", 200, 1, 50, pSite) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@cnc", 200, 1, 50, pCnc) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@ncif", 200, 1, 50, pNcif) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@machinenum", 200, 1, 50, pMachineNum) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@hosttype", 200, 1, 50, pHostType) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@ftppri", 200, 1, 100, pFtpPri) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@ftpsec", 200, 1, 100, pFtpSec) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@ftpacct", 200, 1, 100, pFtpAcct) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@debug", 200, 1, 50, pDebug) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@uploads", 200, 1, 100, pUploads) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@scanner", 200, 1, 50, pScanner) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@dripfeed", 200, 1, 50, pDripFeed) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@addset", 200, 1, 255, pAddSet) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@dualpath", 3, 1, , pDualPath) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@path1", 200, 1, 100, pPath1) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@path2", 200, 1, 100, pPath2) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@ge32", 3, 1, , pGe32) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@ge64", 3, 1, , pGe64) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@genotes", 200, 1, 255, pGeNotes) cmdInsert.Execute If Err.Number <> 0 Then LogToFile "ERROR inserting DNC config: " & Err.Description InsertDNCConfig = False Else InsertDNCConfig = True End If End Function ' ============================================================================ ' HELPER FUNCTIONS - RELATIONSHIPS & WARRANTY ' ============================================================================ Function CreatePCMachineRelationship(pcMachineid, machineNumber) On Error Resume Next If machineNumber = "" Then CreatePCMachineRelationship = False Exit Function End If ' Find equipment by machine number (Phase 2: PCs have pctypeid IS NOT NULL, Equipment has pctypeid IS NULL) Dim strSQL, rsResult, safeMachineNumber safeMachineNumber = Replace(machineNumber, "'", "''") strSQL = "SELECT machineid FROM machines WHERE machinenumber = '" & safeMachineNumber & "' AND pctypeid IS NULL" LogToFile "CreatePCMachineRelationship: Executing SQL: " & strSQL Set rsResult = objConn.Execute(strSQL) Dim equipmentMachineid If Not rsResult.EOF Then equipmentMachineid = CLng(rsResult("machineid")) LogToFile "CreatePCMachineRelationship: Found equipment machineid=" & equipmentMachineid & " for machine number: " & machineNumber If Err.Number <> 0 Then LogToFile "CreatePCMachineRelationship: ERROR reading machineid: " & Err.Description Err.Clear rsResult.Close Set rsResult = Nothing CreatePCMachineRelationship = False Exit Function End If Else LogToFile "CreatePCMachineRelationship: Equipment not found for machine number: " & machineNumber rsResult.Close Set rsResult = Nothing CreatePCMachineRelationship = False Exit Function End If rsResult.Close Set rsResult = Nothing LogToFile "CreatePCMachineRelationship: Creating relationship PC " & pcMachineid & " -> Controls -> Equipment " & equipmentMachineid ' Get "Controls" relationship type ID strSQL = "SELECT relationshiptypeid FROM relationshiptypes WHERE relationshiptype = 'Controls'" Set rsResult = objConn.Execute(strSQL) Dim relationshiptypeid If Not rsResult.EOF Then relationshiptypeid = rsResult("relationshiptypeid") Else LogToFile "CreatePCMachineRelationship: Controls relationship type not found" rsResult.Close Set rsResult = Nothing CreatePCMachineRelationship = False Exit Function End If rsResult.Close Set rsResult = Nothing ' Check if relationship already exists (PC -> Equipment) strSQL = "SELECT relationshipid FROM machinerelationships " & _ "WHERE machineid = " & CLng(pcMachineid) & " AND related_machineid = " & CLng(equipmentMachineid) & " AND relationshiptypeid = " & CLng(relationshiptypeid) LogToFile "CreatePCMachineRelationship: Checking for duplicate: " & strSQL Set rsResult = objConn.Execute(strSQL) If Not rsResult.EOF Then ' Relationship already exists LogToFile "CreatePCMachineRelationship: Relationship already exists (relationshipid=" & rsResult("relationshipid") & ")" rsResult.Close Set rsResult = Nothing CreatePCMachineRelationship = True Exit Function End If LogToFile "CreatePCMachineRelationship: No duplicate found, proceeding with INSERT" rsResult.Close Set rsResult = Nothing ' Create new Controls relationship (PC -> Equipment) ' Fixed: PC should be machineid, Equipment should be related_machineid Dim cmdInsert Set cmdInsert = Server.CreateObject("ADODB.Command") cmdInsert.ActiveConnection = objConn cmdInsert.CommandText = "INSERT INTO machinerelationships (" & _ "machineid, related_machineid, relationshiptypeid, isactive" & _ ") VALUES (?, ?, ?, 1)" cmdInsert.Parameters.Append cmdInsert.CreateParameter("@pcid", 3, 1, , CLng(pcMachineid)) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@equipmentid", 3, 1, , CLng(equipmentMachineid)) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@reltypeid", 3, 1, , CLng(relationshiptypeid)) cmdInsert.Execute If Err.Number <> 0 Then LogToFile "ERROR creating PC-machine relationship: " & Err.Description CreatePCMachineRelationship = False Else LogToFile "Created Controls relationship: Equipment " & equipmentMachineid & " controlled by PC " & pcMachineid CreatePCMachineRelationship = True End If End Function Sub UpdateWarrantyData(machineid, warrantyEndDate, warrantyStatus, warrantyServiceLevel, warrantyDaysRemaining) On Error Resume Next If warrantyEndDate = "" Then Exit Sub ' Check if warranty record exists Dim strSQL, rsResult strSQL = "SELECT warrantyid FROM warranties WHERE machineid = " & CLng(machineid) Set rsResult = objConn.Execute(strSQL) If Not rsResult.EOF Then ' UPDATE existing warranty Dim warrantyid warrantyid = rsResult("warrantyid") rsResult.Close Set rsResult = Nothing Dim cmdUpdate Set cmdUpdate = Server.CreateObject("ADODB.Command") cmdUpdate.ActiveConnection = objConn cmdUpdate.CommandText = "UPDATE warranties SET " & _ "enddate = ?, servicelevel = ?, status = ?, daysremaining = ?, " & _ "lastcheckeddate = NOW() " & _ "WHERE warrantyid = ?" ' Prepare parameter values (VBScript doesn't have IIf) Dim pServiceLevel, pStatus, pDaysRemaining If warrantyServiceLevel <> "" Then pServiceLevel = warrantyServiceLevel Else pServiceLevel = Null If warrantyStatus <> "" Then pStatus = warrantyStatus Else pStatus = Null If IsNumeric(warrantyDaysRemaining) Then pDaysRemaining = CLng(warrantyDaysRemaining) Else pDaysRemaining = Null cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@enddate", 135, 1, , CDate(warrantyEndDate)) cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@servicelevel", 200, 1, 100, pServiceLevel) cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@status", 200, 1, 50, pStatus) cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@daysrem", 3, 1, , pDaysRemaining) cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@warrantyid", 3, 1, , CLng(warrantyid)) cmdUpdate.Execute Else ' INSERT new warranty rsResult.Close Set rsResult = Nothing Dim cmdInsert Set cmdInsert = Server.CreateObject("ADODB.Command") cmdInsert.ActiveConnection = objConn cmdInsert.CommandText = "INSERT INTO warranties (" & _ "machineid, enddate, servicelevel, status, daysremaining, lastcheckeddate" & _ ") VALUES (?, ?, ?, ?, ?, NOW())" ' Prepare parameter values (VBScript doesn't have IIf) Dim pServiceLevel2, pStatus2, pDaysRemaining2 If warrantyServiceLevel <> "" Then pServiceLevel2 = warrantyServiceLevel Else pServiceLevel2 = Null If warrantyStatus <> "" Then pStatus2 = warrantyStatus Else pStatus2 = Null If IsNumeric(warrantyDaysRemaining) Then pDaysRemaining2 = CLng(warrantyDaysRemaining) Else pDaysRemaining2 = Null cmdInsert.Parameters.Append cmdInsert.CreateParameter("@machineid", 3, 1, , CLng(machineid)) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@enddate", 135, 1, , CDate(warrantyEndDate)) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@servicelevel", 200, 1, 100, pServiceLevel2) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@status", 200, 1, 50, pStatus2) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@daysrem", 3, 1, , pDaysRemaining2) cmdInsert.Execute End If End Sub ' ============================================================================ ' HELPER FUNCTIONS - LOOKUPS ' ============================================================================ Function GetOrCreateVendor(connString, vendorName) On Error Resume Next Err.Clear If vendorName = "" Then GetOrCreateVendor = 0 Exit Function End If ' Create local connection for this function Dim localConn Set localConn = Server.CreateObject("ADODB.Connection") localConn.ConnectionString = connString localConn.Open If Err.Number <> 0 Then GetOrCreateVendor = 0 Exit Function End If ' Sanitize vendor name (prevent SQL injection) Dim safeName safeName = Replace(vendorName, "'", "''") ' Check if vendor exists Dim strSQL, rsResult strSQL = "SELECT vendorid FROM vendors WHERE vendor = '" & safeName & "'" Set rsResult = localConn.Execute(strSQL) If Err.Number <> 0 Then LogToFile "ERROR querying vendor: " & Err.Description localConn.Close Set localConn = Nothing GetOrCreateVendor = 0 Exit Function End If If Not rsResult.EOF Then GetOrCreateVendor = CLng(rsResult("vendorid")) rsResult.Close Set rsResult = Nothing localConn.Close Set localConn = Nothing LogToFile "Found existing vendor ID: " & GetOrCreateVendor Exit Function End If rsResult.Close Set rsResult = Nothing ' Create new vendor strSQL = "INSERT INTO vendors (vendor) VALUES ('" & safeName & "')" localConn.Execute strSQL If Err.Number <> 0 Then LogToFile "ERROR creating vendor: " & Err.Description localConn.Close Set localConn = Nothing GetOrCreateVendor = 0 Exit Function End If ' Get new vendor ID strSQL = "SELECT LAST_INSERT_ID() AS newid" Set rsResult = localConn.Execute(strSQL) GetOrCreateVendor = CLng(rsResult("newid")) rsResult.Close Set rsResult = Nothing localConn.Close Set localConn = Nothing LogToFile "Created new vendor ID: " & GetOrCreateVendor End Function Function GetOrCreateModel(conn, modelName, vendorId) On Error Resume Next If modelName = "" Then GetOrCreateModel = 1 ' Return TBD model Exit Function End If If vendorId = 0 Then GetOrCreateModel = 1 Exit Function End If ' Check if model exists for this vendor Dim strSQL, rsResult, safeModelName safeModelName = Replace(modelName, "'", "''") strSQL = "SELECT modelnumberid FROM models WHERE modelnumber = '" & safeModelName & "' AND vendorid = " & CLng(vendorId) Set rsResult = conn.Execute(strSQL) If Not rsResult.EOF Then GetOrCreateModel = rsResult("modelnumberid") rsResult.Close Set rsResult = Nothing Exit Function End If rsResult.Close Set rsResult = Nothing ' Create new model Dim cmdInsert Set cmdInsert = Server.CreateObject("ADODB.Command") cmdInsert.ActiveConnection = conn cmdInsert.CommandText = "INSERT INTO models (modelnumber, vendorid, notes, isactive) VALUES (?, ?, ?, 1)" cmdInsert.Parameters.Append cmdInsert.CreateParameter("@model", 200, 1, 100, modelName) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@vendorid", 3, 1, , CLng(vendorId)) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@notes", 200, 1, 255, "Auto-imported via PowerShell") cmdInsert.Execute If Err.Number <> 0 Then LogToFile "ERROR creating model: " & Err.Description GetOrCreateModel = 1 Exit Function End If ' Get new model ID strSQL = "SELECT LAST_INSERT_ID() AS newid" Set rsResult = conn.Execute(strSQL) GetOrCreateModel = rsResult("newid") rsResult.Close Set rsResult = Nothing End Function ' ============================================================================ ' LEGACY FUNCTION REMOVED: GetOrCreatePCType ' All PCs now use machinetypeid=33, with pctypeid determining the specific type ' GetMachineTypeIdFromPCType returns 33 for all PCs ' GetPCTypeIdFromPCType maps pcType string to pctypeid (1=Standard, 2=Engineer, etc.) ' Removed: 2025-11-17 during Phase 2 migration from pc/pctype to machines/machinetypes ' ============================================================================ Function GetOrCreateOSID(osVersion) On Error Resume Next If osVersion = "" Then GetOrCreateOSID = 0 Exit Function End If ' Sanitize OS name Dim safeName safeName = Replace(osVersion, "'", "''") ' Check if OS exists Dim strSQL, rsResult strSQL = "SELECT osid FROM operatingsystems WHERE operatingsystem = '" & safeName & "'" Set rsResult = objConn.Execute(strSQL) If Err.Number <> 0 Then LogToFile "ERROR querying OS: " & Err.Description GetOrCreateOSID = 0 Exit Function End If If Not rsResult.EOF Then GetOrCreateOSID = CLng(rsResult("osid")) rsResult.Close Set rsResult = Nothing Exit Function End If rsResult.Close Set rsResult = Nothing ' Create new OS strSQL = "INSERT INTO operatingsystems (operatingsystem) VALUES ('" & safeName & "')" objConn.Execute strSQL If Err.Number <> 0 Then LogToFile "ERROR creating OS: " & Err.Description GetOrCreateOSID = 0 Exit Function End If ' Get new OS ID strSQL = "SELECT LAST_INSERT_ID() AS newid" Set rsResult = objConn.Execute(strSQL) GetOrCreateOSID = CLng(rsResult("newid")) rsResult.Close Set rsResult = Nothing End Function Function GetOrCreateApplication(appName, appVersion) On Error Resume Next LogToFile "GetOrCreateApplication called with appName='" & appName & "', appVersion='" & appVersion & "'" If appName = "" Then LogToFile "ERROR: appName is empty" GetOrCreateApplication = 0 Exit Function End If ' Check if application exists (applications table has appid and appname columns) Dim strSQL, rsResult, safeAppName safeAppName = Replace(appName, "'", "''") strSQL = "SELECT appid FROM applications WHERE appname = '" & safeAppName & "'" Set rsResult = objConn.Execute(strSQL) If Err.Number <> 0 Then LogToFile "ERROR querying applications: " & Err.Description GetOrCreateApplication = 0 Exit Function End If If Not rsResult.EOF Then GetOrCreateApplication = rsResult("appid") LogToFile "Found existing appid: " & GetOrCreateApplication rsResult.Close Set rsResult = Nothing Exit Function End If rsResult.Close Set rsResult = Nothing LogToFile "Application not found, creating new..." ' Create new application Dim cmdInsert Set cmdInsert = Server.CreateObject("ADODB.Command") cmdInsert.ActiveConnection = objConn cmdInsert.CommandText = "INSERT INTO applications (appname, appdescription, isactive) VALUES (?, ?, ?)" cmdInsert.Parameters.Append cmdInsert.CreateParameter("@appname", 200, 1, 50, appName) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@description", 200, 1, 255, "Auto-detected application") cmdInsert.Parameters.Append cmdInsert.CreateParameter("@isactive", 11, 1, , 1) cmdInsert.Execute If Err.Number <> 0 Then LogToFile "ERROR creating application: " & Err.Description GetOrCreateApplication = 0 Exit Function End If ' Get new application ID strSQL = "SELECT LAST_INSERT_ID() AS newid" Set rsResult = objConn.Execute(strSQL) GetOrCreateApplication = rsResult("newid") LogToFile "Created new application with id: " & GetOrCreateApplication rsResult.Close Set rsResult = Nothing End Function Function GetOrCreateAppVersion(conn, appId, appVersion) ' Returns appversionid for the given app and version ' Creates the version record if it doesn't exist ' conn parameter passed explicitly to avoid VBScript scoping issues On Error Resume Next Err.Clear LogToFile "GetOrCreateAppVersion called with appId=" & appId & ", appVersion='" & appVersion & "'" ' Validate connection object first If conn Is Nothing Then LogToFile "ERROR: conn parameter is Nothing" GetOrCreateAppVersion = 0 Err.Clear Exit Function End If If conn.State <> 1 Then LogToFile "ERROR: conn is not open, state=" & conn.State GetOrCreateAppVersion = 0 Err.Clear Exit Function End If If appId = 0 Or appId = "" Then LogToFile "ERROR: appId is empty or zero" GetOrCreateAppVersion = 0 Err.Clear Exit Function End If ' If no version provided, return 0 (NULL will be stored) If appVersion = "" Or IsNull(appVersion) Then LogToFile "No version provided, returning 0" GetOrCreateAppVersion = 0 Err.Clear Exit Function End If ' Check if version exists for this app Dim strSQL, rsResult, safeVersion safeVersion = Replace(appVersion, "'", "''") strSQL = "SELECT appversionid FROM appversions WHERE appid = " & CLng(appId) & " AND version = '" & safeVersion & "'" LogToFile "SELECT SQL: " & strSQL Set rsResult = conn.Execute(strSQL) If Err.Number <> 0 Then LogToFile "ERROR querying appversions: " & Err.Number & " - " & Err.Description Err.Clear GetOrCreateAppVersion = 0 Exit Function End If ' Check if recordset is valid If rsResult Is Nothing Then LogToFile "ERROR: rsResult is Nothing after Execute" GetOrCreateAppVersion = 0 Err.Clear Exit Function End If If Not rsResult.EOF Then GetOrCreateAppVersion = rsResult("appversionid") LogToFile "Found existing appversionid: " & GetOrCreateAppVersion rsResult.Close Set rsResult = Nothing Err.Clear Exit Function End If rsResult.Close Set rsResult = Nothing LogToFile "Version not found, creating new..." ' Create new version record using direct SQL (omit isactive - let it default, BIT column causes type mismatch) Dim insertSQL insertSQL = "INSERT INTO appversions (appid, version) VALUES (" & CLng(appId) & ", '" & safeVersion & "')" LogToFile "INSERT SQL: " & insertSQL conn.Execute insertSQL If Err.Number <> 0 Then LogToFile "ERROR creating app version: " & Err.Number & " - " & Err.Description Err.Clear GetOrCreateAppVersion = 0 Exit Function End If ' Get new version ID strSQL = "SELECT LAST_INSERT_ID() AS newid" Set rsResult = conn.Execute(strSQL) If Err.Number <> 0 Then LogToFile "ERROR getting LAST_INSERT_ID: " & Err.Number & " - " & Err.Description Err.Clear GetOrCreateAppVersion = 0 Exit Function End If If Not rsResult.EOF Then GetOrCreateAppVersion = CLng(rsResult("newid")) LogToFile "Created new app version with id: " & GetOrCreateAppVersion Else LogToFile "ERROR: LAST_INSERT_ID returned no rows" GetOrCreateAppVersion = 0 End If rsResult.Close Set rsResult = Nothing Err.Clear End Function Function GetMachineTypeIdFromPCType(pcTypeString) ' All PCs use machinetypeid = 33 (PC) ' The specific PC type is determined by pctypeid, not machinetypeid GetMachineTypeIdFromPCType = 33 LogToFile "All PCs use machinetypeid 33, pcType '" & pcTypeString & "' -> pctypeid handles type" End Function Function GetPCTypeIdFromPCType(pcTypeString) On Error Resume Next ' Map pcType parameter to pctypeid (from pctype table) ' pctypeid values: 1=Standard, 2=Engineer, 3=Shopfloor, 4=Uncategorized, ' 5=CMM, 6=Wax/Trace, 7=Keyence, 8=Genspect, 9=Heat Treat, 10=Part Marker Dim pcTypeClean pcTypeClean = Trim(UCase(pcTypeString)) Select Case pcTypeClean Case "ENGINEER", "ENGINEERING" GetPCTypeIdFromPCType = 2 Case "SHOPFLOOR", "SHOP FLOOR" GetPCTypeIdFromPCType = 3 Case "CMM" GetPCTypeIdFromPCType = 5 Case "WAX TRACE", "WAXTRACE", "WAX", "WAX / TRACE" GetPCTypeIdFromPCType = 6 Case "KEYENCE" GetPCTypeIdFromPCType = 7 Case "GENSPECT", "EAS1000" GetPCTypeIdFromPCType = 8 ' Genspect / EAS1000 Case "HEAT TREAT", "HEATTTREAT", "HEATTEAT", "HEAT_TREAT", "HEATTREAT" GetPCTypeIdFromPCType = 9 Case "PART MARKER", "PARTMARKER" GetPCTypeIdFromPCType = 10 Case "MEASURING", "MEASURING TOOL" GetPCTypeIdFromPCType = 7 ' Default other measuring tools to Keyence Case "STANDARD", "" GetPCTypeIdFromPCType = 1 Case Else LogToFile "Unknown pcType '" & pcTypeString & "' for pctypeid, defaulting to Standard (1)" GetPCTypeIdFromPCType = 1 End Select LogToFile "Mapped pcType '" & pcTypeString & "' to pctypeid: " & GetPCTypeIdFromPCType End Function ' ============================================================================ ' HELPER FUNCTIONS - JSON PARSING (Simple) ' ============================================================================ Function ParseJSONArray(jsonString) ' Very simple JSON array parser - splits by objects ' Assumes format: [{"key":"value",...},{"key":"value",...}] If jsonString = "" Or IsNull(jsonString) Then ParseJSONArray = Array() Exit Function End If ' Remove outer brackets and whitespace Dim cleaned cleaned = Trim(jsonString) If Left(cleaned, 1) = "[" Then cleaned = Mid(cleaned, 2) If Right(cleaned, 1) = "]" Then cleaned = Left(cleaned, Len(cleaned) - 1) ' Split by },{ Dim items items = Split(cleaned, "},{") ' Clean up each item (add back braces) Dim i For i = 0 To UBound(items) items(i) = Trim(items(i)) If Left(items(i), 1) <> "{" Then items(i) = "{" & items(i) If Right(items(i), 1) <> "}" Then items(i) = items(i) & "}" Next ParseJSONArray = items End Function Function ParseJSONObject(jsonString) ' Return a dictionary for simple JSON parsing Dim dict Set dict = Server.CreateObject("Scripting.Dictionary") If jsonString = "" Or IsNull(jsonString) Then Set ParseJSONObject = dict Exit Function End If ' Simple key-value extraction Dim cleaned cleaned = Trim(jsonString) If Left(cleaned, 1) = "{" Then cleaned = Mid(cleaned, 2) If Right(cleaned, 1) = "}" Then cleaned = Left(cleaned, Len(cleaned) - 1) ' Split by comma (simple approach) Dim pairs, pair, i pairs = Split(cleaned, ",") For i = 0 To UBound(pairs) pair = Trim(pairs(i)) If InStr(pair, ":") > 0 Then Dim key, value key = Trim(Split(pair, ":")(0)) value = Trim(Split(pair, ":")(1)) ' Remove quotes key = Replace(Replace(key, """", ""), "'", "") value = Replace(Replace(value, """", ""), "'", "") dict.Add key, value End If Next Set ParseJSONObject = dict End Function Function GetJSONValue(jsonObjectString, keyName) ' Extract a single value from JSON object string ' Format: {"Key":"Value",...} If jsonObjectString = "" Or IsNull(jsonObjectString) Then GetJSONValue = "" Exit Function End If Dim pattern pattern = """" & keyName & """\s*:\s*""([^""]*)""|""" & keyName & """\s*:\s*([^,}]*)" Dim regex Set regex = New RegExp regex.Pattern = pattern regex.IgnoreCase = True Dim matches Set matches = regex.Execute(jsonObjectString) If matches.Count > 0 Then If matches(0).SubMatches(0) <> "" Then GetJSONValue = matches(0).SubMatches(0) Else GetJSONValue = Trim(matches(0).SubMatches(1)) End If Else GetJSONValue = "" End If End Function Function GetDictValue(dict, keyName) If dict.Exists(keyName) Then GetDictValue = dict(keyName) Else GetDictValue = "" End If End Function ' ============================================================================ ' HELPER FUNCTIONS - UTILITIES ' ============================================================================ Function ConvertBoolToInt(value) ' Convert various boolean representations to 0/1 or -1 for NULL If IsNull(value) Or value = "" Then ConvertBoolToInt = -1 Exit Function End If Dim strValue strValue = LCase(Trim(CStr(value))) Select Case strValue Case "true", "1", "yes" ConvertBoolToInt = 1 Case "false", "0", "no" ConvertBoolToInt = 0 Case Else ConvertBoolToInt = -1 End Select End Function Function IsIPAddress(value) ' Simple IP address validation If value = "" Then IsIPAddress = False Exit Function End If Dim regex Set regex = New RegExp regex.Pattern = "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$" IsIPAddress = regex.Test(value) End Function ' ============================================================================ ' HELPER FUNCTIONS - RESPONSE & LOGGING ' ============================================================================ Sub SendResponse(responseDict) ' Convert dictionary to JSON and send Response.Clear Response.ContentType = "application/json" Response.Write DictToJSON(responseDict) Response.End End Sub Sub SendError(message) Response.Clear Response.ContentType = "application/json" Response.Write "{""success"":false,""error"":""" & EscapeJSON(message) & """}" Response.End End Sub Function DictToJSON(dict) ' Simple dictionary to JSON converter Dim json, key, value json = "{" Dim first first = True For Each key In dict.Keys If Not first Then json = json & "," first = False value = dict(key) json = json & """" & EscapeJSON(key) & """:" If IsObject(value) Then ' Nested dictionary json = json & DictToJSON(value) ElseIf IsNull(value) Then json = json & "null" ElseIf VarType(value) = vbBoolean Then If value Then json = json & "true" Else json = json & "false" End If ElseIf IsNumeric(value) Then json = json & value Else json = json & """" & EscapeJSON(CStr(value)) & """" End If Next json = json & "}" DictToJSON = json End Function Function EscapeJSON(value) ' Escape special characters for JSON Dim result result = CStr(value) result = Replace(result, "\", "\\") result = Replace(result, """", "\""") result = Replace(result, vbCr, "\r") result = Replace(result, vbLf, "\n") result = Replace(result, vbTab, "\t") EscapeJSON = result End Function Function ExecuteParameterizedQuery(conn, strSQL, params) On Error Resume Next Dim cmd, i Set cmd = Server.CreateObject("ADODB.Command") cmd.ActiveConnection = conn cmd.CommandText = strSQL cmd.CommandType = 1 ' adCmdText ' Add parameters If IsArray(params) Then For i = 0 To UBound(params) If IsNull(params(i)) Then cmd.Parameters.Append cmd.CreateParameter("p" & i, 200, 1, 255, Null) ElseIf IsNumeric(params(i)) Then cmd.Parameters.Append cmd.CreateParameter("p" & i, 3, 1, , CLng(params(i))) Else cmd.Parameters.Append cmd.CreateParameter("p" & i, 200, 1, 255, CStr(params(i))) End If Next End If Set ExecuteParameterizedQuery = cmd.Execute End Function Sub LogToFile(message) On Error Resume Next Dim fso, logFile, logPath ' Create daily log files: api-2025-11-21.log Dim logFileName logFileName = "api-" & Year(Now()) & "-" & Right("0" & Month(Now()), 2) & "-" & Right("0" & Day(Now()), 2) & ".log" logPath = Server.MapPath("./logs/" & logFileName) Set fso = Server.CreateObject("Scripting.FileSystemObject") ' Create logs directory if it doesn't exist Dim logsDir logsDir = Server.MapPath("./logs") If Not fso.FolderExists(logsDir) Then fso.CreateFolder logsDir End If ' Append to log file Set logFile = fso.OpenTextFile(logPath, 8, True) ' 8 = ForAppending logFile.WriteLine Now() & " - " & message logFile.Close Set logFile = Nothing Set fso = Nothing End Sub ' ============================================================================ ' UPDATE WINRM STATUS ' Called when remote PowerShell script successfully connects to a PC ' ============================================================================ Sub UpdateWinRMStatus() On Error Resume Next Dim hostname, hasWinRM hostname = Trim(Request.Form("hostname") & "") hasWinRM = Trim(Request.Form("hasWinRM") & "") ' Also accept query string for GET requests If hostname = "" Then hostname = Trim(Request.QueryString("hostname") & "") If hasWinRM = "" Then hasWinRM = Trim(Request.QueryString("hasWinRM") & "") ' Validate If hostname = "" Then SendError "hostname is required" Exit Sub End If ' Default to enabled if not specified Dim winrmValue If hasWinRM = "0" Then winrmValue = 0 Else winrmValue = 1 End If ' Find PC by hostname Dim safeHostname, strSQL, rs safeHostname = Replace(hostname, "'", "''") strSQL = "SELECT machineid FROM machines WHERE hostname = '" & safeHostname & "' AND pctypeid IS NOT NULL" Set rs = objConn.Execute(strSQL) If rs.EOF Then rs.Close Set rs = Nothing SendError "PC not found: " & hostname Exit Sub End If Dim machineid machineid = rs("machineid") rs.Close Set rs = Nothing ' Update WinRM status strSQL = "UPDATE machines SET iswinrm = " & winrmValue & " WHERE machineid = " & machineid objConn.Execute strSQL If Err.Number <> 0 Then SendError "Update failed: " & Err.Description Exit Sub End If LogMessage "WinRM status updated for " & hostname & " (machineid=" & machineid & ") to " & winrmValue ' Send success response Response.ContentType = "application/json" Response.Write "{""success"":true,""message"":""WinRM status updated"",""hostname"":""" & hostname & """,""iswinrm"":" & winrmValue & "}" End Sub ' ============================================================================ ' UPDATE MACHINE POSITIONS - Bulk update mapleft/maptop for machines ' ============================================================================ Sub UpdateMachinePositions() On Error Resume Next Dim changesJson, changes, i, updateCount, errorCount changesJson = Request.Form("changes") If changesJson = "" Then SendError "Missing changes parameter" Exit Sub End If LogToFile "UpdateMachinePositions: Received " & Len(changesJson) & " bytes" ' Parse JSON array changes = ParseJSONArray(changesJson) If Not IsArray(changes) Then SendError "Invalid changes format" Exit Sub End If updateCount = 0 errorCount = 0 ' Update each machine position For i = 0 To UBound(changes) Dim machineId, newLeft, newTop, updateSQL machineId = GetJSONValue(changes(i), "id") newLeft = GetJSONValue(changes(i), "newLeft") newTop = GetJSONValue(changes(i), "newTop") If machineId <> "" And IsNumeric(machineId) And IsNumeric(newLeft) And IsNumeric(newTop) Then updateSQL = "UPDATE machines SET mapleft = " & CLng(newLeft) & ", maptop = " & CLng(newTop) & _ " WHERE machineid = " & CLng(machineId) objConn.Execute updateSQL If Err.Number = 0 Then updateCount = updateCount + 1 LogToFile " Updated machineid " & machineId & " to (" & newLeft & ", " & newTop & ")" Else errorCount = errorCount + 1 LogToFile " Error updating machineid " & machineId & ": " & Err.Description Err.Clear End If Else errorCount = errorCount + 1 LogToFile " Invalid data for change " & i End If Next LogToFile "UpdateMachinePositions: Updated " & updateCount & ", Errors " & errorCount ' Send response Response.ContentType = "application/json" If errorCount = 0 Then Response.Write "{""success"":true,""message"":""Updated " & updateCount & " position(s)"",""updated"":" & updateCount & "}" Else Response.Write "{""success"":true,""message"":""Updated " & updateCount & ", " & errorCount & " error(s)"",""updated"":" & updateCount & ",""errors"":" & errorCount & "}" End If End Sub %>