=====Startup Trigger Another Example: Retrieves Tool dynamically from the controller===== This page documents the **Generic Host StartupTrigger** used in TransSECS systems. The script initializes a SECS/GEM host controller, configures database connections, sets up connection listeners, and marks the tool as initialized. It is designed to **only run when the system is LIVE**, the incoming value quality is good, and the script has not already been executed. It ** retrieves `toolID` and `toolName` dynamically from the controller**. ====== Script Behavior ===== * Only executes when: - The system is not simulating (`SimulationManager.getCurrentSimulationState() == false`) - Incoming value quality is 0 (`incomingValue.getQuality() == 0`) - Initialization flag is not set (`/Devices/UtilityServers_Servers/Initialized->getIntValue() == 0`) * Fetches the host controller dynamically using `getSingleController()`. * Sets the host communication port to 5000. * Retrieves `toolID` and `toolName` dynamically from the controller. * Configures the database connection. * Registers a connection status listener with safe removal of any existing listener. * Marks the tool as initialized at the end. ======Full script====== // ========================================================== // Generic Host StartupTrigger for TransSECS // This script initializes the SECS/GEM host controller, // sets up database connection configuration, and registers // a connection status listener. // // It only runs when: // - The system is not simulating // - Incoming value quality == 0 // - The script has not already run (Initialized flag) // // Key Features: // - Retry logic for host controller discovery // - Dynamic fetching of toolID and toolName from the controller // - Safe listener setup (removes existing listener if present) // - Detailed logging for each step // ========================================================== // ------------------ Java Imports ------------------ var TransSecsController = Java.type("com.ergotech.transsecs.secs.TransSecsController"); // Host controller access var ConnectionStatusListener = Java.type("com.ergotech.transsecs.secs.host.ConnectionStatusListener"); // Listener for SECS/GEM connection status var SimulationManager = Java.type("com.ergotech.util.SimulationManager"); // Check if system is simulating var DataSource = Java.type("com.ergotech.vib.servers.DataSource"); // Logging utility var ValueChangedEvent = Java.type("com.ergotech.vib.valueobjects.ValueChangedEvent"); // For updating ToolStatus table var StringValueObject = Java.type("com.ergotech.vib.valueobjects.StringValueObject"); // Generic string container for ValueObjects var Thread = Java.type("java.lang.Thread"); // For background initialization thread var LinkedHashMap = Java.type("java.util.LinkedHashMap"); // Map structure for ToolStatus updates var System = Java.type("java.lang.System"); // Access system properties // ------------------ Guard Checks ------------------ // Fetch simulation state var simulationManager = SimulationManager.getSimulationManager(); var isSimulating = simulationManager.getCurrentSimulationState(); // Check incoming value quality var incomingGood = incomingValue.getQuality() == 0; // Check if this script has already initialized var alreadyInitialized = /Devices/UtilityServers_Servers/Initialized->getIntValue() == 1; // Only proceed if the system is LIVE, incoming value is good, and not already initialized if (!isSimulating && incomingGood && !alreadyInitialized) { // ------------------ Start Initialization Thread ------------------ var r = new java.lang.Runnable({ run: function() { try { // Log start DataSource.logMessage("StartupTrigger: Initialization starting..."); // ------------------ Discover Host Controller ------------------ var retries = 0; var tool = TransSecsController.getSingleController(); // Fetch the host controller while (tool == null && retries < 50) { Thread.sleep(100); // Wait 100ms before retry retries++; DataSource.logMessage("StartupTrigger: Retry #" + retries + " - Waiting for host controller..."); tool = TransSecsController.getSingleController(); } if (tool != null) { DataSource.logMessage("StartupTrigger: Found host controller after " + retries + " retries."); // ------------------ Configure Tool ------------------ // Set communication port (must match host settings) tool.setPort(5000); DataSource.logMessage("StartupTrigger: Tool port set to 5000."); // Dynamically fetch toolID and toolName from the controller var toolID = tool.getDeviceId(); var toolName = tool.getControllerName(); DataSource.logMessage("StartupTrigger: toolName=" + toolName + ", toolID=" + toolID); // ------------------ Database Configuration ------------------ DataSource.logMessage("StartupTrigger: Configuring database connection..."); var userName = System.getProperty("dbusername", "username"); // Default fallback var password = System.getProperty("dbpassword", "password"); var ipaddress = System.getProperty("dbAddress", "dbaddress"); var dbName = System.getProperty("dbName", "dbname"); var portStr = System.getProperty("dbPort", "1433"); var port = parseInt(portStr, 10); // Reference to DatabaseConnection server var DBManager = "/Devices/DatabaseConnection"; DBManager-->setUrl("jdbc:sqlserver://" + ipaddress + ":" + port + ";databaseName=" + dbName); DBManager-->setUsername(userName); DBManager-->setPassword(password); DBManager-->setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); DataSource.logMessage("StartupTrigger: DatabaseConnection URL set to " + DBManager-->getUrl()); // ------------------ Connection Status Listener ------------------ try { DataSource.logMessage("StartupTrigger: Setting up connection status listener..."); // Create a listener for host connection events var connectionStatusListener = new ConnectionStatusListener() { connectionStatusChanged: function(connectionStatus, comment) { // Log each status change DataSource.logMessage("ConnectionStatusListener: Status Changed: " + comment + " (" + connectionStatus + ")"); // Update CheckDatabaseConnection for monitoring /Devices/UtilityServers_Servers/CheckDatabaseConnection->setIntValue(connectionStatus); // Update ToolStatus table in DB if database is available var dbStatus = /Devices/UtilityServers_Servers/DatabaseOK->getIntValue(); if (dbStatus != 0) { var vo = new StringValueObject("StatusUpdate"); var map = new LinkedHashMap(); map.put("ToolStatusCode", new StringValueObject(connectionStatus)); map.put("ToolStatus", new StringValueObject(comment)); vo.setProperty("MAP", map); /Devices/UtilityServers_Servers/UpdateToolStatusTable->valueInput(new ValueChangedEvent(this, vo)); DataSource.logMessage("ConnectionStatusListener: ToolStatus table updated."); } // Log specific connection state messages if (connectionStatus == 10) { DataSource.logMessage("ConnectionListener: SECS/GEM connection established."); } else if (connectionStatus == 0) { DataSource.logMessage("ConnectionListener: GEM host configuration completed."); } else if (connectionStatus < 0) { DataSource.logMessage("ConnectionListener: WARNING: Connection issue detected: " + comment); } } }; // Fetch existing listener ValueObject var onlyOnce = /Devices/UtilityServers_Servers/ConnectionListenerSetup->getValueObject(); if (onlyOnce == null) { onlyOnce = new StringValueObject("ConnectionListenerSetupVO"); DataSource.logMessage("StartupTrigger: Created new ConnectionListenerSetup ValueObject."); } // Remove existing listener if present var existing = onlyOnce.getProperty ? onlyOnce.getProperty("Listener") : null; if (existing != null) { try { tool.removeConnectionStatusListener(existing); DataSource.logMessage("StartupTrigger: Removed existing listener before adding new one."); } catch (err) { DataSource.logMessage("StartupTrigger: Exception removing existing listener: " + err); } } // Register the new listener onlyOnce.setProperty("Listener", connectionStatusListener); /Devices/UtilityServers_Servers/ConnectionListenerSetup->setValueObject(onlyOnce); tool.addConnectionStatusListener(connectionStatusListener); DataSource.logMessage("StartupTrigger: Connection Status Listener registered successfully."); } catch (e) { DataSource.logMessage("StartupTrigger: Error setting up connection listener: " + e.stack); } // ------------------ Mark Initialization Complete ------------------ /Devices/UtilityServers_Servers/Initialized->setIntValue(1); DataSource.logMessage("StartupTrigger: Initialization complete for tool " + toolName); } else { DataSource.logMessage("StartupTrigger: ERROR - Could not get host controller after " + retries + " retries."); } } catch (e) { DataSource.logMessage("StartupTrigger Error: " + e.stack); } } }); // Run initialization in a separate thread to avoid blocking new Thread(r).start(); } // Return incomingValue as required incomingValue;