OPCServer

(Engine-Level Function)

Description: Adds a new top-level branch to the VTScada OPC Server’s namespace hierarchy.
Returns: Handle - see comments
Usage: Steady State only.
Function Groups: Network
Related to: SetOPCData
Format: OPCServer(BranchName, CallbackContext)
Parameters:  
BranchName
Required. The name of the branch added at the highest level of the hierarchy.
CallbackContext
Required. The object value of a running module containing some or all of the following callback modules (these callback modules must be implemented by the programmer).

In each case the Item ID passed to the callback will *not* contain the top-level branch name specified in the call to OPCServer.
Modules:

OPCGetItemAttributes(itemID) - Given an OPC item ID, returns a structure containing the attributes of the item. Structure format:

ItemAttributes STRUCT [
        AccessRights;
        Type;
        HasChildren  
 ];

Where:

AccessRights is one of the following values:

1 = READABLE,

2=WRITEABLE,

3= READWRITEABLE


Type is the COM data type of the item value:

2 = VT_I2,

3 = VT_I4,

5 = VT_R8,

8 = VT_BSTR,

11 = VT_BOOL


HasChildren is one of the following values:

0 = has no children,

1 =  has children

OPCGetChildNodes(itemID)  - Given an OPC item ID, returns an array of strings that are the names of child items.

OPCReadItem(itemID) - Given an OPC item ID, returns a structure containing the value, quality and UTC timestamp of the item. Structure format:

OPCVQT Struct [
    Value;
    Quality;
    Timestamp;
  ];

OPCWriteItem(itemID, Value)  -- Given an OPC item ID and a value, attempts to write the value to the item.

OPCGetInternalName(itemID) - Given an OPC item ID, returns the internal name used for that item. This is useful for the case when two or more different item Ids might refer to the same internal "item".

OPCGetProperties(itemID) - Given an OPC item ID, returns an array of structures describing the properties found on that item. Structure format:

  OPCProperty Struct [
    ID             { Property ID number                     };
    Type           { Data type of the property              };
    Name           { Name of the property                   };
    Description    { Description of the property            };
    InvalidMeansBadQuality  { TRUE to indicate that an invalid
 property value implies Bad quality data                     };
  ];

OPCGetPropertyValue(itemID, propertyID) - Given an OPC item ID and a numeric property ID, returns the current value of the specified property.

Comments: This function returns a handle to the OPC server namespace branch (to be used in calls to SetOPCData).

Example:

<
{==================== SimulateOPCServer =====================}
{ This module runs a simulated OPC server.                 }
{============================================================}
SimulateOPCServer
(
  ServerName;
)
[
  OPCGetChildNodes          Module;
  OPCGetPropertyValue       Module;
  OPCGetProperties          Module;
  OPCReadItem               Module;
  OPCWriteItem              Module;
  OPCGetInternalName        Module;
  OPCGetItemAttributes Module;

  CONSTANT OPC_QUALITY_BAD = 0x00;
  CONSTANT OPC_QUALITY_UNCERTAIN = 0x40;
  CONSTANT OPC_QUALITY_GOOD = 0xC0;

  CONSTANT VT_EMPTY = 0;
  CONSTANT VT_NULL  = 1;
  CONSTANT VT_I2    = 2;
  CONSTANT VT_I4    = 3;
  CONSTANT VT_R4    = 4;
  CONSTANT VT_R8    = 5;
  CONSTANT VT_CY    = 6;
  CONSTANT VT_DATE  = 7;
  CONSTANT VT_BSTR  = 8;
]

ServerOn [
  OPCServer(ServerName, Self());
]

<
OPCGetChildNodes
(
  itemID;
)
[
  returnVal = 0;
]

Main [
  If watch(1);
  [
    IfThen(itemID == "",
      returnVal = New(1);
      returnVal[0] = "tags";
    );
    IfThen(itemID == "tags",
      returnVal = New(7);
      returnVal[0] = "ai1";
      returnVal[1] = "ai2";
      returnVal[2] = "NeverSet";
      returnVal[3] = "TextTag";
      returnVal[4] = "ao1";
      returnVal[5] = "AnalogInputs";
      returnVal[6] = "ao2";
    );

    IfThen(itemID == "tags\AnalogInputs",
      returnVal = New(1);
      returnVal[0] = "ai1";
    );
    Return(returnval);
  ]
]
>

<
OPCGetPropertyValue
(
  itemID;
  propertyID;
)
[
  returnVal;
]
Main [
  If watch(1);
  [
    IfThen(propertyID == 5555,
      returnVal = 888;
    );
    IfThen(propertyID == 104,
      returnVal = 99.5;
    );
    IfThen(propertyID == 5000,
      returnVal = "TestArea";
    );
    Return(returnVal);
  ]
]
>

<
OPCGetProperties
(
  itemID;
)
[
  returnVal;
  I;
  OPCProperty Struct [
    ID                { Property ID number             };
    Type              { Data type of the property      };
    Name              { Name of the property           };
    Description       { Description of the property    };
  ];

  OtherStruct Struct [
    TestComment;
    Name;
    ItemHandles;
    Value;
    Quality;
    Timestamp;
  ];
]
Main [
  If watch(1);
  [
      IfThen(itemID == "tags\ai1",
        returnVal = New(3);
        I = 0;
        returnVal[I++] = OPCProperty(104, VT_R8, "HighRawValue",
   "High Instrument Range");
        returnVal[I++] = OPCProperty(5000, VT_BSTR, "Area", "Area");
        returnVal[I++] = OPCProperty(5555, VT_I2, "Type",
                                     "myVTSProp");
      );
      IfThen(itemID == "tags\ai2",
        returnVal = 0;
      );
    Return(returnVal);
  ]
]
>

<
OPCWriteItem
(
  itemID;
  Value;
)
Main [
  If watch(1);
  [
   { Do a write to the specified item. }
    Return(0);
  ]
]
>

<
OPCGetInternalName
(
  itemID;
)
[
  retval;
]

Main [
  If watch(1);
  [
    IfThen(itemID == "tags\ai1",
      retval = "ai1";
    );
    IfThen(itemID == "tags\ai2",
      retval = "ai2";
    );
    IfThen(itemID == "tags\TextTag",
      retval = "TextTag";
    );
    IfThen(itemID == "tags\ao1",
      retval = "ao1";
    );
    IfThen(itemID == "tags\ao2",
      retval = "ao2";
    );
    IfThen(itemID == "tags\AnalogInputs\ai1",
      retval = "ai1";
    );

    Return(retval);
  ]
]
>

<
OPCReadItem
(
  itemID;
)
[
  returnVal;

  OPCVQT Struct [
    Value;
    Quality;
    Timestamp;
  ];

]
Main [
  If watch(1);
  [
    ReadItemTimestamp = CurrentTime();

    IfThen(itemID == "tags\NeverSet",
      returnVal = OPCVQT("NeverSetValue",
                         OPC_QUALITY_UNCERTAIN,
                         ReadItemTimestamp + TimeZone(0));
    );

    Return(returnVal);
  ]
]
>

<
OPCGetItemAttributes
(
  itemID;
)
[
  retval;

  Constant OPCACCESS_READABLE      = 1;
  Constant OPCACCESS_WRITEABLE     = 2;
  Constant OPCACCESS_READWRITEABLE = 3;

  ItemData Struct [
    AccessRights      { Property ID number            };
    Type              { Data type of the property     };
    HasChildren;
  ];
]

Main [
  If watch(1);
  [
    IfThen(itemID == "tags\ai1",
      retval = ItemData(OPCACCESS_READABLE, VT_I4, 0);
   );
    IfThen(itemID == "tags\ai2",
      retval = ItemData(OPCACCESS_READABLE, VT_R8, 0);
    );
    IfThen(itemID == "tags\TextTag",
      retval = ItemData(OPCACCESS_READWRITEABLE, VT_BSTR, 0);
    );
    IfThen(itemID == "tags\ao1",
      retval = ItemData(OPCACCESS_READWRITEABLE, VT_R8, 0);
    );
    IfThen(itemID == "tags\ao2",
      retval = ItemData(OPCACCESS_READWRITEABLE, VT_I4, 0);
    );
    IfThen(itemID == "tags\AnalogInputs\ai1",
      retval = ItemData(OPCACCESS_READABLE, VT_I4, 0);
    );
    IfThen(itemID == "tags\NeverSet",
      retval = ItemData(OPCACCESS_READABLE, VT_BSTR, 0);
    );

{ The following elements are just structural - they have no data }
    IfThen(itemID == "", { A top-level name }
      retval = 0;
    );
    IfThen(itemID == "tags",
      retval = 0;
    );
    IfThen(itemID == "tags\AnalogInputs",
      retval = 0;
    );

    Return(retval);
  ]
]
>

{ End of SimulateOPCServer\CallbacksParent }
>

{ End of SimulateOPCServer }
>