SecsEquip - A Python Class for Deploying Equipment SECS Interfaces


The SecsEquip class library is a high-level Python class for rapidly deploying SEMI standard GEM compliant SECS equipment interfaces.  Without any customization, the class implements almost all of the Fundamental GEM Requirements and the Additional GEM Capabilities.  Method calls are provided for the developer to add his own Status Variables, Equipment Constants, Alarm Definitions, and Event Definitions to complement the existing items specified in the GEM standard.  The developer registers callbacks to receive asynchronous inputs such as Remote Command invocations, Terminal Display invocations, or the reception of any SECS message type of his choosing.  Other callback mechanisms are used to provide Variable values needed for satisfying Host requests and for sending dynamic Event Reports. 

Feature Summary

GEM Compliance Statement

The software is written to conform to SEMI Standard E30 - Generic Model for Communications and Control of SEMI Equipment (GEM).  It also provides compliance to SEMI standards E5, E37, E37.1, and E10.  The software is also fully compliant with photovoltaic industry standard SEMI PV2.

The Equipment OEM developer will need to be mindful of the standards when designing his application in order to insure that compliance is fully met.  Standard reference documentation is also required.  The Hume Datahub SDK includes a SECS/GEM reference document generator app which should be used early in the project development.  The generated document provides additional guidance on topics such as the required user interface features and persistence of connection properties.
 
 
Fundamental GEM Requirement Implemented Gem Compliant Implementation Notes
State Models Yes Yes The Communication State model is implemented by the SecsEquip and controlled by calling the commEnable and commDisable methods.  The current Communication State value is readable as the property, CommState. Your application receives notification of CommState and similar state changes by handling the SecsEquip StateChange event.  This event notifies you of important changes such as communication with the Host starting or ending.

Your logic and your Operator GUI affect the Control State by setting the controlIntentOnline and controlModeRemote properties. 

Comments on the Process State model follows in the next row.  Other equipment models such as Spooling are described below in this table.

Equipment Processing States Yes Yes The example application fully implements a Process State model that you can copy and modify.  Follow the example as far as posting standard GEM events for Process State changes and related events such as selecting a different Process Program.  You also need to update Status Variables to keep track of the previous and current process states, just as the example application demonstrates.
Host Initiated S1F13/F14 Scenario Yes Yes This behavior is fully provided by the SecsEquip class.
Event Notification Yes Yes Your logic needs to call the eventPost() method at the occurrence of standard collection events.  You may choose to define and report additional event types for the activities of your equipment.
On-Line Identification Yes Yes You are obligated to set the property values MDLN and SOFTREV to reflect the hardware and software configuration of the equipment.  Any change in the equipment software requires the developer to also set a new unique value of SOFTREV.
Error Messages Yes Yes The standard requires use of Stream 9 Error reporting.  The SecsEquip sends specific Stream 9 messages for communication faults, conversation timeouts, incorrect device ID, unhandled message stream or function types, and non-standard data.  In the custom message handling logic that you write, use the method sendS9 to send error messages when the received message data is not in the expected format.
Documentation Yes Yes Hume Integration provides a Documentation generation app which fully meets the requirements of the GEM and SECS standards. 

 The SECS Server has the ability to export HTML documents or CSV spreadsheet data of the configured event, alarm, and variable table data.  You may want to use this feature of the table window that is displayed by executing the debugTableWindow method.

Control (Operator Initiated) Yes Yes Use the demonstration application as a worked example.  The startup control state is settable using the property controlStateStartup.  The operator choice of ON-LINE or OFF-LINE control is settable as the property value controlIntentOnline.  The desired substate of ON-LINE control, LOCAL or REMOTE, is settable as the property controlModeRemote.  The actual control state value reflects interaction with the Host and is readable as the property controlState or controlStateEnum.  Your application receives notification of ControlState and similar state changes by handling the SecsEquip StateChange event.
ADDITIONAL CAPABILITIES      
Establish Communications Yes Yes This behavior is fully provided by the SecsEquip class.
Dynamic Event Report Configuration  Yes Yes This behavior is fully provided by the SecsEquip class.

With the capabilities that involve Status Variable values (SV) or Data Variable values (DVVAL), your job is to add equipment specific variables using the variableAdd method.  You either provide their values through a callback using variableMethodSet or by calling variableSet when their values are changed.  You use the eventAdd method to define additional data collection events supported by your equipment.

Variable Data Collection Yes Yes This behavior is fully provided by the SecsEquip class. 
Trace Data Collection Yes Yes This behavior is fully provided by the SecsEquip class. 
Status Data Collection Yes Yes This behavior is fully provided by the SecsEquip class. 
Alarm Management Yes Yes This behavior is fully provided by the SecsEquip class.  Your job is to add equipment specific alarm types using the alarmAdd method.  You use the method alarmSet to indicate when an alarm condition is set or cleared.  You can optionally use the method alarmEnable to enable or disable reporting of an alarm type as a Stream 5 message.  Gem also requires event reports for the Alarm Set and Alarm Clear events.  These event definitions are automatically created and managed for you by the SecsEquip when you use the alarmAdd method.
Remote Control Yes  Yes The example application shows how to use messageTypeAdd to receive and process Remote Commands (S2F21, S2F41, or S2F49) in your application code.  Per the example app, you need to implement control logic that is mindful of the Process State model and the Control State model.  For example, you need to disallow Remote Commands that affect processing when you are in the Online Local Control State. 
Equipment Constants Yes Yes This behavior is fully provided by the SecsEquip class.  Your job is to add equipment specific constants using the parameterAdd method.  You call parameterSet if your GUI logic or controller logic changes a parameter value so that the SECS Server can update the ECIDChangeName GEM variable, and issue the GEM "Operator Equipment Constant Change" event.  If the host changes an Equipment Constant, you are notified via a ParameterChange event.
Process Program Management Yes Yes The SecsEquip class fully implements process program management features with upload and download capabilities.  You can set the directory used for process programs as the property RecipeDirectory.  You can set whether process program data is transferred as binary or text using the RecipesAreBinary property.  Your application is notified of process program change events by handling the SecsEquip StateChange event.   You will receive notice when recipes are downloaded from the host, uploaded to the host, or deleted by the host.  You can use these notifications to trigger validation of downloaded recipes, or you can defer validation until the time the process program is loaded for use.  An OEM that uses a database or other non-file representation of process programs can use the PPFilesByRequest feature to manage writing and reading files when needed to support transfer actions.  The SecsEquip supports transferring larger files using either Stream 13, or with Stream 7 by setting the PPBodyFileMode property True to bypass excessive memory use.
Material Movement Yes Yes The GEM standard only requires that the equipment provide Data Collection events when material is sent from any port on the equipment, or received by any port, whether the transfers are automated or manual.

Automated Material Movement is implemented by calling the method messageTypeAdd and registering a callback for each of the primary message types that the host sends.  In your callback, you parse the received SECS message data using the lsplit and lindex methods.  You send reply messages using the sendReply method.  You initiate your own primary messages and optionally wait for the SECS replies using the sendSecsMsg method.  You can copy-and-paste example parsing code for any standard message type from the Hume website.

Equipment Terminal Services No   This feature is a commonly implemented by various Hume example apps, but it is not featured by the gemtool.py Python app.  It is not an important feature for modern automated factories.  An OEM adds this to the tool GUI by calling messageTypeAdd for the S10F3 and S10F5 message types and dislays the received text to the Operator.  Use the method terminalDisplayAck to send Operator acknowledgment events.
Clock Yes Yes The SecsEquip component fully implements a host-settable Clock variable value with standard data format choices.  The example application does not affect the system clock, the host's setting is saved as an offset.
Limits Monitoring No   See the notes for Material Movement, above, to understand the general approach that is taken to implement this capability.  The SecsEquip does define the LimitVariable, EventLimit, TransitionType variables specified by the Standards for this feature.  As the example app demonstrates, these variables are usually removed as Not Applicable during initialization when the feature is not implemented.
Spooling Yes Yes The SecsEquip component fully implements Spooling.  We recommend that the equipment supplier only allow spooling of Alarm messages, and Event report messages or similar messages where there is no control logic tied to the receiving of the reply messages.  These are exactly the message types that most factory CIM workers want to collect with spooling.  If restricting the spooled message types is not done, there are complex issues with implementation and timing that cannot be adequately tested and verified correct.  The standard describes allowing the spooling of nearly any primary message type, out of consideration that any message may occur when the spool is being unloaded, and it should take its proper sequence at the end of the spool.  In practice this is a rare circumstance because an HSMS implementation can unload thousands of messages in a few seconds.  The downside of allowing messages that have control implications to be spooled is that they are queued for a variable and potentially lengthy delay before delivery.  The equipment provider's job is to provide a robust control system, and we think that knowing immediately that a near real-time message conversation cannot be initiated is the right choice. 

The Equipment provider can add to the message types allowed for spooling using the SpoolingAllow method.  The default behavior is to allow only Stream 5 (Alarms) and Stream 6 (Event reports) to be spooled.

Control (Host-Initiated) Yes Yes The SecsEquip class fully implements this behavior.


User Guide

The Hume Python SECS Equipment .zip download archive is named  python_equip.zip.  The archive contains only python text files and the same download is used for any platform supported by the Hume DMH86 SDK.  The library utilizes the Python tkinter package to work with an embedded Tcl interpreter.  During initialization the embedded Tcl interpreter loads the Hume DMH Tcl package installed by the Datahub SDK.  Loading this package provides low-level C-code extensions for DMH communication.  Instantiating a SecsEquip instance starts a different Tcl/Tk process running in background which is used for the SECS communication, built-in application logic, and management of application data in high-performance in-memory SQL tables.

Here is an overview of the files for the class library and example application.  There are only three python files:

dmhclient.py
This file is python source code for the Dmhclient library which provides methods for communication with the SECS Server process.
secsequip.py
This file is python source code for the SecsEquip class library which provides the features needed for an equipment SECS/GEM implementation.  This file is intended for re-use without modification by the developer.
gemtool.py
This file is python source code for an example equipment application which provides a minimal graphical user interface (GUI) featuring all the required features of the SECS/GEM standards.  The GUI uses the python tkinter library and is identical in appearance to the Tcl/Tk GEM Tool app which is featured on the Hume SDK Start Menu Program Group.  The design is intended to serve as a starting point for OEMs to customize with python programming.

Installation

Installation of the SecsEquip software consists of extracting the files in the zip archive to a directory of your choice, and installing the latest DMH86 Hume Datahub SDK.  If you have already installed the Hume Datahub SDK,  you should not add the files in the python archive to any of the existing Datahub SDK GEM application directories. 

The SecsEquip software uses the SECS/GEM application files provided in the Hume Datahub SDK product.  A developer needs to install the latest and newest Hume Datahub SDK, and specify on the SETUP screen that the GEM/SECS applications should be installed.  Use the usual installation sources to install Python 3.10+.  Python tkinter uses Tcl/Tk 8.6 so your Hume SDK version needs to be DMH86 and not DMH85.  Install and use only 64 bit Python and packages on Windows for compatibility with the Hume Windows 64 bit DMH86 SDK.  The SecsEquip 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. 

An OEM can choose to manage the SDK Tcl application files as a set for a runtime deployment by installing and using the SecsServer large executable file instead of the gem2 and bin directories of an SDK installation.  The Dmhclient python code needs the dmh86 lib directory which is installed by the SDK to /usr/local/lib/dmh86.  This directory could be copied/moved into the system directories used by python for tkinter and Tcl/Tk.  The other SDK files can then be removed or not installed if the single large file executable, SecsServer.exe is installed instead.  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 SecsServer86.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. 

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 file with either the Datahub SDK installed, or with the SecsServer executable for your platform.  Make sure the environment variable DMH_BIN is set and exported if the Datahub SDK is being used.  The environment variable described next should be set for all platforms.

Environment Variable SECS_EQUIP_TCLDIR

When the first SecsEquip instance is constructed, a search is done to figure out if the SecsServer executable is installed or whether using the SDK is intended.  We recommend you explicitly control this search by setting the environment variable SECS_EQUIP_TCLDIR to the directory path containing the SecsServer[.exe] executable, the HumeSDK.exe, or the SDK 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 when configuring the variable value.  On Windows, environment variables can be set by navigating from the Start menu - Start/Settings/Control Panel/System/Advanced/Environment Variables.  An example value for the default SDK installation on Windows is:
SECS_EQUIP_TCLDIR=C:/usr/local/gem2/server

If the environment variable is not defined, the server start logic looks for the server file in the current working directory.  If the SecsServer executable is not found then the startup logic searches for the SecsServer.tcl file in the gem2/server directory of the Datahub SDK installation found using the environment variable DMH_BIN or the default SDK install path. 

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 this licenses.txt file.  Because the python Dmhclient software uses the DMH package, there also needs to be a licenses.txt file in the lib/dmh86 directory.  The default directories used for process program transfer and for persistence are subdirectories of where the SecsServer or SecsServer.tcl file is found.  These directories are customized by setting properties.

You can check the license validity of a 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 during initialization if the DISPLAY environment variable is either not defined, or is defined to be an empty string.  This gives you the capability of executing without being tied to any display.  However, the GEM standards do require certain front-panel features, so chances are you do need X-windows to provide a GUI.

Development

To start using the Hume Python SecsEquip class with an existing python project, the default processing of import statements looks for the Hume-provided files in the same directory of your python code.  Typical import statements might be:

import dmhclient as dmhclient
import secsequip as secsequip
from secsequip import ControlStateEnum, EquipStartupData, SecsEquip, VariableInfo
from dmhclient import lindex, ljoin, lsplit, RcResult

Here we see that certain list functions from dmhclient are being imported so that the developer can type the function names without their dmhclient. prefixes.  Microsoft's IDE code will add import statements automatically to fix broken references. 

Your primary focus as a developer is using the class SecsEquip.  This class implements public methods to send and receive SECS messages, and manage an equipment SECS interface.  Look closely at the sample gemtool.py application, and particularly the app_secs_init() method and basically copy and edit the SECS interface initialization code.

Here is the general flow of using and configuring a SecsEquip instance to deploy an equipment SECS interface:

  1. Setup your error handler callback first by setting the SecsEquip.handlerServerError static pointer item.  Your application may receive error notifications if the license or software installation are not proper when you try to instantiate a SecsEquip instance.  Therefore, have the error handling in place first so you can provide the user notification of any errors.
  2. Construct a SecsEquip instance.  You may get better prompting help if you initially code the construction at the global level of the source file.  For a production app you want the construction to occur after the error handler is installed. 
    secs = SecsEquip("pyapp")
    
    When the SecsEquip instance is constructed, it spawns a SECS Server process. 
  3. Set the secs.handlerStateChange pointer to receive StateChange events.  After the next step is taken and the app begins to pump receiving events, your callback is executed to provide you with initial values of state data.  Our example app does not pump events until the GUI is fully-constructed and ready to update with data change notifications.
  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 application uses the startupLoad() and startupRestore() methods to load and apply saved startup configuration data.  If you choose not to use the startupRestore() method, then you must call connectTypeHsmsPassive(), connectTypeHsmsActive(), or connectTypeSerial() 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 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. Now you can perform the bulk of your SECS interface configuration.  Do the following, in any order:
  6. If you are not using startupRestore() you can set the desired Control State properties.
  7. With the interface configured, and callbacks in place, call commEnable to enable host communication if the persisted startup data says that is desired. 

    Per the standards, you should offer a configuration dialog so that the desired startup configuration of the Contol State and whether communication is enabled is user-specified and persistent.  You may use the dialog and logic of our example application to implement these features.

  8. A Trace window is shown by executing the debugTraceWindow() method.  Plan on including this window in your application or a similar feature so that your users in the field can diagnose communication problems and capture message conversations in log files. 
  9. Your application can call commDisable to disable host communications when shutting down or when SECS communication is no longer desired.  It is called automatically in the SecsEquip destructor method.

Tcl Secs Notation, TSN

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 library 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 lindex or lsplit methods to parse the text, they take care of parsing and removing surrounding braces for you.  If an empty string is received, 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.  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 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.  The application 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 -1"
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 0"
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 SecsEquip class has built-in logic to handle about 100 of the standard SECS message types.  You do not have to code or provide for complex GEM capabilities such as dynamic event reports, or the communication and state models.  See the reference table for more detail on the built-in message types.

Similarly, the variables required for GEM compliance are already defined, and are listed in the built-in variables table. In some cases, such as the PPExecName variable, your custom application logic has to provide current data values.  The example application demonstrates using the variableSet method or the variableMethodSet method as techniques to supply variable values.  If a data item's value is relatively constant, its more efficient to use variableSet which provides the current value to the SECS server process.  The variableMethodSet callback method is the right choice for data items whose value changes more often, or are easier to manage as Python application data items.

The SecsEquip software uses type U4 numeric identifiers for the numeric IDs specified by GEM such as ALID, CEID, ECID, and SVID.  These identifiers are passed as unsigned, 4 byte integers - SEMI Octal code 54.

 There are also some standard event report types specified by GEM and pre-defined for you as listed in the built-in events table. Your application logic needs to call eventPost as these events and your own defined events occur during processing.
 

Custom SECS Message Handling

Use the method messageTypeAdd to have SECS messages routed to your callback code for custom handling.  Your callback code uses sendReply to respond to the inbound message.

Logic in your application can send SECS messages or initiate conversations using the sendSecsMsg method.  For HSMS communication,  if you are sending a message and not waiting for the reply, sendSecsMsg can be used from your GUI code without fear of making your GUI unresponsive.  In some cases you need to wait for a SECS reply message.  If you are using HSMS, under most circumstances, the host's reply or failure to reply will be resolved within a few seconds.  An unusual circumstance is that you still have a TCP/IP connection to the host so your send is successful, but then the host does not reply, and you wait the full T3 timeout period.  You can code your logic so that if the host does not respond to any message, you transition to offline control so subsequent message sends fail right away because they are not appropriate in an offline control state.  So with this change, you risk making the GUI unresponsive for a single T3 period in some unusual circumstances. 

Miscellaneous Notes

Your design will typically use one instance of a SecsEquip component to provide a single SECS interface.  You can use multiple instances of the class to provide more than one SECS interface.  Each interface can have its own custom handling of message types.  Although it would be unusual, an OEM can provide more than one SECS equipment interface to support multiple factory host applications if provision is made for coordinating control.  The latter can be as simple as telling every interface except one that the equipment is under local control. 

SecsEquip Class Reference

 
SecsEquip Properties
Property Access Description
General Notes on Properties The SecsEquip class uses the advanced Python syntax involving @property and propertyName.setter to designate methods as property value getters and property value setters.  A developer can then get or set the property values as if they are public variable members of the class. For example:

# get
if secs.alarmsShareEvents == True:
    print("value was True")
    # set 
    secs.alarmsShareEvents = False

alarmsShareEvents Set this property value True to have the same AlarmDetected and AlarmCleared data collection events reported for any alarm type.  The preferred value of this property should be set before calling the alarmAdd() method.  The preferred behavior for new applications is to have the value set True and to share generic events. The default value is True.
BAUD This integer property sets the baudrate of the serial port for the SECS-I, RS-232 connection type.  The default value is 9600.
bindir This read-only string value is the file system directory where the SDK executables or the SecsServer executable is found.
commState

commStateEnum

class CommStateEnum(Enum):
    CommDisabled = 0
    CommEnabledNotCommunicating = 1
    CommCommunicating = 2
The commState property is a read-only string value of the current 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.

The commStateEnum property returns the same state information as an enum value.
controlIntentOnline Your intended GEM Control State behavior, whether your equipment intends to be ON-LINE.  In the OFF-LINE control state, the tool does not send most message types such as Alarms or Event Reports.  The default setting is OFF-LINE.
controlModeRemote When in ON-LINE control, your intended substate of LOCAL or REMOTE control.  Defaults to False implying LOCAL operator control.
controlState

controlStateEnum
class ControlStateEnum(Enum):
    OfflineEquipment=0
    OfflineAttemptOnline=1
    OfflineHost=2
    OnlineLocal=3
    OnlineRemote=4

controlStateText = [
 'OFF-LINE Equipment', 
 'OFF-LINE SeekOnline', 
 'OFF-LINE Host', 
 'ON-LINE LOCAL', 
 'ON-LINE REMOTE']

These read-only properties return the current GEM Control State as a string or enum value. The current state reflects the controlModeRemote, controlIntentOnline settings interacting with the host.  The StateChange event is used to obtain asynchronous notification of this property value change. 
controlStateStartup Your app can specify the initial state for the GEM Control State model.  The choices are the ControlStateEnum values seen above. This setting defaults to OfflineEquipment, but is overruled to be consistent with your controlIntentOnline and controlModeRemote values.  The consistency logic is applied when commEnable is called.
DEVID This read/write integer value is the SECS Device ID which is imbedded in SECS message header data.  The value is usually left at the default of 0.  The value can be changed dynamically, but it is usually configured as a persistent value that is only changed at startup before communication is enabled.  In the old days, the DEVID value allowed furnace tubes to share a single SECS interface.  Per the standard, the SecsEquip rejects messages from the host that are not for the equipment's Device ID.  The Hume Host software recognizes the Stream 9 error message for an incorrect DEVID and automatically fixes the configured Host value.  Settable range is 0..32767.
DMH SecsEquip instances use a shared DMH message system Dmhclient instance in order to communicate with the SECS server process.  A reference to the connection instance is available as a static property for custom purposes.
DmhGroupName SecsEquip and SecsHost instances use a shared DMH message system Dmhclient instance in order to communicate with the SECS server process.  The same DMH Groupname string property value is used by all instances. 
HSMS Whether the Connection type is HSMS (LAN based).  False implies SECS-I, serial RS-232 communication.  Defaults to True.
HsmsHost For an active HSMS connection, this read/write string value specifies the TCP/IP hostname or IP address of the Host computer.  Both IPv4 and IPv6 are supported.  The value is not used for HSMS passive communication.
HsmsPassive
For an HSMS connection, this boolean property sets whether the SecsEquip plays the passive, TCP/IP server role.  The default value is True which is the usual role of equipment. 
HsmsPort For an HSMS connection, this read/write integer value is the TCP/IP socket port number.  Defaults to 5555.
IdRangeChecked By default, the methods to add Alarm, Event, Variable, and Parameter definitions, restrict the numeric ID values allowed to ranges which prevent colliding with built-in values, or colliding with each other's values.  However, the range checking can be disabled by setting this property value false.  Also, you can renumber the built-in events and variables, and customize the events that are assigned for alarm set and clear events.  Thus, you are able to completely customize the identifiers used by the SECS interface.  If you choose to renumber and customize the identifiers, do it in your initialization logic before enabling communication, but after restoring or configuring the connection type.  This insures that connection instance data exists in the SECS server to hold your customization.
MDLN A read/write string value for the SECS Equipment Model Type limited to no more than 20 characters by the E5 standard.
MULT A boolean read/write value for SECS-I serial connections.  When this property is True, multiple open transactions are allowed.  When False, a new message may be sent requesting a reply before the host has replied to a previous message.  The flag is only for SECS-I, and the default value is True. 

HSMS host implementations should not have a problem with multiple open transactions.  However, there are factories with deficient software who would rather compromise the standards than fix their bugs.  If you get into a customer support situation with HSMS and multiple open transactions, please contact us - we have a lightweight go-between application that queues and serializes the open transactions.

Name This read-only string value is the SecsEquip 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.
ParametersAreSaved This boolean property controls whether the values of parameters (Equipment Constant Variables) are saved at the program exit and restored during the next session.  Saving the values is standard GEM behavior so the default value is True.  When True, the saved values are restored the first time that commEnable is called, unless they have already been restored by calling the method parametersRestore.  In other words, you can use the method parametersRestore to force loading of the saved values before commEnable is called.  The value data is saved as a file of SQL statements in the subdirectory spooldata.  The filename used is "EcvParms_" + Name + ".sql".
PPBodyFileMode 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.  Setting True 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 True 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 1 meg or larger.  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 works the same.
PPFilesByRequest This boolean property is set True if the app must prepare process program files for upload.  A typical use is when process programs are managed in a database and do not exist on the file system.  The setting is used when SECS message types S7F5R or S7F41R are handled by the built-in SECS Server logic.  The value is left at the default value of False if process programs already exist as files in the recipe directory or if the equipment does not feature process program transfers.  When the value is set True, the app must handle PPFileRequest events as the trigger to write process program files.  See the description of the PPFileRequest event for more details.
RecipesAreBinary A boolean value to indicate whether Process Program files should be transferred as type B (binary) data, or type A (ASCII) data.  The default is True, meaning binary transfer.  If Process Program files are printable text, the type A transfer may be easier for the factory personnel to work with.  However, that may encourage error-prone editing and inconsistent use of newlines or carriage returns.  The software is able to transfer binary data as type A but not all host software can accommodate this.
RecipeDirectory This string value is the pathname to the file system directory where Process Program files are located.  The default is "./recipes" - a subdirectory of the SECS Server working directory.
ReportsAreSaved This boolean property controls whether the state of event reporting is saved at the program exit and restored during the next session.  Saving the state of dynamic reporting is standard GEM behavior so the default value is True.  If True, the saved event reporting configuration is restored the first time that commEnable is called.  ReportsRestore can be used to force loading of the saved reporting configuration before commEnable is called.   The report configuration data is saved as a file of SQL statements in the subdirectory spooldata.  The filename used is "reportdata_" + Name + ".sql".
RTY This integer read/write value is the SECS-I retry count.  The value specifies the maximum number of send retry attempts for block transmission.  The default value is 3 with an allowed range of 0..31.
SerialPort This read/write string value specifies the serial port device such as "COM1" for a SECS-I connection.
ServerDir This static property returns the working directory of the SECS server.
SOFTREV This read/write string value is the SECS Software revision - limited to no more than 20 characters.  Default value is "1.0.0".  You may wish to consider a pattern of major.minor.patchlevel.  The value should be revised any time a change is made to the equipment SECS interface software.
SpoolDirectory A configurable property for the file system directory for spooling, report configuration, alarm enablement, and parameter (ECV) persistence files.  The default TraceSaving logging directory is also underneath the spooling directory.  The get method returns a fully qualified path that uses slash path separators on all platforms.  The default spooling directory is the sub-directory spooling under the working directory of the SECS server.  For a default Datahub SDK installation and startup, the directory is /usr/local/gem2/server/spooling.  The directory value may be set early in the initialization before startupRestore() or connectTypeSet is called.  An exception is thrown by the set method if the specified directory is not valid or if the method call is not made before the connection type is set.
SpoolingAllow This string property is set to specify the streams which the host is allowed to specify for spooling in message type S2F43.  It is formatted as a space separated list of "S<s>" tokens where the <s> value is stream number.  The standard does not allow Stream 1 to be spooled.  The default value is "S5 S6" which allows for spooling alarm messages and event reports.  An empty string value disallows any spooling.  The value only affects the handling of S2F43 messages from the host.  Your software is able to change at any time which message types are being spooled using the method, SpoolStreamFns.
SpoolingIsActive This read-only boolean property returns True if spooling of messages is currently active.
State A read-only string 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.  The StateChange event is used to obtain asynchronous notification of this property value change.
T1 This read/write integer property is the SECS-I Inter-Character Timeout in milliseconds, range 100..10000, default 500
T2 This read/write integer property is the SECS-I Protocol Timeout in milliseconds, range 200..25000, default 10000
T3 This read/write integer property is the SECS Reply Timeout in milliseconds, range 1000..120000, default 45000
T4 This read/write integer property is the SECS-I Inter-Block Timeout in milliseconds, range 1000..120000, default 45000
T5 This read/write integer property is the HSMS Connect Separation Timeout - the delay between re-connection attempts in milliseconds, range 1000..240000, default 10000
T6 This read/write integer property is the HSMS Control Transaction Timeout in milliseconds, range 1000..240000, default 5000
T7 This read/write integer property is the HSMS Not Selected Timeout in milliseconds, range 1000..240000, default 10000
T8 This read/write integer property is the HSMS Network Intercharacter Timeout, default value 5000.  This value is not used.
TRACE This read/write integer property is 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.  The value 0x440E is a reasonable default for Trace Window initialization. 

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 

TraceLogMaxWidth This integer read/write 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.
setTraceSaving(save:bool, compress:bool, maxDayFiles:int, saveDir:str, zipCmd:str) -> RcResult
 
TraceDataIsCompressed
TraceDataIsSaved
TraceSaveDir
TraceSaveMaxDay
TraceSaveZipCmd
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 before overwriting, 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 other properties listed provide read-only access to individual values.

Trace 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.exe -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. 

The RcResult return value of setTraceSaving() is used as follows.  If the rc value is less than 0 the 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.

useS13 This boolean property chooses whether to enable using Stream 13 large process program transfer message types when an online control state exists.  In addition to the Stream 13 messages, this property also enables or disables using S7F29, S7F37, S7F38, S7F41, and S7F42 which are used with Stream 13 for transferring large unformatted, process programs.  The default value is False.  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.  If Stream 13 message types are enabled, per GEM your application should implement sending S7F27 process program verification messages for  received process programs.


 
SecsEquip 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 can be class methods where the callback value is assigned to be object.method as in self.my_callback or they can be non-class methods where a global function name is assigned to the callback pointer.

The library is single-threaded and callback execution happens as the secs.pump method is executed.  A tkinter GUI app will usually call the secs.pumpSchedule method to setup a periodic timer which runs the pump.  A non-GUI application can import sched and run the pump with periodic calls using a sched.scheduler object.  Other GUI packages such as wxWidgets/wxPython feature periodic timers that can be used.  The library cannot function properly unless the pump method is called by the application event loop.

We will use secs in the code below as our SecsEquip object for method executions.

 


# File Request

def PPFileRequestHandler(ppfr:FileRequest):
    print("FR: Asked to write ppid=" + ppfr.ppid +\
  " dir=" + ppfr.recipeDir)
    pathname = ppfr.recipeDir + "/" + ppfr.ppid
    # we did not change S7F19 so these files already exist
    # pretend we wrote the file
    if os.path.isfile(pathname):
        filename = ppfr.ppid
        ppfr.fileWriteOk(filename)
    else:
        ppfr.fileWriteFailure(ACKC7.PPIDNotFound,\
 "PPID not found.")

secs.PPFilesByRequest(True)
secs.handlerPPFileRequest = PPFileRequestHandler

This callback feature supports implementing Stream 7 or Stream 13 Process Program uploads for apps that manage Process Programs in a database, or otherwise not as single files.  The app should set the property PPFilesByRequest True and code a handler for this callback type.  When the host sends S7F5R or S7F41R to initiate an upload, a PPFileRequest event is raised to trigger the application to write the process program file in the recipe directory.  Use the event argument data structure field ppid for the name of the desired process program, and use the recipeDir value for the file system directory where the file is written.  The filename assigned by the app may differ from the ppid value.  For example, it is common to have a file extension which is not part of the ppid.  The app writes the file or fails.  On success, the fileWriteOk method of the argument object is executed, passing in the filename as it exists in the recipe directory.  Do not include the full pathname, pass only the filename.  If the app cannot write the file, it calls the fileWriteFailure method of the callback argument providing an ACKC7 enum value, and an error description.  Possible ACKC7 are defined in the library, and can be selected by IDE prompting. Approximately 20 seconds are provided to write the file.  If this timeout period is not adequate, the app should instead offer a remote command that initiates a file export and then performs an equipment initiated upload.

This callback is only part of what the application must do to properly manage process programs that are not managed as files in the recipe directory.  The app should call messageTypeAdd(7, 17) and (7,19) to handle delete and directory requests.  The app should also use the StateChange events, recipe_download, and dataset_download to trigger file import logic.  The app can use recipe_upload and dataset_upload to trigger deletion of the export files if desired, or they can left alone to be overwritten by future uploads and downloads.

# Parameter Change

def on_parameter_change(name:str, newvalue:str):
    if toolwin is not None:
        toolwin.on_parameter_change(name, newvalue)
        return

secs.handlerParameterChange = on_parameter_change

This callback event happens with host initiated Equipment Configuration Variable (ECV) changes.  The new value is within the limits you have configured.
# SECS Message Receiving

# S3F1R - add next line to setup
secs.messageTypeAdd( 3, 1, secs_receive_S3F1R)

def secs_receive_S3F1R(sp:SecsEquip, stream:int, function:int, \
send_reply:bool, transactionID:int, TSN_data:str, header:str):
    '''Receive SECS Message S3F1R.'''
    ok = True
    while ok:   # break out of loop on error
        # no data expected
        if send_reply:
            # TODO create reply message, use ljoin() 
            sp.sendReply( 3, 2, transactionID, reply_data)
        return # finished ok
    # here by break from while ok
    # bad data 
    sp.sendS9( 7, header)
# end recv_S3F1R

SECS Message receiving callback - use messageTypeAdd described in the next section to receive SECS messages in your application. 

Example message parsing code for any standard message type can be copied from http://www.hume.com/secs

# SECS Server Error

# callback pointer is class static value
SecsEquip.handlerServerError = on_secs_server_error

def on_secs_server_error(msg:str):
    msg = "SECS Server Error:" + msg
    print(msg)
    if toolwin is not None:
        toolwin.info(msg)
        return

# SECS Server Disconnected

SecsEquip.handlerServerDisconnected = on_secs_server_exit

def on_secs_server_exit():
   print("SECS Server disconnected " + \
"- normal operation is not possible, exiting.")
   exit(3)

# SECS Server Debug

SecsEquip.handlerDebugEvent = on_debug_event

def on_debug_event(message:str):
    print("Debug Message:", message)

Errors that are trapped in the SECS Server process are reported using the callback pointer handlerServerError which is defined as a static member of the SecsEquip class in the secsequip.py file.  Example errors include startup problems because of an improper installation, or trying to send an improperly formatted SECS message.  Once the application has started, error events will happen during development but should be rare for debugged code.

In addition, there are optional debugging messages available to troubleshoot the initial connection to the SECS Server background process at startup.  When the first SecsEquip 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 secsequip.py 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. 

If the SECS Server background process is terminated, the app learns about it from a Server Disconnected callback.  The default handling of this event is to terminate the application.  The gemtool.py example app uses a technique so that closing the SECS Server table window causes it to hide instead of exiting.

# SECS Trace

# ignore SECS Trace data
secs.handlerSecsTrace = on_secs_trace

def on_secs_trace(name:str, value:str):
    # This is the Trace data flow 
    # optionally seen in
    # secs.debugTraceWindow()
    #print(name + ':' + value)
    pass

This event provides the detailed information of SECS message traffic that is viewable in the SECS Trace window.  The information is controlled by setting the TRACE property..
# Spooling Alert

secs.handlerSpoolingAlert = toolwin.on_spooling_alert

def on_spooling_alert(self, msgid:str):
    """Our handler for Operator Spooling alerts."""
    self.info(\
 "\n\n**** Operator Alert %s occurred. ****\n" % msgid)
    # ...

The GEM standard describes Spooling events that are to be brought to the attention of the equipment operator.  The msgid values include SPOOLING_ACTIVATED, SPOOLING_FULL, SPOOLING_TERMINATED, SPOOLING_NOT_PERSISTENT, and SPOOLING_DATA_DISCARDED.  The latter two values are not seen in normal circumstances.
# State Change Events

secs.handlerStateChange = self.on_state_change

def on_state_change(self, name:str, newValue:str):
    if name == "comm_state":
        self.comm_state_change()
        self.info("Communication state changed to " + newValue)
        return
    # ...

This event notifies your application of state value changes. Possible name values include 
  • state - the State property value changed
  • clock_offset - this value is the number of seconds added to the system clock to provide CLOCK variable values for the host.  If the value differs from 0, the host has used S2F31 to set the clock.  Your logic can work with host specified time values by adjusting the system time using this offset value, or by reading the CLOCK variable using variableGet().  We recommend that you avoid this complexity by instructing your customers to use NTP time synchronization and that you disable S2F31 using messageTypeRemove().
  • comm_state - the CommState property value changed
  • control_state - the ControlState property value changed
  • dataset_download - a process program has been downloaded from the host using Stream 13 transfer messages.  The newValue argument is a two item list, the ppid, and the pathname to the newly received file.  Use the lsplit or lindex method to parse the list.  See the discussion of downloaded files in the description of method processProgramLargeRequest.
  • dataset_upload - a process program was successfully transmitted to the host using Stream 13 transfer messages.  The newValue argument is the ppid.
  • event - this value changes when a data collection event is posted either by your logic calling the eventPost method, or by the built-in SECS server logic.  The newValue argument is a two item list, the CEID of the event, and a 1 or 0 indicating whether an event report message was (sent or spooled) or not.  A report is not (sent or spooled) if communication is disabled, or if the event type is disabled, or if the control state is offline.  It is possible when spooling is active that the event type has not been configured for spooling.
  • recipe_delete - the name of a recipe that is being deleted by the host, or being replaced with a downloaded version using Stream 7 messages.
  • recipe_download - the name of a recipe that has just been received from the host using Stream 7 messages.
  • recipe_upload - the name of a recipe that has just been uploaded to the host using Stream 7 messages.  However, if the PPFilesByRequest feature is being used, the newValue argument is a two item list, the ppid, and the pathname to the newly received file.
  • spooling_state - the SecsEquip spooling state, ACTIVE or INACTIVE
  • SpoolCountActual - the number of SECS messages currently spooled
  • SpoolCountTotal - the total number of messages spooled and/or discarded
  • SpoolMax - the configured maximum number of spooled messages
  • SpoolStreamFns - the list of S<s>, S<s>F<f> message types that are configured for spooling
Your application gets notified of the initial values of these items when the SecsEquip connection type is initialized.
# Variable Value Request

# Use callbacks for variable values that change often 
# intead of calling variableSet() with each change.
secs.handlerVarValueRequest = on_VarValueRequest

def on_VarValueRequest(vidList, valueList):
    for i in range(len(vidList)):
        vid = int(vidList[i])
        #print("varvalue request for varID ", vid) 
        # assigned values are converted to str( )
        if vid == VarID.VID_ChamberTemperature.value:
            valueList[i] = "76.4"
            continue
        if vid == VarID.VID_OperatorCommandLast.value:
            valueList[i] = operatorCommandLast
            continue
        if vid == VarID.VID_ProcessRecipeName.value:
            valueList[i] = processRecipeName
            continue
        if vid == VarID.VID_ProcessStateCurrent.value:
            valueList[i] = processStateCurrent.value
            continue
        if vid == VarID.VID_ProcessStatePrevious.value:
            valueList[i] = processStatePrevious.value
            continue
        # else a data type error or informative text value
        valueList[i] = "unhandled VarValueRequest, varID="\
 + str(vid)

The VarValueRequest callback is used to ask your app for variable values if you have elected to manage their values in your app.  Call the method variableMethodSet to specify the variables that your code will manage.  In your event handler, loop through the varID list and assign the current variable value to each corresponding element in the valueList.  This callback only executes when one or more variable values are actually needed to respond to a host query, or to provide data in an event report.

SecsEquip Methods
METHOD DESCRIPTION
General Comments
 
 

 

String data formatted as Tcl lists are commonly used. Tcl list manipulation methods are implemented by the Dmhclient class and usually imported into the app namespace along with the dmhclient.RcResult class.

Many of the method calls return an RcResult structure containing a 0 return code and an empty string value for the usual successful invocation.  In case of error, the return code is non-zero, and the result value is an error message that could be logged or displayed to the user. 

from dmhclient import lindex, ljoin, lsplit, RcResult

    rcr = secs.some_method()
    print("return code =" + str(rcr.rc))  # 0 is usual success
    print("result string =" + rcr.result) # success result or possible error message
    # or call the display method
    rcr.display() 
    # or just print as a string value
    print(str(rcr))
 

In general the methods used during runtime do not raise exceptions, and you do not need to use try and except around method calls.  Exceptions are used to flag errors for configuration methods used during initialization.
alarmAdd(ALID:int, ALTX:str, setCEID:int = 0, clearCEID:int = 0) Add an alarm type definition.  Newly added alarms are enabled.  The Set and Clear event report CEID arguments are commonly left as default values for automatic configuration.  Depending on the setting of the AlarmsShareEvents property, the GEM alarm set and clear data collection events will either be the same events shared by all alarm types, or two new events will be created for each alarm type.  Set your preferred value of AlarmsShareEvents before using this method.

If the AlarmsShareEvents property is True, the Set and Clear event IDs are ignored and should be left as default values.  Use any ALID value from 1000 to 3999.

If the AlarmsShareEvents property is False, and the Set and Clear arguments are defaulted, choose only even numbers for the ALID from 1000 to 3998 to allow for two enabled events to be created for each alarm; an alarm Set event with CEID == ALID, and an alarm Clear event with CEID == ALID+1.

The ALTX argument is a description of the alarm and it has a length limit of 120 ASCII characters.  The ALTX should not contain single quote characters.

The alarmAdd() method lets you specify the CEID values used for the alarm Set and Clear event reports when AlarmsShareEvents is False. Use the CEID arguments if you choose to customize which data collection events are posted for the alarm's Set and Clear events.  If the event types do not already exist, they are created.  There is no validation performed on the specified CEID values, they only need to be representable as 4 byte unsigned integers.   When explicitly providing CEID arguments you are able to specify any ALID value from 1000 to 3999 with the default range restriction in place.

You are able to bypass the usual range restriction of the ALID value by setting the property IdRangeChecked false.

alarmEnable(ALID:int, is_enabled:bool) Enable or disable reporting of an Alarm type (S5F1).  This method is not commonly used, it is usually the host's role to decide which alarms are enabled.

By default per the GEM standard E30, there is built-in logic to save and restore the enabled/disabled settings of the alarms.  The file "alarmdata_" + Name + ".sql" is written to the SpoolDirectory.  When communication is first enabled, this file is read to restore the enabled/disabled settings from the prior session.  An app can disable the built-in logic using the PropertySet method.

alarmIsEnabled(ALID:int) -> bool Test if the reporting of an alarm type is enabled 
alarmIsSet(ALID:int) -> bool Test if the alarmed state is currently set
alarmSet(ALID:int, is_set:bool) Set or Clear the alarmed state of an alarm.  The built-in logic takes care of sending alarm report and event report messages.
alarmText(ALID:int) -> str Lookup the description, ALTX, of an alarm type.  An empty string is returned for a non-existent alarm type.
int binToInt(binValue:str) -> int Converts a SECS B (Binary  - Semi "10") data value formatted as a hexadecimal or decimal string to an integer value.
close() Shutdown the SecsEquip while preserving persisted data.  This method call is the usual shutdown method.
commDisable() Disable SECS communication.  The SecsEquip is initialized without communication enabled so using this method only makes sense after commEnable has been called.
commEnable() 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.  When the equipment is configured for the Active HSMS role, field personnel will want to display the trace window in order to see detailed information on the status of communication attempts. 
connectTypeHsmsActive(host_or_ip:str, port:int) This method is an alternative to setting the underlying property values to specify an active HSMS connection type, and calling connectTypeSet().  The connection type should be set before communication is enabled.
connectTypeHsmsPassive(port:int) This method is an alternative to setting the underlying property values to specify a passive HSMS connection type, and calling connectTypeSet().  The connection type should be set before communication is enabled.
connectTypeSerial(serialPort:str, baudrate::int)
This method is an alternative to setting the underlying property values to specify a SECS-I connection type, and calling connectTypeSet().
connectTypeSet() -> int 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.
debugInspect() This method can be used to exec the Inspect introspection debugger which is useful for examing Tcl code and data in the SECS Server process.  The method is not commonly used.
debugTableWindow(show:bool) This method causes the SECS Server Datahub table management GUI to be shown or dismissed.  On Linux, there needs to be an X-windows session with a DISPLAY defined.
debugTraceWindow(show:bool) This method is used to display a window which updates to show SECS message traffic and state information for the SecsEquip.   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/Tk version of the Trace window which is created by the SECS Server process.  If the window menu is used to change TRACE-related properties, the changes are not propagated back to the python app.  There are scenarios where this could be an issue for example if the app disabled communication and re-enabled it, the app properties would be re-applied. 

Including trace window access in the administration features of your equipment GUI is a practical necessity to help field personnel diagnose communication problems. 

delete() Shutdown and delete the SecsEquip and delete persisted data.
eventAdd(eventName:str, CEID:int, description:str, is_reported:bool = True) This method is used to create an Event type.  With the default range checking of ID values, you are restricted to use CEID values between 5000 and 9999 so you do not collide with Alarm Set and Clear events, or the built-in events.  You can set the IdRangeChecked property false if you need to customize the assigned IDs.  Events are given meaningful names, usually using CamelCase such as RecipeStepComplete.  Specify names that are less than 256 characters and consist of alphanumeric characters and/or the hyphen or underscore.  The event name value should be unique among all of the event names for the SecsEquip instance.
eventDvvals(eventName:str, dvvalNames) The app provides descriptive information for custom added event types to support replying to S1F24.  For event types which have associated Data Value variables (class DVVAL), the application uses this method to inform the SECS Server of the association using the variable varname values.   This method is used late in the initialization after the event type and the associated DVVAL variables have been added.  The developer can choose to pass varname values as a python list or tuple.
eventEnable(CEID:int, is_enabled:bool) Event reports are enabled for an event type when first created.  This method is not commonly used, it is usually the host's role to decide which events are enabled.
eventExists(CEID:int) -> bool Query the SECS Server to see if an event type is defined.
eventIsEnabled(CEID:int) -> Query the SECS Server to see if reporting of an event type is currently enabled.
eventPost(CEID:int)

eventPostByName(eventName:str)

These methods are used to announce when an event has occurred.  In general, make sure that the data items that the host might want in an event report are set to their proper values before eventPost is called.  This is not a concern if a VarValue callback is used to provide relevant variable values.  The varGroupSetEventPost method is an alternative means of setting a group of variable values and posting an event in one action to assure data integrity.  Events should be posted without the app testing to see if reporting of the event is enabled and without other testing of the communication or control states. The two methods allow for posting the event by its CEID or its name.
eventRenumber (eventName:str, newCEID:int) -> int This method is provided so that the CEID values of the built-in events can be customized.  Use the method after restoring or configuring the connection type, and before enabling communication.  If the newCEID value is in use by a different event, that event is given a "temporary" ID value of the current value plus 1 million under the assumption that it will be renumbered as well.  After initialization, if events are found with ID values greater than 1 million, they indicate that more than one event has been assigned to the same ID value. 

A positive return value is a warning, and the value 0 indicates success.  In more detail, the return values and their meanings are:

0
The event already has the desired ID, or the event was renumbered successfully.
1
The new ID was in in-use so the existing event was renumbered to a "temporary" ID.
2 or more
The return value is the number of events of this name that were found.  The extra table records were deleted and the surviving table record has the desired ID or was renumbered successfully.  This condition is not ordinarily expected.
Exception
If the eventName does not identify an existing event an exception is raised.  Also, if the method does not succeed from an unexpected error such as a timeout, an exception is raised.  The data passed when the exception is thrown is a string describing the problem.
eventReportLinks() -> list This method returns a list of (CEID, RPTID) pair tuples which are usually setup by the host using S2F35 but could be setup using the reportLink method.  This method supports displaying or enabling editing of the event report configuration which is not commonly done by equipment.  A developer can review the current configuration of reporting using the DebugTableWindow and browsing the table data.
eventUnlink(CEID:int);
This method can be used to unlink (disassociate) any reports that are associated with an event type.  The call can be used if your tool supports manual editing of event reports. 
linktest() -> bool 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.  Useful for equipment to force a broken connection to be discovered just before important event reports so that the report messages are spooled or so that the app is in sync with the actual communication state.  Returns True if the link is up, False if the link is down.
linktestAsync()
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.
from dmhclient import lappend
 
lappend(tcl_list:str, *args) -> str
Append one or more elements to the end of a Tcl list string.  Be sure to assign the result, the passed list argument is not modified.  The arguments are converted to strings if necessary as they are appended.  It is a good programming practice to use lappend or ljoin 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. 

This is not a class method; it is defined at the global level in the source file.

from dmhclient import lconvert

lconvert(sequenceType) -> str

Returns a Tcl list string from the elements of a python list or tuple.  Elements are converted to strings as they are appended to the result. 

The dmhclient package offers the same function as a non-member global function.

from dmhclient import lindex

lindex(tcl_list:str, *index_args) -> str

This method is the lindex command of Tcl.  It will parse tcl_list and return the specified element.  Indexes are zero-based.  More that one index can be supplied to parse nested lists.  If a specified index is out of bounds, an empty string is returned.

This is not a class method; it is defined at the global level in the source file.

from dmhclient import ljoin

ljoin(*args) -> str

Returns a Tcl list string made by each argument being converted to a string and appended to the result.

This is not a class method; it is defined at the global level in the source file.

from dmhclient import llength

llength(tcl_list:str, raise_exception:bool = False) -> int

Returns the number of elements in a Tcl list string.  Not all strings are valid lists.  Failure occurs when there are unmatched braces, unmatched quotes, or non-whitespace following braces or quotes.  The caller can use raiseException to choose if he wants invalid lists to raise an exception.

This is not a class method; it is defined at the global level in the source file.

from dmhclient import lsplit

lplit(tcl_list:str, raise_exception:bool = False) -> list

Returns a python list for a Tcl list string.  Not all strings are valid Tcl lists.  Failure occurs when there are unmatched braces, unmatched quotes, or non-whitespace following braces or quotes.  The caller can use raiseException to choose if he wants invalid lists to raise an exception or to merely return an empty list.

This is not a class method; it is defined at the global level in the source file.

messageTypeAdd(stream:int, function:int, callback) Call this method to have SECS messages processed by your custom handler method when the SecsEquip is in online control, and the message is received from the host.  You can provide for new SECS message types, or you can replace the existing SecsEquip handling of particular messages.  Use the sendReply, sendS9, and sendAbort methods to send reply messages. 

See the SECS Message Receiving description in the Events section for information on how to write callback functions.

messageTypeRemove(stream:int, function:int) This method is used to cancel SECS message handlers that you have setup using messageTypeAdd or to cancel the handling of particular messages during the online control state by the built-in SecsEquip logic.  For example, you may wish remove Process Program management message types for a tool that does not use Process Programs. 

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 messages are replied to with an abort reply.  If the unhandled message does not ask for a reply, an S9F5 message is sent to indicate an unknown function.

parameterAdd(varID:int, varname:str, description:str,
value_TSN:str, initialValue, minValue, maxValue, defaultValue, units:str,
affectsProcessing:bool)
This method is used to add Equipment Configuration Variable definitions (ECVs).  With the default range checking active, use varID values that are between 1000 to 2999.  Use a unique value for each parameter.  The varname is specified as a CamelCase name for the parameter (up to 32 characters) such as AlignAngle.  The value_TSN argument is the Tcl SECS notation type code for the ECV value such as BL for boolean, I4 for integer, F4 for floating point, or A:80 for an ASCII string up to 80 characters long.  With type A always indicate the maximum number of characters, n, that you wish to allow the host to set, by using a type code of the form A:n.  The value of n can be as large as 60000.  The boolean affectsProcessing argument specifies whether the parameter affects processing.  If it does, the host is not allowed to change the value unless the control state is online with remote control.

The host queries/sets parameters using message types S2F13 and S2F15.  Call parameterSet when the ECV value is changed by your GUI or controller logic so that the SECS Server can manage the appropriate GEM event. 

If you have custom ID requirements, you can set the IdRangeChecked property false to disable varID range checking, and you can renumber existing Parameters and Variables using the variableRenumber method.

parameterGet(varID:int) -> str

parameterGetByName(varname:str) -> str

These methods get the current value of an ECV.  The return value is an empty string if there is unexpected error.
parameterGetInfo(varID:int) -> VariableInfo

parameterGetInfoByName(varname:str) -> VariableInfo

These methods return the configuration data of an ECV.  The return value is a VariableInfo data structure - see variableGetInfo

parameterSet(varID:int, newvalue)

parameterSetByName(varname:str, newvalue)

These methods are used to update the value of an ECV parameter.  The built-in logic takes care of event reports notifying the host of any change.
parametersRestore() Restores the saved values of the parameters (Equipment Constant Variables).  Hume prefers to call these Equipment Configuration Variables because they are not constant.  The parametersRestore() method gets called automatically when you first enable communication if property ParametersAreSaved is true, and parametersRestore() has not already been called.  The call restores the values of parameters from the last session, and it initializes saving for the current session.  There is logic so that restoring only occurs once.  It is useful to make this call if you want to force the restore action to occur before communication is enabled.  For example, this could support viewing the current values of the parameters before communication is enabled.  Initialize the connection type and define all of the parameters before calling this method.
processProgramDownload(ppid:str) -> RcResult Initiates the download of a process program from the host using S7F5.  The ppid argument value is both the process program identifier and the file name that is used by the equipment for the process program file.  There is no standard SECS command for the equipment to know what process programs are available from the host for downloading.  The return value is a structure containing an integer return code, rc, and a result string, result.  If the return code value is 0 which indicates success, the result string is the full pathname to the process program file.  Negative return code values indicate error.  Possible errors include those described with sendSecsMsg().  In addition the following error codes are also possible:  -10 file system error, -11 improper data received, -12 request denied by the host. In the case of error, the result string is a diagnostic message.
RcResult processProgramLargeRequest(ppid:str) -> RcResult Initiates the download of a process program from 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 both the process program identifier and the file name that is used by the equipment for the process program file.  There is no standard SECS message for the equipment to know what process programs are available for download.  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 host's reply to S7F41.  The transfer is not complete when the method returns.  The large data set transfer logic receives the downloaded file in the subdirectory, dataset_transfer, of the directory set by the RecipeDirectory property.  When the transfer is complete, there is a StateChange event with the name dataset_download and the newvalue being a two element list consisting of the ppid value and the full pathname to the newly received file.  To fully comply with the large process program transfer scenarios specified by GEM E30, your application should react to the StateChange event by verifying the newly received process program and sending the S7F27 Process Program Verification message to the host using sendSecsMsg.  The S7F27 message is sent with replyIsWanted true, but there is no reason to wait for the host's reply.  After verification, your application can move the file into the RecipeDirectory for use, possibly overwriting an earlier version.

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
-13 PP transfers are disabled when spooling is active
-14 A large PP receive is already in progress for ppid
-15 Stream 13 transfers are disabled either from configuration or initialization failure
-16 PPID is not usable as a restricted filename
-17 error when parsing the S7F42 reply

processProgramLargeSend(filename:str) -> RcResult Initiates the upload of a process program to the host using Stream 13 message types which are designed for large data set transfers.  In most cases, the filename argument value is both the process program identifier and the file name that is used by the equipment for the process program file.  However, when using the PPFilesByRequest feature, the argument value should be the process program identifier, ppid, instead of the filename.  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 host's reply to S7F37.  The transfer is not complete when the method returns.  The large data set transfer logic makes a temporary copy of the file for transfer in the subdirectory, dataset_transfer, of the directory set by the RecipeDirectory property.  This allows your application to change or access the process program while the copy is being transferred.  When the transfer is complete, there is a StateChange event with the name dataset_upload and the newvalue being the filename value.  If the transfer does not complete successfully, there is additional status information is the SECS server table ei_dataset_xfer.  The SECS Server also posts UploadSuccess, UploadTimeout, and UploadFailure data collection events that can be monitored as StateChange events with the name event.

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
-13 PP transfers are disabled when spooling is active
-14 A large PP receive is already in progress for ppid
-15 Stream 13 transfers are disabled either from configuration or initialization failure
-16 error copying the PPID for large send
-17 error when parsing the S7F38 reply
 

processProgramUpload(ppid:str) -> RcResult Initiates transferring a process program to the host using S7F3.  The ppid argument value is identically the file name of the process program and the identifier for the process program.  The return value is a date structure containing an integer return code and a result string.  The return code value is 0 for complete success.  Negative return code values indicate an error.  Possible error values include those possible with processProgramDownload().  In addition, the return code value of -13 is used to indicate "upload disabled during spooling".  A positive return code value is the SECS standard ACKC7 code value sent by the host.  Diagnostic text is provided in the result string for all return code values. 
Important:  Do not assume that the host saves process program files with the same file names or in the same format that the equipment does.  The only proper way to use an uploaded process program file is to download it using the same host software that uploaded it. 
processStateNames(stateValue:list, stateName:list) Call this method during initialization to add a Status Variable named ProcessStateNames whose value is a list of Process State values and their names.  The variable is not required by the standards but including it is strongly recommended.  It helps the host provide better displays of processing status.  The stateValue argument is a list of process state integer values.  The stateName argument is a corresponding list of state names. 
pump(is_tkinter_app:bool = False) This method must be called repeatedly to process receiving and have callbacks execute.  Most apps will use some kind of periodic timer or check from the event loop to run the pump.
pumpSchedule(appTk, period_msecs:int = 100, is_tkinter_app:bool = True) Setup and run a periodic Tk timer to call pump().  A tkinter app passes in a reference to the Tk instance to setup a periodic timer to call pump.  Linux apps need to run in an X-windows session with a DISPLAY defined in order to construct a Tk object.
propertySet(name:str, value) There are some less commonly configured properties that can be initialized using this method, such as:
AlarmsAreSaved
Set to 0 to disable the built-in saving and restoring of alarm enablement.
dataid
set to a starting integer such as 0 to cause DATAID values to be sequential integers
recv_max
the maximum number of bytes for a received message (default is 2048000)
spool_no_reply
set to 1 to cause spooling activation when the host does not reply to a primary message
stricttypes
set to 1 to limit the use of S1F3 and S2F13 message types to SV and ECV variables respectively.
trace
additional messages can be added to the tracing and logging
VarValueTimeout
the timeout number of milliseconds for a variable value request (default 20000)
wbit_s5f1
set to 1 to cause S5F1 alarm reports to be sent asking for a reply
wbit_s6f1
set to 1 to cause S6F1 trace reports to be sent asking for a reply

Current settings can be viewed using the Trace Window. In general, refrain from changing element values of the SECS connection array except as advised.

reportDefine(rptID:int, varIDs:list) -> int This method is optionally used to update, create, or delete an event report definition.  If the varIDs list argument is None or empty, the report configuration is deleted.  The return values are:
0 - a new report created,
1 - an existing report updated,
2 - report deleted,
-2 unknown variable ID,
-3 invalid rptID ,
-1 unexpected transaction error.
Any positive number can be used for a report ID, rptID value.

Manual editing of event reports, or the creation of built-in event reports is not required by GEM since dynamic reporting is provided.  We recommend that you do not provide predefined, built-in reports.  Let the host configure the reporting that is desired.  If you do provide built-in reports, you have a complex situation since GEM specifies that the state of event reporting setup by the host is persistent.  This means the saved and restored reports can delete your predefined ones.  If you choose to implement built-in reports, we recommend that you add an equipment parameter (ECV) and make the user choose between having the built-in reports or having the saved reports defined at startup.  Do one of the following to insure built-in reports are available:  (1) Set the property ReportsAreSaved to false to prevent your built-in reports from being replaced by the restore logic, or (2) Call reportsRestore after your events and variables are defined, and then add your built-in reports after the restore logic has run.

reportDelete(rptID:int) Delete an event report definition.  The method reportsClear() can be used to delete all of the event reports.  Only used if your tool features manual report editing which is not common.
reportGetDef(rptID:int) -> list Returns a list of the integer variable IDs in an event report definition.  An empty list is returned if the report does not exist. 
reportGetInfo(rptID:int) -> list Returns a list of VariableInfo objects for the variables in a report definition.  An empty list is returned if the report does not exist. 
reportLink(rptID:int, CEID:int) -> int Link or associate a report definition to an event type, causing the report to be sent as part of the event report message.  Both the report and the event type should exist at the time the method is called.  The return values are: 0 success, -2 invalid rptID, -3 invalid CEID, -1 unexpected internal error.
reportUnlink(rptID:int) Remove the association of a report from all events.
reportsClear() This method erases any existing event report definitions, unlinks the event reports from event types, and disables the event reports that were linked to the deleted reports.  The call also deletes any saved event report data, so it can be used to prevent or nullify the restoring of event reports from the previous saved session.  The method is not usually called since saving and restoring the dynamic event report configuration is standard GEM behavior.
reportsList() -> list Return a list of integer report ID values for the event reports.  A developer can browse the event report configuration using the debugTableWindow.
reportsRestore() Restore the state of event reporting from the last session, and initialize saving for the current session.  ReportsRestore gets called automatically when you first enable communication if property ReportsAreSaved is true, and ReportsRestore has not already been called.  Restoring overwrites the existing event report definitions.  There is logic so that restoring only occurs once.  A connection type should be set and the variables and event types should be defined before calling this method.
SecsEquip(spname:str = "equip0" , dmhGroup:str = "PYSECSEQUIP") The class 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 SecsEquip instance, and not coincide with a keyword in the Tcl programming language.  The default value of spname is equip0 for the first instance.  The name should be a single alphanumeric token. 

The dmhGroup argument becomes the DMH message system group name used by the SecsEquip and SECS Server process.  If you are instantiating more than one SecsEquip instance in your process, construct each instance using the same dmhGroup name argument so that the SECS Server process is shared.  The groupname chosen needs to be unique among other DMH server instances on the computer where the SecsEquip is executing.  The default value does not conflict with the default value for Hume Datahub instances or Host applications..  The name should be a single alphanumeric token. 

The SecsEquip SECS Server child 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.

sendAbort(stream:str, primary_function:int) 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.  For example, when the control state is ON-LINE LOCAL, the abort reply should be sent to a host message that would affect processing.
sendReply(stream:int, function:int, transactionID, TSN_data:str = "") This method is used by your custom SECS message handling logic to send reply messages either with or without data.  The reply function value is the received primary message function plus 1.  The reply data is formatted as Tcl Secs Notation text.
sendS9(errcode:int, header:str) This method is used to send an error response to a received message - it is sent in lieu of a normal reply.  The SecsEquip software takes care of many of the possible error conditions automatically, including, 1 - bad Device ID, 3 - bad stream, 5 - bad function, and 9 - T3 timeout.  You will not receive a message type, unless you register for it.  Therefore, you will mostly send the errcode value 7 to indicate improper data. Other possible values for your app include 11 - too much data, and 13 - conversation timeout.

 

sendSecsMsg(stream:int, function:int, reply_wanted:bool, TSN_data:str = "", waitForReply:bool = False) -> RcResult

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 sendSecsMsg() call returns a data structure that has an integer return code and a result string.  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
-3 
OFF-LINE   - the control state is OFF-LINE and per GEM only S1F1, S1F13, and S9FX are sendable.
-4 
DISCARDED   - spooling is active and this message type is not spooled.  Usually the connection is down.  But this result can also occur for a newly established connection before the host has purged or finished unloading the spool.
-5 
BUSY   - an eq_send call is currently active.  You should not see this error, since by design send commands are serialized using DMH messages to the connection's command mailbox.
SPOOLED    Your message has been spooled for later sending.  Even if you specify waiting for the reply result you receive this instead of the reply data if the message is spooled.  We recommend you not allowing spooling of message types where you care about the reply.
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".

from secsequip import ServerSqlCmd
ServerSQLCmd(sql:str)
Send an SQL command to the SECS Server process without waiting for a reply.  This method is used by the SecsEquip software and made public in case of custom requirements.
from secsequip import ServerSqlReply
ServerSqlReply(sql:str) -> RcResult
Send an SQL command to the SECS Server process and wait for the reply.  This method is used by the SecsEquip software and made public in case of custom requirements.
from secsequip import ServerTclCmd
ServerTclCmd(tclCommand:str)
Send a Tcl command to the SECS Server process without waiting for a reply.  This method is used by the SecsEquip software and made public in case of custom requirements.  After a SecsEquip instance has been constructed and the connection type set, the tclCmd( ) SecsEquip 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.
from secsequip import ServerTclReply

ServerTclReply(tclCommand:str) -> RcResult

Send a Tcl command to the SECS Server process and wait for the evaluation result reply message.  This call is used by the SecsEquip software and made public in case of custom requirements.  After a SecsEquip 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.
spoolPurge() This method discards any spooled messages that are queued for the host.
spoolStop() This method sets the messages types that are enabled for spooling to an empty string, thus, further spooling is stopped.
spoolStreamFns(StreamFns:str) The method is used to set the spooled message types.  The call bypasses the SpoolingAllow property and enables spooling for the S<s> and S<s>F<f> message types that are specified in the input string.
SecsEquip.startupLoad(name:str) -> EquipStartupData

class EquipStartupData
See secsequip.py source.
This method retrieves the persisted startup configuration for the named interface.  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 method uses the SECS server's ei_equipment data table.  The table data is saved as the file ei_equipment.tab in the SECS server's working directory when the startupSave() method is called.

The declaration of the EquipStartupData class in the source code can be viewed for the comments on the field usage, in addition to reviewing the example GUI application source code. 

startupRestore(esd:EquipStartupData) 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.
SecsEquip.startupSave(esd:EquipStartupData) -> RcResult The startupSave method creates or updates a row in the ei_equipment SECS Server table using the passed configuration, and then saves all of the table data to the file system as the file ei_equipment.tab in the SECS server's working directory.  A non-zero return code is returned if the table data is not saved successfully.  There is only partial checking of the validity of the passed data.  The return value data structure is used to pass a possible warning message for the values controlling tracing and logging.  In this case, the return code value is greater than 0.
tclCmd(tcl:str) This method is used to send Tcl code to the SECS server command mailbox for the connection.  It is used by the SecsEquip software and made public to support custom requirements.
tclReply(tcl:str) -> RcResult 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 SecsEquip software and made public to support custom requirements.  The method returns an RcResult data structure whose first element is a return code for the evaluation with 0 meaning success.  The second element is the string result value from the executed Tcl code, or an error message if the return code is not 0.
terminalDisplayAck() Calling this method posts the data collection event named TerminalServicesOperatorAck which is used by the equipment to indicate acknowledgment of a host Terminal Display, message type S10F3 or S10F5.
varGroupSet(varID:list, value:list) This method is a more efficient alternative to calling variableSet() multiple times, the method sends the updated values to the SECS Server in one message.
varGroupSetEventPost(varID:list, value:list, CEID:int) This method is a more efficient alternative to calling variableSet() multiple times and then posting a Data Collection event using eventPost().  The method sends the variable values and posts the event using one message to the SECS Server which provides better data integrity and better performance.  The list of varID values should be the same length as the list of variable values, and the elements of each list should correspond in sequence.

If the CEID value is less than 0, no event is posted, and the method is equivalent to varGroupSet(). 

The method is most efficient for applications which use the SECS Server ei_variable table to manage variable values instead of using VarValueRequest callbacks.   When callbacks are used, the event posting methods should be called directly.  They feature an optimization which queries the SECS Server for needed variable values and sends them in a single second message.

variableAdd(varID:int, varname:str, description:str, varClass:str, value_TSN:str, varmethod:str, initialValue:str, units:str = "") Use this method to add a Status Value variable (varClass == "SV") or a Data Value variable (varClass == "DVVAL").  Both classes of variables are available for the host to configure in event reports.  A DVVAL does not need to have a valid value, for example the alarm ID of the latest alarm when there have been no alarms.  With the default checking of Id values, use varID values between 3000 and 9999.  Leave the varmethod argument as None or an empty string if the variable value will be represented in the ei_variable table, or you will subsequently call variableMethodSet to configure an evaluation callback. 

If you have custom ID requirements, you can set the IdRangeChecked property False to disable varID range checking, and you can renumber existing Parameters and Variables using the variableRenumber method.

variableExists(varID:int) -> bool Test if a variable or parameter is defined.
variableGet(varID:int) -> str
variableGetByName(varname:str) -> str
These methods are used to get the current value of a variable.  They use the same access logic that host requests use so this is a means of testing your custom value logic.  The return value is an empty string if there is an error.
variableGetInfo(varID:int) -> VariableInfo

variableGetInfoByName(varname:str) -> VariableInfo
class VariableInfo contains these variable members:
    int varID
    str varname
    str description
    str varClass
    str value_TSN
    str varmethod
    str units
    str minValue
    str maxValue
    str defaultValue

These methods return the configuration information of a variable or parameter (ECV).
variableMethodSet(varID:int, use_callback:bool) Use this method to configure whether the SECS Server asks the app for the current variable value when needed using a callback or whether the app calls variableSet() to keep the SECS Server in sync with value changes.  See the application example.
variableRenumber(varname:str, newID:int) -> int This method is provided so that the ID values of the built-in variables and parameters (ECVs)  can be customized.  All of these data items are represented in the same table, and should be given unique numeric identifiers.  Use the method after restoring or configuring the connection type, and before enabling communication.   If the newId value is in use by a different variable, that variable is given a "temporary" varID value of the current value plus 1 million under the assumption that it will be renumbered as well.  After initialization, if variables are found with ID values greater than 1 million, they indicate that more than one variable has been assigned to the same ID value. 

A positive return value is a warning, and the value 0 indicates success.  In more detail, the return values and their meanings are:

0
The variable already has the desired ID, or the variable was renumbered successfully.
1
The newVarId was in in-use so the existing variable was renumbered to a "temporary" ID.
2 or more
The return value is the number of variables of this name that were found.  The extra table records were deleted and the surviving table record has the desired ID or was renumbered successfully.  This condition is not ordinarily expected.
Exception
If the varname does not identify an existing variable an exception is rasied.  Also, if the method does not succeed from an unexpected error such as a timeout, an exception is raised.  The data passed when the exception is raised is a string describing the problem.

variableSet(varID:int, newValue:str)

variableSetByName(varname:str, newValue:str)

These methods are used to update the value of a Status Value or Data Value variable whose current value is represented in the ei_variable table.


Built-in Features

The table of contents link in the frameset viewer shows the SECS Equipment Built-in Features document for this section. Having a separate document shared with the multiple Equipment libraries helps us provide you with more accurate, detailed information.

License Terms

Subject to Change Without Notice

This is licensed and supported software.
©Copyright 2022, Hume Integration Software
All Rights Reserved

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


Document Version

Date of the last revision to this document: $Date: 2023/08/28 20:40:21 $