31
31
#include < lib/core/CHIPEncoding.h>
32
32
33
33
using namespace chip ;
34
+ using namespace chip ::app;
35
+ using namespace chip ::app::Clusters;
34
36
using namespace chip ::app::Clusters::Thermostat;
35
37
using namespace chip ::app::Clusters::Thermostat::Attributes;
36
38
39
+ using imcode = Protocols::InteractionModel::Status;
40
+
37
41
constexpr int16_t kDefaultAbsMinHeatSetpointLimit = 700 ; // 7C (44.5 F) is the default
38
42
constexpr int16_t kDefaultAbsMaxHeatSetpointLimit = 3000 ; // 30C (86 F) is the default
39
43
constexpr int16_t kDefaultMinHeatSetpointLimit = 700 ; // 7C (44.5 F) is the default
@@ -62,6 +66,90 @@ constexpr int8_t kDefaultDeadBand = 25; // 2.5C is the default
62
66
63
67
#define FEATURE_MAP_DEFAULT FEATURE_MAP_HEAT | FEATURE_MAP_COOL | FEATURE_MAP_AUTO
64
68
69
+ namespace {
70
+
71
+ class ThermostatAttrAccess : public AttributeAccessInterface
72
+ {
73
+ public:
74
+ ThermostatAttrAccess () : AttributeAccessInterface(Optional<EndpointId>::Missing(), Thermostat::Id) {}
75
+
76
+ CHIP_ERROR Read (const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override ;
77
+ CHIP_ERROR Write (const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) override ;
78
+ };
79
+
80
+ ThermostatAttrAccess gThermostatAttrAccess ;
81
+
82
+ CHIP_ERROR ThermostatAttrAccess::Read (const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
83
+ {
84
+ VerifyOrDie (aPath.mClusterId == Thermostat::Id);
85
+
86
+ uint32_t ourFeatureMap;
87
+ bool localTemperatureNotExposedSupported = (FeatureMap::Get (aPath.mEndpointId , &ourFeatureMap) == EMBER_ZCL_STATUS_SUCCESS) &&
88
+ ((ourFeatureMap & to_underlying (Feature::kLocalTemperatureNotExposed )) != 0 );
89
+
90
+ switch (aPath.mAttributeId )
91
+ {
92
+ case LocalTemperature::Id:
93
+ if (localTemperatureNotExposedSupported)
94
+ {
95
+ return aEncoder.EncodeNull ();
96
+ }
97
+ break ;
98
+ case RemoteSensing::Id:
99
+ if (localTemperatureNotExposedSupported)
100
+ {
101
+ uint8_t valueRemoteSensing;
102
+ EmberAfStatus status = RemoteSensing::Get (aPath.mEndpointId , &valueRemoteSensing);
103
+ if (status != EMBER_ZCL_STATUS_SUCCESS)
104
+ {
105
+ StatusIB statusIB (ToInteractionModelStatus (status));
106
+ return statusIB.ToChipError ();
107
+ }
108
+ valueRemoteSensing &= 0xFE ; // clear bit 1 (LocalTemperature RemoteSensing bit)
109
+ return aEncoder.Encode (valueRemoteSensing);
110
+ }
111
+ break ;
112
+ default : // return CHIP_NO_ERROR and just read from the attribute store in default
113
+ break ;
114
+ }
115
+
116
+ return CHIP_NO_ERROR;
117
+ }
118
+
119
+ CHIP_ERROR ThermostatAttrAccess::Write (const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder)
120
+ {
121
+ VerifyOrDie (aPath.mClusterId == Thermostat::Id);
122
+
123
+ uint32_t ourFeatureMap;
124
+ bool localTemperatureNotExposedSupported = (FeatureMap::Get (aPath.mEndpointId , &ourFeatureMap) == EMBER_ZCL_STATUS_SUCCESS) &&
125
+ ((ourFeatureMap & to_underlying (Feature::kLocalTemperatureNotExposed )) != 0 );
126
+
127
+ switch (aPath.mAttributeId )
128
+ {
129
+ case RemoteSensing::Id:
130
+ if (localTemperatureNotExposedSupported)
131
+ {
132
+ uint8_t valueRemoteSensing;
133
+ ReturnErrorOnFailure (aDecoder.Decode (valueRemoteSensing));
134
+ if (valueRemoteSensing & 0x01 ) // If setting bit 1 (LocalTemperature RemoteSensing bit)
135
+ {
136
+ return CHIP_IM_GLOBAL_STATUS (ConstraintError);
137
+ }
138
+
139
+ EmberAfStatus status = RemoteSensing::Set (aPath.mEndpointId , valueRemoteSensing);
140
+ StatusIB statusIB (ToInteractionModelStatus (status));
141
+ return statusIB.ToChipError ();
142
+ }
143
+ break ;
144
+ default : // return CHIP_NO_ERROR and just write to the attribute store in default
145
+ break ;
146
+ }
147
+
148
+ return CHIP_NO_ERROR;
149
+ }
150
+
151
+ } // anonymous namespace
152
+
65
153
void emberAfThermostatClusterServerInitCallback (chip::EndpointId endpoint)
66
154
{
67
155
// TODO
@@ -78,8 +166,6 @@ void emberAfThermostatClusterServerInitCallback(chip::EndpointId endpoint)
78
166
// or should this just be the responsibility of the thermostat application?
79
167
}
80
168
81
- using imcode = Protocols::InteractionModel::Status;
82
-
83
169
Protocols::InteractionModel::Status
84
170
MatterThermostatClusterServerPreAttributeChangedCallback (const app::ConcreteAttributePath & attributePath,
85
171
EmberAfAttributeType attributeType, uint16_t size, uint8_t * value)
@@ -754,4 +840,7 @@ bool emberAfThermostatClusterSetpointRaiseLowerCallback(app::CommandHandler * co
754
840
return true ;
755
841
}
756
842
757
- void MatterThermostatPluginServerInitCallback () {}
843
+ void MatterThermostatPluginServerInitCallback ()
844
+ {
845
+ registerAttributeAccessOverride (&gThermostatAttrAccess );
846
+ }
0 commit comments