SECS/GEM data collection is based around three primary concepts, data, represented by VIDs, events, represented by CEIDs which indicate when something of interest has happened at the tool and reports, represented by RPTIDs that link data to events.

The VIDs and CEIDs are defined in the SECS/GEM manual for your tool and you can manually create a SECS/GEM model using the manual - this is the traditional approach to building data collection applications. TransSECS lets you add/edit these in an easy-to-use editor but a much better approach is to request them directly from the tool. TransSECS communicates online with the tool which allows it to query the tool directly for these parameters improving accuracy (SECS/GEM manuals are notoriously unreliable) and speeding development.

Once you have this SECS/GEM model, you can deploy it with one-button push to a .NET assembly. The assembly name follows the name of the tool, so here GEMTool.dll. Including that in your project gives you access to all the features of the SECS/GEM model.

One-time .NET Project Setup

When you first create your project you will need to modify your .csproj to include the TransSECS generated jar. You need to modify the ItemGroup to include the generated .jar file Reference and AssemblyName.

The names should follow your TransSECS project name, so if you're using the GEMHost sample project included with TransSECS and you have copied that jar in the lib folder of your project then you may have a lines like this:

<IkvmReference Include=“lib\GEMHostDotNetRuntime.jar”> <AssemblyName>GEMHostDotNetRuntime</AssemblyName>

If your project was “MySpecialHostProject” and you've again copied the jar to the lib then you'd have this:

<IkvmReference Include=“lib\MySpecialHostProject.jar”> <AssemblyName>MySpecialHostProject</AssemblyName>

Here's the detailed steps using the GEMHost sample project as an example:

* Open a command prompt or PowerShell window.

* Navigate to your project directory.

* Run the following commands:

 
     dotnet add package IKVM
     dotnet add package IKVM.Image.JRE
 

* Open your project's .csproj file in a text editor; you should see the following lines (your IKVM version can be different):

     
     <ItemGroup>
         <PackageReference Include="IKVM" Version="8.4.5" />
         <PackageReference Include="IKVM.Image.JRE" Version="8.4.5" />
     </ItemGroup>
 

* Add the following lines to your .csproj file:

    
    <ItemGroup> 
        <IkvmReference Include="lib\GEMHostDotNetRuntime.jar"> 
            <AssemblyName>GEMHostDotNetRuntime</AssemblyName> 
            <AssemblyVersion>1.0.0.0</AssemblyVersion> 
            <AssemblyFileVersion>1.0.0.0</AssemblyFileVersion> 
        </IkvmReference> 
    </ItemGroup>

* Remember to replace “lib\GEMHostDotNetRuntime.jar” with the path to the generated jar file. You can also change the assembly information as needed.

* Save and close the .csproj file.

Sample Host

The attached example demonstrates a host application. It is a complete, functioning GEM host.

The host is created and configured at the start of the application.

            host = new EquipmentController();
            host.SetEquipmentHostName(hostname);
            host.SetActivePort(portNumber);
            host.SetDeviceId(deviceID);

The host model is created and the connection is made to the tool.

               host.Init();
               host.Start();

The connection is managed and will be recreated by TransSECS whenever it is lost - you do not have to monitor the connection in your code.

Getting notification of events and values is simple - just register for them:

            // Add a listener for event CEID 7502.  Anytime and event 7502 is sent from the tool this event listener will be notified.
            // In the sample tool provided with TransSECS this is the "Completed" event.
            host.AddEventListener(7502, new EventListener());
            // Add a report listener for report RPTID 1001.  Whenever this report is received, regardless of which event the report was associated with, this
            // listener will be notified.  This is usually the most productive listener.
            host.AddReportListener(1001, new EventListener());
            // Add a listener for VID 1510 a value from the tool.  Whenever this value is sent as part of any report or event this listener will be notified.
            // This is the "WaferCount" in the sample tool.
            host.AddVidListener(1510, new EventListener());
            // Add the alarm listener.  All Alarms (S5F1 messages) sent from the tool will be sent to this notification.
            host.AddAlarmListener(new AlarmListener());

To turn this from a demonstration to you full application you need to implement listeners and register them - the samples are at the bottom of the file. Unless you want to control the tool, once that is done your application is ready for production

If you do want to control the tool, select a recipes, start the tool, etc., the sample also contains a demonstration of how to send a “Remote Command” message. All other messages are similar, they're just instances with which you interact.

Using the SECS/GEM model for your tool, you can also create a simulator in TransSECS. This allows you to exercise and test your application without having access to the real tool. That is, you can develop without impacting production.

If you do want to control the tool, select a recipes, start the tool, etc., the sample also contains a demonstration of how to send a “Remote Command” message. All other messages are similar, they're just instances with which you interact.

Using the SECS/GEM model for your tool, you can also create a simulator in TransSECS. This allows you to exercise and test your application without having access to the real tool. That is, you can develop without impacting production.

A simple, manual simulator is deployed directly from TransSECS. You can also build a simulator in .NET if you need a sophisticated solution (see the tool example).

Here's the full code for the C# Host example. This will run against the “StandaloneTool” that is provided as part of the TransSECS installation.

GEMHostExample.cs

using System;
using Deploy.GEMHost;
using Ergotech;
using Ergotech.Util;
using Ergotech.Secs;
using Ergotech.Secs.Gem;
using Ergotech.Transsecs.Secs;
using Ergotech.Vib.Exceptions;
using Ergotech.Vib.Valueobjects;
using Ergotech.Transsecs.Secs.Host;
using System.Collections;
 
 
 
namespace Example
{
    class GEMHostExample
    {
        //you must reference your TransSECS generated dll assembly for EquipmentController
        // this is the representation of the SECS/GEM interface to the tool.
        protected EquipmentController host;
 
        static void Main(string[] args)
        {
            GEMHostExample program = new GEMHostExample();
            program.StartExample();
        }
 
        public void StartExample()
        {
            Ergotech.Util.SimulationManager.GetSimulationManager().SetSimulating(false);
 
            //set up parameters for the tool connection
            String hostname = "localhost"; //IP Address or host name of the tool (probably not localhost)
            int portNumber = 5010; //tool's port number
            int deviceID = 1; //tool's device id
 
 
 
            // Connect to the tool, change parameter values here if needed
            host = new EquipmentController();
            host.SetEquipmentHostName(hostname);
            host.SetActivePort(portNumber);
            host.SetDeviceId(deviceID);
            try
            {
                host.Init();
                host.Start();
                // at this point, the connection to the host is complete.
                // TransSECS has made the connection and configured the tool
                // TransSECS constantly monitors the connection and will recreate
                // and reconfigure the connection whenever the connection is lost.
            }
            catch (BadParameterException e1)
            {
                e1.printStackTrace();
            }
            catch (VIBUpdateFailedException e1)
            {
                e1.printStackTrace();
            }
 
            // Add a listener for event CEID 7502.  Anytime and event 7502 is sent from the tool this event listener will be notified.
            // In the sample tool provided with TransSECS this is the "Completed" event.
            host.AddEventListener(7502, new EventListener());
            // Add a report listener for report RPTID 1001.  Whenever this report is received, regardless of which event the report was associated with, this 
            // listener will be notified.  This is usually the most productive listener.
            host.AddReportListener(1001, new EventListener());
            // Add a listener for VID 1510 a value from the tool.  Whenever this value is sent as part of any report or event this listener will be notified.
            // This is the "WaferCount" in the sample tool.
            host.AddVidListener(1510, new EventListener());
            // Add the alarm listener.  All Alarms (S5F1 messages) sent from the tool will be sent to this notification.
            host.AddAlarmListener(new AlarmListener());
 
        }
 
        /** Send the host command to the tool. Sends the message and waits for a reply.
         * 
         * This is just a sample of how to send any message and receive a response.  "Host Commands" or "Remote Commands" are used to control the
         * tool.  The exact host commands that each tool supports are documented in the tool manual.  Common commands are "PP_SELECT" which selects
         * a recipe and "START" which starts the tool.  This is an example of a "START" command that will also set the PPID (recipe name) and start
         * the tool.
       */
        public void SendHostCommand()
        {
            HostCommandSTART s2f41 = null;
 
            try
            {
                // this is the message as defined in the TransSECS editor.
                s2f41 = (HostCommandSTART)host.GetMessageBean("HostCommandSTART");
            }
            catch (BadParameterException e1)
            {
                e1.printStackTrace();
            }
            //change a recipe parameter value for testing to some random string.
            Random r = new Random();
            // All messages are "flattened" by TransSECS so that setting parameters, regardless of how convoluted the message, is achieved by a simple "Set" method.
            s2f41.SetRecipeName("REC" + r.Next(10));  // sets the recipe name that will be sent to the tool in the message.
 
            try
            {
                HostCommandReply response = (HostCommandReply)s2f41.SendMessageAndWait();
                Console.WriteLine("Host Command Message Status: " + (s2f41.GetDataSource(VIBMessageBean.RESPONSE_STATUS_NAME).GetIntValue()));
                if (response != null && s2f41.GetDataSource(VIBMessageBean.RESPONSE_STATUS_NAME).GetIntValue() == 0)
                { // successful response 
                    // similar to "Set", values can be read from a message with at "Get" method.
                    if (response.GetHCACK()[0] == 0)
                    {
                        Console.WriteLine("Host Command Successful");
                    }
                    else
                    {
                        Console.WriteLine("Host Command Failed" + response.GetHCACK()[0] + " Reason " + response.GetReasonList());
                    }
                }
            }
            catch (SecsException e)
            {
                e.printStackTrace();
            }
            catch (BadParameterException e)
            {
                e.printStackTrace();
            }
        }
 
        /** Return a string describing the response to the message. 
         * 
         *  Possible responses are constants in SecsMsg
         * 
        */
        public String ResponseStatus(int responseCode)
        {
            switch (responseCode)
            {
                case SecsMsg.NO_ERROR:
                    return "Successful - No Error"; // the message was sent and (if appropriate) the response was received.
                case SecsMsg.TIMEOUT_ERROR:
                    return "Message Timed Out";  // no response to the message within T3 timeout
                case SecsMsg.S9_ERROR:
                    return "S9 Message Reponse";  // the tool does not understand the primary and return an S9 message (probably S9F5 or S9F7)
                case SecsMsg.F0_ERROR:
                    return "F0 Message Response";  // the tool return an SxF0 message. This usually means that the tool is offline or online local
                case SecsMsg.CANNOT_SEND:
                    return "No Connection to Tool"; // there is no connection to the tool, the message cannot be sent.
                case SecsMsg.UNSOLICITED:
                    return "Unsolicted Message"; // this is not a repsonse, but a primary message received 
            }
            return "Unknown";
        }
    }
 
 
 
    /** The event listener class.  Instance of Ergotech.Transsecs.Secs.Host.EventListener can be registered to receive 
     * notification when an event is received.
     */
    class EventListener : Ergotech.Transsecs.Secs.Host.EventListener
    {
        public void EventReceived(GemHostModel.GemReportVariable ceid, IList @event)
        {
            Console.WriteLine("Event Received " + ceid);
        }
    }
 
    /** Instances of Ergotech.Transsecs.Secs.Host.AlarmListener can be registered to receive all alarm notifications. 
     */
    class AlarmListener : Ergotech.Transsecs.Secs.Host.AlarmListener
    {
        public void AlarmReceived(AlarmValues alarmValues)
        {
            Console.WriteLine("Alarm Received " + alarmValues);
        }
    }
 
    /** Instances of Ergotech.Transsecs.Secs.Host.ReportListener can be registered with the host and will be notified whenever
     * a particular report is received.  This notification will occur regardless of which event the report was attached to.
     */
    class ReportListener : Ergotech.Transsecs.Secs.Host.ReportListener
    {
        public void ReportUpdated(ReportValues report)
        {
            Console.WriteLine("Report Received " + report.GetVidValues());
        }
    }
 
    /** An instance of Ergotech.Transsecs.Secs.Host.VidListener can be registered to receive notification of any received value.
     * This will occur regardless of which report contains the value.
     */
    class VidListener : Ergotech.Transsecs.Secs.Host.VidListener
    {
 
        public void VidUpdated(GemHostModel.GemValueVariable value)
        {
            Console.WriteLine("VID Received " + value);
        }
    }
}