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 "call-command-handler.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 DoorLock {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
  {
      {
          switch (aCommandId)
          {
          case ZCL_CLEAR_ALL_PINS_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterClearAllPinsResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_CLEAR_ALL_RFIDS_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterClearAllRfidsResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_CLEAR_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterClearHolidayScheduleResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_CLEAR_PIN_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterClearPinResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_CLEAR_RFID_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterClearRfidResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_CLEAR_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_CLEAR_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterClearYeardayScheduleResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_GET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t scheduleId;
              bool scheduleIdExists = false;
              uint8_t status;
              bool statusExists = false;
              uint32_t localStartTime;
              bool localStartTimeExists = false;
              uint32_t localEndTime;
              bool localEndTimeExists = false;
              uint8_t operatingModeDuringHoliday;
              bool operatingModeDuringHolidayExists = false;
              uint32_t validArgumentCount           = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (scheduleIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(scheduleId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          scheduleIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 2:
                      if (localStartTimeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(localStartTime);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          localStartTimeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 3:
                      if (localEndTimeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(localEndTime);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          localEndTimeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 4:
                      if (operatingModeDuringHolidayExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          operatingModeDuringHolidayExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterGetHolidayScheduleResponseCallback(apCommandObj, scheduleId, status, localStartTime,
                                                                           localEndTime, operatingModeDuringHoliday);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      5, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_GET_LOG_RECORD_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint16_t logEntryId;
              bool logEntryIdExists = false;
              uint32_t timestamp;
              bool timestampExists = false;
              uint8_t eventType;
              bool eventTypeExists = false;
              uint8_t source;
              bool sourceExists = false;
              uint8_t eventIdOrAlarmCode;
              bool eventIdOrAlarmCodeExists = false;
              uint16_t userId;
              bool userIdExists = false;
              const uint8_t * pin;
              bool pinExists              = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (logEntryIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(logEntryId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          logEntryIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (timestampExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(timestamp);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          timestampExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 2:
                      if (eventTypeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(eventType);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          eventTypeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 3:
                      if (sourceExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(source);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          sourceExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 4:
                      if (eventIdOrAlarmCodeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(eventIdOrAlarmCode);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          eventIdOrAlarmCodeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 5:
                      if (userIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(userId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          userIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 6:
                      if (pinExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(pin);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          pinExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterGetLogRecordResponseCallback(apCommandObj, logEntryId, timestamp, eventType, source,
                                                                     eventIdOrAlarmCode, userId, const_cast<uint8_t *>(pin));
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      7, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_GET_PIN_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint16_t userId;
              bool userIdExists = false;
              uint8_t userStatus;
              bool userStatusExists = false;
              uint8_t userType;
              bool userTypeExists = false;
              const uint8_t * pin;
              bool pinExists              = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (userIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(userId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          userIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (userStatusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(userStatus);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          userStatusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 2:
                      if (userTypeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(userType);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          userTypeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 3:
                      if (pinExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(pin);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          pinExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterGetPinResponseCallback(apCommandObj, userId, userStatus, userType,
                                                               const_cast<uint8_t *>(pin));
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      4, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_GET_RFID_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint16_t userId;
              bool userIdExists = false;
              uint8_t userStatus;
              bool userStatusExists = false;
              uint8_t userType;
              bool userTypeExists = false;
              const uint8_t * rfid;
              bool rfidExists             = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (userIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(userId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          userIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (userStatusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(userStatus);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          userStatusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 2:
                      if (userTypeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(userType);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          userTypeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 3:
                      if (rfidExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(rfid);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          rfidExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterGetRfidResponseCallback(apCommandObj, userId, userStatus, userType,
                                                                const_cast<uint8_t *>(rfid));
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      4, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_GET_USER_TYPE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint16_t userId;
              bool userIdExists = false;
              uint8_t userType;
              bool userTypeExists         = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (userIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(userId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          userIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (userTypeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(userType);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          userTypeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterGetUserTypeResponseCallback(apCommandObj, userId, userType);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      2, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_GET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t scheduleId;
              bool scheduleIdExists = false;
              uint16_t userId;
              bool userIdExists = false;
              uint8_t status;
              bool statusExists = false;
              uint8_t daysMask;
              bool daysMaskExists = false;
              uint8_t startHour;
              bool startHourExists = false;
              uint8_t startMinute;
              bool startMinuteExists = false;
              uint8_t endHour;
              bool endHourExists = false;
              uint8_t endMinute;
              bool endMinuteExists        = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (scheduleIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(scheduleId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          scheduleIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (userIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(userId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          userIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 2:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 3:
                      if (daysMaskExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(daysMask);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          daysMaskExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 4:
                      if (startHourExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(startHour);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          startHourExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 5:
                      if (startMinuteExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(startMinute);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          startMinuteExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 6:
                      if (endHourExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(endHour);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          endHourExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 7:
                      if (endMinuteExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(endMinute);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          endMinuteExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterGetWeekdayScheduleResponseCallback(apCommandObj, scheduleId, userId, status, daysMask,
                                                                           startHour, startMinute, endHour, endMinute);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      8, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_GET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t scheduleId;
              bool scheduleIdExists = false;
              uint16_t userId;
              bool userIdExists = false;
              uint8_t status;
              bool statusExists = false;
              uint32_t localStartTime;
              bool localStartTimeExists = false;
              uint32_t localEndTime;
              bool localEndTimeExists     = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (scheduleIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(scheduleId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          scheduleIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (userIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(userId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          userIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 2:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 3:
                      if (localStartTimeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(localStartTime);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          localStartTimeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 4:
                      if (localEndTimeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(localEndTime);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          localEndTimeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterGetYeardayScheduleResponseCallback(apCommandObj, scheduleId, userId, status, localStartTime,
                                                                           localEndTime);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      5, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_LOCK_DOOR_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterLockDoorResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_SET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterSetHolidayScheduleResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_SET_PIN_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterSetPinResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_SET_RFID_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterSetRfidResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_SET_USER_TYPE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterSetUserTypeResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_SET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_SET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterSetYeardayScheduleResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_UNLOCK_DOOR_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterUnlockDoorResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_UNLOCK_WITH_TIMEOUT_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists           = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(apCommandObj, status);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DOOR_LOCK_CLUSTER_ID);
              break;
          }
          }
      }
  }
  
  } // namespace DoorLock
  
  namespace GeneralCommissioning {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
  {
      {
          switch (aCommandId)
          {
          case ZCL_ARM_FAIL_SAFE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t errorCode;
              bool errorCodeExists = false;
              const uint8_t * debugText;
              bool debugTextExists        = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (errorCodeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(errorCode);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          errorCodeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (debugTextExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          debugTextExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(apCommandObj, errorCode,
                                                                                const_cast<uint8_t *>(debugText));
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      2, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_COMMISSIONING_COMPLETE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t errorCode;
              bool errorCodeExists = false;
              const uint8_t * debugText;
              bool debugTextExists        = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (errorCodeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(errorCode);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          errorCodeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (debugTextExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          debugTextExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback(apCommandObj, errorCode,
                                                                                          const_cast<uint8_t *>(debugText));
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      2, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_SET_REGULATORY_CONFIG_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t errorCode;
              bool errorCodeExists = false;
              const uint8_t * debugText;
              bool debugTextExists        = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (errorCodeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(errorCode);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          errorCodeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (debugTextExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          debugTextExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback(apCommandObj, errorCode,
                                                                                        const_cast<uint8_t *>(debugText));
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      2, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID);
              break;
          }
          }
      }
  }
  
  } // namespace GeneralCommissioning
  
  namespace Groups {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
  {
      {
          switch (aCommandId)
          {
          case ZCL_ADD_GROUP_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists = false;
              uint16_t groupId;
              bool groupIdExists          = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (groupIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(groupId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          groupIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfGroupsClusterAddGroupResponseCallback(apCommandObj, status, groupId);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      2, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_GET_GROUP_MEMBERSHIP_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t capacity;
              bool capacityExists = false;
              uint8_t groupCount;
              bool groupCountExists = false;
              /* TYPE WARNING: array array defaults to */ uint8_t * groupList;
              bool groupListExists        = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (capacityExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(capacity);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          capacityExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (groupCountExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(groupCount);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          groupCountExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 2:
                      if (groupListExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // Just for compatibility, we will add array type support in IM later.
                      TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(groupList));
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          groupListExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfGroupsClusterGetGroupMembershipResponseCallback(apCommandObj, capacity, groupCount, groupList);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      3, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_REMOVE_GROUP_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists = false;
              uint16_t groupId;
              bool groupIdExists          = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (groupIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(groupId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          groupIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfGroupsClusterRemoveGroupResponseCallback(apCommandObj, status, groupId);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      2, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_VIEW_GROUP_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists = false;
              uint16_t groupId;
              bool groupIdExists = false;
              const uint8_t * groupName;
              bool groupNameExists        = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (groupIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(groupId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          groupIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 2:
                      if (groupNameExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(groupName);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          groupNameExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfGroupsClusterViewGroupResponseCallback(apCommandObj, status, groupId, const_cast<uint8_t *>(groupName));
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      3, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GROUPS_CLUSTER_ID);
              break;
          }
          }
      }
  }
  
  } // namespace Groups
  
  namespace Identify {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
  {
      {
          switch (aCommandId)
          {
          case ZCL_IDENTIFY_QUERY_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint16_t timeout;
              bool timeoutExists          = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (timeoutExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(timeout);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          timeoutExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfIdentifyClusterIdentifyQueryResponseCallback(apCommandObj, timeout);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IDENTIFY_CLUSTER_ID);
              break;
          }
          }
      }
  }
  
  } // namespace Identify
  
  namespace NetworkCommissioning {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
  {
      {
          switch (aCommandId)
          {
          case ZCL_ADD_THREAD_NETWORK_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t errorCode;
              bool errorCodeExists = false;
              const uint8_t * debugText;
              bool debugTextExists        = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (errorCodeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(errorCode);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          errorCodeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (debugTextExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          debugTextExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(apCommandObj, errorCode,
                                                                                     const_cast<uint8_t *>(debugText));
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      2, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_ADD_WI_FI_NETWORK_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t errorCode;
              bool errorCodeExists = false;
              const uint8_t * debugText;
              bool debugTextExists        = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (errorCodeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(errorCode);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          errorCodeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (debugTextExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          debugTextExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(apCommandObj, errorCode,
                                                                                   const_cast<uint8_t *>(debugText));
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      2, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_DISABLE_NETWORK_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t errorCode;
              bool errorCodeExists = false;
              const uint8_t * debugText;
              bool debugTextExists        = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (errorCodeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(errorCode);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          errorCodeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (debugTextExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          debugTextExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(apCommandObj, errorCode,
                                                                                   const_cast<uint8_t *>(debugText));
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      2, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_ENABLE_NETWORK_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t errorCode;
              bool errorCodeExists = false;
              const uint8_t * debugText;
              bool debugTextExists        = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (errorCodeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(errorCode);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          errorCodeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (debugTextExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          debugTextExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(apCommandObj, errorCode,
                                                                                  const_cast<uint8_t *>(debugText));
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      2, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_REMOVE_NETWORK_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t errorCode;
              bool errorCodeExists = false;
              const uint8_t * debugText;
              bool debugTextExists        = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (errorCodeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(errorCode);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          errorCodeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (debugTextExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          debugTextExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(apCommandObj, errorCode,
                                                                                  const_cast<uint8_t *>(debugText));
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      2, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_SCAN_NETWORKS_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t errorCode;
              bool errorCodeExists = false;
              const uint8_t * debugText;
              bool debugTextExists = false;
              /* TYPE WARNING: array array defaults to */ uint8_t * wifiScanResults;
              bool wifiScanResultsExists = false;
              /* TYPE WARNING: array array defaults to */ uint8_t * threadScanResults;
              bool threadScanResultsExists = false;
              uint32_t validArgumentCount  = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (errorCodeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(errorCode);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          errorCodeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (debugTextExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          debugTextExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 2:
                      if (wifiScanResultsExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // Just for compatibility, we will add array type support in IM later.
                      TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(wifiScanResults));
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          wifiScanResultsExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 3:
                      if (threadScanResultsExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // Just for compatibility, we will add array type support in IM later.
                      TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(threadScanResults));
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          threadScanResultsExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfNetworkCommissioningClusterScanNetworksResponseCallback(
                      apCommandObj, errorCode, const_cast<uint8_t *>(debugText), wifiScanResults, threadScanResults);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      4, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_UPDATE_THREAD_NETWORK_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t errorCode;
              bool errorCodeExists = false;
              const uint8_t * debugText;
              bool debugTextExists        = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (errorCodeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(errorCode);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          errorCodeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (debugTextExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          debugTextExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback(apCommandObj, errorCode,
                                                                                        const_cast<uint8_t *>(debugText));
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      2, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_UPDATE_WI_FI_NETWORK_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t errorCode;
              bool errorCodeExists = false;
              const uint8_t * debugText;
              bool debugTextExists        = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (errorCodeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(errorCode);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          errorCodeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (debugTextExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(debugText);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          debugTextExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback(apCommandObj, errorCode,
                                                                                      const_cast<uint8_t *>(debugText));
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      2, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID);
              break;
          }
          }
      }
  }
  
  } // namespace NetworkCommissioning
  
  namespace OperationalCredentials {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
  {
      {
          switch (aCommandId)
          {
          case ZCL_GET_FABRIC_ID_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              chip::FabricId FabricId;
              bool FabricIdExists         = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (FabricIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(FabricId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          FabricIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfOperationalCredentialsClusterGetFabricIdResponseCallback(apCommandObj, FabricId);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      1, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId,
                           ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID);
              break;
          }
          }
      }
  }
  
  } // namespace OperationalCredentials
  
  namespace Scenes {
  
  void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
  {
      {
          switch (aCommandId)
          {
          case ZCL_ADD_SCENE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists = false;
              uint16_t groupId;
              bool groupIdExists = false;
              uint8_t sceneId;
              bool sceneIdExists          = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (groupIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(groupId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          groupIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 2:
                      if (sceneIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(sceneId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          sceneIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfScenesClusterAddSceneResponseCallback(apCommandObj, status, groupId, sceneId);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      3, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_GET_SCENE_MEMBERSHIP_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists = false;
              uint8_t capacity;
              bool capacityExists = false;
              uint16_t groupId;
              bool groupIdExists = false;
              uint8_t sceneCount;
              bool sceneCountExists = false;
              /* TYPE WARNING: array array defaults to */ uint8_t * sceneList;
              bool sceneListExists        = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (capacityExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(capacity);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          capacityExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 2:
                      if (groupIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(groupId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          groupIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 3:
                      if (sceneCountExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(sceneCount);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          sceneCountExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 4:
                      if (sceneListExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // Just for compatibility, we will add array type support in IM later.
                      TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(sceneList));
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          sceneListExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfScenesClusterGetSceneMembershipResponseCallback(apCommandObj, status, capacity, groupId, sceneCount,
                                                                         sceneList);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      5, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_REMOVE_ALL_SCENES_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists = false;
              uint16_t groupId;
              bool groupIdExists          = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (groupIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(groupId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          groupIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfScenesClusterRemoveAllScenesResponseCallback(apCommandObj, status, groupId);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      2, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_REMOVE_SCENE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists = false;
              uint16_t groupId;
              bool groupIdExists = false;
              uint8_t sceneId;
              bool sceneIdExists          = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (groupIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(groupId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          groupIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 2:
                      if (sceneIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(sceneId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          sceneIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfScenesClusterRemoveSceneResponseCallback(apCommandObj, status, groupId, sceneId);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      3, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_STORE_SCENE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists = false;
              uint16_t groupId;
              bool groupIdExists = false;
              uint8_t sceneId;
              bool sceneIdExists          = false;
              uint32_t validArgumentCount = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (groupIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(groupId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          groupIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 2:
                      if (sceneIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(sceneId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          sceneIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfScenesClusterStoreSceneResponseCallback(apCommandObj, status, groupId, sceneId);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      3, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          case ZCL_VIEW_SCENE_RESPONSE_COMMAND_ID: {
              // 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.
              CHIP_ERROR TLVError       = CHIP_NO_ERROR;
              CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
              uint8_t status;
              bool statusExists = false;
              uint16_t groupId;
              bool groupIdExists = false;
              uint8_t sceneId;
              bool sceneIdExists = false;
              uint16_t transitionTime;
              bool transitionTimeExists = false;
              const uint8_t * sceneName;
              bool sceneNameExists = false;
              /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets;
              bool extensionFieldSetsExists = false;
              uint32_t validArgumentCount   = 0;
  
              while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
              {
                  switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
                  {
                  case 0:
                      if (statusExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(status);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          statusExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 1:
                      if (groupIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(groupId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          groupIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 2:
                      if (sceneIdExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(sceneId);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          sceneIdExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 3:
                      if (transitionTimeExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      TLVUnpackError = aDataTlv.Get(transitionTime);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          transitionTimeExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 4:
                      if (sceneNameExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(sceneName);
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          sceneNameExists = true;
                          validArgumentCount++;
                      }
                      break;
                  case 5:
                      if (extensionFieldSetsExists)
                      {
                          ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
                          TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
                          break;
                      }
                      // Just for compatibility, we will add array type support in IM later.
                      TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(extensionFieldSets));
                      if (CHIP_NO_ERROR == TLVUnpackError)
                      {
                          extensionFieldSetsExists = true;
                          validArgumentCount++;
                      }
                      break;
                  default:
                      // Unsupported tag, ignore it.
                      ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
                      break;
                  }
                  if (TLVUnpackError != CHIP_NO_ERROR)
                  {
                      ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
                                      TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
              }
              else
              {
                  ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
              }
  
              // TODO(#5590) We should encode a response of status code for invalid TLV.
              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.
                  emberAfScenesClusterViewSceneResponseCallback(apCommandObj, status, groupId, sceneId, transitionTime,
                                                                const_cast<uint8_t *>(sceneName), extensionFieldSets);
              }
              else
              {
                  apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
                                              Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
                  ChipLogProgress(
                      Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
                      6, validArgumentCount, TLVError, TLVUnpackError);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
              ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_SCENES_CLUSTER_ID);
              break;
          }
          }
      }
  }
  
  } // namespace Scenes
  
  } // 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)
      {
      default:
          // Unrecognized cluster ID, error status will apply.
          apCommandObj->AddStatusCode(nullptr, 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
  