Add UDC Performance Dashboard and Tool Health features
- Add displayudc.asp with Dashboard tab containing: - Production Trend chart (daily parts) - OOT Rate Trend chart (daily OOT %) - Machine Utilization chart (top 10 by runtime hours) - Top Operators chart (top 10 by parts produced) - Add tabs for drill-down: Live Activity, Operators, Machines, Parts, Quality/OOT, Timing, Activity Log, Tool Health, Uptime, IT Diagnostics - Add Tool Health section to displaymachine.asp UDC tab: - Summary cards (tools monitored, measurements, OOT count) - Tool status table with health indicators - Recent OOT events display - Add UDC API endpoints in api.asp: - getUDCPartRuns, getUDCOperatorStats, getUDCMachineStats, getUDCManualTiming - Add sql/udctables.sql schema for UDC data storage - Update docs/API.md with UDC endpoint documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
360
api.asp
360
api.asp
@@ -49,10 +49,14 @@ Select Case action
|
|||||||
GetRecordedIP()
|
GetRecordedIP()
|
||||||
Case "updateMachinePositions"
|
Case "updateMachinePositions"
|
||||||
UpdateMachinePositions()
|
UpdateMachinePositions()
|
||||||
Case "logDNCEvent"
|
Case "getUDCPartRuns"
|
||||||
LogDNCEvent()
|
GetUDCPartRuns()
|
||||||
Case "getDNCStats"
|
Case "getUDCOperatorStats"
|
||||||
GetDNCStats()
|
GetUDCOperatorStats()
|
||||||
|
Case "getUDCMachineStats"
|
||||||
|
GetUDCMachineStats()
|
||||||
|
Case "getUDCManualTiming"
|
||||||
|
GetUDCManualTiming()
|
||||||
Case Else
|
Case Else
|
||||||
SendError "Invalid action: " & action
|
SendError "Invalid action: " & action
|
||||||
End Select
|
End Select
|
||||||
@@ -2546,99 +2550,47 @@ Sub UpdateMachinePositions()
|
|||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
' ============================================================================
|
' ============================================================================
|
||||||
' eDNC SPECIAL CHARACTER FIX - LOGGING
|
' UDC LOG DATA ENDPOINTS
|
||||||
' ============================================================================
|
' ============================================================================
|
||||||
|
|
||||||
Sub LogDNCEvent()
|
Sub GetUDCPartRuns()
|
||||||
On Error Resume Next
|
On Error Resume Next
|
||||||
|
|
||||||
' Get parameters
|
' Get optional filters
|
||||||
Dim hostname, filename, eventAction, bytesRemoved, version, message
|
Dim machinenumber, startdate, enddate, badgenumber
|
||||||
hostname = Trim(Request.Form("hostname") & "")
|
machinenumber = Trim(Request.QueryString("machinenumber") & "")
|
||||||
filename = Trim(Request.Form("filename") & "")
|
startdate = Trim(Request.QueryString("startdate") & "")
|
||||||
eventAction = Trim(Request.Form("eventType") & "")
|
enddate = Trim(Request.QueryString("enddate") & "")
|
||||||
bytesRemoved = Request.Form("bytesRemoved")
|
badgenumber = Trim(Request.QueryString("badgenumber") & "")
|
||||||
version = Trim(Request.Form("version") & "")
|
|
||||||
message = Trim(Request.Form("message") & "")
|
|
||||||
|
|
||||||
' Validate required fields
|
' Build query
|
||||||
If hostname = "" Or eventAction = "" Then
|
Dim sql, conditions
|
||||||
SendError "hostname and eventType are required"
|
sql = "SELECT p.partrunid, s.machinenumber, p.partnumber, p.opernumber, p.serialnumber, " & _
|
||||||
Exit Sub
|
"p.programname, p.jobnumber, p.badgenumber, p.programstart, p.programend, " & _
|
||||||
|
"p.cycletime, p.changeover, p.measurementcount, p.manualcount, p.probecount, p.ootcount " & _
|
||||||
|
"FROM udcparts p " & _
|
||||||
|
"JOIN udcsessions s ON p.sessionid = s.sessionid "
|
||||||
|
|
||||||
|
conditions = ""
|
||||||
|
If machinenumber <> "" Then
|
||||||
|
conditions = conditions & " AND s.machinenumber = '" & Replace(machinenumber, "'", "''") & "'"
|
||||||
|
End If
|
||||||
|
If startdate <> "" Then
|
||||||
|
conditions = conditions & " AND p.programstart >= '" & Replace(startdate, "'", "''") & "'"
|
||||||
|
End If
|
||||||
|
If enddate <> "" Then
|
||||||
|
conditions = conditions & " AND p.programstart <= '" & Replace(enddate, "'", "''") & " 23:59:59'"
|
||||||
|
End If
|
||||||
|
If badgenumber <> "" Then
|
||||||
|
conditions = conditions & " AND p.badgenumber = '" & Replace(badgenumber, "'", "''") & "'"
|
||||||
End If
|
End If
|
||||||
|
|
||||||
' Default bytesRemoved to 0 if not numeric
|
If conditions <> "" Then
|
||||||
If Not IsNumeric(bytesRemoved) Or bytesRemoved = "" Then bytesRemoved = 0
|
sql = sql & " WHERE 1=1 " & conditions
|
||||||
|
|
||||||
' Get machineid from hostname (required for logging)
|
|
||||||
Dim safeHostname, machineid, rsLookup
|
|
||||||
safeHostname = Replace(hostname, "'", "''")
|
|
||||||
Set rsLookup = objConn.Execute("SELECT machineid FROM machines WHERE UPPER(hostname) = UPPER('" & safeHostname & "') AND pctypeid IS NOT NULL LIMIT 1")
|
|
||||||
|
|
||||||
If rsLookup.EOF Then
|
|
||||||
rsLookup.Close
|
|
||||||
Set rsLookup = Nothing
|
|
||||||
SendError "Unknown hostname: " & hostname
|
|
||||||
Exit Sub
|
|
||||||
End If
|
End If
|
||||||
|
sql = sql & " ORDER BY p.programstart DESC LIMIT 1000"
|
||||||
|
|
||||||
machineid = CLng(rsLookup("machineid"))
|
Dim rs
|
||||||
rsLookup.Close
|
|
||||||
Set rsLookup = Nothing
|
|
||||||
|
|
||||||
' Sanitize remaining inputs
|
|
||||||
Dim safeFilename, safeAction, safeVersion, safeMessage
|
|
||||||
safeFilename = Replace(filename, "'", "''")
|
|
||||||
safeAction = Replace(eventAction, "'", "''")
|
|
||||||
safeVersion = Replace(version, "'", "''")
|
|
||||||
safeMessage = Replace(message, "'", "''")
|
|
||||||
|
|
||||||
' Insert log entry using machineid
|
|
||||||
Dim insertSQL
|
|
||||||
insertSQL = "INSERT INTO ednclogs (machineid, filename, action, bytes_removed, version, message) " & _
|
|
||||||
"VALUES (" & machineid & ", '" & safeFilename & "', '" & safeAction & "', " & _
|
|
||||||
CLng(bytesRemoved) & ", '" & safeVersion & "', '" & safeMessage & "')"
|
|
||||||
objConn.Execute insertSQL
|
|
||||||
|
|
||||||
If Err.Number <> 0 Then
|
|
||||||
SendError "Failed to log event: " & Err.Description
|
|
||||||
Exit Sub
|
|
||||||
End If
|
|
||||||
|
|
||||||
' Track in installedapps (appid 79 = eDNC Special Character Fix)
|
|
||||||
Dim edncAppId, rsApp
|
|
||||||
edncAppId = 79
|
|
||||||
|
|
||||||
' Check if already in installedapps
|
|
||||||
Set rsApp = objConn.Execute("SELECT installedappid FROM installedapps WHERE machineid = " & machineid & " AND appid = " & edncAppId)
|
|
||||||
If rsApp.EOF Then
|
|
||||||
' Insert new record
|
|
||||||
objConn.Execute "INSERT INTO installedapps (appid, machineid, isactive) VALUES (" & edncAppId & ", " & machineid & ", 1)"
|
|
||||||
End If
|
|
||||||
rsApp.Close
|
|
||||||
Set rsApp = Nothing
|
|
||||||
|
|
||||||
' Send success response
|
|
||||||
Response.Write "{""success"":true,""message"":""Event logged""}"
|
|
||||||
End Sub
|
|
||||||
|
|
||||||
Sub GetDNCStats()
|
|
||||||
On Error Resume Next
|
|
||||||
|
|
||||||
' Get stats derived from ednclogs, joined to machines for hostname
|
|
||||||
Dim sql, rs
|
|
||||||
sql = "SELECT m.hostname, " & _
|
|
||||||
"(SELECT version FROM ednclogs WHERE machineid = l.machineid ORDER BY created DESC LIMIT 1) AS version, " & _
|
|
||||||
"MIN(l.created) AS first_seen, " & _
|
|
||||||
"MAX(l.created) AS last_seen, " & _
|
|
||||||
"SUM(CASE WHEN l.action = 'cleaned' THEN 1 ELSE 0 END) AS total_cleaned, " & _
|
|
||||||
"SUM(CASE WHEN l.action = 'failed' THEN 1 ELSE 0 END) AS total_failed, " & _
|
|
||||||
"(SELECT COUNT(*) FROM ednclogs WHERE machineid = l.machineid AND created > DATE_SUB(NOW(), INTERVAL 24 HOUR)) AS events_24h " & _
|
|
||||||
"FROM ednclogs l " & _
|
|
||||||
"INNER JOIN machines m ON l.machineid = m.machineid " & _
|
|
||||||
"GROUP BY l.machineid, m.hostname " & _
|
|
||||||
"ORDER BY last_seen DESC"
|
|
||||||
|
|
||||||
Set rs = objConn.Execute(sql)
|
Set rs = objConn.Execute(sql)
|
||||||
|
|
||||||
If Err.Number <> 0 Then
|
If Err.Number <> 0 Then
|
||||||
@@ -2648,7 +2600,7 @@ Sub GetDNCStats()
|
|||||||
|
|
||||||
' Build JSON response
|
' Build JSON response
|
||||||
Dim json, first
|
Dim json, first
|
||||||
json = "{""success"":true,""installations"":["
|
json = "{""success"":true,""partruns"":["
|
||||||
first = True
|
first = True
|
||||||
|
|
||||||
Do While Not rs.EOF
|
Do While Not rs.EOF
|
||||||
@@ -2656,22 +2608,236 @@ Sub GetDNCStats()
|
|||||||
first = False
|
first = False
|
||||||
|
|
||||||
json = json & "{" & _
|
json = json & "{" & _
|
||||||
"""hostname"":""" & (rs("hostname") & "") & """," & _
|
"""partrunid"":" & CLng(rs("partrunid") & "0") & "," & _
|
||||||
"""version"":""" & (rs("version") & "") & """," & _
|
"""machinenumber"":""" & (rs("machinenumber") & "") & """," & _
|
||||||
"""firstSeen"":""" & (rs("first_seen") & "") & """," & _
|
"""partnumber"":""" & (rs("partnumber") & "") & """," & _
|
||||||
"""lastSeen"":""" & (rs("last_seen") & "") & """," & _
|
"""opernumber"":""" & (rs("opernumber") & "") & """," & _
|
||||||
"""totalCleaned"":" & (rs("total_cleaned") + 0) & "," & _
|
"""serialnumber"":""" & (rs("serialnumber") & "") & """," & _
|
||||||
"""totalFailed"":" & (rs("total_failed") + 0) & "," & _
|
"""programname"":""" & (rs("programname") & "") & """," & _
|
||||||
"""events24h"":" & (rs("events_24h") + 0) & _
|
"""jobnumber"":""" & (rs("jobnumber") & "") & """," & _
|
||||||
|
"""badgenumber"":""" & (rs("badgenumber") & "") & """," & _
|
||||||
|
"""programstart"":""" & (rs("programstart") & "") & """," & _
|
||||||
|
"""programend"":""" & (rs("programend") & "") & """," & _
|
||||||
|
"""cycletime"":" & CLng(rs("cycletime") & "0") & "," & _
|
||||||
|
"""changeover"":" & CLng(rs("changeover") & "0") & "," & _
|
||||||
|
"""measurementcount"":" & CLng(rs("measurementcount") & "0") & "," & _
|
||||||
|
"""manualcount"":" & CLng(rs("manualcount") & "0") & "," & _
|
||||||
|
"""probecount"":" & CLng(rs("probecount") & "0") & "," & _
|
||||||
|
"""ootcount"":" & CLng(rs("ootcount") & "0") & _
|
||||||
"}"
|
"}"
|
||||||
rs.MoveNext
|
rs.MoveNext
|
||||||
Loop
|
Loop
|
||||||
|
|
||||||
json = json & "]}"
|
json = json & "]}"
|
||||||
|
|
||||||
rs.Close
|
rs.Close
|
||||||
Set rs = Nothing
|
Set rs = Nothing
|
||||||
|
|
||||||
|
Response.ContentType = "application/json"
|
||||||
|
Response.Write json
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub GetUDCOperatorStats()
|
||||||
|
On Error Resume Next
|
||||||
|
|
||||||
|
Dim startdate, enddate
|
||||||
|
startdate = Trim(Request.QueryString("startdate") & "")
|
||||||
|
enddate = Trim(Request.QueryString("enddate") & "")
|
||||||
|
|
||||||
|
Dim sql, conditions
|
||||||
|
sql = "SELECT p.badgenumber, COUNT(*) AS partsrun, " & _
|
||||||
|
"AVG(p.cycletime) AS avgcycletime, AVG(p.changeover) AS avgchangeover, " & _
|
||||||
|
"SUM(p.measurementcount) AS totalmeasurements, SUM(p.manualcount) AS totalmanual, " & _
|
||||||
|
"SUM(p.ootcount) AS totaloot, MIN(p.programstart) AS firstrun, MAX(p.programend) AS lastrun, " & _
|
||||||
|
"(SELECT AVG(mr.responseseconds) FROM udcmanualrequests mr " & _
|
||||||
|
" JOIN udcparts p2 ON mr.partrunid = p2.partrunid WHERE p2.badgenumber = p.badgenumber) AS avgmanualtime " & _
|
||||||
|
"FROM udcparts p " & _
|
||||||
|
"WHERE p.badgenumber IS NOT NULL AND p.badgenumber != '' "
|
||||||
|
|
||||||
|
If startdate <> "" Then
|
||||||
|
sql = sql & " AND p.programstart >= '" & Replace(startdate, "'", "''") & "'"
|
||||||
|
End If
|
||||||
|
If enddate <> "" Then
|
||||||
|
sql = sql & " AND p.programstart <= '" & Replace(enddate, "'", "''") & " 23:59:59'"
|
||||||
|
End If
|
||||||
|
|
||||||
|
sql = sql & " GROUP BY p.badgenumber ORDER BY partsrun DESC"
|
||||||
|
|
||||||
|
Dim rs
|
||||||
|
Set rs = objConn.Execute(sql)
|
||||||
|
|
||||||
|
If Err.Number <> 0 Then
|
||||||
|
SendError "Database error: " & Err.Description
|
||||||
|
Exit Sub
|
||||||
|
End If
|
||||||
|
|
||||||
|
Dim json, first
|
||||||
|
Dim avgCycle, avgChange, avgManual
|
||||||
|
json = "{""success"":true,""operators"":["
|
||||||
|
first = True
|
||||||
|
|
||||||
|
Do While Not rs.EOF
|
||||||
|
If Not first Then json = json & ","
|
||||||
|
first = False
|
||||||
|
|
||||||
|
If IsNull(rs("avgcycletime")) Then avgCycle = 0 Else avgCycle = Round(CDbl(rs("avgcycletime")), 0)
|
||||||
|
If IsNull(rs("avgchangeover")) Then avgChange = 0 Else avgChange = Round(CDbl(rs("avgchangeover")), 0)
|
||||||
|
If IsNull(rs("avgmanualtime")) Then avgManual = 0 Else avgManual = Round(CDbl(rs("avgmanualtime")), 0)
|
||||||
|
|
||||||
|
json = json & "{" & _
|
||||||
|
"""badgenumber"":""" & (rs("badgenumber") & "") & """," & _
|
||||||
|
"""partsrun"":" & CLng(rs("partsrun") & "0") & "," & _
|
||||||
|
"""avgcycletime"":" & avgCycle & "," & _
|
||||||
|
"""avgchangeover"":" & avgChange & "," & _
|
||||||
|
"""avgmanualtime"":" & avgManual & "," & _
|
||||||
|
"""totalmeasurements"":" & CLng(rs("totalmeasurements") & "0") & "," & _
|
||||||
|
"""totalmanual"":" & CLng(rs("totalmanual") & "0") & "," & _
|
||||||
|
"""totaloot"":" & CLng(rs("totaloot") & "0") & "," & _
|
||||||
|
"""firstrun"":""" & (rs("firstrun") & "") & """," & _
|
||||||
|
"""lastrun"":""" & (rs("lastrun") & "") & """" & _
|
||||||
|
"}"
|
||||||
|
rs.MoveNext
|
||||||
|
Loop
|
||||||
|
|
||||||
|
json = json & "]}"
|
||||||
|
rs.Close
|
||||||
|
Set rs = Nothing
|
||||||
|
|
||||||
|
Response.ContentType = "application/json"
|
||||||
|
Response.Write json
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub GetUDCMachineStats()
|
||||||
|
On Error Resume Next
|
||||||
|
|
||||||
|
Dim startdate, enddate
|
||||||
|
startdate = Trim(Request.QueryString("startdate") & "")
|
||||||
|
enddate = Trim(Request.QueryString("enddate") & "")
|
||||||
|
|
||||||
|
Dim sql
|
||||||
|
sql = "SELECT s.machinenumber, COUNT(*) AS partsrun, " & _
|
||||||
|
"AVG(p.cycletime) AS avgcycletime, AVG(p.changeover) AS avgchangeover, " & _
|
||||||
|
"SUM(p.measurementcount) AS totalmeasurements, SUM(p.ootcount) AS totaloot, " & _
|
||||||
|
"MIN(p.programstart) AS firstrun, MAX(p.programend) AS lastrun " & _
|
||||||
|
"FROM udcparts p " & _
|
||||||
|
"JOIN udcsessions s ON p.sessionid = s.sessionid "
|
||||||
|
|
||||||
|
If startdate <> "" Or enddate <> "" Then
|
||||||
|
sql = sql & " WHERE 1=1 "
|
||||||
|
If startdate <> "" Then
|
||||||
|
sql = sql & " AND p.programstart >= '" & Replace(startdate, "'", "''") & "'"
|
||||||
|
End If
|
||||||
|
If enddate <> "" Then
|
||||||
|
sql = sql & " AND p.programstart <= '" & Replace(enddate, "'", "''") & " 23:59:59'"
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
|
sql = sql & " GROUP BY s.machinenumber ORDER BY partsrun DESC"
|
||||||
|
|
||||||
|
Dim rs
|
||||||
|
Set rs = objConn.Execute(sql)
|
||||||
|
|
||||||
|
If Err.Number <> 0 Then
|
||||||
|
SendError "Database error: " & Err.Description
|
||||||
|
Exit Sub
|
||||||
|
End If
|
||||||
|
|
||||||
|
Dim json, first
|
||||||
|
Dim avgCycle, avgChange
|
||||||
|
json = "{""success"":true,""machines"":["
|
||||||
|
first = True
|
||||||
|
|
||||||
|
Do While Not rs.EOF
|
||||||
|
If Not first Then json = json & ","
|
||||||
|
first = False
|
||||||
|
|
||||||
|
If IsNull(rs("avgcycletime")) Then avgCycle = 0 Else avgCycle = Round(CDbl(rs("avgcycletime")), 0)
|
||||||
|
If IsNull(rs("avgchangeover")) Then avgChange = 0 Else avgChange = Round(CDbl(rs("avgchangeover")), 0)
|
||||||
|
|
||||||
|
json = json & "{" & _
|
||||||
|
"""machinenumber"":""" & (rs("machinenumber") & "") & """," & _
|
||||||
|
"""partsrun"":" & CLng(rs("partsrun") & "0") & "," & _
|
||||||
|
"""avgcycletime"":" & avgCycle & "," & _
|
||||||
|
"""avgchangeover"":" & avgChange & "," & _
|
||||||
|
"""totalmeasurements"":" & CLng(rs("totalmeasurements") & "0") & "," & _
|
||||||
|
"""totaloot"":" & CLng(rs("totaloot") & "0") & "," & _
|
||||||
|
"""firstrun"":""" & (rs("firstrun") & "") & """," & _
|
||||||
|
"""lastrun"":""" & (rs("lastrun") & "") & """" & _
|
||||||
|
"}"
|
||||||
|
rs.MoveNext
|
||||||
|
Loop
|
||||||
|
|
||||||
|
json = json & "]}"
|
||||||
|
rs.Close
|
||||||
|
Set rs = Nothing
|
||||||
|
|
||||||
|
Response.ContentType = "application/json"
|
||||||
|
Response.Write json
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub GetUDCManualTiming()
|
||||||
|
On Error Resume Next
|
||||||
|
|
||||||
|
Dim machinenumber, startdate, enddate
|
||||||
|
machinenumber = Trim(Request.QueryString("machinenumber") & "")
|
||||||
|
startdate = Trim(Request.QueryString("startdate") & "")
|
||||||
|
enddate = Trim(Request.QueryString("enddate") & "")
|
||||||
|
|
||||||
|
Dim sql, conditions
|
||||||
|
sql = "SELECT mr.requestid, p.badgenumber, s.machinenumber, " & _
|
||||||
|
"mr.requesttime, mr.responsetime, mr.responseseconds, mr.description " & _
|
||||||
|
"FROM udcmanualrequests mr " & _
|
||||||
|
"JOIN udcparts p ON mr.partrunid = p.partrunid " & _
|
||||||
|
"JOIN udcsessions s ON p.sessionid = s.sessionid "
|
||||||
|
|
||||||
|
conditions = ""
|
||||||
|
If machinenumber <> "" Then
|
||||||
|
conditions = conditions & " AND s.machinenumber = '" & Replace(machinenumber, "'", "''") & "'"
|
||||||
|
End If
|
||||||
|
If startdate <> "" Then
|
||||||
|
conditions = conditions & " AND mr.requesttime >= '" & Replace(startdate, "'", "''") & "'"
|
||||||
|
End If
|
||||||
|
If enddate <> "" Then
|
||||||
|
conditions = conditions & " AND mr.requesttime <= '" & Replace(enddate, "'", "''") & " 23:59:59'"
|
||||||
|
End If
|
||||||
|
|
||||||
|
If conditions <> "" Then
|
||||||
|
sql = sql & " WHERE 1=1 " & conditions
|
||||||
|
End If
|
||||||
|
sql = sql & " ORDER BY mr.requesttime DESC LIMIT 1000"
|
||||||
|
|
||||||
|
Dim rs
|
||||||
|
Set rs = objConn.Execute(sql)
|
||||||
|
|
||||||
|
If Err.Number <> 0 Then
|
||||||
|
SendError "Database error: " & Err.Description
|
||||||
|
Exit Sub
|
||||||
|
End If
|
||||||
|
|
||||||
|
Dim json, first
|
||||||
|
json = "{""success"":true,""manualrequests"":["
|
||||||
|
first = True
|
||||||
|
|
||||||
|
Do While Not rs.EOF
|
||||||
|
If Not first Then json = json & ","
|
||||||
|
first = False
|
||||||
|
|
||||||
|
json = json & "{" & _
|
||||||
|
"""requestid"":" & CLng(rs("requestid") & "0") & "," & _
|
||||||
|
"""badgenumber"":""" & (rs("badgenumber") & "") & """," & _
|
||||||
|
"""machinenumber"":""" & (rs("machinenumber") & "") & """," & _
|
||||||
|
"""requesttime"":""" & (rs("requesttime") & "") & """," & _
|
||||||
|
"""responsetime"":""" & (rs("responsetime") & "") & """," & _
|
||||||
|
"""responseseconds"":" & CLng(rs("responseseconds") & "0") & "," & _
|
||||||
|
"""description"":""" & Replace(rs("description") & "", """", "\""") & """" & _
|
||||||
|
"}"
|
||||||
|
rs.MoveNext
|
||||||
|
Loop
|
||||||
|
|
||||||
|
json = json & "]}"
|
||||||
|
rs.Close
|
||||||
|
Set rs = Nothing
|
||||||
|
|
||||||
|
Response.ContentType = "application/json"
|
||||||
Response.Write json
|
Response.Write json
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,24 @@
|
|||||||
Response.Redirect("default.asp")
|
Response.Redirect("default.asp")
|
||||||
Response.End
|
Response.End
|
||||||
End If
|
End If
|
||||||
|
|
||||||
|
' Check if machine has UDC data (only for equipment with machinenumber)
|
||||||
|
Dim rsUDCCheck, hasUDCData, strSQL2, machineNum
|
||||||
|
hasUDCData = False
|
||||||
|
machineNum = rs("machinenumber") & ""
|
||||||
|
If machineNum <> "" Then
|
||||||
|
strSQL2 = "SELECT COUNT(*) as cnt FROM udcparts p " & _
|
||||||
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
||||||
|
"WHERE s.machinenumber = ?"
|
||||||
|
Set rsUDCCheck = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineNum))
|
||||||
|
If Not rsUDCCheck Is Nothing Then
|
||||||
|
If Not rsUDCCheck.EOF Then
|
||||||
|
If CLng(rsUDCCheck("cnt") & "0") > 0 Then hasUDCData = True
|
||||||
|
End If
|
||||||
|
rsUDCCheck.Close
|
||||||
|
Set rsUDCCheck = Nothing
|
||||||
|
End If
|
||||||
|
End If
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<body class="bg-theme <%=Server.HTMLEncode(theme)%>">
|
<body class="bg-theme <%=Server.HTMLEncode(theme)%>">
|
||||||
@@ -143,6 +161,12 @@
|
|||||||
<h5 class="card-text"><%=Server.HTMLEncode(rs("machinetype") & "")%></h5>
|
<h5 class="card-text"><%=Server.HTMLEncode(rs("machinetype") & "")%></h5>
|
||||||
<%' machinedescription column doesn't exist in Phase 2 schema %>
|
<%' machinedescription column doesn't exist in Phase 2 schema %>
|
||||||
<p class="card-text"><%=Server.HTMLEncode(rs("machinenotes") & "")%></p>
|
<p class="card-text"><%=Server.HTMLEncode(rs("machinenotes") & "")%></p>
|
||||||
|
<%
|
||||||
|
' Only show Print Badge for equipment (has machinenumber), not servers/network devices
|
||||||
|
If Trim(rs("machinenumber") & "") <> "" Then
|
||||||
|
%>
|
||||||
|
<a href="./printbadge.asp?machineid=<%=Server.HTMLEncode(machineid)%>" target="_blank" class="btn btn-primary btn-sm mt-3">Print Badge</a>
|
||||||
|
<% End If %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -168,6 +192,11 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="javascript:void();" data-target="#applications" data-toggle="pill" class="nav-link"><i class="zmdi zmdi-apps"></i> <span class="hidden-xs">Applications</span></a>
|
<a href="javascript:void();" data-target="#applications" data-toggle="pill" class="nav-link"><i class="zmdi zmdi-apps"></i> <span class="hidden-xs">Applications</span></a>
|
||||||
</li>
|
</li>
|
||||||
|
<% End If %>
|
||||||
|
<% If hasUDCData Then %>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="javascript:void();" data-target="#udc" data-toggle="pill" class="nav-link"><i class="zmdi zmdi-chart"></i> <span class="hidden-xs">UDC</span></a>
|
||||||
|
</li>
|
||||||
<% End If %>
|
<% End If %>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="./machineedit.asp?machineid=<%=Server.HTMLEncode(machineid)%>" class="nav-link" style="background: linear-gradient(45deg, #667eea 0%, #764ba2 100%); color: white;"><i class="zmdi zmdi-edit"></i> <span class="hidden-xs">Edit Machine</span></a>
|
<a href="./machineedit.asp?machineid=<%=Server.HTMLEncode(machineid)%>" class="nav-link" style="background: linear-gradient(45deg, #667eea 0%, #764ba2 100%); color: white;"><i class="zmdi zmdi-edit"></i> <span class="hidden-xs">Edit Machine</span></a>
|
||||||
@@ -408,6 +437,7 @@ End If
|
|||||||
<tr>
|
<tr>
|
||||||
<th>PC Hostname</th>
|
<th>PC Hostname</th>
|
||||||
<th>IP Address</th>
|
<th>IP Address</th>
|
||||||
|
<th>Location</th>
|
||||||
<th>Relationship</th>
|
<th>Relationship</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -416,7 +446,8 @@ End If
|
|||||||
' Query PCs that control this machine (directly or via dualpath)
|
' Query PCs that control this machine (directly or via dualpath)
|
||||||
' Check both directions - the PC is identified by pctypeid IS NOT NULL
|
' Check both directions - the PC is identified by pctypeid IS NOT NULL
|
||||||
' Use GROUP_CONCAT to combine multiple IPs into one row per PC
|
' Use GROUP_CONCAT to combine multiple IPs into one row per PC
|
||||||
strSQL2 = "SELECT m.machineid, m.machinenumber, m.hostname, GROUP_CONCAT(DISTINCT c.address ORDER BY c.address SEPARATOR ', ') as address, 'Controls' as relationshiptype " & _
|
strSQL2 = "SELECT m.machineid, m.machinenumber, m.hostname, " & _
|
||||||
|
"GROUP_CONCAT(DISTINCT c.address ORDER BY c.address SEPARATOR ', ') as address, 'Controls' as relationshiptype " & _
|
||||||
"FROM machinerelationships mr " & _
|
"FROM machinerelationships mr " & _
|
||||||
"JOIN machines m ON (mr.machineid = m.machineid OR mr.related_machineid = m.machineid) " & _
|
"JOIN machines m ON (mr.machineid = m.machineid OR mr.related_machineid = m.machineid) " & _
|
||||||
"LEFT JOIN communications c ON m.machineid = c.machineid AND c.comstypeid IN (1, 3) AND c.isactive = 1 " & _
|
"LEFT JOIN communications c ON m.machineid = c.machineid AND c.comstypeid IN (1, 3) AND c.isactive = 1 " & _
|
||||||
@@ -425,11 +456,11 @@ End If
|
|||||||
"GROUP BY m.machineid, m.machinenumber, m.hostname"
|
"GROUP BY m.machineid, m.machinenumber, m.hostname"
|
||||||
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid, machineid, machineid))
|
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid, machineid, machineid))
|
||||||
|
|
||||||
|
Dim pcHostname, pcIP, pcMachineID
|
||||||
If rs2.EOF Then
|
If rs2.EOF Then
|
||||||
Response.Write("<tr><td colspan='3' class='text-muted text-center'>No controlling PC assigned</td></tr>")
|
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No controlling PC assigned</td></tr>")
|
||||||
Else
|
Else
|
||||||
Do While Not rs2.EOF
|
Do While Not rs2.EOF
|
||||||
Dim pcHostname, pcIP, pcMachineID
|
|
||||||
pcHostname = rs2("hostname") & ""
|
pcHostname = rs2("hostname") & ""
|
||||||
pcIP = rs2("address") & ""
|
pcIP = rs2("address") & ""
|
||||||
pcMachineID = rs2("machineid")
|
pcMachineID = rs2("machineid")
|
||||||
@@ -440,6 +471,7 @@ End If
|
|||||||
Response.Write("<tr>")
|
Response.Write("<tr>")
|
||||||
Response.Write("<td><a href='./displaypc.asp?machineid=" & pcMachineID & "'>" & Server.HTMLEncode(pcHostname) & "</a></td>")
|
Response.Write("<td><a href='./displaypc.asp?machineid=" & pcMachineID & "'>" & Server.HTMLEncode(pcHostname) & "</a></td>")
|
||||||
Response.Write("<td>" & pcIP & "</td>")
|
Response.Write("<td>" & pcIP & "</td>")
|
||||||
|
Response.Write("<td class='text-center'><a href='#' class='location-link text-info' data-machineid='" & pcMachineID & "' data-name='" & Server.HTMLEncode(pcHostname) & "'><i class='zmdi zmdi-pin' style='font-size:1.2rem;'></i></a></td>")
|
||||||
Response.Write("<td><span class='badge badge-primary'>" & Server.HTMLEncode(rs2("relationshiptype") & "") & "</span></td>")
|
Response.Write("<td><span class='badge badge-primary'>" & Server.HTMLEncode(rs2("relationshiptype") & "") & "</span></td>")
|
||||||
Response.Write("</tr>")
|
Response.Write("</tr>")
|
||||||
rs2.MoveNext
|
rs2.MoveNext
|
||||||
@@ -787,6 +819,338 @@ End If
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<% End If %>
|
||||||
|
<% If hasUDCData Then %>
|
||||||
|
<div class="tab-pane" id="udc">
|
||||||
|
<h5 class="mb-3">UDC Performance Data</h5>
|
||||||
|
|
||||||
|
<!-- Today's Stats Summary Cards -->
|
||||||
|
<div class="row mb-4">
|
||||||
|
<%
|
||||||
|
' Get today's UDC stats for this machine
|
||||||
|
Dim rsUDCToday, todayParts, todayOOT, todayAvgCycle, todayLastBadge
|
||||||
|
strSQL2 = "SELECT COUNT(*) as partstoday, " & _
|
||||||
|
"SUM(ootcount) as oottoday, " & _
|
||||||
|
"AVG(cycletime) as avgcycle, " & _
|
||||||
|
"(SELECT badgenumber FROM udcparts p2 JOIN udcsessions s2 ON p2.sessionid = s2.sessionid " & _
|
||||||
|
" WHERE s2.machinenumber = ? ORDER BY p2.programend DESC LIMIT 1) as lastbadge " & _
|
||||||
|
"FROM udcparts p " & _
|
||||||
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
||||||
|
"WHERE s.machinenumber = ? AND DATE(p.programstart) = CURDATE()"
|
||||||
|
Set rsUDCToday = ExecuteParameterizedQuery(objConn, strSQL2, Array(rs("machinenumber") & "", rs("machinenumber") & ""))
|
||||||
|
If Not rsUDCToday.EOF Then
|
||||||
|
todayParts = CLng(rsUDCToday("partstoday") & "0")
|
||||||
|
todayOOT = CLng(rsUDCToday("oottoday") & "0")
|
||||||
|
If Not IsNull(rsUDCToday("avgcycle")) Then
|
||||||
|
todayAvgCycle = FormatNumber(CDbl(rsUDCToday("avgcycle")) / 60, 1)
|
||||||
|
Else
|
||||||
|
todayAvgCycle = "0"
|
||||||
|
End If
|
||||||
|
todayLastBadge = rsUDCToday("lastbadge") & ""
|
||||||
|
Else
|
||||||
|
todayParts = 0
|
||||||
|
todayOOT = 0
|
||||||
|
todayAvgCycle = "0"
|
||||||
|
todayLastBadge = ""
|
||||||
|
End If
|
||||||
|
rsUDCToday.Close
|
||||||
|
Set rsUDCToday = Nothing
|
||||||
|
%>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card bg-success text-white">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<h3 class="mb-0"><%=todayParts%></h3>
|
||||||
|
<small>Parts Today</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card bg-info text-white">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<h3 class="mb-0"><%=todayAvgCycle%>m</h3>
|
||||||
|
<small>Avg Cycle Time</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card <% If todayOOT > 0 Then Response.Write("bg-danger") Else Response.Write("bg-secondary") End If %> text-white">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<h3 class="mb-0"><%=todayOOT%></h3>
|
||||||
|
<small>OOT Today</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card bg-primary text-white">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<h3 class="mb-0"><%If todayLastBadge <> "" Then Response.Write(Server.HTMLEncode(todayLastBadge)) Else Response.Write("-")%></h3>
|
||||||
|
<small>Current Operator</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Recent Activity Log -->
|
||||||
|
<h6 class="mb-2"><i class="zmdi zmdi-time-restore"></i> Recent Activity</h6>
|
||||||
|
<div class="table-responsive mb-4">
|
||||||
|
<table class="table table-hover table-striped table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Time</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Badge</th>
|
||||||
|
<th>Details</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<%
|
||||||
|
' Get recent activity (violations + badge changes) for this machine
|
||||||
|
Dim rsActivity, actBadge
|
||||||
|
strSQL2 = "SELECT * FROM (" & _
|
||||||
|
"SELECT eventtime, 'Violation' as acttype, badgenumber, " & _
|
||||||
|
"CONCAT(crossingdesc, ': ', previousval, ' -> ', currentval) as details " & _
|
||||||
|
"FROM udcviolations WHERE machinenumber = ? " & _
|
||||||
|
"UNION ALL " & _
|
||||||
|
"SELECT eventtime, 'Badge Change' as acttype, badgenumber, details " & _
|
||||||
|
"FROM udcheaderupdates WHERE machinenumber = ? " & _
|
||||||
|
") combined ORDER BY eventtime DESC LIMIT 15"
|
||||||
|
Set rsActivity = ExecuteParameterizedQuery(objConn, strSQL2, Array(rs("machinenumber") & "", rs("machinenumber") & ""))
|
||||||
|
If rsActivity.EOF Then
|
||||||
|
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No recent activity</td></tr>")
|
||||||
|
Else
|
||||||
|
Do While Not rsActivity.EOF
|
||||||
|
If rsActivity("acttype") = "Violation" Then
|
||||||
|
actBadge = "<span class='badge badge-light'>Setting Change</span>"
|
||||||
|
Else
|
||||||
|
actBadge = "<span class='badge badge-info'>Badge</span>"
|
||||||
|
End If
|
||||||
|
|
||||||
|
Response.Write("<tr>")
|
||||||
|
Response.Write("<td class='small'>" & Server.HTMLEncode(rsActivity("eventtime") & "") & "</td>")
|
||||||
|
Response.Write("<td>" & actBadge & "</td>")
|
||||||
|
Response.Write("<td>" & Server.HTMLEncode(rsActivity("badgenumber") & "") & "</td>")
|
||||||
|
Response.Write("<td class='small'>" & Server.HTMLEncode(rsActivity("details") & "") & "</td>")
|
||||||
|
Response.Write("</tr>")
|
||||||
|
rsActivity.MoveNext
|
||||||
|
Loop
|
||||||
|
End If
|
||||||
|
rsActivity.Close
|
||||||
|
Set rsActivity = Nothing
|
||||||
|
%>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tool Health Section -->
|
||||||
|
<h6 class="mb-2 mt-4"><i class="zmdi zmdi-settings"></i> Tool Health</h6>
|
||||||
|
<%
|
||||||
|
' Get tool health summary for this machine (last 30 days)
|
||||||
|
Dim rsToolSummary, toolCount, toolMeasurements, toolOOT, toolLastCheck
|
||||||
|
strSQL2 = "SELECT COUNT(DISTINCT t.toolnumber) as unique_tools, " & _
|
||||||
|
"COUNT(*) as total_measurements, " & _
|
||||||
|
"SUM(t.oot) as oot_count, " & _
|
||||||
|
"MAX(t.eventtime) as last_check " & _
|
||||||
|
"FROM udctooldata t " & _
|
||||||
|
"JOIN udcsessions s ON t.sessionid = s.sessionid " & _
|
||||||
|
"WHERE s.machinenumber = ? AND t.eventtime >= DATE_SUB(NOW(), INTERVAL 30 DAY)"
|
||||||
|
Set rsToolSummary = ExecuteParameterizedQuery(objConn, strSQL2, Array(rs("machinenumber") & ""))
|
||||||
|
If Not rsToolSummary.EOF Then
|
||||||
|
toolCount = CLng(rsToolSummary("unique_tools") & "0")
|
||||||
|
toolMeasurements = CLng(rsToolSummary("total_measurements") & "0")
|
||||||
|
toolOOT = CLng(rsToolSummary("oot_count") & "0")
|
||||||
|
toolLastCheck = rsToolSummary("last_check") & ""
|
||||||
|
Else
|
||||||
|
toolCount = 0
|
||||||
|
toolMeasurements = 0
|
||||||
|
toolOOT = 0
|
||||||
|
toolLastCheck = ""
|
||||||
|
End If
|
||||||
|
rsToolSummary.Close
|
||||||
|
Set rsToolSummary = Nothing
|
||||||
|
|
||||||
|
If toolMeasurements > 0 Then
|
||||||
|
%>
|
||||||
|
<!-- Tool Health Summary Cards -->
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card bg-secondary text-white">
|
||||||
|
<div class="card-body text-center py-2">
|
||||||
|
<h4 class="mb-0"><%=toolCount%></h4>
|
||||||
|
<small>Tools Monitored</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card bg-info text-white">
|
||||||
|
<div class="card-body text-center py-2">
|
||||||
|
<h4 class="mb-0"><%=toolMeasurements%></h4>
|
||||||
|
<small>Measurements (30d)</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card <% If toolOOT > 0 Then Response.Write("bg-danger") Else Response.Write("bg-success") End If %> text-white">
|
||||||
|
<div class="card-body text-center py-2">
|
||||||
|
<h4 class="mb-0"><%=toolOOT%></h4>
|
||||||
|
<small>Out of Tolerance</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card bg-primary text-white">
|
||||||
|
<div class="card-body text-center py-2">
|
||||||
|
<h6 class="mb-0"><%If toolLastCheck <> "" Then Response.Write(Server.HTMLEncode(Left(toolLastCheck, 16))) Else Response.Write("-")%></h6>
|
||||||
|
<small>Last Tool Check</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tool Status Table -->
|
||||||
|
<div class="table-responsive mb-3">
|
||||||
|
<table class="table table-hover table-striped table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Tool #</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Checks</th>
|
||||||
|
<th>Avg Dev</th>
|
||||||
|
<th>Max Dev</th>
|
||||||
|
<th>Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<%
|
||||||
|
' Get tool status by tool number
|
||||||
|
Dim rsTools, toolStatus, toolStatusClass, toolAvgDev, toolMaxDev, toolDevPct
|
||||||
|
strSQL2 = "SELECT t.toolnumber, " & _
|
||||||
|
"MAX(t.description) as description, " & _
|
||||||
|
"COUNT(*) as measurements, " & _
|
||||||
|
"ROUND(AVG(t.deviation), 4) as avg_deviation, " & _
|
||||||
|
"ROUND(MAX(ABS(t.deviation)), 4) as max_deviation, " & _
|
||||||
|
"MAX(ABS(t.minval)) as tolerance_ref, " & _
|
||||||
|
"SUM(t.oot) as oot_count " & _
|
||||||
|
"FROM udctooldata t " & _
|
||||||
|
"JOIN udcsessions s ON t.sessionid = s.sessionid " & _
|
||||||
|
"WHERE s.machinenumber = ? AND t.eventtime >= DATE_SUB(NOW(), INTERVAL 30 DAY) " & _
|
||||||
|
"GROUP BY t.toolnumber " & _
|
||||||
|
"ORDER BY oot_count DESC, measurements DESC " & _
|
||||||
|
"LIMIT 10"
|
||||||
|
Set rsTools = ExecuteParameterizedQuery(objConn, strSQL2, Array(rs("machinenumber") & ""))
|
||||||
|
If rsTools.EOF Then
|
||||||
|
Response.Write("<tr><td colspan='6' class='text-muted text-center'>No tool data available</td></tr>")
|
||||||
|
Else
|
||||||
|
Do While Not rsTools.EOF
|
||||||
|
' Calculate status based on OOT and deviation
|
||||||
|
If CLng(rsTools("oot_count") & "0") > 0 Then
|
||||||
|
toolStatus = "<i class='zmdi zmdi-alert-circle'></i> <strong>OOT</strong>"
|
||||||
|
toolStatusClass = "bg-danger text-white"
|
||||||
|
Else
|
||||||
|
toolStatus = "<i class='zmdi zmdi-check-circle text-success'></i> OK"
|
||||||
|
toolStatusClass = ""
|
||||||
|
End If
|
||||||
|
|
||||||
|
If Not IsNull(rsTools("avg_deviation")) Then
|
||||||
|
toolAvgDev = FormatNumber(CDbl(rsTools("avg_deviation")), 4)
|
||||||
|
Else
|
||||||
|
toolAvgDev = "-"
|
||||||
|
End If
|
||||||
|
If Not IsNull(rsTools("max_deviation")) Then
|
||||||
|
toolMaxDev = FormatNumber(CDbl(rsTools("max_deviation")), 4)
|
||||||
|
Else
|
||||||
|
toolMaxDev = "-"
|
||||||
|
End If
|
||||||
|
|
||||||
|
Response.Write("<tr class='" & toolStatusClass & "'>")
|
||||||
|
Response.Write("<td><strong>" & Server.HTMLEncode(rsTools("toolnumber") & "") & "</strong></td>")
|
||||||
|
Response.Write("<td class='small'>" & Server.HTMLEncode(Left(rsTools("description") & "", 30)) & "</td>")
|
||||||
|
Response.Write("<td>" & rsTools("measurements") & "</td>")
|
||||||
|
Response.Write("<td>" & toolAvgDev & "</td>")
|
||||||
|
Response.Write("<td>" & toolMaxDev & "</td>")
|
||||||
|
Response.Write("<td>" & toolStatus & "</td>")
|
||||||
|
Response.Write("</tr>")
|
||||||
|
rsTools.MoveNext
|
||||||
|
Loop
|
||||||
|
End If
|
||||||
|
rsTools.Close
|
||||||
|
Set rsTools = Nothing
|
||||||
|
%>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<%
|
||||||
|
' Check for recent OOT events
|
||||||
|
Dim rsOOT, ootEventCount
|
||||||
|
strSQL2 = "SELECT COUNT(*) as cnt FROM udctooldata t " & _
|
||||||
|
"JOIN udcsessions s ON t.sessionid = s.sessionid " & _
|
||||||
|
"WHERE s.machinenumber = ? AND t.oot = 1 AND t.eventtime >= DATE_SUB(NOW(), INTERVAL 7 DAY)"
|
||||||
|
Set rsOOT = ExecuteParameterizedQuery(objConn, strSQL2, Array(rs("machinenumber") & ""))
|
||||||
|
ootEventCount = 0
|
||||||
|
If Not rsOOT.EOF Then ootEventCount = CLng(rsOOT("cnt") & "0")
|
||||||
|
rsOOT.Close
|
||||||
|
Set rsOOT = Nothing
|
||||||
|
|
||||||
|
If ootEventCount > 0 Then
|
||||||
|
%>
|
||||||
|
<!-- Recent OOT Events -->
|
||||||
|
<h6 class="mb-2"><i class="zmdi zmdi-alert-triangle text-warning"></i> Recent Out-of-Tolerance Events (7 days)</h6>
|
||||||
|
<div class="table-responsive mb-3">
|
||||||
|
<table class="table table-hover table-sm">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th>Time</th>
|
||||||
|
<th>Tool #</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Actual</th>
|
||||||
|
<th>Min/Max</th>
|
||||||
|
<th>Deviation</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<%
|
||||||
|
Dim rsOOTEvents
|
||||||
|
strSQL2 = "SELECT t.eventtime, t.toolnumber, t.description, " & _
|
||||||
|
"t.actualval, t.minval, t.maxval, t.deviation " & _
|
||||||
|
"FROM udctooldata t " & _
|
||||||
|
"JOIN udcsessions s ON t.sessionid = s.sessionid " & _
|
||||||
|
"WHERE s.machinenumber = ? AND t.oot = 1 AND t.eventtime >= DATE_SUB(NOW(), INTERVAL 7 DAY) " & _
|
||||||
|
"ORDER BY t.eventtime DESC LIMIT 10"
|
||||||
|
Set rsOOTEvents = ExecuteParameterizedQuery(objConn, strSQL2, Array(rs("machinenumber") & ""))
|
||||||
|
Do While Not rsOOTEvents.EOF
|
||||||
|
Response.Write("<tr class='bg-warning'>")
|
||||||
|
Response.Write("<td class='small'>" & Server.HTMLEncode(rsOOTEvents("eventtime") & "") & "</td>")
|
||||||
|
Response.Write("<td><strong>" & Server.HTMLEncode(rsOOTEvents("toolnumber") & "") & "</strong></td>")
|
||||||
|
Response.Write("<td class='small'>" & Server.HTMLEncode(Left(rsOOTEvents("description") & "", 25)) & "</td>")
|
||||||
|
Response.Write("<td>" & FormatNumber(CDbl(rsOOTEvents("actualval") & "0"), 4) & "</td>")
|
||||||
|
Response.Write("<td class='small'>" & FormatNumber(CDbl(rsOOTEvents("minval") & "0"), 4) & " / " & FormatNumber(CDbl(rsOOTEvents("maxval") & "0"), 4) & "</td>")
|
||||||
|
Response.Write("<td class='text-danger'><strong>" & FormatNumber(CDbl(rsOOTEvents("deviation") & "0"), 4) & "</strong></td>")
|
||||||
|
Response.Write("</tr>")
|
||||||
|
rsOOTEvents.MoveNext
|
||||||
|
Loop
|
||||||
|
rsOOTEvents.Close
|
||||||
|
Set rsOOTEvents = Nothing
|
||||||
|
%>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<%
|
||||||
|
End If ' ootEventCount > 0
|
||||||
|
Else ' toolMeasurements = 0
|
||||||
|
%>
|
||||||
|
<div class="alert alert-secondary">
|
||||||
|
<i class="zmdi zmdi-info-outline"></i> No tool measurement data available for this machine.
|
||||||
|
</div>
|
||||||
|
<%
|
||||||
|
End If ' toolMeasurements > 0
|
||||||
|
%>
|
||||||
|
|
||||||
|
<!-- Link to Full Dashboard -->
|
||||||
|
<div class="text-center">
|
||||||
|
<a href="./displayudc.asp?machine=<%=Server.URLEncode(rs("machinenumber") & "")%>" class="btn btn-primary">
|
||||||
|
<i class="zmdi zmdi-chart"></i> View Full UDC Dashboard
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<% End If %>
|
<% End If %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1024,7 +1388,7 @@ End If
|
|||||||
$('.location-link').on('mouseenter', function(e) {
|
$('.location-link').on('mouseenter', function(e) {
|
||||||
var $link = $(this);
|
var $link = $(this);
|
||||||
var machineId = $link.data('machineid');
|
var machineId = $link.data('machineid');
|
||||||
var locationName = $link.text().trim();
|
var locationName = $link.data('name') || $link.text().trim();
|
||||||
var mouseEvent = e;
|
var mouseEvent = e;
|
||||||
|
|
||||||
if (hoverTimer) {
|
if (hoverTimer) {
|
||||||
@@ -1043,6 +1407,15 @@ End If
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Also handle click for location links (useful for touch devices)
|
||||||
|
$('.location-link').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var $link = $(this);
|
||||||
|
var machineId = $link.data('machineid');
|
||||||
|
var locationName = $link.data('name') || $link.text().trim();
|
||||||
|
showLocationPopup(machineId, locationName, e);
|
||||||
|
});
|
||||||
|
|
||||||
$popup.on('mouseenter', function() {});
|
$popup.on('mouseenter', function() {});
|
||||||
$popup.on('mouseleave', function() {
|
$popup.on('mouseleave', function() {
|
||||||
hideLocationPopup();
|
hideLocationPopup();
|
||||||
|
|||||||
2173
displayudc.asp
Normal file
2173
displayudc.asp
Normal file
File diff suppressed because it is too large
Load Diff
189
docs/API.md
189
docs/API.md
@@ -906,6 +906,191 @@ Monitor these metrics:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## UDC Log Data Endpoints
|
||||||
|
|
||||||
|
These endpoints provide access to parsed UDC (Universal Data Collector) log data for management reporting.
|
||||||
|
|
||||||
|
### 5. `getUDCPartRuns`
|
||||||
|
|
||||||
|
**Purpose:** Get part run data with cycle times and measurement counts
|
||||||
|
|
||||||
|
**Method:** GET
|
||||||
|
|
||||||
|
**Parameters (all optional):**
|
||||||
|
- `machinenumber` - Filter by machine number (e.g., "3110")
|
||||||
|
- `startdate` - Start date filter (YYYY-MM-DD)
|
||||||
|
- `enddate` - End date filter (YYYY-MM-DD)
|
||||||
|
- `badgenumber` - Filter by operator badge
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"partruns": [
|
||||||
|
{
|
||||||
|
"partrunid": 123,
|
||||||
|
"machinenumber": "3110",
|
||||||
|
"partnumber": "4096525-725G01",
|
||||||
|
"opernumber": "00602",
|
||||||
|
"serialnumber": "FGB0T7LH",
|
||||||
|
"programname": "03100042",
|
||||||
|
"jobnumber": "8J2R4",
|
||||||
|
"badgenumber": "020620BZ",
|
||||||
|
"programstart": "11/19/2025 10:02:53 AM",
|
||||||
|
"programend": "11/20/2025 2:05:16 AM",
|
||||||
|
"cycletime": 57743,
|
||||||
|
"changeover": 720,
|
||||||
|
"measurementcount": 205,
|
||||||
|
"manualcount": 25,
|
||||||
|
"probecount": 180,
|
||||||
|
"ootcount": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```bash
|
||||||
|
curl "http://server/api.asp?action=getUDCPartRuns&machinenumber=3110&startdate=2025-11-01"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6. `getUDCOperatorStats`
|
||||||
|
|
||||||
|
**Purpose:** Get aggregated operator statistics including average cycle times and manual response times
|
||||||
|
|
||||||
|
**Method:** GET
|
||||||
|
|
||||||
|
**Parameters (all optional):**
|
||||||
|
- `startdate` - Start date filter (YYYY-MM-DD)
|
||||||
|
- `enddate` - End date filter (YYYY-MM-DD)
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"operators": [
|
||||||
|
{
|
||||||
|
"badgenumber": "020620BZ",
|
||||||
|
"partsrun": 156,
|
||||||
|
"avgcycletime": 19347,
|
||||||
|
"avgchangeover": 5000,
|
||||||
|
"avgmanualtime": 245,
|
||||||
|
"totalmeasurements": 27920,
|
||||||
|
"totalmanual": 3500,
|
||||||
|
"totaloot": 10,
|
||||||
|
"firstrun": "11/1/2025 9:15:51 AM",
|
||||||
|
"lastrun": "12/10/2025 6:54:28 AM"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```bash
|
||||||
|
curl "http://server/api.asp?action=getUDCOperatorStats&startdate=2025-11-01&enddate=2025-12-31"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7. `getUDCMachineStats`
|
||||||
|
|
||||||
|
**Purpose:** Get aggregated machine statistics including parts produced and OOT rates
|
||||||
|
|
||||||
|
**Method:** GET
|
||||||
|
|
||||||
|
**Parameters (all optional):**
|
||||||
|
- `startdate` - Start date filter (YYYY-MM-DD)
|
||||||
|
- `enddate` - End date filter (YYYY-MM-DD)
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"machines": [
|
||||||
|
{
|
||||||
|
"machinenumber": "4003",
|
||||||
|
"partsrun": 156,
|
||||||
|
"avgcycletime": 19347,
|
||||||
|
"avgchangeover": 5000,
|
||||||
|
"totalmeasurements": 27920,
|
||||||
|
"totaloot": 10,
|
||||||
|
"firstrun": "5/4/2025 9:15:51 AM",
|
||||||
|
"lastrun": "6/17/2025 6:54:28 AM"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```bash
|
||||||
|
curl "http://server/api.asp?action=getUDCMachineStats"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 8. `getUDCManualTiming`
|
||||||
|
|
||||||
|
**Purpose:** Get manual data entry response times (time from request prompt to operator entry)
|
||||||
|
|
||||||
|
**Method:** GET
|
||||||
|
|
||||||
|
**Parameters (all optional):**
|
||||||
|
- `machinenumber` - Filter by machine number
|
||||||
|
- `startdate` - Start date filter (YYYY-MM-DD)
|
||||||
|
- `enddate` - End date filter (YYYY-MM-DD)
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"manualrequests": [
|
||||||
|
{
|
||||||
|
"requestid": 123,
|
||||||
|
"badgenumber": "020620BZ",
|
||||||
|
"machinenumber": "3110",
|
||||||
|
"requesttime": "11/19/2025 10:00:27 AM",
|
||||||
|
"responsetime": "11/19/2025 10:05:31 AM",
|
||||||
|
"responseseconds": 304,
|
||||||
|
"description": "GAGE CUT STG4 BLADE DROP"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```bash
|
||||||
|
curl "http://server/api.asp?action=getUDCManualTiming&machinenumber=3110"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## UDC Data Import
|
||||||
|
|
||||||
|
UDC log files are imported using the Python parser at `/home/camp/projects/UDC/parser/udcparser.py`.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
# Import all log files from default directory
|
||||||
|
python3 udcparser.py
|
||||||
|
|
||||||
|
# Import specific file
|
||||||
|
python3 udcparser.py --file /path/to/UDC_Log_3110.log
|
||||||
|
|
||||||
|
# Specify custom directory
|
||||||
|
python3 udcparser.py --dir /path/to/logs
|
||||||
|
```
|
||||||
|
|
||||||
|
**Database Tables:**
|
||||||
|
- `udcsessions` - Log file sessions
|
||||||
|
- `udcparts` - Part runs with cycle times
|
||||||
|
- `udcmeasurements` - Individual measurements (PROCESSDATA, TOOLDATA)
|
||||||
|
- `udcevents` - Item crossings, messages
|
||||||
|
- `udcmanualrequests` - Manual data entry timing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Future Enhancements
|
## Future Enhancements
|
||||||
|
|
||||||
### Planned Features:
|
### Planned Features:
|
||||||
@@ -926,7 +1111,7 @@ Monitor these metrics:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Version:** 1.1
|
**Version:** 1.2
|
||||||
**Last Updated:** 2025-12-11
|
**Last Updated:** 2025-12-12
|
||||||
**Maintained By:** ShopDB Development Team
|
**Maintained By:** ShopDB Development Team
|
||||||
**Support:** Review `/logs/api.log` for troubleshooting
|
**Support:** Review `/logs/api.log` for troubleshooting
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<%
|
<%
|
||||||
' Calculate fiscal week (GE fiscal year starts first Monday of January)
|
' Calculate fiscal week (GE fiscal year starts first Monday of January)
|
||||||
Dim fwToday, fwYearStart, fwFirstMonday, fwDayOfWeek, fwDaysFromStart, fiscalWeek
|
Dim fwToday, fwYearStart, fwFirstMonday, fwDayOfWeek, fwDaysFromStart, fiscalWeek
|
||||||
|
Dim fwPrevYearStart, fwPrevFirstMonday, fwPrevDayOfWeek
|
||||||
fwToday = Date()
|
fwToday = Date()
|
||||||
|
|
||||||
' Find first Monday of current year
|
' Find first Monday of current year
|
||||||
@@ -14,7 +15,6 @@ End If
|
|||||||
|
|
||||||
' If we're before the first Monday, use previous year's week count
|
' If we're before the first Monday, use previous year's week count
|
||||||
If fwToday < fwFirstMonday Then
|
If fwToday < fwFirstMonday Then
|
||||||
Dim fwPrevYearStart, fwPrevFirstMonday, fwPrevDayOfWeek
|
|
||||||
fwPrevYearStart = DateSerial(Year(fwToday) - 1, 1, 1)
|
fwPrevYearStart = DateSerial(Year(fwToday) - 1, 1, 1)
|
||||||
fwPrevDayOfWeek = Weekday(fwPrevYearStart, vbMonday)
|
fwPrevDayOfWeek = Weekday(fwPrevYearStart, vbMonday)
|
||||||
If fwPrevDayOfWeek = 1 Then
|
If fwPrevDayOfWeek = 1 Then
|
||||||
@@ -82,7 +82,11 @@ End If
|
|||||||
<i class="zmdi zmdi-collection-image text-yellow"></i><span>Reports</span>
|
<i class="zmdi zmdi-collection-image text-yellow"></i><span>Reports</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="./displayudc.asp">
|
||||||
|
<i class="zmdi zmdi-chart text-info"></i><span>UDC Reports</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="sidebar-header">Admin</li>
|
<li class="sidebar-header">Admin</li>
|
||||||
<li><a href="./displaysubnets.asp"><i class="zmdi zmdi-network text-danger"></i><span>Network</span></a></li>
|
<li><a href="./displaysubnets.asp"><i class="zmdi zmdi-network text-danger"></i><span>Network</span></a></li>
|
||||||
|
|||||||
292
sql/udctables.sql
Normal file
292
sql/udctables.sql
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
-- ============================================================================
|
||||||
|
-- UDC Log Parser Database Schema
|
||||||
|
-- Stores parsed data from UDC (Universal Data Collector) log files
|
||||||
|
-- Created: 2025-12-12
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- Sessions table - tracks each log file imported
|
||||||
|
CREATE TABLE IF NOT EXISTS udcsessions (
|
||||||
|
sessionid INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
machineid INT,
|
||||||
|
machinenumber VARCHAR(20),
|
||||||
|
logfilename VARCHAR(255) NOT NULL,
|
||||||
|
sessionstart DATETIME,
|
||||||
|
sessionend DATETIME,
|
||||||
|
recordcount INT DEFAULT 0,
|
||||||
|
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
INDEX idx_machineid (machineid),
|
||||||
|
INDEX idx_machinenumber (machinenumber),
|
||||||
|
INDEX idx_sessionstart (sessionstart),
|
||||||
|
UNIQUE INDEX idx_logfilename (logfilename(191))
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- Parts table - tracks each part run (serial number cycle)
|
||||||
|
CREATE TABLE IF NOT EXISTS udcparts (
|
||||||
|
partrunid INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
sessionid INT NOT NULL,
|
||||||
|
machineid INT,
|
||||||
|
partnumber VARCHAR(50),
|
||||||
|
opernumber VARCHAR(20),
|
||||||
|
serialnumber VARCHAR(50),
|
||||||
|
programname VARCHAR(50),
|
||||||
|
jobnumber VARCHAR(50),
|
||||||
|
badgenumber VARCHAR(20),
|
||||||
|
programstart DATETIME,
|
||||||
|
programend DATETIME,
|
||||||
|
cycletime INT,
|
||||||
|
changeover INT,
|
||||||
|
measurementcount INT DEFAULT 0,
|
||||||
|
manualcount INT DEFAULT 0,
|
||||||
|
probecount INT DEFAULT 0,
|
||||||
|
ootcount INT DEFAULT 0,
|
||||||
|
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
INDEX idx_sessionid (sessionid),
|
||||||
|
INDEX idx_machineid (machineid),
|
||||||
|
INDEX idx_serialnumber (serialnumber),
|
||||||
|
INDEX idx_partnumber (partnumber),
|
||||||
|
INDEX idx_jobnumber (jobnumber),
|
||||||
|
INDEX idx_badgenumber (badgenumber),
|
||||||
|
INDEX idx_programstart (programstart),
|
||||||
|
CONSTRAINT fk_udcparts_session FOREIGN KEY (sessionid) REFERENCES udcsessions(sessionid) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- Measurements table - all PROCESSDATA, TOOLDATA, MACHINEDATA entries
|
||||||
|
CREATE TABLE IF NOT EXISTS udcmeasurements (
|
||||||
|
measurementid INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
partrunid INT,
|
||||||
|
sessionid INT NOT NULL,
|
||||||
|
eventtime DATETIME,
|
||||||
|
eventtype VARCHAR(20),
|
||||||
|
method VARCHAR(20),
|
||||||
|
dimid VARCHAR(20),
|
||||||
|
description VARCHAR(255),
|
||||||
|
seqnumber INT,
|
||||||
|
minval DECIMAL(12,6),
|
||||||
|
maxval DECIMAL(12,6),
|
||||||
|
actualval DECIMAL(12,6),
|
||||||
|
deviation DECIMAL(12,6),
|
||||||
|
oot TINYINT DEFAULT 0,
|
||||||
|
INDEX idx_partrunid (partrunid),
|
||||||
|
INDEX idx_sessionid (sessionid),
|
||||||
|
INDEX idx_eventtime (eventtime),
|
||||||
|
INDEX idx_method (method),
|
||||||
|
INDEX idx_oot (oot),
|
||||||
|
CONSTRAINT fk_udcmeasurements_partrun FOREIGN KEY (partrunid) REFERENCES udcparts(partrunid) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_udcmeasurements_session FOREIGN KEY (sessionid) REFERENCES udcsessions(sessionid) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- Events table - item crossings, messages, manual requests
|
||||||
|
CREATE TABLE IF NOT EXISTS udcevents (
|
||||||
|
eventid INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
partrunid INT,
|
||||||
|
sessionid INT NOT NULL,
|
||||||
|
eventtime DATETIME,
|
||||||
|
eventtype VARCHAR(30),
|
||||||
|
itemnumber VARCHAR(20),
|
||||||
|
description TEXT,
|
||||||
|
INDEX idx_partrunid (partrunid),
|
||||||
|
INDEX idx_sessionid (sessionid),
|
||||||
|
INDEX idx_eventtime (eventtime),
|
||||||
|
INDEX idx_eventtype (eventtype),
|
||||||
|
CONSTRAINT fk_udcevents_partrun FOREIGN KEY (partrunid) REFERENCES udcparts(partrunid) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_udcevents_session FOREIGN KEY (sessionid) REFERENCES udcsessions(sessionid) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- Manual requests table - tracks timing of manual data entry
|
||||||
|
CREATE TABLE IF NOT EXISTS udcmanualrequests (
|
||||||
|
requestid INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
partrunid INT,
|
||||||
|
measurementid INT,
|
||||||
|
requesttime DATETIME,
|
||||||
|
responsetime DATETIME,
|
||||||
|
responseseconds INT,
|
||||||
|
description VARCHAR(255),
|
||||||
|
INDEX idx_partrunid (partrunid),
|
||||||
|
INDEX idx_requesttime (requesttime),
|
||||||
|
INDEX idx_responseseconds (responseseconds),
|
||||||
|
CONSTRAINT fk_udcmanualrequests_partrun FOREIGN KEY (partrunid) REFERENCES udcparts(partrunid) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_udcmanualrequests_measurement FOREIGN KEY (measurementid) REFERENCES udcmeasurements(measurementid) ON DELETE SET NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- Tool data table - TOOLDATA entries (tool offsets, wear, corner radius)
|
||||||
|
CREATE TABLE IF NOT EXISTS udctooldata (
|
||||||
|
tooldataid INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
partrunid INT,
|
||||||
|
sessionid INT NOT NULL,
|
||||||
|
eventtime DATETIME,
|
||||||
|
method VARCHAR(20),
|
||||||
|
dimid VARCHAR(20),
|
||||||
|
description VARCHAR(255),
|
||||||
|
toolnumber INT,
|
||||||
|
minval DECIMAL(12,6),
|
||||||
|
maxval DECIMAL(12,6),
|
||||||
|
actualval DECIMAL(12,6),
|
||||||
|
deviation DECIMAL(12,6),
|
||||||
|
oot TINYINT DEFAULT 0,
|
||||||
|
INDEX idx_partrunid (partrunid),
|
||||||
|
INDEX idx_sessionid (sessionid),
|
||||||
|
INDEX idx_eventtime (eventtime),
|
||||||
|
INDEX idx_toolnumber (toolnumber),
|
||||||
|
INDEX idx_oot (oot),
|
||||||
|
CONSTRAINT fk_udctooldata_partrun FOREIGN KEY (partrunid) REFERENCES udcparts(partrunid) ON DELETE SET NULL,
|
||||||
|
CONSTRAINT fk_udctooldata_session FOREIGN KEY (sessionid) REFERENCES udcsessions(sessionid) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- Errors table - error events from UDC logs
|
||||||
|
CREATE TABLE IF NOT EXISTS udcerrors (
|
||||||
|
errorid INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
sessionid INT,
|
||||||
|
machinenumber VARCHAR(20),
|
||||||
|
eventtime DATETIME,
|
||||||
|
errortype VARCHAR(100),
|
||||||
|
errormessage TEXT,
|
||||||
|
sourcemethod VARCHAR(255),
|
||||||
|
INDEX idx_sessionid (sessionid),
|
||||||
|
INDEX idx_machinenumber (machinenumber),
|
||||||
|
INDEX idx_eventtime (eventtime),
|
||||||
|
INDEX idx_errortype (errortype)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- Connections table - serial/network connection events
|
||||||
|
CREATE TABLE IF NOT EXISTS udcconnections (
|
||||||
|
connectionid INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
sessionid INT,
|
||||||
|
machinenumber VARCHAR(20),
|
||||||
|
eventtime DATETIME,
|
||||||
|
eventtype VARCHAR(20),
|
||||||
|
comport VARCHAR(20),
|
||||||
|
details VARCHAR(255),
|
||||||
|
INDEX idx_sessionid (sessionid),
|
||||||
|
INDEX idx_machinenumber (machinenumber),
|
||||||
|
INDEX idx_eventtime (eventtime),
|
||||||
|
INDEX idx_eventtype (eventtype)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- Active sessions table - tracks currently running machines
|
||||||
|
CREATE TABLE IF NOT EXISTS udcactivesessions (
|
||||||
|
activeid INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
machinenumber VARCHAR(20) NOT NULL,
|
||||||
|
sessionid INT,
|
||||||
|
partnumber VARCHAR(50),
|
||||||
|
badgenumber VARCHAR(20),
|
||||||
|
partsrun INT DEFAULT 0,
|
||||||
|
sessionstart DATETIME,
|
||||||
|
lastupdate DATETIME,
|
||||||
|
UNIQUE INDEX idx_machinenumber (machinenumber),
|
||||||
|
INDEX idx_sessionid (sessionid),
|
||||||
|
INDEX idx_lastupdate (lastupdate)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- Header updates table - badge changes during part runs
|
||||||
|
CREATE TABLE IF NOT EXISTS udcheaderupdates (
|
||||||
|
updateid INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
partrunid INT,
|
||||||
|
sessionid INT,
|
||||||
|
machinenumber VARCHAR(20),
|
||||||
|
eventtime DATETIME,
|
||||||
|
details VARCHAR(255),
|
||||||
|
description VARCHAR(255),
|
||||||
|
badgenumber VARCHAR(20),
|
||||||
|
INDEX idx_partrunid (partrunid),
|
||||||
|
INDEX idx_sessionid (sessionid),
|
||||||
|
INDEX idx_machinenumber (machinenumber),
|
||||||
|
INDEX idx_eventtime (eventtime)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- Violations table - item crossing value changes
|
||||||
|
CREATE TABLE IF NOT EXISTS udcviolations (
|
||||||
|
violationid INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
partrunid INT,
|
||||||
|
sessionid INT,
|
||||||
|
machinenumber VARCHAR(20),
|
||||||
|
eventtime DATETIME,
|
||||||
|
previousval DECIMAL(12,4),
|
||||||
|
currentval DECIMAL(12,4),
|
||||||
|
badgenumber VARCHAR(20),
|
||||||
|
itemno VARCHAR(20),
|
||||||
|
crossingdesc VARCHAR(255),
|
||||||
|
INDEX idx_partrunid (partrunid),
|
||||||
|
INDEX idx_sessionid (sessionid),
|
||||||
|
INDEX idx_machinenumber (machinenumber),
|
||||||
|
INDEX idx_eventtime (eventtime)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- Useful Views for Reporting
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- Part runs with machine info
|
||||||
|
CREATE OR REPLACE VIEW vwudcpartruns AS
|
||||||
|
SELECT
|
||||||
|
p.partrunid,
|
||||||
|
p.sessionid,
|
||||||
|
p.machineid,
|
||||||
|
s.machinenumber,
|
||||||
|
p.partnumber,
|
||||||
|
p.opernumber,
|
||||||
|
p.serialnumber,
|
||||||
|
p.programname,
|
||||||
|
p.jobnumber,
|
||||||
|
p.badgenumber,
|
||||||
|
p.programstart,
|
||||||
|
p.programend,
|
||||||
|
p.cycletime,
|
||||||
|
p.changeover,
|
||||||
|
p.measurementcount,
|
||||||
|
p.manualcount,
|
||||||
|
p.probecount,
|
||||||
|
p.ootcount
|
||||||
|
FROM udcparts p
|
||||||
|
JOIN udcsessions s ON p.sessionid = s.sessionid;
|
||||||
|
|
||||||
|
-- Operator stats aggregation
|
||||||
|
CREATE OR REPLACE VIEW vwudcoperatorstats AS
|
||||||
|
SELECT
|
||||||
|
badgenumber,
|
||||||
|
COUNT(*) AS partsrun,
|
||||||
|
AVG(cycletime) AS avgcycletime,
|
||||||
|
AVG(changeover) AS avgchangeover,
|
||||||
|
SUM(measurementcount) AS totalmeasurements,
|
||||||
|
SUM(manualcount) AS totalmanual,
|
||||||
|
SUM(ootcount) AS totaloot,
|
||||||
|
MIN(programstart) AS firstrun,
|
||||||
|
MAX(programend) AS lastrun
|
||||||
|
FROM udcparts
|
||||||
|
WHERE badgenumber IS NOT NULL AND badgenumber != ''
|
||||||
|
GROUP BY badgenumber;
|
||||||
|
|
||||||
|
-- Machine stats aggregation
|
||||||
|
CREATE OR REPLACE VIEW vwudcmachinestats AS
|
||||||
|
SELECT
|
||||||
|
s.machinenumber,
|
||||||
|
p.machineid,
|
||||||
|
COUNT(*) AS partsrun,
|
||||||
|
AVG(p.cycletime) AS avgcycletime,
|
||||||
|
AVG(p.changeover) AS avgchangeover,
|
||||||
|
SUM(p.measurementcount) AS totalmeasurements,
|
||||||
|
SUM(p.ootcount) AS totaloot,
|
||||||
|
MIN(p.programstart) AS firstrun,
|
||||||
|
MAX(p.programend) AS lastrun
|
||||||
|
FROM udcparts p
|
||||||
|
JOIN udcsessions s ON p.sessionid = s.sessionid
|
||||||
|
GROUP BY s.machinenumber, p.machineid;
|
||||||
|
|
||||||
|
-- Manual request response times
|
||||||
|
CREATE OR REPLACE VIEW vwudcmanualtiming AS
|
||||||
|
SELECT
|
||||||
|
r.requestid,
|
||||||
|
p.badgenumber,
|
||||||
|
s.machinenumber,
|
||||||
|
r.requesttime,
|
||||||
|
r.responsetime,
|
||||||
|
r.responseseconds,
|
||||||
|
r.description
|
||||||
|
FROM udcmanualrequests r
|
||||||
|
JOIN udcparts p ON r.partrunid = p.partrunid
|
||||||
|
JOIN udcsessions s ON p.sessionid = s.sessionid;
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- Verify
|
||||||
|
-- ============================================================================
|
||||||
|
SELECT 'UDC tables created successfully' AS status;
|
||||||
|
SHOW TABLES LIKE 'udc%';
|
||||||
Reference in New Issue
Block a user