24
24
#include < app-common/zap-generated/cluster-objects.h>
25
25
#include < app-common/zap-generated/ids/Attributes.h>
26
26
#include < app-common/zap-generated/ids/Clusters.h>
27
+ #include < app/AttributeAccessInterfaceRegistry.h>
27
28
#include < app/CommandHandler.h>
28
29
#include < app/ConcreteCommandPath.h>
29
30
#include < app/clusters/fan-control-server/fan-control-server.h>
@@ -389,7 +390,7 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt
389
390
// Plus 99 then integer divide by 100 instead of multiplying 0.01 to avoid floating point precision error
390
391
uint8_t speedSetting = static_cast <uint8_t >((speedMax * percent + 99 ) / 100 );
391
392
392
- if (currentSpeedSetting. IsNull () || speedSetting != currentSpeedSetting. Value () )
393
+ if (currentSpeedSetting != speedSetting )
393
394
{
394
395
status = SpeedSetting::Set (attributePath.mEndpointId , speedSetting);
395
396
VerifyOrReturn (Status::Success == status,
@@ -413,33 +414,75 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt
413
414
ChipLogError (Zcl, " Failed to set FanMode to off with error: 0x%02x" , to_underlying (status)));
414
415
}
415
416
416
- // Adjust PercentSetting from a speed value change for SpeedSetting
417
- // percent = floor( speed/SpeedMax * 100 )
418
- uint8_t speedMax;
419
- status = SpeedMax::Get (attributePath.mEndpointId , &speedMax);
420
- VerifyOrReturn (Status::Success == status,
421
- ChipLogError (Zcl, " Failed to get SpeedMax with error: 0x%02x" , to_underlying (status)));
417
+ // Adjust PercentSetting from a speed value change for SpeedSetting only when the SpeedSetting change was received
418
+ // on a write command, not when it was changed by the server or the app logic. This avoids circular logic such as
419
+ // (with a SpeedMax of 10):
420
+ // 1. Client sets the PercetSetting to 25%
421
+ // 2. Server sets the SpeedSetting to 3 through the server callbackm, which sets the PercentSetting to 30%
422
+ // 3. Server sets the PercentSetting to 30% through the server callback
423
+ }
424
+ break ;
425
+ }
426
+ default :
427
+ break ;
428
+ }
429
+ }
422
430
423
- DataModel::Nullable<Percent> currentPercentSetting;
424
- status = PercentSetting::Get (attributePath.mEndpointId , currentPercentSetting);
425
- VerifyOrReturn (Status::Success == status,
426
- ChipLogError (Zcl, " Failed to get PercentSetting with error: 0x%02x" , to_underlying (status)));
431
+ CHIP_ERROR FanControlAttributeAccessInterface::Write (const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder)
432
+ {
433
+ Status status = Status::Success;
434
+ switch (aPath.mAttributeId )
435
+ {
436
+ case SpeedSetting::Id: {
437
+ DataModel::Nullable<uint8_t > speedSetting;
438
+ ReturnErrorOnFailure (aDecoder.Decode (speedSetting));
439
+
440
+ DataModel::Nullable<uint8_t > currentSpeedSetting;
441
+ status = SpeedSetting::Get (aPath.mEndpointId , currentSpeedSetting);
442
+ ReturnLogErrorOnFailure (StatusIB (status).ToChipError ());
427
443
428
- float speed = speedSetting.Value ();
429
- Percent percentSetting = static_cast <Percent>(speed / speedMax * 100 );
444
+ if (speedSetting != currentSpeedSetting)
445
+ {
446
+ status = SpeedSetting::Set (aPath.mEndpointId , speedSetting);
447
+ ReturnLogErrorOnFailure (StatusIB (status).ToChipError ());
448
+ // Skip the last step if we are writing NULL
449
+ VerifyOrReturnValue (!speedSetting.IsNull (), CHIP_NO_ERROR);
430
450
431
- if (currentPercentSetting. IsNull () || percentSetting != currentPercentSetting. Value ( ))
451
+ if (SupportsMultiSpeed (aPath. mEndpointId ))
432
452
{
433
- status = PercentSetting::Set (attributePath.mEndpointId , percentSetting);
434
- VerifyOrReturn (Status::Success == status,
435
- ChipLogError (Zcl, " Failed to set PercentSetting with error: 0x%02x" , to_underlying (status)));
453
+ // If SpeedSetting is set to 0, the server SHALL set the FanMode attribute value to Off.
454
+ if (speedSetting.Value () == 0 )
455
+ {
456
+ status = SetFanModeToOff (aPath.mEndpointId );
457
+ ReturnLogErrorOnFailure (StatusIB (status).ToChipError ());
458
+ }
459
+
460
+ // Adjust PercentSetting from a speed value change for SpeedSetting
461
+ // percent = floor( speed/SpeedMax * 100 )
462
+ uint8_t speedMax;
463
+ status = SpeedMax::Get (aPath.mEndpointId , &speedMax);
464
+ ReturnLogErrorOnFailure (StatusIB (status).ToChipError ());
465
+
466
+ DataModel::Nullable<Percent> currentPercentSetting;
467
+ status = PercentSetting::Get (aPath.mEndpointId , currentPercentSetting);
468
+ ReturnLogErrorOnFailure (StatusIB (status).ToChipError ());
469
+
470
+ float speed = speedSetting.Value ();
471
+ Percent percentSetting = static_cast <Percent>(speed / speedMax * 100 );
472
+
473
+ if (currentPercentSetting != percentSetting)
474
+ {
475
+ status = PercentSetting::Set (aPath.mEndpointId , percentSetting);
476
+ ReturnLogErrorOnFailure (StatusIB (status).ToChipError ());
477
+ }
436
478
}
437
479
}
438
480
break ;
439
481
}
440
482
default :
441
483
break ;
442
484
}
485
+ return CHIP_NO_ERROR;
443
486
}
444
487
445
488
bool emberAfFanControlClusterStepCallback (app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
0 commit comments