WJ import loader: metrology PCs are computers that control a synthesized tool
Routing by pctype wrongly swept ~105 metrology PCs (CMM/Genspect/Keyence/Wax) into measuringtools - but a PC that drives an instrument is still a computer; the physical CMM/gauge is the tool. Dropped the pctype override: those PCs now import as computers (measuringtools drops to the 48 real instrument rows). Classic has no separate tool row for a metrology PC, so they'd be orphaned. New metrology stage synthesizes a measuring-tool asset per metrology PC (typed by its pctype: CMM / Form Tracer / Vision System / Genspect) and a Controls relationship PC -> tool, mirroring what the runtime collector does. Result: computers 663->751, measuringtools = 48 real + 88 synthesized (each linked to its controlling PC), 88 new Controls relationships, no orphans.
This commit is contained in:
@@ -50,8 +50,10 @@ def _upsert(h, path, payload, unique_field, idfield, list_path=None):
|
|||||||
|
|
||||||
|
|
||||||
# --- classic machinetype routing (per the resolved import decisions) ---------
|
# --- classic machinetype routing (per the resolved import decisions) ---------
|
||||||
|
# measuringtools are the physical instruments (the CMM/gauge machine types). A
|
||||||
|
# PC that DRIVES one (pctype CMM/Genspect/Keyence/Wax) is still a computer, not a
|
||||||
|
# measuring tool - routing by pctype wrongly swept ~105 PCs into measuringtools.
|
||||||
MEASURING_MTYPES = {3, 5, 8, 23, 47, 48} # CMM, Wax, Eddy, Measuring, Inspection, Spline
|
MEASURING_MTYPES = {3, 5, 8, 23, 47, 48} # CMM, Wax, Eddy, Measuring, Inspection, Spline
|
||||||
MEASURING_PCTYPES = {5, 6, 7, 8} # PC subtypes: CMM, Wax/Trace, Keyence, Genspect
|
|
||||||
COMPUTER_MTYPES = {33, 20} # PC, Server
|
COMPUTER_MTYPES = {33, 20} # PC, Server
|
||||||
NETWORK_MTYPES = {16, 17, 18, 19, 46} # Access, IDF, Camera, Switch, Firewall
|
NETWORK_MTYPES = {16, 17, 18, 19, 46} # Access, IDF, Camera, Switch, Firewall
|
||||||
SKIP_MTYPES = {15, 44} # Printer (printers table), USB (cmmc source)
|
SKIP_MTYPES = {15, 44} # Printer (printers table), USB (cmmc source)
|
||||||
@@ -79,9 +81,7 @@ def _route(machinetypeid, pctypeid, islocationonly=False):
|
|||||||
if machinetypeid in MEASURING_MTYPES:
|
if machinetypeid in MEASURING_MTYPES:
|
||||||
return 'measuringtool'
|
return 'measuringtool'
|
||||||
if machinetypeid in COMPUTER_MTYPES:
|
if machinetypeid in COMPUTER_MTYPES:
|
||||||
if machinetypeid == 33 and pctypeid in MEASURING_PCTYPES:
|
return 'computer' # a metrology PC is still a PC (it CONTROLS a tool)
|
||||||
return 'measuringtool'
|
|
||||||
return 'computer'
|
|
||||||
return 'machine' # includes the 134 untyped (machinetypeid=1) shop machines
|
return 'machine' # includes the 134 untyped (machinetypeid=1) shop machines
|
||||||
|
|
||||||
|
|
||||||
@@ -349,6 +349,52 @@ def stage_printers(h):
|
|||||||
return {'printers': made}
|
return {'printers': made}
|
||||||
|
|
||||||
|
|
||||||
|
# classic pctype -> the measuring instrument that PC drives
|
||||||
|
METROLOGY_PCTYPE_TOOL = {5: 'CMM', 6: 'Form Tracer', 7: 'Vision System', 8: 'Genspect'}
|
||||||
|
|
||||||
|
|
||||||
|
def stage_metrology(h):
|
||||||
|
"""Metrology PCs (CMM/Genspect/Keyence/Wax) are computers that CONTROL an
|
||||||
|
instrument. Classic has no separate tool row, so synthesize a measuring-tool
|
||||||
|
asset per metrology PC and a Controls relationship (PC -> tool), mirroring
|
||||||
|
what the runtime collector does. Runs after the asset hub (needs the PC's
|
||||||
|
assetid from the crosswalk)."""
|
||||||
|
controls_id = _upsert(h, '/api/assets/relationshiptypes',
|
||||||
|
{'relationshiptype': 'Controls'}, 'relationshiptype',
|
||||||
|
'relationshiptypeid', '/api/assets/relationshiptypes')
|
||||||
|
made = linked = 0
|
||||||
|
for m in h.source.rows('shopdb_src',
|
||||||
|
'SELECT machineid, alias, hostname, machinenumber, businessunitid, '
|
||||||
|
'mapleft, maptop, pctypeid FROM machines '
|
||||||
|
'WHERE machinetypeid=33 AND pctypeid IN (5,6,7,8) '
|
||||||
|
'AND (islocationonly IS NULL OR islocationonly=0)'):
|
||||||
|
pc_assetid = h.ids.get('asset', m['machineid'])
|
||||||
|
if not pc_assetid:
|
||||||
|
continue # PC not imported (dup-skipped etc.)
|
||||||
|
toolname = METROLOGY_PCTYPE_TOOL[m['pctypeid']]
|
||||||
|
typeid = _upsert(h, '/api/measuringtools/types', {'name': toolname},
|
||||||
|
'name', 'measuringtooltypeid', '/api/measuringtools/types')
|
||||||
|
pcname = (m['alias'] or m['hostname'] or m['machinenumber'] or '').strip()
|
||||||
|
status, data = h.post('/api/measuringtools', {
|
||||||
|
'assetnumber': f"MT-{m['machineid']}",
|
||||||
|
'name': (f"{pcname} {toolname}").strip() or toolname,
|
||||||
|
'measuringtooltypeid': typeid,
|
||||||
|
'businessunitid': h.ids.get('businessunit', m['businessunitid']),
|
||||||
|
'mapx': m['mapleft'], 'mapy': m['maptop']})
|
||||||
|
if status not in (200, 201):
|
||||||
|
continue
|
||||||
|
tool_assetid = _id_of(data, 'assetid')
|
||||||
|
made += 1
|
||||||
|
if tool_assetid and controls_id:
|
||||||
|
h.ids.put('metrologytool', m['machineid'], tool_assetid)
|
||||||
|
st, _ = h.post('/api/assets/relationships', {
|
||||||
|
'sourceassetid': pc_assetid, 'targetassetid': tool_assetid,
|
||||||
|
'relationshiptypeid': controls_id})
|
||||||
|
if st in (200, 201):
|
||||||
|
linked += 1
|
||||||
|
return {'measuringtools_synth': made, 'controls_links': linked}
|
||||||
|
|
||||||
|
|
||||||
def stage_communications(h):
|
def stage_communications(h):
|
||||||
"""Fold each asset's primary IP from the source communications table. There
|
"""Fold each asset's primary IP from the source communications table. There
|
||||||
is no bulk-communications endpoint, so this is one of the plan's documented
|
is no bulk-communications endpoint, so this is one of the plan's documented
|
||||||
@@ -722,6 +768,7 @@ STAGES = {
|
|||||||
'assets': stage_assets,
|
'assets': stage_assets,
|
||||||
'locations': stage_locations,
|
'locations': stage_locations,
|
||||||
'printers': stage_printers,
|
'printers': stage_printers,
|
||||||
|
'metrology': stage_metrology,
|
||||||
'communications': stage_communications,
|
'communications': stage_communications,
|
||||||
'applications': stage_applications,
|
'applications': stage_applications,
|
||||||
'warranties': stage_warranties,
|
'warranties': stage_warranties,
|
||||||
@@ -739,7 +786,7 @@ def main():
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--stages',
|
'--stages',
|
||||||
default='reference,employees,catalog,assets,locations,printers,'
|
default='reference,employees,catalog,assets,locations,printers,'
|
||||||
'communications,applications,warranties,notifications,'
|
'metrology,communications,applications,warranties,notifications,'
|
||||||
'knowledgebase,relationships,subnets,usb,verify',
|
'knowledgebase,relationships,subnets,usb,verify',
|
||||||
help='comma list of stages to run')
|
help='comma list of stages to run')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|||||||
Reference in New Issue
Block a user