#pragma once #include #include "UsbDeviceManager.h" #include "ByteCommand.h" #include "ExePost.h" #include "LaunchedSimpleCommandInfo.h" #include "DeviceInfoJsonParser.h" #include "DeviceWebApiSimpleCommand.h" #include "DeviceCommandInfoJsonPacker.h" #include "DeviceCommandStatusConverter.h" #include "JsonCommandFactory.h" #include "VariantJsonCommandInfo.h" #include "JsonWebApiCommandWrapper.h" namespace Incart::DeviceWebApi { class DeviceWebApiJsonCommand : public Net::WebApi::exePost { private: Usb::UsbDeviceManager* m_usbDeviceManager; Net::WebApi::JsonCommandFactory* m_jsonCommands; public: DeviceWebApiJsonCommand(Usb::UsbDeviceManager* usbDeviceManager, Net::WebApi::JsonCommandFactory* jsonCommands) : exePost() , m_usbDeviceManager(usbDeviceManager) , m_jsonCommands(jsonCommands) { } public: void exe(Net::WebApi::ParsingURI&, QByteArray& body, QTcpSocket* socket) override { QJsonDocument jdoc = QJsonDocument::fromJson(body); if (!jdoc.isObject()) { m_resp->retError("400 Bad Request"); sentResponse(socket); return; } QJsonObject jobj = jdoc.object(); QVariantMap jmap = jobj.toVariantMap(); std::string commandName = jmap["cmd"].toString().toStdString(); uint32_t commandUid = jmap["uid"].toUInt(); //std::cout << "[JsonCommand.exe begin] " << commandName << " " << commandUid << std::endl; Usb::DeviceCommand::EStatus answerStatus = Usb::DeviceCommand::EStatus::OK; // try parse simple command std::vector simpleCommands = m_usbDeviceManager->getCommandSet()->getDeviceSimpleCommandsInfo(); if (simpleCommands.size() == 0) { answerStatus = Usb::DeviceCommand::EStatus::DEVICE_DISCONNECTED; std::string message = "Command \"" + commandName + "\" was not started due to an error: " + Usb::DeviceCommandStatusConverter::toText(Usb::DeviceCommand::EStatus::DEVICE_DISCONNECTED); emit m_usbDeviceManager->signalError("CommandError", message); } else if (Common::StringExtensions::isEqualsInsensitive(commandName, std::string("CustomByteCommand"))) { std::shared_ptr commandInfo = parseSimpleCommandInfo(jmap); commandInfo->name = "Custom"; if (commandInfo == nullptr) { m_resp->retError("400 Bad Request"); sentResponse(socket); return; } std::vector commandBytes; answerStatus = m_usbDeviceManager->getCommandSet()->createCommandBytes(commandInfo, commandBytes); if (answerStatus == Usb::DeviceCommand::EStatus::OK) { Usb::ByteCommandQueue* commandQueue = m_usbDeviceManager->getCommandQueue(); std::shared_ptr webApiCommand = std::make_shared(commandInfo->name, commandUid, socket, std::move(commandBytes)); connect(webApiCommand.get(), &DeviceWebApiSimpleCommand::answerIsReady, this, &DeviceWebApiJsonCommand::handleSimpleCommandAnswerIsReady); commandQueue->enqueue(webApiCommand); return; } } else { for (size_t i = 0; i < simpleCommands.size(); i++) { if (Common::StringExtensions::isEqualsInsensitive(commandName, simpleCommands[i].name)) { std::shared_ptr commandInfo = parseSimpleCommandInfo(jmap); if (commandInfo == nullptr) { m_resp->retError("400 Bad Request"); sentResponse(socket); return; } std::vector commandBytes; answerStatus = m_usbDeviceManager->getCommandSet()->createCommandBytes(commandInfo, commandBytes); if (answerStatus == Usb::DeviceCommand::EStatus::OK) { Usb::ByteCommandQueue* commandQueue = m_usbDeviceManager->getCommandQueue(); std::shared_ptr webApiCommand = std::make_shared(commandInfo->name, commandUid, socket, std::move(commandBytes)); connect(webApiCommand.get(), &DeviceWebApiSimpleCommand::answerIsReady, this, &DeviceWebApiJsonCommand::handleSimpleCommandAnswerIsReady); commandQueue->enqueue(webApiCommand); return; } break; } } if (answerStatus == Usb::DeviceCommand::EStatus::OK) { answerStatus = Usb::DeviceCommand::EStatus::NOT_EXIST; } } // try execute complex command if (answerStatus == Usb::DeviceCommand::EStatus::NOT_EXIST) { std::shared_ptr complexJsonCommand = std::dynamic_pointer_cast(m_jsonCommands->create(commandName)); if (complexJsonCommand != nullptr) { Net::WebApi::JsonWebApiCommandWrapper* webApiCommand = new Net::WebApi::JsonWebApiCommandWrapper(complexJsonCommand, socket); connect(webApiCommand, &Net::WebApi::JsonWebApiCommandWrapper::answerIsReady, this, &DeviceWebApiJsonCommand::handleComplexCommandAnswerIsReady); std::shared_ptr statusInfo = complexJsonCommand->execute(std::make_shared(commandName, commandUid, jmap["data"])); answerStatus = (statusInfo->result == Net::WebApi::EJsonCommandStatus::OK) ? Usb::DeviceCommand::EStatus::OK : Usb::DeviceCommand::EStatus::BAD_DATA; } } if (answerStatus != Usb::DeviceCommand::EStatus::OK) { if (answerStatus == Usb::DeviceCommand::EStatus::NOT_EXIST) { std::string errorMessage = "Command \"" + commandName + "\" was not started due to an error: " + Usb::DeviceCommandStatusConverter::toText(Usb::DeviceCommand::EStatus::NOT_EXIST); emit m_usbDeviceManager->signalError("CommandError", errorMessage); } QJsonObject jsonCommandAnswer; jsonCommandAnswer.insert("cmd", QString::fromStdString(commandName)); jsonCommandAnswer.insert("uid", static_cast(commandUid)); jsonCommandAnswer.insert("status", "error"); jsonCommandAnswer.insert("errorcode", QString::fromStdString(Usb::DeviceCommandStatusConverter::toText(answerStatus))); QJsonDocument document(jsonCommandAnswer); QByteArray answerBytes = document.toJson(QJsonDocument::Compact); m_resp->ret200("json", answerBytes); sentResponse(socket); } } private slots: void handleSimpleCommandAnswerIsReady(std::shared_ptr command, std::vector answer, int32_t status) { std::shared_ptr webApiCommand = std::dynamic_pointer_cast(command); QJsonObject jsonCommandAnswer; jsonCommandAnswer.insert("uid", static_cast(webApiCommand->getUid())); std::vector resultData; if ((status == Usb::DeviceCommand::EStatus::OK) && (answer.size() > 7)) { for (size_t i = 4; i < answer.size() - 3; i++) { resultData.push_back(answer[i]); } } Usb::DeviceCommand::EStatus answerStatus = (Usb::DeviceCommand::EStatus)status; if (answerStatus == Usb::DeviceCommand::EStatus::OK) { jsonCommandAnswer.insert("data", Usb::DeviceCommandInfoJsonPacker::pack(resultData)); jsonCommandAnswer.insert("status", "ok"); } else { jsonCommandAnswer.insert("status", "error"); jsonCommandAnswer.insert("errorcode", QString::fromStdString(Usb::DeviceCommandStatusConverter::toText(answerStatus))); } QJsonDocument document(jsonCommandAnswer); QByteArray answerBytes = document.toJson(QJsonDocument::Compact); //std::cout << "[JsonCommand.exe end sc] " << webApiCommand->getName() << " " << webApiCommand->getUid() << std::endl; m_resp->ret200("json", answerBytes); sentResponse(webApiCommand->getSocket()); } void handleComplexCommandAnswerIsReady(Net::WebApi::JsonWebApiCommandWrapper* command, QJsonDocument answer, std::shared_ptr status) { QJsonObject jsonCommandAnswer; QJsonValue result; if (answer.isObject()) result = answer.object(); else if (answer.isArray()) result = answer.array(); else result = {}; jsonCommandAnswer.insert("uid", static_cast(command->getUid())); if (status->result == Net::WebApi::EJsonCommandStatus::OK) { jsonCommandAnswer.insert("data", result); jsonCommandAnswer.insert("status", "ok"); } else { std::shared_ptr answerErrorStatus = std::dynamic_pointer_cast(status); jsonCommandAnswer.insert("status", "error"); jsonCommandAnswer.insert("errorcode", QString::fromStdString(answerErrorStatus->errorText)); } QJsonDocument document(jsonCommandAnswer); QByteArray answerBytes = document.toJson(QJsonDocument::Compact); //std::cout << "[JsonCommand.exe end cc] " << webApiCommand->getName() << " " << webApiCommand->getUid() << std::endl; m_resp->ret200("json", answerBytes); sentResponse(command->getSocket()); delete command; } private: std::shared_ptr parseSimpleCommandInfo(QVariantMap jmap) { std::string name = jmap["cmd"].toString().toStdString(); uint32_t uid = jmap["uid"].toUInt(); std::vector data; QVariant dataField = jmap["data"]; QString d = ""; if (!dataField.isNull() && ((dataField.userType() != QMetaType::QString) || !dataField.toString().isEmpty())) { bool parseResult; data = DevicesInfo::DeviceInfoJsonParser::parseByteList(dataField.toStringList(), parseResult); if (!parseResult) { return nullptr; } } return std::make_shared(name, uid, data); } }; } // namespace Incart::DeviceWebApi