Lua を使用したデータソースの定義

Lua データソースを使用すると、Lua プログラミング言語を使って、Kanzi Studio でデザインと並行してアプリケーションの外部データ依存関係を定義およびシミュレートできます。

注釈

Kanzi Studio の Lua データソースはエクスペリメンタル機能であり、皆様からのフィードバックは非常に重要です。フィードバックを送信するには、こちらの フィードバックフォーム を使用してください。

Lua データソースは、Lua スクリプトと同様に、kzlua プラグインへの依存関係を kzb ファイルに記録します。アプリケーションは、ランタイムにそのプラグインを読み込めるようにする必要があります。Lua プラグインのデプロイ を参照してください。

Lua データソースの作成

Lua データソースを作成するには、次のようにします。

  1. Data Sources ウィンドウで Create Data Source をクリックします。

    ../../_images/create-data-source.png
  2. Create Data Source ウィンドウセットで:

    • このデータソースに使用したい名前を Name に設定します。

    • Data Source Type を Kanzi.LuaDataSource に設定

    OK をクリックします。

    ../../_images/lua-data-source-create.png
  3. Data Sources ウィンドウで クイック編集 をクリックし、Lua Data Script プロパティの値を、Lua Data Source のデータ構造を定義する Lua データスクリプトに設定します。

    ../../_images/lua-data-source-configure.png
  4. ルートデータオブジェクトを返す Lua データスクリプトを作成します。

    Execute Lua Action で使用する通常の Lua スクリプトとは異なり、Lua データスクリプトは、Lua データソースのデータ定義を含むルート DataObject を返す必要があります。

    ヒント

    Lua データスクリプト内でデータオブジェクトをグローバル変数として定義すると、他のスクリプトからデータに簡単にアクセスして変更できます。

    例:

    -- Define a root data object, containing all the data.
    local rootDataObject = DataObject:create("cluster", {
        speed = 100,
        rpm = 2300,
        notifications = {
            { notification = "Service Due"},
            { notification = "Oil Change Needed"},
            { notification = "Dirty Air Filter"},
        },
    })
    
    -- Store all data objects in a global table for easier access from simulation scripts.
    globalData = {}
    
    for child in rootDataObject:iterateChildren() do
        globalData[child:getName()] = child
    end
    
    -- Return the root data object.
    return rootDataObject
    
  5. Data Sources ウィンドウで、データソースの隣にある リロードデータソース をクリックして、そのデータソースからデータオブジェクトを作成します。

    Lua Data Source がデータスクリプトを実行した後、スクリプトで定義されたデータオブジェクトをプロジェクトで使用できます。データオブジェクトの使用 を参照してください。

    ../../_images/load-data-source.png ../../_images/lua-data-source-loaded.png

データのシミュレーション

Execute Lua Action を使用して、Kanzi Studio プロジェクト内のデータフローをシミュレートできます。アプリケーションに Lua ロジックを追加する方法については、Luaを使用して を参照してください。

ヒント

トリガー条件を使用して、アプリケーションでシミュレーションを無効にできます。トリガーに条件を追加する を参照してください。

例:

  1. Kanzi Studio プロジェクトで、継承可能な新しい論理値プロパティタイプを定義します。

    ../../_images/lua-data-source-data-simulation-property.png
  2. このプロパティをプロジェクトのルートノードに追加します。

    ../../_images/lua-data-source-data-simulation-root.png
  3. このプロパティの値を、シミュレーション用 Lua スクリプトを実行するトリガーの条件として使用します。

    ../../_images/lua-data-source-data-simulation-condition.png

    例えば、On Timer トリガーを使用して、時間の経過に伴うデータ更新をシミュレートします。

    -- Initialize global timestamp variable for simulating data update over time.
    if timestamp == nil then
        timestamp = 0
    end
    
    -- Simulate speed and RPM changes.
    local modifier = math.sin(timestamp)
    
    local speed = math.floor(90 + modifier * 30)
    local rpm = math.floor(2000 + modifier * 1000)
    
    -- Use globally defined data table to simulate the data update.
    if globalData then
        globalData.speed:setValue(speed)
        globalData.rpm:setValue(rpm)
    end
    
    -- Advance time.
    timestamp = timestamp + 0.01
    
  4. アプリケーションコードで、ルートノードのこのプロパティの値をオーバーライドして、シミュレーションスクリプトを無効にします。

    例:

    void onProjectLoaded() override
    {
        // Project file has been loaded from .kzb file.
    
        // Project sets "DataSimulation.IsSimulation" property on a Root Node, which is used in triggers conditions to enable simulation scripts.
        // To disable the simulation, set this property value to false on a Root Node.
        DynamicPropertyType<bool> isSimulationProperty("DataSimulation.IsSimulation");
    
        const auto rootNode = getScreen()->getChild(0);
        kzAssert(rootNode);
    
        // Disable data simulation.
        rootNode->setProperty(isSimulationProperty, false);
     }
    
  5. Lua スクリプトで定義したデータオブジェクトを使用して、アプリケーションから実際のデータ値を提供します。

    // Define a DataObjectList to provide actual list data.
    class NotificationsDataObject : public DataObjectList
    {
    public:
    
        ...
    
        // Follow the same data structure as the one you defined in Lua.
        DataObjectSharedPtr getItemTemplate() override
        {
           auto item = DataObject::create(getDomain(), "item");
           item->addChild(DataObjectString::create(getDomain(), "notification"));
           return item;
        }
     };
    
    void onProjectLoaded() override
    {
        ...
    
        // Use data model defined by the Lua Data Source. Retrieve the Data Context from the Root Node.
        auto dataContext = dynamic_pointer_cast<DataContext>(rootNode->getProperty(DataContext::DataContextProperty));
        kzAssert(dataContext);
    
        // Store the data objects to update.
        m_speedData = dynamic_pointer_cast<DataObjectInt>(dataContext->lookupDataContext("speed"));
        kzAssert(m_speedData);
    
        m_rpmData = dynamic_pointer_cast<DataObjectInt>(dataContext->lookupDataContext("rpm"));
        kzAssert(m_rpmData);
    
        // For list data, replace the existing simulation data object list with the actual data object list.
        auto simulationNotificationsDataObject = dynamic_pointer_cast<DataObjectList>(dataContext->lookupDataContext("notifications"));
        kzAssert(simulationNotificationsDataObject);
    
        auto rootDataObject = dataContext->getData();
        kzAssert(rootDataObject);
    
        rootDataObject->removeChild(*simulationNotificationsDataObject);
        rootDataObject->addChild(notificationsData);
    
        // Notify that the data context has been modified.
        dataContext->notifyModified();
    
        getMainLoopScheduler().appendTask(UserStage, kzMakeFixedString("UpdateData"), MainLoopScheduler::TaskRecurrence::Recurring,
            [this](auto)
            {
                this->updateSpeedAndRPMData();
            }
        );
    }
    

関連項目

データオブジェクトの使用

Lua プラグインのデプロイ