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)