Skip to content

Commit

Permalink
Add FabricIndex to ECOINFO attributes for fabric-scoping to work
Browse files Browse the repository at this point in the history
  • Loading branch information
tehampson committed Aug 15, 2024
1 parent 78ce5b0 commit 40b09c3
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,13 @@ EcosystemDeviceStruct::Builder & EcosystemDeviceStruct::Builder::AddUniqueLocati
return *this;
}

EcosystemDeviceStruct::Builder & EcosystemDeviceStruct::Builder::SetFabricIndex(FabricIndex aFabricIndex)
{
VerifyOrDie(!mIsAlreadyBuilt);
mFabricIndex = aFabricIndex;
return *this;
}

std::unique_ptr<EcosystemDeviceStruct> EcosystemDeviceStruct::Builder::Build()
{
VerifyOrReturnValue(!mIsAlreadyBuilt, nullptr, ChipLogError(Zcl, "Build() already called"));
Expand All @@ -136,6 +143,8 @@ std::unique_ptr<EcosystemDeviceStruct> EcosystemDeviceStruct::Builder::Build()
VerifyOrReturnValue(!mDeviceTypes.empty(), nullptr, ChipLogError(Zcl, "No device types added"));
VerifyOrReturnValue(mUniqueLocationIds.size() <= kUniqueLocationIdsListMaxSize, nullptr,
ChipLogError(Zcl, "Too many location ids"));
VerifyOrReturnValue(mFabricIndex >= kMinValidFabricIndex, nullptr, ChipLogError(Zcl, "Fabric index is invalid"));
VerifyOrReturnValue(mFabricIndex <= kMaxValidFabricIndex, nullptr, ChipLogError(Zcl, "Fabric index is invalid"));

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

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

deviceStruct.uniqueLocationIDsLastEdit = mUniqueLocationIdsLastEditEpochUs;

// TODO(#33223) this is a hack, use mFabricIndex when it exists.
deviceStruct.SetFabricIndex(aFabricIndex);
deviceStruct.SetFabricIndex(mFabricIndex);
return aEncoder.Encode(deviceStruct);
}

Expand Down Expand Up @@ -208,31 +215,41 @@ EcosystemLocationStruct::Builder::SetLocationDescriptorLastEdit(uint64_t aLocati
return *this;
}

EcosystemLocationStruct::Builder & EcosystemLocationStruct::Builder::SetFabricIndex(FabricIndex aFabricIndex)
{
VerifyOrDie(!mIsAlreadyBuilt);
mFabricIndex = aFabricIndex;
return *this;
}


std::unique_ptr<EcosystemLocationStruct> EcosystemLocationStruct::Builder::Build()
{
VerifyOrReturnValue(!mIsAlreadyBuilt, nullptr, ChipLogError(Zcl, "Build() already called"));
VerifyOrReturnValue(!mLocationDescriptor.mLocationName.empty(), nullptr, ChipLogError(Zcl, "Must Provided Location Name"));
VerifyOrReturnValue(mLocationDescriptor.mLocationName.size() <= kLocationDescriptorNameMaxSize, nullptr,
ChipLogError(Zcl, "Must Location Name must be less than 64 bytes"));
VerifyOrReturnValue(mFabricIndex >= kMinValidFabricIndex, nullptr, ChipLogError(Zcl, "Fabric index is invalid"));
VerifyOrReturnValue(mFabricIndex <= kMaxValidFabricIndex, nullptr, ChipLogError(Zcl, "Fabric index is invalid"));

// std::make_unique does not have access to private constructor we workaround with using new
std::unique_ptr<EcosystemLocationStruct> ret{ new EcosystemLocationStruct(std::move(mLocationDescriptor),
mLocationDescriptorLastEditEpochUs) };
mLocationDescriptorLastEditEpochUs,
mFabricIndex) };
mIsAlreadyBuilt = true;
return ret;
}

CHIP_ERROR EcosystemLocationStruct::Encode(const AttributeValueEncoder::ListEncodeHelper & aEncoder,
const std::string & aUniqueLocationId, const FabricIndex & aFabricIndex)
const std::string & aUniqueLocationId)
{
Structs::EcosystemLocationStruct::Type locationStruct;
VerifyOrDie(!aUniqueLocationId.empty());
locationStruct.uniqueLocationID = CharSpan(aUniqueLocationId.c_str(), aUniqueLocationId.size());
locationStruct.locationDescriptor = GetEncodableLocationDescriptorStruct(mLocationDescriptor);
locationStruct.locationDescriptorLastEdit = mLocationDescriptorLastEditEpochUs;
locationStruct.SetFabricIndex(mFabricIndex);

// TODO(#33223) this is a hack, use mFabricIndex when it exists.
locationStruct.SetFabricIndex(aFabricIndex);
return aEncoder.Encode(locationStruct);
}

Expand Down Expand Up @@ -352,11 +369,10 @@ CHIP_ERROR EcosystemInformationServer::EncodeDeviceDirectoryAttribute(EndpointId
return aEncoder.EncodeEmptyList();
}

FabricIndex fabricIndex = aEncoder.AccessingFabricIndex();
return aEncoder.EncodeList([&](const auto & encoder) -> CHIP_ERROR {
for (auto & device : deviceInfo.mDeviceDirectory)
{
ReturnErrorOnFailure(device->Encode(encoder, fabricIndex));
ReturnErrorOnFailure(device->Encode(encoder));
}
return CHIP_NO_ERROR;
});
Expand All @@ -379,11 +395,10 @@ CHIP_ERROR EcosystemInformationServer::EncodeLocationStructAttribute(EndpointId
return aEncoder.EncodeEmptyList();
}

FabricIndex fabricIndex = aEncoder.AccessingFabricIndex();
return aEncoder.EncodeList([&](const auto & encoder) -> CHIP_ERROR {
for (auto & [id, device] : deviceInfo.mLocationDirectory)
{
ReturnErrorOnFailure(device->Encode(encoder, id, fabricIndex));
ReturnErrorOnFailure(device->Encode(encoder, id));
}
return CHIP_NO_ERROR;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class EcosystemDeviceStruct
Builder & SetOriginalEndpoint(EndpointId aOriginalEndpoint);
Builder & AddDeviceType(Structs::DeviceTypeStruct::Type aDeviceType);
Builder & AddUniqueLocationId(std::string aUniqueLocationId, uint64_t aUniqueLocationIdsLastEditEpochUs);
Builder & SetFabricIndex(FabricIndex aFabricIndex);

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

CHIP_ERROR Encode(const AttributeValueEncoder::ListEncodeHelper & aEncoder, const FabricIndex & aFabricIndex);
CHIP_ERROR Encode(const AttributeValueEncoder::ListEncodeHelper & aEncoder);

private:
// Constructor is intentionally private. This is to ensure that it is only constructed with
// values that conform to the spec.
explicit EcosystemDeviceStruct(std::string && aDeviceName, uint64_t aDeviceNameLastEditEpochUs, EndpointId aBridgedEndpoint,
EndpointId aOriginalEndpoint, std::vector<Structs::DeviceTypeStruct::Type> && aDeviceTypes,
std::vector<std::string> && aUniqueLocationIds, uint64_t aUniqueLocationIdsLastEditEpochUs) :
std::vector<std::string> && aUniqueLocationIds, uint64_t aUniqueLocationIdsLastEditEpochUs,
FabricIndex aFabricIndex) :
mDeviceName(std::move(aDeviceName)),
mDeviceNameLastEditEpochUs(aDeviceNameLastEditEpochUs), mBridgedEndpoint(aBridgedEndpoint),
mOriginalEndpoint(aOriginalEndpoint), mDeviceTypes(std::move(aDeviceTypes)),
mUniqueLocationIds(std::move(aUniqueLocationIds)), mUniqueLocationIdsLastEditEpochUs(aUniqueLocationIdsLastEditEpochUs)
mUniqueLocationIds(std::move(aUniqueLocationIds)), mUniqueLocationIdsLastEditEpochUs(aUniqueLocationIdsLastEditEpochUs),
mFabricIndex(aFabricIndex)

{}

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

struct LocationDescriptorStruct
Expand All @@ -113,6 +115,7 @@ class EcosystemLocationStruct
Builder & SetFloorNumber(std::optional<int16_t> aFloorNumber);
Builder & SetAreaTypeTag(std::optional<Globals::AreaTypeTag> aAreaTypeTag);
Builder & SetLocationDescriptorLastEdit(uint64_t aLocationDescriptorLastEditEpochUs);
Builder & SetFabricIndex(FabricIndex aFabricIndex);

// Upon success this object will have moved all ownership of underlying
// types to EcosystemDeviceStruct and should not be used afterwards.
Expand All @@ -121,28 +124,25 @@ class EcosystemLocationStruct
private:
LocationDescriptorStruct mLocationDescriptor;
uint64_t mLocationDescriptorLastEditEpochUs = 0;
FabricIndex mFabricIndex = kUndefinedFabricIndex;
bool mIsAlreadyBuilt = false;
};

CHIP_ERROR Encode(const AttributeValueEncoder::ListEncodeHelper & aEncoder, const std::string & aUniqueLocationId,
const FabricIndex & aFabricIndex);
CHIP_ERROR Encode(const AttributeValueEncoder::ListEncodeHelper & aEncoder, const std::string & aUniqueLocationId);

private:
// Constructor is intentionally private. This is to ensure that it is only constructed with
// values that conform to the spec.
explicit EcosystemLocationStruct(LocationDescriptorStruct && aLocationDescriptor, uint64_t aLocationDescriptorLastEditEpochUs) :
mLocationDescriptor(aLocationDescriptor), mLocationDescriptorLastEditEpochUs(aLocationDescriptorLastEditEpochUs)
explicit EcosystemLocationStruct(LocationDescriptorStruct && aLocationDescriptor, uint64_t aLocationDescriptorLastEditEpochUs, FabricIndex aFabricIndex) :
mLocationDescriptor(aLocationDescriptor), mLocationDescriptorLastEditEpochUs(aLocationDescriptorLastEditEpochUs), mFabricIndex(aFabricIndex)
{}
// EcosystemLocationStruct is used as a value in a key-value map.
// Because UniqueLocationId is manditory when an entry exist, and
// it is unique, we use it as a key to the key-value pair and is why it is
// not explicitly in this struct.
LocationDescriptorStruct mLocationDescriptor;
uint64_t mLocationDescriptorLastEditEpochUs;
// TODO(#33223) This structure needs to contain fabric index to be spec compliant.
// To keep initial PR smaller, we are going to assume that all entries
// here are for any fabric. This will allow follow up PR introducing
// fabric scoped to be more throughly reviewed with focus on fabric scoping.
FabricIndex mFabricIndex;
};

class EcosystemInformationServer
Expand Down

0 comments on commit 40b09c3

Please sign in to comment.