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 <noreply@anthropic.com>
This commit is contained in:
cproudlock
2025-12-10 20:09:56 -05:00
parent f8083be467
commit b4b81b850a
4 changed files with 431 additions and 0 deletions

View File

@@ -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
%>

View File

@@ -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

View File

@@ -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
'=============================================================================

View File

@@ -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;