Skip to content

Commit

Permalink
Non-generating changes
Browse files Browse the repository at this point in the history
  • Loading branch information
du48s03 authored and dinglamazon committed Oct 29, 2021
1 parent 83e33e0 commit 73c722d
Show file tree
Hide file tree
Showing 8 changed files with 434 additions and 2 deletions.
1 change: 1 addition & 0 deletions examples/all-clusters-app/esp32/main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ set(SRC_DIRS_LIST
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/content-launch-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/media-input-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/mode-select-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/low-power-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/keypad-input-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/media-playback-server"
Expand Down
2 changes: 2 additions & 0 deletions examples/all-clusters-app/mbed/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ target_sources(${APP_TARGET} PRIVATE
${APP_CLUSTERS}/low-power-server/low-power-server.cpp
${APP_CLUSTERS}/media-input-server/media-input-server.cpp
${APP_CLUSTERS}/media-playback-server/media-playback-server.cpp
${APP_CLUSTERS}/mode-select-server/mode-select-server.cpp
${APP_CLUSTERS}/mode-select-server/static-supported-modes-manager.cpp
${APP_CLUSTERS}/network-commissioning/network-commissioning-ember.cpp
${APP_CLUSTERS}/network-commissioning/network-commissioning.cpp
${APP_CLUSTERS}/on-off-server/on-off-server.cpp
Expand Down
5 changes: 5 additions & 0 deletions src/app/chip_data_model.gni
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ template("chip_data_model") {
"${_app_root}/clusters/${cluster}/${cluster}-ember.cpp",
"${_app_root}/clusters/${cluster}/${cluster}.cpp",
]
} else if (cluster == "mode-select-server") {
sources += [
"${_app_root}/clusters/${cluster}/${cluster}.cpp",
"${_app_root}/clusters/${cluster}/static-supported-modes-manager.cpp",
]
} else {
sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp" ]
}
Expand Down
114 changes: 114 additions & 0 deletions src/app/clusters/mode-select-server/mode-select-server.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
*
* Copyright (c) 2021 Project CHIP Authors
*
* 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.
*/

#include <app-common/zap-generated/af-structs.h>
#include <app-common/zap-generated/att-storage.h>
#include <app-common/zap-generated/attribute-type.h>
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/cluster-objects.h>
#include <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/AttributeAccessInterface.h>
#include <app/CommandHandler.h>
#include <app/ConcreteCommandPath.h>
#include <app/clusters/mode-select-server/static-supported-modes-manager.h>
#include <app/util/af.h>
#include <app/util/attribute-storage.h>
#include <lib/support/CodeUtils.h>

using namespace std;
using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;

namespace {

class ModeSelectAttrAccess : public AttributeAccessInterface
{
public:
ModeSelectAttrAccess() : AttributeAccessInterface(Optional<EndpointId>::Missing(), ModeSelect::Id) {}

CHIP_ERROR Read(const ConcreteAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
};

ModeSelectAttrAccess gModeSelectAttrAccess;

CHIP_ERROR ModeSelectAttrAccess::Read(const ConcreteAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
VerifyOrDie(aPath.mClusterId == ModeSelect::Id);

const ModeSelect::StaticSupportedModesManager & gSupportedModeManager =
ModeSelect::StaticSupportedModesManager::getStaticSupportedModesManagerInstance();

if (ModeSelect::Attributes::SupportedModes::Id == aPath.mAttributeId)
{
const ModeSelect::StaticSupportedModesManager::IteratorFactory* iteratorFactory =
gSupportedModeManager.getIteratorFactory(aPath.mEndpointId);
if (iteratorFactory == nullptr)
{
aEncoder.Encode(DataModel::List<ModeSelect::Structs::ModeOptionStruct::Type>());
return CHIP_NO_ERROR;
}
CHIP_ERROR err;
err = aEncoder.EncodeList([iteratorFactory](const TagBoundEncoder & encoder) -> CHIP_ERROR {
const auto & end = *(iteratorFactory->end());
for (auto it = *(iteratorFactory->begin()); it != end; ++it)
{
emberAfPrintln(EMBER_AF_PRINT_DEBUG, "ModeSelect: dereferencing it");
emberAfPrintln(EMBER_AF_PRINT_DEBUG, "ModeSelect: it= %p", (void*) it.operator->());
auto& modeOption = *it;
ReturnErrorOnFailure(encoder.Encode(modeOption));
}
return CHIP_NO_ERROR;
});
ReturnErrorOnFailure(err);
}
return CHIP_NO_ERROR;
}

} // anonymous namespace

bool emberAfModeSelectClusterChangeToModeCallback(
CommandHandler * commandHandler, const ConcreteCommandPath & commandPath,
const ModeSelect::Commands::ChangeToMode::DecodableType & commandData)
{
emberAfPrintln(EMBER_AF_PRINT_DEBUG, "ModeSelect: Entering emberAfModeSelectClusterChangeToModeCallback");
EndpointId endpointId = commandPath.mEndpointId;
uint8_t newMode = commandData.newMode;
// Check that the newMode matches one of the supported options
const ModeSelect::Structs::ModeOptionStruct::Type * modeOptionPtr;
const ModeSelect::StaticSupportedModesManager & gSupportedModeManager =
ModeSelect::StaticSupportedModesManager::getStaticSupportedModesManagerInstance();
EmberAfStatus checkSupportedModeStatus = gSupportedModeManager.getModeOptionByMode(endpointId, newMode, &modeOptionPtr);
if (EMBER_ZCL_STATUS_SUCCESS != checkSupportedModeStatus)
{
emberAfPrintln(EMBER_AF_PRINT_DEBUG, "ModeSelect: Failed to find the option with mode %" PRIu8, newMode);
emberAfSendImmediateDefaultResponse(checkSupportedModeStatus);
return false;
}
ModeSelect::Attributes::CurrentMode::Set(endpointId, newMode);
// TODO: Implement application logic

emberAfPrintln(EMBER_AF_PRINT_DEBUG, "ModeSelect: ChangeToMode successful");
emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS);
return true;
}

void MatterModeSelectPluginServerInitCallback(void)
{
registerAttributeAccessOverride(&gModeSelectAttrAccess);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// Created by Ding, Li-an on 10/21/21.
//
#include <app/clusters/mode-select-server/static-supported-modes-manager.h>
#include <map>
#include <vector>

using namespace std;
using namespace chip;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::ModeSelect;

using ModeOptionStructType = Structs::ModeOptionStruct::Type;
using storage_value_type = const ModeOptionStructType *;
namespace
{
Structs::ModeOptionStruct::Type buildModeOptionStruct(const char * label, uint8_t mode, uint32_t semanticTag)
{
Structs::ModeOptionStruct::Type option;
option.label = CharSpan(label, strlen(label));
option.mode = mode;
option.semanticTag = semanticTag;
return option;
}
}

const Structs::ModeOptionStruct::Type StaticSupportedModesManager::blackOption = buildModeOptionStruct("Black", 0, 0);
const Structs::ModeOptionStruct::Type StaticSupportedModesManager::cappuccinoOption = buildModeOptionStruct("Cappuccino", 4, 0);
const Structs::ModeOptionStruct::Type StaticSupportedModesManager::espressoOption = buildModeOptionStruct("Espresso", 7, 0);
storage_value_type StaticSupportedModesManager::coffeeOptions[] = { &blackOption, &cappuccinoOption, &espressoOption };
const Span<storage_value_type> StaticSupportedModesManager::coffeeOptionsSpan =
Span<storage_value_type>(StaticSupportedModesManager::coffeeOptions);
const map<EndpointId, Span<storage_value_type>> StaticSupportedModesManager::optionsByEndpoints = {
{ 1, StaticSupportedModesManager::coffeeOptionsSpan }
};

const StaticSupportedModesManager StaticSupportedModesManager::instance = StaticSupportedModesManager();

const StaticSupportedModesManager::IteratorFactory *
StaticSupportedModesManager::getIteratorFactory(EndpointId endpointId) const
{
const auto& it = _iteratorFactoriesByEndpoints.find(endpointId);
return (it == _iteratorFactoriesByEndpoints.end()) ? nullptr : &(it->second);
}

EmberAfStatus StaticSupportedModesManager::getModeOptionByMode(unsigned short endpointId, unsigned char mode,
const ModeOptionStructType ** dataPtr) const
{
auto* iteratorFactory = this->getIteratorFactory(endpointId);
if(iteratorFactory == nullptr)
{
return EMBER_ZCL_STATUS_UNSUPPORTED_CLUSTER;
}
const StaticSupportedModesManager::Iterator & begin = *(this->getIteratorFactory(endpointId)->begin());
const StaticSupportedModesManager::Iterator & end = *(this->getIteratorFactory(endpointId)->end());
for (auto it = begin; it != end; ++it)
{
auto & modeOption = *it;
if (modeOption.mode == mode)
{
*dataPtr = &modeOption;
return EMBER_ZCL_STATUS_SUCCESS;
}
}
emberAfPrintln(EMBER_AF_PRINT_DEBUG, "Cannot find the mode %c", mode);
return EMBER_ZCL_STATUS_INVALID_ARGUMENT;
}
133 changes: 133 additions & 0 deletions src/app/clusters/mode-select-server/static-supported-modes-manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
*
* Copyright (c) 2021 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 <cstring>
#include <app/clusters/mode-select-server/supported-modes-manager.h>
#include <map>
#include <vector>
#include <app/util/af.h>

namespace chip {
namespace app {
namespace Clusters {
namespace ModeSelect {

/**
* This implementation statically defines the options.
*/

class StaticSupportedModesManager : public chip::app::Clusters::ModeSelect::SupportedModesManager
{
using ModeOptionStructType = Structs::ModeOptionStruct::Type;
using storage_value_type = const ModeOptionStructType*;

static const ModeOptionStructType blackOption;
static const ModeOptionStructType cappuccinoOption;
static const ModeOptionStructType espressoOption;

static const ModeOptionStructType* coffeeOptions[];
static const Span<storage_value_type> coffeeOptionsSpan;
static const std::map<EndpointId, Span<storage_value_type>> optionsByEndpoints;



public:
static const StaticSupportedModesManager instance;

struct Iterator: public chip::app::Clusters::ModeSelect::SupportedModesManager::ModeOptionStructIterator
{
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using pointer = storage_value_type*;
using base_iterator_type= chip::app::Clusters::ModeSelect::SupportedModesManager::ModeOptionStructIterator;

Iterator(const pointer aPtr):mPtr(aPtr) {}
~Iterator() = default;

const ModeOptionStructType& operator*() const override { return **mPtr; }
const ModeOptionStructType* operator->() override { return *mPtr; }
const ModeOptionStructType* operator->() const override { return *mPtr; }

// Prefix increment
base_iterator_type& operator++() override { ++mPtr; return *this; }

bool operator== (const base_iterator_type& other) const override
{
// Warning: we are not doing type check
// TODO: use of typeid requires -frtti
// if (typeid(other) != typeid(*this))
// {
// return false;
// }
return this->operator->() == other.operator->();
}
bool operator!= (const base_iterator_type& other) const override { return !((*this) == other); }

private:
pointer mPtr;

};

struct IteratorFactory: public chip::app::Clusters::ModeSelect::SupportedModesManager::ModeOptionStructIteratorFactory
{
using pointer = Iterator*;
using const_pointer = const pointer;

IteratorFactory(const Span<storage_value_type>& aSupportedOptions): _begin(Iterator(aSupportedOptions.data())), _end(Iterator(aSupportedOptions.data() + aSupportedOptions.size())) { }
~IteratorFactory() = default;

const Iterator* begin() const override { return &_begin; }
const Iterator* end() const override { return &_end; }

private:
const Iterator _begin;
const Iterator _end;

};

const IteratorFactory* getIteratorFactory(EndpointId endpointId) const override;

EmberAfStatus getModeOptionByMode(EndpointId endpointId, uint8_t mode, const ModeOptionStructType ** dataPtr) const override;

~StaticSupportedModesManager(){};

StaticSupportedModesManager() : StaticSupportedModesManager(&optionsByEndpoints) {}

static inline const StaticSupportedModesManager & getStaticSupportedModesManagerInstance() { return instance; }

private:
StaticSupportedModesManager(const std::map<EndpointId, Span<storage_value_type>> * const supportedModes) :
_iteratorFactoriesByEndpoints(std::map<EndpointId, IteratorFactory>())
{
for (auto & entry : *supportedModes)
{
_iteratorFactoriesByEndpoints.insert(std::pair<EndpointId, IteratorFactory>(entry.first, IteratorFactory(entry.second)));
}
}
// TODO: Implement move constructor?

std::map<EndpointId, IteratorFactory> _iteratorFactoriesByEndpoints;
};


} // namespace ModeSelect
} // namespace Clusters
} // namespace app
} // namespace chip
Loading

0 comments on commit 73c722d

Please sign in to comment.