diff --git a/src/app/zap-templates/common/ClustersHelper.js b/src/app/zap-templates/common/ClustersHelper.js
index d0e67ce3e73ed9..d40e4b3697668d 100644
--- a/src/app/zap-templates/common/ClustersHelper.js
+++ b/src/app/zap-templates/common/ClustersHelper.js
@@ -85,6 +85,22 @@ function loadClusters()
.then(clusters => clusters.filter(cluster => cluster.enabled == 1));
}
+function loadCommandResponse(command, packageId)
+{
+ const { db, sessionId } = this.global;
+ return queryCommand.selectCommandById(db, command.id, packageId).then(commandDetails => {
+ if (commandDetails.responseRef == null) {
+ command.response = null;
+ return command;
+ }
+
+ return queryCommand.selectCommandById(db, commandDetails.responseRef, packageId).then(response => {
+ command.response = response;
+ return command;
+ });
+ });
+}
+
function loadCommandArguments(command, packageId)
{
const { db, sessionId } = this.global;
@@ -101,6 +117,7 @@ function loadCommands(packageId)
.then(endpointTypes => queryEndpointType.selectClustersAndEndpointDetailsFromEndpointTypes(db, endpointTypes))
.then(endpointTypesAndClusters => queryCommand.selectCommandDetailsFromAllEndpointTypesAndClusters(
db, endpointTypesAndClusters, true))
+ .then(commands => Promise.all(commands.map(command => loadCommandResponse.call(this, command, packageId))))
.then(commands => Promise.all(commands.map(command => loadCommandArguments.call(this, command, packageId))));
}
@@ -377,51 +394,18 @@ function enhancedCommands(commands, types)
commands.forEach(command => {
command.isResponse = command.name.includes('Response');
command.isManufacturerSpecificCommand = !!this.mfgCode;
- });
-
- commands.forEach(command => {
- // This filter uses the assumption that a response to a command has a well defined name, such as
- // (response name) == (command name + 'Response') or s/Request/Response. This is very often the case,
- // but this is not always true since some clusters use the same response to answer different commands, such as the
- // operational cluster.
- const automaticFilter = response => {
- if (!response.isResponse) {
- return false;
- }
-
- if (response.clusterName != command.clusterName) {
- return false;
- }
-
- if (response.name == command.name) {
- return false;
- }
-
- return (response.name == (command.name + 'Response')) || (response.name == (command.name.replace('Request', 'Response')));
- };
-
- const manualFilter = response => {
- switch (command.name) {
- case 'AddNOC':
- case 'UpdateNOC':
- case 'UpdateFabricLabel':
- case 'RemoveFabric':
- return response.name == 'NOCResponse';
- default:
- return false;
- }
- };
- const filter = response => automaticFilter(response) || manualFilter(response);
- const response = commands.find(filter);
- if (response) {
- command.hasSpecificResponse = true;
- command.responseName = response.name;
- command.response = response;
+ command.hasSpecificResponse = !!command.response;
+ if (command.response) {
+ const responseName = command.response.name;
+ command.responseName = responseName;
+ // The 'response' property contains the response returned by the `selectCommandById`
+ // helper. But this one does not contains all the metadata informations added by
+ // `enhancedItem`, so instead of using the one from ZAP, retrieve the enhanced version.
+ command.response = commands.find(command => command.name == responseName);
} else {
- command.hasSpecificResponse = false;
- command.responseName = 'DefaultSuccess';
- command.response = { arguments : [] };
+ command.responseName = 'DefaultSuccess';
+ command.response = { arguments : [] };
}
});
diff --git a/src/app/zap-templates/zcl/data-model/chip/operational-credentials-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/operational-credentials-cluster.xml
index 7f5aca0a6087ff..e47701cdc0a44e 100644
--- a/src/app/zap-templates/zcl/data-model/chip/operational-credentials-cluster.xml
+++ b/src/app/zap-templates/zcl/data-model/chip/operational-credentials-cluster.xml
@@ -93,7 +93,7 @@ limitations under the License.
-
+
Sender is requesting to add the new node operational certificates.
@@ -102,7 +102,7 @@ limitations under the License.
-
+
Sender is requesting to update the node operational certificates.
@@ -115,12 +115,12 @@ limitations under the License.
-
+
This command SHALL be used by an Administrative Node to set the user-visible Label field for a given Fabric, as reflected by entries in the Fabrics attribute.
-
+
This command is used by Administrative Nodes to remove a given fabric index and delete all associated fabric-scoped data.
diff --git a/src/controller/data_model/controller-clusters.zap b/src/controller/data_model/controller-clusters.zap
index a97e2d16b0d2ee..4520939c4ba982 100644
--- a/src/controller/data_model/controller-clusters.zap
+++ b/src/controller/data_model/controller-clusters.zap
@@ -2772,6 +2772,25 @@
],
"attributes": []
},
+ {
+ "name": "Diagnostic Logs",
+ "code": 50,
+ "mfgCode": null,
+ "define": "DIAGNOSTIC_LOGS_CLUSTER",
+ "side": "server",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "RetrieveLogsResponse",
+ "code": 1,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": []
+ },
{
"name": "General Diagnostics",
"code": 51,
diff --git a/src/controller/java/zap-generated/CHIPClusters-JNI.cpp b/src/controller/java/zap-generated/CHIPClusters-JNI.cpp
index 62078df45a4416..78bc4bd72958d8 100644
--- a/src/controller/java/zap-generated/CHIPClusters-JNI.cpp
+++ b/src/controller/java/zap-generated/CHIPClusters-JNI.cpp
@@ -1142,6 +1142,85 @@ class CHIPContentLauncherClusterLaunchURLResponseCallback
jobject javaCallbackRef;
};
+class CHIPDiagnosticLogsClusterRetrieveLogsResponseCallback
+ : public Callback::Callback
+{
+public:
+ CHIPDiagnosticLogsClusterRetrieveLogsResponseCallback(jobject javaCallback) :
+ Callback::Callback(CallbackFn, this)
+ {
+ JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
+ if (env == nullptr)
+ {
+ ChipLogError(Zcl, "Could not create global reference for Java callback");
+ return;
+ }
+
+ javaCallbackRef = env->NewGlobalRef(javaCallback);
+ if (javaCallbackRef == nullptr)
+ {
+ ChipLogError(Zcl, "Could not create global reference for Java callback");
+ }
+ }
+ ~CHIPDiagnosticLogsClusterRetrieveLogsResponseCallback()
+ {
+ JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
+ if (env == nullptr)
+ {
+ ChipLogError(Zcl, "Could not create global reference for Java callback");
+ return;
+ }
+ env->DeleteGlobalRef(javaCallbackRef);
+ };
+
+ static void CallbackFn(void * context, uint8_t status, chip::ByteSpan content, uint32_t timeStamp, uint32_t timeSinceBoot)
+ {
+ chip::DeviceLayer::StackUnlock unlock;
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
+ jobject javaCallbackRef;
+ jmethodID javaMethod;
+ CHIPDiagnosticLogsClusterRetrieveLogsResponseCallback * cppCallback = nullptr;
+ jbyteArray contentArr;
+
+ VerifyOrExit(env != nullptr, err = CHIP_JNI_ERROR_NO_ENV);
+
+ cppCallback = reinterpret_cast(context);
+ VerifyOrExit(cppCallback != nullptr, err = CHIP_JNI_ERROR_NULL_OBJECT);
+
+ javaCallbackRef = cppCallback->javaCallbackRef;
+ VerifyOrExit(javaCallbackRef != nullptr, err = CHIP_NO_ERROR);
+
+ err = JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(I[BJJ)V", &javaMethod);
+ SuccessOrExit(err);
+
+ contentArr = env->NewByteArray(content.size());
+ VerifyOrExit(contentArr != nullptr, err = CHIP_ERROR_NO_MEMORY);
+ env->ExceptionClear();
+ env->SetByteArrayRegion(contentArr, 0, content.size(), reinterpret_cast(content.data()));
+ VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
+
+ env->CallVoidMethod(javaCallbackRef, javaMethod, static_cast(status), contentArr, static_cast(timeStamp),
+ static_cast(timeSinceBoot));
+
+ env->DeleteLocalRef(contentArr);
+
+ exit:
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(Zcl, "Error invoking Java callback: %" CHIP_ERROR_FORMAT, err.Format());
+ }
+ if (cppCallback != nullptr)
+ {
+ cppCallback->Cancel();
+ delete cppCallback;
+ }
+ }
+
+private:
+ jobject javaCallbackRef;
+};
+
class CHIPDoorLockClusterClearAllPinsResponseCallback : public Callback::Callback
{
public:
@@ -14130,8 +14209,10 @@ JNI_METHOD(void, DiagnosticLogsCluster, retrieveLogsRequest)
JniByteArray transferFileDesignatorArr(env, transferFileDesignator);
- std::unique_ptr onSuccess(
- Platform::New(callback), Platform::Delete);
+ std::unique_ptr
+ onSuccess(Platform::New(callback),
+ Platform::Delete);
std::unique_ptr onFailure(
Platform::New(callback), Platform::Delete);
VerifyOrExit(onSuccess.get() != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
diff --git a/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java b/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java
index 56d5456926b6ef..6bc8d40bd37441 100644
--- a/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java
+++ b/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java
@@ -2072,7 +2072,7 @@ public static long clusterId() {
public native long initWithDevice(long devicePtr, int endpointId);
public void retrieveLogsRequest(
- DefaultClusterCallback callback,
+ RetrieveLogsResponseCallback callback,
int intent,
int requestedProtocol,
byte[] transferFileDesignator) {
@@ -2082,10 +2082,16 @@ public void retrieveLogsRequest(
private native void retrieveLogsRequest(
long chipClusterPtr,
- DefaultClusterCallback callback,
+ RetrieveLogsResponseCallback callback,
int intent,
int requestedProtocol,
byte[] transferFileDesignator);
+
+ public interface RetrieveLogsResponseCallback {
+ void onSuccess(int status, byte[] content, long timeStamp, long timeSinceBoot);
+
+ void onError(Exception error);
+ }
}
public static class DoorLockCluster extends BaseChipCluster {
diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge.mm b/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge.mm
index 92f7279b3f13bb..38edb936b15a11 100644
--- a/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge.mm
@@ -661,6 +661,17 @@
});
};
+void CHIPDiagnosticLogsClusterRetrieveLogsResponseCallbackBridge::OnSuccessFn(
+ void * context, uint8_t status, chip::ByteSpan content, uint32_t timeStamp, uint32_t timeSinceBoot)
+{
+ DispatchSuccess(context, @ {
+ @"status" : [NSNumber numberWithUnsignedChar:status],
+ @"content" : [NSData dataWithBytes:content.data() length:content.size()],
+ @"timeStamp" : [NSNumber numberWithUnsignedLong:timeStamp],
+ @"timeSinceBoot" : [NSNumber numberWithUnsignedLong:timeSinceBoot],
+ });
+};
+
void CHIPDoorLockClusterClearAllPinsResponseCallbackBridge::OnSuccessFn(void * context, uint8_t status)
{
DispatchSuccess(context, @ {
diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge_internal.h b/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge_internal.h
index 9a0209d1a840cd..7b3c4e37966142 100644
--- a/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge_internal.h
+++ b/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge_internal.h
@@ -521,6 +521,17 @@ class CHIPContentLauncherClusterLaunchURLResponseCallbackBridge
static void OnSuccessFn(void * context, chip::CharSpan data, uint8_t contentLaunchStatus);
};
+class CHIPDiagnosticLogsClusterRetrieveLogsResponseCallbackBridge
+ : public CHIPCallbackBridge
+{
+public:
+ CHIPDiagnosticLogsClusterRetrieveLogsResponseCallbackBridge(dispatch_queue_t queue, ResponseHandler handler,
+ CHIPActionBlock action, bool keepAlive = false) :
+ CHIPCallbackBridge(queue, handler, action, OnSuccessFn, keepAlive){};
+
+ static void OnSuccessFn(void * context, uint8_t status, chip::ByteSpan content, uint32_t timeStamp, uint32_t timeSinceBoot);
+};
+
class CHIPDoorLockClusterClearAllPinsResponseCallbackBridge : public CHIPCallbackBridge
{
public:
diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.mm b/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.mm
index 827b02d3db7292..b6ac5ec6dfb83e 100644
--- a/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.mm
@@ -1690,10 +1690,11 @@ - (void)retrieveLogsRequest:(uint8_t)intent
transferFileDesignator:(NSData *)transferFileDesignator
responseHandler:(ResponseHandler)responseHandler
{
- new CHIPDefaultSuccessCallbackBridge(self.callbackQueue, responseHandler, ^(Cancelable * success, Cancelable * failure) {
- return self.cppCluster.RetrieveLogsRequest(
- success, failure, intent, requestedProtocol, [self asByteSpan:transferFileDesignator]);
- });
+ new CHIPDiagnosticLogsClusterRetrieveLogsResponseCallbackBridge(
+ self.callbackQueue, responseHandler, ^(Cancelable * success, Cancelable * failure) {
+ return self.cppCluster.RetrieveLogsRequest(
+ success, failure, intent, requestedProtocol, [self asByteSpan:transferFileDesignator]);
+ });
}
@end
diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h
index 0e7ceaa57f8dfe..e218cad687e28d 100644
--- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h
+++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h
@@ -1185,6 +1185,19 @@ static void OnContentLauncherLaunchURLResponseSuccess(
command->SetCommandExitStatus(CHIP_NO_ERROR);
};
+static void OnDiagnosticLogsRetrieveLogsResponseSuccess(
+ void * context, const chip::app::Clusters::DiagnosticLogs::Commands::RetrieveLogsResponse::DecodableType & data)
+{
+ ChipLogProgress(Zcl, "Received RetrieveLogsResponse:");
+ ChipLogProgress(Zcl, " status: %" PRIu8 "", data.status);
+ ChipLogProgress(Zcl, " content: %zu", data.content.size());
+ ChipLogProgress(Zcl, " timeStamp: %" PRIu32 "", data.timeStamp);
+ ChipLogProgress(Zcl, " timeSinceBoot: %" PRIu32 "", data.timeSinceBoot);
+
+ ModelCommand * command = static_cast(context);
+ command->SetCommandExitStatus(CHIP_NO_ERROR);
+};
+
static void
OnDoorLockClearAllPinsResponseSuccess(void * context,
const chip::app::Clusters::DoorLock::Commands::ClearAllPinsResponse::DecodableType & data)
@@ -8505,7 +8518,7 @@ class DiagnosticLogsRetrieveLogsRequest : public ModelCommand
chip::Controller::DiagnosticLogsCluster cluster;
cluster.Associate(device, endpointId);
- return cluster.InvokeCommand(mRequest, this, OnDefaultSuccess, OnDefaultFailure);
+ return cluster.InvokeCommand(mRequest, this, OnDiagnosticLogsRetrieveLogsResponseSuccess, OnDefaultFailure);
}
private:
diff --git a/zzz_generated/controller-clusters/zap-generated/CHIPClientCallbacks.cpp b/zzz_generated/controller-clusters/zap-generated/CHIPClientCallbacks.cpp
index 35c3fcc73f4ad8..a0798676e0427f 100644
--- a/zzz_generated/controller-clusters/zap-generated/CHIPClientCallbacks.cpp
+++ b/zzz_generated/controller-clusters/zap-generated/CHIPClientCallbacks.cpp
@@ -835,6 +835,23 @@ bool emberAfContentLauncherClusterLaunchURLResponseCallback(EndpointId endpoint,
return true;
}
+bool emberAfDiagnosticLogsClusterRetrieveLogsResponseCallback(EndpointId endpoint, app::CommandSender * commandObj, uint8_t status,
+ chip::ByteSpan content, uint32_t timeStamp, uint32_t timeSinceBoot)
+{
+ ChipLogProgress(Zcl, "RetrieveLogsResponse:");
+ ChipLogProgress(Zcl, " status: %" PRIu8 "", status);
+ ChipLogProgress(Zcl, " content: %zu", content.size());
+ ChipLogProgress(Zcl, " timeStamp: %" PRIu32 "", timeStamp);
+ ChipLogProgress(Zcl, " timeSinceBoot: %" PRIu32 "", timeSinceBoot);
+
+ GET_CLUSTER_RESPONSE_CALLBACKS("DiagnosticLogsClusterRetrieveLogsResponseCallback");
+
+ Callback::Callback * cb =
+ Callback::Callback::FromCancelable(onSuccessCallback);
+ cb->mCall(cb->mContext, status, content, timeStamp, timeSinceBoot);
+ return true;
+}
+
bool emberAfDoorLockClusterClearAllPinsResponseCallback(EndpointId endpoint, app::CommandSender * commandObj, uint8_t status)
{
ChipLogProgress(Zcl, "ClearAllPinsResponse:");
diff --git a/zzz_generated/controller-clusters/zap-generated/CHIPClientCallbacks.h b/zzz_generated/controller-clusters/zap-generated/CHIPClientCallbacks.h
index c9536f6e8cadc4..b7c61a1a325b9e 100644
--- a/zzz_generated/controller-clusters/zap-generated/CHIPClientCallbacks.h
+++ b/zzz_generated/controller-clusters/zap-generated/CHIPClientCallbacks.h
@@ -41,6 +41,8 @@ typedef void (*ApplicationLauncherClusterLaunchAppResponseCallback)(void * conte
typedef void (*ContentLauncherClusterLaunchContentResponseCallback)(void * context, chip::CharSpan data,
uint8_t contentLaunchStatus);
typedef void (*ContentLauncherClusterLaunchURLResponseCallback)(void * context, chip::CharSpan data, uint8_t contentLaunchStatus);
+typedef void (*DiagnosticLogsClusterRetrieveLogsResponseCallback)(void * context, uint8_t status, chip::ByteSpan content,
+ uint32_t timeStamp, uint32_t timeSinceBoot);
typedef void (*DoorLockClusterClearAllPinsResponseCallback)(void * context, uint8_t status);
typedef void (*DoorLockClusterClearAllRfidsResponseCallback)(void * context, uint8_t status);
typedef void (*DoorLockClusterClearHolidayScheduleResponseCallback)(void * context, uint8_t status);
diff --git a/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp b/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp
index 7a015b06b3e3e3..baf39de5757a88 100644
--- a/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp
+++ b/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp
@@ -3893,9 +3893,10 @@ CHIP_ERROR DiagnosticLogsCluster::RetrieveLogsRequest(Callback::Cancelable * onS
// DiagnosticLogs Cluster Attributes
template CHIP_ERROR ClusterBase::InvokeCommand(
+ chip::app::Clusters::DiagnosticLogs::Commands::RetrieveLogsResponse::DecodableType>(
const chip::app::Clusters::DiagnosticLogs::Commands::RetrieveLogsRequest::Type &, void *,
- CommandResponseSuccessCallback, CommandResponseFailureCallback);
+ CommandResponseSuccessCallback,
+ CommandResponseFailureCallback);
// DoorLock Cluster Commands
CHIP_ERROR DoorLockCluster::ClearAllPins(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback)
diff --git a/zzz_generated/controller-clusters/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/controller-clusters/zap-generated/IMClusterCommandHandler.cpp
index 0ef28c73c599c3..4575661e6fc356 100644
--- a/zzz_generated/controller-clusters/zap-generated/IMClusterCommandHandler.cpp
+++ b/zzz_generated/controller-clusters/zap-generated/IMClusterCommandHandler.cpp
@@ -420,6 +420,118 @@ void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPa
} // namespace ContentLauncher
+namespace DiagnosticLogs {
+
+void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv)
+{
+ // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
+ // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
+ // Any error value TLVUnpackError means we have received an illegal value.
+ // The following variables are used for all commands to save code size.
+ CHIP_ERROR TLVError = CHIP_NO_ERROR;
+ CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
+ uint32_t validArgumentCount = 0;
+ uint32_t expectArgumentCount = 0;
+ uint32_t currentDecodeTagId = 0;
+ bool wasHandled = false;
+ {
+ switch (aCommandPath.mCommandId)
+ {
+ case Commands::RetrieveLogsResponse::Id: {
+ expectArgumentCount = 4;
+ uint8_t status;
+ chip::ByteSpan content;
+ uint32_t timeStamp;
+ uint32_t timeSinceBoot;
+ bool argExists[4];
+
+ memset(argExists, 0, sizeof argExists);
+
+ while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
+ {
+ // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
+ // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
+ if (!TLV::IsContextTag(aDataTlv.GetTag()))
+ {
+ continue;
+ }
+ currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
+ if (currentDecodeTagId < 4)
+ {
+ if (argExists[currentDecodeTagId])
+ {
+ ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
+ TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
+ break;
+ }
+ else
+ {
+ argExists[currentDecodeTagId] = true;
+ validArgumentCount++;
+ }
+ }
+ switch (currentDecodeTagId)
+ {
+ case 0:
+ TLVUnpackError = aDataTlv.Get(status);
+ break;
+ case 1:
+ TLVUnpackError = aDataTlv.Get(content);
+ break;
+ case 2:
+ TLVUnpackError = aDataTlv.Get(timeStamp);
+ break;
+ case 3:
+ TLVUnpackError = aDataTlv.Get(timeSinceBoot);
+ break;
+ default:
+ // Unsupported tag, ignore it.
+ ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
+ break;
+ }
+ if (CHIP_NO_ERROR != TLVUnpackError)
+ {
+ break;
+ }
+ }
+
+ if (CHIP_END_OF_TLV == TLVError)
+ {
+ // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
+ TLVError = CHIP_NO_ERROR;
+ }
+
+ if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount)
+ {
+ wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsResponseCallback(aCommandPath.mEndpointId, apCommandObj,
+ status, content, timeStamp, timeSinceBoot);
+ }
+ break;
+ }
+ default: {
+ // Unrecognized command ID, error status will apply.
+ ReportCommandUnsupported(apCommandObj, aCommandPath);
+ return;
+ }
+ }
+ }
+
+ if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
+ {
+ apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand);
+ ChipLogProgress(Zcl,
+ "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT
+ ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32,
+ validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId);
+ // A command with no arguments would never write currentDecodeTagId. If
+ // progress logging is also disabled, it would look unused. Silence that
+ // warning.
+ UNUSED_VAR(currentDecodeTagId);
+ }
+}
+
+} // namespace DiagnosticLogs
+
namespace DoorLock {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv)
@@ -5307,6 +5419,9 @@ void DispatchSingleClusterResponseCommand(const ConcreteCommandPath & aCommandPa
case Clusters::ContentLauncher::Id:
Clusters::ContentLauncher::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
+ case Clusters::DiagnosticLogs::Id:
+ Clusters::DiagnosticLogs::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
+ break;
case Clusters::DoorLock::Id:
Clusters::DoorLock::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;