Skip to content

Commit 4ab2609

Browse files
committed
Add README and fix migration issues for RelativeHumidityMeasurement cluster
1 parent 5c10a3d commit 4ab2609

File tree

8 files changed

+191
-170
lines changed

8 files changed

+191
-170
lines changed

examples/air-purifier-app/air-purifier-common/include/relative-humidity-sensor-manager.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,7 @@ class RelativeHumiditySensorManager
3030
public:
3131
RelativeHumiditySensorManager(EndpointId aEndpointId) : mEndpointId(aEndpointId){};
3232

33-
void Init()
34-
{
35-
ReturnAndLogOnFailure(RelativeHumidityMeasurement::SetMeasuredValueRange(mEndpointId, DataModel::MakeNullable(uint16_t(0)),
36-
DataModel::MakeNullable(uint16_t(10000))),
37-
NotSpecified, "Failed to set RelativeHumidityMeasurement min/max range");
38-
};
33+
void Init() {};
3934

4035
void OnHumidityChangeHandler(uint16_t newValue)
4136
{

examples/air-quality-sensor-app/air-quality-sensor-common/include/relative-humidity-sensor-manager.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,7 @@ namespace Clusters {
1010
class RelativeHumiditySensorManager
1111
{
1212
public:
13-
RelativeHumiditySensorManager(EndpointId aEndpointId) : mEndpointId(aEndpointId)
14-
{
15-
CHIP_ERROR err = RelativeHumidityMeasurement::SetMeasuredValueRange(mEndpointId, DataModel::MakeNullable<uint16_t>(0),
16-
DataModel::MakeNullable<uint16_t>(100));
17-
VerifyOrReturn(CHIP_NO_ERROR == err,
18-
ChipLogError(NotSpecified, "Failed to set RelativeHumidityMeasurement min/max range: %" CHIP_ERROR_FORMAT,
19-
err.Format()));
20-
};
13+
RelativeHumiditySensorManager(EndpointId aEndpointId) : mEndpointId(aEndpointId) {};
2114

2215
void OnHumidityChangeHandler(uint16_t newValue)
2316
{

src/app/clusters/relative-humidity-measurement-server/CodegenIntegration.cpp

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -43,43 +43,40 @@ class IntegrationDelegate : public CodegenClusterIntegration::Delegate
4343
ServerClusterRegistration & CreateRegistration(EndpointId endpointId, unsigned clusterInstanceIndex,
4444
uint32_t optionalAttributeBits, uint32_t featureMap) override
4545
{
46-
RelativeHumidityMeasurementCluster::OptionalAttributeSet optionalAttributeSet(optionalAttributeBits);
4746
using namespace chip::Protocols::InteractionModel;
4847

4948
// Read default values from the Ember attribute store. Not all apps set
5049
// defaults, so failure is tolerated.
51-
DataModel::Nullable<uint16_t> minMeasuredValue{};
52-
if (MinMeasuredValue::Get(endpointId, minMeasuredValue) != Status::Success)
50+
RelativeHumidityMeasurementCluster::Config config;
51+
52+
if (MinMeasuredValue::Get(endpointId, config.minMeasuredValue) != Status::Success)
5353
{
54-
minMeasuredValue.SetNull();
54+
config.minMeasuredValue.SetNull();
5555
}
5656

57-
DataModel::Nullable<uint16_t> maxMeasuredValue{};
58-
if (MaxMeasuredValue::Get(endpointId, maxMeasuredValue) != Status::Success)
57+
if (MaxMeasuredValue::Get(endpointId, config.maxMeasuredValue) != Status::Success)
5958
{
60-
maxMeasuredValue.SetNull();
59+
config.maxMeasuredValue.SetNull();
6160
}
6261

6362
// If both values are non-null but form an invalid range (e.g. ZAP defaults of 0/0),
6463
// treat both as null rather than crashing.
65-
if (!minMeasuredValue.IsNull() && !maxMeasuredValue.IsNull() && maxMeasuredValue.Value() < minMeasuredValue.Value() + 1)
64+
if (!config.minMeasuredValue.IsNull() && !config.maxMeasuredValue.IsNull() &&
65+
config.maxMeasuredValue.Value() < config.minMeasuredValue.Value() + 1)
6666
{
67-
minMeasuredValue.SetNull();
68-
maxMeasuredValue.SetNull();
67+
config.minMeasuredValue.SetNull();
68+
config.maxMeasuredValue.SetNull();
6969
}
7070

71-
uint16_t tolerance{};
71+
RelativeHumidityMeasurementCluster::OptionalAttributeSet optionalAttributeSet(optionalAttributeBits);
7272
if (optionalAttributeSet.IsSet(Tolerance::Id))
7373
{
74+
uint16_t tolerance{};
7475
VerifyOrDie(Tolerance::Get(endpointId, &tolerance) == Status::Success);
76+
config.WithTolerance(tolerance);
7577
}
7678

77-
gServers[clusterInstanceIndex].Create(endpointId, optionalAttributeSet,
78-
RelativeHumidityMeasurementCluster::StartupConfiguration{
79-
.minMeasuredValue = minMeasuredValue,
80-
.maxMeasuredValue = maxMeasuredValue,
81-
.tolerance = tolerance,
82-
});
79+
gServers[clusterInstanceIndex].Create(endpointId, config);
8380
return gServers[clusterInstanceIndex].Registration();
8481
}
8582

@@ -149,12 +146,5 @@ CHIP_ERROR SetMeasuredValue(EndpointId endpointId, DataModel::Nullable<uint16_t>
149146
return cluster->SetMeasuredValue(measuredValue);
150147
}
151148

152-
CHIP_ERROR SetMeasuredValueRange(EndpointId endpointId, DataModel::Nullable<uint16_t> minMeasuredValue,
153-
DataModel::Nullable<uint16_t> maxMeasuredValue)
154-
{
155-
auto * cluster = FindClusterOnEndpoint(endpointId);
156-
VerifyOrReturnError(cluster != nullptr, CHIP_ERROR_NOT_FOUND);
157-
return cluster->SetMeasuredValueRange(minMeasuredValue, maxMeasuredValue);
158-
}
159149

160150
} // namespace chip::app::Clusters::RelativeHumidityMeasurement

src/app/clusters/relative-humidity-measurement-server/CodegenIntegration.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,5 @@ RelativeHumidityMeasurementCluster * FindClusterOnEndpoint(EndpointId endpointId
2828
/// Convenience helper — pushes a new measured value to the cluster on the given endpoint.
2929
CHIP_ERROR SetMeasuredValue(EndpointId endpointId, DataModel::Nullable<uint16_t> measuredValue);
3030

31-
/// Convenience helper — updates the min/max measured value range on the given endpoint.
32-
CHIP_ERROR SetMeasuredValueRange(EndpointId endpointId, DataModel::Nullable<uint16_t> minMeasuredValue,
33-
DataModel::Nullable<uint16_t> maxMeasuredValue);
3431

3532
} // namespace chip::app::Clusters::RelativeHumidityMeasurement
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Relative Humidity Measurement Cluster
2+
3+
This cluster uses the code-driven approach. The Ember attribute accessors for
4+
`MeasuredValue`, `MinMeasuredValue`, `MaxMeasuredValue`, and `Tolerance` are no
5+
longer available.
6+
7+
## Setting a new humidity reading
8+
9+
### BEFORE (using Ember accessors)
10+
11+
```cpp
12+
RelativeHumidityMeasurement::Attributes::MeasuredValue::Set(endpointId, newValue);
13+
```
14+
15+
### NOW (code-driven)
16+
17+
```cpp
18+
CHIP_ERROR err = RelativeHumidityMeasurement::SetMeasuredValue(endpointId,
19+
DataModel::MakeNullable(uint16_t(newValue)));
20+
if (err != CHIP_NO_ERROR)
21+
{
22+
// handle error
23+
}
24+
```
25+
26+
## Configuring min/max range and tolerance
27+
28+
`MinMeasuredValue`, `MaxMeasuredValue`, and `Tolerance` are fixed hardware
29+
characteristics. They are configured once at startup via the `Config` struct and
30+
cannot be changed at runtime.
31+
32+
The default values are read from the ZAP-configured Ember attribute store at
33+
init time. If your app needs specific values, configure them in the ZAP file
34+
(`.zap`) for the endpoint.
35+
36+
If you need to set them programmatically (e.g. in tests or for dynamic
37+
endpoints), pass a `Config` at construction time:
38+
39+
```cpp
40+
// Min/max only
41+
RelativeHumidityMeasurementCluster::Config config;
42+
config.minMeasuredValue = DataModel::MakeNullable(uint16_t(0));
43+
config.maxMeasuredValue = DataModel::MakeNullable(uint16_t(10000));
44+
auto cluster = RelativeHumidityMeasurementCluster(endpointId, config);
45+
46+
// With optional Tolerance attribute
47+
RelativeHumidityMeasurementCluster::Config config;
48+
config.minMeasuredValue = DataModel::MakeNullable(uint16_t(0));
49+
config.maxMeasuredValue = DataModel::MakeNullable(uint16_t(10000));
50+
config.WithTolerance(100);
51+
auto cluster = RelativeHumidityMeasurementCluster(endpointId, config);
52+
```
53+
54+
### BEFORE (using Ember accessors)
55+
56+
```cpp
57+
RelativeHumidityMeasurement::Attributes::MinMeasuredValue::Set(endpointId, 0);
58+
RelativeHumidityMeasurement::Attributes::MaxMeasuredValue::Set(endpointId, 10000);
59+
```

src/app/clusters/relative-humidity-measurement-server/RelativeHumidityMeasurementCluster.cpp

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,37 @@ namespace chip::app::Clusters {
2424

2525
using namespace RelativeHumidityMeasurement::Attributes;
2626

27-
// Per the Matter spec (Relative Humidity Measurement cluster):
28-
// MinMeasuredValue is constrained to [0, 9999]
27+
// Spec-defined upper bound for MinMeasuredValue
2928
constexpr uint16_t kMinMeasuredValueMax = 9999;
30-
// Global ceiling for any measured humidity value (applies to MeasuredValue and MaxMeasuredValue)
29+
// Spec-defined upper bound for MeasuredValue and MaxMeasuredValue
3130
constexpr uint16_t kMeasuredValueMax = 10000;
31+
// Spec-defined upper bound for Tolerance
32+
constexpr uint16_t kMaxTolerance = 2048;
3233

33-
RelativeHumidityMeasurementCluster::RelativeHumidityMeasurementCluster(EndpointId endpointId,
34-
const OptionalAttributeSet & optionalAttributeSet,
35-
const StartupConfiguration & config) :
34+
RelativeHumidityMeasurementCluster::RelativeHumidityMeasurementCluster(EndpointId endpointId, const Config & config) :
3635
DefaultServerCluster({ endpointId, RelativeHumidityMeasurement::Id }),
37-
mOptionalAttributeSet(optionalAttributeSet)
36+
mOptionalAttributeSet(config.mOptionalAttributeSet)
3837
{
38+
if (!config.minMeasuredValue.IsNull())
39+
{
40+
VerifyOrDie(config.minMeasuredValue.Value() <= kMinMeasuredValueMax);
41+
42+
if (!config.maxMeasuredValue.IsNull())
43+
{
44+
VerifyOrDie(config.maxMeasuredValue.Value() >= config.minMeasuredValue.Value() + 1);
45+
}
46+
}
47+
48+
if (!config.maxMeasuredValue.IsNull())
49+
{
50+
VerifyOrDie(config.maxMeasuredValue.Value() <= kMeasuredValueMax);
51+
}
52+
53+
VerifyOrDie(!mOptionalAttributeSet.IsSet(Tolerance::Id) || config.mTolerance <= kMaxTolerance);
54+
3955
mMinMeasuredValue = config.minMeasuredValue;
4056
mMaxMeasuredValue = config.maxMeasuredValue;
41-
mTolerance = config.tolerance;
57+
mTolerance = config.mTolerance;
4258
}
4359

4460
DataModel::ActionReturnStatus RelativeHumidityMeasurementCluster::ReadAttribute(const DataModel::ReadAttributeRequest & request,
@@ -96,27 +112,4 @@ CHIP_ERROR RelativeHumidityMeasurementCluster::SetMeasuredValue(DataModel::Nulla
96112
return CHIP_NO_ERROR;
97113
}
98114

99-
CHIP_ERROR RelativeHumidityMeasurementCluster::SetMeasuredValueRange(DataModel::Nullable<uint16_t> minMeasuredValue,
100-
DataModel::Nullable<uint16_t> maxMeasuredValue)
101-
{
102-
if (!minMeasuredValue.IsNull())
103-
{
104-
VerifyOrReturnError(minMeasuredValue.Value() <= kMinMeasuredValueMax, CHIP_IM_GLOBAL_STATUS(ConstraintError));
105-
106-
if (!maxMeasuredValue.IsNull())
107-
{
108-
VerifyOrReturnError(maxMeasuredValue.Value() >= minMeasuredValue.Value() + 1, CHIP_IM_GLOBAL_STATUS(ConstraintError));
109-
}
110-
}
111-
112-
if (!maxMeasuredValue.IsNull())
113-
{
114-
VerifyOrReturnError(maxMeasuredValue.Value() <= kMeasuredValueMax, CHIP_IM_GLOBAL_STATUS(ConstraintError));
115-
}
116-
117-
SetAttributeValue(mMinMeasuredValue, minMeasuredValue, MinMeasuredValue::Id);
118-
SetAttributeValue(mMaxMeasuredValue, maxMeasuredValue, MaxMeasuredValue::Id);
119-
return CHIP_NO_ERROR;
120-
}
121-
122115
} // namespace chip::app::Clusters

src/app/clusters/relative-humidity-measurement-server/RelativeHumidityMeasurementCluster.h

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,47 @@
2424

2525
namespace chip::app::Clusters {
2626

27-
class RelativeHumidityMeasurementCluster : public DefaultServerCluster
27+
class RelativeHumidityMeasurementCluster;
28+
29+
// Fixed configuration for RelativeHumidityMeasurementCluster. MinMeasuredValue,
30+
// MaxMeasuredValue, and Tolerance reflect hardware characteristics and do not
31+
// change at runtime. Use WithTolerance() to enable the optional Tolerance
32+
// attribute — this ensures both the value and the attribute presence flag are
33+
// always set together.
34+
class RelativeHumidityMeasurementConfig
2835
{
2936
public:
30-
using OptionalAttributeSet = app::OptionalAttributeSet<RelativeHumidityMeasurement::Attributes::Tolerance::Id>;
37+
DataModel::Nullable<uint16_t> minMeasuredValue{};
38+
DataModel::Nullable<uint16_t> maxMeasuredValue{};
3139

32-
struct StartupConfiguration
40+
RelativeHumidityMeasurementConfig & WithTolerance(uint16_t value)
3341
{
34-
DataModel::Nullable<uint16_t> minMeasuredValue{};
35-
DataModel::Nullable<uint16_t> maxMeasuredValue{};
36-
uint16_t tolerance{};
37-
};
42+
mTolerance = value;
43+
mOptionalAttributeSet.template Set<RelativeHumidityMeasurement::Attributes::Tolerance::Id>();
44+
return *this;
45+
}
46+
47+
private:
48+
friend class RelativeHumidityMeasurementCluster;
49+
app::OptionalAttributeSet<RelativeHumidityMeasurement::Attributes::Tolerance::Id> mOptionalAttributeSet{};
50+
uint16_t mTolerance{};
51+
};
52+
53+
class RelativeHumidityMeasurementCluster : public DefaultServerCluster
54+
{
55+
public:
56+
using OptionalAttributeSet = app::OptionalAttributeSet<RelativeHumidityMeasurement::Attributes::Tolerance::Id>;
57+
using Config = RelativeHumidityMeasurementConfig;
3858

39-
RelativeHumidityMeasurementCluster(EndpointId endpointId, const OptionalAttributeSet & optionalAttributeSet,
40-
const StartupConfiguration & config);
59+
RelativeHumidityMeasurementCluster(EndpointId endpointId, const Config & config = {});
4160

4261
// ServerClusterInterface implementation
4362
DataModel::ActionReturnStatus ReadAttribute(const DataModel::ReadAttributeRequest & request,
4463
AttributeValueEncoder & encoder) override;
4564
CHIP_ERROR Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder<DataModel::AttributeEntry> & builder) override;
4665

47-
// Setters — intended for application use to push new sensor readings
66+
// Setter — intended for application use to push new sensor readings
4867
CHIP_ERROR SetMeasuredValue(DataModel::Nullable<uint16_t> measuredValue);
49-
CHIP_ERROR SetMeasuredValueRange(DataModel::Nullable<uint16_t> minMeasuredValue,
50-
DataModel::Nullable<uint16_t> maxMeasuredValue);
5168

5269
// Getters
5370
DataModel::Nullable<uint16_t> GetMeasuredValue() const { return mMeasuredValue; }

0 commit comments

Comments
 (0)