open-insight/LSL2/STPROC/WAFER_COUNTER_SERVICES.txt
2024-10-31 14:22:20 -07:00

408 lines
17 KiB
Plaintext

Function Wafer_Counter_Services(@Service, @Params)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Wafer_Counter_Services
Description : Handler program for all module related services.
Notes : The generic parameters should contain all the necessary information to process the services. Often
this will be information like the data Record and Key ID.
Parameters :
Service [in] -- Name of the service being requested
Param1-10 [in/out] -- Additional request parameter holders
Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure
Metadata :
History : (Date, Initials, Notes)
09/26/23 djs Adapted from FlatFinder_Services.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$Insert LOGICAL
$Insert SERVICE_SETUP
$Insert RDS_EQUATES
$Insert WO_LOG_EQUATES
$Insert WM_OUT_EQUATES
$Insert RLIST_EQUATES
$Insert WAFER_COUNTER_EQUATES
Equ Tab$ to \09\
Equ CRLF$ to \0D0A\
Equ LF$ to \0A\
Equ Comma$ to ','
* Reduce Modes
Equ new_exist$ To 0
Equ next_cur$ To 1
Equ add_exist$ to 2
Declare subroutine Error_Services, Database_Services, Logging_Services, Httpclient_Services, Reduce, SRP_JSON
Declare function Database_Services, Environment_Services, Logging_Services, Httpclient_Services
Declare function RTI_CreateGuid, SRP_JSON
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\WaferCounter'
LogDate = Oconv(Date(), 'D4/')
LogTime = Oconv(Time(), 'MTS')
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Wafer Counter Import Log.csv'
Headers = 'Logging DTM':@FM:'ToolID':@FM:'Operation':@FM:'Datetime':@FM:'LotID':@FM:'CassNo':@FM:'Wafer Count':@FM:'Import Result'
objLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$)
LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM
GoToService else
Error_Services('Set', Service : ' is not a valid service request within the ' : ServiceModule : ' services module.')
end
Return Response else ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
Options WAFER_SIZES = '6INCH', '8INCH'
Options LOCATIONS = 'MU', 'QA', 'EPR-EAST', 'EPR-WEST'
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// ImportWaferCounterFiles
//
// Looks for available wafer counter CSV files that are ready to be imported into the RDS table.
//----------------------------------------------------------------------------------------------------------------------
Service ImportWaferCounterFiles()
hSysLists = Database_Services('GetTableHandle', 'SYSLISTS')
Lock hSysLists, ServiceKeyID then
DataPath = Environment_Services('GetApplicationRootPath') : '\WaferCounter\'
BackupPath = Environment_Services('GetApplicationRootPath') : '\WaferCounter\BackupFiles\'
InitDir DataPath : '*.csv'
FileList = DirList()
For Each File in FileList using @FM
OSRead WaferCounterData from DataPath : File then
BackupDate = Oconv(Date(), 'D4/')
BackupTime = Oconv(Time(), 'MTS')
Convert ':' to '-' in BackupTime
BackupFileName = BackupDate[7, 4] : '-' : BackupDate[1, 2] : '-' : BackupDate[4, 2] : '-' : BackupTime : ' ' : File
If Count(File, '-') LE 1 then
OSWrite WaferCounterData to BackupPath : BackupFileName
end
Swap CRLF$ with '' in WaferCounterData
Swap ',' with @FM in WaferCounterData
ToolID = Trim(WaferCounterData<2>)
Operation = Trim(WaferCounterData<3>)
Datetime = IConv(Trim(WaferCounterData<4>), 'DT')
ReferenceKeyID = Trim(WaferCounterData<5>)
CassetteNo = Trim(WaferCounterData<6>)
WaferCount = Trim(WaferCounterData<7>)
Result = False$
LogData = LoggingDTM
LogData<2> = ToolID
LogData<3> = Operation
LogData<4> = Trim(WaferCounterData<4>)
LogData<5> = ReferenceKeyID
LogData<6> = CassetteNo
LogData<7> = WaferCount
If ReferenceKeyID[1, 2] EQ '1T' or ReferenceKeyID[1, 1] EQ 'O' then
Convert 'O' to '' in ReferenceKeyID
Swap '1T' with '' in ReferenceKeyID
If Index(ReferenceKeyID, '.', 1) then
// A dot means this is a WorkOrderNo.Cassette value. Need to create a WM_OUT Key ID.
WorkOrderNo = ReferenceKeyID[1, '.']
WOStepKeyID = ReferenceKeyID[Col2() + 1, '.']
CassetteNo = ReferenceKeyID[Col2() + 1, '.']
WMOutKeyID = WorkOrderNo : '*' : WOStepKeyID : '*' : CassetteNo
WMOutRow = Database_Services('ReadDataRow', 'WM_OUT', WMOutKeyID)
If Error_Services('NoError') then
WMOutRow<WM_OUT_WAFER_COUNTER_DTM$> = DateTime
WMOutRow<WM_OUT_WAFER_COUNTER_QTY$> = WaferCount
Database_Services('WriteDataRow', 'WM_OUT', WMOutKeyID, WMOutRow, True$, False$, True$)
end
end else
// No dot in the reference key means this is an RDS Key ID.
Transfer ReferenceKeyID to RDSKeyID
If Num(RDSKeyID) then RDSKeyID = RDSKeyID + 0
RDSRow = Database_Services('ReadDataRow', 'RDS', RDSKeyID)
If Error_Services('NoError') then
RDSRow<RDS_WAFER_COUNTER_DTM$> = DateTime
RDSRow<RDS_WAFER_COUNTER_QTY$> = WaferCount
Database_Services('WriteDataRow', 'RDS', RDSKeyID, RDSRow, True$, False$, True$)
end
end
If Error_Services('NoError') then
Result = 'Success'
end else
Result = 'Failure: ':Error_Services('GetMessage')
end
end else
// Throw error - either invalid barcode scanned or user manually entered data
Result = 'Failure: ReferenceKeyID "':ReferenceKeyID:'" is invalid.'
end
LogData<8> = Result
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
OSDelete DataPath : File
end
Next File
Unlock hSysLists, ServiceKeyID else Null
end
end service
Service ConvertWaferData(FileData)
ErrorMsg = ''
WaferArray = ''
If FileData NE '' then
Swap CRLF$ with @FM in FileData
WaferTotal = FileData<1>
WaferData = FileData<2>
If ( (Len(WaferTotal) EQ 3) and (WaferTotal[1, 1] EQ 'T') and (Len(WaferData) EQ 8 ) and (WaferData[1, 1] EQ 'P') ) then
Convert 'T' to '' in WaferTotal
WaferArray = ''
For CharIndex = 2 to 8
Val = IConv(WaferData[CharIndex, 1], 'MX')
Val = OConv(Val, 'MB')
If CharIndex GT 2 then Val = Fmt(Val, 'R(0)#4')
WaferArray := Val
Next CharIndex
If (Len(WaferArray) NE 25) then
ErrorMsg = 'Error in ':Service:' service. Invalid wafer array length.'
end else
// Reverse the array so it is in order from slot 1 to 25
WaferArray = WaferArray[-1, -25]
// Return @VM delimited array for ease of use in OI BASIC+
DelimArray = ''
For CharIndex = 1 to 25
DelimArray<0, CharIndex> = WaferArray[CharIndex, 1]
Next CharIndex
If (Sum(DelimArray) EQ WaferTotal) then
Response = DelimArray
end else
ErrorMsg = 'Error in ':Service:' service. Wafer total does not match array total.'
end
end
end else
ErrorMsg = 'Error in ':Service:' service. Invalid data format passed in FileData variable.'
end
end else
ErrorMsg = 'Error in ':Service:' service. Null FileData passed into service.'
end
If ErrorMsg NE '' then
Error_Services('Add', ErrorMsg)
end
end service
Service GetWaferCounterJSON(WaferSize, ToolLocation, CassID)
If ( (WaferSize NE '') and (ToolLocation NE '') and (CassID NE '') ) then
URL = 'https://oi-metrology-viewer-prod.mes.infineon.com:4438/api/v1/WaferCounter/{waferSize}/last-quantity-and-slot-map/?area={area}&text={cassID}'
Swap '{waferSize}' with WaferSize in URL
Swap '{area}' with ToolLocation in URL
Swap '{cassID}' with CassID in URL
// Set timeout to 24 seconds. This value was decided upon with Mike Phares to allow time
// for EAF to receive the new wafer counter file from the tool and serve it up.
Httpclient_Services('SetTimeoutDuration', 24)
Response = Httpclient_Services('SendHTTPRequest', 'GET', URL, '', '', '', '', False$, False$, '')
If Error_Services('NoError') then
StatusCode = Httpclient_Services('GetResponseStatusCode')
If StatusCode NE 200 then
Begin Case
Case Response EQ ''
ErrorMsg = 'Unexpected server error.'
Case Response EQ 'No files!'
ErrorMsg = 'No data. Please re-seat cassette and try again.'
Case Otherwise$
// Use message in response body to populate error services
ErrorMsg = Response
End Case
Error_Services('Add', ErrorMsg)
end
end
end
end service
Service AddScan(LotID, ScanQty, ScanDtm, ScanTool, ScanUser, ScanLocation, WaferMap)
KeyID = RTI_CreateGuid()
Record = ''
Record<WAFER_COUNTER.LOT_ID$> = LotID
Record<WAFER_COUNTER.SCAN_QTY$> = ScanQty
If Not(Num(ScanDtm)) then
ScanYear = ScanDtm[1, 'F-']
ScanMonth = ScanDtm[Col2() + 1, 'F-']
ScanDay = ScanDtm[Col2() + 1, 'F ']
ScanTime = ScanDtm[Col2() + 1, 999]
Convert ' ' to '' in ScanTime
ScanDtm = ScanMonth:'/':ScanDay:'/':ScanYear:' ':ScanTime
ScanDtm = IConv(ScanDtm, 'DT')
end
Record<WAFER_COUNTER.SCAN_DTM$> = ScanDtm
Record<WAFER_COUNTER.SCAN_TOOL$> = ScanTool
Record<WAFER_COUNTER.SCAN_USER$> = ScanUser
If ScanLocation EQ 'FQA' then ScanLocation = 'QA'
Record<WAFER_COUNTER.SCAN_LOCATION$> = ScanLocation
Record<WAFER_COUNTER.SCAN_WAFER_MAP$> = WaferMap
Database_Services('WriteDataRow', 'WAFER_COUNTER', KeyID, Record)
end service
Service GetLastScan(LotID, ScanLocation=LOCATIONS)
ErrorMsg = ''
WCRec = ''
If LotID NE '' then
Tablename = "WAFER_COUNTER"
Flag = ""
Done = False$
CursorVar = ""
GoSub ClearCursors
SortList = "#SCAN_DTM"
ReduceScript = 'WITH {LOT_ID} EQ ':Quote(LotID)
If ScanLocation NE '' then
ReduceScript := ' AND WITH {SCAN_LOCATION} EQ ':Quote(ScanLocation)
end
Mode = NEXT_CUR$
Reduce(ReduceScript, SortList, Mode, Tablename, Cursorvar, Flag)
If Flag then
Select Tablename By SortList Using Cursorvar then
Open Tablename To hTable then
KeyID = ''
Loop
ReadNext KeyID Using Cursorvar By AT Else Done = TRUE$
If KeyID NE '' then
Done = True$
Read WCRec from hTable, KeyID then
WCRec<WAFER_COUNTER.SCAN_DTM$> = OConv(WCRec<WAFER_COUNTER.SCAN_DTM$>, 'DT/^2H')
end else
ErrorMsg = 'Error in ':Service:' service. Error reading ':KeyID:' from ':Tablename:' table.'
end
end
Until Done or (KeyID NE '')
Repeat
End Else
ErrorMsg = 'Error in ':Service:' service. Error in opening ':Tablename:'.'
End
End Else
ErrorMsg = 'Error in ':Service:' service. Error in selecting ':Tablename:'.'
end
End Else
ErrorMsg = 'Error in ':Service:' service. Error in Reduce call.'
End
end else
ErrorMsg = 'Error in ':Service:' service. Null LotID passed into service.'
end
If ErrorMsg NE '' then
Error_Services('Add', ErrorMsg)
end
Response = WCRec
end service
Service GetProdWaferCounter(WaferSize=WAFER_SIZES, Location=LOCATIONS)
ToolID = ''
ErrorMsg = ''
If ( (WaferSize NE '') and (Location NE '') ) then
Query = "SELECT TOOL WITH @ID CONTAINING 'WC":WaferSize:"' AND WITH TOOL_LOC EQ '":Location:"' AND WITH CURR_MODE EQ 'PROD'"
GoSub ClearCursors
RList(Query, TARGET_ACTIVELIST$, '', '', '')
ErrCode = ''
If Not(Get_Status(ErrCode)) then
Begin Case
Case @RecCount EQ 0
ErrorMsg = 'Error in ':Service:' service. No production wafer counter found!'
Case @RecCount EQ 1
ReadNext ToolID else
ErrorMsg = 'Error in ':Service:' service. Error reading production wafer counter tool ID!'
end
Case @RecCount GT 1
ErrorMsg = 'Error in ':Service:' service. More than one production wafer counter found!'
End Case
GoSub ClearCursors
end else
ErrorMsg = 'Error in ':Service:' service. Error calling RList. Error code: ':ErrCode:'.'
end
end else
ErrorMsg = 'Error in ':Service:' service. Null WaferSize or Location passed into service.'
end
If ErrorMsg NE '' then
Error_Services('Add', ErrorMsg)
end
Response = ToolID
end service
Service GetWaferCounterToolID(WaferSize=WAFER_SIZES, Location=LOCATIONS)
ToolID = ''
ErrorMsg = ''
If ( (WaferSize NE '') and (Location NE '') ) then
Query = "SELECT TOOL WITH @ID CONTAINING 'WC":WaferSize:"' AND WITH TOOL_LOC EQ '":Location:"'"
GoSub ClearCursors
RList(Query, TARGET_ACTIVELIST$, '', '', '')
ErrCode = ''
If Not(Get_Status(ErrCode)) then
Begin Case
Case @RecCount EQ 0
ErrorMsg = 'Error in ':Service:' service. No wafer counter tool found for ':WaferSize:' ':Location:'.'
Case @RecCount EQ 1
ReadNext ToolID else
ErrorMsg = 'Error in ':Service:' service. Error reading wafer counter tool ID!'
end
Case @RecCount GT 1
ErrorMsg = 'Error in ':Service:' service. More than one wafer counter tool found for ':WaferSize:' ':Location:'.'
End Case
GoSub ClearCursors
end else
ErrorMsg = 'Error in ':Service:' service. Error calling RList. Error code: ':ErrCode:'.'
end
end else
ErrorMsg = 'Error in ':Service:' service. Null WaferSize or Location passed into service.'
end
If ErrorMsg NE '' then
Error_Services('Add', ErrorMsg)
end
Response = ToolID
end service
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ClearCursors:
For counter = 0 to 8
ClearSelect counter
Next counter
return