@@ -205,6 +205,48 @@ bool MatterWindowCovering::attributeChangeCB(uint16_t endpoint_id, uint32_t clus
205205 log_d (" Window Covering Target Lift Percentage changed to %d%%" , targetLiftPercent);
206206 // Call callback to trigger movement - do NOT update currentLiftPercent here
207207 // `CurrentPosition` will be updated by the application when the device actually moves
208+ // Get current position to detect StopMotion command
209+ uint16_t currentLiftPercent100ths = 0 ;
210+ esp_matter_attr_val_t currentVal = esp_matter_invalid (NULL );
211+ if (getAttributeVal (WindowCovering::Id, WindowCovering::Attributes::CurrentPositionLiftPercent100ths::Id, ¤tVal)) {
212+ if (!chip::app::NumericAttributeTraits<uint16_t >::IsNullValue (currentVal.val .u16 )) {
213+ currentLiftPercent100ths = currentVal.val .u16 ;
214+ log_d (" Window Covering Current Lift Percentage is %d%%" , (uint8_t )(currentLiftPercent100ths / 100 ));
215+ }
216+ }
217+
218+ // Detect command type based on target value and call appropriate callbacks
219+ // Commands modify TargetPositionLiftPercent100ths:
220+ // - UpOrOpen: sets TargetPosition = 0 (WC_PERCENT100THS_MIN_OPEN)
221+ // - DownOrClose: sets TargetPosition = 10000 (WC_PERCENT100THS_MAX_CLOSED)
222+ // - StopMotion: sets TargetPosition = CurrentPosition
223+ // Priority: UpOrOpen/DownOrClose > StopMotion > GoToLiftPercentage
224+ // Note: If StopMotion is executed when CurrentPosition is at 0 or 10000,
225+ // it will be detected as UpOrOpen/DownOrClose (acceptable behavior)
226+ if (targetLiftPercent100ths == 0 ) {
227+ // UpOrOpen command - fully open (priority check)
228+ log_d (" Window Covering: UpOrOpen command detected" );
229+ if (_onOpenCB != NULL ) {
230+ ret &= _onOpenCB ();
231+ }
232+ } else if (targetLiftPercent100ths == 10000 ) {
233+ // DownOrClose command - fully closed (priority check)
234+ log_d (" Window Covering: DownOrClose command detected" );
235+ if (_onCloseCB != NULL ) {
236+ ret &= _onCloseCB ();
237+ }
238+ } else if (targetLiftPercent100ths == currentLiftPercent100ths && currentLiftPercent100ths != 0 && currentLiftPercent100ths != 10000 ) {
239+ // StopMotion command - target equals current position (but not at limits)
240+ // This detects StopMotion when TargetPosition is set to CurrentPosition
241+ // and CurrentPosition is not at the limits (0 or 10000)
242+ log_d (" Window Covering: StopMotion command detected" );
243+ if (_onStopCB != NULL ) {
244+ ret &= _onStopCB ();
245+ }
246+ }
247+
248+ // Always call the generic onGoToLiftPercentage callback for compatibility
249+ // This handles all target position changes, including commands and direct attribute writes
208250 if (_onGoToLiftPercentageCB != NULL ) {
209251 ret &= _onGoToLiftPercentageCB (targetLiftPercent);
210252 }
0 commit comments