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>
@@ -50,6 +51,8 @@ static_assert(kFanControlDelegateTableSize <= kEmberInvalidEndpointIndex, "FanCo
50
51
51
52
Delegate * gDelegateTable [kFanControlDelegateTableSize ] = { nullptr };
52
53
54
+ FanControlAttributeAccessInterface gFanControlAttributeAccess ;
55
+
53
56
} // anonymous namespace
54
57
55
58
namespace chip {
@@ -413,33 +416,75 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt
413
416
ChipLogError (Zcl, " Failed to set FanMode to off with error: 0x%02x" , to_underlying (status)));
414
417
}
415
418
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)));
419
+ // Adjust PercentSetting from a speed value change for SpeedSetting only when the SpeedSetting change was received
420
+ // on a write command, not when it was changed by the server or the app logic. This avoids circular logic such as
421
+ // (with a SpeedMax of 10):
422
+ // 1. Client sets the PercetSetting to 25%
423
+ // 2. Server sets the SpeedSetting to 3 through the server callbackm, which sets the PercentSetting to 30%
424
+ // 3. Server sets the PercentSetting to 30% through the server callback
425
+ }
426
+ break ;
427
+ }
428
+ default :
429
+ break ;
430
+ }
431
+ }
422
432
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)));
433
+ CHIP_ERROR FanControlAttributeAccessInterface::Write (const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder)
434
+ {
435
+ Status status = Status::Success;
436
+ switch (aPath.mAttributeId )
437
+ {
438
+ case SpeedSetting::Id: {
439
+ DataModel::Nullable<uint8_t > speedSetting;
440
+ ReturnErrorOnFailure (aDecoder.Decode (speedSetting));
427
441
428
- float speed = speedSetting.Value ();
429
- Percent percentSetting = static_cast <Percent>(speed / speedMax * 100 );
442
+ DataModel::Nullable<uint8_t > currentSpeedSetting;
443
+ status = SpeedSetting::Get (aPath.mEndpointId , currentSpeedSetting);
444
+ ReturnLogErrorOnFailure (StatusIB (status).ToChipError ());
430
445
431
- if (currentPercentSetting.IsNull () || percentSetting != currentPercentSetting.Value ())
446
+ if (speedSetting != currentSpeedSetting)
447
+ {
448
+ status = SpeedSetting::Set (aPath.mEndpointId , speedSetting);
449
+ ReturnLogErrorOnFailure (StatusIB (status).ToChipError ());
450
+ // Skip the last step if we are writing NULL
451
+ VerifyOrReturnValue (!speedSetting.IsNull (), CHIP_NO_ERROR);
452
+
453
+ if (SupportsMultiSpeed (aPath.mEndpointId ))
432
454
{
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)));
455
+ // If SpeedSetting is set to 0, the server SHALL set the FanMode attribute value to Off.
456
+ if (speedSetting.Value () == 0 )
457
+ {
458
+ status = SetFanModeToOff (aPath.mEndpointId );
459
+ ReturnLogErrorOnFailure (StatusIB (status).ToChipError ());
460
+ }
461
+
462
+ // Adjust PercentSetting from a speed value change for SpeedSetting
463
+ // percent = floor( speed/SpeedMax * 100 )
464
+ uint8_t speedMax;
465
+ status = SpeedMax::Get (aPath.mEndpointId , &speedMax);
466
+ ReturnLogErrorOnFailure (StatusIB (status).ToChipError ());
467
+
468
+ DataModel::Nullable<Percent> currentPercentSetting;
469
+ status = PercentSetting::Get (aPath.mEndpointId , currentPercentSetting);
470
+ ReturnLogErrorOnFailure (StatusIB (status).ToChipError ());
471
+
472
+ float speed = speedSetting.Value ();
473
+ Percent percentSetting = static_cast <Percent>(speed / speedMax * 100 );
474
+
475
+ if (currentPercentSetting.IsNull () || percentSetting != currentPercentSetting.Value ())
476
+ {
477
+ status = PercentSetting::Set (aPath.mEndpointId , percentSetting);
478
+ ReturnLogErrorOnFailure (StatusIB (status).ToChipError ());
479
+ }
436
480
}
437
481
}
438
482
break ;
439
483
}
440
484
default :
441
485
break ;
442
486
}
487
+ return CHIP_NO_ERROR;
443
488
}
444
489
445
490
bool emberAfFanControlClusterStepCallback (app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
@@ -477,3 +522,8 @@ bool emberAfFanControlClusterStepCallback(app::CommandHandler * commandObj, cons
477
522
commandObj->AddStatus (commandPath, status);
478
523
return true ;
479
524
}
525
+
526
+ void MatterFanControlPluginServerInitCallback ()
527
+ {
528
+ AttributeAccessInterfaceRegistry::Instance ().Register (&gFanControlAttributeAccess );
529
+ }
0 commit comments