From a364cf9d8044a7aec586fb5ffc92fccef5d770bb Mon Sep 17 00:00:00 2001 From: libenyao Date: Thu, 23 Feb 2023 15:08:14 +0800 Subject: [PATCH] add cli/CommandLine.cpp CommandLineInterface.cpp Signed-off-by: libenyao --- cli/CommandLine.cpp | 323 +++++++++++++++++++++++++++++++++++ cli/CommandLineInterface.cpp | 258 ++++++++++++++++++++++++++++ 2 files changed, 581 insertions(+) create mode 100644 cli/CommandLineInterface.cpp diff --git a/cli/CommandLine.cpp b/cli/CommandLine.cpp index d70b1ee..7a065bf 100644 --- a/cli/CommandLine.cpp +++ b/cli/CommandLine.cpp @@ -985,4 +985,327 @@ void BrightnessCommand::RunSet() Json::Value result = true; SetCommandResult("result", result); ILOG("Set brightness run finished, the value is: %s", args["Brightness"].asString().c_str()); +} + +bool BrightnessCommand::IsSetArgValid() const +{ + if (args.isNull() || !args.isMember("Brightness")) { + ELOG("Invalid number of arguments!"); + return false; + } + if (!std::regex_match(args["Brightness"].asString().data(), std::regex("\\d+"))) { + ELOG("Invalid arguments!"); + return false; + } + uint8_t temp = ToUint8(args["Brightness"].asString()); + if (!SharedData::IsValid(BRIGHTNESS_VALUE, temp)) { + ELOG("BrightnessCommand invalid value: ", temp); + return false; + } + return true; +} + +HeartRateCommand::HeartRateCommand(CommandType commandType, const Json::Value& arg, const LocalSocket& socket) + : CommandLine(commandType, arg, socket) +{ +} + +void HeartRateCommand::RunGet() +{ + Json::Value result; + result["HeartRate"] = SharedData::GetData(HEARTBEAT_VALUE); + SetCommandResult("result", result); + ILOG("Get heartRate run finished"); +} + +void HeartRateCommand::RunSet() +{ + SharedData::SetData(HEARTBEAT_VALUE, static_cast(atoi(args["HeartRate"].asString().data()))); + Json::Value result = true; + SetCommandResult("result", result); + ILOG("Set heartRate run finished, the value is: %s", args["HeartRate"].asString().c_str()); +} + +bool HeartRateCommand::IsSetArgValid() const +{ + if (args.isNull() || !args.isMember("HeartRate")) { + ELOG("Invalid number of arguments!"); + return false; + } + if (!std::regex_match(args["HeartRate"].asString().data(), std::regex("\\d+"))) { + ELOG("Invalid arguments!"); + return false; + } + if (atoi(args["HeartRate"].asString().data()) > UINT8_MAX) { + ELOG("Invalid arguments!"); + return false; + } + uint8_t temp = ToUint8(args["HeartRate"].asString()); + if (!SharedData::IsValid(HEARTBEAT_VALUE, temp)) { + ELOG("HeartRateCommand invalid value: %d", temp); + return false; + } + return true; +} + +StepCountCommand::StepCountCommand(CommandType commandType, const Json::Value& arg, const LocalSocket& socket) + : CommandLine(commandType, arg, socket) +{ +} + +void StepCountCommand::RunGet() +{ + Json::Value result; + result["StepCount"] = SharedData::GetData(SUMSTEP_VALUE); + SetCommandResult("result", result); + ILOG("Get stepCount run finished"); +} + +void StepCountCommand::RunSet() +{ + SharedData::SetData(SUMSTEP_VALUE, static_cast(atoi(args["StepCount"].asString().data()))); + Json::Value result = true; + SetCommandResult("result", result); + ILOG("Set stepCount run finished, the value is: %s", args["StepCount"].asString().c_str()); +} + +bool StepCountCommand::IsSetArgValid() const +{ + if (args.isNull() || !args.isMember("StepCount")) { + ELOG("Invalid number of arguments!"); + return false; + } + if (!std::regex_match(args["StepCount"].asString().data(), std::regex("\\d+"))) { + ELOG("Invalid arguments!"); + return false; + } + + uint32_t temp = ToUint8(args["StepCount"].asString()); + if (!SharedData::IsValid(SUMSTEP_VALUE, temp)) { + ELOG("StepCountCommand invalid value: %d", temp); + return false; + } + return true; +} + +InspectorJSONTree::InspectorJSONTree(CommandType commandType, const Json::Value& arg, const LocalSocket& socket) + : CommandLine(commandType, arg, socket) +{ +} + +void InspectorJSONTree::RunAction() +{ + ILOG("GetJsonTree run!"); + std::string str = JsAppImpl::GetInstance().GetJSONTree(); + if (str == "null") { + str = "{\"children\":\"empty json tree\"}"; + } + SetCommandResult("result", str); + ILOG("SendJsonTree end!"); +} + +InspectorDefault::InspectorDefault(CommandType commandType, const Json::Value& arg, const LocalSocket& socket) + : CommandLine(commandType, arg, socket) +{ +} + +void InspectorDefault::RunAction() +{ + ILOG("GetDefaultJsonTree run!"); + std::string str = JsAppImpl::GetInstance().GetDefaultJSONTree(); + SetCommandResult("result", str); + ILOG("SendDefaultJsonTree end!"); +} + +ExitCommand::ExitCommand(CommandType commandType, const Json::Value& arg, const LocalSocket& socket) + : CommandLine(commandType, arg, socket) +{ +} + +void ExitCommand::RunAction() +{ + ILOG("ExitCommand run."); + Json::Value res = true; + SetCommandResult("result", res); + SendResult(); + Interrupter::Interrupt(); + ILOG("Ready to exit"); +} + +DeviceTypeCommand::DeviceTypeCommand(CommandLine::CommandType commandType, + const Json::Value& arg, + const LocalSocket& socket) + : CommandLine(commandType, arg, socket) +{ +} + +void DeviceTypeCommand::RunSet() {} + +ResolutionCommand::ResolutionCommand(CommandLine::CommandType commandType, + const Json::Value& arg, + const LocalSocket& socket) + : CommandLine(commandType, arg, socket) +{ +} + +void ResolutionCommand::RunSet() {} + +BackClickedCommand::BackClickedCommand(CommandLine::CommandType commandType, + const Json::Value& arg, + const LocalSocket& socket) + : CommandLine(commandType, arg, socket) +{ +} + +void BackClickedCommand::RunAction() +{ + MouseInputImpl::GetInstance().DispatchOsBackEvent(); + ILOG("BackClickCommand run"); + Json::Value res = true; + SetCommandResult("result", res); + ILOG("BackClickCommand end"); +} + +RestartCommand::RestartCommand(CommandLine::CommandType commandType, const Json::Value& arg, const LocalSocket& socket) + : CommandLine(commandType, arg, socket) +{ +} + +void RestartCommand::RunAction() +{ + ILOG("RestartCommand start"); + JsAppImpl::GetInstance().Restart(); + Json::Value res = true; + SetCommandResult("result", res); + ILOG("RestartCommand end"); +} + +FastPreviewMsgCommand::FastPreviewMsgCommand(CommandType commandType, const Json::Value& arg, const LocalSocket& socket) + : CommandLine(commandType, arg, socket) +{ +} + +void FastPreviewMsgCommand::RunGet() +{ + Json::Value resultContent; + std::string fastPreviewMsg = VirtualScreenImpl::GetInstance().GetFastPreviewMsg(); + resultContent["FastPreviewMsg"] = fastPreviewMsg; + SetResultToManager("args", resultContent, "MemoryRefresh"); + ILOG("Get FastPreviewMsgCommand run finished."); +} + +DropFrameCommand::DropFrameCommand(CommandType commandType, const Json::Value& arg, const LocalSocket& socket) + : CommandLine(commandType, arg, socket) +{ +} + +bool DropFrameCommand::IsSetArgValid() const +{ + if (args.isNull() || !args.isMember("frequency") || !args["frequency"].isInt()) { + ELOG("Invalid DropFrame of arguments!"); + return false; + } + if (args["frequency"].asInt() < 0) { + ELOG("DropFrame param frequency must greater than or equal to 0"); + return false; + } + return true; +} + +void DropFrameCommand::RunSet() +{ + ILOG("Set DropFrame frequency start."); + int frequency = args["frequency"].asInt(); + VirtualScreenImpl::GetInstance().SetDropFrameFrequency(frequency); + SetCommandResult("result", true); + ILOG("Set DropFrame frequency: %sms.", frequency); +} + +bool KeyPressCommand::IsActionArgValid() const +{ + if (args.isNull() || !args.isMember("isInputMethod") || !args["isInputMethod"].isBool()) { + ELOG("Param isInputMethod's value is invalid."); + return false; + } + bool isInputMethod = args["isInputMethod"].asBool(); + if (isInputMethod) { + return IsImeArgsValid(); + } else { + return IsKeyArgsValid(); + } +} + +bool KeyPressCommand::IsImeArgsValid() const +{ + if (!args.isMember("codePoint") || !args["codePoint"].isInt()) { + ELOG("Param codePoint's value is invalid."); + return false; + } + return true; +} + +bool KeyPressCommand::IsKeyArgsValid() const +{ + if (!args.isMember("keyCode") || !args["keyCode"].isInt() || !args["keyAction"].isInt() || + !args.isMember("keyAction") || !args["keyAction"].isInt() || + !args.isMember("pressedCodes") || !args["pressedCodes"].isArray() || + args["pressedCodes"].size() < 1) { + ELOG("Param keyEvent's value is invalid."); + return false; + } + if (args["keyAction"].asInt() < minActionVal || args["keyAction"].asInt() > maxActionVal) { + ELOG("Param keyAction's value is invalid,value range %d-%d.", minActionVal, maxActionVal); + return false; + } + int keyCode = args["keyCode"].asInt(); + if (keyCode > maxKeyVal || keyCode < minKeyVal) { + ELOG("Param pressedCode value is invalid,value range %d-%d.", minKeyVal, maxKeyVal); + return false; + } + Json::Value arrayNum = args["pressedCodes"]; + for (unsigned int i = 0; i < arrayNum.size(); i++) { + if (!arrayNum[i].isInt()) { + ELOG("Param pressedCodes's value is invalid."); + return false; + } + int pressedCode = arrayNum[i].asInt(); + if (pressedCode > maxKeyVal || pressedCode < minKeyVal) { + ELOG("Param pressedCode value is invalid,value range %d-%d.", minKeyVal, maxKeyVal); + return false; + } + } + return true; +} + +KeyPressCommand::KeyPressCommand(CommandType commandType, const Json::Value& arg, + const LocalSocket& socket) + : CommandLine(commandType, arg, socket) +{ +} + +void KeyPressCommand::RunAction() +{ + if (CommandParser::GetInstance().GetScreenMode() == CommandParser::ScreenMode::STATIC) { + return; + } + bool isInputMethod = args["isInputMethod"].asBool(); + if (isInputMethod) { + VirtualScreen::inputMethodCountPerMinute++; + unsigned int codePoint = args["codePoint"].asInt(); + KeyInputImpl::GetInstance().SetCodePoint(codePoint); + KeyInputImpl::GetInstance().DispatchOsInputMethodEvent(); + } else { + VirtualScreen::inputKeyCountPerMinute++; + int32_t keyCode = args["keyCode"].asInt(); + int32_t keyAction = args["keyAction"].asInt(); + Json::Value pressedCodes = args["pressedCodes"]; + vector pressedCodesVec; + for (unsigned int i = 0; i < pressedCodes.size(); i++) { + pressedCodesVec.push_back(pressedCodes[i].asInt()); + } + KeyInputImpl::GetInstance().SetKeyEvent(keyCode, keyAction, pressedCodesVec); + KeyInputImpl::GetInstance().DispatchOsKeyEvent(); + } + SetCommandResult("result", true); + ILOG("KeyPressCommand run finished."); } \ No newline at end of file diff --git a/cli/CommandLineInterface.cpp b/cli/CommandLineInterface.cpp new file mode 100644 index 0000000..2d103ad --- /dev/null +++ b/cli/CommandLineInterface.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. + * Description: The command line factory iterface implication + * Create: 2020-05-11 + */ + +#include "CommandLineInterface.h" + +#include +#include + +#include "CommandLine.h" +#include "CommandLineFactory.h" +#include "JsonReader.h" +#include "ModelManager.h" +#include "PreviewerEngineLog.h" +#include "VirtualScreen.h" + +using namespace std; + +const string CommandLineInterface::COMMAND_VERSION = "1.0.1"; +bool CommandLineInterface::isFirstWsSend = true; +bool CommandLineInterface::isPipeConnected = false; +CommandLineInterface::CommandLineInterface() : socket(nullptr) {} + +CommandLineInterface::~CommandLineInterface() {} + +void CommandLineInterface::InitPipe(const string name) +{ + if (socket != nullptr) { + socket.reset(); + ELOG("CommandLineInterface::InitPipe socket is not null"); + } + + socket = std::make_unique(); + if (socket == nullptr) { + FLOG("CommandLineInterface::Connect socket memory allocation failed!"); + } + + if (!socket->ConnectToServer(socket->GetCommandPipeName(name), LocalSocket::READ_WRITE)) { + FLOG("CommandLineInterface command pipe connect failed"); + } + isPipeConnected = true; +} + +CommandLineInterface& CommandLineInterface::GetInstance() +{ + static CommandLineInterface instance; + return instance; +} + +void CommandLineInterface::SendJsonData(const Json::Value& value) +{ + *(GetInstance().socket) << value.toStyledString(); +} + +void CommandLineInterface::SendJSHeapMemory(size_t total, size_t alloc, size_t peak) const +{ + Json::Value result; + result["version"] = COMMAND_VERSION; + result["property"] = "memoryUsage"; + Json::Value memory; + memory["totalBytes"] = static_cast(total); + memory["allocBytes"] = static_cast(alloc); + memory["peakAllocBytes"] = static_cast(peak); + result["result"] = memory; + if (socket == nullptr) { + ELOG("CommandLineInterface::SendJSHeapMemory socket is null"); + return; + } + *socket << result.toStyledString(); +} + +void CommandLineInterface::SendWebsocketStartupSignal() const +{ + Json::Value result; + Json::Value args; + result["MessageType"] = "imageWebsocket"; + args["port"] = VirtualScreen::webSocketPort; + result["args"] = args; + *socket << result.toStyledString(); +} + +void CommandLineInterface::ProcessCommand() const +{ + string message; + if (socket == nullptr) { + ELOG("CommandLineInterface::ProcessCommand socket is null"); + return; + } + if (isPipeConnected && VirtualScreen::isWebSocketListening && isFirstWsSend) { + isFirstWsSend = false; + SendWebsocketStartupSignal(); + } + *socket >> message; + if (message.empty()) { + return; + } + + ProcessCommandMessage(message); +} + +void CommandLineInterface::ProcessCommandMessage(std::string message) const +{ + Json::CharReaderBuilder builder; + Json::CharReader* reader = builder.newCharReader(); + if (reader == nullptr) { + FLOG("CommandLineInterface: CharReader memory allocation failed."); + } + + Json::Value jsonData; + std::string errors; + + bool parsingSuccessful = reader->parse(message.c_str(), message.c_str() + message.size(), &jsonData, &errors); + delete reader; + reader = nullptr; + + if (!ProcessCommandValidate(parsingSuccessful, jsonData, errors)) { + return; + } + + CommandLine::CommandType type = GetCommandType(jsonData["type"].asString()); + if (type == CommandLine::INVALID) { + return; + } + + string command = jsonData["command"].asString(); + std::unique_ptr commandLine = + CommandLineFactory::CreateCommandLine(command, type, jsonData["args"], *socket); + if (commandLine == nullptr) { + ELOG("Unsupported command"); + return; + } + commandLine->CheckAndRun(); +} + +bool CommandLineInterface::ProcessCommandValidate(bool parsingSuccessful, + const Json::Value& jsonData, + const std::string& errors) const +{ + if (!parsingSuccessful) { + ELOG("Failed to parse the JSON, errors: %s", errors.c_str()); + return false; + } + + if (!jsonData.isObject()) { + ELOG("Command is not a object!"); + return false; + } + + if (!jsonData.isMember("type") || !jsonData.isMember("command") || !jsonData.isMember("version")) { + ELOG("Command error!"); + return false; + } + + if (!regex_match(jsonData["version"].asString(), regex("(([0-9]|([1-9]([0-9]*))).){2}([0-9]|([1-9]([0-9]*)))"))) { + ELOG("Invalid command version!"); + return false; + } + return true; +} + +CommandLine::CommandType CommandLineInterface::GetCommandType(string name) const +{ + CommandLine::CommandType type = CommandLine::INVALID; + if (name == "set") { + type = CommandLine::SET; + } else if (name == "get") { + type = CommandLine::GET; + } else if (name == "action") { + type = CommandLine::ACTION; + } else { + ELOG("Command type invalid!"); + } + return type; +} + +void CommandLineInterface::ApplyConfig(const Json::Value& val) const +{ + const string set("setting"); + if (val.isMember(set)) { + Json::Value versionMembers = val[set]; + if (!versionMembers.isObject()) { + return; + } + + Json::Value::Members versions = versionMembers.getMemberNames(); + + for (Json::Value::Members::iterator viter = versions.begin(); viter != versions.end(); viter++) { + string version = *viter; + Json::Value commands = versionMembers[version]; + if (!commands.isObject()) { + continue; + } + Json::Value::Members members = commands.getMemberNames(); + + ApplyConfigMembers(commands, members); + } + } +} + +void CommandLineInterface::ApplyConfigMembers(const Json::Value& commands, + const Json::Value::Members& members) const +{ + for (Json::Value::Members::const_iterator iter = members.begin(); iter != members.end(); iter++) { + string key = *iter; + if (!commands[key].isObject() || !commands[key].isMember("args") || !commands[key]["args"].isObject()) { + ELOG("Invalid JSON: %s", commands[key].asString().c_str()); + continue; + } + std::unique_ptr command = + CommandLineFactory::CreateCommandLine(key, CommandLine::SET, commands[key]["args"], *socket); + ApplyConfigCommands(key, command); + } +} + +void CommandLineInterface::ApplyConfigCommands(const string& key, + const unique_ptr& command) const +{ + if (command == nullptr) { + ELOG("Unsupported configuration: %s", key.c_str()); + return; + } + + if (command->IsArgValid()) { + command->RunSet(); + } +} + +void CommandLineInterface::Init(string pipeBaseName) +{ + CommandLineFactory::InitCommandMap(); + InitPipe(pipeBaseName); +} + +void CommandLineInterface::ReadAndApplyConfig(string path) const +{ + if (path.empty()) { + return; + } + string jsonStr = JsonReader::ReadFile(path); + Json::Value val = JsonReader::ParseJsonData(jsonStr); + ApplyConfig(val); +} + +void CommandLineInterface::CreatCommandToSendData(const string commandName, + const Json::Value jsonData, + const string type) const +{ + CommandLine::CommandType commandType = GetCommandType(type); + std::unique_ptr commandLine = + CommandLineFactory::CreateCommandLine(commandName, commandType, jsonData, *socket); + if (commandLine == nullptr) { + ELOG("Unsupported CreatCommandToSendData: %s", commandName.c_str()); + return; + } + commandLine->RunAndSendResultToManager(); +}