| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- /*
- *
- * 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.
- */
- /**
- * @brief Contains Implementation of the ContentAppCommandDelegate
- */
- #include "ContentAppCommandDelegate.h"
- #include <app-common/zap-generated/cluster-objects.h>
- #include <app/CommandHandlerInterface.h>
- #include <app/util/config.h>
- #include <jni.h>
- #include <lib/core/DataModelTypes.h>
- #include <lib/support/CHIPJNIError.h>
- #include <lib/support/JniReferences.h>
- #include <lib/support/JniTypeWrappers.h>
- #include <lib/support/jsontlv/TlvJson.h>
- #include <zap-generated/endpoint_config.h>
- namespace chip {
- namespace AppPlatform {
- using CommandHandlerInterface = chip::app::CommandHandlerInterface;
- using LaunchResponseType = chip::app::Clusters::ContentLauncher::Commands::LauncherResponse::Type;
- using PlaybackResponseType = chip::app::Clusters::MediaPlayback::Commands::PlaybackResponse::Type;
- using NavigateTargetResponseType = chip::app::Clusters::TargetNavigator::Commands::NavigateTargetResponse::Type;
- using GetSetupPINResponseType = chip::app::Clusters::AccountLogin::Commands::GetSetupPINResponse::Type;
- using Status = Protocols::InteractionModel::Status;
- const std::string FAILURE_KEY = "PlatformError";
- const std::string FAILURE_STATUS_KEY = "Status";
- void ContentAppCommandDelegate::InvokeCommand(CommandHandlerInterface::HandlerContext & handlerContext)
- {
- if (handlerContext.mRequestPath.mEndpointId >= FIXED_ENDPOINT_COUNT)
- {
- TLV::TLVReader readerForJson;
- readerForJson.Init(handlerContext.mPayload);
- CHIP_ERROR err = CHIP_NO_ERROR;
- Json::Value json;
- err = TlvToJson(readerForJson, json);
- if (err != CHIP_NO_ERROR)
- {
- handlerContext.SetCommandHandled();
- handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath,
- Protocols::InteractionModel::Status::InvalidCommand);
- return;
- }
- JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
- Json::Value value = json["value"];
- std::string payload = JsonToString(value);
- UtfString jsonString(env, payload.c_str());
- ChipLogProgress(Zcl, "ContentAppCommandDelegate::InvokeCommand send command being called with payload %s", payload.c_str());
- jstring resp = (jstring) env->CallObjectMethod(
- mContentAppEndpointManager, mSendCommandMethod, static_cast<jint>(handlerContext.mRequestPath.mEndpointId),
- static_cast<jlong>(handlerContext.mRequestPath.mClusterId), static_cast<jlong>(handlerContext.mRequestPath.mCommandId),
- jsonString.jniValue());
- if (env->ExceptionCheck())
- {
- ChipLogError(Zcl, "Java exception in ContentAppCommandDelegate::sendCommand");
- env->ExceptionDescribe();
- env->ExceptionClear();
- FormatResponseData(handlerContext, "{\"value\":{}}");
- }
- else
- {
- JniUtfString respStr(env, resp);
- ChipLogProgress(Zcl, "ContentAppCommandDelegate::InvokeCommand got response %s", respStr.c_str());
- FormatResponseData(handlerContext, respStr.c_str());
- }
- env->DeleteLocalRef(resp);
- }
- else
- {
- handlerContext.SetCommandNotHandled();
- }
- }
- Status ContentAppCommandDelegate::InvokeCommand(EndpointId epId, ClusterId clusterId, CommandId commandId, std::string payload,
- bool & commandHandled, Json::Value & value)
- {
- if (epId >= FIXED_ENDPOINT_COUNT)
- {
- JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
- UtfString jsonString(env, payload.c_str());
- ChipLogProgress(Zcl, "ContentAppCommandDelegate::InvokeCommand send command being called with payload %s", payload.c_str());
- jstring resp =
- (jstring) env->CallObjectMethod(mContentAppEndpointManager, mSendCommandMethod, static_cast<jint>(epId),
- static_cast<jlong>(clusterId), static_cast<jlong>(commandId), jsonString.jniValue());
- if (env->ExceptionCheck())
- {
- ChipLogError(Zcl, "Java exception in ContentAppCommandDelegate::sendCommand");
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
- else
- {
- JniUtfString respStr(env, resp);
- ChipLogProgress(Zcl, "ContentAppCommandDelegate::InvokeCommand got response %s", respStr.c_str());
- Json::Reader reader;
- if (!reader.parse(respStr.c_str(), value))
- {
- env->DeleteLocalRef(resp);
- return Protocols::InteractionModel::Status::Failure;
- }
- }
- env->DeleteLocalRef(resp);
- // handle errors from platform-app
- if (!value[FAILURE_KEY].empty())
- {
- value = value[FAILURE_KEY];
- if (!value[FAILURE_STATUS_KEY].empty() && value[FAILURE_STATUS_KEY].isUInt())
- {
- return static_cast<Protocols::InteractionModel::Status>(value[FAILURE_STATUS_KEY].asUInt());
- }
- return Protocols::InteractionModel::Status::Failure;
- }
- return Protocols::InteractionModel::Status::UnsupportedEndpoint;
- }
- else
- {
- commandHandled = false;
- return Protocols::InteractionModel::Status::UnsupportedEndpoint;
- }
- }
- void ContentAppCommandDelegate::FormatResponseData(CommandHandlerInterface::HandlerContext & handlerContext, const char * response)
- {
- handlerContext.SetCommandHandled();
- Json::Reader reader;
- Json::Value value;
- if (!reader.parse(response, value))
- {
- return;
- }
- // handle errors from platform-app
- if (!value[FAILURE_KEY].empty())
- {
- value = value[FAILURE_KEY];
- if (!value[FAILURE_STATUS_KEY].empty() && value[FAILURE_STATUS_KEY].isUInt())
- {
- handlerContext.mCommandHandler.AddStatus(
- handlerContext.mRequestPath, static_cast<Protocols::InteractionModel::Status>(value[FAILURE_STATUS_KEY].asUInt()));
- return;
- }
- handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Protocols::InteractionModel::Status::Failure);
- return;
- }
- switch (handlerContext.mRequestPath.mClusterId)
- {
- case app::Clusters::ContentLauncher::Id: {
- Status status;
- LaunchResponseType launchResponse = FormatContentLauncherResponse(value, status);
- if (status != Protocols::InteractionModel::Status::Success)
- {
- handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status);
- }
- else
- {
- handlerContext.mCommandHandler.AddResponseData(handlerContext.mRequestPath, launchResponse);
- }
- break;
- }
- case app::Clusters::TargetNavigator::Id: {
- Status status;
- NavigateTargetResponseType navigateTargetResponse = FormatNavigateTargetResponse(value, status);
- if (status != Protocols::InteractionModel::Status::Success)
- {
- handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status);
- }
- else
- {
- handlerContext.mCommandHandler.AddResponseData(handlerContext.mRequestPath, navigateTargetResponse);
- }
- break;
- }
- case app::Clusters::MediaPlayback::Id: {
- Status status;
- PlaybackResponseType playbackResponse = FormatMediaPlaybackResponse(value, status);
- if (status != Protocols::InteractionModel::Status::Success)
- {
- handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status);
- }
- else
- {
- handlerContext.mCommandHandler.AddResponseData(handlerContext.mRequestPath, playbackResponse);
- }
- break;
- }
- case app::Clusters::AccountLogin::Id: {
- if (app::Clusters::AccountLogin::Commands::GetSetupPIN::Id != handlerContext.mRequestPath.mCommandId)
- {
- // No response for other commands in this cluster
- break;
- }
- Status status;
- GetSetupPINResponseType getSetupPINresponse = FormatGetSetupPINResponse(value, status);
- if (status != Protocols::InteractionModel::Status::Success)
- {
- handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status);
- }
- else
- {
- handlerContext.mCommandHandler.AddResponseData(handlerContext.mRequestPath, getSetupPINresponse);
- }
- break;
- }
- default:
- handlerContext.SetCommandNotHandled();
- }
- }
- LaunchResponseType ContentAppCommandDelegate::FormatContentLauncherResponse(Json::Value value, Status & status)
- {
- status = Protocols::InteractionModel::Status::Success;
- LaunchResponseType launchResponse;
- std::string statusFieldId =
- std::to_string(to_underlying(app::Clusters::ContentLauncher::Commands::LauncherResponse::Fields::kStatus));
- if (value[statusFieldId].empty())
- {
- status = Protocols::InteractionModel::Status::Failure;
- return launchResponse;
- }
- else
- {
- launchResponse.status = static_cast<app::Clusters::ContentLauncher::ContentLaunchStatusEnum>(value[statusFieldId].asInt());
- std::string dataFieldId =
- std::to_string(to_underlying(app::Clusters::ContentLauncher::Commands::LauncherResponse::Fields::kData));
- if (!value[dataFieldId].empty())
- {
- launchResponse.data = chip::MakeOptional(CharSpan::fromCharString(value[dataFieldId].asCString()));
- }
- }
- return launchResponse;
- }
- NavigateTargetResponseType ContentAppCommandDelegate::FormatNavigateTargetResponse(Json::Value value, Status & status)
- {
- status = Protocols::InteractionModel::Status::Success;
- NavigateTargetResponseType navigateTargetResponse;
- std::string statusFieldId =
- std::to_string(to_underlying(app::Clusters::TargetNavigator::Commands::NavigateTargetResponse::Fields::kStatus));
- if (value[statusFieldId].empty())
- {
- status = Protocols::InteractionModel::Status::Failure;
- return navigateTargetResponse;
- }
- else
- {
- navigateTargetResponse.status =
- static_cast<app::Clusters::TargetNavigator::TargetNavigatorStatusEnum>(value[statusFieldId].asInt());
- std::string dataFieldId =
- std::to_string(to_underlying(app::Clusters::TargetNavigator::Commands::NavigateTargetResponse::Fields::kData));
- if (!value[dataFieldId].empty())
- {
- navigateTargetResponse.data = chip::MakeOptional(CharSpan::fromCharString(value[dataFieldId].asCString()));
- }
- }
- return navigateTargetResponse;
- }
- PlaybackResponseType ContentAppCommandDelegate::FormatMediaPlaybackResponse(Json::Value value, Status & status)
- {
- status = Protocols::InteractionModel::Status::Success;
- PlaybackResponseType playbackResponse;
- std::string statusFieldId =
- std::to_string(to_underlying(app::Clusters::MediaPlayback::Commands::PlaybackResponse::Fields::kStatus));
- if (value[statusFieldId].empty())
- {
- status = Protocols::InteractionModel::Status::Failure;
- return playbackResponse;
- }
- else
- {
- playbackResponse.status = static_cast<app::Clusters::MediaPlayback::MediaPlaybackStatusEnum>(value[statusFieldId].asInt());
- std::string dataFieldId =
- std::to_string(to_underlying(app::Clusters::MediaPlayback::Commands::PlaybackResponse::Fields::kData));
- if (!value[dataFieldId].empty())
- {
- playbackResponse.data = chip::MakeOptional(CharSpan::fromCharString(value[dataFieldId].asCString()));
- }
- }
- return playbackResponse;
- }
- GetSetupPINResponseType ContentAppCommandDelegate::FormatGetSetupPINResponse(Json::Value value, Status & status)
- {
- status = Protocols::InteractionModel::Status::Success;
- GetSetupPINResponseType getSetupPINresponse;
- std::string setupPINFieldId =
- std::to_string(to_underlying(app::Clusters::AccountLogin::Commands::GetSetupPINResponse::Fields::kSetupPIN));
- if (!value[setupPINFieldId].empty())
- {
- getSetupPINresponse.setupPIN = CharSpan::fromCharString(value[setupPINFieldId].asCString());
- }
- else
- {
- getSetupPINresponse.setupPIN = "";
- }
- return getSetupPINresponse;
- }
- } // namespace AppPlatform
- } // namespace chip
|