From b4b81b850ad57b42b74b84850257d9c9cb4f53f8 Mon Sep 17 00:00:00 2001 From: cproudlock Date: Wed, 10 Dec 2025 20:09:56 -0500 Subject: [PATCH] Add equipment data sync for dualpath partner machines When a dualpath relationship is created, equipment data is now automatically synced between partners. This ensures both machines share the same: - Controller type and OS - Model number - Serial number - Communication settings (IP, Serial config) Location data (mapleft, maptop) is NOT synced since dualpath machines occupy slightly different physical positions. Changes: - includes/db_helpers.asp: Add CopyEquipmentDataToDualpathPartner(), CopyCommConfigToDualpathPartner(), and SyncDualpathPartnerData() functions - savemachineedit.asp: Call SyncDualpathPartnerData() on dualpath creation - savemachine_direct.asp: Call SyncDualpathPartnerData() on dualpath creation - sql/sync_dualpath_equipment_data.sql: One-time script to sync existing pairs Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- includes/db_helpers.asp | 241 +++++++++++++++++++++++++++ savemachine_direct.asp | 3 + savemachineedit.asp | 3 + sql/sync_dualpath_equipment_data.sql | 184 ++++++++++++++++++++ 4 files changed, 431 insertions(+) create mode 100644 sql/sync_dualpath_equipment_data.sql diff --git a/includes/db_helpers.asp b/includes/db_helpers.asp index c836e09..77d79d9 100644 --- a/includes/db_helpers.asp +++ b/includes/db_helpers.asp @@ -431,4 +431,245 @@ Function PropagateControllerFromDualpathMachine(conn, machineId1, machineId2) PropagateControllerFromDualpathMachine = cnt End Function + +'----------------------------------------------------------------------------- +' FUNCTION: CopyEquipmentDataToDualpathPartner +' PURPOSE: Copy equipment settings from source to dualpath partner +' PARAMETERS: +' conn (ADODB.Connection) - Database connection object +' sourceMachineId (Integer) - Machine ID with the data to copy FROM +' targetMachineId (Integer) - Machine ID to copy data TO +' COPIES: controllertypeid, controllerosid, modelnumberid, serialnumber +' DOES NOT COPY: mapleft, maptop (location data), machinenumber, hostname +' RETURNS: Boolean - True if successful +'----------------------------------------------------------------------------- +Function CopyEquipmentDataToDualpathPartner(conn, sourceMachineId, targetMachineId) + On Error Resume Next + + Dim rsSource, cmdUpdate + Dim srcControllertypeid, srcControllerosid, srcModelnumberid, srcSerialnumber + + ' Get source machine data + Set rsSource = conn.Execute("SELECT controllertypeid, controllerosid, modelnumberid, serialnumber " & _ + "FROM machines WHERE machineid = " & CLng(sourceMachineId)) + + If rsSource.EOF Then + CopyEquipmentDataToDualpathPartner = False + rsSource.Close + Set rsSource = Nothing + Exit Function + End If + + ' Store values (handle NULLs) + If Not IsNull(rsSource("controllertypeid")) Then + srcControllertypeid = CLng(rsSource("controllertypeid")) + Else + srcControllertypeid = Null + End If + + If Not IsNull(rsSource("controllerosid")) Then + srcControllerosid = CLng(rsSource("controllerosid")) + Else + srcControllerosid = Null + End If + + If Not IsNull(rsSource("modelnumberid")) Then + srcModelnumberid = CLng(rsSource("modelnumberid")) + Else + srcModelnumberid = Null + End If + + If Not IsNull(rsSource("serialnumber")) Then + srcSerialnumber = rsSource("serialnumber") & "" + Else + srcSerialnumber = Null + End If + + rsSource.Close + Set rsSource = Nothing + + ' Update target machine with source data + Set cmdUpdate = Server.CreateObject("ADODB.Command") + cmdUpdate.ActiveConnection = conn + cmdUpdate.CommandText = "UPDATE machines SET " & _ + "controllertypeid = ?, controllerosid = ?, modelnumberid = ?, serialnumber = ? " & _ + "WHERE machineid = ?" + cmdUpdate.CommandType = 1 + + ' Add parameters + If IsNull(srcControllertypeid) Then + cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@ctrl", 3, 1, , Null) + Else + cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@ctrl", 3, 1, , srcControllertypeid) + End If + + If IsNull(srcControllerosid) Then + cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@ctrlOS", 3, 1, , Null) + Else + cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@ctrlOS", 3, 1, , srcControllerosid) + End If + + If IsNull(srcModelnumberid) Then + cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@model", 3, 1, , Null) + Else + cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@model", 3, 1, , srcModelnumberid) + End If + + If IsNull(srcSerialnumber) Then + cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@serial", 200, 1, 100, Null) + Else + cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@serial", 200, 1, 100, srcSerialnumber) + End If + + cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@targetId", 3, 1, , CLng(targetMachineId)) + + cmdUpdate.Execute + Set cmdUpdate = Nothing + + If Err.Number <> 0 Then + CopyEquipmentDataToDualpathPartner = False + Else + CopyEquipmentDataToDualpathPartner = True + End If +End Function + +'----------------------------------------------------------------------------- +' FUNCTION: CopyCommConfigToDualpathPartner +' PURPOSE: Copy communication settings (IP, Serial) from source to dualpath partner +' PARAMETERS: +' conn (ADODB.Connection) - Database connection object +' sourceMachineId (Integer) - Machine ID with the comm config to copy FROM +' targetMachineId (Integer) - Machine ID to copy comm config TO +' COPIES: IP address/port, Serial settings (baud, databits, stopbits, parity) +' RETURNS: Integer - Number of comm records created +'----------------------------------------------------------------------------- +Function CopyCommConfigToDualpathPartner(conn, sourceMachineId, targetMachineId) + On Error Resume Next + + Dim rsComm, rsCheck, cmdInsert, cnt + cnt = 0 + + ' Get source communication settings (IP and Serial types only) + Set rsComm = conn.Execute("SELECT comstypeid, address, port, baud, databits, stopbits, parity " & _ + "FROM communications WHERE machineid = " & CLng(sourceMachineId) & " " & _ + "AND comstypeid IN (SELECT comstypeid FROM comstypes WHERE typename IN ('IP', 'Serial')) " & _ + "AND isactive = 1") + + Do While Not rsComm.EOF + ' Check if target already has this comm type + Set rsCheck = conn.Execute("SELECT comid FROM communications " & _ + "WHERE machineid = " & CLng(targetMachineId) & " " & _ + "AND comstypeid = " & CLng(rsComm("comstypeid")) & " AND isactive = 1") + + If rsCheck.EOF Then + ' Create the comm config for target + Set cmdInsert = Server.CreateObject("ADODB.Command") + cmdInsert.ActiveConnection = conn + cmdInsert.CommandText = "INSERT INTO communications " & _ + "(machineid, comstypeid, address, port, baud, databits, stopbits, parity, isactive) " & _ + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1)" + cmdInsert.CommandType = 1 + + cmdInsert.Parameters.Append cmdInsert.CreateParameter("@machid", 3, 1, , CLng(targetMachineId)) + cmdInsert.Parameters.Append cmdInsert.CreateParameter("@comtype", 3, 1, , CLng(rsComm("comstypeid"))) + + If IsNull(rsComm("address")) Then + cmdInsert.Parameters.Append cmdInsert.CreateParameter("@addr", 200, 1, 50, Null) + Else + cmdInsert.Parameters.Append cmdInsert.CreateParameter("@addr", 200, 1, 50, rsComm("address") & "") + End If + + If IsNull(rsComm("port")) Then + cmdInsert.Parameters.Append cmdInsert.CreateParameter("@port", 3, 1, , Null) + Else + cmdInsert.Parameters.Append cmdInsert.CreateParameter("@port", 3, 1, , CLng(rsComm("port"))) + End If + + If IsNull(rsComm("baud")) Then + cmdInsert.Parameters.Append cmdInsert.CreateParameter("@baud", 3, 1, , Null) + Else + cmdInsert.Parameters.Append cmdInsert.CreateParameter("@baud", 3, 1, , CLng(rsComm("baud"))) + End If + + If IsNull(rsComm("databits")) Then + cmdInsert.Parameters.Append cmdInsert.CreateParameter("@databits", 3, 1, , Null) + Else + cmdInsert.Parameters.Append cmdInsert.CreateParameter("@databits", 3, 1, , CLng(rsComm("databits"))) + End If + + If IsNull(rsComm("stopbits")) Then + cmdInsert.Parameters.Append cmdInsert.CreateParameter("@stopbits", 3, 1, , Null) + Else + cmdInsert.Parameters.Append cmdInsert.CreateParameter("@stopbits", 3, 1, , CLng(rsComm("stopbits"))) + End If + + If IsNull(rsComm("parity")) Then + cmdInsert.Parameters.Append cmdInsert.CreateParameter("@parity", 200, 1, 10, Null) + Else + cmdInsert.Parameters.Append cmdInsert.CreateParameter("@parity", 200, 1, 10, rsComm("parity") & "") + End If + + cmdInsert.Execute + Set cmdInsert = Nothing + cnt = cnt + 1 + End If + + rsCheck.Close + Set rsCheck = Nothing + rsComm.MoveNext + Loop + + rsComm.Close + Set rsComm = Nothing + + CopyCommConfigToDualpathPartner = cnt +End Function + +'----------------------------------------------------------------------------- +' FUNCTION: SyncDualpathPartnerData +' PURPOSE: Sync all relevant data between dualpath partners (bidirectional) +' PARAMETERS: +' conn (ADODB.Connection) - Database connection object +' machineId1 (Integer) - First machine in dualpath +' machineId2 (Integer) - Second machine in dualpath +' BEHAVIOR: Copies data from whichever machine has data to the one missing it +' RETURNS: Boolean - True if any data was synced +'----------------------------------------------------------------------------- +Function SyncDualpathPartnerData(conn, machineId1, machineId2) + On Error Resume Next + + Dim rsM1, rsM2, hasData1, hasData2 + + ' Check which machine has controller data + Set rsM1 = conn.Execute("SELECT controllertypeid FROM machines WHERE machineid = " & CLng(machineId1)) + Set rsM2 = conn.Execute("SELECT controllertypeid FROM machines WHERE machineid = " & CLng(machineId2)) + + hasData1 = False + hasData2 = False + + If Not rsM1.EOF Then + hasData1 = Not IsNull(rsM1("controllertypeid")) + End If + If Not rsM2.EOF Then + hasData2 = Not IsNull(rsM2("controllertypeid")) + End If + + rsM1.Close + rsM2.Close + Set rsM1 = Nothing + Set rsM2 = Nothing + + ' Copy from machine with data to machine without + If hasData1 And Not hasData2 Then + Call CopyEquipmentDataToDualpathPartner(conn, machineId1, machineId2) + Call CopyCommConfigToDualpathPartner(conn, machineId1, machineId2) + SyncDualpathPartnerData = True + ElseIf hasData2 And Not hasData1 Then + Call CopyEquipmentDataToDualpathPartner(conn, machineId2, machineId1) + Call CopyCommConfigToDualpathPartner(conn, machineId2, machineId1) + SyncDualpathPartnerData = True + Else + SyncDualpathPartnerData = False + End If +End Function %> diff --git a/savemachine_direct.asp b/savemachine_direct.asp index b947da3..edda5b4 100644 --- a/savemachine_direct.asp +++ b/savemachine_direct.asp @@ -608,6 +608,9 @@ ' Propagate controller from dualpath partner if exists Call PropagateControllerFromDualpathMachine(objConn, newMachineId, dualpathidVal) + + ' Sync equipment data between dualpath partners (controller type, model, comm config) + Call SyncDualpathPartnerData(objConn, newMachineId, dualpathidVal) End If End If diff --git a/savemachineedit.asp b/savemachineedit.asp index 5a1c305..2bc2295 100644 --- a/savemachineedit.asp +++ b/savemachineedit.asp @@ -646,6 +646,9 @@ ' Propagate controller from dualpath partner if exists Call PropagateControllerFromDualpathMachine(objConn, CLng(machineid), tempDualpathID) + + ' Sync equipment data between dualpath partners (controller type, model, comm config) + Call SyncDualpathPartnerData(objConn, CLng(machineid), tempDualpathID) End If '============================================================================= diff --git a/sql/sync_dualpath_equipment_data.sql b/sql/sync_dualpath_equipment_data.sql new file mode 100644 index 0000000..abe22df --- /dev/null +++ b/sql/sync_dualpath_equipment_data.sql @@ -0,0 +1,184 @@ +-- ============================================================================ +-- Script: sync_dualpath_equipment_data.sql +-- Purpose: Sync equipment data (controller type, model, comm config) between +-- dualpath partner machines +-- Target: MySQL 5.6 (dev and production) +-- +-- Data Synced: +-- - controllertypeid (equipment controller type) +-- - controllerosid (controller OS) +-- - modelnumberid (equipment model) +-- - serialnumber (equipment serial) +-- - communications (IP and Serial config) +-- +-- NOT Synced (location-specific): +-- - mapleft, maptop (map position) +-- - machinenumber, hostname (unique identifiers) +-- ============================================================================ + +-- ============================================================================ +-- STEP 1: SHOW DUALPATH PAIRS WITH MISMATCHED DATA +-- ============================================================================ + +SELECT 'Dualpath pairs with mismatched controller settings:' AS analysis; + +SELECT + m1.machinenumber AS machine1, + m1.controllertypeid AS m1_ctrl_type, + ct1.controllertype AS m1_controller, + m2.machinenumber AS machine2, + m2.controllertypeid AS m2_ctrl_type, + ct2.controllertype AS m2_controller +FROM machinerelationships mr +JOIN machines m1 ON mr.machineid = m1.machineid +JOIN machines m2 ON mr.related_machineid = m2.machineid +JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid +LEFT JOIN controllertypes ct1 ON m1.controllertypeid = ct1.controllertypeid +LEFT JOIN controllertypes ct2 ON m2.controllertypeid = ct2.controllertypeid +WHERE rt.relationshiptype = 'Dualpath' +AND mr.isactive = 1 +AND ( + COALESCE(m1.controllertypeid, 0) <> COALESCE(m2.controllertypeid, 0) + OR COALESCE(m1.controllerosid, 0) <> COALESCE(m2.controllerosid, 0) + OR COALESCE(m1.modelnumberid, 0) <> COALESCE(m2.modelnumberid, 0) +) +ORDER BY m1.machinenumber; + +-- ============================================================================ +-- STEP 2: SYNC CONTROLLER TYPE, OS, AND MODEL +-- Copy from m1 to m2 where m1 has data and m2 doesn't +-- ============================================================================ + +SELECT 'Syncing controller settings from populated machines to empty partners...' AS status; + +-- Update controllertypeid where m1 has it and m2 doesn't +UPDATE machines m2 +JOIN machinerelationships mr ON m2.machineid = mr.related_machineid +JOIN machines m1 ON mr.machineid = m1.machineid +JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid +SET m2.controllertypeid = m1.controllertypeid +WHERE rt.relationshiptype = 'Dualpath' +AND mr.isactive = 1 +AND m1.controllertypeid IS NOT NULL +AND m2.controllertypeid IS NULL; + +-- Update controllerosid where m1 has it and m2 doesn't +UPDATE machines m2 +JOIN machinerelationships mr ON m2.machineid = mr.related_machineid +JOIN machines m1 ON mr.machineid = m1.machineid +JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid +SET m2.controllerosid = m1.controllerosid +WHERE rt.relationshiptype = 'Dualpath' +AND mr.isactive = 1 +AND m1.controllerosid IS NOT NULL +AND m2.controllerosid IS NULL; + +-- Update modelnumberid where m1 has it and m2 doesn't +UPDATE machines m2 +JOIN machinerelationships mr ON m2.machineid = mr.related_machineid +JOIN machines m1 ON mr.machineid = m1.machineid +JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid +SET m2.modelnumberid = m1.modelnumberid +WHERE rt.relationshiptype = 'Dualpath' +AND mr.isactive = 1 +AND m1.modelnumberid IS NOT NULL +AND m2.modelnumberid IS NULL; + +-- Update serialnumber where m1 has it and m2 doesn't +UPDATE machines m2 +JOIN machinerelationships mr ON m2.machineid = mr.related_machineid +JOIN machines m1 ON mr.machineid = m1.machineid +JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid +SET m2.serialnumber = m1.serialnumber +WHERE rt.relationshiptype = 'Dualpath' +AND mr.isactive = 1 +AND m1.serialnumber IS NOT NULL AND m1.serialnumber <> '' +AND (m2.serialnumber IS NULL OR m2.serialnumber = ''); + +-- ============================================================================ +-- STEP 3: SYNC COMMUNICATION SETTINGS (IP AND SERIAL) +-- Copy comm config from m1 to m2 where m2 is missing it +-- ============================================================================ + +SELECT 'Syncing communication settings...' AS status; + +-- Get IP and Serial comstypeids +SET @ip_comstypeid = (SELECT comstypeid FROM comstypes WHERE typename = 'IP' LIMIT 1); +SET @serial_comstypeid = (SELECT comstypeid FROM comstypes WHERE typename = 'Serial' LIMIT 1); + +-- Insert IP comm config for dualpath partners that are missing it +INSERT INTO communications (machineid, comstypeid, address, port, isactive) +SELECT DISTINCT + m2.machineid, + c1.comstypeid, + c1.address, + c1.port, + 1 +FROM machinerelationships mr +JOIN machines m1 ON mr.machineid = m1.machineid +JOIN machines m2 ON mr.related_machineid = m2.machineid +JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid +JOIN communications c1 ON m1.machineid = c1.machineid AND c1.comstypeid = @ip_comstypeid AND c1.isactive = 1 +WHERE rt.relationshiptype = 'Dualpath' +AND mr.isactive = 1 +AND NOT EXISTS ( + SELECT 1 FROM communications c2 + WHERE c2.machineid = m2.machineid + AND c2.comstypeid = @ip_comstypeid + AND c2.isactive = 1 +); + +-- Insert Serial comm config for dualpath partners that are missing it +INSERT INTO communications (machineid, comstypeid, address, port, baud, databits, stopbits, parity, isactive) +SELECT DISTINCT + m2.machineid, + c1.comstypeid, + c1.address, + c1.port, + c1.baud, + c1.databits, + c1.stopbits, + c1.parity, + 1 +FROM machinerelationships mr +JOIN machines m1 ON mr.machineid = m1.machineid +JOIN machines m2 ON mr.related_machineid = m2.machineid +JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid +JOIN communications c1 ON m1.machineid = c1.machineid AND c1.comstypeid = @serial_comstypeid AND c1.isactive = 1 +WHERE rt.relationshiptype = 'Dualpath' +AND mr.isactive = 1 +AND NOT EXISTS ( + SELECT 1 FROM communications c2 + WHERE c2.machineid = m2.machineid + AND c2.comstypeid = @serial_comstypeid + AND c2.isactive = 1 +); + +-- ============================================================================ +-- VERIFICATION +-- ============================================================================ + +SELECT 'Verification - dualpath pairs after sync:' AS status; + +SELECT + m1.machinenumber AS machine1, + ct1.controllertype AS m1_controller, + mo1.modelnumber AS m1_model, + m2.machinenumber AS machine2, + ct2.controllertype AS m2_controller, + mo2.modelnumber AS m2_model, + CASE WHEN COALESCE(m1.controllertypeid,0) = COALESCE(m2.controllertypeid,0) THEN 'MATCH' ELSE 'MISMATCH' END AS ctrl_status +FROM machinerelationships mr +JOIN machines m1 ON mr.machineid = m1.machineid +JOIN machines m2 ON mr.related_machineid = m2.machineid +JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid +LEFT JOIN controllertypes ct1 ON m1.controllertypeid = ct1.controllertypeid +LEFT JOIN controllertypes ct2 ON m2.controllertypeid = ct2.controllertypeid +LEFT JOIN models mo1 ON m1.modelnumberid = mo1.modelnumberid +LEFT JOIN models mo2 ON m2.modelnumberid = mo2.modelnumberid +WHERE rt.relationshiptype = 'Dualpath' +AND mr.isactive = 1 +ORDER BY m1.machinenumber +LIMIT 20; + +SELECT 'Sync complete!' AS status;