Tutorial Code Snippets and Assets
- Snippet 1: Classroom Code Snippet
- Snippet 2: Classroom Code Snippet
- Snippet 3: Classroom Code Snippet
- Snippet 4 - mesutils
- Script Snippet 5 | params: prodRecipeName, newRecipeName, itemPath, state
- Script Snippet 6: Scheduling Operations
- Script Snippet 7: Creating OEE Objects Via Script
- XML Report Export
- Create Machine Recipe Set Points on a Line
|
This page is to be used by the instructor to paste in completed code snippets for students to copy/paste into their projects, to help catch up or avoid extensive debugging during class time. |
Snippet 1: Classroom Code Snippet
Python |
def getLotTraceResultsDataset(lotNumber): def getLotTraceResults(lotNumber, traceDict): import system ds = system.dataset.toPyDataSet(system.mes.getLotTraceByLotName(lotNumber, "", 100, True)) for row in ds: lotUse = row["LotUse"] lotName = row["LotName"] lotUUID = row["LotUUID"] segUUID = row["SegmentUUID"] traceData = [lotName, lotNumber, row["LotStatus"], lotUse, row["LotBeginDateTime"], row["LotEndDateTime"], row["LotQuantity"], row["MaterialName"], row["LotLocationName"], row["SegmentUUID"], row["SegmentName"], row["SegmentLocationName"]] if segUUID not in traceDict.keys(): traceDict.update({segUUID:{lotUUID:traceData}}) if lotUse == 'In': traceDict = getLotTraceResults(lotName, traceDict) else: if lotUUID not in traceDict[segUUID].keys(): traceDict[segUUID][lotUUID] = traceData if lotUse == 'In': traceDict = getLotTraceResults(lotName, traceDict) return traceDict traceHeader = ["LotName", "ParentLotName", "LotStatus", "LotUse", "LotBeginDateTime", "LotEndDateTime", "LotQuantity", "MaterialName", "LotLocationName", "SegmentUUID", "SegmentName", "SegmentLocationName"] traceDict = getLotTraceResults(lotNumber, {}) traceData = [] for key in traceDict: for lotUUID in traceDict[key]: traceData.append(traceDict[key][lotUUID]) ds = system.dataset.toDataSet(traceHeader, traceData) return system.dataset.sort(ds, "LotEndDateTime", False, True) |
Snippet 2: Classroom Code Snippet
Python |
##Example of tag change script to check a new product code coming from the PLC, and create it if necessary. ##Necessary protection of the current production run and the existance of the "unknown pc's" class need to be added for prod system. pc = 'Turkey Bacon' eqPath = 'New Enterprise\Site\Area\Line 1' matList = system.mes.oee.getEquipmentAvailableMaterial(eqPath, pc) print matList if pc in matList: print 'hooray, just start the run' ##FIRST CHECK IF ANYTHING IS RUNNING, ETC. seg = system.mes.oee.beginOEERun(pc, eqPath) else: print 'check to see if the pc exists' ##getMaterialItems requires knowing the Equipment Class. ##system.mes.oee.getMaterialItems() filter = system.mes.object.filter.createFilter() filter.setMESObjectTypeName('MaterialDef') filter.setMESObjectNamePattern(pc) result = system.mes.searchMESObjects(filter) matExists = False for item in result: if item.getName() == pc: matExists = True break if not matExists: obj = system.mes.createMESObject('MaterialDef') obj.setPropertyValue('Name', pc) system.mes.saveMESObject(obj) obj = system.mes.loadMESObject(pc, 'MaterialDef') classObj = system.mes.loadMESObject('Unknown PCs', 'MaterialClass') classObj.addChild(obj) system.mes.saveMESObject(classObj) ##Create the OPerations Definition with the Generic Production Settings obj = system.mes.loadMESObject(pc, 'MaterialDef') matLink = system.mes.getMESObjectLink(obj.getUUID()) ops = system.mes.oee.createMaterialProcessSegment(matLink, eqPath) system.mes.saveMESObjects(ops) |
Snippet 3: Classroom Code Snippet
Python |
def pretty_dir(obj, filter=""): results = [item for item in dir(obj) if filter in item.lower()] method_dict = {"get_methods": [], "set_methods": [], "is_methods": [], "add_methods": [], "remove_methods": []} for i in reversed(range(len(results))): if results[i].startswith('get'): method_dict["get_methods"].append(results.pop(i)) elif results[i].startswith('set'): method_dict["set_methods"].append(results.pop(i)) elif results[i].startswith('is'): method_dict["is_methods"].append(results.pop(i)) elif results[i].startswith('add'): method_dict["add_methods"].append(results.pop(i)) elif results[i].startswith('remove'): method_dict["remove_methods"].append(results.pop(i)) for key, values in method_dict.iteritems(): print key for item in values: print " %s" % item print "others" for item in results: print " %s" % item |
Snippet 4 - mesutils
Classroom Code Snippet
Python |
def checkForObject(objName, objType): ##Create an MES Object Filter (search) filter = system.mes.object.filter.createFilter() filter.setMESObjectTypeName(objType) filter.setMESObjectNamePattern(objName) linkList = system.mes.searchMESObjects(filter) return True if linkList.size() > 0 else False # ================================================================================= ##Create new function getLotTraceResults ##The purpose being to return geneology data for the lotnumber provided. def getLotTraceResults(lotNumber, usedLotNumbers=[], depth=0): import system ##If we are at the top level of the geneology, we have no used lot numbers ##therefore initialize as empty list. if depth == 0: usedLotNumbers = [] ##If we've already seen this lot number, return an empty list to the calling function. ##Otherwise, add the current lot number to our usedLotNumber list, so we don't double count it. if lotNumber in usedLotNumbers: return [] else: usedLotNumbers.append(lotNumber) ##Initialize trace and subtrace lists traceData = [] subTraceData = [] ##Get the lot trace dataset from T&T module, convert it to a PyDataset results = system.dataset.toPyDataSet(system.mes.getLotTraceByLotName(lotNumber, "", 100, True)) ##Iterate through the results, building the trace data list. for row in results: lotUse = row["LotUse"] lotName = row["LotName"] traceData.append([row["LotName"], lotNumber, row["LotStatus"], row["LotUse"], row["LotBeginDateTime"], row["LotEndDateTime"], row["LotQuantity"], row["MaterialName"], row["LotLocationName"], row["SegmentUUID"], row["SegmentName"], row["SegmentLocationName"], depth]) ##Add incoming lot trace to the current trace data. Increase the depth counter to track our ##recursion depth. if lotUse == "In": traceData.extend(getLotTraceResults(lotName, usedLotNumbers, depth + 1)) ##Return the list of lists for building our total trace data table. return traceData # ================================================================================= ##Function to build a dataset and call the recursive geneology function. def getLotTraceResultsDataset(lotNumber): import system log = system.util.getLogger("Lot Trace Results Report") log.info(lotNumber) traceHeader = ["LotName", "ParentLotName", "LotStatus", "LotUse", "LotBeginDateTime", "LotEndDateTime", "LotQuantity", "MaterialName", "LotLocationName", "SegmentUUID", "SegmentName", "SegmentLocationName", "Depth"] traceData = getLotTraceResults(lotNumber) return system.dataset.toDataSet(traceHeader, traceData) def createRecipe(recipeName): from org.apache.log4j import Logger log = Logger.getLogger('createRecipeScriptLogger') ##Check to see if the Recipe Name exists among enabled recipes in the system. query = """SELECT * FROM REC_Recipe WHERE Deleted = 0 AND Name = ?""" db = 'MES' result = system.db.runPrepQuery(query, [recipeName], db, '') if result.getRowCount() == 0: # create the recipe parentRecipeName = '' note = 'Manually-created recipe' system.recipe.createRecipe(recipeName, parentRecipeName, note) # assign production item to recipe itemPath = 'New Enterprise\Site\Area\Line 1' system.recipe.addItemToRecipe(recipeName, itemPath, note) # display current recipe values category = '1' # indicates recipe values were created by the recipe module recipeVals = system.recipe.getRecipeValues(itemPath, recipeName, category) log.info('Original recipe values') log.info('--------------------------------') for ndx in range(recipeVals.size()): recipeItem = recipeVals.get(ndx) # get the recipe value item object #recipeItem = recipeVals.get(ndx).getRecipeValue() # if used in gateway scope itemName = recipeItem.getName() itemValue = str(recipeItem.getValue()) #itemSort = recipeItem.getSortOrder() #recipeItem.getMinValue() #recipeItem.getMaxValue() #recipeItem.getAssignedBy() #recipeItem.getSortOrder() #recipeItem.hasDescription() #recipeItem.getDescription() #recipeItem.getFormat() #recipeItem.getUnits() log.info('%s=%s' %(itemName, itemValue)) # assign values to the recipes items valueName = 'Torque Setting 1' value = '3.0' # always assign as a string, the module will convert to the proper type note = 'value changed' system.recipe.setPathRecipeValue(itemPath, recipeName, valueName, value, note) valueName = 'Zero Location' value = '7.5' note = 'value changed' system.recipe.setPathRecipeValue(itemPath, recipeName, valueName, value, note) # display new values recipeVals = system.recipe.getRecipeValues(itemPath, recipeName, category) log.info(' ') log.info('Modified recipe values') log.info('--------------------------------') for ndx in range(recipeVals.size()): recipeItem = recipeVals.get(ndx) itemName = recipeItem.getName() itemValue = str(recipeItem.getValue()) log.info('%s=%s' %(itemName, itemValue)) return True else: return False |
Script Snippet 5 | params: prodRecipeName, newRecipeName, itemPath, state
Code Snippet 5
Python |
def getParentRecipe(prodRecipeName): # There is no function currently available to get the Master Recipe for a recipe but we can do it through querying the REC_Recipe table #If the passed recipe is not a descendant of any master recipe, then this function will return a null object analysisDBConnName = "MES" #This is the database connection name query = """ SELECT Name FROM REC_Recipe WHERE RecipeUUID = (SELECT ParentRecipeUUID FROM REC_Recipe WHERE Name = ?) """ parentRecipeName = system.db.runScalarPrepQuery(query, [prodRecipeName], analysisDBConnName) if parentRecipeName is None: parentRecipeName = '' return parentRecipeName ##################################################################### def getRecipeProductionItems(LinePath): print 'LinePath - ', LinePath filter = system.mes.object.filter.createFilter() filter.setMESObjectTypeName('LineCell') filter.setPrimaryMESObjectPath(LinePath) list = system.mes.searchMESObjects(filter) data = [] data.append(LinePath) for ndx in range(list.size()): mesObject = list.get(ndx) # print mesObject.getName() mesObject = list.get(ndx).getMESObject() cellPath = mesObject.getEquipmentPath() data.append(cellPath) return data ####################################################################### retVal = "" recipeState = 'DEV' recipeGroup = '' note = 'Copy of ' + prodRecipeName try: system.recipe.deleteRecipe(testRecipeName, '') except: pass parentRecipeName = getParentRecipe(prodRecipeName) system.recipe.createRecipe(newRecipeName, parentRecipeName, recipeState, recipeGroup, note) retVal = retVal + ' Created %s from %s' %(newRecipeName, prodRecipeName) #Now get the recipe items and values and copy them to the new recipe productionItemList = getRecipeProductionItems(itemPath) category = '' for prodItem in productionItemList: print 'prodItem - ' , prodItem if parentRecipeName == '': retVal = retVal + ' Adding %s to %s' %(prodItem, newRecipeName) print 'Adding %s to %s' %(prodItem, newRecipeName) try: system.recipe.addItemToRecipe(newRecipeName, itemPath, 'Adding prod item to recipe') except: print "Couldn't add item" pass dict = {} list = system.recipe.getRecipeValueList(prodItem,prodRecipeName, category) if list.size() > 0: retVal = retVal + ' The recipe values for %s:' %prodRecipeName for rv in list: retVal = retVal + ' %s = %s' % (rv.getDisplayText(), str(rv.getRecipeValue())) dict[rv.getDisplayText()] = str(rv.getRecipeValue()) system.recipe.setPathRecipeValues(prodItem, newRecipeName, dict, note) else: retVal = retVal + ' No production items found for %s' %prodItem return retVal |
Script Snippet 6: Scheduling Operations
Python |
##Load the operation definition object operationsDefinition = system.mes.loadMESObject('RT1_Scheduling Example 1', 'OperationsDefinition') #Create a schedule for the specified operation schedule = system.mes.createSchedule(operationsDefinition) ##Print each item for verification purposes for ndx in range(schedule.size()): print schedule.get(ndx) ##Set the date range startDate = system.date.getDate(2020, 01, 10) startDate = system.date.setTime(startDate, 14, 0, 0) dueDate = system.date.addDays(startDate, 15) scheduleList = system.mes.scheduleOperations(schedule, startDate, dueDate, False, 'Active') for item in scheduleList: print item ##Save the schedule objects to make them manifest in the system. system.mes.saveSchedule(scheduleList) eqPaths = ['New Enterprise\Site\Area\Line 1', '[global]\New Enterprise\Site\Area\Storage Zone 1\Storage Unit 1', '[global]\New Enterprise\Site\Area\Storage Zone 1\Tank'] for i in range(len(eqPaths)): list = system.mes.getEquipmentScheduleEntries(eqPaths[i], startDate, dueDate, 'Active', 1) print list for item in list: print item |
Script Snippet 7: Creating OEE Objects Via Script
Python |
eqPath = "New Enterprise\Site 1" site = system.mes.loadMESObjectByEquipmentPath(eqPath) obj = system.mes.createMESObject('Area') obj.setPropertyValue('Name', 'Alternate Area') obj.setActive(1) obj.addParent(site) system.mes.saveMESObject(obj) ##Create a New Line in a given Area: parentObj = system.mes.loadMESObject('Alternate Area', 'Area') newMESObj = system.mes.createMESObject('Line') newMESObj.setPropertyValue('Name', 'Line B') newMESObj.setActive(1) newMESObj.addParent(parentObj) system.mes.saveMESObject(newMESObj) eq_path = 'New Enterprise\Site 1\Alternate Area\Line B' eq_obj = system.mes.loadMESObjectByEquipmentPath(eq_path) old_state_class_uuid = eq_obj.getPropertyValue('EquipmentStateClassUUID') print old_state_class_uuid new_state_class_obj = system.mes.loadMESObject('Default (1)', 'EquipmentStateClass') new_state_class_uuid = new_state_class_obj.getUUID() print new_state_class_uuid eq_obj.setPropertyValue('EquipmentStateClassUUID', new_state_class_uuid) system.mes.saveMESObject(eq_obj) # eqPath = 'New Enterprise\Site 1\Alternate Area\Line B' obj = system.mes.loadMESObjectByEquipmentPath(eqPath) prop = obj.createComplexProperty('Counter', 'Material In') prop.setCountKind('Infeed') prop.setCountMode('Positive Change') prop.setTagPath('{Equipment Path}/Infeed') system.mes.saveMESObject(obj) eqPath = 'New Enterprise\Site 1\Alternate Area\Line B' obj = system.mes.loadMESObjectByEquipmentPath(eqPath) prop = obj.createComplexProperty('AdditionalFactor', 'Operator') prop.setTagPath('{Equipment Path}/Operator') system.mes.saveMESObject(obj) eqPath = 'New Enterprise\Site 1\Alternate Area\Line B' obj = system.mes.loadMESObjectByEquipmentPath(eqPath) prop = obj.createComplexProperty('LiveAnalysis', 'Run') prop.setDataPoints('Equipment Mode,Equipment State,Product Code,Shift,OEE') prop.setLiveAnalysisPeriod('Top of Hour') system.mes.saveMESObject(obj) def checkForObject(objName, objType): filter = system.mes.object.filter.createFilter() filter.setMESObjectTypeName(objType) filter.setMESObjectNamePattern(objName) linkList = system.mes.searchMESObjects(filter) return True if linkList.size() > 0 else False ##Create a New Material Definition within a given Material Class matClass = system.mes.loadMESObject('Production Materials', 'MaterialClass') obj = system.mes.createMESObject('MaterialDef') obj.setPropertyValue('Name', 'Grapefruit Juice') obj.addParent(matClass) system.mes.saveMESObject(obj) ##Create a New Operation Definition for a given Material-Equipment Combination eqPath = 'New Enterprise\Site\Area\Line 2' obj = system.mes.loadMESObject('Grapefruit Juice', 'MaterialDef') matLink = system.mes.object.link.create(obj) objList = system.mes.oee.createMaterialProcessSegment(matLink, eqPath) system.mes.saveMESObjects(objList) ##Create a new Equipment State in a given Equipment State Class def getStateOptions(eqPath, parentUUID, codeList): stateList = system.mes.getEquipmentStateOptions(eqPath, parentUUID, '') for state in stateList: codeList.append(state.getStateCode()) if len(state.getChildCollection()) > 0: codeList.extend(getStateOptions(eqPath, state.getUUID(), codeList)) return codeList val = 12 eqPath = 'New Enterprise\Site\Alternate Area\Line B' defaultClass = system.mes.loadMESObject('Default', 'EquipmentStateClass') codeList = getStateOptions(eqPath, defaultClass.getUUID(), []) if val not in codeList: stateCls = system.mes.loadMESObject('Default', 'EquipmentStateClass') state = system.mes.createMESObject('EquipmentState') state.addParent(stateCls) state.setPropertyValue('Name', 'Overheated') state.setPropertyValue('EquipmentStateCode', 12) state.setPropertyValue('EquipmentStateType', 'Unplanned Downtime') #valid values for EquipmentStateType: "Running", "Idle", "Blocked", "Starved", "Planned Downtime", "Unplanned Downtime", "Disabled" state.setPropertyValue('EquipmentStateOverride', 'Optional') state.setPropertyValue('EquipmentStateOverrideScope', 'Detected Equipment State') system.mes.saveMESObject(state) else: system.gui.messageBox('State Code is already taken!', 'Take a Training Class') |
XML Report Export
Python |
path = 'Lot Trace Report' params = {'LotNumber':'MES-Training-00000000011'} actionParams = { "path":'D:\Users\mes3\Downloads\test', "fileName":'bestfileever.xml', "format":'xml'} system.report.executeAndDistribute(path, '', params, 'save', actionParams) |
Create Machine Recipe Set Points on a Line
Python |
eqPath = 'New Enterprise\Site\Test Area\Line B' setPointNames = ['Torque Setting 1', 'Torque Setting 2', 'Zero Location', 'Vacuum Pressure Target'] baseTagPath = '{Equipment Path}/' tagDataType = 6 ### float4 is 6 ### float8 is 8 obj = system.mes.loadMESObjectByEquipmentPath(eqPath) for sp in setPointNames: defaultRecipeValue = obj.createDefaultRecipeValue(sp) defaultRecipeValue.setTagPath(baseTagPath + sp) defaultRecipeValue.setRecipeDataType(tagDataType) defaultRecipeValue.setDefaultValue(10.0) system.mes.saveMESObject(obj) |