@@ -1040,7 +1040,7 @@ void ColorControlServer::startColorLoop(EndpointId endpoint, uint8_t startFromSt
1040
1040
colorHueTransitionState->transitionTime = MAX_INT16U_VALUE;
1041
1041
colorHueTransitionState->endpoint = endpoint;
1042
1042
1043
- SetQuietReportRemainingTime (endpoint, MAX_INT16U_VALUE);
1043
+ SetQuietReportRemainingTime (endpoint, MAX_INT16U_VALUE, true /* isNewTransition */ );
1044
1044
1045
1045
scheduleTimerCallbackMs (configureHSVEventControl (endpoint), TRANSITION_UPDATE_TIME_MS.count ());
1046
1046
}
@@ -1091,7 +1091,10 @@ void ColorControlServer::SetHSVRemainingTime(chip::EndpointId endpoint)
1091
1091
// When the hue transition is loop, RemainingTime stays at MAX_INT16
1092
1092
if (hueTransitionState->repeat == false )
1093
1093
{
1094
- SetQuietReportRemainingTime (endpoint, max (hueTransitionState->timeRemaining , saturationTransitionState->timeRemaining ));
1094
+ bool hsvTransitionStart = (hueTransitionState->stepsRemaining == hueTransitionState->stepsTotal ) ||
1095
+ (saturationTransitionState->stepsRemaining == saturationTransitionState->stepsTotal );
1096
+ SetQuietReportRemainingTime (endpoint, max (hueTransitionState->timeRemaining , saturationTransitionState->timeRemaining ),
1097
+ hsvTransitionStart);
1095
1098
}
1096
1099
}
1097
1100
@@ -1484,7 +1487,7 @@ bool ColorControlServer::moveHueCommand(app::CommandHandler * commandObj, const
1484
1487
colorHueTransitionState->repeat = true ;
1485
1488
1486
1489
// hue movement can last forever. Indicate this with a remaining time of maxint
1487
- SetQuietReportRemainingTime (endpoint, MAX_INT16U_VALUE);
1490
+ SetQuietReportRemainingTime (endpoint, MAX_INT16U_VALUE, true /* isNewTransition */ );
1488
1491
1489
1492
// kick off the state machine:
1490
1493
scheduleTimerCallbackMs (configureHSVEventControl (endpoint), TRANSITION_UPDATE_TIME_MS.count ());
@@ -2052,7 +2055,7 @@ bool ColorControlServer::colorLoopCommand(app::CommandHandler * commandObj, cons
2052
2055
uint16_t storedEnhancedHue = 0 ;
2053
2056
Attributes::ColorLoopStoredEnhancedHue::Get (endpoint, &storedEnhancedHue);
2054
2057
MarkAttributeDirty markDirty =
2055
- SetQuietReportAttribute (quietEnhancedHue[epIndex], storedEnhancedHue, true /* isStartOrEndOfTransition */ , 0 );
2058
+ SetQuietReportAttribute (quietEnhancedHue[epIndex], storedEnhancedHue, true /* isEndOfTransition */ , 0 );
2056
2059
Attributes::EnhancedCurrentHue::Set (endpoint, quietEnhancedHue[epIndex].value ().Value (), markDirty);
2057
2060
}
2058
2061
else
@@ -2094,10 +2097,6 @@ void ColorControlServer::updateHueSatCommand(EndpointId endpoint)
2094
2097
uint16_t previousSaturation = colorSaturationTransitionState->currentValue ;
2095
2098
uint16_t previousEnhancedhue = colorHueTransitionState->currentEnhancedHue ;
2096
2099
2097
- bool isHueTansitionStart = (colorHueTransitionState->stepsRemaining == colorHueTransitionState->stepsTotal );
2098
- bool isSaturationTransitionStart =
2099
- (colorSaturationTransitionState->stepsRemaining == colorSaturationTransitionState->stepsTotal );
2100
-
2101
2100
bool isHueTansitionDone = computeNewHueValue (colorHueTransitionState);
2102
2101
bool isSaturationTransitionDone = computeNewColor16uValue (colorSaturationTransitionState);
2103
2102
@@ -2117,7 +2116,7 @@ void ColorControlServer::updateHueSatCommand(EndpointId endpoint)
2117
2116
if (colorHueTransitionState->isEnhancedHue )
2118
2117
{
2119
2118
markDirty = SetQuietReportAttribute (quietEnhancedHue[epIndex], colorHueTransitionState->currentEnhancedHue ,
2120
- (isHueTansitionStart || isHueTansitionDone) , colorHueTransitionState->transitionTime );
2119
+ isHueTansitionDone, colorHueTransitionState->transitionTime );
2121
2120
Attributes::EnhancedCurrentHue::Set (endpoint, quietEnhancedHue[epIndex].value ().Value (), markDirty);
2122
2121
currentHue = static_cast <uint8_t >(colorHueTransitionState->currentEnhancedHue >> 8 );
2123
2122
@@ -2135,8 +2134,7 @@ void ColorControlServer::updateHueSatCommand(EndpointId endpoint)
2135
2134
}
2136
2135
}
2137
2136
2138
- markDirty = SetQuietReportAttribute (quietHue[epIndex], currentHue, (isHueTansitionStart || isHueTansitionDone),
2139
- colorHueTransitionState->transitionTime );
2137
+ markDirty = SetQuietReportAttribute (quietHue[epIndex], currentHue, isHueTansitionDone, colorHueTransitionState->transitionTime );
2140
2138
Attributes::CurrentHue::Set (endpoint, quietHue[epIndex].value ().Value (), markDirty);
2141
2139
2142
2140
if (previousSaturation != colorSaturationTransitionState->currentValue )
@@ -2145,8 +2143,7 @@ void ColorControlServer::updateHueSatCommand(EndpointId endpoint)
2145
2143
}
2146
2144
2147
2145
markDirty = SetQuietReportAttribute (quietSaturation[epIndex], colorSaturationTransitionState->currentValue ,
2148
- (isSaturationTransitionStart || isSaturationTransitionDone),
2149
- colorSaturationTransitionState->transitionTime );
2146
+ isSaturationTransitionDone, colorSaturationTransitionState->transitionTime );
2150
2147
Attributes::CurrentSaturation::Set (endpoint, quietSaturation[epIndex].value ().Value (), markDirty);
2151
2148
2152
2149
computePwmFromHsv (endpoint);
@@ -2298,7 +2295,7 @@ Status ColorControlServer::moveToColor(uint16_t colorX, uint16_t colorY, uint16_
2298
2295
colorYTransitionState->lowLimit = MIN_CIE_XY_VALUE;
2299
2296
colorYTransitionState->highLimit = MAX_CIE_XY_VALUE;
2300
2297
2301
- SetQuietReportRemainingTime (endpoint, transitionTime);
2298
+ SetQuietReportRemainingTime (endpoint, transitionTime, true /* isNewTransition */ );
2302
2299
2303
2300
// kick off the state machine:
2304
2301
scheduleTimerCallbackMs (configureXYEventControl (endpoint), transitionTime ? TRANSITION_UPDATE_TIME_MS.count () : 0 );
@@ -2405,7 +2402,7 @@ bool ColorControlServer::moveColorCommand(app::CommandHandler * commandObj, cons
2405
2402
colorYTransitionState->lowLimit = MIN_CIE_XY_VALUE;
2406
2403
colorYTransitionState->highLimit = MAX_CIE_XY_VALUE;
2407
2404
2408
- SetQuietReportRemainingTime (endpoint, max (transitionTimeX, transitionTimeY));
2405
+ SetQuietReportRemainingTime (endpoint, max (transitionTimeX, transitionTimeY), true /* isNewTransition */ );
2409
2406
2410
2407
// kick off the state machine:
2411
2408
scheduleTimerCallbackMs (configureXYEventControl (endpoint), TRANSITION_UPDATE_TIME_MS.count ());
@@ -2485,7 +2482,7 @@ bool ColorControlServer::stepColorCommand(app::CommandHandler * commandObj, cons
2485
2482
colorYTransitionState->lowLimit = MIN_CIE_XY_VALUE;
2486
2483
colorYTransitionState->highLimit = MAX_CIE_XY_VALUE;
2487
2484
2488
- SetQuietReportRemainingTime (endpoint, transitionTime);
2485
+ SetQuietReportRemainingTime (endpoint, transitionTime, true /* isNewTransition */ );
2489
2486
2490
2487
// kick off the state machine:
2491
2488
scheduleTimerCallbackMs (configureXYEventControl (endpoint), transitionTime ? TRANSITION_UPDATE_TIME_MS.count () : 0 );
@@ -2521,15 +2518,10 @@ void ColorControlServer::updateXYCommand(EndpointId endpoint)
2521
2518
scheduleTimerCallbackMs (configureXYEventControl (endpoint), TRANSITION_UPDATE_TIME_MS.count ());
2522
2519
}
2523
2520
2524
- bool isXTransitionStart = (colorXTransitionState->stepsRemaining == colorXTransitionState->stepsTotal );
2525
- bool isYTransitionStart = (colorYTransitionState->stepsRemaining == colorYTransitionState->stepsTotal );
2526
-
2527
- MarkAttributeDirty markXDirty =
2528
- SetQuietReportAttribute (quietColorX[epIndex], colorXTransitionState->currentValue ,
2529
- (isXTransitionStart || isXTransitionDone), colorXTransitionState->transitionTime );
2530
- MarkAttributeDirty markYDirty =
2531
- SetQuietReportAttribute (quietColorY[epIndex], colorYTransitionState->currentValue ,
2532
- (isYTransitionStart || isYTransitionDone), colorYTransitionState->transitionTime );
2521
+ MarkAttributeDirty markXDirty = SetQuietReportAttribute (quietColorX[epIndex], colorXTransitionState->currentValue ,
2522
+ isXTransitionDone, colorXTransitionState->transitionTime );
2523
+ MarkAttributeDirty markYDirty = SetQuietReportAttribute (quietColorY[epIndex], colorYTransitionState->currentValue ,
2524
+ isYTransitionDone, colorYTransitionState->transitionTime );
2533
2525
2534
2526
Attributes::CurrentX::Set (endpoint, quietColorX[epIndex].value ().Value (), markXDirty);
2535
2527
Attributes::CurrentY::Set (endpoint, quietColorY[epIndex].value ().Value (), markYDirty);
@@ -2623,6 +2615,8 @@ Status ColorControlServer::moveToColorTemp(EndpointId aEndpoint, uint16_t colorT
2623
2615
colorTempTransitionState->lowLimit = temperatureMin;
2624
2616
colorTempTransitionState->highLimit = temperatureMax;
2625
2617
2618
+ SetQuietReportRemainingTime (endpoint, transitionTime, true /* isNewTransition */ );
2619
+
2626
2620
// kick off the state machine
2627
2621
scheduleTimerCallbackMs (configureTempEventControl (endpoint), transitionTime ? TRANSITION_UPDATE_TIME_MS.count () : 0 );
2628
2622
return Status::Success;
@@ -2687,36 +2681,32 @@ void ColorControlServer::startUpColorTempCommand(EndpointId endpoint)
2687
2681
2688
2682
if (status == Status::Success && !startUpColorTemp.IsNull ())
2689
2683
{
2690
- uint16_t updatedColorTemp = MAX_TEMPERATURE_VALUE;
2691
- status = Attributes::ColorTemperatureMireds::Get (endpoint, &updatedColorTemp);
2684
+ uint16_t tempPhysicalMin = MIN_TEMPERATURE_VALUE;
2685
+ Attributes::ColorTempPhysicalMinMireds::Get (endpoint, &tempPhysicalMin);
2686
+ // Avoid potential divide-by-zero in future Kelvin conversions.
2687
+ tempPhysicalMin = std::max (static_cast <uint16_t >(1u ), tempPhysicalMin);
2692
2688
2693
- if (status == Status::Success)
2694
- {
2695
- uint16_t tempPhysicalMin = MIN_TEMPERATURE_VALUE;
2696
- Attributes::ColorTempPhysicalMinMireds::Get (endpoint, &tempPhysicalMin);
2697
- // Avoid potential divide-by-zero in future Kelvin conversions.
2698
- tempPhysicalMin = std::max (static_cast <uint16_t >(1u ), tempPhysicalMin);
2689
+ uint16_t tempPhysicalMax = MAX_TEMPERATURE_VALUE;
2690
+ Attributes::ColorTempPhysicalMaxMireds::Get (endpoint, &tempPhysicalMax);
2699
2691
2700
- uint16_t tempPhysicalMax = MAX_TEMPERATURE_VALUE;
2701
- Attributes::ColorTempPhysicalMaxMireds::Get (endpoint, &tempPhysicalMax);
2692
+ if (tempPhysicalMin <= startUpColorTemp.Value () && startUpColorTemp.Value () <= tempPhysicalMax)
2693
+ {
2694
+ // Apply valid startup color temp value that is within physical limits of device.
2695
+ // Otherwise, the startup value is outside the device's supported range, and the
2696
+ // existing setting of ColorTemp attribute will be left unchanged (i.e., treated as
2697
+ // if startup color temp was set to null).
2698
+ uint16_t epIndex = getEndpointIndex (endpoint);
2699
+ MarkAttributeDirty markDirty = SetQuietReportAttribute (quietTemperatureMireds[epIndex], startUpColorTemp.Value (),
2700
+ false /* isEndOfTransition */ , 0 );
2701
+ status = Attributes::ColorTemperatureMireds::Set (endpoint, quietTemperatureMireds[epIndex].value ().Value (), markDirty);
2702
2702
2703
- if (tempPhysicalMin <= startUpColorTemp. Value () && startUpColorTemp. Value () <= tempPhysicalMax )
2703
+ if (status == Status::Success )
2704
2704
{
2705
- // Apply valid startup color temp value that is within physical limits of device.
2706
- // Otherwise, the startup value is outside the device's supported range, and the
2707
- // existing setting of ColorTemp attribute will be left unchanged (i.e., treated as
2708
- // if startup color temp was set to null).
2709
- updatedColorTemp = startUpColorTemp.Value ();
2710
- status = Attributes::ColorTemperatureMireds::Set (endpoint, updatedColorTemp);
2711
-
2712
- if (status == Status::Success)
2713
- {
2714
- // Set ColorMode attributes to reflect ColorTemperature.
2715
- auto updateColorMode = ColorModeEnum::kColorTemperatureMireds ;
2716
- Attributes::ColorMode::Set (endpoint, updateColorMode);
2705
+ // Set ColorMode attributes to reflect ColorTemperature.
2706
+ auto updateColorMode = ColorModeEnum::kColorTemperatureMireds ;
2707
+ Attributes::ColorMode::Set (endpoint, updateColorMode);
2717
2708
2718
- Attributes::EnhancedColorMode::Set (endpoint, static_cast <EnhancedColorModeEnum>(updateColorMode));
2719
- }
2709
+ Attributes::EnhancedColorMode::Set (endpoint, static_cast <EnhancedColorModeEnum>(updateColorMode));
2720
2710
}
2721
2711
}
2722
2712
}
@@ -2729,7 +2719,8 @@ void ColorControlServer::startUpColorTempCommand(EndpointId endpoint)
2729
2719
*/
2730
2720
void ColorControlServer::updateTempCommand (EndpointId endpoint)
2731
2721
{
2732
- Color16uTransitionState * colorTempTransitionState = getTempTransitionState (endpoint);
2722
+ uint16_t epIndex = getEndpointIndex (endpoint);
2723
+ Color16uTransitionState * colorTempTransitionState = getTempTransitionStateByIndex (epIndex);
2733
2724
bool isColorTempTransitionDone;
2734
2725
2735
2726
isColorTempTransitionDone = computeNewColor16uValue (colorTempTransitionState);
@@ -2763,7 +2754,9 @@ void ColorControlServer::updateTempCommand(EndpointId endpoint)
2763
2754
scheduleTimerCallbackMs (configureTempEventControl (endpoint), TRANSITION_UPDATE_TIME_MS.count ());
2764
2755
}
2765
2756
2766
- Attributes::ColorTemperatureMireds::Set (endpoint, colorTempTransitionState->currentValue );
2757
+ MarkAttributeDirty markDirty = SetQuietReportAttribute (quietTemperatureMireds[epIndex], colorTempTransitionState->currentValue ,
2758
+ isColorTempTransitionDone, colorTempTransitionState->timeRemaining );
2759
+ Attributes::ColorTemperatureMireds::Set (endpoint, quietTemperatureMireds[epIndex].value ().Value (), markDirty);
2767
2760
2768
2761
ChipLogProgress (Zcl, " Color Temperature %d" , colorTempTransitionState->currentValue );
2769
2762
@@ -2882,7 +2875,7 @@ bool ColorControlServer::moveColorTempCommand(app::CommandHandler * commandObj,
2882
2875
colorTempTransitionState->lowLimit = colorTemperatureMinimum;
2883
2876
colorTempTransitionState->highLimit = colorTemperatureMaximum;
2884
2877
2885
- SetQuietReportRemainingTime (endpoint, transitionTime);
2878
+ SetQuietReportRemainingTime (endpoint, transitionTime, true /* isNewTransition */ );
2886
2879
2887
2880
// kick off the state machine:
2888
2881
scheduleTimerCallbackMs (configureTempEventControl (endpoint), TRANSITION_UPDATE_TIME_MS.count ());
@@ -3005,7 +2998,7 @@ bool ColorControlServer::stepColorTempCommand(app::CommandHandler * commandObj,
3005
2998
colorTempTransitionState->lowLimit = colorTemperatureMinimum;
3006
2999
colorTempTransitionState->highLimit = colorTemperatureMaximum;
3007
3000
3008
- SetQuietReportRemainingTime (endpoint, transitionTime);
3001
+ SetQuietReportRemainingTime (endpoint, transitionTime, true /* isNewTransition */ );
3009
3002
3010
3003
// kick off the state machine:
3011
3004
scheduleTimerCallbackMs (configureTempEventControl (endpoint), transitionTime ? TRANSITION_UPDATE_TIME_MS.count () : 0 );
@@ -3103,7 +3096,6 @@ void ColorControlServer::levelControlColorTempChangeCommand(EndpointId endpoint)
3103
3096
* Utility function used to update a color control attribute which has the quiet reporting quality.
3104
3097
* matching the following report conditions:
3105
3098
* - At most once per second, or
3106
- * - At the start of the movement/transition, or
3107
3099
* - At the end of the movement/transition, or
3108
3100
* - When it changes from null to any other value and vice versa. (Implicit to the QuieterReportingAttribute class)
3109
3101
*
@@ -3114,20 +3106,20 @@ void ColorControlServer::levelControlColorTempChangeCommand(EndpointId endpoint)
3114
3106
*
3115
3107
* @param quietReporter: The QuieterReportingAttribute<TYPE> object for the attribute to update.
3116
3108
* @param newValue: Value to update the attribute with
3117
- * @param isStartOrEndOfTransition : Boolean that indicatse whether the update is occurring at the start or end of a level transition
3109
+ * @param isEndOfTransition : Boolean that indicates whether the update is occurring at the end of a color transition
3118
3110
* @return MarkAttributeDirty::kYes when the attribute must be marked dirty and be reported. MarkAttributeDirty::kNo when
3119
3111
* no report is needed.
3120
3112
*/
3121
3113
template <typename Q, typename V>
3122
3114
MarkAttributeDirty ColorControlServer::SetQuietReportAttribute (QuieterReportingAttribute<Q> & quietReporter, V newValue,
3123
- bool isStartOrEndOfTransition , uint16_t transitionTime)
3115
+ bool isEndOfTransition , uint16_t transitionTime)
3124
3116
{
3125
3117
AttributeDirtyState dirtyState;
3126
3118
auto now = System::SystemClock ().GetMonotonicTimestamp ();
3127
3119
3128
- if (isStartOrEndOfTransition )
3120
+ if (isEndOfTransition )
3129
3121
{
3130
- // At the start or end of the movement/transition we must report if the value changed
3122
+ // At the end of the movement/transition we must report if the value changed
3131
3123
auto predicate = [](const typename QuieterReportingAttribute<Q>::SufficientChangePredicateCandidate &) -> bool {
3132
3124
return true ;
3133
3125
};
@@ -3157,23 +3149,42 @@ MarkAttributeDirty ColorControlServer::SetQuietReportAttribute(QuieterReportingA
3157
3149
* @brief
3158
3150
* Function used to set the remaining time based on quiet reporting conditions.
3159
3151
* It will update the attribute storage and report the attribute if it is determined dirty.
3160
- * The condition on which the attribute must be reported are defined by the set QuieterReportingPolicyFlags
3161
- * of the quietRemainingTime object and the implicit conditions of the QuieterReportingAttribute class
3152
+ * The conditions on which the attribute must be reported are:
3153
+ * - When it changes from 0 to any value higher than 10, or
3154
+ * - When it changes, with a delta larger than 10, caused by the invoke of a command, or
3155
+ * - When it changes to 0.
3162
3156
*
3163
3157
* @param endpoint: Endpoint of the RemainingTime attribute to set
3164
3158
* @param newRemainingTime: Value to update the RemainingTime attribute with
3165
3159
* @return Success in setting the attribute value or the IM error code for the failure.
3166
3160
*/
3167
- Status ColorControlServer::SetQuietReportRemainingTime (EndpointId endpoint, uint16_t newRemainingTime)
3168
- {
3169
- uint16_t epIndex = getEndpointIndex (endpoint);
3170
- auto markDirty = MarkAttributeDirty::kNo ;
3171
- auto now = System::SystemClock ().GetMonotonicTimestamp ();
3172
- // Establish the quiet report condition for the RemainingTime Attribute
3173
- // The quiet report is by the previously set policies :
3174
- // - kMarkDirtyOnChangeToFromZero : When the value changes from 0 to any other value and vice versa, or
3175
- // - kMarkDirtyOnIncrement : When the value increases.
3176
- if (quietRemainingTime[epIndex].SetValue (newRemainingTime, now) == AttributeDirtyState::kMustReport )
3161
+ Status ColorControlServer::SetQuietReportRemainingTime (EndpointId endpoint, uint16_t newRemainingTime, bool isNewTransition)
3162
+ {
3163
+ uint16_t epIndex = getEndpointIndex (endpoint);
3164
+ uint16_t lastRemainingTime = quietRemainingTime[epIndex].value ().ValueOr (0 );
3165
+ auto markDirty = MarkAttributeDirty::kNo ;
3166
+ auto now = System::SystemClock ().GetMonotonicTimestamp ();
3167
+
3168
+ auto predicate =
3169
+ [isNewTransition, lastRemainingTime](
3170
+ const typename QuieterReportingAttribute<uint16_t >::SufficientChangePredicateCandidate & candidate) -> bool {
3171
+ constexpr uint16_t reportDelta = 10 ;
3172
+ bool isDirty = false ;
3173
+ if (candidate.newValue .Value () == 0 || (candidate.lastDirtyValue .Value () == 0 && candidate.newValue .Value () > reportDelta))
3174
+ {
3175
+ isDirty = true ;
3176
+ }
3177
+ else if (isNewTransition &&
3178
+ (candidate.newValue .Value () > static_cast <uint32_t >(lastRemainingTime + reportDelta) ||
3179
+ static_cast <uint32_t >(candidate.newValue .Value () + reportDelta) < lastRemainingTime ||
3180
+ candidate.newValue .Value () > static_cast <uint32_t >(candidate.lastDirtyValue .Value () + reportDelta)))
3181
+ {
3182
+ isDirty = true ;
3183
+ }
3184
+ return isDirty;
3185
+ };
3186
+
3187
+ if (quietRemainingTime[epIndex].SetValue (newRemainingTime, now, predicate) == AttributeDirtyState::kMustReport )
3177
3188
{
3178
3189
markDirty = MarkAttributeDirty::kYes ;
3179
3190
}
0 commit comments