Professional Documents
Culture Documents
Version 8.0
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Programmer’s Access Kit
•
•
•
•
Disclaimer of Liability
The information contained in this document (and other media provided
herewith) constitutes confidential information of Siemens AG 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 Siemens AG.
The information contained in this document and related media
constitutes documentation relating to a software product and is being
provided solely for use with such software product. The software product
was provided pursuant to a separate license or other agreement and
such information is subject to the restrictions and other terms and
conditions of such license or other agreement.
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 Siemens AG. Except for
warranties, if any, set forth in the separate license or other agreement
relating to the applicable software product, Siemens AG makes no
warranty, express or implied, with respect to such information or such
software product.
Trademarks
Siemens AG and FactoryLink are trademarks or registered trademarks of
Siemens AG in the United States and/or other countries. All other brand
or product names are trademarks or registered trademarks of their
respective holders.
•
•
•
•
Programmer’s Access Kit
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Using this Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513
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
•
•
•
•
•
•
•
•
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:
1 In your application, open Other Tasks > Skeleton FL Task > Trigger Tags.
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.
1 From the Windows Start menu, open either Microsoft Visual Studio (2000 or 2003) or
Microsoft Visual C++ 6.0.
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 tag since each
task has access to the same global tags.
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.
The multi-user architecture allows duplicate USER domains by allocating an array of pointers
to database segments for each user. This allows the tag numbers (indices into the pointer array)
themselves to remain the same for each user while referencing a private data area for each user.
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 tags in the SHARED domain or tags 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 tag are associated with
the SHARED domain. At run time the task runs as a shared entity with one set of tags 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
tags. 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 tags. 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
tags of a single data type. Whenever you define an tag, the system prompts you to identify the
data type of the tag 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 a tag 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 tag 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 tag numbers to read from or write to tags in the
Real-Time Database.
Structure of a Tag
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 tag, 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 a tag 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 tags through either
• Write call
• Forced-write calls
Tasks use the Kernel Service’s write-call function to update a value of a tag. This function first
determines whether the tag value changed. If the new value differs from the old, the write-call
function sets each of the tag change-status bits to 1 and stores the new value in the tag;
however, if the comparison determines the new value for the tag is identical to the old, nothing
changes. This method saves processing time because tasks watching the tag 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 tag has changed and sets all of the tag change-status bits to ON as it stores the new value,
even if the updated value being assigned to the tag is the same as the old. Forced writes are
useful when you need to trigger processes setting the tag change bit but do not wish to change
the actual contents of the tag or when an tag 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 tag to the calling process
regardless of the value of the tag change-status bit assigned to that process.
When a task makes a change-read-call, the reading task requests change-status information
about specific tags. If the function finds that the change-status bit of a tag has been set since it
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 tags. Once a task makes
its call, the task then hibernates while waiting for a tag to change. When a task is asleep, it uses
no CPU cycles. The task wakes when any one of the specified tags have changed and/or have
had their change-status bits set to 1 by another task since the last reading. In other words, this
call blocks the calling process until at least one of the specified tags change-status bits are
toggled.
Regardless the method of reading a tag, the act of reading a tag resets the tag change-status bit
associated with the reading task to OFF by writing a 0 to the task change-status bit in the tag.
As successive tasks read a tag, they toggle the change-status bits in the tag, 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 a tag has changed and then take an action.
Wait bits: For each tag, one wait bit exists for each possible client process. When the client is
currently waiting to read the specified tag, the value of the bit is 1; otherwise, the value is 0.
Run-Time Architecture
for an exchange of information among the tasks. You use the configuration tables to specify the
tags each task reads or writes. A task is only aware of the tags 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 tags
• Write one or more database tags
• Determine whether a database tag has been modified by another task since it last read the
tag
• Sleep until any one member of a list of specific database tags is modified
• Access miscellaneous utilities
Any task can use any tag in the Real-Time Database as long as the data type and domain of that
tag matches the type required for the indicated operation. It is possible— even beneficial— for
two tasks to use the same tag. When this occurs, both tasks share the information stored in the
tag.
Although some tasks may only read or write to tags, most tasks have both read and write
access to the tags. Remember all tags are global, so any task can use any tag as long as that tag
data type matches the type required for the indicated operation. It is possible for two tasks to
use the same tag, sharing responsibility for updating the information stored in the tag.
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 tag, it is impossible to know which task is responsible for the data in the tag. 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 tag.
Example 1. When you enter a new value from the keyboard, the Graphics Task gets the value
and writes it to the tag associated with the input object.
Example 2. The Graphics Task uses a change-read function that executes in a loop to
determine whether tag 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 tag
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 tags in the Real-Time Database or read tags 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) tags. 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.
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 tags to open and the actions to perform on those tags. 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.
Two conditions must exist for a tag to trigger an event in existing FactoryLink tasks:
• Value of the tag must be 1.
• Value of the change-status flag being read must be non-zero.
When a task reads a trigger tag, the reading task sets its change-status flag to 0 and begins the
operation designated by the trigger if the tag value is 1 and has changed since the last time it
was read.
Forced-writing a 1 to a digital tag, even though it may not change the actual value of the tag (if
the tag 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 tag 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 tags created for each task and the actions each task
performs on these tags. 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 tables that provide
predefined entry fields for information required for the task to function.
This is how the control and information tables for a particular task are related. In the following
sample Control table, 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 tags to receive or
supply information from/to the DDE source (Microsoft Excel spreadsheet) in the following
sample Information table, which is associated with the previous Read/Write control table.
A task may require both Control and Information tables or just an Information table.
Tag Names
Each tag has a unique, developer-defined, symbolic tag name. You assign these tag names, one
for each tag used in the application during system configuration and the system stores them in
a separate predefined data file. Tag names are linked at run time with pointers to their
associated tags, 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 tag names stored as text strings. This, in part, accounts for
FactoryLink’s high processing speed.
Tag name assignment: During configuration you create and assign a tag name to a tag by
defining at a minimum its name, data type, and possibly its domain dimension. If the tag you
referenced does not exist, the system automatically creates it. Once a tag has been defined in
this way, other tasks refer to this tag using its tag name, reading or writing data to or from the
tag at run time. 4
Valid tag names conform to the following grammar:
[<node>:]<name>[<dims>][.<ext>]
Configuration
Architecture
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.
Syntax Samples
• Sample tag name: plc_readval
• Sample remote tag name: serverl:plc_readval
• Sample arrayed tag name: plc_readval[5][6]
• Sample member tag name: plc_readval.raw
• Sample remote, arrayed, member tag name: node name plc_readval [5][6].raw
Arrayed Tags
A tag array is a block of tags of the same type. As such, it frees the developer from having to
define large numbers of scalar tags separately. Certain FactoryLink tasks, such as Math &
Logic and Database Browser, can detect the arrayed property of a tag and can access the entire
tag array when given a reference to just one of its tags.
Define tag arrays in a configuration table by using at least a two-part tag name. A two-part tag
name consists of an alphanumeric string (the arrayed tag 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 tag 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 tags is also an array and its tags are referenced by [row,column] pairs.
The array dimensions defined within the square brackets are the sizing factors that determine
the number of tags in an array. For example, if you specify the size of a one-dimensional tag
array is 5, the Real-Time Database creates five separate tags referenced individually or as a
group. Their array tag names are the same, but they have different array indices.
Each set of square brackets represents a dimension or spatial characteristic of the tag array,
such as length, width, or height. When you define a tag array in a configuration table, 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 tag name
brackets because C arrays are indexed from zero to the specified dimension. For example, if
the tag name is tagname[0][0], the default dimension sizes displayed in the dialog are 1,1. If
the tag name is tagname[4][6][3], the default dimension sizes are 5,7,4.
This also means that arrays are indexed beginning at zero. For example, tagname[0] is the first
tag of the array tagname.
The number of array dimensions and the number of tags allowed in an array are constrained in
two ways:
• The tag name field limits the size of the array dimensions. Sixteen characters are allowed in
the dimension portion of a tag name. For example, the array tag name
tempset[3][1][10][1][1] contains 7 characters in the tag 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 tag arrays containing up to 64K (65535) numbers of tags.
Use the following formula to determine the number of tags created in an array with a given set
of dimensions:
axbxc
4
where
a Is the size of the first dimension.
b Is the size of the second dimension.
Configuration
Architecture
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 table for each tag referenced to reference individual tags in
the array.
the default sizes of the two dimensions displayed in the dialog are
2,2
Enter msg_tag[index1][index2] in the table for each tag referenced to reference individual tags
in this array.
Suppose you need to define message tags whose values indicate the colors the cars on one
conveyor belt are painted. If 300 cars are painted on the conveyor belt and tag arrays are not
used, you must define 300 tags individually. With tag arrays, however, you define only one
two-part tag name and specify that the name contains 300 tags by entering 299 (creating tags 0
to 299) inside the brackets, as in
color[299]
Set the integer ([299]) sizing the single dimension of the tag to one less than the desired
number since tags are numbered beginning at index zero (0). Here, the desired number of tags
(299 + 1 or 300) are created under one tag name, as in
color[0]
color[1]
color[2]
.
.
color[299]
Suppose you want to define tags to indicate the colors cars on three conveyor belts are painted.
You can define a two-dimensional tag array by entering one tag 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 4
conveyors. As a result, the correct number of tags [(299 + 1) X (2 + 1) or 900] are created
under one tag name, as in
paint[0][0] paint[0][1] paint[0][2]
Configuration
Architecture
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 tags 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 tag
array using one tag name as in
car_truck[299][2][1]
The third dimension ([1]) indicates the type of automobile. In this example, 1,800 tags are
created under one tag name as in
(299 + 1) X (2 + 1) X (1 + 1) = 1800
The three-dimensional array may be thought of as a cube of indexed tags with each tag having
an (x,y,z) coordinate reference, such as depth, vertical position, and horizontal position.
Each task can have tables with tags 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 tags identified
by the tag numbers and data types listed in the CT files.
Predefined Tags
The FactoryLink starter application FLNEW comes with a set of predefined tags for internal
use. These also serve as a convenience so you can use these when configuring tasks.
Predefined tags 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
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
are only present when that task is used in the application.
Configuration
Architecture
DOMAIN
TYPE
OBJECT
XREF
TYPE
The TYPE database table defines the segments that consist of one of the six data types and one
of the domains used in FactoryLink. Each of these types corresponds to a record in the TYPE
table.
Type Description
DIGITAL Boolean value (on or off).
ANALOG 16-bit signed integer.
LONGANA 32-bit signed integer.
FLOAT double precision floating point.
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 tags 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 a tag in any task-specific table. This information
allows the Configuration Explorer to locate all occurrences of a particular tag 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 table and an Information table. The Control table
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
*.CDB Database tables that store information about the tags such
as name, type, number of definitions (number of writes
specified by the defining task), number of references, and
task specific information.
\ASC *.ASC ASCII database tables that store information about the
Real-Time Database tags 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
tags. 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 table(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 table(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 Table 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:
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
JA 1 YES
N 0 N
J 1 Y
LANGSAM 1 SLW
SCHNELL 2 FST
FactoryLink Task
Constructing a
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 table(s) to be stored in the newly-created database table(s).
When converting database tables to CTs, you must write a configuration table generator (CTG)
script that tells the CTGEN utility (generate binary CT files) how to extract data from the
database tables and combine it to produce a binary Configuration Table (CT) file. You must
also verify the script performs the desired conversion.
Ultimately, an executable must be created that reads the configuration information entered into
the task configuration databases (CDBs) and later converted into binary configuration tables
(CT). This involves writing a C program that invokes the methods provided by the
FactoryLink library.
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.
A custom program should not adversely affect or otherwise interfere with concurrently
running tasks, directly access system resources, such as I/O devices under the control of the
operating system, or severely degrade the performance of FactoryLink.
The program must conform to certain requirements imposed by the Run-Time Manager in
order for the latter to carry out its supervisory duties effectively.
The following figure illustrates the portion of the Task Construction Flowchart involved in
setting up the configuration environment.
FactoryLink Task
Constructing a
Designing the Task-Specific Database Table(s)
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 tables required or just an Information table?
• What is the table design, including the following items:
• Name of the table
• Table layout, such as column headings and order of information
• Data type of any tag to be entered on the table
• 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 a tag to be monitored for an alarm condition. In addition to the tag, you can
also specify alarm messages and limits. The Configuration Explorer adds the tag to the
OBJECT table if it has not already been created. In addition, the Configuration Explorer adds
the tag 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.
An Attribute Catalog (AC) file represents one option Configuration Explorer and may or may
not represent an entire task. For example, to configure the Batch Recipe task, you choose only
one option, Recipe, and fill in the associated tables. This option corresponds to the
RECIPE.AC file.
Each task has multiple tables that can be configured for it. Each table 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.
AC File Format
5
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
FactoryLink Task
Constructing a
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.
The TASK statement defines the task name and title for the task list. Only one TASK statement
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]]
5
The EDIT statement defines a module or program used to edit this database table. If the EDIT
FactoryLink Task
statement is not included, the Configuration Explorer uses the default edit procedure.
Constructing a
Parameter Description Valid Entries
type Determiner of the DEFAULT (Standard panel edit procedure, which
module or program means you complete the columns and rows of the
used for editing. table using the Tab key or arrow keys to move from
field to field or row to row.)
The VALIDATE statement defines the level of editing you are allowed when completing a
configuration table and the program or module that performs the editing.
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.
FactoryLink Task
Constructing a
FIELD
FIELD name, type, width, field_prec, key_file, default, low, high, flags
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 table 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 (').
FactoryLink Task
Parameter Valid Entries
Constructing a
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
The HEADING option defines the text used as a field heading and the character width for the
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
[RELATE CDB_name, field_name, index_file]
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.
Note: In .AC files, do not use RELATE statements with a field of type
TAG.
TYPE
5
[Type “field_name”]
The TYPE statement causes the TAG type of a TAG field to be displayed.
FactoryLink Task
Constructing a
Parameter Description Valid Entries
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.
DOMAIN
DOMAIN “DOMAIN”, 8
Enter the DOMAIN statement exactly as shown above for each configuration table in each AC
file. Do not change this statement.
After you configure a table, 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 tag with the domain defined in the Tag Definition pop-up table.
This statement must be included for each configuration table defined in an AC file for
FactoryLink to operate correctly.
The SELECT statement defines a selection field. Each CT may have one or more select fields
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
SEQ field_name , width
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.
INDEX
INDEX index_file, key_expression, key_length
5
The INDEX statement defines an index for the database. The first INDEX statement defines
FactoryLink Task
the primary index and controls the order of records on the screen. If needed, define additional
Constructing a
indices for use by external programs, such as CTGEN. The Configuration Explorer updates all
indices whenever a database record is updated.
END
END
The END statement terminates a CT definition; therefore, one END statement corresponds to
each CT statement in the AC file.
PAK currently uses a dBASE-compatible database library that dictates the following
parameters.
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 following table shows the tokens for an internationalized LOGGER.AC file.
5
Language Name Description
EN Logger_Task Logger Task.
FactoryLink Task
Constructing a
FR Logger_Task Tache du consignateur.
DE Logger_Task Logger Task.
EN Logger_Info Logger Information.
FR Logger_Info Informations du consignateur.
DE Logger_Info Logger-Information.
EN Value_Tag Value Tag.
FR Value_Tag Tag de valeur.
DE Value_Tag Wert-Tag.
EN Field_Width Field_Width.
FR Field_Width Largeur du champ.
DE Field_Width Feldbreite.
EN Logger_Cntl Logger Control.
FR Logger_Cntl Controle du consignateur.
DE Logger_Cntl Logger-Kontrolle.
EN Table_Name Table Name.
FR Table_Name Nom table.
DE Table_Name Tabellenname.
EN Trigger_Tag Trigger Tag.
FR Trigger_Tag Tag declencheur.
DE Trigger_Tag Trigger-TAG.
EN Path Path.
FR Path Chemin.
DE Path Pfad.
Name Description
Logger_Task Logger Task
Logger_Info Logger Information
Value_Tag Value Tag
Field_Width Field Width
Logger_Cntl Logger Control
Table_Name Table Name
Trigger_Tag Trigger Tag
Path Path
Name Description
Logger_Task Tache du consignateur
Logger_Info Informations du consignateur
Value_Tag Tag de valeur
Field_Width Largeur du champ
Logger_Cntl Controle du consignateur
Table_Name Nom table
Trigger_Tag Tag declencheur
Path Chemin
Name Description
Logger_Task Logger-Task
Logger_Info Logger-Information
Value_Tag Wert- Tag
Field_Width Feldbreite
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 5
Task.
FactoryLink Task
Language Name Description
Constructing a
EN START Starting
FR START Demarrage
DE START Startet
EN RUN Running
FR RUN Execution
DE RUN Lauft
EN STOP Normal shutdown
FR STOP Arret normal
DE STOP Normaler Shutdown
EN NOMEMORY Out of RAM
FR NOMEMORY Memoire RAM saturee
DE NOMEMORY Kein Arbeitsspeicher mehr
EN NOCT Can’t open CT
FR NOCT Impossible d’ouvrir la TC
DE NOCT CT Kann nicht geoffnet werden
EN NOTRIGGERS No triggers defined
FR NOTRIGGERS Aucun declencheur defini
DE NOTRIGGERS Keine Trigger definiert
EN CTINDEX Error reading CT index
FR CTINDEX Erreur lors de la lecture de l’index de la TC
DE CTINDEX Fehler beim Lesen von CT-Index
EN CTHEADER Error reading CT header
FR CTHEADER Erreur lors de la lecture de l’en-tete de la TC
DE CTHEADER Fehler beim Lesen von CT-Kopf
EN BADTAG Invalid trigger tag
FR BADTAG Tag declencheur incorrect
DE BADTAG Ungultiges Trigger-TAG
EN CTRECORD Error reading CT record
The next three tables show the internationalized English, French, and German token files
generated from this message .AC file. 5
Name Description
FactoryLink Task
Constructing a
START Starting
RUN Running
STOP Normal shutdown
NOMEMORY Out of RAM
NOCT Can’t open CT
NOTRIGGERS No triggers defined
CTINDEX Error reading CT index
CTHEADER Error reading CT header
BADTAG Invalid trigger tag
CTRECORD Error reading CT record
CANTOPEN Can’t open: %s
TRIGCRE Error creating trigger manager
TRIGINS Error instering trigger into manager
Name Description
START Demarrage
RUN Execution
STOP Arret normal
NOMEMORY Memoire RAM saturee
NOCT Impossible d’ouvrir la TC
NOTRIGGERS Aucun declencheur defini
CTINDEX Erreur lors de la lecture de l’index de la TC
CTHEADER Erreur lors de la lecture de l’en-tete de la TC
BADTAG Tag declencheur incorrect
CTRECORD Erreur lors de la lecture de l’enregistrement de la TC
CANTOPEN Impossible d’ouvrir : %s
TRIGCRE Erreur lors de la creation du gestionnaire de declencheurs
TRIGINS Erreur lors de l’insertion du declencheur dans le gestionnaire
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 21 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 table; therefore, it is the parent table to
the Tag List table, which is the child table.
As described in the FIELD statements for the Trigger Tags table, the table 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 tag 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 table, choose the desired Table Name, and open the Tag
List table, the chosen Table Name displays in the field above Cancel on the Tag List table.
As described in the FIELD statement for this table, you complete only one field, Tag Name,
by entering the name of a tag (TAG type in FIELD statement) of any data type.
Both table and field help should be created for all ACs. This equates to creating a formatted
text file and placing the results in directory {FLINK}\msg\en, {FLINK}\msg\fr, or
{FLINK}\msg\de for each supported language. AC help files have a .hlp extension.
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 table 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.
FactoryLink Task
Constructing a
Configuration Environment” on page 88 for more information.
Parameter Description
task Name of the FactoryLink run-time task.
task_title Text displayed in Configuration Explorer.
ct_name Name of the configuration table.
file_spec Specifics for the file to edit.
executable Editor executable.
cmd_arguments Argument strings to be passed to the editor.
format_string Format string for command arguments. If %s is displayed in the
format string, it is replaced with the file spec option and passed to the
editor as a command line argument.
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 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
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 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.
FactoryLink Task
• Save it with a new name
Constructing a
Sample KEY File
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.
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 table 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.
FactoryLink Task
Constructing a
Viewing Contents of a Configuration Database without Configuration Explorer
• CDBLIST dumps the contents of configuration database. The command line is:
cdblist [-d] <file.cdb> [<file.mdx]
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.
PAGEDIT is a standalone utility that allows for the creation of additional pages for the Single
Point Dialog. As the new notebook page is created, the fields on the notebook page are
connected to fields in the AC file.
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.
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 Siemens.
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.
"ac/ACname.acr" Name of the file in %FLINK%/ac that contains the custom notebook page
information. The ac/ prefix must be included in the filename. 5
FIELD statement
FactoryLink Task
Format FIELD Field_ID, GraphType, "Field Name", FieldType, ...
Constructing a
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 table.
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 table 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.AC
#
XLATES “templ_ac.txt”
DEFINES “ac/template.h”
DOMAIN “DOMAIN, 8
END
FactoryLink Task
VALIDLIST “temp_sta”, “STATION, “COMMENT”
Constructing a
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
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.
FactoryLink Task
Constructing a
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 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.
Notice the tag-based information is arranged at the top, and several fields from the control
table are displayed in a read-only section at the bottom of the page. Since Table Name is the 5
key field for the control table, it is represented as a pulldown listbox that allows the user to
select the table the tag being input is placed into. No information from the control table need be
displayed, nor is it required that all fields from the information table be displayed.
FactoryLink Task
Constructing a
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.)
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.
FactoryLink Task
Constructing a
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 101. 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.
@begin(literal)
@relmargin(36 8)
@popup(STATION Logical Station)
@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)
@end(literal)
@begin(literal)
@end(literal
These entries add comments to the help source, allowing for easier maintenance of the source.
FactoryLink Task
Constructing a
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.
The popup keyword establishes a jump from the current context to the given context, but
creates a popup window to show the linked information. The APPEDIT convention for popup
help is to display help that is common to several pages. The template example shows the help
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.
FactoryLink Task
• Convert Database Tables to CTs
Constructing a
• Create the CTG Conversion Scripts
• Test the Conversion Process
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
Conversion Overview
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.
FactoryLink Task
Constructing a
binary data from the CT archive directly into memory. The /{FLINK}/CTGEN directory
contains sample CT conversion scripts.
SORT “FIELD1”,”FIELD2”
DOMAIN “DOMAIN”, S, 8
FIELD name, format, storage, [options]
RECORD database, namefield, indexfile
SORT “FIELD1”,”FIELD2”,”FIELD3”
DOMAIN “DOMAIN”, S, 8
FIELD name, format, storage [option] [DEFAULT dfltval]
SKIP count, value
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.
The HEADER statement defines the format of the header section of the CT. No more than one
header record is written for a CT; however, the header record may be non-existent.
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.
FactoryLink Task
Constructing a
DOMAIN
DOMAIN “DOMAIN”, S, 8
Enter the DOMAIN statement exactly as shown above for each configuration table 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 64.
S Indicates the domain directory name consists of a character string.
8 Is the number of characters in the domain directory name. This number
must be the same as the number in the DOMAIN statement of the
corresponding AC file.
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.
The FIELD statement defines the translation of one field in the database table to bytes in the
CT entry. Include as many FIELD statements as necessary.
FactoryLink Task
segment and offset as
Constructing a
converted. binary as numerical
values.
DIM The dimensions of the
TAG contained in the
database field is used
as the output data.
TYPE The type of the TAG
contained in the
database field is used
as the output data.
KEY <keyfile> Specifies the keyfile
to use to translate
the field string value
into a numeric value.
dftval Default value. Specifies the default value to be used if the
database field contains a NULL string.
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}.
A SKIP statement causes one or more bytes to be written to the output. The SKIP statement
allows padding of fields to match the task data structures as well as insertion of specific binary
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
FactoryLink Task
Constructing a
internal structures required to perform the job. To improve performance, tasks use the tag
number from the CT instead of the tag names in the database table(s) to access the Real-Time
Database.
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.
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 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.
where
<file.ct> CT file to dump.
FactoryLink Task
monitors specific database tags in the Real-Time Database on a per-task basis.
Constructing a
The requirements include:
• Initialization
• Kernel Check
• Error Handling
• New Configuration Notification
• Termination Notification
• Orderly Shutdown
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.
Create Source
Modules
Compile Source
Modules
No
Link Object
Modules
No
Execute Program
Problems
Yes Debug Program
Found?
No
Create Installation
Medium
I NITIALIZATION
5
First, the task attaches with the Real-Time Database (or Kernel) by calling FLIB function
fl_proc_init( ) to obtain a task id (taskid). Function fl_proc_init( ) uses environment variables
FactoryLink Task
{FLNAME}, {FLDOMAIN}, and {FLUSER} to determine which Real-Time Database to
Constructing a
attach. If the task needs to attach elsewhere, FLIB function fl_proc_init_app( ) can be called.
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 tags by calling to
fl_get_env( ). The environment tags, which are used to communicate with the Run-Time
Manager, include the following information:
• Status tag for reporting task status as an ANALOG value
• Message tag 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 tag and Running to its message tag. 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
If the task encounters any errors, failures, or other problems during execution, it reports
appropriate error messages to its environment STATUS and MESSAGE tags.
• In case of a fatal error, the task exits following the shutdown procedure described in the
Orderly Shutdown requirement.
• In case of a non-fatal error, the task sets its environment STATUS tag to FLS_ERROR. This
indicates to the Run-Time Manager the task encountered problems but is continuing
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:
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 METHOD keyword indicates what method is used to update the given task with online
configuration. If the following keyword is CYCLE, the task will be stopped and restarted. If
the following keyword is SIGNAL, the task will be sent the kernel signal
FLC_SIG_NEWCONFIG. If a task is to be signaled instead of cycled, then the developer must
modify the task code to recognize the signal and dynamically reload its configuration
information. Only one method definition is allowed and required per bump 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. 5
The BUMP_DEPENDENCY keyword precedes the comma-delineated list of additional bump
record names on which the task is dependent. The <bumpname> entry should match the
FactoryLink Task
Constructing a
<bumpname> used to define a separate BUMP record or group. One or more bump
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
BUMP_DEPENDENCY or7_hist, db4_hist, syb_hist, odbchists
ENDGROUP
DPLOGGER.RTM:
BUMP dplogger
METHOD CYCLE
FILE_DEPENDENCY ct\dplogger.ct*
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 tag.
• 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.
O RDERLY S HUTDOWN
5
The task performs the following actions before calling EXIT:
• Writes a message explaining the reason for termination to its environment MESSAGE tag,
FactoryLink Task
which is then displayed in the MESSAGE column of the Run-Time Manager display.
Constructing a
• Sets its environment STATUS tag to FLS_INACTIVE, which causes the Inactive symbol to
display in the STATUS column of the Run-Time Manager display.
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
fl_proc_init Attach to the Kernel.
fl_proc_exit Detach from the Kernel.
fl_set_term_flag Sets the termination flag of a client process.
fl_test_term_flag Asks the Kernel the status of current task termination
flag.
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_env Returns KENV structure of the client process.
fl_get_ctrl_tag Returns control tag for the specified process.
fl_get_stat_tag Returns value of the Real-Time Database analog status tag for the
specified process.
fl_get_msg_tag Returns value of the Real-Time Database message tag for the
specified process.
fl_get_pgm_dir Returns program directory for the specified process.
fl_get_app_dir Returns application directory for the specified process.
fl_get_cmd_line Returns command line for the specified process.
fl_get_title Returns pointer to the name of the product (FactoryLink).
fl_get_copyrt Returns a pointer to a copyright message.
fl_get_version Gets the Kernel version number.
Function Description
fl_lock Locks the Real-Time Database on behalf of the calling process.
fl_unlock Unlocks the Real-Time Database for the calling process.
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,
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
application from performing any work.
Signals
6
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
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
fl_send_sig Sends a signal to a target process.
fl_recv_sig Receives a signal for the calling process.
fl_hold_sig Prevents or allows signal delivery for the calling process.
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.
Function Description
fl_get_tick Gets the current clock tick and/or current date and time
maintained and reported by the operating system.
fl_global_tag Retrieves the tag number for one or more global tags.
fl_name_to_id Translates a process name to a FactoryLink ID.
fl_id_to_name Translates a FactoryLink ID to a process name.
fl_sleep Forces program to release the CPU for a given period of
time.
spool Sends a file to the FactoryLink spool task.
Any task may read a given tag; 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.
Function Description
fl_read Reads specified tags from the Real-Time Database.
fl_write Writes specified tags to the Real-Time Database.
fl_forced_write Force-writes a specified tag to the Real-Time Database.
Function Description
6
fl_wait Waits to read, write, or access the Real-Time Database or certain
tags in the database.
Real-Time Database
The corresponding typedefs for each data type are found in FLIB.H.
Database Tags
Each set of bits consists of a single bit for each client process or, more properly, for each
potential client process. A process does not officially become a client process until it registers
with the Kernel by initializing the calling process through a call to fl_proc_init( ), but the bits
still exist.
Change-status bits. For each database tag, each possible client process has one change-status
bit. If the value of a bit is 0, the value has not changed since client (or task) number N last read
the tag where N = 0 through 30. The value of the bit is set to 1 when a new value is written to
the tag.
Wait bits. Each possible client process has one wait bit. When the client is currently waiting to
read or to write the specified tag, the value of the bit is 1; otherwise, the value is 0. A client can
set the value of a wait bit to 1 by performing one of the following actions:
• Call fl_change_wait( ). This sets the value to 1 only if none of the specified tags has
changed (it sleeps until someone writes a new value into one or more of the tags).
• Call fl_set_wait( ).
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 tags.
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);
6
.
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
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 tag that holds a queue of mailbox messages consisting of structures (typedef
MBXMSG) and some associated message data. Since mailboxes are tags, a process can read
and write values to them just as with other types of database tags; that is, the following
functions work when passed to a mailbox tag:
• 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 tag is set to 1. When
the mailbox is empty, the change bit for the associated tag is clear (value of 0).
Signal 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.
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
fl_count_mbx Determines the number of messages in a mailbox, validates a
mailbox, or monitors a mailbox.
fl_query_mbx Queries a mailbox for a range of queued messages.
Function Description
6
fl_read_app_mbx Reads and dequeues a message from a mailbox.
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.
If the task sending the mailbox message is expecting a reply, it should put the mailbox tag of
where it wants the reply sent into the mm_mbx field of the mailbox message. If it does not
want a reply, it should set mm_mbx.t_type and mm_mbx.t_data to 1 (0xFFFF). Otherwise,
FL/LAN thinks it wants a reply and since it will never get one, FL/LAN’s internal table where
it stores pending replies will fill up.
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)
The symbolic representations of these error numbers are found in the header file FLIB.H.
Use the following lists (excerpts from FLDEFS.H) as references for error numbers.
Error
FactoryLink Error Codes Description
Number
FLE_INTERNAL 1 General error code.
FLE_OUT_OF_MEMORY 2 Memory allocation error because of
system exhaustion or FactoryLink
allocation.
FLE_OPERATING_SYSTEM 3 Unable to map Kernel semaphores.
FLE_NO_FLINK_INIT 4 Cannot locate Real-Time Database for
given {FLNAME}.
FLE_NO_PROC_INIT 5 Cannot locate Real-Time Database
area for {FLDOMAIN}+{FLUSER}.
FLE_BAD_FUNCTION 6 Reserved.
FLE_BAD_ARGUMENT 7 Bad input parameter passed into
function.
FLE_BAD_DATA 8 TAG structure received with an
invalid offset member.
FLE_BAD_TAG 9 TAG structure received with an
invalid type or offset member.
FLE_NULL_POINTER 10 Reserved.
FLE_NO_CHANGE 11 Change read/wait function call failed
because no changes for given tag
array.
FLE_PROC_TABLE_FULL 12 Maximum number of tasks has
registered for the given
{FLNAME}/{FLDOMAIN}/
{FLUSER}.
FLE_BAD_PROC_NAME 13 Invalid task name received.
Error
FactoryLink Error Codes
Number
Description 6
FLE_BAD_USER_NAME 14 Invalid user name received.
CT A CCESS S ERVICES
6
CT access functions allow client processes to access the CT archives. The term archive refers
Function Description
ct_open Opens a CT archive file.
ct_read_index Reads an index from a CT archive.
ct_read_hdr Reads the header for ctp into buffer.
ct_read_rec Reads a record from the current CT into memory.
ct_read_recs Reads records from the current CT into memory.
ct_close Closes a CT archive.
ct_create Creates/truncates/opens a CT for update.
ct_find_index Finds an index.
ct_get_hdrlen Gets the length of the current CT table header.
ct_get_name Gets the name of the current CT table.
ct_get_ncts Determines the number of CT tables in the archive.
ct_get_nrecs Determines the number of records in the last selected CT table.
ct_get_reclen Determines the record length of records in the current CT table.
ct_get_type Gets the type field from the current CT table.
O BJECT CT A CCESS
6
The object CT is a binary representation of a configuration database file similar to any other
The object CT API written using the PAK ct_...( ) primitives hides the details of how the object
database contents are coerced into a CT.
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)
{
printf(“Object %s in domain %s\n”, 6
flobjrec_get_name(rec), tgt_dom);
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
ct_find_obj Finds object definition for given object name.
ct_nrecs_obj Returns the number of object definitions held in CT.
ct_open_obj Opens object CT.
ct_read_obj Reads object definition(s) from object CT.
flobjrec_get_chgbits Extracts change bits attribute from object definition.
flobjrec_get_descr Extracts description attribute from object definition.
flobjrec_get_dimen Extracts dimension attribute from object definition.
flobjrec_get_domain Extracts domain attribute from object definition.
flobjrec_get_name Extracts the name from object definition.
flobjrec_get_perwhen Extracts persistence attribute from object definition.
flobjrec_get_tag Extracts tag attribute from object definition.
flobjrec_get_type Extracts type attribute from object definition.
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.
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
Function Description
fldtp_create Creates a DTP instance.
fldtp_destroy Destroys a DTP instance.
fldtp_get_comparef Get DTP comparison function pointer.
fldtp_get_msglen Get DTP message tag read buffer size.
fldtp_get_tagcnt Get DTP tag count.
fldtp_set_comparef Set DTP ID comparison function pointer.
fldtp_set_msglen Set DTP message tag read buffer size.
fldtp_set_proc_by Set DTP message tag read buffer size.
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.
Function Description
fldtp_action_get_args Get associated user-defined arguments.
fldtp_action_get_destroyf Get associated destruction notification function pointer.
Function Description
6
fldtp_action_get_id Get associated ID.
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
fldtp_insert Insert tag/action into DTP.
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
pointers to information related to the tag action. When processing tag actions, these pointers
are passed to the process function along with the tag value.
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
fldtp_remove Remove tag/action into DTP.
fldtp_remove_group Remove actions from DTP based on a criteria.
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 number 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 table. 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.
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
flntag_calc_base Calculates base tag address from arrayed tag.
flntag_calc_tag Calculates arrayed tag address from base tag.
flntag_create Creates FLNTAG instance.
flntag_destroy Destroys FLNTAG instance.
flntag_find_def Returns tag definition for given FLNTAG structure.
flntag_find_tag Returns tag definition for given TAG structure.
flntag_gen_objname Generates object name string.
flntag_gen_ref Generates tag reference string.
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
fl_xlate Translates keyword to its associated message.
fl_xlate_init Loads the first message file. The message
translation data structure is a tree.
fl_xlate_load Loads the specified file into the current translation
tree, replacing any duplicate keywords. The
function returns the number of entries loaded from
this file or returns ERROR.
fl_xlate_get_tree Returns the address of the current translation tree or
NULL if no translation files have been loaded.
fl_xlate_set_tree Sets the current translation tree to the tree at the
specified address.
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)
still loads /temp/test.txt into the tree and returns the number of translations.
Translating
char FAR *fl_xlate(char FAR *key)
6
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 */
Extended Characters
Because FactoryLink is translated into several languages, it is important to know that extended
characters present in foreign languages are interpreted by the various programs you use to edit
files.
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),
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>
int ct_close_obj(CT* objct);
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.
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>
int ct_find_obj(CT* objct, char* objname, FLOBJREC* rec;
CT _ GET _ HDRLEN
Get the length of the current CT table header.
Syntax include <flib.h>
int ct_get_hdrlen(CT* ctp);
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>
char *ct_get_name(CT* ctp);
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>
int ct_get_nrecs(CT* ctp);
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>
int ct_get_reclen(CT* ctp);
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>
int ct_nrecs_obj(CT* objct, u32* nrecs);
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>
int ct_open (CT* ctp, char* dirp, char* namep);
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>
int ct_open_obj(CT* objct, char* flapp);
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>
int ct_read_hdr(CT* ctp, void* hdrp);
CT _ READ _ INDEX
Read and index from a CT archive.
Syntax #include <flib.h>
int ct_read_index (CT* ctp, uint ndx);
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.
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>
int ct_read_rec(CT* ctp, void recp, uint rec);
Returns GOOD
CT_NULL_POINTER
CT_FILE_NOT_OPEN
CT_BAD_INDEX
CT_BAD_RECORD
CT _ READ _ RECS
Read records from the current CT into memory.
Syntax #include <flib.h>
int ct_read_recs(CT* ctp, void* recp, uint rec, uint recs);
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
Read the first tag that has changed since it was last read.
Syntax #include <flib.h>
int fl_change_read(id_t id, TAG* tp, uint n, uint* ip, void* vp);
Library
kernel.
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 tags in the real-time database. The calling
process is immediately informed (it is never blocked) as to whether any of the
specified tags changed since last read. ip specifies the first tag to examine; however,
in contrast to fl_change_wait( ), ip does not wrap around the tag array.
In the case of a message tag, be sure the m_ptr and m_mbx members of value area vp
are initialized.
In the case of a mailbox tag, the value passed back is the MBXMSG for the head
message without the associated message data.
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
tag, 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 tags in the real-time database. If any of these
tags 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 tags 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
tags 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 tag is first, ip is used in
wraparound fashion within the tag array.
In the case of a message tag, be sure the m_ptr and m_mbx members of value area vp
are initialized.
In the case of a mailbox tag, 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 tags.
Syntax #include <flib.h>
Library
Arguments id_t id in Caller’s FactoryLink ID.
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 tags 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 tags.
Syntax #include <flib.h>
int fl_clear_wait(id_t id, TAG* tp, uint n);
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
FL _ COUNT _ MBX
Determine the number of messages in a mailbox, validate a mailbox, or monitor a
mailbox.
Syntax #include <flib.h>
int fl_count_mbx(id_t id, TAG mbx, uint* np);
FL _ DBFMTT
7
Prepare a formatted string from a set of tag values.
Syntax #include <flib.h>
Library
Arguments id_t id in Task ID used to access real-time database.
FL _ ERRNO
Return the last FactoryLink error number generated by the calling process.
Syntax #include <flib.h>
int fl_errno(id_t id);
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 tags defined in the SHARED domain.
Library
GLOBAL.CT contains global tags available to all tasks. The GLOBAL.CT is
searched for a matching value for each member of the ids array. The associated tag 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 _ FORCED _ WRITE
Force-write a specified tag into the real-time database.
Syntax #include <flib.h>
int fl_forced_write(id_t id, TAG* tp, uint n, void* vp);
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 tags involved are awakened.
Library
Arguments id_t id in Caller’s FactoryLink ID.
FL _ GET _ COPYRT
Return a pointer to a copyright message for FactoryLink.
Syntax #include <flib.h>
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
Return the KENV structure of the client process.
Syntax #include <flib.h>
int fl_get_env(id_t id, KENV* uep);
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.
Library
encountering, and other similar information (another self-reporting mechanism). It is
passed directly from the Run-Time Manager to the Real-Time Graphics process for
display on the Run-Time Manager screen.
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.
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.
Library
involved.
uint n in Number of tags involved.
i16* dp out Pointer to description array to be returned.
u16* op out Pointer to offset array to be returned.
Returns GOOD
ERROR
Remarks The dp array is filled in with one of the following values that correspond to the tags
passed to it
Value Description
FL_BAD_DATA Tag is out-of-range (bad t_data field).
FL_BAD_TYPE Tag is a bad t_type field.
FL_UNDEFINED Tag is undefined.
FL_DIGITAL Tag is a digital (DIG).
FL_ANALOG Tag is an analog (ANA).
FL_MESSAGE Tag is a message (MSG).
FL_LANALOG Tag is a long analog (longana).
FL_FLOAT Tag is floating point (FLP).
FL_MAILBOX Tag 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 tags in
the tp array are valid, and ERROR if one or more of them is bad.
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.
FL _ GLOBAL _ TAG
7
Retrieve the tag number for one or more global tags.
Syntax #include <flib.h>
Library
uint n in Number of tags to read.
FL _ ID _ TO _ NAME
Translate a FactoryLink ID to a process name.
Syntax #include <flib.h>
int fl_id_to_name(id_t id, char* name);
FL _ LIMIT _ MBX
7
RTDB Access API.
Library
u16* klimp;
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.
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 tags via
fl_write( ) or fl_forced_write( ).
FL _ NAME _ TO _ ID
Translate a process name to a FactoryLink ID.
Syntax #include <flib.h>
id_t fl_name_to_id(id_t id, char* name);
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.
FL _ PATH _ ACCESS
7
Check file access mode for a given file.
Syntax #include <flpath.h>
Library
Arguments NPATH* path in Pointer to a previously allocated NPATH
structure containing a normalized path name
buffer.
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>
void fl_path_add(NPATH* path1, NPATH* path2);
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
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
FL _ PATH _ CLOSEDIR
7
Ends a directory search for a file.
Syntax #include <flpath.h>
Library
Arguments NPATH* path in Pointer to a previously allocated NPATH structure
containing a normalized path name buffer.
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>
int fl_path_create(NPATH* path);
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>
NPATH *fl_path_cwd(NPATH* path);
FL _ PATH _ DATE
Places formatted system date and time stamp from a specified file's header into
specified buffer.
Syntax #include <flpath.h>
long fl_path_date(NPATH* path, char* buf, size_t length);
Library
containing a normalized path name buffer.
FL _ PATH _ INFO
Initialize date, time, size, and type of files allowed for the specified path.
Syntax #include <flpath.h>
int fl_path_info(NPATH* path);
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( ).
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
FL _ PATH _ NORM
7
Convert part or all of a system-specific path string into a normalized path.
Syntax #include <flpath.h>
Library
Arguments NPATH* path in/out Pointer to a previously allocated NPATH structure
containing a normalized path name buffer.
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>
int fl_path_opendir(NPATH* path);
Returns GOOD
ERROR
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);
See also “fl_path_opendir”
“fl_path_closedir” and related calls
FL _ PATH _ REMOVE
7
Delete the file specified by the complete path given.
Syntax #include <flpath.h>
Library
Arguments NPATH* path in Pointer to a previously allocated NPATH structure
containing a normalized path name buffer.
FL _ PATH _ RMDIR
Delete the directory specified by the directory portion of the indicated path.
Syntax #include <flpath.h>
int fl_path_rmdir(NPATH* path);
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
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
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_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
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
FL _ PATH _ SYS
7
Convert a normalized path into a system-specific path string.
Syntax #include <flpath.h>
Library
Arguments NPATH* path in Pointer to a previously allocated NPATH
structure containing a normalized path name
buffer.
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 _ PROC _ EXIT
Detaches the task from the kernel.
Syntax #include <flib.h>
int fl_proc_exit(id_t id);
Returns GOOD
ERROR
Remarks This function renounces all further access to the real-time database.
FL _ PROC _ INIT
7
Initialize the FactoryLink calling process.
Syntax #include <flib.h>
Library
maximum, null-terminated.
char* desc in Pointer to process description, 80 characters
maximum, null-terminated.
Returns If successful at registering the start-up process with the kernel, function returns the
calling routine FactoryLink task ID.
If unsuccessful, function 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
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 be written to use fl_proc_init_app( ) to register with the kernel. Any
task, even one written for a previous release, may now override the environment
values (use command arguments), if desired, by calling fl_proc_init_app( ). This API
now calls the new version.
The current fl_proc_init( ) is now implemented as:
int fl_proc_init(char* task, char* desc)
{
char flname[MAX_USR_NAME] ;
char fluser[MAX_USR_NAME] ;
char fldomain[MAX_USR_NAME];
fl_getvar(FLNAME, flname, sizeof(flname)) ;
fl_getvar(FLDOMAIN, fldomain, sizeof(fldomain)) ;
fl_getvar(FLUSER, fluser, sizeof(fluser)) ;
return fl_proc_init_app(task,desc,flname,fldomain,fluser);
}
See also “fl_proc_init_app”
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
Remarks A calling process must pass a process name and description to fl_proc_init_app( ).
After validating the name, the kernel returns the FactoryLink ID for use in subsequent 7
kernel calls to identify the caller.
Multiple threads of a single process can execute separate fl_proc_init_app( )s. In
Library
thread uses an ID not initially assigned to it.
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);
FL _ READ
Read specified tags from the real-time database.
Syntax #include <flib.h>
int fl_read(id_t id, TAG* tp, uint n, void* vp);
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 tags may have mixed data types, as with all database access calls. The values of
the tags are read from the real-time database and placed in the private data area of the
calling process pointed to by vp. After each tag is read, its change bit for the calling
process is cleared. The change state for other client processes are unaffected. When
reading blocks of mixed tag types, use fl_get_tag_info( ) to find out how much
memory to prepare before calling fl_read( ) when reading blocks of mixed tag types.
See also “fl_read_no_clear”
Library
Arguments id_t id in Caller’s FactoryLink ID.
id_t rid in FactoryLink ID of process owning the
mailbox.
MBX mbx in Mailbox to be accessed.
MBXMSG* msg out Pointer to a single mailbox message to be
returned.
uint i in Index relative to head of queue.
LE_NULL_POINTER
FLE_BAD_TAG
FLE_NOT_MAILBOX
FLE_NO_MESSAGES
FLE_ACCESS_DENIED
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 be written to use fl_read_app_mbx( ) with additional capabilities
for multi-user systems. fl_read_mbx( ) can only be used to send messages to tasks in
the same domain instance.
The following function call:
fl_read_mbx(id, &mbxtag, mmp, 0) ;
is equivalent to:
fl_read_app_mbx (id, id, &mbxtag, mmp, O) ;
FL _ READ _ NO _ CLEAR
7
Syntax #include <flib.h>
int fl_read(id_t id, TAG* tp, uint n, void* vp);;
Library
TAG* tp in Pointer to tag array specifying which tags to
read.
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 _ SEND _ SIG
Send a signal to a target process.
Syntax #include <flib.h>
int fl_send_sig(id_t id, char* name, int sig);
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.
Note the following function:
fl_ set_term_flag(id, name) ;
Library
Syntax #include <flib.h>
int fl_set_chng(id_t id, TAG* tp, uint n);
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 tags 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.
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”
Library
Arguments id_t id in Task ID.
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_PROC_NAME
FLE_NO_PROC_INIT
Remarks Set the termination flag of a client process within the same domain as the caller,
which may be different from the calling process. Normally, only the Run-Time
Manager uses this service.
FL _ SET _ WAIT
Set the calling task wait flags for specified tags.
Syntax #include <flib.h>
int fl_set_wait(id_tid, TAG* tp, uint n);
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
FL _ SLEEP
Delay execution of the task for the indicated number of milliseconds.
Syntax #include <flib.h>
void fl_sleep(ulong msecs);
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
7
Unlock the real-time database for the calling process.
Syntax #include <flib.h>
Library
Returns GOOD
ERROR: if error, call the fl_errno( ) function with the caller's FactoryLink ID for
details.
Remarks Calls to fl_lock( ) and fl_unlock( ) nest; one call to fl_unlock( ) undoes one previous
call to fl_lock( ).
FL _ WAIT
Wait to read, write, or access the real-time database or certain tags in the database.
Syntax #include <flib.h>
int fl_wait(id_t id, int req);
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.
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 tags may have mixed data types. The values of the tags 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 tag. If the new value of the tag is
different from its previous value, the tag change state for all client processes is set to
ON after it is written. Those processes waiting on a change to this tag 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
This allocates space for the message based on the value of m_max but will not set the
change flag for the tag. This works only if no prior writes to the message tag have 7
occurred.
Library
Syntax #include <flib.h>
int fl_write_app_mbx(id_t id, id_t wid, TAG mbx, MBXMSG* msg);
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.
FL _ WRITE _ MBX
Write and queue a message into a mailbox. (Obsolete. See fl_write_ app_mbx( )).
Syntax #include <flib.h>
int fl_write_mbx(id_t id, TAG mbx, MBXMSG* mmp);
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) ;
FL _ XLATE
7
Translate a key to its associated message.
Syntax #include <flib.h>
Library
Arguments char* key in Pointer to key to search for.
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>
int fl_xlate_init (char* name, char* bp, uint blen);
Library
FL _ XLATE _ LOAD
Load the specified file (passed as a parameter) into the current translation tree
replacing any duplicate key.
Syntax #include <flib.h>
int fl_xlate_load (char* fname);
Library
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 */
int num_msg1, num_msg2;
num_msg1 = fl_xlate_init(english/iml, NULL, 0);
english = fl_xlate_get_tree();
num_msg2 = fl_xlate_init(french/iml, NULL, 0);
french = fl_xlate_get_tree();
fl_xlate_set_tree (english); /* Switch to English tree */
printf (%s\n, fl_xlate(token);
fl_xlate_set_tree (french); /* Switch to French tree */
printf (%s\n, fl_xlate(token);
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”
french = fl_xlate_get_tree();
fl_xlate_set_tree (english); /* Switch to English tree */ 7
printf (%s\n, fl_xlate(token);
fl_xlate_set_tree (french); /* Switch to French tree */
Library
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”
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”
Library
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( ).
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_destroy”
“fldtp_action_set_args”
“fldtp_remove”
“fldtp_remove_group”
“fldtp_destroy”
Library
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
Remarks Function fldtp_action_set_priority( ) binds a processing priority to the given action
record. The action record priority controls the order simultaneous tag changes are
processed in. The default priority for action records in 0.
The priority is only considered when the DTP is processing by priority.
See also “fldtp_action_get_priority”
“fldtp_set_proc_by”
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”
FLDTP _ CREATE
Syntax #include <fldtp.h>
int fldtp_create(FLDTP* dtp);
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
7
Syntax #include <fldtp.h>
int fldtp_destroy(FLDTP* dtp);
Library
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
Remarks Function fldtp_get_comparef( ) returns the function used when comparing the IDs
associated with an action record.
See also “fldtp_get_compare”
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”
FLDTP _ INSERT
7
Syntax #include <fldtp.h>
int fldtp_insert(FLDTP* dtp, TAG* tag, FLDTP_FUNC_ACTION afunc, FLDTP_ACTION** ap);
Library
FLDTP_FUNC_ACTION afunc in Function to process tag with.
fldtp_action** ap out Record created by insertion.
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”
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_proc( ) immediately invokes all action records inserted into the given
DTP. For each action record, the associated tag is read and its action function invoked
with the tag value. Only a single pass through the tags is made.
See also “fldtp_proc_wait”
“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”
Library
id_t task_id in Task handle.
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks Function fldtp_proc_change( ) invokes the action functions bound to those tags
within the DTP that have changed. Only a single pass through the tags is made.
This function is similar to function fldtp_proc_wait( ), except it does not put the task
to sleep. Hence, the function is most useful for tasks that must poll the real-time
database because they are waiting on external events (network traffic, GUI events).
See also “fldtp_proc_wait”
“fldtp_set_proc_by”
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.
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
processed before the function returns to the caller.
Function fldtp_proc_wait ( ) is the most commonly used of the DTP process
functions.
See also “fldtp_proc_change”
“fldtp_set_proc_by”
FLDTP _ REMOVE
Syntax #include <fldtp.h>
int fldtp_remove(FLDTP* dtp, FLDTP_ACTION* ap);
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.
Library
#include <fldtp.h>
int fldtp_remove_group(FLDTP* dtp, TAG* tag,
FLDTP_FUNC_ACTION afunc, void* id);
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
Remarks fldtp_set_comparef( ) establishes the function to use when comparing the IDs
associated with an action record. Typedef FLDTP_FUNC_COMPARE defines the
Syntax to which the comparison function must conform:
typedef int (*FLDTP_FUNC_COMPARE) (void* , void*);
#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”
Library
int msglen in New length for message read buffer.
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.
FLDTP _ WAIT
Syntax #include <fldtp.h>
int fldtp_wait(FLDTP* dtp, id_t task_id);
Returns FLDTP_E_GOOD
FLDTP_E_{…} error code
Remarks fldtp_proc_wait( ) is analogous to fl_wait( ) in that the task goes to sleep until one of
the tags inserted into the DTP changes. Unlike the PAK function, fldtp_wait( ) returns
immediately if one of the tags within the DTP has changed prior to invoking this
function.
See also “fldtp_proc_change”
Library
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 _ CREATE
Normalized Tag API.
Syntax #include <flntag.h>
FLNTAG* flntag_create(void);
Returns This function returns:
Type Description
Library
FLNTAG _ DESTROY
Normalized Tag API.
Syntax: #include <flntag.h>
FLNTAG* flntag_destroy(FLNTAG* ntag);
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.
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 tag.
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”
Library
int flntag_gen_str(FLNTAG* ntag, u16 incl, char* outstr, int maxlen);
#define flntag_gen_objname(ntag, outstr, maxlen) \ flntag_gen_str(ntag,FLNTAG_S_DIMEN, outstr, maxlen);
#define flntag_gen_ref(ntag, tagref, maxlen) \
flntag_gen_str(ntag, 0, tagref, maxlen);
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
i16 flntag_parse_comma4dims(char* dimstr, u16* dims, u16 dimslen);
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”
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”
Library
Syntax #include <flntag.h>
int flntag_set_dimen(FLNTAG* ntag, char* dimen);
int flntag_set_member(FLNTAG* ntag, char* member);
int flntag_set_name(FLNTAG* ntag, char* name);
int flntag_set_node(FLNTAG* ntag, char* node);
Arguments FLNTAG* ntag in/out FLNTAG whose components are being set.
char* value in Target set value.
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].
Returns VALUE
Remarks This set of flobjrec_get_…( ) functions allows the caller to obtain an attribute value
from an object definition.
While most of the return values are self-explanatory, a few require more detail.
Function flobjrec_get_chgbits( ) refers to a persistence attribute, namely whether to
set the change bit on when restoring the persistent value. The value is 1 for
set-the-change-bit and 0 for not.
Function flobjrec_get_perwhen( ) refers to a persistence attribute, namely whether to
save the object value based on time, on value change, or on domain persistence
settings. The legal values for this attribute are as follows
Value Meaning
0 No persistence of value.
1 Timed-based persistence.
2 Exception-based persistence.
7
3 Time-based and exception-based persistence.
4 Domain setting persistence.
Library
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.
To maintain backward compatibility with previous releases, make_full_path( ) has
been retained in FLIB, but it is currently implemented using the fl_path( ) functions.
For new development, fl_path( ) functions should be used.
void make_full_path(pathp, dirp, filep)
{
NPATH *p1;
NPATH *p2;
p1 = fl_path_alloc( );
p2 = fl_path_alloc( );
if ( dirp == NULL )
fl_path_free(p1);
fl_path_free(p2);
}
See also fl_path( ) and related functions
SPOOL
7
Spool a file or line.
Syntax #include <flib.h>
Library
Arguments id_t id in Caller’s FactoryLink ID.
char* flags in Pointer to zero-terminated string.
String specifies file or line to be
printed, output device to be used
(Devices 1 through 5), type of data
(text or binary) to be expected, and
whether to delete the file (assuming
file, not line, is specified) after
successful printing. The following
recognized characters determine these
actions and may or may not display in
the string.
Char. Action
B Use binary mode in
reading and printing file
or line. Send Binary ON
command sequence before
beginning and Binary
OFF sequence upon
completion of print job.
D Delete file after
successful printing.
L Print line that follows
(message specifies line
to be printed).
# Use output Device
number # (where # stands
for digit from 1-5 with
default = 1).
char* message in Pointer to character string.
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
Remarks The SPOOL function is related to the FactoryLink Print Spooler task.
Print Spooler Task 7
The Print Spooler processes job requests from other FactoryLink tasks running on the
Library
specify what file or line is to be printed, which output device is to be used, and what
type of data (text or binary) printed.
When the SPOOL task receives a job request, it checks to see whether the designated
output device is processing earlier requests. If the output device is busy, it queues, or
spools, the current request. Otherwise, it processes the request immediately. Requests
queued for later processing are not prioritized. In effect, printing occurs on all output
devices simultaneously.
EXAMPLES
The following examples in C illustrate how to use the SPOOL function:
Example 1
int spool(id, “2", ”C:/CONFIG.SYS", 0);
MEANING: Print the indicated text file on Device 2.
Example 2
int spool(id, “L”, “** WARNING: Line pressure LOW. *”, 0);
MEANING: Print the indicated line on Device 1 (the default printer).
Example 3
int spool(id, B3, C:/{FLINK}/USR/TASK.DAT, 0);
MEANING: Print the indicated binary data file on Device 3.
Example 4
int spool(id, D, C:/SOURCE/TEST.LOG, 0);
MEANING: Print the indicated text file on Device 1 and delete the file afterwards.
In all of these examples, the value of int should be checked. The only possible return
values in these examples are -2 through 2.
•
•
•
•
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
Type: Long
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
Parameters:
8
Application Objects
Type: String
Access: In
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
Public: Yes
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
Public: Yes
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
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
•
•
•
•
•
325
•
•
•
•
•
•
•
•
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.
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
flCfgSeq Configuration database sequence field handle.
Architecture
flCfgFld Configuration database data field handle.
The following graph depicts how these structures are linked to each other. The library services
provide entry points your CFGPAK program can navigate through this hierarchy with and
obtain the desired handle.
flCfgSess
flCfgAC
flCfgCDB
flCfgCDB
flCfgAC
flCfgCDB
flCfgCDB
flCfgDom
flCfgSeq
flCfgFld 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, flCfgKey)
• Configuration Text File API (flCfgText)
• Object Database API (flCfgObj, flCfgTag) 10
• Exception Handling
Services
directory {FLINK}/src/examples/skeleton where {FLINK} is the location of the FactoryLink
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_num_hdrcdb Gets number of ACs within the session FLINK.
flCfgAC_num_text Get the number of text file groups defined within the AC.
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.
Services
....
/* Open/create the tables defined within the SKEL AC */
if ((rv = flCfgAC_open_cdbs(cfgacp, 1)) != FLCFG_E_GOOD)
{
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.
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.
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.
flCfgFld_get_default_tagtype Get the field’s default tag type (for tag fields).
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.
flCfgFld *cfgfldp;
int m, n;
flCfgCDB_get_domfld(cfgcdbp, &cfgdomp);
if (cfgdomp != NULL)
{
for (n = 0; n < indent; n++)
printf("\t");
printf("Domain: %s(%d) - Domain Field\n",
flCfgDom_get_name(cfgdomp),
flCfgDom_get_size(cfgdomp));
}
for (m = 0; m < flCfgCDB_num_selfld(cfgcdbp); m++)
{ 10
flCfgCDB_nth_selfld(cfgcdbp, m, &cfgselp);
Services
printf("Select: %s(%d) - %s\n",
flCfgSel_get_name(cfgselp),
flCfgSel_get_size(cfgselp),
flCfgSel_get_title(cfgselp));
}
flCfgCDB_get_seqfld(cfgcdbp, &cfgseqp);
if (cfgseqp != NULL)
{
for (n = 0; n < indent; n++)
printf("\t");
printf("Sequence: %s(%d) - Sequence Field\n",
flCfgSeq_get_name(cfgseqp),
flCfgSeq_get_size(cfgseqp));
}
for (m = 0; m < flCfgCDB_num_fld(cfgcdbp); m++)
{
Code Sample
DLLEXPORT int flCfgKey_num(flCfgKey *cfgkeyp);
DLLEXPORT int flCfgKey_nth_label(flCfgKey *cfgkeyp, int n, char **label);
DLLEXPORT int flCfgKey_nth_token(flCfgKey *cfgkeyp, int n, char **token);
DLLEXPORT int flCfgKey_nth_id(flCfgKey *cfgkeyp, int n, long *id);
flCfgCDB_ select_criteria Reads header’s select values into the relate CDB.
flCfgCDB_ select_first Moves to the first row that meets selection criteria.
flCfgCDB_ select_last Moves to the last row that meets selection criteria.
flCfgCDB_ select_next Moves to the next row that meets selection criteria.
flCfgCDB_ select_previous Moves to the previous row that meets selection criteria. 10
flCfgCDB_ select_rowno Moves to row with the given number.
Services
flCfgCDB_ nth_relatecdb Gets handle of nth related 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
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.
In the code sample above , the CDB handle and selection domain are passed into the function.
The steps in this procedure include:
2 Once the selection has begun, adjust the selection criteria for the given domain and then
position on the first record matching this criteria.
Services
dump_cdb_contents(relcdbp, NULL, indent+1);
}
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
rv = RV_GOOD;
break;
case FLCFG_E_VALERR:
printf("Validation Error: %s(%s): %s\n",
flCfgValErr_get_fldname(&valerr),
flCfgValErr_get_fldvalue(&valerr),
flCfgValErr_get_valmsg(&valerr));
rv = RV_ERROR;
break;
default:
printf("Insert error: %d\n", rv);
rv = RV_ERROR;
break;
}
return rv;
}
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.
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:
printf("Insert error: %d\n", rv);
rv = RV_ERROR;
break; 10
}
Services
Updating a Row Within a CDB
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.
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;
default:
printf("Update error: %d\n", rv);
rv = RV_ERROR; 10
break;
Services
else
{
rv = RV_ERROR;
}
....
. End the open selection held open for the update: flCfgCDB_select_end(skelp);
....
return RV_GOOD;
}
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.
found = 0;
while (rv == FLCFG_E_GOOD)
{
flCfgFld_get_value(tblfldp, tblval, tblsize);
if (strcmp(tblval, tbl) == 0)
{
flCfgCDB_select_delete(skelp); 10
rv = flCfgCDB_select_current(skelp);
Services
{
rv = flCfgCDB_select_next(skelp);
}
}
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.
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>.
Consider the following sequence of events that may occur in the absence of a lock on the CDB.
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 10
the lock is held; therefore, the lock should be held as long as required to protect the entire
transaction but released immediately upon completion.
flCfgText_get_filespec Gets the file specifier for the text file group.
FactoryLink application configuration not only includes databases, but text files as well.
Within an AC file, a file specifier defines the location and name of text files that are part of the
AC task’s configuration. This file specifier may reference a single file, or it may contain a
wildcard that references a group of files. The file specifier may also indicate that the text file
location depends on a domain.
Examples of currently existing configuration text files are math and logic procedure files,
report format files, and FLLAN group definition files.
The location and number of configuration text files varies depending on the file specifier. The
following table should assist in choosing the correct API functions to navigate a particular file
specifer.
Example File
Implied Location Appropriate API Sequence
Specifier
Services
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.
Services
flCfgTag_set_attrval Sets value of tag definitions attribute.
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.
Attribute ID Description
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.
Services
return;
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.
default:
printf("Insert error: %d\n", rv);
rv = RV_ERROR;
break;
}
....
. Subsequently destroy flCfgTag and flCfgValErr structures and continue work.
....
Services
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.
{
printf("Unable to locate tag to rename: %s\n", tagname);
rv = RV_ERROR;
}
flCfgObj_select_end(objp);
....
. Subsequently destroy flCfgTag and flCfgValErr structures and continue work.
....
Services
tag or its members, then the removal of the structured tag deletes the member tags.
Services
FLCFG_E_INVUPD -21 Relate CDBs cannot update domain/select fields.
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
Furthermore, for more exotic activities, input from the user is necessary to direct the lower
level CFGPAK functions how to proceed.
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.
Services
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.
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
FL C FG AC_ GET _ GUID
FL 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_guid(flCfgAC *cfgacp);
char* flCfgAC_get_filename(flCfgAC *cfgacp);
char* flCfgAC_get_task(flCfgAC *cfgacp);
char* flCfgAC_get_title(flCfgAC *cfgacp);
Reference Library
Config PAK API
whose range of legal values is dependent on the contents of another table.
See Also “flCfgAC_nth_hdrcdb”
“flCfgSess_nth_ac”
Remarks Function flCfgCDB_find_fld( ) returns the handle to the field whose name matches the
given name. Given this handle, the field properties can be accessed.
See Also “flCfgCDB_nth_fld”
“flCfgCDB_num_fld”
Reference Library
Config PAK API
Returns Success: FLCFG_E_GOOD.
Failure: FLCFG_E_{...} error code.
Remarks Function flCfgCDB_find_selfld( ) returns the handle to the select field whose name
matches the given name. Given this handle, the field properties can be accessed.
See Also “flCfgCDB_nth_selfld”
“flCfgCDB_num_selfld”
Remarks Function flCfgCDB_get_seqfld( ) returns the handle to the sequence field structure
for the given CDB. The value of the sequence field determines the order that
Configuration Explorer presents the rows. Sequence values are unique among all
rows sharing the same selection criteria. In other words, the sequence number is
unique among all rows sharing the same combination of domain and selection field
values.
Most CDBs have a sequence field. For those that do not, error code
FLCFG_E_NOTFOUND is returned.
See Also “flCfgCDB_get_domfld”
“flCfgCDB_nth_selfld”
“flCfgCDB_nth_fld”
Reference Library
Config PAK API
Arguments flCfgCDB* cfgcdbp in CDB to get attribute
FL C FG CDB_ LOCK
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgCDB_lock(flCfgCDB *cfgcdbp, int incl_relcdbs);
Reference Library
Config PAK API
Syntax #include <flcfg.h>
int flCfgCDB_nth_selfld(flCfgCDB *cfgcdbp, int n, flCfgSel **selfldp);
Remarks Function flCfgCDB_row_insert( ) inserts a record into the given CDB, using the
values found within the CDB structure itself. Field level validation is performed, and
any such errors abort the insert. Specifics about the validation error are returned in the
flCfgValErr structure. Relations, such as whether the parent record exists, are not
checked.
When a record is inserted, a sequence number is usually associated with it. If the
given sequence value is zero, then the row is assigned the next largest sequence
number appropriate for the row's relations. Unless you have specific ordering needs, it
is best to allow flCfgCDB_row_insert( ) to assign the next available sequence number
by setting the sequence value to zero.
Function flCfgCDB_row_insert( ) updates the cross-reference (XREF) database with
any tag references contained within the inserted row.
See Also “flCfgCDB_row_validate”
Reference Library
Syntax #include <flcfg.h>
The selection criteria equates to the field values held in the domain and select fields,
as defined within the CDB schema. For selections from header CDBs, the user should
subsequently update the selection criteria by setting the domain field value since no
control record exists to derive the desired selection domain from.
Selections cannot be nested. If attempted, code FLCFG_E_SELBEGUN is returned.
The outstanding selection must be ended prior to initiating a subsequent selection.
See Also “flCfgCDB_select_first”
“flCfgCDB_select_next”
“flCfgCDB_select_end”
“flCfgDom_set_value”
“flCfgSel_set_value”
Reference Library
int flCfgCDB_select_criteria(flCfgCDB *cfgcdbp);
Deletions will be disallowed if any one of the related CDBs to which the deletion may
be propagated to is held open by an active selection.
See Also “flCfgCDB_select_begin”
“flCfgCDB_select_current”
Reference Library
Config PAK API
behalf of a selection. For every selection begun, a corresponding end should be
issued.
See Also “flCfgCDB_select_begin”
“flCfgCDB_select_first”
“flCfgCDB_select_next”
FL C FG C BD _ SELECT _ LAST
Object Database API
Syntax #include <flcfg.h>
int flCfgCDB_select_last(flCfgDB *Cfgcdbp);
Arguments flCfgCDB* cfgcdbp in CDB handle.
Returns Success:FLCFG_E_GOOD
Failure:FLCFG_E_{...} error code
Description Function flCfgCDB_select_last() takes the values currently set as the selection
criteria and reads the last row that matches it. A call to function
flCfgCDB_select_begin() must precede this call. If no rows match the selection
criteria, then error code FLCFG_E_ENDOFSEL is returned.
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 has been begun, 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_previous
flCfgCDB_select_end
flCfgDom_get_value
flCfgSel_get_value
flCfgFld_get_value
Reference Library
Config PAK API
See Also “flCfgCDB_select_begin”
“flCfgCDB_select_first”
“flCfgCDB_select_end”
“flCfgDom_get_value”
“flCfgSel_get_value”
“flCfgFld_get_type”
Reference Library
Updates are disallowed if any one of the related CDBs the update would be
FL C FG CDB_ UNLOCK
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgCDB_unlock(flCfgCDB *cfgcdbp, int incl_relcdbs);
FL C FG D OM _ GET _ NAME
Configuration Database API.
Syntax #include <flcfg.h>
char* flCfgDom_get_name(flCfgDom *cfgdomp);
FL C FG D OM _ GET _ SIZE
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgDom_get_size(flCfgDom *cfgdomp);
FL C FG D OM _ GET _ VALUE
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgDom_get_value(flCfgDom *cfgdomp, char *domval, int maxlen);
Reference Library
Config PAK API
FL C FG D OM _ SET _ VALUE
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgDom_set_value(flCfgDom *cfgdomp, char *domval);
FL C FG F LD _ GET _ FLAG
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgFld_get_flag(flCfgFld *cfgfldp, int id);
Reference Library
Config PAK API
FLCFGFLD_FLAG_HEX Field is hexadecimal.
FLCFGFLD_FLAG_OCTAL Field is octal.
FLCFGFLD_FLAG_RANGE Field does apply range check.
FLCFGFLD_FLAG_READONLY Field is read-only.
FLCFGFLD_FLAG_UPPERCASE Field forces all values to uppercase.
FL C FG F LD _ GET _ HIGH
Configuration Database API.
Syntax #include <flcfg.h>
char* flCfgFld_get_high(flCfgFld *cfgfldp);
FL C FG F LD _ GET _ LOW
Configuration Database API.
Syntax #include <flcfg.h>
char* flCfgFld_get_low(flCfgFld *cfgfldp);
Reference Library
Configuration Database API.
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 _ TYPE
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgFld_get_type(flCfgFld *cfgfldp, int id);
Reference Library
Config PAK API
FLCFGFLD_TYPE_NUMBER Numeric string.
FLCFGFLD_TYPE_KEY Alphanumeric string from restrictive list.
FLCFGFLD_TYPE_TAG Tag names
FLCFGFLD_TYPE_TAGCHAR Tag name or alphanumeric string
FLCFGFLD_TYPE_TAGNUM Tag names or numeric string
FLCFGFLD_TYPE_TAGKEY Tag names or string from list.
FL C FG F LD _ GET _ VALUE
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgFld_get_value(flCfgFld *cfgfldp, char *value, int maxlen);
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 K EY _ GET _ FILENAME
Configuration Database API.
Syntax #include <flcfg.h>
char* flCfgKey_get_filenamee(flCfgKey *cfgkeyp);
FL C FG K EY _ NTH _ LABEL
FL C FG K EY _ NTH _ ID
FL C FG K EY _ NTH _ TOKEN
Configuration Database API.
Syntax #include <flcfg.h>
int flCfgKey_nth_label(flCfgKey *cfgkeyp, int n, char **label);
int flCfgKey_nth_id(flCfgKey *cfgkeyp, int n, long *id);
int flCfgKey_nth_token(flCfgKey *cfgkeyp, int n, char **token);
Reference Library
Config PAK API
Returns Success: FLCFG E GOOD
Failure: FLCFG_E_{...} error code.
Remarks Function flCfgKey_nth_label( ) returns the the label of the nth in the given key file.
The label is a language-specific string value. Use this string when setting the
associated field’s value, for this is what the field validation routines expect..
Function flCfgKey_nth_id( ) returns the numeric ID of the nth in the given key file.
This value is more applicable to CTGEN and the run-time environment than
configuration time.
Function flCfgKey_nth_id( ) returns the token of the nth in the given key file. The
token is a language-independent string value. Do not use this string when setting the
associated field’s value. The token string is stored in the configuration databases,
thus keeping the application configuration language independent.
See Also “flCfgFld_get_key_tagtypes”
“flCfgFld_get_key_values”
FL C FG O BJ _ ADD
Object Database API.
Syntax #include <flcfg.h>
int flCfgObj_add(flCfgObj *objp, flCfgTag *tagp,flCfgValErr *valerr);
FL C FG O BJ _ GET _ CDB
Object Database API.
Syntax #include <flcfg.h>
int flCfgObj_get_cdb(flCfgSess *sess, flCfgCDB **objp);
Reference Library
Config PAK API
FL C FG O BJ _ SELECT _ BEGIN
Object Database API.
Syntax #include <flcfg.h>
int flCfgObj_select_begin(flCfgObj *objp);
FL C FG O BJ _ SELECT _ DELETE
Object Database API.
Syntax #include <flcfg.h>
int flCfgObj_select_delete(flCfgObj *objp);
For structured tags, this constraint includes references to any of its member tags. If
there are no references to a structured tag and its members, then the delete call
removes both the currently selected tag and all of its members.
See Also “flCfgKey_get_filename”
FL C FG O BJ _ SELECT _ END
Object Database API.
Syntax #include <flcfg.h>
int flCfgObj_select_end(flCfgCDB *objp);
Reference Library
Failure: FLCFG_E_{...} error code.
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 _ LAST
Object Database API
Syntax #include <flcfg.h>
int flCfgObj_select_last(flCfgObj *objp, flCfgTag *tagp);
FL C FG O BJ _ SELECT _ NAME
Object Database API.
Syntax #include <flcfg.h>
Reference Library
Config PAK API
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>
FL C FG O BJ _ SELECT _ PREVIOUS
Object Database API.
Syntax #include <flcfg.h>
int flCfgObj_select_previous(flCfgObj *objp);
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
“flCfgObj_select_delete”
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
FL C FG S ESS _ OPEN
Configuration Session API.
Syntax #include <flcfg.h>
int flCfgSess_open(char *flink, char *flapp, flCfgSess **sess);
FL C FG TAG _ CREATE
FL C FG TAG _ DESTROY
Object Database API.
Syntax #include <flcfg.h>
int flCfgTag_create(flCfgTag **tagp);
int flCfgTag_destroy(flCfgTag **tagp);
Reference Library
See Also “flCfgKey_get_filename”
flCfgTag_get_attrval( ):
int id in Attribute ID
Reference Library
See Also “flCfgAC_nth_text”
Arguments flCfgText* cfgtextp in Text file group handle from which to get file
specifier
Arguments flCfgText* cfgtextp in Text file group handle from which to get title
Remarks Function flCfgText_get_title( ) returns the title associated with the given handle.
See Also “flCfgAC_nth_text”
Reference Library
Config PAK API
For cases where only a single text file applies to the given handle, this function
returns error FLCFG_E_TEXTONE. For this case, an iterator is not needed to access
what files belong to the text group. Function flCfgText_get_filepath() should be
called to locate the file path instead.
See Also “flCfgAC_nth_text”
“flCfgText_select_first”
“flCfgText_select_end”
“flCfgText_set_domain”
Remarks Function flCfgText_select_end( ) positions the iterator on the first file that is a
member of the text file group cfgtxtp. This function should be invoked once the
selection through the files is complete.
See Also “flCfgText_select_begin”
Reference Library
Config PAK API
Remarks Function flCfgText_set_domain( ) sets the current domain from which text files shall
be selected.
For cases where text files for the given handle are not domain specific, this function
returns error FLCFG_E_NOTFOUND.
See Also “flCfgAC_nth_text”
“flCfgText_select_begin”
“flCfgText_get_domain”
Reference Library
Config PAK API
Remarks Function flCfgValErr_get_…( ) returns the specifics associated with a validation
error.
See Also “flCfgText_get_domain”
•
•
•
•
•
•
•
•
•
•
•
•
•
435
•
•
•
•
•
•
•
•
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}\INC\MCI3.H
• {FLINK}\INC\MCI3_FMT.H
• {FLINK}\INC\MCI3_INT.h
• {FLINK}\LIB\MCI3.LIB
{FLINK} designates which FLINK environment setting or directory the FactoryLink system 13
software has been installed in.
The two tasks communicate with one another via FactoryLink mailbox tags. The IOX task
makes requests upon the driver task to send and fetch data to/from a device, such as an RTU or
PLC. The driver task concerns itself only with communicating with an external device. The
IOX task provides all data conversions and tag storage.
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.
or
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 452 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 452 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 table (the driver used in this example is called Widget).
The following IOX Dataset Definition table shows a reference to the same dataset defined in
the driver Dataset Definition table. 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 tags starting with the tag at address 1.
Therefore, if a READ request occurs on the dataset analog_ds[0], 20 consecutive tags, residing
in the external device, starting at address 1 are stored in widget_analogs[0] (tag at address 1, tag
at address 2, tag at address 3 … tag at address 20).
For purposes of this illustration, the tags 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 table, but they are explained in detail in the I/O
Translator information on the documentation CD.
1. The IOX task determines a READ or WRITE trigger has occurred for a referenced dataset
• The IOX task creates a mail message and sets certain parameters in the message based on
the given dataset.
• The message is mailed to the driver owning the dataset.
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.
The following depicts the flow of a dataset from the IOX task to the protocol driver.
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
14
The external device may have internal regions allocated for IMX Messaging
data storage dedicated to certain data types. For example, this
external device may have address regions reserved for analog
(16 bit words) data.
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.
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)
mm_type.type = MCI_READ_REQ
mm_type.ident = MCI_TAG
mm_type.more = Not applicable
mm_type.ident = local host direction
mm_type.station_id = local station id
mm_user1 = Job sequence number
mm_user2 = dataset control tag
mm_sendid = IOX FactoryLink Task ID
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 14
response looks similar to the following:
Block Read Response MBXMSG Structure
IMX Messaging
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
m_type.more = not applicable
Data Retrieved
data
.
.
data
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
used with Mci_Read_Error( ) as the error code parameter. The IOX task displays the error on
the run manager screen.
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.
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
mm_mbx = not applicable
mm_type.type = MCI_WRITE_RSP
mm_type.ident = MCI_TAG
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
boundary: = MCI_WORD_BND
len; = 80
start; = 10
cde; = CDE_BLOCK
14
IMX Messaging
cde; = CDE_BYTE
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 tag is to be sent. The CDE code
implies the data size of the tag 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 tag 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 tag 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
14
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 IMX Messaging
of the dataset. In the method for normal exception writes described previously, the tag 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.
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. 14
IMX Messaging
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 tags of
variable size from a dataset. The following example shows how to use some of these functions:
#define HOST_HIGH_2_LOW
char buffer[ 256];
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*/
You must decide in the code which function to use at run time depending on the data direction
of the external device data. At compile time, the source code also requires a decision on the
data direction of the host. You determine this when making a program definition (PDEF) of
HOST_HIGH_2_LOW or HOST_LOW_2_HIGH. This definition forces the compiler to insert
different macros in the source code depending on the host data direction. These macros are
listed in the file format3.h.
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.
In the first case, the single exception tag is either the same size or greater than the destination
area. If the tag is the same size as the destination area, the tag can be written out as a simple
block write operation (the IOX task automatically determines this for a driver).
If the tag 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 tag 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)).
The 8 signifies to start at bit 8 that gives bits 8 to 15, which is the left byte.
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 tag specifies the data direction of the originating host. Because the MCI
header is always in the host format, this tag 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
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
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 */
Mci_Set_Bnd_Dir ( &ds, MCI_HIGH_2_LOW); /* every word is stored in the device in HIGH to LOW
format*/
Mci_Set_Bit_Dir ( &ds, MCI_HIGH_2_LOW); /* bits in a word in the device are stored in HIGH to LOW
format */
Mci_Set_Bnd_Offset ( &ds, 0); /* boundary offset starts at 0 */
x_Set_Bit_Offset ( &ds, 0); /* bit offset starts at 0 */
Mci_Set_Start ( &ds, 10); /* first tag in this dataset resides at address 10 in the device */
Mci_Set_Len ( &ds, 20); /* there are 20 contiguous tags for this dataset, address 10, 11, 12,..., 29
*/
Mci_Set_Udata ( &ds, ( void *)&more_info); /* attach the more information structure to this dataset
more_info would have been set with some supplemental information that may
be used with this dataset (i.e. device station id, port, etc.... this is up to
the developer to assign any supplemental information.*/
Mci_Set_Ufnc ( &ds, process_ds); /* call back function that will be invoked whenever an event
occurs on this dataset. */
/* 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.
The polling method (Mci_Event_Check( )) is used in a driver because the driver may have to
perform other duties, such as check its communications port for incoming or unsolicited data.
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 15
to a single dataset. When a dataset event occurs, the procedure you defined is invoked. That
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
from a CT record. In an actual driver, the dataset CT records are used as the source for
characteristics of a dataset.
./*
* Example of user event function. This is automatically called by the MCI library when a dataset this function is defined for has an
event active for the dataset.
*/
int process_ds( MCIDS *ds); /* user event function for dataset */
/* retrieve the pointer to supplemental dataset information, this could be information such as CT data associated with the
dataset or any other info you like.*/
/* 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
•
•
•
•
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 a tag.
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
• 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
language.
• See also: Lists related function(s).
Returns GOOD.
Error: FLE_OUT_OF_MEMORY.
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)
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 tags 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:
MCI_BAD_CTRL.
MCI_BAD_SNDMBX.
FLE_NULL_POINTER.
FLE_BAD_TAG. 16
FLE_NOT_MAILBOX.
FLE_NO_MESSAGES. IMX Reference Guide
FLE_ACCESS_DENIED.
FLE_OUT_OF_MEMORY.
FLE_LOCK_FAILED.
FLE_LOCK_EXPIRED.
Remarks Usually I/O translator tasks use this function at initialization time in order to retrieve
all the information on a dataset.
Protocol drivers do not use this function.
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.
FLE_NO_MESSAGES.
FLE_ACCESS_DENIED.
FLE_OUT_OF_MEMORY.
FLE_LOCK_FAILED.
FLE_LOCK_EXPIRED.
16
Remarks The I/O translator tasks uses this function to read a complete dataset. The function
sends an MCI read command to the remote task, which is usually a protocol driver. If
the protocol driver remains in the same application, the dataset control tag is IMX Reference Guide
triggered. If the communication is over a LAN, a mailbox message is generated.
Triggering only the dataset control tag is a faster way of communication.
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,
int (__cdecl **e_fnc)( void *ds, VAL val))
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 tags.
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
Returns the size of the data according to the operation (CDE) specified.
Syntax intMci_Get_CDE_Size( ushort cde)
Returns Size of the tag according to CDE code, which can be one of the following
16
0 MCI_BIT_BND Boundaries on bit basis (1 char 1 bit).
Errors:
ERROR CDE code does not exist.
Remarks The size of the tag returned also corresponds to the boundary of the tag.
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
Remarks The mode of writing, either
MCI_NORMAL_WRITE.
MCI_ENCODED_WRITE.
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 tags according to the boundary
size.
Syntax u16 Mci_Get_Len( MCIDS *dataset)
M CI _G ET _N AME
Gets the name of the dataset control tag as specified in the FactoryLink real-time
database.
Syntax char *Mci_Get_Name( 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 _S TART
Gets the start address of the data in the dataset message.
Syntax u16 Mci_Get_Start( MCIDS *dataset)
M CI _G ET _S TATION _I D
Gets the remote station id received from on the dataset message.
Syntax uchar Mci_Get_Station_Id( MCIDS *dataset)
M CI _G ET _T_B UFFER
Gets the buffer parameters currently set on this dataset.
Syntax MSG* Mci_Get_T_Buffer( 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.
M CI _G ET _TYPE
Gets the type of the MCI message.
Syntax uchar Mci_Get_Type( MCIDS *dataset)
Returns The type of the message, which can be one of the following:
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.
M CI _I NIT
Initializes the MCI library for use.
Syntax int Mci_Init( MCISYSTEM *sys)
Returns GOOD.
FLE_OUT_OF_MEMORY.
FLE_NULL_POINTER.
FLE_BAD_TAG.
FLE_NOT_MAILBOX.
FLE_NO_MESSAGES.
FLE_LOCK_FAILED.
FLE_LOCK_EXPIRED.
Remarks This function must be called before any other function of the MCI library.
M CI _M IRROR
Reverses a character buffer of specified length.
Syntax void Mci_Mirror( char *buf, ushort length)
Returns None
Remarks This function gets the first tag of the message buffer (I/O data area), checks the
operation code (CDE) and places the data in the correct position in the tag, and
converts the tag to the final boundary.
This function is usually used for exception write commands that require only one tag
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 tag 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)
Indices in the queue should not be saved for later use because they can change.
*M CI _Q_I NIT
Initializes the task MCI mailbox queue.
Syntax int Mci_Q_Init( void)
Arguments None
Returns GOOD.
Errors:
FLE_OUT_OF_MEMORY.
FLE_NULL_POINTER.
FLE_BAD_TAG.
FLE_NOT_MAILBOX.
FLE_NO_MESSAGES.
FLE_LOCK_FAILED.
FLE_LOCK_EXPIRED.
Remarks This function initializes the mailbox queue by deleting every message in the queue
except for query messages. It is not advisable for an application to use this function.
This function is called by the MCI library at start up.
M CI _Q_N UM
Determines the number of active MCI messages in the task mailbox queue.
Syntax int Mci_Q_Num( uint *num)
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
message from the mailbox queue. Prior to calling this function, the task sets a
different message buffer to store the message when it is pulled from the mailbox. If
this is not done, the message buffer defined at registration time for the dataset is used.
The message buffer is contained inside the dataset structure.
M CI _R ESET _B UFFER
Resets the buffer parameters on the dataset message.
Syntax void Mci_Reset_Buffer( MCIDS *dataset)
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. 16
Syntax int Mci_Send( MCIDS *dataset)
Arguments MCIDS *dataset Pointer to MCI dataset structure. IMX Reference Guide
Returns GOOD.
Errors:
MCI_BAD_CTRL.
MCI_BAD_SNDMBX.
FLE_NULL_POINTER.
FLE_BAD_TAG.
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
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.
See Also “Mci_Set_Type”
M CI _S ET _B IT _D IR
Gets the direction of bit information within the boundary tags.
Syntax void Mci_Set_Bit_Dir( MCIDS *dataset, uchar dir)
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)
16
Arguments MCIDS *dataset Pointer to MCI dataset structure.
uchar offset Bit addressing offset of ds. IMX Reference Guide
Returns None
Remarks The bit addressing offset can be either 0 or 1.
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)
Returns None
M CI _S ET _D S _C TRL
Sets the dataset control tag on this dataset.
Syntax void Mci_Set_Ds_Ctrl( MCIDS *dataset, TAG ctrl)
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) 16
Returns None
Remarks The mode of writing, either
MCI_NORMAL_WRITE.
MCI_ENCODED_WRITE.
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 tags 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)
Returns None
Remarks The dataset control tag name must be set before registering. The tag name must
correspond to the tag id.
M CI _S ET _O RG _H OST _D IR
Sets the originating host data direction.
Syntax void Mci_Get_Set_Org_Host_Dir( MCIDS *dataset, uchar dir)
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. 16
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.
Returns None
Remarks This function must be called before registering the dataset. Afterwards, the function is
not used.
M CI _S ET _S TART
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 _S TATION _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.
Syntax void Mci_Set_T_Buffer( MCIDS *dataset, MSG *buf)
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.
M CI _S ET _TYPE
Sets the type of the MCI message.
Syntax void Mci_Set_Type( MCIDS *dataset, uchar type)
Returns None
See Also “Mci_Get_Type”
M CI _S ET _U DATA _P TR 16
Sets the pointer to the additional user dataset information buffer.
Syntax void Mci_Set_Udata_Ptr( MCIDS *dataset, char *buf) IMX Reference Guide
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.
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)
Returns Returns the tag value of the MCI systems mailbox tag of this task.
M CI _S YS _G ET _S TATION _I D
Gets the station id of this host machine as registered in the MCI library.
Syntax uchar Mci_Sys_Get_Station_Id( MCISYSTEM *sys)
M CI _S YS _G ET _TASK _I D
Gets the FactoryLink task id currently registered in the MCI library.
Syntax u16 Mci_Sys_Get_Task_Id( MCISYSTEM *sys)
Returns None
Remarks This task should be called before the Mci_Init( ) function with the mailbox tag used
for MCI communication.
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.
•
•
•
•
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.
Appendix
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
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.
Index
AC files 339 CDBLIST utility 88, 89
comments in 65 CDE codes 463
created 59, 64 block data commands 463
described 39, 59, 64 data header direction 463
example 83 exception data commands 463
example (external editor program) 85 CDE operation codes 445, 459
format 65 CFGPAK (Configuration PAK) 327
format (external editor program) 85 change-read call 34
with CONFIG PAK 329 change-status bits 32, 127
accessing CDBs 339 change-wait call 34
acctmgr -c -d utility 337 changing name of tag definition 368
adding tag definitions 366 common functions in interface library 452
analog data type 31, 53 compiling
Application Editor 329 BASIC PAK 18
archive (CT) 104 RAPD 439
arrayed tags compiling and executing Skeleton Task 23
described 47 CONFIG PAK
examples 49 error messages 371
arrays 46 message box type requests 372
attribute catalog return codes/error messages 370
See AC files storage entities 328
attribute catalogs validation error reporting 373
with CONFIG PAK 337 configuration architecture
BASIC PAK 45
CONFIG PAK 328
B configuration database (CDB) 337
binary CT generation utility 111 configuration database API 341
block read function 452 configuration database tables 52
block write function 455 configuration environment 59
design database tables 59
C setting up 62, 103
calling and return conventions 131 testing 61, 88
Index
external configuration 329 calling process 115
installation
F BASIC PAK 18
FactoryLink CONFIG PAK 327
API 26 RAPD 437
Kernel 27 interface library
operation 25 common functions 452
failure scenarios with CONFIG PAK 330 inter-process communication (IPC) 125, 130
field handles 342 IOX driver communications 471
FL_LOCK
relationship to FL_UNLOCK 217 K
FLAPP Kernel 27
directory files 55, 56 Kernel and library services
with CONFIG PAK 329 database access 121
FLINK KEY files
directory 437 created 39, 60, 86
directory files 42 described 60, 86
with CONFIG PAK 329 example 87
floating point data type 31, 53 missing 88
flow of code 467
forced-write call 33, 40 L
functions LANS communication and IMX 466
block read 452 layout of panels 63
block write 455 library functions
exception writes 458 BASIC PAK
unsolicited receive 460 CT Access 135
Direct Tag Processing 140
I Kernel Interface 122
I/O functionality 452 Message Translation 159
IMX Normalized Tag Reference 148
interface library 441 Object CT Access 137
LANS communication 466 Path Manipulation 153
Index
protocol driver default message buffer 469 System Configuration Table 26
protocol driver design example 467
protocol message 453 T
tag definitions
R adding 366
RAPD changing name 368
principle with IOX 438 deleting 369
RAPD principle illustrated 438 printing 365
read calls 33 reading 364
reading configuration from CDB 347 updating 367
reading tag definitions 364 writing 365
Real-Time Database tag modification routines 329
described 31 tag name
locking 128 assignment 46
structure of tags 32 structure 47
Run-Time Manager 26, 113, 119 tag names 46
and CT files 39 tag number 128
interaction with other tasks 26 tags
run-time requirements 113 described 52
run-time task name storage 52
writing 61 predefined 52
structure 32
S task
selection criteria 347 constructing 57
setting up configuration environment 62, 103 task construction flowchart 62
setup script 18 task/Kernel session management 122
Skeleton Task attaching/detaching from Kernel 122
compiling and executing 23 database access 126
CONFIG PAK 333 error reporting 131
converting script 22 mailbox 130
described 21 miscellaneous session services 125
integrating 22 obtaining environment access 124
U
unlocking the database 128
unsolicited receive function 460
updating a tag definition 367
utilities
acctmgr -c -d 337
CDBLIST 88, 89
CTGEN 61, 105, 111
CTLIST 111
V
VAL union structure 128
W
wait bits 34, 127
write calls 33