From fc606110f5e24a4daf23e2f334a8e0b51d993b43 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Mon, 3 Oct 2022 13:46:20 -0700 Subject: [PATCH] Use seperate timers to control lift and tilt window coverings (#22733) --- .../linux/WindowCoveringManager.cpp | 139 ++++++++++++------ .../linux/WindowCoveringManager.h | 9 +- .../window-covering-server.cpp | 6 +- 3 files changed, 108 insertions(+), 46 deletions(-) diff --git a/examples/all-clusters-app/linux/WindowCoveringManager.cpp b/examples/all-clusters-app/linux/WindowCoveringManager.cpp index 0418d7f1cde7f5..21c9253703b36a 100644 --- a/examples/all-clusters-app/linux/WindowCoveringManager.cpp +++ b/examples/all-clusters-app/linux/WindowCoveringManager.cpp @@ -35,72 +35,115 @@ constexpr const uint16_t kDefaultMovementStep = 2000; void WindowCoveringManager::Init(EndpointId endpoint) { mState = OperationalState::Stall; - mCurrentPosition.SetNonNull(static_cast(0)); - mTargetPosition.SetNonNull(static_cast(0)); + mCurrentLiftPosition.SetNonNull(static_cast(0)); + mTargetLiftPosition.SetNonNull(static_cast(0)); + mCurrentTiltPosition.SetNonNull(static_cast(0)); + mTargetTiltPosition.SetNonNull(static_cast(0)); SetEndpoint(endpoint); } -void WindowCoveringManager::HandleMovementTimer(System::Layer * layer, void * aAppState) +void WindowCoveringManager::HandleLiftMovementTimer(System::Layer * layer, void * aAppState) { WindowCoveringManager * manager = reinterpret_cast(aAppState); VerifyOrReturn(manager->mState != OperationalState::Stall); - uint16_t currentPosition = manager->mCurrentPosition.Value(); - uint16_t targetPosition = manager->mTargetPosition.Value(); + Percent100ths currentPosition = manager->mCurrentLiftPosition.Value(); + Percent100ths targetPosition = manager->mTargetLiftPosition.Value(); - ChipLogProgress(NotSpecified, "HandleMovementTimer:currentPosition:%u, targetPosition:%u", currentPosition, targetPosition); + ChipLogProgress(NotSpecified, "HandleLiftMovementTimer:currentPosition:%u, targetPosition:%u", currentPosition, targetPosition); if (OperationalState::MovingUpOrOpen == manager->mState) { - if (currentPosition > targetPosition) - { - uint16_t tempPosition = - currentPosition > kDefaultMovementStep ? static_cast(currentPosition - kDefaultMovementStep) : 0; - currentPosition = tempPosition > targetPosition ? tempPosition : targetPosition; - - manager->mCurrentPosition.SetNonNull(currentPosition); - } - else + if (ComputeOperationalState(targetPosition, currentPosition) != OperationalState::MovingUpOrOpen) { ChipLogProgress(NotSpecified, "Reached the target position"); return; } + + Percent100ths tempPosition = + ComputePercent100thsStep(OperationalState::MovingUpOrOpen, currentPosition, kDefaultMovementStep); + currentPosition = tempPosition > targetPosition ? tempPosition : targetPosition; + manager->mCurrentLiftPosition.SetNonNull(currentPosition); } else { - if (currentPosition < targetPosition) - { - uint16_t tempPosition = static_cast(currentPosition + kDefaultMovementStep); - currentPosition = tempPosition < targetPosition ? tempPosition : targetPosition; - manager->mCurrentPosition.SetNonNull(currentPosition); - } - else + if (ComputeOperationalState(targetPosition, currentPosition) != OperationalState::MovingDownOrClose) { ChipLogProgress(NotSpecified, "Reached the target position"); return; } + + Percent100ths tempPosition = + ComputePercent100thsStep(OperationalState::MovingDownOrClose, currentPosition, kDefaultMovementStep); + currentPosition = tempPosition < targetPosition ? tempPosition : targetPosition; + manager->mCurrentLiftPosition.SetNonNull(currentPosition); } - if (HasFeature(manager->mEndpoint, Feature::kPositionAwareLift)) + LiftPositionSet(manager->mEndpoint, manager->mCurrentLiftPosition); + + if (manager->mCurrentLiftPosition != manager->mTargetLiftPosition) { - LiftPositionSet(manager->mEndpoint, manager->mCurrentPosition); + LogErrorOnFailure(DeviceLayer::SystemLayer().StartTimer(kIncrementMovementTimeout, HandleLiftMovementTimer, aAppState)); } +} + +void WindowCoveringManager::HandleTiltMovementTimer(System::Layer * layer, void * aAppState) +{ + WindowCoveringManager * manager = reinterpret_cast(aAppState); + + VerifyOrReturn(manager->mState != OperationalState::Stall); + + Percent100ths currentPosition = manager->mCurrentTiltPosition.Value(); + Percent100ths targetPosition = manager->mTargetTiltPosition.Value(); + + ChipLogProgress(NotSpecified, "HandleTiltMovementTimer:currentPosition:%u, targetPosition:%u", currentPosition, targetPosition); + + if (OperationalState::MovingUpOrOpen == manager->mState) + { + if (ComputeOperationalState(targetPosition, currentPosition) != OperationalState::MovingUpOrOpen) + { + ChipLogProgress(NotSpecified, "Reached the target position"); + return; + } - if (HasFeature(manager->mEndpoint, Feature::kPositionAwareTilt)) + Percent100ths tempPosition = + ComputePercent100thsStep(OperationalState::MovingUpOrOpen, currentPosition, kDefaultMovementStep); + currentPosition = tempPosition > targetPosition ? tempPosition : targetPosition; + manager->mCurrentTiltPosition.SetNonNull(currentPosition); + } + else { - TiltPositionSet(manager->mEndpoint, manager->mCurrentPosition); + if (ComputeOperationalState(targetPosition, currentPosition) != OperationalState::MovingDownOrClose) + { + ChipLogProgress(NotSpecified, "Reached the target position"); + return; + } + + Percent100ths tempPosition = + ComputePercent100thsStep(OperationalState::MovingDownOrClose, currentPosition, kDefaultMovementStep); + currentPosition = tempPosition < targetPosition ? tempPosition : targetPosition; + manager->mCurrentTiltPosition.SetNonNull(currentPosition); } - if (manager->mCurrentPosition != manager->mTargetPosition) + TiltPositionSet(manager->mEndpoint, manager->mCurrentTiltPosition); + + if (manager->mCurrentTiltPosition != manager->mTargetTiltPosition) { - LogErrorOnFailure(DeviceLayer::SystemLayer().StartTimer(kIncrementMovementTimeout, HandleMovementTimer, aAppState)); + LogErrorOnFailure(DeviceLayer::SystemLayer().StartTimer(kIncrementMovementTimeout, HandleTiltMovementTimer, aAppState)); } } CHIP_ERROR WindowCoveringManager::HandleMovement(WindowCoveringType type) { - mState = OperationalStateGet(mEndpoint, OperationalStatus::kGlobal); + if (type == WindowCoveringType::Lift) + { + mState = OperationalStateGet(mEndpoint, OperationalStatus::kLift); + } + else + { + mState = OperationalStateGet(mEndpoint, OperationalStatus::kTilt); + } if (OperationalState::Stall == mState) { @@ -108,31 +151,45 @@ CHIP_ERROR WindowCoveringManager::HandleMovement(WindowCoveringType type) return CHIP_NO_ERROR; } - // Cancel ongoing window covering movement timer if any. - DeviceLayer::SystemLayer().CancelTimer(HandleMovementTimer, this); + CHIP_ERROR err = CHIP_NO_ERROR; // 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); + // Cancel ongoing window covering movement timer if any. + DeviceLayer::SystemLayer().CancelTimer(HandleLiftMovementTimer, this); + + Attributes::CurrentPositionLiftPercent100ths::Get(mEndpoint, mCurrentLiftPosition); + Attributes::TargetPositionLiftPercent100ths::Get(mEndpoint, mTargetLiftPosition); + + VerifyOrReturnError(!mCurrentLiftPosition.IsNull(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(!mTargetLiftPosition.IsNull(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mCurrentLiftPosition != mTargetLiftPosition, CHIP_ERROR_INCORRECT_STATE); + + err = DeviceLayer::SystemLayer().StartTimer(kIncrementMovementTimeout, HandleLiftMovementTimer, this); } else { - Attributes::CurrentPositionTiltPercent100ths::Get(mEndpoint, mCurrentPosition); - Attributes::TargetPositionTiltPercent100ths::Get(mEndpoint, mTargetPosition); - } + // Cancel ongoing window covering movement timer if any. + DeviceLayer::SystemLayer().CancelTimer(HandleTiltMovementTimer, this); + + Attributes::CurrentPositionTiltPercent100ths::Get(mEndpoint, mCurrentTiltPosition); + Attributes::TargetPositionTiltPercent100ths::Get(mEndpoint, mTargetTiltPosition); - VerifyOrReturnError(!mCurrentPosition.IsNull(), CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(!mTargetPosition.IsNull(), CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mCurrentPosition != mTargetPosition, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(!mCurrentTiltPosition.IsNull(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(!mTargetTiltPosition.IsNull(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mCurrentTiltPosition != mTargetTiltPosition, CHIP_ERROR_INCORRECT_STATE); + + err = DeviceLayer::SystemLayer().StartTimer(kIncrementMovementTimeout, HandleTiltMovementTimer, this); + } - return DeviceLayer::SystemLayer().StartTimer(kIncrementMovementTimeout, HandleMovementTimer, this); + return err; } CHIP_ERROR WindowCoveringManager::HandleStopMotion() { - DeviceLayer::SystemLayer().CancelTimer(HandleMovementTimer, this); + DeviceLayer::SystemLayer().CancelTimer(HandleLiftMovementTimer, this); + DeviceLayer::SystemLayer().CancelTimer(HandleTiltMovementTimer, this); return CHIP_NO_ERROR; } diff --git a/examples/all-clusters-app/linux/WindowCoveringManager.h b/examples/all-clusters-app/linux/WindowCoveringManager.h index 8687329e1ec717..64a61604b611ce 100644 --- a/examples/all-clusters-app/linux/WindowCoveringManager.h +++ b/examples/all-clusters-app/linux/WindowCoveringManager.h @@ -33,14 +33,17 @@ class WindowCoveringManager : public Delegate private: OperationalState mState; - NPercent100ths mCurrentPosition; - NPercent100ths mTargetPosition; + NPercent100ths mCurrentLiftPosition; + NPercent100ths mTargetLiftPosition; + NPercent100ths mCurrentTiltPosition; + NPercent100ths mTargetTiltPosition; /** * @brief * The callback function to be called when "movement timer" expires. */ - static void HandleMovementTimer(chip::System::Layer * layer, void * aAppState); + static void HandleLiftMovementTimer(chip::System::Layer * layer, void * aAppState); + static void HandleTiltMovementTimer(chip::System::Layer * layer, void * aAppState); }; } // namespace WindowCovering diff --git a/src/app/clusters/window-covering-server/window-covering-server.cpp b/src/app/clusters/window-covering-server/window-covering-server.cpp index 0f7562853bf770..65237ba9b1211f 100644 --- a/src/app/clusters/window-covering-server/window-covering-server.cpp +++ b/src/app/clusters/window-covering-server/window-covering-server.cpp @@ -652,7 +652,8 @@ bool emberAfWindowCoveringClusterUpOrOpenCallback(app::CommandHandler * commandO { LogErrorOnFailure(delegate->HandleMovement(WindowCoveringType::Lift)); } - else if (HasFeature(endpoint, Feature::kPositionAwareTilt)) + + if (HasFeature(endpoint, Feature::kPositionAwareTilt)) { LogErrorOnFailure(delegate->HandleMovement(WindowCoveringType::Tilt)); } @@ -702,7 +703,8 @@ bool emberAfWindowCoveringClusterDownOrCloseCallback(app::CommandHandler * comma { LogErrorOnFailure(delegate->HandleMovement(WindowCoveringType::Lift)); } - else if (HasFeature(endpoint, Feature::kPositionAwareTilt)) + + if (HasFeature(endpoint, Feature::kPositionAwareTilt)) { LogErrorOnFailure(delegate->HandleMovement(WindowCoveringType::Tilt)); }