dpQueryConnectSingle()

The function dpQueryConnectSingle subscribes to attributes of configs from multiple Data Point Elements, which meet a certain query condition. When a subscribed attribute changes, a callback function (“work” function) is executed. The Event Manager will send every single change separately, so update messages will normally contain only one element. If however several of the subscribed attributes are changed together within one message (i.e. in one dpSet() function call), then these will be all be forwarded in one message to the subscribing work function. Additionally, the execution of the work function can be delayed with the optional parameter blockingTime to accumulate more changes, increasing performance.

Synopsis

int dpQueryConnectSingle([class object,] string|function_ptr work,bool wantsanswer, anytype userData, string query,[int blockingTime]);

Parameters

Parameter Meaning
object An object of a Control++ class.
work

Name of the callback function ("work function") that is called when data point values change.

Or

The name of a function pointer to the work function (callback function).

wantsanswer Defines whether the work function is to be called immediately on registration.
userData User-defined data which is passed as parameter to the callback function.
query

The query as an SQL statement

VORSICHT: Connect functions can only be used for configs which are managed by the event manager. Therefore it is not possible to make a connect on the following configs: _archive, _address, _cmd_conv, _msg_conv, _smooth
blockingTime Timerange in [ms] where the call of the callback function is blocked by the open queries. Specify the blocking time in milliseconds <=32767. If the blockingTime is set to 0, the callback function is not blocked. Without this value, the value is read from the config entry [different sections] queryHLBlockedTime from the config file.

Return Value

dpQueryConnectSingle() returns 0, -1 in the event of an error.

The return value only indicates whether a CONNECT message was sent, but not whether the execution of the function (query) was successful. The error is written to the thread after the function has been executed and can be retrieved with a subsequent call of the function getLastError(). See also Error Handling.

Errors

Errors can be retrieved with getLastError(). This includes missing arguments (also of the work function), undefined functions, incorrect arguments (for example, no Control expression), and if no identifier or query is specified. The usage of erroneous queries or non-initialized variables for the parameter userData will raise an error.

Description

The function dpQueryConnectSingle calls the workfunc function (also called the callback function) when values of data points change. When a value changes, the changed value is returned. The workfunc function is only called once for simultaneous value changes. If there are several asynchronous (not simultaneous) value changes, the workfunc is called for each value change.

All attributes of configs that are held by the Event manager, such as _original, _online, _alert_hdl etc. can be queried, for example:

"SELECT '_online.._value' FROM '*'"

But configs from other managers cannot be queried in this way, e.g:

 "SELECT '_adress.._active' FROM '*' WHERE ('_adress.._active' == 0)"

The query above returns an empty string of type anytype.

If an immediate answer of the function after registration is forced with the parameter wantsanswer = "true", the entire result table is returned, meaning that values are immediately returned.

The optional parameter blockingTime allows the definition of a delay time for the execution of the callback function. After the specified time, the work function is executed with all the value change updates accumulated during this period. This allows for group-wise execution of code and therefore enhanced performance.

The registered function workfunc() must have the following parameters:

void workfunc( anytype userData, dyn_dyn_anytype result)

Parameters Meaning
userData User-defined data passed to the workfunc function.
result Result of the query (values)

Since dpQueryConnectSingle is handled in the Event Manager, the keywords "SELECT ALL" and "SELECT with TIMERANGE" should not be used for query connects.

Note that if you want to include a data point type in a query you can do it in the following way:

 dpQueryConnectSingle("SELECT '_online.._value' FROM '*' WHERE _DPT = \"ExampleDP_Float\" ", ddaTab);

A data point element of type struct cannot be queried via dpQueryConnectSingle(). When querying a data point element of type struct, the following warning may occur:

 WCCILevent (0), <TIMESTAMP>, IMPL, WARNING, 54, Unexpected state, DP: <DP-ID>:_original.._stime, MAN: (SYS: 1 Event -num 0 CONN: 1), EvDpManager::getDpValueAttribut: no config

In this case, check the configuration of the data point type. A data point element in a data point structure must always be a "real" data type (e.g. integer, string, float,...) in order to query the data point element via dpQueryConnectSingle().

When querying the _original config of a DPE and an update of the query was performed (meaning new data points were created), the result will also contain struct elements (structs). Normally, structs are removed when creating a query by filtering out blank lines, which increases performance. However, when a query is updated, new data points are added to the table, resulting in structs being shown in the table after that point.

Creating and deleting optional data point configs only triggers a callback if the _type attribute is available for the configs.

Result table: Example of the result in the variable ddaTab

ddaTab[1][1] (empty) ddaTab[1][2] column header
ddaTab[2][1] line name 2 ddaTab[2][2] contents of line 2
ddaTab[3][1] line name 3 ddaTab[3][2] contents of line 3
... ...

The first entry ddaTab[1][1] is not used, ddaTab[1][2] contains the overview of the columns and ddaTab[n][1] (n>1) contains the name of the column in question. The name found in the query is finally located in ddaTab[n][2], n>1.

The following example queries the data point type ExampleDP_Arg and sets the values of the data points ExampleDP_Arg1 and ExampleDP_Arg2. The values are then output and written to two text fields in the workfunc "doIt".

main()
{
  string query = "SELECT '_online.._value' FROM 'ExampleDP*' WHERE _LEAF";
  //_LEAF returns the leaves of the DPs (without structural nodes)
  dpQueryConnectSingle("doIt", FALSE, "User Data", query); 
}

void doIt(string userData, dyn_dyn_anytype ddaTab)
{
  float fNewValue;
  string DPE;
  int i;   
 
  for(i=2;i<=dynlen(ddaTab);i++)
  {
    DPE = ddaTab[i][1];          //first column always contains full qualified descriptor of DPE.
    fNewValue = ddaTab[i][2];    //second column contains the new value of the subscribed attribute}
    DebugN(DPE, fNewValue);
  }
}

The example outputs:

WCCOAui1:["System1:ExampleDP_Arg2."][100]
WCCOAui1:["System1:ExampleDP_Arg2."][100]
WCCOAui1:["System1:ExampleDP_Result."][104]
WCCOAui1:["System1:ExampleDP_Result."][104]
WCCOAui1:["System1:ExampleDP_Arg2."][69]
WCCOAui1:["System1:ExampleDP_Arg2."][69]
WCCOAui1:["System1:ExampleDP_Result."][73]
WCCOAui1:["System1:ExampleDP_Result."][73]
WCCOAui1:["System1:ExampleDP_Arg1."][16]
WCCOAui1:["System1:ExampleDP_Arg1."][16]
WCCOAui1:["System1:ExampleDP_Result."][85]
WCCOAui1:["System1:ExampleDP_Result."][85]

You can find an example of how to use a Control++ class instance in a connect function in the chapter dpConnect().

Assignment

Data point function, Waiting Control function

Availability

CTRL