011 Metadata

  • Status: WIP
  • Deciders: tbd.

Context and Problem Statement

The data source contains metadata information about its variables such as range or engineering units. The South API should provide the means to transport the information to the TEK. The TEK may expose the information in a OPC UA compliant fashion through the North API in the OPC UA server. For example, the range of a variable is encoded as AnalogItem in the OPC UA server exposing the range information using OPC UA datatype "Range" in the property "EURange" of the variable.

In addition, TEK scripts may use the information to perform specific actions. For example, an event may be fired when a data point is not in its range (metadata range information) or a temperature will always be converted to Celsius.

A variable may contain structured data. The API should allow to associate metadata with some fields, for example, the member 'temperature' of the struct has unit '° Celsius'.

The API should provide the means for the TEK to identify which metadata of a variable is associated with each read of the variable, i.e., data point at time X was a temperature in Celsius, data point at time Y was a temperature in Fahrenheit.

Decision Drivers

  • Define the means to transport the same metadata information, e.g. unit, from multiple data clients uniformly to the TEK
  • Allow extension of additional metadata "types" without breaking the API or ABI

Considered Options

Option 1: meta data content struct provided as parameter for "register_field" method and as part of "tek_sa_struct_field_type_definition"

The API will expose a metadata struct that contains the metadata information that can be set by data client. The metadata are set during register field.

struct tek_sa_metadata
{
  double range_min;
  double range_max;
  const char *unit;
};

struct tek_sa_api {
  // ...
  TEK_SA_RESULT (*register_field)(tek_sa_data_client_handle dc,
                                  const char* name,
                                  enum tek_sa_field_attributes attributes,
                                  enum tek_sa_variant_type type,
                                  tek_sa_field_handle* new_field_handle,
                                  struct tek_sa_metadata const *metadata);
  // ...
};

Option 2: key/value pair solution without semantic

The data client can set the metadata using a metadata key and a value per field. To remove a metadata information a null value can be set.

struct tek_sa_api {
  void update_metadata(data_client_handle dc, field_handle fh, tek_metadata_key key, struct tek_sa_variant const *value);
};

The key may be predefined values, e.g. int with different constants, or a name with optional reserved strings, e.g. "RANGE_MIN", "RANGE_MAX".

// with int constants
typedef int tek_metadata_key;

#define TEK_METADATA_KEY_RANGE_MIN 1
#define TEK_METADATA_KEY_RANGE_MAX 2
#define TEK_METADATA_KEY_UNIT 3

// with string constants
typedef char * tek_metadata_key;
const char *TEK_METADATA_KEY_RANGE_MIN "RANGE_MIN";
const char *TEK_METADATA_KEY_RANGE_MAX "RANGE_MAX";
const char *TEK_METADATA_KEY_UNIT "RANGE_UNIT";

TODO clarify when the update_metadata function should or must be called.

Decision Outcome

tbd.

Pros and Cons of the Options

Option 1

  • Good, because metadata can be set at simply and unambiguously in through the struct.
  • Bad, because adding new metadata types breaks the API.
  • Bad, because metadata information may not yet be available when register_field is called. Metadata may only be available when the data client is connected to the data source.
  • Bad, because metadata information cannot be updated.
  • Bad, because metadata cannot be stored for a member of a struct.

Option 2

  • Good, because extending new metadata types do not break the API.
  • Good, because updating metadata can be performed during execution of the TEK.
  • Bad, because data client may use keys that are not known to the TEK.