3.9 KiB
3.9 KiB
| task | version | source | status |
|---|---|---|---|
| Write a Traditional class with prompts, signals built from the object name, and items created from a template | R1.03 | IM 36K10P10-01EN §1–§5, §8, §10, §11.2.8; IM 36K10L10-01EN; practiced with CI-Eng-Sample class CIENG_TANK 2026-09-30 | verified |
Traditional class: prompts, signals, created items
Worked example: class CIENG_TANK and object CI-Eng-Sample.TANK1.CALC
(examples/CI-Eng-Sample/06_class_df.qli, 07_object_df.qli). Loading and removing: task
load-class-object.md. Language reference: knowledge/manuals/IM36K10P10-01EN.md.
1. Design
One class = one kind of equipment; one object per piece of equipment. Put the variable parts (which items, which settings) in the class prolog so they are fixed when each object is created:
| Need | Use |
|---|---|
| Setting per object, asked at creation | ATTRIBUTE x OBJECT FLOAT; + PROMPT x QUERY "…"; → ATTR_VALUE_n in OBJECT_DF |
| Setting shared by all objects | ATTRIBUTE x CLASS …; |
| Existing item next to the object | `SIGNAL s := SECTION |
| New item per object | SIGNAL s := FROM "<template item>" MAKE "FIELD" EQUAL value …; |
| Refuse bad input | IF … THEN ERROR "text"; ENDIF; in the class prolog |
| Periodic run | trigger group on the class (TRIGGER_1) or object |
| Run on a change | TRIGGER VALUE (or STATUS, UPDATE …) on the signal |
Template items: keep them in their own section (sample: CI-Eng-Sample.TEMPLATES.TPL_REAL)
and load them before the class.
2. Example
CLASS CIENG_TANK;
PROLOG
ATTRIBUTE CAPACITY OBJECT FLOAT;
PROMPT CAPACITY QUERY "Tank capacity (m3)";
SIGNAL LEVEL := SECTION || ".LEVEL" TRIGGER VALUE;
SIGNAL VOLUME := FROM "CI-Eng-Sample.TEMPLATES.TPL_REAL" MAKE
"DESCRIPTION" EQUAL "Tank volume (m3), class CIENG_TANK";
IF CAPACITY <= 0 THEN
ERROR "CIENG_TANK: capacity must be > 0";
ENDIF;
BODY
METHOD CALC;
BODY
VOLUME := LEVEL * CAPACITY / 100.0;
IF LEVEL >=: 80.0 THEN
PRINT "CIENG_TANK ", SECTION, ": level reached 80 pct, volume ", VOLUME;
ENDIF;
ENDMETHOD CALC;
ENDCLASS CIENG_TANK;
Object CI-Eng-Sample.TANK1.CALC with ATTR_VALUE_1 = "200":
SECTION=CI-Eng-Sample.TANK1, soLEVEL→CI-Eng-Sample.TANK1.LEVEL.VOLUMEhas no"NAME", so the item isCI-Eng-Sample.TANK1.CALC.VOLUME; the sectionTANK1.CALCis created too. Both are deleted with the object.LEVEL50 →VOLUME100; 82 → 164.>=:prints once when the level crosses 80 (message inumhlog.log, senderOPCEXE1).
Rules learned on the test system:
- Do not put
%inPRINTtext: the message is cut at that point (ISS-025). - An object at root level has an empty
SECTION; build names with anIFthen (release notes). - Item names in
SIGNALstrings must match exactly; an item that does not exist makes the object creation fail.
3. Check and operate
- Signals → items: export
OBJECT_SIGNAL_DFwith filter'OBJECT = "<object>"'(sample:…CALC:LEVEL→CI-Eng-Sample.TANK1.LEVEL,…CALC:VOLUME→…CALC.VOLUME). - Attribute values: export
OBJECT_ATTR_VAL(same filter); record name<object>:<attribute>, fieldATTR_VALUE. - Change an attribute of a running object (verified):
dssqld -monOBJECT_ATTR_VAL:
The new value is used from the next run (level 50 → volume 200). Do not change attributes that were used to build signal names: the signal keeps its old item (P10 §8.3).@FIELDS NAME,ATTR_VALUE @OBJECT_ATTR_VAL "CI-Eng-Sample.TANK1.CALC:CAPACITY","400" - Class-wide attributes:
CLASS_ATTR_VAL(<class>:<attribute>), not practiced. - Refused object: loading
ATTR_VALUE_1="0"gaveErrors 1withOPC-E-INFO, CIENG_TANK: capacity must be > 0in the.qlo; nothing was created.
Changing the class source later: task change-reset-class.md.