Matterデータモデルの要素について学習したので、次はコードの観点からデータモデルを設定し、操作する方法を学びます。
Matter仕様でサポートされているすべてのクラスタには、Matterコード内に対応する実装があります。これらの実装は<install_path>/modules/lib/matter/src/app/clustersディレクトリにあります。
作成したカスタムクラスタでない限り、Matterクラスタに対して独自の実装を提供する必要はありません。カスタムクラスタの作成については、本レッスンの演習2で行います。
Matterプロジェクトは現在、元の設計から新しい設計への移行期間にあります。つまり、対話方法はクラスタによって異なります。本レッスンでは、すべての可能なケースに対応するため、両方の方法を取り上げます。
移行は進行中です。各Matterリビジョンごとに、より多くのクラスタが新しい設計を採用し、最終的には完全なカバレッジが達成されます。
レガシーアプローチでは、元々Zigbeeプロジェクトで使用されていたEmberライブラリを使用します。コードはZCL Advanced Platform tool(ZAP Tool)によって生成されます。ZAP ToolはGUIを備えたツールで、クラスタとそのコンテンツの有効化と無効化、および属性のデフォルト値の設定が可能です。設定は専用の.zap拡張子を持つファイルに保存され、Matterスクリプトによってソースファイルとヘッダーファイルが生成され、コンパイルプロセスに含まれます。
nRF Connect SDKで利用可能なすべてのMatterサンプルアプリケーションには、src/default_zapディレクトリがあり、.zap拡張子を持つファイルとzap-generatedディレクトリが含まれています。zap-generatedディレクトリ内のファイルは、.zapファイルに保存された設定に基づいて生成されます。
この対話方法は、まだ新しい設計に移行していないすべてのクラスタに適用されます。
Code-Drivenと呼ばれる新しい設計は、ZAP Toolの使用とそれが生成するファイルを置き換えることを目的としています。Code-Driven設計では、クラスタとそのコンテンツの有効化または無効化を、開発者がアプリケーションコードから直接行うことを前提としています。通常、基本クラスタオブジェクトから継承するデリゲートと呼ばれる追加のクラスオブジェクトの実装が必要です。
この対話方法は、新しく作成されたクラスタと、新しい設計に完全に移行したクラスタに適用されます。
移行期間中の後方互換性を提供するため、Matter開発者は新しいソリューションとレガシーソリューションの間のブリッジとして機能する追加ファイルを実装しました。これにより、ユーザーはZAP Toolを使用してクラスタを設定し、ファイルを生成し続けることができます。ZAPによって生成されたコールバックメソッドは、これらの「ブリッジ」ファイルによって上書きされ、Code-Driven関連のメソッドと対話します。これらのクラスタは、クラスタのディレクトリ内のCodegenIntegration.cppファイルを探すことで識別できます。例えば、modules/lib/matter/src/app/clusters/identify-serverディレクトリを参照してください。
このソリューションにより、ユーザーはどちらかの対話方法を選択できますが、まだすべての利用可能なクラスタをカバーしているわけではありません。
クラスタのステータスはmodules/lib/matter/src/app/common/templates/config-data.ymlファイルで追跡されています。参考までに、以下のリストはCode-Drivenアプローチで完全にサポートされているクラスタのステータスを示しています。
より詳細な(ただしより複雑な)リファレンスについては、modules/lib/matter/src/app/zap-templates/zcl/内のzcl.jsonファイルを確認してください。このファイルには、ZAP生成コードではなく、アプリケーションまたはMatterスタックコードによって制御されるすべての属性がリストされています。これには、部分的にのみ移行されたクラスタ内の個別の属性も含まれます。
クラスタと属性のリストを確認するには、zcl.jsonファイル内のattributeAccessInterfaceAttributesキーを参照してください。
,およびイベントの有効化と無効化両方のアプローチは、クラスタ設定(クラスタ、属性、コマンド、またはイベントの有効化)にZAP Toolを引き続き使用します。違いは、実装がデータを処理する方法にあります。
ZAP Toolでは、左パネルからエンドポイントを選択し、チェックボックスを使用してリストからクラスタを有効にします。各クラスタは、Serverロール、Clientロール、またはその両方で有効にできます。例えば、Door LockデバイスタイプのDoor Lockクラスタを有効にするには、Serverロールをチェックします。

クラスタのコンテンツを設定するには、歯車アイコンをクリックします。詳細ビューでは、Attributes、Commands、Events、Featuresタブを切り替えることができます。特定の要素の有効化と無効化は、Attributes、Events、Featuresにはスライダーを使用し、Commandsにはチェックボックスを使用して行います。例えば、次の図では、Door Lockクラスタに対してLockState、LockType、ActuatorEnabled、NumberOfTotalUsersSupported、NumberOfPINUsersSupported属性が有効になっていることがわかります。

Code-Driven設計にまだ移行していないクラスタと属性については、デフォルト値とストレージオプションはZAP Toolを使用して設定されます。ストレージオプションは、属性がRAMまたは不揮発性メモリ(NVM)に保存され、再起動後もその値を保持するかどうかを決定します。例えば、次の図では、いくつかの属性がDefault列に値を設定しています。

すでにCode-Drivenに移行したクラスタと属性については、Storage Optionフィールドはグレー表示され、Externalに設定されています。また、ZAP ToolのGUIではDefault列の値を変更できないことにも気付くでしょう。例えば、Basic Informationクラスタについては次の図で確認できます。

ZAP生成コードに基づくクラスタの場合、属性を変更または読み取りたい場所にAccessors.hヘッダーファイルをインクルードします。
#include <app-common/zap-generated/attributes/Accessors.h>属性の値は、クラスタ名と属性名を名前空間で使用して呼び出す必要がある次のメソッドを使用して設定できます。
chip::app::Clusters::ClusterName::Attributes::AttributeName::Set(endpointId, value)例えば、LevelControlクラスタのCurrentLevel属性の値を100に設定し、エンドポイント1で有効になっていると仮定すると、次のコード行を使用して実行できます。
chip::app::Clusters::LevelControl::Attributes::CurrentLevel::Set(1, 100)同様に、chip::app::Clusters::LevelControl::Attributes::CurrentLevel::Get()メソッドを使用してデータモデルから属性の値を取得できます。
アプリケーションでMatterPostAttributeChangeCallbackコールバックを実装します。modules/lib/matter/src/app/util/generic-callbacks.h内のドキュメントを参照してください。
変更された属性とクラスタIDはattributePath引数を通じて渡されます。例えば、LevelControlクラスタのCurrentLevel属性の変更に反応するには、次のようにします。
if (attributePath.mClusterId == LevelControl::Id && attributePath.mAttributeId == LevelControl::Attributes::CurrentLevel::Id)変更された値は、type、size、value引数から取得できます。
Code-Drivenクラスタの場合、属性を変更するための共通の設計はありません。最善のアプローチは、modules/lib/matter/src/app/clusters内の特定のクラスタによって公開されているAPIを確認することです。
例1:Valve Configuration and Control
valve-configuration-and-control-serverディレクトリにあるこのクラスタは、属性値を変更するためにthe valve-configuration-and-control-cluster.hファイル内で次のAPIを公開しています。
CloseValveSetValveLevelUpdateCurrentLevelUpdateCurrentStateUpdateAutoCloseTimeまた、valve-configuration-and-control-delegate.hファイル内のDelegateクラスから継承し、SetDefaultDelegateを使用して登録することで、アプリケーションが実装できるデリゲートも提供します。デリゲートは、属性の変更に反応するための次のハンドラを提供します。
HandleCloseValveHandleOpenValveHandleRemainingDurationTick例2:Boolean State
boolean-state-serverディレクトリにあるこのクラスタは、boolean-state-cluster.hファイル内で次のAPIを公開しています。
SetStateValueGetStateValueこのAPIはエンドポイントIDを直接受け入れません。代わりに、まずFindClusterOnEndpointを使用して特定のエンドポイントのBooleanStateClusterインスタンスを取得します。
bool newState = true;
auto booleanState = chip::app::Clusters::BooleanState::FindClusterOnEndpoint(1);
if (booleanState == nullptr) {
return;
}
booleanState->SetStateValue(newState);