Skip to content

Commit

Permalink
[ClusterObjects] Add kIsFabricScoped to all cluster objects (#14227)
Browse files Browse the repository at this point in the history
  • Loading branch information
erjiaqing authored and pull[bot] committed Feb 24, 2022
1 parent d61d577 commit e15e7dd
Show file tree
Hide file tree
Showing 8 changed files with 331 additions and 23 deletions.
25 changes: 24 additions & 1 deletion src/app/EventLogging.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,14 @@ class EventLogger : public EventLoggingDelegate
* @param[out] aEventNumber The event Number if the event was written to the
* log, 0 otherwise. The Event number is expected to monotonically increase.
*
* TODO: Revisit spec foc nullable fabric index in event.
*
* @return CHIP_ERROR CHIP Error Code
*/
template <typename T, std::enable_if_t<DataModel::IsFabricScoped<T>::value, bool> = true>
template <typename T,
std::enable_if_t<DataModel::IsFabricScoped<T>::value &&
std::is_same<decltype(std::declval<T>().GetFabricIndex()), FabricIndex>::value,
bool> = true>
CHIP_ERROR LogEvent(const T & aEventData, EndpointId aEndpoint, EventNumber & aEventNumber,
EventOptions::Type aUrgent = EventOptions::Type::kNotUrgent)
{
Expand All @@ -78,6 +83,24 @@ CHIP_ERROR LogEvent(const T & aEventData, EndpointId aEndpoint, EventNumber & aE
return logMgmt.LogEvent(&eventData, eventOptions, aEventNumber);
}

template <typename T,
std::enable_if_t<DataModel::IsFabricScoped<T>::value &&
std::is_same<decltype(std::declval<T>().GetFabricIndex()), DataModel::Nullable<FabricIndex>>::value,
bool> = true>
CHIP_ERROR LogEvent(const T & aEventData, EndpointId aEndpoint, EventNumber & aEventNumber,
EventOptions::Type aUrgent = EventOptions::Type::kNotUrgent)
{
EventLogger<T> eventData(aEventData);
ConcreteEventPath path(aEndpoint, aEventData.GetClusterId(), aEventData.GetEventId());
EventManagement & logMgmt = chip::app::EventManagement::GetInstance();
EventOptions eventOptions;
eventOptions.mUrgent = aUrgent;
eventOptions.mPath = path;
eventOptions.mPriority = aEventData.GetPriorityLevel();
eventOptions.mFabricIndex = aEventData.GetFabricIndex().IsNull() ? kUndefinedFabricIndex : aEventData.GetFabricIndex().Value();
return logMgmt.LogEvent(&eventData, eventOptions, aEventNumber);
}

template <typename T, std::enable_if_t<!DataModel::IsFabricScoped<T>::value, bool> = true>
CHIP_ERROR LogEvent(const T & aEventData, EndpointId aEndpoint, EventNumber & aEventNumber,
EventOptions::Type aUrgent = EventOptions::Type::kNotUrgent)
Expand Down
14 changes: 7 additions & 7 deletions src/app/clusters/access-control-server/access-control-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,14 +272,14 @@ struct AccessControlEntryCodec
return CHIP_NO_ERROR;
}

bool MatchesFabricIndex(FabricIndex fabricIndex) const
static constexpr bool kIsFabricScoped = true;

auto GetFabricIndex() const
{
FabricIndex entryFabricIndex;
if (entry.GetFabricIndex(entryFabricIndex) == CHIP_NO_ERROR)
{
return fabricIndex == entryFabricIndex;
}
return false;
FabricIndex fabricIndex = kUndefinedFabricIndex;
// Ignore the error value
entry.GetFabricIndex(fabricIndex);
return fabricIndex;
}

AccessControl::Entry entry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ struct GroupTableCodec
mProvider(provider), mFabric(fabric_index), mInfo(info)
{}

static constexpr bool kIsFabricScoped = true;

auto GetFabricIndex() const { return mFabric; }

CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag) const
{
TLV::TLVType outer;
Expand Down
60 changes: 60 additions & 0 deletions src/app/data-model/BasicTypes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
*
* Copyright (c) 2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <lib/support/BitFlags.h>
#include <lib/support/Span.h>

#include <type_traits>

namespace chip {
namespace app {
namespace DataModel {

/**
* IsBasicType checks whether the given type can be encoded into TLV as a single value. numeric values, as well as bitmaps, char
* strings and octet strings are basic types, see spec 7.18.1.
*/
template <typename X>
struct IsBasicType
{
static constexpr bool value = std::is_integral<X>::value || std::is_floating_point<X>::value || std::is_enum<X>::value;
};

template <typename X>
struct IsBasicType<BitFlags<X>>
{
static constexpr bool value = true;
};

template <>
struct IsBasicType<ByteSpan>
{
static constexpr bool value = true;
};

template <>
struct IsBasicType<CharSpan>
{
static constexpr bool value = true;
};

} // namespace DataModel
} // namespace app
} // namespace chip
34 changes: 21 additions & 13 deletions src/app/data-model/FabricScoped.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
* Copyright (c) 2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -18,31 +18,39 @@

#pragma once

#include <lib/support/TypeTraits.h>
#include <app/data-model/BasicTypes.h>

#include <type_traits>

namespace chip {
namespace app {
namespace DataModel {

/*
* Check whether a cluster object struct is fabric scoped.
* A fabric scoped struct contains a field of "FabricIndex" type, however, we cannot tell the difference between that field and
* other uint8_t fields. Thus we add a GetFabricIndex member function for getting the fabric id. Here, IsFabricScoped checks the
* presence of GetFabricIndex function. This template can be used with std::enable_if.
/**
* IsFabricScoped checks whether the given type is fabric scoped. Non-basic types (i.e. cluster objects), should provide a
* static constexpr indicating whether the type is a fabric scoped struct, and basic types will never be fabric scoped.
*
* Using IsFabricScoped<X>::value without a basic type or cluster object with kIsFabricScoped will cause a compile error. This is
* an intended behavior to make users explicitly decide whether their cluster object is fabric-scoped or not.
*/
template <typename T>
template <typename X>
class IsFabricScoped
{
private:
template <typename Tp>
static auto TestHasFabricIndex(int) -> TemplatedTrueType<decltype(&Tp::GetFabricIndex)>;
template <typename X0, decltype(std::decay_t<X0>::kIsFabricScoped) = true>
static constexpr bool IsFabricScopedClusterObject()
{
return std::decay_t<X0>::kIsFabricScoped;
}

template <typename Tp>
static auto TestHasFabricIndex(long) -> std::false_type;
template <typename X0, std::enable_if_t<IsBasicType<std::decay_t<X0>>::value, bool> = true>
static constexpr bool IsFabricScopedClusterObject()
{
return false;
}

public:
static constexpr bool value = decltype(TestHasFabricIndex<std::decay_t<T>>(0))::value;
static constexpr bool value = IsFabricScopedClusterObject<X>();
};

} // namespace DataModel
Expand Down
11 changes: 11 additions & 0 deletions src/app/zap-templates/partials/cluster-objects-struct.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ namespace {{asUpperCamelCase name}} {
{{#unless struct_contains_array}}
CHIP_ERROR Decode(TLV::TLVReader &reader);
{{/unless}}

static constexpr bool kIsFabricScoped = {{struct_is_fabric_scoped}};

{{#if struct_is_fabric_scoped}}
auto GetFabricIndex() const {
return {{ asLowerCamelCase struct_fabric_idx_field }};
Expand All @@ -30,6 +33,14 @@ namespace {{asUpperCamelCase name}} {
{{zapTypeToDecodableClusterObjectType type}} {{asLowerCamelCase label}}{{> cluster_objects_field_init}};
{{/zcl_struct_items}}
CHIP_ERROR Decode(TLV::TLVReader &reader);

static constexpr bool kIsFabricScoped = {{struct_is_fabric_scoped}};

{{#if struct_is_fabric_scoped}}
auto GetFabricIndex() const {
return {{ asLowerCamelCase struct_fabric_idx_field }};
}
{{/if}}
};
{{else}}
using DecodableType = Type;
Expand Down
3 changes: 1 addition & 2 deletions src/app/zap-templates/templates/app/cluster-objects.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -208,17 +208,16 @@ public:
static constexpr PriorityLevel GetPriorityLevel() { return kPriorityLevel; }
static constexpr EventId GetEventId() { return Events::{{asUpperCamelCase name}}::Id; }
static constexpr ClusterId GetClusterId() { return Clusters::{{asUpperCamelCase parent.name}}::Id; }
static constexpr bool kIsFabricScoped = {{event_is_fabric_scoped}};

{{#zcl_event_fields}}
{{zapTypeToEncodableClusterObjectType type}} {{asLowerCamelCase name}}{{> cluster_objects_field_init}};
{{/zcl_event_fields}}

{{#if event_is_fabric_scoped}}
{{#unless event_is_fabric_index_nullable}}
auto GetFabricIndex() const {
return {{ asLowerCamelCase event_fabric_idx_field }};
}
{{/unless}}
{{/if}}

CHIP_ERROR Encode(TLV::TLVWriter &writer, TLV::Tag tag) const;
Expand Down
Loading

0 comments on commit e15e7dd

Please sign in to comment.