Skip to content

Commit

Permalink
Merge 82b94f6 into 0e0fd72
Browse files Browse the repository at this point in the history
  • Loading branch information
erwinpan1 authored Jul 24, 2023
2 parents 0e0fd72 + 82b94f6 commit 1070120
Show file tree
Hide file tree
Showing 9 changed files with 9,663 additions and 7 deletions.
210 changes: 210 additions & 0 deletions examples/chef/common/chef-channel-manager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/**
*
* 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.
*/
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/callback.h>
#include <app/util/config.h>
#include <vector>

// Include Channel Cluster Server callbacks only when the server is enabled
#ifdef EMBER_AF_PLUGIN_CHANNEL_SERVER
#include <chef-channel-manager.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters::Channel;
using namespace chip::Uint8;

ChefChannelManager::ChefChannelManager()
{
ChannelInfoType abc;
abc.affiliateCallSign = MakeOptional(chip::CharSpan::fromCharString("KAAL"));
abc.callSign = MakeOptional(chip::CharSpan::fromCharString("KAAL-TV"));
abc.name = MakeOptional(chip::CharSpan::fromCharString("ABC"));
abc.majorNumber = static_cast<uint8_t>(6);
abc.minorNumber = static_cast<uint16_t>(0);
mChannels.push_back(abc);

ChannelInfoType pbs;
pbs.affiliateCallSign = MakeOptional(chip::CharSpan::fromCharString("KCTS"));
pbs.callSign = MakeOptional(chip::CharSpan::fromCharString("KCTS-TV"));
pbs.name = MakeOptional(chip::CharSpan::fromCharString("PBS"));
pbs.majorNumber = static_cast<uint8_t>(9);
pbs.minorNumber = static_cast<uint16_t>(1);
mChannels.push_back(pbs);

ChannelInfoType pbsKids;
pbsKids.affiliateCallSign = MakeOptional(chip::CharSpan::fromCharString("KCTS"));
pbsKids.callSign = MakeOptional(chip::CharSpan::fromCharString("KCTS-TV"));
pbsKids.name = MakeOptional(chip::CharSpan::fromCharString("PBS Kids"));
pbsKids.majorNumber = static_cast<uint8_t>(9);
pbsKids.minorNumber = static_cast<uint16_t>(2);
mChannels.push_back(pbsKids);

ChannelInfoType worldChannel;
worldChannel.affiliateCallSign = MakeOptional(chip::CharSpan::fromCharString("KCTS"));
worldChannel.callSign = MakeOptional(chip::CharSpan::fromCharString("KCTS-TV"));
worldChannel.name = MakeOptional(chip::CharSpan::fromCharString("World Channel"));
worldChannel.majorNumber = static_cast<uint8_t>(9);
worldChannel.minorNumber = static_cast<uint16_t>(3);
mChannels.push_back(worldChannel);

mCurrentChannelIndex = 0;
mCurrentChannel = mChannels[mCurrentChannelIndex];
}

static bool isChannelMatched(const ChannelInfoType & channel, const CharSpan & match)
{
char number[32];
sprintf(number, "%d.%d", channel.majorNumber, channel.minorNumber);
bool nameMatch = channel.name.HasValue() ? channel.name.Value().data_equal(match) : false;
bool affiliateCallSignMatch =
channel.affiliateCallSign.HasValue() ? channel.affiliateCallSign.Value().data_equal(match) : false;
bool callSignMatch = channel.callSign.HasValue() ? channel.callSign.Value().data_equal(match) : false;
bool numberMatch = match.data_equal(chip::CharSpan::fromCharString(number));

return affiliateCallSignMatch || callSignMatch || nameMatch || numberMatch;
}

CHIP_ERROR ChefChannelManager::HandleGetChannelList(app::AttributeValueEncoder & aEncoder)
{
// TODO: Insert code here
return aEncoder.EncodeList([](const auto & encoder) -> CHIP_ERROR {
for (auto const & channel : ChefChannelManager().mChannels)
{
ReturnErrorOnFailure(encoder.Encode(channel));
}
return CHIP_NO_ERROR;
});
}

CHIP_ERROR ChefChannelManager::HandleGetLineup(app::AttributeValueEncoder & aEncoder)
{
LineupInfoType lineup;
lineup.operatorName = chip::CharSpan::fromCharString("Comcast");
lineup.lineupName = MakeOptional(chip::CharSpan::fromCharString("Comcast King County"));
lineup.postalCode = MakeOptional(chip::CharSpan::fromCharString("98052"));
lineup.lineupInfoType = chip::app::Clusters::Channel::LineupInfoTypeEnum::kMso;

return aEncoder.Encode(lineup);
}

CHIP_ERROR ChefChannelManager::HandleGetCurrentChannel(app::AttributeValueEncoder & aEncoder)
{
return aEncoder.Encode(mCurrentChannel);
}

void ChefChannelManager::HandleChangeChannel(CommandResponseHelper<ChangeChannelResponseType> & helper,
const chip::CharSpan & match)
{
std::vector<ChannelInfoType> matchedChannels;
uint16_t index = 0;
for (auto const & channel : mChannels)
{
// verify if CharSpan matches channel name
// or callSign or affiliateCallSign or majorNumber.minorNumber
if (isChannelMatched(channel, match))
{
matchedChannels.push_back(channel);
}
else if (matchedChannels.size() == 0)
{
// "index" is only used when we end up with matchedChannels.size() == 1.
// In that case, we want it to be the number of non-matching channels we saw before
// the matching one.
index++;
}
}

ChangeChannelResponseType response;

// Error: Found multiple matches
if (matchedChannels.size() > 1)
{
response.status = chip::app::Clusters::Channel::ChannelStatusEnum::kMultipleMatches;
helper.Success(response);
}
else if (matchedChannels.size() == 0)
{
// Error: Found no match
response.status = chip::app::Clusters::Channel::ChannelStatusEnum::kNoMatches;
helper.Success(response);
}
else
{
response.status = chip::app::Clusters::Channel::ChannelStatusEnum::kSuccess;
response.data = chip::MakeOptional(CharSpan::fromCharString("data response"));
mCurrentChannel = matchedChannels[0];
mCurrentChannelIndex = index;
helper.Success(response);
}
}

bool ChefChannelManager::HandleChangeChannelByNumber(const uint16_t & majorNumber, const uint16_t & minorNumber)
{
// TODO: Insert code here
bool channelChanged = false;
uint16_t index = 0;
for (auto const & channel : mChannels)
{
// verify if major & minor matches one of the channel from the list
if (channel.minorNumber == minorNumber && channel.majorNumber == majorNumber)
{
// verify if channel changed by comparing values of current channel with the requested channel
if (channel.minorNumber != mCurrentChannel.minorNumber || channel.majorNumber != mCurrentChannel.majorNumber)
{
channelChanged = true;
mCurrentChannelIndex = index;
mCurrentChannel = channel;
}
}
index++;
}
return channelChanged;
}

bool ChefChannelManager::HandleSkipChannel(const int16_t & count)
{
int32_t newChannelIndex = static_cast<int32_t>(count) + static_cast<int32_t>(mCurrentChannelIndex);
uint16_t channelsSize = static_cast<uint16_t>(mChannels.size());

// handle newChannelIndex out of range.
newChannelIndex = newChannelIndex % channelsSize;

if (newChannelIndex < 0)
{
newChannelIndex = newChannelIndex + channelsSize;
}

mCurrentChannelIndex = static_cast<uint16_t>(newChannelIndex);
mCurrentChannel = mChannels[mCurrentChannelIndex];
return true;
}

uint32_t ChefChannelManager::GetFeatureMap(chip::EndpointId endpoint)
{
if (endpoint > EMBER_AF_CHANNEL_CLUSTER_SERVER_ENDPOINT_COUNT)
{
return 0;
}

uint32_t featureMap = 0;
Attributes::FeatureMap::Get(endpoint, &featureMap);
return featureMap;
}

#endif /* EMBER_AF_PLUGIN_CHANNEL_SERVER */
64 changes: 64 additions & 0 deletions examples/chef/common/chef-channel-manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
*
* 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 <app/clusters/channel-server/channel-server.h>
#include <vector>

using namespace chip;
using namespace chip::app;

using chip::CharSpan;
using chip::app::AttributeValueEncoder;
using chip::app::CommandResponseHelper;
using ChannelDelegate = chip::app::Clusters::Channel::Delegate;
using ChangeChannelResponseType = chip::app::Clusters::Channel::Commands::ChangeChannelResponse::Type;
using ChannelInfoType = chip::app::Clusters::Channel::Structs::ChannelInfoStruct::Type;
using LineupInfoType = chip::app::Clusters::Channel::Structs::LineupInfoStruct::Type;

class ChefChannelManager : public ChannelDelegate
{

public:
ChefChannelManager();

CHIP_ERROR HandleGetChannelList(app::AttributeValueEncoder & aEncoder);
CHIP_ERROR HandleGetLineup(app::AttributeValueEncoder & aEncoder);
CHIP_ERROR HandleGetCurrentChannel(app::AttributeValueEncoder & aEncoder);

void HandleChangeChannel(CommandResponseHelper<ChangeChannelResponseType> & helper, const chip::CharSpan & match);
bool HandleChangeChannelByNumber(const uint16_t & majorNumber, const uint16_t & minorNumber);
bool HandleSkipChannel(const int16_t & count);

static ChefChannelManager & Instance()
{
static ChefChannelManager instance;
return instance;
}

// bool HasFeature(chip::EndpointId endpoint, Feature feature);
uint32_t GetFeatureMap(chip::EndpointId endpoint);

~ChefChannelManager() = default;

protected:
uint16_t mCurrentChannelIndex;
ChannelInfoType mCurrentChannel;
std::vector<ChannelInfoType> mChannels;
};
10 changes: 10 additions & 0 deletions examples/chef/common/stubs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,13 @@ bool emberAfPluginDoorLockSetCredential(chip::EndpointId endpointId, uint16_t cr
}

#endif /* EMBER_AF_PLUGIN_DOOR_LOCK_SERVER */

#ifdef EMBER_AF_PLUGIN_CHANNEL_SERVER
#include <chef-channel-manager.h>

void emberAfChannelClusterInitCallback(EndpointId endpoint)
{
app::Clusters::Channel::SetDefaultDelegate(endpoint,
static_cast<app::Clusters::Channel::Delegate *>(&(ChefChannelManager::Instance())));
}
#endif // EMBER_AF_PLUGIN_CHANNEL_SERVER
Loading

0 comments on commit 1070120

Please sign in to comment.