Tutorial Code Snippets

Tutorial Code Snippets and Assets

Note 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)