diff --git a/src/app/clusters/level-control/level-control.cpp b/src/app/clusters/level-control/level-control.cpp index 87f6044619a62e..22db98f75f2a0a 100644 --- a/src/app/clusters/level-control/level-control.cpp +++ b/src/app/clusters/level-control/level-control.cpp @@ -701,6 +701,7 @@ static EmberAfStatus moveToLevelHandler(EndpointId endpoint, CommandId commandId actualStepSize = static_cast(currentLevel.Value() - state->moveToLevel); } +#ifndef IGNORE_LEVEL_CONTROL_CLUSTER_TRANSITION // If the Transition time field takes the value null, then the time taken // to move to the new level shall instead be determined by the On/Off // Transition Time attribute. If On/Off Transition Time, which is an @@ -740,6 +741,12 @@ static EmberAfStatus moveToLevelHandler(EndpointId endpoint, CommandId commandId // Time) as tenths of a second, but we work in milliseconds. state->transitionTimeMs = (transitionTimeDs.Value() * MILLISECOND_TICKS_PER_SECOND / 10); } +#else + // Transition is not supported so always use fastest transition time and ignore + // both the provided transition time as well as OnOffTransitionTime. + emberAfLevelControlClusterPrintln("Device does not support transition, ignoring transition time"); + state->transitionTimeMs = FASTEST_TRANSITION_TIME_MS; +#endif // IGNORE_LEVEL_CONTROL_CLUSTER_TRANSITION // The duration between events will be the transition time divided by the // distance we must move. @@ -844,6 +851,7 @@ static void moveHandler(EndpointId endpoint, CommandId commandId, uint8_t moveMo } } +#ifndef IGNORE_LEVEL_CONTROL_CLUSTER_TRANSITION // If the Rate field is null, the device should move at the default move rate, if available, // Otherwise, move as fast as possible if (rate.IsNull()) @@ -870,6 +878,12 @@ static void moveHandler(EndpointId endpoint, CommandId commandId, uint8_t moveMo { state->eventDurationMs = MILLISECOND_TICKS_PER_SECOND / rate.Value(); } +#else + // Transition/rate is not supported so always use fastest transition time and ignore + // both the provided transition time as well as OnOffTransitionTime. + emberAfLevelControlClusterPrintln("Device does not support transition, ignoring rate"); + state->eventDurationMs = FASTEST_TRANSITION_TIME_MS; +#endif // IGNORE_LEVEL_CONTROL_CLUSTER_TRANSITION state->transitionTimeMs = difference * state->eventDurationMs; state->elapsedTimeMs = 0; @@ -979,6 +993,7 @@ static void stepHandler(EndpointId endpoint, CommandId commandId, uint8_t stepMo } } +#ifndef IGNORE_LEVEL_CONTROL_CLUSTER_TRANSITION // If the Transition Time field is null, the device should move as fast as // it is able. if (transitionTimeDs.IsNull()) @@ -998,6 +1013,12 @@ static void stepHandler(EndpointId endpoint, CommandId commandId, uint8_t stepMo state->transitionTimeMs = (state->transitionTimeMs * actualStepSize / stepSize); } } +#else + // Transition is not supported so always use fastest transition time and ignore + // both the provided transition time as well as OnOffTransitionTime. + emberAfLevelControlClusterPrintln("Device does not support transition, ignoring transition time"); + state->transitionTimeMs = FASTEST_TRANSITION_TIME_MS; +#endif // IGNORE_LEVEL_CONTROL_CLUSTER_TRANSITION // The duration between events will be the transition time divided by the // distance we must move. @@ -1063,6 +1084,20 @@ void emberAfOnOffClusterLevelControlEffectCallback(EndpointId endpoint, bool new return; } + // if the OnOff feature is not supported, the effect on LevelControl is ignored + if (!HasFeature(endpoint, chip::app::Clusters::LevelControl::LevelControlFeature::kOnOff)) + { + emberAfLevelControlClusterPrintln("OnOff feature not supported, ignore LevelControlEffect"); + if (!newValue) + { + // OnOff server expects LevelControl to handle the OnOff attribute change, + // when going to off state. The attribute is set directly rather + // than using setOnOff function to avoid misleading comments in log. + OnOff::Attributes::OnOff::Set(endpoint, OnOff::Commands::Off::Id); + } + return; + } + uint8_t minimumLevelAllowedForTheDevice = state->minLevel; // "Temporarily store CurrentLevel." @@ -1277,4 +1312,13 @@ static bool areStartUpLevelControlServerAttributesNonVolatile(EndpointId endpoin void emberAfPluginLevelControlClusterServerPostInitCallback(EndpointId endpoint) {} +bool HasFeature(chip::EndpointId endpoint, chip::app::Clusters::LevelControl::LevelControlFeature feature) +{ + bool success; + uint32_t featureMap; + success = (Attributes::FeatureMap::Get(endpoint, &featureMap) == EMBER_ZCL_STATUS_SUCCESS); + + return success ? ((featureMap & to_underlying(feature)) != 0) : false; +} + void MatterLevelControlPluginServerInitCallback() {} diff --git a/src/app/clusters/level-control/level-control.h b/src/app/clusters/level-control/level-control.h index 4abb51062c36b9..d87d41d6ee7482 100644 --- a/src/app/clusters/level-control/level-control.h +++ b/src/app/clusters/level-control/level-control.h @@ -26,6 +26,7 @@ #include +#include #include /** @brief On/off Cluster Server Post Init @@ -36,3 +37,5 @@ * @param endpoint Endpoint that is being initialized Ver.: always */ void emberAfPluginLevelControlClusterServerPostInitCallback(chip::EndpointId endpoint); + +bool HasFeature(chip::EndpointId endpoint, chip::app::Clusters::LevelControl::LevelControlFeature feature);