SecsHostCpp - A C++ Class for Host SECS Interfaces


The SecsHostCpp class library provides a high-level starting point when deploying Host SECS Interface software using C++ on Windows or POSIX/Linux platforms.  Without any code development, the software is able to communicate with GEM standard equipment, manage dynamic Event Reports, upload and download process programs, and manage Equipment Constant values.  The software also imbeds extensive fallback logic that accommodates working with non-standard and non-GEM compliant equipment.  A demonstration console application is provided with source code that enables you to configure and manage multiple Host interfaces.  The SecsHostCpp class can be imbedded and deployed in an application of your own design.  An application developer registers callback handlers to receive asynchronous inputs such as Event Reports, Alarm Reports, or specified SECS message types.  The example application code demonstrates using these techniques without undue complexity.  You can readily understand how to use the class and get on with building your own application.

Feature Summary


User Guide


The Hume C++ SECS Host .zip download archive is named  SecsHostCpp<xxx>.zip. where <xxx> has values such as Win32, Win64, Linux_i686, or Linux_x86_64 to indicate the platform.  If you received the DMH software on CDROM, this archive is in the subdirectory LAN_IMAGE.   The distributions also contain DLLs for the DMH Multi-Threaded C library and the Pthreads library.  The Win64 distribution has example project files and 32bit and 64bit DLLs built with Visual Studio 2010, and the Win32 distribution has project files for VS2005 and 32 bit binaries that are built with VS2005.  In addition there is a Win64-vs17 distribution that is the same as the Win64 distribution except for being built with Visual Studio 2017. If you are using a Visual Studio newer than 2010, download the Win64 or Win64-vs17 archive instead of the Win32 archive;  the solution and projects import easily into new versions.

Here is an overview of the project files for the class library and example applications.  The main folder for the SecsHostCpp distribution contains several files and several subdirectory folders which are described next. 

The files seen in the top level folder, SecsHostCpp, depend on which download archive is installed. 

A Linux or POSIX developer sees:

The distributions contain the following subdirectory folders:

The SecsHostCpp subdirectory folder contains resuable SECS interface logic that the developer will not usually modify:

The SecsHostConsoleApp subdirectory folder contains source code for a console demonstration application that is portable to Linux, Windows, and other POSIX systems. The dmh subdirectory folder contains DMH message system library dependencies for all versions.

Installation

Installation of the SecsHostCpp software consists of extracting the files in the platform specific archive to a directory of your choice, and installing the Hume Datahub SDK.  If you have already installed the Hume Datahub SDK,  you should not add the files in the SecsHostCpp archive to any of the existing Datahub SDK GEM application directories.  The SecsHostCpp class is able to find and use the Datahub SDK GEM directories without usage of a common directory.

The stored paths in the Windows .zip archive and the existing project settings and makefiles assume several peer level directories and their subdirectories.  For example, if you unzip the archive in the directory C:\Users\hume, you will recreate our development directory structure as follows

    c:\Users\hume\SecsHostCpp
|- SecsHostCpp
|- SecsHostConsoleApp
|- release (and/or release64)
|- debug (and/or debug64)
|- dmh
|- win32_release (and/or win64_release)
The .zip archive has some copies of the same DLL files in both the application release and debug directories to simplify your building and executing debug or release versions of the projects.   

The SecsHostCpp software uses the SECS/GEM application files provided in the Hume Datahub SDK product.  A developer needs to install the Hume Datahub SDK, and specify on the SETUP screen that the GEM/SECS applications should be installed.  The SecsHostCpp startup code is able to find the Datahub SDK files using the environment variable DMH_BIN which is set when the Datahub SDK is installed.

The situation can be simplified for a runtime deployment of your host SECS interface.  Instead of installing the Datahub SDK, you can simply deploy a single file executeable, SecsServer.exe.  This file is provided by Hume Integration for the usual case of using the as-provided SDK files.  If you have customized the SDK files, you are able to create a custom version of SecsServer.exe using a build script.  We encourage you to use the full SDK during development so that you have the toolset documentation, the debugging tools, and you are able to view the SDK GEM application source code.  When you are ready for deployment, you can download the SecsServer.zip archive from the Hume customer support website to obtain the SecServer.exe program and its build script.  There are different SecsServer download archives for Windows, Linux, or other platforms.  There are not separate 32bit and 64bit SecsServer versions.

Installing the POSIX version is similar to the Windows version.  You can unzip the archive in a convenient directory of your choice.  You face the same choice of using the files with either the Datahub SDK installed, or with the SecsServer executable for your platform.  You need to make sure the environment variable DMH_BIN is set and exported if the Datahub SDK is being used.  The environment variable described below should be set for all platforms.

Environment Variable SECS_EQUIP_TCLDIR

When a SecsHostCpp instance is constructed, it needs to find the Datahub SDK files or the SecsServer.exe executable. The startup logic first looks for the SecsServer.exe program in (1) the directory pointed to by the environment variable SECS_EQUIP_TCLDIR and then (2) the current working directory, and then (3) one or two directory levels up from the current working directory, which is the common development scenario when an executable is run from the Debug or Release subdirectories.   If the SecsServer.exe program is not found, then the startup logic looks for the SecsServer.tcl application script and the supporting files that are part of the Datahub SDK.  The search order for the SecsServer.tcl file is (1) the directory pointed to by the environment variable, SECS_EQUIP_TCLDIR,   and (2)  the gem2/server directory of the Datahub SDK installation found using the environment variable DMH_BIN or by checking the default installation path.  Alternately, you may set the environment variable SECS_EQUIP_TCLDIR to the directory path containing the SecsServer executable or the SecsServer.tcl application script.  This gives you the ability to deploy the executables with whatever directory structure you desire.  Use slash directory separators on all platforms.  On Windows, environment variables are set by navigating from the Start menu - Start/Settings/Control Panel/System/Advanced/Environment Variables.  An example value is:
SECS_EQUIP_TCLDIR=C:/usr/local/gem2/server
In a runtime deployment, the SecsServer executable file is placed in the directory of your choice as specified by the SECS_EQUIP_TCLDIR environment variable.   A licenses.txt file is also installed in this directory.  You can execute the SecsServer program from the command line with the single argument -license to perform a check of the runtime license installation.  The default directories used for process program transfer and for non-volatile storage are subdirectories of where the SecsServer or SecsServer.tcl file is found.

You can check the validity of the Datahub SDK installation by executing the DMH Wish (dmh_wish) program and looking for a message in the console window.  There is no message when a permanent and proper license is found.  If a temporary license is used, there is a message specifying how many days remain before expiration.

On POSIX systems, the SecsServer executable does not use X-Windows if the DISPLAY environment variable is either not defined, or defined to be an empty string.   This gives you the capability of executing without being tied to any display.

The same environment variable, SECS_EQUIP_TCLDIR is used for both the SecsHostCpp and SecsEquipCpp class libraries.  This facilitates using both host and equipment instances in the same program as you would to provide a single equipment interface to a set of linked equipment.

Environment Variable HUME_SUPERVISOR_DIR

An application that uses the supervisorStart() method can be told to use a specific base working directory for application data files by setting the environment variable, HUME_SUPERVISOR_DIR.  The directory can be specified as a relative path to the C++ app working directory, or as an absolute path.  Unix style slashes should be used on all platforms.  The directory should already exist.  The default directory for application data files is the Datahub SDK gem2/server directory or the directory where the SecsServer[.exe] program is found.  The file system is used for saving and loading *.tab SQL files, log files, and recipe transfers.

A custom application can use the setServerDir() method call to explicitly set the working directory for application data files.  If this method is called any setting of the HUME_SUPERVISOR_DIR environment variable is ignored.

Development

To start using the Hume C++ SecsHostCpp class with an existing Visual Studio project, you add the files in the SecsHostCpp subdirectory to your project files.  A Windows developer edits his application project:
  1. Add the SecsHostCpp.h, DmhCppClient.h header files to the project
  2. Add the SecsHostCpp.cpp, DmhCppClient.cpp source files to the project
  3. Add the dmh/dmh.h file as a project header file, or tell the C Preprocessor where to find it. 
  4. Add the dmh.lib or dmh64.lib to the project link dependencies.
  5. Copy the dmh and pthread DLLs from the release or release64 directory to your project release and debug directories.  Release versions of the DMH and Pthreads library are used for both debug and release application builds.
Your primary focus as a developer is using the class SecsHostCpp.  This class implements public methods to send and receive SECS messages, and manage a host SECS interface.  You will look closely at the sample application, particularly the initialization code, and basically copy and edit the SECS interface initialization code.

Here is the general flow of using and configuring the SecsHostCpp:

  1. Setup your error handler callback first by setting the SecsHostCpp::secsServerErrorCallback static pointer item.  Your application may receive error notifications if the license or software installation are not proper when you try to instantiate a SecsHostCpp instance.  Therefore, have the error handling in place first so you can provide the user notification of any errors.
  2. Construct a SecsHostCpp instance.   At runtime, constructing the instance causes the child SECS server process to be started.  The SupervisorStart method uses a constructor that passes many of the configurable property values in a saved and restored SecsHostStartupData structure.  There are also simpler constructors where you create your instance, and subsequently use property assignment statements to configure the instance.
  3. Setup your event handlers for event callbacks.  The reception of Event Reports and Alarm Reports are dispatched into your application as events.  Set the stateChangeCallback pointer to receive StateChange events.  Once the next step is taken, your StateChange callback is executed to provide you with initial values of state data.  In general the callbacks are executed from a different thread than the main thread that started your application.
  4. Use saved user configuration data to know the desired startup connection properties such as the HSMS socket port and whether the active or passive role is desired.  Our example console application uses the startupLoad() and startupRestore() methods to load and apply saved startup configuration data.  The startupRestore() method uses configuration data that was saved in a prior session by calling superSave(). If you choose not to use the startupRestore() method, then you must call connectTypeHsmsPassive(), connectTypeHsmsActive(),  connectTypeSerial(), or connectTypeTerminalServer() to set the connection type.  When the connection type is set, the SECS server creates a data array and table records for the SECS interface.  Some of the other configuration method calls require the table records or the array being present.  So a connectType call should be made early in the initialization.  Its ok to call a connectType method with default argument values, and later in the initialization, make another connectType call with other argument values.  The important point is to make the connectType call early.
  5. Use the messageTypeAdd method to register callback delegates for SECS message types that you desire to handle in your application.  Getting communication established and capturing alarms and event reports is already provided for.
  6. At this stage, your application logic can edit the configuration of event reports.  GEM equipment supports letting the host discover status variables and parameters,  so interactive report configuration is usually done after being online and discovering the data items, or after restoring the data items known in a previous session.  If your equipment lacks support for discovery, at this point you can call the manual configuration methods such as variableAdd and eventAdd.  Proper GEM equipment may lack features for the discovery of events and DVVAL variables.  The Hume equipment software features description variables to provide the host with this configuration information so that manual configuration of these items is not necessary.
  7. Now, with your desired configuration in place, call commEnable to enable communication with the equipment.  The establishment of communication takes place some time after the call returns.  If you want to exchange SECS messages with the equipment, trigger your custom logic from receiving the AUTO_VIRT_INIT event report.  This event report occurs every time after an online control state has been entered and the automatic initialization has performed the event report setups.  You will receive this event after recovery from any communication interruption in the future in addition to during the startup.  You can use the AUTO_INIT_RESULT variable to determine whether the initialization logic ran successfully.  See the eventReportDefine method, the list of Built-in events, and the eventReport event description.  You can also receive status indications from the StateChange event.  You do not need to re-invent initialization logic - take advantage of the configurable and robust automatic initialization by using the AUTO_VIRT_INIT event.
  8. If you update any of the connection properties after communication is enabled, call connectTypeSet or one of the ConnectType<Type> methods.  The method call will disable communication so you will need to call commEnable again.  Connection properties include the ConnectionType, BAUD, HsmsHostname, HsmsPassive, HsmsPort, and SerialPort.
  9. Non-connection properties such as the Device ID, timer values, data types, etc. can be updated at any time without disrupting communication.  The Hume software does feature adaptive logic to automatically correct the Device ID, and to learn the data types used by the equipment.  Your configuration effort is substantially reduced compared to other products.
  10. Automatic initialization occurs by default whenever the equipment transitions to an online control state.  The default behavior is to attempt to discover the equipment's alarms, variables, and events, and setup the configured event reports, managed alarms, managed equipment constants, and synchronize the clock.  This behavior is controlled by setting the appropriate property values and/or configuring the managed reports, alarms, or constants.
  11. Call commDisable to disable host communications.  It is called automatically when the SecsHostCpp instance is deleted.

Tcl Secs Notation

SECS messages are passed into and out of the application as formatted strings.  The format is similar to the notation in the SEMI documents except that the list formatting conventions of the Tcl programming language are followed.  The SecsHostCpp class provides methods to split, join, append, and extract list elements.  In general, curly braces, { }, are used to surround list elements which contain white space.  By using the API calls to append list elements or join strings as list elements, you can be sure that your strings are properly formatted, and you do not need to manually balance opening and closing curly braces.  Developers who have worked with both XML and TSN list notation have found that the TSN notation is more compact, closer to the SEMI documentation, and easier for a human to scan and validate when reviewing diagnostic output.

As general guidance, when you expect a string value, you will get a two element list, of the form "A:n {this is n chars of text}".  If a string value does not have imbedded white space, it may be formatted without braces, such as "A:8 OneToken".  When you use the listElement or listSplit methods to parse the text, they take care of parsing and removing surrounding braces for you.  If an empty string is sent, you will see a one element list, A:0.  With ASCII string data that contains null characters, a two byte seqence, 0xc0 0x80, is used to represent each null character in C++ string data and in the Tcl SECS Server environment.  This modified UTF-8 representation allows using C runtime library routines that are designed for null-terminated strings with TSN message data.

SECS has the notion of array data - 0 or more values of a given type.  When you expect to receive a single numeric value, you receive a two element list, with the type code as the first element, such as "U4:1 290".  You can also receive an empty array "U4:0" or an array with more than one value as in "U4:3 0 1 2".  Binary data values are formatted using C-language hexadecimal integer notation, for example, "B:3 0x00 0x01 0x02".  You can use the binToInt method to convert these values to integer values.  With received data, the type code has a length value appended to it after a colon.  With data that you format for sending, the length information is optional, the data is parsed to determine the length.  See the TSN.html document for more details.
 
Semi Octal type code TSN type code Meaning & Examples
00 L List,  L, L:0,   "L {A {atc 100}} {A 1.0.0}", "L:2 {L:2 {U4 200} {U4 210}} {B 0}"
10 B binary - unsigned 8 bit data, "B 0", "B 1 2 3"
11 TF  boolean data, TSN type codes BL or BOOLEAN are also accepted as input, "TF 1"
20 A Character string data.  Traditionally this has meant printable ASCII characters but some implementations are sending any 8 bit characters including nulls using this type.
"A {hello world}", "A hello"
21 J Japan International Standard (JIS-8) encoded text.  This format is not commonly used or supported because in the past the SEMI standards have failed to identify specific reference documents.
22 V1..VE Variant data, also known as Localized Character Strings.  Your .NET unicode text is automatically converted into the chosen encoding.  V1 is for Unicode 2.0, V2 is for UTF-8 encoding.  See the TSN.html document for more details. "V1 {sent as Unicode}"
30 I8 8-byte signed integer, "I8 123"
31 I1 1-byte signed integer, "I1 -3"
32 I2 2-byte signed integer, "I2 99",  "I2 15 -7 99"
34 I4 4-byte integer signed, "I4 -5"
40 F8 8-byte floating point, "F8 6.02e23", "F8 0.1"
44 F4 4-byte floating point, "F4 1.0"
50 U8 8-byte unsigned integer, "U8 927"
51 U1 1-byte unsigned integer, "U1 0"
52 U2 2-byte unsigned integer, "U2 512"
54 U4 4-byte unsigned integer, "U2 979"

 

Built-in SECS Data, Message Handling, Events

The SecsHostCpp class has built-in logic to handle many of the standard SECS message types.  You do not have to code or provide for complex GEM capabilities such as configuring and receiving dynamic event reports, or managing the equipment communication and state models. See the table at the end of this document for more detail on the built-in message types.  If you are not familiar with the Hume host SECS software, you may wonder if the example application is missing code to manually add variable definitions or event definitions.  In most cases, the software automatically determines the Status Variables and Equipment Constants by querying the equipment.  The SECS standards lack support for directly determining types of events.  The software listens to the events reported by the equipment, and adds them to its table of known event types.  If new Status Variables are seen in an Event Report, the software automatically saves configuration records for the newly discovered variables.  So instead of laboriously configuring event and variables from some inaccurate manual, you simply deploy the software, and run the equipment to accumulate configuration information.  Discrete Variable Event Reports (S6F3) and Discrete Variables are another area where the standards are deficient, and do not provide for programmatic introspection.  The built-in logic saves configuration information on the format of Discrete Event Reports and their included variables as they are encountered.  The class library has the ability to copy the accumulated configuration information determined from an equipment interface to new names.  This provides the ability to clone working interfaces for use with multiple instances of similar equipment in your factory.  In the rare circumstances where you want to manually make configuration changes, you can use the debugTableWindow method to bring up a GUI that enables you to interactively examine, edit, and save the SECS Server configuration tables.   There are also methods provided to explicitly define items in code statements.
 

Custom SECS Message Handling

Use the method messageTypeAdd to have SECS messages routed to your event handling code.  Use sendReply to respond to the inbound message.  The method sendSecsMsg can be used to initiate sending a new SECS message with optionally waiting for a reply message.   If you do not choose to wait for a reply, sending a new message is nearly instantaneous.  When waiting for a reply, your application can continue to receive report events, or alarms that are delivered using a different thread.   The API is threadsafe so if you want to start and use your own threads to make method calls, you may.  Multiple invocations of sendSecsMsg by different threads are serialized in a DMH message system queue so if you wait for replies, each send and reply is processed before the next one is sent.

You should never wait for a reply unless you have a valid reason to do so.   You can use the messageTypeAdd to register handling code for the asynchronous receiving of replies too.

Miscellaneous Notes

You can use multiple instances of the SecsHostCpp class to provide more than one SECS interface.  Each interface can have its own custom handling of message types.  You may also use multiple instances of the Hume SecsEquipCpp equipment component in the same application.  A typical use of multiple host instances is to act as a host for sub equipment and provide a single control interface to the factory software.

SecsHostCpp API Reference


 
SecsHostCpp Properties
Property Access Description
bool getAutoInit(void)
void setAutoInit(bool)
Configures whether the interface should execute initialization logic automatically when an online control state is established or re-established.  Since the actions performed during initialization are configurable using other properties, most application will configure the individual actions, and leave this overall flag at its default value of true.
bool getAutoStart(void)
void setAutoStart(bool)
Configures whether the interface should be started automatically with communication enabled.  This property is used if the interface is created using the constructor method that accepts the property values as string array arguments.  The default value is false.
 int getBAUD(void)
 void setBAUD(int baudrate)
If you are using the SECS-I, RS-232 connection type, this property sets the baudrate of the serial port.  The default value is 9600.
const char *getCeidOffline(void)
void setCeidOffline(const char *)
The event report identifier (CEID) that signifies that the equipment is transitioning to an off-line control state.  This value is used by the logic that tracks the equipment control state.  The default value is "4000".
static DmhCppClient & getDmh() SecsHostCpp instances use a shared connection to the DMH message system in order to communicate with the SECS server process.  The connection reference is available in case you want to access it in your application. 
const char *getCommState(void)

CommStateEnum getCommStateEnum(void);

enum CommStateEnum { CommUnknown=-1, CommDisabled=0, CommEnabledNotCommunicating=1, CommCommunicating=2};
Read-only value of your GEM Communication State.  Possible values are DISABLED, ENABLED {NOT COMMUNICATING}, and COMMUNICATING.   The StateChange event is used to obtain asynchronous notification of this property value change.
int getConnectionType(void)
void setConnectionType(int ct)
Configures the basic choice of connection type.  IntelliSense prompting shows the choices.  The value 0 means SECS-I RS-232, 1 means SECS-I terminal server, 1993 is for non-standard Draft HSMS, 1995 is for standard HSMS.  The default is 1995.
const char *getControlState(void) A read-only value of the GEM Control State.  Possible values are OFF-LINE and ON-LINE.
int getDEVID(void)
void setDEVID(int DEVID);
The SECS Device ID.  An identifier imbedded in SECS header data usually left at the default of 0.  The SecsHostCpp software has adaptive logic to correct an improper value.  Settable range is 0..32767.
static const char * getGroupName() The DMH message system groupname used by the SECS server.  The same groupname should be specified to the constructor of every SecsHostCpp or SecsEquipCpp instance in the application in order to share the same SECS server process.
const char *getHsmsHostname(void)
void setHsmsHostname(const char *h)
For an active HSMS connection, specifies the TCP/IP hostname or IP address of the Equipment computer.  The default value is "localhost".
 bool getHsmsPassive(void)
void setHsmsPassive(bool p)

For an HSMS connection, whether the SecsHostCpp plays the passive, TCP/IP server role.  The default value is false since the usual role for the host is non-passive. 
int getHsmsPort()
void setHsmsPort(int p)
For an HSMS connection, the TCP/IP socket port number.  Defaults to 5555.
static SecsHostCpp *getInstance(const char *name); The getInstance() static method returns a pointer to the named SecsHostCpp instance.   If the named instance does not exist, then a NULL pointer is returned.
static void getInstances(std::vector<std::string> &names);
The static getInstances() method returns a vector of names for the instantiated SecsHostCpp objects. 
 
bool getMULT(void)
void setMULT(bool b)
A flag used for SECS-I only to specify whether the equipment can handle owing more than one reply at a time.  The default value is true.
const char *getName();
The SecsHostCpp name passed to the constructor and used in the SECS server process as a Tcl command name, a global array name, and an identifier in SQL table records.
bool getPPbodyFileMode()

void setPPBodyFileMode(bool isFileMode)
This boolean property controls whether S7F3 and S7F6 process program transfer messages are handled by direct data transfers to and from files bypassing handling the messages in memory.  This avoids possibly large memory allocations and enables transferring process programs that are as large as the 16 meg limit of Stream 7.   Setting the option also reduces the data that is seen by tracing and logging - only summary information can be seen in the diagnostics.  The default value is false.  It is recommended to set the option true if process programs sizes are as large as 1 meg.  The mode is transparent to the application; the processProgramDownload and Upload methods work the same and the built-in SECS Server Stream 7 receiving with StateChange notifications work the same irrespective of the PPbodyFileMode setting.
const char *getRecipeDirectory(void)
void setRecipeDirectory(const char *RecipeDirectory)
A pathname to the file system directory where Process Program files are located.  The default value is the relative subdirectory  "<Name>_recipes" of the directory where the SECS server is executing.  Note that by default, each interface has its own directory for Process Program files.  Reading this property returns the absolute directory path to the process program directory.

bool getReportsClear(void)
void setReportsClear(bool)
This boolean property controls whether to delete all existing event reports during initialization before defining new ones.  When this value is false, the report definition logic deletes reports one at a time as each new report is defined to make sure the report ID is not in use  The value can be set true to eliminate possible undesired event reports, or to have only a single deletion message sent when setting up new reports. The default is false. 

bool getReportsEnable(void)
void setReportsEnable(bool)
Setting this boolean property true insures that all equipment based events are enabled for reporting during initialization.  If the value is set false, only the events that are specifically configured with data reports or for being enabled are enabled.  However, if there are no event reports configured, then all equipment based event reports are enabled irrespective of this property setting.  So, the meaning of the property is to  insure that all equipment based events are enabled, and the false value is not used for disabling event reports. The default value is true. 

bool getReportsUnlink(void)
void setReportsUnlink(bool)
This boolean property accommodates certain equipment that requires the S2F35 report link message to be sent first with an empty list of reports, and then sent again with the desired reports.  The target equipment features built-in reports that must be explicitly unlinked in this manner.  The default value is false. meaning extra S2F35 messages are not sent.  The property value affects the event report setup logic that executes when Initialize is called, or during automatic initialization.
int getRTY(void)
void setRTY(int RTY);
SECS-I maximum send retry, range 0..31, default 3
const char *getSerialPort()
void setSerialPort(const char *SerialPort)
For a SECS-I connection, the serial port device such as "COM1".  The default value is "COM1" on Windows and "/dev/ttyS0" on POSIX systems.

static const char *getServerDir()

static void setServerDir(const char *directory)
The default directory for file system saving and loading is where the SecsServer[.exe] program is found, or where the Datahub SDK gem2/server directory is found.  This property can be set by a custom application in order to specify a different base directory for file system writing and reading.  The directory argument may be relative to the C++ application working directory or an absolute directory path specification.  Use slashes for path separators, for example, "C:/Users/cim/data".  When used, the property must be set before supervisorStart() is called or any connections are instantiated, and may only be called once.  Specifying a system environment variable, HUME_SUPERVISOR_DIR, with the desired directory value works as an alternative to using this method for applications that call the supervisorStart() method.  Setting the property affects all SECS connection instances including possible SecsEquipCpp instances which are using the SECS Server process.

Applications that directly instantiate SecsHostCpp instances instead of calling supervisorStart() can also use this property to specify the root working directory for file system writing and reading for all SecsHostCpp instances.  The property value must be set before instantiating any SECS connections.  Here we assume these apps do not use the SecsHostCpp constructor that uses StartupData structures as the supervisor app does.
const char *getSpoolInit(void)
void setSpoolInit(const char *)
Controls initialization of equipment spooling.  The allowed values are PURGE, UNLOAD, or IGNORE.  The default value is UNLOAD.
const char *getState(void)
A read-only value of the low-level connection state.  Possible values include OFFLINE, LISTENING, and COMMUNICATING.  You will see the OFFLINE state if the connection to the host is broken, or in the case of SECS-I implicitly broken by a conversation timeout.  The StateChange event is used to obtain asynchronous notification of this property value change.
int getT1(void)
void setT1(int millisecs)
SECS-I Inter-Character Timeout in milliseconds, range 100..10000, default 500
int getT2(void)
void setT1(int millisecs)
SECS-I Protocol Timeout in milliseconds, range 200..25000, default 10000
int getT3(void)
void setT1(int millisecs)
SECS Reply Timeout in milliseconds, range 1000..120000, default 45000
int getT4(void)
void setT1(int millisecs)
SECS-I Inter-Block Timeout in milliseconds, range 1000..120000, default 45000
int getT5(void)
void setT1(int millisecs)
HSMS Connect Separation Timeout - the delay between re-connection attempts in milliseconds, range 1000..240000, default 10000.  The T5 timer value is also used for SECS-I host logic as a retry timer for communication attempts.
int getT6(void)
void setT1(int millisecs)
HSMS Control Transaction Timeout in milliseconds, range 1000..240000, default 5000
int getT7(void)
void setT1(int millisecs)
HSMS Not Selected Timeout in milliseconds, range 1000..24000, default 10000
int getTRACE()

void setTRACE(int trace)
static const int values:

TRACE_READ_WRITE_IO=1;
TRACE_STATE_LOGIC=2;
TRACE_RECV_HDR_HEX=0x0100;
TRACE_RECV_HDR_INTERP=0x0200;
TRACE_RECV_SF_DESC=0x0400;
TRACE_RECV_MSG_HEXDUMP=0x0800;
TRACE_RECV_MSG_TSN=0x0004;
TRACE_SENT_HDR_HEX=0x1000;
TRACE_SENT_HDR_INTERP=0x2000;
TRACE_SENT_SF_DESC=0x4000;
TRACE_SENT_MSG_HEXDUMP=0x8000;
TRACE_SENT_MSG_TSN=0x0008;
Used as a bitfield to control diagnostic trace information for SECS port activity which is passed to the application in the SecsTrace event.  By setting specific bits, the corresponding output is turned on. 

General Tracing: (TraceType = trace) 
Bit        Output Description 
0x0001     Read and write calls
0x0002     state changes including connection attempts 

Receive Tracing: (TraceType = rtrace) 
Bit        Description for Received Messages 
0x0100     Header binary dump 
0x0200     Header interpretation 
0x0400     Stream and Function description
0x0800     Message data binary dump 
0x0004     The Message as TSN 

Send Tracing: (TraceType = strace) 
Bit        Description for Sent Messages 
0x1000     Header binary dump
0x2000     Header interpretation
0x4000     Stream and Function description
0x8000     Message data binary dump
0x0008     The Message as TSN 

int getTraceLogMaxWidth()
void setTraceLogMaxWidth(int ctChars);
This property allows setting an approximate maximum number of characters in text lines when saving Trace data to log files.  Lines that are longer than the maximum are trimmed and a short explanation message is appended.  The property helps you reduce the size of the log files when large Process Programs are transfered or other long data messages are logged.  The value may be configured as 0 for no limit, or a value greater than or equal to 1000; the default is 4000.
RcResult setTraceSaving(bool save, bool compress, int maxDayFiles, const char *saveDir = NULL, const char *zipCmd = NULL)

struct RcResult {
  int rc;  // return code
  std::string result;
};

bool isTraceDataSaved()

bool isTraceDataCompressed()

const char * getTraceSaveDir()

int getTraceSaveMaxDayFiles()

const char *getTraceSaveZipCmd()

The toolset software has the configurable feature of continuously saving the SECS communication trace data to files - one file per day, up to a maximum number per year, and optionally compressing the closed file from the previous day shortly after midnight.  The SetTraceSaving method is used to reconfigure the logging feature with the various properties being set atomically in one call.  The RcResult return value is used as follows.  If the rc value is less than 0 the SetTraceSaving() arguments were not acceptable and an error message is provided as the result string.  If the rc value is 0, the call succeeded.  If the rc value is greater than 0, the call succeeded with an advisory message as the result string.  For example, a message occurs if compression is set true but there is a maximum of only 1 file, so there is no distinct file for the previous day to compress.

The saving logic writes each day's output to a distinct file, in the directory named by the saveDir argument.  The maxDayFiles argument controls how many day files are saved per year.  It can be configured between 1 and 366.  When file saving is initiated, the output filename is set to traceNNN.txt where the NNN value is the current day of the year, 0 to 365, modulo the maxDayFiles value.  If this file already exists and has been written to earlier in the same day, then the output is appended to it, otherwise the file is created as a new file. Note that if the maxDayFiles value is set to 1, each day's output is saved to the same filename, trace000.txt.  The default values provide for saving the data from each connection in a separate directory.  Separate directories are required for each connection.  When trace data is being written, the compress argument controls whether the logic attempts to compress the output file when it is closed at the end of the day (midnight).  For compression to occur, the maxDayFiles value must be greater than 1 and a non-blank compression command must exist as the zipCmd argument.  The default assignment of zipCmd is similar to zip -m tracetxt.zip. This command causes the data file from the previous day to be moved into the tracetxt.zip archive, creating the archive if it does not exist.   The compression logic appends the day file name to the configured command before execution.  Only trusted persons should be allowed to configure the compression command because of the security considerations.

int getTracewinMaxWidth()
void setTracewinMaxWidth(int ctChars);
The approximate maximum number of characters to display in a single line of the trace window.  This value guards against excessive data use when long messages such as recipe transfer occur and the trace window is displaying connection activity.  Range 1000..120000, default 4000.
const char *getTypeDATAID(void)
void setTypeDATAID(const char *type)
The SECS TSN type code for DATAID items.  Defaults to U4.
const char *getTypeDATALENGTH(void)
void setTypeDATALENGTH(const char *type)
The SECS TSN type code for DATALENGTH items.  Defaults to U4.
const char *getTypeLENGTH(void)
void setTypeLENGTH(const char *type)
The SECS TSN type code for LENGTH items.  Defaults to U4.
const char *getTypePPID(void)
void setTypePPID(const char *type)
The SECS TSN type code for PPID items.  Defaults to A.
const char *getTypeREPGSZ(void)
void setTypeREPGSZ(const char *type)
The SECS TSN type code for REPGSZ items.  Defaults to U4.
const char *getTypeRPTID(void)
void setTypeRPTID(const char *type)
The SECS TSN type code for RPTID items.  Defaults to U4.
const char *getTypeTOTSMP(void)
void setTypeTOTSMP(const char *type)
The SECS TSN type code for TOTSMP items.  Defaults to U4.
const char *getTypeTRID(void)
void setTRID(const char *type)
The SECS TSN type code for TRID items.  Defaults to A.
bool getUseS1F3(void)
void setUseS1F3(bool use)
Whether to use S1F3 during initialization to query Status Variable values.  After initialization, subsequent value changes are ordinarily known to the host by being received in event reports. The default value is true.
bool getUseS1F11(void)
void setUseS1F11(bool use)
Whether to use S1F11 during initialization to determine Status Variables.   Since the set of variables does not ordinarily change, and can be loaded from saved data, the initialization query can be disabled if it is time consuming.  The default value is true.
bool getUseS1F13(void)
void setUseS1F13(bool use)
Whether to use S1F13 during initialization to establish communications.  The default value is true, and is almost always appropriate since the logic will use S1F1 if S1F13 is rejected. However, there is some defective equipment in use that gets confused if it receives S1F13.
bool getUseS1F17(void)
void setUseS1F17(bool use)
Whether to use S1F17 during initialization to request the Online Control State.  The default value is true.
bool getUseS1F21(void)
void setUseS1F21(bool use)
Whether to use S1F21 during initialization to determine the Data Value Variables (DVVALs).  The default value is false.  The message is not supported by older equipment.
bool getUseS1F23(void)
void setUseS1F23(bool use)
Whether to use S1F23 during initialization to discover Data Collection Events.  The default value is false.  The message is not supported by older equipment.
bool getUseS2F13(void)
void setUseS2F13(bool use)
Whether to use S2F13 during initialization to query Equipment Constant values.  The default value is true.
bool getUseS2F29(void)
void setUseS2F29(bool use)
Whether to use S2F29 during initialization to determine Equipment Constants.  The default value is true.  Since the set of constants does not ordinarily change, and can be loaded from saved data, the initialization query can be disabled if it is time consuming.
bool getUseS2F31(void)
void setUseS2F31(bool use)
Whether to use S2F31 during initialization to synchronize the equipment clock.  The default value is true.
bool getUseS5F5(void)
void setUseS5F5(bool use)
Whether to use S5F5 during initialization to determine Alarm types.  The default value is true.  This query is not used during every initialization. It is only used if the logic sees an enabled alarm type that it does not already know about.
bool getUseS5F7(void)
void setUseS5F7(bool use)
Whether to use S5F7 during initialization to determine enabled Alarms.  The default value is true.

bool getUseS13(void)
void setUseS13(bool use)
This boolean property chooses whether to enable using Stream 13 large process program transfer message types.  In addition to the Stream 13 messages, this property also enables or disables using S7F27, S7F29, S7F37, S7F38, S7F41, and S7F42 which are used with Stream 13 for transferring large unformatted, process programs.  The default value is true which causes an S13F9 reset message to be sent during initialization.  Stream 13 message types are preferred for transferring large data sets because the data is split into multiple smaller messages which require less memory use.


 
SecsHostCpp Events
Event Handler and Argument Data  Description


All event handlers - NOTES
 
 
 
 
 

 

Callback pointers are used to pass event invocations into your application.  The callback functions you write need to be static functions, and you need to use ClientData arguments or pointers to class instances if you want to execute method calls of objects.  Assign the address of your callback function to the class pointer data item specified in this table in order to receive the specified event types.  The example application demonstrates these techniques.  As noted earlier, the thread that executes the callback is not your main GUI thread, and you need to use threadsafe programming techniques.

typedef void (SecsAlarmProc)(SecsHostCpp *, std::string &alid, int isSet, std::string &altx, std::string &clock);

SecsAlarmProc *secsAlarmCallback;
This event is raised upon receiving an S5F1 alarm report message.  Modern GEM equipment posts events for alarm set and alarm clear conditions so the idea of alarms as distinct from events is becoming obsolete.

We expect you to use our example application in addition to this document for coding help. 

typedef void (SecsEventProc)(SecsHostCpp *, std::string &ceid, std::string &eventID, std::map<std::string,std::string> & varnameValues);

SecsEventProc *secsEventCallback;
Use the eventReportDefine method to create data collection event reports.  Your application needs to call the initialize method after defining the desired event reports to setup and enable the desired event reports with the equipment.  

Events can be given meaningful names and descriptions using the eventUpdate method.  In the event report data, you receive both the underlying event identifier sent by the equipment, the CEID value, and the identifier for the event you have optionally customized, the EventID.   The data of the event report is passed as a std::map instance which contains variable name and value pairs.  The variable names are from the VFEIname column of the SECS server ei_variable table.  You are able to assign your own virtual variable names using the variableUpdate method.  Using a host given name for variables allows the logic to ensure that each name is unique, and provides for uniform naming across equipment instances.  If you do not provide your own name values for variables, the default variable names are assigned using the naming conventions of the SEMATECH Virtual Factory Equipment Interface (VFEI) standard.  The ability to rename events and variables is referred to as Virtual Reporting.

The default names for variables are computed as follows.  The variable names defined by the equipment are folded to uppercase, with white space and non-alphanumeric letters being replaced by underscores.  Hyphens are not changed. An underscore is inserted for each transition from lowercase to uppercase in the equipment provided name.  If the computed name is not unique for the equipment instance, the name is made unique by concatenating an underscore and the variable ID.  For example, the equipment variable name PPExecName is assigned the default name PP_EXEC_NAME.  The following 8 computed names are exceptions to the naming algorithm and are reassigned based on the Sematech VFEI standard: 
ESTABLISH_COMMUNICATONS_TIMEOUT becomes COM_TIMER, 
MDLN becomes EQ_MODEL_ID, 
PREVIOUS_PROCESS_STATE becomes PREV_PROC_STATE, SOFTREV becomes EQ_SOFT_VER, 
MID becomes MATERIAL_ID, 
CMD becomes CMD_VAR, 
TID becomes TID_VAR, and 
MTY becomes MTY_VAR.

typedef void (SecsMsgRecvProc)(SecsHostCpp *, int stream, int function, bool sendReply,
        int transactionID, const char *TSN_data, const char *header, void *clientData);
See the messageTypeAdd method described in the next section  to register to receive specific SECS messages in your application.
typedef void (SecsTraceDataProc)(SecsHostCpp *, std::string &traceType, std::string &text);
SecsTraceDataProc *secsTraceCallback;
This event provides you with the detailed information of SECS message traffic that is typically viewed in a SECS Trace window - see the debugTraceWindow method.  The flow of  information is controlled by setting the TRACE property.
typedef void (DMHDisconnectedProc) (DMHClient);

SecsHostCpp::getDmh().disconnectedProcSet(DMHDisconnectedProc *);
If the SECS Server process exits your application receives the ServerDisconnected event.  This event is not ordinarily expected.  A production application will limit access to the SECS Server windows so that users will not use the Exit menu items on these windows.
typedef bool (SecsServerErrorProc)(const char *title, const char *message, bool isRetryable, bool isFatal)
static SecsServerErrorProc *secsServerErrorCallback;
The SecsHostCpp class reports Tcl programming errors that are trapped in the SECS Server process as ServerError events.  An example would be trying to send an improperly formatted SECS message.  These error events will happen during development but should be rare once the code is debugged.

In addition, there are optional debugging messages available to troubleshoot the initial connection to the SECS Server background process at startup.  When the first SecsEquipCpp instance is instantiated, a SECS Server background process is started, and the application is usually able to setup DMH communication with the SECS Server within a few seconds. In an uncommon situation such as computer system that is running low on resources, the connection setup may require more time.  The timing and retry logic is optionally affected by defining and setting the following environment variables:

DMH_CONNECT_DEBUG=1    Define and set this environment variable to 1 to obtain connection debug events.   Debug events provide diagnostic messages for each connection attempt.  They show the timing and the error messages of failed attempts.  The isRetryable and isFatal argument values are set false for debug events.

DMH_CONNECT_WAIT=milliseconds    This variable can be defined and set to the desired number of milliseconds of waiting per connection attempt.  The default is 500.  The value may be set from 1 to 60000.

DMH_CONNECT_RETRY=maxAttempts    This environment variable can be defined and set to the desired maximum number of communication attempts.  The default is 20.  The value may be set from 1 to 100.

See the dmhConnect method coded in the SecsHostCpp.cpp file for more details.  Note that the DMH_CONNECT_* environment variables can be defined and set on a deployed system to affect the startup timing  without making code changes, and without having coded an error event handler.  This is a new feature of the software as of January 2016.

The context information passed to the application is usually presented in a MessageBox for the retryable or fatal errors.  Your handler function returns true to specify that retryable errors should be retried.  
typedef void (SecsDataChangeProc)(SecsHostCpp *, std::string &varname, std::string &newvalue);

SecsDataChangeProc *stateChangeCallback;
This event notifies your application of state value changes. Possible varname values include 
  • state - the State property value changed
  • comm_state - the CommState property value changed
  • control_state - the ControlState property value changed
  • dataset_delete - a process program has been replaced with a newly received one.  Stream 13 messages were used for the transfer.  The newvalue argument is the ppid.
  • dataset_download - a process program was downloaded to the equipment using Stream 13 messages.  This event happens when the S7F29 length verification message is received with the correct length specified.  The newvalue argument is the ppid.
  • dataset_upload - a process program was received using Stream 13 transfer messages.   Proper GEM equipment will also post an UploadSuccess event.  The newvalue argument is the ppid.
  • recipe_delete - a process program was replaced with an uploaded version using Stream 7 messages.
  • recipe_download - a process program was downloaded to the equipment using Stream 7 messages.
  • recipe_upload - a process program was received from the equipment using Stream 7 messages.
Your application gets notified of the initial values of these items when the SecsHostCpp connection type is initialized.  With the recipe_* events, the newvalue string is the process program identifier (ppid).

SecsHostCpp Methods
METHOD DESCRIPTION
General Comments
 
 

 

The List manipulation methods, which are static, are implemented by the DmhCppClient class and also exposed for your convenience by the SecsHostCpp class.
RcResult alarmAdd(const char *ALID, const char * ALTX, const char * ID_TSN)

struct RcResult {
   int rc;   // return code
   std::string result;
   }

This method is used to manually add alarm definitions for equipment that does not support discovery of alarm types using S5F5.  The ALID argument value is the alarm type identifier which is usually an integer.  The ALTX argument is static text for the alarm description and it is limited to 40 characters in length.  The ID_TSN argument is the SECS item data type for the ALID in TSN notation such as U4. 

If the method succeeds, the rc field in the result structure is set to 0. It is not an error if the alarm definition already exists, the argument values are used to update the existing definition.  A non-zero result indicates an error, and the result string should be examined.  Possible error return codes include:
-2  invalid ALID
-3  invalid ALTX value 
-4  an error occured using the ID_TSN value to format the ALID value as a SECS data item
-9  unexpected SQL error

void alarmEnable(const char * ALID, bool is_enabled) Enable or disable reporting of an Alarm type (S5F1).
bool alarmIsEnabled(const char * ALID) Test if the reporting of an alarm type is enabled 
bool alarmIsSet(const char * ALID) Test if the alarmed state is currently set
int binToInt(const char * binValue)

 

Converts a SECS B (Binary  - Semi "10") data value usually formatted as a hexadecimal string to an integer value.
void commDisable() Disable SECS communication.  The SecsHostCpp is initialized without communication enabled so using this method only makes sense after CommEnable has been called.
RcResult commEnable()

struct RcResult {
   int rc;   // return code
   std::string result;
   }

Enables SECS communication.  The CommState property value will change and StateChange events will be received.  These changes are the asynchronous indications for success or failure to establish communication.  You may want to display the trace window  in order to see detailed information on the status of communication attempts.  If there is an error setting up the connection, the return code value will be non-zero, and the result string will be an error message.
RcResult connectTypeHsmsActive(const char * host_or_ip, int port) This method is an alternative to setting the underlying property values to specify an active HSMS connection type, and calling ConnectTypeSet().
RcResult connectTypeHsmsPassive(int port) This method is an alternative to setting the underlying property values to specify a passive HSMS connection type, and calling ConnectTypeSet().
RcResult connectTypeSerial(const char * comDevice, int baudrate) This method is an alternative to setting the underlying property values to specify a SECS-I connection type, and calling ConnectTypeSet().
RcResult connectTypeSet()

struct RcResult {
   int rc;   // return code
   std::string result;
   }

This method is called to use the current property values and initialize a SECS interface for the indicated connection type.  It is called by the ConnectType<Type> methods.  If you are setting connection property data directly, call this method after your property values are set.  The method returns the value 0 to indicate success.  If communication is enabled when this method is called, it becomes disabled as a result of setting up the new connection.  A non-zero return code value indicates an error setting up the connection, in which case the result will be an error message.
RcResult connectTypeTerminalServer(const char *host_or_ip, int port) This method is an alternative to setting the underlying property values to specify a SECS-I connection type over a TCP/IP terminal server connection and calling ConnectTypeSet().
void controlStateOffline() This method sends a S1F15R message to request the offline control state. 
int controlStateOnline() This method sends a S1F17R message to request the online control state.  If the return value is 0 or 2 the online state is indicated.
void copy(SecsHostCpp &dest) This method copies the configurable SecsHostCpp property values to another instance.
bool copyAll(SecsHostCpp &dest, int *rowsFound=NULL, int *rowsCopied=NULL) This method calls Copy to copy the current property values to another instance, and it also copies table records of events, event reports, alarms, variables, etc in the SECS Server to the destination instance.  The return data provides a boolean success code and two integers - the total number of table rows found, and the number of rows copied.  The rows copied is less than the total if the destination connection type is set and some table rows exist to hold property values.
void debugDMHStatus(bool show) This method causes the DMH message system status window to either be shown or dismissed.
void debugInspect() This method can be used to exec the Inspect introspection debugger.
void debugTclConsole(bool show) This method causes a console window for the SECS Server to be shown or dismissed.
void debugTableWindow(bool show) This method causes the Datahub table management GUI to be shown or dismissed. 
void debugTraceWindow(bool show) This method is used to display a window which updates to show SECS message traffic and state information for the SecsHost.   There are menu options to control the data displayed, and menu actions to save the displayed data to the file system.  This method invokes the Tcl version of the Trace window which is created by the SECS Server process. 
Equipment Constant Set see parameterSet Equipment Constant is a misnomer; we have started calling ECVs Equipment Configuration Variables, and we invite you to do likewise.
RcResult eventAdd(const char * CEID, const char * ID_TSN, const char * eventName, const char * description)

struct RcResult {
   int rc;   // return code
   std::string result;
   }

This method is used to manually add event definitions for equipment that does not support discovery of event types.  The CEID argument value is the event type identifier which is usually an integer.  The ID_TSN argument is the SECS item data type for the CEID in TSN notation such as U4.  The eventName argument is a virtual name for the event type defined by the user.  The desciption argument can be used to provide guidance in selection lists.  If any of the arguments ID_TSN, eventName, or desciption are provided as empty strings, then default values are used:  U4 for ID_TSN, and the CEID value as a string for the eventName.

If the method succeeds, the rc field in the result structure is set to 0.  No error occurs if an event definition with the same CEID already exists - the other fields are updated per the call arguments.  A non-zero result indicates an error, and the result string should be examined.  Possible error return codes include:
-2  invalid CEID
-3  invalid eventName value 
-4  an error occured using the ID_TSN value to format the CEID value as a SECS data item
-9  unexpected SQL error

bool eventChoice(std::vector<std::string> &choiceList) This method returns a vector of {CEID EventName Description) string values of event types that do not currently have an associated event report.  The method is used to help implement the GUI feature of new report creation.
int eventDiscovery() The SECS-II standard does not provide a way to discover equipment events.  This method is called to attempt event discovery by enabling all events and asking the equipment which events are enabled.  This technique requires that the equipment support the underlying message types and implements an EventsEnabled variable that has the expected name.  A positive return value indicates the number of new event types discovered.  Negative return values indicate various failure modes.
int eventsEnable()
int eventsEnable(std::vector<std::string> & CeidList, bool isEnabled)
Called with no arguments, eventsEnable requests that the equipment enable all event reports.  By providing arguments, you can request the enabling or disabling of selected events.  The SecsHostCpp automatically enables the reporting of events for which you have configured event reports during online initialization.   A negative return value indicates an unexpected internal error.  The value 0 means success, and 1 means at least one of the events does not exist.
bool eventIsHostEnabled(const char * CEID) Test if reporting of an event type has been configured in the SecsHostCpp software to be enabled during the initialization logic.
bool eventIsReported(const char * CEID) Test if the reporting of an event is currently established with the equipment.
bool eventReportConfig(const char *eventName, EventReportConfig &);

struct EventReportConfig {
    std::string CEID;
    std::string eventName;
    std::string description;
    std::vector<std::string> variableList;
};
This method fills in a data structure for the configuration of an event report.  The elements are CEID, virtualName, Description, and Variables.  The return value is false in case of error.
bool eventReportConfigs(std::vector<EventReportConfig> &reportConfigs);
This method returns a vector of the existing event report configurations. 
int eventReportDefine(const char *eventName, std::vector<std::string> &varnames); Create or update an event report configuration.  The eventName argument is the virtual name of the event which can be configured to be different than the CEID value by using the eventUpdate method.  The varNames argument is an array of the virtual names of the variables whose values are to be reported when the event occurs.  The method variableChoice provides a current list of virtual variable names.  You can use the variableUpdate method to provide your own virtual variable names.  The default virtual variable names are assigned per the conventions of Sematech as explained in the EventReport Event section above.  After calling this method, you need to call the initialize method to have your desired event reports setup and enabled with the equipment.  The initialize method is called automatically whenever an online control state is established if the AutoInit property is true.

The method returns 0 for success, -1 if the eventName is not known, or -2 if a variable is not known.  If  you have more than one machine event with the same virtual event name, each machine event will be setup with the desired report.

void eventReportDelete(const char *eventName) Delete an event report configuration.
bool eventTable(std::vector<EventConfig> &eventConfigs); This method returns a DataTable featuring a subset of the SECS server's event table for the current SecsHost.  The included columns are: spname, CEID, VFEIname, host_managed, host_wants_enabled, event_class, is_reported, and description.
std::string eventUpdate(const char *CEID, const char *eventName, const char *description = ""); Assign or update the virtual event name and description for an event type.  Per the SECS-II standard, events use integer values for identifiers.  There is no standardization of values.  You are able to provide meaningful names and descriptions for events.  You can use this feature to great advantage and create virtual equipment drivers with standard event and variable names.  If the description value is passed as an empty string, the current value for the event is not changed.
RcResult initialize()

struct RcResult {
   int rc;   // return code
   std::string result;
   }
Performs online initialization which enables communication and sets up event reports.  Initialization is controlled by your settings of property values, and configured items.  It optionally includes:
  • establishing communications if not already established
  • requesting the equipment go online if the online control state is not already established
  • querying the status of alarms and variables if being online is new
  • synching the equipment clock
  • setting equipment constant values for the ones that you have configured persistent values
  • setting up event reports per your configuration
  • enabling all events if you do not have any configured equipment based event reports so you can capture the event definitions needed for event reports
  • unloading, purging, or ignoring the spool
By default this initialization is attempted automatically whenever an online control state is established.  The autoInit property is used to enable or disable automatic initialization.  We recommend that your application simply call commEnable() with autoInit set true instead of directly calling this method.  However, an application does call this method after revising the event report configuration for the purpose of setting up the event reports with the equipment.

The return code value in the returned data structure is 0 for success.  Error return values include:  -1 TIMEOUT, 1 communication failed, 2 not online, 3 clock set, 4 setting of Eq. Constants, 5 disabling of events & reports, 6 event & report enabling, 7 alarm management, 8 Spool init, or ei_custom_init error.   In the event of error, the result string has explanatory text.

bool linktest(void)
Synchronously test a COMMUNICATING HSMS connection to verify that the link is responsive.  May take up to timeout period T6 to return. On failure, the HSMS socket connection is closed and the CommState will no longer be COMMUNICATING.  Returns true if the link is up, false if the link is down.
void linktestAsync(void)
Cause a linktest HSMS control message to be sent to test if a healthy connection still exists.  Forces discovery of a bad connection after a T6 timeout. If the link test fails, the HSMS socket connection is closed and the CommState is no longer COMMUNICATING.  The method is useful for periodic polling if there is an issue with broken connections not being discovered soon enough.
static
void listAppend(std::string &list, const char *e1, const char *e2 = NULL,  const char *e3 = NULL, const char *e4=NULL, const char *e5=NULL, const char *e6=NULL);


 

This method is used to add one to six list elements to text that is formatted as a Tcl list.  It is a good programming practice to use listAppend or listJoin to build a Tcl list, in order to make sure that imbedded white space or other special characters are properly delimited with curly braces or escaped with backslashes.  An empty string may be passed as any of the element argument values, in order to represent an empty list or empty element.  The first NULL argument indicates the previous argument is the end of the list.
static
std::string listElement(const char *list, int index1, int index2=-1, int index3=-1);

static
std::string listElement(const string &list, int index1, int index2=-1, int index3=-1);

This function is similar to the lindex function of Tcl.  It will parse text formatted as a list and return the specified element.  Indexing starts from 0.  Arguments index2 and index3 may be used to indicate that parsing of the list should continue up to two additional levels as a nested list structure. If a specified index is out of bounds, an empty string is returned.  Not all strings are valid lists.  If an invalid list is parsed, an empty string is returned.  
static
std::string listJoin(int argc, const char * [] argv);

static
std::string listJoin(std::vector<std::string> &sv);
Joins together strings as Tcl list elements forming a result string that is a Tcl list.  Braces are added as needed to delimit empty elements, or to delimit special Tcl character sequences involving backslashes , square brackets, etc.  
static
int listSplit(const char *list,
  std::vector<std::string> &elements)

static
int listSplit(const string &list,
  std::vector<std::string> &elements)
listSplit( ) parses a string formatted as a list into a vector of string elements.  The function understands the list format usage of quotes, braces and backslash sequences.  Not all strings are valid lists. The return value is 0 on success. Failure occurs when there are unmatched braces, unmatched quotes, or non-whitespace following braces or quotes.
void messageTypeAdd(int stream, int function, SecsMsgRecvProc *callback,   void *clientData = NULL);)

typedef void (SecsMsgRecvProc)(SecsHostCpp *, int stream, int function, bool sendReply, int transactionID, const char *TSN_data, const char *header, void *clientData);

Call this method to have SECS messages dispatched to your callback handler.

See http://www.hume.com/secs for parsing code for all of the standard message types of SECS/GEM.

You can provide for new SECS message types, or you can replace the SecsHostCpp handling of particular messages.  For example, you could take over the handling of S6F3 discrete data reports for equipment that uses non-standard formats.  Use the sendReply method to send reply messages. 
void messageTypeRemove(int stream, int function) This method is used to cancel SECS message handlers that you have setup using messageTypeAdd or to cancel the handling of particular messages by the built-in SecsHostCpp logic.  If you have called messageTypeAdd for the specified message type, the Add is cancelled.  If you have not called messageTypeAdd, the SECS server is told not to handle the message. Unhandled primary messages are replied to with an abort reply.
RcResult parameterAdd(const char *varID, const char *IdTsn, const char *valueTsn, const char *varname, const char *virtualName, const char * description)

struct RcResult {
   int rc;   // return code
   std::string result;
   }

This method is used to manually add parameter (ECV) definitions for equipment that does not support discovery of them using S2F29.  The varID argument value is the parameter identifier which is usually an integer.  The ID_TSN argument is the SECS item data type for the varID in TSN notation such as U4.  The value_TSN argument is the data type of the parameter value in TSN notation such as "F4".  The varName argument is a name for the parameter as defined by the equipment.  The virtualName argument is a name for the parameter chosen by the user.  The desciption argument can be used to provide guidance in selection lists.  If any of the arguments ID_TSN, varName, virtualName, or desciption are provided as empty strings, then default values are used:  U4 for ID_TSN,  the varID value as a string for the varName, and programmatic mapping of the varName value for the virtualName.

If the method succeeds, the rc field in the result structure is set to 0.  No error occurs if a definition with the same ID already exists - the other fields are updated per the call arguments.  A non-zero result indicates an error, and the result string should be examined.  Possible error return codes include:
-2  invalid varID
-3  invalid varName value 
-4  an error occured using the ID_TSN value to format the varID value as a SECS data item
-5 an error occured using the value_TSN value to format an example value
-9  unexpected SQL error

RcResult parameterSet(const char *varID, const char * newValue) Use this method to set the value of an ECV parameter.  The return value is "0" for success, -1 and an error message if improper data is used, "1" if the variable does not exist, "2" if the equipment refuses to change the value at present, and "3" if the equipment rejects the new value. 
bool processProgramList(std::vector<std::string> &pplist)
Obtain the current list of process programs using S7F19R.  The return value is false in case of error such as the equipment not being online or not supporting S7F19.
RcResult processProgramDownload(const char * pathname)

struct RcResult {
   int rc;   // return code
   std::string result;
   }

Download a process program to the equipment using Stream 7 messages.  The process program must be in the process program directory.  If there is no saved table record in file ei_ppid.tab describing the process program file, the logic assumes that the file format contains both the PPID and PPBODY in text TSN notation which was the upload format used prior to May 2008.  The return value of the method call is a two element structure, a return code and text.  The return code is 0 for success, in which case the text will be the PPID (the process program name).  Possible error codes include:
-1 unexpected transaction error
-2 file not found
-6 SECS transaction error
-10 file open or read error
-11  no upload description data and the file data is not consistent with the older upload format



RcResult processProgramLargeRequest(const char *ppid)

struct RcResult {
   int rc;   // return code
   std::string result;
   }
This method initiates the upload of a process program to the host using the message types of Stream 13 which are designed for large data set transfers.  Using these messages is more complex than the usual Stream 7 transfer messages so they are less commonly supported.  The ppid argument value is the process program identifier used by the equipment.  The upload logic saves only the data passed as the body of the process program in the uploaded file.  The ppid value used to identify the process program may not be a valid filename.  The upload logic assigns a unique filename to the uploaded program, using the ppid value if possible.  The logic also creates or updates a file of SQL statements, ei_ppid.tab, in the process program directory.  The ei_ppid.tab file saves the ppid value to filename mapping, as well as the datatype of the transferred program.  The ei_ppid.tab file has to be preserved along with the uploaded process programs in order to download them in the future.

The return value is a two element structure, a return code and text.  The return code is 0 if the transfer is initiated successfully as determined by the reply to S7F41.  The transfer is not complete when the method returns.   The large data set transfer logic receives the file in the subdirectory, dataset_transfer, of the directory set by the ProcessProgramDir property.  When the transfer is complete, if there is already an earlier version of the process program file in the process program directory, then there is a StateChange event with the name dataset_delete and the newvalue being the ppid value, which informs you that the earlier version file is being replaced.  Next, there is a StateChange event with the name dataset_upload and the newvalue being the ppid value which informs you of the successful upload completion.  Proper GEM equipment will also post UploadSuccess or UploadFailure data collection event reports to indicate completion as well. 

If the transfer does not complete successfully, there is additional status information is the SECS server table ei_dataset_xfer.   It is possible to query this table or subscribe to data changes of this table to better integrate transfer status information.

Possible error results include values of the ACKC7 reply to S7F41 and the following:
1 permission not granted
4 PPID not found
6 other error
-6  error when sending S7F41 or receiving the S7F42 reply
-14 A large PP receive is already in progress for ppid
-15 Stream 13 transfers are disabled either from configuration or initialization failure
-17 error when parsing the S7F42 reply



RcResult processProgramLargeSend(const char * filename)

struct RcResult {
   int rc;   // return code
   std::string result;
   }
This method initiates the download of a process program to the equipment using the message types of Stream 13 which are designed for large data set transfers.  Using these messages is more complex than the usual Stream 7 transfer messages so they are less commonly supported.  The filename argument value is the file name of a previously uploaded process program in the process program directory.  The file is expected to contain only the data of a process program - this transfer method is not compatible with the previously used upload format that saved both the PPID and PPBODY in TSN notation.  The filename may not be the same as the process program identifier, ppid.  The saved information in the ei_ppid.tab file in the ProcessProgramDir is checked for a possibly different ppid

The return value is a two element structure, a return code and text.  The return code is 0 if the transfer is initiated successfully as determined by the reply to S7F37.  The transfer is not complete when the method returns.  After the data has been sent to the equipment, per GEM, the equipment is expected to verify the byte count of the download process program file using S7F29.  When this verification occurs with the correct byte count, there is a StateChange event with the name dataset_download and the newvalue being the ppid value.   If the transfer does not complete successfully, there is additional status information is the SECS server table ei_dataset_xfer.  

Possible error results include values of the ACKC7 reply to S7F37 and the following:
1 permission not granted
6 other error
-4  PPID filename not found
-6  error when sending S7F37 or receiving the S7F37 reply
-14 A large PP receive is already in progress for ppid
-15 Stream 13 transfers are disabled either from configuration or initialization failure
-17 error when parsing the S7F38 reply
RcResult processProgramUpload(const char * ppid)

struct RcResult {
   int rc;   // return code
   std::string result;
   }

Upload a process program from the equipment to our file system.  The return value is a two element structure, a return code and text.  The return code is 0 for success, in which case the text will be the pathname of the saved program..  Possible error codes include
-1 unexpected transaction error
-2 upload refused or failed
-3 file system error
SecsHostCpp(const char *spname = "", const char *dmhGroup = "GEMHOST");

SecsHostCpp(SecsHostStartupData &startupData);


The constructor.  The spname argument becomes the name of a global data item and a Tcl command in the SECS Server process.  It needs to be unique for each SecsHostCpp instance, and not coincide with a keyword in the Tcl programming language.   The spname value should also not be a simple token like a, i, or spname which might conflict with a variable name in the SECS server logic.  If the name argument is defaulted the value assigned is similar to host0. The name should be a single alphanumeric token. 

One of the constructor forms accepts property values in a data structure.  The SecsHostStartupData structure is defined near the end of the SecsHostCpp.h file and there are comments on how the fields are used.  This form of the constructor is an alternative to using the startupRestore method which is used by supervisorStart.

The dmhGroup argument becomes the DMH message system group name used by the SecsHostCpp and SECS Server process.  If you are instantiating more than one  instance in your process, construct each instance using the same dmhGroup name argument so that the SECS Server process is shared.  If you want to have both SecsHostCpp and SecsPortCpp equipment interfaces in the same application, use the constructor choices that allow you to specify the same dmhGroup argument value so the SECS Server is shared.  The groupname chosen needs to be unique among other DMH server instances on the computer where the SecsHostCpp is executing.  The default value is GEMHOST.  This value does not conflict with the default value for Hume Datahub instances which is mbx, or the default value for the GemEqApp which is GEM.  The name should be a single alphanumeric token.

The  SECS Server process can be debugged remotely by connecting to the DMH mailbox SERVER_RPC@hostname:dmhGroup using the Inspect application or using the DMH mailbox SERVER_SQL@hostname:dmhGroup by the hubclient application.

void sendAbort(int stream, int primaryFunction) This method is used to send an F0 abort message in lieu of a proper reply.  It is used to indicate that the received message is not appropriate in the current context.

void sendReply(int stream, int function, int transactionID, const char * TSN_data = NULL)

This method is used by your custom SECS message handling logic to send reply messages either with or without data.  The reply data is formatted as Tcl Secs Notation text.
void sendS9(int function, const char * header) This method is used to indicate an error condition response to a received message - it is sent in lieu of a normal reply.  You will not receive a message type, unless you register for it.  In general, host software has less of a need to send Stream 9 messages than equipment software.
 RcResult sendSecsMsg(int stream, int function, bool replyWanted, const char *TsnData, bool waitForReply)



struct RcResult {
   int rc;   // return code
  std::string result;
   }
 
 
 
 
 

 

This method is used to send a primary SECS message, optionally indicating a reply is wanted, and optionally indicating that the call should wait for a reply. The stream and function arguments are the message type identifiers of SECS.  The TsnData argument is a string representation of the message body using the type notation of TSN.   The list methods listAppend and listJoin are recommended for building complex messages to insure valid formats. A NULL or empty string value may be used for the TsnData argument when a header only message is to be sent.  If a multiblock enquire/grant transaction is required for the message type, the SecsHostCpp software does it automatically. 

The sendSecsMsg() return value is a structure containing an integer return code and a string result.  The possible return values are:
-1
errorMessage  - the error message starts with "ERROR" and describes the fault
-2
DISABLED   - communication is disabled so the message could not be sent
-4 
SENDFAILURE   - the send attempt failed.
-5 
BUSY   - the background thread is currently active.  You may see this error when the worker thread is used if you re-enter your sending logic.  If the worker thread is not used, you should not see this error, since by design send commands are serialized using DMH messages to the connection's command mailbox.
-8
MULTIBLOCK_REFUSED - You are sending a message type that requires multiblock enquire/grant and the equipment failed to send the code 0 GRANT reply.  Enquire/grant messages by default are not used for HSMS communication, but it is possible to enable them. (Possible with message types S2F33, S2F35, S2F45, S4F19, & S7F3).
SENT_NO_REPLY  - sent successfully no reply requested
SENT_NO_REPLY_WAIT  - sent successfully, a reply was indicated, not waiting for the reply was indicated.  The reply will be ignored when it arrives.
ReplyTsnData   -sent ok, reply requested and received.
-6 
TIMEOUT  - sent ok, reply requested, no reply, T3 timeout. 
-7 
ABORTED  - sent ok, F0 abort reply received.
-9
REJECTED  - sent ok, Stream 9 error message "reply".
listElement( ) or listSplit( ) can be used to parse a reply message. See the example parsing code for any standard message reply at http://www.hume.com/secs/.

void sendSecsMsgAsync(int stream, int function, bool replyWanted, const char *TsnData = ""); Send a primary SECS message without waiting for the send success, send failure, or a reply. Wanting a reply can still be indicated, and the reply can be received asynchronously using messageTypeAdd() or ignored.  This method provides a completely asynchronous send which does not wait to determine if the SECS Server has successfully sent the SECS message.   The method can provide better performance than sendSecsMsg, and it keeps the calling thread responsive to other events as the SECS message is being sent.
static
void serverSQLCmd(const char *sql)
Send an SQL command to the SECS Server process without waiting for a reply.  This method is used by the SecsHostCpp software and made public in case of custom requirements.
static
std::string serverSQLReply(const char *sql)
Send an SQL command to the SECS Server process and wait for the reply.  This method is used by the SecsHostCpp software and made public in case of custom requirements.
static void serverTclCmd(const char * tclCommand); Send a Tcl command to the SECS Server process without waiting for a reply.  This method is used by the SecsHostCpp software and made public in case of custom requirements.  After a SecsHostCpp instance has been constructed and the connection type set, the tclCmd( ) method should be used instead of this method for commands that are directed to a particular interface instance.  Why?  Doing so serializes the commands for a particular interface, and provides re-entrant execution protection.
static std::string serverTclReply(const char * tclCommand); Send a Tcl command to the SECS Server process and wait for the reply message.  This call is used by the SecsHostCpp software and made public in case of custom requirements.  After a SecsHostCpp instance has been constructed and the connection type set, the TclReply( ) method should be used instead of this method for commands that are directed to a particular interface instance.
static SecsHostStartupData startupLoad(const char *name, bool loadTableFile = true);
This method retrieves the persisted startup configuration for the named interface.  The first time the method is called, the loadTableFile argument should be defaulted or set true so that the ei_startup table data is read from the file system.  After the first call, the loadTableFile argument can be passed as false to avoid re-reading the same data.

If no startup data is found, the returned data structure is populated with reasonable defaults, and the name field in the data structure is set to an empty string to indicate that a saved record did not exist.  The host method uses the SECS server's ei_startup data table.  The table data is saved as the file ei_startup.tab in the SECS server's working directory when the superSave() method is called.

The declaration of the SecsHostStartupData struct in the header file SecsHostCpp.h can be viewed for the comments on the field usage, in addition to reviewing the example application source code.  The comments in the header are displayed by the Intellisense prompting of the Visual Studio IDE.
void startupRestore(SecsHostStartupData &sd);
The method applies the passed startup configuration to the instance, configuring properties according to the data and calling connectTypeSet(). The method does not call commEnable() which allows you to fully configure the instance before going online.  The name field in the input structure is ignored since the instance has already been constructed and given a name. 
RcResult startupSync()
This method creates or updates a row in the SECS Server ei_startup SQL table with the property values of the SecsHostCpp instance.  The method supports the persistence of startup information used by the Supervisor application.  The tables used by the SECS Server are described in the Tcl/Tk SECS/GEM application document.
static int superSave() Save the SECS server table data including interface startup configurations.  You can write your own applications with your own persistence mechanisms.  Our example Supervisor application uses this method to save the state of the configured interfaces for the next session.  The tables used by the SECS Server are described in the Tcl/Tk SECS/GEM application document.
static int superSaveStartup()
Saves only the startup configurations of the current SecsHostCpp instances as the file of SQL statements, ei_startup.tab, in the working directory of the SECS Server.  
static void supervisorStart (const char *dmhGroup) This method is the startup call for our Supervisor application example.  It restores data from the last SuperSave call, and instantiates all of the configured interfaces.  The interfaces that are configured with autoStart true, are enabled for communication.

If the application has not called setServerDir() a check is made for the existence of a system environment variable HUME_SUPERVISOR_DIR when this method is executed.  If a value exists, the supervisorStart method sets the SECS Server working directory using the value before attempting to read or write application data.
void tclCmd(const char * tcl) This method is used to send Tcl code to the SECS server command mailbox for the connection.  It is used by the SecsHostCpp software and made public to support custom requirements.

RcResult tclReply(const char * tcl)

struct RcResult {
   int rc;   // return code
   std::string result;
   }

This method is used to send Tcl code to the SECS server command mailbox for the connection and wait for the evaluation result.  It is used by the SecsHostCpp software and made public to support custom requirements.   The rc data structure element is a return code for the evaluation with 0 meaning success.  The result element is the return value from the executed Tcl code, or an error message if the return code is not 0. 
int traceSetup(const char * traceId, int periodSeconds, int totalSamples, int samplesPerReport, const char * SVIDs) Control of TRACE Reports - a convenience method to send the S2F23R message.  If totalSamples is 0, the trace is disabled.  If totalSamples is greater than 0, you should insure that it is an even multiple of samplesPerReport.  The reporting period value specified in seconds, periodSeconds, is subject to equipment limitations.  The SVIDs argument is a white space delimited list of Status Variable identifiers.  The return values are 0 = success, 1 = too many SVIDs, 2 = no more traces allowed, 3 = invalid period specified, -1 = error such as not being in online communication, -2 = at least one unknown SVID, -3 at least one variable is not a Status Variable (class SV). 

The method also creates or updates event report configuration data so that the S6F1 trace reports are received as event reports with the CEID of TRACE_REPORT.  When there are multiple samples per report, the event report logic parses the received data into multiple event reports, one per sample.  In this situation you will usually want the CLOCK variable as one of the reported items to know the observation time of the sample.  If you want to have more than one trace report series active at a time, then you can use the messageTypeAdd() method to register for the S6F1 messages and receive them directly without using the virtual event report receiving logic.

RcResult variableAdd(const char * varID, const char * ID_TSN, const char * varName, const char *virtualName, const char *description, const char * varClass)

struct RcResult {
   int rc;   // return code
   std::string result;
   }


static const char *VARCLASS_SV;
static const char *VARCLASS_DVVAL;


This method is used to manually add variable definitions for equipment that does not support discovery of them.  The method can also be used to insure that variable definitions exist and reports using them can be defined before initialization logic is executed.  The most common scenario is that initialization logic is run and discovered data is saved by calling superSave() during a prior session, and this method is not used. The varID argument value is the variable identifier which is usually an integer.  The ID_TSN argument is the SECS item data type for the varID in TSN notation such as U4.  The varName argument is the name for the variable as defined by the equipment.  The virtualName argument is a name for the variable chosen by the user.  The virtualName should be unique.  System assigned virtualName values are described above with the EventReport event description.  If both the varName and the virtualName values are set to the varID value, the built-in initialization logic of processing S1F12 will replace the varName and virtualName values with system computed values.  Therefore, provide a different varName value if you wish to use the varID value as the virtualName. The description argument can be used to provide guidance in selection lists.  The varClass argument value is set to "SV" for Status Variables and "DVVAL" for Data Value variables.  If any of the arguments ID_TSN, varName, VFEIname, or description are provided as empty strings, then default values are used:  U4 for ID_TSN,  the varID value as a string for the varName, and programmatic mapping of the varName value for the VFEIname.

If the method succeeds, the rc field in the result structure is set to 0.  No error occurs if a definition with the same ID already exists - the other fields are updated per the call arguments.  A non-zero result indicates an error, and the result string should be examined.  Possible error return codes include:
-2  invalid varID
-3  invalid varClass value 
-4  an error occured using the ID_TSN value to format the varID value as a SECS data item
-9  unexpected SQL error

bool variableChoice(std::vector<std::string> &varlist) This method returns a list of variable names which are candidates for use in dynamic Event Report configuration.  A false value is returned in case of error.
 bool variableGetId(const char *virtualNames, std::string &varIDs)

bool variableGetId(std::vector<std::string> &virtualNames, std::vector<std::string> &varIDs)
These methods are used to map variable Virtual names assigned by using the variableUpdate method or assigned by default when the variables are first known, to the identifiers used by the equipment.  The latter are typically integer values such as SVID's or ECID's.  If called with a string argument, the virtualNames value may contain 1 or more white space separated names, and the result will be a white space separated list of the corresponding Ids.  An empty result is returned for an unknown name value.  If called with a string vector argument, each vector element is expected to contain a single name, and a string vector result is returned for the corresponding Id values.
bool variableGetInfo(const char *varID, HostVariableInfo &info)

struct HostVariableInfo
{
    std::string varID;
    std::string idTsn;
    std::string varname;
    std::string virtualName;
    std::string description;
    std::string varClass;
    std::string valueTSN;
    std::string varmethod;
    std::string varValue;
    std::string tLatest;
    std::string units;
    std::string minValue;
    std::string maxValue;
    std::string defaultValue;
};

This method returns the known configuration and value information of a variable or Equipment Constant Variable (ECV).  A false result is returned for an unknown variable.  The information comes from the replies to messages that are sent during the online initialization, from data received in event reports and trace reports, or from the restored table data of a previous session.

bool variableGetVirtualName(const char *Ids, std::string &virtualNames);

bool variableGetVirtualName(std::vector<std::string> &varIds, std::vector<std::string> &virtualNames);
These methods are used to map variable identifiers which are typically integer values (SVID, ECID, etc) to the Virtual names assigned by using the variableUpdate method or assigned by default when the variables are first known.  If called with a string argument, the Ids value may contain 1 or more white space separated Id values, and the result will be a white space separated list of the corresponding Virtual names.  An empty name result is returned for an unknown Id value.  If called with a string vector argument, each vector element is expected to contain a single Id, and a string vector result is returned for the corresponding Virtual names.
RcResult variableQuery(int varID)
RcResult variableQuery(const char * varName)
bool variableQuery(std::vector<std::string> &varIdlist, std::vector<RcResult> &values);
RcResult variableQueryVirtual(const char *virtualName);

struct RcResult {
   int rc;   // return code
   std::string result;
   }
These methods are used to obtain the value of a Parameter or Status Variable using the numeric or name identifier.  The varName argument represents the name given the variable by the equipment.   Note that some equipment has the same variable names used more than once.   The variableQueryVirtual method uses the virtual variable name as the argument value which is unique for each variable.   There is also a vector version of variableQuery that asks the host for one or more variable values in one method call, and returns a vector of return code values and results.  With the array version, if you combine querying for Parameters and Status Variables, then there will be two SECS message exchanges to query the values according to their type. 

An alternative to these methods that can include DVVAL variables is to define an event report that includes the desired variables, and then to ask for the event report using sendSecsMsg to send S6F17R.

For the methods to succeed, you must be communicating in an online state, and the variables must be known from the replies that are received during online initialization to S1F11 and S2F29.  The variable data can either be discovered during the current session, or known by loading variable data saved from a previous session.

If the method succeeds, the rc field in the result structure is set to 0.   A non-zero rc result indicates an error, and the result string can be examined for a description.  Possible error return codes include:

-1 unexpected error
-2  communication is not enabled
-3 unknown identifier (can occur if initialization queries have not been completed)
-6  no reply TIMEOUT, abort reply, or Stream 9 error reply
bool variableTable(std::vector<HostVariableInfo> &v); This method returns a current subset of the SECS server variable table for the SecsHostCpp instance. 
int variableUpdate(const char * varID, const char * virtualName, const char * description) You are able to assign meaningful names and descriptions to the equipment variables using this method.  The virtualName values are used in Event Report configurations and as the variable names in the Event Report event data.  If the description field is passed as a null value, the current description is not changed.

SecsHostCpp Built-in Features


This section of the document has information on the built-in features of the SecsHostCpp software in regards to the SEMI E5 and GEM standards.
 

Built-In Variables and Events

The SecsHostCpp software creates certain variable table records to hold configured property values.  These records are of little interest to the C++ developer since they are managed through property value settings.

There is only one other variable record of note.  The AUTO_INIT_RESULT variable exists to save the execution result when the initialization logic executes automatically.  It is common to configure this variable to be part of the event report for the AUTO_VIRT_INIT event.  This dynamic event report can be configured and received even if the underlying equipment does not support dynamic event reports.  The event report is created and managed by the SecsHostCpp software.  There are three other events that are synthesized in the SecsHostCpp software and presented to the application using the same mechanisms used to dispatch equipment based event reports.  Here is a list of the built-in SecsHostCpp data collection events:

AUTO_VIRT_INIT
This event report occurs when the autoInit property is left at its default value of true, and the SecsHostCpp attempts the initialization logic for the virtual reporting system automatically after establishing an online control state with the equipment.  When the event is posted, the value of the AUTO_INIT_RESULT variable is set to a two element list.  The first element indicates whether there was a trapped execution error during initialization.  The first element will ordinarily be 0 to indicate that execution proceeded without error.  The second element will be an error message if an execution error was trapped.  In the usual success case, the second element is the return code from the ei_initialize procedure.  The following return values are possible: 0 meaning success, 1 communication failure, 2 request online failed, 3 clock synchronization failed, 4 failed setting equipment constants, 5 failed disabling events, 6 failed enabling events and reports, 7 failed enabling disabling alarms, 8 spool initialization failed.  You can and should edit the properties of your SecsHostCpp so the initialization does not attempt to use message types that your equipment cannot handle.
COM_DISABLE
This event report occurs when communication with the equipment is lost.
COM_ENABLE
This event report occurs when communication with the equipment is established (or re-established).
TRACE_REPORT
The SecsHostCpp logic maps Trace Reports into Event Reports with this event name.  This lets you use common software to capture trace and event reports.

Built-in Handling of SECS Message Types

The E5 standard identifies data items used in message items with all uppercase letters such as CEID.  Typically, the standard allows for different data types to be used for a particular message item.  Historically, the host software has been required to know and use the specific data types that the equipment implements when the standard allows for different data types.  That is why the SecsHostCpp has configurable properties for the data types that the built-in logic uses and that cannot be discovered automatically.  For most message types, the Hume SECS equipment software accepts any data type for a message data item as long as the value is equivalent.  This behavior cannot be assumed for other implementations.  The table below lists the subset of message types where the SecsHostCpp has built-in handling of the message type, or sends the message type as part of its built-in logic.  Other message types can be easily sent by your application using the sendSecsMsg method or received and handled by your application using the messageTypeAdd method.  The Data Formats in the table below show the Host message formats in situations where host and equipment send the same message type with different data formats.
 
Type Sender Data Format Comments
S1F1R H, E   "Are You There?"
S1F2 H L "On Line Data"
S1F3R H L [<SVID>]*
<SVID>  := {U4 <varID>}
"Selected Equipment Status Request" 
S1F4 E L [<SV>]* "Selected Equipment Status Data"
The data type of the SV value depends on the variable.
S1F11R H L [<SVID>]*  "Status Variable Namelist Request"
S1F12 E L [{L:3 <SVID> <SVNAME> <UNITS>}]+  "Status Variable Namelist Reply"
S1F13R H,E L  "Establish Communications Request"
S1F14 H L:2 {B 0} L  "Establish Communications Request Acknowledge"
S1F15R H   "Request OFF-LINE"
S1F16 E <OFLACK> "OFF-LINE Acknowledge"
S1F17R H   "Request ON-LINE"
S1F18 E <ONLACK> "ON-LINE Acknowledge"
       
S2F13 H L [<ECID>]* "Equipment Constant Request"
S2F14 E L [<ECV>]* "Equipment Constant Data"
S2F15R H L [{L:2 <ECID> <ECV>}]* "New Equipment Constant Send"
S2F16 E <EAC> "New Equipment Constant Ack"
S2F17R H   "Date and Time Request"
S2F18 E A:16 YYYYMMDDHHMMSScc 
A:12 YYMMDDHHMMSS
"Date and Time Data"
S2F23R H L:5 <TRID> <DSPER> <TOTSMP> <REPGSZ> {L [<SVID>]+}  "Trace Initialize Send"
S2F24 E <TIAACK> "Trace Initialize Acknowledge"
S2F25R H,E B [<b>]* "Loopback Diagnostic Request"
S2F26 H B [<b>]*  "Loopback Diagnostic Data"
S2F29R H L [<ECID>]* "Equipment Constant Namelist Request"
S2F30 E L [L:6 <ECID> <ECNAME> <ECMIN> <ECMAX> <ECDEF> <UNITS>]+  "Equipment Constant Namelist"
S2F31R H A:16 YYYYMMDDHHMMSScc 
A:12 YYMMDDHHMMSS
"Date and Time Set Request"
S2F32 E <TIACK> "Date and Time Set Acknowledge"
S2F33R H L:2 <DATAID> {L [{L:2 <RPTID> {L [<VID>]*}]*} "Define Report"
S2F34 E <DRACK> "Define Report Acknowledge"
S2F35R H L:2 <DATAID> {L [<CEID> {L [<RPTID>]*}]*} "Link Event Report"
S2F36 E <LRACK> "Link Event Report Acknowledge"
S2F37R H L:2 <CEED> {L [<CEID>]*} "Enable/Disable Event Report"
S2F38 E <ERACK> "Enable/Disable Event Report Acknowledge"
S2F39R H L:2 <DATAID> <DATALENGTH> "Multi-block Inquire"
S2F40 E <GRANT> "Multi-block Grant"
       
S4F25R H L:2 <DATAID> <DATALENGTH> "Multi-block Inquire"
S4F26 E <GRANT> "Multi-block Grant"




S5F1R E L:3 <ALCD> <ALID> <ALTX> "Alarm Report Send"
S5F2 H B 0 "Alarm Report Ack"
S5F3R H L:2 <ALED> <ALID> "Enable/Disable Alarm Send"
S5F4 E <ACKC5> "Enable/Disable Alarm Ack"
S5F5R H <ALID vector> "List Alarms Request"
S5F6 E L [{L:3 <ALCD> <ALID> <ALTX>}]* "List Alarm Data"
S5F7R H   "List Enabled Alarm Request"
S5F8 E L [{L:3 <ALCD> <ALID> <ALTX>}]* "List Enabled Alarm Data"
       
S6F1 E L:4 <TRID> <SMPLN> <STIME> {L [<SV>]+} "Trace Data Send"
S6F3[R] E L:3 <DATAID> <CEID> [{L:n {L:2 <DSID1> {L:m [{L:2 <DVNAME> <DVVAL>}]*}}]* "Discrete Variable Data Send"
S6F4 H B 0 "Discrete Variable Data Ack"
S6F5R E L:2 <DATAID> <DATALENGTH> "Multi-block Data Send Inquire"
S6F6 H B 0 "Multi-block Grant"
S6F11R E L:3 <DATAID> <CEID> {L [{L:2 <RPTID> {L [<V>]+}}]+} "Event Report Send"
S6F12 H B 0 "Event Report Ack"
S6F13R E L:3 <DATAID> <CEID> {L [{L:2 {U4 <rptid>} {L [{L:2 {U4 <vid>} <V>}]+}}]+} "Annotated Event Report Send"
S6F14 H B 0 "Annotated Event Report Ack"
S6F23R H <RSDC> "Request or Purge Spooled Data"
S6F24 E <RSDA> "Request or Purge Spooled Data Ack"
       
S7F1R H,E L:2 <PPID> <LENGTH> "Process Program Load Inquire"
S7F2 E,H <PPGNT> "Process Program Load Grant" - The SecsHostCpp always sends B 0.
S7F3R H,E L:2 <PPID> <PPBODY> "Process Program Download"
S7F4 E,H <ACKC7> "Process Program Download Acknowledge"
S7F5R H,E <PPID> "Process Program Upload Request"
S7F6 E,H L:2 <PPID> <PPBODY> "Process Program Upload Data"
S7F19R H   "Current Process Program Dir Request"
S7F20 E L [<PPID>]* "Current Process Program Data"
S7F27R
E
L:2 {A <ppid>} {L {L:3 {B <ackc7a>} {U4 <seqnum>} {A <errw7>}}}
"Process Program Verification Send"
S7F28
H

"Process Program Verification Acknowledge"
S7F29R
E
{U4 <length>}
"Process Program Verification Inquire"
S7F30
H
<PPGNT>
"Process Program Verification Grant"
S7F37R
E, H
A <dsname>
"Large Process Program Send"
The sender wishes to send a large process program using Stream 13 messages.
S7F38
E, H
B <ackc7>
"Large Process Program Acknowledge"
Return values are: 0 = ok, 1 = permission not granted
S7F41R
E, H
A <dsname> "Large Process Program Request"
The sender of this message wishes to receive a large process program using Stream 13 messages.
S7F42
E, H
B <ackc7> "Large Process Program Acknowledge"
Return values are: 0 = ok, 1 = permission not granted, 4 = PPID not found, 6 = other error
Error value 6 is returned if there is a file system error such as the file being locked. 




S*F0     abort replies are handled as a special case of reply
S9F1 E <MHEAD> "Unknown Device ID"  - The SecsHostCpp has logic to automatically correct this error when first establishing communication.
S9F3 E <MHEAD> "Unknown Stream"
S9F5 E <MHEAD> "Unknown Function"
S9F7 E,H <MHEAD> "Illegal Data"
S9F9 E,H <MHEAD> "Transaction Timeout"
T3 timeout
S9F11 E <MHEAD> "Data Too Long" 
       
S10F1 E L:2 {B 0} {A <text>} "Terminal Request"
the example application handles this message type
S10F3R H L:2 <TID> {A <text>} "Terminal Display, Single"
 S10F4  E  <ACKC10>  




S13F1R E L:1 {A <dsname>}
"Send Data Set Send"
Per the process program transfer scenarios in GEM E30, only the equipment sends S13F1R to offer uploading a large, unformatted PP.
S13F2
H
L:2 {A <dsname>} {B <ackc13>}
"Send Data Set Acknowledge"
Per GEM E30, this reply is expected to be sent only by the host.
S13F3R
E, H
L:3 {U4 <handle>} {A <dsname>} {U4 <ckpnt>}
"Open Data Set Request"
S13F4
E, H
L:5 {U4 <handle>} {A <dsname>} {B <ackc13>} {U1 <rtype>} {U4 <reclen>}
"Open Data Set Data"
Ackc13 return code values are: 0 = ok, 2 = unknown data set name, 3 = bad checkpoint value,  9 = handle in use, or 66 = file system error
The equipment can use any data type for HANDLE but the U4 type is used for sending.  The <rtype> value sent is 0 indicating a stream.  The <reclen> value sent as a maximum read size is 65536 which reflects a balance of many considerations.
S13F5R
E, H
L:2 {U4 <handle>} {U4 <readln>}
"Read Data Set Request"
If the maximum read size, <reclen>, is greater than 32768, the host sets <readln> to 16384.  If the maximum read size is less than or equal to 32768, the host uses the maximum read size as the <readln> value.
S13F6
E, H
L:4 {U4 <handle>} {B <ackc13>} {U4 <ckpnt>} {L:n {B <fildat>}}
"Read Data Set Data"
Ackc13 return code values are: 0 = ok, 6 = no open data set for the handle, 7 file system error, 8 = at end of data.
On sending, the host sends <fildat> as a single list item binary vector (L:1 {B <fldat>}).  On receiving, the host is able to handle lists of any number of elements.  Only data types B or A are allowed for <FILDAT>.
S13F7R
E, H
L:1 {U4 <handle>}
"Close Data Set Send"
S13F8
E, H
L:2 {U4 <handle>} {B <ackc13>}
"Close Data Set Acknowledge"
Ackc13 return code values are: 0 = ok, 6 = no open data set for the handle
S13F9R
E, H

"Reset Data Set Send"
The property value use_S13 determines whether this message is send during initialization.
S13F10
E, H

"Reset Data Set Acknowledge"

License Terms

Subject to Change Without Notice

The Hume SecsHostCpp software is licensed for development and runtime use at no additional charge for computers that are licensed for development use of the Hume Integration Datahub SDK.

Hume Integration is also pleased to offer separate runtime licenses for using the SecsHostCpp software on systems that are not licensed as development systems.  Contact Hume Integration for more information.


Version Information

Date of last document revision: $Date: 2023/09/22 16:20:10 $