Configure Performance Reasons
Performance reasons are organized like the other Kanoa reason codes:
- Performance state classes act as folders for related reasons, for example by area or by cause (equipment, material, labor, process).
- Performance states are the reasons themselves, each with a name and a color used in reports.
- Links to assets (and optionally items) control where each reason can be selected, so an operator on Machine 1 only sees reasons that make sense for a machining center.
-
Navigate to Configuration → Ops → Performance Reasons.
-
Create a performance state class named
Machining. -
Under
Machining, create these performance reasons, giving each a distinct color:Reason Typical cause Tool WearFeed rate reduced to protect a worn cutting tool Coolant Flow LowSpindle speed reduced while coolant pressure recovers Material Hardness VariationHarder bar stock forcing slower cuts Operator PacingManual load/unload slower than the cycle allows -
Open each reason with the edit button and confirm its class, color, and that it is enabled.
- On the same screen, click on the
Performance state Linkstab and select theMachiningclass so all four reasons are included. - In the asset section, find Machine 1 (
CoreForge\Philadelphia\Machining\Machine 1). - Click the link button to link the reasons to the asset.
Reasons that aren't linked to an asset don't appear when someone codes a performance event on that asset. A reason for a jammed tape applicator on a packaging line shouldn't be selectable on a machining center.
Copy this script into the Ignition Designer Script Console (Tools → Script Console) and run it. It checks the Machining class, the four reasons (name, class, enabled, distinct colours) and that each one is linked to Machine 1. It doesn't change anything.
Show the check script
# Kanoa Ops Training - check "Configure Performance Reasons" (Performance events, lesson 1)
#
# Run in the Ignition Designer Script Console (Tools > Script Console). It only
# reads; it changes nothing. Every check prints PASS or FAIL with what to fix.
CLASS = 'Machining'
REASONS = ['Tool Wear', 'Coolant Flow Low', 'Material Hardness Variation', 'Operator Pacing']
ASSET = 'CoreForge\\Philadelphia\\Machining\\Machine 1'
ps = system.kanoa.performanceState
results = []
def check(ok, what, fix=None):
results.append(bool(ok))
if ok:
print 'PASS %s' % what
else:
print 'FAIL %s' % what
if fix:
print ' -> %s' % fix
def field(row, *names):
for n in names:
if row.get(n) is not None:
return row[n]
return None
def text(v):
return '' if v is None else unicode(v).strip()
def key(v):
return ' '.join(text(v).lower().split())
def truthy(v):
return str(v).lower() in ('true', '1')
def rows(data):
return system.kanoa.utilities.convertDatasetToJSON(data) if data is not None else []
print '=' * 70
print 'Kanoa Ops Training - Configure Performance Reasons check'
print '=' * 70
# 1. The performance state class
print '\n-- Performance reason class'
classes = rows(ps.getPerformanceStateClasses({}))
classPaths = dict((key(field(c, 'performanceStateClassPath', 'path')), text(field(c, 'performanceStateClassPath', 'path'))) for c in classes)
if CLASS in classPaths.values():
check(True, 'Class %s exists' % CLASS)
elif key(CLASS) in classPaths:
check(False, 'Class %s exists' % CLASS, "Found '%s'. Rename it to %s." % (classPaths[key(CLASS)], CLASS))
else:
check(False, 'Class %s exists' % CLASS, 'In Configuration > Ops > Performance Reasons, create a class named %s.' % CLASS)
# 2. The four reasons
print '\n-- Performance reasons'
states = rows(ps.getPerformanceStates({}))
byName = {}
for s in states:
byName.setdefault(key(field(s, 'performanceStateName')), []).append(s)
found = {}
for reason in REASONS:
matches = byName.get(key(reason), [])
if not matches:
check(False, '%s exists' % reason, 'Under %s, add a performance reason named %s.' % (CLASS, reason))
continue
s = matches[0]
found[reason] = s
actual = text(field(s, 'performanceStateName'))
check(actual == reason, '%s exists' % reason, "Found '%s'. Rename it to %s." % (actual, reason))
classPath = text(field(s, 'performanceStateClassPath'))
if classPath:
check(key(classPath) == key(CLASS), '%s is in the %s class' % (reason, CLASS),
"It's in '%s'. Edit it and set its class to %s." % (classPath, CLASS))
if field(s, 'enabled') is not None:
check(truthy(field(s, 'enabled')), '%s is enabled' % reason, 'Edit it and tick Enabled.')
colours = [key(field(s, 'performanceStateColor', 'color')) for s in found.values()]
colours = [c for c in colours if c]
if len(colours) == len(found) and found:
check(len(set(colours)) == len(colours), 'Each reason has its own colour',
'Some reasons share a colour (%s). Give each one a distinct colour so they can be told apart in reports.' % ', '.join(sorted(colours)))
# 3. Linked to Machine 1
print '\n-- Linked to Machine 1'
linked = set(key(field(r, 'performanceStateName')) for r in rows(ps.getAssetPerformanceStates({'assetPath': ASSET})))
for reason in REASONS:
check(key(reason) in linked, '%s is linked to Machine 1' % reason,
'On the Performance state Links tab, select the %s class and Machine 1, then click the link button.' % CLASS)
passed = results.count(True)
print '\n' + '=' * 70
print 'Result: %d of %d checks passed' % (passed, len(results))
if passed == len(results):
print 'All good. Your performance reasons are set up.'
else:
print 'Fix the FAIL items above, then run this again.'
print '=' * 70