#pragma once #include #include #include "JDefines.h" #include "JTerminal.h" #include "JMessageHandler.h" #include "WebSocketTerminal.h" #include "WebSocketServer.h" #include "UsbEventLoopWorker.h" #include "GetCmdListJsonCommand.h" #include "DeviceWebApiJsonCommand.h" #include "DeviceWebApiByteCommand.h" #include "ComplexCommandFactory.h" #include "DirectoryQueue.h" #include "NetQt/WebApi/WebApiServer.h" #include "exeGetError.h" #include "exeGetFileHtml.h" #include "exePostError.h" #include "DeviceCommandLinker.h" #include "DeviceInfoJsonParser.h" #include "CableTypeInfoJsonParser.h" #include "EventWithoutDataMessagePacker.h" #include "ErrorEventMessagePacker.h" namespace Incart::StartBox { class LinkConfiguration : public QObject { Q_OBJECT private: const bool MYDEBUG = false; Net::WebSockets::WebSocketServer* m_adcSocket; Net::WebSockets::WebSocketServer* m_eventSocket; std::unordered_map> m_eventsPackerMap; //Net::WebSockets::WebSocketServer* m_dataListener; public: explicit LinkConfiguration(QString appPath) : QObject() { Common::JT() << __PRETTY_FUNCTION__; // загрузка файла конфигурации устройства QString programBackendConfigPath = appPath + "/settings.json"; if (!Common::JFile::isFile(programBackendConfigPath)) { Common::JTerminal(JCL_RED) << __PRETTY_FUNCTION__ << "no file" << programBackendConfigPath; Common::JSys::abort(); return; } QByteArray& settingsBytes = Common::JFile::readFile(programBackendConfigPath); QJsonDocument settingsJsonDocument = QJsonDocument::fromJson(settingsBytes); if (!settingsJsonDocument.isObject()) { Common::JTerminal(JCL_RED) << __PRETTY_FUNCTION__ << "json object interpretation error"; Common::JSys::abort(); return; } QVariantMap settingsObject = settingsJsonDocument.object().toVariantMap(); quint16 deviceAdapterPort = 12345; quint16 adcSocketPort = 2222; quint16 eventSocketPort = 2223; quint16 terminalPort = 1200; auto mapField = settingsObject["deviceAdapter"].toMap(); deviceAdapterPort = static_cast(mapField["port"].toUInt()); mapField = settingsObject["adcSender"].toMap(); adcSocketPort = static_cast(mapField["port"].toUInt()); mapField = settingsObject["eventSender"].toMap(); eventSocketPort = static_cast(mapField["port"].toUInt()); mapField = settingsObject["terminal"].toMap(); terminalPort = static_cast(mapField["port"].toUInt()); Common::JTerminal(JCL_GREEN) << __FUNCTION__ << "Start"; // read device's info std::unordered_map devicesInfo; QString pathToDeviceCommonInfo = QCoreApplication::applicationDirPath()+ "/Devices"; QString pathToDeviceCommandsInfo = QCoreApplication::applicationDirPath()+ "/DeviceCommands"; QString pathToComplexCommandInfo = QCoreApplication::applicationDirPath() + "/ComplexCommandHandlers"; if (!DevicesInfo::DeviceInfoJsonParser::parseDevicesInfo(pathToDeviceCommonInfo, pathToDeviceCommandsInfo, pathToComplexCommandInfo, devicesInfo)) { Common::JTerminal(JCL_RED) << "Error: can't read device info"; return; } QString pathToCablesJson = QCoreApplication::applicationDirPath()+ "/Cables.json"; std::vector cableTypes; if (!Usb::CableTypeInfoJsonParser::parse(pathToCablesJson, cableTypes)) { Common::JTerminal(JCL_RED) << "Error: can't read cable types info"; return; } // запуск Usb устройства QString errorLogPath = settingsObject["errorLogPath"].toString(); if (errorLogPath.isEmpty()) { errorLogPath = appPath + "/ErrorLog.txt"; } static Usb::ComplexCommandFactory complexCommandFactory; static Net::WebApi::JsonCommandFactory jsonCommandFactory; std::unordered_set usbDeviceManagerFlags = { Usb::UsbDeviceManagerFlags::WithoutAdcOn //Usb::UsbDeviceManagerFlags::WithoutEmbeddedCommands //Usb::UsbDeviceManagerFlags::CableExistAutoCheck }; static Usb::UsbEventLoopWorker m_usb(devicesInfo, cableTypes, &complexCommandFactory, errorLogPath.toStdString(), usbDeviceManagerFlags, false); static Net::WebApi::DirectoryQueue htmlDirectories; QStringList htmlDirectoriesNames = settingsObject["htmlDirectories"].toStringList(); for (auto it = htmlDirectoriesNames.begin(); it != htmlDirectoriesNames.end(); it++) { htmlDirectories.AddName(*it); } // конфигуратор команд для WebTcpIpServer static Net::WebApi::QMapWebApiGet m_exeGet; //{ static Net::WebApi::exeGetError errorExeGet; m_exeGet["__err"] = &errorExeGet; // по умолчанию static Net::WebApi::exeGetFileHtml getFileExeGet(&htmlDirectories, settingsObject["defaultHtmlDirectory"].toString()); m_exeGet["__file"] = &getFileExeGet; // дать файлы frontend проекта //} static Net::WebApi::QMapWebApiPost m_exePost; { static Net::WebApi::exePostError errorExePost; m_exePost["__err"] = &errorExePost; // по умолчанию static DeviceWebApi::DeviceWebApiJsonCommand deviceWebApiCommand(m_usb.getDeviceManager(), &jsonCommandFactory); m_exePost["cmd"] = &deviceWebApiCommand; } DeviceWebApi::DeviceCommandLinker::createLink(m_usb, jsonCommandFactory); // запуск WebTcpIpServer - локального командного интерфейса static Net::WebApi::WebApiServer webApiServer(deviceAdapterPort, m_exeGet, m_exePost); // запуск WebSocketServer - локального визуализатора сигнала static Net::WebSockets::WebSocketServer adcSocket(adcSocketPort); m_adcSocket = &adcSocket; connect(m_usb.getSignalManager().get(), &Usb::AdcChannelsManager::signalTransfer, &adcSocket, &Net::WebSockets::WebSocketServer::slotTransfer); // открытие сокета для отправки событий клиентам m_eventsPackerMap.insert(std::pair>("deviceConnect", std::make_shared("deviceConnect"))); m_eventsPackerMap.insert(std::pair>("deviceDisconnect", std::make_shared("deviceDisconnect"))); m_eventsPackerMap.insert(std::pair>("cableConnect", std::make_shared("cableConnect"))); m_eventsPackerMap.insert(std::pair>("cableDisconnect", std::make_shared("cableDisconnect"))); static Net::WebSockets::WebSocketServer eventSocket(eventSocketPort); m_eventSocket = &eventSocket; connect(m_usb.getSignalManager().get(), &Usb::AdcChannelsManager::eventTransfer, &eventSocket, &Net::WebSockets::WebSocketServer::slotTransfer); // запуск WebSocketTerminal - дублируем отладку в WebBrowser static Net::WebSockets::WebSocketTerminal jet(terminalPort); connect(&jet, &Net::WebSockets::WebSocketTerminal::signalError, this, &LinkConfiguration::slotError, Qt::QueuedConnection); //connect(&m_usb, &Usb::UsbEventLoopWorker::deviceIsConnected, &jet, &Net::WebSockets::WebSocketTerminal::slotDeviceConnect, Qt::QueuedConnection); //connect(&m_usb, &Usb::UsbEventLoopWorker::deviceIsDisconnected, &jet, &Net::WebSockets::WebSocketTerminal::slotDeviceDisconnect, Qt::QueuedConnection); connect(&m_usb, &Usb::UsbEventLoopWorker::deviceIsConnected, this, &LinkConfiguration::slotDeviceConnect, Qt::QueuedConnection); connect(&m_usb, &Usb::UsbEventLoopWorker::deviceIsDisconnected, this, &LinkConfiguration::slotDeviceDisconnect, Qt::QueuedConnection); connect(&m_usb, &Usb::UsbEventLoopWorker::cableIsConnected, this, &LinkConfiguration::slotCableConnect, Qt::QueuedConnection); connect(&m_usb, &Usb::UsbEventLoopWorker::cableIsDisconnected, this, &LinkConfiguration::slotCableDisconnect, Qt::QueuedConnection); connect(&m_usb, &Usb::UsbEventLoopWorker::signalError, this, &LinkConfiguration::slotError, Qt::QueuedConnection); Common::JMessageHandler::ExtTerminal(&jet); } ~LinkConfiguration() { //Common::JT() << __PRETTY_FUNCTION__; Common::JMessageHandler::ExtTerminal(nullptr,true); // отключаем внешние терминалы } private slots: void slotError(const std::string& errorType, const std::string& message) { std::shared_ptr eventMessagePacker = std::make_shared(errorType, message); Common::MessagePacker messagePacker; messagePacker.start_map(2); messagePacker.add_value("type", std::string("event")); messagePacker.add_array_value("data", 1); eventMessagePacker->pack(messagePacker); m_eventSocket->slotTransfer(messagePacker.pack()); } void slotDeviceConnect() { Common::JTerminal() << __PRETTY_FUNCTION__ << " (1)"; std::string eventName = "deviceConnect"; sendEventWithoutData(eventName); } void slotDeviceDisconnect() { std::string eventName = "deviceDisconnect"; sendEventWithoutData(eventName); } void slotCableConnect() { std::string eventName = "cableConnect"; sendEventWithoutData(eventName); } void slotCableDisconnect() { std::string eventName = "cableDisconnect"; sendEventWithoutData(eventName); } private: void sendEventWithoutData(std::string& eventName_) { std::cout << "sendEventWithoutData " << eventName_ << std::endl; auto it = m_eventsPackerMap.find(eventName_); if (it != m_eventsPackerMap.end()) { Common::MessagePacker messagePacker; messagePacker.start_map(2); messagePacker.add_value("type", std::string("event")); messagePacker << std::string("data"); it->second->pack(messagePacker); m_eventSocket->slotTransfer(messagePacker.pack()); } } }; } // namespace Incart::StartBox