Client Functions

Direct Read

To minimize overhead for sending answer messages from the database to the client (via NGA backend -> NGA frontend -> Data manager to the client), the Direct Read feature allows reading of historical data directly from the database, avoiding the message based overhead. This feature is similar to the direct read feature in the RDB manager. If the direct read operation is faster than a non-direct read depends on multiple parameters, e.g. the size of the answer and the location of the reading client (local / remote).

To use direct read in NGA, the "CtrlNgaFrontend" Control Extension must be loaded in a CONTROL script via #uses "CrtlNgaFrontend". The Control Extension provides the following functions:

  • alertGetPeriodNGA
  • dpGetAsynchNGA
  • dpGetPeriodNGA
  • dpQueryNGA
Note: RDB Control functions can be used to read data in an NGA project by using the RDB Control Extension. To use the RDB Control Extension, use the keyword #uses "ctrlRDBArchive" in your script.
Note:

Datapoints that are deleted cannot be queried anymore and are not included in a query result.

Datapoints whose archive config is deleted remain in the database and can be queried.

Using the config entry “useNGADirectRead” (bool, in [general], [ui] or [ctrl] section) the behavior of the standard WinCC OA historical read functions can be changed to always use their “NGA” counterpart, i.e. use direct read, This means e.g. when a client calls dpGetPeriod(), the direct read counterpart dpGetPeriod-NGA() is called instead.

By using the CONTROL function:

bool setNGADirectRead(bool newState);

The current setting of the queryNGAdirect setting can be changed at runtime from within the CONTROL script. The functionality is identical to the function setQueryRDBdirect() for the RDB manager.

By using the CONTROL function:

bool useNGADirectRead();

the current state of the queryNGAdirect setting can be queried.

Examples

Offline values can be queried as follows:

main()
{
  dyn_float val; //Contains the values
  dyn_time t;//Contains the source times of the values
  int ant;//The function returns -1 in case of errors
  //from the 07.03.2021 to 08.03.2021, at least 1 value before 07.03.2021 and after 08.03.2021
  ant = dpGetPeriodNGA(makeTime(2021,3,7),makeTime(2021,3,8), 1,"System1:ExampleDP_Arg1.:", val, t);
  if ((ant== -1) || (dynlen(val) == 0)) // Is executed if a query error occurs or no values exist
  {
    DebugN("dpGetPeriod caused an error or no values exist");
  }
  else
  {
    int i;//loop variable
    DebugN("Result values:");
    for(i=1;i<=dynlen(val);i++)
    DebugN(val[i],t[i]);
  }
}
main()
{
  float val;
  int ant;
  ant = dpGetAsynchNGA(makeTime(2021, 3, 8, 11, 27), "System1:ExampleDP_Arg1.:", val);
  DebugN("Value of the ExampleDPArg1 on the eighth of March 11.27 am:", val);
}

To query the user who set the value, use ":_offline.._user" as follows:

main()
{
  dyn_int val2; //Contains the users
  dyn_time t;//Contains the source times of the values
  int ant;//The function returns -1 in case of errors
  //from the 07.03.2021 to 08.03.2021, at least 1 value before 07.03.2021 and after 08.03.2021
  ant = dpGetPeriodNGA(makeTime(2021,3,7),makeTime(2021,3,8), 1,"System1:ExampleDP_Arg1.:_offline.._user", val2, t);
  if ((ant== -1) || (dynlen(val2) == 0)) // Is executed if a query error occurs or no values exist
  {
    DebugN("dpGetPeriodNGA caused an error or no values exist");
  }
  else
  {
    int i;//loop variable
    DebugN("Result values and user IDs:");
    for(i=1;i<dynlen(val2);i++)
    DebugN(val2[i],t[i]);
  }
}

Message splitting

There are specific read commands available in WinCC OA to make use of the message splitting feature. „With dpQuerySplit and dpGetPeriodSplit message splitting can be used. Instead of one large answer, multiple smaller answers are received in the calling code. This has a positive impact on the performance since the required work in every component can overlap in time. In other terms: While the CTRL or UI manager receives the first answer, the NGA manager can already work on the second answer, while the database already works on the third answer. Due to this overlap, the total query time is reduced. The size of a "chunk" can be defined with the option Split size of the NGA backend configuration panel.

These functions are identical to the already existing split functions for HDB (ValueArchive). Further explanation can be found in the documentation for these functions.

dpGetPeriodSplit()
dpQuerySplit()
dpCancelSplitRequest()

NGA-specific Split Functions

NGA specific direct read versions of these functions are available (see section Direct Read above):

If you query a frontend by using dpQuerySplitNGA() or dpQueryNGA(), the backend always queries the InfluxDB® in "chunks". Use the option "Split size" on the Database Engineering -> Backend -> Extended Settings tab to specify how big the chunks are. The recommended range is 200-10.000 lines. 1 means that the backend is not queried in "chunks" and the result is received as one result instead of "chunks". Avoid values outside the recommended range as this can have a big impact on performance.

dpGetPeriodSplitNGA()

For a description, see dpGetPeriodSplit()

dpQuerySplitNGA()

For a description, see dpQuerySplit()

dpCancelSplitRequestNGA()

For a description, see dpCancelSplitRequest()

useNGA()

The useNGA() Ctrl function can be used to detect if NGA is used in the current project.