TOC PREV NEXT INDEX

Put your logo here!


2 USER'S GUIDE

2.1 Overview

The VLT architecture relies on an On-Line database (DB) that provides real-time data capabilities on a distributed architecture[2].

As a consequence, a relevant part of the design of the VLT is the design of the sections of this database distributed on the different Workstations and LCUs.

Each local database has a hierarchical structure mapping the physical objects that constitute the telescope system (instruments, telescope control components....) and describing how they are logically contained one inside the other (how one component is "part-of" another one).

Each local database has a partial image only of the units of the system that the particular WS or LCU has to use. These components can be true property of the Workstation or LCU itself, or can be just images locally maintained for performance reasons, so that it is not necessary to ask for data through the network every time. The whole database is the merge of all the local sections.

This means that the global database comprehending all the Workstations and LCUs will have often different images for the same physical objects (usually a complete one for the LCU that handles it and a partial one for the WS controlling that LCU).

At the same time there will be a lot of different places in the database describing objects with the same or with a very similar internal structure and behavior. For example, the VLT system will have a lot of motors, decoders or moving axis that have the same general characteristics and can be represented in a logical tree; here common logical parts can be grouped together and the designer can describe only the differences that characterize the peculiarities of each object.

Using an Object-Oriented terminology, inside the database there are a lot of different instances of the same class (such as motors and encoders) or of similar classes (different kinds of motors), and different images of the same object: a "model" describing the full properties of the object (usually on the LCU's database) and some partial "views" (usually on a control Workstation), containing only what is necessary to control the device from outside.

2.2 Design, development and maintenance requirements

To help the database design, development and maintenance phases during the lifetime of the VLT project, it is necessary to have tools able to automate and enforce the implementation of the concepts introduced in the previous paragraph.

2.2.1 Database design

During the design phase of the database, it is necessary to have access to a common repository of templates for the description of the different modules than can be reused by various parts of the VLT, introducing some peculiar characteristics where necessary. The concept of class helps a lot in this task:

· a wide library of classes describing objects commonly used is available. These can be simple basic components (such as I/O signals, encoders, motors) or higher level parts (such as axis, CCD devices...);
· a component of the VLT completely described by a class is created with just a reference to the class, with the setting for initial values where necessary;
· an object that is different just for some aspects with respect to an instance of the class is created making a reference to the class and describing what it has more and/or different: all the rest is inherited from the base class;
· a new object useful for reuse becomes a class in itself and is readily available to all other potential users;
· the description of a class is not a flat entity, but it can contain, as internal members, objects of other classes, for example an axis contains an encoder, a control loop and a motor.

Having these concepts implemented, it will help a lot the designers to create similar database structures, uniform for the whole VLT project, and in reusing the code sharing knowledge.

2.2.2 Database development

Once a proper design has been done, the development of the true database must be a straightforward process.

To get this result, a simple description language is necessary for the database structure that:

· handles the definition of instances from classes
· is able to define a new class by difference with a parent class
· can describe multiple views of the same instance in a single place
· takes proper defaults for everything not specified

2.2.3 Database maintenance

During the maintenance phase there is often the need of modifying the characteristics or the behavior of an entity that has been used in many different places.

It is therefore necessary a support to modify the general description (i.e. the class description) in a way that the modification is automatically applied to all the instances.

At the same time, the modification has to be applied automatically to all the sub-classes.

This means that the simple copy-and-paste technique, where there is a template and new classes or instances are obtained copying and modifying it, cannot be used. This technique is at the same time tedious and error prone:

· it is easy to introduce errors while copying
· modifications cannot be propagated automatically
· it is difficult not to forget to propagate some modification manually or not to introduce errors while doing this

It is also important to have in the same place the description for all the different views of the same object, in order to have a better control of it while making minor modifications.

2.3 Rtap Database structure

The local branches of the On-line database on the Workstations are based on the commercial hierarchical real-time database of Rtap[7]. The second part of the database is distributed on the LCUs and has been developed in order to be compatible with the Rtap implementation for what concerns the general structure and the syntax used for the point configuration files; these are the ways to describe the database structure to the system[4][5].

The description of a database is a directory tree on the Unix or VxWorks filesystem: every directory represents a database point and contains a configuration file describing the point characteristics and subdirectories for the description of sub-points.

The design and development of a database consist of building the directory tree.

The concept of template is implemented having standard trees of point description files that can be copied in a specific position and modified by hand.

Obviously this approach cannot give any automatic support for inheritance and suffers for all the problems mentioned in the previous paragraph about copy-and-paste technique.

2.4 Class support extension

The requirements described in the previous paragraphs are implemented extending the syntax of the Rtap point configuration files.

Using this extension a single file can describe a full database branch, and thus gets the name of "branch configuration file".

It implements the concept of class using inheritance to derive new classes and to get instances of classes.

The dbl tool reads "branch configuration files" as input and generates the corresponding database in the form of Rtap standard "point configuration files", resolving all the dependencies between classes.

The actual database points will have some special internal structure used to implement features related with class inheritance, but these will remain generally hidden to the user and will not have a relevant impact on access performances.

2.4.1 Branch definition

The branch configuration file has to describe a full branch of the database. The full database of a Workstation or of a LCU is built loading one or more branch config files with the loader tool. The loader takes care of checking that all the branches are coherent.

This means that a branch config file contains the description of all the objects that are logically contained (i.e. subject to a "part-of" relation) inside a single entity.

Each branch config files contains:

· general branch definitions
· local classes definitions
· points declaration

The most important general definition is the database path of the root point for the whole branch. It is called the BranchRoot point. Each point described in the file has to be inside the branch starting from it. The default BranchRoot is the local database root.

To specify a BranchRoot different from the default, insert a line of the form:

BranchRoot root_point_path

Using the features of the C preprocessor it is possible to make use of conditional compilation and #define directives to have different BranchRoot points, in order to compile the same file for alternative views of the branch.

A typical example is when defining a sub-branch for a whole LCU (LTE23 in the example). On the database of the LCU itself, the file will describe the complete database, on the control Workstation it will be loaded as a sub-branch of the whole WS database.
The more convenient approach is to have a single configuration file for both these implementations of the database.
This result can be obtained with the following definition:

#ifdef LTE23
BranchRoot ":"
#else
BranchRoot ":path_to_LCU:LTE23:"
#endif

#define directives can help to make more general the code and the usage of the #include directive help to implement common conventions.

Once defined the reference BranchRoot, the config file contains the list of point definitions.

It can also contain definitions for local classes, used only in the scope of this configuration file.


SUMMARY:
- All logically connected points are in the same file (concept of branch)
- Tools to handle different views of the same entity (conditional compilation)

2.4.2 Point definition

The points are the true objects that have to be put in the database to describe the system.

Usually they have to be instances of a class. The main target of this approach is in fact to have an extensible library of classes able to fullfil all the needs of the model: new requirements must be satisfied designing new classes or changing the characteristics of already existing ones. This is the key to have a uniform environment within all the parts of the database and to maintain it without manual intervention.

In the simplest case, it is necessary only to declare a point as an instance of the desired class. The loader will take care of retrieving the class definition, creating the point with all the attributes inherited from the parent class and its ancestors and assigning the initial values to the attributes:

POINT ClassName point_name

where ClassName is the name for the class of the point and point_name is the name given to the instance (it can be a database path name relative to BranchRoot, but all the intermediate points in the path must have already been defined). A point can be defined "on the fly", without inheriting from any class. In this case ClassName must be replaced by NULL_CLASS(3.1.8).

Consider the common example of a point used to get a temperature value from an input channel. This task can be accomplished using a point of class TEMPERATURE_INPUT. This is a specialized sub-class of a more generic ANALOG_INPUT.
In the simple example in which we have just to use an instance of TEMPERATURE_INPUT, without having to modify anything, we can simply declare it in the short form:

POINT TEMPERATURE_INPUT myTemperatureValue

The loader will add to the DB a point (child of BranchRoot) with all the characteristics inherited by the TEMPERATURE_INPUT class and its ancestors; for example the new point will have attributes to deal with:
- actual temperature value
- scaling and conversion information
- out-of-range indication
- quality indication
and so on.
Using this technique will ensure that all the points used to collect temperature values in the whole VLT database will have the same structure and behavior. The access techniques to the point can at the same time be standardized and be implemented via commonly accessible "class methods", implemented through a library of C or C++ access functions, with obvious advantages in terms of code reuse and maintainability.

In some cases it is necessary to assign special initial values to some of the inherited attributes, to configure the initial status of the point.

This can be done using an extended point declaration format:


POINT ClassName PointName
BEGIN

... point description ...
END

Inside the BEGIN ... END area, it is possible:

· redefine attributes to assign new initial values
· add new attributes that will be placed only in this specific point instance, without the need of defining a new class
· overload class-type attributes (this point will be explained in paragraph 2.4.4).

All the attributes not specifically declared will be inherited without changes.

For example, the TEMPERATURE_INPUT class inherits from its parent ANALOG_INPUT the ability of generating alarms when the monitored value becomes higher than a specified limit (defaulted to 100 arbitrary units). In our specific instance the limit has to change to 50 arbitrary units, because the device where it is installed is more sensitive to heating effects. This can be done using the extended syntax:

POINT TEMPERATURE_INPUT myTemperatureValue
BEGIN

ATTRIBUTE int maxValue 50
END

The special behavior of the object is described only in terms of differences from the standard class.

If a declared attribute already exists in the list of inherited ones the new value is assigned, provided that the new declaration is coherent (i.e. it is different only for characteristics that can be overloaded, such as the value in this case). If an attribute with the same name does not exist, a new one is added to the point.


SUMMARY:
- Classes enforce the design of a uniform database
- Class definition is a centralized place where common characteristics are maintained
- Classes make reusability of code easy and natural

2.4.3 Class definition and inheritance

From a logical point of view, a class is a data type able to describe structured structures, just like an integer attribute is able to describe an elementary entity.

The class definition can thus be considered as a definition of a new structured data type and this will be used as any other available data type. This means that a class instance can be used just in the same way as a native type (it is called a class-type) while defining attributes inside classes or points. It is then possible to build hierarchies of points logically contained one inside the other.

For example, every tracking axis will contain an encoder, a control loop and a drive (that are library-provided classes): this structure must be described while defining the class for the tracking axis and the declaration of a point of this new type must automatically generate the sub-points, just in the same way it generates the normal attributes.

Each new class has to be derived from another class, from which it inherits all the properties, in terms of attributes and behavior. Beyond just inheriting attributes, a class definition may:

· redefine attributes to assign new initial values
· add new attributes
· overload class-type attributes (this point will be explained in paragraph 2.4.4).

The basic class that must appear as an anchestor for every other class is BASE_CLASS (2.4.3): it implements only the internal behavior used to support the class concept inside the Rtap DB.

Class definitions could be inserted directly in the branch configuration files, but should be put in separate files (one per class), placed in a common search path and examined automatically by the loader while resolving class dependencies.

The class definition syntax resembles the syntax used to define points:

CLASS ParentClass ClassName
BEGIN
... class description ...
END


where all the attributes definitions (basic types or class types) are placed in the class description.

The TRACKING_AXIS's class definition of the previous example will have the following format:

CLASS MOVING_AXIS TRACKING_AXIS
BEGIN
ATTRIBUTE ENCODER encoder
ATTRIBUTE CONTROL_LOOP loop
ATTRIBUTE DRIVE drive
END

Where the base class is MOVING_AXIS.

A class definition consists not only in the data description that will be loaded on the database, but also in the behavior of the class: this is implemented defining a library of C functions or a C++ access class associated with the database class. Actions on the data stored in the points will be executed using these methods. The simplest examples are read and write operations, performed through methods instead of the plain dbRead() and dbWrite() functions. This warranties that only allowed operations are executed and that the object itself can perform all the necessary checks before arbitrarily changing attribute values.

Consider the example of managing the exposure time of a CCD camera.
Since every CCD will have such a parameter, it will be defined as an attribute of the CCD base class and there will be several instances of it in the VLT database.
At the same time the exposure time is not a plain floating point variable: it is an entity characterized by:
- value
- minim allowed exposure time
- maximum allowed exposure time
- measurement units
and by a behavior:
- every time someone tries to change the value, it must be checked against the limit values and accepted or rejected.
The correct implementation for this configuration defines the CCD base class as containing and instance of the library-provided EXPOSURE_TIME class:

CLASS BASE_CLASS CCD_BASE_CLASS
BEGIN

......
ATTRIBUTE EXPOSURE_TIME expTime
......
END

This will completely define the expTime attribute inside the class, giving it a standard structure, common to all the other instances, also if developed by other people. Standard implementation and code reuse is enforced by the presence of classes and no more left to the database designer: a class definition is placed in unique "class description file" available for immediate usage by anyone and centrally maintainable. Thus the class can be considered more error safe than a new implementation from scratch.

Grouping the classes in logical hierarchies where common characteristics are defined in a unique entity at an higher level of abstraction (a super-class) carries on a lot of advantages, as already put in evidence.

Another important aspect is that it also helps to identify the responsibilities of each entity, making easier to apply the general principle that "knowledge" should be concentrated on as few places as possible, and on a hierachical level as high as possible and as low as necessary (but not lower!). It often happens that some different entities provide the same kind of services, but they have to be implemented in several different ways. This means that these entities have a common logical root, but have at the same time some peculiar properties.

A good way to model these concepts is to have a common base class defining the services, and the specific subclasses implementing them. The user asks for the service without worrying about the way it will be satisfied: it is full responsibility of the sub-class implementer, the only entity with all the necessary knowledge. This kind of behavior (commonly called polymorphism) is implemented by defining a C++ access class to provide methods and using C++ inheritance in subclasses.

In the previous example we have made use of an instance of the EXPOSURE_TIME class, without worrying about its class-hierarchy.
In the VLT class library this class is not an immediate descendant of BASE_CLASS, but it is just a leaf in a hierarchy of classes that implements the basic (and widely used) concept of range-controlled value.
All the classes in the hierarchy represent a variable that has to be checked and whose allowed values are within a specified range.
This is a general concept, implemented in the base class; the actual type of the value (integer, floating point, character string....) and the type of range (boolean, min-max analog, min-max digital, one of a list...) are defined in the specific sub-classes.
The following diagram shows some of the classes in the hierarchy (ready to be used by everyone to create instances or new sub-classes):



The ANALOG_VALUE and DIGITAL_VALUE classes handles values that can accept only an analog (floating point) or digital (discrete, with a predefined step, by default integer) value, within a specified min-max range, so they are both sub-classes of MIN_MAX_VALUE, where the attributes are defined.
To use these classes it is just necessary to create an instance (or a specialized sub-class) and set the limit values:

POINT ANALOG_VALUE myValue
BEGIN
ATTRIBUTE float min 20
ATTRIBUTE float max 100
END

By the way the values are often the readout or readin for some device, and therefore they have some physical unit and unit conversion rules, as well as physically meaningful range definitions. In this case it is much better to use specifically designed classes such as EXPOSURE_TIME or TEMPERATURE:

POINT TEMPERATURE myTemperature
POINT EXPOSURE_TIME myCCD_ExposureTime

On the other branch of the hierarchy are CHOICE_VALUE classes, where the stored value can have only a value chosen within a predefined list. In this case it is necessary only to overload the table with a new one initialized with the selectable values.
The base class RANGE_VALUE defines the methods (in a C++ access class):

Set(newValue)
Check(value)

to ask an instance respectively to assume a new value (represented in character string format) or to check if a proposed value is acceptable.
The implementation of the methods is different for every leaf class (some check the limits, some have to search in the list of values.....) but the interface is only one.
This makes for example straightforward the checking and setting of setup-files: it is necessary only to write a "main loop" over all the points that have to be setup. Every time it is called, the "same" Set(value) service and the responsibility of actual parameter check (with acceptance or rejection of the requested value) is let completely to the point to be setup. The setup program does not actually need to know the properties of the points it is initializing.

SUMMARY:
- Composite objects are described in a unique class that appears as a data type
- New types of objects are described by difference from already defined classes
- Classes describe non only data but also behavior (methods through C++ access classes or c functions)
- Classes help to design having responsibilities in mind

2.4.4 Overloading of class-type attributes

Inside a class definition we can put as attributes sub-points of a class. For example every instance of TRACKING_AXIS will have a motor.

By the way, quite often we are not able to really specify in the general class definition what specific type of sub-component will be instantiated. For example, different types of TRACKING_AXIS (i.e. ALTITUDE_TA, AZIMUTH_TA or ADAPTER_ROTATOR) will all have motors, but of different kinds.

This means that we must have the possibility to specify a generic class type for an attribute of the class, and to give more details about it at instance time or while defining sub-classes.

This procedure is what we call "overloading of class-type attributes":

Every class-type attribute of a class can be re-specified (overloaded) with another class-type, provided that it is a sub-class of the original one.

This is particularly useful when the general knowledge is enough to drive the device from outside (for example with commands from a workstation, using an access function or methods provided by a C++ access class), but must be considered internally also hardware constraint that depends from the specific instance.

In the TRACKING_AXIS example, we will have a hierarchy of classes defined in the library and inheriting from the base class. Every sub-class will overload the motor attribute with a proper specific motor type. Consider the sample hierarchy for MOVING_AXIS and MOTOR given in figure:


If the TRACKING_AXIS class is defined in the following way:

CLASS MOVING_AXIS TRACKING_AXIS
BEGIN
.....
ATTRIBUTE MOTOR motor
.....
END

The sub-class will overload the motor attribute. For the example the AltitudeTA class will be:

CLASS TRACKING_AXIS ALTITUDE_TA
BEGIN
ATTRIBUTE ALTITUDE_MOTOR motor
END

The new class type will be checked by the loader.

While defining a sub-class or an instance of a class that contains class-type attributes, the need of overloading some characteristics (typically the value) of an attribute inside the class-type attribute itself may arise. When there are more levels of nesting between sub-points, the attribute to be modified can be some levels down in the hierarchy of the instances.

In the last example, when we create an instance of the ALTITUDE_TA, we have to set the maximum allowed speed of the ALTITUDE_MOTOR that is "part-of" the altitude tracking axis. This value is stored in the "max" attribute of the motor's class-type attribute "speed" (it is of class ANALOG_VALUE): We have in this example three levels.

These situations are handled by specifying to the loader the path to reach the desired "sub-attribute". When such a definition is encountered, the loader checks that all the intermediate points exist and are of the correct types.

In our example the instance of ALTITUDE_TA can be specified as follows:

POINT ALTITUDE_TA telescopeAltitude
BEGIN
ATTRIBUTE float "motor:speed.max" 0.2
END

The loader:
- searches for an attribute of name "motor"
- this must be a class-type and have an attribute of name "speed"
- this must be a class-type and have an attribute of name "max"
- this must be of type float
- if all the conditions are satisfied, the value is overloaded
- otherwise an error is reported


SUMMARY:
- Specialization of generic definitions helps to write code reusable in similar, but not identical situations
- Only the "unique" characteristics have to be specified
- External users do not need to know the specific features
- Overloading of sub-attributes helps to specify easily special properties for composite entities

2.4.5 Scan system links

In the general VLT database architecture, the same physical object can be mapped both on the local database of a LCU and on the one of a Workstation. By the way, in most cases this last image is only a partial view of the LCU true object and not all the attributes will be mapped.

More over, the mapped attributes must actually contain the same values stored in the LCU image.

This means that values that can change with time must be kept aligned using the Scan System.

Since this necessity is usually known at database design time, the loader provides a way to define Scan Links.

In the ATTRIBUTE declaration it is possible to define scan links to attributes of other points using a simple syntax:

ATTRIBUTE Type AttributeName
BEGIN
// To define scan by polling
SCAN_POLL PathOfScannedAttribute PollTime
// To define scan by srbx
SCAN_SRBX PathOfScannedAttribute deadband_type deadband
END

Consider for example an attribute that must contain a value polled from a given attribute of a point on a LCU every 2.0 seconds:

ATTRIBUTE float temperatureCurrentValue
BEGIN
SCAN_POLL "@LTE23:<alias>temperature.value" 2.0
END

This, coupled with the ability to use preprocessor directives, makes easy to define in the same branch config file both the images of a point.

Consider the example of a device for which we have to monitor the temperature. The device will have its model on a LCU and an image on the control Workstation. The only attribute we need to monitor from the workstation is the value of the temperature, and this must be kept aligned via the Scan system.
To implement this behavior we can define the class for the device in the following way:

CLASS BASE_CLASS HEATING_DEVICE
BEGIN
#ifdef LCU
..... attributes used only in the LCU
#endif

// "double definition" for the temperature attribute
ATTRIBUTE TEMPERATURE_INPUT temperature
BEGIN
#ifdef LCU
... attributes properties in the LCU ...
#else
SCAN_POLL "@LTE23:heatingDevice.temperature" 0.5
#endif
END

END

SUMMARY:
- Different views of the same objects are kept aligned in an easy way, putting all the information in a unique and maintainable place.

2.4.6 Static and automatic attributes

Usually all the attributes defined in a class will contain values to represent the current status of a specific instance of the class. These values can be constant or can vary with time, but in any case they are used to specify the properties of that single specific instance.


Consider for example an instance of a motor.
Without any doubt the position of the motor specifies the current status of the device and can vary with time: at a given instant every motor has its own position.
At the same time the maximum rotation of the motor is a constant, but it is (at a first level of analysis) specific of THAT motor and other motors can have different values for that same attribute.

Each instance of the class must have its own personal copy of all these attributes (called "automatic") and by consequence the point put in the database will contain all these automatic attributes as inherited by all the ancestor classes.

It is easy to see that this is not the only case: some attributes describe characteristics common to all the instances of a class (called "static"). In this case, it does not make sense to have a private copy of the attribute in each instance.


If we consider a configuration in which we use 10 exactly identical motors, it becomes evident that the maximum rotation is a constant value common to all these 10 instances. The better solution in this case is to have a special sub-class of motor and to have a way of defining and accessing the maxRotation attribute as "static" for the whole class.

The loader recognize the following syntax to define "static" attributes:

STATIC_ATTRIBUTE Type AttributeName [value]

or

STATIC_ATTRIBUTE <Type | ClassName> AttributeName
BEGIN
.... attribute description ...
END

From the user point of view, there is no difference in accessing static or automatic attributes with the services provided by the CCS, but the static ones are actually stored in a common place inside each local database and are actually shared by all the instances of the same class residing in that local database. Some characteristics of an attribute (like for example the value) can be overloaded also for static attributes: the new definition has to take place in a class definition and will affect all the instances of that class and descendents (but not ancestors).

A particular type of motor can work only if its temperature is under 80 degrees. This limiting temperature is logically defined as a static attribute of the class that describe that type of motor. In some special places it will be used and improved version of the motor. The only difference is that it can work up to 150 degrees. This improved motor is well described deriving a new class from the first one. It will only overload the value for the static parameter used to define the temperature.

2.5 Final database format

The loader tool processes a branch configuration file and produces the corresponding branch description in Rtap point config file format.

This description is compatible with both Workstation and LCU databases and can be loaded on any of them.

From the user's point of view, the Rtap database branch has a point per each point described in the configuration files. Class-type attributes are expanded as true points in the database and hierarchical structures are replicated with Rtap hierarchies of points.

Class dependencies are resolved expanding the point structure: the Rtap point will have its own copy of every (non static) attribute declared in all its anchestor classes, taking into account overloading of properties.his is exactly the same final structure that will have been carried out without the concept of classes: every single object must be specified completely in all its characteristics.

The centralized definition of common properties, that is inside the idea of class, leads to this result making easier the work of design, development and maintenance of the database.

The users of the database built by the loader mainly see a standard database and can interact with it using the standard LCU and Rtap utilities (such as RtapDbConfig and RtapPtDisplay). At the same time, all the standard CCS db functions and the Rtap Calculation Engine (on the workstation side) work properly. Interactive tools will be developed at a second time to replace the Rtap utilities and to make possible to navigate inside the database or to modify it using an Object Oriented approach. A short description of the function provided by these tools is given in the following paragraphs.

The following figure shows the general structure of the database; a box represents a hierarchy of points and the area grayed-out contains configuration sections used by the class implementation and normally not accessed by the user:

In order to implement these additional features, the database is integrated with ad-hoc attributes and points and CCS and Rtap Calculation Engine are to be extended to take advantage of these features, but they are usually not seen by the user:

· Every point that is an instance of a class has:
· the standard class flag filled with a proper class identification number
· a class attribute that points to a special point describing the class.
· The database contains a special "class definition" branch where is described the class structure of the database: it contains one point per class, organized following the class inheritance hierarchy. The "class point" contains mainly the static attributes.
· All the classes are represented in the "class config" special point. The class numbers are automatically assigned by the loader.
· CCS read/write functions are modified in order to be able to navigate the class hierarchy and to locate the static attributes in a completely transparent way.
· A new Calculation Engine function implements the "class database view" to make it possible to write CE definitions using static attributes.

2.6 Design guidelines

For the following topics :

· database structure
· identification and design of classes
· usage of inheritance
· definition of Calculation Engine formulas on the WS database
· method's implementation using C functions or C++ access classes
· usage of the VLT class library

please refer to document VLT Software Guidelines:

The provider of a software library or of an application accessing the database, has to define also one or more classes for the database points.

When the software or the application are configured, instances of these classes are created in the proper position in the database and all the attributes having non-default values are configured.

The VLT standard environment provides support for this development and installation phases, defining standard directories and standard makefile targets for database definitions (look at the man pages of the vltMakefile tool for more details).

Suppose that the user is developing a module in $MODROOT.

1. the software developer designs the classes for the database points. The class description files are placed in the $MODROOT/dbl directory and have extension .class. All the classes already designed and installed in $INTROOT or $VLTROOT are available.
2. The software developer writes some sample/test database branches using the new classes. He creates some .db files in the $MODROOT/dbl directory. These files have also to be installed in order to be used as templates.
3. Using the rules provided by the Makefiles, he can load a test database in $MODROOT/DB and check by hand what has been produced, load the points with the RTAP interactive tools (with the dbl tools when they will be available) or load the database on a running test environment.
4. when the development is complete, the database can be installed in the $INTROOT or $VLTROOT using the Makefile. This copies all the class definition files in the dbl subdirectory, so that they are available for everybody.

All these steps are controlled by the Makefile in the $MODROOT/src directory.

The list DBL_CLASSES contains the class files defined (without the .class extension).

The list DBL_BCF contains branch config files defined (without the .db extension).

The list DBL_LOAD contains the branch config files (without the .db extension) that must be loaded when the make db command is issued. It is a subset of DBL_BCF.

The target db will load the branch config files in $MODROOT/DB for testing, while the target install will install all the DBL_CLASS and DBL_BCF files in the integration or $VLTROOT area.

A true VLT environment is configured by the environment system manager, or by an automatic installation procedure, by editing the DATABASE.db file in the dbl directory of the environment.

This file must always be present and contains a list of include directives to build the database; among these are standard class definitions, template files and local .db files with the actual configuration of the database. It is always better to have in the DATABASE.db file only a list of includes and not directly point declarations.

The directory contains also a Makefile, usually empty.

The Makefiles's target db will load the whole database in the DB directory of the environment. The target clean will clean the whole DB directory.

Observe that if a file called DATABASE.db is present in the module's ../dbl directory, the command make db assumes automatically that this is the file to be loaded, no regard what is specified in the DBL_LOAD entry of the Makefile.

If the destination environment correspond to a LCU, it is only necessary to define for the Makefile the variable MAKE_VXWORKS. This will be passed as a #define to the dbl and can be used for conditional compilation.

The clean and db targets in a development $MODROOT/src directory will NOT clean the DB database destination directory. In particular this means that old database points, not any more described in the branch config files, are not removed automatically, but must be removed by hand. If the DB directory contains only points loaded with make db, it is suggested to modify this target's definition adding the cleaning of the DB directory as the first step. The same applies to the clean target.

In order to merge Point Config Files with a database description based on dbLoader's Branch Config Files it is necessary to follow the following steps:

· In a module directory, during development:

· Put the Point Config Files' tree in the module's directory

<mod>/dbl

· Modify the Makefile's target for db:
Add here a line to copy the PCF branch from the <mod>/dbl directory to the <mod>/DB directory, like for example:

db : db_all
cp -r ../dbl/PCF_BRANCH ../DB/PCF_BRANCH
@echo " . . . db done"

· Modify the Makefile's target for install:

This procedure must copy the branch to some destination directory where it can be copied in the destination environment during configuration. It can be the $(xxxROOT)/dbl directory, where xxxROOT stands for VLTROOT or INTROOT

In an environment directory, during configuration:

· Put the Point Config Files' tree in the environment's directory

$VLTROOT/ENVIRONMENTS/<env>/dbl

Copying them from where they have been put by the module's install procedure.

· Modify the Makefile's target for db:
Add here a line to copy the PCF branch from the <mod>/dbl directory to the <mod>/DB directory, like for example:

db : db_all
cp -r ../dbl/PCF_BRANCH ../DB/PCF_BRANCH
@echo " . . . db done"

2.7 Database loading on a running environment

The current release of dbl does not implement the options for directly loading databases on workstation's and lcu's running environments. A preliminary implementation of the loading on ws (-wl option) is available only internally to ESO.

This section contains some suggestions about the steps necessary to load by hand a database generated with dbl.

Essentially the steps are:

1. unload the database in one of the following ways (if it is necessary to restore current database values after having loaded the new database or if there are points not described in the .db files):
· using the batch command RtapDbUnloader
· with the interactive menu from RtapDbConfig
or make a backup of some points using the CCS database backup and restore
utilities provided with this release of CCS
for example:
> rm -r dbDir
> RtapDbUnloader -d dbDir -e wte16 -p ":"
2. load in the same directory the branch config files:
> dbl points.db dbDir
3. reload the database in one of the following ways:
· with RtapDbStartup:
- shutdown the database
- edit it's RtapEnvTable to modify the flags for
RtapDbStartup:

# The next line starts up the database from snapshot files.
# To reconfigure the database at startup, uncomment out the line
# with "RtapDbStartup -r" and comment out the next line.
# (Lines which begin with a `#' character are commented lines.)
# 0 2 N P N A N 0 128 RtapDbStartup
0 2 N P N A N 0 128 RtapDbStartup -r

- restart the database
- reload it from the files using the RtapDbStartup menus
- reverse editing of RtapEnvTable and restart the db.

· With the interactive tool RtapDbConfig:
- Delete all the points in the db
- load the new points with the load menu
4. The attribute's values saved with the CCS database backup procedure can now be restored.

2.8 Caveats

This section contains solutions to common problems encountered when using the database loader.

It will be extended taking into account SPRs and frequently asked questions.

2.8.1 Limits of the preprocessor

The database loader support all but only the C language preprocessor (cpp) directives, as defined in Appendix A12 of the Kernighan & Ritchie[6].

This means that it is not a C interpreter and that it is not able to cope with C syntax that goes beyond what is defined for the C preprocessor.

Typical examples of not supported structures that one could be tempted to use are typedef and enum.

2.8.2 Sharing code with C and C++ programs

It is a good practice to put defines for symbols and values that must be shared between C or C++ code and database points in a common include file, used in every situation.

In order to do this, it is necessary to write an include file that contains only expressions that can be understood both by dbl and by the C compiler (typically #defines, see 2.8.1).

This can be placed in the ../include module's directory.

In order to make it visible for dbl, modify the Makefile's entry for DBL_FLAGS adding the C include directories to the search path, using the variable $(IPATH):


DBL_FLAGS = $(I_PATH)

For conditional compilation, the macro MAKE_DBL is defined automatically by dbl at compile time. With this macro is possible to have separated dbl and C/C++ code in the same source file. For example :

#ifdef MAKE_DBL
.#define vltDOUBLE DOUBLE
#endif

For a piece of code to be use only by dbl sources.

2.8.3 The file DATABASE.db

If a file called DATABASE.db is present in the module's ../dbl directory, the command make db assumes automatically that this is the file to be loaded, no regard what is specified in the DBL_LOAD entry of the Makefile.

2.8.4 Loading big databases

Sometimes a database is too big to be loaded in one single step.

In this case it is enough to split the loading in two or more smaller sections.

In order to do this:

· Make sure that a DATABASE.db file does not exist (see 2.8.3)
· Create 2 or more independent files to be loaded
· Declare them in the Makefile's entry DBL_LOAD.
· Issue the usual command make db. Make will issue a separate dbl command per every file in the DBL_LOAD section

2.8.5 Scan link configuration files

During database loading, scan-link definitions are currently only appended to the scan-link definition file, without checking if the same definition already exist in the file from a previous loading.

As a consequence, reloading several time the same files without cleaning the ../DB module's directory will result in scan-link definition files containing multiple times the same definitions.

2.8.6 Inheritance and overloaded classes

The database loader now supports the overloading of attributes in sub-points inside a class definition.

This remark replaces the corresponding section in the previous version of the manual and will be removed in the next release.

2.8.7 Duplicate alias names

When loading by hand on Rtap (with RtapDbConfig or RtapDbLoader) a database branch generated by dbl it is possible to get the error "duplicate alias" and the loading fails.

This happens when the same database is shared during development by more modules and is due to two facts:

· dbl cannot access the rtap database to see what aliases have been already used
· rtap cannot automatically generate aliases

As a consequence, when loading on a non empty database a new branch, it is likely to find that some aliases are already used there in other branches previously loaded.

The dbl command line option -a <num> can be used to overcome this problem defining the first alias number that must be used for the points of the current branch. The option can be set in the Makefile entry for DBL_FLAGS setting it in the following way:


DBL_FLAGS = -a <num>

As an alternative solution, since dbl keeps track of the aliases it has used, usually it is enough to issue again (one or more times) the "dbl" or "make db" command.Every time the database is regenerated, its points get higher alias values and will find soon and area not already used.

2.8.8 Multi-line macros definition

The standard preprocessor's splicing character `\' is just used to "pretty formatting" lines, that are anyway expanded on a single line.

As a consequence the following sample macro:

#define FULL_POINT_MACRO(name) \
POINT NULL_CLASS name \
BEGIN \
ATTRIBUTE int32 testAttr 5 \
END

will expand on a single line in the following way:


POINT NULL_CLASS myName BEGIN ATTRIBUTE int32 testATTR 5 END

That is probably not the desired result.

In order to overcome this problem, the preprocessor syntax has been extended adding the line break identifier "-;-". Every time this string is found in a macro definition, a new line character is inserted in the macro expansion.

The following sample macro will expand as a full point, whose name is given as a macro's argument, as desired:

#define FULL_POINT_MACRO(name) -;-\
POINT NULL_CLASS name -;-\
BEGIN -;-\
ATTRIBUTE int32 testAttr 5 -;-\
END

2.8.9 Parser limitations

The dbl parser has some limitations due to its internal structure:

· No check can be performed on the value assigned to attributes. In particular no check can be performed on the values assigned to table and vector attributes. The check is performed by Rtap or by LCC during database loading in memory. This means that malformed expressions (misstype, wrong data types, wrong number of records or of elements, forgotten commas...) are often accepted by dbl or generate errors difficult to be interpreted by the user. If accepted, a proper error is anyway generated by Rtap at load time.
· In vector and table attribute definition and in attribute's value definition, the open round parenthesis "(" must be on the same line containing the attribute name or the "Value" keyword.
· Malformed expressions or unforeseen splitting of expressions between multiple lines can generate unexpected errors.

2.8.10 General branch properties

It is possible everywhere along the file to set the default values for general branch properties (3.1.6).

It is important to remember that these properties are in this way set from that point on as default values.

In particular, if a property is set inside an included file, it will be applied not only to the file itself, but from the inclusion point on in the rest of the main file and in all other eventually included files.

As a consequence general branch properties should never be used inside files that can be included by other files.

2.8.11 Parent class: BASE_CLASS or <base>?

As described in the reference section of this manual concerning class declaration (3.1.7), if a new class does not inherit from any special class, the parameter ParentClass should be set to BASE_CLASS; only in special cases, when no support for static attributes and no class support point are necessary, <base> can be used as parent class.

2.8.12 A class does not appear in the dbl class browser panels

The dbl class browser shows the hierarchy of all classes derived from BASE_CLASS. If a class does not have BASE_CLASS as an ancestor and is a sub class of <base>, it does not appear in the dbl class browser.

2.8.13 Wrong expansion for a macro appended to a string terminated by interpuntion character

As described in spr 960089, whenever a macro is appended to a string terminated by `:' or by `.', the pre-processor adds a space.

Example:


#define CCDNAME ccdUvR
#define CCDROOT :Appl_data:CCDNAME

The result of this expansion is :Appl_data: ccdUvR instead of :Appl_data:ccdUvR

This is a limitation of DBL and is due to the implementation of the underlying CPP preprocessor.

See spr 960089 for details.

2.9 Interactive database tools

The interactive database tools distributed within the Rtap package can be used with the database created by the loader, but only to browse the database structure (modifications will easily put it in an inconsistent status). VLT engineering user interface tools ([4],[5]) can be used to access database points and change their values.

The only tool developed up to now and available as a prototype is a class browser. Other tools, such as a database editor to replace RtapDbConfig with a better user interface and class support, are under investigation.

2.9.1 Class Browser

This tool is an interactive user interface to manipulate the classes' definitions and the classes' hierachies, similar in concepts to the class browsers available for all the object oriented programming languages.1

It acts on the static information saved in the class description files and does not use any run time information from the on-line database.

It is useful to define and edit new classes, but, from the user's point of view, it is first of all a source of documentation. If a class library is well documented, an interactive graphical representation of the hierarchy is much more useful in order to collect information about class usage.

It will contain also functions to print class documentation suitable for insertion in official VLT documents.

The interaction with the browser is driven by the concept of "selected class". It is possible to set the "selected class" in several ways. When a class is selected, it appears on a status line and menus and

all buttons bindings acts on it.

The browser is divided in some windows. Some of them can be switched ON/OFF. Whenever the "selected class" is changed all relevant windows are automatically updated.

Two TREE windows are provided to show the representation of the class hierarchy and the point hierarchy for the points contained in classes with structured attributes.

An object selected with the left mouse button becomes the "selected class". It is possible to hide subbranches of the trees clicking on a tree node:

· middle click toggles ON/OFF the sub-branch
· right click toggles ON/OFF the parent branch.

Examples:
- If I am looking at the full tree and I middle click on a node, the children are hidden. Dead branches shows that there are hidden children.
- If I right click on a node in the middle of the tree, it becomes the root of what I am viewing.
- If I right click on the root of what I am viewing, its parent point appears, with dead branches for the not shouwn children.
- If now I middle click on the new root, all the children branches appears.

A LIST window will contain the list of defined classes. It is possible to select what is shown using wildcard expressions (e.g AH* will show only all the classes starting with the string AH). A list element selected with the left mouse button becomes the "selected class".

A DEFINITION window will contains the definition of the currently selected class. A class is selected by clicking it on a TREE or LIST window (its name is shown in a status line). A list element (for example a class type attribute) selected with the left mouse button becomes the "selected class".

The definition window contains the definition for its data members (type, name, initial value) choosing from a menu one of the following display strategies:

· All attributes (flat)
· All attributes (ordered by class, with the base class last)
· Only attributes specific for the current class (inherited attributes are not shown)

Table's and vector's records could be shown on a separate window when requested (otherwise a clean formatting would be difficult).

It is possible to freeze a DEFINITION window and open a new one, in order to view at the same time the definitions for more than one class.

A MAN PAGE window contains the man page of the currently selected class, formatting from its source file standard VLT header. It is possible to freeze a MAN PAGE window and open a new one, in order to view at the same time the man page for more than one class.

These actions are defined for the class hierarchy TREE window menus:

File menu

Open Open and process a class description file which was not in the original search path
Print To print a file with a description of the currently selected branch (a visible in the TREE window).
Quit Exit the dblcb application

Edit menu

Edit Class Bring up an editor with the file of the currentlyselected class

View menu

Parent Select the parent class of the currently selected class
Select Bring up an input window to allow the user to define the "selected class" via an input prompt
Hierarchy Bring up the TREE window displaying the structured attributes for the selected class
Definition Bring up the definition window for the selected class

Help

Extended help

Quit

Exit the dblcb application

These actions are defined for the TREE window displaying the structured attributes for the "selected class":

File menu

Print To print a file with a description of the currently selected branch (a visible in the TREE window). It must be used to prepare documentation to be inserted in the manuals.
Quit Exit the dblcb application

Edit menu

Edit Class Bring up an editor with the file of the currently selected class

View menu

Select Bring up an input window to allow the user to define the "selected class" via an input prompt
Definition Bring up the definition window for the selected class

These actions are defined for the menu on the DEFINITION window

View menu

All Attributes Display all attributes in the order that they would appear in the point definition.
Sort by Class Sort and display attributes indicating which class they were inherited from
Class Specific Only Only display attributes defined in this class

2.10 Sample definition files

This chapter contains some complete examples of "branch configuration file" and of "class definition files". For some of this examples it is given also the corresponding structure in term of standard "Rtap point configuration files", to make easy the check of the differences between the two approaches and to put in evidence the advantages introduced by the concept of class.

2.10.1 Sample database for the motor library

// ************************************************************************
// * MotorExample.db
// *
// * G.Chiozzi, P.Duhoux
// *
// * This example shows a simplified implementation of the MOTOR database.
// *
// ************************************************************************


// ========================================================================
// In the first part of this example we define the MOTOR class and the
// support classes, used to define sub-components of the motor
//
// Every class should be placed in a separate file named
// CLASS_NAME.class, so that the dbl will be able to locate the
// class definition without having to explicitly include the
// definition file. They appear here in a unique file just to make more
// compact the example




// CLASS INTERRUPT
// ===============
// This class describes a generic interrupt handler.
// Each motion controller will be able to handle a certain number of
// interrupts.
// This is a generic class and will be probably widely used, not
// only to define interrupt handlers inside motors but also
// in other modules.

CLASS BASE_CLASS INTERRUPT
BEGIN
ATTRIBUTE bytes32 interrupt // Interrupt name
ATTRIBUTE int function // Interrupt function (pointer to)
ATTRIBUTE int parameter // Parameter for the function

END



// CLASS MOTOR_STATUS
// =======================
// This class contains a set of attributes used to specify
// the status of any motor (specialized motors can have more).
// In this example, we just build a list of a few attributes. There are
// much more and they should be grouped in logical subcomponents
// (for example using RANGE_VALUE point classes to deal with ranges)

CLASS BASE_CLASS MOTOR_STATUS
BEGIN
ATTRIBUTE int opMode 1
ATTRIBUTE int motionMode 1
ATTRIBUTE int motionStatus 1
ATTRIBUTE int motionStep 0
ATTRIBUTE int brakeClamped 0
........
END


// CLASS SERVO_AMPLI
// =======================
// Every motor has a servo amplifier.
CLASS BASE_CLASS SERVO_AMPLI
BEGIN
ATTRIBUTE int id // Servo ampli. identification value
ATTRIBUTE int boardStatus
ATTRIBUTE int axisStatus
ATTRIBUTE int DACOffsetCfg
ATTRIBUTE int DACOffset
ATTRIBUTE int velocityRef
ATTRIBUTE int motorCurrent
END


// CLASS MC_VALUES
// =======================
// This class describes a set of values that characterize every
// MOTION_CONTROLLER. There will be two instances of this object
// inside every controller: one to hold configuration values and
// one for the actual values.
// Specific subclasses of MOTION_CONTROLLER will overload this
// default definition to add some new parameters or to differentiate
// between configuration and run time values.

CLASS BASE_CLASS MC_VALUES
BEGIN
// Only some sample attributes:
ATTRIBUTE int LA
ATTRIBUTE int LS
ATTRIBUTE int LI
.........
END


// CLASS MOTION_CONTROLLER
// ==============================
// This is the base class to define a motion controller.
// Note the two class-type attributes used to hold run-time and
// configuration values

CLASS BASE_CLASS MOTION_CONTROLLER
BEGIN
ATTRIBUTE int id // Controller identification value (one of a list)
ATTRIBUTE int status
ATTRIBUTE MC_VALUES config
ATTRIBUTE MC_VALUES current

// The INTERRUPT common to every controller.
// Other will be added in specific subclasses
ATTRIBUTE INTERRUPT driveFault
END


// =========== THIS SECTION DESCRIBES THE MOTOR CLASSES ================

// These are abstract types of motors, since it is not actually
// specified what specific industrial devices they will contain.

// CLASS MOTOR
// ================
// This is the basic motor class.
// Every motor is characterized by to components:
// - A motor status
// - A servo amplifier
// They are both represented with instances of the corresponding class
// and will appear on the DB as sub-points.

CLASS BASE_CLASS MOTOR
BEGIN
ATTRIBUTE MOTOR_STATUS status
ATTRIBUTE SERVO_AMPLI amplifier
END


// CLASS MOTOR_MCON
// ====================
// This is a special kind of motor: it has also a MOTION_CONTROLLER.
// It is inherited from the basic MOTOR class, and only the new
// feature is added.

CLASS MOTOR MOTOR_MCON
BEGIN
ATTRIBUTE MOTION_CONTROLLER controller
END



================ THIS SECTION DESCRIBES CHARACTERISTICS OF
================ ACTUAL MOTOR COMPONENTS (NOT ABSTRACT DESCRITPIONS)

// We will have here as many classes as different types of servo
// amplifiers and motion controllers we have.
// This is the only code that is necessary to write to integrate
// a new type of device inside the motor class library or to
// define a new special motor class


// CLASS VME4SA
// ======================
// VME4SA is a specific servo amplifier.
// There is no difference with the base class. We only assign a
// special value to the "id". Every different type of servo amplifier
// has its own ID. We do this by overloading the default value for the
// attribute.
// We use a define to make it more readable.

#define VME4SA_ID 1

CLASS SERVO_AMPLI VME4SA
BEGIN
ATTRIBUTE int id VME4SA_ID
END


// CLASS MAC4
// ======================
// MAC4 is a specific motion controller.
// It has two more interrupts with respect to the base class,
// so we add two more new entries of class INTERRUPT
// We also set the specific ID, using a define to make it
// more readable, overloading the initial value of the id attribute..

#define MAC4_ID 1

CLASS MOTION_CONTROLLER MAC4
BEGIN
ATTRIBUTE int id MAC4_ID
ATTRIBUTE INTERRUPT emergencyStop
ATTRIBUTE INTERRUPT motionEnd
END


// CLASS STD_MOTOR_1
// ========================
// STD_MOTOR_1 is a standard motor configuration used in the VLT.
// This motor is driven by a VME4SA amplifier and a MAC4 controller.
// We define a specific class that can be instantiated everywhere
// a motor of this kind is needed.
// In the class definition, we overload the generic "amplifier" and
// "controller" attributes with the ones actually used inside the
// motor device.

CLASS MOTOR_MCON STD_MOTOR_1
BEGIN
// Here we are not adding attributes, but overloading
// generic class attributes with specialized instances.
// This is correct because VME4SA and MAC4 are subclasses
// of the original types.
ATTRIBUTE VME4SA amplifier
ATTRIBUTE MAC4 controller
END


================ THIS SECTION SHOWS HOW TRUE INSTANCES ARE DECLARED

// The following lines are part of a branch config file.
// We can consider for example a branch defining the structure
// of the telescope dome (Dome will be the root point).
// Among all the other points, there will be the dome main motor,
// used for dome rotation, two flap motors used to drive dome flaps
// (inside the flaps sub-branch) and two windscreen motors.
// Let us suppose all these motors are of class STD_MOTOR_1.
// The following figure is a sketch of the DB structure:
//
// |--- .....
// |
// |
// |--- mainMotor
// |
// Dome ------| |--- ....
// |--- flaps ---|--- motor_1
// | |--- motor_2
// |
// | |--- ....
// |--- winds ---|--- motor_1
// | |--- motor_2
//

// There will be all the other points' definitions ....
// Among them:

POINT STD_MOTOR_1 mainMotor


// While describing the flaps sub-branch
// (after having defined the "flaps" point)
// =============================================

// The motors are not direct children of Dome, so we specify the path
POINT STD_MOTOR_1 flaps:motor_1
BEGIN
Alias "flaps_motor_1" // For this motor we define an alias
END

POINT STD_MOTOR_1 flaps:motor_2
BEGIN
Alias "flaps_motor_2" // For this motor we define an alias
END


// While describing the windscreen sub-branch
// (after having defined the "winds" point)
// ===========================================

// The motors are not direct children of Dome, so we specify the path
POINT STD_MOTOR_1 winds:motor_1
POINT STD_MOTOR_1 winds:motor_2

The interrelations between the classes defined in this example can be summarized in the following diagram, where the "is a" relation, (inheritance dependence between a class and a sub-class) and the "part of" relation (an instance of a class is a member of another class) are put in evidence.

As a consequence, every time we define an instance of class STD_MOTOR_1 we get the following Rtap database structure:

2.10.2 The RANGE_VALUE class hierarchy

In the following example we give a simplified description of the RANGE_VALUE class hierarchy. These classes are given in the VLT class library.

Their purpose is to give a standard way to treat attributes whose values have to be checked against a range of allowed choices.

An example of the use of these classes has been given in paragraph 2.4.3.

The diagram shows the interrelations between the defined classes. The classes enclosed in a box are expanded in the example.

// ************************************************************************
// * RangeValue.db
// *
// * G.Chiozzi
// *
// * This example shows a simplified implementation of the RANGE_VALUE
// * class hierarchy.
// * Only some classes are described here.
// ************************************************************************


// CLASS RANGE_VALUE
// ==================
// This is the base class of the hierarchy.
// Every point intended to handle a value that must be checked against
// a range of allowed choices must be an instance of a sub-class of
// RANGE_VALUE.
// This base class does not define any range rule. These must be
// defined in the derived classes.

// A set of C functions or C++ access classes must be provided

// for every class in order to implement access methods.


CLASS BASE_CLASS RANGE_VALUE
BEGIN
// We need the CE for the outOfRange flag
CEIndicator enabled

ATTRIBUTE bytes32 stringValue // Value in string format
ATTRIBUTE boolean outOfRange // Flag for out of range cond
BEGIN
// It has a CE function to check the value
Description "Check([.stringValue])"
END
END


// CLASS MIN_MAX_VALUE
// ====================
// This is the base class to describe points where the range
// is delimited by a minimum and a maximum value of some numeric kind.
// In this sample description we add here an attribute for the
// value in numerical format and two attributes where to
// store min and max values. They are of type "double", the more
// general numeric value.
// The attribute stringValue is kept aligned with the value in
// numeric format.

CLASS RANGE_VALUE MIN_MAX_VALUE
BEGIN
ATTRIBUTE double value 0.0
ATTRIBUTE double min MIN_DOUBLE
ATTRIBUTE double max MAX_DOUBLE
END


// CLASS ANALOG_VALUE
// ===================
// In this implementation, the ANALOG_VALUE class adds nothing to the
// parent class. It is used only to have a logical symmetry in the
// class tree with DIGITAL_VALUE.
// It is the class from where we have to get instances.

CLASS MIN_MAX_VALUE ANALOG_VALUE
BEGIN
// Nothing to do in this simplified example
END


// CLASS EXPOSURE_TIME
// =====================
// This class deals with an analog value, but taking into account that
// time is measured in seconds and that an exposure time must be
// positive.

CLASS ANALOG_VALUE EXPOSURE_TIME
BEGIN
ATTRIBUTE double min 0.0
ATTRIBUTE bytes32 units "sec"
END


// CLASS DIGITAL_VALUE
// ====================
// A digital value cannot assume every floating point value, but
// can change only using a discrete step. The class adds an attribute
// to define the step size.
// The default step is 1.0, that means only integer values,
// but any step is valid.

CLASS MIN_MAX_VALUE DIGITAL_VALUE
BEGIN
ATTRIBUTE double step 1.0

END


// CLASS CHOICE_VALUE
// ==================
// The allowed values are in this case placed inside a list
// of legal string values (or numbers expressed in string format).
// The class defines a list. Specific subclasses will
// fill the list with proper values

CLASS RANGE_VALUE CHOICE_VALUE
BEGIN
// This is the vector for the legal choices
// The number of elements will be properly overloaded
// in the derived classes.
ATTRIBUTE Vector choices(0,bytes32)
END


// CLASS SLIDE_POSITION
// ====================
// A slide position is a typical example of value to be
// selected within a list.
CLASS CHOICE_VALUE SLIDE_POSITION
BEGIN
// We define here the allowed values, overloading the
// inherited table.
ATTRIBUTE Vector choices(5,bytes32)
BEGIN
Value ("Closed", "Opened 1/4", "Opened 1/2",
"Opened 3/4", "Fully opened" )
END
END

// ========================================================
// Other classes can implement a more complex behaviour.
// For example the DATE_VALUE class has to check for
// correct day, month and year combinations.....
// ========================================================

2.10.3 Rewriting an example of Point Configuration File

The following example is just the rewriting, using the new syntax, of the sample Point Configuration File given at page 21 of the LCU Common Software User Manual[5].

Here we do not make any use of the class concept, but we just translate the point description: the new format is much more readable and compact.

// ***************************************************************
// * The following point description is the translation of a

// * sample "Point Config File

// *

// * G.Chiozzi

// *************************************************************

// The point has no class support

POINT NULL_CLASS processes

BEGIN

Alias "MAIN"

ATTRIBUTE float airUse 300

ATTRIBUTE bytes8 airUnits "m^3/sec"

ATTRIBUTE float waterUse 8.0938139

ATTRIBUTE Bytes16 wsupplyCondition "Water supply on"

ATTRIBUTE Table breakerDetail(10,

uint8 control, uint8 status, bytes8 condition,

bytes48 location, float rating)

BEGIN

Value ( (0, 0, "", "Control Room", 22.0),

(0, 0, "", "Computer Room", 18.5),

(0, 0, "", "Storage Room", 15.3),

(1, 1, "", "Enclosure", 10.42),

(1, 1, "", "Nasmyth A Instrument", 11.38),

(0, 0, "", "Nasmyth B Instrument", 9.67),

(0, 0, "", "Cassegrain Cage", 12.73),

(1, 1, "", "Coude Room", 14.81),

(1, 1, "", "Hydraulic Plant", 19.2),

(1, 1, "", "Air Conditioning", 5.27)

)

END

ATTRIBUTE Vector dutyAlarmVector(9, uint)

BEGIN

Value (1, 43, 46, 24, 196, 0, 2, 75, 56)

END

ATTRIBUTE double rainIn 0.5392742753102887

ATTRIBUTE uint32 dbfCategories 4294967295

END

1
A prototype version of the dblcb tool is part of the current release. Look in the release notes for limitations and known problems



Quadralay Corporation
http://www.webworks.com
Voice: (512) 719-3399
Fax: (512) 719-3606
sales@webworks.com
TOC PREV NEXT INDEX