Using service runtime data

Service runtime data is a structured format used to transfer time-critical information from a Kanzi Connect service to a Kanzi Connect Client and then to the UI of an application.

You can define the service runtime data structure either at compile time inside the service description XML document, or at runtime by the service implementation.

This is an example of runtime data:

<runtime-data>
  <current_user>
    <userid datatype="int" default="42" />
    <username datatype="string" default="inactive" />
    <quota datatype="float" />
    <administrator datatype="bool" default="false"/>
    <phone>
      <mobile datatype="string" default=”555-1234”/>
      <office datatype="string" default=”555-4321”/>
    </phone>
    <subordinates datatype="list">
      <useridentifier datatype="int" />
      <username datatype="string" />
    </subordinates>
 </current_user>
</runtime-data>

These rules apply to the runtime data:

  • Supported data types include int, float, string, bool, list, and object.

    • Object type is used for structure definition and cannot contain data but can act as a parent from any type of object.

    • List type can contain any other type except a list itself, which is why you cannot use list recursion.

      You cannot access list elements using the dot notation.

  • Runtime data is reusable as-is when configuring the Kanzi Connect data source using an XML file.

When you access the runtime data through code, use the dot notation.

For example, to access in the above example data the mobile string element that has the default value of 555-1234, use

current_user.phone.mobile

Overriding the compile-time runtime data

To override the runtime data defined at compile time, implement this method in the AbstractService class:

string provideServiceRuntimeDataOverride() { }

If this function returns a non-empty string that contains a valid XML runtime data definition, Kanzi Connect interprets that as the runtime data of the service. When you override this function, Kanzi Connect calls it during service initialization.

Updating runtime data in a service

A service that defines runtime data is responsible for updating that data.

Note

Updating the runtime data excessively can cause performance issues. The recommended maximum update rate is 16ms.

When you make changes to runtime data, Kanzi Connect reports each change of data asynchronously. If you want to update all runtime data changes manually, call the ServiceRuntimeData::notifyModified method.

The generic pattern for the data maintenance is:

runtimeData().setValue("current_user.phone.office", "555-4567");
runtimeData().setValue("current_user.quota", (double)3.3);

// (Optional) flush the changes synchronously.
runtimeData().notifyModified("current_user");

Updating list runtime data in a service

For list type of content, the RuntimeDataObjectList class contains the methods that you can use to modify the content of lists.

This code snippet adds one element to the list defined in the XML file at the beginning of this topic.

auto list = runtimeData().getListObject("current_user.subordinates");
auto listElement = list->createItemInplace();
listElement->findChild<RuntimeDataObjectInt>("useridentifier")->setValue(10);
listElement->findChild<RuntimeDataObjcetString>("username")->setValue("peter");

runtimeData().notifyModified("current_user.subordinates");

Updating runtime data from outside the main thread

A known limitation in Kanzi Connect services is that the execution context is critical for the service implementation.

For example, you can access service properties safely only from the context of the Kanzi Connect main thread.

To invoke the main thread execution, call the notifyWork() method of a service from any execution context. This causes Kanzi Connect to call the work(ConnectWorkItem) method of the service in the main thread context.

This example code updates runtime data from outside the main thread.

void MyServiceService::onRadialRotated(double angleDelta)
{
    notifyWork([this, angleDelta]()
    {
        kzLogInfo(KZ_LOG_CATEGORY_GENERIC, ("Surface Dial rotation angle: {}", angleDelta));
        auto obj = runtimeData().getObject("surfaceDial");
        if (obj)
        {
            auto targetObj = obj->findChild<RuntimeDataObjectReal>("rotationDeltaDegrees");
            if (targetObj)
            {
                targetObj->setValue(angleDelta);
                // (Optional) flush the changes synchronously.
                runtimeData().notifyModified();
            }
         }
   });
}

Using runtime data with Kanzi Connect data source

Kanzi Connect data source accepts the same XML definitions that are used to define the runtime data structure within a service.

Accessing runtime data using HTTP URIs

Kanzi Connect Server provides the runtime data structure of each local and remote service through a HTTP URI

http://localhost:8080/serviceruntimeschema/<servicename>

For example, to access the Cluster Service runtime data schema use:

http://localhost:8080/serviceruntimeschema/cluster

To access the current runtime data, use:

http://localhost:8080/serviceruntimedata/<servicename>

For example, to access the Cluster Service runtime data use:

http://localhost:8080/serviceruntimedata/cluster

Limitations

For large lists the structured runtime data can be inefficient. In such cases, use the regular table-based content providers.