Просмотр исходного кода

Fix CurrentPositionLiftPercent100ths attribute read value mismatch (#22497)

* Fix CurrentPositionLiftPercent100ths attribute read value mismatch

* Run codegen

* Adjust the delay to improve the CI stability
Yufeng Wang 3 лет назад
Родитель
Сommit
f8a696abdf

+ 1 - 0
examples/all-clusters-app/linux/BUILD.gn

@@ -26,6 +26,7 @@ source_set("chip-all-clusters-common") {
     "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp",
     "AllClustersCommandDelegate.cpp",
     "AppOptions.cpp",
+    "WindowCoveringManager.cpp",
     "include/tv-callbacks.cpp",
     "include/tv-callbacks.h",
     "main-common.cpp",

+ 138 - 0
examples/all-clusters-app/linux/WindowCoveringManager.cpp

@@ -0,0 +1,138 @@
+/**
+ *
+ *    Copyright (c) 2022 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.
+ */
+
+#include "WindowCoveringManager.h"
+#include <app-common/zap-generated/attributes/Accessors.h>
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+#include <system/SystemClock.h>
+
+using namespace chip;
+using namespace chip::app;
+using namespace chip::app::Clusters::WindowCovering;
+using namespace chip::System::Clock::Literals;
+
+namespace {
+
+constexpr const System::Clock::Milliseconds32 kIncrementMovementTimeout = 700_ms32;
+constexpr const uint16_t kDefaultMovementStep                           = 2000;
+
+} // namespace
+
+void WindowCoveringManager::Init(EndpointId endpoint)
+{
+    mState = OperationalState::Stall;
+    mCurrentPosition.SetNonNull(static_cast<uint16_t>(0));
+    mTargetPosition.SetNonNull(static_cast<uint16_t>(0));
+    SetEndpoint(endpoint);
+}
+
+void WindowCoveringManager::HandleMovementTimer(System::Layer * layer, void * aAppState)
+{
+    WindowCoveringManager * manager = reinterpret_cast<WindowCoveringManager *>(aAppState);
+
+    VerifyOrReturn(manager->mState != OperationalState::Stall);
+
+    uint16_t currentPosition = manager->mCurrentPosition.Value();
+    uint16_t targetPosition  = manager->mTargetPosition.Value();
+
+    ChipLogProgress(NotSpecified, "HandleMovementTimer:currentPosition:%u, targetPosition:%u", currentPosition, targetPosition);
+
+    if (OperationalState::MovingUpOrOpen == manager->mState)
+    {
+        if (currentPosition > targetPosition)
+        {
+            uint16_t tempPosition =
+                currentPosition > kDefaultMovementStep ? static_cast<uint16_t>(currentPosition - kDefaultMovementStep) : 0;
+            currentPosition = tempPosition > targetPosition ? tempPosition : targetPosition;
+
+            manager->mCurrentPosition.SetNonNull(currentPosition);
+        }
+        else
+        {
+            ChipLogProgress(NotSpecified, "Reached the target position");
+            return;
+        }
+    }
+    else
+    {
+        if (currentPosition < targetPosition)
+        {
+            uint16_t tempPosition = static_cast<uint16_t>(currentPosition + kDefaultMovementStep);
+            currentPosition       = tempPosition < targetPosition ? tempPosition : targetPosition;
+            manager->mCurrentPosition.SetNonNull(currentPosition);
+        }
+        else
+        {
+            ChipLogProgress(NotSpecified, "Reached the target position");
+            return;
+        }
+    }
+
+    if (HasFeature(manager->mEndpoint, Feature::kPositionAwareLift))
+    {
+        LiftPositionSet(manager->mEndpoint, manager->mCurrentPosition);
+    }
+
+    if (HasFeature(manager->mEndpoint, Feature::kPositionAwareTilt))
+    {
+        TiltPositionSet(manager->mEndpoint, manager->mCurrentPosition);
+    }
+
+    if (manager->mCurrentPosition != manager->mTargetPosition)
+    {
+        LogErrorOnFailure(DeviceLayer::SystemLayer().StartTimer(kIncrementMovementTimeout, HandleMovementTimer, aAppState));
+    }
+}
+
+CHIP_ERROR WindowCoveringManager::HandleMovement(WindowCoveringType type)
+{
+    mState = OperationalStateGet(mEndpoint, OperationalStatus::kGlobal);
+
+    if (OperationalState::Stall == mState)
+    {
+        ChipLogProgress(NotSpecified, "Covering is currently not moving");
+        return CHIP_NO_ERROR;
+    }
+
+    // Cancel ongoing window covering movement timer if any.
+    DeviceLayer::SystemLayer().CancelTimer(HandleMovementTimer, this);
+
+    // At least one of the Lift and Tilt features SHALL be supported.
+    if (type == WindowCoveringType::Lift)
+    {
+        Attributes::CurrentPositionLiftPercent100ths::Get(mEndpoint, mCurrentPosition);
+        Attributes::TargetPositionLiftPercent100ths::Get(mEndpoint, mTargetPosition);
+    }
+    else
+    {
+        Attributes::CurrentPositionTiltPercent100ths::Get(mEndpoint, mCurrentPosition);
+        Attributes::TargetPositionTiltPercent100ths::Get(mEndpoint, mTargetPosition);
+    }
+
+    VerifyOrReturnError(!mCurrentPosition.IsNull(), CHIP_ERROR_INCORRECT_STATE);
+    VerifyOrReturnError(!mTargetPosition.IsNull(), CHIP_ERROR_INCORRECT_STATE);
+    VerifyOrReturnError(mCurrentPosition != mTargetPosition, CHIP_ERROR_INCORRECT_STATE);
+
+    return DeviceLayer::SystemLayer().StartTimer(kIncrementMovementTimeout, HandleMovementTimer, this);
+}
+
+CHIP_ERROR WindowCoveringManager::HandleStopMotion()
+{
+
+    DeviceLayer::SystemLayer().CancelTimer(HandleMovementTimer, this);
+    return CHIP_NO_ERROR;
+}

+ 49 - 0
examples/all-clusters-app/linux/WindowCoveringManager.h

@@ -0,0 +1,49 @@
+/**
+ *
+ *    Copyright (c) 2022 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.
+ */
+
+#pragma once
+
+#include <app/clusters/window-covering-server/window-covering-server.h>
+
+namespace chip {
+namespace app {
+namespace Clusters {
+namespace WindowCovering {
+
+class WindowCoveringManager : public Delegate
+{
+public:
+    void Init(chip::EndpointId endpoint);
+    CHIP_ERROR HandleMovement(WindowCoveringType type) override;
+    CHIP_ERROR HandleStopMotion() override;
+
+private:
+    OperationalState mState;
+    NPercent100ths mCurrentPosition;
+    NPercent100ths mTargetPosition;
+
+    /**
+     * @brief
+     *  The callback function to be called when "movement timer" expires.
+     */
+    static void HandleMovementTimer(chip::System::Layer * layer, void * aAppState);
+};
+
+} // namespace WindowCovering
+} // namespace Clusters
+} // namespace app
+} // namespace chip

+ 9 - 0
examples/all-clusters-app/linux/main-common.cpp

@@ -18,6 +18,7 @@
 
 #include "main-common.h"
 #include "AllClustersCommandDelegate.h"
+#include "WindowCoveringManager.h"
 #include "include/tv-callbacks.h"
 #include <app-common/zap-generated/att-storage.h>
 #include <app-common/zap-generated/attribute-type.h>
@@ -59,6 +60,7 @@ constexpr const char kChipEventFifoPathPrefix[] = "/tmp/chip_all_clusters_fifo_"
 LowPowerManager sLowPowerManager;
 NamedPipeCommands sChipNamedPipeCommands;
 AllClustersCommandDelegate sAllClustersCommandDelegate;
+chip::app::Clusters::WindowCovering::WindowCoveringManager sWindowCoveringManager;
 
 // TODO(#20664) REPL test will fail if signal SIGINT is not caught, temporarily keep following logic.
 
@@ -264,3 +266,10 @@ void emberAfLowPowerClusterInitCallback(EndpointId endpoint)
     ChipLogProgress(NotSpecified, "TV Linux App: LowPower::SetDefaultDelegate");
     chip::app::Clusters::LowPower::SetDefaultDelegate(endpoint, &sLowPowerManager);
 }
+
+void emberAfWindowCoveringClusterInitCallback(chip::EndpointId endpoint)
+{
+    sWindowCoveringManager.Init(endpoint);
+    chip::app::Clusters::WindowCovering::SetDefaultDelegate(endpoint, &sWindowCoveringManager);
+    chip::app::Clusters::WindowCovering::ConfigStatusUpdateFeatures(endpoint);
+}

+ 78 - 0
src/app/clusters/window-covering-server/window-covering-delegate.h

@@ -0,0 +1,78 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    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.
+ */
+
+#pragma once
+
+#include <app-common/zap-generated/cluster-objects.h>
+#include <app/AttributeAccessInterface.h>
+#include <app/CommandResponseHelper.h>
+#include <app/util/af.h>
+
+namespace chip {
+namespace app {
+namespace Clusters {
+namespace WindowCovering {
+
+// Window Covering Type
+enum class WindowCoveringType : uint8_t
+{
+    Lift     = 0x00, // window coverings that lift up and down or slide left to right
+    Tilt     = 0x01, // window coverings with vertical or horizontal strips
+    Reserved = 0x02, // dont use
+};
+
+/** @brief
+ *    Defines methods for implementing application-specific logic for the WindowCovering Cluster.
+ */
+class Delegate
+{
+public:
+    /**
+     * @brief
+     *   This method adjusts window covering position so the physical lift/slide and tilt is at the target
+     *   open/up position set before calling this method. This will happen as fast as possible.
+     *
+     *   @param[in]  type            window covering type.
+     *
+     *   @return CHIP_NO_ERROR On success.
+     *   @return Other Value indicating it failed to adjust window covering position.
+     */
+    virtual CHIP_ERROR HandleMovement(WindowCoveringType type) = 0;
+
+    /**
+     * @brief
+     *   This method stops any adjusting to the physical tilt and lift/slide that is currently occurring.
+     *
+     *   @return CHIP_NO_ERROR On success.
+     *   @return Other Value indicating it failed to stop any adjusting to the physical tilt and lift/slide that is currently
+     * occurring..
+     */
+    virtual CHIP_ERROR HandleStopMotion() = 0;
+
+    virtual ~Delegate() = default;
+
+    void SetEndpoint(chip::EndpointId endpoint) { mEndpoint = endpoint; }
+
+protected:
+    EndpointId mEndpoint = 0;
+};
+
+} // namespace WindowCovering
+} // namespace Clusters
+} // namespace app
+} // namespace chip

+ 128 - 98
src/app/clusters/window-covering-server/window-covering-server.cpp

@@ -37,6 +37,7 @@
 #endif // EMBER_AF_PLUGIN_SCENES
 
 using namespace chip;
+using namespace chip::app::Clusters;
 using namespace chip::app::Clusters::WindowCovering;
 
 #define CHECK_BOUNDS_INVALID(MIN, VAL, MAX) ((VAL < MIN) || (VAL > MAX))
@@ -44,13 +45,27 @@ using namespace chip::app::Clusters::WindowCovering;
 
 #define FAKE_MOTION_DELAY_MS 5000
 
+namespace {
+
+constexpr size_t kWindowCoveringDelegateTableSize =
+    EMBER_AF_WINDOW_COVERING_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT;
+
+Delegate * gDelegateTable[kWindowCoveringDelegateTableSize] = { nullptr };
+
+Delegate * GetDelegate(EndpointId endpoint)
+{
+    uint16_t ep = emberAfFindClusterServerEndpointIndex(endpoint, WindowCovering::Id);
+    return ((ep == kInvalidEndpointId || ep >= EMBER_AF_WINDOW_COVERING_CLUSTER_SERVER_ENDPOINT_COUNT) ? nullptr
+                                                                                                       : gDelegateTable[ep]);
+}
+
 /*
  * ConvertValue: Converts values from one range to another
  * Range In  -> from  inputLowValue to   inputHighValue
  * Range Out -> from outputLowValue to outputtHighValue
  */
-static uint16_t ConvertValue(uint16_t inputLowValue, uint16_t inputHighValue, uint16_t outputLowValue, uint16_t outputHighValue,
-                             uint16_t value)
+uint16_t ConvertValue(uint16_t inputLowValue, uint16_t inputHighValue, uint16_t outputLowValue, uint16_t outputHighValue,
+                      uint16_t value)
 {
     uint16_t inputMin = inputLowValue, inputMax = inputHighValue, inputRange = UINT16_MAX;
     uint16_t outputMin = outputLowValue, outputMax = outputHighValue, outputRange = UINT16_MAX;
@@ -88,10 +103,11 @@ static uint16_t ConvertValue(uint16_t inputLowValue, uint16_t inputHighValue, ui
     return outputMax;
 }
 
-static Percent100ths ValueToPercent100ths(AbsoluteLimits limits, uint16_t absolute)
+Percent100ths ValueToPercent100ths(AbsoluteLimits limits, uint16_t absolute)
 {
     return ConvertValue(limits.open, limits.closed, WC_PERCENT100THS_MIN_OPEN, WC_PERCENT100THS_MAX_CLOSED, absolute);
 }
+} // namespace
 
 namespace chip {
 namespace app {
@@ -199,6 +215,7 @@ void OperationalStatusSet(chip::EndpointId endpoint, chip::BitMask<OperationalSt
     // Filter changes
     if (newStatus != prevStatus)
     {
+        OperationalStatusPrint(newStatus);
         Attributes::OperationalStatus::Set(endpoint, newStatus);
     }
 }
@@ -490,72 +507,6 @@ Percent100ths ComputePercent100thsStep(OperationalState direction, Percent100ths
     return percent100ths;
 }
 
-void emberAfPluginWindowCoveringFinalizeFakeMotionEventHandler(EndpointId endpoint)
-{
-    NPercent100ths position;
-
-    OperationalState opLift = OperationalStateGet(endpoint, OperationalStatus::kLift);
-    OperationalState opTilt = OperationalStateGet(endpoint, OperationalStatus::kTilt);
-
-    emberAfWindowCoveringClusterPrint("WC DELAYED CALLBACK 100ms w/ OpLift=0x%02X OpTilt=0x%02X", (unsigned char) opLift,
-                                      (unsigned char) opTilt);
-
-    /* Update position to simulate movement to pass the CI */
-    if (OperationalState::Stall != opLift)
-    {
-        Attributes::TargetPositionLiftPercent100ths::Get(endpoint, position);
-        if (!position.IsNull())
-        {
-            LiftPositionSet(endpoint, position);
-        }
-    }
-
-    /* Update position to simulate movement to pass the CI */
-    if (OperationalState::Stall != opTilt)
-    {
-        Attributes::TargetPositionTiltPercent100ths::Get(endpoint, position);
-        if (!position.IsNull())
-        {
-            TiltPositionSet(endpoint, position);
-        }
-    }
-}
-
-/**
- * @brief Get event control object for an endpoint
- *
- * @param[in] endpoint
- * @return EmberEventControl*
- */
-EmberEventControl * GetEventControl(EndpointId endpoint)
-{
-    static EmberEventControl eventControls[EMBER_AF_WINDOW_COVERING_CLUSTER_SERVER_ENDPOINT_COUNT];
-    uint16_t index            = emberAfFindClusterServerEndpointIndex(endpoint, WindowCovering::Id);
-    EmberEventControl * event = nullptr;
-
-    if (index < ArraySize(eventControls))
-    {
-        event = &eventControls[index];
-    }
-    return event;
-}
-
-/**
- * @brief Configure Fake Motion event control object for an endpoint
- *
- * @param[in] endpoint
- * @return EmberEventControl*
- */
-EmberEventControl * ConfigureFakeMotionEventControl(EndpointId endpoint)
-{
-    EmberEventControl * controller = GetEventControl(endpoint);
-
-    controller->endpoint = endpoint;
-    controller->callback = &emberAfPluginWindowCoveringFinalizeFakeMotionEventHandler;
-
-    return controller;
-}
-
 void PostAttributeChange(chip::EndpointId endpoint, chip::AttributeId attributeId)
 {
     // all-cluster-app: simulation for the CI testing
@@ -571,27 +522,23 @@ void PostAttributeChange(chip::EndpointId endpoint, chip::AttributeId attributeI
 
     switch (attributeId)
     {
-    /* RO OperationalStatus */
-    case Attributes::OperationalStatus::Id:
-        if (OperationalState::Stall != OperationalStateGet(endpoint, OperationalStatus::kGlobal))
-        {
-            // Finish the fake motion attribute update:
-            emberEventControlSetDelayMS(ConfigureFakeMotionEventControl(endpoint), FAKE_MOTION_DELAY_MS);
-        }
-        break;
     /* ============= Positions for Position Aware ============= */
     case Attributes::CurrentPositionLiftPercent100ths::Id:
-        if (OperationalState::Stall != opLift)
+        Attributes::TargetPositionLiftPercent100ths::Get(endpoint, target);
+        Attributes::CurrentPositionLiftPercent100ths::Get(endpoint, current);
+        if ((OperationalState::Stall != opLift) && (current == target))
         {
-            opLift = OperationalState::Stall;
             emberAfWindowCoveringClusterPrint("Lift stop");
+            OperationalStateSet(endpoint, OperationalStatus::kLift, OperationalState::Stall);
         }
         break;
     case Attributes::CurrentPositionTiltPercent100ths::Id:
-        if (OperationalState::Stall != opTilt)
+        Attributes::TargetPositionTiltPercent100ths::Get(endpoint, target);
+        Attributes::CurrentPositionTiltPercent100ths::Get(endpoint, current);
+        if ((OperationalState::Stall != opTilt) && (current == target))
         {
-            opTilt = OperationalState::Stall;
             emberAfWindowCoveringClusterPrint("Tilt stop");
+            OperationalStateSet(endpoint, OperationalStatus::kTilt, OperationalState::Stall);
         }
         break;
     /* For a device supporting Position Awareness : Changing the Target triggers motions on the real or simulated device */
@@ -599,12 +546,14 @@ void PostAttributeChange(chip::EndpointId endpoint, chip::AttributeId attributeI
         Attributes::TargetPositionLiftPercent100ths::Get(endpoint, target);
         Attributes::CurrentPositionLiftPercent100ths::Get(endpoint, current);
         opLift = ComputeOperationalState(target, current);
+        OperationalStateSet(endpoint, OperationalStatus::kLift, opLift);
         break;
     /* For a device supporting Position Awareness : Changing the Target triggers motions on the real or simulated device */
     case Attributes::TargetPositionTiltPercent100ths::Id:
         Attributes::TargetPositionTiltPercent100ths::Get(endpoint, target);
         Attributes::CurrentPositionTiltPercent100ths::Get(endpoint, current);
         opTilt = ComputeOperationalState(target, current);
+        OperationalStateSet(endpoint, OperationalStatus::kTilt, opTilt);
         break;
     /* Mode change is either internal from the application or external from a write request */
     case Attributes::Mode::Id:
@@ -619,10 +568,6 @@ void PostAttributeChange(chip::EndpointId endpoint, chip::AttributeId attributeI
     default:
         break;
     }
-
-    /* This decides and triggers fake motion for the selected endpoint */
-    OperationalStateSet(endpoint, OperationalStatus::kLift, opLift);
-    OperationalStateSet(endpoint, OperationalStatus::kTilt, opTilt);
 }
 
 EmberAfStatus GetMotionLockStatus(chip::EndpointId endpoint)
@@ -649,6 +594,21 @@ EmberAfStatus GetMotionLockStatus(chip::EndpointId endpoint)
     return EMBER_ZCL_STATUS_SUCCESS;
 }
 
+void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate)
+{
+    uint16_t ep = emberAfFindClusterServerEndpointIndex(endpoint, Channel::Id);
+
+    // if endpoint is found and is not a dynamic endpoint
+    if (ep != 0xFFFF && ep < EMBER_AF_WINDOW_COVERING_CLUSTER_SERVER_ENDPOINT_COUNT)
+    {
+        gDelegateTable[ep] = delegate;
+    }
+    else
+    {
+        emberAfWindowCoveringClusterPrint("Failed to set WindowCovering delegate for endpoint:%u", endpoint);
+    }
+}
+
 } // namespace WindowCovering
 } // namespace Clusters
 } // namespace app
@@ -658,19 +618,6 @@ EmberAfStatus GetMotionLockStatus(chip::EndpointId endpoint)
 // Callbacks
 //------------------------------------------------------------------------------
 
-/** @brief Window Covering Cluster Init
- *
- * Cluster Init
- *
- * @param endpoint    Endpoint that is being initialized
- */
-void emberAfWindowCoveringClusterInitCallback(chip::EndpointId endpoint)
-{
-    emberAfWindowCoveringClusterPrint("Window Covering Cluster init");
-
-    ConfigStatusUpdateFeatures(endpoint);
-}
-
 /**
  * @brief  Cluster UpOrOpen Command callback (from client)
  */
@@ -697,7 +644,26 @@ bool emberAfWindowCoveringClusterUpOrOpenCallback(app::CommandHandler * commandO
     {
         Attributes::TargetPositionTiltPercent100ths::Set(endpoint, WC_PERCENT100THS_MIN_OPEN);
     }
+
+    Delegate * delegate = GetDelegate(endpoint);
+    if (delegate)
+    {
+        if (HasFeature(endpoint, Feature::kPositionAwareLift))
+        {
+            LogErrorOnFailure(delegate->HandleMovement(WindowCoveringType::Lift));
+        }
+        else if (HasFeature(endpoint, Feature::kPositionAwareTilt))
+        {
+            LogErrorOnFailure(delegate->HandleMovement(WindowCoveringType::Tilt));
+        }
+    }
+    else
+    {
+        emberAfWindowCoveringClusterPrint("WindowCovering has no delegate set for endpoint:%u", endpoint);
+    }
+
     emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS);
+
     return true;
 }
 
@@ -728,6 +694,24 @@ bool emberAfWindowCoveringClusterDownOrCloseCallback(app::CommandHandler * comma
         Attributes::TargetPositionTiltPercent100ths::Set(endpoint, WC_PERCENT100THS_MAX_CLOSED);
     }
     emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS);
+
+    Delegate * delegate = GetDelegate(endpoint);
+    if (delegate)
+    {
+        if (HasFeature(endpoint, Feature::kPositionAwareLift))
+        {
+            LogErrorOnFailure(delegate->HandleMovement(WindowCoveringType::Lift));
+        }
+        else if (HasFeature(endpoint, Feature::kPositionAwareTilt))
+        {
+            LogErrorOnFailure(delegate->HandleMovement(WindowCoveringType::Tilt));
+        }
+    }
+    else
+    {
+        emberAfWindowCoveringClusterPrint("WindowCovering has no delegate set for endpoint:%u", endpoint);
+    }
+
     return true;
 }
 
@@ -750,6 +734,16 @@ bool emberAfWindowCoveringClusterStopMotionCallback(app::CommandHandler * comman
         return true;
     }
 
+    Delegate * delegate = GetDelegate(endpoint);
+    if (delegate)
+    {
+        LogErrorOnFailure(delegate->HandleStopMotion());
+    }
+    else
+    {
+        emberAfWindowCoveringClusterPrint("WindowCovering has no delegate set for endpoint:%u", endpoint);
+    }
+
     if (HasFeaturePaLift(endpoint))
     {
         (void) Attributes::CurrentPositionLiftPercent100ths::Get(endpoint, current);
@@ -789,6 +783,15 @@ bool emberAfWindowCoveringClusterGoToLiftValueCallback(app::CommandHandler * com
     if (HasFeature(endpoint, Feature::kAbsolutePosition) && HasFeaturePaLift(endpoint))
     {
         Attributes::TargetPositionLiftPercent100ths::Set(endpoint, LiftToPercent100ths(endpoint, liftValue));
+        Delegate * delegate = GetDelegate(endpoint);
+        if (delegate)
+        {
+            LogErrorOnFailure(delegate->HandleMovement(WindowCoveringType::Lift));
+        }
+        else
+        {
+            emberAfWindowCoveringClusterPrint("WindowCovering has no delegate set for endpoint:%u", endpoint);
+        }
         emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS);
     }
     else
@@ -824,6 +827,15 @@ bool emberAfWindowCoveringClusterGoToLiftPercentageCallback(app::CommandHandler
         if (IsPercent100thsValid(percent100ths))
         {
             Attributes::TargetPositionLiftPercent100ths::Set(endpoint, percent100ths);
+            Delegate * delegate = GetDelegate(endpoint);
+            if (delegate)
+            {
+                LogErrorOnFailure(delegate->HandleMovement(WindowCoveringType::Lift));
+            }
+            else
+            {
+                emberAfWindowCoveringClusterPrint("WindowCovering has no delegate set for endpoint:%u", endpoint);
+            }
             emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS);
         }
         else
@@ -863,6 +875,15 @@ bool emberAfWindowCoveringClusterGoToTiltValueCallback(app::CommandHandler * com
     if (HasFeature(endpoint, Feature::kAbsolutePosition) && HasFeaturePaTilt(endpoint))
     {
         Attributes::TargetPositionTiltPercent100ths::Set(endpoint, TiltToPercent100ths(endpoint, tiltValue));
+        Delegate * delegate = GetDelegate(endpoint);
+        if (delegate)
+        {
+            LogErrorOnFailure(delegate->HandleMovement(WindowCoveringType::Tilt));
+        }
+        else
+        {
+            emberAfWindowCoveringClusterPrint("WindowCovering has no delegate set for endpoint:%u", endpoint);
+        }
         emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS);
     }
     else
@@ -898,6 +919,15 @@ bool emberAfWindowCoveringClusterGoToTiltPercentageCallback(app::CommandHandler
         if (IsPercent100thsValid(percent100ths))
         {
             Attributes::TargetPositionTiltPercent100ths::Set(endpoint, percent100ths);
+            Delegate * delegate = GetDelegate(endpoint);
+            if (delegate)
+            {
+                LogErrorOnFailure(delegate->HandleMovement(WindowCoveringType::Tilt));
+            }
+            else
+            {
+                emberAfWindowCoveringClusterPrint("WindowCovering has no delegate set for endpoint:%u", endpoint);
+            }
             emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS);
         }
         else

+ 4 - 1
src/app/clusters/window-covering-server/window-covering-server.h

@@ -17,6 +17,7 @@
 
 #pragma once
 
+#include "window-covering-delegate.h"
 #include <app-common/zap-generated/attribute-id.h>
 #include <app-common/zap-generated/cluster-objects.h>
 #include <app-common/zap-generated/enums.h>
@@ -37,9 +38,9 @@ namespace WindowCovering {
 typedef DataModel::Nullable<Percent> NPercent;
 typedef DataModel::Nullable<Percent100ths> NPercent100ths;
 typedef DataModel::Nullable<uint16_t> NAbsolute;
-
 typedef Optional<Percent> OPercent;
 typedef Optional<Percent100ths> OPercent100ths;
+
 // Match directly with OperationalStatus 2 bits Fields
 enum class OperationalState : uint8_t
 {
@@ -129,6 +130,8 @@ EmberAfStatus GetMotionLockStatus(chip::EndpointId endpoint);
  */
 void PostAttributeChange(chip::EndpointId endpoint, chip::AttributeId attributeId);
 
+void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate);
+
 } // namespace WindowCovering
 } // namespace Clusters
 } // namespace app

+ 6 - 6
src/app/tests/suites/certification/Test_TC_WNCV_3_1.yaml

@@ -231,7 +231,7 @@ tests:
           from DUT"
       command: "readAttribute"
       attribute: "CurrentPositionLiftPercent100ths"
-      PICS: WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000e && PICS_SKIP_SAMPLE_APP
+      PICS: WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000e
       response:
           constraints:
               type: Percent100ths
@@ -244,7 +244,7 @@ tests:
           attribute from DUT"
       command: "readAttribute"
       attribute: "CurrentPositionLiftPercentage"
-      PICS: WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A0008 && PICS_SKIP_SAMPLE_APP
+      PICS: WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A0008
       response:
           constraints:
               type: Percent
@@ -257,7 +257,7 @@ tests:
           from DUT"
       command: "readAttribute"
       attribute: "CurrentPositionTiltPercent100ths"
-      PICS: WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000f && PICS_SKIP_SAMPLE_APP
+      PICS: WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000f
       response:
           constraints:
               type: Percent100ths
@@ -270,7 +270,7 @@ tests:
           attribute from DUT"
       command: "readAttribute"
       attribute: "CurrentPositionTiltPercentage"
-      PICS: WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A0009 && PICS_SKIP_SAMPLE_APP
+      PICS: WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A0009
       response:
           constraints:
               type: Percent
@@ -320,7 +320,7 @@ tests:
           from DUT"
       command: "readAttribute"
       attribute: "TargetPositionLiftPercent100ths"
-      PICS: WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000b && PICS_SKIP_SAMPLE_APP
+      PICS: WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000b
       response:
           constraints:
               type: Percent100ths
@@ -333,7 +333,7 @@ tests:
           from DUT"
       command: "readAttribute"
       attribute: "TargetPositionTiltPercent100ths"
-      PICS: WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000c && PICS_SKIP_SAMPLE_APP
+      PICS: WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000c
       response:
           constraints:
               type: Percent100ths

+ 6 - 7
src/app/tests/suites/certification/Test_TC_WNCV_3_2.yaml

@@ -226,13 +226,12 @@ tests:
                 value: 3000
 
     ### Mandatory Depends on the FeatureMap
-    ### Issue https://github.com/project-chip/connectedhomeip/issues/22265
     - label:
           "3b: If (PA & LF) TH reads CurrentPositionLiftPercent100ths attribute
           from DUT"
       command: "readAttribute"
       attribute: "CurrentPositionLiftPercent100ths"
-      PICS: WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000e && PICS_SKIP_SAMPLE_APP
+      PICS: WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000e
       response:
           constraints:
               type: Percent100ths
@@ -245,7 +244,7 @@ tests:
           attribute from DUT"
       command: "readAttribute"
       attribute: "CurrentPositionLiftPercentage"
-      PICS: WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A0008 && PICS_SKIP_SAMPLE_APP
+      PICS: WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A0008
       response:
           constraints:
               type: Percent
@@ -258,7 +257,7 @@ tests:
           from DUT"
       command: "readAttribute"
       attribute: "CurrentPositionTiltPercent100ths"
-      PICS: WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000f && PICS_SKIP_SAMPLE_APP
+      PICS: WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000f
       response:
           constraints:
               type: Percent100ths
@@ -271,7 +270,7 @@ tests:
           attribute from DUT"
       command: "readAttribute"
       attribute: "CurrentPositionTiltPercentage"
-      PICS: WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A0009 && PICS_SKIP_SAMPLE_APP
+      PICS: WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A0009
       response:
           constraints:
               type: Percent
@@ -321,7 +320,7 @@ tests:
           from DUT"
       command: "readAttribute"
       attribute: "TargetPositionLiftPercent100ths"
-      PICS: WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000b && PICS_SKIP_SAMPLE_APP
+      PICS: WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000b
       response:
           constraints:
               type: Percent100ths
@@ -334,7 +333,7 @@ tests:
           from DUT"
       command: "readAttribute"
       attribute: "TargetPositionTiltPercent100ths"
-      PICS: WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000c && PICS_SKIP_SAMPLE_APP
+      PICS: WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000c
       response:
           constraints:
               type: Percent100ths

+ 12 - 24
zzz_generated/chip-tool/zap-generated/test/Commands.h

@@ -41325,29 +41325,25 @@ private:
         }
         case 19: {
             LogStep(19, "3b: If (PA & LF) TH reads CurrentPositionLiftPercent100ths attribute from DUT");
-            VerifyOrDo(!ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000e && PICS_SKIP_SAMPLE_APP"),
-                       return ContinueOnChipMainThread(CHIP_NO_ERROR));
+            VerifyOrDo(!ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000e"), return ContinueOnChipMainThread(CHIP_NO_ERROR));
             return ReadAttribute(kIdentityAlpha, GetEndpoint(1), WindowCovering::Id,
                                  WindowCovering::Attributes::CurrentPositionLiftPercent100ths::Id, true, chip::NullOptional);
         }
         case 20: {
             LogStep(20, "3c: If (PA & LF) TH reads CurrentPositionLiftPercentage optional attribute from DUT");
-            VerifyOrDo(!ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A0008 && PICS_SKIP_SAMPLE_APP"),
-                       return ContinueOnChipMainThread(CHIP_NO_ERROR));
+            VerifyOrDo(!ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A0008"), return ContinueOnChipMainThread(CHIP_NO_ERROR));
             return ReadAttribute(kIdentityAlpha, GetEndpoint(1), WindowCovering::Id,
                                  WindowCovering::Attributes::CurrentPositionLiftPercentage::Id, true, chip::NullOptional);
         }
         case 21: {
             LogStep(21, "3d: If (PA & TL) TH reads CurrentPositionTiltPercent100ths attribute from DUT");
-            VerifyOrDo(!ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000f && PICS_SKIP_SAMPLE_APP"),
-                       return ContinueOnChipMainThread(CHIP_NO_ERROR));
+            VerifyOrDo(!ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000f"), return ContinueOnChipMainThread(CHIP_NO_ERROR));
             return ReadAttribute(kIdentityAlpha, GetEndpoint(1), WindowCovering::Id,
                                  WindowCovering::Attributes::CurrentPositionTiltPercent100ths::Id, true, chip::NullOptional);
         }
         case 22: {
             LogStep(22, "3e: If (PA & LF) TH reads CurrentPositionTiltPercentage optional attribute from DUT");
-            VerifyOrDo(!ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A0009 && PICS_SKIP_SAMPLE_APP"),
-                       return ContinueOnChipMainThread(CHIP_NO_ERROR));
+            VerifyOrDo(!ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A0009"), return ContinueOnChipMainThread(CHIP_NO_ERROR));
             return ReadAttribute(kIdentityAlpha, GetEndpoint(1), WindowCovering::Id,
                                  WindowCovering::Attributes::CurrentPositionTiltPercentage::Id, true, chip::NullOptional);
         }
@@ -41383,15 +41379,13 @@ private:
         }
         case 27: {
             LogStep(27, "5b: If (PA & LF) TH reads TargetPositionLiftPercent100ths attribute from DUT");
-            VerifyOrDo(!ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000b && PICS_SKIP_SAMPLE_APP"),
-                       return ContinueOnChipMainThread(CHIP_NO_ERROR));
+            VerifyOrDo(!ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000b"), return ContinueOnChipMainThread(CHIP_NO_ERROR));
             return ReadAttribute(kIdentityAlpha, GetEndpoint(1), WindowCovering::Id,
                                  WindowCovering::Attributes::TargetPositionLiftPercent100ths::Id, true, chip::NullOptional);
         }
         case 28: {
             LogStep(28, "5c: If (PA & TL) TH reads TargetPositionTiltPercent100ths attribute from DUT");
-            VerifyOrDo(!ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000c && PICS_SKIP_SAMPLE_APP"),
-                       return ContinueOnChipMainThread(CHIP_NO_ERROR));
+            VerifyOrDo(!ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000c"), return ContinueOnChipMainThread(CHIP_NO_ERROR));
             return ReadAttribute(kIdentityAlpha, GetEndpoint(1), WindowCovering::Id,
                                  WindowCovering::Attributes::TargetPositionTiltPercent100ths::Id, true, chip::NullOptional);
         }
@@ -41801,29 +41795,25 @@ private:
         }
         case 19: {
             LogStep(19, "3b: If (PA & LF) TH reads CurrentPositionLiftPercent100ths attribute from DUT");
-            VerifyOrDo(!ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000e && PICS_SKIP_SAMPLE_APP"),
-                       return ContinueOnChipMainThread(CHIP_NO_ERROR));
+            VerifyOrDo(!ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000e"), return ContinueOnChipMainThread(CHIP_NO_ERROR));
             return ReadAttribute(kIdentityAlpha, GetEndpoint(1), WindowCovering::Id,
                                  WindowCovering::Attributes::CurrentPositionLiftPercent100ths::Id, true, chip::NullOptional);
         }
         case 20: {
             LogStep(20, "3c: If (PA & LF) TH reads CurrentPositionLiftPercentage optional attribute from DUT");
-            VerifyOrDo(!ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A0008 && PICS_SKIP_SAMPLE_APP"),
-                       return ContinueOnChipMainThread(CHIP_NO_ERROR));
+            VerifyOrDo(!ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A0008"), return ContinueOnChipMainThread(CHIP_NO_ERROR));
             return ReadAttribute(kIdentityAlpha, GetEndpoint(1), WindowCovering::Id,
                                  WindowCovering::Attributes::CurrentPositionLiftPercentage::Id, true, chip::NullOptional);
         }
         case 21: {
             LogStep(21, "3d: If (PA & TL) TH reads CurrentPositionTiltPercent100ths attribute from DUT");
-            VerifyOrDo(!ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000f && PICS_SKIP_SAMPLE_APP"),
-                       return ContinueOnChipMainThread(CHIP_NO_ERROR));
+            VerifyOrDo(!ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000f"), return ContinueOnChipMainThread(CHIP_NO_ERROR));
             return ReadAttribute(kIdentityAlpha, GetEndpoint(1), WindowCovering::Id,
                                  WindowCovering::Attributes::CurrentPositionTiltPercent100ths::Id, true, chip::NullOptional);
         }
         case 22: {
             LogStep(22, "3e: If (PA & LF) TH reads CurrentPositionTiltPercentage optional attribute from DUT");
-            VerifyOrDo(!ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A0009 && PICS_SKIP_SAMPLE_APP"),
-                       return ContinueOnChipMainThread(CHIP_NO_ERROR));
+            VerifyOrDo(!ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A0009"), return ContinueOnChipMainThread(CHIP_NO_ERROR));
             return ReadAttribute(kIdentityAlpha, GetEndpoint(1), WindowCovering::Id,
                                  WindowCovering::Attributes::CurrentPositionTiltPercentage::Id, true, chip::NullOptional);
         }
@@ -41859,15 +41849,13 @@ private:
         }
         case 27: {
             LogStep(27, "5b: If (PA & LF) TH reads TargetPositionLiftPercent100ths attribute from DUT");
-            VerifyOrDo(!ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000b && PICS_SKIP_SAMPLE_APP"),
-                       return ContinueOnChipMainThread(CHIP_NO_ERROR));
+            VerifyOrDo(!ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000b"), return ContinueOnChipMainThread(CHIP_NO_ERROR));
             return ReadAttribute(kIdentityAlpha, GetEndpoint(1), WindowCovering::Id,
                                  WindowCovering::Attributes::TargetPositionLiftPercent100ths::Id, true, chip::NullOptional);
         }
         case 28: {
             LogStep(28, "5c: If (PA & TL) TH reads TargetPositionTiltPercent100ths attribute from DUT");
-            VerifyOrDo(!ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000c && PICS_SKIP_SAMPLE_APP"),
-                       return ContinueOnChipMainThread(CHIP_NO_ERROR));
+            VerifyOrDo(!ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000c"), return ContinueOnChipMainThread(CHIP_NO_ERROR));
             return ReadAttribute(kIdentityAlpha, GetEndpoint(1), WindowCovering::Id,
                                  WindowCovering::Attributes::TargetPositionTiltPercent100ths::Id, true, chip::NullOptional);
         }

+ 12 - 12
zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h

@@ -66428,7 +66428,7 @@ public:
         case 20:
             ChipLogProgress(
                 chipTool, " ***** Test Step 20 : 3b: If (PA & LF) TH reads CurrentPositionLiftPercent100ths attribute from DUT\n");
-            if (ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000e && PICS_SKIP_SAMPLE_APP")) {
+            if (ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000e")) {
                 NextTest();
                 return;
             }
@@ -66437,7 +66437,7 @@ public:
         case 21:
             ChipLogProgress(chipTool,
                 " ***** Test Step 21 : 3c: If (PA & LF) TH reads CurrentPositionLiftPercentage optional attribute from DUT\n");
-            if (ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A0008 && PICS_SKIP_SAMPLE_APP")) {
+            if (ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A0008")) {
                 NextTest();
                 return;
             }
@@ -66446,7 +66446,7 @@ public:
         case 22:
             ChipLogProgress(
                 chipTool, " ***** Test Step 22 : 3d: If (PA & TL) TH reads CurrentPositionTiltPercent100ths attribute from DUT\n");
-            if (ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000f && PICS_SKIP_SAMPLE_APP")) {
+            if (ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000f")) {
                 NextTest();
                 return;
             }
@@ -66455,7 +66455,7 @@ public:
         case 23:
             ChipLogProgress(chipTool,
                 " ***** Test Step 23 : 3e: If (PA & LF) TH reads CurrentPositionTiltPercentage optional attribute from DUT\n");
-            if (ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A0009 && PICS_SKIP_SAMPLE_APP")) {
+            if (ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A0009")) {
                 NextTest();
                 return;
             }
@@ -66490,7 +66490,7 @@ public:
         case 28:
             ChipLogProgress(
                 chipTool, " ***** Test Step 28 : 5b: If (PA & LF) TH reads TargetPositionLiftPercent100ths attribute from DUT\n");
-            if (ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000b && PICS_SKIP_SAMPLE_APP")) {
+            if (ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000b")) {
                 NextTest();
                 return;
             }
@@ -66499,7 +66499,7 @@ public:
         case 29:
             ChipLogProgress(
                 chipTool, " ***** Test Step 29 : 5c: If (PA & TL) TH reads TargetPositionTiltPercent100ths attribute from DUT\n");
-            if (ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000c && PICS_SKIP_SAMPLE_APP")) {
+            if (ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000c")) {
                 NextTest();
                 return;
             }
@@ -67430,7 +67430,7 @@ public:
         case 20:
             ChipLogProgress(
                 chipTool, " ***** Test Step 20 : 3b: If (PA & LF) TH reads CurrentPositionLiftPercent100ths attribute from DUT\n");
-            if (ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000e && PICS_SKIP_SAMPLE_APP")) {
+            if (ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000e")) {
                 NextTest();
                 return;
             }
@@ -67439,7 +67439,7 @@ public:
         case 21:
             ChipLogProgress(chipTool,
                 " ***** Test Step 21 : 3c: If (PA & LF) TH reads CurrentPositionLiftPercentage optional attribute from DUT\n");
-            if (ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A0008 && PICS_SKIP_SAMPLE_APP")) {
+            if (ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A0008")) {
                 NextTest();
                 return;
             }
@@ -67448,7 +67448,7 @@ public:
         case 22:
             ChipLogProgress(
                 chipTool, " ***** Test Step 22 : 3d: If (PA & TL) TH reads CurrentPositionTiltPercent100ths attribute from DUT\n");
-            if (ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000f && PICS_SKIP_SAMPLE_APP")) {
+            if (ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000f")) {
                 NextTest();
                 return;
             }
@@ -67457,7 +67457,7 @@ public:
         case 23:
             ChipLogProgress(chipTool,
                 " ***** Test Step 23 : 3e: If (PA & LF) TH reads CurrentPositionTiltPercentage optional attribute from DUT\n");
-            if (ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A0009 && PICS_SKIP_SAMPLE_APP")) {
+            if (ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A0009")) {
                 NextTest();
                 return;
             }
@@ -67492,7 +67492,7 @@ public:
         case 28:
             ChipLogProgress(
                 chipTool, " ***** Test Step 28 : 5b: If (PA & LF) TH reads TargetPositionLiftPercent100ths attribute from DUT\n");
-            if (ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000b && PICS_SKIP_SAMPLE_APP")) {
+            if (ShouldSkip("WNCV.S.F00 && WNCV.S.F02 && WNCV.S.A000b")) {
                 NextTest();
                 return;
             }
@@ -67501,7 +67501,7 @@ public:
         case 29:
             ChipLogProgress(
                 chipTool, " ***** Test Step 29 : 5c: If (PA & TL) TH reads TargetPositionTiltPercent100ths attribute from DUT\n");
-            if (ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000c && PICS_SKIP_SAMPLE_APP")) {
+            if (ShouldSkip("WNCV.S.F01 && WNCV.S.F04 && WNCV.S.A000c")) {
                 NextTest();
                 return;
             }