[Level Control] Added ability to disable transitioning and OnOff feature (#23679)
* Added ability to disable transitioning and onoff feature
* Fixes from restyle
* Fixed missing OnOff attribute change
* Only handle OnOff state for off
diff --git a/src/app/clusters/level-control/level-control.cpp b/src/app/clusters/level-control/level-control.cpp
index 87f60446..22db98f 100644
--- a/src/app/clusters/level-control/level-control.cpp
+++ b/src/app/clusters/level-control/level-control.cpp
@@ -701,6 +701,7 @@
actualStepSize = static_cast<uint8_t>(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 @@
// 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 @@
}
}
+#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 @@
{
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 @@
}
}
+#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 @@
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 @@
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 @@
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 4abb510..d87d41d 100644
--- a/src/app/clusters/level-control/level-control.h
+++ b/src/app/clusters/level-control/level-control.h
@@ -26,6 +26,7 @@
#include <stdint.h>
+#include <app-common/zap-generated/cluster-objects.h>
#include <app/util/basic-types.h>
/** @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);