Programmers Access Kit
Programmers Access Kit
Version 7.5
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Programmer’s Access Kit
•
•
•
•
© Copyright 2004 Tecnomatix group of companies. All rights reserved.
NOTICE:
The information contained in this document (and other media provided herewith)
constitutes confidential information of Tecnomatix group of companies (“Tecnomatix”)
and is protected by copyright laws and international copyright treaties, as well as other
intellectual property laws and treaties. Such information is not to be disclosed, used or
copied by, or transferred to, any individual, corporation, company or other entity, in
any form, by any means or for any purpose, without the express written permission of
Tecnomatix.
The information contained in this document and related media is subject to change
without notice and does not represent a commitment and does not constitute any
warranty on the part of Tecnomatix. Except for warranties, if any, set forth in the
separate license or other agreement relating to the applicable software product,
Tecnomatix makes no warranty, express or implied, with respect to such information
or such software product.
•
•
•
•
Programmer’s Access Kit
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Using this Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Getting Help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
P URPOSE
The FactoryLink Programmer’s Access Kit is a collection of software tools for use in the
design and construction of FactoryLink-compatible tasks. This guide provides the technical
information programmers of these systems need to complete their applications.
The major audience of this guide is programmers who design and construct programs to
• Create new tasks that perform functions not performed by standard FactoryLink tasks.
• Develop communications interfaces to computers or devices for which standard interface
tasks are not already developed.
In addition, FactoryLink Customer Support Services personnel use the procedures and
examples to help you develop and troubleshoot your applications.
Located within each part of this guide is a section named “ … at a Glance”. This section
provides a quick key to locations to find information to perform the procedures detailed in that
part with hypertext links to those locations.
Convention Description
press nnnnn Press is used to denote a key on the keyboard. The key
name will appear in a sans serif type.
click nnnnn Click is used to denote a button on the screen. The button
name will appear in a sans serif type.
Shift+F1 The + indicates the keys must be pressed simultaneously.
Shift+F1 indicates you hold down the Shift key while you
press another key or mouse button (indicated here by F1).
Other key combinations are presented in the same manner.
Convention Description
Example Syntax
where
command is typed as it is displayed in the syntax.
input_file indicates a variable the user supplies.
[input_file…] indicates the user can optionally supply multiple input file names, each
name separated by a space.
{a|b} indicates either the a or b must be specified as an argument.
output_file indicates the user must specify an output file.
•
•
•
•
•
•
•
•
•
•
•
•
•
15
•
•
•
•
6. Read about Library Services, including the Kernel Chapter 6, “PAK Library
interface, CT access, object CT access, direct tag Services”
processing, normalized tag reference, path
manipulation, and message translation.
•
•
•
•
Programmer’s Access Kit
Overview 1
Programmer’s Access
Kit Overview
The FactoryLink Programmer's Access Kit (PAK) is a collection of optional FactoryLink
software tools and related documentation for use in the design and construction of
FactoryLink-compatible tasks.
PAK allows you to take full advantage of FactoryLink's open architecture. This guide describes
the C-language calling conventions; however, you can develop programs using any language
that supports these calling conventions. Customer-written programs have full access to
FactoryLink's real-time database and operate in conjunction with other FactoryLink programs.
Unlike any other open architecture system, FactoryLink fully integrates a customer-written
task into the FactoryLink environment. The FactoryLink Configuration Explorer fully supports
new tasks with full-screen editing, context-sensitive help, and documentation utilities.
I NSTALLATION R EQUIREMENTS
PAK is an option used in conjunction with a FactoryLink Development System. Refer to the
FactoryLink Release Notes. PAK requires specific versions of software tools not included with
PAK. See the FactoryLink Installation Guide for a list of FactoryLink software and
requirements and for information on which compiler to use.
Install the Programmer’s Access Kit as an option during the installation procedure for
FactoryLink following the procedure explained in FactoryLink Installation Guide.
C OMPILING P ROGRAMS
PAK provides a command script for all supported compilers named setup<platform>.bat that
sets the environment variables required to successfully build the example programs. This
command script must be executed prior to building any of the shipped examples. The set up
script resides in directory {FLINK}/src/examples/skel.
Each example program is accompanied with a makefile. Execute the compiler make facility at
the command prompt to build the example programs. While PAK does not provide any
pre-built projects for use within the compiler integrated developer’s environment, you should
be able to create one with limited effort.
F OR A LL U SERS
1
Whenever you receive a new version of FactoryLink, you must relink all tasks to the new
Programmer’s Access
libraries. Also, you cannot run old FactoryLink tasks with the new ones. You must run all new
FactoryLink tasks.
Kit Overview
Caution: Failure to heed these concerns will almost certainly result in
an immediate crash of your entire application.
•
•
•
•
Skeleton Task
2
Skeleton Task
O VERVIEW
The Skeleton Task serves as a framework to build a custom task designed to meet your unique
needs. Ensure the Skeleton Task is both functional and integrated into your FactoryLink
system before beginning the PAK task construction.
The source code and support files for the Skeleton Task reside in the directory
{FLINK}\src\skeleton and include the following files.
4 Copy the on-line configuration handling script skel.rtm to the CT directory: {FLINK}\ctgen.
5 Make the Skeleton Task conversion script known to the FactoryLink system. With a text editor,
add the line skel: skeltrig skeltags to {FLINK}\ctgen\ctlist.
6 Copy the translation file skel.txt into the message directory: {FLINK}\msg\{FLLANG}.
7 To verify the Skeleton Task is successfully integrated into the development environment,
perform these steps:
Skeleton Task
2 Create a row in the Triggers Tag table with the Table Name as A and the Trigger Tag as
skeltrig_a. Accept the defaults when creating the trigger tag.
3 Close the table and open System > System Configuration > System Configuration
Explorer in grid view. Again, configure a row for the Skeleton Task. Make the row the same
as the one pre-configured for the RTMON task, except set the tag dimension indices to the next
available slot. A common technique is to copy and paste the RTMON line and then change the
array indices and task specific fields to reflect the new skel task. Also, set the following fields
to the values shown.
4 Exit Configuration Explorer, run FLRUN, and then shut down the application. Verify this
sequence generates the file {FLAPP}\shared\ct\skel.ct.
You have now confirmed the successful integration of the Skeleton Task into the FactoryLink
system.
2 Using the Microsoft development tool, open the Microsoft Visual C++ project: Skeleton.dsp.
If you are using Visual Studio, you will receive a message that prompts you to convert the
Microsoft Visual C++ 6.0 project. If this message appears, perform the conversion.
2 Run the application created earlier a second time to verify the task is functional.
3 When the graphics for the application are displayed, switch to the SHARED Run-time
Manager screen (either 1 or 2) that has the SKEL task listed. The screen indicates the
task is running.
4 To verify the SKEL task is working as expected, use RTMON to write a 1 to the skeltrig_a tag.
A message displays in the Skeleton Task Message field that effectively verifies the Skeleton
Task has read its configuration and is correctly processing it.
•
•
•
•
Run-Time Architecture
3
Run-Time Architecture
FactoryLink is a modular system of individual tasks that perform separate functions. These
tasks communicate and share data with one another through the Real-Time Database managed
by the FactoryLink Run-Time Manager and Kernel. This system provides the following
advantages over systems relying on real-time inter-process communications (IPC) through
passing buffers or sharing files:
• Tasks maintain their independence and inherent compatibility with one another.
• Data formats for interfaces will not change unpredictably as the maintenance programmer
changes.
• Tasks can hand off the inter-process communication to the database function, which acts as
an intermediary, meaning less time is spent waiting for another task to acknowledge
error-free receipt of data.
• Functions, conditions, or events can be related through the use of a common element since
each task has access to the same global elements.
FactoryLink allows you to create custom applications by selecting, configuring, and linking
different programs to exchange information freely in real time.
The Run-Time Manager reads the System Configuration table [sys.ct]to determine the startup
criteria for each task. The Run-Time Manager communicates with each task by sending
commands to and reading status information from the Real-Time Database. Each task must
monitor the command objects so the task shuts down when instructed to by the Run-Time
Manager.
The Run-Time Manager interacts with the other tasks within a specific domain through the
FactoryLink API and the Real-Time Database as shown in the following figure.
Run-Time
SYS.CT
Manager
Read Write
FactoryLink
Real-time
Database
Read Write
FactoryLink
*.CT Application
Tasks
Run-Time Architecture
and serializes access to the memory so tasks can communicate with each other. When you start
the FactoryLink Run-Time system, the Run-Time Manager creates the shared memory using
the Kernel Services. Other tasks also use the Kernel Services to access the shared memory as
they start.
Domain
FactoryLink supports the concept of shared and private data areas by the separation of data
access into domains. The SHARED domain is the shared portion of the Real-Time Database
and the collection of shared processes that have access to that data. The USER domain is an
instance of the user Real-Time Database and the set of all the user processes having access to
that Real-Time Database. Multiple USER domains each have their own set of user processes.
Each can access both the SHARED Real-Time Database and the USER instance of the
Real-Time Database.
When FactoryLink runs, the entire Real-Time Database is created, including the SHARED
portion and all Real-Time Database USER instances. Next, the SHARED Run-Time Manager
initializes the SHARED Run-Time Database and starts the SHARED processes. As USER
instances start, each USER Run-Time Manager initializes its instance of the USER Real-Time
Database and starts an instance of all USER processes.
Within the starter and example application, default domain associations are made in the
System Configuration Table. These defaults determine which domain a task is associated with
at run time. Some tasks are associated with both SHARED and USER domains. Review the
default domain associations during application planning to verify they are compatible with
current needs. These default associations may be changed if an application has special
requirements.
Some FactoryLink tasks monitor and control processes, such as a PLC driver task, that require
the process data values be the same for all users. The subset of the Real-Time Database shared
by all users is known as the SHARED domain.
Application Instances/Identification
Since multiple copies of a FactoryLink task may be running concurrently, a task must identify
itself to the Kernel. The task must specify the application, domain, and user instance as well as
the task name.
Each application instance is specified by its invocation name. The invocation name is a
character string of up to 16 characters. The invocation identifies an instance of the Real-Time
Database and is used to locate the memory segment the kernel is stored in. The Run-Time
Manager refers to the invocation name stored in the environment variable {FLNAME} and
stores it in the tags FLNAME_U or FLNAME_S, depending upon the domain.
The domain within an application is specified by the domain name. The domain name is a
character string of up to 16 characters and is used to determine which portion of the Real-Time
Database the task has access to: either the elements in the SHARED domain or elements in one
of the duplicate USER domains. In addition, the task uses the domain name to determine which
CT files should be processed. The Run-Time Manager refers to the domain in the environment
variable {FLDOMAIN} and stores it in the tag FLDOMAIN_U or FLDOMAIN_S, depending
upon the domain.
The user instance is specified by the user name. The user name is a character string of up to 16
characters and is used to determine which instance of the duplicate USER portions of the
Real-Time Database the task has access to. The Run-Time Manager refers to the environment
variable FLUSER and stores it in the tag FLUSER_U or FLUSER_S, depending upon the
domain. The FLUSER environment variable must be unique for each user of the application.
When a FactoryLink application is started, the Run-Time Manager must be supplied with the
invocation name, domain name, and user name on the command line or through environment
variables. All sub-processes the Run-Time Manager creates inherit these environment
variables.
Domain Tables
3
The domain table in the Configuration Explorer contains the definition of domains in the
Run-Time Architecture
application. Currently, two domains are supported: SHARED and USER. The definition of
these domains includes the number of allowed instances as well as domain-wide persistence
attributes.
The Configuration Explorer has a domain selection feature that must be set before tasks are
configured. The default is SHARED. If the run-time domain associations do not match the
configuration domain associations, the application will not run as intended.
Domain Associations
Domain designations are critically important. Before each task begins to run, the associated
domain is defined as an environment variable. Typically, the task inherits the environment
from the Run-Time Manager when the Run-Time Manager starts the task. This variable must
match one of the previously defined domain values. Two types of domain relationships are
possible:
• A task may be designed to run as SHARED. All tables and database elements are associated
with the SHARED domain. At run time the task runs as a shared entity with one set of
elements for all users.
• A task may be designed to run as USER. You have a private copy (domain instance) of the
task for every user. The tasks may use both the SHARED and USER Run-Time Database
elements. At run time all user domain instances are identical when generated; however,
individual user actions are independent, and the resulting data is stored in a Real-Time
Database unique to each operator.
In the following example, you have created an application that allows multiple operators to run
separate user instances of the same application in which each operator has his own USER
domain tasks and Real-Time Database.
USER
SHARED
USER
Run-Time Architecture
value of the application elements. It exists only in memory and does not persist between
subsequent invocations of the FactoryLink system.
The Real-Time Database is made up of arrays and pointers. Each array consists of up to 65535
elements of a single data type. Whenever you define an element, the system prompts you to
identify the data type of the element by choosing one of FactoryLink predefined data types.
The following table shows the storage capacities, ranges, and accuracies of each data type.
Formula = storage requirement for an element defined for the SHARED domain:
(N - 4) + (4 x I)
where
N Is the storage in Kernel area from the table above.
I Is the number of instances (shared + user).
where
N Is the storage in kernel area from the table above.
I Is the number of instances (shared + user).
Example:
A USER domain floating-point element in a system with a maximum of two USER
instances:
24 bytes (from table) x [1 (shared) + 2(user)] = 72 bytes
The FactoryLink Kernel uses data types and element numbers to read from or write to elements
in the Real-Time Database.
Structure of an Element
FactoryLink pre-allocates a single bit to each potential client task in each of these status words.
Each domain instance has potentially 31 possible processes. The 32nd bit is a digital tag value
or unused.
Change-Status Bits
For each element, one change-status bit exists for each potential client process. The read-call
and write-call functions use the change-status bits within the FactoryLink Kernel to indicate
changes in an element value. The value of the change-status bit can be either ON (equal to 1)
or OFF (equal to 0). 3
Run-Time Architecture
FactoryLink tasks write information to elements through either
• Write call
• Forced-write calls
Tasks use the Kernel Service’s write-call function to update a value of an element. This
function first determines whether the element value changed. If the new value differs from the
old, the write-call function sets each of the element change-status bits to 1 (ON) and stores the
new value in the element; however, if the comparison determines the new value for the element
is identical to the old, nothing changes. This method saves processing time because tasks
watching the element will not waken to process unchanged values.
Alternatively, the writing task can also use the Kernel Service’s forced-write function. This
function does not compare old and new values. Instead, the forced-write call function assumes
the element has changed and sets all of the element change-status bits to ON as it stores the
new value, even if the updated value being assigned to the element is the same as the old.
Forced writes are useful when you need to trigger processes setting the element change bit but
do not wish to change the actual contents of the element or when an element needs to be
processed a second time, even if its value has not changed.
The read-call function always returns the current value of the element to the calling process
regardless of the value of the element change-status bit assigned to that process.
When a task makes a change-read-call, the reading task requests change-status information
about specific elements. If the function finds that the change-status bit of an element has been
When a task makes a change-wait call, the reading task uses the change-wait-call function
within the Kernel to request change-status information about specific elements. Once a task
makes its call, the task then hibernates while waiting for an element to change. When a task is
asleep, it uses no CPU cycles. The task wakes when any one of the specified elements have
changed and/or have had their change-status bits set to 1 (ON) by another task since the last
reading. In other words, this call blocks the calling process until at least one of the specified
elements change-status bits are toggled.
Regardless the method of reading an element, the act of reading an element resets the element
change-status bit associated with the reading task to OFF by writing a 0 to the task
change-status bit in the element. As successive tasks read an element, they toggle the
change-status bits in the element, one by one, to OFF.
The Kernel maintains the change-status bits in a manner transparent to the tasks; however, you
can use these bits in the Math & Logic task.
For example, you can write a Math & Logic procedure that uses the ? operator to determine
whether the value of an element has changed and then take an action.
Wait bits: For each element, one wait bit exists for each possible client process. When the
client is currently waiting to read the specified element, the value of the bit is 1 (ON);
otherwise, the value is 0 (OFF).
Run-Time Architecture
for an exchange of information among the tasks. You use the configuration tables to specify the
elements each task reads or writes. A task is only aware of the elements it is reading and
writing, not of other tasks; therefore, it does not know which task wrote the data it is reading
from the database nor can it know which task is reading the data it is writing to the database.
An application task calls functions to perform the following FactoryLink operations involving
the Real-Time Database:
• Lock the database
• Unlock the database
• Read one or more database elements
• Write one or more database elements
• Determine whether a database element has been modified by another task since it last read
the element
• Sleep until any one member of a list of specific database elements is modified
• Access miscellaneous utilities
Any task can use any element in the Real-Time Database as long as the data type and domain
of that element matches the type required for the indicated operation. It is possible— even
beneficial— for two tasks to use the same element. When this occurs, both tasks share the
information stored in the element.
Although some tasks may only read or write to elements, most tasks have both read and write
access to the elements. Remember all elements are global, so any task can use any element as
long as that element data type matches the type required for the indicated operation. It is
possible for two tasks to use the same element, sharing responsibility for updating the
information stored in the element.
It is important to plan and configure the system so read and write operations to the Real-Time
Database are predictable. For example, if two tasks are configured to write simultaneously to
the same element, it is impossible to know which task is responsible for the data in the
element. Even though it is sometimes desirable to have such a capability, most applications
should be designed so only one writer task and one or more reader tasks function for any
particular element.
Example 1. When you enter a new value from the keyboard, the Graphics Task gets the value
and writes it to the element associated with the input object.
Example 2. The Graphics Task uses a change-read function that executes in a loop to
determine whether element values linked to a screen display have changed. The function
informs the task if no values have changed. The function returns the new value for the changed
element from the Real-Time Database if a value has changed. At the completion of the
execution of the loop, the task relinquishes the CPU to another process or task.
Example 3. The Batch Recipe task is configured to read values from a file and write them to
associated elements in the Real-Time Database or read elements from the database and write
their values to a file on the disk.
Example 4. A programmable controller task reads values from the programmable controller
and writes them to the Real-Time Database. It can also read values from the Read-Time
Database and write them to the programmable controller.
Run-Time Architecture
Overview of FactoryLink Architecture
ASCII Application
/{FLAPP}/, MPS (ASCII)
FLSAVE/FLREST *Attribute
Catalogs
/{FLINK}/BIN/ /{FLINK}/AC/*.AC
FactoryLink
Configuration
Manager
Configuration *Key Word Files
Database Tables /{FLINK}/Key/{FLLANG}/*.KEY
/{FLAPP}/
*ConfigurationTable
FLRUN
/{FLINK}/BIN/ Generator Scripts
CTGEN.EXE /{FLINK}/CTG/*.CTG
TASK.CT
*Source Run-Time
Manager
Starts other
task
Compile & Link
/{FLINK}/BIN/TASK.EXE
FactoryLink
FLIB Task
Real-Time
/{FLINK}/INC/ Database
/{FLINK}/LIB/
Configuration Database Tables that store information about the Real-Time Database
(.CDB) elements. You must design these tables as part of task
development. In this guide, configuration database tables are
referred to as database tables.
Attribute Catalogs (.AC) Programmer-created ASCII text files that describe the
database tables and the editing criteria for operator-entered
data.
Key Word Files (.KEY) ASCII text files that 1) delimit valid entries for a database
table field; and 2) provide binary value for conversion by
CTGEN.
Configuration Table Programmer-created script files that tell the CTGEN utility
Generator Scripts (generate binary CT files) how to extract data from the
database tables and combine it to produce a binary
Configuration Table (CT) file at run time.
Configuration Tables Binary files produced by the CTGEN utility at run time
(Binary) (.CT) containing data extracted from the database tables.
Compile and Link Step to compile source code into object code and link object
modules.
Run-Time Architecture
FLIB FactoryLink library. Collection of utility functions serving
primarily to interface application and system programs to the
FactoryLink Kernel.
Task Task that performs a required operation. Up to 31 tasks,
including the Run-Time Manager, may be active concurrently
per domain instance.
Run-Time Manager Task that monitors and controls other FactoryLink tasks using
the services of the Real-Time Database.
Only portions of the FactoryLink architecture affect you directly. You must design the database
tables for the task. These tables contain all information required to completely describe the
application with the possible exception of operator-entered menu selections and/or commands.
Once the design is final, you must create an Attribute Catalog file for one or more database
tables. The Attribute Catalog file represents an option in the Configuration Explorer. If the
Attribute Catalog file references a KEY file, you must create a KEY file that provides the
Configuration Explorer with information on developer-entered keywords placed in the
database tables. Then, you must open the Configuration Explorer and use it to test whether the
Attribute Catalog file(s) and, if used, the KEY files, accurately reflect the desired database
table design and editing requirements.
At run time the Run-Time Manager starts and the database tables are converted into one or
more sorted binary files known as a CT file(s). When a task begins running, it reads its CT file
to determine the elements to open and the actions to perform on those elements. You must
write a configuration table generator script that describes how to extract data from the database
tables and produce the CT file at run time.
The custom-developed program describes how the custom-developed task functions in relation
to other tasks, including the Run-Time Manager.
TRIGGERS
Many FactoryLink tasks use digital elements to trigger certain actions. Events, such as read or
write operations, can be configured to occur as the result of a combination of bit value and
change-status flag value in a trigger element. A trigger element can be used as a trigger by
more than one task.
When a task reads a trigger element, the reading task sets its change-status flag to 0 and begins
the operation designated by the trigger if the element value is 1 and has changed since the last
time it was read.
Forced-writing a 1 to a digital element, even though it may not change the actual value of the
element (if the element was already equal to 1), causes the events tied to that trigger to be
triggered during the next read operation. If multiple tasks are to use the same element as a
trigger, using the forced-write technique simplifies inter-task handshaking requirements.
C ONFIGURATION E XPLORER
3
The Configuration Explorer is a development system program used to set up or configure a
Run-Time Architecture
FactoryLink application. It is used only for system configuration and application development.
You create an application by specifying the elements created for each task and the actions each
task performs on these elements. In the Configuration Explorer, you enter data in one or more
database tables for each task. The Configuration Explorer normally opens a default table editor
that provides a data entry table for each of the database tables; however, the Configuration
Explorer may open specialized editors to handle non-textual configuration.
Advantages of using the Configuration Explorer include reduction of development time for an
application and having the same developmental look and feel as standard FactoryLink tasks.
Run-Time Architecture
\LIB *.LIB (WIN& ) Library files.
*. a
•
•
•
•
FactoryLink Configuration
Architecture 4
Configuration
Architecture
This chapter highlights the following aspects of constructing tasks and integrating them with
the rest of the FactoryLink system:
• Configuring FactoryLink
• FactoryLink Application Directory ({FLAPP})
This information allows tasks to read data from and write data to the Real-Time Database,
providing developer-configurable communication links between FactoryLink tasks.
Establishing these links is the essence of creating a FactoryLink application.
Enter information in a table by opening one or more screen displays or panels that provide
predefined entry fields for information required for the task to function.
This is how the control and information panels for a particular task are related. In the following
sample Control panel, specify types and priorities of read and/or write operations performed.
Then, enter the DDE item names read or written and the names of RTDB elements to receive
or supply information from/to the DDE source (Microsoft Excel spreadsheet) in the following
sample Information panel, which is associated with the previous Read/Write control panel.
A task may require both Control and Information panels or just an Information panel.
Element Names
Each element has a unique, developer-defined, symbolic element name (tag). You assign these
element names, one for each element used in the application during system configuration and
the system stores them in a separate predefined data file. Element names are linked at run time
with pointers to their associated elements, allowing their use by any task. Because the
Real-Time Database is completely memory-resident and is organized as arrays and pointers
when loaded at run time, FactoryLink does not have to keep track of element names stored as
text strings. This, in part, accounts for FactoryLink’s high processing speed.
Element name assignment: During configuration you create and assign an element name to
an element by defining at a minimum its name, data type, and possibly its domain dimension. 4
If the element you referenced does not exist, the system automatically creates it. Once an
element has been defined in this way, other tasks refer to this element using its element name,
reading or writing data to or from the element at run time.
Configuration
Architecture
Valid tag names conform to the following grammar:
[<node>:]<name>[<dims>][.<ext>]
where
<node> Is limited to 8 characters.
<name> Is limited to 32 characters.
<dims> Is limited to 16 characters.
<ext> Is limited to 16 characters.
The maximum tag name length, including <node>, <name>, <ext>, and the separators : and .
is 32. Legal characters for the <node>, <name>, and <ext> strings are
• {A-Z}
• {a-z}
• {0-9}
• {@$_}
Users cannot directly create a tag name with extensions, such as abc.mymember. These are
considered member tags. The Application Editor creates these automatically through the tag
definition notebook. Currently, only member tags related to scaling and deadbanding are
supported.
Arrayed Elements
An element array is a block of elements of the same type. As such, it frees the developer from
having to define large numbers of scalar elements separately. Certain FactoryLink tasks, such
as Math & Logic and Database Browser, can detect the arrayed property of an element and can
access the entire element array when given a reference to just one of its elements.
Define element arrays in a configuration table by using at least a two-part element name. A
two-part element name consists of an alphanumeric string (the arrayed element name)
followed by one set of square brackets containing an integer (array index) for each dimension
of the array. Dimension refers to the capacity or size of the array. If an array has more than one
dimension, it is called multi-dimensional, and each element will have as many array indices as
the array has dimensions. Think of the Cartesian coordinate system in which both vertical and
horizontal indices are specified to pinpoint a position on the spatial grid. A two-dimensional
array is an array in which each of the elements is also an array and its elements are referenced
by [row,column] pairs.
The array dimensions defined within the square brackets are the sizing factors that determine
the number of elements in an array. For example, if you specify the size of a one-dimensional
element array is 5, the Real-Time Database creates five separate elements referenced
individually or as a group. Their array element names are the same, but they have different
array indices.
The following is a sample arrayed element name:
set_temp[2][1]
Each set of square brackets represents a dimension or spatial characteristic of the element
array, such as length, width, or height. When you define an element array in a configuration
panel, a dialog displays showing default sizes for each dimension you can modify before
pressing Enter.
The size of a default dimension is always one larger than the integer specified in the element
name brackets because C arrays are indexed from zero to the specified dimension. For
example, if the element name is tagname[0][0], the default dimension sizes displayed in the
dialog are 1,1. If the element name is tagname[4][6][3], the default dimension sizes are 5,7,4. 4
This also means that arrays are indexed beginning at zero. For example, tagname[0] is the first
element of the element array tagname.
Configuration
Architecture
The number of array dimensions and the number of elements allowed in an array are
constrained in two ways:
• The element name field limits the size of the array dimensions. Sixteen characters are
allowed in the dimension portion of an element name. For example, the array element name
tempset[3][1][10][1][1] contains 7 characters in the element name portion (first field) and 16
characters (the maximum) in the dimension portion. The 16-character limit in the dimension
field allows you to specify up to five dimensions, assuming most of the dimensions are
single-digit.
• You can create element arrays containing up to 64K (65535) numbers of elements.
Use the following formula to determine the number of elements created in an array with a
given set of dimensions:
axbxc
where
a Is the size of the first dimension.
b Is the size of the second dimension.
c Is the size of the third dimension.
If an array contains more than three dimensions, use the same method to multiply by the sizes
of the additional dimensions.
Enter tagarray[index number] in the panel for each element referenced to reference individual
elements in the array.
the default sizes of the two dimensions displayed in the dialog are
2,2
Enter msg_tag[index1][index2] in the panel for each element referenced to reference individual
elements in this array.
Suppose you need to define message elements whose values indicate the colors the cars on one
conveyor belt are painted. If 300 cars are painted on the conveyor belt and element arrays are
not used, you must define 300 elements individually. With element arrays, however, you define
only one two-part element name and specify that the name contains 300 elements by entering
299 (creating elements 0 to 299) inside the brackets, as in
color[299]
Set the integer ([299]) sizing the single dimension of the element to one less than the desired
number since elements are numbered beginning at index zero (0). Here, the desired number of 4
elements (299 + 1 or 300) are created under one element name, as in
color[0]
color[1]
Configuration
color[2]
Architecture
.
.
color[299]
Suppose you want to define elements to indicate the colors cars on three conveyor belts are
painted. You can define a two-dimensional element array by entering one element name, such
as
paint[299][2]
The integer ([299]) for the first dimension indicates one fewer than the number of cars on each
conveyor. The integer ([2]) for the second dimension indicates one fewer than the number of
conveyors. As a result, the correct number of elements [(299 + 1) X (2 + 1) or 900] are created
under one element name, as in
paint[0][0] paint[0][1] paint[0][2]
paint[1][0] paint[1][1] paint[1][2]
paint[2][0] paint[2][1] paint[2][2]
paint[3][0] paint[3][1] paint[3][2]
. . .
. . .
. . .
paint[299][0] paint[299][1] paint[299][2]
Suppose you must define elements whose values indicate the colors that cars on three conveyor
belts and trucks on three conveyor belts are painted. You can define a three-dimensional
element array using one element name as in
car_truck[299][2][1]
The three-dimensional array may be thought of as a cube of indexed elements with each
element having an (x,y,z) coordinate reference, such as depth, vertical position, and horizontal
position.
Element Descriptions
A description includes optional information about the element defined or referenced with an
element name in a data entry panel. When you enter a reference to a new element and click
Enter, the system prompts you to define the element. Tag definitions can include a description
of up to 80 characters. Two methods for changing descriptions are available:
• Open the Element Tag List in the Configuration Explorer and modify the description field.
• Place the cursor in the element name field on the panel where the field has been defined and
press Ctrl-T. The Element Tag Definition dialog displays, allowing you to change
information about this element including its description.
Each task can have tables with elements referenced by name. These tables are converted to
binary configuration table files (CT files) and, at run time, the typical FactoryLink application
program reads its configuration table files and makes calls to read and/or write elements
identified by the element numbers and data types listed in the CT files.
Predefined Elements
The FactoryLink starter application FLNEW comes with a set of predefined elements for
internal use. These also serve as a convenience so you can use these when configuring tasks.
Predefined elements in the USER domain contain a unique extension to the identifier of _U.
The model for data entered and managed by the Configuration Explorer is a set of relational
database tables including:
• DOMAIN
• TYPE
• OBJECT
• XREF
• Task-Specific 4
The DOMAIN, TYPE, OBJECT, and XREF database tables are reserved system tables and are
not developer-definable. The task-specific database tables, however, are developer-defined and
Configuration
are only present when that task is used in the application.
Architecture
The database tables form a set of relational databases as follows.
DATABASE TABLES
DOMAIN
TYPE
OBJECT
XREF
Type Description
DIGITAL Boolean value (on or off).
ANALOG 16-bit signed integer.
LONGANA 32-bit signed integer.
FLOAT double precision floating point.
MESSAGE Variable length binary or ASCII data.
MAILBOX Variable length data, organized as a queue.
OBJECT
The Configuration Explorer maintains the Real-Time Database tag definitions for each
application in the OBJECT database table. Knowledge of the format is generally not required
to add a new task. The OBJECT table contains a list of real-time elements defined by the
developer, but it does not contain task-specific information. Task-specific information is kept
in other tables related solely to that task.
XREF
The Configuration Explorer maintains a cross-reference table. The XREF database table
contains a record for each occurrence of an element in any task-specific table. This information
allows the Configuration Explorer to locate all occurrences of a particular element in the
task-specific tables quickly.
Task-Specific
A task consists of one or more developer-definable task-specific database tables. There is no
limit on the number of tables per task. If a task has more than two tables, the tables may be
related either serially or in a one-to-many fashion.
For example, suppose a PLC task consists of a Write table and a Read table. The Write and
Read tables each consist of a Control panel and an Information panel. The Control panel
contains header records specifying the trigger information for a group of data records. The
control and information records are stored in different tables because they have different
structures.
Configuration
Architecture
Subdirectory File(s) Description
\ASC *.ASC ASCII database tables that store information about the
Real-Time Database elements and task specific
information. They are used to import/export configuration
data from one application directory to another (typically,
from one platform to another platform).
\ASC *.ASC ASCII database tables that store information about the
elements. Used to import/export configuration data from
one application directory to another (typically, from one
platform to another).
\DRW *.G* Graphics and PowerVB files created with the Application
*.PL* Editor and used by Run-time graphics files.
•
•
•
•
Constructing a FactoryLink
Task 5
FactoryLink Task
Constructing a
This chapter details the procedure for constructing tasks and integrating them with the rest of
the system. Topics include:
• Overview
• Guidelines for Task Design
• Creating the Configuration Environment
• Run-Time Requirements
• Task Program Skeleton
FactoryLink Task
• Writing the Run-Time Task
Constructing a
Setting up the Configuration Environment
Setting up the Configuration Environment includes four steps:
Designing the database table(s) for the task involves laying out the panel(s) opened in
Configuration Explorer, where you enter configuration information for the task. Designing
these tables involves mapping the work performed into a set of relational databases.
With the possible exception of operator selections and/or commands entered at run time, the
database table contains the information the task program needs to do its job. For example, it
serves as the storage area for the user-entered inputs when you select this task.
A table consists of one or more fixed-length database records. Each table is associated with an
index to control the logical order of the records. The task may require more than one table to
describe the work to be performed. These database tables can be related or unrelated to each
other.
Create at least one Attribute Catalog (with extension .AC) for each set of database table(s) to
describe the structure of this table. In addition, it lists the panel(s) displayed when the user
chooses this task.
An AC file is an ASCII text file that may be created and edited with an ordinary text editor,
such as Notepad. It tells the Configuration Explorer the format or structures of the records,
how to interpret operator input, and how to fill in the fields of the records.
Place the AC file(s) in the {FLINK}/AC directory that contains AC files for all FactoryLink
tasks. Create the translation file for the AC headings.
If necessary, create any KEY files referenced by the Attribute Catalog(s) or the Panel file(s).
Create the KEY file(s) with a text editor, such as Notepad. Limit the alpha-numeric strings to
32 characters. This file tells the Configuration Explorer how to validate operator-entered key
words to be placed in the database table. After the KEY file(s) have been created, place them in
the /{FLINK}/KEY\EN, /{FLINK}/KEY\FR, or /{FLINK}/KEY\DE directory. Example KEY files
are shown below.
flink\key\en\example.key
NULL -1 NULL
NO 0 NO
YES 1 YES
N 0 N
Y 1 Y
SLW 1 SLW
FST 2 FST
flink\key\fr\example.key
NULL -1 NULL
NON 0 NO
OUI 1 YES
N 0 N
O 1 Y
LENT 1 SLW
RAPIDE 2 FST
flink\key\de\example.key
NULL -1 NULL
NEIN 0 NO
5
JA 1 YES
FactoryLink Task
N 0 N
Constructing a
J 1 Y
LANGSAM 1 SLW
SCHNELL 2 FST
Inform FactoryLink about the new task by adding the name of the AC file to the TITLES file.
Using the Configuration Explorer, test the configuration environment, including the Attribute
Catalog.
Once errors or problems are analyzed and corrected, choose the task, entering a variety of
simulated data in the panel(s) to be stored in the newly-created database table(s).
You must remember certain high-level concepts during the design of a custom task. Proper
design enables the task to coexist efficiently with other FactoryLink programs. In addition,
designing to the PAK guidelines provides an upgrade path to other operating systems.
FactoryLink Task
Constructing a
• Design the Database Table(s)
• Create the Attribute Catalog(s)
• Create the KEY Files
• Add AC File Names to TITLES file
• Test the Configuration Environment
The following figure illustrates the portion of the Task Construction Flowchart involved in
setting up the configuration environment.
When you construct a task for a custom application, you must design one or more database
tables.
Designing the task-specific database table(s) is the first step in task construction. The design
process should include the following considerations:
• What type of data is required for this task?
• What data must be stored in this task-specific database table.
• What other tasks require information supplied by this task?
• Are both Control and Information panels required or just an Information panel?
• What is the panel design, including the following items:
• Name of the panel
• Panel layout, such as column headings and order of information
• Data type of any element to be entered on the panel
• Editing validation required for a field, such as data type limitation or value- range check
Task-specific tables contain information for the Configuration Explorer to add to the other
run-time tables on behalf of the task. For example, the Alarm Supervisor configuration allows
the specification of an element to be monitored for an alarm condition. In addition to the
element, you can also specify alarm messages and limits. The Configuration Explorer adds the
element to the OBJECT table if it has not already been created. In addition, the Configuration
Explorer adds the element name and task-specific information to the Alarm Supervisor table.
Tasks run in one or more domains. The configuration for these tasks are normally unique per
domain; therefore, a domain is associated with each record entered into the configuration
database. Configuration in one domain is not accessible to the task executing in another
domain.
FactoryLink Task
Constructing a
RECIPE.AC file.
Each task has multiple tables that can be configured for it. Each panel corresponds to a
database table whose characteristics are specified in the AC file that corresponds to the option
chosen.
An AC file indicates
• Name of the task
• Parent/Child relationship between the tables
• Relationships between the database tables
• Validation information
Each field you can edit in a database table record must be specified in the AC file. AC files are
found in {FLINK}\ac\<filename>.ac.
Because they are ASCII text files, the AC files for standard tasks are easily copied and altered
to create an AC for a new task. The best way to create an AC file is
• Copy an existing AC file from the {FLINK}/ac directory
• Make necessary changes to this file
• Save it with a new name
Note: Text files (*.txt) are now stored in one of the following directory
paths:
\flink\msg\en
\flink\msg\de
\flink\msg\fr
The text files were previously found in the \flink\msg or
\flink\msg\english directory paths.
In an AC file, each statement begins with a keyword followed by one or more parameters
separated by commas. Comments may be included in the AC file by beginning the line with an
asterisk. The comment continues to the end of the line. Blank lines and leading spaces are
ignored. A statement may be split over multiple lines. The keyword DELETE may not be used
in an AC file. It is reserved for an internal function and is not available to the programmer.
XLATES “xlatefilename”
XLATES
XLATES “filename”
Filename is the name of the file in \flink\msg\en, \flink\msg\fr, or \flink\msg\de that contains
the tranlsations of the tokens used in the AC.
TASK
5
TASK name, {title}
The TASK statement defines the task name and title for the task list. Only one TASK statement
FactoryLink Task
Constructing a
is included in an AC file.
CT
CT table_name, file_name, “{titletokenstring}”
The CT statement defines a database table. A task may have as many CT statements as needed,
one per table.
EDIT
[EDIT type [, editor]]
The EDIT statement defines a module or program used to edit this database table. If the EDIT
statement is not included, the Configuration Explorer uses the default edit procedure.
VALIDATE
[VALIDATE type]
5
The VALIDATE statement defines the level of editing you are allowed when completing a
FactoryLink Task
configuration table and the program or module that performs the editing.
Constructing a
Parameter Description Valid Entries
PANEL
PANEL panel_file, x, y, width, height
The PANEL statement defines the display/edit window(s) for the database table. If the PANEL
statement is not included, you cannot edit records in the table with the Configuration Explorer
default edit functions.
FIELD
FIELD name, type, width, field_prec, key_file, default, low, high, flags
name Field name as stored in the Valid field name with 10 characters
database table definition. maximum.
key_file KEY or TAG types only: Name of the key file; do not use the
Name of a keyword file used to extension; no entry.
validate the value in the field.
default Default value for the field. String. If the type is KEY, then the
entry must be included in the key_file.
If the type is TAG, then the entry must
be a valid tag type.
FactoryLink Task
Lowest value allowed in this
Constructing a
field.
Tag constants provide a means wherein a user can enter a tag name or a constant value within a
single field. This increased flexibility in field types often simplifies the configuration of a task
by reducing the number of fields to be configured.
Configuration Explorer automatically precedes all field descriptions in the displayed panel
with an asterisk to eliminate confusion as to whether a tag name, value, or both may be entered
into a field.
Inputs into TAGCHAR and TAGKEY type fields, which allow tag names or character
constants as input, need a way for Configuration Explorer to distinguish a tag name from a
character constant. To do this, Configuration Explorer requires any constant value entered into
a TAGCHAR and TAGKEY type field to be preceded by a single quotation mark (').
The affect of tag constant type on valid entries for the following field parameters follow.
key_file Since a tag constant field allows entry of tag names or constant values,
there may be more than one validation file for TAGKEY type fields. One
key file specifies the allowable tag types. The other key file specifies the
valid key constant entries. As such, concatenate both key file names into
this parameter with a | dividing the names.
Example: “<tag_types_key>|<constants_key>”
default The default parameter has a | dividing the default tag type from the default
value for a constant. The default tag type precedes the default constant
value.
Example: “<tag_type_default>|<constant_default>”
low/high These parameters are still applied to constant value validation. The only
tag constant twist applies to the TAGCHAR type fields where the low and
high parameters specify the minimum and maximum number of characters
allowed in the character string.
Examples
FIELD "YEAR", "TAGNUM", 48, 0, "TYPEAL", "ANALOG|1992", 1980, 2200, "bv"
HEADING "{Yearhd}", 44
FIELD "MONTH", "TAGKEY", 48, 0, "TYPEAFML|MONTH", "MESSAGE|JAN", 0, 0, "bu"
HEADING "{Monthhd}", 44
FIELD "DOW", "TAGCHAR", 48, 0, "TYPEM", "MESSAGE|MON", 0, 3, bu"
HEADING "{DOWhd}", 44
HEADING
5
[HEADING “{tokenstring}”, width]
FactoryLink Task
The HEADING option defines the text used as a field heading and the character width for the
Constructing a
column. If you do not specify a heading, the field name is used as the field heading and the
width is calculated based on the number of characters in the field. The Configuration Explorer
allows an unlimited number of lines of text for the HEADING parameter. Delimit lines with
the vertical bar on the first line and Heading on the second line.
RELATE
A RELATE entry indicates this field is used as a relational field. The current value of the field
is used to select records in another database table. The index file is currently unused.
field_name Name of field to set using data from this Name parameter entry of a
field. FIELD statement in related
CT in this AC file.
index_file Name of index to use for ordering; not Index_file parameter entry of
currently implemented. an INDEX statement in
related CT in this AC file.
Note: In .AC files, do not use RELATE statements with a field of type
TAG.
field_name TAG field associated with the String containing the name of a
type. field of type TAG in this CT.
DESC
[DESC “fieldname”]
The DESC statement indicates the description of an OBJECT field should be displayed.
field_name TAG field associated with this String containing the name of a field
description. of type TAG in this CT.
DOMAIN
DOMAIN “DOMAIN”, 8
Enter the DOMAIN statement exactly as shown above for each configuration panel in each AC
file. Do not change this statement.
After you configure a panel, the task-specific CDB file DOMAIN statement contains
SHARED or USER, depending on the domain selected in the Domain Selection box. The
OBJECT.CDB associates each element with the domain defined in the Tag Definition pop-up
panel.
This statement must be included for each configuration table defined in an AC file for
FactoryLink to operate correctly.
SELECT
5
SELECT field_name , width [<HEADING {tokenstring}> , width]
FactoryLink Task
The SELECT statement defines a selection field. Each CT may have one or more select fields
Constructing a
that determine whether or not a record in the CT is displayed and edited by matching the
current value of the selection with the value contained in the database. Normally, select fields
are not listed in the FIELD statements and you cannot change them. The first select field,
however, is displayed at the bottom of the table and you may change it. The HEADING option
allows a string to be defined to label the select input box. Any other select fields should be set
by a RELATE statement in another CT.
SEQ
The SEQ statement defines a field that contains a sequence number for the records. Sequence
numbers can be included in the primary key for the database so that records are sorted in the
same order they were entered. The Configuration Explorer automatically generates the
sequence number.
field_name Name of the field containing a sequence Valid database field name.
number for the records.
The INDEX statement defines an index for the database. The first INDEX statement defines
the primary index and controls the order of records on the screen. If needed, define additional
indices for use by external programs, such as CTGEN. The Configuration Explorer updates all
indices whenever a database record is updated.
key_expression List of fields used to form the key Entry format is:
for the database. A field contained “FIELD+FIELD2+...FIELDN”
in the key should not be listed in
the FIELD statements.
END
END
The END statement terminates a CT definition; therefore, one END statement corresponds to
each CT statement in the AC file.
Naming Considerations
5
PAK currently uses a dBASE-compatible database library that dictates the following
parameters.
FactoryLink Task
Constructing a
Entries Maximum Length/Width
All table and index names. 8 characters.
Field names. 10 characters.
Field width. 255 characters.
Sample AC File
The following code sample shows the Attribute Catalog for the FactoryLink Logger task:
* Attribute Catalog for Logger Task
xlates “loggerac.txt”
TASK "LOGGER", "{Logger_Task}" * Task name and Title
The next three tables show the tokens for internationalized English, French, and German
LOGGER.AC files generated from the previous code. 5
Name Description
FactoryLink Task
Constructing a
Logger_Task Logger Task.
Path Path.
Name Description
Name Description
Logger_Task Logger-Task.
Logger_Info Logger-Information.
Logger_Cntl Logger-Kontrolle.
Table_Name Tabellenname.
Trigger_Tag Trigger-Tag.
Path Pfad.
The next table contains the tokens for internationalized English, French, and German
LOGGER messages. These tokens are not related to the AC file, but they are part of the Logger
Task.
EN START Starting.
FR START Demarrage.
DE START Startet.
EN RUN Running.
FR RUN Execution.
DE RUN Lauft.
EN STOP Normal shutdown.
FactoryLink Task
EN NOCT Can’t open CT.
Constructing a
FR NOCT Impossible d’ouvrir la TC.
DE NOCT CT Kann nicht geoffnet werden.
The next three tables show the internationalized English, French, and German token files
generated from this message .AC file.
Name Description
START Starting.
RUN Running.
Name Description 5
START Demarrage.
FactoryLink Task
RUN Execution.
Constructing a
STOP Arret normal.
NOMEMORY Memoire RAM saturee.
Name Description
START Startet.
RUN Lauft.
FactoryLink Task
If you have not yet integrated the skeleton task into your FLINK system, execute the steps in
Constructing a
“Skeleton Task” on page 23 prior to proceeding with the following procedure.
In your application, open Other Tasks > Skeleton FL Task > Trigger Tags. As described
in the CT statements in the SKEL.AC file, the Trigger Tags displays.
The second CT definition describes the Trigger Tags panel; therefore, it is the parent table to
the Tag List panel, which is the child table.
As described in the FIELD statements for the Trigger Tags panel, the panel contains two fields,
Trigger Tag and Table Name. Since the type parameter in the FIELD statement is TAG and
the key_file parameter is TYPED (digital) in the Trigger Tag field, you enter the name of a
digital Real-Time Database element when configuring the task. Since the type parameter in the
FIELD statement is CHARACTER and the width parameter is 16 in the Table Name field,
enter a string of 1-16 characters when configuring the task.
After you complete the Trigger Tags panel, choose the desired Table Name, and open the Tag
List panel, the chosen Table Name displays in the field above Cancel on the Tag List panel.
As described in the FIELD statement for this panel, you complete only one field, Tag Name,
by entering the name of an element (TAG type in FIELD statement) of any data type.
FactoryLink Task
Constructing a
The help format is very simple. It contains several repeating blocks of the following:
<Description text>
Whenever field help is requested, Configuration Explorer locates the entry associated with the
selected field and displays the description text in a message box. The title of the message box
is <Help title>. To locate the help text, the values for <CT name> and <Field name> must
match the names entered in the corresponding AC exactly.
Use the string TABLE_HELP for <Field name> to create panel help for a CT.
Execute command “mkhelp -v” from the system prompt to integrate the help file into the
FactoryLink system. This rebuilds the index of help entries that Configuration Explorer
references later.
Note: The HLP and VHS files have been moved to a new directory
structure, \flink\help\{EN, FR, DE}\ *.{hlp, vhs}, where the EN, FR and
DE subdirectories contain the English, French, and German translations,
respectively. There are no other changes to the HLP or VHS files.
The Configuration Explorer can load any executable program as an editor; therefore, to run an
editor from the Configuration Explorer, create an AC file for the external editor program.
Remember to add the name of the AC file to the TITLES file. Refer to “Testing the
Configuration Environment” on page 93 for more information.
Parameter Description
The following sample AC file loads the system E.EXE to edit FactoryLink Math & Logic files.
TASK “IML”, “Edit Math Procedures with System Editor”
CT “iml”, “%s/procs/*.prg”, “”
EDIT EXECUTE “e.exe”, “”, “%s”
VALIDATE DEFAULT
END
Since the file specification contains a wildcard character, the screen displays a list box of all
PRG files in the {FLAPP}/procs directory. You select a file name from this list to be passed to
the editor. If the file spec contains wildcard characters and is not a full path name, the current
application directory is added to the front of the file name to make a full path name.
The string specified as the format string is passed to the C-language function SPRINTF. Only
one % can be specified. Also, if a percent sign must be passed as an argument, denote this by
using two percent signs.
If the file spec option does not contain any wildcard characters, then the display does not
contain the file list box and the file spec option is used exactly as it is displayed in the AC file.
If you select MYPROC.PRG from the file list box, the following command is executed:
e.exe {FLAPP}/SHARED/PROCS/MYPROC.PRG 5
FactoryLink Task
Constructing a
KEY files are used to validate table entries. The CTGEN utility that generates the binary CT
files also uses key files to translate ASCII values into binary values. If a KEY file does not
exist that contains the desired values, create a new KEY file with an ordinary text editor, such
as Notepad on Windows.
Each active line of a KEY file specifies a text-to-binary value conversion. Comment lines,
which are not used by the system and are for information and documentation purposes only,
begin with an asterisk.
By convention, the text and its associated value are displayed on the same line separated from
each other by a vertical bar. The Configuration Explorer ignores any leading and trailing
blanks surrounding the text or the value. The binary values in the KEY file must be entered in
decimal notation.
The Key files are found in {FLINK}\key\en, {FLINK}\key\fr, or {FLINK}\key\de.
The third column of the *.KEY files contains English versions of the string. This English string
is what is stored in the MPS files. In FactoryLink the English string is mapped for display to
the proper language, based on the current language setting in flink\install\fllang.lst. This allows
applications to be saved on a system using one language and restored on a system using
another language.
A sample KEY file is MONTH.KEY, used for translating abbreviations of the names of the
months to numeric values:
* MONTH, KEY
*NAME | NUMBER
NULL | -1 | NULL
JAN | 1 | JAN
FEB | 2 | FEB
MAR | 3 | MAR
APR | 4 | APR
MAY | 5 | MAY
JUN | 6 | JUN
JUL | 7 | JUL
AUG | 8 | AUG
SEP | 9 | SEP
OCT | 10 | OCT
NOV | 11 | NOV
DEC | 12 | DEC
You must configure FactoryLink to load and start up the task to fully integrate the new task
with FactoryLink. Complete the following to inform FactoryLink about the task:
• Add the name of the AC file to the TITLES file to make the task accessible in Configuration
Explorer.
• Execute acctmgr -c -d at the system prompt to update the AC map with the latest edition of
the TITLES file.
FactoryLink Task
the name of the AC file must be added to the TITLES file. Perform the following steps to open
Constructing a
the task configuration table(s):
2 Add filename.AC to the TITLES file. The entry location of the new AC file in the TITLES file
reflects the location of that task selection.
4 Execute acctmgr -c -d to update the map with the latest TITLES file.
Test the Attribute Catalog using the Configuration Explorer and a dBASE-compatible database
manager.
Choose the new task in the Configuration Explorer. If an error exists in the AC file or if it
cannot locate a KEY file referenced by the AC file, it displays an error panel stating the nature
of the problem.
Once any errors are analyzed and corrected, invoke the Configuration Explorer repeatedly,
each time entering a variety of simulated data in the panels, and, therefore, in the
developer-created database tables. Using a compatible database manager or the CDBLIST
utility included with the PAK, examine the resulting database table(s) to ensure the
Configuration Explorer is generating the correct and expected data and placing it in the proper
location within the table.
If the Configuration Explorer finds a syntax error in the AC file or if it cannot locate a
KEY file referenced by the AC file, it displays an error message stating the nature of the
problem. Return to the AC file and correct this error. Reopen the Configuration Explorer.
If no problems exist or once any problems have been resolved, the name specified in the
title parameter of the TASK statement in the AC file is displayed as a selection in the
Configuration Explorer.
where
-d Shows the database schema (field names, and optionally, the index
expressions).
<file.cdb> Is the database file to show contents.
<file.mdx> Is the index for the given database.
Adding a page to the Single Point Tag Definition dialog allows for tags to be configured
within APPEDIT and creates entries in Configuration Explorer panels/databases for each
configured tab page. These entries are fully compatible with those in Configuration Explorer.
FactoryLink Task
Constructing a
TASK “GTITLE” substatement
Format GTITLE "R/W Information CT name", "Tab Title String"
"R/W Information Defines the CT used to fill in the page.
CT name"
"Tab Title String" Defines the title to display on the notebook page tab.
DEFINES statement
Format DEFINES "ACname.h"
"ACname.h" Include file that defines necessary ID numbers.
ID statement
Format ID CTID, Flags
CTID Unique ID number for this CT. It should be unique at least within the CT.
User configured IDs start above 7000. Current FactoryLink supported ACs
use the 6000 range.
Note: If you might use this extension with other third party extensions,
a range of unique ID numbers should be obtained from Tecnomatix.
Flags 0x10 = Multiple records can be entered for this page (Alarm Information
only)
0x20 = Read/Write Control Table
0x80 = FIELD/SELECT format (statements contain IDs and graphics type)
Note: All Single Point Extension ACs must set this bit.
DIALOG statement
Format: DIALOG CTID, "ac/ACname.acr"
CTID Use the same unique ID number as in the ID statement for this CT. It should
be unique at least within the CT. User configured IDs start above 7000.
Current FactoryLink supported ACs use the 6000 range.
FIELD statement
Format FIELD Field_ID, GraphType, "Field Name", FieldType, ...
Example:
FIELD XXXXTAG, TEDIT, "TAG", CT_PTAG, ...
Field_ID Unique number for each field within the AC file that links the Single Point
Dialog to column data. This value also serves as the unique object name in
the translate file for title substitution on the panel.
GraphType TEDIT, LISTBOX, TOGGLE. This is used to define the field graphical
representation.
FieldType CT_PTAG, CT_TAG, CT_NUMB, CT_KEY, CT_CHAR,
CT_TAGNUM,CT_TAGCHAR, CT_TAGKEY
CTRLFLD statement
Format CTRLFLD Field_ID, "SELECT Name", “Field Name", FieldSize
Example:
CTRLFLD XXXX__WRITETRIG, "TABLE_NAME", "WRITETRIG", 48
Field_ID Unique number within the AC file that refers to a field within the control
table displayed on the page in a read-only field.
"SELECT Name" Control table entry Field_ID is obtained from.
"Field Name" Field name as it is in the database.
Field Size Field size as it is in the database.
A simple example follows that defines a tag-based table with four fields of information and
also defines a control table with five fields. All five fields from the control table are displayed
read-only on the new notebook page. Information from the control panel need not be displayed
on the notebook page. This example is designed as a template to allow you to change the
XXXX to any string of your choice and also to change the words Template and temp to
something more meaningful.
To use the template, read the next section and make the necessary changes to template.acr.
Then,
• Add template.ac to the TITLES file
• Use Configuration Explorer to define a control table
• Start APPEDIT and add tags using the Single Point Dialog
template.H
#define ID_RWC_XXXX 6013
5
#define ID_RWI_XXXX 6014
#define ID_STC_XXXX 6015
FactoryLink Task
Constructing a
#define XXXXTAG 6500
#define XXXXSTATION 6501
#define XXXXADDRESS 6502
#define XXXXDATATYPE 6503
#define XXXXTABLE_NAME 6504
#define XXXXUNSOLRD 6505
#define XXXXEXCEPWR 6506
#define XXXXREADTRIG 6507
#define XXXXWRITETRIG 6508
#define XXXXCOMMENT 6509
#
# template.AC
#
XLATES “templ_ac.txt”
DEFINES “ac/template.h”
DOMAIN “DOMAIN, 8
END
HEADING “{STATION4}”, 54
VALIDLIST “temp_sta”, “STATION, “COMMENT”
FIELD XXXXADDRESS, TEDIT, “ADDRESS”, CT_CHAR, 22, 0, ““, ““, 0, 0, “u”
HEADING “{ADDRESS5}”, 160
FIELD XXXXDATATYPE, LISTBOX, “DATATYPE”, CT_KEY, 7, 0, “type”, “ANALOG”, 0, 0, “u”
HEADING “{DATATYPE6}”, 60
CTRLFLD XXXXWRITETRIG, “TABLE_NAME, “WRITETRIG”, 48
CTRLFLD XXXXREADTRIG, “TABLE_NAME, “READTRIG”, 48
CTRLFLD XXXXEXCEPWR, “TABLE_NAME, “EXCEPWR”, 3
CTRLFLD XXXXUNSOLRD, “TABLE_NAME, “UNSOLRD”, 5
DOMAIN “DOMAIN”, 8
Using PAGEDIT
5
Configuration tables consisting primarily of tag based information are information tables and
can be added to the Single Point Dialog provided they have a defined parent configuration
table, also called control table. When this is the case, you can use the PAGEDIT utility to
FactoryLink Task
Constructing a
define new custom notebook pages that represent the information tables and display as tabs on
the Single Point Dialog.
The PAGEDIT utility is a graphical interface builder that specializes in building pages for the
Single Point Dialog. The basic page is constructed using drag and drop operations placing
fields and labels where appropriate. Once an item has been placed, double-clicking it displays
a Property Window dialog that allows you to edit the various attributes of the variable. This is
where the object is linked to the appropriate field within the AC file.
PAGEDIT is started by entering pagedit at the command prompt. Once PAGEDIT is started,
you can click the folder icon to bring up a file chooser to locate and open an ACR file. A
template ACR file, named template.acr is included to work with the template.ac file. Figure
2-1 shows PAGEDIT's main window that lists any opened pages in the ACR file, in this case
template.acr.
The Type and Tag are displayed together on a line. The Tag is also displayed in an editable
field across the bottom. Select the page line, and in the edit field, change the Tag value to
match the CTID specified in the ID statement in the AC file. To test the template, replace the
XXXX with the same string used in the AC file. This links the page to the information table.
To continue, double-clicking the page entry will allow you to edit the page.
The Field_ID and GraphType entries added to the FIELD statement in the AC file serve as
each field connection to the notebook page. An object created in PAGEDIT is given Field_ID
as its tagname and GraphType is set in the AC file based on the type of graphical object used to
display the field.
The following screen shows the PAGEDIT utility as it displays the page from template.acr
that corresponds to the template AC file. 5
FactoryLink Task
Constructing a
The Item Palette shown depicts the various objects you can place in any arrangement on the
page. You add objects by pressing the left mouse button on an object in the palette and
dragging it onto the page. The object can then be moved around on the page as needed.
This palette button is used to place label items on the page. Label items are static and
do not relate to a field in the AC file. The value of the label is set by editing the Title
field in the object Property Window.
This palette button is used to place editable text fields on the page. This field type can
be used for any type of alpha-numeric input. Validation of the field will be performed
by a call to the CM validation. When using this object, set GraphType to TEDIT.
This palette button is used to place checkbox items on the page. The checkbox's label
works like a label item. When using this object, set GraphType to TOGGLE.
This palette button is used to place drop-down listboxes on the page. Drop-down lists
are good for providing lists of key values. When using this object, set GraphType to
LISTBOX.
This palette button is used to place boxes on the page. Boxes are used to group
related fields together.
This palette button is used to place listbox items on the page. Use this object when
you want the list to remain visible. When using this object, set GraphType to
LISTBOX. (This is not implemented yet.)
This palette button is used to place combo-boxes on the page. The combo-box allows
for text entry in the field, or selection from a drop-down list. When using this object,
set GraphType to LISTBOX. (This is not implemented yet.)
Double-clicking an object on the page displays the Property Window dialog. Figure 2-3 shows
the Property Window dialog for the text field that displays the value of the Address field. The 5
text field is linked to the AC field by setting the object Tag to the Field_ID used for this item in
the AC file. The GraphType is set in the AC file based on the type of object used to represent
the field. In this case, because an editable text field is used, GraphType is set to TEDIT.
FactoryLink Task
Constructing a
Each field on the page should have a tag value that references an item in a configuration table.
The Enabled checkbox determines whether or not you can the field. For read-only fields from
the control table, the checkbox should be unselected. The Click Focusable checkbox controls
whether the field can gain focus by clicking with the mouse or by pressing the Tab key to move
to the field. The buttons display choosers to set the Foreground or Background colors and
change the font used in the field.
Once all fields have been added and their tags have been set, save the ACR file and quit
PAGEDIT.
Note: You can reorder the items in your list, by selecting an entry to be
moved with the mouse, then holding down both the left and right mouse
buttons and dragging the item to the desired location in the list.
Context-sensitive help can be added to your new notebook pages. Your help will appear
exactly as the standard FactoryLink notebook pages help does, providing seamless integration.
The help can be associated with the entire page or with specific dialog items on the page. To
accomplish this you need to create an ASCII file containing the information required by
APPEDIT to implement the help. After the file is created you must run the mkhelp utility to
build the new help source into the APPEDIT help system and move the new files into the
appropriate directory. The help system supports English, French and German language
versions of the help.
The ASCII text file you create to define your help must conform to the syntax described in
“Source Syntax for Tag Dictionary Notebook Page Help” on page 106. The file must have the
extension .ahs and the English language version must be placed in the {FLINK}\help\en\
directory. The French and German language versions must be placed in the {FLINK}\help\fr\
and {FLINK}\help\de\ directories, respectively.
It is recommended that you create your .ahs file by copying the template file provided and
modifying it to describe your page. For example, to copy the three template files to
mypage.ahs you would enter the following commands at the command prompt:
The contents of the template help source file provided with FactoryLink are shown below.
Keywords are those that begin with the @ symbol. Definition constants are those words that
are fully capitalized. Many of these definitions are derived from entries from within the related
AC file.
For example, the identifier for the template dialog is specified in the template AC file as
ID_RWI_XXXX. This identifier is referenced many places within the page help source file to
associate the help with the appropriate page. This applies to the definition constants (i.e.
XXXXDATATYPE) associated with field definitions.
FactoryLink Task
Constructing a
@popup(TABLE_NAME Table Name)
@link(Context_XXXXADDRESS Address)
@link(Context_XXXXDATATYPE Data Type)
@popup(CANCEL_BUTTON Cancel)
@popup(CLEAR_BUTTON Clear)
@popup(WRITETRIG Write Trigger)
@popup(READTRIG Read Trigger)
@popup(EXCEPT_WRITE Exception Write)
@popup(UNSOL_READ Unsolicited Read)
@end(relmargin)
@end(literal)
@begin(literal)
Address description goes here.
@end(literal)
@begin(literal)
@end(literal
@comment(<comment string>)
These entries add comments to the help source, allowing for easier maintenance of the source.
These do not affect the contents or presentation of the page help.
Every help topic is called a section, and the section keyword associates a name and a
description string to each topic.
For APPEDIT’s help to associate a topic with a notebook page, the help section's name is built
from the AC's dialog identifier. For example, the section describing the template's page has the
name ID_SPTDLG_ID_RWI_XXXX_GFI_HELP, where ID_RWI_XXXX is the identifier of
the template AC's dialog.
For Appedit's help to associate a topic with an item on a notebook page, the help section's
name is built from a combination the AC's dialog identifier and the AC's field identifier for the
related item. For example, the section describing the template's page ADDRESS text input
field has the name ID_SPTDLG_ID_RWI_XXXXXXXXADDRESS where ID_RWI_XXXX
is the identifier of the template AC's dialog and XXXXADDRESS is the identifier of the
template AC's ADDRESS field.
@parent(ID_SPTDLG_GFI_HELP)
@parent(ID_SPTDLG_[<AC DIALOG define>]_GFI_HELP)
The parent keyword establishes the help section hierarchy. All page overview help sections
have the same help section parent, denoted by the section name ID_SPTDLG_GFI_HELP.
The parent of a field help section is the help overview section for the page, and the name of the
page's overview help section name should be used.
The context keyword creates subtopic within the current section for the given name.
For the help section describing an item on a page, the context name must have the name of
"Context_" concatenated with the AC identifier for the field item.
The link keyword establishes a jump from the current context to the given context.
FactoryLink Task
Constructing a
definition names useful for displaying common descriptions, such as for the CANCEL button.
@italic(<description string>)
@begin(literal)
@end(literal)
@relmargin(<left_margin> <right_margin>)
@end(relmargin)
These keywords affect the presentation of the help text in the manner that the keyword
suggests.
Once your .ahs file has been created you must build it into the APPEDIT help system. When
you distribute your application to users, this process occurs automatically during the
installation procedure. During development you need to use the mkhelp utility to build your
help into the APPEDIT help system. Enter the following at the command prompt to run
mkhelp:
mkhelp -c
If an error associated with your help file occurs during the build process the error messages are
written to the file vdebug.log and the appropriate {FLINK}\help\<en\fr\de> directory.
Running the mkhelp program builds the appedit.vhs file for each language and places it in the
appropriate {FLINK}/dll/<en\fr\de> directory. A copy of the file corresponding to the current
language is placed in the {FLINK}\bin directory.
The figure below illustrates the portion of the Task Construction Flowchart involved in
converting database tables to CTs.
Create CTG
Conversion Script
Run CTGEN
Examine Binary
CT File
Problems
Yes Edit Script
with CT Files?
No
FactoryLink Task
Constructing a
The conversion process translates database tables into run-time, binary configuration tables.
The binary tables are arrays of records with a format that matches the internal C-structure
within the target task. This enables FactoryLink run-time tasks to load the tables with little or
no additional processing. The task simply copies the data into its internal structure.
All run-time CTs use a common archive format. The term archive refers to the binary CT file
containing data for more than one database table. For example, the TIMER.CT file contains
information for the event timer and interval timer database tables.
1. Each CT file begins with an archive header indicating the number of CTs in the archive.
2. The header is followed by an index entry for each CT. Each CT consists of an optional
header section followed by zero or more records. Each record within a CT has the same
format:
[CT index 0]
[CT index 1]
[CT index n]
[CT 0 header]
[CT 0 records]
[CT 1 header]
[CT 1 records]
[CT n header]
[CT n records]
Library services are provided that enable a task to read the CT files. The developer determines
the contents of the CT header and CT records that vary according to the database table.
A conversion script, which is processed by the CTGEN utility, controls conversion of database
table information into CT files. Generally, design the conversion script so the output from
CTGEN matches the run-time task data structures. This allows the run-time task to read the
binary data from the CT archive directly into memory. The /{FLINK}/CTGEN directory
contains sample CT conversion scripts.
TABLE
TABLE type, name, hdrlen, reclen
The TABLE statement defines one CT type in the archive. The values of the parameters are
placed in the appropriate fields in the CT index record. A single TABLE definition may result
in multiple CT index entries. The HEADER database determines the number of times the table
is repeated.
Multiple TABLE definitions may exist in the script. Each one is processed in order.
HEADER
HEADER database, namefield
5
The HEADER statement defines the format of the header section of the CT. No more than one
FactoryLink Task
header record is written for a CT; however, the header record may be non-existent.
Constructing a
Parameter Description Valid Entries
database Name of the database table to be Valid database table name (string of
used. characters enclosed in quotes).
RECORD
RECORD database, namefield, indexfile
The RECORD statement defines the format of the repeated record entries in a CT. Multiple
RECORD statements are allowed. Each is processed in order.
indexfile Name of the index file used to read Index containing namefield as the
the records. primary key.
DOMAIN
DOMAIN “DOMAIN”, S, 8
Enter the DOMAIN statement exactly as shown above for each configuration panel in each
CTG file if the source database table has a DOMAIN field. Do not change the statement.
where
DOMAIN References the domain field in the database in the CDB file, which is
created by the DOMAIN statement of the corresponding AC file. For
additional information about AC files, refer to “Create the Attribute
Catalog(s)” on page 67.
The DOMAIN statement in the CTG file places the CT file in the domain-specific path
specified in this parameter, which is {FLAPP}/{FLDOMAIN}/*.CT.
Failing to put this statement in means the configuration is domain independent resulting in the
CT being placed at {FLAPP}/ct. This usage is the exception rather than the rule.
FIELD
FIELD name, format, storage [option] [DEFAULT dftval]
5
The FIELD statement defines the translation of one field in the database table to bytes in the
FactoryLink Task
CT entry. Include as many FIELD statements as necessary.
Constructing a
Parameter Description Valid Entries
Generally, each tag constant field in the AC file results in two references to that field within the
CTG script. One field reference outputs the field as a tag and the other reference outputs the
field as a constant value. When outputting the constant value, append to the CONST or
KEYCONST keyword so the field value returns as 0 or a NULL string if a tag name has been
entered in the field. The CONST option applies to character or numeric constants and the
KEYCONST option applies to key constants. When outputting a constant value as a TAG, the
returned tag equals the invalid tag identifier {-1, -1}.
SKIP
SKIP count, value
5
A SKIP statement causes one or more bytes to be written to the output. The SKIP statement
FactoryLink Task
allows padding of fields to match the task data structures as well as insertion of specific binary
Constructing a
data into the CT file. Include as many SKIP statements as needed. FIELD and SKIP statements
may be mixed in any order.
SORT
The SORT statement defines the order records are read in from the configuration databases and
written to the binary CTs or the repeated header or record entries in a CT. The SORT
immediately follows the HEADER or RECORD it applies to and may contain one or more
field names to be used to sort the entries. Only one SORT statement is allowed per HEADER
or RECORD entry.
By default, the order of CT information conform to ordering viewed from the configuration
database.
The following file is a sample conversion script included in the PAK software as SKEL.CTG.
It is found in the {FLINK}\src\examples\skeleton directory.
TABLE 0, “”, 4, 4
HEADER “SKELTRIG.CDB”, “TABLE_NAME”
FIELD “TRIGGER”, T, 4, TAG
DOMAIN “DOMAIN”, S, 8
Conversion scripts must reside in directory {FLINK}\ctgen. For the system to be aware of and
process a conversion script, an entry for it must be appended to the CTLIST file that resides in
{FLINK}/ctgen. With a text editor, append a line in the following format:
The <task> entry is the name of the conversion script without the .ctg extension. The names
that follow are the configuration database file names without the .cdb extension referenced
within the conversion script. This equates to a dependency list where, if the binary CT for the
task is older than any of the listed CDBs, regenerate the binary CT.
For example, the entry for the skeleton task is:
CTGEN uses the CTLIST file to build CTs and rebuild all CTs whose database tables have
changed. CTGEN can be run stand-alone or with a combination of parameters.
To run CTGEN, enter the following command at the DOS prompt:
ctgen <Enter>
To run CTGEN with parameters, enter the following command at the DOS prompt:
ctgen [-i<name.ctg>][-a <flapp>] [-o<ouput path>] -c -r -v(#) <Enter>
where
-i Indicates only those CTs referenced within the specified CTG file are to be
rebuilt. Next to -i, enter the file name of the CTG file to be used.
({FLINK}/CTGEN is the default directory.)
-a CTs in alternate FLAPP directories.
FactoryLink Task
Constructing a
-r Indicates all files are to be rebuilt. (Usually preceded by -c).
-v (#) Indicates verbose mode and level. Each verbose level displays cumulative
messages. For example, v2 displays general activity messages and historian
and client task messages. Choose v1 for general viewing. Use v2-v4 for
debugging..
where
<file.ct> CT file to dump.
In addition, for proper operation in a foreign language environment, the task should use
fl_xlate to translate any output messages into the language being used and fl_xlate_init to load
the translations when the task is started.
The following figure illustrates the portion of the Task Construction Flowchart involved in
completing run-time requirements. 5
Create Source
Modules
FactoryLink Task
Constructing a
Compile Source
Modules
No
Link Object
Modules
No
Execute Program
Problems
Yes Debug Program
Found?
No
Create Installation
Medium
If the call fails (taskid = ERROR), the task writes an appropriate error message to STDOUT
and calls EXIT.
If the call succeeds (taskid! = ERROR), the task obtains the task environment elements by
calling to fl_get_env( ). The environment elements, which are used to communicate with the
Run-Time Manager, include the following information:
• Status element for reporting task status as an ANALOG value
• Message element for reporting task status as a MESSAGE
• Application path specification
• Program path specification
• Command line arguments
Then, the task writes FLS_ACTIVE to its status element and Running to its message element.
This causes the Active symbol to be displayed in the STATUS column and Running to be
displayed in the MESSAGE column of the Run-Time Manager display.
E RROR H ANDLING
5
If the task encounters any errors, failures, or other problems during execution, it reports
appropriate error messages to its environment STATUS and MESSAGE elements.
FactoryLink Task
• In case of a fatal error, the task exits following the shutdown procedure described in the
Constructing a
Orderly Shutdown requirement.
• In case of a non-fatal error, the task sets its environment STATUS element to FLS_ERROR.
This indicates to the Run-Time Manager the task encountered problems but is continuing
execution, and the Run-Time Manager displays ERROR in the STATUS column of its
display. The task writes a description of the problem to its environment MESSAGE element
N EW C ONFIGURATION N OTIFICATION
Custom tasks developed by users and 3rd party vendors can be enabled for online
configuration simply by creating an RTM file for each task that gets installed into the
{FLINK}\CTGEN directory. The format for the RTM files is described below:
A new file type, the RTM file, lists the bump dependencies for individual tasks. If any file in
the list is newer than when the task last started, RUNMGR needs to bump the associated task.
BUMP <bumpname>
METHOD <CYCLE | SIGNAL>
[FILE_DEPENDENCY <filespec> [, <filespec>]]
[BUMP_DEPENDENCY <bumpname> [, <bumpname>]]
ENDBUMP
GROUP <bumpname>
BUMP_DEPENDENCY <bumpname> [, <bumpname>]]
ENDGROUP
* <comment>
The BUMP keyword establishes a record that holds the criteria for when a task should be
bumped. Token <bumpname> should match the task name used to obtain a task ID from the
kernel (fl_proc_init()). The ENDBUMP keyword closes the record definition.
The FILE_DEPENDENCY keyword precedes the comma-delineated list of files on which the
task is dependent. The <filespec> entry is a file specification relative to the current FLAPP,
although full paths can be specified. Wildcards are allowed, as are environment variables
denoted by braces. One or more file dependency lists can be included within a single bump
record definition.
The GROUP keyword establishes a collection of dependencies that are not tied to any
particular task. Hence, token <bumpname> should not match any task name. However, these
groups can be referenced in other record or group bump dependency lists, thereby reducing the
amount of information duplicated across the individual task bump record definitions. An
example of where this is useful is the historian and client tasks. All the client tasks are
dependent on the historians and must be bumped if an historian is bumped. Using the GROUP
method the individual historian task names do not need to be referenced in the RTM file for
each client. In addition, if a new historian is defined, only one file needs to be updated instead
of several. The ENDGROUP keyword closes the group definition.
Finally, more than one bump records can exist in an RTM file. Also, comment lines are
denoted an asterisk (*) at the beginning of the line.
Examples:
SKEL.RTM:
* RTM file for the Skeleton task
BUMP skel
METHOD CYCLE
FILE_DEPENDENCY ct\skel.ct*
ENDBUMP
PERSIST.RTM:
BUMP persist
METHOD SIGNAL
FILE_DEPENDENCY ct\persist*, ct\object.ct*
ENDBUMP
HISTRIAN.RTM:
GROUP historians 5
BUMP_DEPENDENCY or7_hist, db4_hist, syb_hist, odbchists
ENDGROUP
FactoryLink Task
Constructing a
DPLOGGER.RTM:
BUMP dplogger
METHOD CYCLE
FILE_DEPENDENCY ct\dplogger.ct*
BUMP_DEPENDENCY historians
ENDBUMP
If a custom task is to be signaled instead of stopped and restarted, the developer must modify
the task code to be able to receive signals and recognize the newly added online configuration
signal. See the fl_hold_sig() and fl_recv_sig() API functions for information to implement
signal handling. FLC_SIG_NEWCONFIG supports signaling tasks during an online update.
Upon receiving the FLC_SIG_NEWCONFIG signal, a task can adjust its configuration in
accordance to the latest CT files. Exactly what this entails and how it is actually done is totally
up to the developer and specific to each task design and requirements.
TERMINATION N OTIFICATION
A task must shut down when the Run-Time Manager notifies it to do so. Tasks must check the
current status of the task termination flag often. They do this by calling fl_test_term_flag ( ).
• If the value of the flag is 1 (ON), the task goes through the shutdown procedure in and
writes normal shutdown to its environment MESSAGE element.
• If the value of the flag is 0 (OFF), the task continues execution.
You can terminate the task from the Run-Time Manager. The task terminates along with its
associated FactoryLink session.
Message Translation
Rather than using hard-coded messages, tasks should translate error and informational
messages so multiple languages can be supported. Instead of saying “showerr (“error:out of
memory”), the task should say “showerr (fl_xlate (“NORAM”)). Then, the following records
should correspond to the following files:
•
•
•
•
PAK Library Services
6
This guide assumes you develop client processes in the C Programming Language or in a
language that provides a calling sequence compatible with the C language. This chapter
includes information about the service functions and how to use them.
Function names are case-sensitive. All API function names are entirely lower-case. For
example, a client process calls fl_proc_init( ) with the following command:
taskid = fl_proc_init(“RUNMGR”, “Run-Time Manager”) ;
Function Description
These functions help the Kernel and the Run-Time Manager control client processes. Since a
prospective client must make itself known to the Kernel before doing anything, it must
successfully call fl_proc_init( ) that assigns a FactoryLink ID before calling any other Kernel
service. An exception to this rule is any functions that do not have the FactoryLink ID as one
of the arguments. A client process may not call any other Kernel service after calling
fl_proc_exit ( ), which releases to the system or renounces the caller's FactoryLink ID.
FactoryLink tasks process real-time data until it detects its termination flag has been set. This
is accomplished by frequently calling function fl_test_term_flag( ).
The following example illustrates the use of the process-management functions. It does not
illustrate the interaction of a task with the Run-Time Manager.
#include “FLIB.H”
char name[] = “MYNAME”; /*my name(name of this task)*/
int taskid; task number to be assigned*/
The Kernel provides read-only access to the FactoryLink environment attributes. The
environment access services consist of the following functions.
Function Description
fl_get_stat_tag Returns value of the Real-Time Database analog status element for the
specified process.
fl_get_msg_tag Returns value of the Real-Time Database message element for the
specified process.
fl_get_pgm_dir Returns program directory for the specified process.
Function Description
Often times, a task needs to transact several operations with the Kernel without being
interrupted by another task.
For example, a task may want to both write a value to a tag and clear its change bit for that tag
without the possibility of another task writing a value to that tag between the two operations,
which would result in the task missing the change since it subsequently clears the change flag.
By placing an fl_lock( ) and fl_unlock( ) combination around small portions of the code, the
task assures that intermediate values will be unavailable until the transaction is over. However, 6
care must be taken with these functions for no other tasks can access the Kernel while a lock is
held. Lengthy locks seriously degrade performance and an unreleased lock prevents the entire
Signals
Signals are notifications of events, particularly change of status, sent by one process to another,
referred to as the target process. Signals are a form of inter-process communication (IPC). In
some cases, the Kernel itself may send a signal to a target process, but this is still a form of IPC
since the Kernel always executes in the context of the calling process and acts on its behalf.
The target process, rather than the caller, is notified of the event or what status has changed.
Mailbox services also provide an IPC mechanism to FactoryLink processes. Compared with
signals, mailboxes allow data passing and are more flexible; however, they are slower. Also,
messages sent to a given mailbox are placed in a queue, so they are read in the same order as
they are sent. Signals are prioritized but not queued.
Signals provide a primitive, but very fast, form of IPC; therefore, they are ideally suited for
process synchronization. Each signal is assigned a numerical value in the range 0-31 so only
32 different events can be described by signals. The following events are predefined by the
Kernel and have special meaning.
Function Description
The Kernel provides service functions to do miscellaneous odd jobs that fall into none of the
other categories. These include database lock/unlock functions (semaphores), sleep/wake
functions, initialization functions, and system data item retrieval functions.
The miscellaneous services consist of the following functions.
Function Description
fl_get_tick Gets the current clock tick and/or current date and time
maintained and reported by the operating system.
Any task may read a given Real-Time Database element; however, only one task, the “defining
task,” should write it. This restriction is not enforced, but it is a good design technique to use to
avoid possible ambiguity in the Real-Time Database.
The database access functions are functions callable by C-language application and system
programs. The Library functions make calls to the Kernel. The Kernel maintains the
Real-Time Database shared among all client processes and permits client processes to access it
only through these functions.
Real-Time Database
The corresponding typedefs for each data type are found in FLIB.H.
Database Elements
Change-status bits. For each database element, each possible client process has one
change-status bit. If the value of a bit is 0 (OFF), the value has not changed since client (or
task) number N last read the element where N = 0 through 30. The value of the bit is set to 1
(ON) when a new value is written to the element.
Wait bits. Each possible client process has one wait bit. When the client is currently waiting to
read or to write the specified element, the value of the bit is 1 (ON); otherwise, the value is 0
(OFF). A client can set the value of a wait bit to 1 (ON) by performing one of the following
actions:
• Call fl_change_wait( ). This sets the value to 1 (ON) only if none of the specified elements
has changed (it sleeps until someone writes a new value into one or more of the elements).
• Call fl_set_wait( ).
Tag Number. In the Kernel, a tag number completely specifies a database element because it
includes the data type as well as the array index. All database access service operates on mixed
types; that is, on elements of various data types defined and allocated at run time.
Locking/Unlocking Database
The Kernel automatically locks the database during execution of any of these database access
functions and unlocks it upon completion. This ensures service calls are atomic operations in
the sense that, once begun, they cannot be interrupted by service calls from other clients. The
only exception is when the calling process may block another process waiting to write
synchronous elements.
All database types besides message and mailbox are read and written the same way, accessing
the correct member of the union.
The following examples illustrate the use of the database access functions in the FactoryLink
Library. These examples are not complete C programs. None of the examples illustrates the
interaction of the task with the Run-Time Manager.
Example A
Example A demonstrates how to use fl_read( ) to read messages from the database.
.
.
int task_id
TAG t;
VAL v;
char buffer[100];
v.msg.m_ptr = buffer;
v.msg.m_len = 0;
v.msg.m_max = sizeof(buffer);
fl_read(task_id, &t, 1, &v);
.
.
Example B
Example B demonstrates how to use fl_write( ) to write messages into the database.
.
.
int task_id;
TAG t;
VAL v;
char buffer[100];
Example C demonstrates how to use fl_read( ) to read analog values from the database.
.
.
int task_id;
TAG t;
VAL v;
Example D
Example D demonstrates how to use fl_write( ) to write analog values to the database.
.
.
int task_id;
TAG t;
VAL v;
v.ana = 100;
fl_write(task_id, &t, 1, &v);
.
.
Mailbox
A mailbox is a Real-Time Database element that holds a queue of mailbox messages consisting
of structures (typedef MBXMSG) and some associated message data. Since mailboxes are
Real-Time Database elements, a process can read and write values to them just as with other
types of database elements; that is, the following functions work when passed to a mailbox
element:
• fl_read( )
• fl_write( )
• fl_forced_write( )
• fl_change_read( )
• fl_change_wait( )
When messages are present in a mailbox, the change bit for the associated Real-Time Database
element is set to 1. When the mailbox is empty, the change bit for the associated Real-Time 6
Database element is clear (value of 0).
fl_read_app_mbx( ) allows messages to be read in a different order than they were sent.
The message queue associated with a mailbox contains a head and a tail. The head of the queue
is the oldest message in the mailbox; the tail is the newest. Mailbox message reads occur at the
head or relative to the head of the queue; writes always occur at the tail.
Function Description
Some tasks communicate with each other via FactoryLink mailbox messages. It is possible to
configure an application so that these tasks are on different nodes, and the mailbox messages
and replies are sent across the network by FL/LAN. This is transparent to the tasks, but the
following conventions must be observed; otherwise, FL/LAN will not handle replies correctly.
Also, if a reply is expected, the mm_sendid of the mailbox message must contain the sending
task’s FactoryLink task id; otherwise, FL/LAN will not be able to write the reply to the correct
instance of a user domain mailbox tag (since FL/LAN runs in the shared domain).
Function Description
fl_errno Returns the last error number generated by the calling process.
The following calling and return conventions apply to application programs that call any of the
FactoryLink Library functions:
• Most functions in the library return an item of C data type int.
• A return value of -1 invariably indicates the function failed. The reason for such a failure
depends on the function and the circumstances it is called under.
The calling task must call fl_errno( ) with its task id to access the specific failure code error.
In the source code, the error numbers may be referred to by the integer value or the symbolic
representation of the number. We recommend using the symbolic representation. For example,
the symbolic representation of 0 is GOOD. A line of code might read as follows:
if (fl_proc_init(“SKEL”,”Skeleton Task”) != GOOD)
This code checks whether the return value from a request to connect to the Kernel indicates an
error occurred. When the symbolic representation of GOOD is used, this code does not require
any changes if, for some reason, the integer value of GOOD is later changed to a value other
than 0. If the integer value is used in the code and it changes, the code must be changed and
recompiled.
The symbolic representations of these error numbers are found in the header file FLIB.H.
FLE_BAD_OPTION 15 Reserved.
FLE_BAD_CHECKSUM 16 Reserved.
FLE_NO_OPTIONS 17 Reserved.
FLE_NO_KEY 18 Reserved.
FLE_BAD_KEY 19 Reserved.
FLE_NO_PORT 20 Reserved.
FLE_PORT_BUSY 21 Reserved.
FLE_ALREADY_ACTIVE 22 Initializing task with same name as
one currently running.
FLE_NOT_LOCKED 23 Attempted to unlock Kernel without
holding a lock.
FLE_LOCK_FAILED 24 Unable to attain lock to the Kernel.
FLE_LOCK_EXPIRED 25 Attempted to release a lock that has
expired on the Kernel.
FLE_WAIT_FAILED 26 Invalid task ID passed into fl_wait( ).
FLE_TERM_FLAG_SET 27 Termination flag for given task ID set
to ON.
FLE_QSIZE_TOOBIG 28 Internal error - failed to allocate
mailbox queue.
FLE_QSIZE_CHANGED 29 Internal error - inconsistent queue
size.
FLE_NO_TAG_LIST 30 Reserved.
FLE_TAG_LIST_CHANGED 31 Reserved.
FLE_WAKEUP_FAILED 32 Failure occurred awakening task
sleeping on the Kernel.
FLE_NO_SIGNALS 33 No signals pending for caller.
Error
FactoryLink Error Codes
Number
Description 6
Function Description
The object CT API written using the PAK ct_...( ) primitives hides the details of how the object
database contents are coerced into a CT.
This structure reflects the current attributes that define a FactoryLink object. Applications
should treat this structure as opaque and not access its members directly. A function-based 6
interface, included with the Object CT API, should be used to query FLOBJREC’s values.
Using the API shields the PAK task from future changes that alter the object structure and its
The Object CT API is a data abstracted set of functions. Its usage generally follows some
variant of the following sequence:
• Open the application object table
• Search for definitions for one or more objects
• Close the object table
/*
* Function print_objs4dom writes to standard output all objects
* configured for a particular domain.
*/
int print_objs4dom(char *flapp, char *tgt_dom)
{
FLOBJREC rec;
u32 nrecs;
u32 k;
CT objct;
nrecs = ct_nrecs_obj(objct);
for (k = 0; k < nrecs; k++)
{
ct_read_objs(objct, &rec, k, 1);
if (strcmp(tgt_dom, flobjrec_get_domain(rec)) == 0)
An object is a user-defined name associated with a set of attributes, such as type, dimension,
and domain. This set of attributes equates to the object definition.
An application consists of many objects. Open the Configuration Explorer and right click on
“MyStarterApp” and select View > View Object Table to view the objects defined within an
application. The resulting list shows all objects with their definitions.
Function Description
The FactoryLink Kernel library services provide the low-level functionality required to
awaken upon Real-Time Database value changes as well as to identify which value changed.
However, determining the actions the task is to take for that change is left to the developer.
This is where the Direct Tag Processing (DTP) API enters the picture. The FLDTP API wraps
itself around the Kernel services and presents a higher level interface to the developer. With
DTP, the developer associates an action directly with the tag. In other words, whenever the
value of a tag changes, its associated action is invoked. Therefore, the value-add for DTP is the
developer spends more time on writing the processing than on routing value changes to the
processing.
This section categorizes the interfaces exposed by the FLDTP API. It should also help you
envision how to make it work for your task. All of the code samples have been taken from the
PAK Skeleton task.
In general terms, the DTP is a container of actions bound to tags with the normal overhead of
construction, attribution, and destruction functionality.
The main structure is fldtp. This structure is the tag manager and most work with the FLDTP
API requires a handle to one of its instances.
The next most visible structure is the fldtp_action( ) or action record. The action record
represents one process to invoke on behalf of a tag.
Finally, the fldtp_tag( ) structure represents a tag inserted into the DTP. Several actions can be
chained off the same tag. Users normally do not directly operate upon this structure.
DPT Instance
6
Function Description
To use DTP, an instance of it must be created. Depending on the complexity of the program,
there may be several DTP instances.
An fldtp instance equates to a tag process manager. Through it, tag processing actions are
added, invoked, and removed. It serves as a container for all the events that the task needs to
respond to.
An action record (the fldtp_action( ) structure) contains all the information required to process
its associated tag. The user does not directly create these records. Instead, an action record is
created on behalf of the user whenever a tag action is inserted into the DTP.
Many attributes can be attached to the action record once its handle has been returned to the
user.
Function Description
Once the DTP is created, tags, along with their actions, need to be loaded into it. In terms of
code, this means calling the function dtp_insert( ) with the appropriate parameters: the handle
to the DTP instance to insert the action into, the tag the action is to be bound to, and the action
to be invoked. The term action means the pointer to the process function to invoke with the tag
value.
A successful insert into the DTP returns the handle to the action record that embodies the
inserted information. With this handle, additional attributes can be attached. Of these
attributes, the user data arguments are the most important. User data arguments are an array of
To illustrate, consider the following code sample. Here, a trigger is being inserted into the DTP.
Once inserted, the related CT information is attached to the action record representing this
trigger event. Later, when DTP invokes action, function proc_trig( ) is called and the CT
information will be passed to it. Also, a destruction notification function free_triginfo( ) is
being attached to the action record. This allows the task to release the memory held by CT
information when the action record is later destroyed. This attachment would not be necessary
if the memory allocated for the CT information was managed elsewhere.
Once the DTP is loaded with the tags and their actions, the next step is to process them. Each
of the process functions in the preceding table offer a unique scope of processing. The most
commonly used is fldtp_proc_wait( ) where the task sleeps until one or tags within the DTP
change. At that time, the actions tied to the changed tags are invoked and control is returned to
the caller. The other process functions either restrict processing to a particular subset of DTP
entries or tune its blocking/non-blocking behavior. The following scrap depicts the normal
process of a FactoryLink task using DTP:
Since the DTP invokes the action functions directly, the only work to perform outside of the
process function is to check the task termination flag.
As for the work to perform from within the process function, note the following code sample
that depicts a simple process function. Whenever a tag associated with process function
proc_trig( ) changes, function fldtp_proc_wait( ) invokes that function with the following
arguments: the tag, its value, and the associated user-defined arguments.
The above code sample takes the tag value from the digital member of the VAL union. This is
because the Skeleton task restricts its triggers to type DIGITAL. For more information on VAL
union, see “fl_read” in Chapter 7 in the API Library.
Function Description
Most tasks initialize the DTP with a set of tags and their actions and never adjust them again
for the life of the task. These tasks do not need to use DTP’s removal function. More
sophisticated tasks, however, may very well need to dynamically alter their processing lists
over the task lifetime.
When a particular action is no longer required, it should be removed from the DTP so the task
need not wake-up unnecessarily. There are two ways to accomplish this. First, function
fldtp_remove( ) accepts the handle the particular action record to remove. While very surgical
and quick, the downside to this is the developer must keep track of all action records held
within the DTP.
The second way is to use function fldtp_remove_group( ). Here, the caller specifies a criteria
used to remove records from the DTP. This criteria is any combination of action function
pointer, user-defined ID, or tag binding. This allows the caller to remove particular records
without necessarily recording the individual handles to each and every DTP insertion the task
has ever made.
Finally, FactoryLink object may have a local or remote value source. This source is known as
its node. This node is sometimes referred to as an external domain.
A tag refers to a single location within the FactoryLink Real-Time Database. A FactoryLink
object equates to one or more tags, depending on whether it is an arrayed object and/or whether
it has member objects associated with it.
Given these parameters, a reference to a FactoryLink object conforms to the following syntax:
[{node}:]{name}[[dimensions]][.member]
where:
node (optional) The source node for the given tag
name The base name for the tag
dimension (optional) The particular tag element for an arrayed tag
member (optional) The sub-component identifier for the base tag
For example, the object reference plc1:tagx[4][5].raw has a node of plc1, a name of tagx, the
dimensions of [4][5], and a member of raw.
This syntax provides the precision required to resolve an object reference to a single,
Real-Time Database location (or tag).
Also given this syntax, the combination of a reference node, name, and member equates to the
name of the object, as seen through Configuration Explorer object list panel. Please keep in
mind the object name component may not be sufficient to uniquely identify a tag. It must be
accompanied by its associated source, dimension, or member attributes.
The FLNTAG API consolidates this processing into a single interface. References can be
decomposed into their base components, have these components modified individually, and
ultimately recombined into a reference string. The API also provides hooks for obtaining
object definitions and RTDB locations.
The services provided by the FLNTAG API are
• Creation and destruction of an FLNTAG instance
• Decomposition of a tag reference string into a FLNTAG
• Object definition and RTDB location retrieval based on the FLNTAG
• Component level manipulation of a FLNTAG
• Generation of a string (reference, object name, …) from a FLNTAG
1. Open the application object table (table containing all known objects)
4. Obtain the RTDB location for the reference, using the FLNTAG API
Therefore, the reference location within the RTDB can be determined in a hands-off manner.
Additionally, should the syntax for a reference change, code based on the API need not change
to support it.
/*
* Function convert_ref2tag() returns the RTDB location for the
* given reference.
*/
int convert_ref2tag(char *flapp, char *tagref, TAG *tag)
{
FLNTAG *ntag;
CT objct;
int rv;
ct_close_obj(&objct);
return rv;
}
Function Description
P ATH M ANIPULATION
6
The functions beginning with the name fl_path( ) are all concerned with allowing developers
The normalized path functions eliminate system-specific path name dependencies and allow
porting of code to different platforms without changes. FactoryLink multi-platform code
should use only these functions to generate path names, open file information, and search
directories.
It is essential you call the fl_path( ) functions instead of attempting to hard-code or build path
names using string functions into the programs if you plan on porting the applications to other
systems and on retaining compatibility with future releases of FactoryLink.
This information is stored in the NPATH C-structure. The NPATH structure should be
considered opaque and its members should not be accessed directly. The fl_path( ) API
provides functions to extract member values.
translates to
DRIVE:\DIRECTORY\SUBDIRECTORY\FILENAME
fl_path( ) functions under Microsoft Windows NT, Windows 95 normalize paths as follows:
• If a DOS-style path string is supplied to fl_path_norm( ), FactoryLink assumes any name
following the last slash character is a file name.
• If a path refers to a directory, add a trailing slash to the path name in order for
fl_path_norm( ) to normalize the path as a directory.
• If the path refers to a directory and adding a trailing slash is a problem, use the
fl_path_set_dir( ) function to normalize the path.
• fl_path_add_dir
• fl_path_set_dir 6
• fl_path_set_file
The function fl_path_alloc( ) allocates and returns a pointer to a normalized path buffer. This
function should be called rather than allocating the NPATH structure directly so you can add a
buffer for system-dependent information to the path buffer.
The function fl_path_free( ) releases the space allocated by a call to fl_path_alloc( ). The
NPATH structure should not be accessed after fl_path_free( ) is called. This leads to
unpredictable behavior of the system.
The function fl_path_sys( ) converts a normalized path into a system specific path string. If the
path argument is null, fl_path_sys( ) calls malloc( ) to allocate memory for the resulting path.
Release the memory when it is no longer in use.
fl_path_set_dir( ) replaces the directory portion of the path and the directory argument is
converted to normalized form. If the NPATH argument is NULL, fl_path_set_dir( ) first calls
fl_path_alloc( ) to allocate a NPATH buffer. The file name, extension and version are not
modified by the fl_path_ser_dir( ) function.
fl_path_cwd( ) builds a normalized path for the current working directory. If the NPATH
argument is NULL, fl_path_cwd( ) first calls fl_path_alloc( ) to allocate a NPATH buffer.
fl_path_add( ) catenates two paths. Any missing component of the second path, p2, is taken
from the first path, p1, or from the current directory if the first path is null.
fl_path_set_pattern( ) sets the wild card pattern for subsequent directory search.
fl_path_set_extension( ) replaces the extension of the current file name portion of the path.
fl_path_mkdir( ) creates the directory given by the directory portion of the path.
fl_path_rmdir( ) deletes the directory given by the directory portion of the path.
fl_path_readdir( ) reads the next matching file in the directory and places the name of the file
into the file name component of the path. The file type, date, time, and size are also stored in
the NPATH structure. fl_path_readdir( ) returns GOOD if a matching file is found or ERROR
if not.
fl_path_info( ) initializes the date, time, size, and type for the path. If the file does not exist,
fl_path_date( ) formats the date of a file into the caller's buffer and returns the date and time
(concatenated) as a long integer.
fl_path_time( ) formats the time of the file into the caller's buffer. This function is operating
system-dependent.
Under Windows NT and Windows 95, the format is controlled by the country code returned by
the MS-DOS function 38h.
Functions Descriptions
Use the fl_xlate( ) functions for output from all messages to create a language-independent
task.
If file names or other data need to be imbedded in a message, use fl_xlate( ) to retrieve the
format string and then sprintf ( ) using that format, as in the following example:
Example 1
When loading translation files, the file fllang.lst in \flink\install is examined to determine the
current language. It is appended to the {FLINK}/MSG path used to load the master file as well
as user-defined files.
If the user-specified file contains path information, it is folded into the {FLINK}/MSG/<lang>
path when loading the file.
The function fl_xlate_init( ) starts a fresh translation tree and loads the default translation file
master.txt. The user-specified translation file is then loaded on top of the existing definitions.
Duplicate definitions are superseded by the last file loaded. The function returns the total
number of translations loaded from both the master.txt file as well as the user-specified file or
returns ERROR.
The function does not use the buff and len parameters of fl_xlate_init( ) but are retained to stay
compatible with existing code.
The function fl_xlate_load( ) loads the specified file into the current translation tree, replacing
any duplicate keys. The function returns the number of entries loaded from this file or returns
ERROR.
Example 2
If the current language variable is defined to be DE for German, the following call:
fl_xlate_init(“iml”, NULL, 0)
loads {FLINK}/MSG/DE/master.txt into the tree and then loads {flink}/msg/de/iml.txt into the
tree. The return value is the total number of translations loaded from both files (duplicates are
counted only once).
The call
fl_xlate_load(“iml”)
loads {FLINK}/MSG/DE/iml.txt into the tree and returns the number of translations.
The call
fl_xlate_load(/temp/test) 6
Translating
char FAR *fl_xlate(char FAR *key)
The function fl_xlate( ) returns a pointer to the translation text for the requested key if the key
is found in the tree. The pointer to the original key is returned if no translation is found.
The function fl_xlate_get_tree( ) returns the address of the current translation tree or NULL if
no translation files are loaded.
The function fl_xlate_set_tree( ) sets the current translation tree to the specified address.
Future file loads and translations are facilitated using this tree.
Example 3
void *tree1, *tree2 ; /* pointers to 2 trees */
fl_xlate_load(“file1") ;
tree1 = fl_xlate_get_tree() ;
fl_xlate_load(“file2") ;
tree2 = fl_xlate_get_tree() ;
fl_xlate_set_tree(tree1) ;
printf(“%s\n”, fl_xlate(“token”)) ;
fl_xlate_set_tree(tree2) ;
printf(“%s\n”, fl_xlate(“token”)) ;
fl_xlate_set_tree( ) may also be used to start a fresh tree, as in the following example:
Example 4
fl_xlate_set_tree(NULL) ; /* start new tree */
All translated text returns with the characters in the Windows codepage 1252. It is important
that the translated files in the FactoryLink ECS baseline, like multilanguage TXT files (*.mlt),
remain in this representation so you can convert from 1252 to other codepages for other
platforms. For this reason, any edits to these files must be performed on a Windows or VMS
platform.
When it is necessary to edit a file that contains text in a foreign language, make sure to
preserve the 1252 representation. Most Windows-based products should be able to handle the
1252 codepage correctly, for example, Microsoft Word, Microsoft Write, Notepad, and
Codewright. You may want to choose one of these editors as your best choice for editing text
files with foreign language data. If you cannot see all the characters clearly, it may be
necessary to select another font.
•
•
•
•
PAK API Reference Library
7
Library
tasks, such as functions to read and write data contained in the real-time database. Where
possible, the API is consistent across operating systems and platforms. This permits programs
written in ANSI C to be compiled without source modification on any of the FactoryLink
platforms. You can upgrade the hardware platform by physically porting the application over
to a different platform and recompiling it.
This chapter provides the following information about each API function:
• Syntax: Valid format for this function
• Arguments: List containing the following information about each argument:
• Type
• Name
• Direction (input = in; output = out; or both = in/out)
• Description
• Returns: Description of the returned data from the function, usually a symbolic
representation representing the integer value returned by the function, such as ERROR or
GOOD.
• Remarks: Additional information about the function, such as code fragments in the C
language.
• See also: Lists related function(s).
Returns GOOD
CT_NULL_POINTER
CT_FILE_NOT_OPEN
CT_CANNOT_CLOSE_FILE
See also “ct_open”
CT _ CLOSE _ OBJ
Object CT API.
Syntax #include <objct.h>
Returns CT_NULL_PTR
CT_FILE_NOT_OPEN
CT_CANNOT_CLOSE_FILE
Remarks Function ct_close_obj( ) closes the object CT. The CT handle should not be
referenced after being closed.
See also “ct_open_obj”
CT _ FIND _ INDEX
7
Find an index.
Syntax #include <flib.h>
Library
Arguments CT* ctp in CT file buffer.
char* ndx in Name field.
Returns GOOD
CT_NULL_POINTER
CT_FILE_NOT_OPEN
CT_SEEK_ERROR
CT_READ_ERROR
CT_BAD_DATA
CT_BAD_INDEX
Remarks Find an index by matching the name field.
CT _ FIND _ OBJ
Object CT API.
Syntax #include <objct.h>
CT _ GET _ HDRLEN
Get the length of the current CT table header.
Syntax include <flib.h>
Returns Length of the header. The return value is undefined if the CT archive is not opened.
Remarks Determine the length of the table header of the currently selected CT table.
See also “ct_read_hdr”
CT _ GET _ NAME
Get the name of the current CT table.
Syntax #include <flib.h>
Returns Table name. The return value is undefined if the CT archive is not opened.
Remarks Returns a pointer to the name field of the currently selected CT table. Do not modify
the memory pointed to by the return value.
CT _ GET _ NCTS
7
Determine the number of CT tables in the archive.
Syntax #include <flib.h>
Library
Arguments CT* ctp in CT file buffer.
Returns Number of CT tables. The return value is undefined if the CT archive is not opened.
CT _ GET _ NRECS
Determine the number of records in the last selected CT table.
Syntax #include <flib.h>
Returns Number of records. The return value is undefined if the CT archive is not opened.
CT _ GET _ RECLEN
Determine the record length of records in current CT table.
Syntax #include <flib.h>
Returns Length of individual records. The return value is undefined if the CT archive is not
opened.
Remarks All tables have fixed-length records.
Returns Table type number. The return value is undefined if the CT archive is not opened.
CT _ NRECS _ OBJ
Object CT API.
Syntax #include <objct.h>
Returns GOOD
ERROR
Remarks Function ct_nrecs_obj( ) returns the total number of objects contained within the
given object CT.
See also “ct_open_obj”
“ct_read_objs”
CT _ OPEN
Open a CT archive file.
Syntax #include <flib.h>
Returns GOOD
CT_NULL_POINTER 7
CT_CANNOT_OPEN_FILE
Library
Remarks ct_open( ) places information about the CT archive into the buffer ctp points to. The
archive is positioned at the first table in the archive.
CT _ OPEN _ OBJ
Object CT API.
Syntax #include <objct.h>
Returns GOOD
CT_NULL_PTR
CT_CANNOT_OPEN_FILE
CT_READ_ERROR
CT_BAD_MAGIC
Description Function ct_open_obj( ) opens the object CT. This CT handle is passed to all
subsequent object CT API calls.
See also “ct_close_obj”
CT _ READ _ HDR
Read the header for ctp into buffer.
Syntax #include <flib.h>
CT _ READ _ INDEX
Read and index from a CT archive.
Syntax #include <flib.h>
Returns GOOD
CT_NULL_POINTER
CT_FILE_NOT_OPEN
CT_BAD_INDEX
CT_SEEK_ERROR
CT_READ_ERROR
Remarks Each table in the archive has an associated index containing information about the
table. The index is read into the CT file buffer ctp points to. Reading an index selects
a specific CT for reading.
CT _ READ _ OBJS
7
Object CT API.
Syntax #include <objct.h>
Library
Arguments CT* objct in Object CT handle.
FLOBJREC* recs out Buffer for object definitions.
Returns GOOD
ERROR
Remarks Function ct_read_obsj( ) reads the given number of definitions (nrecs) into target
buffer recs, beginning at record srec.
See also “ct_open_obj”
“ct_nrecs_obj”
CT _ READ _ REC
Read a record from the current CT into memory.
Syntax #include <flib.h>
Returns GOOD
CT_NULL_POINTER
CT_FILE_NOT_OPEN
CT_BAD_INDEX
CT _ READ _ RECS
Read records from the current CT into memory.
Syntax #include <flib.h>
Returns GOOD
CT_NULL_POINTER
CT_FILE_NOT_OPEN
CT_BAD_INDEX
CT_BAD_RECORD
CT_SEEK_ERROR
CT_READ_ERROR
Remarks Read the indicated records from the currently selected CT into the memory pointed to
by the buffer. Reading begins at record number rec.
FL _ CHANGE _ READ
7
Read the first real-time database element that has changed since it was last read.
Syntax #include <flib.h>
Library
Arguments id_t id in Caller’s FactoryLink ID.
TAG* tp in Pointer to tag array specifying which
elements to examine.
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller's FactoryLink ID and it
returns one of the following errors:
FLE_NULL_POINTER
FLE_BAD_ARGUMENT
FLE_NO_CHANGE
FLE_LOCK_FAILED
FLE_BAD_TAG
Remarks Test for a change in value of one or more elements in the real-time database. The
calling process is immediately informed (it is never blocked) as to whether any of the
specified real-time database elements changed since last read. ip specifies the first
element to examine; however, in contrast to fl_change_wait( ), ip does not wrap
around the tag array.
In the case of a message element, be sure the m_ptr and m_mbx members of value
area vp are initialized.
In the case of a mailbox element, the value passed back is the MBXMSG for the head
message without the associated message data.
int fl_change_wait (id_t id, TAG* tp, uint n, uint* ip, void* vp);
uint* ip out Pointer to index into tag array to be used and updated,
if necessary, by the kernel.
void vp out Pointer to area to receive the value of the first changed
element, if r==GOOD.
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller's FactoryLink ID and it
returns one of the following errors:
FLE_NULL_POINTER
FLE_BAD_ARGUMENT
FLE_NO_CHANGE
Remarks Wait on a change in value of one or more elements in the real-time database. If any of
these elements has changed, control is returned immediately to the caller as in
fl_change_read( ). Otherwise, the calling process is put to sleep (blocked) until one
or more of the specified real-time database elements changes. At this point, it is
awakened. While sleeping, the calling task is also awakened if another process wakes
it up. This can be done either directly via fl_send_sig( ) or indirectly via
fl_set_term_flag( ). Although all n elements are waited upon, only one value is read
and returned in vp. This is the one detected as the first one to change. In deciding
which element is first, ip is used in wraparound fashion within the tag array.
In the case of a message element, be sure the m_ptr and m_mbx members of value
area vp are initialized.
In the case of a mailbox element, the value passed back is the MBXMSG for the head
message without the associated message data.
FL _ CLEAR _ CHNG
7
Clear the calling task change-status flags for specified real-time database elements.
Syntax #include <flib.h>
Library
Arguments id_t id in Caller’s FactoryLink ID.
TAG* tp in Pointer to tag array.
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller's FactoryLink ID and it
returns one of the following errors:
FLE_NULL_POINTER
FLE_LOCK_FAILED
FLE_BAD_TAG
Remarks Clear (to 0) the change state of the specified real-time database elements for the
calling process only. This function undoes action of fl_set_chng( ). It is also useful
for establishing initial conditions for a programming loop.
FL _ CLEAR _ WAIT
Clear the calling task wait flags for specified real-time database elements.
Syntax #include <flib.h>
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller’s FactoryLink ID and it
returns one of the following errors:
FL _ COUNT _ MBX
Determine the number of messages in a mailbox, validate a mailbox, or monitor a
mailbox.
Syntax #include <flib.h>
FL _ DBFMTT
7
Prepare a formatted string from a set of real-time database element values.
Syntax #include <flib.h>
Library
Arguments id_t id in Task ID used to access real-time database.
int maxlen in Maximum number of characters that can be stored
in the output buffer.
FL _ ERRNO
Return the last FactoryLink error number generated by the calling process.
Syntax #include <flib.h>
Returns GOOD
Last Error Number
Remarks Returns the last FactoryLink error number generated by the calling process during the
last call to the kernel that resulted in an error.
Arguments TAG* tagp out Array where tag numbers are returned.
Remarks Function fl_find_global_tag( ) performs searches for global tags based on the
application domain hierarchy. 7
If fl_global_tag is called from the SHARED domain, it looks in the GLOBAL.CT
configuration table for tags matching elements defined in the SHARED domain.
Library
GLOBAL.CT contains global elements available to all tasks. The GLOBAL.CT is
searched for a matching value for each member of the ids array. The associated
element is then copied into the corresponding member of the tagp array.
The id values are defined in FLIB.H.
The following code illustrates an example of the use of this function:
#include <flib.h>
…
uint ids[3] = {GT_SECONDS, GT_MINUTES, GT_HOURS};
TAG gtags[3];
ANA vals[3];
fl_find_global_tag(>ags[0], 3, &ids[0],getenv(“FLAPP”),
setenv(“FLDOMAIN));;
seconds = vals[0];
minutes = vals[1];
hours = vals[2];
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller's FactoryLink ID and it
returns one of the following errors:
FLE_NULL_POINTER
FLE_LOCK_FAILED
FLE_BAD_TAG
FLE_OUT_OF_MEMORY
FLE_FLOAT_NAN
FLE_FLOAT_POS_INF
FLE_FLOAT_NEG_INF
Remarks This function operates similarly to fl_write( ) except all change states are set on
regardless of whether the new values written into the database are the same as the
previous values stored there. Upon completion of writing, those client processes
waiting on any of the elements involved are awakened.
Library
Arguments id_t id in Caller’s FactoryLink ID.
char* dir out Pointer to directory string to be returned.
char* fl_get_copyrt(void);
Arguments None.
Returns Pointer to copyright message.
Remarks Do not modify the pointer returned by this function.
FL _ GET _ ENV
7
Return the KENV structure of the client process.
Syntax #include <flib.h>
Library
Arguments id_t id in Client FactoryLink ID (0-30) used as an index into
array of KENVs kept by the kernel.
Returns GOOD
ERROR
Remarks Return a KENV structure describing the environment of the given client process,
usually the calling process. The Run-Time Manager calls fl_set_env( ) to define this
structure before the client process is started. This function returns all fields of the
KENV structure.
FL _ GET _ SERIAL
Return a pointer to the serial number assigned to the FactoryLink system.
Syntax char* fl_get_serial(void);
Arguments None.
Returns If successful, the function returns a pointer to serial number of the FactoryLink
system.
If unable to access the kernel (task not initialized with the kernel), the function returns
NULL.
Remarks Do not modify the pointer returned by this function.
Library
Arguments id_t id in Caller’s FactoryLink ID.
TAG* tag out Pointer to status element to be returned.
The Run-Time Manager converts the status value to an ASCII string and passes it to
the Real-Time Graphics process for display on the Run-Time Manager screen.
Returns GOOD
ERROR
Remarks The dp array is filled in with one of the following values that correspond to the
elements passed to it
Value Description
FL_BAD_DATA Element is out-of-range (bad t_data field).
FL_BAD_TYPE Element is a bad t_type field.
FL_UNDEFINED Element is undefined.
FL_DIGITAL Element is a digital (DIG).
FL_ANALOG Element is an analog (ANA).
FL_MESSAGE Element is a message (MSG).
FL_LANALOG Element is a long analog (longana).
FL_FLOAT Element is floating point (FLP).
FL_MAILBOX Element is mailbox (holds MBXMSGs).
The kernel fills in the op array with the offset into the vp buffer where the value is
stored if fl_read( ), fl_write( ) or fl_forced_write( ) are called with the argument list
(id, tp, n, vp). The caller may set either or both of the pointers dp or op to NULL if he
does not wish to receive corresponding information, fl_get_tag_info( ) if all n
elements in the tp array are valid, and ERROR if one or more of them is bad.
FL _ GET _ TICK
7
Get the current clock tick and/or current date and time maintained and reported by the
operating system.
Library
Arguments u32 tickp out Pointer to location for storing clock tick.
KDT* datetimep out Pointer to location for storing data and time.
FL _ GET _ TITLE
Return a pointer to the name of the product.
Syntax #include <flib.h>
char* fl_get_title(void);
Arguments None.
Returns Pointer to name of product.
Remarks Do not modify the pointer returned by this function.
FL _ GET _ VERSION
Get the kernel version number.
Syntax #include <flib.h>
uint fl_get_version();
Arguments None.
Returns FactoryLink kernel version number. Numerically returns version x.y as
(x * 256) + y.
Arguments TAG* tagp out Array where tag numbers are returned.
…
uint ids[3] = {GT_SECONDS, GT_MINUTES, GT_HOURS};
TAG gtags[3];
ANA vals[3];
fl_global_tag(>ags[0], 3, &ids[0]);
seconds = vals[0];
minutes = vals[1];
hours = vals[2];
A smart run-time task can initiate a shutdown of the FactoryLink system. To cause the
Run-Time Manager to begin an immediate system shutdown, the task writes a value
of 1 (ON) to the global, predefined analog element, RTMCMD.
FL _ HOLD _ SIG
7
Prevent or allow signal delivery for the calling process.
Syntax #include <flib.h>
Library
int sig in Signal (0-31) to be affected.
int hold in Hold value:
1 = prevent signal delivery.
0 = allow signal delivery.
FL _ ID _ TO _ NAME
Translate a FactoryLink ID to a process name.
Syntax #include <flib.h>
u16* klimp in/out If setting values, the new limits are passed within
this array.
If getting values, the mailbox limits are returned
within this array.
FL _ LOCK
7
Lock the real-time database on behalf of the calling process.
Syntax #include <flib.h>
Library
Arguments id_t id in Caller’s FactoryLink ID.
Returns GOOD
ERROR
Remarks Only one client process may have the real-time database locked at any given time. If
the calling process calls fl_lock( ) and the real-time database is already locked by that
same process, a counter is incremented and the lock remains in effect for the caller.
This counter allows calls to fl_lock( ) and fl_unlock( ) to be nested.
If another client process has already locked the real-time database, the caller is put to
sleep (blocked) until his lock request can be honored. Upon return from fl_lock( ),
only the calling process is granted access to the real-time database until it makes a
corresponding call to fl_unlock( ), provided it does not execute fl_wait( ), either
directly or indirectly. fl_wait( ) releases its lock and puts it to sleep. When it awakes,
the lock is reinstated.
If the caller wants to keep the real-time database locked and thereby retain exclusive
access to it, it must not call fl_change_wait( ) or write any synchronous elements via
fl_write( ) or fl_forced_write( ).
FL _ NAME _ TO _ ID
Translate a process name to a FactoryLink ID.
Syntax #include <flib.h>
Returns FactoryLink ID
ERROR: if error, an invalid process name is assumed
Remarks fl_name_to_id( ) searches the domain of the given task id for the specified process
name; and, if the process name is found, returns the associated FactoryLink ID.
Returns The file access mode of the file as one of the following character strings:
NPATH_READ
NPATH_WRITE
NPATH_READ | NPATH_WRITE
If specified file does not exist, returns ERROR.
Remarks The function fl_path_access( ) returns a string informing the calling program of the
mode(s) (read-only, write-enable, or read/write) the calling program is authorized to
access the specified file in, if available.
See also fl_path and related calls
FL _ PATH _ ADD
Catenates two normalized paths.
Syntax #include <flpath.h>
Returns N/A
Remarks fl_path_add( ) catenates two paths. Any missing component of the second path p2 is
taken from the first path p1 or from the current directory if the first path is null.
See also fl_path and related calls
Library
Arguments NPATH* path in/out Pointer to a previously allocated NPATH structure
containing a normalized path name buffer.
Returns N/A
Remarks fl_path_add_dir( ) adds a subdirectory specification to the end of the directory
portion of a path. Only one subdirectory can be added to a path during each call to
fl_path_add_dir( ). The subdirectory name should not contain any path-separator
characters.
See also fl_path and related calls
FL _ PATH _ ALLOC
Allocate a normalized path name buffer.
Syntax #include <flpath.h>
NPATH* fl_path_alloc(void);
Arguments None.
Returns If successful, returns a pointer to an allocated normalized path buffer.
If unsuccessful, returns NULL; an invalid process name is assumed.
Remarks The function fl_path_alloc( ) allocates and returns a pointer to a normalized path
buffer. Programmers should call this function, rather than allocate the NPATH
structure directly so a buffer for system-dependent information can be added to the
path buffer.
See also fl_path and related calls
Returns N/A
Remarks fl_path_closedir( ) ends a directory search.
See also “fl_path_opendir” and related calls
FL _ PATH _ CREATE
Create an empty file using the complete path specified.
Syntax #include <flpath.h>
Returns GOOD
ERROR
Remarks fl_path_create( ) creates an empty file using the complete path specified by the given
NPATH. The file may then be opened, copied, referenced, or closed by any task with
the proper file access privileges.
FL _ PATH _ CWD
Build a normalized path for the current working directory.
Syntax #include <flpath.h>
Returns Pointer to a normalized path buffer. The pointer is returned in the variable named in
the call: PATH = fl_path_cwd( ). 7
NULL
Library
name built.
FL _ PATH _ DATE
Places formatted system date and time stamp from a specified file's header into
specified buffer.
Syntax #include <flpath.h>
FL _ PATH _ INFO
Initialize date, time, size, and type of files allowed for the specified path.
Syntax #include <flpath.h>
Returns GOOD
ERROR
Remarks fl_path_info( ) initializes the date, time, size, and type for the path. If the path does
not exist, fl_path_info( ) returns ERROR. Otherwise, it returns GOOD.
This function is called automatically by fl_path_opendir( ) and fl_path_readdir( ).
FL _ PATH _ MKDIR
7
Creates the directory specified by the directory portion of the indicated path.
Syntax #include <flpath.h>
Library
Arguments NPATH* path in Pointer to a previously allocated NPATH structure
containing a normalized path name buffer.
Returns GOOD
ERROR
Remarks fl_path_mkdir( ) creates the directory given by the directory portion of the path, if the
directory does not already exist. It creates all directories and subdirectories necessary
for the path, up to and including the last subdirectory specified in the NPATH
structure.
For example, if none of the following directories exist:
/test
/test/mystuff
/test/mystuff/log
the following code fragment in C creates them all, in hierarchical order:
NPATH* np;
np = fl_path_set_dir(NULL, /test/mystuff/log);
fl_path_mkdir(np);
This function returns GOOD if the directories already exist. It returns ERROR only if
at least one of the directories cannot be created because of a system error or
insufficient privilege levels on the part of the caller.
See also “fl_path_rmdir” and related calls
Returns Pointer to the NPATH structure; also, if the pointer argument p passed in was NULL,
an NPATH buffer has been allocated and the pointer value is now set.
NULL
Remarks fl_path_norm( ) converts a system-specific path string into a normalized path. Any or
all components of the path may be left out. If the NPATH argument is NULL,
fl_path_norm( ) first calls fl_path_alloc( ) to allocate a NPATH buffer.
FL _ PATH _ OPENDIR
Begins a directory search for a file.
Syntax #include <flpath.h>
Returns GOOD
ERROR
FL _ PATH _ READDIR
7
Reads next matching file from directory during a directory search for a file.
Syntax #include <flpath.h>
Library
Arguments NPATH* path in/out Pointer to a previously allocated NPATH structure
containing a normalized path name buffer.
Returns GOOD
ERROR
Remarks fl_path_readdir( ) reads the next matching file in the directory and places the name of
the file into the file name component of the path. The file type, date, time, and size are
also stored in the NPATH structure. fl_path_readdir( ) returns GOOD if a matching
file was found or ERROR, if not found.
The following code fragment in C demonstrates how to use directory search functions
to print a directory listing:
NPATH* p;
char date[80];
char time[80];
char fullpath[MAX_PATH_NAME];
= fl_path_norm(NULL, *.*);
if ( fl_path_opendir(p) == ERROR )
{
printf(Directory Not found\n);
return;
}
do
{
fl_path_date(p, date);
fl_path_time(p, time);
fl_path_sys(p, fullpath);
printf(%s %s %s\n, date, time, fullpath);
} while ( fl_path_readdir(p) != ERROR );
fl_path_closedir(p);
fl_path_free(p);
FL _ PATH _ RMDIR
Delete the directory specified by the directory portion of the indicated path.
Syntax #include <flpath.h>
Returns GOOD
ERROR
Remarks fl_path_rmdir( ) deletes the directory given by the directory portion of the path.
See also “fl_path_mkdir” and related calls
Library
Arguments NPATH* path in/out Pointer to a previously allocated NPATH structure
containing a normalized path name buffer.
char* dir in Directory name in system-specific format.
Returns N/A
Remarks fl_path_set_device( ) replaces the drive (device) name portion of the path with the
specified argument after converting the argument to normalized form.
See also fl_path( ) and related calls
Returns N/A
Remarks fl_path_set_extension( ) replaces the file extension portion of the path with the
specified argument after converting the argument to normalized form.
See also fl_path( ) and related calls
Returns N/A
Remarks fl_path_set_file( ) replaces the file name portion of the path with the specified
argument after converting the argument to normalized form.
See also fl_path( ) and related calls
Library
Arguments NPATH* path in/out Pointer to a previously allocated NPATH
structure containing a normalized path name
buffer.
char* node in Node name in system-specific format.
Returns N/A
Remarks fl_path_set_node( ) replaces the node name portion of the path with the specified
argument after converting the argument to normalized form.
See also fl_path( ) and related calls
Returns N/A
Remarks fl_path_set_pattern( ) sets a wild card pattern in the specified portion of the path in
normalized form for subsequent directory searches.
See also fl_path( ) and related calls
FILE *ac_file;
char *flink; /* Buffer containing FLINK path*/ char *filename; /*
Buffer containing AC file name */
np = fl_path_alloc();
if (np == NULL)
return ERROR;
fl_path_sys(path, flink, sizeof(flink));
np = fl_path_add_dir(np, ac);
fl_path_set_file(np, filename);
fl_path_set_extension(np, ac);
fl_path_set_version(np, "");
ac_file = fl_path_fopen(np, r);
fl_path_free(np);
if (ac_file == NULL)
return ERROR;
FL _ PATH _ TIME
7
Places formatted system time stamp from a specified file's header into specified
buffer.
Library
Arguments NPATH* path in Pointer to a previously allocated NPATH
structure containing a normalized path name
buffer.
char* buf out Buffer to contain returned time stamp.
FL _ PROC _ EXIT
Detaches the task from the kernel.
Syntax #include <flib.h>
Returns GOOD
ERROR
Remarks This function renounces all further access to the real-time database.
Library
char* flname, char* fldomain, char* fluser);
The flname argument specifies the name of the invocation the task is registering
with. Normally, the value of the environment variable FLNAME is used.
The fldomain argument specifies the domain the task is registering for and is
associated with at run time. Normally, the value of the environment variable
FLDOMAIN is used.
The fluser argument specifies which instance of the specified domain the task is
registering for. Normally, the value of the environment variable FLUSER is used.
Returns Calling routine FactoryLink task ID
If unsuccessful at registering the start-up process with the kernel, returns one of the
following negative (sign bit on) error codes:
FLE_NO_FLINK_INIT
FLE_BAD_PROC_NAME
FLE_ALREADY_ACTIVE
FLE_NULL_POINTER
FLE_NO_PROC_INIT
FLE_PROC_TABLE_FULL
FL _ QUERY _ MBX
Query a mailbox for a range of queued messages.
Syntax #include <flib.h>
int fl_query_mbx(id_t id, TAG mbx, MBXMSG* mmp, uint i, uint n, uint* np);
Remarks Use this function to read one or more mailbox message headers without reading their
message data and without dequeueing them. The MBXMSG holds information about 7
the message, such as type, who sent it, and length of its data. Therefore, call
fl_query_mbx( ) prior to allocating space for the message data and calling
Library
queue is the oldest message in the mailbox. The argument n specifies how many
maximum mailbox messages are requested to be read and the kernel fills in np with
the actual number read.
FL _ READ
Read specified elements from the real-time database.
Syntax #include <flib.h>
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller's FactoryLink ID and it
returns one of the following errors:
FLE_NULL_POINTER
FLE_LOCK_FAILED
FLE_BAD_TAG
Remarks The elements may have mixed data types, as with all database access calls. The values
of the elements are read from the real-time database and placed in the private data
area of the calling process pointed to by vp. After each element is read, its change bit
for the calling process is cleared. The change state for other client processes are
int fl_read_app_mbx(id_t id, id_t rid, MBX mbx, MBXMSG* msg, uint i);
FLE_ACCESS_DENIED
FLE_LOCK_FAILED
FLE_LOCK_EXPIRED
Remarks Use fl_read_app_mbx( ) to read a single mailbox message together with its message
data. After this is done, the message is deleted or dequeued from the mailbox. If the 7
buffer provided by the caller is not large enough, message data may be lost.
Just as in fl_query_mbx( ), the argument i specifies which mailbox message, relative
Library
fl_read_app_mbx(id, id, &mbxtag, mmp, 0);
is equivalent to:
fl_read(id, &mbx, 1, mmp);
FL _ READ _ MBX
Read and dequeue a message from a mailbox (Obsolete. See fl_read_ app_mbx).
Syntax #include <flib.h>
LE_NULL_POINTER
FLE_BAD_TAG
FLE_NOT_MAILBOX
FLE_NO_MESSAGES
FLE_ACCESS_DENIED
FLE_LOCK_FAILED
FLE_LOCK_EXPIRED
FL _ READ _ NO _ CLEAR
Syntax #include <flib.h>
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller's FactoryLink ID and it
returns one of the following errors:
FLE_NULL_POINTER
FLE_LOCK_FAILED
FLE_BAD_TAG
Remarks Function fl_read_no_clear( ) behaves exactly the same as function fl_read( ), except
that the change bits for the reading tasks are not cleared. This enables the program to
obtain the latest value of a tag while preserving the current state of the tag change bit
such that a changed value can be processed at some later point.
See also “fl_change_read”
“fl_read”
FL _ RECV _ SIG
7
Receive a signal for the calling process.
Syntax #include <flib.h>
Library
Arguments id_t id in Caller’s FactoryLink ID.
FL _ SEND _ SIG
Send a signal to a target process.
Syntax #include <flib.h>
Remarks It is legal to send any signal to any active FactoryLink process. If the intended
recipient of the signal is asleep or waiting to lock or to access the database in the
kernel and the signal is not being held, the recipient is immediately awakened and
returned the error code FLE_SIGNALLED. The recipient should then call
fl_recv_sig( ) to see which signal was sent.
FL _ SET _ CHNG
Set the calling task change-status flags for specified real-time database elements.
Syntax #include <flib.h>
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller's FactoryLink ID and it
returns one of the following errors:
FLE_NULL_POINTER
FLE_LOCK_FAILED
FLE_BAD_TAG
Remarks Set the change state of the specified real-time database elements for the calling
process only to ON. This establishes initial conditions prior to entering a
programming loop, particularly those that use fl_change_read( ) or
fl_change_wait( ) to read real-time database values.
Library
Arguments id_t id in Task ID.
TAG mbx in Mailbox to modify.
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller's FactoryLink ID and it
returns one of the following errors:
FLE_BAD_TAG
FLE_NOT_MAILBOX
FLE_ACCESS_DENIED
Remarks Use this function to set the owner of a mailbox.
If the value of onoff is TRUE, the owner of the mailbox is set to the calling task.
If the value of onoff is FALSE, the mailbox ownership is removed.
When a write is performed on the mailbox, the owner of a mailbox is signaled with
flc_sig_message_received( ).
See also “fl_send_sig”
FL _ SET _ WAIT
Set the calling task wait flags for specified real-time database elements.
Syntax #include <flib.h>
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller's FactoryLink ID and it
returns one of the following errors:
FLE_NULL_POINTER
FLE_LOCK_FAILED
FLE_BAD_TAG
Remarks Set the wait flag of the specified real-time database elements for the calling process
only to ON. This function is used in conjunction with fl_wait( ) to wait on a set of
real-time database elements.
FL _ SLEEP
7
Delay execution of the task for the indicated number of milliseconds.
Syntax #include <flib.h>
Library
Arguments ulong msecs in Number of milliseconds to delay.
Returns None.
Remarks The actual resolution of the delay is system-specific; however, at most, the delay is
one second.
Returns OFF
ON
ERROR
Remarks Test the termination flag of the calling process and return its state to OFF or ON.
If the flag is ON, another client process (usually the Run-Time Manager) has
requested that the caller exit via fl_proc_exit( ).
FL _ UNLOCK
Unlock the real-time database for the calling process.
Syntax #include <flib.h>
FL _ WAIT
Wait to read, write, or access the real-time database or certain elements in the
database.
Syntax #include <flib.h>
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller's FactoryLink ID and it
returns one of the following errors:
FLE_BAD_ARGUMENT
FLE_WAIT_FAILED
FLE_TERM_FLAG_SET
Remarks Ensure the fl_wait( ) function call is embedded between calls to functions fl_lock( )
and fl_unlock( ); otherwise, the task keeps the run-time database locked. Normally, a
task only waits to read a value; therefore, the constant FLC_WAIT_READ is passed
into the function.
FL _ WRITE
7
Write specified elements into the real-time database.
Syntax #include <flib.h>
Library
TAG* tp in Pointer to tag array specifying which
elements are to be written.
uint n in Number of elements to be written.
void* vp in Pointer to area holding the values.
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller's FactoryLink ID and it
returns one of the following errors:
FLE_NULL_POINTER
FLE_LOCK_FAILED
FLE_BAD_TAG
FLE_OUT_OF_MEMORY
FLE_FLOAT_NAN
FLE_FLOAT_POS_INF
FLE_FLOAT_NEG_INF
Remarks The elements may have mixed data types. The values of the elements are read from
the private data area pointed to by vp and written into the kernel database. After each
value transfer, vp is incremented by the size of the element. If the new value of the
element is different from its previous value, the element change state for all client
processes is set to ON after it is written. Those processes waiting on a change to this
element are then awakened.
The amount of data that can be written to a message tag is established by the length of
data of the first write to that tag. The one exception is if an explicit message length is
set within the tag definition.
For cases in which the length has not been pre-defined and the task needs to initialize
the space allocated to the message for that value, then:
set m_ptr member of the MSG structure is set to NULL
set m_max field is set to a non-zero value
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller's FactoryLink ID and it
returns one of the following errors:
FLE_NULL_POINTER
FLE_BAD_TAG
FLE_NOT_MAILBOX
FLE_NO_MESSAGES
FLE_ACCESS_DENIED
FLE_OUT_OF_MEMORY
FLE_LOCK_FAILED
FLE_LOCK_EXPIRED
Remarks Use fl_write_app_mbx( ) to write a single mailbox message together with its message
data to a mailbox by application instance. The message being written is added to the
end of the queue. Prior to making this call, the caller must fill in the MBXMSG and
the message data. The additional arguments in the current API allow the caller to
specify the ID of the owner of the mailbox and an index into the queue. The owner's
ID is used to determine which instance of the mailbox to write this message into.
Note that within the same domain instance, fl_write( ) does the same thing as
fl_write_app_mbx( ) when passed a mailbox TAG. That is, the function call 7
fl_write_app_mbx(id, id, &mbx, mmp) ;
Library
FL _ WRITE _ MBX
Write and queue a message into a mailbox. (Obsolete. See fl_write_ app_mbx( )).
Syntax #include <flib.h>
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller's FactoryLink ID and it
returns one of the following errors:
FLE_NULL_POINTER
FLE_BAD_TAG
FLE_NOT_MAILBOX
FLE_NO_MESSAGES
FLE_ACCESS_DENIED
FLE_OUT_OF_MEMORY
FLE_LOCK_FAILED
FLE_LOCK_EXPIRED
Remarks This API has been retained from previous releases of FactoryLink to maintain
compatibility for users to upgrade with no changes to existing startup code. However,
new tasks should use fl_write_app_mbx( ) with additional capabilities for multi-user
systems. fl_write_mbx( ) can only be used to send messages to tasks in the same
domain instance.
fl_write_mbx(id, &mbxtag, mmp) ;
is equivalent to:
fl_write_app_mbx(id, Id, &mbxtag, mp) ;
Returns Pointer to message if key found; equal to keyptr if key not found
Remarks This function returns the text associated with the passed in key. The associations must
have been previously created by loading a message translation file via fl_xlate_init( )
and/or fl_xlate_load( ).
Example 1
Allocate a message array, such as message[ ], and call the translation function to
access messages in the message file and put the result in message[ ]. In the following
example, the function copies the string normal shutdown (the message associated
with the key SHUTDOWN) into message[ ].
char message[100];
strcpy(message, fl_xlate(SHUTDOWN));
See also “fl_xlate_init”
“fl_xlate_load”
FL _ XLATE _ INIT
Message translation initialization; loads the first message file.
Syntax #include <flib.h>
Remarks This function, along with fl_xlate( ), comprises the basis of the message-translation
facility. These two functions allow run-time tasks to print messages stored in external 7
disk files called message files.
When called to initialize the message translation environment, the function
Library
function returns the total number of translations loaded from both the MASTER.TXT
file as well as the user-specified file or it returns ERROR if there has been an error.
The buff and len parameters of fl_xlate_init( ) are not used by the function but were
retained to stay compatible with existing code.
A task that uses the message translation facility can be written so it is independent of
the messages it prints. It is dependent on the mnemonic keys but not the messages. In
particular, it may be written so it is independent of the language the messages are
written in. Achievement of this independence is the main purpose of message
translation.
Message files are ASCII text files that can be edited and changed with an ordinary
text editor. The current working copies of these files on a FactoryLink system are in
the directory {FLINK}/MSG/{LANG} and all are assumed to have the extension
.TXT. Message files must conform to the following rules:
The message translation functions assume lines beginning with an asterisk are
comments and ignores these lines. They also ignore blank lines.
Non-comment, non-blank lines serve to translate a key to an associated message.
They must have the following form:
KEY white space MESSAGE
The message may be enclosed within double quote marks for clarity and to avoid the
stripping of leading and trailing white space by the translation function. It may
contain %, the substitution character used by PRINTF and SPRINTF.
A vertical bar (|) is allowed as a separator within the white space for compatibility
with the format of FactoryLink .KEY files.
When editing a message file, place the most commonly used messages near the
beginning of the file so access to the commonly used messages is quicker than to
other messages, particularly when the buffer in use is small.
To use the message-translation functions, a task first calls the initialization function,
which opens the message file {FLINK}/MSG/EN/RUNMGR.TXT, as shown in the
following example:
fl_xlate_init(RUNMGR, NULL, 0);
FL _ XLATE _ LOAD
Load the specified file (passed as a parameter) into the current translation tree
replacing any duplicate key.
Syntax #include <flib.h>
Example 2
If the current language variable is not defined, the call: 7
num_msg = fl_xlate_init(iml, NULL, 0)
Library
The call
num_msg = fl_xlate_load(iml)
loads the file {FLINK}/MSG/iml.txt into the tree and returns the number of
translations.
The call
num_msg = fl_xlate_load(/temp/test)
loads the file /TEMP/test.txt into the tree and returns the number of translations.
Example 3
If the current language variable is defined as DE, the following call:
num_msg = fl_xlate_init(iml, NULL, 0)
loads the {FLINK}/MSG/DE/master.txt file into the tree and then loads the
{FLINK}/MSG/DE/iml.txt file into the tree. The return value is the total number of
translations loaded from both files. Duplicates are counted only once.
The call
num_msg = fl_xlate_load(iml)
now loads the file {FLINK}/MSG/DE/iml.txt into the tree and returns the number of
translations.
The call
num_msg = fl_xlate_load(/temp/test)
still loads the file /TEMP/test.txt into the tree and returns the number of translations.
See also “fl_xlate”
“fl_xlate_init”
“fl_xlate_set_tree”
“fl_xlate_get_tree”
Return Address of the current translation tree; returns NULL if no translation files have been
loaded
Remarks This is useful when a program maintains multiple translation trees. This function
returns the address of the current translation tree (default translations for FactoryLink
tasks) is returned by calling this function.
Tasks may maintain more than one translation tree. Translation files may be kept in
libraries, one per language used, for ease of use. This guarantees all tasks remain
language-independent and allows run-time tasks to use the fl_xlate( ) functions for all
message output.
Example
void *english, *french; /* pointers to 2 trees */
english = fl_xlate_get_tree();
french = fl_xlate_get_tree();
You may switch translation trees at any point in the program and switch back when
ready without losing any data.
See also “fl_xlate”
“fl_xlate_init”
“fl_xlate_set_tree”
“fl_xlate_get_tree”
Library
Arguments char* progname in Pointer to path of program directory to be
used for translation.
english = fl_xlate_get_tree();
french = fl_xlate_get_tree();
You switch translation trees at any point in the program and switch back when ready
without losing any data.
The following example shows fl_xlate_set_tree( ) starting a fresh tree:
fl_xlate_set_tree(NULL) ; /* start new tree */
See also “fl_xlate”
“fl_xlate_init”
“fl_xlate_get_tree”
“fl_xlate_load”
Library
Arguments FLDTP_ACTION* ap in DTP action handle.
Returns FLDTP_E_GOOD
FLDTP_e_{…} error code
Remarks Function fldtp_action_get_destroyf( ) returns a pointer to the destruction notification
function associated with the given action record.
See also “fldtp_action_set_destroyf”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_action_get_id( ) returns the identifier bound to the given action
record.
See also “fldtp_action_set_id”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_action_get_priority( ) returns a processing priority that has been
assigned to the given action record.
See also “fldtp_action_set_priority”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_action_set_args( ) binds user data to the given action record. This
allows the process function to have all salient information immediately available.
Consider the typedef FLDTP_FUNC_ACTION process functions must conform to:
typedef void (*FLDTP_FUNC_ACTION) (TAG*, VAL*, short, void**);
When processing tag values, the DTP calls the process function pointed to by afunc
with its tag, its value, and a pair of user-defined arguments. The short and void**
parameters, as shown in the above typedef, are the f_argc and f_argv set using
fldtp_action_set_args( ).
Arguments f_argc and f_argv define the user arguments to pass to the process
function. Function fldtp_action_set_args( ) makes a copy of void pointer array 7
f_argv when attaching it to the given action record. As such, the caller need not to
preserve the void pointer array afterwards.
Library
See also “fldtp_action_get_args”
“fldtp_action_set_destroyf”
“fldtp_insert”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_action_set_destroyf( ) attaches a destruction notification function to
the given action record. This function is called just prior to the action record being
destroyed. Action records are destroyed as a result of a DTP removal call or as part of
destroying the DTP it is attached to.
Consider the typedef FLDTP_FUNC_DESTROY process functions must conform to:
typedef void (*FLDTP_FUNC_DESTROY) (TAG*, short, void**);
The short and void** parameters, as shown in the above typedef, are the f_argc and
f_argv set using fldtp_action_set_args( ).
The main motivation for associating a destruction function with an action record is to
provide an easy mechanism to release memory referenced in the f_argv void array. If
the action record is the sole user of attached information, this destruction callback
allows the user to release it.
See also “fldtp_action_get_destroyf”
“fldtp_action_set_args”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_action_set_id( ) binds an identifier to the given action record.
Setting the ID provides a mechanism for differentiating one action record from
another, either by groups or by individuals. The most common use for this ID is the
removal of a group of action records from the DTP based on this ID.
The ID is a void* and, by default, ID comparisons are based on equality. This default
comparison can be superseded with a user provided function.
See also “fldtp_action_get_id”
“fldtp_remove_group”
“fldtp_set_comparef”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Library
FLDTP _ CHANGE _ READ
Syntax #include <fldtp.h>
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Analogous to fl_change_read( ), function fldtp_change_read( ) reads the value of
the next changed tag. The definition of next is set by the start_from parameter. Only a
single pass through the tags is made.
See also “fldtp_proc_wait”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_create( ) allocates, initializes, and returns a DTP handle. This DTP
handle is passed in all subsequent calls to the FLDTP API.
See also “fldtp_destroy”
FLDTP _ DESTROY
Syntax #include <fldtp.h>
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_destroy( ) releases the DTP handle along with all resources held by it.
This handle should not be referenced once it is destroyed.
See also “fldtp_create”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code 7
Remarks Function fldtp_get_comparef( ) returns the function used when comparing the IDs
Library
FLDTP _ GET _ MSGLEN
Syntax #include <fldtp.h>
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_get_msglen( ) returns the size for the buffer used to read the value of a
message tag from the real-time database.
See also “fldtp_get_msglen”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_get_tagcnt( ) returns the number of unique tags inserted into the given
DTP.
See also “fldtp_insert”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_insert( ) registers a tag with its action into the DTP. The dtp argument
specifies which DTP instance to insert into. The tag argument specifies the tag to be
processed. The afunc argument specifies the process function to use for processing
the given tag. The typedef FLDTP_FUNC_ACTION defines the Syntax the process
function must conform to:
typedef void (*FLDTP_FUNC_ACTION) (TAG*, VAL*, short, void**);
When processing tag values, the DTP calls the process function pointed to by afunc
with its tag, its value, and a pair of user-defined arguments. The short and void**
parameters, as shown in the above typedef, are an argc/argv combination analogous
to the arguments to the main routine of a C program.
It is legal to insert the same tag multiple times. In such a case, the process function
will be called for each insertion. In FactoryLink terminology, DTP supports using the
same tag to trigger several events.
See also “fldtp_action_set_args”
“fldtp_remove”
FLDTP _ PROC
Syntax #include <fldtp.h>
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code 7
Remarks Function fldtp_proc( ) immediately invokes all action records inserted into the given
Library
“fldtp_set_proc_by”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_proc_action( ) reads the tag and invokes the action function associated
with the given action record handle.
See also “fldtp_insert”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_proc_tag( ) reads the tag and processes all action records associated
with it. Priority-based processing is honored by this function.
See also “fldtp_proc_wait”
“fldtp_set_proc_by”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_proc_wait( ) invokes the action functions bound to those tags within
the changed DTP. Only a single pass through the tags is made. 7
If no changes are outstanding when calling this function, then it puts the task to sleep
until one of the tags within DTP tags changes. Upon awakening, any changed tags are
Library
functions.
See also “fldtp_proc_change”
“fldtp_set_proc_by”
FLDTP _ REMOVE
Syntax #include <fldtp.h>
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_remove( ) deletes the given action record from the DTP. If a
destruction function is associated with the action record, it is invoked during the
removal.
Removing the action record from the DTP destroys it. As such, the action record
handle should no longer be referenced after the fldtp_remove( ) call.
See also “fldtp_action_set_destroyf”
“fldtp_insert”
“fldtp_remove_group”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_remove_group( ) deletes a group of action records from the DTP
based on any combination of tag, action function pointer, and/or ID. Passing NULL
for parameter tag, afunc, or id excludes that parameter from being included in the
removal criteria.
For example, passing NULL for both tag and afunc means that all action records
whose ID matches parameter id will be removed. The parameters passed as NULL are
not considered as part of the removal criteria.
Whenever an action record is removed, its destruction handler, if set, is invoked.
See also “fldtp_action_set_id”
“fldtp_action_set_destroyf”
“fldtp_insert”
“fldtp_remove”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code 7
Remarks fldtp_set_comparef( ) establishes the function to use when comparing the IDs
Library
#define FLDTP_ID_SAME 0
#define FLDTP_ID_DIFF 1
The comparison function is used when removing action records based on a particular
ID. The user provided comparison function returns constant FLDTP_SAME_ID for
equivalent IDs or constant FLDTP_DIFF_ID for different ones.
The default comparison is a simple equality (void* a == void* b). Setting the
comparison function to NULL returns the DTP back to this default.
See also “fldtp_action_set_id”
“fldtp_remove_group”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_set_msglen( ) establishes a new size for the buffer used to read the
value of a message tag from the real-time database. The default size is 80 characters.
See also “fldtp_get_msglen”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks fldtp_set_proc_by( ) determines the order by which simultaneous tag changes are
processed. The selection of process order profoundly affects the operation of the DTP.
The following discusses the behavior of both.
Processing by first-in-first-out, or FLDTP_BY_FIFO( ), is analogous to how most
FactoryLink tasks currently operate. The order of processing mirrors the order unique
tag entries are inserted into the DTP. This manner of processing is optimal since the
value of a single tag is stored in memory at any one time. It is also the default mode of
processing unless the DTP is explicitly set otherwise.
Processing by priority, or FLDTP_BY_PRIO( ), invokes change handlers based on an
ascending order of priorities. Priority-based processing begins by taking a snapshot of
all changed tags with their values. Then, the process functions for the changed tags
are invoked in order of their assigned priority. As a result, the overhead of tag
processing increases in terms of reaction time and memory use.
Unless your task has specific requirements that one action always be processed prior
to another, use FLDTP_BY_FIFO( ).
See also “fldtp_action_set_priority”
FLDTP _ WAIT
Syntax #include <fldtp.h>
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code 7
Remarks fldtp_proc_wait( ) is analogous to fl_wait( ) in that the task goes to sleep until one of
Library
See also “fldtp_proc_change”
Returns FLNTAG_E_GOOD
FLNTAG_E_HANDLE
FLNTAG_E_INVARG
FLNTAG_E_DIMNUM
FLNTAG_E_DIMSIZ
Remarks Given a normalized tag reference, its RTDB location and its dimension definition,
function flntag_calc_base( ) calculates the RTDB location for the base of the given
ntag. For nonarrayed objects, the location of a tag reference always equals the base
tag location obtained from the object definition.
This function is commonly called during the loading of a task CT. CTs often contain
the reference string, the RTDB location for the reference string, and the dimension
definition for the object being referenced. This function uses these three pieces of
information to obtain the base location for reference.
See also “flntag_create”
“flntag_find_def”
Returns FLNTAG_E_GOOD
FLNTAG_E_HANDLE
FLNTAG_E_INVARG
FLNTAG_E_DIMNUM
FLNTAG_E_DIMSIZ
Remarks Given a normalized tag reference, its base RTDB location, and its dimension
definition, function flntag_calc_tag( ) calculates the RTDB location for the given
ntag. For nonarrayed objects, the location of a tag reference always equals the base
tag location obtained from the object definition.
Code Sample: Converting a FLNTAG to a TAG
#include <flntag.h>
/*
* given reference.
*/
FLOBJREC def
int rv;
{ 7
rv = flntag_calc_tag(ntag,
flobjrec_get_dimen(&def),
Library
tag);
return rv;
FLNTAG _ CREATE
Normalized Tag API.
Syntax #include <flntag.h>
FLNTAG* flntag_create(void);
Type Description
Remarks Function flntag_destroy( ) releases all resources associated with the given handle.
This handle should not be referenced after being destroyed.
See also “flntag_create”
Returns FLNTAG_E_GOOD
FLNTAG_E_GENERAL
FLNTAG_E_HANDLE
FLNTAG_E_INVARG
Remarks Function flntag_find_def( ) returns the definition for the object referenced by the
given ntag. This definition is obtained by searching the application object CT.
Parameter objct, a required argument for this function, is obtained via function
ct_open_obj( ).
See also “flntag_create”
“flntag_parse_ref”
“ct_open_obj”
Library
Arguments FLNTAG* ntag in FLNTAG to obtain object for.
CT* objct in Object CT handle.
Returns FLNTAG_E_GOOD
FLNTAG_E_GENERAL
FLNTAG_E_HANDLE
FLNTAG_E_INVARG
FLNTAG_E_DIMNUM
FLNTAG_E_DIMSIZ
Remarks Function flntag_find_tag( ) returns the RTDB location (the tag) for the object
referenced by the given ntag. This location is obtained by searching the application
object CT for the object definition, obtaining the base RTDB location from that
definition, and finally, calculating the offset from the base if the tag is an arrayed
element.
For example, if the ntag equates to reference x[3], function flntag_find_tag( ) returns
RTDB location for x[3], not x[0].
Parameter objct, a required argument for this function, is obtained via function
ct_open_obj( ).
See Also: “flntag_create”
“flntag_calc_tag”
“flntag_parse_ref”
“ct_open_obj”
Returns RTN>0
FLNTAG_E_HANDLE
FLNTAG_E_INVARG
Remarks Function flntag_gen_str( ) generates the reference string to which the given ntag
equates. When nonzero, parameter incl, a bit mask, includes one or more components
from the resulting string.
Normally, the entire reference is desired and the macro flntag_gen_ref( ) can be used
to build it.
Macro flntag_gen_objname( ) can be used for cases where the object name is
needed.
See also “flntag_create”
“flntag_parse_ref”
Library
Syntax #include <flntag.h>
Returns >=0
FLNTAG_E_HANDLE
FLNTAG_E_INVARG
FLNTAG_E_REFSYN
Remarks Functions flntag_parse_brkt4dims( ) and flntag_parse_comma4dims( ) parses the
given dimension string and returns the number of dimensions contained within it.
These functions can also return the value of the each individual dimension as a u16
array.
Function flntag_parse_brkt4dims( ) expects dimension strings such as [2][4].
Function flntag_parse_comma4dims( ) expects dimension strings such as 2,4.
See also “flntag_parse_ref”
Library
Arguments FLNTAG* ntag in/out FLNTAG to load according to given
reference.
Return FLNTAG_E_GOOD
FLNTAG_E_HANDLE
FLNTAG_E_INVARG
FLNTAG_E_REFSYN
Remarks Function flntag_parse_ref( ) parses the given object reference string and loads its
components into the given normalized tag handle. Each component is validated to
ensure it has a legal syntax.
The previous contents of the given ntag are overwritten by this operation.
See also “flntag_create”
“flntag_gen_ref”
Returns FLNTAG_E_GOOD
FLNTAG_E_HANDLE
FLNTAG_E_INVARG
FLNTAG_E_REFSYN
Remarks Normalized tags consist of four components: node, name, dimension, and member.
This set of flntag_set_…( ) functions allows an individual component of the
FLNTAG to be modified.
Valid syntax is enforced by these functions. The enforced rules include the following
Type Description
flntag_set_node Allowed characters are _@$ and alphanumeric.
flntag_set_name First character cannot be numeric.
flntag_set_member
flntag_set_dimen String containing dimensions delineated by brackets: [4]
[5].
“flntag_create”
“flntag_gen_str” 7
“flntag_get_dimen”
Library
“flntag_get_node”
Returns VALUE
Remarks This set of flobjrec_get_…( ) functions allows the caller to obtain an attribute value
from an object definition.
Value Meaning
0 No persistence of value.
1 Timed-based persistence.
2 Exception-based persistence.
Function flobjrec_get_tag( ) returns the base RTDB location. For arrayed objects,
this is the RTDB location for the object that has all dimensions equal to zero.
Currently these entry points are implemented as macros, which, in some cases, return
a pointer to the private members of the FLOBJREC structure. These addresses must
be treated in a read-only manner.
See also “ct_find_obj”
“ct_open_obj”
Returns No values
Remarks The name of the file to be added to the directory may contain a relative path. 7
To maintain backward compatibility with previous releases, make_full_path( ) has
Library
{
NPATH *p1;
NPATH *p2;
p1 = fl_path_alloc( );
p2 = fl_path_alloc( );
if ( dirp == NULL )
fl_path_cwd(p1);
else
fl_path_set_dir(p1, dirp);
fl_path_norm(p2, filep);
fl_path_add(p1, p2);
fl_path_sys(p1, pathp, MAX_PATH);
fl_path_free(p1);
fl_path_free(p2);
Library
Do not specify both the L and D flags in the same job request. Any other combination
is permitted. The order of characters in the flags string is immaterial.
Returns A signed integer (an int) that indicates the status of the job request. A value of zero
indicates the request has been accepted and queued by the SPOOL task. Any non-zero
value indicates some sort of error has occurred.
If the return value is negative, it was not received by the SPOOL task.
If the return value is positive, it was received by SPOOL but could not be processed.
Specifically, the return values have the following meanings
•
•
•
•
Application Objects API
Reference Library 8
In application objects, the AOObjectServer (IAOServer) is the only object that publishes
events. If these are required, it will be necessary to early bind to the object. The above example
would be rewritten as:
AOObjectServer
(IAOServer)
AObjects AObject
(IAOObjects) (IAOObject)
AOOPCItems IAOOPCItem
(IAOOPCItems) (IAOOPCItem)
Legend
Class Objects
Instance Objects
Both
Returned by
AOObjectServer
Application Objects
Flink7Defns Interface: IAOServer
Public: Yes
Creatable: Yes
Properties
SilentMode A Boolean property which dictates whether the server displays error messages or
raises errors. This property has not yet been implemented.
Type: Boolean
Access: Read/Write
ParentHWnd A long that is the parent hwnd of the window which is controlling application objects.
This property is used to control the dialogs that Application displays.
Type: Long
Access: Read/Write
TagEdit A property of type EnumFL6TagExistOptions. The value of this property determines
what happens when a config object wants to create a tag, and the tag to be created
already exists, but with different properties. For example, if tagA is to be created as an
Analog and it already exists as a Float.
By default, when an object is created, the value is FL6TagAbortIfDiff. This causes a
prompt to appear allowing the user to choose to keep the tag (FL6TagKeepExisting)
or to modify the tag (FL6TagModifyExisting). This choice can be applied to all
objects if desired. The property is reset to FL6TagAbortIfDiff when the
ApplicationObject finishes, unless the user explicitly set it.
Type: Enumeration EnumFL6TagExistOptions
FL6TagAbortIfDiff = 0
FL6TagKeepExisting = 1
FL6TagModifyExisting = 2
Access: Read/Write
Methods
Create Creates an application object, AOObject, initializes its properties, and returns it to the
user. Note that this does not actually save the object to the database. See the Update
method for information on how to save an application object.
Parameters:
Application Objects
Once the replication properties are set on the object,
the ReplicationString property will return the
packed string.
PresentationString A packed string representing how the template
variable is presented to the user. The packed string
is obtained by creating a FlinkCDBObjects.c
TemplatePresentation object (Interface
ItemplatePresentation). Once the presentation
properties are set on the object, the
PresentationString property will return the packed
string.
Type: String
Access: In
Description Description of the template variable.
Type: String
Access: In
Application Objects
Type: String
Access: In
ContainerID ID of the container application object. This object
must exist. Currently, only objects of type
AOApplicationObject(2) can act as containers.
Type: String
Access: In
ParentID ID of the application object that will be the parent of
the new object. This object must exist. When adding
objects to the root level of the application object,
this ID will be the same as the container ID.
Type: String
Access: In
ParentMember (Optional) A qualifier used to differentiate between
multiple objects of the same type. By default, the
member parameter is an empty string. If two
instances of the same object inside of an application
object exist, the member value of “” refers to the
first object and “2” refers to the second object.
Type: String
Access: In
ChildID ID of the application object being added to the
container. This object must exist.
Type: String
Access: In
ChildMember (Optional) A qualifier used to differentiate between
multiple objects of the same type. By default, the
member parameter is an empty string. If two
instances of the same object inside of an application
object exist, the member value of “” refers to the
first object and “2” refers to the second object.
Type: String
Access: In
Return Value: None
TVarUsed Returns a boolean specifying whether the variable is used by any Application.
Parameters: 8
CreateIObject Creates application objects instances in the target Flapp. If successful, the instance ID
of the top most object created is returned. 8
Parameters:
ParentPath (Optional) The table that acts as the top most parent
record. This is used for the parent record of Config
Objects. The notation of a path is
FlappDir/Task/Domain/Table1!FieldInfo/
Table2!FieldInfo Note that forward slashes must be
used for the path and back slashes must be used in
the Flapp Directory.
Type: String
Access: In
RefreshIObject Refreshes all configuration by reading the data sources again and updating all objects.
Note that prompt template variables are not prompted; they must be changed through 8
the ModifyIObject method.
Application Objects
Flapp The FactoryLink Application Directory that contains
the instance object to be refreshed.
Type: String
Access: In
Most events processing is done by the event servers, FlinkcdbEvents and AppObjectEvents.
The AOObjectServer provides VB events relating to instantiation progress. It is necessary to
early bind to the AOObjectServer object, not IAOServer, to use these events.
BeginFeedBack Event notifying the user that an action is about to occur.
Parameters:
ProvideFeedBack Event notifying the user that an action has occurred and feedback can be given to the
user.
Parameters:
ProvideDetails Event notifying the user that an action has occurred and feedback can be given to the
user. This event provides more detail than providefeedback
Parameters:
EndFeedBack Event notifying the user that the action has finished
IO BJECTS
8
IObjects is a collection-based object that contains IObject object types.
Public: Yes
Creatable: Yes
Properties
Methods
IO BJECT
8
IObject is an object, which represents a group of instantiated application objects. Each IObject
Application Objects
Flink7Defns Interface: IAOIObject
Public: Yes
Creatable: Yes
Properties
Methods
I NSTANCES
8
Instances is a collection-based object that contains the instance type objects.
Public: Yes
Creatable: Yes
Properties
Methods
I NSTANCE
8
Instance is an object that represents a single instance of an application objects.
Application Objects
Public: Yes
Creatable: Yes
Properties
Methods
DisplayName Returns a string, which is the instance key and, optionally, the instance description.
This method is obsolete.
Parameters:
AOTVAR I NSTANCES
8
AOTVarInstances is a collection-based object that contains AOTVarInstance object types.
Public: Yes
Creatable: Yes
Properties
Methods
AOTVAR I NSTANCE
8
An AOTVarInstance is an object that represents a template variable that was used in an
Application Objects
Flink7Defns Interface: IAOTVarInstance
Public: Yes
Creatable: Yes
Properties
Public: Yes
Creatable: Yes
Properties
Methods
Creatable: Yes
Properties
VariableData Sets the variable’s data source. This property maps is passed directly into the
Source replication object and is provided so the user does not have to access the replication 8
object directly.
Application Objects
TVKeyboard (0)
tvgenerated (1)
tvTextFile (2)
tvExcel = (3)
tvODBC = (4)
Access: Read/Write
Properties This is a collection based object of type AOProperties. It holds named value pairs that
map into the Replication object and presentation object. The names of the properties
it holds depend upon the VariableDataSource and VariablePromptPresentation values.
When the Variable Data Source and VariablePromptPresentation is set, the object is
filled with the pertinent properties from the two objects necessary to describe the
variable. These can be modified and are saved when the Update Method is invoked.
This object was provided to so that the user does not have to access the Replication
object and presentation object directly
Type: AOProperties
Access: Read/Write
VariablePrompt Sets the variable’s presentation style. This property maps is passed directly into the
Presentation presentation object and is provided so the user does not have to access the
presentation object directly.
Type: Enumeration EnumAOPresentationStyles
AOPTextBox (0)
AOPComboBox (1)
AOPListBox (2)
AOPCheckBox (3)
AOPRadio (4)
Access: Read/Write
Flapp The FactoryLink Application Directory.
Type: String
Access: Read/Write
ValidName Checks a name for validity and returns true if it is a valid name. This does not check
to see if the variable name already exists.
Parameters:
AOP ROPERTIES
8
AOProperties is a collection-based object that contains AOProperty object types.
Public: Yes
Creatable: Yes
Properties
Methods
AOP ROPERTY
8
An AOProperty is an object that represents a general named-value pair. The name property is
Application Objects
Flink7Defns Interface: IAOProperty
Public: Yes
Creatable: Yes
Properties
Public: Yes
Creatable: No
Properties
Methods
Creatable: No
Properties
ItemProperty Description of the configuration field that resulted in this OPC item. In FactoryLink,
Description this is the description of the field in the AC file.
Type: String
Access: Read/Write
ItemProperty Name of the configuration field that resulted in this OPC item. In FactoryLink, this is
Name the name of the field in the AC file.
Type: String
Access: Read/Write
ItemName OPC item name. In FactoryLink, this is the tag name.
Type: String
Access: Read/Write
ItemType OPC item type. Only items of type FlinkTag(0) are valid.
Type: OPCItemType
Access: Read/Write
MiscProperties A collection-based object of type AOProperties. It holds named value pairs. Currently
this property is not used.
Type: AOProperties
Access: Read/Write
ItemDefinition Template variable, if any, that resulted in this OPC item.
Type: String
Access: Read/Write
AOO BJECTS
8
AOObjects is a collection-based object that contains AOObject object types.
Public: Yes
Creatable: Yes
Properties
Methods
Public: Yes
Creatable: Yes
Properties
the call. Sub objects will continue to use their DefaultInstances property when they
are created. This must be a string that can be converted to a long integer, a template 8
variable or a ?.
Application Objects
Access: Read/Write
Properties This is a collection-based object of type AOProperties. It holds named value pairs.
The names of the properties it holds depend upon the object type. When the object is
first created, usually with the Create method on the AOObjectServer Object, the
properties collection is filled with properties pertinent to that type of object. These
can be modified and are saved when the Update Method on the AOObjectServer
Object is invoked. Currently, the following properties are supported
Object Type
AOFlinkRecord (0):
ParentTableFields Field values that each parent table needs to have set.
It is in the form table=‘Value’, table=‘Value’. For
example, al_group=‘GRPNAM’, al_info=‘NUM’.
The field values can be template variables.
Type: String
Access: In/Out
RecordTablePath Path of the table to be written to. It is in the form
task/Domain/table/table… For example,
al_def/SHARED/al_group/al_info/al_rel
Type: String
Access: In/Out
AOFlinkFile (1):
8
DuplicateRecordFields Fields to examine for matching values to determine
Application Objects
Field1,Field2. For example, ATag, AID
Type: String
Access: In/Out
FileRecordPath Path of the file to create. It is in the form:
task/Domain/table!$FILENAME= filename.ext, for
example:
IMLP/SHARED/IMLTAGS!$FILENAME=
dplogsim.prg. This can property can have template
variables in it.
Type: String
Access: In/Out
FileExistsAction What to do when the file exists. The choices are to
replace the file or to leave it alone. If the
FileObjectCreation property is AOFOCSameFile
(0), this value must be AOFileReplace (1)
Type: Enumeration AOFileExistsAction
AOFileLeave (0)
AOFileReplace (1)
Access: In/Out
FileObjectCreation Where to place each file object instance. Valid
choices are in the same file, or in separate files.
Type: Enumeration AOFileObjCreation
AOFOCSameFile (0)
AOFOCSeparateFiles (1)
Access: In/Out
FileHeaderText Text to place at the beginning of each file. If each
instance is in separate files, this text is written into
each file. If each instance is in the same file, this text
is written once at the beginning. This can property
can have template variables in it.
Type: String
Access: In/Out
AOApplicationObject (2):
Currently, objects of type AOApplicationObject do not have custom properties filled
into their properties collection.
InstanceBase Base name of the group of instances. This property can take a template variable. If the
Name GroupBaseName exists, the instance numbers will be assigned, starting at the end of
the last instance, otherwise, the instance numbers will be assigned starting at 1.
Type: String
Access: Read/Write
Instance Description of the instance. This property can take template variables.
Description
Type: String
Access: Read/Write
InstanceKey Key of the instance. If this property is specified, it must be a template variable that
resolves to a unique key for the object.
Type: String
Access: Read/Write
InstanceDisable This field is obsolete.
FlagField
Type: String
Access: Read/Write
GroupDescription Description of the base group. This property can take template variables.
Type: String
Access: Read/Write
ClassClosedIcon (Optional) Specifies a custom closed icon for an application object class in the
FlinkTree. The icon must already exist in the tree or the custom icon must have been 8
added to the tree 16x16 icons directory. When adding an icon or bitmap to the
Application Objects
current editors do not have the ability to specify icons. Note that the update method
must be called on the AOObjectServer or on the AOObject to save the icon. This
property may have template variables in it.
Type: String
Access: Read/Write
ClassOpenedIcon (Optional) Specifies a custom opened icon for an application object class in the
FlinkTree. See ClassClosed Icon Property.
Type: String
Access: Read/Write
InstanceClosed (Optional) Specifies a custom closed icon for an application object group of instances
Icon in the FlinkTree. See ClassClosed Icon Property.
Type: String
Access: Read/Write
InstanceOpened (Optional) Specifies a custom opened icon for an application object group of
Icon instances in the FlinkTree. See ClassClosed Icon Property.
Type: String
Access: Read/Write
ParameterString Reserved for future use.
Type: String
Access: Read/Write
HTMLProperty (Optional) Specifies a user-defined Web Page to use to display properties. The page
Page should exist in the {Flapp}\AppObj directory.
Type: String
Access: Read/Write
DisableVariable An template variable (including the { }) that application objects check to see if it
matches the DisableValue to determine whether to disable the object or not.
Type: String
Access: Read/Write
Methods
8
FindVariable Retrieves a template variable, based upon its name. The name is not case-sensitive.
AOIO BJ D ATA
8
The AOIObjData object is a special object available for instances of the configuration of file
Application Objects
Flink7Defns Interface: IAOIObjData
Public: Yes
Creatable: Yes
Properties
•
•
•
•
•
331
•
•
•
•
•
•
•
•
Configuration PAK
Architecture
O VERVIEW
The Configuration PAK (CFGPAK) is a collection of software libraries, C-language source
modules, and related documentation used to design and construct programs that directly
manipulate the configuration databases of a FactoryLink application.
Users generally configure tasks, or more specifically configuration databases, using the
Configuration Explorer. Configuration Explorer provides an interactive, graphical interface to
view, add, modify, and/or delete task information within a particular application. As the user
alters this task configuration, Configuration Explorer maintains the application integrity by 9
validating new records, creating undefined tags, and recording the location of tag references.
Configuration PAK
Programs created with CFGPAK are able to automate many of the operations found in
Configuration Explorer, saving users from manually importing and exporting configuration
Architecture
using Configuration Explorer. For example, a programmable logic controller (PLC) software
package could scan the active PLC addresses and enter corresponding read/write records into
that driver’s configuration databases.
This part assumes the reader is proficient at PAK task creation; therefore, it does not cover
material found in Part I.
Installation
To install the Configuration Databases Programmer’s Access Kit, consult your operating
system’s installation guide regarding the installation of option media.
The order of these topics parallels the order of the client task usage of these resources. The
layered CFGPAK architecture enforces this ordering.
Configuration Storage
FactoryLink applications consist of a heterogeneous set of configuration databases, drawing
files, and Math & Logic scripts. CFGPAK groups these storage entities into three types:
• Reserved configuration databases (CDBs)
• Task CDBs
• External configuration
CFGPAK provides access to the application’s reserved and task CDBs. Reserved CDBs are
those the system maintains internally and are indirectly altered by the user. FactoryLink
development tools, such as the Configuration Explorer, manage these tables behind the scenes.
The system tables are DOMAIN, OBJECT, TYPE, and XREF. Internal constraints apply to
these tables and the CFGPAK prevents invalid alterations of them.
domain Holds the configured SHARED and USER domains for the
application.
object Holds the object or tag definitions.
type Holds the type for the RTDB segments within the kernel.
Task CDBs are the physical storage for the configuration entered into the panels of
Configuration Explorer. The information contained therein directs the task to its run-time
duties. The CDB itself is a relational database table. It consists of one or more records (or
rows), each comprised of several fixed-length fields.
Tasks are often configured by more than one CDB, and these CDBs are usually related in a
manner similar to SQL’s (Structured Query Language) definition of a primary key. A primary
key is a combination of one or more fields whose values form a unique identifier for each
record in the table. Given this primary key, a record from one table can be related to one or
more records in a secondary table. By including the primary key in records of a related table,
an association forms between the related table and the table owning the primary key. This is
known as a one-to-many relationship, and these types of relationships are a prevalent theme
throughout task CDB configuration.
Note: The one exception to this is the tag modification routines, where
Configuration PAK
the renaming of a RTDB object or tag propagates to all affected drawings
Architecture
and logic scripts.
Configuration Sessions
Altering an application requires referencing both system as well as application files. As such, a
configuration session is an attachment to a given FactoryLink system (FLINK) and a given
FactoryLink application (FLAPP). From the FLINK, the CFGPAK obtains the definitions for
the configurable tasks declared in the various attribute catalogs (AC), key files, and include
files. From the FLAPP, the CFGPAK attaches to the actual CDBs that contain the
configuration data.
The main focus of CFGPAK users is to alter task CDBs. However, session-level overhead must
be processed prior to manipulating task configuration. Namely, the caller needs to navigate
through the available configurable options to locate the task(s) of interest. The session
facilitates this.
When establishing a configuration session, the session first determines what tasks are available
for configuration. Since the Attribute Catalog (AC) defines the structure of a task CDB, the
presence of an AC file within the session’s FLINK of an AC ultimately determines whether a
task can be configured. However, the presence alone does not determine whether the session
will see an AC.
When establishing a configuration session, the session determines AC availability via file:
{FLINK}/ac/ac2ct.map. Among other purposes, this map cross-references a CDB to the AC
A TITLES file is a text file containing a list of AC files. The TITLES file that Configuration
Explorer uses is located at {FLINK}/ac/titles. All AC files listed in the TITLES file must exist
in the {FLINK}/ac directory. If an AC file does not exist, the title’s entry is ignored, because
Configuration Explorer assumes the absent AC file is for an option that has not been
purchased.
In the preceding figure, the TITLES file references AC file sys.ac, which in turn references the
configuration CDB named SYS. While this may seem fairly straight forward, it is a common
failure point where CFGPAK fails to locate its target CDB definition.
Configuration PAK
flCfgFld Configuration database data field handle.
Architecture
flCfgSess
flfCfgAC flfCfgAC
flCfgCDB flCfgCDB
flCfgCDB flCfgCDB
flCfgSel flCfgFld
•
•
•
•
Configuration PAK Library
Services
This chapter describes the general purpose and usage for the services found within CFGPAK.
Detailed information regarding these functions can be found in the API reference library. This
chapter gives an overview of the following:
• Configuration Session API (flCfgSess)
• Attributes Catalog API (flCfgAC)
• Configuration Database API (flCfgCDB, flCfgSel, flCfgFld)
• Object Database API (flCfgObj, flCfgTag)
• Exception Handling 10
To illustrate the usage of each service, a thread of constructing a configuration utility for the
Services
system.
A configuration session provides the environment applications are modified through. Function
flCfgSess_open( ) requires two inputs to open a session: the FactoryLink system directory
{FLINK} and the application directory {FLAPP}. Upon successfully accessing system files in
the given {FLINK} and {FLAPP}, flCfgSess_open( ) returns a session handle.
Similar to Configuration Explorer, the application must exist in order to open a session.
Opening a session will not create an application.
Once a session is open, the next step towards accessing a configuration database is to locate its
schema definition. Since attribute catalogs (ACs) contain these definitions, the AC associated
with the target task needs to be located. To locate a particular AC, use functions
flCfgSess_num_ac( ) and flCfgSess_nth_ac( ) to iterate through all ACs known to the
session.
After the program completes accessing an application configuration, it should close its session.
Closing the session flushes all disk buffers, closes all open databases files, and releases the
memory attached to the session.
Services
/* Close the session and exit */
flCfgSess_close(&sess);
return 0;
}
The program seeks out a particular AC after opening a session. In the case of the Skeleton task,
the program searches through the ACs known to the session for the one associated with task
SKEL.
If the search for an AC fails, there are two likely causes. One is the AC file is not listed in the
text file: {FLINK}\ac\titles. If not, append an entry for the AC file to the TITLES file. The other
failure point is an entry for the AC file is missing from file: {FLINK}\ac\ac2ct.map. If so, type
and execute “acctmgr -c -d” at the system command prompt. This utility rebuilds the
AC-to-CT mapping for all AC files referenced within the various FactoryLink TITLES files.
Services
flCfgAC_nth_hdrcdb Gets/loads an Attribute Catalog.
Attribute Catalogs contain descriptions (or schemas) of one or more configuration databases
(CDB) utilized by a particular task. As such, the AC structure also serves as a header to the
individual table definitions. Information about the AC file is available via access functions
flCfgAC_get_filename( ), flCfgAC_get_task( ), and flCfgAC_get_title( ).
The preceding AC defines one header CDB named skeltrig. It is related to another CDB named
skeltags via the field TABLE_NAME. In other words, for every row within CDB skeltrig,
there will be zero or more rows in CDB skeltags with that same value in its TABLE_NAME
field.
Note: Be aware that this is not the complete story since a row’s domain
is also part of the relation. However, this topic is better left till when
discussing the flCfgCDB( ) API.
....
. Open session “sess” and locate the SKEL AC
10
....
Services
{
printf("Error(%d): unable to open SKELETON tables\n", rv);
flCfgSess_close(&sess);
return 1;
}
....
. Process the CDB
....
flCfgAC_close_cdbs(cfgacp);
....
. Continue processing
....
Up to this point, most of the work has been navigating through the application to locate the
configuration databases (CDB) to be accessed. Next comes manipulation of the CDB schemas
and contents via the CDB API. At the top level are access functions to get the CDB name and
title. Beyond that, things get more involved.
Services
flCfgCDB_num_selfld Gets CDB number of select fields.
We provide name-based search functions for component types where multiple fields may
apply.
Given a field handle, information about the field, such as name, title, or size, can be retrieved.
The handle is also used for setting field values when reading and writing CDB records. The
functions that manipulate the four components of a CDB are as follows:
Most CDBs associate their records with a domain. If a domain field is present, it is always
considered part of the selection criteria (see section “Reading Configuration from a CDB”).
Selection fields exist for CDBs whose records depend on the values of another table (API
refers to these as relate CDBs). There may be many select fields, as many as required to
uniquely bind the CDBs records to an individual record in the header table.
10
Sequence Field API
Services
flCfgSeq_get_name Gets sequence field name.
flCfgSeq_get_size Gets sequence field size.
Sequence fields maintain the order of row entry. Maintaining this order allows Configuration
Explorer to show CDB contents in a consistent manner, as opposed to potentially showing a
different ordering of rows between editing sessions. Almost all tables have a sequence field.
All CDBs have data fields. Data fields hold the task configuration information, as opposed to
the other fields that mainly serve to organize and/or sort the data.
To illustrate, consider the following function that prints the schema for a given handle to a
CDB to stdout. This example shows how to go through the fields that make up a table as well
as how to obtain the properties of each field.
Services
flCfgSeq_get_name(cfgseqp),
flCfgSeq_get_size(cfgseqp));
}
for (m = 0; m < flCfgCDB_num_fld(cfgcdbp); m++)
{
flCfgCDB_nth_fld(cfgcdbp, m, &cfgfldp);
for (n = 0; n < indent; n++)
printf("\t");
printf("Field: %s(%d) - %s\n",
flCfgFld_get_name(cfgfldp),
flCfgFld_get_size(cfgfldp),
flCfgFld_get_title(cfgfldp));
}
}
flCfgCDB_ select_criteria Reads header’s select values into the relate CDB.
At its simplest usage, reading data is a four-step sequence involving four functions:
2. A call to function flCfgCDB_select_first( ) takes the selection criteria and positions the
record pointer on the first row that matches that criteria.
3. Function flCfgCDB_select_next( ) is called as many times as needed to visit all rows that
match the selection criteria.
4. Finally, a call to flCfgCDB_select_end( ) releases all locks and resources held on behalf of
the selection.
Given the above, an overview of how selection criteria works within Configuration Explorer
and the CFGPAK is needed. All CDBs have a primary index (it is the first INDEX listed within
an AC CT definition). This index equates to the selection criteria. For header CDBs, the most
common index expression is “DOMAIN+SEQ”. Ignoring sequence number (SEQ) for now,
selections against header CDBs are for all rows within a particular domain.
To illustrate, consider the following function dump_cdb_contents( ) that prints the contents of
a table to stdout, and all tables related to it, for a particular domain.
Services
<step 2b> rv = flCfgCDB_select_first(cfgcdbp);
}
while (rv == FLCFG_E_GOOD)
{
....
. Print out current record (use flCfgFld_get_value() for each field).
....
for (m = 0; m < flCfgCDB_num_relatecdb(cfgcdbp); m++)
{
flCfgCDB_nth_relatecdb(cfgcdbp, m, &relcdbp);
dump_cdb_contents(relcdbp, NULL, indent+1);
}
<step 3> rv = flCfgCDB_select_next(cfgcdbp);
}
<step 4> flCfgCDB_select_end(cfgcdbp);
}
2 Once the selection has begun, adjust the selection criteria for the given domain and then
position on the first record matching this criteria.
illustrates accessing data in another CDB that relates to the current row of the CDB being
processed. In the example, the related CDBs are iterated through, and for each, the dump
function is called recursively. What is not obvious here is that the selection criteria is being
implicitly defined for these related CDBs. When the selection for a related CDB is begun, the
select field values are set equal to the field values found in the header CDB. This is why NULL
is being passed as the domain value. When dumping related CDBs, use the domain value of the
header row.
Writing to a CDB almost equates to reversing the function call order of the selection (reading)
process. Prior to invoking the insert, the values associated with the field handles must be set to
the values to be inserted. These values are referenced by the writer functions such as function
flCfgCDB_row_insert( ) when it inserts a row.
When a row is inserted, the values specified for the data fields are validated. The validation
performed is equivalent to the validation performed by Configuration Explorer. As with
Configuration Explorer, any tags referenced by the newly inserted row will have a
corresponding entry made in the cross-reference databases.
The sequence field has a unique property when a row is being inserted. Since the sequence
number exists to sort records according to their entry order, the field itself is generally hidden
from the user. As such, its value is automatically generated by Configuration Explorer. In
keeping with this theme, the insert routine will automatically assign the next appropriate
sequence value to the given row when the sequence value is set to zero. Unless your program
has a need to sort records in a particular order, use this auto-assignment mechanism as it will
prevent the inappropriate assignment of the same sequence number to two records.
Services
flCfgFld *tblfldp;
flCfgFld *trigfldp;
flCfgValErr valerr;
int rv;
/* Locate the needed table components */
if ((flCfgCDB_get_seqfld(skelp, &seqfldp) != FLCFG_E_GOOD)
|| (flCfgCDB_find_fld(skelp,"TABLE_NAME",&tblfldp) != FLCFG_E_GOOD)
|| (flCfgCDB_find_fld(skelp, "TRIGGER", &trigfldp) != FLCFG_E_GOOD)
|| (flCfgCDB_get_domfld(skelp, &domfldp) != FLCFG_E_GOOD))
{
return RV_ERROR;
}
flCfgDom_set_value(domfldp, dom);
flCfgSeq_set_value(seqfldp, 0); /* 0 means to autoset the seq # */
flCfgFld_set_value(tblfldp, tbl);
flCfgFld_set_value(trigfldp, trig);
rv = flCfgCDB_row_insert(skelp, &valerr);
When inserting into a relate CDB, the values for the select fields must be set as well. While
this can be explicitly done by calling flCfgSel_set_value( ), it is best to use the values within
the relations. This guarantees records will not be inserted in relate CDBs that have no owning
row in the header CDB.
For example, if tag A_SEC is inserted into table SKELTAGS with an association to skeltrig
table TBL_A and no entry for table TBL_A exists in the skeltrig CDB, the inserted row will be
an orphan.
Function flCfgCDB_select_criteria( ) loads the domain and relate values for the currently
selection record of its header CDB(s) into the given CDB handle. In the following code
sample, the row insertion into CDB SKELTAG has its domain and table name fields set the
value of the row currently selected in the SKELTRIG CDB. As such, the row is guaranteed not
to be an orphan.
Services
flCfgFld_set_value(fldp, tag);
rv = flCfgCDB_row_insert(skeltagp, &valerr);
switch (rv)
{
case FLCFG_E_GOOD:
rv = RV_GOOD;
break;
case FLCFG_E_VALERR:
printf("Validation Error: %s(%s = %s): %s\n",
flCfgValErr_get_ctname(&valerr),
flCfgValErr_get_fldname(&valerr),
flCfgValErr_get_fldvalue(&valerr),
flCfgValErr_get_valmsg(&valerr));
rv = RV_ERROR;
break;
default:
Row updates and selections are closely coupled operations. In order for a row to be updated, it
must first be selected. In other words, once the target row is selected, a call to function
flCfgCDB_select_update( ) modifies that row with the given values set within the CDB
handle. Of note here is an update may affect more the currently selected row. If one or more
fields of the update are related upon by another CDB, the update propagates to these relate
CDBs. This propagation preserves the relation between the updated row and those rows related
upon it.
In all cases, the affected cross-reference database entries are updated accordingly (additions,
deletions, and/or modifications).
Consider the following code sample. Once the record for the given domain and table name has
been selected, the new values are set within the skeltrig CDB handle and the update function
invoked. If only the trigger field value is different, then the update stops at modifying the
selected row. However, if the table name field value is different, all records in the related
skeltags CDB are also updated with the new table name.
For example, if the table name is switched from T1 to T2, then all rows in the skeltags CDB
whose table name value is T1 becomes T2.
int rv;
/* Locate the needed table components */
if ((flCfgCDB_find_fld(skelp, "TABLE_NAME", &tblfldp) !=
FLCFG_E_GOOD)
|| (flCfgCDB_find_fld(skelp, "TRIGGER", &trigfldp) != FLCFG_E_GOOD)
|| (flCfgCDB_get_domfld(skelp, &domfldp) != FLCFG_E_GOOD))
{
return RV_ERROR;
}
....
. Select the record that matches the given domain and table name (params ‘dom’+‘tbl’)
....
/* If the requested table exists, update it. */ 10
if (found)
Services
flCfgFld_set_value(tblfldp, newtbl);
flCfgFld_set_value(trigfldp, newtrig);
rv = flCfgCDB_select_update(skelp, &valerr);
switch (rv)
{
case FLCFG_E_GOOD:
rv = RV_GOOD;
break;
case FLCFG_E_VALERR:
printf("Validation Error: %s(fld=%s; val=%s): %s\n",
flCfgValErr_get_ctname(&valerr),
flCfgValErr_get_fldname(&valerr),
flCfgValErr_get_fldvalue(&valerr),
flCfgValErr_get_valmsg(&valerr));
rv = RV_ERROR;
break;
As with row updates, row deletion and selection are coupled operations. For a row to be
deleted, it must first be selected. Function flCfgCDB_select_delete( ) removes both the
currently selected row and all rows in the relate CDBs tied to that row. Also, any tags
referenced within the deleted row(s) have their corresponding cross-reference database entries
removed.
Be aware that deleting a row positions the active selection onto the next row that meets the
selection criteria. As such, function flCfgCDB_select_current( ) is called to iterate through a
selection after a delete as opposed to the standard call to function flCfgCDB_select_next( ).
Consider the following code sample. It begins by selecting all tables associated with a given
domain. Once the selection has begun, it iterates through all the records, searching for the
given table name. Upon finding the target record, the procedure deletes the record and
proceeds onto the next record by calling function flCfgCDB_select_current( ) because the
delete call has already positioned it onto the next record.
Services
tblsize = flCfgFld_get_size(tblfldp)+1;
if ((tblval = (char*) malloc(tblsize)) == NULL)
return RV_ERROR;
found = 0;
while (rv == FLCFG_E_GOOD)
{
flCfgFld_get_value(tblfldp, tblval, tblsize);
if (strcmp(tblval, tbl) == 0)
{
flCfgCDB_select_end(skelp);
free(tblval);
return RV_GOOD;
}
For the general case, the CFGPAK automatically handles the multi-user considerations that
arise when manipulating the application’s CDBs. However, cases exist where the locking and
releasing of one or more CDBs need to be explicitly managed by the CFGPAK program. To
illustrate, consider the following code sample.
Services
flCfgCDB_rowno(cfgcdbp, &rowno);
flCfgCDB_select_end(cfgcdbp);
....
. Process <Block A> - Other processes may access CDB ‘cfgcdbp’.
....
if ((rv = flCfgCDB_select_begin(cfgcdbp)) == FLCFG_E_GOOD)
rv = flCfgCDB_select_rowno(cfgcdbp, rowno);
flCfgCDB_select_end(cfgcdbp);
flCfgCDB_unlock(cfgcdbp, 0);
In the preceding sequence, CDB locking prevents the row number from being invalidated by
the operations of another process. If the lock was not held over the life of both selections,
another process could be deleting and adding rows to the CDB during the time spent in <Block
A>.
1. The CFGPAK program begins executing the code sample and remembers row number 5.
The CFGPAK program then enters the time-consuming operation represented as <Block
A>.
2. Another user starts Configuration Explorer, selects the same CDB, and deletes the row tied
to number 5. The user then adds a new row, which Configuration Explorer assigns number
5 since it is now available.
3. The CFGPAK program returns from <Block A> and selects row 5.
The above sequence represents a failure, since the row selected by the CFGPAK program is not
the row it should be accessing. That row had been deleted and replaced by Configuration
Explorer.
Therefore, locking prevents other processes from changing the state of CDB your CFGPAK
program is operating on. However, be aware no other processes can access the CDB as long as
the lock is held; therefore, the lock should be held as long as required to protect the entire
transaction but released immediately upon completion.
Services
flCfgObj_select_update Updates currently selected tag definition.
One of the application’s reserved configuration databases, the object database, holds all the tag
definitions. The Object CDB API, which is essentially just another CDB, inherits most of its
entry points from the standard CDB API.
However, the Object CDB is a reserved table. As such, it is best the code does not assume
anything about the name or contents of the fields found within this table since these could
change in the future. Also, numerous, system integrity rules apply to the manipulation of
records found therein. In other words, keep with the flCfgObj API when accessing the object
database as opposed to using the lower-level CDB functions.
The object CDB handle is a standard CDB handle. Any functions used to interrogate the
schema definitions, as described in the CDB API chapter, are applicable.
The transfer of definitions to and from the Object CDB API is conducted via a tag definition
data structure. As such, functions have been provided to create, manipulate, and destroy this
structure.
Tag definitions consist of many attributes, such as the tag name, its domain and its dimensions.
The get and set functions provide access to all of these attributes. Instead of providing a
separate access function for each function, each attribute is assigned an ID, which the caller
passes into the get and set functions. The requested attribute value is then returned as a string
(or a string is passed in when setting an attribute value).
Attribute ID Description
Services
FLCFGTAG_ATTR_PERWHEN Tag persistence storage frequency
In either case, subsequent calls to flCfgObj_select_next( ) steps the caller through all
remaining tag definitions. Once the selection is complete, a call to function
flCfgObj_select_end( ) closes the operation.
rv = flCfgObj_select_first(objp, tagp);
while (rv == FLCFG_E_GOOD)
{
flCfgTag_get_attrvalp(tagp, FLCFGTAG_ATTR_NAME, &tagname);
printf("\t%s\n", tagname);
rv = flCfgObj_select_next(objp, tagp);
}
flCfgTag_destroy(&tagp);
flCfgObj_select_end(objp);
}
Writing to the object CDB equates to adding, modifying, or deleting a tag definition.
Function flCfgObj_add( ) creates a new tag according to the tag definition structure passed into
it. Validation of all aspects of the proposed definition is conducted prior to its actual insertion.
Specifics regarding any validation errors are returned via the flCfgValErr structure.
and
2. the member tag’s proposed definition has the same dimensions and domain as the
structured tag.
Services
flCfgTag_set_attrval(tagp, FLCFGTAG_ATTR_TYPE, type);
....
. Subsequently destroy flCfgTag and flCfgValErr structures and continue work.
....
To illustrate the costs of changing an object’s core attributes, consider the effects of changing
an object’s name. Changing an object’s name is expensive since every reference to that object
must be physically updated. For example, if the reference to the object is within a task’s CDB,
the row in the task CDB must be modified. Furthermore, if that object is referenced by a Math
& Logic script (also known as a PRG), all references in the script must be located, altered and
validated. This case raises ambiguous situations, such as what if the new object name conflicts
with the script’s local variable. Drawing files are another problem area For example, if a
template was used to form the object reference, a decision to either reject the new name or drop
the template association needs to be made.
The point is that changing an object’s core attributes is prone to being rejected for a wide
variety of reasons. Furthermore the operation may generate warnings that require the user to
decide whether to commit or rollback the change, such as whether to change the tag name even
though a Math & Logic script does not validate. To communicate errors and warnings between
the internals of the flCfgObj_select_update( ) function and the invoking CFGPAK program, a
series of OK-CANCEL boxes are requested via the message box callback (for more
information, see function flCfg_set_msgbox_handler( )). The responses to these dialogs
control what action the update takes.
Note: Member tag names cannot be a source or target name string for a
tag rename. For example, y cannot be renamed to x.raw, nor can x.raw be
renamed to y.
Services
break;
case FLCFG_E_VALERR:
printf("Validation Error: %s(fld=%s; val=%s): %s\n",
flCfgValErr_get_ctname(valerr),
flCfgValErr_get_fldname(valerr),
flCfgValErr_get_fldvalue(valerr),
flCfgValErr_get_valmsg(valerr));
rv = RV_ERROR;
break;
default:
printf("Rename error: %d\n", rv);
rv = RV_ERROR;
break;
}
}
else
Structured tags further constrain the behavior of this function. If the tag being deleted is
structured with one or more member, there must not be any references to the member tags, or
the deletion will be rejected (if tag x is structured with a member tag x.raw, then a reference to
tag x.raw prevents tag x from being deleted). Similarly, if no references exist to the structured
tag or its members, then the removal of the structured tag deletes the member tags.
Services
FLCFG_E_GOOD -0 No error occurred.
When internal errors and warnings are encountered, additional, textual messages may be
written to stdout. These strings provide more detailed information regarding the failure than
can be provided by an error code.
However, it is likely that sending output to stdout is inappropriate for the application utilizing
CFGPAK. For example, a GUI program may re-direct these outputs to a message box. To that
end, function flCfg_set_msgbox_handler( ) allows a callback function to be installed directs
all message to the given function pointer.
Furthermore, for more exotic activities, input from the user is necessary to direct the lower
level CFGPAK functions how to proceed. 10
Code Sample: Prototype for the Message Box Callback
Services
Once a callback handler is set, all error message are passed to it. The arguments consist of a
title string, a message string, and a box type request. Message box type requests are:
The callback function should return the ID of the button pressed. The button IDs are:
If no message box callback is set, the default CFGPAK message box handler writes the title
and message to stdout, and then returns FLCFG_MBID_OK for OK message boxes or
FLCFG_MBID_CANCEL for OK-CANCEL message boxes.
When inserting or updating a row, the values contained therein may not be legal. Legality is
determined either by restrictions specified in the CDB definition within the AC file or by an
external validation routine. Should the prospective value of a field fail to validate, the insert or
update call returns an error. When a validation failure occurs, the validation error structure
passed into the insert function is filled with details about the nature of the violation. This
information includes the violated field name, the offending value, and a message stating what
is wrong with the value.
For example, if a field is designated as a NUMBER type with a valid range of 0 to 100, an
attempt to insert a row with the value of 256 will be rejected. In this case, the function returns
code FLCFG_E_VALERR, and the validation error structure contains specifics about the
failure.
•
•
•
•
Configuration Database
ActiveX Component
The FactoryLink CFGPAK ActiveX control (OCX) exposes the functions of the FactoryLink
CFGPAK C library as methods and events accessible to OLE containers that support scripting,
such as Microsoft's Visual Basic.
To install and register the CFGPAK component and its DLLs, run the installation executable
located at {FLINK}\flcfgocx\flcfgocx.exe. The target directory for the installation should be
the FactoryLink directory itself.
Library Services
functionality of the OCX method and its associated C function is equivalent.
The mapping of C-function name to OCX method name is as follows:
flCfgAC_close_cdbs AcCloseCdbs
flCfgAC_get_filename AcGetFilename
flCfgAC_get_task AcGetTask
flCfgAC_get_title AcGetTitle
flCfgAC_nth_hdrcdb AcNthHdrcdb
flCfgAC_num_hdrcdb AcNumHdrcdb
flCfgAC_open_cdbs AcOpenCdbs
flCfgCDB_find_fld CdbFindFld
flCfgCDB_find_selfld CdbFindSelfld
flCfgCDB_get_domfld CdbGetDomfld
flCfgCDB_get_name CdbGetName
flCfgCDB_get_seqfld CdbGetSeqfld
flCfgCDB_get_title CdbGetTitle
flCfgCDB_lock CdbLock
flCfgCDB_nth_fld CdbNthFld
flCfgCDB_nth_relatecdb CdbNthRelatecdb
flCfgCDB_nth_selfld CdbNthSelfld
flCfgCDB_num_fld CdbNumFld
flCfgCDB_num_relatecdb CdbNumRelateCdb
flCfgCDB_num_selfld CdbNumSelfld
flCfgCDB_row_insert CdbRowInsert
flCfgCDB_row_validate CdbRowValidate
flCfgCDB_rowno CdbRowno
flCfgCDB_select_begin CdbSelectBegin
flCfgCDB_select_criteria CdbSelectCriteria
flCfgCDB_select_current CdbSelectCurrent
flCfgCDB_select_delete CdbSelectDelete
flCfgCDB_select_end CdbSelectEnd
flCfgCDB_select_first CdbSelectFirst
flCfgCDB_select_last CdbSelectLast
flCfgCDB_select_next CdbSelectNext
flCfgCDB_select_previous CdbSelectPrevious
flCfgCDB_select_rowno CdbSelectRowno
flCfgCDB_select_update CdbSelectUpdate
flCfgCDB_unlock CdbUnlock
flCfgDom_get_name DomGetName
flCfgDom_get_size DomGetSize
flCfgDom_get_value DomGetValue
flCfgDom_set_value DomSetValue
11
flCfgFld_get_name FldGetName
Library Services
flCfgFld_get_size FldGetSize
flCfgFld_get_title FldGetTitle
flCfgFld_get_value FldGetValue
flCfgFld_set_value FldSetValue
flCfgObj_add ObjAdd
flCfgObj_get_cdb ObjGetCdb
flCfgObj_select_begin ObjSelectBegin
flCfgObj_select_current ObjSelectCurrent
flCfgObj_select_delete ObjSelectDelete
flCfgObj_select_end ObjSelectEnd
Another difference is the return of string values. For example, consider retrieving the value of
a configuration database field. With the C library function flCfgFld_get_value(), the
application passed a target character buffer that was to be filled in by the CFGPAK function.
The related OCX method FldGetValue() returns a string instead.
The handling of constants differs between the OCX and the C library. Since there is no header
file for a control in which to define constants such as how #define FLCFG_E_GOOD is
defined in C header file flcfg.h, OCX method GetDefineValue() is added to the control. It takes
the definition's name as a parameter and returns its numeric value. The returned value can then
be used by the OCX application just as the #define could be used in the C program.
One last difference between the OCX and the C library is the message box callback for errors
and warnings. The OCX exposes event MessageBox that the user overrides instead of invoking
a callback function.
Other than noted above, the CFGPAK control works like the C library, so the function
descriptions for the C library also apply to the OCX methods.
•
•
•
•
Configuration PAK API
Reference Library
This chapter provides the following information about each API function:
• Syntax: Valid format for this function
• Arguments: List containing the following information about each argument:
1. Type
2. Name
Reference Library
representation of the integer value returned by the function, such as ERROR or GOOD.
The function should return the ID of the button pressed. The button IDs are:
In general, the type of message box requested is the OK box; therefore, the function
should return the ID of the OK button. The one exception is the use of the message
box during a tag definition modification where the OK-CANCEL functionality is
requested. The OK-CANCEL functionality allows the user to make the choice as to
how the activity is to proceed for cases where a trade-off is involved. For an example
of this case, please see the description for function “flCfgObj_select_previous”.
If no handler is installed, then the error messages are routed to standard output.
See Also “flCfgObj_select_previous”
Reference Library
Config PAK API
F L C FG AC_ GET _ FILENAME
FL C FG AC_ GET _ TASK
FL C FG AC_ GET _ TITLE
Attribute Catalog API.
Syntax #include <flcfg.h>
char* flCfgAC_get_filename(flCfgAC *cfgacp);
char* flCfgAC_get_task(flCfgAC *cfgacp);
char* flCfgAC_get_title(flCfgAC *cfgacp);
Reference Library
flag indicates whether the function should create the databases if they do not already
Remarks Function flCfgCDB_get_domfld( ) returns the handle to the domain field structure for
the given CDB. The value of the domain field determines the domain to which a
given row belongs.
Most CDBs have a domain field. Error code FLCFG_E_NOTFOUND is returned for
those that do not.
See Also “flCfgCDB_nth_selfld”
“flCfgCDB_nth_fld”
“flCfgCDB_get_seqfld”
Reference Library
Config PAK API
Returns Success: (char*) to CDB name.
Failure: NULL.
Remarks Function flCfgCDB_get_name( ) returns the table name for the given CDB.
See Also “flCfgCDB_get_title”
FL C FG CDB_ LOCK
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgCDB_lock(flCfgCDB *cfgcdbp, int incl_relcdbs);
Remarks Function flCfgCDB_lock( ) locks the entire CDB contents, preventing other processes
from reading or writing its contents. Locks are useful when performing complex
transactions that require others to be blocked until the operation is complete. Since
complex operations often involve the CDBs related to the given CDB, the
incl_relcdbs parameter allows the entire CDB tree to be locked with a single function
call.
Calls to function flCfgCDB_lock( ) can be nested, but care must be taken to ensure the
same number of unlock calls are made for each lock call.
See Also “flCfgCDB_unlock”
Reference Library
Config PAK API
int n in Index identifier for a particular field.
FlCfgFld** v out Handle to the requested field.
Reference Library
Config PAK API
Function flCfgCDB_num_relatecdb( ) returns the number of CDBs whose contents
are primarily dependent upon the given CDB.
Function flCfgCDB_num_selfld( ) returns the number of selection fields defined
within the given CDB.
See Also “flCfgCDB_nth_fld”
“flCfgCDB_nth_relatecdb”
“flCfgCDB_nth_selfld”
FL C FG CDB_ ROWNO
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgCDB_rowno(flCfgCDB *cfgcdbp, long *rowno);
Reference Library
“flCfgCDB_lock”
Reference Library
memory.
Once the record is read, the field values for the current record are available via
functions flCfgDom_get_value( ), flCfgSel_get_value( ), and flCfgFld_get_value( ).
Once a selection against the given CDB begins, it is legal to reset the selection back to
the first record by invoking this function without intermediate calls to the selection
begin/end functions.
See Also “flCfgCDB_select_begin”
“flCfgCDB_select_next”
“flCfgCDB_select_end”
“flCfgDom_get_value”
“flCfgSel_get_value”
“flCfgFld_get_value”
FL C FG C BD _ SELECT _ LAST
Object Database API 12
Syntax #include <flcfg.h>
Reference Library
int flCfgCDB_select_last(flCfgDB *Cfgcdbp);
Reference Library
“flCfgCDB_select_last”
FL C FG CDB_ UNLOCK
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgCDB_unlock(flCfgCDB *cfgcdbp, int incl_relcdbs);
Reference Library
FL C FG D OM _ GET _ NAME
FL C FG D OM _ GET _ VALUE
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgDom_get_value(flCfgDom *cfgdomp, char *domval, int maxlen);
FL C FG D OM _ SET _ VALUE
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgDom_set_value(flCfgDom *cfgdomp, char *domval);
Reference Library
a call to flCfgCDB_select_criteria( ) normally precedes the call to function
FL C FG F LD _ GET _ NAME
Configuration Database API.
Syntax #include <flcfg.h>
char* flCfgFld_get_name(flCfgFld *cfgfldp);
FL C FG F LD _ GET _ TITLE
Configuration Database API.
Syntax #include <flcfg.h>
char* flCfgFld_get_title(flCfgFld *cfgfldp);
FL C FG F LD _ GET _ VALUE
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgFld_get_value(flCfgFld *cfgfldp, char *value, int maxlen);
Reference Library
Config PAK API
“flCfgFld_get_name”
“flCfgFld_get_size”
FL C FG F LD _ SET _ VALUE
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgFld_set_value(flCfgFld *cfgfldp, char *value);
FL C FG O BJ _ GET _ CDB
Object Database API.
Syntax #include <flcfg.h>
int flCfgObj_get_cdb(flCfgSess *sess, flCfgCDB **objp);
FL C FG O BJ _ SELECT _ BEGIN
Object Database API.
Syntax #include <flcfg.h>
int flCfgObj_select_begin(flCfgObj *objp);
Reference Library
“flCfgObj_select_end”
FL C FG O BJ _ SELECT _ CURRENT
Object Database API.
Syntax #include <flcfg.h>
int flCfgObj_select_current(flCfgCDB *objp, flCfgTag *tagp);
FL C FG O BJ _ SELECT _ DELETE
Object Database API.
Syntax #include <flcfg.h>
int flCfgObj_select_delete(flCfgObj *objp);
FL C FG O BJ _ SELECT _ END
Object Database API.
Syntax #include <flcfg.h>
int flCfgObj_select_end(flCfgCDB *objp);
Reference Library
Config PAK API
FL C FG O BJ _ SELECT _ FIRST
Object Database API.
Syntax #include <flcfg.h>
int flCfgObj_select_first(flCfgObj *objp, flCfgTag *tagp);
FL C FG O BJ _ SELECT _ NAME
Object Database API.
Syntax #include <flcfg.h>
The definition for the tag that alphabetically falls immediately after where the
requested tag would reside is read if no such tag exists. In this case, the selection
returns error code FLCFG_E_NOTFOUND. Error code FLCFG_E_ENDOFSEL is
returned if no such tag exists.
See Also “flCfgObj_select_begin”
“flCfgObj_select_next”
“flCfgObj_select_end”
“flCfgTag_get_attrval”
FL C FG O BJ _ SELECT _ NEXT
Object Database API.
Syntax #include <flcfg.h>
Reference Library
Config PAK API
flCfgTag* tagp out First tag definition.
FL C FG O BJ _ SELECT _ UPDATE
Object Database API.
Syntax #include <flcfg.h>
int flCfgObj_select_update(flCfgObj *objp,
flCfgTag *tagp,flCfgValErr *valerr);
Reference Library
Config PAK API
Syntax #include <flcfg.h>
char* flCfgSel_get_name(flCfgSel *cfgselp);
FL C FG S EL _ GET _ TITLE
Configuration Database API.
Syntax #include <flcfg.h>
char* flCfgSel_get_title(flCfgSel *cfgselp);
FL C FG S EL _ GET _ VALUE
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgSel_get_value(flCfgSel *cfgselp, char *value, int maxlen);
Reference Library
Config PAK API
“flCfgSel_get_name”
“flCfgSel_get_size”
FL C FG S EL _ SET _ VALUE
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgSel_set_value(flCfgSel *cfgselp, char *value);
FL C FG S EQ _ GET _ NAME
Configuration Database API.
Syntax #include <flcfg.h>
char* flCfgSeq_get_name(flCfgSeq *cfgseqp);
FL C FG S EQ _ GET _ SIZE
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgSeq_get_size(flCfgSeq *cfgseqp);
FL C FG S EQ _ GET _ VALUE
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgSeq_get_value(flCfgSeq *cfgseqp, long *value);
Reference Library
Config PAK API
FL C FG S EQ _ SET _ VALUE
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgSeq_set_value(flCfgSeq *cfgseqp, long value);
Arguments flCfgSess** sess in/out Address of session handle. Set to NULL upon
session closure.
FL C FG S ESS _ NTH _ AC
Configuration Session API.
Syntax #include <flcfg.h>
int flCfgSess_nth_ac(flCfgSess *sess, int n, flCfgAC **cfgacp);
FL C FG S ESS _ NUM _ AC
Configuration Session API.
Syntax #include <flcfg.h>
int flCfgSess_num_ac(flCfgSess *sess);
Reference Library
your PAK task), it is likely the TITLES file, ASCII file {FLINK}/ac/titles, is missing
Reference Library
FL C FG TAG _ DESTROY
flCfgTag_get_attrval( ):
flCfgTag_get_attrvalp( ):
Reference Library
Config PAK API
“flCfgObj_select_previous”
“flCfgTag_clear_attrvals”
“flCfgTag_get_attrval”
FL C FG VAL E RR _ CREATE
FL C FG VAL E RR _ DESTROY
Validation Error API.
Syntax #include <flcfg.h>
int flCfgValErr_create(flCfgValErr **valerrp);
int flCfgValErr_destroy(flCfgValErr **valerrp);
•
•
•
•
•
•
•
•
•
•
•
•
•
427
•
•
•
•
1. Read what RAPD does and about MCI Chapter 13, “RAPD
Architecture, including compiling with the MCI Principle”
library.
•
•
•
•
RAPD Principle
O VERVIEW
The FactoryLink Rapid Application Protocol Drive technology is the basis for the RAPD
Programmer’s Access Kit (RAPD PAK). This technology affords FactoryLink software
developers and application designers an alternative to the existing External Device Interface
(EDI) method. The new technology allows a reduction in driver software and applications
development.
The RAPD PAK is based on the Intertask Mail Exchange (MCI) library. The MCI library
defines a method for FactoryLink tasks to communicate via mailbox tags.
Compliant with FactoryLink open architecture, client tasks created with the RAPD PAK are
fully integrated into FactoryLink development and run-time systems.
I NSTALLATION
The following files are on your system after installing the software components:
• {FLINK}\SRC\RAPD\MCI_PAK\INC\MCI3.H
• {FLINK}\SRC\RAPD\MCI_PAK\INC\FORMAT3.H
• {FLINK}\SRC\RAPD\MCI_PAK\LIB\MCI3.LIB
{FLINK} designates which FLINK environment setting or directory the FactoryLink system
software has been installed in. 13
The current version of MCI PAK is 3.0.
You must also have the FactoryLink Programmer’s Access Kit installed. Your driver will not RAPD Principle
compile or link properly without FactoryLink PAK.
All data is based on dataset definitions. These datasets define contiguous regions of data within
an external device. The IOX task and a protocol driver task pass datasets through their
respective mailbox tags. Data is directly packaged and unpackaged within a dataset.
MCI specifications and APIs define the method for processing datasets.
The following figure illustrates the RAPD principle with the IOX task and protocol driver
communicating via FactoryLink mailboxes.
Aside from storage duties, the IOX task provides for data conversions (analog to float, IEEE
conversions) for I/O data to/from a protocol driver.
For example, if your host machine uses an INTEL processor or compatible processor, data is
stored in LOW/HIGH format. You should then specify -DHOST_LOW_2_HIGH in the CFLAGS
directive or use a #define HOST_LOW_2_HIGH in your header file.
At run time, the MCI library makes the appropriate data conversions when using the data
format functions. Failure to define the correct data direction at compile time results in incorrect
data placement.
13
RAPD Principle
•
•
•
•
MCI Messaging
This chapter discusses how the IOX task and a RAPD driver task communicate using the MCI
APIs by detailing the messaging scheme. Topics include:
• Mailbox Communications
• Datasets
• I/O Functionality
• Exception Write Function
• Data Directions
• MCI and LANS
A RAPD protocol driver and the IOX task communicate via FactoryLink mailboxes using the
MCI interface library. This process includes:
1 The IOX task translates I/O data bidirectionally to a protocol driver in the form of MCI
messages.
2 The protocol driver translates these requests into protocol messages to an external device.
3 Then, based on the results from the external device, the protocol driver responds via an MCI
message to the IOX task.
The method of creating, setting and extracting the message parameters are facilitated through
the various MCI function calls.
14
IMX Messaging
}MBXMSG;
Every task using mailbox communication under FactoryLink uses the MBXMSG structure and
assigns its own meaning to the user definable members.
The sub-sections that follow describe the members of the MBXMSG structure.
mm_msg
The mm_msg parameter of the MBXMSG structure stores a data header in front of the data to
send (I/O data). The length of this header is 8 bytes. This means the programmer must always
reserve the first 8 bytes of the message buffer for a header area.
Therefore, the mm_msg data member is a structure that includes a data header of structure
type MCIHDR followed immediately by some I/O data. The size should be at least 8 bytes plus
the size of the I/O data to pass.
CDE Means code extension and specifies the operation code that should be taken
upon the data. An MCI data header always specifies the operation on the
data that must be taken. The following CDE identifiers are a sample of the
possible operational codes:
CDE_B0_15 Bit operation bit 0 - 15
CDE_B16_3 Bit operation bit 16- 31
CDE_NIBBLE Nibble operation
CDE_BYTE Signed byte operation
CDE_UBYTE Unsigned byte operation
CDE_SIGNED Signed word operation
CDE_UNSIGNED Unsigned word operation
These codes are used primarily for exception write cases (except CDE_BLOCK). In an
exception write example, a CDE_UNSIGNED code could be used to specify a write of a single
unsigned word. The receiving task (driver) would then generate a command according to the
specific protocol to write the single word. 14
The code CDE_BLOCK is used for block operations.
IMX Messaging
For example, if the mm_type data member of the MBXMSG structure indicates an
MCI_READ_REQ(and the CDE is CDE_BLOCK, the driver performs a block read operation.
Refer to “I/O Functionality” on page 447 for details about CDE codes.
The CDE operation codes are used in case of an exception write (normal or encoded) to specify
which action the write must take. CDE codes are built up with a base CDE code and an
additional bit number to specify the exact operation.
For example, the following code must be specified if an operation must be performed on the
left byte of a variable of type u16:
CDE_UBYTE + 8 (bits) = 0x0508
mm_type
The definition of the mm_type member of the MBXMSG data structure is as follows:
typedef struct _MCITYPE {
unsigned type: 4; /* type of MCI message */
}MCITYPE;
The type parameter specifies what kind of MCI message is being sent or received. The
following types are available:
mm_user1
The layout of the mm_user1 parameter for the MCIMSG structure is defined as follows:
u16 mm_user1 ----> job sequence number
This data member holds a job sequence number used to keep track of messages from one task
to another. A programmer is not obligated to make use of this data member.
mm_user2
The layout of the mm_user2 parameter for the MBXMSG structure is defined as follows:
u32 mm_user2 ----> dataset control tag
This data member holds the dataset control tag used to identify a block of data being
exchanged between two MCI tasks. This parameter must always be specified whenever
sending an MCI message.
D ATASETS
The previous section describes the data structure of the mailbox message. This section
discusses the dataset information that goes into the mailbox message.
The concept of a dataset is key to understanding how a RAPD driver interacts with the IOX
task. The following subsection discusses datasets from the perspective of an application. Refer
to “I/O Functionality” on page 447 for details about the use of datasets as they pertain to
specific MCI messages.
Dataset Definition
A dataset for an application is defined as a contiguous area of storage location within an
external device. These locations are sometimes referred to as memory locations, registers,
addresses, files, or regions. The exact terminology is dependent on the type of device. The
protocol driver uses a dataset definition as the key to either read or write data from/to an
external device.
Transactions between the IOX task and a driver are based on passing dataset information back
and forth between the tasks. If the IOX task has a request for a protocol driver to act on a
WRITE operation, it defines some dataset parameters in a message to the driver. The driver
receives the message and, according to the dataset information received, carries out the
directive.
The following graphic displays an example of a dataset definition within a driver’s Dataset
Definition panel (the driver used in this example is called Widget).
The following IOX Dataset Definition panel shows a reference to the same dataset defined in
the driver Dataset Definition panel. The data collected on the dataset is stored in the tag
defined in the Data Tag field.
In this case, it is a tag array that stores 20 consecutive elements starting with the element at
address 1. Therefore, if a READ request occurs on the dataset analog_ds[0], 20
consecutive elements, residing in the external device, starting at address 1 are stored in
widget_analogs[0] (element at address 1, element at address 2, element at address 3 …
element at address 20).
For purposes of this illustration, the elements being collected on this dataset are all analog type
data (16 bits wide). They are stored in analog tags when read. The data comes from the same
analog tags when written to the external device.
There are other fields in the same IOX panel, but they are explained in detail in the I/O
Translator information on the documentation CD.
2. The driver detects an MCI event on the dataset and the mail message is received.
• A protocol message is built on the dataset parameters defined in the message by the IOX
task.
• The driver sends the message to the external device.
• The device sends a response back to the driver.
• The driver packages a response message to the IOX task, which may or may not include
data received from the device, by setting some parameters on the dataset and mails a
message to the IOX task.
14
IMX Messaging
1
mail message containing I/O Translator
dataset information the driver
must know to operate on 3
data returned in
mail message
from the driver
dataset translated into FactoryLink
protocol messages Workstation
Protocol Driver
exchange of
protocol messages
2
I/O F UNCTIONALITY
You implement the following common functions for external device drivers with the MCI
interface library:
• Block read function
• Block write function
• Exception write function
• Encoded write function
• Unsolicited receive function
Every task that implements MCI functionality has an MCI mailbox. Different MCI tasks that
communicate with each other write MCI messages into each other’s MCI mailboxes.
For example, both the IOX task and the protocol driver have their own MCI mailbox tag. If the
IOX task wants to address a command to the protocol driver, it writes a message in the protocol
driver mailbox.
The following sections discuss the common functions supported by the MCI library. The
examples give you an idea of how the messages are constructed so they can be decoded and a
driver can respond to them.
Before discussing the various request functions, note that the IOX task performs a query of all
datasets from protocol drivers at startup. The query function Mci_Ds_Query( ) (used only by
IOX tasks) is automatically answered by the MCI library event check routine in a driver.
The original dataset definitions must be retrieved at startup because this IOX task completely
defines the dataset parameters in an MCI message to a driver. Since tasks can span a network,
this information eases the burden on a driver from having to constantly retrieve a dataset’s
original definition.
14
The Block Read Function
A block read means the IOX task generates a request for the protocol driver to read a complete
dataset (first element to last element) defined in the protocol driver.
IMX Messaging
The layout of the MBXMSG structure for a block read request is as follows:
Block Read Request
mm_msg.m_ptr = pointer to message buffer containing only an MCI data header
mm_msg.m_max = not applicable
mm_msg.m_len = length of the size of MCI data header
mm_mbx = IOX mailbox (reply mailbox)
The layout of the data header structure for a block read request is displayed as follows (the
header is the part of the message buffer pointed to by mm_msg.m_ptr in the preceding
figure):
Data Header for a Block Read Request
version: = 3
handling: = not applicable
bnd_dir: = MCI_HIGH_2_LOW
bit_dir: = MCI_HIGH_2_LOW
bnd_start: = 0
bit_start: = 1
boundary: = MCI_WORD_BND
len; = 80
start; = 10
cde; = CDE_BLOCK
After the block read request is sent to the driver, the driver creates a protocol message based on
the header data and then responds to the IOX task with data collected from the device. The
response looks similar to the following:
Block Read Response MBXMSG Structure
mm_msg.m_ptr = pointer to a message buffer (contains an MCI data header + data)
mm_msg.m_max = not applicable
mm_msg.m_len = length of received data including the MCI data h
mm_mbx = not applicable
mm_type.type = MCI_READ_RSP
mm_type.ident = MCI_TAG
Data Retrieved
data
.
.
.
14
.
.
data IMX Messaging
data
The IOX task reads this message from its own mailbox and analyzes the received data. The
length of the received data is located in the mm_msg.m_len member of the MBXMSG
structure. This member contains the total number of characters received, including the data
header.
In this example, the block read was successful. If the protocol driver encounters an error while
gathering the data, it sends an error to the IOX task. The function Mci_Send_Error( ) can be
When both the IOX task and a driver exist on the same machine, a block read request is
expedited through a direct trigger of the targeted dataset with no mail exchanged.
Over a LAN, the IOX task sends a mail message containing a block read request. For a driver,
the MCI library hides the method the request is delivered in. In either case, the block read
request is handled by the driver in a common manner.
bnd_start: = 0
bit_start: = 0
boundary: = MCI_WORD_BND
len; = 80
start; = 10
cde; = CDE_BLOCK
The driver extracts the information from the header area as well as the accompanying tag data
to create a protocol message to send to the device.
The response from the driver to the block write request from the IOX task is in the following
form:
Block Write Response MBXMSG Structure
mm_msg.m_ptr = pointer to a message buffer (contains only an MCIHDR structure)
mm_msg.m_max = not applicable
mm_msg.m_len = length of the MCI data header
14
mm_mbx = not applicable
mm_type.type = MCI_WRITE_RSP
mm_type.ident = MCI_TAG IMX Messaging
mm_type.more = not applicable
mm_type.org_host_dir = originating host direction
mm_type.station_id = remote station id
mm_user1 = Job sequence number
mm_user2 = dataset control tag
mm_sendid = IOX FactoryLink Task ID
The exception write MCI message differs from the block write message in that the operation
code CDE specifies what kind of write should be performed. The length of the data is not
specified because an exception write always implies only one element is to be sent. The CDE
code implies the data size of the element itself. In the preceding example, a byte of data is
written to a word area.
Sometimes writing out the data cannot be accomplished in one operation. In the case of writing
a data element that is a byte (8 bits) to an area in a device that has a word boundary (16 bits), it
may take two operations. The device protocol may not support direct byte operations, so the
solution is:
• Read the word area
• Patch in the byte value
• Write out the word to the device
After the driver has carried out the write operation, it responds to the IOX task in the same
manner as in a response to a block write. You can test for an exception write request to see if it
can be transformed into a normal block write. Being able to transform an exception write
(read-before-write) to a block write reduces message traffic. This is determined by a call to
Mci_ Ds_Evaluate_Write( ). The results of this function determine if the exception write can
be converted into a block write.
The encoded exception write function is the same as the exception write function but differs in
that it does not directly write to the element in the external device. The definition of the MCI
message is exactly the same as described with the exception write function except the
following member differs:
handling: = MCI_ENCODED_WRITE
The encoded write (also called coded) causes the driver to perform a block write. The block
write is to an area in the device (PLC) that causes the device to perform an internal logic
procedure to make a direct change of a desired data item. This function has been introduced
because the exception write can be very slow for operations on data smaller than the boundary
of the dataset. In the method for normal exception writes described previously, the element to
manipulate must be read first, patched, and then written back. This is time consuming and
results in an increase in message transactions.
The encoded write request is used if the C option is chosen in the IOX task under the
Exception Write column. How one implements the encoded write feature in a driver depends
on the protocol. The driver receives a message that would normally be sent as an exception
write except the CDE code is different. The driver must extract the information and then create
a block write message based on the extracted data.
With the encoded write, it is not necessary to first read and then write back the exception
element. The operation on the element is written only once. The performance of exception
write requests can be optimized using this method. For this function, the driver must be able to
address a block of registers.
The information taken from the exception write request from the IOX task is written into the
block of registers. When the block is sent out to the external device, the external device ladder
logic performs the required operation based on data contained in the block write.
After the protocol driver has performed the exception write, it generates an MCI response
message and sends it back to the IOX task. This is accomplished in the same manner as the
block write function. An Mci_Write_Error( ) can be set in an Mci_Send_Error( ) function call
in case an error occurs.
Unsolicited Data
data
.
.
.
.
.
data
data
The IOX task receives this message, identifies the data with the dataset control tag, and
processes the data.
If the protocol driver encounters an error while receiving unsolicited data, it sends an
Mci_Rcv_Error( ) code in an Mci_Send_Error ( ) function to the IOX task. The IOX task
displays the error on the run manager screen.
D ATA D IRECTIONS
A very important issue with external devices and host machines is the direction of data.
Problems occur whenever the direction of data of the host machine (where the driver is
running) differs from the data direction of the external device.
For example, the data direction on the host can be from high to low and the external device
direction from low to high. If a word (2 bytes) is being read from the device, the bytes of this
word must be swapped. When a long data type is being read, then the bytes of this long data
type must be reversed in order to get a readable value. The following figure illustrates this
principle.
I/O Translator Data Directions
In MCIPAK, a group of defined data direction dependent functions are used to retrieve
elements of variable size from a dataset. The following example shows how to use some of
these functions: 14
#define HOST_HIGH_2_LOW
char buffer[ 256];
IMX Messaging
void *data = buffer;
if( Mci_Get_Bnd_Dir( &ds) == MCI_HIGH_2_LOW)
analog = Mci_Get_Word_H2L( data); /* device stores data in high to low format
and the host machine uses high/low also no conversion is done*/
else
analog = Mci_Get_Word_L2H( data); /* device stores data in low to high format
but the host uses high/low, bytes are swapped*/
The data header is a special part of the message buffer and is always placed in front of the I/O
data. The direction of the header is always in the data direction of the host platform where the
software is running. This means if the IOX task and the protocol driver are running on the
same system, no conversion is needed for the header structure. In the MBXMSG structure of
an MCI message, Org_Host_Dir( ) is defined to specify the data direction of the originating
host. If this data direction differs from the local host data direction, the header part must be
converted. MCIPAK handles this automatically using the MCI library.
The block read and write functions operate with contiguous blocks of data. The CDE operation
of the MCI message is always set to Cde_Block( ). In this case, the data direction always
corresponds to the direction set in the MCI message and applies to the set boundary. The IOX
task (sender of the MCI message) is responsible for ensuring the data is valid and corresponds
to the direction set in the message.
For example, in an MCI message from the IOX task, the CDE code is set to Cde_Byte( ) (size
is byte) and the boundary for the dataset is a word.
In the first case, the single exception element is either the same size or greater than the
destination area. If the element is the same size as the destination area, the element can be
written out as a simple block write operation (the IOX task automatically determines this for a
driver).
If the element is greater than the destination area, as in the following figure, it is still
considered a block write operation. This figure illustrates a byte ordering situation. The IOX
task takes care of switching the data correctly for the driver. The driver assumes the data is
adjusted correctly and does not have to make any conversions before writing it to the device.
I/O Translator Exception Data Commands
In the second case, the CDE code defines a data element smaller than the destination area in
the device.
For example, if a byte is to be written to a word area (16 bits) in a device, what byte (left or
right) must the data be written to? The CDE code specifies the proper byte. If the left byte is
the desired byte and it is unsigned, the CDE code is set to 0x0508 (CDE_UBYTE+8(bits)). 14
The 8 signifies to start at bit 8 that gives bits 8 to 15, which is the left byte.
IMX Messaging
A driver should never convert the MCI message block data functions. For block operations, the
protocol driver has no information about the data types (actual I/O data) the IOX task stores in
the MCI message. Types can be greater than the dataset boundary, such as a long being written
to a word area, and need more conversion. But the driver cannot correctly do the switching.
Therefore, block write message requests received from the IOX task must match the
corresponding dataset exactly; otherwise, the write message request cannot be sent to the
external device. The IOX task takes care of this for the driver. In the case of response data
resulting from a block read request, it is forwarded as is to the IOX task, and the IOX task
performs the necessary conversions.
The exception write commands can usually be transformed in size. This is dependent on where
the data has to be written or destination boundary in the external device as defined by the
dataset.
The problem with exception writes is the dataset has to be read first (read-patch-write) because
it may only be necessary to manipulate a portion of the dataset.
For example, after a read when a byte must be changed in a word, the byte value can be
manipulated in the word then written back out to the device. Failure to perform a read
operation as the first step may cause the other byte in the word to inadvertently get changed.
Subsequently, read-before-writes result in an increase in message traffic.
The org_host_dir element specifies the data direction of the originating host. Because the
MCI header is always in the host format, this element is checked against the local host data
direction. If they do not match, the MCI header must be converted to the local host data
direction. The MCI library takes care of this conversion automatically; therefore, no code is
required to be implemented in a protocol driver to handle this.
The station identification is a unique number of the host station on the LAN. The user must
assign this number and keep it unique over the LAN. The station identification can be passed
to the driver task as a program argument. You can use the station id number for checking if a
message did or did not originate over a LAN.
If tasks are to support communications over a LAN, some information must be exchanged
between the tasks before they can begin communications. The tasks are probably running on
separate nodes in two different FactoryLink applications, which means all tag ids are most
likely not consistent. MCI uses the dataset control tag for identification of the dataset. But, if a
problem prevails, the dataset control tags cannot be exchanged as they exist because the
remote application does not recognize the dataset control tag.
To resolve the problem, dataset information must first be exchanged between the tasks by the
IOX task using the Mci_Query_Cmd( ) function. This function is used to retrieve all
information about a dataset. The receiving task, usually a protocol driver, responds to the 14
request. The MCI library handles this automatically for a driver, so you need not implement
code to do this.
Once the information about the dataset control tags have been exchanged, further IMX Messaging
communications between the tasks is possible. You must perform a dataset registration in order
to link the local and remote datasets. The MCI library does this automatically for the
developer. The only requirement for developing a task for use with the FactoryLink LAN is to
execute a query command at start-up for every dataset used (the IOX task automatically does
this). The MCI library transparently handles all further requirements needed for LAN
communication.
•
•
•
•
Writing a RAPD Driver
O VERVIEW
This chapter discusses designing a protocol driver using the MCI libraries. The following
outlines the basic flow of code for any driver:
4. Define the characteristics of each data set and register them one at a time.
5. Go into the main loop of the program and check for MCI events. The loop terminates when
it detects the task is to terminate.
6. Make a call to exit the MCI library services after the loop terminates.
int main(){
15
/*only one dataset will be defined in this example, of course you may have many more
datasets in your task */
/* register this information to the MCI and receive a pointer to the registered dataset */
if( ( reg_ds = Mci_Ds_Register ( ds)) != GOOD) exit( 0);
/* go into the main task loop */
while ( fl_test_term_flag( ..... ) /* continue to loop until the task has been
terminated */
{
/* call the check event function of MCI on a polling basis */
if( Mci_Event_Check() == GOOD) {
/* do additional processing and other tasks here (i.e. check for unsolicited
messages coming in) */
.............................
}
fl_sleep(1000); /* let other tasks have a chance to run */
}
Mci_Exit();
exit( 0);
end program */
You define a temporary message buffer other than the default buffer by making a call to
Mci_Set_T_Buffer( ). In the example, a temporary buffer is used because, although the default
buffer was previously defined, it was not set as the current message buffer. The subsequent
MCI calls (Mci_Set_( )) require a message buffer to be defined. If this is not done, the program
attempts to write to an unallocated memory block.
Setting the dataset tag name has to be extracted from the CT record of the dataset. The example
included here has the name hard coded as Control_Tag.
15
The polling method (Mci_Event_Check( )) is used in a driver because the driver may have to
Arriving events are always per single dataset. They do not come in groups or as lists; therefore,
every event is processed in a first-come-first-served order. Every event that occurs corresponds
to a single dataset. When a dataset event occurs, the procedure you defined is invoked. That
procedure operates on the dataset accordingly.
The sample code shows a single dataset. A typical driver has to support more than one dataset,
so each must be setup according to each dataset CT record and then registered with the MCI
library one at a time. The dataset information in the sample code does not show that it came
The following sample illustrates the function you designed to call for a block read event for the
dataset:.
./*
*Exampleofusereventfunction.ThisisautomaticallycalledbytheMCIlibrarywhena datasetthis
function is defined for has an event active for the dataset.
*/
int process_ds( MCIDS *ds); /* user event function for dataset */
/* initiate the read command for this dataset on the external device */
build_cmd(ds, &cmd); /* build the protocol cmd msg to perform the block
read */
query_device(&cmd, &respdata, &len); /* query the device (send the message) */
bld_IOX_resp(ds, respdata); /* build response to IO translator */
Mci_Send(ds); /* send response to block read request to the IOX*/
break;
default:
..........
break;
}
return GOOD;
}
Typically, for every dataset, a single user defined procedure is defined. The procedure should
handle any kind of event possible on a single dataset.
The IOX task does not have to prompt (block and exception requests) drivers for data. Drivers
may also send unsolicited messages (messages sent by an external device on its own) to the
IOX task.
15
1 Internal error.
2 Out of memory.
3 Operating system error.
4 Initialization not successful.
5 Initialization not successful.
6 Incorrect function.
7 Incorrect argument.
8 Incorrect data.
9 Bad data.
10 Null pointer assignment.
11 Change flag not set.
12 Procedure table full.
13 Bad procedure name.
14 Bad user name.
15 Bad option.
16 Incorrect check sum.
17 No options.
18 No key.
19 Bad key.
20 No port available.
21 Port busy.
22 FactoryLink already active.
23 No lock.
24 Lock failed.
25 Lock expired.
26 Wait failed.
27 Termination flag set.
28 Q-size too big.
29 Q-size changed.
30 No tag list.
31 Tag list changed.
32 Wake up failed.
33 No signals.
34 Signaled.
35 Not a mailbox.
36 No messages.
37 Access denied. 15
38 Attribute failure.
39 Invalid attribute. Writing a RAPD Driver
40 Attribute not defined.
41 Application exists.
42 RTDB does not exist.
43 No task bit.
44 Not a lite task.
•
•
•
•
MCI Reference Library
F UNCTION C ATEGORIES
The functions in MCI are divided into different categories depending on the operation to be
performed. This chapter lists all MCI functions in these categories.
General MCI
Global Functionality
Mci_Init Initializes the MCI.
Mci_Exit Exits the MCI.
Mci_Recv Receives a MCI message from the MCI mailbox.
Mci_Send Sends an MCI message to a MCI mailbox.
Mci_Send_Error Sends an error response depending on type of message.
Mci_Mirror Reverses data.
Mci_Place_Data Places data on the exact spot within an element.
Mci_Get_CDE_Size Gets the size in byte of a CDE type.
Mci_Buffer_Alloc Allocates a buffer for use with MCI.
16
Dataset Functionality
Event Functionality
Mci_Event_Retrieve Gets the event arrays for true event driven processing.
Mci_Event_Check Checks for MCI events on a polled basis.
MCI API S
This section provides the following information about each MCI API function:
• Syntax: Valid format for this function
• Arguments: List containing the following information about each argument:
• Type
• Name
• Description
16
• Returns: Description of the returned data from the function, usually a symbolic
representation of the integer value returned by the function, such as ERROR or GOOD.
• Remarks: Additional information about the function, such as code fragments in the C IMX Reference Guide
language.
• See also: Lists related function(s).
Returns GOOD.
Error: FLE_OUT_OF_MEMORY.
Remarks This function allocates an MCI buffer and sets the pointer directly to the message.
The application must first set the length of the buffer using the m_max parameter.
This function can be used for setting allocating buffers for use with MCI but is not
strictly necessary. In case the application wants to allocate its own buffers, it should
also allocate space for the MCIHDR part, which is always in front of the data. The
buffer can be set by either using the Mci_Set_R_Buffer( ) or Mci_Set_T_Buffer( ).
The pointer to the first element in the buffer must be retrieved using
Mci_Get_U_Buffer( ). The pointer to the original allocated buffer can be retrieved
using Mci_Get_Org_Buffer( ).
M CI _D S _E VALUATE _W RITE
Evaluates the MCI dataset to see if it is possible to write this dataset in one operation.
A write operation is treated as an exception write (reading before writing) or a block
write.
Syntax intMci_Ds_Evaluate_Write( MCIDS *dataset)
This function speeds up communication because, in most cases, one write command
is needed against a read before a write.
This function can alter the received dataset parameters and data in order to convert it.
M CI _D S _P REPARE
Loads the default values set at registering time on the dataset.
Syntax int Mci_Ds_Prepare( MCIDS *dataset, MSG *buffer)
Returns GOOD.
Remarks The prepare function can be used before sending an MCI message to a remote task.
After preparing the dataset, the type of the MCI command must be set and all
elements of the dataset can be redefined to meet the characteristics of the command.
M CI _D S _Q UERY
Sends a query request for information of the dataset to the remote task where the
dataset has been defined.
Syntax int Mci_Ds_Query( MCIDS *dataset)
Returns GOOD.
Errors: 16
MCI_BAD_CTRL.
MCI_BAD_SNDMBX. IMX Reference Guide
FLE_NULL_POINTER.
FLE_BAD_TAG.
FLE_NOT_MAILBOX.
FLE_NO_MESSAGES.
FLE_ACCESS_DENIED.
FLE_OUT_OF_MEMORY.
M CI _D S _R EGISTER
Registers a dataset for use with the MCI library.
Syntax MCIDS *Mci_Ds_Register(MCIDS *dataset)
M CI _D S _R EMOVE
Removes all datasets from the task MCI mailbox queue that have the same MCI
functionality and dataset control tag.
Syntax intMci_Ds_Remove(MCIMSG *dataset)
Returns GOOD.
Errors:
MCI_WRONG_INDEX.
MCI_NOT_FOUND.
FLE_OUT_OF_MEMORY.
FLE_NULL_POINTER.
FLE_BAD_TAG.
FLE_NOT_MAILBOX.
FLE_NO_MESSAGES.
FLE_ACCESS_DENIED.
FLE_LOCK_FAILED.
FLE_LOCK_EXPIRED.
MCI_BAD_CTRL.
Remarks This function scans all active messages in the MCI mailbox queues and removes
those messages that have the same MCI functionality and dataset control tag.
The MCI has four command capabilities: QUERY, READ, WRITE and RECEIVE.
For every message removed and representing an active command from the queue, an
error message with error MCI_MSG_REJECTED( ) is sent to the originating task.
M CI _D S _TRIGGER
Triggers a dataset for reading by the remote MCI task.
Syntax intMci_Ds_Trigger(MCIDS *dataset)
Returns GOOD.
Errors:
MCI_BAD_CTRL.
MCI_BAD_SNDMBX.
FLE_NULL_POINTER.
FLE_BAD_TAG.
FLE_NOT_MAILBOX.
16
FLE_NO_MESSAGES.
M CI _E VENT _R ETRIEVE
Gets the event arrays for true event driven processing.
Syntax int Mci_Event_Retrieve( TAG **tags, void **datasets, u32 *num,
Arguments TAG **tags Pointer to hold internal MCI array of event tags.
void **datasets Pointer to hold internal MCI array of datasets.
u32 *num Pointer to total number of MCI events.
--- **e_fnc Pointer to hold internal MCI array of function pointers.
Returns GOOD: All parameters are filled with the internal MCI pointer values.
Remarks If a task wants to operate in an event driven mode, this function retrieves the events of
the MCI. The following arrays are returned:
Tags: return a list of all tags that can generate an MCI event. This tag list can be
added to the applications tag list and passed to the fl_wait_.. functions of FactoryLink.
FactoryLink Datasets: return a list of pointers to all registered datasets of the MCI.
This pointer must be used as first parameter of the user function in case of event.
e_fnc: return a list of event function pointers that must be called in case of an MCI
event.
The data of every index of the three arrays correspond to each other. If an MCI event
occurs, the event function with the event index and corresponding data must be
called. For example:
e_fnc[ index]( dataset[ index], val);
The value val can be retrieved from the fl_wait... functions. The application must call
the event function supplied by the MCI, and then the event function automatically
calls the user function registered with the dataset.
M CI _E XIT
Exits the Inter-Task Mail Exchange library for use.
Syntax intMci_Exit( void)
Arguments None.
Returns GOOD.
Remarks This function frees all internal resources of the MCI library and should be called just
before exiting the application.
M CI _G ET _B IT _D IR
Gets the direction of bit information within the boundary elements.
Syntax ucharMci_Get_Bit_Dir( MCIDS *dataset 16
M CI _G ET _B ND _D IR
Gets the boundary of normal data in the dataset MCI message.
Syntax ucharMci_Get_Bnd_Dir( MCIDS *dataset)
M CI _G ET _B ND _O FFSET
Gets the boundary addressing offset determined by the external device.
Syntax ucharMci_Get_Bnd_Offset( MCIDS *dataset)
M CI _G ET _B OUNDARY
Gets the boundary of data for this dataset.
Syntax ucharMci_Get_Boundary( MCIDS *dataset)
Returns Returns the data boundary, which can be one of the following:
M CI _G ET _CDE
Gets the operation code CDE that indicates the operation on the data in case of an
exception write.
Syntax u16Mci_Get_CDE( MCIDS *dataset)
M CI _G ET _CDE_S IZE 16
Returns the size of the data according to the operation (CDE) specified.
Returns Size of the element according to CDE code, which can be one of the following
Errors:
ERROR CDE code does not exist.
Remarks The size of the element returned also corresponds to the boundary of the element.
M CI _G ET _D S _C TRL
Gets the dataset control tag of this received dataset message.
Syntax TAG Mci_Get_Ds_Ctrl( MCIDS *dataset)
M CI _G ET _H ANDLING
Gets the handling of a write command on the dataset message.
Syntax uchar Mci_Get_Handling( MCIDS *dataset)
Returns None.
M CI _G ET _I NDEX
Gets the index of the dataset message in the mailbox queue.
Syntax uint Mci_Get_Index( MCIDS *dataset)
M CI _G ET _J OB _S EQUENCE
Gets the job sequence number of the received dataset message.
Syntax u16 Mci_Get_Job_Sequence( MCIDS *dataset)
M CI _G ET _L EN
Gets the length of the data in the dataset message in elements according to the
boundary size.
Syntax u16 Mci_Get_Len( MCIDS *dataset)
16
Arguments MCIDS *dataset Pointer to MCI dataset structure.
Returns The length of the data in the message. IMX Reference Guide
M CI _G ET _O RG _H OST _D IR
Gets the originating host data direction.
Syntax ucharMci_Get_Org_Host_Dir( MCIDS *dataset)
M CI _G ET _R_B UFFER
Gets the registered buffer parameters of this dataset.
Syntax MSG*Mci_Get_R_Buffer( MCIDS *dataset)
Returns Pointer to a FactoryLink MSG structure that contains the parameters of the buffer.
Remarks This function retrieves the buffer parameters which were set during registration of
this dataset. The dataset uses this buffer if it is not overruled by using the functions
Mci_Ds_Prepare( ) or Mci_Set_T_Buffer( ).
M CI _G ET _S ND _M BX
Gets the MCI mailbox tag of this dataset used for sending messages.
Syntax TAGMci_Get_Snd_Mbx( MCIDS *dataset)
Returns The tag of the MCI send mailbox for this dataset.
Remarks This tag must be set during dataset registration.
M CI _G ET _START
Gets the start address of the data in the dataset message.
Syntax u16 Mci_Get_Start( MCIDS *dataset)
M CI _G ET _STATION _I D
Gets the remote station id received from on the dataset message.
Syntax uchar Mci_Get_Station_Id( MCIDS *dataset)
Returns Pointer to a FactoryLink MSG structure that contains the parameters of the buffer.
Remarks This function retrieves the buffer parameters currently set on the dataset. This can be
the default parameters (at registration) or a buffer that overruled the default.
Returns The type of the message, which can be one of the following:
M CI _G ET _U_B UFFER
Gets the pointer to the first element of the dataset data buffer currently set.
Syntax char * Mci_Get_U_Buffer( MCIDS *dataset)
M CI _G ET _U DATA _P TR
Gets the pointer to the additional user dataset information buffer.
Syntax char * Mci_Get_Udata_Ptr( MCIDS *dataset)
M CI _G ET _U FNC _P TR
Gets the user function pointer called when an MCI event occurs.
Syntax int (*)( MCIDS *)Mci_Get_Ufnc_Ptr( MCIDS *dataset)
Returns Pointer to the user function that takes a pointer to a dataset as parameter.
M CI _G ET _VERSION
Gets the version of the MCI which generated this dataset message.
Syntax uchar Mci_Get_Version( MCIDS *dataset)
Returns The version number of the MCI that generated this dataset message.
16
M CI _I NIT
Returns GOOD.
FLE_OUT_OF_MEMORY.
FLE_NULL_POINTER.
FLE_BAD_TAG.
M CI _M IRROR
Reverses a character buffer of specified length.
Syntax void Mci_Mirror( char *buf, ushort length)
Returns None.
Remarks Reverses a character buffer of specified length. This function is used internally in the
MCI library for converting data elements of host machines with different data
directions.
M CI _P LACE _D ATA
Places data in the correct position within an element depending on the direction of the
data.
Syntax void Mci_Place_Data( MCIMSG *dataset, char bnd_dir)
Returns None.
Remarks This function gets the first element of the message buffer (I/O data area), checks the
operation code (CDE) and places the data in the correct position in the element, and
converts the element to the final boundary.
This function is usually used for exception write commands that require only one
element and, for the most part, is only used internally in the MCI library.
For example, when a message has the CDE code CDE_B0_15 with a specific bit
number set, the bit value is placed on the position of the bit number. The data
direction of the data element changes to the direction specified.
M CI _Q_D S _ SRCH
Searches the task MCI mailbox queue for a certain dataset.
Syntax int Mci_Q_Ds_Srchl( MCIDS *dataset)
*M CI _Q_I NIT
Initializes the task MCI mailbox queue.
Syntax int Mci_Q_Init( void)
Arguments None. 16
Returns GOOD.
M CI _Q_N UM
Determines the number of active MCI messages in the task mailbox queue.
Syntax int Mci_Q_Num( uint *num)
Returns GOOD.
Errors:
FLE_NULL_POINTER.
FLE_BAD_TAG.
FLE_NOT_MAILBOX.
FLE_LOCK_FAILED.
FLE_LOCK_EXPIRED.
Remarks Returns the number of active MCI messages in the MCI mailbox queue of the task.
This number can differ from the total number of messages in the queue.
M CI _Q_Q UERY
Queries a dataset in the queue but does not remove the dataset.
Syntax int Mci_Q_Query( MCIDS *dataset)
Returns GOOD.
Errors:
FLE_NULL_POINTER.
FLE_BAD_TAG.
FLE_NOT_MAILBOX.
FLE_NO_MESSAGES.
FLE_LOCK_FAILED.
FLE_LOCK_EXPIRED.
Remarks Before querying the dataset, the index in the queue must be valid. This is
accomplished by using the Mci_Set_Index( ) function. The query function only
returns data of the MCI section, MCIMSG. This means only a limited number of MCI
functions can be used (no functions that operate on the MCIHDR section). Usually
the application does not have to use this function because the MCI library queries the
new message (before calling the user function) with every event.
M CI _R ECV
Retrieves an MCI message from the task mailbox.
Syntax int Mci_Recv( MCIDS *dataset)
Returns GOOD.Errors:
MCI_WRONG_INDEX.
FLE_NULL_POINTER.
FLE_BAD_TAG.
FLE_NOT_MAILBOX.
FLE_NO_MESSAGES.
FLE_ACCESS_DENIED.
FLE_LOCK_FAILED.
FLE_LOCK_EXPIRED.
MCI_BAD_CTRL.
Remarks This function reads an MCI message from the task MCI mailbox using the parameters
set on the dataset, such as the index in the mailbox queue. The function removes the 16
message from the mailbox queue. Prior to calling this function, the task sets a
Returns None.
Remarks Resets the buffer parameters on the dataset currently used. If no other buffer is set, the
default buffer set during registration is used in subsequent MCI calls.
M CI _S END
Sends a dataset to a remote task through the designated send MCI mailbox of the
dataset.
Syntax int Mci_Send( MCIDS *dataset)
Returns GOOD.
Errors:
MCI_BAD_CTRL.
MCI_BAD_SNDMBX.
FLE_NULL_POINTER.
FLE_BAD_TAG.
FLE_NOT_MAILBOX.
FLE_NO_MESSAGES.
FLE_ACCESS_DENIED.
FLE_OUT_OF_MEMORY.
FLE_LOCK_FAILED.
FLE_LOCK_EXPIRED.
Remarks This function sends the dataset to the remote task using the send (remote task
mailbox) mailbox which was set at registration time. All parameters must be defined
for the dataset before calling this function. Default parameters, which were set at
registration time, can be set by using the Mci_Ds_Prepare( ) function. After
retrieving default values, specific value can then be set on the same dataset, such as
the command type (which must be set).
M CI _S END _E RROR
Sends an MCI error message to the remote task depending on the type of the dataset.
Syntax int Mci_Send_Error( MCIDS *dataset, u16 error)
Returns GOOD.
Errors:
MCI_BAD_TYPE.
MCI_BAD_CTRL.
MCI_BAD_SNDMBX.
FLE_NULL_POINTER.
FLE_BAD_TAG.
FLE_NOT_MAILBOX.
FLE_NO_MESSAGES.
FLE_ACCESS_DENIED.
FLE_OUT_OF_MEMORY.
FLE_LOCK_FAILED.
FLE_LOCK_EXPIRED.
Remarks This function generates an MCI error message depending on the dataset type and
sends it to the remote task. This function is usually used after an MCI event, which
means all relevant parameters are already set on the dataset. No preparation is 16
required other than the call to the function. The function uses an independent internal
message buffer for sending the message. It returns with the MCI message buffer
parameters reset to NULL.
IMX Reference Guide
See Also “Mci_Set_Type”
Returns None.
Remarks The direction of bit data, either
Mci_High_2_Low.
Mci_Low_2_High.
M CI _S ET _B IT _O FFSET
Sets the bit addressing offset determined by the external device.
Syntax void Mci_Set_Bit_Offset( MCIDS *dataset, uchar offset)
Returns None.
Remarks The bit addressing offset can be either 0 or 1.
M CI _S ET _B ND _D IR
Sets the boundary of normal data in the dataset MCI message.
Syntax void Mci_Set_Bnd_Dir( MCIDS *dataset, uchar dir)
Returns None.
Remarks The direction of data, either
Mci_High_2_Low.
Mci_Low_2_High.
M CI _S ET _B ND _O FFSET
Sets the boundary addressing offset determined by the external device.
Syntax void Mci_Set_Bnd_Offset( MCIDS *dataset, uchar offset)
Returns None.
Remarks The boundary addressing offset can be either 0 or 1.
M CI _S ET _B OUNDARY
Sets the boundary of data of this dataset message.
Syntax void Mci_Set_Boundary( MCIDS *, uchar bnd)
Returns None.
See Also Mci_Get_Boundary( )
M CI _S ET _CDE
Gets the operation code CDE that indicates the operation on the data in case of an
exception write.
Syntax void Mci_Set_CDE( MCIDS *dataset, u16 cde)
16
Returns None.
Returns None.
Remarks The application will probably use this function once: just before registering the
dataset. After the dataset has been registered, the application does not have to call this
function.
M CI _S ET _H ANDLING
Sets the handling of a write command on the dataset message.
Syntax void Mci_Set_Handling( MCIMSG *, uchar mode)
Returns None.
Remarks The mode of writing, either
MCI_NORMAL_WRITE.
MCI_ENCODED_WRITE.
M CI _S ET _I NDEX
Sets the index of the dataset message in the mailbox queue.
Syntax void Mci_Set_Index( MCIDS *dataset, uint index)
Returns None.
Remarks This function should not be used by the application directly because the search
function of the MCI library automatically sets the index of the dataset in the queue.
M CI _S ET _J OB _S EQUENCE
Sets the job sequence number on the dataset message.
Syntax void Mci_Set_Job_Sequence( MCIDS *dataset, u16 num)
Returns None.
Remarks This function is used to set a sequence number on command for keeping track of the
command. The responding task returns the same job number as received.
M CI _S ET _L EN
Sets the length of the data in the dataset message in elements according to the
boundary size.
Syntax void Mci_Set_Len( MCIDS *dataset, u16 len)
Returns None.
M CI _S ET _N AME
Sets the name of the dataset control tag on the dataset for registering.
Syntax void Mci_Set_Name( MCIDS *dataset, char *name) 16
Returns None.
Remarks The dataset control tag name must be set before registering. The tag name must
correspond to the tag id.
Returns None.
Remarks The application should not use this function because the MCI library sets this
parameter.
M CI _S ET _R_B UFFER
Sets the registered buffer parameters of this dataset.
Syntax void Mci_Set_R_Buffer( MCIDS *dataset, MSG *buf)
Returns None.
Remarks This function must be called before registering a dataset. The function sets the default
buffer the MCI library uses if it is not overruled.
M CI _S ET _S ND _M BX
Sets the MCI mailbox tag of this dataset used for sending messages.
Syntax void Mci_Set_Snd_Mbx( MCIDS *dataset, TAG send)
Returns None.
Remarks This function must be called before registering the dataset. Afterwards, the function is
not used.
M CI _S ET _START
Sets the start address of the data in the dataset message.
Syntax void Mci_Set_Start( MCIDS *dataset, u16 start)
Returns None.
M CI _S ET _STATION _I D
Sets the remote station id received from the dataset message.
Syntax void Mci_Set_Station_Id( MCIDS *dataset, uchar station)
Returns None.
Remarks This function can be used to set the local station identification number but is not to be
used by the application because this is completed internally by the MCI library. The
station id set during initialization is used.
M CI _S ET _T_B UFFER
Sets the temporary buffer parameters of this dataset. The default parameters are
overruled. 16
Syntax void Mci_Set_T_Buffer( MCIDS *dataset, MSG *buf)
Arguments MCIDS *dataset Pointer to MCI dataset structure. IMX Reference Guide
MSG *buf Buffer parameters.
Returns None.
Remarks This function sets the buffer parameters on the dataset. This overrules the default
buffer parameters, but they are preserved. If the default parameters must be used,
reset the buffer parameters with Mci_Reset_Buffer( ) before executing other
functions.
Returns None.
See Also “Mci_Get_Type”
M CI _S ET _U DATA _P TR
Sets the pointer to the additional user dataset information buffer.
Syntax void Mci_Set_Udata_Ptr( MCIDS *dataset, char *buf)
Returns None.
Remarks The application sets a pointer to a user defined buffer of a dataset. This buffer is used
for specifying additional dataset information. This data can be retrieved when MCI
events occur. This function must be called before registering the dataset.
MCI_S ET _U FNC _P TR
Sets the pointer to the user function.
Syntax void Mci_Set_Ufnc_Ptr( MCIDS *dataset, int (*u_fnc)( MCIDS *))
Returns None.
Remarks The user function pointer must be set and is called if an MCI event occurs on this
dataset. The user function must accept a pointer to the dataset as parameter and return
an integer.
*M CI _S ET _VERSION
Sets the version of the MCI library on the dataset message.
Syntax void Mci_Set_Version( MCIDS *dataset, uchar version)
Returns None.
Remarks The application should not use this function because the version is set internally by
the MCI library.
MCI_SYS_GET_FUNCTIONS
Gets the MCI functions supported by this task as registered at initialization.
Syntax ushort Mci_Sys_Get_Functions( MCISYSTEM *sys)
M CI _S YS _G ET _M BX
Gets the MCI mailbox tag as registered for this task.
Syntax TAG Mci_Sys_Get_Mbx( MCISYSTEM *sys)
M CI _S YS _S ET _M BX
Sets the MCI mailbox tag for registering for this task.
Syntax void Mci_Sys_Set_Mbx( MCISYSTEM *sys, TAG mbx)
Returns None.
Remarks This task should be called before the Mci_Init( ) function with the mailbox tag used
for MCI communication.
M CI _S YS _S ET _S TATION _I D
Sets the station id of this host machine for registering in the MCI library.
Syntax void Mci_Sys_Set_Station_Id( MCISYSTEM *sys, uchar station)
Returns None.
Remarks This function must be called before the Mci_Init( ) function with an unique station
number on the LAN.
M CI _S YS _S ET _TASK _I D
Sets the FactoryLink task id for registering in the MCI library.
Syntax void Mci_Sys_Set_Task_Id( MCIDS *dataset, u16 id)
Returns None.
Remarks The id number the fl_init_app( ) returns must be passed with this function. This
function must be called before the Mci_Init( ) function.
16
•
•
•
•
PAK Conversion
Considerations
This appendix contains information on converting from earlier versions of FactoryLink to the
present version. Some of this information was presented in previous Release Notes, which
should be used only if it still applies to your situation.
While these are the only two changes that are known to require custom tasks and custom EDI
Drivers to be rebuilt, it is recommended that all custom tasks be rebuilt with each new release
of FactoryLink.
Appendix
2 Install your third-party driver task or PAK task according to vendor instructions. After
installation, make any associated changes per the task installation instructions.
3 Run the FactoryLink mv_pak utility. The mv_pak utility copies your driver and/or PAK
files in the correct directory structure and renames the initial *.txt files to *.bkt, *.hlp files
to *.bkh, and *.key files to *.bkk.
1 Change all references to header files “imx.h”, “imx_fmt.h”, and “imx_int.h” to “mci3.h”,
“mci3_fmt.h”, and “mci3_int.h”.
2 Change all references to RAPD PAK functions that include the string “imx” to “mci”. Be sure
to preserve the case of the string. For example, “IMX” becomes “MCI”, and “Imx” becomes
“Mci”.
3 Update all calls to Mci_Send(), Mci_Send_Error(), and Mci_Recv() to include the new
Appendix
MCISYSTEM* argument. Use the MCISYSTEM pointer returned by the driver's call to
Mci_Init().
4 Add support for command line argument "-LS#", where '#' is the logical station number. This
is required in order for the user's driver to support mailbox marshalling. Initialize the RAPD
PAK with this logical station number via function Mci_Sys_Set_Station_Id(), which must be
executed prior to call Mci_Init(). If the logical station is not set on the command line, initialize
the logical station to 0.
6 Compile all modules using the /MD flag, which generates code using the multithreaded DLL
run-time library.
Once the above steps have been completed, the driver should compile and run without error.
A C
Index
AC files 347 calling and return conventions 136
comments in 68 CDB (configuration database) 345
created 61, 67 CDBLIST utility 93, 94
described 41, 61, 67 CDE codes 458
example 87 block data commands 458
example (external editor program) 90 data header direction 458
format 68 exception data commands 458
format (external editor program) 89 CDE operation codes 439, 454
with CONFIG PAK 337 CFGPAK (Configuration PAK) 335
accessing CDBs 347 change-read call 36
acctmgr -c -d utility 345 change-status bits 34, 132
adding tag definitions 371 change-wait call 36
analog data type 33, 56 changing name of tag definition 373
Application Editor 337 common functions in interface library 447
archive (CT) 109 compiling
arrayed elements BASIC PAK 20
described 50 RAPD 433
examples 51 compiling and executing Skeleton Task 25
arrays 48 CONFIG PAK
attribute catalog error messages 377
See AC files message box type requests 377
attribute catalogs return codes/error messages 375
with CONFIG PAK 345 storage entities 336
validation error reporting 378
B configuration architecture
binary CT generation utility 116 BASIC PAK 47
block read function 447 CONFIG PAK 336
block write function 450 configuration database (CDB) 345
configuration database API 349
Index
editor program execution from CM 89 forced-write call 35, 42
element names 48 functions
elements block read 447
described 54 block write 450
name storage 54 exception writes 453
predefined 54 unsolicited receive 455
structure 34
environment variables 20 I
error code 450, 452, 456 I/O functionality 447
error numbers 137 IMX
exception processing 36 interface library 435
exception writes 453 LANS communication 461
encoded 454 library functions 471
normal 453 messages
testing 454 converting 460
exit the calling process 124 specifications 435
external configuration 337 information panels 48, 66
informing FactoryLink about new task 92
F initialize
FactoryLink calling process 120
API 28 installation
Kernel 29 BASIC PAK 20
operation 27 CONFIG PAK 335
failure scenarios with CONFIG PAK 338 RAPD 431
field handles 350 interface library
FL_LOCK common functions 447
relationship to FL_UNLOCK 224 inter-process communication (IPC) 129, 135
FLAPP IOX driver communications 467
directory files 57, 58
Index
parameters read calls 35
error code 450 reading configuration from CDB 354
mm_msg 437 reading tag definitions 369
mm_type 441 Real-Time Database
mm_user1 442 described 33
mm_user2 442 locking 132
passing a dataset 445 structure of elements 34
path manipulation 159 Run-Time Manager 28, 118, 124
allocating/destroying path 161 and CT files 41
building and representation 159 interaction with other tasks 28
converting to/from 161 run-time requirements 118
environment variables 160 run-time task
files writing 64
creating/deleting 162
getting information 164 S
searching for 163 selection criteria 354
modifying 162 setting up configuration environment 65, 108
path names setup script 20
components 159 Skeleton Task
predefined data types 33 compiling and executing 25
predefined elements. See tag name CONFIG PAK 341
primary key 337 converting script 24
printing tag definitions 370 described 23
processing a dataset 445 integrating 24
Programmer’s Access Kit (PAK) procedure 24
described 19 verifying 24
installation 20 software design model
software requirements 20 flowchart 60
protocol driver default message buffer 465 station identification number 461
protocol driver design example 463 steps in reading configuration data in CDB 354
X
XREF database table 56
Index