text: /*
   *
   *    Copyright (c) 2021 Project CHIP Authors
   *
   *    Licensed under the Apache License, Version 2.0 (the "License");
   *    you may not use this file except in compliance with the License.
   *    You may obtain a copy of the License at
   *
   *        http://www.apache.org/licenses/LICENSE-2.0
   *
   *    Unless required by applicable law or agreed to in writing, software
   *    distributed under the License is distributed on an "AS IS" BASIS,
   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *    See the License for the specific language governing permissions and
   *    limitations under the License.
   */
  
  // THIS FILE IS GENERATED BY ZAP
  
  #include <cinttypes>
  #include <cstdint>
  
  #include "af-structs.h"
  #include "app/util/util.h"
  #include "callback.h"
  #include "cluster-id.h"
  #include "command-id.h"
  
  #include <app/InteractionModelEngine.h>
  
  // Currently we need some work to keep compatible with ember lib.
  #include <app/util/ember-compatibility-functions.h>
  
  namespace chip {
  namespace app {
  
  // Cluster specific command parsing
  
  namespace clusters {
  
  namespace AccountLogin {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_GET_SETUP_PIN_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              const uint8_t * setupPIN;
              bool argExists[1];
  
              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 < 1)
                  {
                      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:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(setupPIN);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfAccountLoginClusterGetSetupPINResponseCallback(apCommandObj, const_cast<uint8_t *>(setupPIN));
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_ACCOUNT_LOGIN_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ACCOUNT_LOGIN_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_ACCOUNT_LOGIN_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace AccountLogin
  
  namespace ApplicationLauncher {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_LAUNCH_APP_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t status;
              const uint8_t * data;
              bool argExists[2];
  
              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 < 2)
                  {
                      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:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(data);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled =
                      emberAfApplicationLauncherClusterLaunchAppResponseCallback(apCommandObj, status, const_cast<uint8_t *>(data));
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_APPLICATION_LAUNCHER_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_APPLICATION_LAUNCHER_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_APPLICATION_LAUNCHER_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace ApplicationLauncher
  
  namespace ContentLaunch {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_LAUNCH_CONTENT_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              const uint8_t * data;
              uint8_t contentLaunchStatus;
              bool argExists[2];
  
              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 < 2)
                  {
                      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:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(data);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(contentLaunchStatus);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfContentLaunchClusterLaunchContentResponseCallback(apCommandObj, const_cast<uint8_t *>(data),
                                                                                        contentLaunchStatus);
              }
              break;
          }
          case ZCL_LAUNCH_URL_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              const uint8_t * data;
              uint8_t contentLaunchStatus;
              bool argExists[2];
  
              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 < 2)
                  {
                      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:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(data);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(contentLaunchStatus);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfContentLaunchClusterLaunchURLResponseCallback(apCommandObj, const_cast<uint8_t *>(data),
                                                                                    contentLaunchStatus);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_CONTENT_LAUNCH_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_CONTENT_LAUNCH_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_CONTENT_LAUNCH_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace ContentLaunch
  
  namespace DoorLock {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_CLEAR_ALL_PINS_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterClearAllPinsResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_CLEAR_ALL_RFIDS_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterClearAllRfidsResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_CLEAR_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterClearHolidayScheduleResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_CLEAR_PIN_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterClearPinResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_CLEAR_RFID_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterClearRfidResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_CLEAR_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_CLEAR_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterClearYeardayScheduleResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_GET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 5;
              uint8_t scheduleId;
              uint8_t status;
              uint32_t localStartTime;
              uint32_t localEndTime;
              uint8_t operatingModeDuringHoliday;
              bool argExists[5];
  
              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 < 5)
                  {
                      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(scheduleId);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(status);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(localStartTime);
                      break;
                  case 3:
                      TLVUnpackError = aDataTlv.Get(localEndTime);
                      break;
                  case 4:
                      TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday);
                      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 && 5 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterGetHolidayScheduleResponseCallback(
                      apCommandObj, scheduleId, status, localStartTime, localEndTime, operatingModeDuringHoliday);
              }
              break;
          }
          case ZCL_GET_LOG_RECORD_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 7;
              uint16_t logEntryId;
              uint32_t timestamp;
              uint8_t eventType;
              uint8_t source;
              uint8_t eventIdOrAlarmCode;
              uint16_t userId;
              const uint8_t * pin;
              bool argExists[7];
  
              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 < 7)
                  {
                      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(logEntryId);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(timestamp);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(eventType);
                      break;
                  case 3:
                      TLVUnpackError = aDataTlv.Get(source);
                      break;
                  case 4:
                      TLVUnpackError = aDataTlv.Get(eventIdOrAlarmCode);
                      break;
                  case 5:
                      TLVUnpackError = aDataTlv.Get(userId);
                      break;
                  case 6:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(pin);
                      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 && 7 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterGetLogRecordResponseCallback(
                      apCommandObj, logEntryId, timestamp, eventType, source, eventIdOrAlarmCode, userId, const_cast<uint8_t *>(pin));
              }
              break;
          }
          case ZCL_GET_PIN_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 4;
              uint16_t userId;
              uint8_t userStatus;
              uint8_t userType;
              const uint8_t * pin;
              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(userId);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(userStatus);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(userType);
                      break;
                  case 3:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(pin);
                      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)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterGetPinResponseCallback(apCommandObj, userId, userStatus, userType,
                                                                            const_cast<uint8_t *>(pin));
              }
              break;
          }
          case ZCL_GET_RFID_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 4;
              uint16_t userId;
              uint8_t userStatus;
              uint8_t userType;
              const uint8_t * rfid;
              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(userId);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(userStatus);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(userType);
                      break;
                  case 3:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(rfid);
                      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)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterGetRfidResponseCallback(apCommandObj, userId, userStatus, userType,
                                                                             const_cast<uint8_t *>(rfid));
              }
              break;
          }
          case ZCL_GET_USER_TYPE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint16_t userId;
              uint8_t userType;
              bool argExists[2];
  
              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 < 2)
                  {
                      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(userId);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(userType);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterGetUserTypeResponseCallback(apCommandObj, userId, userType);
              }
              break;
          }
          case ZCL_GET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 8;
              uint8_t scheduleId;
              uint16_t userId;
              uint8_t status;
              uint8_t daysMask;
              uint8_t startHour;
              uint8_t startMinute;
              uint8_t endHour;
              uint8_t endMinute;
              bool argExists[8];
  
              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 < 8)
                  {
                      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(scheduleId);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(userId);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(status);
                      break;
                  case 3:
                      TLVUnpackError = aDataTlv.Get(daysMask);
                      break;
                  case 4:
                      TLVUnpackError = aDataTlv.Get(startHour);
                      break;
                  case 5:
                      TLVUnpackError = aDataTlv.Get(startMinute);
                      break;
                  case 6:
                      TLVUnpackError = aDataTlv.Get(endHour);
                      break;
                  case 7:
                      TLVUnpackError = aDataTlv.Get(endMinute);
                      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 && 8 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterGetWeekdayScheduleResponseCallback(
                      apCommandObj, scheduleId, userId, status, daysMask, startHour, startMinute, endHour, endMinute);
              }
              break;
          }
          case ZCL_GET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 5;
              uint8_t scheduleId;
              uint16_t userId;
              uint8_t status;
              uint32_t localStartTime;
              uint32_t localEndTime;
              bool argExists[5];
  
              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 < 5)
                  {
                      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(scheduleId);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(userId);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(status);
                      break;
                  case 3:
                      TLVUnpackError = aDataTlv.Get(localStartTime);
                      break;
                  case 4:
                      TLVUnpackError = aDataTlv.Get(localEndTime);
                      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 && 5 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterGetYeardayScheduleResponseCallback(apCommandObj, scheduleId, userId, status,
                                                                                        localStartTime, localEndTime);
              }
              break;
          }
          case ZCL_LOCK_DOOR_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterLockDoorResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_SET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterSetHolidayScheduleResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_SET_PIN_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterSetPinResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_SET_RFID_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterSetRfidResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_SET_USER_TYPE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterSetUserTypeResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_SET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_SET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterSetYeardayScheduleResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_UNLOCK_DOOR_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterUnlockDoorResponseCallback(apCommandObj, status);
              }
              break;
          }
          case ZCL_UNLOCK_WITH_TIMEOUT_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(apCommandObj, status);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_DOOR_LOCK_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DOOR_LOCK_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_DOOR_LOCK_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace DoorLock
  
  namespace GeneralCommissioning {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_ARM_FAIL_SAFE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t errorCode;
              const uint8_t * debugText;
              bool argExists[2];
  
              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 < 2)
                  {
                      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(errorCode);
                      break;
                  case 1:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(apCommandObj, errorCode,
                                                                                             const_cast<uint8_t *>(debugText));
              }
              break;
          }
          case ZCL_COMMISSIONING_COMPLETE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t errorCode;
              const uint8_t * debugText;
              bool argExists[2];
  
              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 < 2)
                  {
                      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(errorCode);
                      break;
                  case 1:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback(
                      apCommandObj, errorCode, const_cast<uint8_t *>(debugText));
              }
              break;
          }
          case ZCL_SET_REGULATORY_CONFIG_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t errorCode;
              const uint8_t * debugText;
              bool argExists[2];
  
              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 < 2)
                  {
                      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(errorCode);
                      break;
                  case 1:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback(
                      apCommandObj, errorCode, const_cast<uint8_t *>(debugText));
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_GENERAL_COMMISSIONING_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_GENERAL_COMMISSIONING_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace GeneralCommissioning
  
  namespace Groups {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_ADD_GROUP_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t status;
              uint16_t groupId;
              bool argExists[2];
  
              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 < 2)
                  {
                      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(groupId);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfGroupsClusterAddGroupResponseCallback(apCommandObj, status, groupId);
              }
              break;
          }
          case ZCL_GET_GROUP_MEMBERSHIP_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 3;
              uint8_t capacity;
              uint8_t groupCount;
              /* TYPE WARNING: array array defaults to */ uint8_t * groupList;
              bool argExists[3];
  
              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 < 3)
                  {
                      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(capacity);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(groupCount);
                      break;
                  case 2:
                      // Just for compatibility, we will add array type support in IM later.
                      TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(groupList));
                      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 && 3 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfGroupsClusterGetGroupMembershipResponseCallback(apCommandObj, capacity, groupCount, groupList);
              }
              break;
          }
          case ZCL_REMOVE_GROUP_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t status;
              uint16_t groupId;
              bool argExists[2];
  
              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 < 2)
                  {
                      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(groupId);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfGroupsClusterRemoveGroupResponseCallback(apCommandObj, status, groupId);
              }
              break;
          }
          case ZCL_VIEW_GROUP_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 3;
              uint8_t status;
              uint16_t groupId;
              const uint8_t * groupName;
              bool argExists[3];
  
              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 < 3)
                  {
                      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(groupId);
                      break;
                  case 2:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(groupName);
                      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 && 3 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled =
                      emberAfGroupsClusterViewGroupResponseCallback(apCommandObj, status, groupId, const_cast<uint8_t *>(groupName));
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_GROUPS_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GROUPS_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_GROUPS_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace Groups
  
  namespace Identify {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_IDENTIFY_QUERY_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint16_t timeout;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(timeout);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfIdentifyClusterIdentifyQueryResponseCallback(apCommandObj, timeout);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_IDENTIFY_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IDENTIFY_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_IDENTIFY_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace Identify
  
  namespace KeypadInput {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_SEND_KEY_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t status;
              bool argExists[1];
  
              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 < 1)
                  {
                      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;
                  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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfKeypadInputClusterSendKeyResponseCallback(apCommandObj, status);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_KEYPAD_INPUT_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_KEYPAD_INPUT_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_KEYPAD_INPUT_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace KeypadInput
  
  namespace MediaPlayback {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_MEDIA_FAST_FORWARD_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t mediaPlaybackStatus;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(mediaPlaybackStatus);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfMediaPlaybackClusterMediaFastForwardResponseCallback(apCommandObj, mediaPlaybackStatus);
              }
              break;
          }
          case ZCL_MEDIA_NEXT_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t mediaPlaybackStatus;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(mediaPlaybackStatus);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfMediaPlaybackClusterMediaNextResponseCallback(apCommandObj, mediaPlaybackStatus);
              }
              break;
          }
          case ZCL_MEDIA_PAUSE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t mediaPlaybackStatus;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(mediaPlaybackStatus);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfMediaPlaybackClusterMediaPauseResponseCallback(apCommandObj, mediaPlaybackStatus);
              }
              break;
          }
          case ZCL_MEDIA_PLAY_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t mediaPlaybackStatus;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(mediaPlaybackStatus);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfMediaPlaybackClusterMediaPlayResponseCallback(apCommandObj, mediaPlaybackStatus);
              }
              break;
          }
          case ZCL_MEDIA_PREVIOUS_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t mediaPlaybackStatus;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(mediaPlaybackStatus);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfMediaPlaybackClusterMediaPreviousResponseCallback(apCommandObj, mediaPlaybackStatus);
              }
              break;
          }
          case ZCL_MEDIA_REWIND_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t mediaPlaybackStatus;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(mediaPlaybackStatus);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfMediaPlaybackClusterMediaRewindResponseCallback(apCommandObj, mediaPlaybackStatus);
              }
              break;
          }
          case ZCL_MEDIA_SKIP_BACKWARD_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t mediaPlaybackStatus;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(mediaPlaybackStatus);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfMediaPlaybackClusterMediaSkipBackwardResponseCallback(apCommandObj, mediaPlaybackStatus);
              }
              break;
          }
          case ZCL_MEDIA_SKIP_FORWARD_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t mediaPlaybackStatus;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(mediaPlaybackStatus);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfMediaPlaybackClusterMediaSkipForwardResponseCallback(apCommandObj, mediaPlaybackStatus);
              }
              break;
          }
          case ZCL_MEDIA_SKIP_SEEK_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t mediaPlaybackStatus;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(mediaPlaybackStatus);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfMediaPlaybackClusterMediaSkipSeekResponseCallback(apCommandObj, mediaPlaybackStatus);
              }
              break;
          }
          case ZCL_MEDIA_START_OVER_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t mediaPlaybackStatus;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(mediaPlaybackStatus);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfMediaPlaybackClusterMediaStartOverResponseCallback(apCommandObj, mediaPlaybackStatus);
              }
              break;
          }
          case ZCL_MEDIA_STOP_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t mediaPlaybackStatus;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(mediaPlaybackStatus);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfMediaPlaybackClusterMediaStopResponseCallback(apCommandObj, mediaPlaybackStatus);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_MEDIA_PLAYBACK_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_MEDIA_PLAYBACK_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_MEDIA_PLAYBACK_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace MediaPlayback
  
  namespace NetworkCommissioning {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_ADD_THREAD_NETWORK_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t errorCode;
              const uint8_t * debugText;
              bool argExists[2];
  
              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 < 2)
                  {
                      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(errorCode);
                      break;
                  case 1:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(apCommandObj, errorCode,
                                                                                                  const_cast<uint8_t *>(debugText));
              }
              break;
          }
          case ZCL_ADD_WI_FI_NETWORK_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t errorCode;
              const uint8_t * debugText;
              bool argExists[2];
  
              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 < 2)
                  {
                      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(errorCode);
                      break;
                  case 1:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(apCommandObj, errorCode,
                                                                                                const_cast<uint8_t *>(debugText));
              }
              break;
          }
          case ZCL_DISABLE_NETWORK_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t errorCode;
              const uint8_t * debugText;
              bool argExists[2];
  
              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 < 2)
                  {
                      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(errorCode);
                      break;
                  case 1:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(apCommandObj, errorCode,
                                                                                                const_cast<uint8_t *>(debugText));
              }
              break;
          }
          case ZCL_ENABLE_NETWORK_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t errorCode;
              const uint8_t * debugText;
              bool argExists[2];
  
              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 < 2)
                  {
                      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(errorCode);
                      break;
                  case 1:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(apCommandObj, errorCode,
                                                                                               const_cast<uint8_t *>(debugText));
              }
              break;
          }
          case ZCL_REMOVE_NETWORK_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t errorCode;
              const uint8_t * debugText;
              bool argExists[2];
  
              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 < 2)
                  {
                      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(errorCode);
                      break;
                  case 1:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(apCommandObj, errorCode,
                                                                                               const_cast<uint8_t *>(debugText));
              }
              break;
          }
          case ZCL_SCAN_NETWORKS_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 4;
              uint8_t errorCode;
              const uint8_t * debugText;
              /* TYPE WARNING: array array defaults to */ uint8_t * wifiScanResults;
              /* TYPE WARNING: array array defaults to */ uint8_t * threadScanResults;
              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(errorCode);
                      break;
                  case 1:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      break;
                  case 2:
                      // Just for compatibility, we will add array type support in IM later.
                      TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(wifiScanResults));
                      break;
                  case 3:
                      // Just for compatibility, we will add array type support in IM later.
                      TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(threadScanResults));
                      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)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfNetworkCommissioningClusterScanNetworksResponseCallback(
                      apCommandObj, errorCode, const_cast<uint8_t *>(debugText), wifiScanResults, threadScanResults);
              }
              break;
          }
          case ZCL_UPDATE_THREAD_NETWORK_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t errorCode;
              const uint8_t * debugText;
              bool argExists[2];
  
              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 < 2)
                  {
                      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(errorCode);
                      break;
                  case 1:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback(
                      apCommandObj, errorCode, const_cast<uint8_t *>(debugText));
              }
              break;
          }
          case ZCL_UPDATE_WI_FI_NETWORK_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t errorCode;
              const uint8_t * debugText;
              bool argExists[2];
  
              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 < 2)
                  {
                      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(errorCode);
                      break;
                  case 1:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback(apCommandObj, errorCode,
                                                                                                   const_cast<uint8_t *>(debugText));
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_NETWORK_COMMISSIONING_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_NETWORK_COMMISSIONING_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace NetworkCommissioning
  
  namespace OperationalCredentials {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_OP_CSR_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 6;
              chip::ByteSpan CSR;
              chip::ByteSpan CSRNonce;
              chip::ByteSpan VendorReserved1;
              chip::ByteSpan VendorReserved2;
              chip::ByteSpan VendorReserved3;
              chip::ByteSpan Signature;
              bool argExists[6];
  
              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 < 6)
                  {
                      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: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      CSR                  = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 1: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      CSRNonce             = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 2: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      VendorReserved1      = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 3: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      VendorReserved2      = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 4: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      VendorReserved3      = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 5: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      Signature            = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  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 && 6 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfOperationalCredentialsClusterOpCSRResponseCallback(apCommandObj, CSR, CSRNonce, VendorReserved1,
                                                                                         VendorReserved2, VendorReserved3, Signature);
              }
              break;
          }
          case ZCL_OP_CERT_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 3;
              uint8_t StatusCode;
              uint64_t FabricIndex;
              const uint8_t * DebugText;
              bool argExists[3];
  
              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 < 3)
                  {
                      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(StatusCode);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(FabricIndex);
                      break;
                  case 2:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(DebugText);
                      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 && 3 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfOperationalCredentialsClusterOpCertResponseCallback(apCommandObj, StatusCode, FabricIndex,
                                                                                          const_cast<uint8_t *>(DebugText));
              }
              break;
          }
          case ZCL_SET_FABRIC_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              chip::FabricId FabricId;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(FabricId);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfOperationalCredentialsClusterSetFabricResponseCallback(apCommandObj, FabricId);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId,
                           ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace OperationalCredentials
  
  namespace Scenes {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_ADD_SCENE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 3;
              uint8_t status;
              uint16_t groupId;
              uint8_t sceneId;
              bool argExists[3];
  
              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 < 3)
                  {
                      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(groupId);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(sceneId);
                      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 && 3 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfScenesClusterAddSceneResponseCallback(apCommandObj, status, groupId, sceneId);
              }
              break;
          }
          case ZCL_GET_SCENE_MEMBERSHIP_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 5;
              uint8_t status;
              uint8_t capacity;
              uint16_t groupId;
              uint8_t sceneCount;
              /* TYPE WARNING: array array defaults to */ uint8_t * sceneList;
              bool argExists[5];
  
              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 < 5)
                  {
                      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(capacity);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(groupId);
                      break;
                  case 3:
                      TLVUnpackError = aDataTlv.Get(sceneCount);
                      break;
                  case 4:
                      // Just for compatibility, we will add array type support in IM later.
                      TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(sceneList));
                      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 && 5 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfScenesClusterGetSceneMembershipResponseCallback(apCommandObj, status, capacity, groupId,
                                                                                      sceneCount, sceneList);
              }
              break;
          }
          case ZCL_REMOVE_ALL_SCENES_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t status;
              uint16_t groupId;
              bool argExists[2];
  
              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 < 2)
                  {
                      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(groupId);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfScenesClusterRemoveAllScenesResponseCallback(apCommandObj, status, groupId);
              }
              break;
          }
          case ZCL_REMOVE_SCENE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 3;
              uint8_t status;
              uint16_t groupId;
              uint8_t sceneId;
              bool argExists[3];
  
              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 < 3)
                  {
                      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(groupId);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(sceneId);
                      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 && 3 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfScenesClusterRemoveSceneResponseCallback(apCommandObj, status, groupId, sceneId);
              }
              break;
          }
          case ZCL_STORE_SCENE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 3;
              uint8_t status;
              uint16_t groupId;
              uint8_t sceneId;
              bool argExists[3];
  
              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 < 3)
                  {
                      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(groupId);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(sceneId);
                      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 && 3 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfScenesClusterStoreSceneResponseCallback(apCommandObj, status, groupId, sceneId);
              }
              break;
          }
          case ZCL_VIEW_SCENE_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 6;
              uint8_t status;
              uint16_t groupId;
              uint8_t sceneId;
              uint16_t transitionTime;
              const uint8_t * sceneName;
              /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets;
              bool argExists[6];
  
              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 < 6)
                  {
                      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(groupId);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(sceneId);
                      break;
                  case 3:
                      TLVUnpackError = aDataTlv.Get(transitionTime);
                      break;
                  case 4:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(sceneName);
                      break;
                  case 5:
                      // Just for compatibility, we will add array type support in IM later.
                      TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(extensionFieldSets));
                      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 && 6 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfScenesClusterViewSceneResponseCallback(apCommandObj, status, groupId, sceneId, transitionTime,
                                                                             const_cast<uint8_t *>(sceneName), extensionFieldSets);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_SCENES_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_SCENES_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_SCENES_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace Scenes
  
  namespace TvChannel {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_CHANGE_CHANNEL_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              /* TYPE WARNING: array array defaults to */ uint8_t * ChannelMatch;
              uint8_t ErrorType;
              bool argExists[2];
  
              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 < 2)
                  {
                      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:
                      // Just for compatibility, we will add array type support in IM later.
                      TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(ChannelMatch));
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(ErrorType);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfTvChannelClusterChangeChannelResponseCallback(apCommandObj, ChannelMatch, ErrorType);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_TV_CHANNEL_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_TV_CHANNEL_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_TV_CHANNEL_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace TvChannel
  
  namespace TargetNavigator {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_NAVIGATE_TARGET_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 2;
              uint8_t status;
              const uint8_t * data;
              bool argExists[2];
  
              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 < 2)
                  {
                      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:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(data);
                      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 && 2 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled =
                      emberAfTargetNavigatorClusterNavigateTargetResponseCallback(apCommandObj, status, const_cast<uint8_t *>(data));
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_TARGET_NAVIGATOR_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_TARGET_NAVIGATOR_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_TARGET_NAVIGATOR_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace TargetNavigator
  
  namespace TestCluster {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_TEST_SPECIFIC_RESPONSE_COMMAND_ID: {
              expectArgumentCount = 1;
              uint8_t returnValue;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(returnValue);
                      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 && 1 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfTestClusterClusterTestSpecificResponseCallback(apCommandObj, returnValue);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_TEST_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_TEST_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_TEST_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace TestCluster
  
  namespace Thermostat {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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 (aCommandId)
          {
          case ZCL_CURRENT_WEEKLY_SCHEDULE_COMMAND_ID: {
              expectArgumentCount = 4;
              uint8_t numberOfTransitionsForSequence;
              uint8_t dayOfWeekForSequence;
              uint8_t modeForSequence;
              /* TYPE WARNING: array array defaults to */ uint8_t * payload;
              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(numberOfTransitionsForSequence);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(dayOfWeekForSequence);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(modeForSequence);
                      break;
                  case 3:
                      // Just for compatibility, we will add array type support in IM later.
                      TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(payload));
                      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)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfThermostatClusterCurrentWeeklyScheduleCallback(apCommandObj, numberOfTransitionsForSequence,
                                                                                     dayOfWeekForSequence, modeForSequence, payload);
              }
              break;
          }
          case ZCL_RELAY_STATUS_LOG_COMMAND_ID: {
              expectArgumentCount = 6;
              uint16_t timeOfDay;
              uint16_t relayStatus;
              int16_t localTemperature;
              uint8_t humidityInPercentage;
              int16_t setpoint;
              uint16_t unreadEntries;
              bool argExists[6];
  
              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 < 6)
                  {
                      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(timeOfDay);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(relayStatus);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(localTemperature);
                      break;
                  case 3:
                      TLVUnpackError = aDataTlv.Get(humidityInPercentage);
                      break;
                  case 4:
                      TLVUnpackError = aDataTlv.Get(setpoint);
                      break;
                  case 5:
                      TLVUnpackError = aDataTlv.Get(unreadEntries);
                      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 && 6 == validArgumentCount)
              {
                  // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
                  wasHandled = emberAfThermostatClusterRelayStatusLogCallback(apCommandObj, timeOfDay, relayStatus, localTemperature,
                                                                              humidityInPercentage, setpoint, unreadEntries);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 ZCL_THERMOSTAT_CLUSTER_ID, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_THERMOSTAT_CLUSTER_ID);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             ZCL_THERMOSTAT_CLUSTER_ID, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogProgress(Zcl,
                          "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32
                          " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
      }
  }
  
  } // namespace Thermostat
  
  } // namespace clusters
  
  void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::EndpointId aEndPointId,
                                    chip::TLV::TLVReader & aReader, Command * apCommandObj)
  {
      ChipLogDetail(Zcl, "Received Cluster Command: Cluster=%" PRIx16 " Command=%" PRIx8 " Endpoint=%" PRIx8, aClusterId, aCommandId,
                    aEndPointId);
      Compatibility::SetupEmberAfObjects(apCommandObj, aClusterId, aCommandId, aEndPointId);
      TLV::TLVType dataTlvType;
      SuccessOrExit(aReader.EnterContainer(dataTlvType));
      switch (aClusterId)
      {
      case ZCL_ACCOUNT_LOGIN_CLUSTER_ID:
          clusters::AccountLogin::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_APPLICATION_LAUNCHER_CLUSTER_ID:
          clusters::ApplicationLauncher::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_CONTENT_LAUNCH_CLUSTER_ID:
          clusters::ContentLaunch::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_DOOR_LOCK_CLUSTER_ID:
          clusters::DoorLock::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_GENERAL_COMMISSIONING_CLUSTER_ID:
          clusters::GeneralCommissioning::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_GROUPS_CLUSTER_ID:
          clusters::Groups::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_IDENTIFY_CLUSTER_ID:
          clusters::Identify::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_KEYPAD_INPUT_CLUSTER_ID:
          clusters::KeypadInput::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_MEDIA_PLAYBACK_CLUSTER_ID:
          clusters::MediaPlayback::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_NETWORK_COMMISSIONING_CLUSTER_ID:
          clusters::NetworkCommissioning::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID:
          clusters::OperationalCredentials::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_SCENES_CLUSTER_ID:
          clusters::Scenes::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_TV_CHANNEL_CLUSTER_ID:
          clusters::TvChannel::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_TARGET_NAVIGATOR_CLUSTER_ID:
          clusters::TargetNavigator::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_TEST_CLUSTER_ID:
          clusters::TestCluster::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case ZCL_THERMOSTAT_CLUSTER_ID:
          clusters::Thermostat::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      default:
          // Unrecognized cluster ID, error status will apply.
          chip::app::CommandPathParams returnStatusParam = { aEndPointId,
                                                             0, // GroupId
                                                             aClusterId, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
  
          apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                      Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
          ChipLogError(Zcl, "Unknown cluster %" PRIx16, aClusterId);
          break;
      }
  exit:
      Compatibility::ResetEmberAfObjects();
      aReader.ExitContainer(dataTlvType);
  }
  
  } // namespace app
  } // namespace chip
  