blob: 9d7c2556e4ece95aab2e5def7bd3d508c8e9d15e [file] [log] [blame]
/**
*
* 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 "ChannelManager.h"
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app/util/config.h>
#include <vector>
using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters::Channel;
using namespace chip::Uint8;
ChannelManager::ChannelManager()
{
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];
}
CHIP_ERROR ChannelManager::HandleGetChannelList(AttributeValueEncoder & aEncoder)
{
// TODO: Insert code here
return aEncoder.EncodeList([](const auto & encoder) -> CHIP_ERROR {
for (auto const & channel : ChannelManager().mChannels)
{
ReturnErrorOnFailure(encoder.Encode(channel));
}
return CHIP_NO_ERROR;
});
}
CHIP_ERROR ChannelManager::HandleGetLineup(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 ChannelManager::HandleGetCurrentChannel(AttributeValueEncoder & aEncoder)
{
return aEncoder.Encode(mCurrentChannel);
}
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;
}
void ChannelManager::HandleChangeChannel(CommandResponseHelper<ChangeChannelResponseType> & helper, const 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 ChannelManager::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 ChannelManager::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 ChannelManager::GetFeatureMap(chip::EndpointId endpoint)
{
if (endpoint >= EMBER_AF_CONTENT_LAUNCHER_CLUSTER_SERVER_ENDPOINT_COUNT)
{
return mDynamicEndpointFeatureMap;
}
uint32_t featureMap = 0;
Attributes::FeatureMap::Get(endpoint, &featureMap);
return featureMap;
}