Skip to content

Commit 96ee61e

Browse files
tehampsonrestyled-commitsandy31415
authored
Add fabric scoping to ECOINFO cluster attributes (project-chip#35022)
--------- Co-authored-by: Restyled.io <commits@restyled.io> Co-authored-by: Andrei Litvin <andy314@gmail.com>
1 parent c4a5a95 commit 96ee61e

File tree

2 files changed

+47
-33
lines changed

2 files changed

+47
-33
lines changed

src/app/clusters/ecosystem-information-server/ecosystem-information-server.cpp

+23-17
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,13 @@ EcosystemDeviceStruct::Builder & EcosystemDeviceStruct::Builder::AddUniqueLocati
128128
return *this;
129129
}
130130

131+
EcosystemDeviceStruct::Builder & EcosystemDeviceStruct::Builder::SetFabricIndex(FabricIndex aFabricIndex)
132+
{
133+
VerifyOrDie(!mIsAlreadyBuilt);
134+
mFabricIndex = aFabricIndex;
135+
return *this;
136+
}
137+
131138
std::unique_ptr<EcosystemDeviceStruct> EcosystemDeviceStruct::Builder::Build()
132139
{
133140
VerifyOrReturnValue(!mIsAlreadyBuilt, nullptr, ChipLogError(Zcl, "Build() already called"));
@@ -136,6 +143,8 @@ std::unique_ptr<EcosystemDeviceStruct> EcosystemDeviceStruct::Builder::Build()
136143
VerifyOrReturnValue(!mDeviceTypes.empty(), nullptr, ChipLogError(Zcl, "No device types added"));
137144
VerifyOrReturnValue(mUniqueLocationIds.size() <= kUniqueLocationIdsListMaxSize, nullptr,
138145
ChipLogError(Zcl, "Too many location ids"));
146+
VerifyOrReturnValue(mFabricIndex >= kMinValidFabricIndex, nullptr, ChipLogError(Zcl, "Fabric index is invalid"));
147+
VerifyOrReturnValue(mFabricIndex <= kMaxValidFabricIndex, nullptr, ChipLogError(Zcl, "Fabric index is invalid"));
139148

140149
for (auto & locationId : mUniqueLocationIds)
141150
{
@@ -145,12 +154,12 @@ std::unique_ptr<EcosystemDeviceStruct> EcosystemDeviceStruct::Builder::Build()
145154
// std::make_unique does not have access to private constructor we workaround with using new
146155
std::unique_ptr<EcosystemDeviceStruct> ret{ new EcosystemDeviceStruct(
147156
std::move(mDeviceName), mDeviceNameLastEditEpochUs, mBridgedEndpoint, mOriginalEndpoint, std::move(mDeviceTypes),
148-
std::move(mUniqueLocationIds), mUniqueLocationIdsLastEditEpochUs) };
157+
std::move(mUniqueLocationIds), mUniqueLocationIdsLastEditEpochUs, mFabricIndex) };
149158
mIsAlreadyBuilt = true;
150159
return ret;
151160
}
152161

153-
CHIP_ERROR EcosystemDeviceStruct::Encode(const AttributeValueEncoder::ListEncodeHelper & aEncoder, const FabricIndex & aFabricIndex)
162+
CHIP_ERROR EcosystemDeviceStruct::Encode(const AttributeValueEncoder::ListEncodeHelper & aEncoder)
154163
{
155164
Structs::EcosystemDeviceStruct::Type deviceStruct;
156165
if (!mDeviceName.empty())
@@ -172,9 +181,7 @@ CHIP_ERROR EcosystemDeviceStruct::Encode(const AttributeValueEncoder::ListEncode
172181
deviceStruct.uniqueLocationIDs = DataModel::List<CharSpan>(locationIds.data(), locationIds.size());
173182

174183
deviceStruct.uniqueLocationIDsLastEdit = mUniqueLocationIdsLastEditEpochUs;
175-
176-
// TODO(#33223) this is a hack, use mFabricIndex when it exists.
177-
deviceStruct.SetFabricIndex(aFabricIndex);
184+
deviceStruct.SetFabricIndex(mFabricIndex);
178185
return aEncoder.Encode(deviceStruct);
179186
}
180187

@@ -226,12 +233,9 @@ CHIP_ERROR EcosystemLocationStruct::Encode(const AttributeValueEncoder::ListEnco
226233
const std::string & aUniqueLocationId, const FabricIndex & aFabricIndex)
227234
{
228235
Structs::EcosystemLocationStruct::Type locationStruct;
229-
VerifyOrDie(!aUniqueLocationId.empty());
230236
locationStruct.uniqueLocationID = CharSpan(aUniqueLocationId.c_str(), aUniqueLocationId.size());
231237
locationStruct.locationDescriptor = GetEncodableLocationDescriptorStruct(mLocationDescriptor);
232238
locationStruct.locationDescriptorLastEdit = mLocationDescriptorLastEditEpochUs;
233-
234-
// TODO(#33223) this is a hack, use mFabricIndex when it exists.
235239
locationStruct.SetFabricIndex(aFabricIndex);
236240
return aEncoder.Encode(locationStruct);
237241
}
@@ -266,16 +270,20 @@ CHIP_ERROR EcosystemInformationServer::AddDeviceInfo(EndpointId aEndpoint, std::
266270
}
267271

268272
CHIP_ERROR EcosystemInformationServer::AddLocationInfo(EndpointId aEndpoint, const std::string & aLocationId,
269-
std::unique_ptr<EcosystemLocationStruct> aLocation)
273+
FabricIndex aFabricIndex, std::unique_ptr<EcosystemLocationStruct> aLocation)
270274
{
271275
VerifyOrReturnError(aLocation, CHIP_ERROR_INVALID_ARGUMENT);
272276
VerifyOrReturnError((aEndpoint != kRootEndpointId && aEndpoint != kInvalidEndpointId), CHIP_ERROR_INVALID_ARGUMENT);
277+
VerifyOrReturnError(!aLocationId.empty(), CHIP_ERROR_INVALID_ARGUMENT);
278+
VerifyOrReturnError(aFabricIndex >= kMinValidFabricIndex, CHIP_ERROR_INVALID_ARGUMENT);
279+
VerifyOrReturnError(aFabricIndex <= kMaxValidFabricIndex, CHIP_ERROR_INVALID_ARGUMENT);
273280

274-
auto & deviceInfo = mDevicesMap[aEndpoint];
275-
VerifyOrReturnError((deviceInfo.mLocationDirectory.find(aLocationId) == deviceInfo.mLocationDirectory.end()),
281+
auto & deviceInfo = mDevicesMap[aEndpoint];
282+
EcosystemLocationKey key = { .mUniqueLocationId = aLocationId, .mFabricIndex = aFabricIndex };
283+
VerifyOrReturnError((deviceInfo.mLocationDirectory.find(key) == deviceInfo.mLocationDirectory.end()),
276284
CHIP_ERROR_INVALID_ARGUMENT);
277285
VerifyOrReturnError((deviceInfo.mLocationDirectory.size() < kLocationDirectoryMaxSize), CHIP_ERROR_NO_MEMORY);
278-
deviceInfo.mLocationDirectory[aLocationId] = std::move(aLocation);
286+
deviceInfo.mLocationDirectory[key] = std::move(aLocation);
279287
return CHIP_NO_ERROR;
280288
}
281289

@@ -352,11 +360,10 @@ CHIP_ERROR EcosystemInformationServer::EncodeDeviceDirectoryAttribute(EndpointId
352360
return aEncoder.EncodeEmptyList();
353361
}
354362

355-
FabricIndex fabricIndex = aEncoder.AccessingFabricIndex();
356363
return aEncoder.EncodeList([&](const auto & encoder) -> CHIP_ERROR {
357364
for (auto & device : deviceInfo.mDeviceDirectory)
358365
{
359-
ReturnErrorOnFailure(device->Encode(encoder, fabricIndex));
366+
ReturnErrorOnFailure(device->Encode(encoder));
360367
}
361368
return CHIP_NO_ERROR;
362369
});
@@ -379,11 +386,10 @@ CHIP_ERROR EcosystemInformationServer::EncodeLocationStructAttribute(EndpointId
379386
return aEncoder.EncodeEmptyList();
380387
}
381388

382-
FabricIndex fabricIndex = aEncoder.AccessingFabricIndex();
383389
return aEncoder.EncodeList([&](const auto & encoder) -> CHIP_ERROR {
384-
for (auto & [id, device] : deviceInfo.mLocationDirectory)
390+
for (auto & [key, device] : deviceInfo.mLocationDirectory)
385391
{
386-
ReturnErrorOnFailure(device->Encode(encoder, id, fabricIndex));
392+
ReturnErrorOnFailure(device->Encode(encoder, key.mUniqueLocationId, key.mFabricIndex));
387393
}
388394
return CHIP_NO_ERROR;
389395
});

src/app/clusters/ecosystem-information-server/ecosystem-information-server.h

+24-16
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class EcosystemDeviceStruct
4949
Builder & SetOriginalEndpoint(EndpointId aOriginalEndpoint);
5050
Builder & AddDeviceType(Structs::DeviceTypeStruct::Type aDeviceType);
5151
Builder & AddUniqueLocationId(std::string aUniqueLocationId, uint64_t aUniqueLocationIdsLastEditEpochUs);
52+
Builder & SetFabricIndex(FabricIndex aFabricIndex);
5253

5354
// Upon success this object will have moved all ownership of underlying
5455
// types to EcosystemDeviceStruct and should not be used afterwards.
@@ -62,21 +63,25 @@ class EcosystemDeviceStruct
6263
std::vector<Structs::DeviceTypeStruct::Type> mDeviceTypes;
6364
std::vector<std::string> mUniqueLocationIds;
6465
uint64_t mUniqueLocationIdsLastEditEpochUs = 0;
66+
FabricIndex mFabricIndex = kUndefinedFabricIndex;
6567
bool mIsAlreadyBuilt = false;
6668
};
6769

68-
CHIP_ERROR Encode(const AttributeValueEncoder::ListEncodeHelper & aEncoder, const FabricIndex & aFabricIndex);
70+
CHIP_ERROR Encode(const AttributeValueEncoder::ListEncodeHelper & aEncoder);
6971

7072
private:
7173
// Constructor is intentionally private. This is to ensure that it is only constructed with
7274
// values that conform to the spec.
7375
explicit EcosystemDeviceStruct(std::string && aDeviceName, uint64_t aDeviceNameLastEditEpochUs, EndpointId aBridgedEndpoint,
7476
EndpointId aOriginalEndpoint, std::vector<Structs::DeviceTypeStruct::Type> && aDeviceTypes,
75-
std::vector<std::string> && aUniqueLocationIds, uint64_t aUniqueLocationIdsLastEditEpochUs) :
77+
std::vector<std::string> && aUniqueLocationIds, uint64_t aUniqueLocationIdsLastEditEpochUs,
78+
FabricIndex aFabricIndex) :
7679
mDeviceName(std::move(aDeviceName)),
7780
mDeviceNameLastEditEpochUs(aDeviceNameLastEditEpochUs), mBridgedEndpoint(aBridgedEndpoint),
7881
mOriginalEndpoint(aOriginalEndpoint), mDeviceTypes(std::move(aDeviceTypes)),
79-
mUniqueLocationIds(std::move(aUniqueLocationIds)), mUniqueLocationIdsLastEditEpochUs(aUniqueLocationIdsLastEditEpochUs)
82+
mUniqueLocationIds(std::move(aUniqueLocationIds)), mUniqueLocationIdsLastEditEpochUs(aUniqueLocationIdsLastEditEpochUs),
83+
mFabricIndex(aFabricIndex)
84+
8085
{}
8186

8287
const std::string mDeviceName;
@@ -86,10 +91,7 @@ class EcosystemDeviceStruct
8691
std::vector<Structs::DeviceTypeStruct::Type> mDeviceTypes;
8792
std::vector<std::string> mUniqueLocationIds;
8893
uint64_t mUniqueLocationIdsLastEditEpochUs;
89-
// TODO(#33223) This structure needs to contain fabric index to be spec compliant.
90-
// To keep initial PR smaller, we are going to assume that all entries
91-
// here are for any fabric. This will allow follow up PR introducing
92-
// fabric scoped to be more throughly reviewed with focus on fabric scoping.
94+
FabricIndex mFabricIndex;
9395
};
9496

9597
struct LocationDescriptorStruct
@@ -134,15 +136,11 @@ class EcosystemLocationStruct
134136
mLocationDescriptor(aLocationDescriptor), mLocationDescriptorLastEditEpochUs(aLocationDescriptorLastEditEpochUs)
135137
{}
136138
// EcosystemLocationStruct is used as a value in a key-value map.
137-
// Because UniqueLocationId is manditory when an entry exist, and
138-
// it is unique, we use it as a key to the key-value pair and is why it is
139+
// Because UniqueLocationId and FabricIndex are mandatory when an entry exist,
140+
// and needs to be unique, we use it as a key to the key-value pair and is why it is
139141
// not explicitly in this struct.
140142
LocationDescriptorStruct mLocationDescriptor;
141143
uint64_t mLocationDescriptorLastEditEpochUs;
142-
// TODO(#33223) This structure needs to contain fabric index to be spec compliant.
143-
// To keep initial PR smaller, we are going to assume that all entries
144-
// here are for any fabric. This will allow follow up PR introducing
145-
// fabric scoped to be more throughly reviewed with focus on fabric scoping.
146144
};
147145

148146
class EcosystemInformationServer
@@ -186,7 +184,7 @@ class EcosystemInformationServer
186184
* @return #CHIP_NO_ERROR on success.
187185
* @return Other CHIP_ERROR associated with issue.
188186
*/
189-
CHIP_ERROR AddLocationInfo(EndpointId aEndpoint, const std::string & aLocationId,
187+
CHIP_ERROR AddLocationInfo(EndpointId aEndpoint, const std::string & aLocationId, FabricIndex aFabricIndex,
190188
std::unique_ptr<EcosystemLocationStruct> aLocation);
191189

192190
/**
@@ -203,12 +201,22 @@ class EcosystemInformationServer
203201
CHIP_ERROR ReadAttribute(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder);
204202

205203
private:
204+
struct EcosystemLocationKey
205+
{
206+
bool operator<(const EcosystemLocationKey & other) const
207+
{
208+
return mUniqueLocationId < other.mUniqueLocationId ||
209+
(mUniqueLocationId == other.mUniqueLocationId && mFabricIndex < other.mFabricIndex);
210+
}
211+
std::string mUniqueLocationId;
212+
FabricIndex mFabricIndex;
213+
};
214+
206215
struct DeviceInfo
207216
{
208217
Optional<uint64_t> mRemovedOn = NullOptional;
209218
std::vector<std::unique_ptr<EcosystemDeviceStruct>> mDeviceDirectory;
210-
// Map key is using the UniqueLocationId
211-
std::map<std::string, std::unique_ptr<EcosystemLocationStruct>> mLocationDirectory;
219+
std::map<EcosystemLocationKey, std::unique_ptr<EcosystemLocationStruct>> mLocationDirectory;
212220
};
213221

214222
CHIP_ERROR EncodeRemovedOnAttribute(EndpointId aEndpoint, AttributeValueEncoder & aEncoder);

0 commit comments

Comments
 (0)